Adapt for web
This commit is contained in:
1 parent
7418bbbe27
commit
9f82e7a2e6
14 files changed
+189
-40
No files matched your search
+93
-11
@@ -5,15 +5,87 @@
|
||||
#include <android/log.h>
|
||||
#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;
|
||||
#endif
|
||||
|
||||
|
||||
void MainLoop() {
|
||||
#ifdef EMSCRIPTEN
|
||||
if (g_game) g_game->update();
|
||||
#else
|
||||
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__
|
||||
|
||||
extern "C" int SDL_main(int argc, char* argv[]) {
|
||||
@@ -34,7 +106,7 @@ extern "C" int SDL_main(int argc, char* argv[]) {
|
||||
|
||||
__android_log_print(ANDROID_LOG_INFO, "Game", "Display resolution: %dx%d",
|
||||
ZL::Environment::width, ZL::Environment::height);
|
||||
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
@@ -52,13 +124,13 @@ extern "C" int SDL_main(int argc, char* argv[]) {
|
||||
ZL::Environment::width, ZL::Environment::height,
|
||||
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN
|
||||
);
|
||||
|
||||
|
||||
if (!ZL::Environment::window) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "Failed to create window: %s", SDL_GetError());
|
||||
SDL_Quit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
SDL_GLContext ctx = SDL_GL_CreateContext(ZL::Environment::window);
|
||||
if (!ctx) {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "Game", "SDL_GL_CreateContext failed: %s", SDL_GetError());
|
||||
@@ -94,7 +166,7 @@ extern "C" int SDL_main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -103,8 +175,8 @@ extern "C" int SDL_main(int argc, char* argv[]) {
|
||||
int main(int argc, char *argv[]) {
|
||||
try
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
constexpr int CONST_WIDTH = 1280;
|
||||
constexpr int CONST_HEIGHT = 720;
|
||||
|
||||
@@ -142,6 +214,20 @@ int main(int argc, char *argv[]) {
|
||||
SDL_GL_MakeCurrent(win, glContext);
|
||||
|
||||
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
|
||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
|
||||
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_GL_MakeCurrent(ZL::Environment::window, ctx);
|
||||
#endif
|
||||
|
||||
game.setup();
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
emscripten_set_main_loop(MainLoop, 0, 1);
|
||||
#else
|
||||
while (!game.shouldExit()) {
|
||||
game.update();
|
||||
SDL_Delay(2);
|
||||
@@ -182,4 +264,4 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
Reference in new issue
Block a user