Adapt for web
This commit is contained in:
parent
7418bbbe27
commit
9f82e7a2e6
@ -115,12 +115,15 @@ set(EMSCRIPTEN_FLAGS
|
|||||||
|
|
||||||
target_compile_options(space-game001 PRIVATE ${EMSCRIPTEN_FLAGS} "-O2")
|
target_compile_options(space-game001 PRIVATE ${EMSCRIPTEN_FLAGS} "-O2")
|
||||||
|
|
||||||
|
# Only loading.png and the shaders used before resources.zip is ready are preloaded.
|
||||||
|
# resources.zip is downloaded asynchronously at runtime and served as a separate file.
|
||||||
set(EMSCRIPTEN_LINK_FLAGS
|
set(EMSCRIPTEN_LINK_FLAGS
|
||||||
${EMSCRIPTEN_FLAGS}
|
${EMSCRIPTEN_FLAGS}
|
||||||
"-O2"
|
"-O2"
|
||||||
"-sPTHREAD_POOL_SIZE=4"
|
"-sPTHREAD_POOL_SIZE=4"
|
||||||
"-sALLOW_MEMORY_GROWTH=1"
|
"-sALLOW_MEMORY_GROWTH=1"
|
||||||
"--preload-file resources.zip"
|
"--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../resources/loading.png@resources/loading.png"
|
||||||
|
"--preload-file ${CMAKE_CURRENT_SOURCE_DIR}/../resources/shaders@resources/shaders"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Применяем настройки линковки
|
# Применяем настройки линковки
|
||||||
@ -170,8 +173,8 @@ install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/space-game001plain.html"
|
|||||||
DESTINATION .
|
DESTINATION .
|
||||||
)
|
)
|
||||||
|
|
||||||
# Если вам все еще нужен сам resources.zip отдельно в папке public:
|
# resources.zip is served separately and downloaded asynchronously at runtime
|
||||||
#install(FILES "${RESOURCES_ZIP}" DESTINATION .)
|
install(FILES "${RESOURCES_ZIP}" DESTINATION .)
|
||||||
|
|
||||||
add_custom_command(TARGET space-game001 POST_BUILD
|
add_custom_command(TARGET space-game001 POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} --install .
|
COMMAND ${CMAKE_COMMAND} --install .
|
||||||
|
|||||||
45
src/Game.cpp
45
src/Game.cpp
@ -23,6 +23,10 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef EMSCRIPTEN
|
||||||
|
#include <emscripten.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "network/LocalClient.h"
|
#include "network/LocalClient.h"
|
||||||
#include "network/ClientState.h"
|
#include "network/ClientState.h"
|
||||||
|
|
||||||
@ -36,6 +40,22 @@ namespace ZL
|
|||||||
const char* CONST_ZIP_FILE = "";
|
const char* CONST_ZIP_FILE = "";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef EMSCRIPTEN
|
||||||
|
Game* Game::s_instance = nullptr;
|
||||||
|
|
||||||
|
void Game::onResourcesZipLoaded(const char* /*filename*/) {
|
||||||
|
if (s_instance) {
|
||||||
|
s_instance->mainThreadHandler.EnqueueMainThreadTask([&]() {
|
||||||
|
s_instance->setupPart2();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Game::onResourcesZipError(const char* /*filename*/) {
|
||||||
|
std::cerr << "Failed to download resources.zip" << std::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Game::Game()
|
Game::Game()
|
||||||
: window(nullptr)
|
: window(nullptr)
|
||||||
, glContext(nullptr)
|
, glContext(nullptr)
|
||||||
@ -53,7 +73,11 @@ namespace ZL
|
|||||||
if (window) {
|
if (window) {
|
||||||
SDL_DestroyWindow(window);
|
SDL_DestroyWindow(window);
|
||||||
}
|
}
|
||||||
|
#ifndef EMSCRIPTEN
|
||||||
|
// In Emscripten, SDL must stay alive across context loss/restore cycles
|
||||||
|
// so the window remains valid when the game object is re-created.
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::setup() {
|
void Game::setup() {
|
||||||
@ -64,21 +88,30 @@ namespace ZL
|
|||||||
renderer.InitOpenGL();
|
renderer.InitOpenGL();
|
||||||
|
|
||||||
#ifdef EMSCRIPTEN
|
#ifdef EMSCRIPTEN
|
||||||
renderer.shaderManager.AddShaderFromFiles("defaultColor", "resources/shaders/defaultColor.vertex", "resources/shaders/defaultColor_web.fragment", CONST_ZIP_FILE);
|
// These shaders and loading.png are preloaded separately (not from zip),
|
||||||
renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_web.fragment", CONST_ZIP_FILE);
|
// so they are available immediately without waiting for resources.zip.
|
||||||
|
renderer.shaderManager.AddShaderFromFiles("defaultColor", "resources/shaders/defaultColor.vertex", "resources/shaders/defaultColor_web.fragment", "");
|
||||||
|
renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_web.fragment", "");
|
||||||
|
loadingTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/loading.png", ""));
|
||||||
#else
|
#else
|
||||||
renderer.shaderManager.AddShaderFromFiles("defaultColor", "resources/shaders/defaultColor.vertex", "resources/shaders/defaultColor_desktop.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("defaultColor", "resources/shaders/defaultColor.vertex", "resources/shaders/defaultColor_desktop.fragment", CONST_ZIP_FILE);
|
||||||
renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_desktop.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_desktop.fragment", CONST_ZIP_FILE);
|
||||||
|
loadingTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/loading.png", CONST_ZIP_FILE));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
loadingTexture = std::make_unique<Texture>(CreateTextureDataFromPng("resources/loading.png", CONST_ZIP_FILE));
|
|
||||||
loadingMesh.data = CreateRect2D({ Environment::width * 0.5, Environment::height * 0.5 }, { Environment::width * 0.5, Environment::height*0.5 }, 3);
|
loadingMesh.data = CreateRect2D({ Environment::width * 0.5, Environment::height * 0.5 }, { Environment::width * 0.5, Environment::height*0.5 }, 3);
|
||||||
loadingMesh.RefreshVBO();
|
loadingMesh.RefreshVBO();
|
||||||
|
|
||||||
|
#ifdef EMSCRIPTEN
|
||||||
|
// Asynchronously download resources.zip; setupPart2() is called on completion.
|
||||||
|
// The loading screen stays visible until the download finishes.
|
||||||
|
s_instance = this;
|
||||||
|
emscripten_async_wget("resources.zip", "resources.zip", onResourcesZipLoaded, onResourcesZipError);
|
||||||
|
#else
|
||||||
mainThreadHandler.EnqueueMainThreadTask([this]() {
|
mainThreadHandler.EnqueueMainThreadTask([this]() {
|
||||||
this->setupPart2();
|
this->setupPart2();
|
||||||
});
|
});
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -322,6 +355,8 @@ namespace ZL
|
|||||||
// Обновляем размеры и сбрасываем кеш текстов, т.к. меши хранятся в пикселях
|
// Обновляем размеры и сбрасываем кеш текстов, т.к. меши хранятся в пикселях
|
||||||
Environment::width = event.window.data1;
|
Environment::width = event.window.data1;
|
||||||
Environment::height = event.window.data2;
|
Environment::height = event.window.data2;
|
||||||
|
std::cout << "Window resized: " << Environment::width << "x" << Environment::height << std::endl;
|
||||||
|
|
||||||
space.clearTextRendererCache();
|
space.clearTextRendererCache();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -54,6 +54,12 @@ namespace ZL {
|
|||||||
void handleUp(int mx, int my);
|
void handleUp(int mx, int my);
|
||||||
void handleMotion(int mx, int my);
|
void handleMotion(int mx, int my);
|
||||||
|
|
||||||
|
#ifdef EMSCRIPTEN
|
||||||
|
static Game* s_instance;
|
||||||
|
static void onResourcesZipLoaded(const char* filename);
|
||||||
|
static void onResourcesZipError(const char* filename);
|
||||||
|
#endif
|
||||||
|
|
||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
SDL_GLContext glContext;
|
SDL_GLContext glContext;
|
||||||
|
|
||||||
|
|||||||
@ -183,8 +183,8 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
uiManager.setButtonCallback("multiplayerButton2", [this](const std::string& name) {
|
uiManager.setButtonCallback("multiplayerButton2", [this, shipSelectionRoot, loadGameplayUI](const std::string& name) {
|
||||||
std::cerr << "Multiplayer button pressed → opening multiplayer menu\n";
|
/*std::cerr << "Multiplayer button pressed → opening multiplayer menu\n";
|
||||||
|
|
||||||
uiManager.startAnimationOnNode("playButton", "buttonsExit");
|
uiManager.startAnimationOnNode("playButton", "buttonsExit");
|
||||||
uiManager.startAnimationOnNode("settingsButton", "buttonsExit");
|
uiManager.startAnimationOnNode("settingsButton", "buttonsExit");
|
||||||
@ -219,6 +219,37 @@ namespace ZL {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::cerr << "Failed to load multiplayer menu\n";
|
std::cerr << "Failed to load multiplayer menu\n";
|
||||||
|
}*/
|
||||||
|
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("exitButton", [](const std::string& name) {
|
uiManager.setButtonCallback("exitButton", [](const std::string& name) {
|
||||||
|
|||||||
@ -616,13 +616,11 @@ namespace ZL
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Space::drawRemoteShips() {
|
void Space::drawRemoteShips() {
|
||||||
// Используем те же константы имен для шейдеров, что и в drawShip
|
|
||||||
static const std::string defaultShaderName = "default";
|
static const std::string defaultShaderName = "default";
|
||||||
static const std::string vPositionName = "vPosition";
|
static const std::string vPositionName = "vPosition";
|
||||||
static const std::string vTexCoordName = "vTexCoord";
|
static const std::string vTexCoordName = "vTexCoord";
|
||||||
static const std::string textureUniformName = "Texture";
|
static const std::string textureUniformName = "Texture";
|
||||||
|
|
||||||
// Активируем шейдер и текстуру (предполагаем, что меш у всех одинаковый)
|
|
||||||
renderer.shaderManager.PushShader(defaultShaderName);
|
renderer.shaderManager.PushShader(defaultShaderName);
|
||||||
renderer.RenderUniform1i(textureUniformName, 0);
|
renderer.RenderUniform1i(textureUniformName, 0);
|
||||||
|
|
||||||
@ -633,10 +631,6 @@ namespace ZL
|
|||||||
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
static_cast<float>(Environment::width) / static_cast<float>(Environment::height),
|
||||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||||
|
|
||||||
// Биндим текстуру корабля один раз для <20>?сех правильных игроков
|
|
||||||
// ?????????: ?????? ???????? ?????????? ?????? ????? ? ??????????? ?? ClientState.shipType
|
|
||||||
|
|
||||||
// Если сервер прислал коробки, применяем их однократно вместо локальной генерации
|
|
||||||
if (!serverBoxesApplied && networkClient) {
|
if (!serverBoxesApplied && networkClient) {
|
||||||
auto sboxes = networkClient->getServerBoxes();
|
auto sboxes = networkClient->getServerBoxes();
|
||||||
auto destroyedFlags = networkClient->getServerBoxDestroyedFlags();
|
auto destroyedFlags = networkClient->getServerBoxDestroyedFlags();
|
||||||
@ -664,7 +658,6 @@ namespace ZL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Итерируемся по актуальным данным из extrapolateRemotePlayers
|
|
||||||
for (auto const& [id, remotePlayer] : remotePlayerStates) {
|
for (auto const& [id, remotePlayer] : remotePlayerStates) {
|
||||||
|
|
||||||
const ClientState& playerState = remotePlayer;
|
const ClientState& playerState = remotePlayer;
|
||||||
@ -674,7 +667,7 @@ namespace ZL
|
|||||||
renderer.LoadIdentity();
|
renderer.LoadIdentity();
|
||||||
|
|
||||||
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom });
|
||||||
renderer.TranslateMatrix({ 0, -6.f, 0 }); //Ship camera offset
|
//renderer.TranslateMatrix({ 0, -6.f, 0 }); //Ship camera offset
|
||||||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
||||||
renderer.TranslateMatrix(-Environment::shipState.position);
|
renderer.TranslateMatrix(-Environment::shipState.position);
|
||||||
|
|
||||||
@ -682,7 +675,6 @@ namespace ZL
|
|||||||
Eigen::Vector3f relativePos = playerState.position;// -Environment::shipPosition;
|
Eigen::Vector3f relativePos = playerState.position;// -Environment::shipPosition;
|
||||||
renderer.TranslateMatrix(relativePos);
|
renderer.TranslateMatrix(relativePos);
|
||||||
|
|
||||||
// 3. Поворот врага
|
|
||||||
renderer.RotateMatrix(playerState.rotation);
|
renderer.RotateMatrix(playerState.rotation);
|
||||||
|
|
||||||
if (playerState.shipType == 1 && cargoTexture) {
|
if (playerState.shipType == 1 && cargoTexture) {
|
||||||
|
|||||||
90
src/main.cpp
90
src/main.cpp
@ -5,15 +5,87 @@
|
|||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef EMSCRIPTEN
|
||||||
|
#include <emscripten.h>
|
||||||
|
#include <emscripten/html5.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// For Emscripten the game is heap-allocated so it can be destroyed and
|
||||||
|
// re-created when the WebGL context is lost and restored (e.g. fullscreen).
|
||||||
|
// For Android and Desktop a plain global value is used (no context loss).
|
||||||
|
#ifdef EMSCRIPTEN
|
||||||
|
ZL::Game* g_game = nullptr;
|
||||||
|
#else
|
||||||
ZL::Game game;
|
ZL::Game game;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void MainLoop() {
|
void MainLoop() {
|
||||||
|
#ifdef EMSCRIPTEN
|
||||||
|
if (g_game) g_game->update();
|
||||||
|
#else
|
||||||
game.update();
|
game.update();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef EMSCRIPTEN
|
||||||
|
|
||||||
|
EM_BOOL onWebGLContextLost(int /*eventType*/, const void* /*reserved*/, void* /*userData*/) {
|
||||||
|
delete g_game;
|
||||||
|
g_game = nullptr;
|
||||||
|
return EM_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EM_BOOL onWebGLContextRestored(int /*eventType*/, const void* /*reserved*/, void* /*userData*/) {
|
||||||
|
g_game = new ZL::Game();
|
||||||
|
g_game->setup();
|
||||||
|
return EM_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resize the canvas, notify SDL, and push a synthetic SDL_WINDOWEVENT_RESIZED
|
||||||
|
// so Game::update()'s existing handler updates Environment::width/height and clears caches.
|
||||||
|
static void applyResize(int w, int h) {
|
||||||
|
if (w <= 0 || h <= 0) return;
|
||||||
|
// Resize the actual WebGL canvas — without this the rendered pixels stay at
|
||||||
|
// the original size no matter what Environment::width/height say.
|
||||||
|
emscripten_set_canvas_element_size("#canvas", w, h);
|
||||||
|
if (ZL::Environment::window)
|
||||||
|
SDL_SetWindowSize(ZL::Environment::window, w, h);
|
||||||
|
SDL_Event e = {};
|
||||||
|
e.type = SDL_WINDOWEVENT;
|
||||||
|
e.window.event = SDL_WINDOWEVENT_RESIZED;
|
||||||
|
e.window.data1 = w;
|
||||||
|
e.window.data2 = h;
|
||||||
|
SDL_PushEvent(&e);
|
||||||
|
}
|
||||||
|
|
||||||
|
EM_BOOL onWindowResized(int /*eventType*/, const EmscriptenUiEvent* e, void* /*userData*/) {
|
||||||
|
// Use the event's window dimensions — querying the canvas element would
|
||||||
|
// return its old fixed size (e.g. 1280x720) before it has been resized.
|
||||||
|
applyResize(e->windowInnerWidth, e->windowInnerHeight);
|
||||||
|
return EM_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
EM_BOOL onFullscreenChanged(int /*eventType*/, const EmscriptenFullscreenChangeEvent* e, void* /*userData*/) {
|
||||||
|
if (e->isFullscreen) {
|
||||||
|
// e->screenWidth/screenHeight comes from screen.width/screen.height in JS,
|
||||||
|
// which on mobile browsers returns physical pixels (e.g. 2340x1080),
|
||||||
|
// causing the canvas to extend far off-screen. window.innerWidth/innerHeight
|
||||||
|
// always gives CSS logical pixels and is correct on both desktop and mobile.
|
||||||
|
int w = EM_ASM_INT({ return window.innerWidth; });
|
||||||
|
int h = EM_ASM_INT({ return window.innerHeight; });
|
||||||
|
applyResize(w, h);
|
||||||
|
}
|
||||||
|
// Exiting fullscreen: the browser fires a window resize event next,
|
||||||
|
// which onWindowResized handles automatically.
|
||||||
|
return EM_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
|
|
||||||
extern "C" int SDL_main(int argc, char* argv[]) {
|
extern "C" int SDL_main(int argc, char* argv[]) {
|
||||||
@ -142,6 +214,20 @@ int main(int argc, char *argv[]) {
|
|||||||
SDL_GL_MakeCurrent(win, glContext);
|
SDL_GL_MakeCurrent(win, glContext);
|
||||||
|
|
||||||
ZL::Environment::window = win;
|
ZL::Environment::window = win;
|
||||||
|
|
||||||
|
g_game = new ZL::Game();
|
||||||
|
g_game->setup();
|
||||||
|
|
||||||
|
// Re-create the game object when the WebGL context is lost and restored
|
||||||
|
// (this happens e.g. when the user toggles fullscreen in the browser).
|
||||||
|
emscripten_set_webglcontextlost_callback("#canvas", nullptr, EM_TRUE, onWebGLContextLost);
|
||||||
|
emscripten_set_webglcontextrestored_callback("#canvas", nullptr, EM_TRUE, onWebGLContextRestored);
|
||||||
|
|
||||||
|
// Keep Environment::width/height in sync when the canvas is resized.
|
||||||
|
emscripten_set_resize_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, nullptr, EM_FALSE, onWindowResized);
|
||||||
|
emscripten_set_fullscreenchange_callback(EMSCRIPTEN_EVENT_TARGET_DOCUMENT, nullptr, EM_FALSE, onFullscreenChanged);
|
||||||
|
|
||||||
|
emscripten_set_main_loop(MainLoop, 0, 1);
|
||||||
#else
|
#else
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
||||||
SDL_Log("SDL init failed: %s", SDL_GetError());
|
SDL_Log("SDL init failed: %s", SDL_GetError());
|
||||||
@ -161,13 +247,9 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
SDL_GLContext ctx = SDL_GL_CreateContext(ZL::Environment::window);
|
SDL_GLContext ctx = SDL_GL_CreateContext(ZL::Environment::window);
|
||||||
SDL_GL_MakeCurrent(ZL::Environment::window, ctx);
|
SDL_GL_MakeCurrent(ZL::Environment::window, ctx);
|
||||||
#endif
|
|
||||||
|
|
||||||
game.setup();
|
game.setup();
|
||||||
|
|
||||||
#ifdef EMSCRIPTEN
|
|
||||||
emscripten_set_main_loop(MainLoop, 0, 1);
|
|
||||||
#else
|
|
||||||
while (!game.shouldExit()) {
|
while (!game.shouldExit()) {
|
||||||
game.update();
|
game.update();
|
||||||
SDL_Delay(2);
|
SDL_Delay(2);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#include "ClientState.h"
|
#include "ClientState.h"
|
||||||
|
|
||||||
uint32_t fnv1a_hash(const std::string& data) {
|
uint32_t fnv1a_hash(const std::string& data) {
|
||||||
uint32_t hash = 0x811c9dc5;
|
uint32_t hash = 0x811c9dc5;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <Eigen/Dense>
|
#include <Eigen/Dense>
|
||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
@ -19,7 +19,7 @@ constexpr float ROTATION_SENSITIVITY = 0.002f;
|
|||||||
|
|
||||||
constexpr float PLANET_RADIUS = 20000.f;
|
constexpr float PLANET_RADIUS = 20000.f;
|
||||||
constexpr float PLANET_ALIGN_ZONE = 1.05f;
|
constexpr float PLANET_ALIGN_ZONE = 1.05f;
|
||||||
constexpr float PLANET_ANGULAR_ACCEL = 0.01f; // ??????? ??? ????????
|
constexpr float PLANET_ANGULAR_ACCEL = 0.01f;
|
||||||
constexpr float PLANET_MAX_ANGULAR_VELOCITY = 10.f;
|
constexpr float PLANET_MAX_ANGULAR_VELOCITY = 10.f;
|
||||||
constexpr float PITCH_LIMIT = static_cast<float>(M_PI) / 9.f;//18.0f;
|
constexpr float PITCH_LIMIT = static_cast<float>(M_PI) / 9.f;//18.0f;
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ struct ClientState {
|
|||||||
|
|
||||||
std::string nickname = "Player";
|
std::string nickname = "Player";
|
||||||
int shipType = 0;
|
int shipType = 0;
|
||||||
// ??? ??????? ????
|
|
||||||
std::chrono::system_clock::time_point lastUpdateServerTime;
|
std::chrono::system_clock::time_point lastUpdateServerTime;
|
||||||
|
|
||||||
void simulate_physics(size_t delta);
|
void simulate_physics(size_t delta);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#include "LocalClient.h"
|
#include "LocalClient.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "NetworkInterface.h"
|
#include "NetworkInterface.h"
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#ifdef NETWORK
|
#ifdef NETWORK
|
||||||
|
|
||||||
#include "WebSocketClient.h"
|
#include "WebSocketClient.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef NETWORK
|
#ifdef NETWORK
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#ifdef NETWORK
|
#ifdef NETWORK
|
||||||
|
|
||||||
#include "WebSocketClientBase.h"
|
#include "WebSocketClientBase.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "NetworkInterface.h"
|
#include "NetworkInterface.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user