From 8ff81ace72afbab9bbce01bd15d4aa354464a402 Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Sun, 28 Jan 2024 14:51:01 +0100 Subject: [PATCH 1/5] Rewrite player collisions --- include/CollisionHandler.h | 44 ++++++++++++++++++ include/Component.h | 10 ---- include/Constants.h | 2 + include/Entity.h | 26 ++++++++++- include/Game.h | 4 +- include/Manager.h | 9 ++-- include/PlayerComponent.h | 9 ++++ include/Vector2D.h | 1 + src/ColliderComponent.cpp | 7 +-- src/CollisionHandler.cpp | 94 ++++++++++++++++++++++++++++++++++++++ src/Entity.cpp | 12 +++++ src/Game.cpp | 83 ++++++++++++++++++--------------- src/Manager.cpp | 39 ++++++++++++---- src/PlayerComponent.cpp | 1 + src/TransformComponent.cpp | 48 ++++++++++++++++--- src/Vector2D.cpp | 6 +++ 16 files changed, 324 insertions(+), 71 deletions(-) create mode 100644 include/CollisionHandler.h create mode 100644 include/PlayerComponent.h create mode 100644 src/CollisionHandler.cpp create mode 100644 src/PlayerComponent.cpp diff --git a/include/CollisionHandler.h b/include/CollisionHandler.h new file mode 100644 index 0000000..2783925 --- /dev/null +++ b/include/CollisionHandler.h @@ -0,0 +1,44 @@ +#pragma once + +#include "Entity.h" +#include "SpriteComponent.h" +#include "Vector2D.h" +#include + +class ColliderComponent; +class Manager; +class Entity; + +constexpr uint8_t DIRECTION_C = 4; + +enum class direction +{ + LEFT = 0, + RIGHT, + UP, + DOWN +}; + +using IntersectionBitSet = std::bitset; + +class CollisionHandler +{ +private: + Manager& manager; + +public: + + CollisionHandler(Manager& mManager) : + manager(mManager) { }; + ~CollisionHandler(); + + + 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); + + std::vector getColliders(GroupLabel groupLabel); // temporary function, remove once game.cpp cleaned up + + void update(); +}; \ No newline at end of file diff --git a/include/Component.h b/include/Component.h index bc788ac..095b370 100644 --- a/include/Component.h +++ b/include/Component.h @@ -2,16 +2,6 @@ class Entity; -enum class GroupLabel -{ - MAP, - PLAYERS, - ENEMIES, - COLLIDERS, - PROJECTILE, - HEARTS -}; - class Component { public: diff --git a/include/Constants.h b/include/Constants.h index 502bd2b..cd330f5 100644 --- a/include/Constants.h +++ b/include/Constants.h @@ -3,9 +3,11 @@ #include using Group = std::size_t; +using Team = std::size_t; constexpr std::size_t MAX_COMPONENTS = 32; constexpr std::size_t MAX_GROUPS = 32; +constexpr std::size_t MAX_TEAMS = 8; // constexpr int SCREEN_SIZE_HEIGHT = 640; constexpr int SCREEN_SIZE_WIDTH = 800; diff --git a/include/Entity.h b/include/Entity.h index 326ff7c..630e2fe 100644 --- a/include/Entity.h +++ b/include/Entity.h @@ -15,10 +15,28 @@ using ComponentBitSet = std::bitset; using GroupBitSet = std::bitset; using ComponentArray = std::array; +enum class GroupLabel +{ + MAPTILES, + PLAYERS, + ENEMIES, + COLLIDERS, + PROJECTILE, + HEARTS +}; + +enum class TeamLabel +{ + NONE, + BLUE, + RED +}; + class Entity { public: - explicit Entity(Manager& mManager) : manager(mManager) { } + explicit Entity(Manager& mManager) : + manager(mManager) { }; void update() const; void draw() const; @@ -30,6 +48,11 @@ public: void addGroup(Group mGroup); void delGroup(Group mGroup); + void setTeam(TeamLabel teamLabel); + TeamLabel getTeam(); + + Manager& getManager() { return manager; }; + template bool hasComponent() const { return componentBitSet[getComponentTypeID()]; @@ -63,4 +86,5 @@ private: ComponentArray componentArray = {}; ComponentBitSet componentBitSet; GroupBitSet groupBitSet; + TeamLabel teamLabel; }; \ No newline at end of file diff --git a/include/Game.h b/include/Game.h index ed07f38..64fa511 100644 --- a/include/Game.h +++ b/include/Game.h @@ -5,7 +5,7 @@ #include class AssetManager; -class ColliderComponent; +class CollisionHandler; class Game { @@ -24,7 +24,7 @@ public: static void addTile(int id, int x, int y); static SDL_Renderer* renderer; static SDL_Event event; - static std::vector colliders; + static CollisionHandler* collisionHandler; static AssetManager* assets; bool getWinner(); diff --git a/include/Manager.h b/include/Manager.h index f85f3b8..0046c33 100644 --- a/include/Manager.h +++ b/include/Manager.h @@ -5,8 +5,7 @@ #include #include "Constants.h" - -class Entity; +#include "Entity.h" class Manager { @@ -18,9 +17,13 @@ public: void addToGroup(Entity* mEntity, Group mGroup); std::vector& getGroup(Group mGroup); + void addToTeam(Entity* mEntity, Team mTeam); + std::vector& getTeam(Team mTeam); + Entity& addEntity(); private: std::vector> entities; - std::array, MAX_GROUPS> groupedEntities; + std::array, MAX_GROUPS> entitiesByGroup; + std::array, MAX_TEAMS> entitiesByTeam; }; \ No newline at end of file diff --git a/include/PlayerComponent.h b/include/PlayerComponent.h new file mode 100644 index 0000000..922fd04 --- /dev/null +++ b/include/PlayerComponent.h @@ -0,0 +1,9 @@ +#pragma once + +#include "Component.h" + +class PlayerComponent : public Component +{ +public: +private: +}; \ No newline at end of file diff --git a/include/Vector2D.h b/include/Vector2D.h index 96380f8..11704a7 100644 --- a/include/Vector2D.h +++ b/include/Vector2D.h @@ -13,6 +13,7 @@ public: friend Vector2D& operator-(Vector2D& vector1, const Vector2D& vector2); friend Vector2D& operator*(Vector2D& vector1, const Vector2D& vector2); friend Vector2D& operator/(Vector2D& vector1, const Vector2D& vector2); + friend Vector2D& operator+=(Vector2D& vector1, const Vector2D& vector2); Vector2D& operator*(const int& i); Vector2D& zero(); diff --git a/src/ColliderComponent.cpp b/src/ColliderComponent.cpp index d1c59c0..d5ea1e5 100644 --- a/src/ColliderComponent.cpp +++ b/src/ColliderComponent.cpp @@ -1,5 +1,6 @@ #include "ColliderComponent.h" +#include "CollisionHandler.h" #include "Entity.h" #include "Game.h" #include "TransformComponent.h" @@ -26,13 +27,13 @@ void ColliderComponent::init() } transform = &entity->getComponent(); - Game::colliders.push_back(this); + //Game::collisionHandler->add(this); } void ColliderComponent::update() { - collider.x = transform->position.x; - collider.y = transform->position.y; + collider.x = transform->position.x - (transform->width - transform->width * transform->scale * this->hitboxScale) / 2; + collider.y = transform->position.y - (transform->width - transform->width * transform->scale * this->hitboxScale) / 2; collider.w = (transform->width * transform->scale) * this->hitboxScale; diff --git a/src/CollisionHandler.cpp b/src/CollisionHandler.cpp new file mode 100644 index 0000000..a96f54a --- /dev/null +++ b/src/CollisionHandler.cpp @@ -0,0 +1,94 @@ +#include "CollisionHandler.h" + +#include "ColliderComponent.h" +#include "Constants.h" +#include "Entity.h" +#include "Manager.h" +#include "Vector2D.h" + +#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() || + !entityB->hasComponent()) + return std::bitset(); + + SDL_Rect* colliderA = &entityA->getComponent().collider; + SDL_Rect* colliderB = &entityB->getComponent().collider; + + if (!SDL_HasIntersection( + colliderA, + colliderB)) + return std::bitset(); + + std::bitset intersections; + + // checks all 4 directions to allow checking full overlap + if (colliderA->x + posModA.x < colliderB->x + colliderB->w + posModB.x) + intersections.set((size_t) direction::LEFT) = 1; + + if (colliderA->x + colliderA->w + posModA.x > colliderB->x + posModB.x) + intersections.set((size_t) direction::RIGHT) = 1; + + if (colliderA->y + posModA.y < colliderB->y + colliderB->h + posModB.y) + intersections.set((size_t) direction::UP) = 1; + + if (colliderA->y + colliderA->h + posModA.y > colliderB->y + posModB.y) + intersections.set((size_t) direction::DOWN) = 1; + + return intersections; +} + +IntersectionBitSet CollisionHandler::getIntersectionWithBounds(Entity* entity) +{ + return getIntersectionWithBounds(entity, Vector2D(0,0)); +} + +IntersectionBitSet CollisionHandler::getIntersectionWithBounds(Entity* entity, Vector2D posMod) +{ + if (!entity->hasComponent()) + return std::bitset(); + + SDL_Rect* collider = &entity->getComponent().collider; + + std::bitset intersections; + + // 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) + intersections.set((size_t) direction::LEFT); + + if (collider->x + collider->w + posMod.x < 0 || + collider->x + collider->w + posMod.x > SCREEN_SIZE_WIDTH) + intersections.set((size_t) direction::RIGHT); + + if (collider->y + posMod.y < 0 || + collider->y + posMod.y > SCREEN_SIZE_HEIGHT) + intersections.set((size_t) direction::UP); + + if (collider->y + collider->h + posMod.y < 0 || + collider->y + collider->h + posMod.y > SCREEN_SIZE_HEIGHT) + intersections.set((size_t) direction::DOWN); + + return intersections; +} + +std::vector CollisionHandler::getColliders(GroupLabel groupLabel) +{ + std::vector colliders; + + for (auto& entity : manager.getGroup((size_t) groupLabel)) { + if (!entity->hasComponent()) + continue; + colliders.emplace_back(&entity->getComponent()); + } + + return colliders; +} \ No newline at end of file diff --git a/src/Entity.cpp b/src/Entity.cpp index 8ec725d..6817071 100644 --- a/src/Entity.cpp +++ b/src/Entity.cpp @@ -2,6 +2,7 @@ #include "Manager.h" #include "Component.h" +#include void Entity::update() const { @@ -28,3 +29,14 @@ void Entity::delGroup(Group mGroup) { groupBitSet[mGroup] = false; } + +void Entity::setTeam(TeamLabel teamLabel) +{ + teamLabel = teamLabel; + manager.addToTeam(this, (size_t) teamLabel); +} + +TeamLabel Entity::getTeam() +{ + return teamLabel; +} diff --git a/src/Game.cpp b/src/Game.cpp index a979a8b..a365d63 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -1,8 +1,10 @@ #include "Game.h" +#include "CollisionHandler.h" #include "Components.h" #include "AssetManager.h" +#include "Entity.h" #include "Map.h" #include "TextureManager.h" @@ -11,14 +13,15 @@ Manager manager; AssetManager* Game::assets = new AssetManager(&manager); +CollisionHandler* Game::collisionHandler = new CollisionHandler(manager); + SDL_Renderer* Game::renderer = nullptr; SDL_Event Game::event; -std::vector Game::colliders; +auto& player1(manager.addEntity()); +auto& player2(manager.addEntity()); -auto& player(manager.addEntity()); -auto& enemy(manager.addEntity()); auto& wall(manager.addEntity()); //auto& projectile (manager.addEntity()); @@ -110,25 +113,27 @@ void Game::init(const char* title, int xpos, int ypos, int width, int height, bo //ecs implementation - player.addComponent(80,80,2); //posx, posy, scale - player.addComponent("assets/chicken_knight_spritesheet.png", true); //adds sprite (32x32px), path needed - player.addComponent(SDL_SCANCODE_W, SDL_SCANCODE_S, SDL_SCANCODE_A, SDL_SCANCODE_D, SDL_SCANCODE_E, Vector2D(1, 0));//custom keycontrols can be added - player.addComponent("player", 0.8f); //adds tag (for further use, reference tag) - player.addComponent(5, &manager, true); - player.addGroup((size_t)GroupLabel::PLAYERS); //tell programm what group it belongs to for rendering order + 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.addGroup((size_t) GroupLabel::PLAYERS); //tell programm what group it belongs to for rendering order + player1.setTeam(TeamLabel::BLUE); - enemy.addComponent(600, 500, 2); - enemy.addComponent("assets/chicken_spritesheet.png", true); - enemy.addComponent(SDL_SCANCODE_UP, SDL_SCANCODE_DOWN, SDL_SCANCODE_LEFT, SDL_SCANCODE_RIGHT, SDL_SCANCODE_RCTRL, Vector2D(-1, 0)); - enemy.addComponent("enemy", 0.8f); - enemy.addComponent(5, &manager, false); - enemy.addGroup((size_t)GroupLabel::ENEMIES); + 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.addGroup((size_t) GroupLabel::PLAYERS); + player2.setTeam(TeamLabel::RED); } -auto& tiles(manager.getGroup((size_t)GroupLabel::MAP)); +auto& tiles(manager.getGroup((size_t)GroupLabel::MAPTILES)); auto& players(manager.getGroup((size_t)GroupLabel::PLAYERS)); -auto& enemies(manager.getGroup((size_t)GroupLabel::ENEMIES)); +auto& enemies(manager.getGroup((size_t)GroupLabel::PLAYERS)); auto& projectiles(manager.getGroup((size_t)GroupLabel::PROJECTILE)); auto& hearts(manager.getGroup((size_t)GroupLabel::HEARTS)); @@ -148,64 +153,70 @@ void Game::handleEvents() void Game::update() { - Vector2D playerPos = player.getComponent().position; - Vector2D enemyPos = enemy.getComponent().position; + Vector2D playerPos = player1.getComponent().position; + Vector2D enemyPos = player2.getComponent().position; manager.refresh(); manager.update(); - for (auto cc : colliders) + + + /*for (auto cc : Game::collisionHandler->getColliders(GroupLabel::COLLIDERS)) { - if (SDL_HasIntersection(&player.getComponent().collider, &cc->collider) && strcmp(cc->tag, "player") && cc->hasCollision) + if (cc->hasCollision && + strcmp(cc->tag, "player") && + SDL_HasIntersection(&player1.getComponent().collider, &cc->collider)) { - player.getComponent().position = playerPos; + player1.getComponent().position = playerPos; } - if (SDL_HasIntersection(&enemy.getComponent().collider, &cc->collider) && strcmp(cc->tag, "enemy") && cc->hasCollision) + if (cc->hasCollision && + strcmp(cc->tag, "enemy") && + SDL_HasIntersection(&player2.getComponent().collider, &cc->collider)) { - enemy.getComponent().position = enemyPos; + player2.getComponent().position = enemyPos; } - } + }*/ //checking if projectiles hit player1 or player2 for (auto& p : projectiles) { - if(SDL_HasIntersection(&enemy.getComponent().collider, &p->getComponent().collider) + if(SDL_HasIntersection(&player2.getComponent().collider, &p->getComponent().collider) && (p->getComponent().hasCollision) && !p->getComponent().getSource()) { //std::cout << "Enemy hit!"; p->getComponent().removeCollision(); p->destroy(); - enemy.getComponent().getDamage(); + player2.getComponent().getDamage(); //display updated health | pretty scuffed but works ig for(auto h : hearts) h->destroy(); - player.getComponent().createAllHearts(); - enemy.getComponent().createAllHearts(); + player1.getComponent().createAllHearts(); + player2.getComponent().createAllHearts(); - if(enemy.getComponent().getHealth() < 1) { + if(player2.getComponent().getHealth() < 1) { std::cout << "Player1 wins!" << std::endl; winner = true; isRunning = false; } } - if(SDL_HasIntersection(&player.getComponent().collider, &p->getComponent().collider) + if(SDL_HasIntersection(&player1.getComponent().collider, &p->getComponent().collider) && (p->getComponent().hasCollision) && p->getComponent().getSource()) { //std::cout << "Player hit!"; p->getComponent().removeCollision(); p->destroy(); - player.getComponent().getDamage(); + player1.getComponent().getDamage(); //display updated health for(auto h : hearts) h->destroy(); - player.getComponent().createAllHearts(); - enemy.getComponent().createAllHearts(); + player1.getComponent().createAllHearts(); + player2.getComponent().createAllHearts(); - if(player.getComponent().getHealth() < 1) { + if(player1.getComponent().getHealth() < 1) { std::cout << "Player2 wins!" << std::endl; winner = false; isRunning = false; @@ -251,7 +262,7 @@ void Game::addTile(int id, int x, int y) auto& tile(manager.addEntity()); tile.addComponent(x, y, TILE_SIZE, TILE_SIZE, id); if (id == 1) tile.addComponent("water"); - tile.addGroup((size_t)GroupLabel::MAP); + tile.addGroup((size_t)GroupLabel::MAPTILES); } bool Game::running() const diff --git a/src/Manager.cpp b/src/Manager.cpp index ba800b1..3759704 100644 --- a/src/Manager.cpp +++ b/src/Manager.cpp @@ -2,12 +2,7 @@ #include -#include "Entity.h" - -void Manager::update() -{ - for (auto& e : entities) e->update(); -} +#include "Constants.h" void Manager::draw() { @@ -18,7 +13,7 @@ void Manager::refresh() { for (auto i(0u); i < MAX_GROUPS; i++) { - auto& v(groupedEntities[i]); + auto& v(entitiesByGroup[i]); v.erase( std::remove_if(std::begin(v), std::end(v), [i](Entity* mEntity) @@ -27,6 +22,17 @@ void Manager::refresh() }), std::end(v)); } + for (auto i(0u); i < MAX_TEAMS; i++) + { + auto& v(entitiesByTeam[i]); + v.erase( + std::remove_if(std::begin(v), std::end(v), + [i](Entity* mEntity) + { + return !mEntity->isActive() || (size_t)(mEntity->getTeam()) != i; + }), std::end(v)); + } + entities.erase(std::remove_if(std::begin(entities), std::end(entities), [](const std::unique_ptr& mEntity) { @@ -35,14 +41,29 @@ void Manager::refresh() std::end(entities)); } +void Manager::update() +{ + for (auto& e : entities) e->update(); +} + void Manager::addToGroup(Entity* mEntity, Group mGroup) { - groupedEntities[mGroup].emplace_back(mEntity); + entitiesByGroup[mGroup].emplace_back(mEntity); } std::vector& Manager::getGroup(Group mGroup) { - return groupedEntities[mGroup]; + return entitiesByGroup[mGroup]; +} + +void Manager::addToTeam(Entity* mEntity, Team mTeam) +{ + entitiesByTeam[mTeam].emplace_back(mEntity); +} + +std::vector& Manager::getTeam(Team mTeam) +{ + return entitiesByTeam[mTeam]; } Entity& Manager::addEntity() diff --git a/src/PlayerComponent.cpp b/src/PlayerComponent.cpp new file mode 100644 index 0000000..3afa811 --- /dev/null +++ b/src/PlayerComponent.cpp @@ -0,0 +1 @@ +#include "PlayerComponent.h" \ No newline at end of file diff --git a/src/TransformComponent.cpp b/src/TransformComponent.cpp index 9f73934..f77278b 100644 --- a/src/TransformComponent.cpp +++ b/src/TransformComponent.cpp @@ -1,5 +1,12 @@ #include "TransformComponent.h" + +#include "CollisionHandler.h" +#include "ColliderComponent.h" #include "Constants.h" +#include "Entity.h" +#include "Game.h" +#include "Vector2D.h" +#include TransformComponent::TransformComponent() { @@ -44,12 +51,39 @@ void TransformComponent::update() // if(velocity.x != 0 && velocity.y != 0) float multiplier = velocity.x != 0 && velocity.y != 0 ? 0.707 : 1; //normalizes vector - Vector2D newPos( - position.x + velocity.x * speed * multiplier, - position.y + velocity.y * speed * multiplier + Vector2D positionChange( + velocity.x * speed * multiplier, + velocity.y * speed * multiplier ); - if (newPos.x < 0 || newPos.x + (this->width * this->scale) > SCREEN_SIZE_WIDTH || newPos.y < 0 || newPos.y + (this->height * this->scale) > SCREEN_SIZE_HEIGHT) - return; - position = newPos; -} + 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)) { + 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)) { + 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; + + if (intersectionsX.test((size_t) direction::RIGHT) && positionChange.x > 0) + 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) + positionChange.y = 0; + + position += positionChange; + +}; \ No newline at end of file diff --git a/src/Vector2D.cpp b/src/Vector2D.cpp index 7fae1a5..71d2848 100644 --- a/src/Vector2D.cpp +++ b/src/Vector2D.cpp @@ -36,6 +36,12 @@ Vector2D& operator/(Vector2D& vector1, const Vector2D& vector2) vector1.y /= vector2.y; return vector1; } +Vector2D& operator+=(Vector2D& vector1, const Vector2D& vector2) +{ + vector1.x += vector2.x; + vector1.y += vector2.y; + return vector1; +} Vector2D& Vector2D::operator*(const int& i) { this->x *= i; From 0c1c9a7f840438e1937d39f52d0434e126975578 Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Sun, 28 Jan 2024 15:10:01 +0100 Subject: [PATCH 2/5] Hotfix only calculate for player --- src/Game.cpp | 18 ------------ src/TransformComponent.cpp | 60 +++++++++++++++++++++----------------- 2 files changed, 33 insertions(+), 45 deletions(-) diff --git a/src/Game.cpp b/src/Game.cpp index a365d63..0874e1a 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -159,24 +159,6 @@ void Game::update() manager.refresh(); manager.update(); - - - /*for (auto cc : Game::collisionHandler->getColliders(GroupLabel::COLLIDERS)) - { - if (cc->hasCollision && - strcmp(cc->tag, "player") && - SDL_HasIntersection(&player1.getComponent().collider, &cc->collider)) - { - player1.getComponent().position = playerPos; - } - if (cc->hasCollision && - strcmp(cc->tag, "enemy") && - SDL_HasIntersection(&player2.getComponent().collider, &cc->collider)) - { - player2.getComponent().position = enemyPos; - } - }*/ - //checking if projectiles hit player1 or player2 for (auto& p : projectiles) { if(SDL_HasIntersection(&player2.getComponent().collider, &p->getComponent().collider) diff --git a/src/TransformComponent.cpp b/src/TransformComponent.cpp index f77278b..3065e1f 100644 --- a/src/TransformComponent.cpp +++ b/src/TransformComponent.cpp @@ -56,34 +56,40 @@ void TransformComponent::update() velocity.y * speed * multiplier ); - 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)); + // 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)) { + intersectionsX |= CollisionHandler::getIntersection(entity, collider->entity, Vector2D(positionChange.x, 0), Vector2D(0, 0)); + } + for (auto& collider : Game::collisionHandler->getColliders(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)) { + intersectionsY |= CollisionHandler::getIntersection(entity, collider->entity, Vector2D(0, positionChange.y), Vector2D(0, 0)); + } + + if (this->entity->hasGroup((size_t) GroupLabel::PLAYERS) && this->entity->getTeam() == TeamLabel::BLUE) + std::cout << intersectionsX << std::endl; + + if (intersectionsX.test((size_t) direction::LEFT) && positionChange.x < 0) + positionChange.x = 0; + + if (intersectionsX.test((size_t) direction::RIGHT) && positionChange.x > 0) + 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) + positionChange.y = 0; } - for (auto& collider : Game::collisionHandler->getColliders(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)) { - 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; - - if (intersectionsX.test((size_t) direction::RIGHT) && positionChange.x > 0) - 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) - positionChange.y = 0; position += positionChange; - }; \ No newline at end of file From f538e95623520f8901581a0dc5a2bf30e95fe456 Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Sun, 28 Jan 2024 15:19:27 +0100 Subject: [PATCH 3/5] Hotfix collision to the right breaks sliding --- src/CollisionHandler.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/CollisionHandler.cpp b/src/CollisionHandler.cpp index a96f54a..b809f31 100644 --- a/src/CollisionHandler.cpp +++ b/src/CollisionHandler.cpp @@ -8,6 +8,7 @@ #include #include +#include IntersectionBitSet CollisionHandler::getIntersection(Entity* entityA, Entity* entityB) { @@ -31,17 +32,25 @@ IntersectionBitSet CollisionHandler::getIntersection(Entity* entityA, Entity* en std::bitset intersections; // checks all 4 directions to allow checking full overlap - if (colliderA->x + posModA.x < colliderB->x + colliderB->w + posModB.x) - intersections.set((size_t) direction::LEFT) = 1; + if (colliderA->x + posModA.x < colliderB->x + colliderB->w + posModB.x && + colliderA->x + posModA.x > colliderB->x + posModB.x) { + printf("%zu left\n", (size_t) direction::LEFT); + intersections.set((size_t) direction::LEFT); + } - if (colliderA->x + colliderA->w + posModA.x > colliderB->x + posModB.x) - intersections.set((size_t) direction::RIGHT) = 1; + if (colliderA->x + colliderA->w + posModA.x < colliderB->x + colliderB->w + posModB.x && + colliderA->x + colliderA->w + posModA.x > colliderB->x + posModB.x) { + printf("%zu right\n", (size_t) direction::RIGHT); + intersections.set((size_t) direction::RIGHT); + } - if (colliderA->y + posModA.y < colliderB->y + colliderB->h + posModB.y) - intersections.set((size_t) direction::UP) = 1; + if (colliderA->y + posModA.y < colliderB->y + colliderB->h + posModB.y && + colliderA->y + posModA.y > colliderB->y + posModB.y) + intersections.set((size_t) direction::UP); - if (colliderA->y + colliderA->h + posModA.y > colliderB->y + posModB.y) - intersections.set((size_t) direction::DOWN) = 1; + if (colliderA->y + colliderA->h + posModA.y < colliderB->y + colliderB->h + posModB.y && + colliderA->y + colliderA->h + posModA.y > colliderB->y + posModB.y) + intersections.set((size_t) direction::DOWN); return intersections; } From 9f2df7c6c55c6ee70777d76668ab79ccb32a183f Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Sun, 28 Jan 2024 16:59:59 +0100 Subject: [PATCH 4/5] fixed sliding --- include/CollisionHandler.h | 1 + src/CollisionHandler.cpp | 33 +++++++++++++++++++-------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/include/CollisionHandler.h b/include/CollisionHandler.h index 2783925..cf90905 100644 --- a/include/CollisionHandler.h +++ b/include/CollisionHandler.h @@ -1,6 +1,7 @@ #pragma once #include "Entity.h" +#include "SDL_rect.h" #include "SpriteComponent.h" #include "Vector2D.h" #include diff --git a/src/CollisionHandler.cpp b/src/CollisionHandler.cpp index b809f31..f8975d1 100644 --- a/src/CollisionHandler.cpp +++ b/src/CollisionHandler.cpp @@ -9,6 +9,7 @@ #include #include #include +#include IntersectionBitSet CollisionHandler::getIntersection(Entity* entityA, Entity* entityB) { @@ -21,35 +22,39 @@ IntersectionBitSet CollisionHandler::getIntersection(Entity* entityA, Entity* en !entityB->hasComponent()) return std::bitset(); - SDL_Rect* colliderA = &entityA->getComponent().collider; - SDL_Rect* colliderB = &entityB->getComponent().collider; + SDL_Rect colliderA = entityA->getComponent().collider; + SDL_Rect colliderB = entityB->getComponent().collider; + + colliderA.x += posModA.x; + colliderA.y += posModA.y; + + colliderB.x += posModB.x; + colliderB.y += posModB.y; if (!SDL_HasIntersection( - colliderA, - colliderB)) + &colliderA, + &colliderB)) return std::bitset(); std::bitset intersections; // checks all 4 directions to allow checking full overlap - if (colliderA->x + posModA.x < colliderB->x + colliderB->w + posModB.x && - colliderA->x + posModA.x > colliderB->x + posModB.x) { - printf("%zu left\n", (size_t) direction::LEFT); + if (colliderA.x < colliderB.x + colliderB.w && + colliderA.x > colliderB.x) { intersections.set((size_t) direction::LEFT); } - if (colliderA->x + colliderA->w + posModA.x < colliderB->x + colliderB->w + posModB.x && - colliderA->x + colliderA->w + posModA.x > colliderB->x + posModB.x) { - printf("%zu right\n", (size_t) direction::RIGHT); + if (colliderA.x + colliderA.w < colliderB.x + colliderB.w && + colliderA.x + colliderA.w > colliderB.x) { intersections.set((size_t) direction::RIGHT); } - if (colliderA->y + posModA.y < colliderB->y + colliderB->h + posModB.y && - colliderA->y + posModA.y > colliderB->y + posModB.y) + if (colliderA.y < colliderB.y + colliderB.h && + colliderA.y > colliderB.y) intersections.set((size_t) direction::UP); - if (colliderA->y + colliderA->h + posModA.y < colliderB->y + colliderB->h + posModB.y && - colliderA->y + colliderA->h + posModA.y > colliderB->y + posModB.y) + if (colliderA.y + colliderA.h < colliderB.y + colliderB.h && + colliderA.y + colliderA.h > colliderB.y) intersections.set((size_t) direction::DOWN); return intersections; From 4755076c347cc56ed24ae11aaefcaaea13f7d2dd Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Sun, 28 Jan 2024 17:01:18 +0100 Subject: [PATCH 5/5] removed debug print --- src/TransformComponent.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/TransformComponent.cpp b/src/TransformComponent.cpp index 3065e1f..12609dd 100644 --- a/src/TransformComponent.cpp +++ b/src/TransformComponent.cpp @@ -75,9 +75,6 @@ void TransformComponent::update() intersectionsY |= CollisionHandler::getIntersection(entity, collider->entity, Vector2D(0, positionChange.y), Vector2D(0, 0)); } - if (this->entity->hasGroup((size_t) GroupLabel::PLAYERS) && this->entity->getTeam() == TeamLabel::BLUE) - std::cout << intersectionsX << std::endl; - if (intersectionsX.test((size_t) direction::LEFT) && positionChange.x < 0) positionChange.x = 0;