migrate main

This commit is contained in:
2025-08-10 11:49:07 +02:00
parent 6b987cf78d
commit 8bdcffcfa6
13 changed files with 276 additions and 192 deletions

188
src/td/display/Display.cpp Normal file
View File

@@ -0,0 +1,188 @@
#include <td/display/Display.h>
#include <GL/glew.h>
#include <SDL3/SDL.h>
#include <imgui.h>
#include <imgui_impl_opengl3.h>
#include <imgui_impl_sdl3.h>
#include <td/misc/Format.h>
#include <td/misc/Log.h>
namespace td {
Display::Display(int a_Width, int a_Height, const std::string& a_Title) :
m_LastWidth(0), m_LastHeight(0), m_AspectRatio(1), m_ShouldClose(false) {
m_Window = SDL_CreateWindow(a_Title.c_str(), a_Width, a_Height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
m_LastWidth = a_Width;
m_LastHeight = a_Height;
m_AspectRatio = (float)m_LastWidth / m_LastHeight;
// Prepare and create context
#ifdef __ANDROID__
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#else
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#endif
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
m_GLContext = SDL_GL_CreateContext(m_Window);
if (!m_GLContext) {
utils::LOGE(utils::Format("Could not create context! SDL error: %s", SDL_GetError()));
}
int major, minor, mask;
int r, g, b, a, depth;
int mBuffers, mSamples;
SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &mask);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &r);
SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE, &g);
SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &b);
SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &a);
SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &depth);
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &mBuffers);
SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &mSamples);
const char* mask_desc;
if (mask & SDL_GL_CONTEXT_PROFILE_CORE) {
mask_desc = "core";
} else if (mask & SDL_GL_CONTEXT_PROFILE_COMPATIBILITY) {
mask_desc = "compatibility";
} else if (mask & SDL_GL_CONTEXT_PROFILE_ES) {
mask_desc = "es";
} else {
mask_desc = "?";
}
utils::LOG(utils::Format(
"GL Context : %i.%i %s, Color : R:%i G:%i B:%i A:%i, Depth bits : %i", major, minor, mask_desc, r, g, b, a, depth));
utils::LOG(utils::Format(
"MultiSamples : Buffers : %i, Samples : %i", mBuffers, mSamples));
SDL_GL_MakeCurrent(m_Window, m_GLContext);
GLenum error = glewInit();
if (error) {
utils::LOGE(utils::Format("Error initializing glew : %s", glewGetErrorString(error)));
}
// WindowResizeEvent(WindowWidth, WindowHeight);
// vsync
SDL_GL_SetSwapInterval(1);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
(void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
// Setup Dear ImGui style
ImGui::StyleColorsDark();
// ImGui::StyleColorsLight();
// Setup scaling
float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
// ImGuiStyle& style = ImGui::GetStyle();
// style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this
// // requires resetting Style + calling this again)
// style.FontSizeBase = 13 * main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave
// // both here for documentation purpose)
ImFontConfig cfg;
cfg.SizePixels = 13 * main_scale * 2;
io.Fonts->AddFontDefault(&cfg);
// Setup Platform/Renderer backends
ImGui_ImplSDL3_InitForOpenGL(m_Window, m_GLContext);
ImGui_ImplOpenGL3_Init("#version 330");
}
void Display::Close() {
m_ShouldClose = true;
}
void Display::PollEvents() {
SDL_Event event;
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_EVENT_QUIT:
case SDL_EVENT_WINDOW_CLOSE_REQUESTED: {
m_ShouldClose = true;
break;
}
case SDL_EVENT_WINDOW_RESIZED: {
m_LastWidth = event.window.data1;
m_LastHeight = event.window.data2;
m_AspectRatio = (float)m_LastWidth / m_LastHeight;
OnAspectRatioChange(m_AspectRatio);
break;
}
case SDL_EVENT_KEY_DOWN: {
if(!event.key.repeat)
OnKeyDown(event.key.key);
break;
}
default:
break;
}
ImGui_ImplSDL3_ProcessEvent(&event);
}
// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL3_NewFrame();
ImGui::NewFrame();
}
void Display::Update(float a_Delta) {
StateMachine::Update(a_Delta);
ImGui::Render();
ImGuiIO& io = ImGui::GetIO();
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
// glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
SDL_GL_SwapWindow(m_Window);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
Display::~Display() {
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL3_Shutdown();
ImGui::DestroyContext();
SDL_GL_DestroyContext(m_GLContext);
SDL_DestroyWindow(m_Window);
SDL_Quit();
}
} // namespace td

View File

@@ -0,0 +1,10 @@
#include <td/display/DisplayState.h>
namespace td {
DisplayState::DisplayState(Display& a_Display) : Display::State(a_Display) {
Connect(m_StateMachine.OnKeyDown, std::bind(&DisplayState::OnKeyDown, this, std::placeholders::_1));
Connect(m_StateMachine.OnAspectRatioChange, std::bind(&DisplayState::OnAspectRatioChange, this, std::placeholders::_1));
}
} // namespace td

View File

@@ -0,0 +1,162 @@
#include <td/display/state/DebugWorldState.h>
#include <chrono>
#include <fstream>
#include <iostream>
#include <td/game/World.h>
#include <td/protocol/packet/PacketSerialize.h>
#include <td/protocol/packet/Packets.h>
#include <td/render/renderer/EntityRenderer.h>
#include <td/render/renderer/TowerRenderer.h>
#include <td/render/renderer/WorldRenderer.h>
#include <td/simulation/ClientSimulation.h>
#include <sp/common/DataBuffer.h>
#include <sp/extensions/Compress.h>
#include <sp/io/MessageStream.h>
#include <sp/io/StdIo.h>
#include <server/Server.h>
#include <server/socket/FakeSocket.h>
#include <server/state/GameState.h>
#include <client/Client.h>
#include <client/socket/FakeSocket.h>
#include <client/state/GameState.h>
#include <td/display/Display.h>
#include <td/display/state/DebugWorldState.h>
namespace td {
class ClientHandler : public protocol::PacketHandler {
private:
sim::ClientSimulation& m_Simulation;
using protocol::PacketHandler::Handle;
public:
ClientHandler(sim::ClientSimulation& a_Simulation) : m_Simulation(a_Simulation) {}
void Handle(const protocol::packets::LockStepsPacket& a_LockStep) {
m_Simulation.Handle(a_LockStep);
}
void Handle(const protocol::packets::LockStepResponsePacket& a_LockStep) {
m_Simulation.Handle(a_LockStep);
}
};
class WorldApply : public protocol::PacketHandler {
private:
game::World& m_World;
using protocol::PacketHandler::Handle;
public:
WorldApply(game::World& a_World) : m_World(a_World) {}
void Handle(const protocol::packets::WorldHeaderPacket& a_Header) override {
m_World.LoadMap(*a_Header);
}
void Handle(const protocol::packets::WorldDataPacket& a_Data) override {
m_World.LoadMap(*a_Data);
}
};
void Save(const protocol::PacketBase& header, const protocol::PacketBase& data) {
auto comp = std::make_shared<sp::ZlibCompress>();
std::ofstream fStream("test/tdmap.tdmap3");
auto out = std::make_shared<sp::StdOuput>(fStream);
sp::MessageStream<protocol::PacketFactory> stream(std::move(out), std::move(comp));
stream.WriteMessage(header, false);
stream.WriteMessage(data, false);
}
game::WorldPtr GetWorld() {
auto comp = std::make_shared<sp::ZlibCompress>();
std::ifstream fStream("test/tdmap.tdmap2");
auto out = std::make_shared<sp::StdInput>(fStream);
sp::MessageStream<protocol::PacketFactory> stream(std::move(out), std::move(comp));
auto header = stream.ReadMessage(protocol::PacketID::WorldHeader);
auto data = stream.ReadMessage(protocol::PacketID::WorldData);
auto w = std::make_shared<game::World>();
auto wa = std::make_shared<WorldApply>(*w);
protocol::PacketDispatcher d;
d.RegisterHandler(wa);
d.Dispatch(*header);
d.Dispatch(*data);
Save(*header, *data);
return w;
}
DebugWorldState::DebugWorldState(Display& a_Display) : DisplayState(a_Display) {
game::WorldPtr serverWorld = GetWorld();
// server
auto serverFakeSocket = std::make_shared<server::FakeSocket>();
m_Server = std::make_unique<server::Server>(serverFakeSocket);
// client
auto clientFakeSocket = client::FakeSocket::Connect(serverFakeSocket);
m_Client = std::make_unique<client::Client>(clientFakeSocket);
game::WorldPtr clientWorld = GetWorld();
m_Renderer.AddRenderer<render::WorldRenderer>(m_Camera, *clientWorld);
m_Renderer.AddRenderer<render::EntityRenderer>(m_Camera, *clientWorld);
m_Renderer.AddRenderer<render::TowerRenderer>(m_Camera, *clientWorld);
m_Camera.SetCamPos({77, 7, 13});
m_Camera.UpdatePerspective(m_StateMachine.GetAspectRatio());
m_Simulation = std::make_unique<sim::ClientSimulation>(*clientWorld, STEP_TIME);
m_ClientHandler = std::make_unique<ClientHandler>(*m_Simulation);
// packets from the server to the client
clientFakeSocket->OnReceive.Connect([this](const protocol::PacketBase& a_Packet) { a_Packet.Dispatch(*m_ClientHandler); });
m_Simulation->OnMissingLockSteps.Connect([clientFakeSocket](const std::vector<td::StepTime>& a_MissingSteps) {
clientFakeSocket->Send(protocol::packets::LockStepRequestPacket(a_MissingSteps));
});
m_Server->ChangeState<server::GameState>(serverWorld);
m_Client->ChangeState<client::GameState>(clientWorld);
}
void DebugWorldState::Update(float a_Delta) {
m_Server->Update(a_Delta);
m_Client->Update(a_Delta);
float lerp = m_Simulation->Update(a_Delta);
m_Renderer.Render(lerp);
}
void DebugWorldState::OnAspectRatioChange(float a_Ratio) {
m_Camera.UpdatePerspective(a_Ratio);
}
void DebugWorldState::OnKeyDown(SDL_Keycode a_Key) {
// temporary tests
if (a_Key == SDLK_A) {
m_Client->SendPacket(td::protocol::packets::SpawnTroopPacket(td::EntityType::Zombie, 1));
} else if (a_Key == SDLK_Z) {
m_Client->SendPacket(td::protocol::packets::PlaceTowerPacket(td::TowerType::Archer, td::TowerCoords(77, 13)));
}
}
DebugWorldState::~DebugWorldState() {}
} // namespace td