329 lines
11 KiB
C++
329 lines
11 KiB
C++
#include "MenuManager.h"
|
|
#include <iostream>
|
|
|
|
#ifdef EMSCRIPTEN
|
|
#include <emscripten.h>
|
|
#include <cstdlib>
|
|
#endif
|
|
|
|
namespace ZL {
|
|
|
|
extern bool inverseVertical;
|
|
|
|
MenuManager::MenuManager(Renderer& iRenderer) :
|
|
renderer(iRenderer)
|
|
{
|
|
}
|
|
|
|
void MenuManager::setupMenu()
|
|
{
|
|
mainMenuRoot = loadUiFromFile("resources/config/main_menu.json", renderer, CONST_ZIP_FILE);
|
|
shipSelectionRoot = loadUiFromFile("resources/config/ship_selection_menu.json", renderer, CONST_ZIP_FILE);
|
|
connectingRoot = loadUiFromFile("resources/config/connecting.json", renderer, CONST_ZIP_FILE);
|
|
connectionFailedRoot= loadUiFromFile("resources/config/connection_failed.json", renderer, CONST_ZIP_FILE);
|
|
gameplayRoot = loadUiFromFile("resources/config/ui.json", renderer, CONST_ZIP_FILE);
|
|
gameOverRoot = loadUiFromFile("resources/config/game_over.json", renderer, CONST_ZIP_FILE);
|
|
connectionLostRoot = loadUiFromFile("resources/config/connection_lost.json", renderer, CONST_ZIP_FILE);
|
|
|
|
enterMainMenu();
|
|
}
|
|
|
|
bool MenuManager::shouldRenderSpace() const
|
|
{
|
|
return state == GameState::Gameplay
|
|
|| state == GameState::GameOver
|
|
|| state == GameState::ConnectionLost;
|
|
}
|
|
|
|
// ── State: MainMenu ──────────────────────────────────────────────────────
|
|
|
|
void MenuManager::enterMainMenu()
|
|
{
|
|
state = GameState::MainMenu;
|
|
uiManager.replaceRoot(mainMenuRoot);
|
|
|
|
if (onMainMenuEntered) onMainMenuEntered();
|
|
|
|
uiManager.setButtonCallback("singleButton", [this](const std::string&) {
|
|
enterShipSelectionSingle();
|
|
});
|
|
|
|
uiManager.setButtonCallback("multiplayerButton", [this](const std::string&) {
|
|
enterShipSelectionMulti();
|
|
});
|
|
}
|
|
|
|
// ── State: ShipSelectionSingle ───────────────────────────────────────────
|
|
|
|
void MenuManager::enterShipSelectionSingle()
|
|
{
|
|
state = GameState::ShipSelectionSingle;
|
|
uiManager.replaceRoot(shipSelectionRoot);
|
|
|
|
std::string initialNick;
|
|
#ifdef EMSCRIPTEN
|
|
char* savedNickC = emscripten_run_script_string("localStorage.getItem('spacegame_nick') || ''");
|
|
if (savedNickC) {
|
|
initialNick = savedNickC;
|
|
free(savedNickC);
|
|
}
|
|
#endif
|
|
|
|
auto tf = uiManager.findTextField("nicknameInput");
|
|
if (tf) {
|
|
if (!initialNick.empty()) tf->text = initialNick;
|
|
|
|
#ifdef EMSCRIPTEN
|
|
uiManager.setTextFieldCallback("nicknameInput", [](const std::string&, const std::string& value) {
|
|
EM_ASM_({
|
|
try { localStorage.setItem('spacegame_nick', UTF8ToString($0)); } catch(e) {}
|
|
}, value.c_str());
|
|
});
|
|
#endif
|
|
}
|
|
|
|
uiManager.setButtonCallback("spaceshipButton", [this, initialNick](const std::string&) {
|
|
std::string nick = uiManager.getTextFieldValue("nicknameInput");
|
|
if (nick.empty()) nick = initialNick;
|
|
if (nick.empty()) nick = "Player";
|
|
enterGameplay();
|
|
if (onSingleplayerPressed) onSingleplayerPressed(nick, 0);
|
|
});
|
|
|
|
uiManager.setButtonCallback("cargoshipButton", [this, initialNick](const std::string&) {
|
|
std::string nick = uiManager.getTextFieldValue("nicknameInput");
|
|
if (nick.empty()) nick = initialNick;
|
|
if (nick.empty()) nick = "Player";
|
|
enterGameplay();
|
|
if (onSingleplayerPressed) onSingleplayerPressed(nick, 1);
|
|
});
|
|
|
|
uiManager.setButtonCallback("backButton", [this](const std::string&) {
|
|
enterMainMenu();
|
|
});
|
|
}
|
|
|
|
// ── State: ShipSelectionMulti ─────────────────────────────────────────────
|
|
|
|
void MenuManager::enterShipSelectionMulti()
|
|
{
|
|
state = GameState::ShipSelectionMulti;
|
|
uiManager.replaceRoot(shipSelectionRoot);
|
|
|
|
std::string initialNick;
|
|
#ifdef EMSCRIPTEN
|
|
char* savedNickC = emscripten_run_script_string("localStorage.getItem('spacegame_nick') || ''");
|
|
if (savedNickC) {
|
|
initialNick = savedNickC;
|
|
free(savedNickC);
|
|
}
|
|
#endif
|
|
|
|
auto tf = uiManager.findTextField("nicknameInput");
|
|
if (tf) {
|
|
if (!initialNick.empty()) tf->text = initialNick;
|
|
|
|
#ifdef EMSCRIPTEN
|
|
uiManager.setTextFieldCallback("nicknameInput", [](const std::string&, const std::string& value) {
|
|
EM_ASM_({
|
|
try { localStorage.setItem('spacegame_nick', UTF8ToString($0)); } catch(e) {}
|
|
}, value.c_str());
|
|
});
|
|
#endif
|
|
}
|
|
|
|
uiManager.setButtonCallback("spaceshipButton", [this, initialNick](const std::string&) {
|
|
std::string nick = uiManager.getTextFieldValue("nicknameInput");
|
|
if (nick.empty()) nick = initialNick;
|
|
if (nick.empty()) nick = "Player";
|
|
pendingMultiNick = nick;
|
|
pendingMultiShipType = 0;
|
|
enterConnecting();
|
|
if (onMultiplayerPressed) onMultiplayerPressed(nick, 0);
|
|
});
|
|
|
|
uiManager.setButtonCallback("cargoshipButton", [this, initialNick](const std::string&) {
|
|
std::string nick = uiManager.getTextFieldValue("nicknameInput");
|
|
if (nick.empty()) nick = initialNick;
|
|
if (nick.empty()) nick = "Player";
|
|
pendingMultiNick = nick;
|
|
pendingMultiShipType = 1;
|
|
enterConnecting();
|
|
if (onMultiplayerPressed) onMultiplayerPressed(nick, 1);
|
|
});
|
|
|
|
uiManager.setButtonCallback("backButton", [this](const std::string&) {
|
|
enterMainMenu();
|
|
});
|
|
}
|
|
|
|
// ── State: Connecting ────────────────────────────────────────────────────
|
|
|
|
void MenuManager::enterConnecting()
|
|
{
|
|
state = GameState::Connecting;
|
|
uiManager.replaceRoot(connectingRoot);
|
|
// No interactive elements — just a static "Connecting..." image
|
|
}
|
|
|
|
// ── State: ConnectionFailed ───────────────────────────────────────────────
|
|
|
|
void MenuManager::enterConnectionFailed()
|
|
{
|
|
state = GameState::ConnectionFailed;
|
|
uiManager.replaceRoot(connectionFailedRoot);
|
|
|
|
uiManager.setButtonCallback("connectionFailedReconnectButton", [this](const std::string&) {
|
|
enterConnecting();
|
|
if (onMultiplayerPressed) onMultiplayerPressed(pendingMultiNick, pendingMultiShipType);
|
|
});
|
|
|
|
uiManager.setButtonCallback("connectionFailedGoBack", [this](const std::string&) {
|
|
enterMainMenu();
|
|
});
|
|
}
|
|
|
|
// ── State: Gameplay ──────────────────────────────────────────────────────
|
|
|
|
void MenuManager::enterGameplay()
|
|
{
|
|
state = GameState::Gameplay;
|
|
uiManager.replaceRoot(gameplayRoot);
|
|
|
|
uiManager.findButton("minusButton")->state = ButtonState::Disabled;
|
|
if (auto btn = uiManager.findButton("takeButton")) btn->state = ButtonState::Disabled;
|
|
|
|
|
|
/*
|
|
auto velocityTv = uiManager.findTextView("velocityText");
|
|
if (velocityTv) {
|
|
velocityTv->rect.x = 10.0f;
|
|
velocityTv->rect.y = static_cast<float>(Environment::height) - velocityTv->rect.h - 10.0f;
|
|
}*/
|
|
|
|
uiManager.setButtonPressCallback("shootButton", [this](const std::string&) {
|
|
if (onFirePressed) onFirePressed();
|
|
});
|
|
uiManager.setButtonPressCallback("shootButton2", [this](const std::string&) {
|
|
if (onFirePressed) onFirePressed();
|
|
});
|
|
uiManager.setButtonPressCallback("plusButton", [this](const std::string&) {
|
|
int newVel = Environment::shipState.selectedVelocity + 1;
|
|
if (newVel > 4) newVel = 4;
|
|
uiManager.findButton("minusButton")->state = ButtonState::Normal;
|
|
if (newVel == 4)
|
|
{
|
|
uiManager.findButton("plusButton")->state = ButtonState::Disabled;
|
|
}
|
|
else
|
|
{
|
|
uiManager.findButton("plusButton")->state = ButtonState::Normal;
|
|
}
|
|
if (onVelocityChanged) onVelocityChanged(newVel);
|
|
});
|
|
uiManager.setButtonPressCallback("minusButton", [this](const std::string&) {
|
|
int newVel = Environment::shipState.selectedVelocity - 1;
|
|
if (newVel < 0) newVel = 0;
|
|
uiManager.findButton("plusButton")->state = ButtonState::Normal;
|
|
if (newVel == 0)
|
|
{
|
|
uiManager.findButton("minusButton")->state = ButtonState::Disabled;
|
|
}
|
|
else
|
|
{
|
|
uiManager.findButton("minusButton")->state = ButtonState::Normal;
|
|
}
|
|
if (onVelocityChanged) onVelocityChanged(newVel);
|
|
});
|
|
|
|
uiManager.setButtonPressCallback("takeButton", [this](const std::string&) {
|
|
if (onTakeButtonPressed) onTakeButtonPressed();
|
|
});
|
|
|
|
uiManager.setButtonCallback("showPlayersButton", [this](const std::string&) {
|
|
if (onShowPlayersPressed) onShowPlayersPressed();
|
|
});
|
|
|
|
//inverseMouseButton
|
|
|
|
uiManager.setButtonPressCallback("inverseMouseButton", [this](const std::string&) {
|
|
inverseVertical = !inverseVertical;
|
|
std::cout << "Inverse mouse: " << (inverseVertical ? "ON" : "OFF") << std::endl;
|
|
});
|
|
|
|
|
|
|
|
/*
|
|
uiManager.setSliderCallback("velocitySlider", [this](const std::string&, float value) {
|
|
int newVel = static_cast<int>(roundf(value * 10));
|
|
if (newVel > 2) newVel = 2;
|
|
if (newVel != Environment::shipState.selectedVelocity) {
|
|
if (onVelocityChanged) onVelocityChanged(newVel);
|
|
}
|
|
});*/
|
|
}
|
|
|
|
// ── State: GameOver ──────────────────────────────────────────────────────
|
|
|
|
void MenuManager::enterGameOver(int score)
|
|
{
|
|
state = GameState::GameOver;
|
|
uiManager.replaceRoot(gameOverRoot);
|
|
|
|
uiManager.setText("scoreText", "Score: " + std::to_string(score));
|
|
|
|
uiManager.setButtonCallback("restartButton", [this](const std::string&) {
|
|
if (onRestartPressed) onRestartPressed();
|
|
enterGameplay();
|
|
});
|
|
uiManager.setButtonCallback("gameOverExitButton", [this](const std::string&) {
|
|
enterMainMenu();
|
|
});
|
|
}
|
|
|
|
// ── State: ConnectionLost ─────────────────────────────────────────────────
|
|
|
|
void MenuManager::enterConnectionLost()
|
|
{
|
|
state = GameState::ConnectionLost;
|
|
uiManager.replaceRoot(connectionLostRoot);
|
|
|
|
uiManager.setButtonCallback("reconnectButton", [this](const std::string&) {
|
|
// TODO: reconnect logic
|
|
});
|
|
uiManager.setButtonCallback("exitServerButton", [this](const std::string&) {
|
|
enterMainMenu();
|
|
});
|
|
}
|
|
|
|
// ── Public event API ──────────────────────────────────────────────────────
|
|
|
|
void MenuManager::notifyConnected()
|
|
{
|
|
if (state == GameState::Connecting) {
|
|
enterGameplay();
|
|
}
|
|
}
|
|
|
|
void MenuManager::notifyConnectionFailed()
|
|
{
|
|
if (state == GameState::Connecting) {
|
|
enterConnectionFailed();
|
|
}
|
|
}
|
|
|
|
void MenuManager::showGameOver(int score)
|
|
{
|
|
if (state == GameState::Gameplay) {
|
|
enterGameOver(score);
|
|
}
|
|
}
|
|
|
|
void MenuManager::showConnectionLost()
|
|
{
|
|
if (state == GameState::Gameplay) {
|
|
enterConnectionLost();
|
|
}
|
|
}
|
|
|
|
} // namespace ZL
|