// IAEngine: 2D Game Engine by IA // Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev) // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // #include #include #include #include namespace ia::iae { Asset_Scene *g_activeScene{}; String g_gameName; String g_gamePackageName; String g_gameDeveloperName; String g_gamePublisherName; IA_VERSION_TYPE g_gameVersion{}; Vec2 g_designViewport; SDL_Window *g_windowHandle{}; Vector g_plugins; AssetManager* g_assetManager{}; AssetManager* g_defaultAssetManager{}; #if defined(__IA_DEBUG) && __IA_DEBUG BOOL g_isDebugMode = true; #else BOOL g_isDebugMode = false; #endif BOOL g_isHeadlessMode = false; INT32 Run(IN CONST String &name, IN CONST String &packageName, IN CONST String &developerName, IN CONST String &publisherName, IN IA_VERSION_TYPE version) { INT32 frameCounter{0}; g_gameName = name; g_gameVersion = version; g_gamePackageName = packageName; g_gameDeveloperName = developerName; g_gamePublisherName = publisherName; const auto config = Game_GetConfigRequest(); g_designViewport.x = config->DesignWidth; g_designViewport.y = config->DesignHeight; IAE_LOG_INFO("Booting IAEngine for ", g_gameName); SDL_SetHint(SDL_HINT_ORIENTATIONS, "LandscapeRight"); if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD)) THROW_UNKNOWN("Failed to intialize SDL: ", SDL_GetError()); if (!(g_windowHandle = SDL_CreateWindow(g_gameName.c_str(), config->WindowWidth, config->WindowHeight, SDL_WINDOW_RESIZABLE))) THROW_UNKNOWN("Failed to create the SDL window: ", SDL_GetError()); #if __ANDROID__ SDL_SetWindowFullscreen(g_windowHandle, true); #endif const auto gameVersion = g_gameVersion; SDL_SetAppMetadata(g_gameName.c_str(), IA_STRINGIFY_VERSION(gameVersion).c_str(), g_gamePackageName.c_str()); // EmbeddedResources::Initialize(); IAEngine::__Initialize("./Assets/"); SDL_Event event{}; while (true) { SDL_PollEvent(&event); if (event.type == SDL_EVENT_QUIT) break; IAEngine::__ProcessEvent(&event); IAEngine::__Update(); frameCounter++; if (frameCounter >= 60) { frameCounter = 0; IAEngine::__FixedUpdate(); } IAEngine::__RenderToWindow(); } IAEngine::__Terminate(); // EmbeddedResources::Terminate(); SDL_DestroyWindow(g_windowHandle); IAE_LOG_INFO("Shutting down IAEngine"); return 0; } } // namespace ia::iae namespace ia::iae { VOID IAEngine::__Initialize(IN CONST String& assetDirectory) { g_isHeadlessMode = false; RDC::Initialize(IVec2{g_designViewport.x, g_designViewport.y}, g_windowHandle, g_isDebugMode); g_defaultAssetManager = new AssetManager(); g_assetManager = g_defaultAssetManager; g_assetManager->SetAssetDirectory(assetDirectory); GameData::Initialize(); ChangeActiveScene(GameData::GetEntryScene() ? GameData::GetEntryScene() : g_assetManager->CreateScene({g_designViewport.x, g_designViewport.y})); Game_OnInitialize(); for (auto &p : g_plugins) p->OnInitialize(); } VOID IAEngine::__InitializeHeadless(IN CONST String& assetDirectory) { g_isHeadlessMode = true; if (!g_designViewport.x || !g_designViewport.y) g_designViewport = {800, 600}; g_defaultAssetManager = new AssetManager(); g_assetManager = g_defaultAssetManager; g_assetManager->SetAssetDirectory(assetDirectory); GameData::Initialize(); ChangeActiveScene(GameData::GetEntryScene() ? GameData::GetEntryScene() : g_assetManager->CreateScene({g_designViewport.x, g_designViewport.y})); Game_OnInitialize(); for (auto &p : g_plugins) p->OnInitialize(); } VOID IAEngine::__Terminate() { for (auto &p : g_plugins) p->OnTerminate(); Game_OnTerminate(); GameData::Terminate(); delete g_defaultAssetManager; RDC::Terminate(); } VOID IAEngine::__RenderToWindow() { g_activeScene->GetScene().OnDraw(); RDC::RenderToWindow(); g_activeScene->GetScene().OnDebugDraw(); Game_OnDebugDraw(); for (auto &p : g_plugins) p->OnDebugDraw(); } VOID IAEngine::__RenderToTexture(IN PVOID textureHandle) { g_activeScene->GetScene().OnDraw(); RDC::RenderToTexture((SDL_GPUTexture *) textureHandle); g_activeScene->GetScene().OnDebugDraw(); Game_OnDebugDraw(); for (auto &p : g_plugins) p->OnDebugDraw(); } VOID IAEngine::__Update() { FLOAT32 deltaTime = 0; g_activeScene->GetScene().OnUpdate(deltaTime); Game_OnUpdate(deltaTime); for (auto &p : g_plugins) p->OnUpdate(deltaTime); } VOID IAEngine::__FixedUpdate() { g_activeScene->GetScene().OnFixedUpdate(); Game_OnFixedUpdate(); for (auto &p : g_plugins) p->OnFixedUpdate(); } VOID IAEngine::__ProcessEvent(IN PVOID _event) { const auto event = (SDL_Event *) _event; } VOID IAEngine::AddPlugin(IN Asset_Plugin *plugin) { g_plugins.pushBack(plugin); } AssetManager* IAEngine::GetAssetManager() { return g_assetManager; } VOID IAEngine::SetAssetManager(IN AssetManager *instance) { g_assetManager = instance; } } // namespace ia::iae namespace ia::iae { VOID IAEngine::DrawTile(IN Asset_TileSheet *tileSheet, IN INT32 tileIndexX, IN INT32 tileIndexY, IN Vec2 position, IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH, IN BOOL flipV, IN Vec2 uvOffset) { RDC::DrawSpriteTopLeft(tileSheet->GetTexture(), tileIndexX, tileIndexY, position, scale, rotation, flipH, flipV, uvOffset); } VOID IAEngine::DrawSprite(IN Asset_Sprite *sprite, IN Vec2 position, IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH, IN BOOL flipV, IN Vec2 uvOffset) { RDC::DrawSpriteTopLeft(sprite->GetTexture(), 0, 0, position, scale, rotation, flipH, flipV, uvOffset); } VOID IAEngine::DrawSprite(IN Asset_SpriteSheet *spriteSheet, IN INT32 animationIndex, IN INT32 frameIndex, IN Vec2 position, IN Vec2 scale, IN FLOAT32 rotation, IN BOOL flipH, IN BOOL flipV, IN Vec2 uvOffset) { RDC::DrawSpriteTopLeft(spriteSheet->GetTexture(), frameIndex, animationIndex, position, scale, rotation, flipH, flipV, uvOffset); } } // namespace ia::iae namespace ia::iae { Asset_Scene *IAEngine::GetActiveScene() { return g_activeScene; } VOID IAEngine::ChangeActiveScene(IN Asset_Scene *scene) { g_activeScene = scene; } } // namespace ia::iae