diff --git a/CMakeLists.txt b/CMakeLists.txt index eca6bfe..3720cab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,11 +121,27 @@ set(APP_SOURCES ) # Configuración de SDL3 -find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3) -message(STATUS "SDL3 encontrado: ${SDL3_INCLUDE_DIRS}") +if(EMSCRIPTEN) + # En Emscripten, SDL3 se compila desde source con FetchContent + include(FetchContent) + FetchContent_Declare( + SDL3 + GIT_REPOSITORY https://github.com/libsdl-org/SDL.git + GIT_TAG release-3.2.12 + GIT_SHALLOW TRUE + ) + set(SDL_SHARED OFF CACHE BOOL "" FORCE) + set(SDL_STATIC ON CACHE BOOL "" FORCE) + set(SDL_TEST_LIBRARY OFF CACHE BOOL "" FORCE) + FetchContent_MakeAvailable(SDL3) + message(STATUS "SDL3 compilado desde source para Emscripten") +else() + find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3) + message(STATUS "SDL3 encontrado: ${SDL3_INCLUDE_DIRS}") +endif() -# --- SHADER COMPILATION (Linux/Windows only - macOS uses Metal) --- -if(NOT APPLE) +# --- SHADER COMPILATION (Linux/Windows only - macOS uses Metal, Emscripten no soporta SDL3 GPU) --- +if(NOT APPLE AND NOT EMSCRIPTEN) find_program(GLSLC_EXE NAMES glslc) set(SHADER_VERT_SRC "${CMAKE_SOURCE_DIR}/data/shaders/postfx.vert") @@ -184,13 +200,24 @@ if(NOT APPLE) message(STATUS "glslc no encontrado - usando headers SPIR-V precompilados") endif() else() - message(STATUS "macOS: shaders SPIR-V omitidos (usa Metal)") + if(EMSCRIPTEN) + message(STATUS "Emscripten: shaders SPIR-V omitidos (SDL3 GPU no soportado en WebGL2)") + else() + message(STATUS "macOS: shaders SPIR-V omitidos (usa Metal)") + endif() endif() # --- 2. AÑADIR EJECUTABLE --- -add_executable(${PROJECT_NAME} ${APP_SOURCES}) +if(EMSCRIPTEN) + # En Emscripten no compilamos sdl3gpu_shader (SDL3 GPU no está soportado en WebGL2) + set(APP_SOURCES_WASM ${APP_SOURCES}) + list(REMOVE_ITEM APP_SOURCES_WASM source/core/rendering/sdl3gpu/sdl3gpu_shader.cpp) + add_executable(${PROJECT_NAME} ${APP_SOURCES_WASM}) +else() + add_executable(${PROJECT_NAME} ${APP_SOURCES}) +endif() -if(NOT APPLE AND GLSLC_EXE) +if(NOT APPLE AND NOT EMSCRIPTEN AND GLSLC_EXE) add_dependencies(${PROJECT_NAME} shaders) endif() @@ -233,12 +260,33 @@ elseif(APPLE) -rpath @executable_path/../Frameworks/ ) endif() +elseif(EMSCRIPTEN) + target_compile_definitions(${PROJECT_NAME} PRIVATE EMSCRIPTEN_BUILD NO_SHADERS) + # -fexceptions: habilita excepciones C++ (fkyaml, std::runtime_error...) — sin esto cualquier throw llama a abort() + target_compile_options(${PROJECT_NAME} PRIVATE -fexceptions) + target_link_options(${PROJECT_NAME} PRIVATE + "SHELL:--preload-file ${CMAKE_SOURCE_DIR}/data@/data" + "SHELL:--preload-file ${CMAKE_SOURCE_DIR}/config@/config" + -fexceptions + -sALLOW_MEMORY_GROWTH=1 + -sMAX_WEBGL_VERSION=2 + -sINITIAL_MEMORY=67108864 + -sASSERTIONS=1 + # ASYNCIFY solo para permitir emscripten_sleep(0) durante la precarga de recursos + # (el bucle principal del juego ya usa SDL3 Callback API, no depende de ASYNCIFY). + -sASYNCIFY=1 + ) + set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".html") elseif(UNIX AND NOT APPLE) target_compile_definitions(${PROJECT_NAME} PRIVATE LINUX_BUILD) endif() # Especificar la ubicación del ejecutable -set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}) +if(EMSCRIPTEN) + set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +else() + set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}) +endif() # --- 5. STATIC ANALYSIS TARGETS --- diff --git a/Makefile b/Makefile index 6b57e52..91d295b 100644 --- a/Makefile +++ b/Makefile @@ -407,6 +407,23 @@ raspi_release: # Elimina la carpeta temporal $(RMDIR) "$(RELEASE_FOLDER)" +# ============================================================================== +# COMPILACIÓN PARA WEBASSEMBLY (requiere Docker) +# ============================================================================== +wasm: + @echo "Compilando para WebAssembly - Version: $(VERSION)" + docker run --rm \ + -v $(DIR_ROOT):/src \ + -w /src \ + emscripten/emsdk:latest \ + bash -c "emcmake cmake -S . -B build/wasm -DCMAKE_BUILD_TYPE=Release && cmake --build build/wasm" + $(MKDIR) "$(DIST_DIR)/wasm" + cp build/wasm/$(TARGET_NAME).html $(DIST_DIR)/wasm/ + cp build/wasm/$(TARGET_NAME).js $(DIST_DIR)/wasm/ + cp build/wasm/$(TARGET_NAME).wasm $(DIST_DIR)/wasm/ + cp build/wasm/$(TARGET_NAME).data $(DIST_DIR)/wasm/ + @echo "Output: $(DIST_DIR)/wasm/" + # ============================================================================== # CODE QUALITY (delegados a cmake) # ============================================================================== @@ -447,6 +464,7 @@ help: @echo " make linux_release_desktop - Crear release con integracion desktop para Linux" @echo " make macos_release - Crear release para macOS" @echo " make raspi_release - Crear release para Raspberry Pi" + @echo " make wasm - Crear build WebAssembly (requiere Docker) en dist/wasm" @echo "" @echo " Herramientas:" @echo " make spirv - Compilar shaders SPIR-V" @@ -463,4 +481,4 @@ help: @echo " make show_version - Mostrar version actual ($(VERSION))" @echo " make help - Mostrar esta ayuda" -.PHONY: all debug release windows_release macos_release linux_release linux_release_desktop raspi_release pack_tool resources.pack spirv format format-check tidy tidy-fix show_version help +.PHONY: all debug release windows_release macos_release linux_release linux_release_desktop raspi_release wasm pack_tool resources.pack spirv format format-check tidy tidy-fix show_version help diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index b8f5b90..51b1497 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -10,7 +10,9 @@ #include // Para vector #include "core/input/mouse.hpp" // Para updateCursorVisibility +#ifndef NO_SHADERS #include "core/rendering/sdl3gpu/sdl3gpu_shader.hpp" // Para SDL3GPUShader +#endif #include "core/rendering/text.hpp" // Para Text #include "core/rendering/texture.hpp" // Para Texture #include "core/resources/asset.hpp" // Para Asset diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index 04b9de0..d70c8de 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -51,8 +51,14 @@ Director::Director() { std::cout << "Game start\n"; // Obtener la ruta del ejecutable desde SDL +#ifdef __EMSCRIPTEN__ + // En Emscripten los assets viven en la raíz del MEMFS virtual (/data, /config), + // preloaded vía --preload-file en el linker. No hay ruta de ejecutable. + executable_path_ = ""; +#else const char* base_path = SDL_GetBasePath(); executable_path_ = (base_path != nullptr) ? base_path : ""; +#endif // Crea la carpeta del sistema donde guardar los datos persistentes createSystemFolder("jailgames"); @@ -92,11 +98,11 @@ void Director::init() { #endif // Inicializar sistema de recursos con o sin fallback según el tipo de build -#ifdef RELEASE_BUILD - // Release: Sin fallback - Solo resources.pack (estricto) +#if defined(RELEASE_BUILD) && !defined(__EMSCRIPTEN__) + // Release nativo: Sin fallback - Solo resources.pack (estricto) ResourceHelper::initializeResourceSystem(pack_path, false); #else - // Desarrollo: Con fallback - Puede usar data/ si falta el pack (flexible) + // Desarrollo o Emscripten: Con fallback - carga desde filesystem/MEMFS ResourceHelper::initializeResourceSystem(pack_path, true); #endif @@ -111,6 +117,14 @@ void Director::init() { Options::loadFromFile(); // Carga el archivo de configuración Options::loadPostFXFromFile(); // Carga los presets PostFX Options::loadCrtPiFromFile(); // Carga los presets CrtPi + +#ifdef __EMSCRIPTEN__ + // En la versión web el navegador gestiona la ventana: forzamos zoom=1, + // fullscreen para ocupar el canvas, e integer scale para píxeles nítidos. + Options::window.zoom = 1; + Options::video.fullscreen = true; + Options::video.integer_scale = true; +#endif loadParams(); // Carga los parámetros del programa loadScoreFile(); // Carga el archivo de puntuaciones