diff --git a/CMakeLists.txt b/CMakeLists.txt index 45d0247d..37b6a26b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,12 @@ include_directories(bomberman sources) add_subdirectory(${PROJECT_SOURCE_DIR}/lib/wal) add_subdirectory(${PROJECT_SOURCE_DIR}/lib/Ray) +if (EMSCRIPTEN) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_GLFW=3 -s ASSERTIONS=1 -s WASM=1 -s ASYNCIFY") + set(CMAKE_EXECUTABLE_SUFFIX ".html") # This line is used to set your executable to build with the emscripten html template so taht you can directly open it. +endif () + + set(SOURCES sources/Models/GameState.hpp sources/Runner/Runner.cpp diff --git a/emsdk.sh b/emsdk.sh new file mode 100755 index 00000000..93816bb0 --- /dev/null +++ b/emsdk.sh @@ -0,0 +1,19 @@ +#! /bin/bash +PRJECTDIR=`pwd` +EMSDK_PATH=$HOME/emsdk +cd $EMSDK_PATH && git pull && +./emcmdprompt +./emsdk install latest && +./emsdk activate latest && +source ./emsdk_env.sh && +HELLO=WORLD +EMSCRIPTEN_PATH=$EMSDK_PATH/upstream/emscripten +CLANG_PATH=$EMSDK_PATH/upstream/bin +NODE_PATH=$EMSDK_PATH/node/12.9.1_64bit/bin +PATH=$PATH:$EMSDK_PATH:$EMSCRIPTEN_PATH:$CLANG_PATH:$NODE_PATH && +cd $PRJECTDIR && +emcmake cmake -S . -B build && +make PLATFORM=PLATFORM_WEB -B && +cmake --build build && +make -C build PLATFORM=PLATFORM_WEB -B && +python3 wasm-server.py diff --git a/lib/raylib/Findraylib.cmake b/lib/raylib/Findraylib.cmake index 4baf8bd8..d836183b 100644 --- a/lib/raylib/Findraylib.cmake +++ b/lib/raylib/Findraylib.cmake @@ -14,6 +14,9 @@ if (NOT raylib_FOUND) SET(FETCHCONTENT_QUIET NO) FetchContent_Populate(raylib) SET(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) + if (EMSCRIPTEN) + SET(PLATFORM Web) + endif() ADD_SUBDIRECTORY(${raylib_SOURCE_DIR} ${raylib_BINARY_DIR}) SET(raylib_FOUND TRUE) endif() diff --git a/lib/wal/sources/Wal.hpp b/lib/wal/sources/Wal.hpp index 50a87188..c222862f 100644 --- a/lib/wal/sources/Wal.hpp +++ b/lib/wal/sources/Wal.hpp @@ -15,6 +15,12 @@ #include "System/System.hpp" #include "Models/Callback.hpp" +#ifdef PLATFORM_WEB +#include +WAL::Wal *walPtr = nullptr; +void *callbackPtr = nullptr; +#endif + namespace WAL { //! @brief The main WAL class, it is used to setup and run the ECS. @@ -109,7 +115,14 @@ namespace WAL void run(const std::function &callback, T state = T()) { Callback update(callback); + + #ifdef PLATFORM_WEB + walPtr = this; + callbackPtr = &callback; + return emscripten_set_main_loop_arg(runWASM, &state, 0, 1); + #else return this->run(update, state); + #endif } //! @brief Start the game loop @@ -137,6 +150,27 @@ namespace WAL } } + #ifdef PLATFORM_WEB + template + static void runIteration(T *state) + { + static std::function callback = callbackPtr; + static auto lastTick = std::chrono::steady_clock::now(); + static std::chrono::nanoseconds fBehind(0); + + auto now = std::chrono::steady_clock::now(); + std::chrono::nanoseconds dtime = now - lastTick; + fBehind += dtime; + lastTick = now; + while (fBehind > Wal::timestep) { + fBehind -= Wal::timestep; + this->_fixedUpdate(); + } + walPtr->_update(dtime); + callback(wal, state); + } + #endif + //! @brief A default constructor Wal() = default; //! @brief A WAL can't be copy constructed diff --git a/wasm-server.py b/wasm-server.py new file mode 100644 index 00000000..77aad1db --- /dev/null +++ b/wasm-server.py @@ -0,0 +1,24 @@ +# Python 3 + +import sys +import socketserver +from http.server import SimpleHTTPRequestHandler + +class WasmHandler(SimpleHTTPRequestHandler): + def end_headers(self): + # Include additional response headers here. CORS for example: + #self.send_header('Access-Control-Allow-Origin', '*') + SimpleHTTPRequestHandler.end_headers(self) + + +# Python 3.7.5 adds in the WebAssembly Media Type. If this is an older +# version, add in the Media Type. +if sys.version_info < (3, 7, 5): + WasmHandler.extensions_map['.wasm'] = 'application/wasm' + + +if __name__ == '__main__': + PORT = 8080 + with socketserver.TCPServer(("", PORT), WasmHandler) as httpd: + print("Listening on port {}. Press Ctrl+C to stop.".format(PORT)) + httpd.serve_forever()