diff --git a/BloomFramework/include/Game.h b/BloomFramework/include/Game.h index c48518a..28f21fd 100644 --- a/BloomFramework/include/Game.h +++ b/BloomFramework/include/Game.h @@ -8,13 +8,15 @@ namespace bloom { class BLOOMFRAMEWORK_API Game { public: + Game(Game const&) = delete; + void operator=(Game const&) = delete; + /** - * @param windowSize Required window size - * @param flags Window and renderer flags + * @brief Retrieves a reference to an instance of Game + * + * Only one instance of Game can exist at any singular moment, and will be initialized on first use. */ - Game(components::Size windowSize, const std::pair& flags = { 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC }); - //Game(std::nothrow_t, components::Size windowSize, const std::pair& flags = { SDL_WINDOW_FULLSCREEN, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC }); - ~Game(); + static Game& getInstance(); /** * @brief Initializes SDL subsystems and modules with certain parameters @@ -27,19 +29,15 @@ namespace bloom { const std::tuple& mixerParams = { 44100, MIX_DEFAULT_FORMAT , 2, 2048 }, int imageFlags = IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF | IMG_INIT_WEBP); - /** - * @brief Cleans up initialized SDL subsystems and modules - */ - static bool exit(); - - /** * @brief Creates a window with certain parameters * * @param title Window title * @param pos Window position + * @param windowSize Required window size + * @param flags Window and renderer flags */ - void create(std::string_view title, components::Position pos); + void create(std::string_view title, components::Position pos, components::Size windowSize, const std::pair& flags = { 0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC }); /** * @brief Updates timer @@ -127,12 +125,19 @@ namespace bloom { SDL_Renderer* m_renderer{ nullptr }; SDL_Window* m_window{ nullptr }; components::Size m_windowSize; - const int c_windowFlags, c_rendererFlags; + //const int c_windowFlags, c_rendererFlags; SDL_Color m_color{}; SDL_Event m_event{}; bool m_isRunning; private: - static int s_runningInstancesQnt; + Game() = default; + //Game(std::nothrow_t, components::Size windowSize, const std::pair& flags = { SDL_WINDOW_FULLSCREEN, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC }); + ~Game(); + + /** + * @brief Cleans up initialized SDL subsystems and modules + */ + static void exit(); }; } \ No newline at end of file diff --git a/BloomFramework/include/GameObject.h b/BloomFramework/include/GameObject.h index 3a3ef3d..be493e0 100644 --- a/BloomFramework/include/GameObject.h +++ b/BloomFramework/include/GameObject.h @@ -16,7 +16,7 @@ namespace bloom { */ class GameObject { public: - GameObject(entt::registry& registry, Game*& gameInstance) : m_registry(registry), c_gameInstance(gameInstance) { + GameObject(entt::registry& registry, Game& gameInstance) : m_registry(registry), c_gameInstance(gameInstance) { m_entity = m_registry.create(); m_registry.assign(m_entity); m_registry.assign(m_entity); @@ -33,7 +33,7 @@ namespace bloom { protected: entt::registry& m_registry; - Game* const& c_gameInstance; + Game& c_gameInstance; uint32_t m_entity; }; } \ No newline at end of file diff --git a/BloomFramework/src/Game.cpp b/BloomFramework/src/Game.cpp index 9264494..acef611 100644 --- a/BloomFramework/src/Game.cpp +++ b/BloomFramework/src/Game.cpp @@ -5,21 +5,14 @@ std::clog << "Failed to initialize " << #format << " format support" << std::endl; namespace bloom { - int Game::s_runningInstancesQnt = 0; - - Game::Game(components::Size windowSize, const std::pair& flags) : - m_windowSize(windowSize), - c_windowFlags(flags.first), - c_rendererFlags(flags.second), - m_isRunning(false) - { - ++s_runningInstancesQnt; + Game& Game::getInstance() { + static Game instance; + return instance; } + Game::~Game() { destroy(); - --s_runningInstancesQnt; - //if (s_runningInstancesQnt <= 0) - // exit(); + exit(); } void Game::initialize(uint32_t initFlags, @@ -61,25 +54,21 @@ namespace bloom { std::clog << "SDL_image initialized" << std::endl; } - bool Game::exit() { - // Prevent the SDL from being unloaded if there is at least one alive object - if (!s_runningInstancesQnt) { - IMG_Quit(); - TTF_Quit(); - Mix_Quit(); - SDL_Quit(); - return true; - } - return false; + void Game::exit() { + IMG_Quit(); + TTF_Quit(); + Mix_Quit(); + SDL_Quit(); } - void Game::create(std::string_view title, components::Position pos) { - m_window = SDL_CreateWindow(title.data(), pos.x, pos.y, m_windowSize.w, m_windowSize.h, c_windowFlags); + void Game::create(std::string_view title, components::Position pos, components::Size windowSize, const std::pair& flags) { + m_windowSize = windowSize; + m_window = SDL_CreateWindow(title.data(), pos.x, pos.y, windowSize.w, windowSize.h, flags.first); if (!m_window) throw Exception{ "Game::initialize", SDL_GetError() }; - std::clog << "Window created with width of " << m_windowSize.w << " and height of " << m_windowSize.h << std::endl; + std::clog << "Window created with width of " << windowSize.w << " and height of " << windowSize.h << std::endl; - m_renderer = SDL_CreateRenderer(m_window, -1, c_rendererFlags); + m_renderer = SDL_CreateRenderer(m_window, -1, flags.second); if (!m_renderer) throw Exception{ "Game::initialize", SDL_GetError() }; std::clog << "Renderer initialized." << std::endl; diff --git a/Test Bench/GameObjectTest/TestAnimatedGameObject.h b/Test Bench/GameObjectTest/TestAnimatedGameObject.h index f83bf41..b9d03e8 100644 --- a/Test Bench/GameObjectTest/TestAnimatedGameObject.h +++ b/Test Bench/GameObjectTest/TestAnimatedGameObject.h @@ -16,7 +16,7 @@ class TestAnimChar : public bloom::GameObject { void init(const std::filesystem::path& texturePath = "Assets/TestChar.png") { m_registry.replace(m_entity, 50, 50); m_registry.replace(m_entity, 256, 256); - auto tmp = c_gameInstance->textures.load(texturePath); + auto tmp = c_gameInstance.textures.load(texturePath); m_registry.assign(m_entity, tmp, SDL_Rect{ 0,32,32,32 }); diff --git a/Test Bench/GameObjectTest/TestGameObject.h b/Test Bench/GameObjectTest/TestGameObject.h index f0f365f..4d8279d 100644 --- a/Test Bench/GameObjectTest/TestGameObject.h +++ b/Test Bench/GameObjectTest/TestGameObject.h @@ -19,7 +19,7 @@ class TestChar : public bloom::GameObject { } 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 = c_gameInstance->textures.load(texturePath); + auto tmp = c_gameInstance.textures.load(texturePath); init(tmp, pos_and_size, srcRect); } diff --git a/Test Bench/main.cpp b/Test Bench/main.cpp index 1674fbe..7c6d2d6 100644 --- a/Test Bench/main.cpp +++ b/Test Bench/main.cpp @@ -18,7 +18,7 @@ using bloom::components::Position; using namespace bloom::graphics; using bloom::components::Size; -Game* game = nullptr; +Game& game = Game::getInstance(); const int WINDOW_WIDTH = 800; const int WINDOW_HEIGHT = 600; @@ -59,9 +59,8 @@ void test_drawer(const std::filesystem::path& dataDir) { const int framedelay = 1000 / 60; Uint32 framestart; - game = new Game({ WINDOW_WIDTH, WINDOW_HEIGHT }); try { - game->create("Bloom Test", { SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED }); + game.create("Bloom Test", { SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED }, { WINDOW_WIDTH, WINDOW_HEIGHT }); } catch (Exception & e) { std::cerr << e.what() << std::endl; @@ -70,9 +69,9 @@ void test_drawer(const std::filesystem::path& dataDir) { srand(static_cast(time(nullptr))); SDL_Color randColor = { static_cast(rand() % 255), static_cast(rand() % 255), static_cast(rand() % 255), static_cast(rand() % 255) }; - game->setColor(randColor); - game->clear(); - game->render(); + game.setColor(randColor); + game.clear(); + game.render(); fs::path assetsPath = dataDir / L"Assets"; fs::path fontsPath = dataDir / L"Fonts"; @@ -83,21 +82,21 @@ void test_drawer(const std::filesystem::path& dataDir) { 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.textures.load(spriteSheetPath, SDL_Color{ 64, 176, 104, 113 }); + game.textures.load(testCharPath, SDL_Color{ 144,168,0,0 }); FontStore fonts; constexpr size_t UI_font = 0; fonts.load(fontPath, UI_font); - auto renderer = game->_getRenderer(); + auto renderer = game._getRenderer(); // Test SpriteText(NFont) bloom::graphics::SpriteText testText(renderer, fonts[UI_font], "Hello, World!"); { auto newStyle = testText.getStyle(); newStyle.blendingMode = TextStyle::BlendingMode::blended; - SDL_Color col, curcol = game->getColor(); + SDL_Color col, curcol = game.getColor(); std::clog << "current_color: r: " << +curcol.r << ", g: " << +curcol.g << ", b: " << +curcol.b << std::endl; if (curcol.r + curcol.g + curcol.b >= 384) { col = { 0, 0, 0, 0 }; @@ -110,8 +109,8 @@ void test_drawer(const std::filesystem::path& dataDir) { testText.setStyle(newStyle); } testText.render(std::nullopt, SDL_Point{ 300, 250 }); - game->render(); - game->delay(500); + game.render(); + game.delay(500); // Test Game Object entt::registry testRegistry; @@ -122,16 +121,16 @@ void test_drawer(const std::filesystem::path& dataDir) { testSprite.init(SDL_Rect{ 0, 0, 128, 128 }, spriteSheetPath, SDL_Rect{ 0,0,32,32 }); testSprite.enableRandomPos(); renderSysTest.update(); - game->render(); + game.render(); TestChar testSprite2 = TestChar(testRegistry, game); testSprite2.init(SDL_Rect{ 128, 0, 128, 128 }, testCharPath, SDL_Rect{ 0, 0, 32, 32 }); testSprite2.enableRandomPos(); renderSysTest.update(); - game->render(); + game.render(); TestChar testGO = TestChar(testRegistry, game); testGO.init(SDL_Rect{ 50, 50, 192, 192 }, testCharPath, SDL_Rect{ 64, 96, 32, 32 }); renderSysTest.update(); - game->render(); + game.render(); // Randomizes position of entities (which has `RandomPos` component) RandomPositionSystem randomizer(testRegistry); @@ -147,7 +146,7 @@ void test_drawer(const std::filesystem::path& dataDir) { auto& testGOsize = testRegistry.get(testGO.getEntityID()); int testX = rstep(10), testY = rstep(10); - while (game->isRunning()) { + while (game.isRunning()) { testGOpos.x += testX; testGOpos.y += testY; if (testGOpos.x >= WINDOW_WIDTH) { @@ -158,9 +157,9 @@ void test_drawer(const std::filesystem::path& dataDir) { } // Demo ends here. framestart = SDL_GetTicks(); - auto dt = game->timer.lap(); - game->handleEvents(); - game->clear(); + auto dt = game.timer.lap(); + game.handleEvents(); + game.clear(); animChangerTest.update(); animSysTest.update(dt); randomizer.update(WINDOW_WIDTH - 128, WINDOW_HEIGHT - 128); @@ -170,15 +169,15 @@ void test_drawer(const std::filesystem::path& dataDir) { deltaTimeText += std::to_string(fps); testText.setText(deltaTimeText); testText.render(std::nullopt, SDL_Point{ 0, 0 }); - game->render(); - //game->update(); + game.render(); + //game.update(); int frametime = SDL_GetTicks() - framestart; if (framedelay > frametime) { - game->delay(framedelay - frametime); + game.delay(framedelay - frametime); } } - game->destroy(); + game.destroy(); } int main(int argc, char* argv[]) { @@ -203,7 +202,6 @@ int main(int argc, char* argv[]) { sounds[1]->play(); std::this_thread::sleep_for(3s); sounds.clear(); - delete game; return 0; } \ No newline at end of file