diff --git a/resources/config/ship_selection_menu.json b/resources/config/ship_selection_menu.json new file mode 100644 index 0000000..7d953fe --- /dev/null +++ b/resources/config/ship_selection_menu.json @@ -0,0 +1,64 @@ +{ + "root": { + "name": "shipSelectionRoot", + "type": "node", + "children": [ + + { + "type": "TextField", + "name": "nicknameInput", + "x": 400, + "y": 150, + "width": 400, + "height": 50, + "placeholder": "Enter your nickname", + "fontPath": "resources/fonts/DroidSans.ttf", + "fontSize": 16, + "maxLength": 256, + "color": [122, 156, 198, 1], + "placeholderColor": [122, 156, 198, 1], + "backgroundColor": [15, 29, 51, 1], + "borderColor": [15, 29, 51, 1] + }, + { + "type": "Button", + "name": "spaceshipButton", + "x": 300, + "y": 320, + "width": 200, + "height": 80, + "textures": { + "normal": "resources/multiplayer_menu/JoinServer.png", + "hover": "resources/multiplayer_menu/JoinServer.png", + "pressed": "resources/multiplayer_menu/JoinServer.png" + } + }, + { + "type": "Button", + "name": "cargoshipButton", + "x": 700, + "y": 320, + "width": 200, + "height": 80, + "textures": { + "normal": "resources/multiplayer_menu/JoinServer.png", + "hover": "resources/multiplayer_menu/JoinServer.png", + "pressed": "resources/multiplayer_menu/JoinServer.png" + } + }, + { + "type": "Button", + "name": "backButton", + "x": 449, + "y": 280, + "width": 382, + "height": 56, + "textures": { + "normal": "resources/multiplayer_menu/Backbutton.png", + "hover": "resources/multiplayer_menu/Backbutton.png", + "pressed": "resources/multiplayer_menu/Backbutton.png" + } + } + ] + } + } \ No newline at end of file diff --git a/src/Game.cpp b/src/Game.cpp index a6981b9..96a09a5 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -103,9 +103,22 @@ namespace ZL menuManager.setupMenu(); - menuManager.onSingleplayerPressed = [this]() { + menuManager.onSingleplayerPressed = [this](const std::string& nickname, int shipType) { + Environment::shipState.nickname = nickname; + Environment::shipState.shipType = shipType; + networkClient = std::make_unique(); networkClient->Connect("", 0); + +#ifndef NETWORK + auto localClient = dynamic_cast(networkClient.get()); + if (localClient) { + ZL::ClientState st = Environment::shipState; + st.id = localClient->GetClientId(); + localClient->setLocalPlayerState(st); + } +#endif + lastTickCount = 0; spaceGameStarted = 1; }; diff --git a/src/MenuManager.cpp b/src/MenuManager.cpp index 752552c..2dca211 100644 --- a/src/MenuManager.cpp +++ b/src/MenuManager.cpp @@ -21,6 +21,7 @@ namespace ZL { gameOverSavedRoot = loadUiFromFile("resources/config/game_over.json", renderer, CONST_ZIP_FILE); + auto shipSelectionRoot = loadUiFromFile("resources/config/ship_selection_menu.json", renderer, CONST_ZIP_FILE); std::function loadGameplayUI; loadGameplayUI = [this]() { uiManager.replaceRoot(uiSavedRoot); @@ -114,10 +115,38 @@ namespace ZL { }); }; - uiManager.setButtonCallback("singleButton", [loadGameplayUI, this](const std::string& name) { - std::cerr << "Single button pressed: " << name << " -> load gameplay UI\n"; - loadGameplayUI(); - onSingleplayerPressed(); + uiManager.setButtonCallback("singleButton", [this, shipSelectionRoot, loadGameplayUI](const std::string& name) { + std::cerr << "Single button pressed: " << name << " -> open ship selection UI\n"; + if (!shipSelectionRoot) { + std::cerr << "Failed to load ship selection UI\n"; + return; + } + if (uiManager.pushMenuFromSavedRoot(shipSelectionRoot)) { + uiManager.setButtonCallback("spaceshipButton", [this, loadGameplayUI](const std::string& btnName) { + std::string nick = uiManager.getTextFieldValue("nicknameInput"); + if (nick.empty()) nick = "Player"; + int shipType = 0; + uiManager.popMenu(); + loadGameplayUI(); + if (onSingleplayerPressed) onSingleplayerPressed(nick, shipType); + }); + + uiManager.setButtonCallback("cargoshipButton", [this, loadGameplayUI](const std::string& btnName) { + std::string nick = uiManager.getTextFieldValue("nicknameInput"); + if (nick.empty()) nick = "Player"; + int shipType = 1; + uiManager.popMenu(); + loadGameplayUI(); + if (onSingleplayerPressed) onSingleplayerPressed(nick, shipType); + }); + + uiManager.setButtonCallback("backButton", [this](const std::string& btnName) { + uiManager.popMenu(); + }); + } + else { + std::cerr << "Failed to push ship selection menu\n"; + } }); uiManager.setButtonCallback("multiplayerButton", [loadGameplayUI, this](const std::string& name) { std::cerr << "Multiplayer button pressed: " << name << " -> load gameplay UI\n"; diff --git a/src/MenuManager.h b/src/MenuManager.h index 7ad6d87..18b935f 100644 --- a/src/MenuManager.h +++ b/src/MenuManager.h @@ -34,7 +34,7 @@ namespace ZL { std::function onVelocityChanged; std::function onFirePressed; - std::function onSingleplayerPressed; + std::function onSingleplayerPressed; std::function onMultiplayerPressed; }; diff --git a/src/Space.cpp b/src/Space.cpp index f96e170..32a5e9f 100644 --- a/src/Space.cpp +++ b/src/Space.cpp @@ -454,8 +454,14 @@ namespace ZL renderer.TranslateMatrix({ 0, -6.f, 0 }); //Ship camera offset if (shipAlive) { - glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID()); - renderer.DrawVertexRenderStruct(spaceship); + if (Environment::shipState.shipType == 1 && cargoTexture) { + glBindTexture(GL_TEXTURE_2D, cargoTexture->getTexID()); + renderer.DrawVertexRenderStruct(cargo); + } + else { + glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID()); + renderer.DrawVertexRenderStruct(spaceship); + } } renderer.PopMatrix(); glEnable(GL_BLEND); diff --git a/src/network/ClientState.h b/src/network/ClientState.h index 11c868c..c9fb48f 100644 --- a/src/network/ClientState.h +++ b/src/network/ClientState.h @@ -4,6 +4,7 @@ #define _USE_MATH_DEFINES #include #include +#include using std::min; @@ -29,36 +30,37 @@ constexpr long long CUTOFF_TIME = 5000; //ms uint32_t fnv1a_hash(const std::string& data); struct ClientState { - int id = 0; - Eigen::Vector3f position = { 0, 0, 45000.0f }; - Eigen::Matrix3f rotation = Eigen::Matrix3f::Identity(); - Eigen::Vector3f currentAngularVelocity = Eigen::Vector3f::Zero(); - float velocity = 0.0f; - int selectedVelocity = 0; - float discreteMag = 0; - int discreteAngle = -1; + int id = 0; + Eigen::Vector3f position = { 0, 0, 45000.0f }; + Eigen::Matrix3f rotation = Eigen::Matrix3f::Identity(); + Eigen::Vector3f currentAngularVelocity = Eigen::Vector3f::Zero(); + float velocity = 0.0f; + int selectedVelocity = 0; + float discreteMag = 0; + int discreteAngle = -1; - int shipType = 0; - // ??? ??????? ???? - std::chrono::system_clock::time_point lastUpdateServerTime; + std::string nickname = "Player"; + int shipType = 0; + // ??? ??????? ???? + std::chrono::system_clock::time_point lastUpdateServerTime; - void simulate_physics(size_t delta); + void simulate_physics(size_t delta); - void apply_lag_compensation(std::chrono::system_clock::time_point nowTime); + void apply_lag_compensation(std::chrono::system_clock::time_point nowTime); - void handle_full_sync(const std::vector& parts, int startFrom); + void handle_full_sync(const std::vector& parts, int startFrom); - std::string formPingMessageContent(); + std::string formPingMessageContent(); }; struct ClientStateInterval { std::vector timedStates; - void add_state(const ClientState& state); + void add_state(const ClientState& state); - bool canFetchClientStateAtTime(std::chrono::system_clock::time_point targetTime) const; + bool canFetchClientStateAtTime(std::chrono::system_clock::time_point targetTime) const; - ClientState fetchClientStateAtTime(std::chrono::system_clock::time_point targetTime) const; + ClientState fetchClientStateAtTime(std::chrono::system_clock::time_point targetTime) const; };