Collision.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /*
  2. * 2D Game Engine
  3. * Collision.h:
  4. * Based on pikuma.com 2D game engine in C++ and Lua course
  5. * Copyright (c) 2021 986-Studio. All rights reserved.
  6. *
  7. * Created by Manoël Trapier on 15/02/2021.
  8. */
  9. #ifndef GAMEENGINE_COLLISION_H
  10. #define GAMEENGINE_COLLISION_H
  11. #include <SDL.h>
  12. #include <ECS.h>
  13. #include <Logger.h>
  14. #include <EventBus.h>
  15. #include <Components/Transform.h>
  16. #include <Components/BoxCollider.h>
  17. #include <Events/Collision.h>
  18. class CollisionSystem: public System
  19. {
  20. class BoxRect
  21. {
  22. double x0, y0, x1, y1;
  23. public:
  24. BoxRect(TransformComponent tc, BoxColliderComponent bc)
  25. {
  26. this->x0 = tc.position.x + bc.offset.x;
  27. this->x1 = this->x0 + bc.width;
  28. this->y0 = tc.position.y + bc.offset.y;
  29. this->y1 = this->y0 + bc.height;
  30. }
  31. bool collideWith(BoxRect &b) const
  32. {
  33. return ((this->x0 < b.x1) && (this->x1 > b.x0) && (this->y0 < b.y1) && (this->y1 > b.y0));
  34. }
  35. };
  36. public:
  37. CollisionSystem()
  38. {
  39. this->requireComponent<TransformComponent>();
  40. this->requireComponent<BoxColliderComponent>();
  41. }
  42. void update(std::unique_ptr<EventBus> &eventBus)
  43. {
  44. auto entities = this->getSystemEntities();
  45. for(auto entity: entities)
  46. {
  47. auto &collider = entity.getComponent<BoxColliderComponent>();
  48. collider.isColliding = false;
  49. }
  50. for(auto i = entities.begin(); i != entities.end(); i++)
  51. {
  52. for(auto j = (i + 1); j != entities.end(); j++)
  53. {
  54. auto &collideA = i->getComponent<BoxColliderComponent>();
  55. auto &collideB = j->getComponent<BoxColliderComponent>();
  56. BoxRect boxA = BoxRect(i->getComponent<TransformComponent>(), collideA);
  57. BoxRect boxB = BoxRect(j->getComponent<TransformComponent>(), collideB);
  58. if (boxA.collideWith(boxB))
  59. {
  60. //Logger::Debug("Entity #%d collided with #%d!", i->getId(), j->getId());
  61. collideB.isColliding = true;
  62. collideA.isColliding = true;
  63. eventBus->emitEvent<CollisionEvent>(*i, *j);
  64. }
  65. }
  66. }
  67. }
  68. void debugRender(SDL_Renderer *renderer, SDL_Rect &camera)
  69. {
  70. for(auto entity: this->getSystemEntities())
  71. {
  72. auto collider = entity.getComponent<BoxColliderComponent>();
  73. auto transform = entity.getComponent<TransformComponent>();
  74. SDL_Rect rect;
  75. rect.x = static_cast<int>(transform.position.x + collider.offset.x - camera.x);
  76. rect.y = static_cast<int>(transform.position.y + collider.offset.y - camera.y);
  77. rect.w = static_cast<int>(collider.width * transform.scale.x);
  78. rect.h = static_cast<int>(collider.height * transform.scale.y);
  79. if (collider.isColliding)
  80. {
  81. SDL_SetRenderDrawColor(renderer, 255, 64, 16, 255);
  82. }
  83. else
  84. {
  85. SDL_SetRenderDrawColor(renderer, 64, 255, 21, 255);
  86. }
  87. SDL_RenderDrawRect(renderer, &rect);
  88. }
  89. }
  90. };
  91. #endif /* GAMEENGINE_COLLISION_H */