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