diff --git a/Game/Data/StaticMesh.h b/Game/Data/StaticMesh.h new file mode 100644 index 0000000..2130bd4 --- /dev/null +++ b/Game/Data/StaticMesh.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +struct StaticMesh +{ + DECLARE_ENTITY() +}; +DEFINE_ENTITY(StaticMesh); diff --git a/Game/Debug/DebugTopBar.cpp b/Game/Debug/DebugTopBar.cpp new file mode 100644 index 0000000..61991d2 --- /dev/null +++ b/Game/Debug/DebugTopBar.cpp @@ -0,0 +1,50 @@ +#include + +#include +#include + +namespace +{ + Juliet::String GetGameModeName(GameMode gameMode) + { + using namespace Juliet; + switch (gameMode) + { + case GameMode::Editor: return WrapString("Editor"); + case GameMode::Play: return WrapString("Play"); + case GameMode::Debug: return WrapString("Debug"); + default: return WrapString("Unknown ERROR"); + } + } +} // namespace + +void DrawTopBar() +{ + auto* gameState = GetGameState(); + + ImGuiViewport* viewport = ImGui::GetMainViewport(); + ImGui::SetNextWindowPos(viewport->Pos); + ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, 10.0f)); + + ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings | + ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav; + + ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.6f)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10.0f, 5.0f)); + + if (ImGui::Begin("TopBarOverlay", nullptr, flags)) + { + ImGui::Text("Game Mode: %s", CStr(GetGameModeName(gameState->Mode))); + + char fps_text[32]; + snprintf(fps_text, sizeof(fps_text), "FPS: %.1f (%.2f ms)", ImGui::GetIO().Framerate, 1000.0f / ImGui::GetIO().Framerate); + float text_width = ImGui::CalcTextSize(fps_text).x; + ImGui::SameLine(viewport->Size.x - text_width - 15.0f); // 15px right padding + // Render FPS text + ImGui::Text("%s", fps_text); + } + ImGui::End(); + + ImGui::PopStyleVar(); + ImGui::PopStyleColor(); +} diff --git a/Game/Debug/DebugTopBar.h b/Game/Debug/DebugTopBar.h new file mode 100644 index 0000000..64085ac --- /dev/null +++ b/Game/Debug/DebugTopBar.h @@ -0,0 +1,5 @@ +#pragma once + +#if JULIET_DEBUG +void DrawTopBar(); +#endif diff --git a/Game/Entity/EntityManager.cpp b/Game/Entity/EntityManager.cpp index 71c4c62..6cc6a88 100644 --- a/Game/Entity/EntityManager.cpp +++ b/Game/Entity/EntityManager.cpp @@ -1,6 +1,7 @@ #include #include +#include EntityID EntityManager::ID = 0; @@ -29,3 +30,14 @@ void RegisterEntity(EntityManager& /*manager*/, Entity* entity) { entity->ID = EntityManager::ID++; } + +void UpdateEntityManager(EntityManager& manager) +{ + for (Entity& ent : manager.Entities) + { + if (ent.MeshInstance != indexMax) + { + Juliet::SetMeshInstanceTransform(ent.MeshInstance, Juliet::MatrixTranslation(ent.X, ent.Y, 0.0f)); + } + } +} diff --git a/Game/Entity/EntityManager.h b/Game/Entity/EntityManager.h index 6ec9ead..0a212ae 100644 --- a/Game/Entity/EntityManager.h +++ b/Game/Entity/EntityManager.h @@ -21,3 +21,4 @@ void InitEntityManager(Juliet::NonNullPtr world); void ShutdownEntityManager(); EntityManager& GetEntityManager(); void RegisterEntity(EntityManager& manager, Entity* entity); +void UpdateEntityManager(EntityManager& manager); diff --git a/Game/game.cpp b/Game/game.cpp index 146d784..4036be5 100644 --- a/Game/game.cpp +++ b/Game/game.cpp @@ -1,53 +1,37 @@ - -#include // TODO: remove because our dll should not be platform dependant -#undef min -#undef max - #include #include -#include #include #include #include #include #include +#include #include #include #include #include #include -GameState* gGameState = nullptr; +#if JULIET_DEBUG +#include +#endif + +namespace +{ + GameState* gGameState = nullptr; +} + GameState* GetGameState() { return gGameState; } -// Test code -namespace Game -{ - struct Door - { - DECLARE_ENTITY() - bool IsOpened; - }; - DEFINE_ENTITY(Door); - - struct Rock - { - DECLARE_ENTITY() - int Health; - }; - DEFINE_ENTITY(Rock); -} // namespace Game - extern "C" JULIET_API void __cdecl GameShutdown() { printf("Shutting down game...\n"); using namespace Juliet; - using namespace Game; ShutdownEntityManager(); } @@ -55,7 +39,6 @@ extern "C" JULIET_API void __cdecl GameShutdown() extern "C" JULIET_API void __cdecl GameUpdate(Juliet::GameData* params, [[maybe_unused]] float deltaTime) { using namespace Juliet; - using namespace Game; gGameState = params->GameState; if (!gGameState) @@ -81,60 +64,71 @@ extern "C" JULIET_API void __cdecl GameUpdate(Juliet::GameData* params, [[maybe_ // Entity Use case InitEntityManager(gameState->World); - auto& manager = GetEntityManager(); - Door* door = MakeEntity(manager, 10.0f, 2.0f); - door->IsOpened = true; + auto& manager = GetEntityManager(); - Entity* ent = door->Base; - [[maybe_unused]] Door* stillDoor = DownCast(ent); - Assert(door == stillDoor); + NonNullPtr mesh = MakeEntity(manager, 1.f, 2.f); - Rock* rock = MakeEntity(manager, 1.f, 2.f); - rock->Health = 100; - Assert(door->Base != rock->Base); - - MeshAssetID cubeAsset = GetCubePrimitiveMeshAssetID(); - MeshInstanceID meshInst = CreateMeshInstance(cubeAsset, 0, MatrixIdentity()); - rock->Base->MeshInstance = meshInst; - - printf("Door is %s\n", door->IsOpened ? "Opened" : "Closed"); - printf("Rock has %d health points\n", rock->Health); + MeshAssetID cubeAsset = GetCubePrimitiveMeshAssetID(); + MeshInstanceID meshInst = CreateMeshInstance(cubeAsset, 0, MatrixIdentity()); + mesh->Base->MeshInstance = meshInst; // Summer at 2pm lighting - Vector3 sunDirection = { -0.2f, -0.9f, -0.3f }; - Vector3 sunColor = { 1.0f, 0.95f, 0.85f }; - float ambientIntensity = 0.4f; + Vector3 sunDirection = { -0.2f, -0.9f, -0.3f }; + Vector3 sunColor = { 1.0f, 0.95f, 0.85f }; + float ambientIntensity = 0.4f; SetGlobalLight(sunDirection, sunColor, ambientIntensity); } +#if JULIET_DEBUG + DrawTopBar(); +#endif + GameMode previousFrameMode = gGameState->Mode; if (IsKeyPressed(ScanCode::F1)) { - gGameState->Mode = static_cast((ToUnderlying(gGameState->Mode) + 1) % 2); + if (previousFrameMode == GameMode::Play) + { + gGameState->Mode = GameMode::Debug; + } + else if (previousFrameMode == GameMode::Debug) + { + gGameState->Mode = GameMode::Play; + } + } + + if (gGameState->Mode == GameMode::Editor) + { + if (IsKeyPressed(ScanCode::F5)) + { + gGameState->Mode = GameMode::Play; + } } if (gGameState->Mode == GameMode::Play) { + if (IsKeyPressed(ScanCode::Escape)) + { + gGameState->Mode = GameMode::Editor; + } + // update game } - - // Sync entity transforms to meshes + auto& manager = GetEntityManager(); - for (Entity& ent : manager.Entities) - { - if (ent.MeshInstance != static_cast(-1)) - { - SetMeshInstanceTransform(ent.MeshInstance, MatrixTranslation(ent.X, ent.Y, 0.0f)); - } - } + UpdateEntityManager(manager); if (gGameState->Mode == GameMode::Debug) { - if (previousFrameMode != gGameState->Mode) + if (previousFrameMode == GameMode::Play) { ActivateDebugController(); } + if (IsKeyPressed(ScanCode::Escape)) + { + gGameState->Mode = GameMode::Editor; + } + UpdateDebugController(deltaTime); #if JULIET_DEBUG @@ -143,11 +137,8 @@ extern "C" JULIET_API void __cdecl GameUpdate(Juliet::GameData* params, [[maybe_ ImGui::End(); #endif } - else + if (gGameState->Mode != GameMode::Debug && previousFrameMode == GameMode::Debug) { - if (previousFrameMode != gGameState->Mode) - { - DeactivateDebugController(); - } + DeactivateDebugController(); } } diff --git a/Game/game.h b/Game/game.h index 46faa99..66bc767 100644 --- a/Game/game.h +++ b/Game/game.h @@ -12,6 +12,7 @@ struct World enum class GameMode { + Editor, Play, Debug }; @@ -22,7 +23,7 @@ struct GameState World* World; - GameMode Mode = GameMode::Play; + GameMode Mode = GameMode::Editor; float TotalTime; int Score;