added enter nicknamw

This commit is contained in:
Vlad 2026-03-10 14:25:00 +06:00
parent 59b5bea540
commit 9e692c9ec3
3 changed files with 206 additions and 8 deletions

View File

@ -18,12 +18,51 @@
border: none; border: none;
} }
#status { color: white; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } #status { color: white; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
/* Nick modal */
#nickOverlay {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(0,0,0,0.85);
z-index: 9999;
}
#nickBox {
background: #111;
border: 1px solid #444;
padding: 24px;
width: 320px;
box-shadow: 0 8px 24px rgba(0,0,0,0.6);
text-align: center;
}
#nickBox h2 { margin: 0 0 12px 0; font-size: 18px; color: #eee; }
#nickBox input[type="text"] {
width: 100%;
padding: 10px;
font-size: 16px;
box-sizing: border-box;
margin-bottom: 12px;
border: 1px solid #333;
background: #000;
color: #fff;
}
#nickBox button {
padding: 10px 16px;
font-size: 16px;
background: #2a9fd6;
border: none;
color: #fff;
cursor: pointer;
}
#nickSkip { margin-left: 8px; background: #666; }
</style> </style>
</head> </head>
<body> <body>
<div id="status">Downloading...</div> <div id="status">Downloading...</div>
<canvas id="canvas" oncontextmenu="event.preventDefault()" tabindex="-1"></canvas> <canvas id="canvas" oncontextmenu="event.preventDefault()" tabindex="-1"></canvas>
<!--
<script> <script>
var statusElement = document.getElementById("status"); var statusElement = document.getElementById("status");
var canvas = document.getElementById("canvas"); var canvas = document.getElementById("canvas");
@ -47,6 +86,112 @@
}); });
</script> </script>
<script async src="space-game001.js"></script> <script async src="space-game001.js"></script>-->
<div id="nickOverlay" style="display:none;">
<div id="nickBox">
<h2>Enter your nickname</h2>
<input id="nickInput" type="text" maxlength="32" placeholder="Player" />
<div>
<button id="nickSubmit">Start</button>
</div>
</div>
</div>
<script>
// Utility: подготовить глобальный Module до загрузки Emscripten-скрипта
function prepareModuleEnvironment() {
window.Module = window.Module || {};
var canvasEl = document.getElementById('canvas');
// Устанавливаем canvas для Emscripten, чтобы createContext не падал
window.Module.canvas = canvasEl;
// Подготовим заглушку setStatus, если ещё нет
window.Module.setStatus = window.Module.setStatus || function (text) {
var statusElement = document.getElementById("status");
statusElement.innerHTML = text;
statusElement.style.display = text ? 'block' : 'none';
};
}
// Show overlay only if no nickname saved.
function loadGameScript() {
var s = document.createElement('script');
s.src = 'space-game001.js';
s.async = true;
document.body.appendChild(s);
}
function showNickOverlay() {
var overlay = document.getElementById('nickOverlay');
overlay.style.display = 'flex';
var input = document.getElementById('nickInput');
input.focus();
}
function hideNickOverlay() {
var overlay = document.getElementById('nickOverlay');
overlay.style.display = 'none';
}
function saveNickAndStart(nick) {
try {
if (!nick || nick.trim() === '') nick = 'Player';
localStorage.setItem('spacegame_nick', nick);
} catch (e) {
console.warn('localStorage not available', e);
}
hideNickOverlay();
// перед загрузкой скрипта гарантируем, что Module.canvas задан
prepareModuleEnvironment();
loadGameScript();
}
document.addEventListener('DOMContentLoaded', function() {
// Готовим Module сразу — даже если откроется модалка, поле canvas будет доступно для скрипта (если он загружается позже)
prepareModuleEnvironment();
var stored = null;
try {
stored = localStorage.getItem('spacegame_nick');
} catch (e) {
console.warn('localStorage not available', e);
}
if (stored && stored.trim() !== '') {
// Nick is present — start immediately
loadGameScript();
} else {
// Show modal to request nickname before loading WASM
showNickOverlay();
var submit = document.getElementById('nickSubmit');
var skip = document.getElementById('nickSkip');
var input = document.getElementById('nickInput');
submit.addEventListener('click', function() {
saveNickAndStart(input.value);
});
skip.addEventListener('click', function() {
saveNickAndStart('Player');
});
input.addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
saveNickAndStart(input.value);
}
});
}
});
window.addEventListener("orientationchange", function() {
// Chrome на Android обновляет innerWidth/Height не мгновенно.
// Ждем завершения анимации поворота.
setTimeout(() => {
// В Emscripten это вызовет ваш onWindowResized в C++
window.dispatchEvent(new Event('resize'));
}, 200);
});
</script>
</body> </body>
</html> </html>

View File

@ -1,6 +1,11 @@
#include "MenuManager.h" #include "MenuManager.h"
#include <iostream> #include <iostream>
#ifdef EMSCRIPTEN
#include <emscripten.h>
#include <cstdlib>
#endif
namespace ZL { namespace ZL {
MenuManager::MenuManager(Renderer& iRenderer) : MenuManager::MenuManager(Renderer& iRenderer) :
@ -53,15 +58,39 @@ namespace ZL {
state = GameState::ShipSelectionSingle; state = GameState::ShipSelectionSingle;
uiManager.replaceRoot(shipSelectionRoot); uiManager.replaceRoot(shipSelectionRoot);
uiManager.setButtonCallback("spaceshipButton", [this](const std::string&) { 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"); std::string nick = uiManager.getTextFieldValue("nicknameInput");
if (nick.empty()) nick = initialNick;
if (nick.empty()) nick = "Player"; if (nick.empty()) nick = "Player";
enterGameplay(); enterGameplay();
if (onSingleplayerPressed) onSingleplayerPressed(nick, 0); if (onSingleplayerPressed) onSingleplayerPressed(nick, 0);
}); });
uiManager.setButtonCallback("cargoshipButton", [this](const std::string&) { uiManager.setButtonCallback("cargoshipButton", [this, initialNick](const std::string&) {
std::string nick = uiManager.getTextFieldValue("nicknameInput"); std::string nick = uiManager.getTextFieldValue("nicknameInput");
if (nick.empty()) nick = initialNick;
if (nick.empty()) nick = "Player"; if (nick.empty()) nick = "Player";
enterGameplay(); enterGameplay();
if (onSingleplayerPressed) onSingleplayerPressed(nick, 1); if (onSingleplayerPressed) onSingleplayerPressed(nick, 1);
@ -79,8 +108,31 @@ namespace ZL {
state = GameState::ShipSelectionMulti; state = GameState::ShipSelectionMulti;
uiManager.replaceRoot(shipSelectionRoot); uiManager.replaceRoot(shipSelectionRoot);
uiManager.setButtonCallback("spaceshipButton", [this](const std::string&) { 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"); std::string nick = uiManager.getTextFieldValue("nicknameInput");
if (nick.empty()) nick = initialNick;
if (nick.empty()) nick = "Player"; if (nick.empty()) nick = "Player";
pendingMultiNick = nick; pendingMultiNick = nick;
pendingMultiShipType = 0; pendingMultiShipType = 0;
@ -88,8 +140,9 @@ namespace ZL {
if (onMultiplayerPressed) onMultiplayerPressed(nick, 0); if (onMultiplayerPressed) onMultiplayerPressed(nick, 0);
}); });
uiManager.setButtonCallback("cargoshipButton", [this](const std::string&) { uiManager.setButtonCallback("cargoshipButton", [this, initialNick](const std::string&) {
std::string nick = uiManager.getTextFieldValue("nicknameInput"); std::string nick = uiManager.getTextFieldValue("nicknameInput");
if (nick.empty()) nick = initialNick;
if (nick.empty()) nick = "Player"; if (nick.empty()) nick = "Player";
pendingMultiNick = nick; pendingMultiNick = nick;
pendingMultiShipType = 1; pendingMultiShipType = 1;

View File

@ -8,8 +8,8 @@ namespace ZL {
void WebSocketClientEmscripten::Connect(const std::string& host, uint16_t port) { void WebSocketClientEmscripten::Connect(const std::string& host, uint16_t port) {
// Формируем URL. Обратите внимание, что в Web часто лучше использовать ws://localhost // Формируем URL. Обратите внимание, что в Web часто лучше использовать ws://localhost
//std::string url = "ws://" + host + ":" + std::to_string(port); //std::string url = "ws://" + host + ":" + std::to_string(port);
std::string url = "wss://api.spacegame.fishrungames.com"; //std::string url = "wss://api.spacegame.fishrungames.com";
std::string url = "ws://localhost:8081";
EmscriptenWebSocketCreateAttributes attr = { EmscriptenWebSocketCreateAttributes attr = {
url.c_str(), url.c_str(),
nullptr, nullptr,