diff --git a/proj-web/space-game001plain.html b/proj-web/space-game001plain.html
index 17708db..72892cd 100644
--- a/proj-web/space-game001plain.html
+++ b/proj-web/space-game001plain.html
@@ -1,100 +1,76 @@
-
-
+
+
+
+
+
+ Space Game
+
+
+
+
+ Downloading...
+
-
-
-
- Space Game
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
\ No newline at end of file
diff --git a/resources/Cargo_Base_color_sRGB.png b/resources/Cargo_Base_color_sRGB.png
index 6ec9e8e..58aee2f 100644
--- a/resources/Cargo_Base_color_sRGB.png
+++ b/resources/Cargo_Base_color_sRGB.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:6bd5d071ed94f2bd8ce3ab060136e9b93b04b06d5eabaffc7845a99d73faeb30
-size 2345111
+oid sha256:88a34dad270df316707d8492823653a4c3143ee948f6c3fcdca232fa3f27a184
+size 2577457
diff --git a/resources/DefaultMaterial_BaseColor_shine.png b/resources/DefaultMaterial_BaseColor_shine.png
deleted file mode 100644
index 53e6f41..0000000
--- a/resources/DefaultMaterial_BaseColor_shine.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:26c118a182e269aebfa22684489836d8632b0b2cb6631be646c2678c18493463
-size 90539
diff --git a/resources/MainCharacter_Base_color_sRGB.png b/resources/MainCharacter_Base_color_sRGB.png
index 73d132c..ba3e58c 100644
--- a/resources/MainCharacter_Base_color_sRGB.png
+++ b/resources/MainCharacter_Base_color_sRGB.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:dc8c7262949a4f2f86d2cc47daf572d908294868d89f7577a771149c7e2e60e5
-size 1296067
+oid sha256:6e49da5723497cd4bf152d5f3fd99608f597f2dc3646c05fb478507f36b89697
+size 1669304
diff --git a/resources/game_over/Container.png b/resources/game_over/Container.png
index 226e276..e2af5b9 100644
--- a/resources/game_over/Container.png
+++ b/resources/game_over/Container.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d495f21543ab72e6a2cb5082507212616c666bef11bc99bd0447e6906a957836
-size 6709
+oid sha256:4292ab255136aeeff003e265bfde42bef4aabb092427bd68f9b2ac42d86916a1
+size 27198
diff --git a/resources/game_over/Filledbuttons.png b/resources/game_over/Filledbuttons.png
index 808344f..a9b2806 100644
--- a/resources/game_over/Filledbuttons.png
+++ b/resources/game_over/Filledbuttons.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:f6283a169f71822d3c3f8b3c80369cd3ac25b70ef51d3f34685687b1d2819a1b
-size 2406
+oid sha256:436d9137c479b475d8bc753961986ea3f58b6a2439de6f83b5d707172c3f2ff9
+size 7976
diff --git a/resources/game_over/FinalScore.png b/resources/game_over/FinalScore.png
index 7ac0bbc..af06f07 100644
--- a/resources/game_over/FinalScore.png
+++ b/resources/game_over/FinalScore.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:6bb6e8e59482729d6da84188c830842cf07e4e379076ba64d7916b8b0d45cf09
-size 1244
+oid sha256:ea4e2a8408fa1b68793fd8d81135902ff15ef2779ea898a99a9ef83ff6e147e8
+size 4142
diff --git a/resources/game_over/MissionFailed.png b/resources/game_over/MissionFailed.png
index 1a8731d..ec8d6c3 100644
--- a/resources/game_over/MissionFailed.png
+++ b/resources/game_over/MissionFailed.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:930565f3911bcb11904808fe67ca278c1460f42f7c7c7dcfffc2301f5c0d408c
-size 2678
+oid sha256:c2187818c1fbfb127f70c130f033aa7c16cc3b3a02a2ea59317413437f530c30
+size 9982
diff --git a/resources/game_over/Secondarybutton.png b/resources/game_over/Secondarybutton.png
index 5bb684a..37cdae0 100644
--- a/resources/game_over/Secondarybutton.png
+++ b/resources/game_over/Secondarybutton.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:00a1c3c32da992686febd87918801868d4af2ec99904ed3f80b0c8f58009c5b2
-size 1840
+oid sha256:113c524330190fbdf36f0f7b4ebfc03032170aff5011f8c17201533b52db872f
+size 5387
diff --git a/src/Environment.cpp b/src/Environment.cpp
index 1fec925..9c41b4d 100644
--- a/src/Environment.cpp
+++ b/src/Environment.cpp
@@ -36,5 +36,25 @@ ClientState Environment::shipState;
const float Environment::CONST_Z_NEAR = 5.f;
const float Environment::CONST_Z_FAR = 5000.f;
+float Environment::projectionWidth = 1280.0f;
+float Environment::projectionHeight = 720.0f;
+
+void Environment::computeProjectionDimensions()
+{
+ if (width <= 0 || height <= 0) return;
+
+ const float refShortSide = 720.0f;
+ float aspect = (float)width / (float)height;
+
+ if (width >= height) {
+ // Landscape: fix height to 720, scale width to preserve aspect
+ projectionHeight = refShortSide;
+ projectionWidth = refShortSide * aspect;
+ } else {
+ // Portrait: fix width to 720, scale height to preserve aspect
+ projectionWidth = refShortSide;
+ projectionHeight = refShortSide / aspect;
+ }
+}
} // namespace ZL
diff --git a/src/Environment.h b/src/Environment.h
index 5d3c1ca..17125ac 100644
--- a/src/Environment.h
+++ b/src/Environment.h
@@ -35,8 +35,15 @@ public:
static const float CONST_Z_NEAR;
static const float CONST_Z_FAR;
+ // Virtual projection dimensions used for all 2D/UI rendering.
+ // These maintain the screen's actual aspect ratio but normalize the
+ // height to 720 (landscape) or width to 720 (portrait), giving a
+ // consistent coordinate space regardless of physical screen resolution.
+ static float projectionWidth;
+ static float projectionHeight;
-
+ // Call this once at startup and whenever the window is resized.
+ static void computeProjectionDimensions();
};
} // namespace ZL
diff --git a/src/Game.cpp b/src/Game.cpp
index e653d94..253b475 100644
--- a/src/Game.cpp
+++ b/src/Game.cpp
@@ -83,6 +83,8 @@ namespace ZL
void Game::setup() {
glContext = SDL_GL_CreateContext(ZL::Environment::window);
+ Environment::computeProjectionDimensions();
+
ZL::BindOpenGlFunctions();
ZL::CheckGlError();
renderer.InitOpenGL();
@@ -99,7 +101,7 @@ namespace ZL
loadingTexture = std::make_unique(CreateTextureDataFromPng("resources/loading.png", CONST_ZIP_FILE));
#endif
- loadingMesh.data = CreateRect2D({ Environment::width * 0.5, Environment::height * 0.5 }, { Environment::width * 0.5, Environment::height*0.5 }, 3);
+ loadingMesh.data = CreateRect2D({ Environment::projectionWidth * 0.5f, Environment::projectionHeight * 0.5f }, { Environment::projectionWidth * 0.5f, Environment::projectionHeight * 0.5f }, 3);
loadingMesh.RefreshVBO();
#ifdef EMSCRIPTEN
@@ -141,17 +143,14 @@ namespace ZL
Environment::shipState.nickname = nickname;
Environment::shipState.shipType = shipType;
- networkClient = std::make_unique();
+ auto localClient = new LocalClient;
+ ClientState st = Environment::shipState;
+ st.id = localClient->GetClientId();
+ localClient->setLocalPlayerState(st);
+
+ networkClient = std::unique_ptr(localClient);
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;
};
@@ -160,8 +159,7 @@ namespace ZL
Environment::shipState.nickname = nickname;
Environment::shipState.shipType = shipType;
- networkClient = std::make_unique();
-#ifdef NETWORK
+
#ifdef EMSCRIPTEN
networkClient = std::make_unique();
networkClient->Connect("localhost", 8081);
@@ -169,19 +167,6 @@ namespace ZL
networkClient = std::make_unique(taskManager.getIOContext());
networkClient->Connect("localhost", 8081);
#endif
-#else
- networkClient->Connect("", 0);
-#endif
-
-#ifndef NETWORK
- auto localClient = dynamic_cast(networkClient.get());
- if (localClient) {
- ZL::ClientState st = Environment::shipState;
- st.id = localClient->GetClientId();
- localClient->setLocalPlayerState(st);
- }
-#endif
-
if (networkClient) {
std::string joinMsg = std::string("JOIN:") + nickname + ":" + std::to_string(shipType);
@@ -264,8 +249,8 @@ namespace ZL
renderer.EnableVertexAttribArray(vPositionName);
renderer.EnableVertexAttribArray(vTexCoordName);
- float width = Environment::width;
- float height = Environment::height;
+ float width = Environment::projectionWidth;
+ float height = Environment::projectionHeight;
renderer.PushProjectionMatrix(
0, width,
@@ -350,16 +335,18 @@ namespace ZL
if (event.type == SDL_QUIT) {
Environment::exitGameLoop = true;
}
-#if SDL_VERSION_ATLEAST(2,0,5)
- else if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) {
+
+
+ if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED) {
// Обновляем размеры и сбрасываем кеш текстов, т.к. меши хранятся в пикселях
Environment::width = event.window.data1;
Environment::height = event.window.data2;
- std::cout << "Window resized: " << Environment::width << "x" << Environment::height << std::endl;
+ Environment::computeProjectionDimensions();
+ std::cout << "Window resized: " << Environment::width << "x" << Environment::height << std::endl;
space.clearTextRendererCache();
}
-#endif
+
#ifdef __ANDROID__
if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_AC_BACK) {
Environment::exitGameLoop = true;
@@ -368,22 +355,38 @@ namespace ZL
#ifdef __ANDROID__
if (event.type == SDL_FINGERDOWN) {
- int mx = static_cast(event.tfinger.x * Environment::width);
- int my = static_cast(event.tfinger.y * Environment::height);
+ int mx = static_cast(event.tfinger.x * Environment::projectionWidth);
+ int my = static_cast(event.tfinger.y * Environment::projectionHeight);
handleDown(mx, my);
}
else if (event.type == SDL_FINGERUP) {
- int mx = static_cast(event.tfinger.x * Environment::width);
- int my = static_cast(event.tfinger.y * Environment::height);
+ int mx = static_cast(event.tfinger.x * Environment::projectionWidth);
+ int my = static_cast(event.tfinger.y * Environment::projectionHeight);
handleUp(mx, my);
}
else if (event.type == SDL_FINGERMOTION) {
- int mx = static_cast(event.tfinger.x * Environment::width);
- int my = static_cast(event.tfinger.y * Environment::height);
+ int mx = static_cast(event.tfinger.x * Environment::projectionWidth);
+ int my = static_cast(event.tfinger.y * Environment::projectionHeight);
handleMotion(mx, my);
}
#else
- if (event.type == SDL_MOUSEBUTTONDOWN) {
+
+
+ if (event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) {
+ // Преобразуем экранные пиксели в проекционные единицы
+ int mx = static_cast((float)event.button.x / Environment::width * Environment::projectionWidth);
+ int my = static_cast((float)event.button.y / Environment::height * Environment::projectionHeight);
+
+ if (event.type == SDL_MOUSEBUTTONDOWN) handleDown(mx, my);
+ else handleUp(mx, my);
+ }
+ else if (event.type == SDL_MOUSEMOTION) {
+ int mx = static_cast((float)event.motion.x / Environment::width * Environment::projectionWidth);
+ int my = static_cast((float)event.motion.y / Environment::height * Environment::projectionHeight);
+ handleMotion(mx, my);
+ }
+
+ /*if (event.type == SDL_MOUSEBUTTONDOWN) {
int mx = event.button.x;
int my = event.button.y;
handleDown(mx, my);
@@ -397,7 +400,7 @@ namespace ZL
int mx = event.motion.x;
int my = event.motion.y;
handleMotion(mx, my);
- }
+ }*/
if (event.type == SDL_MOUSEWHEEL) {
static const float zoomstep = 2.0f;
@@ -454,7 +457,7 @@ namespace ZL
void Game::handleDown(int mx, int my)
{
int uiX = mx;
- int uiY = Environment::height - my;
+ int uiY = Environment::projectionHeight - my;
menuManager.uiManager.onMouseDown(uiX, uiY);
@@ -482,7 +485,7 @@ namespace ZL
void Game::handleUp(int mx, int my)
{
int uiX = mx;
- int uiY = Environment::height - my;
+ int uiY = Environment::projectionHeight - my;
menuManager.uiManager.onMouseUp(uiX, uiY);
@@ -497,7 +500,7 @@ namespace ZL
void Game::handleMotion(int mx, int my)
{
int uiX = mx;
- int uiY = Environment::height - my;
+ int uiY = Environment::projectionHeight - my;
menuManager.uiManager.onMouseMove(uiX, uiY);
diff --git a/src/Space.cpp b/src/Space.cpp
index 146d7bc..ba82066 100644
--- a/src/Space.cpp
+++ b/src/Space.cpp
@@ -159,15 +159,15 @@ namespace ZL
// В пределах экрана?
// (можно оставить, можно клампить)
- float sx = (ndc.x() * 0.5f + 0.5f) * Environment::width;
- float sy = (ndc.y() * 0.5f + 0.5f) * Environment::height;
+ float sx = (ndc.x() * 0.5f + 0.5f) * Environment::projectionWidth;
+ float sy = (ndc.y() * 0.5f + 0.5f) * Environment::projectionHeight;
outX = sx;
outY = sy;
// Можно отсеять те, что вне:
- if (sx < -200 || sx > Environment::width + 200) return false;
- if (sy < -200 || sy > Environment::height + 200) return false;
+ if (sx < -200 || sx > Environment::projectionWidth + 200) return false;
+ if (sy < -200 || sy > Environment::projectionHeight + 200) return false;
return true;
}
@@ -296,12 +296,12 @@ namespace ZL
cubemapTexture = std::make_shared(
std::array{
- CreateTextureDataFromPng("resources/sky/space_red.png", CONST_ZIP_FILE),
- CreateTextureDataFromPng("resources/sky/space_red.png", CONST_ZIP_FILE),
- CreateTextureDataFromPng("resources/sky/space_red.png", CONST_ZIP_FILE),
- CreateTextureDataFromPng("resources/sky/space_red.png", CONST_ZIP_FILE),
- CreateTextureDataFromPng("resources/sky/space_red.png", CONST_ZIP_FILE),
- CreateTextureDataFromPng("resources/sky/space_red.png", CONST_ZIP_FILE)
+ CreateTextureDataFromPng("resources/sky/space1.png", CONST_ZIP_FILE),
+ CreateTextureDataFromPng("resources/sky/space1.png", CONST_ZIP_FILE),
+ CreateTextureDataFromPng("resources/sky/space1.png", CONST_ZIP_FILE),
+ CreateTextureDataFromPng("resources/sky/space1.png", CONST_ZIP_FILE),
+ CreateTextureDataFromPng("resources/sky/space1.png", CONST_ZIP_FILE),
+ CreateTextureDataFromPng("resources/sky/space1.png", CONST_ZIP_FILE)
});
@@ -859,8 +859,8 @@ namespace ZL
// если ничего не изменилось — не трогаем VBO
if (crosshairMeshValid &&
- crosshairLastW == Environment::width &&
- crosshairLastH == Environment::height &&
+ crosshairLastW == Environment::projectionWidth &&
+ crosshairLastH == Environment::projectionHeight &&
std::abs(crosshairLastAlpha - crosshairCfg.alpha) < 1e-6f &&
std::abs(crosshairLastThickness - crosshairCfg.thicknessPx) < 1e-6f &&
std::abs(crosshairLastGap - crosshairCfg.gapPx) < 1e-6f &&
@@ -869,18 +869,18 @@ namespace ZL
return;
}
- crosshairLastW = Environment::width;
- crosshairLastH = Environment::height;
+ crosshairLastW = Environment::projectionWidth;
+ crosshairLastH = Environment::projectionHeight;
crosshairLastAlpha = crosshairCfg.alpha;
crosshairLastThickness = crosshairCfg.thicknessPx;
crosshairLastGap = crosshairCfg.gapPx;
crosshairLastScaleMul = crosshairCfg.scaleMul;
- float cx = Environment::width * 0.5f;
- float cy = Environment::height * 0.5f;
+ float cx = Environment::projectionWidth * 0.5f;
+ float cy = Environment::projectionHeight * 0.5f;
// масштаб от reference (стандартно: по высоте)
- float scale = (crosshairCfg.refH > 0) ? (Environment::height / (float)crosshairCfg.refH) : 1.0f;
+ float scale = (crosshairCfg.refH > 0) ? (Environment::projectionHeight / (float)crosshairCfg.refH) : 1.0f;
scale *= crosshairCfg.scaleMul;
float thickness = crosshairCfg.thicknessPx * scale;
@@ -940,7 +940,7 @@ namespace ZL
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
renderer.shaderManager.PushShader("defaultColor");
- renderer.PushProjectionMatrix((float)Environment::width, (float)Environment::height, 0.f, 1.f);
+ renderer.PushProjectionMatrix(Environment::projectionWidth, Environment::projectionHeight, 0.f, 1.f);
renderer.PushMatrix();
renderer.LoadIdentity();
@@ -1187,15 +1187,15 @@ namespace ZL
// 4) Настройки стиля
Eigen::Vector4f enemyColor(1.f, 0.f, 0.f, 1.f); // красный
- float thickness = 10.0f; // толщина линий (px)
+ float thickness = 2.0f; // толщина линий (px)
float z = 0.0f; // 2D слой
// 5) Если цель в кадре: рисуем скобки
if (onScreen)
{
// перевод NDC -> экран (в пикселях)
- float sx = (ndcX * 0.5f + 0.5f) * Environment::width;
- float sy = (ndcY * 0.5f + 0.5f) * Environment::height;
+ float sx = (ndcX * 0.5f + 0.5f) * Environment::projectionWidth;
+ float sy = (ndcY * 0.5f + 0.5f) * Environment::projectionHeight;
// анимация “снаружи внутрь”
// targetAcquireAnim растёт к 1, быстро (похоже на захват)
@@ -1234,7 +1234,7 @@ namespace ZL
glClear(GL_DEPTH_BUFFER_BIT);
renderer.shaderManager.PushShader("defaultColor");
- renderer.PushProjectionMatrix((float)Environment::width, (float)Environment::height, 0.f, 1.f);
+ renderer.PushProjectionMatrix(Environment::projectionWidth, Environment::projectionHeight, 0.f, 1.f);
renderer.PushMatrix();
renderer.LoadIdentity();
@@ -1248,8 +1248,8 @@ namespace ZL
float leadNdcX, leadNdcY, leadNdcZ, leadClipW;
if (projectToNDC(leadWorld, leadNdcX, leadNdcY, leadNdcZ, leadClipW) && leadClipW > 0.0f) {
if (leadNdcX >= -1 && leadNdcX <= 1 && leadNdcY >= -1 && leadNdcY <= 1) {
- float lx = (leadNdcX * 0.5f + 0.5f) * Environment::width;
- float ly = (leadNdcY * 0.5f + 0.5f) * Environment::height;
+ float lx = (leadNdcX * 0.5f + 0.5f) * Environment::projectionWidth;
+ float ly = (leadNdcY * 0.5f + 0.5f) * Environment::projectionHeight;
float distLead = (Environment::shipState.position - leadWorld).norm();
float r = 30.0f / (distLead * 0.01f + 1.0f);
@@ -1323,8 +1323,8 @@ namespace ZL
float edgeNdcX = dirX * k;
float edgeNdcY = dirY * k;
- float edgeX = (edgeNdcX * 0.5f + 0.5f) * Environment::width;
- float edgeY = (edgeNdcY * 0.5f + 0.5f) * Environment::height;
+ float edgeX = (edgeNdcX * 0.5f + 0.5f) * Environment::projectionWidth;
+ float edgeY = (edgeNdcY * 0.5f + 0.5f) * Environment::projectionHeight;
float bob = std::sin(t * 6.0f) * 6.0f;
edgeX += dirX * bob;
@@ -1367,7 +1367,7 @@ namespace ZL
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
renderer.shaderManager.PushShader("defaultColor");
- renderer.PushProjectionMatrix((float)Environment::width, (float)Environment::height, 0.f, 1.f);
+ renderer.PushProjectionMatrix(Environment::projectionWidth, Environment::projectionHeight, 0.f, 1.f);
renderer.PushMatrix();
renderer.LoadIdentity();
diff --git a/src/UiManager.cpp b/src/UiManager.cpp
index 647d72f..6b3dc95 100644
--- a/src/UiManager.cpp
+++ b/src/UiManager.cpp
@@ -657,7 +657,7 @@ namespace ZL {
}
void UiManager::draw(Renderer& renderer) {
- renderer.PushProjectionMatrix(Environment::width, Environment::height, -1, 1);
+ renderer.PushProjectionMatrix(Environment::projectionWidth, Environment::projectionHeight, -1, 1);
renderer.PushMatrix();
renderer.LoadIdentity();
diff --git a/src/main.cpp b/src/main.cpp
index d1bdc1e..6b62092 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -44,20 +44,34 @@ EM_BOOL onWebGLContextRestored(int /*eventType*/, const void* /*reserved*/, void
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);
+static void applyResize(int logicalW, int logicalH) {
+ // Получаем коэффициент плотности пикселей (например, 2.625 на Pixel или 3.0 на Samsung)
+ double dpr = emscripten_get_device_pixel_ratio();
+
+ // Вычисляем реальные физические пиксели
+ int physicalW = static_cast(logicalW * dpr);
+ int physicalH = static_cast(logicalH * dpr);
+
+ // Устанавливаем размер внутреннего буфера канваса
+ emscripten_set_canvas_element_size("#canvas", physicalW, physicalH);
+
+ // Сообщаем SDL о новом размере.
+ // ВАЖНО: SDL2 в Emscripten ожидает здесь именно физические пиксели
+ // для корректной работы последующих вызовов glViewport.
+ if (ZL::Environment::window) {
+ SDL_SetWindowSize(ZL::Environment::window, physicalW, physicalH);
+ }
+
+ // Обновляем ваши внутренние переменные окружения
+ ZL::Environment::width = physicalW;
+ ZL::Environment::height = physicalH;
+
+ // Пушим событие, чтобы движок пересчитал матрицы проекции
SDL_Event e = {};
e.type = SDL_WINDOWEVENT;
e.window.event = SDL_WINDOWEVENT_RESIZED;
- e.window.data1 = w;
- e.window.data2 = h;
+ e.window.data1 = physicalW;
+ e.window.data2 = physicalH;
SDL_PushEvent(&e);
}
@@ -69,17 +83,11 @@ EM_BOOL onWindowResized(int /*eventType*/, const EmscriptenUiEvent* e, void* /*u
}
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.
+ // Вместо window.innerWidth, попробуйте запросить размер целевого элемента
+ // так как после перехода в FS именно он растягивается на весь экран.
+ double clientW, clientH;
+ emscripten_get_element_css_size("#canvas", &clientW, &clientH);
+ applyResize(clientW, clientH);
return EM_FALSE;
}
@@ -226,6 +234,21 @@ int main(int argc, char *argv[]) {
// 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);
+
+ // 2. ИНИЦИАЛИЗАЦИЯ РАЗМЕРОВ:
+ // Получаем реальные размеры окна браузера на момент запуска
+ int canvasW = EM_ASM_INT({ return window.innerWidth; });
+ int canvasH = EM_ASM_INT({ return window.innerHeight; });
+
+ // Вызываем вашу функцию — она сама применит DPR, выставит физический размер
+ // канваса и отправит SDL_WINDOWEVENT_RESIZED для настройки проекции.
+ applyResize(canvasW, canvasH);
+
+ // 3. Создаем игру и вызываем setup (теперь проекция уже будет знать верный size)
+ g_game = new ZL::Game();
+ g_game->setup();
+
+ SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0");
emscripten_set_main_loop(MainLoop, 0, 1);
#else
diff --git a/src/render/TextRenderer.cpp b/src/render/TextRenderer.cpp
index 585ca8d..73e2db1 100644
--- a/src/render/TextRenderer.cpp
+++ b/src/render/TextRenderer.cpp
@@ -362,9 +362,10 @@ void TextRenderer::drawText(const std::string& text, float x, float y, float sca
// 4. Рендеринг
r->shaderManager.PushShader(shaderName);
- // Матрица проекции (экрана)
- float W = (float)Environment::width;
- float H = (float)Environment::height;
+ // Матрица проекции — используем виртуальные проекционные размеры,
+ // чтобы координаты текста были независимы от физического разрешения экрана.
+ float W = Environment::projectionWidth;
+ float H = Environment::projectionHeight;
Eigen::Matrix4f proj = Eigen::Matrix4f::Identity();
proj(0, 0) = 2.0f / W;
proj(1, 1) = 2.0f / H;