Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e7c050c68 | ||
|
|
c88784a669 | ||
|
|
181132e092 | ||
|
|
6fe10eacfc | ||
|
|
9e692c9ec3 |
@ -323,7 +323,7 @@ set(_have_freetype TRUE)
|
||||
foreach(cfg IN LISTS BUILD_CONFIGS)
|
||||
if(NOT EXISTS "${FREETYPE_BASE_DIR}-${cfg}/lib/freetype.lib" AND
|
||||
NOT EXISTS "${FREETYPE_BASE_DIR}-${cfg}/lib/freetyped.lib")
|
||||
#set(_have_freetype FALSE)
|
||||
set(_have_freetype FALSE)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
@ -391,7 +391,7 @@ foreach(cand
|
||||
endforeach()
|
||||
|
||||
if(_ft_debug_lib STREQUAL "" OR _ft_release_lib STREQUAL "")
|
||||
# message(FATAL_ERROR "FreeType libs not found in ${FREETYPE_BASE_DIR}-Debug/Release")
|
||||
message(FATAL_ERROR "FreeType libs not found in ${FREETYPE_BASE_DIR}-Debug/Release")
|
||||
endif()
|
||||
|
||||
add_library(freetype_external_lib UNKNOWN IMPORTED GLOBAL)
|
||||
@ -441,7 +441,7 @@ if(NOT _have_sdl2ttf)
|
||||
endforeach()
|
||||
|
||||
if(_FT_LIB STREQUAL "")
|
||||
# message(FATAL_ERROR "FreeType library not found for ${cfg}")
|
||||
message(FATAL_ERROR "FreeType library not found for ${cfg}")
|
||||
endif()
|
||||
|
||||
log("Configuring SDL_ttf (${cfg}) ...")
|
||||
@ -462,7 +462,7 @@ if(NOT _have_sdl2ttf)
|
||||
RESULT_VARIABLE _ttf_cfg_res
|
||||
)
|
||||
if(NOT _ttf_cfg_res EQUAL 0)
|
||||
#message(FATAL_ERROR "SDL_ttf configure failed for ${cfg}")
|
||||
message(FATAL_ERROR "SDL_ttf configure failed for ${cfg}")
|
||||
endif()
|
||||
|
||||
log("Building SDL_ttf (${cfg}) ...")
|
||||
@ -472,7 +472,7 @@ if(NOT _have_sdl2ttf)
|
||||
RESULT_VARIABLE _ttf_build_res
|
||||
)
|
||||
if(NOT _ttf_build_res EQUAL 0)
|
||||
#message(FATAL_ERROR "SDL_ttf build failed for ${cfg}")
|
||||
message(FATAL_ERROR "SDL_ttf build failed for ${cfg}")
|
||||
endif()
|
||||
|
||||
log("Installing SDL_ttf (${cfg}) ...")
|
||||
@ -482,7 +482,7 @@ if(NOT _have_sdl2ttf)
|
||||
RESULT_VARIABLE _ttf_inst_res
|
||||
)
|
||||
if(NOT _ttf_inst_res EQUAL 0)
|
||||
#message(FATAL_ERROR "SDL_ttf install failed for ${cfg}")
|
||||
message(FATAL_ERROR "SDL_ttf install failed for ${cfg}")
|
||||
endif()
|
||||
|
||||
endforeach()
|
||||
@ -510,7 +510,7 @@ foreach(cand
|
||||
endforeach()
|
||||
|
||||
if(_ttf_debug_lib STREQUAL "" OR _ttf_release_lib STREQUAL "")
|
||||
# message(FATAL_ERROR "SDL_ttf libs not found in install-Debug / install-Release")
|
||||
message(FATAL_ERROR "SDL_ttf libs not found in install-Debug / install-Release")
|
||||
endif()
|
||||
|
||||
add_library(SDL2_ttf_external_lib UNKNOWN IMPORTED GLOBAL)
|
||||
@ -546,4 +546,4 @@ if(NOT TARGET boost_external_lib)
|
||||
add_library(boost_external_lib INTERFACE)
|
||||
# Boost заголовки находятся непосредственно в корне распакованной папки
|
||||
target_include_directories(boost_external_lib INTERFACE "${BOOST_SRC_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
@ -30,13 +30,52 @@
|
||||
border-radius: 5px;
|
||||
}
|
||||
#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>
|
||||
</head>
|
||||
<body>
|
||||
<button id="fs-button">Fullscreen</button>
|
||||
<div id="status">Downloading...</div>
|
||||
<canvas id="canvas" oncontextmenu="event.preventDefault()" tabindex="-1"></canvas>
|
||||
|
||||
<!--
|
||||
<script>
|
||||
var statusElement = document.getElementById("status");
|
||||
var canvas = document.getElementById("canvas");
|
||||
@ -66,6 +105,112 @@
|
||||
});
|
||||
|
||||
</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>
|
||||
</html>
|
||||
@ -41,6 +41,22 @@
|
||||
"disabled": "resources/button_players.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "inverseMouseButton",
|
||||
"x": 0,
|
||||
"y": 100,
|
||||
"width": 150,
|
||||
"height": 150,
|
||||
"horizontal_gravity": "right",
|
||||
"vertical_gravity": "top",
|
||||
"textures": {
|
||||
"normal": "resources/fire.png",
|
||||
"hover": "resources/fire.png",
|
||||
"pressed": "resources/fire2.png",
|
||||
"disabled": "resources/fire.png"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Button",
|
||||
"name": "shootButton",
|
||||
|
||||
@ -46,4 +46,4 @@ if(WIN32)
|
||||
endif()
|
||||
|
||||
# Дополнительный макрос, чтобы Asio знал, что мы работаем без устаревших функций
|
||||
target_compile_definitions(Server PRIVATE BOOST_ASIO_NO_DEPRECATED)
|
||||
target_compile_definitions(Server PRIVATE BOOST_ASIO_NO_DEPRECATED)
|
||||
@ -125,8 +125,6 @@ void Session::sendBoxesToClient() {
|
||||
|
||||
void Session::init()
|
||||
{
|
||||
sendBoxesToClient();
|
||||
|
||||
auto timer = std::make_shared<net::steady_timer>(ws_.get_executor());
|
||||
timer->expires_after(std::chrono::milliseconds(100));
|
||||
timer->async_wait([self = shared_from_this(), timer](const boost::system::error_code& ec) {
|
||||
@ -135,6 +133,8 @@ void Session::init()
|
||||
uint64_t now_ms = static_cast<uint64_t>(
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(now_tp.time_since_epoch()).count());
|
||||
|
||||
self->sendBoxesToClient();
|
||||
|
||||
self->send_message("ID:" + std::to_string(self->id_) + ":" + std::to_string(now_ms));
|
||||
self->do_read();
|
||||
}
|
||||
@ -938,14 +938,14 @@ void Server::accept()
|
||||
int main() {
|
||||
try {
|
||||
net::io_context ioc;
|
||||
tcp::acceptor acceptor{ ioc, {tcp::v4(), 8010} };
|
||||
tcp::acceptor acceptor{ ioc, {tcp::v4(), 8081} };
|
||||
|
||||
Server server(acceptor, ioc);
|
||||
|
||||
server.init();
|
||||
server.accept();
|
||||
|
||||
std::cout << "Server started on port 8010...\n";
|
||||
std::cout << "Server started on port 8081...\n";
|
||||
|
||||
server.update_world();
|
||||
ioc.run();
|
||||
@ -954,4 +954,4 @@ int main() {
|
||||
std::cerr << "Error: " << e.what() << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,15 @@
|
||||
#include "MenuManager.h"
|
||||
#include <iostream>
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
#include <emscripten.h>
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
namespace ZL {
|
||||
|
||||
extern bool inverseVertical;
|
||||
|
||||
MenuManager::MenuManager(Renderer& iRenderer) :
|
||||
renderer(iRenderer)
|
||||
{
|
||||
@ -53,15 +60,39 @@ namespace ZL {
|
||||
state = GameState::ShipSelectionSingle;
|
||||
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");
|
||||
if (nick.empty()) nick = initialNick;
|
||||
if (nick.empty()) nick = "Player";
|
||||
enterGameplay();
|
||||
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");
|
||||
if (nick.empty()) nick = initialNick;
|
||||
if (nick.empty()) nick = "Player";
|
||||
enterGameplay();
|
||||
if (onSingleplayerPressed) onSingleplayerPressed(nick, 1);
|
||||
@ -79,8 +110,31 @@ namespace ZL {
|
||||
state = GameState::ShipSelectionMulti;
|
||||
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");
|
||||
if (nick.empty()) nick = initialNick;
|
||||
if (nick.empty()) nick = "Player";
|
||||
pendingMultiNick = nick;
|
||||
pendingMultiShipType = 0;
|
||||
@ -88,8 +142,9 @@ namespace ZL {
|
||||
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");
|
||||
if (nick.empty()) nick = initialNick;
|
||||
if (nick.empty()) nick = "Player";
|
||||
pendingMultiNick = nick;
|
||||
pendingMultiShipType = 1;
|
||||
@ -189,6 +244,14 @@ namespace ZL {
|
||||
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) {
|
||||
|
||||
@ -36,6 +36,8 @@ namespace ZL
|
||||
extern float y;
|
||||
extern float z;
|
||||
|
||||
bool inverseVertical = true;
|
||||
|
||||
Eigen::Quaternionf generateRandomQuaternion(std::mt19937& gen)
|
||||
{
|
||||
|
||||
@ -2079,11 +2081,22 @@ namespace ZL
|
||||
|
||||
Environment::tapDownHold = true;
|
||||
|
||||
Environment::tapDownStartPos(0) = mx;
|
||||
Environment::tapDownStartPos(1) = my;
|
||||
if (inverseVertical)
|
||||
{
|
||||
Environment::tapDownStartPos(0) = mx;
|
||||
Environment::tapDownStartPos(1) = my;
|
||||
|
||||
Environment::tapDownCurrentPos(0) = mx;
|
||||
Environment::tapDownCurrentPos(1) = my;
|
||||
Environment::tapDownCurrentPos(0) = mx;
|
||||
Environment::tapDownCurrentPos(1) = my;
|
||||
}
|
||||
else
|
||||
{
|
||||
Environment::tapDownStartPos(0) = mx;
|
||||
Environment::tapDownStartPos(1) = -my;
|
||||
|
||||
Environment::tapDownCurrentPos(0) = mx;
|
||||
Environment::tapDownCurrentPos(1) = -my;
|
||||
}
|
||||
}
|
||||
|
||||
void Space::handleUp(int mx, int my)
|
||||
@ -2096,9 +2109,20 @@ namespace ZL
|
||||
{
|
||||
if (playerListVisible) return;
|
||||
|
||||
if (Environment::tapDownHold) {
|
||||
Environment::tapDownCurrentPos(0) = mx;
|
||||
Environment::tapDownCurrentPos(1) = my;
|
||||
|
||||
if (inverseVertical)
|
||||
{
|
||||
if (Environment::tapDownHold) {
|
||||
Environment::tapDownCurrentPos(0) = mx;
|
||||
Environment::tapDownCurrentPos(1) = my;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Environment::tapDownHold) {
|
||||
Environment::tapDownCurrentPos(0) = mx;
|
||||
Environment::tapDownCurrentPos(1) = -my;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ namespace ZL {
|
||||
// Формируем URL. Обратите внимание, что в Web часто лучше использовать ws://localhost
|
||||
//std::string url = "ws://" + host + ":" + std::to_string(port);
|
||||
std::string url = "wss://api.spacegame.fishrungames.com";
|
||||
|
||||
//std::string url = "ws://localhost:8081";
|
||||
EmscriptenWebSocketCreateAttributes attr = {
|
||||
url.c_str(),
|
||||
nullptr,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user