From 84c305819930713603124d984acb51df87761246 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Thu, 2 Nov 2023 20:11:53 -0400 Subject: emscripten port --- CMakeLists.txt | 18 ++------ gamestate.cpp | 53 +++++++++++++-------- hslist.cpp | 20 ++++++-- index.html | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ mazeoflife.cpp | 5 ++ mazeoflife.h | 1 - sdl.h | 20 -------- titlestate.cpp | 15 ++++++ util.cpp | 2 + 9 files changed, 219 insertions(+), 58 deletions(-) create mode 100644 index.html diff --git a/CMakeLists.txt b/CMakeLists.txt index e44357f..8db4315 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,21 +1,11 @@ cmake_minimum_required (VERSION 3.1) project (mazeoflife) -#set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -sUSE_SDL=2 -sUSE_SDL_NET=2 -sUSE_SDL_TTF=2") - -set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) - -find_package(SDL2 REQUIRED) -find_package(SDL2_ttf REQUIRED) -find_package(SDL2_net REQUIRED) - -include_directories( - ${SDL2_INCLUDE_DIR} - ${SDL2_TTF_INCLUDE_DIR} - ${SDL2_NET_INCLUDE_DIRS} -) +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -sUSE_SDL=2 -sUSE_SDL_TTF=2 -pthread") +set(CMAKE_EXECUTABLE_SUFFIX ".html") add_executable(mazeoflife hslist.cpp hs_state.cpp mazeoflife.cpp util.cpp titlestate.cpp gamestate.cpp) set_property(TARGET mazeoflife PROPERTY CXX_STANDARD 17) set_property(TARGET mazeoflife PROPERTY CXX_STANDARD_REQUIRED ON) -target_link_libraries(mazeoflife ${SDL2_LIBRARY} ${SDL2_TTF_LIBRARY} ${SDL2_NET_LIBRARIES}) +set_property(TARGET mazeoflife PROPERTY LINK_FLAGS "--preload-file resources -lidbfs.js -sALLOW_MEMORY_GROWTH") +target_link_libraries(mazeoflife ${SDL2_LIBRARY} ${SDL2_TTF_LIBRARY}) diff --git a/gamestate.cpp b/gamestate.cpp index 953d35b..4a0f701 100644 --- a/gamestate.cpp +++ b/gamestate.cpp @@ -9,9 +9,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -450,34 +452,31 @@ std::unique_ptr startNewLevel(int level, class LoadGameState : public State { public: - LoadGameState(int level) : level_(level) {} - - std::unique_ptr operator()(Game& game) { + LoadGameState(Game& game, int level) : level_(level) { std::ostringstream wintitle; wintitle << "Maze Of Life - Level " << level_; SDL_SetWindowTitle(game.window.get(), wintitle.str().c_str()); // Randomly place the player in a corner - int playerx, playery; switch (std::uniform_int_distribution(0, 3)(game.rng)) { case 0: { - playerx = 1; - playery = 1; + playerx_ = 1; + playery_ = 1; break; } case 1: { - playerx = 1; - playery = HEIGHT - 2; + playerx_ = 1; + playery_ = HEIGHT - 2; break; } case 2: { - playerx = WIDTH - 2; - playery = HEIGHT - 2; + playerx_ = WIDTH - 2; + playery_ = HEIGHT - 2; break; } case 3: { - playerx = WIDTH - 2; - playery = 1; + playerx_ = WIDTH - 2; + playery_ = 1; break; } } @@ -503,18 +502,34 @@ class LoadGameState : public State { SDL_RenderPresent(game.renderer.get()); // Do 50 gens of Conway - std::unique_ptr board = - std::make_unique(game, level_, playerx, playery); + std::thread([&] { + std::unique_ptr board = + std::make_unique(game, level_, playerx_, playery_); + + std::lock_guard boardGuard(boardMutex_); + board_.swap(board); + }).detach(); + } + + std::unique_ptr operator()(Game& game) { + std::lock_guard boardGuard(boardMutex_); + if (board_) { + return startNewLevel(level_, std::move(board_), playerx_, playery_); + } // Wait a bit - SDL_Delay(500); + // SDL_Delay(500); // Start the level - return startNewLevel(level_, std::move(board), playerx, playery); + return nullptr; } private: int level_; + int playerx_; + int playery_; + std::unique_ptr board_; + std::mutex boardMutex_; }; class PlayGameState : public State { @@ -600,7 +615,7 @@ class PlayGameState : public State { } if (trymove && move(to_x, to_y)) { - return std::make_unique(level_ + 1); + return std::make_unique(game, level_ + 1); } } } @@ -641,6 +656,6 @@ std::unique_ptr startNewLevel(int level, playery); } -std::unique_ptr GameState::operator()(Game&) { - return std::make_unique(0); +std::unique_ptr GameState::operator()(Game& game) { + return std::make_unique(game, 0); } diff --git a/hslist.cpp b/hslist.cpp index 9ae2aa4..9547acd 100644 --- a/hslist.cpp +++ b/hslist.cpp @@ -12,6 +12,10 @@ #include "titlestate.h" #include "util.h" +#ifdef __EMSCRIPTEN__ +#include +#endif + HighscoreList::HighscoreList(std::vector hslist) : hslist_(hslist) { resetRanks(); } @@ -118,10 +122,18 @@ int HighscoreList::addHighscore(Highscore h) { } void HighscoreList::writeToFile() { - std::ofstream hsfile(getDataFile()); - hsfile << hslist_.size() << std::endl; + { + std::ofstream hsfile(getDataFile()); + hsfile << hslist_.size() << std::endl; - for (const Highscore& h : hslist_) { - hsfile << h.getName() << std::endl << h.getLevel() << std::endl; + for (const Highscore& h : hslist_) { + hsfile << h.getName() << std::endl << h.getLevel() << std::endl; + } } + +#ifdef __EMSCRIPTEN__ + EM_ASM(FS.syncfs(function(err){ + // Error + });); +#endif } diff --git a/index.html b/index.html new file mode 100644 index 0000000..a63d720 --- /dev/null +++ b/index.html @@ -0,0 +1,143 @@ + + + + + + Emscripten-Generated Code + + + +
+
emscripten
+
Downloading...
+
+ +
+
+ +
+
+
+ Resize canvas + Lock/hide mouse pointer +     + +
+ +
+ +
+ + + + diff --git a/mazeoflife.cpp b/mazeoflife.cpp index 3afff78..873e08c 100644 --- a/mazeoflife.cpp +++ b/mazeoflife.cpp @@ -59,6 +59,11 @@ int main(int, char**) { game.state = std::make_unique(game); #ifdef __EMSCRIPTEN__ + EM_ASM(FS.mkdir('/offline'); FS.mount(IDBFS, {}, '/offline'); + FS.syncfs(true, function(err){ + // Error + });); + emscripten_set_main_loop_arg(main_loop, &game, 0, 1); #else for (;;) { diff --git a/mazeoflife.h b/mazeoflife.h index 8a31d07..d44f021 100644 --- a/mazeoflife.h +++ b/mazeoflife.h @@ -15,7 +15,6 @@ struct Game { sdl_wrapper sdl; ttf_wrapper ttf; - net_wrapper net; window_ptr window; renderer_ptr renderer; diff --git a/sdl.h b/sdl.h index 46d1fa4..4335ed2 100644 --- a/sdl.h +++ b/sdl.h @@ -2,7 +2,6 @@ #define SDL_H_A2226476 #include -#include #include #include @@ -17,11 +16,6 @@ class ttf_error : public std::logic_error { ttf_error() : std::logic_error(TTF_GetError()) {} }; -class net_error : public std::logic_error { - public: - net_error() : std::logic_error(SDLNet_GetError()) {} -}; - class sdl_wrapper { public: sdl_wrapper() { @@ -50,20 +44,6 @@ class ttf_wrapper { ~ttf_wrapper() { TTF_Quit(); } }; -class net_wrapper { - public: - net_wrapper() { - if (SDLNet_Init() == -1) { - net_error ex; - SDLNet_Quit(); - - throw ex; - } - } - - ~net_wrapper() { SDLNet_Quit(); } -}; - class window_deleter { public: void operator()(SDL_Window* ptr) { SDL_DestroyWindow(ptr); } diff --git a/titlestate.cpp b/titlestate.cpp index b68e8fa..95bba6b 100644 --- a/titlestate.cpp +++ b/titlestate.cpp @@ -14,10 +14,21 @@ std::unique_ptr TitleState::operator()(Game& game) { SDL_RenderClear(game.renderer.get()); SDL_RenderCopy(game.renderer.get(), background_.get(), NULL, NULL); + +#ifdef __EMSCRIPTEN__ + applyTexture(game.renderer.get(), pointer_.get(), 136, + selection_ == 0 ? 316 : (selection_ == 1 ? 350 : 381)); + + SDL_Rect eSpace = {164, 412, 79, 33}; + SDL_SetRenderDrawColor(game.renderer.get(), 255, 255, 255, 255); + SDL_RenderFillRect(game.renderer.get(), &eSpace); +#else applyTexture(game.renderer.get(), pointer_.get(), 136, selection_ == 0 ? 316 : (selection_ == 1 ? 350 : (selection_ == 2 ? 381 : 417))); +#endif + SDL_RenderPresent(game.renderer.get()); while (SDL_PollEvent(&e)) { @@ -27,7 +38,11 @@ std::unique_ptr TitleState::operator()(Game& game) { } else if (e.type == SDL_KEYDOWN) { if ((e.key.keysym.sym == SDLK_UP) && (selection_ != 0)) { selection_--; +#ifdef __EMSCRIPTEN__ + } else if ((e.key.keysym.sym == SDLK_DOWN) && (selection_ != 2)) { +#else } else if ((e.key.keysym.sym == SDLK_DOWN) && (selection_ != 3)) { +#endif selection_++; } else if (e.key.keysym.sym == SDLK_RETURN) { switch (selection_) { diff --git a/util.cpp b/util.cpp index 5947620..1bfa900 100644 --- a/util.cpp +++ b/util.cpp @@ -32,6 +32,8 @@ font_ptr loadFont(int size) { std::string getDataFile() { #ifdef WINDOWS char* dir = getenv("USERPROFILE"); +#elif __EMSCRIPTEN__ + const char* dir = "/offline"; #else char* dir = getenv("HOME"); #endif -- cgit 1.4.1