diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a45a644..19add0c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 20) add_subdirectory(${PROJECT_SOURCE_DIR}/lib/wal) add_executable(bomberman - sources/main.cpp + sources/main.cpp ) target_link_libraries(bomberman wal) \ No newline at end of file diff --git a/lib/wal/CMakeLists.txt b/lib/wal/CMakeLists.txt index 9174be58..abfe5129 100644 --- a/lib/wal/CMakeLists.txt +++ b/lib/wal/CMakeLists.txt @@ -4,9 +4,15 @@ project(wal) set(CMAKE_CXX_STANDARD 20) add_library(wal - Entity/Entity.hpp - Component/Component.hpp - System/System.hpp - Wal.cpp - Wal.hpp -) \ No newline at end of file + sources/Entity/Entity.hpp + sources/Component/Component.hpp + sources/System/System.hpp + sources/Wal.cpp + sources/Wal.hpp + sources/Scene/SceneManager.cpp + sources/Scene/SceneManager.hpp + sources/Scene/Scene.cpp + sources/Scene/Scene.hpp + sources/Renderer/Renderer.cpp sources/Renderer/Renderer.hpp sources/Events/EventManager.cpp sources/Events/EventManager.hpp sources/Exception/WalError.cpp sources/Exception/WalError.hpp) + +target_include_directories(wal PUBLIC sources) \ No newline at end of file diff --git a/lib/wal/Component/Component.hpp b/lib/wal/sources/Component/Component.hpp similarity index 100% rename from lib/wal/Component/Component.hpp rename to lib/wal/sources/Component/Component.hpp diff --git a/lib/wal/Entity/Entity.hpp b/lib/wal/sources/Entity/Entity.hpp similarity index 97% rename from lib/wal/Entity/Entity.hpp rename to lib/wal/sources/Entity/Entity.hpp index 029ccf7c..6b71a5f6 100644 --- a/lib/wal/Entity/Entity.hpp +++ b/lib/wal/sources/Entity/Entity.hpp @@ -39,7 +39,7 @@ namespace WAL //! @brief Add a component to this entity. The component is constructed in place. //! @return This entity is returned - template + template Entity &addComponent(Types ...params); //! @brief Copy a component to this entity. diff --git a/lib/wal/Wal.cpp b/lib/wal/sources/Events/EventManager.cpp similarity index 54% rename from lib/wal/Wal.cpp rename to lib/wal/sources/Events/EventManager.cpp index 81ad105f..69b939b7 100644 --- a/lib/wal/Wal.cpp +++ b/lib/wal/sources/Events/EventManager.cpp @@ -2,9 +2,4 @@ // Created by Zoe Roux on 2021-05-14. // -#include "Wal.hpp" - -namespace WAL -{ - -} \ No newline at end of file +#include "EventManager.hpp" diff --git a/lib/wal/sources/Events/EventManager.hpp b/lib/wal/sources/Events/EventManager.hpp new file mode 100644 index 00000000..a1f608e1 --- /dev/null +++ b/lib/wal/sources/Events/EventManager.hpp @@ -0,0 +1,15 @@ +// +// Created by Zoe Roux on 2021-05-14. +// + + +#pragma once + +namespace WAL +{ + //! @brief A class to handle events. + class EventManager + { + + }; +} diff --git a/lib/wal/sources/Exception/WalError.cpp b/lib/wal/sources/Exception/WalError.cpp new file mode 100644 index 00000000..acfc32d5 --- /dev/null +++ b/lib/wal/sources/Exception/WalError.cpp @@ -0,0 +1,20 @@ +// +// Created by Zoe Roux on 2021-05-14. +// + +#include "WalError.hpp" + +namespace WAL +{ + WalError::WalError(const std::string &what) + : std::runtime_error(what) + {} + + SystemExistError::SystemExistError(const std::string &what) + : WalError(what) + {} + + NotFoundError::NotFoundError(const std::string &what) + : WalError(what) + {} +} \ No newline at end of file diff --git a/lib/wal/sources/Exception/WalError.hpp b/lib/wal/sources/Exception/WalError.hpp new file mode 100644 index 00000000..7b456a53 --- /dev/null +++ b/lib/wal/sources/Exception/WalError.hpp @@ -0,0 +1,54 @@ +// +// Created by Zoe Roux on 2021-05-14. +// + + +#pragma once + +#include +#include + +namespace WAL +{ + //! @brief The base class for WAL's exceptions. + class WalError : public std::runtime_error + { + public: + //! @brief Create a new wal exception + explicit WalError(const std::string &what); + //! @brief A wal exception is copy constructable + WalError(const WalError &) = default; + //! @brief A default destructor + ~WalError() override = default; + //! @brief A default assignment operator + WalError &operator=(const WalError &) = default; + }; + + //! @brief An exception informing the user that a system already exists. + class SystemExistError : public WalError + { + public: + //! @brief Create a new wal exception + explicit SystemExistError(const std::string &what); + //! @brief A wal exception is copy constructable + SystemExistError(const SystemExistError &) = default; + //! @brief A default destructor + ~SystemExistError() override = default; + //! @brief A default assignment operator + SystemExistError &operator=(const SystemExistError &) = default; + }; + + //! @brief An exception informing the user that something could not be found + class NotFoundError : public WalError + { + public: + //! @brief Create a new wal exception + explicit NotFoundError(const std::string &what); + //! @brief A wal exception is copy constructable + NotFoundError(const NotFoundError &) = default; + //! @brief A default destructor + ~NotFoundError() override = default; + //! @brief A default assignment operator + NotFoundError &operator=(const NotFoundError &) = default; + }; +} diff --git a/lib/wal/sources/Renderer/Renderer.cpp b/lib/wal/sources/Renderer/Renderer.cpp new file mode 100644 index 00000000..28b61e34 --- /dev/null +++ b/lib/wal/sources/Renderer/Renderer.cpp @@ -0,0 +1,5 @@ +// +// Created by Zoe Roux on 2021-05-14. +// + +#include "Renderer.hpp" diff --git a/lib/wal/Wal.hpp b/lib/wal/sources/Renderer/Renderer.hpp similarity index 84% rename from lib/wal/Wal.hpp rename to lib/wal/sources/Renderer/Renderer.hpp index 009033ba..697f76ad 100644 --- a/lib/wal/Wal.hpp +++ b/lib/wal/sources/Renderer/Renderer.hpp @@ -7,7 +7,7 @@ namespace WAL { - class WAL + class Renderer { }; diff --git a/lib/wal/sources/Scene/Scene.cpp b/lib/wal/sources/Scene/Scene.cpp new file mode 100644 index 00000000..2158ac61 --- /dev/null +++ b/lib/wal/sources/Scene/Scene.cpp @@ -0,0 +1,5 @@ +// +// Created by Zoe Roux on 2021-05-14. +// + +#include "Scene.hpp" diff --git a/lib/wal/sources/Scene/Scene.hpp b/lib/wal/sources/Scene/Scene.hpp new file mode 100644 index 00000000..52a85c4f --- /dev/null +++ b/lib/wal/sources/Scene/Scene.hpp @@ -0,0 +1,20 @@ +// +// Created by Zoe Roux on 2021-05-14. +// + + +#pragma once + +#include +#include "Entity/Entity.hpp" + +namespace WAL +{ + //! @brief Represent a single scene that contains entities. + class Scene + { + private: + //! @brief The list of registered entities + std::vector _entity; + }; +} diff --git a/lib/wal/sources/Scene/SceneManager.cpp b/lib/wal/sources/Scene/SceneManager.cpp new file mode 100644 index 00000000..5ffbcc26 --- /dev/null +++ b/lib/wal/sources/Scene/SceneManager.cpp @@ -0,0 +1,31 @@ +// +// Created by Zoe Roux on 2021-05-14. +// + +#include "SceneManager.hpp" + +namespace WAL +{ + SceneManager &WAL::SceneManager::addScene(WAL::Scene &&scene) + { + this->_scenes.push_front(scene); + return *this; + } + + SceneManager &SceneManager::addBackScene(Scene &&scene) + { + this->_scenes.insert(++this->_scenes.begin(), scene); + return *this; + } + + Scene &SceneManager::getCurrent() + { + return this->_scenes.front(); + } + + SceneManager &SceneManager::closeCurrent() + { + this->_scenes.pop_front(); + return *this; + } +} \ No newline at end of file diff --git a/lib/wal/sources/Scene/SceneManager.hpp b/lib/wal/sources/Scene/SceneManager.hpp new file mode 100644 index 00000000..21765dc9 --- /dev/null +++ b/lib/wal/sources/Scene/SceneManager.hpp @@ -0,0 +1,43 @@ +// +// Created by Zoe Roux on 2021-05-14. +// + + +#pragma once + +#include +#include "Scene/Scene.hpp" + +namespace WAL +{ + //! @brief A class to manage scenes + class SceneManager + { + private: + std::deque _scenes = {}; + public: + //! @brief Add a scene to the container and move to it. + //! @return The manager instance used to call this function is returned. This allow method chaining. + SceneManager &addScene(Scene &&scene); + + //! @brief Add a scene before the current scene to allow + //! @return The manager instance used to call this function is returned. This allow method chaining. + SceneManager &addBackScene(Scene &&scene); + + //! @breif Get the current scene + Scene &getCurrent(); + + //! @brief Remove the current scene and switch to the previous scene on the stack. + //! @return The manager instance used to call this function is returned. This allow method chaining. + SceneManager &closeCurrent(); + + //! @brief A default constructor + SceneManager() = default; + //! @brief A scene manager is copy constructable + SceneManager(const SceneManager &) = default; + //! @brief A default destructor. + ~SceneManager() = default; + //! @brief A scene manager is assignable + SceneManager &operator=(const SceneManager &) = default; + }; +} diff --git a/lib/wal/System/System.hpp b/lib/wal/sources/System/System.hpp similarity index 59% rename from lib/wal/System/System.hpp rename to lib/wal/sources/System/System.hpp index de57d374..5da1d236 100644 --- a/lib/wal/System/System.hpp +++ b/lib/wal/sources/System/System.hpp @@ -12,13 +12,21 @@ namespace WAL public: //! @brief A virtual, default, destructor virtual ~System() = default; - + //! @brief A system can be moved + System(System &&) = default; + //! @brief Get the name of the component corresponding to this system. virtual std::string getComponentName() const = 0; //! @brief Update the corresponding component of the given entity //! @param entity The entity to update. - virtual void onUpdate(Entity &entity) = 0; + //! @param dtime The delta time. + virtual void onUpdate(Entity &entity, float dtime) = 0; + + //! @brief An alternative of onUpdate that is called every 8ms (120 times per seconds). If the system slow down, it will try to catch up. + //! @remark This should be used for Physics, AI and everything that could be imprecise due to float rounding. + //! @param entity The entity to update. + virtual void onFixedUpdate(Entity &entity) = 0; protected: //! @brief A system can't be instantiated, it should be derived. System() = default; diff --git a/lib/wal/sources/Wal.cpp b/lib/wal/sources/Wal.cpp new file mode 100644 index 00000000..2e8e18a8 --- /dev/null +++ b/lib/wal/sources/Wal.cpp @@ -0,0 +1,19 @@ +// +// Created by Zoe Roux on 2021-05-14. +// + +#include "Wal.hpp" + +namespace WAL +{ + + SceneManager &WAL::getSceneManger() + { + return this->_scenes; + } + + void WAL::run() + { + + } +} \ No newline at end of file diff --git a/lib/wal/sources/Wal.hpp b/lib/wal/sources/Wal.hpp new file mode 100644 index 00000000..d280f739 --- /dev/null +++ b/lib/wal/sources/Wal.hpp @@ -0,0 +1,91 @@ +// +// Created by Zoe Roux on 2021-05-14. +// + + +#pragma once + +#include +#include +#include +#include +#include "Events/EventManager.hpp" +#include "Renderer/Renderer.hpp" +#include "Scene/SceneManager.hpp" +#include "Entity/Entity.hpp" +#include "System/System.hpp" + +namespace WAL +{ + //! @brief The main WAL class, it is used to setup and run the ECS. + class WAL + { + private: + //! @brief The scene manager that allow multiple scene to work together. + SceneManager _scenes; + //! @brief The event manager + EventManager _eventManager; + //! @brief The list of registered systems + std::vector> _systems = {}; + //! @brief The renderer used to draw entities + std::unique_ptr _renderer; + public: + //! @brief Create a new system in place. + //! @return The wal instance used to call this function is returned. This allow method chaining. + template + WAL &addSystem(Types ...params) + { + const std::type_info &type = typeid(T); + auto &existing =std::find(this->_systems.begin(), this->_systems.end(), [&type] (auto &sys) { + return typeid(sys) == type; + }); + if (existing != this->_systems.end()) + throw SystemExistError("A system of the type \"" + std::string(type.name()) + "\" already exists."); + this->_systems.push_back(std::make_unique(params...)); + return *this; + } + + //! @brief Add a system by copy. + //! @return The wal instance used to call this function is returned. This allow method chaining. + template + WAL &addSystem(const T &system) + { + const std::type_info &type = typeid(T); + auto &existing =std::find(this->_systems.begin(), this->_systems.end(), [&type] (auto &sys) { + return typeid(sys) == type; + }); + if (existing != this->_systems.end()) + throw SystemExistError("A system of the type \"" + std::string(type.name()) + "\" already exists."); + this->_systems.push_back(std::make_unique(system)); + return *this; + } + + //! @brief Remove a system using it's type. + template + WAL &removeSystem() + { + const std::type_info &type = typeid(T); + auto &existing =std::find(this->_systems.begin(), this->_systems.end(), [&type] (auto &sys) { + return typeid(sys) == type; + }); + if (existing == this->_systems.end()) + throw NotFoundError("No system could be found with the type \"" + std::string(type.name()) + "\"."); + return *this; + } + + //! @brief Get the scene manager. + SceneManager &getSceneManger(); + + //! @brief Start the game loop + void run(); + + //! @brief A default constructor + WAL() = default; + //! @brief A WAL can't be copy constructed + WAL(const WAL &) = delete; + //! @brief A default destructor + ~WAL() = default; + //! @brief A default assignment operator + WAL &operator=(const WAL &) = default; + }; +} diff --git a/sources/main.cpp b/sources/main.cpp index 11d982c5..53c8bb20 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -1,7 +1,15 @@ #include +#include int main() { - std::cout << "Hello, World!" << std::endl; - return 0; + WAL::WAL wal; + + try { + wal.run(); + return 0; + } catch (const std::exception &ex) { + std::cerr << ex.what() << std::endl; + return 84; + } }