diff --git a/README.md b/README.md index acb88d6..576b9e4 100644 --- a/README.md +++ b/README.md @@ -13,19 +13,19 @@ This game is aimed to be a puzzle game in which the player sets different laws f - [ ] Level - [x] Structure - - [x] Parsing from XML + - [ ] Parsing from XML - [ ] A* - [ ] Entities - [x] Structure - - [x] Parsing from XML - - [x] Moving + - [ ] Parsing from XML + - [ ] Moving - [ ] Decorators (Rules) - [ ] Rules - [ ] Creation - [ ] Interaction with entities - [ ] Parsing of rules and creation of subsequent decorators - [ ] Graphics - - [x] Scene rendering + - [ ] Scene rendering - [ ] UI - [ ] Menu ? - [ ] Gameloop diff --git a/UML_Class_Diagram.png b/UML_Class_Diagram.png index 7800665..5f40a3d 100644 Binary files a/UML_Class_Diagram.png and b/UML_Class_Diagram.png differ diff --git a/resources/Building.png b/resources/Building.png deleted file mode 100644 index 32fc6fa..0000000 Binary files a/resources/Building.png and /dev/null differ diff --git a/resources/Head_Boy.png b/resources/Head_Boy.png deleted file mode 100644 index 3a741fc..0000000 Binary files a/resources/Head_Boy.png and /dev/null differ diff --git a/resources/Head_Significant_Boy.png b/resources/Head_Significant_Boy.png deleted file mode 100644 index 8bca5c3..0000000 Binary files a/resources/Head_Significant_Boy.png and /dev/null differ diff --git a/resources/test_level.xml b/resources/test_level.xml index 65faa1f..7b4af30 100644 --- a/resources/test_level.xml +++ b/resources/test_level.xml @@ -2,6 +2,5 @@ - - + \ No newline at end of file diff --git a/resources/verdana.ttf b/resources/verdana.ttf deleted file mode 100644 index 0176950..0000000 Binary files a/resources/verdana.ttf and /dev/null differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3f9b184..df21f86 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,10 +4,9 @@ project(project_maat) set(CMAKE_CXX_STANDARD 17) set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH}) -add_library(engine Level.cpp Level.h Entity.cpp Entity.h Game.cpp Game.h Utils.h Utils.h Utils.cpp) +add_library(engine Level.cpp Level.h Entity.cpp Entity.h Game.cpp Game.h Utils.h Utils.h) target_link_libraries(engine sfml-window sfml-graphics - sfml-system - pugixml) \ No newline at end of file + sfml-system) \ No newline at end of file diff --git a/src/Entity.cpp b/src/Entity.cpp index 921df1f..fd4cfca 100644 --- a/src/Entity.cpp +++ b/src/Entity.cpp @@ -6,95 +6,36 @@ const std::map Entity::entityTypeLookup = { {"Citizen",EntityType::Citizen}, - {"Significant",EntityType::Significant}, + {"Player",EntityType::Player}, {"House",EntityType::House}, {"Car",EntityType::Car}}; -Entity::Entity(int x, int y, EntityType type, sf::Texture* texture, int width, int height) : type(type) +Entity::Entity(int x, int y, EntityType type, int width, int height) { - shape = sf::RectangleShape(sf::Vector2f(width*pro_maat::pixelsPerUnit,height*pro_maat::pixelsPerUnit)); - // Sets the origin at the center of the entity - shape.setOrigin(shape.getSize()/2.0f); - // Adjust position for offset origin - shape.setPosition((x+0.5*width)*pro_maat::pixelsPerUnit,(y+0.5*width)*pro_maat::pixelsPerUnit); - shape.setTexture(texture); - currentState = State::Idle; - nextState = State::Idle; - target = sf::Vector2i(shape.getPosition()); - nextTarget = target; } -Entity::Entity(const pugi::xml_node& entityNode, sf::Texture* texture) - : Entity(entityNode.attribute("x").as_int(), - entityNode.attribute("y").as_int(), - entityTypeLookup.at(entityNode.attribute("type").as_string()), - texture, - entityNode.attribute("w").as_int(1), - entityNode.attribute("h").as_int(1)) {} - -void Entity::move(Orientation orientation) +Entity::Entity(const pugi::xml_node& entityNode) { - // TODO : Add speed ? - shape.setRotation(static_cast(orientation)); - sf::Vector2f movementVector(0,0); - switch (orientation) - { - case Orientation::North: - movementVector.y = -pro_maat::pixelsPerUnit; - break; - case Orientation::East: - movementVector.x = pro_maat::pixelsPerUnit; - break; - case Orientation::South: - movementVector.y = pro_maat::pixelsPerUnit; - break; - case Orientation::West: - movementVector.x = -pro_maat::pixelsPerUnit; - break; - } +} + +void Entity::render(sf::RenderWindow& renderWindow) const +{ + +} + +void Entity::move() +{ - shape.setPosition(shape.getPosition()+movementVector); } void Entity::update() -{} +{ + +} const sf::RectangleShape& Entity::getShape() const { return(shape); } - -const State Entity::getState() const -{ - return currentState; -} - -const sf::Vector2i Entity::getPosition() const -{ - // Safe : size is a multiple of pro_maat::pixelsPerUnit - uint8_t x = (shape.getPosition().x-0.5*shape.getSize().x)/pro_maat::pixelsPerUnit; - uint8_t y = (shape.getPosition().y-0.5*shape.getSize().y)/pro_maat::pixelsPerUnit; - return sf::Vector2i(x,y); -} - -const std::vector> Entity::getOccupiedSquares() const -{ - std::vector> occupiedSquares; - // Safe : size is a multiple of pro_maat::pixelsPerUnit - uint8_t w = shape.getSize().x/pro_maat::pixelsPerUnit; - uint8_t h = shape.getSize().y/pro_maat::pixelsPerUnit; - uint8_t x = shape.getPosition().x/pro_maat::pixelsPerUnit - 0.5*w; - uint8_t y = shape.getPosition().y/pro_maat::pixelsPerUnit - 0.5*h; - - for(int i = 0;i #include -#include #include "Utils.h" @@ -15,7 +14,7 @@ enum class EntityType { Citizen, - Significant, + Player, House, Car, }; @@ -30,10 +29,10 @@ enum class State enum class Orientation { - North = 0, - East = 90, - South = 180, - West = 270, + Nort, + East, + South, + West, }; @@ -41,26 +40,20 @@ class Entity { public: /// x,y, width and height are in grid coordinates - Entity(int x, int y, EntityType type, sf::Texture* texture, int width = 1, int height = 1); - explicit Entity(const pugi::xml_node& entityNode, sf::Texture* texture); + Entity(int x, int y, EntityType type, int width = 1, int height = 1); + Entity(const pugi::xml_node& entityNode); - void move(Orientation orientation); + void render(sf::RenderWindow& renderWindow) const; + void move(); void update(); const sf::RectangleShape& getShape() const; - const State getState() const; - const sf::Vector2i getPosition() const; - // Don't like it : iterates over every square every tick - const std::vector> getOccupiedSquares() const; - /// Position of the target of the current action on the map sf::Vector2i target; private: static const std::map entityTypeLookup; - EntityType type; - // As it contains position, size and orientation, we do not need anything more sf::RectangleShape shape; diff --git a/src/Game.cpp b/src/Game.cpp index b1c7df0..6983d39 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -7,20 +7,22 @@ #include "Game.h" -Game::Game(std::vector& levels, std::vector& textures) : levelFiles(std::move(levels)), - textureFiles(std::move(textures)) +Game::Game(const std::vector& levels, const std::vector& textures) { + + loadTextures(); } void Game::loadLevel(int levelId) { pugi::xml_document document; - pugi::xml_parse_result result = document.load_file((pro_maat::levelFolder+levelFiles.at(levelId)).c_str()); + pugi::xml_parse_result result = document.load_file(levelFiles.at(levelId).c_str()); if(!result) { - pro_maat::errorWindow(result.description()); + std::cerr << "Error while loading level :\n" << "\t" << result.description() << std::endl; + exit(-1); } currentLevel = std::make_unique(document,textures); @@ -32,39 +34,11 @@ void Game::loadTextures() for(const std::string& filePath : textureFiles) { textures.emplace_back(std::make_unique()); - textures.back()->loadFromFile(pro_maat::textureFolder+filePath); + textures.back()->loadFromFile(filePath); } } void Game::runGame() { - sf::RenderWindow window(sf::VideoMode(1280,1024),"Project Maat"); - sf::Clock clock; - - while (window.isOpen()) - { - sf::Event event; - while (window.pollEvent(event)) - { - if (event.type == sf::Event::Closed) - { - window.close(); - } - } - if (clock.getElapsedTime().asMilliseconds() >= 200) - { - currentLevel->runStep(); - clock.restart(); - } - window.clear(sf::Color::White); - // TODO : Consider drawing in a sf::RenderTexture to allow positioning the level at a fixed position ? - currentLevel->render(window); - window.display(); - } -} - -Game::operator bool() const -{ - return (currentLevel ? true : false); } diff --git a/src/Game.h b/src/Game.h index aa149d7..da9f7b2 100644 --- a/src/Game.h +++ b/src/Game.h @@ -11,14 +11,14 @@ #include "Level.h" #include "Entity.h" -#include "Utils.h" + // Used for convenience using TextureStore = std::vector>; class Game { public: - Game(std::vector& levels, std::vector& textures); + Game(const std::vector& levels, const std::vector& textures); /// Loads the level of corresponding ID from Game::levelFiles /// Closes the program if there is a fatal error (Missing file, bad file...) @@ -29,8 +29,6 @@ public: // This should not be called before a level has been loaded void runGame(); - explicit operator bool() const; - private: /// Store the paths to level files const std::vector levelFiles; diff --git a/src/Level.cpp b/src/Level.cpp index e5c4e22..1c0903b 100644 --- a/src/Level.cpp +++ b/src/Level.cpp @@ -14,66 +14,17 @@ Level::Level(const pugi::xml_document& xmlDoc, const TextureStore& textureStore) { if(!strncmp(child.name(),"Entity",6)) { - entities.emplace_back(child,textures.at(child.attribute("textureId").as_int(0)).get()); - - // Initialize the occupied squares vector with the new entity's squares - std::vector> entitySquares = entities.rbegin()->getOccupiedSquares(); - std::move(entitySquares.begin(),entitySquares.end(),std::back_inserter(occupiedSquares)); + entities.emplace_back(child); } } } void Level::render(sf::RenderWindow& renderWindow) const { - for(const Entity& entity : entities) - { - renderWindow.draw(entity.getShape()); - } + } -void Level::runStep() +void Level::runStep() const { - std::vector> newOccupiedSquares{}; - newOccupiedSquares.reserve(occupiedSquares.size()); - for(Entity& entity: entities) - { - entity.update(); - int heuristicSign = 0; - switch (entity.getState()) - { - case State::Moving: - { - heuristicSign = 1; - } - case State::Fleeing: - { - if(heuristicSign == 0) - { - heuristicSign = -1; - } - if(entity.target != entity.getPosition()) - { - entity.move(findPath(entity.getPosition(),entity.target,heuristicSign)); - } - break; - } - case State::Waiting:break; - case State::Idle:break; - } - - // Moves the occupied squares from the entity to the new occupied squares vector - std::vector> entitySquares = entity.getOccupiedSquares(); - std::move(entitySquares.begin(),entitySquares.end(),std::back_inserter(newOccupiedSquares)); - } - - occupiedSquares.swap(newOccupiedSquares); - // Sort the vector as to get O(ln(n)) complexity when searching for a square - std::sort(occupiedSquares.begin(),occupiedSquares.end()); -} - -Orientation Level::findPath(sf::Vector2i start, sf::Vector2i end, int sign) -{ - // TODO : A* which returns the next move - return Orientation::East; } diff --git a/src/Level.h b/src/Level.h index 681a6a6..63379f9 100644 --- a/src/Level.h +++ b/src/Level.h @@ -20,7 +20,7 @@ public: Level(const pugi::xml_document& xmlDoc, const TextureStore& textureStore); void render(sf::RenderWindow& renderWindow) const; - void runStep(); + void runStep() const; private: const sf::Vector2i size; @@ -28,14 +28,6 @@ private: std::vector entities; const TextureStore& textures; - - // - // Pathfinding - // - - std::vector> occupiedSquares; - - Orientation findPath(sf::Vector2i start, sf::Vector2i end, int sign); }; diff --git a/src/Utils.cpp b/src/Utils.cpp deleted file mode 100644 index 4c75c2f..0000000 --- a/src/Utils.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// -// Created by trotfunky on 07/06/19. -// - -#include "Utils.h" - -namespace pro_maat -{ - void errorWindow(const std::string& error) - { - sf::Font font; - if(!font.loadFromFile(std::string(pro_maat::fontFolder)+"verdana.ttf")) - { - std::cerr << "Error while loading font for error :" << std::endl; - std::cerr << error << std::endl; - } - - sf::Text errorMessage(error,font); - errorMessage.setFillColor(sf::Color::Red); - sf::Rect errorArea = errorMessage.getGlobalBounds(); - errorMessage.setPosition(errorArea.width*(1.5/2-0.5),errorArea.height*(0.5)); - sf::RenderWindow window(sf::VideoMode(errorArea.width*1.5,errorArea.height*2),"ERROR"); - while (window.isOpen()) - { - sf::Event event; - while(window.pollEvent(event)) - { - if (event.type == sf::Event::Closed || event.type == sf::Event::KeyPressed || event.type == sf::Event::MouseButtonPressed) - { - window.close(); - exit(-1); - } - } - window.clear(sf::Color::White); - window.draw(errorMessage); - window.display(); - } - } -} \ No newline at end of file diff --git a/src/Utils.h b/src/Utils.h index 4632cb0..8fa40a5 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -6,19 +6,12 @@ #define PROJECT_MAAT_UTILS_H #include -#include -#include -#include + namespace pro_maat { -static constexpr uint8_t pixelsPerUnit = 50; -static constexpr char levelFolder[] = "resources/"; -static constexpr char textureFolder[] = "resources/"; -static constexpr char fontFolder[] = "resources/"; - -void errorWindow(const std::string& error); +static constexpr uint8_t pixelsPerUnit = 20; } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bdde3da..0924c9a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,13 +6,7 @@ set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules" ${CMAKE_MODULE_PATH}) add_executable(gTests gTests.cpp gTests.cpp) -target_include_directories(gTests PRIVATE ${PROJECT_SOURCE_DIR}/../src) - target_link_libraries(gTests engine gtest - pthread - sfml-window - sfml-graphics - sfml-system - pugixml) \ No newline at end of file + pthread) \ No newline at end of file diff --git a/tests/gTests.cpp b/tests/gTests.cpp index bcdb5ff..0eccc74 100644 --- a/tests/gTests.cpp +++ b/tests/gTests.cpp @@ -3,23 +3,6 @@ // #include -#include - -#include "Game.h" - -TEST(Setup,GameSetup) -{ - // TODO : Think about parsing from file ? Currently cumbersome and error-prone - std::vector textures = {"Head_Boy.png","Head_Significant_Boy.png","Building.png"}; - std::vector levels = {"test_level.xml"}; - - Game game(levels,textures); - ASSERT_FALSE(game); - game.loadLevel(0); - ASSERT_TRUE(game); - game.runGame(); -} - int main(int argc, char** argv) {