From 7c7c78cacf224ba473cfaf5a9d85f1dcc805eb59 Mon Sep 17 00:00:00 2001 From: ineslelin Date: Fri, 21 Jun 2024 17:39:07 +0200 Subject: [PATCH 1/9] added interaction component --- include/InteractionComponent.h | 23 +++++++++++++++++ src/InteractionComponent.cpp | 46 ++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 include/InteractionComponent.h create mode 100644 src/InteractionComponent.cpp diff --git a/include/InteractionComponent.h b/include/InteractionComponent.h new file mode 100644 index 0000000..ba07004 --- /dev/null +++ b/include/InteractionComponent.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Component.h" +#include "Entity.h" + +#include + +class InteractionComponent : public Component +{ +public: + InteractionComponent(bool canInteract, bool isInteractable); + ~InteractionComponent(); + + void init() override; + void update() override; + + Entity* getClosestInteractableEntity(/*last direction key input*/ std::vector entities); + bool interact(Entity* interactee); + +private: + bool canInteract; + bool isInteractable; +}; \ No newline at end of file diff --git a/src/InteractionComponent.cpp b/src/InteractionComponent.cpp new file mode 100644 index 0000000..62a83bb --- /dev/null +++ b/src/InteractionComponent.cpp @@ -0,0 +1,46 @@ +#include "InteractionComponent.h" + +InteractionComponent::InteractionComponent(bool canInteract, bool isInteractable) +{ + this->canInteract = canInteract; + this->isInteractable = isInteractable; +} + +InteractionComponent::~InteractionComponent() = default; + +void InteractionComponent::init() +{ + +} + +void InteractionComponent::update() +{ + +} + +Entity* getClosestInteractableEntity(/*last direction key input*/ std::vector entities) +{ + // code to compare and find closest entity + + +} + +bool InteractionComponent::interact(Entity* interactee) +{ + if(!interactee->hasComponent || !interactee->getComponent.isInteractable) + { + return false; + } + + return true; + + // code to interact, basically +} + +// TODO: +// - find a way to determine which entities are interactible (bool, map?) +// - get the last saved key input => if two interactible entities, favour the one closer to last input/m +// maybe only make the one in direction of last input interactible +// - add toggleable marker to show last direction => like stardew? (probably only possible once tmx + layers properly implemented) +// - add key input e for interact/maybe alt gr for other person? + From bc7a8dfdff9bc9892ebeb04450e716313155b2ee Mon Sep 17 00:00:00 2001 From: ineslelin Date: Sat, 22 Jun 2024 12:58:51 +0200 Subject: [PATCH 2/9] finished interact(), put down idea for getting closest entity --- include/InteractionComponent.h | 4 ++-- src/InteractionComponent.cpp | 37 +++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/include/InteractionComponent.h b/include/InteractionComponent.h index ba07004..09b10f6 100644 --- a/include/InteractionComponent.h +++ b/include/InteractionComponent.h @@ -14,8 +14,8 @@ public: void init() override; void update() override; - Entity* getClosestInteractableEntity(/*last direction key input*/ std::vector entities); - bool interact(Entity* interactee); + Entity* getClosestInteractableEntity(Key directionKey, Entity* interactor, std::vector entities); + bool interact(Entity* interactor, Entity* interactee); private: bool canInteract; diff --git a/src/InteractionComponent.cpp b/src/InteractionComponent.cpp index 62a83bb..07b71fc 100644 --- a/src/InteractionComponent.cpp +++ b/src/InteractionComponent.cpp @@ -18,29 +18,48 @@ void InteractionComponent::update() } -Entity* getClosestInteractableEntity(/*last direction key input*/ std::vector entities) +Entity* getClosestInteractableEntity(Key directionKey, Entity* interactor, std::vector entities) { - // code to compare and find closest entity + for(auto e : entities) + { + if(!e->hasComponent() || !e->getComponent().isInteractable) + { + auto it = std::remove(entities.begin(), entities.end(), e); + entities.erase(it, entities.end()); + } + } + if(entities.empty()) + { + return nullptr; + } + for(auto e : entities) + { + if(e->getComponent().position.x) + } } -bool InteractionComponent::interact(Entity* interactee) +bool InteractionComponent::interact(Entity* interactor, Entity* interactee) { - if(!interactee->hasComponent || !interactee->getComponent.isInteractable) + if(!interactor->hasComponent() || !interactor->getComponent().canInteract) + { + throw std::logic_error("Interactor entity cannot interact"); + } + + if(!interactee->hasComponent() || !interactee->getComponent().isInteractable) { return false; } - return true; - // code to interact, basically + return true; } // TODO: -// - find a way to determine which entities are interactible (bool, map?) -// - get the last saved key input => if two interactible entities, favour the one closer to last input/m -// maybe only make the one in direction of last input interactible +// - get the last saved key input => if two interactible entities, favour the one closer to last input/ +// maybe only make the one in direction of last input interactible, or if two entities are ex. left and right and the last +// input was down, then either try to calc the closer one or if theyre the same distance away, favour one side automatically // - add toggleable marker to show last direction => like stardew? (probably only possible once tmx + layers properly implemented) // - add key input e for interact/maybe alt gr for other person? From 3ba0d46fbeb5e83da3f36eabceb4cea34a35304d Mon Sep 17 00:00:00 2001 From: ineslelin Date: Sat, 22 Jun 2024 19:30:04 +0200 Subject: [PATCH 3/9] added functions to check if an entity is within reach in each direction --- include/InteractionComponent.h | 9 +++- src/InteractionComponent.cpp | 87 ++++++++++++++++++++++++++++------ 2 files changed, 81 insertions(+), 15 deletions(-) diff --git a/include/InteractionComponent.h b/include/InteractionComponent.h index 09b10f6..4e10616 100644 --- a/include/InteractionComponent.h +++ b/include/InteractionComponent.h @@ -8,7 +8,7 @@ class InteractionComponent : public Component { public: - InteractionComponent(bool canInteract, bool isInteractable); + InteractionComponent(bool canInteract, bool isInteractable, int reach); ~InteractionComponent(); void init() override; @@ -20,4 +20,11 @@ public: private: bool canInteract; bool isInteractable; + + int reach; + + bool isEntityCloseEnoughRight(Vector2D iPos, Vector2D ePos, int iWidth); + bool isEntityCloseEnoughLeft(Vector2D iPos, Vector2D ePos, int eWidth); + bool isEntityCloseEnoughUp(Vector2D iPos, Vector2D ePos, int eHeight); + bool isEntityCloseEnoughDown(Vector2D iPos, Vector2D ePos, int iHeight); }; \ No newline at end of file diff --git a/src/InteractionComponent.cpp b/src/InteractionComponent.cpp index 07b71fc..958ca17 100644 --- a/src/InteractionComponent.cpp +++ b/src/InteractionComponent.cpp @@ -1,9 +1,10 @@ #include "InteractionComponent.h" -InteractionComponent::InteractionComponent(bool canInteract, bool isInteractable) +InteractionComponent::InteractionComponent(bool canInteract, bool isInteractable, int reach) { this->canInteract = canInteract; this->isInteractable = isInteractable; + this->reach = reach; // ofc that can be set individually, but its probably also okay if you just pass your entities width as its reach here methinks } InteractionComponent::~InteractionComponent() = default; @@ -18,26 +19,53 @@ void InteractionComponent::update() } -Entity* getClosestInteractableEntity(Key directionKey, Entity* interactor, std::vector entities) +Entity* InteractionComponent::getClosestInteractableEntity(Key directionKey, Entity* interactor, std::vector entities) { - for(auto e : entities) + // first kicking all the entities passed here that don't have the ability to be interacted with + for (auto it = entities.begin(); it != entities.end();) { - if(!e->hasComponent() || !e->getComponent().isInteractable) + if (!(*it)->hasComponent() || !(*it)->getComponent().isInteractable) { - auto it = std::remove(entities.begin(), entities.end(), e); - entities.erase(it, entities.end()); + it = entities.erase(it); + continue; } + + it++; } + // quick check if entities isn't empty if(entities.empty()) { return nullptr; } - for(auto e : entities) + // to reduce the amount of accesses to transformcomponent via getComponent() + auto& interactorT = interactor->getComponent(); + + // kicking all entities that are too far away, disgusting code that i dont even know if it works just yet but oh well + for (auto it = entities.begin(); it != entities.end();) { - if(e->getComponent().position.x) + auto& entityT = (*it)->getComponent(); + + if(((entityT.position.x >= interactorT.position.x) && !isEntityCloseEnoughRight(interactorT.position, entityT.position, interactorT.width)) || + ((entityT.position.x <= interactorT.position.x) && !isEntityCloseEnoughLeft(interactorT.position, entityT.position, entityT.width)) || + ((entityT.position.y <= interactorT.position.y) && !isEntityCloseEnoughUp(interactorT.position, entityT.position, entityT.height)) || + ((entityT.position.y >= interactorT.position.y) && !isEntityCloseEnoughDown(interactorT.position, entityT.position, interactorT.height))) + { + it = entities.erase(it); + continue; + } + + it++; } + + // check if entities is empty + if(entities.empty()) + { + return nullptr; + } + + // then check whichever entitiy is closer, based on direction i guess? so if direction left then the entity on the left, if direction down then entity on down???? i guess????? } bool InteractionComponent::interact(Entity* interactor, Entity* interactee) @@ -52,14 +80,45 @@ bool InteractionComponent::interact(Entity* interactor, Entity* interactee) return false; } + return true; +} + +bool InteractionComponent::isEntityCloseEnoughRight(Vector2D iPos, Vector2D ePos, int iWidth) +{ + if(ePos.x > ((int)iPos.x + (iWidth + reach))) + { + return false; + } return true; } -// TODO: -// - get the last saved key input => if two interactible entities, favour the one closer to last input/ -// maybe only make the one in direction of last input interactible, or if two entities are ex. left and right and the last -// input was down, then either try to calc the closer one or if theyre the same distance away, favour one side automatically -// - add toggleable marker to show last direction => like stardew? (probably only possible once tmx + layers properly implemented) -// - add key input e for interact/maybe alt gr for other person? +bool InteractionComponent::isEntityCloseEnoughLeft(Vector2D iPos, Vector2D ePos, int eWidth) +{ + if(ePos.x < ((int)iPos.x - (reach - eWidth))) + { + return false; + } + + return true; +} +bool InteractionComponent::isEntityCloseEnoughUp(Vector2D iPos, Vector2D ePos, int eHeight) +{ + if(ePos.y < ((int)iPos.y - (reach - eHeight))) + { + return false; + } + + return true; +} + +bool InteractionComponent::isEntityCloseEnoughDown(Entity* i, Entity* e) +{ + if(ePos.y > ((int)iPos.y + (iHeight + reach))) + { + return false; + } + + return true; +} \ No newline at end of file From f5a94ac4b917f72b6b40502f51687e032c6c8db6 Mon Sep 17 00:00:00 2001 From: ineslelin Date: Mon, 24 Jun 2024 13:01:24 +0200 Subject: [PATCH 4/9] created the distance checks --- include/InteractionComponent.h | 10 ++- src/InteractionComponent.cpp | 153 +++++++++++++++++++++++++++------ 2 files changed, 138 insertions(+), 25 deletions(-) diff --git a/include/InteractionComponent.h b/include/InteractionComponent.h index 4e10616..0b6415a 100644 --- a/include/InteractionComponent.h +++ b/include/InteractionComponent.h @@ -14,7 +14,7 @@ public: void init() override; void update() override; - Entity* getClosestInteractableEntity(Key directionKey, Entity* interactor, std::vector entities); + Entity* getClosestInteractableEntity(Direction direction, Entity* interactor, std::vector entities); bool interact(Entity* interactor, Entity* interactee); private: @@ -23,8 +23,16 @@ private: int reach; + Entity* findClosestEntityLeft(std::vector& entities, TransformComponent& interactorT); + Entity* findClosestEntityRight(std::vector& entities, TransformComponent& interactorT); + Entity* findClosestEntityUp(std::vector& entities, TransformComponent& interactorT); + Entity* findClosestEntityDown(std::vector& entities, TransformComponent& interactorT); + + float calculateDistance(Vector2D iPos, Vector2D ePos); + bool isEntityCloseEnoughRight(Vector2D iPos, Vector2D ePos, int iWidth); bool isEntityCloseEnoughLeft(Vector2D iPos, Vector2D ePos, int eWidth); bool isEntityCloseEnoughUp(Vector2D iPos, Vector2D ePos, int eHeight); bool isEntityCloseEnoughDown(Vector2D iPos, Vector2D ePos, int iHeight); + }; \ No newline at end of file diff --git a/src/InteractionComponent.cpp b/src/InteractionComponent.cpp index 958ca17..778f9e5 100644 --- a/src/InteractionComponent.cpp +++ b/src/InteractionComponent.cpp @@ -1,5 +1,8 @@ #include "InteractionComponent.h" +#include +#include + InteractionComponent::InteractionComponent(bool canInteract, bool isInteractable, int reach) { this->canInteract = canInteract; @@ -19,18 +22,16 @@ void InteractionComponent::update() } -Entity* InteractionComponent::getClosestInteractableEntity(Key directionKey, Entity* interactor, std::vector entities) +Entity* InteractionComponent::getClosestInteractableEntity(Direction direction, Entity* interactor, std::vector entities) { // first kicking all the entities passed here that don't have the ability to be interacted with - for (auto it = entities.begin(); it != entities.end();) + for (auto it = entities.begin(); it != entities.end(); it++) { if (!(*it)->hasComponent() || !(*it)->getComponent().isInteractable) { it = entities.erase(it); continue; } - - it++; } // quick check if entities isn't empty @@ -42,30 +43,25 @@ Entity* InteractionComponent::getClosestInteractableEntity(Key directionKey, Ent // to reduce the amount of accesses to transformcomponent via getComponent() auto& interactorT = interactor->getComponent(); - // kicking all entities that are too far away, disgusting code that i dont even know if it works just yet but oh well - for (auto it = entities.begin(); it != entities.end();) + // kick all entities that are either too far away or in the opposite direction, then calc distance and find closest entity that way + Entity* entityToInteract = nullptr; + + switch(direction) { - auto& entityT = (*it)->getComponent(); + case Direction::LEFT: entityToInteract = findClosestEntityLeft(entities, interactorT); + break; - if(((entityT.position.x >= interactorT.position.x) && !isEntityCloseEnoughRight(interactorT.position, entityT.position, interactorT.width)) || - ((entityT.position.x <= interactorT.position.x) && !isEntityCloseEnoughLeft(interactorT.position, entityT.position, entityT.width)) || - ((entityT.position.y <= interactorT.position.y) && !isEntityCloseEnoughUp(interactorT.position, entityT.position, entityT.height)) || - ((entityT.position.y >= interactorT.position.y) && !isEntityCloseEnoughDown(interactorT.position, entityT.position, interactorT.height))) - { - it = entities.erase(it); - continue; - } + case Direction::RIGHT: entityToInteract = findClosestEntityRight(entities, interactorT); + break; - it++; + case Direction::UP: entityToInteract = findClosestEntityUp(entities, interactorT); + break; + + case Direction::DOWN: entityToInteract = findClosestEntityDown(entities, interactorT); + break; } - // check if entities is empty - if(entities.empty()) - { - return nullptr; - } - - // then check whichever entitiy is closer, based on direction i guess? so if direction left then the entity on the left, if direction down then entity on down???? i guess????? + return entityToInteract; } bool InteractionComponent::interact(Entity* interactor, Entity* interactee) @@ -83,6 +79,115 @@ bool InteractionComponent::interact(Entity* interactor, Entity* interactee) return true; } +Entity* InteractionComponent::findClosestEntityLeft(std::vector& entities, TransformComponent& interactorT) +{ + Entity* closestEntity = nullptr; + float closestDistance = std::numeric_limits::max(); + + for(auto it = entities.begin(); it != entities.end(); it++) + { + auto& entityT = (*it)->getComponent(); + if(entityT.position.x > interactorT.position.x || !isEntityCloseEnoughLeft(interactorT.position, entityT.position, entityT.width)) + { + it = entities.erase(it); + continue; + } + + float distance = calculateDistance(interactorT.position, entityT.position); + + if (distance < closestDistance) + { + closestDistance = distance; + closestEntity = *it; + } + } + + return closestEntity; +} + +Entity* InteractionComponent::findClosestEntityRight(std::vector& entities, TransformComponent& interactorT) +{ + Entity* closestEntity = nullptr; + float closestDistance = std::numeric_limits::max(); + + for(auto it = entities.begin(); it != entities.end(); it++) + { + auto& entityT = (*it)->getComponent(); + if(entityT.position.x < interactorT.position.x || !isEntityCloseEnoughRight(interactorT.position, entityT.position, interactorT.width)) + { + it = entities.erase(it); + continue; + } + + float distance = calculateDistance(interactorT.position, entityT.position); + + if (distance < closestDistance) + { + closestDistance = distance; + closestEntity = *it; + } + } + + return closestEntity; +} + +Entity* InteractionComponent::findClosestEntityUp(std::vector& entities, TransformComponent& interactorT) +{ + Entity* closestEntity = nullptr; + float closestDistance = std::numeric_limits::max(); + + for(auto it = entities.begin(); it != entities.end(); it++) + { + auto& entityT = (*it)->getComponent(); + if(entityT.position.y < interactorT.position.y || !isEntityCloseEnoughUp(interactorT.position, entityT.position, entityT.height)) + { + it = entities.erase(it); + continue; + } + + float distance = calculateDistance(interactorT.position, entityT.position); + + if (distance < closestDistance) + { + closestDistance = distance; + closestEntity = *it; + } + } + + return closestEntity; +} + +Entity* InteractionComponent::findClosestEntityDown(std::vector& entities, TransformComponent& interactorT) +{ + Entity* closestEntity = nullptr; + float closestDistance = std::numeric_limits::max(); + + for(auto it = entities.begin(); it != entities.end(); it++) + { + auto& entityT = (*it)->getComponent(); + if(entityT.position.y > interactorT.position.y || !isEntityCloseEnoughDown(interactorT.position, entityT.position, interactorT.height)) + { + it = entities.erase(it); + continue; + } + + float distance = calculateDistance(interactorT.position, entityT.position); + + if (distance < closestDistance) + { + closestDistance = distance; + closestEntity = *it; + } + } + + return closestEntity; +} + +float InteractionComponent::calculateDistance(Vector2D iPos, Vector2D ePos) +{ + return std::abs(ePos.x - iPos.x) + std::abs(ePos.y - iPos.y); +} + bool InteractionComponent::isEntityCloseEnoughRight(Vector2D iPos, Vector2D ePos, int iWidth) { if(ePos.x > ((int)iPos.x + (iWidth + reach))) @@ -113,7 +218,7 @@ bool InteractionComponent::isEntityCloseEnoughUp(Vector2D iPos, Vector2D ePos, i return true; } -bool InteractionComponent::isEntityCloseEnoughDown(Entity* i, Entity* e) +bool InteractionComponent::isEntityCloseEnoughDown(Vector2D iPos, Vector2D ePos, int iHeight) { if(ePos.y > ((int)iPos.y + (iHeight + reach))) { From 7e0a2422bd6498edd90e857ba5cf9b627128b9e9 Mon Sep 17 00:00:00 2001 From: ineslelin Date: Tue, 14 Jan 2025 12:38:31 +0100 Subject: [PATCH 5/9] rewrite interaction logic to be more concise forgot to commit this the last time i worked on it --- include/InteractionComponent.h | 17 +-- src/InteractionComponent.cpp | 229 ++++++++------------------------- 2 files changed, 61 insertions(+), 185 deletions(-) diff --git a/include/InteractionComponent.h b/include/InteractionComponent.h index 0b6415a..2de6e0b 100644 --- a/include/InteractionComponent.h +++ b/include/InteractionComponent.h @@ -14,25 +14,20 @@ public: void init() override; void update() override; - Entity* getClosestInteractableEntity(Direction direction, Entity* interactor, std::vector entities); bool interact(Entity* interactor, Entity* interactee); - + + Entity* getClosestInteractableEntity(Direction direction, Entity* interactor, std::vector entities); + private: bool canInteract; bool isInteractable; int reach; - Entity* findClosestEntityLeft(std::vector& entities, TransformComponent& interactorT); - Entity* findClosestEntityRight(std::vector& entities, TransformComponent& interactorT); - Entity* findClosestEntityUp(std::vector& entities, TransformComponent& interactorT); - Entity* findClosestEntityDown(std::vector& entities, TransformComponent& interactorT); + Entity* findClosestEntity(std::vector& entities, TransformComponent& interactorT, Direction direction); + std::function getDirectionalCheck(Direction direction, const TransformComponent& interactorT); + bool isEntityCloseEnough(const TransformComponent& interactorT, const TransformComponent& entityT, Direction direction); float calculateDistance(Vector2D iPos, Vector2D ePos); - bool isEntityCloseEnoughRight(Vector2D iPos, Vector2D ePos, int iWidth); - bool isEntityCloseEnoughLeft(Vector2D iPos, Vector2D ePos, int eWidth); - bool isEntityCloseEnoughUp(Vector2D iPos, Vector2D ePos, int eHeight); - bool isEntityCloseEnoughDown(Vector2D iPos, Vector2D ePos, int iHeight); - }; \ No newline at end of file diff --git a/src/InteractionComponent.cpp b/src/InteractionComponent.cpp index 778f9e5..4cb28a8 100644 --- a/src/InteractionComponent.cpp +++ b/src/InteractionComponent.cpp @@ -4,226 +4,107 @@ #include InteractionComponent::InteractionComponent(bool canInteract, bool isInteractable, int reach) -{ - this->canInteract = canInteract; - this->isInteractable = isInteractable; - this->reach = reach; // ofc that can be set individually, but its probably also okay if you just pass your entities width as its reach here methinks -} + : canInteract(canInteract), isInteractable(isInteractable), reach(reach) {} InteractionComponent::~InteractionComponent() = default; -void InteractionComponent::init() -{ +void InteractionComponent::init() {} -} - -void InteractionComponent::update() -{ - -} - -Entity* InteractionComponent::getClosestInteractableEntity(Direction direction, Entity* interactor, std::vector entities) -{ - // first kicking all the entities passed here that don't have the ability to be interacted with - for (auto it = entities.begin(); it != entities.end(); it++) - { - if (!(*it)->hasComponent() || !(*it)->getComponent().isInteractable) - { - it = entities.erase(it); - continue; - } - } - - // quick check if entities isn't empty - if(entities.empty()) - { - return nullptr; - } - - // to reduce the amount of accesses to transformcomponent via getComponent() - auto& interactorT = interactor->getComponent(); - - // kick all entities that are either too far away or in the opposite direction, then calc distance and find closest entity that way - Entity* entityToInteract = nullptr; - - switch(direction) - { - case Direction::LEFT: entityToInteract = findClosestEntityLeft(entities, interactorT); - break; - - case Direction::RIGHT: entityToInteract = findClosestEntityRight(entities, interactorT); - break; - - case Direction::UP: entityToInteract = findClosestEntityUp(entities, interactorT); - break; - - case Direction::DOWN: entityToInteract = findClosestEntityDown(entities, interactorT); - break; - } - - return entityToInteract; -} +void InteractionComponent::update() {} bool InteractionComponent::interact(Entity* interactor, Entity* interactee) { if(!interactor->hasComponent() || !interactor->getComponent().canInteract) - { throw std::logic_error("Interactor entity cannot interact"); - } if(!interactee->hasComponent() || !interactee->getComponent().isInteractable) - { return false; - } return true; } -Entity* InteractionComponent::findClosestEntityLeft(std::vector& entities, TransformComponent& interactorT) +Entity* InteractionComponent::getClosestInteractableEntity(Direction direction, Entity* interactor, std::vector entities) { - Entity* closestEntity = nullptr; - float closestDistance = std::numeric_limits::max(); + entities.erase(std::remove_if(entities.begin(), entities.end(), [](Entity* e) { + return !e->hasComponent() || !e->getComponent().isInteractable; + }), entities.end()); - for(auto it = entities.begin(); it != entities.end(); it++) - { - auto& entityT = (*it)->getComponent(); - if(entityT.position.x > interactorT.position.x || !isEntityCloseEnoughLeft(interactorT.position, entityT.position, entityT.width)) - { - it = entities.erase(it); - continue; - } + if(entities.empty()) + return nullptr; - float distance = calculateDistance(interactorT.position, entityT.position); - - if (distance < closestDistance) - { - closestDistance = distance; - closestEntity = *it; - } - } - - return closestEntity; + auto& interactorT = interactor->getComponent(); + return findClosestEntity(entities, interactorT, direction); } -Entity* InteractionComponent::findClosestEntityRight(std::vector& entities, TransformComponent& interactorT) +Entity* InteractionComponent::findClosestEntity(std::vector& entities, TransformComponent& interactorT, Direction direction) { Entity* closestEntity = nullptr; float closestDistance = std::numeric_limits::max(); - for(auto it = entities.begin(); it != entities.end(); it++) - { - auto& entityT = (*it)->getComponent(); - if(entityT.position.x < interactorT.position.x || !isEntityCloseEnoughRight(interactorT.position, entityT.position, interactorT.width)) - { - it = entities.erase(it); - continue; - } + auto isInDirection = getDirectionalCheck(direction, interactorT); + entities.erase(std::remove_if(entities.begin(), entities.end(), [&](Entity* e){ + auto& entityT = entity->getComponent(); + return !isInDirection(entityT) || !isEntityCloseEnough(interactorT, entityT, direction); + }), entities.end()); + + for(auto e : entities) + { + auto& entityT = entity->getComponent(); float distance = calculateDistance(interactorT.position, entityT.position); - if (distance < closestDistance) - { + if (distance < closestDistance) { closestDistance = distance; - closestEntity = *it; + closestEntity = entity; } } return closestEntity; } -Entity* InteractionComponent::findClosestEntityUp(std::vector& entities, TransformComponent& interactorT) +std::function InteractionComponent::getDirectionalCheck(Direction direction, const TransformComponent& interactorT) { - Entity* closestEntity = nullptr; - float closestDistance = std::numeric_limits::max(); - - for(auto it = entities.begin(); it != entities.end(); it++) + switch(direction) { - auto& entityT = (*it)->getComponent(); - if(entityT.position.y < interactorT.position.y || !isEntityCloseEnoughUp(interactorT.position, entityT.position, entityT.height)) - { - it = entities.erase(it); - continue; - } - - float distance = calculateDistance(interactorT.position, entityT.position); - - if (distance < closestDistance) - { - closestDistance = distance; - closestEntity = *it; - } + case Direction::LEFT: + return[&interactorT](const TransformComponent& entityT) { + return entityT.position.x < interactorT.position.x; + }; + case Direction::RIGHT: + return[&interactorT](const TransformComponent& entityT) { + return entityT.position.x > interactorT.position.x; + }; + case Direction::UP: + return[&interactorT](const TransformComponent& entityT) { + return entityT.position.y < interactorT.position.y; + }; + case Direction::DOWN: + return[&interactorT](const TransformComponent& entityT) { + return entityT.position.y > interactorT.position.y; + }; + default: + return [](const TransformComponent&) { return false; }; } - - return closestEntity; } -Entity* InteractionComponent::findClosestEntityDown(std::vector& entities, TransformComponent& interactorT) +bool InteractionComponent::isEntityCloseEnough(const TransformComponent& interactorT, const TransformComponent& entityT, Direction direction) { - Entity* closestEntity = nullptr; - float closestDistance = std::numeric_limits::max(); - - for(auto it = entities.begin(); it != entities.end(); it++) + switch (direction) { - auto& entityT = (*it)->getComponent(); - if(entityT.position.y > interactorT.position.y || !isEntityCloseEnoughDown(interactorT.position, entityT.position, interactorT.height)) - { - it = entities.erase(it); - continue; - } - - float distance = calculateDistance(interactorT.position, entityT.position); - - if (distance < closestDistance) - { - closestDistance = distance; - closestEntity = *it; - } + case Direction::LEFT: + return (entityT.position.x >= (interactorT.position.x - reach)); + case Direction::RIGHT: + return (entityT.position.x <= (interactorT.position.x + reach)); + case Direction::UP: + return (entityT.position.y >= (interactorT.position.y - reach)); + case Direction::DOWN: + return (entityT.position.y <= (interactorT.position.y + reach)); + default: + return false; } - - return closestEntity; } float InteractionComponent::calculateDistance(Vector2D iPos, Vector2D ePos) { return std::abs(ePos.x - iPos.x) + std::abs(ePos.y - iPos.y); -} - -bool InteractionComponent::isEntityCloseEnoughRight(Vector2D iPos, Vector2D ePos, int iWidth) -{ - if(ePos.x > ((int)iPos.x + (iWidth + reach))) - { - return false; - } - - return true; -} - -bool InteractionComponent::isEntityCloseEnoughLeft(Vector2D iPos, Vector2D ePos, int eWidth) -{ - if(ePos.x < ((int)iPos.x - (reach - eWidth))) - { - return false; - } - - return true; -} - -bool InteractionComponent::isEntityCloseEnoughUp(Vector2D iPos, Vector2D ePos, int eHeight) -{ - if(ePos.y < ((int)iPos.y - (reach - eHeight))) - { - return false; - } - - return true; -} - -bool InteractionComponent::isEntityCloseEnoughDown(Vector2D iPos, Vector2D ePos, int iHeight) -{ - if(ePos.y > ((int)iPos.y + (iHeight + reach))) - { - return false; - } - - return true; } \ No newline at end of file From b07d68b84b0d60c0b5a7c7d7e8f67738b6c23cb7 Mon Sep 17 00:00:00 2001 From: ineslelin Date: Tue, 14 Jan 2025 13:24:33 +0100 Subject: [PATCH 6/9] fix errors when building --- include/InteractionComponent.h | 3 ++- src/InteractionComponent.cpp | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/InteractionComponent.h b/include/InteractionComponent.h index 2de6e0b..68adb5a 100644 --- a/include/InteractionComponent.h +++ b/include/InteractionComponent.h @@ -4,6 +4,7 @@ #include "Entity.h" #include +#include class InteractionComponent : public Component { @@ -12,7 +13,7 @@ public: ~InteractionComponent(); void init() override; - void update() override; + void update(); bool interact(Entity* interactor, Entity* interactee); diff --git a/src/InteractionComponent.cpp b/src/InteractionComponent.cpp index 4cb28a8..03ace7b 100644 --- a/src/InteractionComponent.cpp +++ b/src/InteractionComponent.cpp @@ -44,18 +44,18 @@ Entity* InteractionComponent::findClosestEntity(std::vector& entities, auto isInDirection = getDirectionalCheck(direction, interactorT); entities.erase(std::remove_if(entities.begin(), entities.end(), [&](Entity* e){ - auto& entityT = entity->getComponent(); + auto& entityT = e->getComponent(); return !isInDirection(entityT) || !isEntityCloseEnough(interactorT, entityT, direction); }), entities.end()); for(auto e : entities) { - auto& entityT = entity->getComponent(); + auto& entityT = e->getComponent(); float distance = calculateDistance(interactorT.position, entityT.position); if (distance < closestDistance) { closestDistance = distance; - closestEntity = entity; + closestEntity = e; } } From 534fd480931d654be6d4d3d24322510d99306c6d Mon Sep 17 00:00:00 2001 From: ineslelin Date: Tue, 14 Jan 2025 13:29:14 +0100 Subject: [PATCH 7/9] does committing this help? --- .gitmodules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitmodules b/.gitmodules index 6dd82fa..9c14583 100644 --- a/.gitmodules +++ b/.gitmodules @@ -17,3 +17,6 @@ path = docs/doxygen-awesome-css url = https://github.com/jothepro/doxygen-awesome-css.git +[submodule "external/tmxlite"] + path = external/tmxlite + url = https://github.com/fallahn/tmxlite.git From 5ffff57b5fcbbf7f596386d7e92a2f75b8250c4a Mon Sep 17 00:00:00 2001 From: ineslelin Date: Tue, 14 Jan 2025 22:17:52 +0100 Subject: [PATCH 8/9] interactions work --- src/InteractionComponent.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/InteractionComponent.cpp b/src/InteractionComponent.cpp index 03ace7b..190e3d8 100644 --- a/src/InteractionComponent.cpp +++ b/src/InteractionComponent.cpp @@ -14,6 +14,9 @@ void InteractionComponent::update() {} bool InteractionComponent::interact(Entity* interactor, Entity* interactee) { + if(interactee == nullptr) + return false; + if(!interactor->hasComponent() || !interactor->getComponent().canInteract) throw std::logic_error("Interactor entity cannot interact"); From 39ccdf4138cc425978469667a9aed64ad25b94d4 Mon Sep 17 00:00:00 2001 From: ineslelin Date: Tue, 14 Jan 2025 23:00:39 +0100 Subject: [PATCH 9/9] add documentation --- include/InteractionComponent.h | 41 +++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/include/InteractionComponent.h b/include/InteractionComponent.h index 68adb5a..9482c87 100644 --- a/include/InteractionComponent.h +++ b/include/InteractionComponent.h @@ -15,8 +15,21 @@ public: void init() override; void update(); + /*! + * \brief Checks if two entities can interact with each other + * \param interactor The source of the interaction + * \param interactee The target of the interaction + * \return A boolean if an interaction is possible + */ bool interact(Entity* interactor, Entity* interactee); + /*! + * \brief Find the closest entity the interactor could interact with + * \param direction The direction in which the interactor is facing, the interactor can only interact with entities in the direction it is facing + * \param interactor The initiator of the interaction + * \param entities A list of entities + * \return The interactable entity closest to the interactor + */ Entity* getClosestInteractableEntity(Direction direction, Entity* interactor, std::vector entities); private: @@ -25,10 +38,36 @@ private: int reach; + /*! + * \brief Find the entity closest to the interactor + * \param entities A list of entities + * \param interactorT TransformComponent of the interactor (contains the coordinates) + * \param direction The direction the interactor is facing + * \return The closest entity + */ Entity* findClosestEntity(std::vector& entities, TransformComponent& interactorT, Direction direction); + + /*! + * \brief Checks if an entity is in the direction the interactor faces + * \param direction The direction the interactor is facing + * \param interactorT TransformComponent of the interactor (contains the coordinates) + */ std::function getDirectionalCheck(Direction direction, const TransformComponent& interactorT); + + /*! + * \brief Checks if entity is within reach of the interactor + * \param interactorT TransformComponent of the interactor (contains the coordinates) + * \param entityT TransformComponent of the entity (contains the coordinates) + * @param direction The direction the interactor is facing + * @return + */ bool isEntityCloseEnough(const TransformComponent& interactorT, const TransformComponent& entityT, Direction direction); + /*! + * \brief Calculates distance between entity and interactor + * \param iPos Coordinates of the interactor + * \param ePos Coordinates of the entity + * \return The distance between interactor and entity + */ float calculateDistance(Vector2D iPos, Vector2D ePos); - }; \ No newline at end of file