diff --git a/src/game/Instance.h b/src/game/Instance.h index 36791c4..923584a 100644 --- a/src/game/Instance.h +++ b/src/game/Instance.h @@ -46,5 +46,7 @@ namespace Game Time Time; PlayerData Player; Level GameLevel; + uint64_t ImguiIniSize = 0; + char ImguiIni[4096]{0}; }; } // namespace Game diff --git a/src/game/Level.cpp b/src/game/Level.cpp index 6cdddd0..8a47c88 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -3,6 +3,7 @@ #include "Instance.h" #include "Level.h" #include "Log.h" +#include "Puzzle.h" #include "SDL3/SDL_mouse.h" #include "bgfx/bgfx.h" #include "imgui.h" @@ -15,6 +16,7 @@ namespace Game void EntityRenderData::Render(const Model* models, const Material* materials) { if (ModelHandle == UINT16_MAX || MaterialHandle == UINT16_MAX) return; + if (!Visible) return; Transform.UpdateMatrix(); bgfx::setTransform(Transform.M.M); @@ -52,6 +54,10 @@ namespace Game bool needReset = false; needReset |= Cubes.Setup(storagePtr, needReset); needReset |= Tests.Setup(storagePtr, needReset); + needReset |= PuzzleTiles.Setup(storagePtr, needReset); + + PuzzleData.Setup(); + if (Cubes.Count == 0) { for (uint32_t yy = 0; yy < 11; ++yy) @@ -63,6 +69,7 @@ namespace Game { c->TestX = xx; c->TestY = yy; + c->Setup(); } } } @@ -70,7 +77,14 @@ namespace Game } if (Tests.Count == 0) { - Tests.New(); + Tests.Get(Tests.New())->Setup(); + } + if (PuzzleTiles.Count == 0) + { + for (uint32_t puzI = 0; puzI < BX_COUNTOF(Puzzles); ++puzI) + { + Puzzles[puzI].Setup(); + } } UpdatePlayerInputMode(); @@ -81,6 +95,7 @@ namespace Game START_PERF(); PlayerData& player = GetInstance().Player; + // Input float delta = GetInstance().Time.Delta; delta = 1.0f / 144.0f; constexpr float moveSpeed = 10.0f; @@ -137,10 +152,18 @@ namespace Game player.PlayerCamTransform.RotateLocal({player.WalkXRot, 0.0f, 0.0f}); } + // Cubes for (uint16_t i = 0; i < Cubes.Count; ++i) { Cubes.Get({i})->Update(); } + + // Puzzle tiles + for (int32_t i = 0; i < BX_COUNTOF(Puzzles); ++i) + { + Puzzles[i].Update(); + } + END_PERF(GetShared().Window.PerfCounters, PerfCounterType::GameLevelUpdate, GetShared().Window.FrameCounter); } @@ -161,15 +184,18 @@ namespace Game { player.FreeflyCamTransform.UpdateMatrix(); bgfx::setViewTransform(viewId, player.FreeflyCamTransform.M.M, proj); + bgfx::dbgTextPrintf(1, 0, 0b1100, "NOCLIP"); } else { player.PlayerCamTransform.UpdateMatrix(); bgfx::setViewTransform(viewId, player.PlayerCamTransform.M.M, proj); + bgfx::dbgTextPrintf(1, 0, 0b1100, " "); } - Cubes.Render(models, materials); + // Cubes.Render(models, materials); Tests.Render(models, materials); + PuzzleTiles.Render(models, materials); } void Cube::Setup() @@ -206,4 +232,40 @@ namespace Game EData.Transform.Position = {0.0f, 0.0f, 10.0f}; EData.TestColor[0] = 0.0f; } + + void WorldPuzzle::Setup() + { + Data.PlacedCardCount = 16; + for (int32_t i = 0; i < 16; ++i) + { + Data.PlacedCards[i].RefCard = {0}; + Data.PlacedCards[i].Position = {int8_t(i % 4), int8_t(i / 4)}; + } + + for (uint32_t cardI = 0; cardI < Data.PlacedCardCount; ++cardI) + { + const Puzzle::PlacedPuzzleCard& card = Data.PlacedCards[cardI]; + auto& tiles = GetInstance().GameLevel.PuzzleTiles; + TileHandles[cardI] = tiles.New(); + bx::Vec3 Pos = { + WorldPosition.x + card.Position.X * WorldCardSize.x, + WorldPosition.y, + WorldPosition.z + card.Position.Y * WorldCardSize.y, + }; + auto& tile = *tiles.Get(TileHandles[cardI]); + tile.EData.Transform.Position = Pos; + tile.EData.MaterialHandle = 0; + } + } + + void WorldPuzzle::Update() + { + for (int32_t cardI = 0; cardI < Data.PlacedCardCount; ++cardI) + { + Puzzle::PlacedPuzzleCard& card = Data.PlacedCards[cardI]; + if (!card.RefCard.IsValid()) continue; + const Puzzle::StaticPuzzleCard& cData = Puzzle::StaticPuzzleData::Get().GetCard(card.RefCard); + GetInstance().GameLevel.PuzzleTiles.Get(TileHandles[cardI])->EData.ModelHandle = cData.ModelHandle; + } + } } // namespace Game diff --git a/src/game/Level.h b/src/game/Level.h index 73bdae7..2af702a 100644 --- a/src/game/Level.h +++ b/src/game/Level.h @@ -21,6 +21,7 @@ namespace Game Transform Transform; uint16_t MaterialHandle = UINT16_MAX; uint16_t ModelHandle = UINT16_MAX; + bool Visible = true; void Render(const Model* models, const Material* materials); }; @@ -86,7 +87,6 @@ namespace Game return {}; } Data[Count] = {}; - Data[Count].Setup(); HandleT H; H.Idx = Count; ++Count; @@ -113,6 +113,17 @@ namespace Game } }; + struct WorldPuzzle + { + static constexpr Vec2 WorldCardSize{10.0f, 10.0f}; + Puzzle::PuzzleData Data; + Vec3 WorldPosition; + PuzzleTileEntityHandle TileHandles[Puzzle::Config::MaxCardsInPuzzle]; + + void Setup(); + void Update(); + }; + class Level { public: @@ -120,6 +131,10 @@ namespace Game EntityManager Tests; EntityManager PuzzleTiles; + public: + Puzzle::StaticPuzzleData PuzzleData; + WorldPuzzle Puzzles[1]; + public: void Setup(GameData& data); void Update(); diff --git a/src/game/Puzzle.cpp b/src/game/Puzzle.cpp index 28a9a23..d4c9069 100644 --- a/src/game/Puzzle.cpp +++ b/src/game/Puzzle.cpp @@ -1,3 +1,4 @@ +#include "Log.h" #include "Puzzle.h" #include @@ -9,10 +10,36 @@ namespace {0, 1}, {1, 0}, }; -} + + Puzzle::StaticPuzzleData* StaticDataInstance = nullptr; +} // namespace namespace Puzzle { + void StaticPuzzleData::Setup() + { + if (StaticDataInstance == nullptr) + { + StaticDataInstance = this; + Log("Setting up static puzzle data"); + } + else + { + Log("Static puzzle data already set up"); + } + } + + StaticPuzzleData& StaticPuzzleData::Get() + { + assert(StaticDataInstance != nullptr); + return *StaticDataInstance; + } + const StaticPuzzleCard& StaticPuzzleData::GetCard(StaticPuzzleCardHandle H) const + { + assert(H.IsValid()); + return Cards[H.Idx]; + } + bool PuzzleNode::HasElement(PuzzleElementType search) const { for (int32_t i = 0; i < Config::MaxElementsPerTile; ++i) @@ -37,11 +64,29 @@ namespace Puzzle return MaxAvailableCount - UsedCount; } + const PuzzleNode& PuzzleData::GetNodeAt(PuzPos pos) const + { + assert(pos.X < Config::MaxPuzzleSizeCards && pos.Y < Config::MaxPuzzleSizeCards && pos.X >= 0 && pos.Y >= 0); + return PlacedNodes[pos.Y * Config::MaxPuzzleSizeCards + pos.X]; + } + + PuzzleElementType PuzzleData::GetElementAt(ElemPos pos) const + { + assert(pos.ElemIdx < Config::MaxElementsPerTile); + const PuzzleNode& node = GetNodeAt(pos.Position); + return node.PlacedTypes[pos.ElemIdx]; + } + bool PuzzleSolver::IsPuzzleSolved(const PuzzleData& puzzle) { bool IsSolved = true; for (uint32_t i = 0; i < puzzle.GoalPositionCount; ++i) { + if (!IsExitSatisfied(puzzle, puzzle.GoalPositions[i])) + { + IsSolved = false; + break; + } } return IsSolved; } diff --git a/src/game/Puzzle.h b/src/game/Puzzle.h index 31e8087..c776fe1 100644 --- a/src/game/Puzzle.h +++ b/src/game/Puzzle.h @@ -64,11 +64,25 @@ namespace Puzzle struct StaticPuzzleCard { PuzzleNode Nodes[Config::NodesPerCard]; + uint16_t ModelHandle = 0; }; struct StaticPuzzleCardHandle { uint16_t Idx = UINT16_MAX; + bool IsValid() + { + return Idx != UINT16_MAX; + } + }; + + struct StaticPuzzleData + { + StaticPuzzleCard Cards[64]; + + void Setup(); + static StaticPuzzleData& Get(); + const StaticPuzzleCard& GetCard(StaticPuzzleCardHandle H) const; }; struct PlacedPuzzleCard diff --git a/src/game/rendering/Rendering.cpp b/src/game/rendering/Rendering.cpp index e848c01..8617f52 100644 --- a/src/game/rendering/Rendering.cpp +++ b/src/game/rendering/Rendering.cpp @@ -8,6 +8,7 @@ #include "SDL3/SDL_events.h" #include "backends/imgui_impl_sdl3.h" #include "bgfx/defines.h" +#include "bx/bx.h" #include "bx/filepath.h" #include "bx/math.h" #include "bx/timer.h" @@ -250,9 +251,15 @@ namespace Game // platIO.Platform_SetWindowSize = TODO; // platIO.Platform_RenderWindow = TODO; - if (!GetInstance().IsInitialized) + GameInstance& inst = GetInstance(); + if (!inst.IsInitialized) { - GetInstance().Time.StartTime = bx::getHPCounter(); + inst.Time.StartTime = bx::getHPCounter(); + } + + if (inst.ImguiIniSize > 0) + { + ImGui::LoadIniSettingsFromMemory(inst.ImguiIni, inst.ImguiIniSize); } } @@ -333,6 +340,11 @@ namespace Game void GameRendering::Shutdown() { + Log("--- RENDERING_SHUTDOWN ---"); + const char* iniData = ImGui::SaveIniSettingsToMemory(reinterpret_cast(&GetInstance().ImguiIniSize)); + assert(GetInstance().ImguiIniSize <= BX_COUNTOF(GameInstance::ImguiIni)); + bx::memCopy( + GetInstance().ImguiIni, iniData, bx::min(GetInstance().ImguiIniSize, BX_COUNTOF(GameInstance::ImguiIni))); ImGui_ImplSDL3_Shutdown(); imguiDestroy(); bgfx::shutdown();