diff --git a/BloomFramework/BloomFramework.vcxproj b/BloomFramework/BloomFramework.vcxproj index f69dc7ee..c3fca11a 100644 --- a/BloomFramework/BloomFramework.vcxproj +++ b/BloomFramework/BloomFramework.vcxproj @@ -181,6 +181,10 @@ + + + + @@ -188,7 +192,10 @@ + + + @@ -203,6 +210,7 @@ + @@ -213,6 +221,8 @@ + + @@ -221,6 +231,7 @@ + diff --git a/BloomFramework/BloomFramework.vcxproj.filters b/BloomFramework/BloomFramework.vcxproj.filters index f60fb7c7..d66b17d7 100644 --- a/BloomFramework/BloomFramework.vcxproj.filters +++ b/BloomFramework/BloomFramework.vcxproj.filters @@ -31,6 +31,12 @@ {61128b5c-6d91-44f6-b147-79f56ad42451} + + {88b678a9-afd8-4bf2-8497-4a206009a84c} + + + {dd833aec-1858-4a66-867e-60efaeeec2cb} + @@ -90,6 +96,18 @@ Source Files\Graphics + + Source Files + + + Source Files + + + Source Files\Scenes + + + Source Files\Scenes + @@ -197,6 +215,30 @@ Header Files\Graphics + + Header Files + + + Header Files\Scenes + + + Header Files\Scenes + + + Header Files\Components + + + Header Files\Components + + + Header Files\Components + + + Header Files\Components + + + Header Files + diff --git a/BloomFramework/include/Components/Components.h b/BloomFramework/include/Components/Components.h index de711fff..dbf2ce1f 100644 --- a/BloomFramework/include/Components/Components.h +++ b/BloomFramework/include/Components/Components.h @@ -1,7 +1,8 @@ #pragma once -#include "Position.h" -#include "Size.h" +#include "Transform.h" +#include "LayerGroup.h" #include "Sprite.h" #include "Animation.h" -#include "AnimationSet.h" \ No newline at end of file +#include "AnimationSet.h" +#include "Tag.h" \ No newline at end of file diff --git a/BloomFramework/include/Components/LayerGroup.h b/BloomFramework/include/Components/LayerGroup.h new file mode 100644 index 00000000..e9076524 --- /dev/null +++ b/BloomFramework/include/Components/LayerGroup.h @@ -0,0 +1,5 @@ +#pragma once + +namespace bloom::components { + using LayerGroup = Uint32; +} \ No newline at end of file diff --git a/BloomFramework/include/Components/Position.h b/BloomFramework/include/Components/Position.h deleted file mode 100644 index 58ec6e49..00000000 --- a/BloomFramework/include/Components/Position.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -namespace bloom::components { - struct Position { - Position(int x = 0, int y = 0) : x(x), y(y) {} - - int x, y; - }; -} \ No newline at end of file diff --git a/BloomFramework/include/Components/Size.h b/BloomFramework/include/Components/Size.h deleted file mode 100644 index db5af32c..00000000 --- a/BloomFramework/include/Components/Size.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -namespace bloom::components { - struct Size { - Size(int w = 1, int h = 1) : w(w), h(h) {} - - int w, h; - }; -} \ No newline at end of file diff --git a/BloomFramework/include/Components/Tag.h b/BloomFramework/include/Components/Tag.h new file mode 100644 index 00000000..2b0dd19d --- /dev/null +++ b/BloomFramework/include/Components/Tag.h @@ -0,0 +1,9 @@ +#pragma once +#include +#include "entt/entt.hpp" + +namespace bloom::components { + template + using Label = entt::label; + +} diff --git a/BloomFramework/include/Components/Transform.h b/BloomFramework/include/Components/Transform.h new file mode 100644 index 00000000..f8f3782d --- /dev/null +++ b/BloomFramework/include/Components/Transform.h @@ -0,0 +1,18 @@ +#pragma once + +#include "Coord.h" + +namespace bloom::components { + using Position = bloom::Coord; + struct Size { + int w, h; + }; + + struct Transform { + Position position; + + double rotation; + + Size size; + }; +} \ No newline at end of file diff --git a/BloomFramework/include/Coord.h b/BloomFramework/include/Coord.h new file mode 100644 index 00000000..8ef0fb29 --- /dev/null +++ b/BloomFramework/include/Coord.h @@ -0,0 +1,33 @@ +#pragma once + +#include "stdIncludes.h" +namespace bloom { + enum CoordType { + absolute, + relative + }; + + enum Positions { + top = 1, + middle = 2, + bottom = 4, + + left = 8, + center = 16, + right = 32 + }; + + struct BLOOMFRAMEWORK_API Coord { + public: + int x, y; + int relativeTo; + + Coord(); + Coord(const Coord & other) = default; + Coord(int x, int y, CoordType type = absolute, int direction = top | left); + Coord(const SDL_Point & point); + + Coord getSDLPos(SDL_Renderer * targetRenderer, int width, int height); + SDL_Point toSDLPoint(SDL_Renderer * targetRenderer); + }; +} \ No newline at end of file diff --git a/BloomFramework/include/Framework.h b/BloomFramework/include/Framework.h index 865e9cd8..4215ee28 100644 --- a/BloomFramework/include/Framework.h +++ b/BloomFramework/include/Framework.h @@ -12,3 +12,4 @@ #include "Graphics/Font.h" #include "Graphics/FontStore.h" #include "Graphics/SpriteText.h" +#include "Coord.h" \ No newline at end of file diff --git a/BloomFramework/include/Game.h b/BloomFramework/include/Game.h index 251d5185..de96ce97 100644 --- a/BloomFramework/include/Game.h +++ b/BloomFramework/include/Game.h @@ -3,6 +3,8 @@ #include "stdIncludes.h" #include "Graphics/TextureStore.h" #include "Timer.h" +#include "Exception.h" +#include "Scenes/SceneManager.h" namespace bloom { class BLOOMFRAMEWORK_API Game { @@ -10,8 +12,8 @@ namespace bloom { friend TextureStore::TextureStore(Game & object); public: - Game(int width, int height, int windowFlags = NULL, int rendererFlags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); - Game(std::nothrow_t, int width, int height, int windowFlags = NULL, int rendererFlags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + Game(int width, int height, int windowFlags = NULL, int rendererFlags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE); + Game(std::nothrow_t, int width, int height, int windowFlags = NULL, int rendererFlags = SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE); ~Game(); static void initialize(Uint32 initFlags = SDL_INIT_EVERYTHING, @@ -45,6 +47,8 @@ namespace bloom { TextureStore textures = TextureStore(m_renderer); Timer timer; + SceneManager sceneManager = SceneManager(*this); + protected: SDL_Renderer * m_renderer = nullptr; SDL_Window * m_window = nullptr; diff --git a/BloomFramework/include/GameObject.h b/BloomFramework/include/GameObject.h index 11cda53c..30459c51 100644 --- a/BloomFramework/include/GameObject.h +++ b/BloomFramework/include/GameObject.h @@ -2,33 +2,22 @@ #include "stdIncludes.h" #include "Components/Components.h" -#include "Game.h" namespace bloom { + class Game; /* * This class is used to make a sort of prefab object. * * This class by default will create an entity with the registry provided. - * The entity will be assigned with bloom::Position since it is expected that an entity would have position. - * - * Use the init() function to assign/replace/reset any Components required. * * The destructor will automatically destroy the entity from the registry when GameObject gets out of scope. */ - class BLOOMFRAMEWORK_API GameObject { - using Position = bloom::components::Position; + struct BLOOMFRAMEWORK_API GameObject { + entt::DefaultRegistry& registry; + Game& gameInstance; + const entt::DefaultRegistry::entity_type entity; - public: - GameObject(entt::DefaultRegistry & registry, Game *& gameInstance); + GameObject(entt::DefaultRegistry& registry, Game& gameInstance); ~GameObject(); - - virtual void init() = 0; - - uint32_t getEntityID(); - - protected: - entt::DefaultRegistry & m_registry; - Game *& m_gameInstance; - uint32_t m_entity; }; } \ No newline at end of file diff --git a/BloomFramework/include/Graphics/Drawable.h b/BloomFramework/include/Graphics/Drawable.h index f8ffaa9f..cfeb2cf6 100644 --- a/BloomFramework/include/Graphics/Drawable.h +++ b/BloomFramework/include/Graphics/Drawable.h @@ -9,7 +9,7 @@ namespace bloom::graphics { Drawable(SDL_Renderer* targetRenderer); virtual ~Drawable() = 0; - virtual void render(std::optional srcRect, SDL_Rect destRect, SDL_RendererFlip flip = SDL_FLIP_NONE); + virtual void render(std::optional srcRect, SDL_Rect destRect, double rotationAngle = 0.0, SDL_RendererFlip flip = SDL_FLIP_NONE); protected: SDL_Renderer* const c_renderer; diff --git a/BloomFramework/include/Graphics/SpriteText.h b/BloomFramework/include/Graphics/SpriteText.h index 79d14583..14334ce1 100644 --- a/BloomFramework/include/Graphics/SpriteText.h +++ b/BloomFramework/include/Graphics/SpriteText.h @@ -20,7 +20,7 @@ namespace bloom::graphics { SpriteText(SDL_Renderer* targetRenderer, std::shared_ptr fontPtr, std::string_view text = std::string_view{}, TextStyle style = TextStyle{}); ~SpriteText() = default; - void render(std::optional srcRect, SDL_Point destPoint, SDL_RendererFlip flip = SDL_FLIP_NONE); + void render(std::optional srcRect, SDL_Point destPoint, double rotationAngle = 0.0, SDL_RendererFlip flip = SDL_FLIP_NONE); int getTextHeight() const { return m_height; } int getTextWidth() const { return m_width; } diff --git a/BloomFramework/include/Scenes/Scene.h b/BloomFramework/include/Scenes/Scene.h new file mode 100644 index 00000000..adbe2901 --- /dev/null +++ b/BloomFramework/include/Scenes/Scene.h @@ -0,0 +1,133 @@ +#pragma once + +#include "stdIncludes.h" +#include "Systems/DefaultSystem.h" +#include "GameObject.h" +#include "Exception.h" +#include "Components/LayerGroup.h" +#include "StdStableSort.h" + +namespace bloom { + class BLOOMFRAMEWORK_API SceneManager; + struct BLOOMFRAMEWORK_API Coord; + + class BLOOMFRAMEWORK_API Scene { + using System = bloom::systems::DefaultSystem; + friend bloom::systems::System::System(bloom::Scene & sceneObject); + + public: + Scene(SceneManager & sceneManager); + ~Scene(); + + void update(double deltaTime); + void draw(); + void start(); + void restart(); + virtual void load() = 0; + + Game & getGameInstance() { return m_gameInstance; } + + //Game Object stuff + template>, typename... TArgs> + void addGameObject(const std::string & tag, InitFunc init, TArgs &&... initArgs); + + void destroyGameObject(const std::string & tag); + + void destroyAllGameObjects(); + + // System stuff + template>> + std::shared_ptr registerSystem(); + + template>> + void unregisterSystem(); + + void unregisterAllSystems(); + + template>> + std::shared_ptr getSystemPtr(); + + // Rotation stuff + void setSceneRotation(double angle); + void adjustSceneRotation(double adjustment); + double getSceneRotation(); + void setSceneRotationCenter(Coord center); + void setSceneRotationCenter(SDL_Point center); + + bool isLoaded() { return m_sceneLoaded; } + + protected: + SceneManager & m_sceneManager; + Game & m_gameInstance; + entt::DefaultRegistry m_registry; + std::vector> m_systems; + std::unordered_map> m_gameObjects; + SDL_Texture * m_sceneTexture; + + double m_sceneRotateAngle = 0.0; + SDL_Point m_sceneRotateCenter; + + bool m_sceneLoaded = false; + }; + + template + void Scene::addGameObject(const std::string & tag, InitFunc init, TArgs &&... initArgs) { + static_assert(std::is_base_of_v, "Type GO passed in is not GameObject based"); + + GO* obj = new GO(m_registry, m_gameInstance); + if constexpr (std::is_member_function_pointer_v) + (obj->*init)(std::forward(initArgs)...); + else + init(obj, std::forward(initArgs)...); // std::mem_fn + + m_gameObjects.emplace(tag, std::unique_ptr(obj)); + + m_registry.sort, misc::StdStableSort>(std::less{}); + } + + // System stuff + template + std::shared_ptr Scene::registerSystem() { + //static_assert (std::is_base_of_v, "Type S passed in is not System based"); + if (auto v = std::find_if(m_systems.begin(), m_systems.end(), + [](auto & i) -> bool { return typeid(*i) == typeid(S); }); + v == m_systems.end()) + { + return std::dynamic_pointer_cast(m_systems.emplace_back(std::make_shared(*this))); + } + else { + std::clog << "This system is already registered." << std::endl; + return std::dynamic_pointer_cast(*v); + } + } + + template + void Scene::unregisterSystem() { + //static_assert (std::is_base_of_v, "Type S passed in is not System based"); + if (auto v = std::find_if(m_systems.begin(), m_systems.end(), + [](auto & i) -> bool { return typeid(*i) == typeid(S); }); + v != m_systems.end()) + { + m_systems.erase(v); + } + else { + std::clog << "Can't unregister system that isn't registered." << std::endl; + } + } + + template + std::shared_ptr Scene::getSystemPtr() + { + //static_assert (std::is_base_of_v, "Type S passed in is not System based"); + if (auto v = std::find_if(m_systems.begin(), m_systems.end(), + [](auto & i) -> bool { return typeid(*i) == typeid(S); }); + v != m_systems.end()) + { + return std::dynamic_pointer_cast(*v); + } + else { + throw Exception("[Scene getSystemPtr] Unable to get System, it is not registered."); + } + } + +} \ No newline at end of file diff --git a/BloomFramework/include/Scenes/SceneManager.h b/BloomFramework/include/Scenes/SceneManager.h new file mode 100644 index 00000000..aaffbd7a --- /dev/null +++ b/BloomFramework/include/Scenes/SceneManager.h @@ -0,0 +1,35 @@ +#pragma once + +#include "stdIncludes.h" +#include "Scene.h" + +namespace bloom { + class BLOOMFRAMEWORK_API Game; + + class BLOOMFRAMEWORK_API SceneManager { + friend Scene::Scene(SceneManager & sceneManager); + + public: + SceneManager(Game& gameInstance); + + template>> + void changeScene(std::shared_ptr newScene); + void update(double deltaTime); + void draw(); + + private: + std::shared_ptr m_currScene; + Game & m_gameInstance; + }; + + template + void SceneManager::changeScene(std::shared_ptr newScene) { + //static_assert(std::is_base_of_v, "Type Scn passed in is not Scene based"); + + newScene->load(); + m_currScene = newScene; + + if (!m_currScene->isLoaded()) + m_currScene->start(); + } +} \ No newline at end of file diff --git a/BloomFramework/include/Screen.h b/BloomFramework/include/Screen.h deleted file mode 100644 index 09851308..00000000 --- a/BloomFramework/include/Screen.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once -#include "stdIncludes.h" -#include "Game.h" - -namespace bloom { - class BLOOMFRAMEWORK_API Screen { - public: - Screen(Game& gameInstance); - void handleInput(); - void render(); - - private: - // std::vector gameObjects; // GameObject not implemented yet. - entt::DefaultRegistry registry; - Game& _gameInstance; - }; -} \ No newline at end of file diff --git a/BloomFramework/include/StdStableSort.h b/BloomFramework/include/StdStableSort.h new file mode 100644 index 00000000..c9584388 --- /dev/null +++ b/BloomFramework/include/StdStableSort.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +namespace bloom::misc { + // Keep docs from entity ;) + + /** + * @brief Function object to wrap `std::stable_sort` in a class type. + * + * Unfortunately, `std::stable_sort` cannot be passed as template argument to a class + * template or a function template.
+ * This class fills the gap by wrapping some flavors of `std::stable_sort` in a + * function object. + */ + struct StdStableSort final { + /** + * @brief Sorts the elements in a range. + * + * Sorts the elements in a range using the given binary comparison function. + * The order of equivalent elements is guaranteed to be preserved. + * + * @tparam It Type of random access iterator. + * @tparam Compare Type of comparison function object. + * @tparam Args Types of arguments to forward to the sort function. + * @param first An iterator to the first element of the range to sort. + * @param last An iterator past the last element of the range to sort. + * @param compare A valid comparison function object. + * @param args Arguments to forward to the sort function, if any. + */ + template, typename... Args> + void operator()(It first, It last, Compare compare = Compare{}, Args &&... args) const { + std::stable_sort(std::forward(args)..., std::move(first), std::move(last), std::move(compare)); + } + }; +} \ No newline at end of file diff --git a/BloomFramework/include/Systems/AnimationSystem.h b/BloomFramework/include/Systems/AnimationSystem.h index 852f7246..c1677b09 100644 --- a/BloomFramework/include/Systems/AnimationSystem.h +++ b/BloomFramework/include/Systems/AnimationSystem.h @@ -9,7 +9,7 @@ namespace bloom::systems { using AnimationPtr = bloom::components::AnimationPtr; using AnimationSet = bloom::components::AnimationSet; using Sprite = bloom::components::Sprite; - using System::DefaultSystem; + using System::System; public: void update(std::optional deltaTime = 0.0) override { diff --git a/BloomFramework/include/Systems/DefaultSystem.h b/BloomFramework/include/Systems/DefaultSystem.h index 12237040..02c4ce4a 100644 --- a/BloomFramework/include/Systems/DefaultSystem.h +++ b/BloomFramework/include/Systems/DefaultSystem.h @@ -3,16 +3,22 @@ #include #include "stdIncludes.h" -namespace bloom::systems { - class DefaultSystem { - public: - DefaultSystem(entt::DefaultRegistry & registry) : m_registry(registry) {}; +namespace bloom { + class Scene; + namespace systems { + class BLOOMFRAMEWORK_API System { + public: + System(bloom::Scene & sceneObject); + virtual ~System() = default; - virtual void update(std::optional deltaTime = std::nullopt) = 0; + virtual void update(std::optional deltaTime = std::nullopt) = 0; - protected: - entt::DefaultRegistry & m_registry; - }; + bool enabled = true; + protected: + bloom::Scene & parentScene; + entt::DefaultRegistry & m_registry; + }; - using System = DefaultSystem; + using DefaultSystem = System; + } } \ No newline at end of file diff --git a/BloomFramework/include/Systems/RenderSystem.h b/BloomFramework/include/Systems/RenderSystem.h index 4f3dc912..536c30a1 100644 --- a/BloomFramework/include/Systems/RenderSystem.h +++ b/BloomFramework/include/Systems/RenderSystem.h @@ -1,28 +1,44 @@ #pragma once +#include #include "stdIncludes.h" #include "Components/Components.h" #include "DefaultSystem.h" +#include "Components/Components.h" namespace bloom::systems { - class RenderSystem : public System { - using Position = bloom::components::Position; - using Size = bloom::components::Size; + class RenderSystem : public DefaultSystem { + using Transform = bloom::components::Transform; + using Rotation = double; using Sprite = bloom::components::Sprite; - using System::DefaultSystem; + using LayerGroup = bloom::components::LayerGroup; + using DefaultSystem::System; public: + ~RenderSystem() = default; + void update(std::optional deltaTime = std::nullopt) override { - m_registry.view().each( - [](auto entity, Position & pos, Size& size, Sprite & spr) { + m_registry.view().each( + [&](auto entity, Transform& trans, Sprite& spr) { + if (trans.size.w < 0) + trans.size.w = 0; + if (trans.size.h < 0) + trans.size.h = 0; + + Coord actualPos = trans.position.getSDLPos(parentScene.getGameInstance().getRenderer(), trans.size.w, trans.size.h); SDL_Rect destRect{ - static_cast(pos.x), - static_cast(pos.y), - static_cast(size.w), - static_cast(size.h) + actualPos.x, + actualPos.y, + trans.size.w, + trans.size.h }; - spr.texture->render(spr.srcRect, destRect); + + // Draw sprite to scene texture + spr.texture->render(spr.srcRect, destRect, trans.rotation); }); } + + private: + SDL_Renderer* renderer; }; } \ No newline at end of file diff --git a/BloomFramework/src/Coord.cpp b/BloomFramework/src/Coord.cpp new file mode 100644 index 00000000..94cb4dbb --- /dev/null +++ b/BloomFramework/src/Coord.cpp @@ -0,0 +1,50 @@ +#include "Coord.h" + +namespace bloom { + Coord::Coord() : x(0), y(0), relativeTo(middle | center) {} + + Coord::Coord(int x, int y, CoordType type, int direction) : x(x), y(y), relativeTo(direction) { + if (type == absolute) + this->relativeTo = (middle | center); + } + + Coord::Coord(const SDL_Point & point) : x(point.x), y(point.y), relativeTo(middle | center) {} + + Coord Coord::getSDLPos(SDL_Renderer * targetRenderer, int width, int height) { + int rendererWidth, rendererHeight; + SDL_RenderGetLogicalSize(targetRenderer, &rendererWidth, &rendererHeight); + Coord result; + + if (width < 0) + width = 0; + if (height < 0) + height = 0; + + // Get SDL style X position, factoring object width as well. + if ((relativeTo & left) == left) + result.x = x; + else if ((relativeTo & center) == center) + result.x = rendererWidth / 2 - width / 2 + x; + else if ((relativeTo & right) == right) + result.x = rendererWidth - width - x; + else + result.x = x; + + // Get SDL style Y position, factoring object height as well. + if ((relativeTo & top) == top) + result.y = y; + else if ((relativeTo & middle) == middle) + result.y = rendererHeight / 2 - height / 2 - y; + else if ((relativeTo & bottom) == bottom) + result.y = rendererHeight - height - y; + else + result.y = y; + + return result; + } + + SDL_Point Coord::toSDLPoint(SDL_Renderer * targetRenderer) { + auto tmp = getSDLPos(targetRenderer, 0, 0); + return SDL_Point{ tmp.x, tmp.y }; + } +} \ No newline at end of file diff --git a/BloomFramework/src/Game.cpp b/BloomFramework/src/Game.cpp index a4882970..8158b854 100644 --- a/BloomFramework/src/Game.cpp +++ b/BloomFramework/src/Game.cpp @@ -110,6 +110,7 @@ namespace bloom { else { std::clog << "Renderer initialized." << std::endl; } + SDL_RenderSetLogicalSize(m_renderer, m_screenWidth, m_screenHeight); m_isRunning = true; std::clog << "Game is now running!" << std::endl; @@ -123,10 +124,13 @@ namespace bloom { } void Game::update() { - std::clog << "Delta time: " << timer.lap() << std::endl; + //double dt = timer.lap(); + sceneManager.update(timer.lap()); + //std::clog << "Delta Time: " << dt << "ms" << std::endl; } void Game::clear() { + SDL_SetRenderDrawColor(m_renderer, m_color.r, m_color.g, m_color.b, m_color.a); SDL_RenderClear(m_renderer); } @@ -135,6 +139,7 @@ namespace bloom { } void Game::render() { + sceneManager.draw(); SDL_RenderPresent(m_renderer); } @@ -160,12 +165,10 @@ namespace bloom { void Game::setColor(const SDL_Color & color) { m_color = color; - SDL_SetRenderDrawColor(m_renderer, m_color.r, m_color.g, m_color.b, m_color.a); } void Game::setColor(Uint8 r, Uint8 g, Uint8 b, Uint8 a) { m_color = { r, g, b, a }; - SDL_SetRenderDrawColor(m_renderer, m_color.r, m_color.g, m_color.b, m_color.a); } SDL_Color Game::getColor() { diff --git a/BloomFramework/src/GameObject.cpp b/BloomFramework/src/GameObject.cpp index 5f4a46ee..12898e0c 100644 --- a/BloomFramework/src/GameObject.cpp +++ b/BloomFramework/src/GameObject.cpp @@ -1,16 +1,14 @@ #include "GameObject.h" namespace bloom { - GameObject::GameObject(entt::DefaultRegistry & registry, Game *& gameInstance) : m_registry(registry), m_gameInstance(gameInstance) { - m_entity = m_registry.create(); - m_registry.assign(m_entity, 0, 0); - } + GameObject::GameObject(entt::DefaultRegistry& registry, Game& gameInstance) : + registry(registry), + gameInstance(gameInstance), + entity(registry.create()) + {} GameObject::~GameObject() { - m_registry.destroy(m_entity); - } - - uint32_t GameObject::getEntityID() { - return m_entity; + if (registry.valid(entity)) + registry.destroy(entity); } } \ No newline at end of file diff --git a/BloomFramework/src/Graphics/Drawable.cpp b/BloomFramework/src/Graphics/Drawable.cpp index 09668451..b464d825 100644 --- a/BloomFramework/src/Graphics/Drawable.cpp +++ b/BloomFramework/src/Graphics/Drawable.cpp @@ -12,7 +12,7 @@ namespace bloom::graphics { SDL_DestroyTexture(m_texture); } - void Drawable::render(std::optional srcRect, SDL_Rect destRect, SDL_RendererFlip flip) { + void Drawable::render(std::optional srcRect, SDL_Rect destRect, double rotationAngle, SDL_RendererFlip flip) { if (!m_texture) return; @@ -23,7 +23,7 @@ namespace bloom::graphics { auto sRectPtr = (srcRect.has_value() && srcRect->w > 0 && srcRect->h > 0) ? &srcRect.value() : nullptr; // Render to screen - if (SDL_RenderCopyEx(c_renderer, m_texture, sRectPtr, &destRect, 0.0, nullptr, flip)) + if (SDL_RenderCopyEx(c_renderer, m_texture, sRectPtr, &destRect, rotationAngle, nullptr, flip)) throw Exception("[Drawable::render] -> " + std::string{ SDL_GetError() }); } } diff --git a/BloomFramework/src/Graphics/SpriteText.cpp b/BloomFramework/src/Graphics/SpriteText.cpp index b9e321f7..a9b97bba 100644 --- a/BloomFramework/src/Graphics/SpriteText.cpp +++ b/BloomFramework/src/Graphics/SpriteText.cpp @@ -11,12 +11,12 @@ namespace bloom::graphics { refreshTexture(); } - void SpriteText::render(std::optional srcRect, SDL_Point destPoint, SDL_RendererFlip flip) { + void SpriteText::render(std::optional srcRect, SDL_Point destPoint, double rotationAngle, SDL_RendererFlip flip) { if (m_refreshRequired) refreshTexture(); if (m_texture) - Drawable::render(srcRect, SDL_Rect{ destPoint.x, destPoint.y, m_width, m_height }, flip); + Drawable::render(srcRect, SDL_Rect{ destPoint.x, destPoint.y, m_width, m_height }, rotationAngle, flip); } void SpriteText::refreshTexture() { diff --git a/BloomFramework/src/Scenes/Scene.cpp b/BloomFramework/src/Scenes/Scene.cpp new file mode 100644 index 00000000..9a9e2169 --- /dev/null +++ b/BloomFramework/src/Scenes/Scene.cpp @@ -0,0 +1,80 @@ +#include "Scenes\Scene.h" +#include "Scenes\SceneManager.h" +#include "Game.h" + +namespace bloom { + Scene::Scene(SceneManager & sceneManager) : + m_sceneManager(sceneManager), + m_gameInstance(sceneManager.m_gameInstance), + m_sceneRotateCenter(Coord().toSDLPoint(m_gameInstance.getRenderer())) + { + m_sceneTexture = SDL_CreateTexture(m_gameInstance.getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, + m_gameInstance.getScreenWidth(), + m_gameInstance.getScreenHeight()); + + SDL_SetTextureBlendMode(m_sceneTexture, SDL_BLENDMODE_BLEND); + } + + Scene::~Scene() { + SDL_DestroyTexture(m_sceneTexture); + } + + void Scene::update(double deltaTime) { + SDL_SetRenderTarget(m_gameInstance.getRenderer(), m_sceneTexture); + SDL_SetRenderDrawColor(m_gameInstance.getRenderer(), 0, 0, 0, 0); + SDL_RenderClear(m_gameInstance.getRenderer()); + for (auto & sys : m_systems) + if (sys->enabled) + sys->update(deltaTime); + SDL_SetRenderTarget(m_gameInstance.getRenderer(), nullptr); + } + + void Scene::draw() { + SDL_RenderCopyEx(m_gameInstance.getRenderer(), m_sceneTexture, nullptr, nullptr, m_sceneRotateAngle, &m_sceneRotateCenter, SDL_FLIP_NONE); + } + + void Scene::start() { + load(); + m_sceneLoaded = true; + } + + void Scene::restart() { + unregisterAllSystems(); + destroyAllGameObjects(); + load(); + m_sceneLoaded = true; + } + + void Scene::destroyGameObject(const std::string & tag) { + m_gameObjects.erase(tag); + } + + void Scene::destroyAllGameObjects() { + m_gameObjects.clear(); + } + + void Scene::unregisterAllSystems() { + m_systems.clear(); + } + + void Scene::setSceneRotation(double angle) { + m_sceneRotateAngle = fmod(angle, 360.0); + } + + void Scene::adjustSceneRotation(double adjustment) { + m_sceneRotateAngle = fmod((m_sceneRotateAngle + adjustment), 360.0); + } + + double Scene::getSceneRotation() { + return m_sceneRotateAngle; + } + + void Scene::setSceneRotationCenter(Coord center) { + m_sceneRotateCenter = center.toSDLPoint(m_gameInstance.getRenderer()); + } + + void Scene::setSceneRotationCenter(SDL_Point center) { + m_sceneRotateCenter = center; + } +} + diff --git a/BloomFramework/src/Scenes/SceneManager.cpp b/BloomFramework/src/Scenes/SceneManager.cpp new file mode 100644 index 00000000..604680bb --- /dev/null +++ b/BloomFramework/src/Scenes/SceneManager.cpp @@ -0,0 +1,19 @@ +#include "Scenes\SceneManager.h" +#include "Scenes\Scene.h" +#include "Game.h" + +namespace bloom { + inline SceneManager::SceneManager(Game & gameInstance) : m_gameInstance(gameInstance) {} + + void SceneManager::update(double deltaTime) { + if (m_currScene != nullptr) + m_currScene->update(deltaTime); + else + std::cerr << "There is no currently active Scene" << std::endl; + } + + void SceneManager::draw() { + if (m_currScene != nullptr) + m_currScene->draw(); + } +} diff --git a/BloomFramework/src/Systems/DefaultSystem.cpp b/BloomFramework/src/Systems/DefaultSystem.cpp new file mode 100644 index 00000000..65da4b0e --- /dev/null +++ b/BloomFramework/src/Systems/DefaultSystem.cpp @@ -0,0 +1,6 @@ +#include "Systems/DefaultSystem.h" +#include "Scenes/Scene.h" + +namespace bloom::systems { + System::System(bloom::Scene & sceneObject) : parentScene(sceneObject), m_registry(sceneObject.m_registry) {} +} \ No newline at end of file diff --git a/Test Bench/GameObjectTest/AnimationChangerSystem.h b/Test Bench/GameObjectTest/AnimationChangerSystem.h index 66ebed54..11e502b7 100644 --- a/Test Bench/GameObjectTest/AnimationChangerSystem.h +++ b/Test Bench/GameObjectTest/AnimationChangerSystem.h @@ -10,7 +10,7 @@ class AnimationChangerSystem : public bloom::systems::System { using AnimationSet = bloom::components::AnimationSet; using AnimationPtr = bloom::components::AnimationPtr; - using bloom::systems::System::DefaultSystem; + using bloom::systems::System::System; public: void update(std::optional deltaTime = std::nullopt) override { diff --git a/Test Bench/GameObjectTest/RandomizerSystem.h b/Test Bench/GameObjectTest/RandomizerSystem.h index 238d97a0..850ef88c 100644 --- a/Test Bench/GameObjectTest/RandomizerSystem.h +++ b/Test Bench/GameObjectTest/RandomizerSystem.h @@ -3,28 +3,30 @@ #include "Framework.h" #include "NoRandomComponent.h" -class RandomPositionSystem : public bloom::systems::System { - using Position = bloom::components::Position; - using bloom::systems::System::DefaultSystem; +class RandomPositionSystem : public bloom::systems::DefaultSystem { + using Transform = bloom::components::Transform; + using bloom::systems::DefaultSystem::System; public: + ~RandomPositionSystem() = default; + void update(std::optional deltaTime = std::nullopt) override { - m_registry.view().each( - [this](auto entity, Position & pos) { + m_registry.view().each( + [this](auto entity, Transform & trans) { if (!m_registry.has(entity)) { - pos.x = rand() % 672; - pos.y = rand() % 472; + trans.position.x = rand() % 672; + trans.position.y = rand() % 472; } }); } void update(int frameWidth, int frameHeight, std::optional dt = std::nullopt) { - m_registry.view().each( - [this, frameWidth, frameHeight](auto entity, Position & pos) { + m_registry.view().each( + [this, frameWidth, frameHeight](auto entity, Transform & transform) { if (!m_registry.has(entity)) { - pos.x = rand() % frameWidth; - pos.y = rand() % frameHeight; + transform.position.x = rand() % frameWidth; + transform.position.y = rand() % frameHeight; } }); } diff --git a/Test Bench/GameObjectTest/SceneRotateSystem.h b/Test Bench/GameObjectTest/SceneRotateSystem.h new file mode 100644 index 00000000..c03a1558 --- /dev/null +++ b/Test Bench/GameObjectTest/SceneRotateSystem.h @@ -0,0 +1,30 @@ +#pragma once +#include "Framework.h" +#include "RandomizerSystem.h" + +class SceneRotateSystem : public bloom::systems::DefaultSystem { + using Position = bloom::components::Position; + using bloom::systems::DefaultSystem::System; + +public: + ~SceneRotateSystem() = default; + + void update(std::optional deltaTime = std::nullopt) override { + if (currentRotate != rotateAmount) { + m_currentAngle += rotateSpeed * (deltaTime.value_or(0.0) / 1000); + currentRotate = static_cast(m_currentAngle / 360.0); + if (currentRotate == rotateAmount) { + m_currentAngle = 0.0; + parentScene.getSystemPtr()->enabled = true; + } + parentScene.setSceneRotation(m_currentAngle); + } + } + + double rotateSpeed = static_cast(rand() % 360); + int rotateAmount = 0; + int currentRotate = 0; + +private: + double m_currentAngle = 0.0; +}; \ No newline at end of file diff --git a/Test Bench/GameObjectTest/SpriteRotatorSystem.h b/Test Bench/GameObjectTest/SpriteRotatorSystem.h new file mode 100644 index 00000000..4fff40b6 --- /dev/null +++ b/Test Bench/GameObjectTest/SpriteRotatorSystem.h @@ -0,0 +1,34 @@ +#pragma once +#include "Framework.h" +#include "SceneRotateSystem.h" + +class SpriteRotatorSystem : public bloom::systems::DefaultSystem { + using Transform = bloom::components::Transform; + using bloom::systems::DefaultSystem::System; + +public: + ~SpriteRotatorSystem() = default; + + void update(std::optional deltaTime = std::nullopt) override { + if (currentRotate != rotateAmount) { + m_currentAngle += rotateSpeed * (deltaTime.value_or(0.0) / 1000); + currentRotate = static_cast(m_currentAngle / 360.0); + currentRotate = static_cast(m_currentAngle / 360.0); + if (currentRotate == rotateAmount) { + m_currentAngle = 0.0; + parentScene.getSystemPtr()->rotateAmount = 5; + } + m_registry.view().each( + [&](auto entity, Transform & trans) { + trans.rotation = fmod(m_currentAngle, 360); + }); + } + } + + double rotateSpeed = static_cast(rand() % 360); + int rotateAmount = 5; + int currentRotate = 0; + +private: + double m_currentAngle = 0.0; +}; \ No newline at end of file diff --git a/Test Bench/GameObjectTest/TestAnimatedGameObject.h b/Test Bench/GameObjectTest/TestAnimatedGameObject.h index 194716d4..2aa74804 100644 --- a/Test Bench/GameObjectTest/TestAnimatedGameObject.h +++ b/Test Bench/GameObjectTest/TestAnimatedGameObject.h @@ -10,17 +10,17 @@ class TestAnimChar : public bloom::GameObject { using AnimationPtr = bloom::components::AnimationPtr; using Animation = bloom::components::Animation; using AnimationSet = bloom::components::AnimationSet; - using bloom::GameObject::GameObject; + using Transform = bloom::components::Transform; + using GameObject::GameObject; public: - void init() override {} + void init(const std::filesystem::path& texturePath) { + Transform trans = { Position(0,0,bloom::relative), 0.0f, Size{256, 256} }; + registry.assign(entity, trans); - void init(const std::filesystem::path texturePath = "Assets/TestChar.png") { - m_registry.replace(m_entity, 50, 50); - m_registry.assign(m_entity, 256, 256); - auto tmp = m_gameInstance->textures.load(texturePath); + auto tmp = gameInstance.textures.load(texturePath); - m_registry.assign(m_entity, tmp, SDL_Rect{ 0,32,32,32 }); + registry.assign(entity, tmp, SDL_Rect{ 0,32,32,32 }); // Seriously not the best way to initialize object animation. @@ -68,8 +68,8 @@ class TestAnimChar : public bloom::GameObject { animSet.add("left", left); animSet.add("right", right); - m_registry.assign(m_entity, animSet); - m_registry.assign(m_entity, up); - m_registry.assign(m_entity); + registry.assign(entity, animSet); + registry.assign(entity, up); + registry.assign(entity); } }; \ No newline at end of file diff --git a/Test Bench/GameObjectTest/TestGameObject.h b/Test Bench/GameObjectTest/TestGameObject.h index b430ed4b..cca1c57e 100644 --- a/Test Bench/GameObjectTest/TestGameObject.h +++ b/Test Bench/GameObjectTest/TestGameObject.h @@ -3,32 +3,39 @@ #include "Framework.h" #include "NoRandomComponent.h" +//using namespace entt; + class TestChar : public bloom::GameObject { - using Position = bloom::components::Position; + using Transform = bloom::components::Transform; + using Position = bloom::Coord; using Size = bloom::components::Size; + using LayerGroup = bloom::components::LayerGroup; using Sprite = bloom::components::Sprite; - using bloom::GameObject::GameObject; - -public: - void init() override {} + template + using Label = bloom::components::Label; - void init(bloom::graphics::TexturePtr texturePtr, SDL_Rect pos_and_size = SDL_Rect{ 50,50, 256, 256 }, std::optional srcRect = std::nullopt) { - m_registry.replace(m_entity, pos_and_size.x, pos_and_size.y); - m_registry.assign(m_entity, pos_and_size.w, pos_and_size.h); + using GameObject::GameObject; - m_registry.assign(m_entity, texturePtr, srcRect); - } - - void init(SDL_Rect pos_and_size = SDL_Rect{ 50,50, 256, 256 }, const std::filesystem::path texturePath = "Assets/TestChar.png", std::optional srcRect = std::nullopt) { - auto tmp = m_gameInstance->textures.load(texturePath); - init(tmp, pos_and_size, srcRect); +public: + void init(Position pos, Size size, const std::filesystem::path& texturePath, std::optional srcRect, uint32_t priority) { + Transform trans = { pos, 0.0f, size }; + registry.assign(entity, trans); + auto tmp = gameInstance.textures.load(texturePath); + registry.assign(entity, tmp, srcRect); + + registry.assign(entity, priority); + +#pragma warning(push) +#pragma warning(disable: 4307) + registry.assign>(entity); +#pragma warning(pop) } void disableRandomPos() { - m_registry.assign(m_entity); + registry.assign(entity); } void enableRandomPos() { - m_registry.reset(m_entity); + registry.reset(entity); } }; \ No newline at end of file diff --git a/Test Bench/GameObjectTest/TestTextObject.h b/Test Bench/GameObjectTest/TestTextObject.h new file mode 100644 index 00000000..f828c28e --- /dev/null +++ b/Test Bench/GameObjectTest/TestTextObject.h @@ -0,0 +1,30 @@ +#pragma once + +#include "Framework.h" +#include "NoRandomComponent.h" + +//using namespace entt; + +class TestChar : public bloom::GameObject { + using Transform = bloom::components::Transform; + using Position = bloom::Coord; + using Size = bloom::components::Size; + using LayerGroup = bloom::components::LayerGroup; + using Sprite = bloom::components::Sprite; + template + using Label = bloom::components::Label; + + using GameObject::GameObject; + +public: + void init(Position pos, Size size, const std::filesystem::path& texturePath, std::optional srcRect, uint32_t priority) { + } + + void disableRandomPos() { + registry.assign(entity); + } + + void enableRandomPos() { + registry.reset(entity); + } +}; \ No newline at end of file diff --git a/Test Bench/Test Bench.vcxproj b/Test Bench/Test Bench.vcxproj index b1e0b238..53471293 100644 --- a/Test Bench/Test Bench.vcxproj +++ b/Test Bench/Test Bench.vcxproj @@ -194,7 +194,7 @@ false - true + false Image
@@ -202,8 +202,12 @@ + + + + diff --git a/Test Bench/Test Bench.vcxproj.filters b/Test Bench/Test Bench.vcxproj.filters index 95773fdd..5e7f15f5 100644 --- a/Test Bench/Test Bench.vcxproj.filters +++ b/Test Bench/Test Bench.vcxproj.filters @@ -52,5 +52,17 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + \ No newline at end of file diff --git a/Test Bench/TestScene.h b/Test Bench/TestScene.h new file mode 100644 index 00000000..13ab93f8 --- /dev/null +++ b/Test Bench/TestScene.h @@ -0,0 +1,52 @@ +#pragma once +#include "Scenes/Scene.h" +#include "GameObjectTest/TestGameObject.h" +#include "GameObjectTest/SceneRotateSystem.h" +#include "GameObjectTest/SpriteRotatorSystem.h" +#include "GameObjectTest/RandomizerSystem.h" +#include "GameObjectTest/TestAnimatedGameObject.h" +#include "GameObjectTest/AnimationChangerSystem.h" + +class TestScene : public bloom::Scene { + using RenderSystem = bloom::systems::RenderSystem; + using Position = bloom::components::Position; + using Size = bloom::components::Size; + using AnimationSystem = bloom::systems::AnimationSystem; + +public: + using bloom::Scene::Scene; + + void load() override { + namespace fs = std::filesystem; + fs::path workingDir = fs::path(getExePath()); + fs::path assetsDir = L"data\\Assets"; + fs::path spriteSheetPath = workingDir / assetsDir / "OverworldTestSpritesheet.png"; + fs::path testCharPath = workingDir / assetsDir / "TestChar.png"; + + auto init = [](TestChar * ptr, Position pos, Size size, const std::filesystem::path & texturePath, std::optional srcRect = std::nullopt, uint32_t priority = 0) { + bloom::components::Transform trans = { pos, 0.0f, size }; + ptr->registry.assign(ptr->entity, trans); + auto tmp = ptr->gameInstance.textures.load(texturePath); + ptr->registry.assign(ptr->entity, tmp, srcRect); + + ptr->registry.assign(ptr->entity, priority); + +#pragma warning(push) +#pragma warning(disable: 4307) + ptr->registry.assign>(ptr->entity); +#pragma warning(pop) + }; + + addGameObject("testSprite", init, Position(10, 10), Size{ 128, 128 }, spriteSheetPath, SDL_Rect{ 0, 0, 32, 32 }); + addGameObject("testSprite2", std::mem_fn(&TestChar::init), Position(0, 0, bloom::relative), Size{ 128, 128 }, testCharPath, SDL_Rect{ 0, 0, 32, 32 }, 2); + addGameObject("testGO", &TestChar::init, Position(50, 50, bloom::relative, (bloom::middle | bloom::right)), Size{ 256, 256 }, testCharPath, SDL_Rect{ 64, 96, 32, 32 }, 3); + addGameObject("testAnimatedSprite", &TestAnimChar::init, testCharPath); + + registerSystem()->enabled = false; // Still wonky because of Coord change. We also don't want to start it immediately. + registerSystem(); + registerSystem(); // Do barrel rolls!!! + registerSystem(); + registerSystem(); + registerSystem(); + } +}; \ No newline at end of file diff --git a/Test Bench/main.cpp b/Test Bench/main.cpp index 542bb662..d89a6eb0 100644 --- a/Test Bench/main.cpp +++ b/Test Bench/main.cpp @@ -10,13 +10,12 @@ #include "GameObjectTest/TestAnimatedGameObject.h" #include "GameObjectTest/AnimationChangerSystem.h" #include "getExePath.h" +#include "TestScene.h" using namespace bloom; using namespace bloom::audio; using namespace std::chrono_literals; -using bloom::components::Position; using namespace bloom::graphics; -using bloom::components::Size; Game* game = nullptr; @@ -34,7 +33,7 @@ void test_player(const std::filesystem::path& dataDir) { fs::path soundsPath = dataDir / L"Sounds"; //MusicTrack track1{ musicPath / L"music_007.mp3" }; - + music.queue.setVolume(15.0); music.push(musicPath / L"music_001.mp3"); music.push(musicPath / L"music_002.mp3"); music.push(musicPath / L"music_003.mp3"); @@ -67,7 +66,6 @@ void test_drawer(const std::filesystem::path& dataDir) { catch (Exception & e) { std::cerr << e.what() << std::endl; } - srand(static_cast(time(nullptr))); SDL_Color randColor = { static_cast(rand() % 255), static_cast(rand() % 255), static_cast(rand() % 255), static_cast(rand() % 255) }; @@ -81,11 +79,13 @@ void test_drawer(const std::filesystem::path& dataDir) { if (!std::filesystem::exists(assetsPath)) throw bloom::Exception("Required assets can't be found."); + fs::path spriteSheetPath = assetsPath / "OverworldTestSpritesheet.png"; fs::path testCharPath = assetsPath / "TestChar.png"; fs::path fontPath = fontsPath / "Fira Code.ttf"; game->textures.load(spriteSheetPath, SDL_Color{ 64, 176, 104, 113 }); game->textures.load(testCharPath, SDL_Color{ 144,168,0,0 }); + game->sceneManager.changeScene(std::make_shared(game->sceneManager)); FontStore fonts; constexpr size_t UI_font = 0; @@ -114,61 +114,14 @@ void test_drawer(const std::filesystem::path& dataDir) { game->render(); game->delay(500); - // Test Game Object - entt::DefaultRegistry testRegistry; - AnimationChangerSystem animChangerTest(testRegistry); - bloom::systems::AnimationSystem animSysTest(testRegistry); - bloom::systems::RenderSystem renderSysTest(testRegistry); - //game->textures.load(spriteSheetPath, SDL_Color{ 64, 176, 104, 113 }); - //game->textures.load(testCharPath, SDL_Color{ 144,168,0,0 }); - TestChar testSprite = TestChar(testRegistry, game); - testSprite.init(SDL_Rect{ 0, 0, 128, 128 }, spriteSheetPath, SDL_Rect{ 0,0,32,32 }); - renderSysTest.update(); - game->render(); - TestChar testSprite2 = TestChar(testRegistry, game); - testSprite2.init(SDL_Rect{ 128, 0, 128, 128 }, testCharPath, SDL_Rect{ 0, 0, 32, 32 }); - renderSysTest.update(); - game->render(); - TestChar testGO = TestChar(testRegistry, game); - testGO.init(SDL_Rect{ 50, 50, 192, 192 }, testCharPath, SDL_Rect{ 64, 96, 32, 32 }); - testGO.disableRandomPos(); - renderSysTest.update(); - game->render(); - - // Randomizes position of entities(excluding those with `NoRandomPos` Component. - RandomPositionSystem randomizer(testRegistry); - TestAnimChar testAnim(testRegistry, game); - testAnim.init(testCharPath); - - // Test SpriteText2 std::string deltaTimeText{ "fps: " }; - - - // If manual control of entities is required, this is the method to do so. - auto & testGOpos = testRegistry.get(testGO.getEntityID()); - - auto & testGOsize = testRegistry.get(testGO.getEntityID()); - int testX = rstep(10), testY = rstep(10); - while (game->isRunning()) { - testGOpos.x += testX; - testGOpos.y += testY; - if (testGOpos.x >= WINDOW_WIDTH) { - testGOpos.x = -testGOsize.w; testX = rstep(10); testY = rstep(10); - } - if (testGOpos.y >= WINDOW_HEIGHT) { - testGOpos.y = -testGOsize.h; testX = rstep(10); testY = rstep(10); - } - // Demo ends here. framestart = SDL_GetTicks(); - auto dt = game->timer.lap(); + auto dt = game->timer.split(); game->handleEvents(); game->clear(); - animChangerTest.update(); - animSysTest.update(dt); - randomizer.update(WINDOW_WIDTH - 128, WINDOW_HEIGHT - 128); - renderSysTest.update(); // Test again. + game->update(); auto fps = 1000.0 / dt; deltaTimeText.erase(5); deltaTimeText += std::to_string(fps); @@ -185,7 +138,6 @@ void test_drawer(const std::filesystem::path& dataDir) { game->destroy(); } - int main() { SetConsoleCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8);