From 28af8c9389e2bfe696dd40bb4f68ff60e4be6619 Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Sun, 28 Jan 2024 18:18:27 +0100 Subject: [PATCH 1/3] minor improvements --- include/CollisionHandler.h | 8 ++++++-- include/Entity.h | 1 + include/Manager.h | 2 ++ src/CollisionHandler.cpp | 11 +++++++++-- src/Entity.cpp | 5 +++++ src/Manager.cpp | 11 +++++++++++ src/TransformComponent.cpp | 20 +++++--------------- 7 files changed, 39 insertions(+), 19 deletions(-) diff --git a/include/CollisionHandler.h b/include/CollisionHandler.h index cf90905..b786c12 100644 --- a/include/CollisionHandler.h +++ b/include/CollisionHandler.h @@ -1,13 +1,17 @@ #pragma once +#include "Constants.h" #include "Entity.h" #include "SDL_rect.h" #include "SpriteComponent.h" #include "Vector2D.h" +#include "Manager.h" + +#include +#include #include class ColliderComponent; -class Manager; class Entity; constexpr uint8_t DIRECTION_C = 4; @@ -39,7 +43,7 @@ public: static IntersectionBitSet getIntersectionWithBounds(Entity* entity);// will fail if speed high enough to switch from no collision to full overlap in one tick static IntersectionBitSet getIntersectionWithBounds(Entity* entity, Vector2D posMod); - std::vector getColliders(GroupLabel groupLabel); // temporary function, remove once game.cpp cleaned up + std::vector getColliders(std::initializer_list const& groupLabels); // temporary function, remove once game.cpp cleaned up void update(); }; \ No newline at end of file diff --git a/include/Entity.h b/include/Entity.h index 630e2fe..afb871a 100644 --- a/include/Entity.h +++ b/include/Entity.h @@ -47,6 +47,7 @@ public: bool hasGroup(Group mGroup); void addGroup(Group mGroup); void delGroup(Group mGroup); + std::bitset getGroupBitSet(); void setTeam(TeamLabel teamLabel); TeamLabel getTeam(); diff --git a/include/Manager.h b/include/Manager.h index 0046c33..61a1c45 100644 --- a/include/Manager.h +++ b/include/Manager.h @@ -20,6 +20,8 @@ public: void addToTeam(Entity* mEntity, Team mTeam); std::vector& getTeam(Team mTeam); + std::vector getAll(); + Entity& addEntity(); private: diff --git a/src/CollisionHandler.cpp b/src/CollisionHandler.cpp index f8975d1..98173e2 100644 --- a/src/CollisionHandler.cpp +++ b/src/CollisionHandler.cpp @@ -94,11 +94,18 @@ IntersectionBitSet CollisionHandler::getIntersectionWithBounds(Entity* entity, V return intersections; } -std::vector CollisionHandler::getColliders(GroupLabel groupLabel) +std::vector CollisionHandler::getColliders(std::initializer_list const& groupLabels) { std::vector colliders; - for (auto& entity : manager.getGroup((size_t) groupLabel)) { + std::bitset groupBitSet; + for (auto& groupLabel : groupLabels) { + groupBitSet.set((size_t) groupLabel); + } + + for (auto& entity : manager.getAll()) { + if ((groupBitSet & entity->getGroupBitSet()).none()) + continue; if (!entity->hasComponent()) continue; colliders.emplace_back(&entity->getComponent()); diff --git a/src/Entity.cpp b/src/Entity.cpp index 6817071..bd9b79a 100644 --- a/src/Entity.cpp +++ b/src/Entity.cpp @@ -30,6 +30,11 @@ void Entity::delGroup(Group mGroup) groupBitSet[mGroup] = false; } +std::bitset Entity::getGroupBitSet() +{ + return groupBitSet; +} + void Entity::setTeam(TeamLabel teamLabel) { teamLabel = teamLabel; diff --git a/src/Manager.cpp b/src/Manager.cpp index 3759704..f3aa133 100644 --- a/src/Manager.cpp +++ b/src/Manager.cpp @@ -1,8 +1,10 @@ #include "Manager.h" #include +#include #include "Constants.h" +#include "Entity.h" void Manager::draw() { @@ -66,6 +68,15 @@ std::vector& Manager::getTeam(Team mTeam) return entitiesByTeam[mTeam]; } +std::vector Manager::getAll() +{ + std::vector entity_vec; + for (auto& entity_ptr : entities) { + entity_vec.emplace_back(entity_ptr.get()); + } + return entity_vec; +} + Entity& Manager::addEntity() { Entity* e = new Entity(*this); diff --git a/src/TransformComponent.cpp b/src/TransformComponent.cpp index 12609dd..b14ecb9 100644 --- a/src/TransformComponent.cpp +++ b/src/TransformComponent.cpp @@ -60,31 +60,21 @@ void TransformComponent::update() if (this->entity->hasGroup((size_t) GroupLabel::PLAYERS)) { IntersectionBitSet intersectionsX = CollisionHandler::getIntersectionWithBounds(entity, positionChange); - for (auto& collider : Game::collisionHandler->getColliders(GroupLabel::MAPTILES)) { - intersectionsX |= CollisionHandler::getIntersection(entity, collider->entity, Vector2D(positionChange.x, 0), Vector2D(0, 0)); - } - for (auto& collider : Game::collisionHandler->getColliders(GroupLabel::COLLIDERS)) { + for (auto& collider : Game::collisionHandler->getColliders({GroupLabel::MAPTILES, GroupLabel::COLLIDERS})) { intersectionsX |= CollisionHandler::getIntersection(entity, collider->entity, Vector2D(positionChange.x, 0), Vector2D(0, 0)); } IntersectionBitSet intersectionsY = CollisionHandler::getIntersectionWithBounds(entity, positionChange); - for (auto& collider : Game::collisionHandler->getColliders(GroupLabel::MAPTILES)) { - intersectionsY |= CollisionHandler::getIntersection(entity, collider->entity, Vector2D(0, positionChange.y), Vector2D(0, 0)); - } - for (auto& collider : Game::collisionHandler->getColliders(GroupLabel::COLLIDERS)) { + for (auto& collider : Game::collisionHandler->getColliders({GroupLabel::MAPTILES, GroupLabel::COLLIDERS})) { intersectionsY |= CollisionHandler::getIntersection(entity, collider->entity, Vector2D(0, positionChange.y), Vector2D(0, 0)); } - if (intersectionsX.test((size_t) direction::LEFT) && positionChange.x < 0) - positionChange.x = 0; + IntersectionBitSet intersections = (intersectionsX & IntersectionBitSet("0011")) | (intersectionsY & IntersectionBitSet("1100")); - if (intersectionsX.test((size_t) direction::RIGHT) && positionChange.x > 0) + if (intersections.test((size_t) direction::LEFT) || intersections.test((size_t) direction::RIGHT)) positionChange.x = 0; - if (intersectionsY.test((size_t) direction::UP) && positionChange.y < 0) - positionChange.y = 0; - - if (intersectionsY.test((size_t) direction::DOWN) && positionChange.y > 0) + if (intersections.test((size_t) direction::UP) || intersections.test((size_t) direction::DOWN)) positionChange.y = 0; } From 973114f351bb8b57f4be291b8baad08552e18642 Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Mon, 29 Jan 2024 23:49:09 +0100 Subject: [PATCH 2/3] Added debug type to CMake --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e5c48a..9ce25dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,4 +26,10 @@ target_link_libraries(${PROJECT_NAME} PRIVATE SDL2_image::SDL2_image-static ) +if(CMAKE_BUILD_TYPE MATCHES "Debug") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fsanitize=address -fno-omit-frame-pointer") + target_link_libraries(${PROJECT_NAME} PRIVATE "-fsanitize=address") +endif() + + file(COPY ${PROJECT_SOURCE_DIR}/assets DESTINATION ${PROJECT_BINARY_DIR}) \ No newline at end of file From fa4586f1dbeed8f73bf16a401e697f613ea03916 Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Mon, 29 Jan 2024 23:49:58 +0100 Subject: [PATCH 3/3] Rewrote collision detection --- include/AssetManager.h | 4 +- include/CollisionHandler.h | 28 ++++++++++--- include/Defines.h | 3 +- include/Direction.h | 7 ++++ include/Entity.h | 8 +++- include/Game.h | 12 +++--- include/HealthComponent.h | 10 ++--- include/ProjectileComponent.h | 4 +- include/SpriteComponent.h | 9 +---- include/TransformComponent.h | 2 +- include/Vector2D.h | 7 +++- src/AssetManager.cpp | 4 +- src/ColliderComponent.cpp | 1 + src/CollisionHandler.cpp | 59 +++++++++++++++++++++------ src/Entity.cpp | 2 +- src/Game.cpp | 76 ++++++++++------------------------- src/HealthComponent.cpp | 32 +++++++++++---- src/KeyboardController.cpp | 24 +++++------ src/Manager.cpp | 8 ++-- src/ProjectileComponent.cpp | 33 ++++++++++++--- src/SpriteComponent.cpp | 5 ++- src/TransformComponent.cpp | 28 ++++++------- src/Vector2D.cpp | 9 +++++ 23 files changed, 229 insertions(+), 146 deletions(-) create mode 100644 include/Direction.h diff --git a/include/AssetManager.h b/include/AssetManager.h index 61b94d2..50ecabe 100644 --- a/include/AssetManager.h +++ b/include/AssetManager.h @@ -1,3 +1,5 @@ +#include "Entity.h" + #include #include #include @@ -12,7 +14,7 @@ public: AssetManager(Manager* manager); ~AssetManager(); - void createProjectile(Vector2D pos, Vector2D velocity, bool source, int scale, int range, int speed, const char* texturePath); + void createProjectile(Vector2D pos, Vector2D velocity, bool source, int scale, int range, int speed, const char* texturePath, TeamLabel teamLabel); //texture management void addTexture(std::string id, const char* path); diff --git a/include/CollisionHandler.h b/include/CollisionHandler.h index b786c12..8cdaad5 100644 --- a/include/CollisionHandler.h +++ b/include/CollisionHandler.h @@ -1,5 +1,6 @@ #pragma once +#include "ColliderComponent.h" #include "Constants.h" #include "Entity.h" #include "SDL_rect.h" @@ -9,6 +10,8 @@ #include #include +#include +#include #include class ColliderComponent; @@ -37,13 +40,28 @@ public: manager(mManager) { }; ~CollisionHandler(); + static IntersectionBitSet getIntersection( // intersections relative to entityA + Entity* entityA, + Entity* entityB, + Vector2D posModA = Vector2D(0,0), + Vector2D posModB = Vector2D(0,0)); + static IntersectionBitSet getIntersectionWithBounds( // will fail to determine direction if speed high enough to switch from no collision to full overlap in one tick + Entity* entity, + Vector2D posMod = Vector2D(0,0)); - static IntersectionBitSet getIntersection(Entity* entityA, Entity* entityB); // intersections relative to entityA - static IntersectionBitSet getIntersection(Entity* entityA, Entity* entityB, Vector2D posModA, Vector2D posModB); - static IntersectionBitSet getIntersectionWithBounds(Entity* entity);// will fail if speed high enough to switch from no collision to full overlap in one tick - static IntersectionBitSet getIntersectionWithBounds(Entity* entity, Vector2D posMod); + // temporary function, remove once game.cpp cleaned up + std::vector getColliders( + std::initializer_list const& groupLabels, + std::initializer_list const& teamLabels = {}, + bool negateTeam = false); - std::vector getColliders(std::initializer_list const& groupLabels); // temporary function, remove once game.cpp cleaned up + template + T getAnyIntersection( + Entity* entity, + Vector2D posMod = {}, + std::initializer_list const& groupLabels = {}, + std::initializer_list const& teamLabels = {}, + bool negateTeam = false); void update(); }; \ No newline at end of file diff --git a/include/Defines.h b/include/Defines.h index 3f59c93..7b9637e 100644 --- a/include/Defines.h +++ b/include/Defines.h @@ -1,2 +1 @@ -#pragma once - +#pragma once \ No newline at end of file diff --git a/include/Direction.h b/include/Direction.h new file mode 100644 index 0000000..a971704 --- /dev/null +++ b/include/Direction.h @@ -0,0 +1,7 @@ +#pragma once + +enum class Direction +{ + LEFT, + RIGHT +}; \ No newline at end of file diff --git a/include/Entity.h b/include/Entity.h index afb871a..9d768b5 100644 --- a/include/Entity.h +++ b/include/Entity.h @@ -5,6 +5,7 @@ #include #include +#include "ColliderComponent.h" #include "ECS.h" #include "Constants.h" @@ -42,7 +43,12 @@ public: void draw() const; bool isActive() const { return this->active; } - void destroy() { this->active = false; } + void destroy() { + this->active = false; + if (this->hasComponent()) { + this->getComponent().removeCollision(); + } + } bool hasGroup(Group mGroup); void addGroup(Group mGroup); diff --git a/include/Game.h b/include/Game.h index 64fa511..86a38c8 100644 --- a/include/Game.h +++ b/include/Game.h @@ -6,6 +6,7 @@ class AssetManager; class CollisionHandler; +enum class TeamLabel; class Game { @@ -21,19 +22,18 @@ public: void clean(); bool running() const; - static void addTile(int id, int x, int y); + static void addTile(unsigned long id, int x, int y); static SDL_Renderer* renderer; static SDL_Event event; static CollisionHandler* collisionHandler; static AssetManager* assets; - - bool getWinner(); private: + void setWinner(TeamLabel winningTeam); + TeamLabel getWinner(); + int counter = 0; bool isRunning = false; SDL_Window* window; - - //true for player1 win / false for player2 win; - bool winner; + TeamLabel winner; }; diff --git a/include/HealthComponent.h b/include/HealthComponent.h index 7cfd2e7..6daf17b 100644 --- a/include/HealthComponent.h +++ b/include/HealthComponent.h @@ -1,5 +1,6 @@ #pragma once +#include "Direction.h" #include "Component.h" class Manager; @@ -8,22 +9,21 @@ class HealthComponent : public Component { public: - HealthComponent(int health, Manager* manager, bool player) : health(health), manager(manager), player(player) {} + HealthComponent(int health, Direction side) : health(health), side(side) {} ~HealthComponent() {} - void getDamage() { this->health--; } + void modifyHealth(int health = -1); int getHealth() { return this->health; } void init() override; - void createAllHearts(); + void resetHearts(); void createHeartComponents(int x); - private: int health; - Manager* manager; + Direction side; bool player; //true if player1 / false if player2 }; \ No newline at end of file diff --git a/include/ProjectileComponent.h b/include/ProjectileComponent.h index 73088c1..8fa949c 100644 --- a/include/ProjectileComponent.h +++ b/include/ProjectileComponent.h @@ -10,7 +10,7 @@ class ProjectileComponent : public Component //can maybe be split in separate .cpp file public: - ProjectileComponent(int range, int speed, Vector2D velocity, bool source) : range(range), speed(speed), velocity(velocity), source(source) {} + ProjectileComponent(int range, int speed, Vector2D direction, bool source) : range(range), speed(speed), direction(direction), source(source) {} ~ProjectileComponent() {} void init() override; @@ -27,5 +27,5 @@ private: const bool source; //true if from player1 / false if from player2 - Vector2D velocity; + Vector2D direction; }; \ No newline at end of file diff --git a/include/SpriteComponent.h b/include/SpriteComponent.h index 109d824..a11865f 100644 --- a/include/SpriteComponent.h +++ b/include/SpriteComponent.h @@ -5,15 +5,10 @@ #include "AnimationHandler.h" #include "Component.h" +#include "Direction.h" class TransformComponent; -enum SpriteDirection -{ - LEFT, - RIGHT -}; - class SpriteComponent : public Component { public: @@ -43,5 +38,5 @@ public: void update() override; void draw() override; void playAnimation(AnimationType type); - void setDirection(SpriteDirection direction); + void setDirection(Direction direction); }; diff --git a/include/TransformComponent.h b/include/TransformComponent.h index 04b193f..deed7f9 100644 --- a/include/TransformComponent.h +++ b/include/TransformComponent.h @@ -7,7 +7,7 @@ class TransformComponent : public Component { public: Vector2D position; - Vector2D velocity; + Vector2D direction; int height = 32; int width = 32; diff --git a/include/Vector2D.h b/include/Vector2D.h index 11704a7..bc2d652 100644 --- a/include/Vector2D.h +++ b/include/Vector2D.h @@ -1,5 +1,8 @@ #pragma once +#include +#include + class Vector2D { public: @@ -17,4 +20,6 @@ public: Vector2D& operator*(const int& i); Vector2D& zero(); -}; \ No newline at end of file +}; + +SDL_Rect operator+(const SDL_Rect& rect, const Vector2D& vector2D); \ No newline at end of file diff --git a/src/AssetManager.cpp b/src/AssetManager.cpp index 766fe27..d30e7de 100644 --- a/src/AssetManager.cpp +++ b/src/AssetManager.cpp @@ -1,5 +1,6 @@ #include "AssetManager.h" +#include "Entity.h" #include "TextureManager.h" #include "Components.h" @@ -15,7 +16,7 @@ SDL_Texture* AssetManager::getTexture(std::string id) { return textures.at(id); } -void AssetManager::createProjectile(Vector2D pos, Vector2D velocity, bool source, int scale, int range, int speed, const char* texturePath) { +void AssetManager::createProjectile(Vector2D pos, Vector2D velocity, bool source, int scale, int range, int speed, const char* texturePath, TeamLabel teamLabel) { auto& projectile(man->addEntity()); projectile.addComponent(pos.x, pos.y, 32, 32, scale); //32x32 is standard size for objects @@ -23,4 +24,5 @@ void AssetManager::createProjectile(Vector2D pos, Vector2D velocity, bool source projectile.addComponent(range, speed, velocity, source); projectile.addComponent("projectile", 0.6f); projectile.addGroup((size_t)GroupLabel::PROJECTILE); + projectile.setTeam(teamLabel); } \ No newline at end of file diff --git a/src/ColliderComponent.cpp b/src/ColliderComponent.cpp index d5ea1e5..a186d9d 100644 --- a/src/ColliderComponent.cpp +++ b/src/ColliderComponent.cpp @@ -28,6 +28,7 @@ void ColliderComponent::init() transform = &entity->getComponent(); //Game::collisionHandler->add(this); + this->update(); } void ColliderComponent::update() diff --git a/src/CollisionHandler.cpp b/src/CollisionHandler.cpp index 98173e2..fc9ac42 100644 --- a/src/CollisionHandler.cpp +++ b/src/CollisionHandler.cpp @@ -11,11 +11,6 @@ #include #include -IntersectionBitSet CollisionHandler::getIntersection(Entity* entityA, Entity* entityB) -{ - return getIntersection(entityA, entityB, Vector2D(0,0), Vector2D(0,0)); -} - IntersectionBitSet CollisionHandler::getIntersection(Entity* entityA, Entity* entityB, Vector2D posModA, Vector2D posModB) { if (!entityA->hasComponent() || @@ -60,11 +55,6 @@ IntersectionBitSet CollisionHandler::getIntersection(Entity* entityA, Entity* en return intersections; } -IntersectionBitSet CollisionHandler::getIntersectionWithBounds(Entity* entity) -{ - return getIntersectionWithBounds(entity, Vector2D(0,0)); -} - IntersectionBitSet CollisionHandler::getIntersectionWithBounds(Entity* entity, Vector2D posMod) { if (!entity->hasComponent()) @@ -76,8 +66,9 @@ IntersectionBitSet CollisionHandler::getIntersectionWithBounds(Entity* entity, V // all 4 directions and both sides to allow checking for fully out of bounds if (collider->x + posMod.x < 0 || - collider->x + posMod.x > SCREEN_SIZE_WIDTH) + collider->x + posMod.x > SCREEN_SIZE_WIDTH) { intersections.set((size_t) direction::LEFT); + } if (collider->x + collider->w + posMod.x < 0 || collider->x + collider->w + posMod.x > SCREEN_SIZE_WIDTH) @@ -94,7 +85,10 @@ IntersectionBitSet CollisionHandler::getIntersectionWithBounds(Entity* entity, V return intersections; } -std::vector CollisionHandler::getColliders(std::initializer_list const& groupLabels) +std::vector CollisionHandler::getColliders( + std::initializer_list const& groupLabels, + std::initializer_list const& teamLabels, + bool negateTeam) { std::vector colliders; @@ -103,13 +97,52 @@ std::vector CollisionHandler::getColliders(std::initializer_ groupBitSet.set((size_t) groupLabel); } + std::bitset teamBitSet; + for (auto& teamLabel : teamLabels) { + teamBitSet.set((size_t) teamLabel); + } + for (auto& entity : manager.getAll()) { if ((groupBitSet & entity->getGroupBitSet()).none()) continue; + if (teamBitSet.any() && negateTeam != (teamBitSet.test((size_t) entity->getTeam()))) + continue; if (!entity->hasComponent()) continue; colliders.emplace_back(&entity->getComponent()); } return colliders; -} \ No newline at end of file +} + +template<> +IntersectionBitSet CollisionHandler::getAnyIntersection( + Entity* entity, + Vector2D posMod, + std::initializer_list const& groupLabels, + std::initializer_list const& teamLabels, + bool negateTeam) +{ + IntersectionBitSet intersections; + for (auto& collider : getColliders(groupLabels, teamLabels)) { + intersections |= getIntersection(entity, collider->entity, posMod); + } + return intersections; +}; + +template<> +Entity* CollisionHandler::getAnyIntersection( + Entity* entity, + Vector2D posMod, + std::initializer_list const& groupLabels, + std::initializer_list const& teamLabels, + bool negateTeam) +{ + for (auto& collider : getColliders(groupLabels, teamLabels)) { + SDL_Rect rect = entity->getComponent().collider + posMod; + if (SDL_HasIntersection(&rect, &collider->collider)) { + return collider->entity; + } + } + return nullptr; +}; \ No newline at end of file diff --git a/src/Entity.cpp b/src/Entity.cpp index bd9b79a..0f523ea 100644 --- a/src/Entity.cpp +++ b/src/Entity.cpp @@ -37,7 +37,7 @@ std::bitset Entity::getGroupBitSet() void Entity::setTeam(TeamLabel teamLabel) { - teamLabel = teamLabel; + this->teamLabel = teamLabel; manager.addToTeam(this, (size_t) teamLabel); } diff --git a/src/Game.cpp b/src/Game.cpp index 0874e1a..3fc3498 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -4,7 +4,9 @@ #include "Components.h" #include "AssetManager.h" +#include "Direction.h" #include "Entity.h" +#include "HealthComponent.h" #include "Map.h" #include "TextureManager.h" @@ -113,27 +115,28 @@ void Game::init(const char* title, int xpos, int ypos, int width, int height, bo //ecs implementation + + player1.setTeam(TeamLabel::BLUE); player1.addComponent(80,80,2); //posx, posy, scale player1.addComponent("assets/chicken_knight_spritesheet.png", true); //adds sprite (32x32px), path needed player1.addComponent(SDL_SCANCODE_W, SDL_SCANCODE_S, SDL_SCANCODE_A, SDL_SCANCODE_D, SDL_SCANCODE_E, Vector2D(1, 0));//custom keycontrols can be added player1.addComponent("player", 0.8f); //adds tag (for further use, reference tag) - player1.addComponent(5, &manager, true); + player1.addComponent(5, Direction::LEFT); player1.addGroup((size_t) GroupLabel::PLAYERS); //tell programm what group it belongs to for rendering order - player1.setTeam(TeamLabel::BLUE); + + player2.setTeam(TeamLabel::RED); player2.addComponent(600, 500, 2); player2.addComponent("assets/chicken_spritesheet.png", true); player2.addComponent(SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_RCTRL, Vector2D(-1, 0)); player2.addComponent("enemy", 0.8f); - player2.addComponent(5, &manager, false); + player2.addComponent(5, Direction::RIGHT); player2.addGroup((size_t) GroupLabel::PLAYERS); - player2.setTeam(TeamLabel::RED); } auto& tiles(manager.getGroup((size_t)GroupLabel::MAPTILES)); auto& players(manager.getGroup((size_t)GroupLabel::PLAYERS)); -auto& enemies(manager.getGroup((size_t)GroupLabel::PLAYERS)); auto& projectiles(manager.getGroup((size_t)GroupLabel::PROJECTILE)); auto& hearts(manager.getGroup((size_t)GroupLabel::HEARTS)); @@ -159,50 +162,10 @@ void Game::update() manager.refresh(); manager.update(); - //checking if projectiles hit player1 or player2 - for (auto& p : projectiles) { - if(SDL_HasIntersection(&player2.getComponent().collider, &p->getComponent().collider) - && (p->getComponent().hasCollision) && !p->getComponent().getSource()) { - //std::cout << "Enemy hit!"; - p->getComponent().removeCollision(); - p->destroy(); - - player2.getComponent().getDamage(); - - //display updated health | pretty scuffed but works ig - for(auto h : hearts) - h->destroy(); - - player1.getComponent().createAllHearts(); - player2.getComponent().createAllHearts(); - - if(player2.getComponent().getHealth() < 1) { - std::cout << "Player1 wins!" << std::endl; - winner = true; - isRunning = false; - } - } - - if(SDL_HasIntersection(&player1.getComponent().collider, &p->getComponent().collider) - && (p->getComponent().hasCollision) && p->getComponent().getSource()) { - //std::cout << "Player hit!"; - p->getComponent().removeCollision(); - p->destroy(); - - player1.getComponent().getDamage(); - - //display updated health - for(auto h : hearts) - h->destroy(); - - player1.getComponent().createAllHearts(); - player2.getComponent().createAllHearts(); - - if(player1.getComponent().getHealth() < 1) { - std::cout << "Player2 wins!" << std::endl; - winner = false; - isRunning = false; - } + // needs to be in game.cpp to have access to internal functions + for (auto& player : manager.getGroup((size_t) GroupLabel::PLAYERS)) { + if (player->getComponent().getHealth() <= 0) { + this->setWinner(player->getTeam()); } } } @@ -218,10 +181,6 @@ void Game::render() { p->draw(); } - for (auto& e : enemies) - { - e->draw(); - } for (auto& p : projectiles) p->draw(); @@ -239,7 +198,7 @@ void Game::clean() std::cout << "Game Cleaned!" << std::endl; } -void Game::addTile(int id, int x, int y) +void Game::addTile(unsigned long id, int x, int y) { auto& tile(manager.addEntity()); tile.addComponent(x, y, TILE_SIZE, TILE_SIZE, id); @@ -252,6 +211,13 @@ bool Game::running() const return isRunning; } -bool Game::getWinner() { +void Game::setWinner(TeamLabel winningTeam) +{ + this->winner = winningTeam; + this->isRunning = false; +} + +TeamLabel Game::getWinner() +{ return this->winner; } \ No newline at end of file diff --git a/src/HealthComponent.cpp b/src/HealthComponent.cpp index 67b2070..4f9132b 100644 --- a/src/HealthComponent.cpp +++ b/src/HealthComponent.cpp @@ -1,26 +1,43 @@ #include "HealthComponent.h" #include "Components.h" +#include "Direction.h" +#include "Entity.h" +#include "Game.h" +#include void HealthComponent::init() { - createAllHearts(); + resetHearts(); } -void HealthComponent::createAllHearts() +void HealthComponent::modifyHealth(int health) { + this->health += health; + this->resetHearts(); +} + +void HealthComponent::resetHearts() +{ + // clear hearts if exist + for (auto& heart : this->entity->getManager().getGroup((size_t) GroupLabel::HEARTS)) { + if (heart->getTeam() == this->entity->getTeam()) { + heart->destroy(); + } + } + int x; //starting position for first health icon - if(player) { + if(side == Direction::LEFT) { x = 10; } else { x = 730; } for(int i = 0; i < health; i++) { - + //checks for player side - if(player) { + if (side == Direction::LEFT) { createHeartComponents(x); x += 50; continue; @@ -31,10 +48,11 @@ void HealthComponent::createAllHearts() } } - void HealthComponent::createHeartComponents(int x) +void HealthComponent::createHeartComponents(int x) { - auto& heart(manager->addEntity()); + auto& heart(this->entity->getManager().addEntity()); heart.addComponent(x,5,2); heart.addComponent("assets/heart.png"); heart.addGroup((size_t)GroupLabel::HEARTS); + heart.setTeam(this->entity->getTeam()); } \ No newline at end of file diff --git a/src/KeyboardController.cpp b/src/KeyboardController.cpp index 2880fe0..507a44e 100644 --- a/src/KeyboardController.cpp +++ b/src/KeyboardController.cpp @@ -23,27 +23,27 @@ void KeyboardController::init() void KeyboardController::update() { - transform->velocity.x = 0; - transform->velocity.y = 0; + transform->direction.x = 0; + transform->direction.y = 0; sprite->playAnimation(IDLE); if (keystates[this->up]) { - transform->velocity.y = -1; + transform->direction.y = -1; sprite->playAnimation(WALK); } if (keystates[this->left]) { - transform->velocity.x = -1; + transform->direction.x = -1; sprite->playAnimation(WALK); - sprite->setDirection(LEFT); + sprite->setDirection(Direction::LEFT); } if (keystates[this->down]) { - transform->velocity.y = 1; + transform->direction.y = 1; sprite->playAnimation(WALK); } if (keystates[this->right]) { - transform->velocity.x = 1; + transform->direction.x = 1; sprite->playAnimation(WALK); - sprite->setDirection(RIGHT); + sprite->setDirection(Direction::RIGHT); } if (keystates[this->fire]) { @@ -57,14 +57,14 @@ void KeyboardController::update() //checks player source via the firing velocity //TODO: adding actual projectile textures if (fireVelocity.x > 0) { - sprite->setDirection(RIGHT); + sprite->setDirection(Direction::RIGHT); Game::assets->createProjectile(Vector2D(player->position.x, player->position.y), fireVelocity, - false, 1, 180, 1, "assets/egg.png"); + false, 1, 180, 1, "assets/egg.png", this->entity->getTeam()); } else { - sprite->setDirection(LEFT); + sprite->setDirection(Direction::LEFT); Game::assets->createProjectile(Vector2D(player->position.x, player->position.y), fireVelocity, - true, 1, 180, 1, "assets/egg.png"); + true, 1, 180, 1, "assets/egg.png", this->entity->getTeam()); } lastFireTime = currentTicks; diff --git a/src/Manager.cpp b/src/Manager.cpp index f3aa133..f98ebdc 100644 --- a/src/Manager.cpp +++ b/src/Manager.cpp @@ -50,22 +50,22 @@ void Manager::update() void Manager::addToGroup(Entity* mEntity, Group mGroup) { - entitiesByGroup[mGroup].emplace_back(mEntity); + entitiesByGroup.at(mGroup).emplace_back(mEntity); } std::vector& Manager::getGroup(Group mGroup) { - return entitiesByGroup[mGroup]; + return entitiesByGroup.at(mGroup); } void Manager::addToTeam(Entity* mEntity, Team mTeam) { - entitiesByTeam[mTeam].emplace_back(mEntity); + entitiesByTeam.at(mTeam).emplace_back(mEntity); // } std::vector& Manager::getTeam(Team mTeam) { - return entitiesByTeam[mTeam]; + return entitiesByTeam.at(mTeam); } std::vector Manager::getAll() diff --git a/src/ProjectileComponent.cpp b/src/ProjectileComponent.cpp index ad50e39..de90155 100644 --- a/src/ProjectileComponent.cpp +++ b/src/ProjectileComponent.cpp @@ -1,21 +1,44 @@ #include "ProjectileComponent.h" +#include "CollisionHandler.h" #include "Components.h" +#include "Entity.h" +#include "Game.h" +#include "HealthComponent.h" +#include "Vector2D.h" +#include +#include void ProjectileComponent::init() { transformComponent = &entity->getComponent(); + transformComponent->direction = direction; } void ProjectileComponent::update() { - transformComponent->velocity = velocity; - distance += speed; + IntersectionBitSet boundsIntersection = Game::collisionHandler->getIntersectionWithBounds(entity); + + if ((boundsIntersection | IntersectionBitSet("1100")).all() || (boundsIntersection | IntersectionBitSet("0011")).all()) { + this->entity->destroy(); + std::cout << "out of bounds" << std::endl; + } + if (distance > range) { - entity->destroy(); - entity->getComponent().removeCollision(); - //std::cout << "out of range" << std::endl; + this->entity->destroy(); + std::cout << "out of range" << std::endl; + } + + Entity* player; + if ((player = Game::collisionHandler->getAnyIntersection( + entity, + Vector2D(0,0), + {GroupLabel::PLAYERS}, + {entity->getTeam()}, + true)) != nullptr) { + player->getComponent().modifyHealth(); + this->entity->destroy(); } } \ No newline at end of file diff --git a/src/SpriteComponent.cpp b/src/SpriteComponent.cpp index 6af7d6b..58e2295 100644 --- a/src/SpriteComponent.cpp +++ b/src/SpriteComponent.cpp @@ -2,6 +2,7 @@ #include +#include "Direction.h" #include "TextureManager.h" #include "Entity.h" #include "TransformComponent.h" @@ -71,9 +72,9 @@ void SpriteComponent::playAnimation(AnimationType type) this->speed = animations.at(type)->speed; } -void SpriteComponent::setDirection(SpriteDirection direction) +void SpriteComponent::setDirection(Direction direction) { - if (direction == RIGHT) { + if (direction == Direction::RIGHT) { this->flipped = true; return; } diff --git a/src/TransformComponent.cpp b/src/TransformComponent.cpp index b14ecb9..f6ab5d1 100644 --- a/src/TransformComponent.cpp +++ b/src/TransformComponent.cpp @@ -6,6 +6,8 @@ #include "Entity.h" #include "Game.h" #include "Vector2D.h" +#include +#include #include TransformComponent::TransformComponent() @@ -43,33 +45,29 @@ TransformComponent::TransformComponent(float x, float y, int w, int h, int scale void TransformComponent::init() { - velocity.zero(); + direction.zero(); } void TransformComponent::update() { // if(velocity.x != 0 && velocity.y != 0) - float multiplier = velocity.x != 0 && velocity.y != 0 ? 0.707 : 1; //normalizes vector + float multiplier = direction.x != 0 && direction.y != 0 ? 0.707 : 1; // normalizes vector; only works if directions are in increments of 45° Vector2D positionChange( - velocity.x * speed * multiplier, - velocity.y * speed * multiplier + direction.x * speed * multiplier, + direction.y * speed * multiplier ); // TODO: move to separate functions if (this->entity->hasGroup((size_t) GroupLabel::PLAYERS)) { - IntersectionBitSet intersectionsX = CollisionHandler::getIntersectionWithBounds(entity, positionChange); - for (auto& collider : Game::collisionHandler->getColliders({GroupLabel::MAPTILES, GroupLabel::COLLIDERS})) { - intersectionsX |= CollisionHandler::getIntersection(entity, collider->entity, Vector2D(positionChange.x, 0), Vector2D(0, 0)); - } - - IntersectionBitSet intersectionsY = CollisionHandler::getIntersectionWithBounds(entity, positionChange); - for (auto& collider : Game::collisionHandler->getColliders({GroupLabel::MAPTILES, GroupLabel::COLLIDERS})) { - intersectionsY |= CollisionHandler::getIntersection(entity, collider->entity, Vector2D(0, positionChange.y), Vector2D(0, 0)); - } - - IntersectionBitSet intersections = (intersectionsX & IntersectionBitSet("0011")) | (intersectionsY & IntersectionBitSet("1100")); + IntersectionBitSet intersections = + (CollisionHandler::getIntersectionWithBounds(entity, Vector2D(positionChange.x, 0)) | + (Game::collisionHandler->getAnyIntersection(entity, Vector2D(positionChange.x, 0), {GroupLabel::MAPTILES, GroupLabel::COLLIDERS})) & + IntersectionBitSet("0011")) | + (CollisionHandler::getIntersectionWithBounds(entity, Vector2D(0, positionChange.y)) | + (Game::collisionHandler->getAnyIntersection(entity, Vector2D(0, positionChange.y), {GroupLabel::MAPTILES, GroupLabel::COLLIDERS})) & + IntersectionBitSet("1100")); if (intersections.test((size_t) direction::LEFT) || intersections.test((size_t) direction::RIGHT)) positionChange.x = 0; diff --git a/src/Vector2D.cpp b/src/Vector2D.cpp index 71d2848..6368ff3 100644 --- a/src/Vector2D.cpp +++ b/src/Vector2D.cpp @@ -1,4 +1,5 @@ #include "Vector2D.h" +#include "SDL_rect.h" Vector2D::Vector2D() { @@ -56,3 +57,11 @@ Vector2D& Vector2D::zero() return *this; } + +SDL_Rect operator+(const SDL_Rect& rect, const Vector2D& vector2D) +{ + SDL_Rect newRect = rect; + newRect.x += vector2D.x; + newRect.y += vector2D.y; + return newRect; +} \ No newline at end of file