Rules are not template anymore (it was dumb)
Entities are now managed with unique_ptr to allow polymorphism (and good memory management) Rules can be added via the Level object Fixed Rule::findTarget not caring about targetType TODO : Find why pathfinding (unlikely) or findTarget (most likely) is broken
This commit is contained in:
parent
4ab83f1124
commit
c94fc5a0be
7 changed files with 221 additions and 193 deletions
187
src/Rule.h
187
src/Rule.h
|
@ -12,12 +12,12 @@
|
|||
|
||||
|
||||
/// Decorates entities with rules which will modify its behaviour
|
||||
template <State targetState, EntityType targetType>
|
||||
class Rule : private Entity
|
||||
class Rule : public Entity
|
||||
{
|
||||
public:
|
||||
Rule(Entity& entity, const std::vector<Entity>& entities,
|
||||
const std::vector<pro_maat::GridPos>& occupiedSquares, const pro_maat::GridPos& mapSize);
|
||||
// The Rule object takes ownership of the Entity*
|
||||
Rule(Entity* entity, State targetState, EntityType targetType, std::vector<std::unique_ptr<Entity>>& entities,
|
||||
const std::vector<pro_maat::GridPos>& occupiedSquares, const pro_maat::GridPos& mapSize);
|
||||
|
||||
/// Update according to the targetState and targetType
|
||||
void update() override;
|
||||
|
@ -26,6 +26,7 @@ public:
|
|||
|
||||
void move(Orientation orientation) override;
|
||||
State getState() const override;
|
||||
EntityType getType() const override;
|
||||
const sf::RectangleShape& getShape() const override;
|
||||
pro_maat::GridPos getTarget() const override;
|
||||
const pro_maat::GridPos getPosition() const override;
|
||||
|
@ -33,182 +34,20 @@ public:
|
|||
|
||||
private:
|
||||
/// Finds the closest free square adjacent to the closest target entity type.
|
||||
/// Currently not thread-safe !
|
||||
/// \return Suitable target square or current position if none was found.
|
||||
pro_maat::GridPos findTarget();
|
||||
|
||||
Entity& entity;
|
||||
const std::vector<Entity>& entities;
|
||||
std::unique_ptr<Entity> entity;
|
||||
|
||||
State targetState;
|
||||
EntityType targetType;
|
||||
|
||||
// TOOD : dropped const-qualifier. Consider using shared_ptr ?
|
||||
std::vector<std::unique_ptr<Entity>>& entities;
|
||||
const std::vector<pro_maat::GridPos>& occupiedSquares;
|
||||
|
||||
const pro_maat::GridPos& mapSize;
|
||||
};
|
||||
|
||||
|
||||
template<State targetState, EntityType targetType>
|
||||
Rule<targetState, targetType>::Rule(Entity& entity,
|
||||
const std::vector<Entity>& entities,
|
||||
const std::vector<pro_maat::GridPos>& occupiedSquares,
|
||||
const pro_maat::GridPos& mapSize)
|
||||
: entity(entity),
|
||||
entities(entities),
|
||||
occupiedSquares(occupiedSquares),
|
||||
mapSize(mapSize)
|
||||
{}
|
||||
|
||||
template<State targetState, EntityType targetType>
|
||||
void Rule<targetState, targetType>::update()
|
||||
{
|
||||
if constexpr (targetState == State::Moving || targetState == State::Fleeing)
|
||||
{
|
||||
entity.nextTarget = findTarget();
|
||||
if(entity.nextTarget == entity.getPosition())
|
||||
{
|
||||
entity.nextState = State::Idle;
|
||||
}
|
||||
else
|
||||
{
|
||||
entity.nextState = targetState;
|
||||
}
|
||||
entity.update();
|
||||
}
|
||||
else if constexpr (targetState == State::Waiting)
|
||||
{
|
||||
entity.nextTarget = entity.getPosition();
|
||||
entity.nextState = State::Waiting;
|
||||
entity.update();
|
||||
}
|
||||
else
|
||||
{
|
||||
entity.nextTarget = entity.getPosition();
|
||||
entity.nextState = State::Idle;
|
||||
entity.update();
|
||||
}
|
||||
}
|
||||
|
||||
template<State targetState, EntityType targetType>
|
||||
pro_maat::GridPos Rule<targetState, targetType>::findTarget()
|
||||
{
|
||||
std::vector<Entity> sortedEntities{};
|
||||
sortedEntities.insert(sortedEntities.end(),entities.begin(),entities.end());
|
||||
|
||||
// Compares entities via their distance to the current entity
|
||||
auto distanceSortEntities = [this](const Entity& leftHandSide, const Entity& rightHandSide){
|
||||
return (pro_maat::manhattanDistance(entity.getPosition(),leftHandSide.getPosition()) <
|
||||
pro_maat::manhattanDistance(entity.getPosition(),rightHandSide.getPosition()));
|
||||
};
|
||||
|
||||
// Same but with grid coordinates
|
||||
auto distanceSortSquares = [this](const pro_maat::GridPos& leftHandSide, const pro_maat::GridPos& rightHandSide){
|
||||
return (pro_maat::manhattanDistance(entity.getPosition(),leftHandSide) <
|
||||
pro_maat::manhattanDistance(entity.getPosition(),rightHandSide));
|
||||
};
|
||||
|
||||
// Get the smallest, non-occupied, inside the map square
|
||||
auto bestTarget = [this](const pro_maat::GridPos& leftHandSide, const pro_maat::GridPos& rightHandSide){
|
||||
// If the left hand side operand is not in the map or occupied, it is not valid
|
||||
if(!pro_maat::isInMap(leftHandSide,mapSize) ||
|
||||
std::find(occupiedSquares.begin(),occupiedSquares.end(),leftHandSide) != occupiedSquares.end())
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
else if(!pro_maat::isInMap(rightHandSide,mapSize) ||
|
||||
std::find(occupiedSquares.begin(),occupiedSquares.end(),rightHandSide) != occupiedSquares.end())
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(leftHandSide < rightHandSide);
|
||||
}};
|
||||
|
||||
|
||||
// Sort in order to minimize entities to process
|
||||
std::sort(sortedEntities.begin(),sortedEntities.end(),distanceSortEntities);
|
||||
|
||||
for(const Entity& processingEntity : sortedEntities)
|
||||
{
|
||||
std::vector<pro_maat::GridPos> potentialTargets{};
|
||||
|
||||
pro_maat::GridUnit entityWidth = processingEntity.shape.getSize().x/pro_maat::pixelsPerUnit;
|
||||
pro_maat::GridUnit entityHeight = processingEntity.shape.getSize().y/pro_maat::pixelsPerUnit;
|
||||
|
||||
potentialTargets.reserve((entityWidth+2)*2+entityHeight*2);
|
||||
|
||||
// Computes the top left corner of the entity
|
||||
pro_maat::GridPos topLeftCorner = processingEntity.getPosition();
|
||||
topLeftCorner.first -= entityWidth*0.5 - 1;
|
||||
topLeftCorner.second -= entityHeight*0.5 - 1;
|
||||
|
||||
|
||||
// Get all the top and bottom adjacent squares
|
||||
for(int i = 0;i<entityWidth+2;i++)
|
||||
{
|
||||
potentialTargets.emplace_back(topLeftCorner.first+i,topLeftCorner.second);
|
||||
potentialTargets.emplace_back(topLeftCorner.first+i,topLeftCorner.second+entityHeight+2);
|
||||
}
|
||||
// Get the missing adjacent squares from the sides
|
||||
for(int i = 1;i<=entityHeight;i++)
|
||||
{
|
||||
potentialTargets.emplace_back(topLeftCorner.first,topLeftCorner.second+i);
|
||||
potentialTargets.emplace_back(topLeftCorner.first+entityWidth+2,topLeftCorner.second+i);
|
||||
}
|
||||
|
||||
|
||||
std::sort(potentialTargets.begin(),potentialTargets.end(),distanceSortSquares);
|
||||
auto target = std::min_element(potentialTargets.begin(),potentialTargets.end(),bestTarget);
|
||||
|
||||
if(target != potentialTargets.end())
|
||||
{
|
||||
return (*target);
|
||||
}
|
||||
}
|
||||
|
||||
return (entity.getPosition());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////
|
||||
// //
|
||||
// Delegate overrides //
|
||||
// //
|
||||
////////////////////////
|
||||
|
||||
|
||||
template<State targetState, EntityType targetType>
|
||||
void Rule<targetState, targetType>::move(Orientation orientation)
|
||||
{
|
||||
entity.move(orientation);
|
||||
}
|
||||
|
||||
template<State targetState, EntityType targetType>
|
||||
State Rule<targetState, targetType>::getState() const
|
||||
{
|
||||
return entity.getState();
|
||||
}
|
||||
|
||||
template<State targetState, EntityType targetType>
|
||||
const sf::RectangleShape& Rule<targetState, targetType>::getShape() const
|
||||
{
|
||||
return entity.getShape();
|
||||
}
|
||||
|
||||
template<State targetState, EntityType targetType>
|
||||
pro_maat::GridPos Rule<targetState, targetType>::getTarget() const
|
||||
{
|
||||
return entity.getTarget();
|
||||
}
|
||||
|
||||
template<State targetState, EntityType targetType>
|
||||
const pro_maat::GridPos Rule<targetState, targetType>::getPosition() const
|
||||
{
|
||||
return entity.getPosition();
|
||||
}
|
||||
|
||||
template<State targetState, EntityType targetType>
|
||||
const std::vector<pro_maat::GridPos> Rule<targetState, targetType>::getOccupiedSquares() const
|
||||
{
|
||||
return entity.getOccupiedSquares();
|
||||
}
|
||||
|
||||
|
||||
#endif //PROJECT_MAAT_RULES_H
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue