mirror of
https://github.com/Nimac0/SDL_Minigame
synced 2026-01-13 14:53:41 +00:00
rewrite interaction logic to be more concise
forgot to commit this the last time i worked on it
This commit is contained in:
parent
a093fe3ccf
commit
7e0a2422bd
@ -14,25 +14,20 @@ public:
|
|||||||
void init() override;
|
void init() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
|
|
||||||
Entity* getClosestInteractableEntity(Direction direction, Entity* interactor, std::vector<Entity*> entities);
|
|
||||||
bool interact(Entity* interactor, Entity* interactee);
|
bool interact(Entity* interactor, Entity* interactee);
|
||||||
|
|
||||||
|
Entity* getClosestInteractableEntity(Direction direction, Entity* interactor, std::vector<Entity*> entities);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool canInteract;
|
bool canInteract;
|
||||||
bool isInteractable;
|
bool isInteractable;
|
||||||
|
|
||||||
int reach;
|
int reach;
|
||||||
|
|
||||||
Entity* findClosestEntityLeft(std::vector<Entity*>& entities, TransformComponent& interactorT);
|
Entity* findClosestEntity(std::vector<Entity*>& entities, TransformComponent& interactorT, Direction direction);
|
||||||
Entity* findClosestEntityRight(std::vector<Entity*>& entities, TransformComponent& interactorT);
|
std::function<bool(const TransformComponent&)> getDirectionalCheck(Direction direction, const TransformComponent& interactorT);
|
||||||
Entity* findClosestEntityUp(std::vector<Entity*>& entities, TransformComponent& interactorT);
|
bool isEntityCloseEnough(const TransformComponent& interactorT, const TransformComponent& entityT, Direction direction);
|
||||||
Entity* findClosestEntityDown(std::vector<Entity*>& entities, TransformComponent& interactorT);
|
|
||||||
|
|
||||||
float calculateDistance(Vector2D iPos, Vector2D ePos);
|
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);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -4,226 +4,107 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
InteractionComponent::InteractionComponent(bool canInteract, bool isInteractable, int reach)
|
InteractionComponent::InteractionComponent(bool canInteract, bool isInteractable, int reach)
|
||||||
{
|
: canInteract(canInteract), isInteractable(isInteractable), reach(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;
|
InteractionComponent::~InteractionComponent() = default;
|
||||||
|
|
||||||
void InteractionComponent::init()
|
void InteractionComponent::init() {}
|
||||||
{
|
|
||||||
|
|
||||||
}
|
void InteractionComponent::update() {}
|
||||||
|
|
||||||
void InteractionComponent::update()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity* InteractionComponent::getClosestInteractableEntity(Direction direction, Entity* interactor, std::vector<Entity*> 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<InteractionComponent>() || !(*it)->getComponent<InteractionComponent>().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<TransformComponent>();
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InteractionComponent::interact(Entity* interactor, Entity* interactee)
|
bool InteractionComponent::interact(Entity* interactor, Entity* interactee)
|
||||||
{
|
{
|
||||||
if(!interactor->hasComponent<InteractionComponent>() || !interactor->getComponent<InteractionComponent>().canInteract)
|
if(!interactor->hasComponent<InteractionComponent>() || !interactor->getComponent<InteractionComponent>().canInteract)
|
||||||
{
|
|
||||||
throw std::logic_error("Interactor entity cannot interact");
|
throw std::logic_error("Interactor entity cannot interact");
|
||||||
}
|
|
||||||
|
|
||||||
if(!interactee->hasComponent<InteractionComponent>() || !interactee->getComponent<InteractionComponent>().isInteractable)
|
if(!interactee->hasComponent<InteractionComponent>() || !interactee->getComponent<InteractionComponent>().isInteractable)
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity* InteractionComponent::findClosestEntityLeft(std::vector<Entity*>& entities, TransformComponent& interactorT)
|
Entity* InteractionComponent::getClosestInteractableEntity(Direction direction, Entity* interactor, std::vector<Entity*> entities)
|
||||||
|
{
|
||||||
|
entities.erase(std::remove_if(entities.begin(), entities.end(), [](Entity* e) {
|
||||||
|
return !e->hasComponent<InteractionComponent>() || !e->getComponent<InteractionComponent>().isInteractable;
|
||||||
|
}), entities.end());
|
||||||
|
|
||||||
|
if(entities.empty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
auto& interactorT = interactor->getComponent<TransformComponent>();
|
||||||
|
return findClosestEntity(entities, interactorT, direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* InteractionComponent::findClosestEntity(std::vector<Entity*>& entities, TransformComponent& interactorT, Direction direction)
|
||||||
{
|
{
|
||||||
Entity* closestEntity = nullptr;
|
Entity* closestEntity = nullptr;
|
||||||
float closestDistance = std::numeric_limits<float>::max();
|
float closestDistance = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
for(auto it = entities.begin(); it != entities.end(); it++)
|
auto isInDirection = getDirectionalCheck(direction, interactorT);
|
||||||
{
|
|
||||||
auto& entityT = (*it)->getComponent<TransformComponent>();
|
|
||||||
if(entityT.position.x > interactorT.position.x || !isEntityCloseEnoughLeft(interactorT.position, entityT.position, entityT.width))
|
|
||||||
{
|
|
||||||
it = entities.erase(it);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
entities.erase(std::remove_if(entities.begin(), entities.end(), [&](Entity* e){
|
||||||
|
auto& entityT = entity->getComponent<TransformComponent>();
|
||||||
|
return !isInDirection(entityT) || !isEntityCloseEnough(interactorT, entityT, direction);
|
||||||
|
}), entities.end());
|
||||||
|
|
||||||
|
for(auto e : entities)
|
||||||
|
{
|
||||||
|
auto& entityT = entity->getComponent<TransformComponent>();
|
||||||
float distance = calculateDistance(interactorT.position, entityT.position);
|
float distance = calculateDistance(interactorT.position, entityT.position);
|
||||||
|
|
||||||
if (distance < closestDistance)
|
if (distance < closestDistance) {
|
||||||
{
|
|
||||||
closestDistance = distance;
|
closestDistance = distance;
|
||||||
closestEntity = *it;
|
closestEntity = entity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return closestEntity;
|
return closestEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity* InteractionComponent::findClosestEntityRight(std::vector<Entity*>& entities, TransformComponent& interactorT)
|
std::function<bool(const TransformComponent&)> InteractionComponent::getDirectionalCheck(Direction direction, const TransformComponent& interactorT)
|
||||||
{
|
{
|
||||||
Entity* closestEntity = nullptr;
|
switch(direction)
|
||||||
float closestDistance = std::numeric_limits<float>::max();
|
|
||||||
|
|
||||||
for(auto it = entities.begin(); it != entities.end(); it++)
|
|
||||||
{
|
{
|
||||||
auto& entityT = (*it)->getComponent<TransformComponent>();
|
case Direction::LEFT:
|
||||||
if(entityT.position.x < interactorT.position.x || !isEntityCloseEnoughRight(interactorT.position, entityT.position, interactorT.width))
|
return[&interactorT](const TransformComponent& entityT) {
|
||||||
{
|
return entityT.position.x < interactorT.position.x;
|
||||||
it = entities.erase(it);
|
};
|
||||||
continue;
|
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; };
|
||||||
}
|
}
|
||||||
|
|
||||||
float distance = calculateDistance(interactorT.position, entityT.position);
|
|
||||||
|
|
||||||
if (distance < closestDistance)
|
|
||||||
{
|
|
||||||
closestDistance = distance;
|
|
||||||
closestEntity = *it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return closestEntity;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity* InteractionComponent::findClosestEntityUp(std::vector<Entity*>& entities, TransformComponent& interactorT)
|
bool InteractionComponent::isEntityCloseEnough(const TransformComponent& interactorT, const TransformComponent& entityT, Direction direction)
|
||||||
{
|
{
|
||||||
Entity* closestEntity = nullptr;
|
switch (direction)
|
||||||
float closestDistance = std::numeric_limits<float>::max();
|
|
||||||
|
|
||||||
for(auto it = entities.begin(); it != entities.end(); it++)
|
|
||||||
{
|
{
|
||||||
auto& entityT = (*it)->getComponent<TransformComponent>();
|
case Direction::LEFT:
|
||||||
if(entityT.position.y < interactorT.position.y || !isEntityCloseEnoughUp(interactorT.position, entityT.position, entityT.height))
|
return (entityT.position.x >= (interactorT.position.x - reach));
|
||||||
{
|
case Direction::RIGHT:
|
||||||
it = entities.erase(it);
|
return (entityT.position.x <= (interactorT.position.x + reach));
|
||||||
continue;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
float distance = calculateDistance(interactorT.position, entityT.position);
|
|
||||||
|
|
||||||
if (distance < closestDistance)
|
|
||||||
{
|
|
||||||
closestDistance = distance;
|
|
||||||
closestEntity = *it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return closestEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
Entity* InteractionComponent::findClosestEntityDown(std::vector<Entity*>& entities, TransformComponent& interactorT)
|
|
||||||
{
|
|
||||||
Entity* closestEntity = nullptr;
|
|
||||||
float closestDistance = std::numeric_limits<float>::max();
|
|
||||||
|
|
||||||
for(auto it = entities.begin(); it != entities.end(); it++)
|
|
||||||
{
|
|
||||||
auto& entityT = (*it)->getComponent<TransformComponent>();
|
|
||||||
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)
|
float InteractionComponent::calculateDistance(Vector2D iPos, Vector2D ePos)
|
||||||
{
|
{
|
||||||
return std::abs(ePos.x - iPos.x) + std::abs(ePos.y - iPos.y);
|
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;
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user