Fixed movement of multiple entities.

Changed std::unique_ptr<Entity> to std::shared_ptr<Entity>.
Fixed pathfinding away from targets

TODO :
 - Fix oscillation around destination
 - Fix fleeing from adjacent target
 - Win conditions
 - GUI
This commit is contained in:
trotFunky 2019-06-10 18:44:45 +02:00
parent 293a564a29
commit 5ccd7d0c13
6 changed files with 33 additions and 21 deletions

View file

@ -5,10 +5,20 @@ Project Maat is the codename of my C++ course "mini-project" based on the quote
This game is aimed to be a puzzle game in which the player sets different laws for the world and the people within it as to control what happens after hitting "play" and achieve the level's goal. I was inspired both by [The Incredible Machine](https://en.wikipedia.org/wiki/The_Incredible_Machine_(video_game)) and its successors and by a much more recent game : [Baba is you](https://en.wikipedia.org/wiki/Baba_Is_You). This game is aimed to be a puzzle game in which the player sets different laws for the world and the people within it as to control what happens after hitting "play" and achieve the level's goal. I was inspired both by [The Incredible Machine](https://en.wikipedia.org/wiki/The_Incredible_Machine_(video_game)) and its successors and by a much more recent game : [Baba is you](https://en.wikipedia.org/wiki/Baba_Is_You).
## Dependencies
The following libraries must be installed on your system or findable by CMake to be able to build:
- SFML
- TGui
- PugiXML
- GTest
## Structure ## Structure
![UML Diagram](UML_Class_Diagram.png) ![UML Diagram](UML_Class_Diagram.png)
The class diagram omits most constructors and getters.
## TODO ## TODO
- [x] Level - [x] Level
@ -25,6 +35,7 @@ This game is aimed to be a puzzle game in which the player sets different laws f
- [x] Interaction with entities - [x] Interaction with entities
- [ ] Parsing of rules and creation of subsequent decorators - [ ] Parsing of rules and creation of subsequent decorators
- [x] Find optimal target for pathfinding - [x] Find optimal target for pathfinding
- [ ] Other rules (Waiting...)
- [ ] Graphics - [ ] Graphics
- [x] Scene rendering - [x] Scene rendering
- [ ] UI - [ ] UI
@ -33,6 +44,7 @@ This game is aimed to be a puzzle game in which the player sets different laws f
- [ ] Transition from starting to running state and vice-versa - [ ] Transition from starting to running state and vice-versa
- [ ] Entity behaviour evolution - [ ] Entity behaviour evolution
- [x] Rule application - [x] Rule application
- [ ] Saving state through serialization ? - [ ] Win condition
- [ ] ~~Saving state through serialization ?~~
- [ ] UML - [ ] UML
- [ ] Unit tests - [ ] Unit tests

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Before After
Before After

View file

@ -14,7 +14,7 @@ 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(std::make_unique<Entity>(child,textures.at(child.attribute("textureId").as_int(0)).get())); entities.emplace_back(std::make_shared<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()->get()->getOccupiedSquares(); std::vector<pro_maat::GridPos> entitySquares = entities.rbegin()->get()->getOccupiedSquares();
@ -23,7 +23,8 @@ Level::Level(const pugi::xml_document& xmlDoc, const pro_maat::TextureStore& tex
} }
// FIXME : For testing purposes // FIXME : For testing purposes
addRule(EntityType::Significant,State::Moving,EntityType::Citizen); addRule(EntityType::Significant,State::Fleeing,EntityType::Citizen);
addRule(EntityType::Citizen,State::Moving,EntityType::Significant);
} }
void Level::addRule(EntityType affectedEntities, const State targetState, EntityType targetEntities) void Level::addRule(EntityType affectedEntities, const State targetState, EntityType targetEntities)
@ -32,7 +33,7 @@ void Level::addRule(EntityType affectedEntities, const State targetState, Entity
{ {
if(entity->getType() == affectedEntities) if(entity->getType() == affectedEntities)
{ {
entity = std::make_unique<Rule>(entity.release(),targetState,targetEntities,entities,occupiedSquares,size); entity = std::make_shared<Rule>(entity,targetState,targetEntities,entities,occupiedSquares,size);
} }
} }
} }
@ -189,7 +190,7 @@ Orientation Level::findPath(pro_maat::GridPos start, pro_maat::GridPos goal, int
} }
pathCosts.insert_or_assign(neighbour,newPathCost); pathCosts.insert_or_assign(neighbour,newPathCost);
estimatedCosts.insert_or_assign(neighbour,newPathCost + pro_maat::manhattanDistance(neighbour,goal)); estimatedCosts.insert_or_assign(neighbour,newPathCost + pro_maat::manhattanDistance(neighbour,goal)*sign);
paths.insert_or_assign(neighbour,currentNode); paths.insert_or_assign(neighbour,currentNode);
} }
} }

View file

@ -11,6 +11,7 @@
#include <cstring> #include <cstring>
#include <set> #include <set>
#include <map> #include <map>
#include <memory>
#include "Utils.h" #include "Utils.h"
#include "Entity.h" #include "Entity.h"
@ -34,7 +35,7 @@ public:
private: private:
const pro_maat::GridPos size; const pro_maat::GridPos size;
std::vector<std::unique_ptr<Entity>> entities; std::vector<std::shared_ptr<Entity>> entities;
const pro_maat::TextureStore& textures; const pro_maat::TextureStore& textures;

View file

@ -5,10 +5,10 @@
#include "Rule.h" #include "Rule.h"
Rule::Rule(Entity* entity, State targetState, EntityType targetType, Rule::Rule(std::shared_ptr<Entity> entity, State targetState, EntityType targetType,
std::vector<std::unique_ptr<Entity>>& entities, const std::vector<std::shared_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)
: entity(entity), : entity(std::move(entity)),
targetState(targetState), targetState(targetState),
targetType(targetType), targetType(targetType),
entities(entities), entities(entities),
@ -47,12 +47,11 @@ void Rule::update()
pro_maat::GridPos Rule::findTarget() pro_maat::GridPos Rule::findTarget()
{ {
// TODO : Sorting in place, consider using shared_ptr ? std::vector<std::shared_ptr<Entity>> sortedEntities{};
// std::vector<Entity> sortedEntities{}; sortedEntities.insert(sortedEntities.end(),entities.begin(),entities.end());
// sortedEntities.insert(sortedEntities.end(),entities.begin(),entities.end());
// Compares entities via their distance to the current entity // Compares entities via their distance to the current entity
auto distanceSortEntities = [this](const std::unique_ptr<Entity>& leftHandSide, const std::unique_ptr<Entity>& rightHandSide){ auto distanceSortEntities = [this](const std::shared_ptr<Entity>& leftHandSide, const std::shared_ptr<Entity>& rightHandSide){
return (pro_maat::manhattanDistance(entity->getPosition(),leftHandSide->getPosition()) < return (pro_maat::manhattanDistance(entity->getPosition(),leftHandSide->getPosition()) <
pro_maat::manhattanDistance(entity->getPosition(),rightHandSide->getPosition())); pro_maat::manhattanDistance(entity->getPosition(),rightHandSide->getPosition()));
}; };
@ -90,9 +89,9 @@ pro_maat::GridPos Rule::findTarget()
// Sort in order to minimize entities to process // Sort in order to minimize entities to process
std::sort(entities.begin(),entities.end(),distanceSortEntities); std::sort(sortedEntities.begin(),sortedEntities.end(),distanceSortEntities);
for(const auto& processingEntity : entities) for(const auto& processingEntity : sortedEntities)
{ {
if(processingEntity->getType() != targetType) continue; if(processingEntity->getType() != targetType) continue;
@ -128,7 +127,6 @@ pro_maat::GridPos Rule::findTarget()
if(target != potentialTargets.end()) if(target != potentialTargets.end())
{ {
std::cout << "Target : (" << (*target).first << ","<< (*target).second << ")" << std::endl;
return (*target); return (*target);
} }
} }

View file

@ -8,7 +8,7 @@
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <math.h> #include <math.h>
#include <iostream> #include <memory>
#include "Entity.h" #include "Entity.h"
@ -18,7 +18,8 @@ class Rule : public Entity
{ {
public: public:
// The Rule object takes ownership of the Entity* // The Rule object takes ownership of the Entity*
Rule(Entity* entity, State targetState, EntityType targetType, std::vector<std::unique_ptr<Entity>>& entities, Rule(std::shared_ptr<Entity> entity, State targetState, EntityType targetType,
const std::vector<std::shared_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
@ -40,13 +41,12 @@ private:
/// \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();
std::unique_ptr<Entity> entity; std::shared_ptr<Entity> entity;
State targetState; State targetState;
EntityType targetType; EntityType targetType;
// TOOD : dropped const-qualifier. Consider using shared_ptr ? const std::vector<std::shared_ptr<Entity>>& entities;
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;