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
|
@ -15,11 +15,11 @@ This game is aimed to be a puzzle game in which the player sets different laws f
|
||||||
- [x] Structure
|
- [x] Structure
|
||||||
- [x] Parsing from XML
|
- [x] Parsing from XML
|
||||||
- [x] A*
|
- [x] A*
|
||||||
- [ ] Entities
|
- [x] Entities
|
||||||
- [x] Structure
|
- [x] Structure
|
||||||
- [x] Parsing from XML
|
- [x] Parsing from XML
|
||||||
- [x] Moving
|
- [x] Moving
|
||||||
- [ ] Decorators (Rules)
|
- [x] Decorators (Rules)
|
||||||
- [ ] Rules
|
- [ ] Rules
|
||||||
- [x] Creation
|
- [x] Creation
|
||||||
- [x] Interaction with entities
|
- [x] Interaction with entities
|
||||||
|
@ -32,7 +32,7 @@ This game is aimed to be a puzzle game in which the player sets different laws f
|
||||||
- [ ] Gameloop
|
- [ ] Gameloop
|
||||||
- [ ] Transition from starting to running state and vice-versa
|
- [ ] Transition from starting to running state and vice-versa
|
||||||
- [ ] Entity behaviour evolution
|
- [ ] Entity behaviour evolution
|
||||||
- [ ] Rule application
|
- [x] Rule application
|
||||||
- [ ] Saving state through serialization ?
|
- [ ] Saving state through serialization ?
|
||||||
- [ ] UML
|
- [ ] UML
|
||||||
- [ ] Unit tests
|
- [ ] Unit tests
|
|
@ -79,6 +79,11 @@ State Entity::getState() const
|
||||||
return currentState;
|
return currentState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EntityType Entity::getType() const
|
||||||
|
{
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
pro_maat::GridPos Entity::getTarget() const
|
pro_maat::GridPos Entity::getTarget() const
|
||||||
{
|
{
|
||||||
return target;
|
return target;
|
||||||
|
|
|
@ -51,6 +51,7 @@ public:
|
||||||
virtual void update();
|
virtual void update();
|
||||||
|
|
||||||
virtual State getState() const;
|
virtual State getState() const;
|
||||||
|
virtual EntityType getType() const;
|
||||||
virtual pro_maat::GridPos getTarget() const;
|
virtual pro_maat::GridPos getTarget() const;
|
||||||
|
|
||||||
virtual const sf::RectangleShape& getShape() const;
|
virtual const sf::RectangleShape& getShape() const;
|
||||||
|
@ -84,7 +85,6 @@ private:
|
||||||
/// Used with rules : last to update has priority
|
/// Used with rules : last to update has priority
|
||||||
pro_maat::GridPos nextTarget;
|
pro_maat::GridPos nextTarget;
|
||||||
|
|
||||||
template<State targetState, EntityType targetType>
|
|
||||||
friend class Rule;
|
friend class Rule;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,24 +14,34 @@ Level::Level(const pugi::xml_document& xmlDoc, const pro_maat::TextureStore& tex
|
||||||
{
|
{
|
||||||
if(!strncmp(child.name(),"Entity",6))
|
if(!strncmp(child.name(),"Entity",6))
|
||||||
{
|
{
|
||||||
entities.emplace_back(child,textures.at(child.attribute("textureId").as_int(0)).get());
|
entities.emplace_back(std::make_unique<Entity>(child,textures.at(child.attribute("textureId").as_int(0)).get()));
|
||||||
|
|
||||||
// Initialize the occupied squares vector with the new entity's squares
|
// Initialize the occupied squares vector with the new entity's squares
|
||||||
std::vector<pro_maat::GridPos> entitySquares = entities.rbegin()->getOccupiedSquares();
|
std::vector<pro_maat::GridPos> entitySquares = entities.rbegin()->get()->getOccupiedSquares();
|
||||||
|
std::move(entitySquares.begin(),entitySquares.end(),std::back_inserter(occupiedSquares));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME : For testing purposes
|
// FIXME : For testing purposes
|
||||||
Rule<State::Moving,EntityType::House> newRule(*entities.rbegin(),entities,occupiedSquares,size);
|
addRule(EntityType::Significant,State::Moving,EntityType::Citizen);
|
||||||
|
}
|
||||||
|
|
||||||
std::move(entitySquares.begin(),entitySquares.end(),std::back_inserter(occupiedSquares));
|
void Level::addRule(EntityType affectedEntities, const State targetState, EntityType targetEntities)
|
||||||
|
{
|
||||||
|
for(auto& entity : entities)
|
||||||
|
{
|
||||||
|
if(entity->getType() == affectedEntities)
|
||||||
|
{
|
||||||
|
entity = std::make_unique<Rule>(entity.release(),targetState,targetEntities,entities,occupiedSquares,size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Level::render(sf::RenderWindow& renderWindow) const
|
void Level::render(sf::RenderWindow& renderWindow) const
|
||||||
{
|
{
|
||||||
for(const Entity& entity : entities)
|
for(const auto& entity : entities)
|
||||||
{
|
{
|
||||||
renderWindow.draw(entity.getShape());
|
renderWindow.draw(entity->getShape());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,11 +50,11 @@ void Level::runStep()
|
||||||
std::vector<pro_maat::GridPos> newOccupiedSquares{};
|
std::vector<pro_maat::GridPos> newOccupiedSquares{};
|
||||||
newOccupiedSquares.reserve(occupiedSquares.size());
|
newOccupiedSquares.reserve(occupiedSquares.size());
|
||||||
|
|
||||||
for(Entity& entity: entities)
|
for(auto& entity: entities)
|
||||||
{
|
{
|
||||||
entity.update();
|
entity->update();
|
||||||
int heuristicSign = 0;
|
int heuristicSign = 0;
|
||||||
switch (entity.getState())
|
switch (entity->getState())
|
||||||
{
|
{
|
||||||
case State::Moving:
|
case State::Moving:
|
||||||
{
|
{
|
||||||
|
@ -57,9 +67,9 @@ void Level::runStep()
|
||||||
{
|
{
|
||||||
heuristicSign = -1;
|
heuristicSign = -1;
|
||||||
}
|
}
|
||||||
if(entity.getTarget() != entity.getPosition())
|
if(entity->getTarget() != entity->getPosition())
|
||||||
{
|
{
|
||||||
entity.move(findPath(entity.getPosition(),entity.getTarget(),heuristicSign));
|
entity->move(findPath(entity->getPosition(),entity->getTarget(),heuristicSign));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -67,7 +77,7 @@ void Level::runStep()
|
||||||
case State::Idle:break;
|
case State::Idle:break;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<pro_maat::GridPos> entitySquares = entity.getOccupiedSquares();
|
std::vector<pro_maat::GridPos> entitySquares = entity->getOccupiedSquares();
|
||||||
|
|
||||||
// FIXME : Very heavy memory usage and a lot of duplicates, slows down occupiedSquares.find() calls too.
|
// FIXME : Very heavy memory usage and a lot of duplicates, slows down occupiedSquares.find() calls too.
|
||||||
// Copy the squares to the currently occupied squares : prevents moving into an entity that just moved
|
// Copy the squares to the currently occupied squares : prevents moving into an entity that just moved
|
||||||
|
|
|
@ -21,13 +21,20 @@ class Level {
|
||||||
public:
|
public:
|
||||||
Level(const pugi::xml_document& xmlDoc, const pro_maat::TextureStore& textureStore);
|
Level(const pugi::xml_document& xmlDoc, const pro_maat::TextureStore& textureStore);
|
||||||
|
|
||||||
|
/// Add a new rule on top of existing ones, thus with a lower priority
|
||||||
|
///
|
||||||
|
/// \param affectedEntities Entities to which the rule will be applied
|
||||||
|
/// \param targetState What action will the rule perform
|
||||||
|
/// \param targetEntities Which entities will be targeted
|
||||||
|
void addRule(EntityType affectedEntities, State targetState, EntityType targetEntities);
|
||||||
|
|
||||||
void render(sf::RenderWindow& renderWindow) const;
|
void render(sf::RenderWindow& renderWindow) const;
|
||||||
void runStep();
|
void runStep();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const pro_maat::GridPos size;
|
const pro_maat::GridPos size;
|
||||||
|
|
||||||
std::vector<Entity> entities;
|
std::vector<std::unique_ptr<Entity>> entities;
|
||||||
|
|
||||||
const pro_maat::TextureStore& textures;
|
const pro_maat::TextureStore& textures;
|
||||||
|
|
||||||
|
|
167
src/Rule.cpp
167
src/Rule.cpp
|
@ -3,3 +3,170 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "Rule.h"
|
#include "Rule.h"
|
||||||
|
|
||||||
|
|
||||||
|
Rule::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)
|
||||||
|
: entity(entity),
|
||||||
|
targetState(targetState),
|
||||||
|
targetType(targetType),
|
||||||
|
entities(entities),
|
||||||
|
occupiedSquares(occupiedSquares),
|
||||||
|
mapSize(mapSize)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Rule::update()
|
||||||
|
{
|
||||||
|
if (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 (targetState == State::Waiting)
|
||||||
|
{
|
||||||
|
entity->nextTarget = entity->getPosition();
|
||||||
|
entity->nextState = State::Waiting;
|
||||||
|
entity->update();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entity->nextTarget = entity->getPosition();
|
||||||
|
entity->nextState = State::Idle;
|
||||||
|
entity->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pro_maat::GridPos Rule::findTarget()
|
||||||
|
{
|
||||||
|
// TODO : Sorting in place, consider using shared_ptr ?
|
||||||
|
// 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 std::unique_ptr<Entity>& leftHandSide, const std::unique_ptr<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(entities.begin(),entities.end(),distanceSortEntities);
|
||||||
|
|
||||||
|
for(const auto& processingEntity : entities)
|
||||||
|
{
|
||||||
|
if(processingEntity->getType() != targetType) continue;
|
||||||
|
|
||||||
|
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 //
|
||||||
|
// //
|
||||||
|
////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
void Rule::move(Orientation orientation)
|
||||||
|
{
|
||||||
|
entity->move(orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
State Rule::getState() const
|
||||||
|
{
|
||||||
|
return entity->getState();
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityType Rule::getType() const
|
||||||
|
{
|
||||||
|
return entity->getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
const sf::RectangleShape& Rule::getShape() const
|
||||||
|
{
|
||||||
|
return entity->getShape();
|
||||||
|
}
|
||||||
|
|
||||||
|
pro_maat::GridPos Rule::getTarget() const
|
||||||
|
{
|
||||||
|
return entity->getTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
const pro_maat::GridPos Rule::getPosition() const
|
||||||
|
{
|
||||||
|
return entity->getPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<pro_maat::GridPos> Rule::getOccupiedSquares() const
|
||||||
|
{
|
||||||
|
return entity->getOccupiedSquares();
|
||||||
|
}
|
||||||
|
|
185
src/Rule.h
185
src/Rule.h
|
@ -12,11 +12,11 @@
|
||||||
|
|
||||||
|
|
||||||
/// Decorates entities with rules which will modify its behaviour
|
/// Decorates entities with rules which will modify its behaviour
|
||||||
template <State targetState, EntityType targetType>
|
class Rule : public Entity
|
||||||
class Rule : private Entity
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Rule(Entity& entity, const std::vector<Entity>& entities,
|
// 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);
|
const std::vector<pro_maat::GridPos>& occupiedSquares, const pro_maat::GridPos& mapSize);
|
||||||
|
|
||||||
/// Update according to the targetState and targetType
|
/// Update according to the targetState and targetType
|
||||||
|
@ -26,6 +26,7 @@ public:
|
||||||
|
|
||||||
void move(Orientation orientation) override;
|
void move(Orientation orientation) override;
|
||||||
State getState() const override;
|
State getState() const override;
|
||||||
|
EntityType getType() const override;
|
||||||
const sf::RectangleShape& getShape() const override;
|
const sf::RectangleShape& getShape() const override;
|
||||||
pro_maat::GridPos getTarget() const override;
|
pro_maat::GridPos getTarget() const override;
|
||||||
const pro_maat::GridPos getPosition() const override;
|
const pro_maat::GridPos getPosition() const override;
|
||||||
|
@ -33,182 +34,20 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Finds the closest free square adjacent to the closest target entity type.
|
/// 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.
|
/// \return Suitable target square or current position if none was found.
|
||||||
pro_maat::GridPos findTarget();
|
pro_maat::GridPos findTarget();
|
||||||
|
|
||||||
Entity& entity;
|
std::unique_ptr<Entity> entity;
|
||||||
const std::vector<Entity>& entities;
|
|
||||||
|
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 std::vector<pro_maat::GridPos>& occupiedSquares;
|
||||||
|
|
||||||
const pro_maat::GridPos& mapSize;
|
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
|
#endif //PROJECT_MAAT_RULES_H
|
||||||
|
|
Loading…
Add table
Reference in a new issue