diff --git a/README.md b/README.md index 576b9e4..5830649 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,11 @@ This game is aimed to be a puzzle game in which the player sets different laws f - [ ] Level - [x] Structure - - [ ] Parsing from XML + - [x] Parsing from XML - [ ] A* - [ ] Entities - [x] Structure - - [ ] Parsing from XML + - [x] Parsing from XML - [ ] Moving - [ ] Decorators (Rules) - [ ] Rules @@ -25,7 +25,7 @@ This game is aimed to be a puzzle game in which the player sets different laws f - [ ] Interaction with entities - [ ] Parsing of rules and creation of subsequent decorators - [ ] Graphics - - [ ] Scene rendering + - [x] Scene rendering - [ ] UI - [ ] Menu ? - [ ] Gameloop diff --git a/resources/Building.png b/resources/Building.png new file mode 100644 index 0000000..32fc6fa Binary files /dev/null and b/resources/Building.png differ diff --git a/resources/Head_Boy.png b/resources/Head_Boy.png new file mode 100644 index 0000000..3a741fc Binary files /dev/null and b/resources/Head_Boy.png differ diff --git a/resources/Head_Significant_Boy.png b/resources/Head_Significant_Boy.png new file mode 100644 index 0000000..8bca5c3 Binary files /dev/null and b/resources/Head_Significant_Boy.png differ diff --git a/resources/test_level.xml b/resources/test_level.xml index 7b4af30..65faa1f 100644 --- a/resources/test_level.xml +++ b/resources/test_level.xml @@ -2,5 +2,6 @@ - + + \ No newline at end of file diff --git a/resources/verdana.ttf b/resources/verdana.ttf new file mode 100644 index 0000000..0176950 Binary files /dev/null and b/resources/verdana.ttf differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index df21f86..3f9b184 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,9 +4,10 @@ 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) +add_library(engine Level.cpp Level.h Entity.cpp Entity.h Game.cpp Game.h Utils.h Utils.h Utils.cpp) target_link_libraries(engine sfml-window sfml-graphics - sfml-system) \ No newline at end of file + sfml-system + pugixml) \ No newline at end of file diff --git a/src/Entity.cpp b/src/Entity.cpp index fd4cfca..a6b14a6 100644 --- a/src/Entity.cpp +++ b/src/Entity.cpp @@ -6,28 +6,37 @@ const std::map Entity::entityTypeLookup = { {"Citizen",EntityType::Citizen}, - {"Player",EntityType::Player}, + {"Significant",EntityType::Significant}, {"House",EntityType::House}, {"Car",EntityType::Car}}; -Entity::Entity(int x, int y, EntityType type, int width, int height) +Entity::Entity(int x, int y, EntityType type, sf::Texture* texture, int width, int height) : type(type) { + 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) -{ - -} - -void Entity::render(sf::RenderWindow& renderWindow) const -{ - -} +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() { - + // FIXME : Testing purposes + shape.setRotation(shape.getRotation()+90); } void Entity::update() diff --git a/src/Entity.h b/src/Entity.h index be52d46..32ddfb9 100644 --- a/src/Entity.h +++ b/src/Entity.h @@ -14,7 +14,7 @@ enum class EntityType { Citizen, - Player, + Significant, House, Car, }; @@ -40,10 +40,9 @@ class Entity { public: /// x,y, width and height are in grid coordinates - Entity(int x, int y, EntityType type, int width = 1, int height = 1); - Entity(const pugi::xml_node& entityNode); + 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); - void render(sf::RenderWindow& renderWindow) const; void move(); void update(); @@ -54,6 +53,8 @@ public: 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 6983d39..0262418 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -7,22 +7,22 @@ #include "Game.h" -Game::Game(const std::vector& levels, const std::vector& textures) +Game::Game(std::vector& levels, std::vector& textures) : levelFiles(std::move(levels)), + textureFiles(std::move(textures)) { - - loadTextures(); } void Game::loadLevel(int levelId) { pugi::xml_document document; - pugi::xml_parse_result result = document.load_file(levelFiles.at(levelId).c_str()); + pugi::xml_parse_result result = document.load_file((pro_maat::levelFolder+levelFiles.at(levelId)).c_str()); if(!result) { - std::cerr << "Error while loading level :\n" << "\t" << result.description() << std::endl; - exit(-1); +// std::cerr << "Error while loading level :\n" << "\t" << result.description() << std::endl; +// exit(-1); + pro_maat::errorWindow(result.description()); } currentLevel = std::make_unique(document,textures); @@ -34,11 +34,37 @@ void Game::loadTextures() for(const std::string& filePath : textureFiles) { textures.emplace_back(std::make_unique()); - textures.back()->loadFromFile(filePath); + textures.back()->loadFromFile(pro_maat::textureFolder+filePath); } } void Game::runGame() { + sf::RenderWindow window(sf::VideoMode(1280,1024),"Project Maat"); + while (window.isOpen()) + { + sf::Event event; + while (window.pollEvent(event)) + { + if (event.type == sf::Event::Closed) + { + window.close(); + } + // FIXME : For testing purposes + if (event.type == sf::Event::KeyPressed) + { + currentLevel->runStep(); + } + } + 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 da9f7b2..aa149d7 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(const std::vector& levels, const std::vector& textures); + Game(std::vector& levels, 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,6 +29,8 @@ 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 1c0903b..20fbfb3 100644 --- a/src/Level.cpp +++ b/src/Level.cpp @@ -14,17 +14,24 @@ Level::Level(const pugi::xml_document& xmlDoc, const TextureStore& textureStore) { if(!strncmp(child.name(),"Entity",6)) { - entities.emplace_back(child); + entities.emplace_back(child,textures.at(child.attribute("textureId").as_int(0)).get()); } } } void Level::render(sf::RenderWindow& renderWindow) const { - + for(const Entity& entity : entities) + { + renderWindow.draw(entity.getShape()); + } } -void Level::runStep() const +void Level::runStep() { - + for(Entity& entity: entities) + { + // FIXME : For testing purposes + entity.move(); + } } diff --git a/src/Level.h b/src/Level.h index 63379f9..52d9f07 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() const; + void runStep(); private: const sf::Vector2i size; diff --git a/src/Utils.cpp b/src/Utils.cpp new file mode 100644 index 0000000..4c75c2f --- /dev/null +++ b/src/Utils.cpp @@ -0,0 +1,39 @@ +// +// 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 8fa40a5..4b837d3 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -6,12 +6,19 @@ #define PROJECT_MAAT_UTILS_H #include - +#include +#include +#include namespace pro_maat { -static constexpr uint8_t pixelsPerUnit = 20; +static constexpr uint8_t pixelsPerUnit = 25; +static constexpr char levelFolder[] = "resources/"; +static constexpr char textureFolder[] = "resources/"; +static constexpr char fontFolder[] = "resources/"; + +void errorWindow(const std::string& error); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0924c9a..bdde3da 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,7 +6,13 @@ 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) \ No newline at end of file + pthread + sfml-window + sfml-graphics + sfml-system + pugixml) \ No newline at end of file diff --git a/tests/gTests.cpp b/tests/gTests.cpp index 0eccc74..6997d4a 100644 --- a/tests/gTests.cpp +++ b/tests/gTests.cpp @@ -3,6 +3,23 @@ // #include +#include + +#include "Game.h" + +TEST(Setup,LevelSetup) +{ + // 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) {