#include "Global.h" #include "Input.h" #include "Instance.h" #include "Level.h" #include "Log.h" #include "Puzzle.h" #include "SDL3/SDL_mouse.h" #include "bgfx/bgfx.h" #include "imgui.h" #include "rendering/Rendering.h" #include #include #include namespace Game { void EntityRenderData::Render(const Model* models, const Material* materials) { if (ModelHandle == UINT16_MAX || MaterialHandle == UINT16_MAX) return; if (!Visible) return; auto& rendering = GameRendering::Get(); Transform.UpdateMatrix(); bgfx::setTransform(Transform.M.M); const Model& currentModel = models[ModelHandle]; const Material& currentMaterial = materials[MaterialHandle]; bgfx::setVertexBuffer(0, currentModel.VertexBuffer); bgfx::setIndexBuffer(currentModel.IndexBuffer); bgfx::setState(currentMaterial.State); float TimeValues[4]{0.0f}; TimeValues[0] = GetInstance().Time.Now; bgfx::setTexture(0, currentMaterial.Textures[0].SamplerHandle, currentMaterial.Textures[0].Handle); bgfx::setTexture(1, rendering.DitherTextures.DitherSampler, rendering.DitherTextures.FinalTex); bgfx::setTexture(2, rendering.DitherTextures.RampSampler, rendering.DitherTextures.RampTex); bgfx::setUniform(currentMaterial.Uniforms[Material::UTime], TimeValues); bgfx::setUniform(currentMaterial.Uniforms[Material::UDotColor], TestColor); bgfx::submit(currentMaterial.ViewID, currentMaterial.Shader); } namespace { void UpdatePlayerInputMode() { bool IsGaming = GetInstance().Player.InputM == InputMode::Game; SDL_SetWindowRelativeMouseMode(GetShared().Window.SDLWindow, IsGaming); auto& IO = ImGui::GetIO(); IO.ConfigFlags = FlagBool(IO.ConfigFlags, ImGuiConfigFlags_NoMouse | ImGuiConfigFlags_NoKeyboard, IsGaming); GameRendering::Get().UIVisible = IsGaming ? UIVisibilityState::Game : UIVisibilityState::Debug; } } // namespace void Level::Setup(GameData& data) { Log("Level setup"); void* storagePtr = data.EntityStorage; 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) { for (uint32_t xx = 0; xx < 11; ++xx) { Cube* c = Cubes.Get(Cubes.New()); if (c) { c->TestX = xx; c->TestY = yy; c->Setup(); } } } Cubes.New(); // Floor } if (Tests.Count == 0) { Tests.Get(Tests.New())->Setup(); } if (PuzzleTiles.Count == 0) { for (uint32_t puzI = 0; puzI < BX_COUNTOF(Puzzles); ++puzI) { Puzzles[puzI].Setup(); } } UpdatePlayerInputMode(); } void Level::Update() { START_PERF(); PlayerData& player = GetInstance().Player; // Input float delta = GetInstance().Time.Delta; delta = 1.0f / 144.0f; constexpr float moveSpeed = 10.0f; constexpr float rotSpeed = 0.6f; float forwardInput = (GetKey(ScanCode::W) ? 1.0f : 0.0f) + (GetKey(ScanCode::S) ? -1.0f : 0.0f); float rightInput = (GetKey(ScanCode::D) ? 1.0f : 0.0f) + (GetKey(ScanCode::A) ? -1.0f : 0.0f); bx::Vec3 moveInput = bx::Vec3{rightInput, forwardInput, 0.0f}; moveInput = bx::normalize(moveInput); bx::Vec3 inputVec = {moveInput.x * delta * moveSpeed, 0.0f, moveInput.y * delta * moveSpeed}; Vec2 mouseMovement = GetMouseMovement(); bx::Vec3 rotInput = {mouseMovement.y * delta * rotSpeed, mouseMovement.x * delta * rotSpeed, 0.0f}; if (GetKeyPressedNow(ScanCode::F1)) { player.CameraM = player.CameraM == CameraMode::Walk ? CameraMode::Freefly : CameraMode::Walk; } if (GetKeyPressedNow(ScanCode::F2)) { if (player.InputM == InputMode::Game) { player.InputM = InputMode::UI; } else { player.InputM = InputMode::Game; } UpdatePlayerInputMode(); } if (player.CameraM == CameraMode::Freefly) { if (GetMouseButton(MouseButton::Left)) { player.FreeflyXRot += rotInput.x; player.FreeflyYRot += rotInput.y; bx::mtxRotateY(player.FreeflyCamTransform.Rotation.M, player.FreeflyYRot); player.FreeflyCamTransform.RotateLocal({player.FreeflyXRot, 0.0f, 0.0f}); } player.FreeflyCamTransform.TranslateLocal({0.0f, 0.0f, -inputVec.z}); player.FreeflyCamTransform.TranslateLocal({-inputVec.x, 0.0f, 0.0f}); } else if (player.CameraM == CameraMode::Walk) { player.PlayerCamTransform.TranslateLocal({0.0f, 0.0f, -inputVec.z}); player.PlayerCamTransform.TranslateLocal({-inputVec.x, 0.0f, 0.0f}); player.PlayerCamTransform.Position.y = -3.0f; player.WalkXRot += rotInput.x; player.WalkYRot += rotInput.y; bx::mtxRotateY(player.PlayerCamTransform.Rotation.M, player.WalkYRot); 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); } void Level::Render(uint16_t viewId, const Model* models, const Material* materials) { auto& shared = GetShared(); float proj[16]; bx::mtxProj(proj, 75.0f, float(shared.Window.WindowWidth) / float(shared.Window.WindowHeight), 0.1f, 1000.0f, bgfx::getCaps()->homogeneousDepth); auto& player = GetInstance().Player; if (player.CameraM == CameraMode::Freefly) { 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); Tests.Render(models, materials); PuzzleTiles.Render(models, materials); } void Cube::Setup() { EData.MaterialHandle = 0; EData.ModelHandle = GameRendering::Get().GetModelHandleFromPath("models/cube.gltf"); } void Cube::Update() { if (TestX >= 0 && TestY >= 0) { double globalTime = GetInstance().Time.Now; double time = TestY <= 5 ? globalTime * 1.0f : 0.0f; float scale = 1.0f + TestX * 0.4f; EData.Transform.Position = bx::Vec3{TestX * 2.0f, TestY * 2.0f, 0.0f}; EData.Transform.Scale = {scale, scale, scale}; } else { EData.Transform.Position = {0.0f, -1.0f, 0.0f}; EData.Transform.Scale = {100.0f, 1.0f, 100.0f}; EData.TestColor[0] = 0.3f; EData.TestColor[1] = 0.325f; EData.TestColor[2] = 0.3f; } } void TestEntity::Setup() { EData.MaterialHandle = 0; EData.ModelHandle = GameRendering::Get().GetModelHandleFromPath("models/zurg.gltf"); 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