Compare commits

..

1 Commits

Author SHA1 Message Date
d6ffbda00d WIP: Metal shader backend para macOS
- Shaders MSL portados desde GLSL (vertex + fragment)
- Estructura básica de MetalShader class
- Device, command queue, pipeline y buffers creados
- CMakeLists.txt actualizado con Metal frameworks
- assets.txt incluye shaders .metal como opcionales

PENDIENTE:
- Implementar render() loop completo
- Obtener MTLTexture desde SDL_Texture
- Crear sampler state
- Testing en macOS real

Ver METAL_BACKEND_NOTES.md para detalles de implementación.
2025-10-02 21:05:28 +02:00
709 changed files with 325616 additions and 41172 deletions

View File

@@ -1,7 +1,6 @@
BasedOnStyle: Google BasedOnStyle: Google
IndentWidth: 4 IndentWidth: 4
NamespaceIndentation: All IndentAccessModifiers: true
IndentAccessModifiers: false
ColumnLimit: 0 # Sin límite de longitud de línea ColumnLimit: 0 # Sin límite de longitud de línea
BreakBeforeBraces: Attach # Llaves en la misma línea BreakBeforeBraces: Attach # Llaves en la misma línea
AllowShortIfStatementsOnASingleLine: true AllowShortIfStatementsOnASingleLine: true

1
.clang-format-ignore Normal file
View File

@@ -0,0 +1 @@
source/external/**

12
.clang-format.bak Normal file
View File

@@ -0,0 +1,12 @@
BasedOnStyle: Google
IndentWidth: 4
IndentAccessModifiers: true
ColumnLimit: 0 # Sin límite de longitud de línea
BreakBeforeBraces: Attach # Llaves en la misma línea
AllowShortIfStatementsOnASingleLine: true
AllowShortBlocksOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AlignOperands: false
AlignAfterOpenBracket: DontAlign
BinPackArguments: false
BinPackParameters: false

68
.clang-tidy.bak Normal file
View File

@@ -0,0 +1,68 @@
Checks: >
readability-identifier-naming,
readability-*,
modernize-*,
clang-analyzer-*,
-readability-identifier-length,
-readability-magic-numbers
WarningsAsErrors: '*'
HeaderFilterRegex: '.*'
FormatStyle: file
CheckOptions:
# Variables locales en snake_case
- { key: readability-identifier-naming.VariableCase, value: lower_case }
# Miembros privados en snake_case con sufijo _
- { key: readability-identifier-naming.PrivateMemberCase, value: lower_case }
- { key: readability-identifier-naming.PrivateMemberSuffix, value: _ }
# Miembros protegidos en snake_case con sufijo _
- { key: readability-identifier-naming.ProtectedMemberCase, value: lower_case }
- { key: readability-identifier-naming.ProtectedMemberSuffix, value: _ }
# Miembros públicos en snake_case (sin sufijo)
- { key: readability-identifier-naming.PublicMemberCase, value: lower_case }
# Namespaces en CamelCase
- { key: readability-identifier-naming.NamespaceCase, value: CamelCase }
# Constantes globales en UPPER_CASE
- { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE }
# Variables constexpr globales en UPPER_CASE
- { key: readability-identifier-naming.ConstexprVariableCase, value: UPPER_CASE }
# Constantes locales en UPPER_CASE
- { key: readability-identifier-naming.LocalConstantCase, value: UPPER_CASE }
# Constantes estáticas dentro de clases en UPPER_CASE (sin sufijo)
- { key: readability-identifier-naming.StaticConstantCase, value: UPPER_CASE }
# Constexpr miembros en UPPER_CASE (sin sufijo)
- { key: readability-identifier-naming.ConstexprMemberCase, value: UPPER_CASE }
# Constexpr miembros privados/protegidos con sufijo _
- { key: readability-identifier-naming.ConstexprMethodCase, value: UPPER_CASE }
# Clases, structs y enums en CamelCase
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
- { key: readability-identifier-naming.StructCase, value: CamelCase }
- { key: readability-identifier-naming.EnumCase, value: CamelCase }
# Valores de enums en UPPER_CASE
- { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE }
# Métodos en camelBack (sin sufijos)
- { key: readability-identifier-naming.MethodCase, value: camelBack }
- { key: readability-identifier-naming.PrivateMethodCase, value: camelBack }
- { key: readability-identifier-naming.ProtectedMethodCase, value: camelBack }
- { key: readability-identifier-naming.PublicMethodCase, value: camelBack }
# Funciones en camelBack
- { key: readability-identifier-naming.FunctionCase, value: camelBack }
# Parámetros en lower_case
- { key: readability-identifier-naming.ParameterCase, value: lower_case }

12
.gitignore vendored
View File

@@ -1,6 +1,5 @@
.vscode/ .vscode
.claude/ .claude
.cache/
build/ build/
data/config/config.txt data/config/config.txt
*.DS_Store *.DS_Store
@@ -18,10 +17,5 @@ coffee_crisis*
debug.txt debug.txt
cppcheck-result* cppcheck-result*
desktop.ini desktop.ini
dist/ ccae_release/
release/windows/coffee.res
resources.pack resources.pack
# Herramienta pack_resources (todas las plataformas)
tools/pack_resources/pack_resources
tools/pack_resources/pack_resources.exe

View File

@@ -6,8 +6,13 @@ project(coffee_crisis_arcade_edition VERSION 2.00)
# Establecer estándar de C++ # Establecer estándar de C++
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Establece la política CMP0072 para indicar cómo se debe seleccionar la implementación de OpenGL.
# En este caso, se elige la opción "GLVND", que utiliza bibliotecas modernas y modulares (libOpenGL, libGLX),
# en lugar de la biblioteca OpenGL clásica (libGL). Esto mejora la compatibilidad con drivers recientes
# y evita ambigüedades cuando se encuentran múltiples implementaciones de OpenGL en el sistema.
cmake_policy(SET CMP0072 NEW)
set(OpenGL_GL_PREFERENCE GLVND)
# --- GENERACIÓN DE VERSIÓN AUTOMÁTICA --- # --- GENERACIÓN DE VERSIÓN AUTOMÁTICA ---
find_package(Git QUIET) find_package(Git QUIET)
@@ -112,61 +117,29 @@ set(EXTERNAL_SOURCES
# Fuentes del sistema de renderizado # Fuentes del sistema de renderizado
set(RENDERING_SOURCES set(RENDERING_SOURCES
source/rendering/sdl3gpu/sdl3gpu_shader.cpp source/rendering/opengl/opengl_shader.cpp
) )
# Añadir backend de Metal en macOS
if(APPLE)
list(APPEND RENDERING_SOURCES
source/rendering/metal/metal_shader.mm
)
message(STATUS "Metal backend habilitado para macOS")
endif()
# Configuración de SDL3 # Configuración de SDL3
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3) find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
message(STATUS "SDL3 encontrado: ${SDL3_INCLUDE_DIRS}") message(STATUS "SDL3 encontrado: ${SDL3_INCLUDE_DIRS}")
# --- SHADER COMPILATION (Linux/Windows only - macOS uses Metal) ---
if(NOT APPLE)
find_program(GLSLC_EXE NAMES glslc)
set(SHADER_VERT_SRC "${CMAKE_SOURCE_DIR}/data/shaders/postfx.vert")
set(SHADER_FRAG_SRC "${CMAKE_SOURCE_DIR}/data/shaders/postfx.frag")
set(SHADER_VERT_H "${CMAKE_SOURCE_DIR}/source/rendering/sdl3gpu/postfx_vert_spv.h")
set(SHADER_FRAG_H "${CMAKE_SOURCE_DIR}/source/rendering/sdl3gpu/postfx_frag_spv.h")
if(GLSLC_EXE)
add_custom_command(
OUTPUT "${SHADER_VERT_H}" "${SHADER_FRAG_H}"
COMMAND "${CMAKE_SOURCE_DIR}/tools/shaders/compile_spirv.sh"
DEPENDS "${SHADER_VERT_SRC}" "${SHADER_FRAG_SRC}"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
COMMENT "Compilando shaders SPIR-V..."
)
add_custom_target(shaders DEPENDS "${SHADER_VERT_H}" "${SHADER_FRAG_H}")
message(STATUS "glslc encontrado: shaders se compilarán automáticamente")
else()
if(NOT EXISTS "${SHADER_VERT_H}" OR NOT EXISTS "${SHADER_FRAG_H}")
message(FATAL_ERROR
"glslc no encontrado y headers SPIR-V no existen.\n"
" Instala glslc: sudo apt install glslang-tools (Linux)\n"
" choco install vulkan-sdk (Windows)\n"
" O genera los headers manualmente: tools/shaders/compile_spirv.sh"
)
else()
message(STATUS "glslc no encontrado - usando headers SPIR-V precompilados")
endif()
endif()
else()
message(STATUS "macOS: shaders SPIR-V omitidos (usa Metal)")
endif()
# --- 2. AÑADIR EJECUTABLE --- # --- 2. AÑADIR EJECUTABLE ---
add_executable(${PROJECT_NAME} ${APP_SOURCES} ${EXTERNAL_SOURCES} ${RENDERING_SOURCES}) add_executable(${PROJECT_NAME} ${APP_SOURCES} ${EXTERNAL_SOURCES} ${RENDERING_SOURCES})
if(NOT APPLE AND GLSLC_EXE)
add_dependencies(${PROJECT_NAME} shaders)
endif()
# --- 3. DIRECTORIOS DE INCLUSIÓN --- # --- 3. DIRECTORIOS DE INCLUSIÓN ---
target_include_directories(${PROJECT_NAME} PUBLIC target_include_directories(${PROJECT_NAME} PUBLIC
"${CMAKE_SOURCE_DIR}/source" "${CMAKE_SOURCE_DIR}/source"
"${CMAKE_SOURCE_DIR}/source/external" "${CMAKE_SOURCE_DIR}/source/external"
"${CMAKE_SOURCE_DIR}/source/rendering" "${CMAKE_SOURCE_DIR}/source/rendering"
"${CMAKE_SOURCE_DIR}/source/rendering/sdl3gpu"
"${CMAKE_BINARY_DIR}" "${CMAKE_BINARY_DIR}"
) )
@@ -189,83 +162,30 @@ target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<CONFIG:DEBUG>:_DEBUG>)
# Configuración específica para cada plataforma # Configuración específica para cada plataforma
if(WIN32) if(WIN32)
target_compile_definitions(${PROJECT_NAME} PRIVATE WINDOWS_BUILD) target_compile_definitions(${PROJECT_NAME} PRIVATE WINDOWS_BUILD)
target_link_libraries(${PROJECT_NAME} PRIVATE ws2_32 mingw32) target_link_libraries(${PROJECT_NAME} PRIVATE ws2_32 mingw32 opengl32)
elseif(APPLE) elseif(APPLE)
target_compile_definitions(${PROJECT_NAME} PRIVATE MACOS_BUILD) target_compile_definitions(${PROJECT_NAME} PRIVATE MACOS_BUILD)
target_compile_options(${PROJECT_NAME} PRIVATE -Wno-deprecated)
set(CMAKE_OSX_ARCHITECTURES "arm64") set(CMAKE_OSX_ARCHITECTURES "arm64")
# Enlazar frameworks de Metal
target_link_libraries(${PROJECT_NAME} PRIVATE
"-framework Metal"
"-framework QuartzCore"
)
elseif(UNIX AND NOT APPLE) elseif(UNIX AND NOT APPLE)
target_compile_definitions(${PROJECT_NAME} PRIVATE LINUX_BUILD) target_compile_definitions(${PROJECT_NAME} PRIVATE LINUX_BUILD)
endif() endif()
# Configuración común para OpenGL
if(NOT WIN32)
find_package(OpenGL REQUIRED)
if(OPENGL_FOUND)
message(STATUS "OpenGL encontrado: ${OPENGL_LIBRARIES}")
target_link_libraries(${PROJECT_NAME} PRIVATE ${OPENGL_LIBRARIES})
else()
message(FATAL_ERROR "OpenGL no encontrado")
endif()
endif()
# Especificar la ubicación del ejecutable # Especificar la ubicación del ejecutable
set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}) set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})
# --- 5. STATIC ANALYSIS TARGETS ---
find_program(CLANG_TIDY_EXE NAMES clang-tidy)
find_program(CLANG_FORMAT_EXE NAMES clang-format)
# Recopilar todos los archivos fuente, excluyendo external/
file(GLOB_RECURSE ALL_SOURCE_FILES
"${CMAKE_SOURCE_DIR}/source/*.cpp"
"${CMAKE_SOURCE_DIR}/source/*.hpp"
"${CMAKE_SOURCE_DIR}/source/*.h"
)
list(FILTER ALL_SOURCE_FILES EXCLUDE REGEX ".*/external/.*")
# Targets de clang-tidy
if(CLANG_TIDY_EXE)
# En macOS con clang-tidy de Homebrew LLVM, es necesario pasar el sysroot
# explícitamente para que encuentre los headers del sistema (string, memory, etc.)
if(APPLE)
execute_process(
COMMAND xcrun --show-sdk-path
OUTPUT_VARIABLE MACOS_SDK_PATH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
set(TIDY_EXTRA_ARGS --extra-arg=-isysroot --extra-arg=${MACOS_SDK_PATH})
endif()
add_custom_target(tidy
COMMAND ${CLANG_TIDY_EXE}
-p ${CMAKE_BINARY_DIR}
${TIDY_EXTRA_ARGS}
${ALL_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-tidy..."
)
add_custom_target(tidy-fix
COMMAND ${CLANG_TIDY_EXE}
-p ${CMAKE_BINARY_DIR}
--fix
${TIDY_EXTRA_ARGS}
${ALL_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-tidy with fixes..."
)
else()
message(STATUS "clang-tidy no encontrado - targets 'tidy' y 'tidy-fix' no disponibles")
endif()
# Targets de clang-format
if(CLANG_FORMAT_EXE)
add_custom_target(format
COMMAND ${CLANG_FORMAT_EXE}
-i
${ALL_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Running clang-format..."
)
add_custom_target(format-check
COMMAND ${CLANG_FORMAT_EXE}
--dry-run
--Werror
${ALL_SOURCE_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Checking clang-format..."
)
else()
message(STATUS "clang-format no encontrado - targets 'format' y 'format-check' no disponibles")
endif()

267
Makefile
View File

@@ -9,21 +9,20 @@ DIR_TOOLS := $(addsuffix /, $(DIR_ROOT)tools)
TARGET_NAME := coffee_crisis_arcade_edition TARGET_NAME := coffee_crisis_arcade_edition
TARGET_FILE := $(DIR_BIN)$(TARGET_NAME) TARGET_FILE := $(DIR_BIN)$(TARGET_NAME)
APP_NAME := Coffee Crisis Arcade Edition APP_NAME := Coffee Crisis Arcade Edition
DIST_DIR := dist RELEASE_FOLDER := ccae_release
RELEASE_FOLDER := dist/_tmp
RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME) RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME)
RESOURCE_FILE := release/windows/coffee.res RESOURCE_FILE := release/coffee.res
# Variables para herramienta de empaquetado # Variables para herramienta de empaquetado
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
PACK_TOOL := $(DIR_TOOLS)pack_resources/pack_resources.exe PACK_TOOL := $(DIR_TOOLS)pack_resources.exe
PACK_CXX := $(CXX) PACK_CXX := $(CXX)
else else
PACK_TOOL := $(DIR_TOOLS)pack_resources/pack_resources PACK_TOOL := $(DIR_TOOLS)pack_resources
PACK_CXX := $(CXX) PACK_CXX := $(CXX)
endif endif
PACK_SOURCES := $(DIR_TOOLS)pack_resources/pack_resources.cpp $(DIR_SOURCES)resource_pack.cpp PACK_SOURCES := $(DIR_TOOLS)pack_resources.cpp $(DIR_SOURCES)resource_pack.cpp
PACK_INCLUDES := -I$(DIR_ROOT) -I$(DIR_BUILD) PACK_INCLUDES := -I$(DIR_ROOT)
# Versión automática basada en la fecha actual (específica por SO) # Versión automática basada en la fecha actual (específica por SO)
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
@@ -42,49 +41,53 @@ else
endif endif
# Nombres para los ficheros de lanzamiento # Nombres para los ficheros de lanzamiento
WINDOWS_RELEASE := $(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-win32-x64.zip WINDOWS_RELEASE := $(TARGET_NAME)-$(VERSION)-win32-x64.zip
MACOS_INTEL_RELEASE := $(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-macos-intel.dmg MACOS_INTEL_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-intel.dmg
MACOS_APPLE_SILICON_RELEASE := $(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-macos-apple-silicon.dmg MACOS_APPLE_SILICON_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-apple-silicon.dmg
LINUX_RELEASE := $(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-linux.tar.gz LINUX_RELEASE := $(TARGET_FILE)-$(VERSION)-linux.tar.gz
RASPI_RELEASE := $(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-raspberry.tar.gz RASPI_RELEASE := $(TARGET_FILE)-$(VERSION)-raspberry.tar.gz
# Lista completa de archivos fuente (basada en CMakeLists.txt) # Lista completa de archivos fuente (basada en CMakeLists.txt)
APP_SOURCES := \ APP_SOURCES := \
source/animated_sprite.cpp \
source/asset.cpp \ source/asset.cpp \
source/audio.cpp \ source/audio.cpp \
source/director.cpp \ source/background.cpp \
source/global_events.cpp \
source/global_inputs.cpp \
source/input.cpp \
source/lang.cpp \
source/main.cpp \
source/param.cpp \
source/resource.cpp \
source/resource_helper.cpp \
source/resource_loader.cpp \
source/resource_pack.cpp \
source/screen.cpp \
source/text.cpp \
source/writer.cpp \
source/ui/menu_option.cpp \
source/ui/menu_renderer.cpp \
source/ui/notifier.cpp \
source/ui/service_menu.cpp \
source/ui/ui_message.cpp \
source/ui/window_message.cpp \
source/balloon_formations.cpp \ source/balloon_formations.cpp \
source/balloon_manager.cpp \ source/balloon_manager.cpp \
source/balloon.cpp \ source/balloon.cpp \
source/bullet.cpp \ source/bullet.cpp \
source/bullet_manager.cpp \ source/color.cpp \
source/define_buttons.cpp \
source/difficulty.cpp \
source/director.cpp \
source/enter_name.cpp \ source/enter_name.cpp \
source/explosions.cpp \ source/explosions.cpp \
source/external/gif.cpp \
source/external/jail_audio.cpp \
source/external/jail_shader.cpp \
source/fade.cpp \
source/game_logo.cpp \ source/game_logo.cpp \
source/global_events.cpp \
source/global_inputs.cpp \
source/input_types.cpp \
source/input.cpp \
source/item.cpp \ source/item.cpp \
source/lang.cpp \
source/main.cpp \
source/manage_hiscore_table.cpp \ source/manage_hiscore_table.cpp \
source/mouse.cpp \
source/moving_sprite.cpp \
source/options.cpp \
source/param.cpp \
source/path_sprite.cpp \
source/player.cpp \ source/player.cpp \
source/resource.cpp \
source/resource_helper.cpp \
source/resource_loader.cpp \
source/resource_pack.cpp \
source/scoreboard.cpp \ source/scoreboard.cpp \
source/tabe.cpp \ source/screen.cpp \
source/sections/credits.cpp \ source/sections/credits.cpp \
source/sections/game.cpp \ source/sections/game.cpp \
source/sections/hiscore_table.cpp \ source/sections/hiscore_table.cpp \
@@ -92,39 +95,33 @@ APP_SOURCES := \
source/sections/intro.cpp \ source/sections/intro.cpp \
source/sections/logo.cpp \ source/sections/logo.cpp \
source/sections/title.cpp \ source/sections/title.cpp \
source/animated_sprite.cpp \ source/shutdown.cpp \
source/background.cpp \
source/fade.cpp \
source/moving_sprite.cpp \
source/path_sprite.cpp \
source/smart_sprite.cpp \ source/smart_sprite.cpp \
source/sprite.cpp \ source/sprite.cpp \
source/texture.cpp \
source/tiled_bg.cpp \
source/color.cpp \
source/demo.cpp \
source/define_buttons.cpp \
source/difficulty.cpp \
source/input_types.cpp \
source/mouse.cpp \
source/options.cpp \
source/shutdown.cpp \
source/stage.cpp \ source/stage.cpp \
source/system_utils.cpp \ source/system_utils.cpp \
source/tabe.cpp \
source/text.cpp \
source/texture.cpp \
source/tiled_bg.cpp \
source/ui/menu_option.cpp \
source/ui/menu_renderer.cpp \
source/ui/notifier.cpp \
source/ui/service_menu.cpp \
source/ui/ui_message.cpp \
source/ui/window_message.cpp \
source/utils.cpp \ source/utils.cpp \
source/external/jail_audio.cpp \ source/writer.cpp
source/external/gif.cpp \
source/rendering/sdl3gpu/sdl3gpu_shader.cpp
# Includes # Includes
INCLUDES := -Isource -Isource/external -Isource/rendering -Isource/rendering/sdl3gpu -I$(DIR_BUILD) INCLUDES := -Isource -Isource/external
# Variables según el sistema operativo # Variables según el sistema operativo
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
FixPath = $(subst /,\\,$1) FixPath = $(subst /,\\,$1)
CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -static-libgcc -Wl,-Bstatic -lpthread -Wl,-Bdynamic -Wl,-subsystem,windows -DWINDOWS_BUILD CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -static-libgcc -Wl,-Bstatic -lpthread -Wl,-Bdynamic -Wl,-subsystem,windows -DWINDOWS_BUILD
CXXFLAGS_DEBUG := -std=c++20 -Wall -g -D_DEBUG -DWINDOWS_BUILD CXXFLAGS_DEBUG := -std=c++20 -Wall -g -D_DEBUG -DWINDOWS_BUILD
LDFLAGS := -lmingw32 -lws2_32 -lSDL3 LDFLAGS := -lmingw32 -lws2_32 -lSDL3 -lopengl32
RM := del /Q RM := del /Q
MKDIR := mkdir MKDIR := mkdir
else else
@@ -138,10 +135,12 @@ else
UNAME_S := $(shell uname -s) UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux) ifeq ($(UNAME_S),Linux)
CXXFLAGS += -DLINUX_BUILD CXXFLAGS += -DLINUX_BUILD
LDFLAGS += -lGL
endif endif
ifeq ($(UNAME_S),Darwin) ifeq ($(UNAME_S),Darwin)
CXXFLAGS += -DMACOS_BUILD CXXFLAGS += -Wno-deprecated -DMACOS_BUILD
CXXFLAGS_DEBUG += -DMACOS_BUILD CXXFLAGS_DEBUG += -Wno-deprecated -DMACOS_BUILD
LDFLAGS += -framework OpenGL
# Configurar arquitectura (por defecto arm64, como en CMake) # Configurar arquitectura (por defecto arm64, como en CMake)
CXXFLAGS += -arch arm64 CXXFLAGS += -arch arm64
CXXFLAGS_DEBUG += -arch arm64 CXXFLAGS_DEBUG += -arch arm64
@@ -149,9 +148,9 @@ else
endif endif
# Reglas para herramienta de empaquetado y resources.pack # Reglas para herramienta de empaquetado y resources.pack
$(PACK_TOOL): FORCE $(PACK_TOOL): $(PACK_SOURCES)
@echo "Compilando herramienta de empaquetado..." @echo "Compilando herramienta de empaquetado..."
$(PACK_CXX) -std=c++20 -Wall -Os $(PACK_INCLUDES) $(PACK_SOURCES) -o $(PACK_TOOL) $(PACK_CXX) -std=c++17 -Wall -Os $(PACK_INCLUDES) $(PACK_SOURCES) -o $(PACK_TOOL)
@echo "✓ Herramienta de empaquetado lista: $(PACK_TOOL)" @echo "✓ Herramienta de empaquetado lista: $(PACK_TOOL)"
pack_tool: $(PACK_TOOL) pack_tool: $(PACK_TOOL)
@@ -165,7 +164,7 @@ resources.pack: $(PACK_TOOL)
windows: windows:
@echo off @echo off
@echo Compilando para Windows con nombre: "$(APP_NAME).exe" @echo Compilando para Windows con nombre: "$(APP_NAME).exe"
windres release/windows/coffee.rc -O coff -o $(RESOURCE_FILE) windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
$(CXX) $(APP_SOURCES) $(RESOURCE_FILE) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(WIN_TARGET_FILE).exe" $(CXX) $(APP_SOURCES) $(RESOURCE_FILE) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(WIN_TARGET_FILE).exe"
strip -s -R .comment -R .gnu.version "$(WIN_TARGET_FILE).exe" --strip-unneeded strip -s -R .comment -R .gnu.version "$(WIN_TARGET_FILE).exe" --strip-unneeded
@@ -179,14 +178,11 @@ windows_debug:
@echo Compilando version debug para Windows: "$(APP_NAME)_debug.exe" @echo Compilando version debug para Windows: "$(APP_NAME)_debug.exe"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(WIN_TARGET_FILE)_debug.exe" $(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(WIN_TARGET_FILE)_debug.exe"
windows_release: windows_release: resources.pack
@$(MAKE) pack_tool
@$(MAKE) resources.pack
@echo off @echo off
@echo Creando release para Windows - Version: $(VERSION) @echo Creando release para Windows - Version: $(VERSION)
# Crea carpeta de distribución y carpeta temporal 'RELEASE_FOLDER' # Crea carpeta temporal 'RELEASE_FOLDER'
powershell if (-not (Test-Path "$(DIST_DIR)")) {New-Item "$(DIST_DIR)" -ItemType Directory}
powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force} powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force}
powershell if (-not (Test-Path "$(RELEASE_FOLDER)")) {New-Item "$(RELEASE_FOLDER)" -ItemType Directory} powershell if (-not (Test-Path "$(RELEASE_FOLDER)")) {New-Item "$(RELEASE_FOLDER)" -ItemType Directory}
@@ -197,11 +193,11 @@ windows_release:
# Copia los ficheros que estan en la raíz del proyecto # Copia los ficheros que estan en la raíz del proyecto
powershell Copy-Item "LICENSE" -Destination "$(RELEASE_FOLDER)" powershell Copy-Item "LICENSE" -Destination "$(RELEASE_FOLDER)"
powershell Copy-Item "README.md" -Destination "$(RELEASE_FOLDER)" powershell Copy-Item "README.md" -Destination "$(RELEASE_FOLDER)"
powershell Copy-Item "release\windows\dll\*.dll" -Destination "$(RELEASE_FOLDER)" powershell Copy-Item "release\*.dll" -Destination "$(RELEASE_FOLDER)"
# Compila # Compila
windres release/windows/coffee.rc -O coff -o $(RESOURCE_FILE) windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
$(CXX) $(APP_SOURCES) $(RESOURCE_FILE) $(INCLUDES) -DRELEASE_BUILD $(CXXFLAGS) $(LDFLAGS) -o "$(WIN_RELEASE_FILE).exe" $(CXX) $(APP_SOURCES) $(RESOURCE_FILE) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(WIN_RELEASE_FILE).exe"
strip -s -R .comment -R .gnu.version "$(WIN_RELEASE_FILE).exe" --strip-unneeded strip -s -R .comment -R .gnu.version "$(WIN_RELEASE_FILE).exe" --strip-unneeded
# Crea el fichero .zip # Crea el fichero .zip
@@ -220,87 +216,63 @@ macos_debug:
@echo "Compilando version debug para macOS: $(TARGET_NAME)_debug" @echo "Compilando version debug para macOS: $(TARGET_NAME)_debug"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug" $(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
macos_release: macos_release: resources.pack
@$(MAKE) pack_tool
@$(MAKE) resources.pack
@echo "Creando release para macOS - Version: $(VERSION)" @echo "Creando release para macOS - Version: $(VERSION)"
# Verificar e instalar create-dmg si es necesario
@which create-dmg > /dev/null || (echo "Instalando create-dmg..." && brew install create-dmg)
# Elimina datos de compilaciones anteriores # Elimina datos de compilaciones anteriores
$(RMDIR) "$(RELEASE_FOLDER)" $(RMDIR) "$(RELEASE_FOLDER)"
$(RMDIR) Frameworks
$(RMFILE) tmp.dmg $(RMFILE) tmp.dmg
$(RMFILE) "$(DIST_DIR)"/rw.*
$(RMFILE) "$(MACOS_INTEL_RELEASE)" $(RMFILE) "$(MACOS_INTEL_RELEASE)"
$(RMFILE) "$(MACOS_APPLE_SILICON_RELEASE)" $(RMFILE) "$(MACOS_APPLE_SILICON_RELEASE)"
# Crea la carpeta de distribución y la carpeta temporal con las carpetas obligatorias para una app macOS # Crea la carpeta temporal para hacer el trabajo y las carpetas obligatorias para crear una app de macos
$(MKDIR) "$(DIST_DIR)"
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks" $(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS" $(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS"
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources" $(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
$(MKDIR) Frameworks
# Copia carpetas y ficheros # Copia carpetas y ficheros
cp -R config "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources" cp -R config "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp resources.pack "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources" cp resources.pack "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp -R release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64/SDL3.framework "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks" cp -R release/frameworks/SDL3.xcframework "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
cp release/icons/*.icns "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources" cp -R release/frameworks/SDL3.xcframework Frameworks
cp release/macos/Info.plist "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents" cp release/*.icns "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp release/Info.plist "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents"
cp LICENSE "$(RELEASE_FOLDER)" cp LICENSE "$(RELEASE_FOLDER)"
cp README.md "$(RELEASE_FOLDER)" cp README.md "$(RELEASE_FOLDER)"
# Crea enlaces
ln -s /Applications "$(RELEASE_FOLDER)"/Applications
# Compila la versión para procesadores Intel # Compila la versión para procesadores Intel
ifdef ENABLE_MACOS_X86_64 ifdef ENABLE_MACOS_X86_64
$(CXX) $(APP_SOURCES) $(INCLUDES) -DMACOS_BUNDLE -DMACOS_BUILD -DRELEASE_BUILD -std=c++20 -Wall -Os -Wno-deprecated -framework SDL3 -F release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64 -ffunction-sections -fdata-sections -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.15 $(CXX) $(APP_SOURCES) $(INCLUDES) -DMACOS_BUNDLE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.15
# Firma la aplicación # Firma la aplicación
codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app" codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app"
# Empaqueta el .dmg de la versión Intel con create-dmg # Empaqueta el .dmg de la versión Intel
@echo "Creando DMG Intel con iconos de 96x96..." hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
create-dmg \ hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_INTEL_RELEASE)"
--volname "$(APP_NAME)" \ $(RMFILE) tmp.dmg
--window-pos 200 120 \
--window-size 720 300 \
--icon-size 96 \
--text-size 12 \
--icon "$(APP_NAME).app" 278 102 \
--icon "LICENSE" 441 102 \
--icon "README.md" 604 102 \
--app-drop-link 115 102 \
--hide-extension "$(APP_NAME).app" \
"$(MACOS_INTEL_RELEASE)" \
"$(RELEASE_FOLDER)" || true
@echo "Release Intel creado: $(MACOS_INTEL_RELEASE)" @echo "Release Intel creado: $(MACOS_INTEL_RELEASE)"
endif endif
# Compila la versión para procesadores Apple Silicon # Compila la versión para procesadores Apple Silicon
$(CXX) $(APP_SOURCES) $(INCLUDES) -DMACOS_BUNDLE -DMACOS_BUILD -DRELEASE_BUILD -DSDL_DISABLE_IMMINTRIN_H -std=c++20 -Wall -Os -Wno-deprecated -framework SDL3 -F release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64 -ffunction-sections -fdata-sections -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11 $(CXX) $(APP_SOURCES) $(INCLUDES) -DMACOS_BUNDLE -DSDL_DISABLE_IMMINTRIN_H $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11
# Firma la aplicación # Firma la aplicación
codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app" codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app"
# Empaqueta el .dmg de la versión Apple Silicon con create-dmg # Empaqueta el .dmg de la versión Apple Silicon
@echo "Creando DMG Apple Silicon con iconos de 96x96..." hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
create-dmg \ hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_APPLE_SILICON_RELEASE)"
--volname "$(APP_NAME)" \ $(RMFILE) tmp.dmg
--window-pos 200 120 \
--window-size 720 300 \
--icon-size 96 \
--text-size 12 \
--icon "$(APP_NAME).app" 278 102 \
--icon "LICENSE" 441 102 \
--icon "README.md" 604 102 \
--app-drop-link 115 102 \
--hide-extension "$(APP_NAME).app" \
"$(MACOS_APPLE_SILICON_RELEASE)" \
"$(RELEASE_FOLDER)" || true
@echo "Release Apple Silicon creado: $(MACOS_APPLE_SILICON_RELEASE)" @echo "Release Apple Silicon creado: $(MACOS_APPLE_SILICON_RELEASE)"
# Elimina las carpetas temporales # Elimina las carpetas temporales
$(RMDIR) Frameworks
$(RMDIR) "$(RELEASE_FOLDER)" $(RMDIR) "$(RELEASE_FOLDER)"
$(RMFILE) "$(DIST_DIR)"/rw.*
linux: linux:
@echo "Compilando para Linux: $(TARGET_NAME)" @echo "Compilando para Linux: $(TARGET_NAME)"
@@ -311,12 +283,12 @@ linux_debug:
@echo "Compilando version debug para Linux: $(TARGET_NAME)_debug" @echo "Compilando version debug para Linux: $(TARGET_NAME)_debug"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug" $(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
linux_release: linux_release: resources.pack
@$(MAKE) pack_tool
@$(MAKE) resources.pack
@echo "Creando release para Linux - Version: $(VERSION)" @echo "Creando release para Linux - Version: $(VERSION)"
# Elimina carpetas previas y recrea (crea dist/ si no existe) # Elimina carpetas previas
$(RMDIR) "$(RELEASE_FOLDER)" $(RMDIR) "$(RELEASE_FOLDER)"
# Crea la carpeta temporal para realizar el lanzamiento
$(MKDIR) "$(RELEASE_FOLDER)" $(MKDIR) "$(RELEASE_FOLDER)"
# Copia ficheros # Copia ficheros
@@ -326,7 +298,7 @@ linux_release:
cp README.md "$(RELEASE_FOLDER)" cp README.md "$(RELEASE_FOLDER)"
# Compila # Compila
$(CXX) $(APP_SOURCES) $(INCLUDES) -DRELEASE_BUILD $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)" $(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
# Empaqueta ficheros # Empaqueta ficheros
@@ -337,11 +309,9 @@ linux_release:
# Elimina la carpeta temporal # Elimina la carpeta temporal
$(RMDIR) "$(RELEASE_FOLDER)" $(RMDIR) "$(RELEASE_FOLDER)"
linux_release_desktop: linux_release_desktop: resources.pack
@$(MAKE) pack_tool
@$(MAKE) resources.pack
@echo "Creando release con integracion desktop para Linux - Version: $(VERSION)" @echo "Creando release con integracion desktop para Linux - Version: $(VERSION)"
# Elimina carpetas previas y recrea (crea dist/ si no existe) # Elimina carpetas previas
$(RMDIR) "$(RELEASE_FOLDER)" $(RMDIR) "$(RELEASE_FOLDER)"
# Crea la estructura de directorios estándar para Linux # Crea la estructura de directorios estándar para Linux
@@ -358,7 +328,7 @@ linux_release_desktop:
cp README.md "$(RELEASE_FOLDER)/$(TARGET_NAME)/" cp README.md "$(RELEASE_FOLDER)/$(TARGET_NAME)/"
# Compila el ejecutable # Compila el ejecutable
$(CXX) $(APP_SOURCES) $(INCLUDES) -DRELEASE_BUILD $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin/$(TARGET_NAME)" $(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin/$(TARGET_NAME)"
strip -s -R .comment -R .gnu.version "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin/$(TARGET_NAME)" --strip-unneeded strip -s -R .comment -R .gnu.version "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin/$(TARGET_NAME)" --strip-unneeded
# Crea el archivo .desktop # Crea el archivo .desktop
@@ -376,22 +346,25 @@ linux_release_desktop:
@echo 'Keywords=arcade;action;shooter;retro;' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop" @echo 'Keywords=arcade;action;shooter;retro;' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
# Copia el icono (si existe) y lo redimensiona si es necesario # Copia el icono (si existe) y lo redimensiona si es necesario
@if [ -f "release/icons/icon.png" ]; then \ @if [ -f "release/icon.png" ]; then \
if command -v magick >/dev/null 2>&1; then \ if command -v magick >/dev/null 2>&1; then \
magick "release/icons/icon.png" -resize 256x256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \ magick "release/icon.png" -resize 256x256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
echo "Icono redimensionado de release/icons/icon.png (usando ImageMagick)"; \ echo "Icono redimensionado de release/icon.png (usando ImageMagick)"; \
elif command -v convert >/dev/null 2>&1; then \ elif command -v convert >/dev/null 2>&1; then \
convert "release/icons/icon.png" -resize 256x256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \ convert "release/icon.png" -resize 256x256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
echo "Icono redimensionado de release/icons/icon.png (usando ImageMagick legacy)"; \ echo "Icono redimensionado de release/icon.png (usando ImageMagick legacy)"; \
elif command -v ffmpeg >/dev/null 2>&1; then \ elif command -v ffmpeg >/dev/null 2>&1; then \
ffmpeg -i "release/icons/icon.png" -vf scale=256:256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png" -y -loglevel quiet; \ ffmpeg -i "release/icon.png" -vf scale=256:256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png" -y -loglevel quiet; \
echo "Icono redimensionado de release/icons/icon.png (usando ffmpeg)"; \ echo "Icono redimensionado de release/icon.png (usando ffmpeg)"; \
else \ else \
cp "release/icons/icon.png" "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \ cp "release/icon.png" "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
echo "Icono copiado sin redimensionar (instalar ImageMagick o ffmpeg para redimensionado automatico)"; \ echo "Icono copiado sin redimensionar (instalar ImageMagick o ffmpeg para redimensionado automatico)"; \
fi; \ fi; \
elif [ -f "release/coffee.png" ]; then \
cp "release/coffee.png" "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
echo "Icono copiado desde release/coffee.png"; \
else \ else \
echo "Advertencia: No se encontró release/icons/icon.png - crear icono manualmente"; \ echo "Advertencia: No se encontró release/icon.png ni release/coffee.png - crear icono manualmente"; \
fi fi
# Crea script de instalación # Crea script de instalación
@@ -424,9 +397,9 @@ linux_release_desktop:
chmod +x "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh" chmod +x "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
# Empaqueta ficheros # Empaqueta ficheros
$(RMFILE) "$(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz" $(RMFILE) "$(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz"
tar -czvf "$(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz" -C "$(RELEASE_FOLDER)" . tar -czvf "$(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz" -C "$(RELEASE_FOLDER)" .
@echo "Release con integracion desktop creado: $(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz" @echo "Release con integracion desktop creado: $(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz"
@echo "Para instalar: extraer y ejecutar ./$(TARGET_NAME)/install.sh" @echo "Para instalar: extraer y ejecutar ./$(TARGET_NAME)/install.sh"
# Elimina la carpeta temporal # Elimina la carpeta temporal
@@ -441,12 +414,12 @@ raspi_debug:
@echo "Compilando version debug para Raspberry Pi: $(TARGET_NAME)_debug" @echo "Compilando version debug para Raspberry Pi: $(TARGET_NAME)_debug"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE -DDEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug" $(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE -DDEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
raspi_release: raspi_release: resources.pack
@$(MAKE) pack_tool
@$(MAKE) resources.pack
@echo "Creando release para Raspberry Pi - Version: $(VERSION)" @echo "Creando release para Raspberry Pi - Version: $(VERSION)"
# Elimina carpetas previas y recrea (crea dist/ si no existe) # Elimina carpetas previas
$(RMDIR) "$(RELEASE_FOLDER)" $(RMDIR) "$(RELEASE_FOLDER)"
# Crea la carpeta temporal para realizar el lanzamiento
$(MKDIR) "$(RELEASE_FOLDER)" $(MKDIR) "$(RELEASE_FOLDER)"
# Copia ficheros # Copia ficheros
@@ -456,7 +429,7 @@ raspi_release:
cp README.md "$(RELEASE_FOLDER)" cp README.md "$(RELEASE_FOLDER)"
# Compila # Compila
$(CXX) $(APP_SOURCES) $(INCLUDES) -DRELEASE_BUILD -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)" $(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
# Empaqueta ficheros # Empaqueta ficheros
@@ -467,9 +440,7 @@ raspi_release:
# Elimina la carpeta temporal # Elimina la carpeta temporal
$(RMDIR) "$(RELEASE_FOLDER)" $(RMDIR) "$(RELEASE_FOLDER)"
anbernic: anbernic: resources.pack
@$(MAKE) pack_tool
@$(MAKE) resources.pack
@echo "Compilando para Anbernic: $(TARGET_NAME)" @echo "Compilando para Anbernic: $(TARGET_NAME)"
# Elimina carpetas previas # Elimina carpetas previas
$(RMDIR) "$(RELEASE_FOLDER)"_anbernic $(RMDIR) "$(RELEASE_FOLDER)"_anbernic
@@ -482,7 +453,7 @@ anbernic:
cp resources.pack "$(RELEASE_FOLDER)"_anbernic cp resources.pack "$(RELEASE_FOLDER)"_anbernic
# Compila # Compila
$(CXX) $(APP_SOURCES) $(INCLUDES) -DRELEASE_BUILD -DANBERNIC -DNO_SHADERS -DARCADE -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(RELEASE_FOLDER)_anbernic/$(TARGET_NAME) $(CXX) $(APP_SOURCES) $(INCLUDES) -DANBERNIC -DNO_SHADERS -DARCADE -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(RELEASE_FOLDER)_anbernic/$(TARGET_NAME)
# Opción para deshabilitar audio (equivalente a la opción DISABLE_AUDIO de CMake) # Opción para deshabilitar audio (equivalente a la opción DISABLE_AUDIO de CMake)
no_audio: no_audio:
@@ -516,10 +487,4 @@ help:
@echo " show_version - Mostrar version actual ($(VERSION))" @echo " show_version - Mostrar version actual ($(VERSION))"
@echo " help - Mostrar esta ayuda" @echo " help - Mostrar esta ayuda"
spirv: .PHONY: windows windows_rec windows_debug windows_release macos macos_debug macos_release linux linux_debug linux_release linux_release_desktop raspi raspi_debug raspi_release anbernic no_audio show_version help pack_tool
@echo "Compilando shaders SPIR-V..."
tools/shaders/compile_spirv.sh
.PHONY: windows windows_rec windows_debug windows_release macos macos_debug macos_release linux linux_debug linux_release linux_release_desktop raspi raspi_debug raspi_release anbernic no_audio show_version help pack_tool resources.pack spirv
FORCE:

View File

@@ -1,9 +1,7 @@
<div align="center">
<img src="https://php.sustancia.synology.me/images/ccae/coffee_crisis_arcade_edition_cover_web.png" width="600" alt="Coffee Crisis Cover">
</div>
# Coffee Crisis Arcade Edition # Coffee Crisis Arcade Edition
<img src="https://php.sustancia.synology.me/images/ccae/coffee_crisis_arcade_edition_cover_web.png" width="300" align="left" style="margin-right: 20px; margin-bottom: 10px;" alt="Coffee Crisis Cover">
## ¡La batalla definitiva pel cafè està ací! ## ¡La batalla definitiva pel cafè està ací!
Coffee Crisis Arcade Edition és una versió ampliada i millorada del aclamat Coffee Crisis. Aquesta versió porta l'acció cooperativa al següent nivell, amb: Coffee Crisis Arcade Edition és una versió ampliada i millorada del aclamat Coffee Crisis. Aquesta versió porta l'acció cooperativa al següent nivell, amb:
@@ -37,7 +35,10 @@ El joc està optimitzat per a ser jugat amb un mando de jocs, encara que un dels
> Nota: El joc suporta nomes un jugador amb teclat. > Nota: El joc suporta nomes un jugador amb teclat.
![Coffee Crisis Arcade Edition - Gameplay](https://php.sustancia.synology.me/images/ccae/ccae1.png) <p align="center">
<img src="https://php.sustancia.synology.me/images/ccae/ccae1.png" alt="Joc" width="45%" />
<img src="https://php.sustancia.synology.me/images/ccae/ccae3.png" alt="Joc" width="45%" />
</p>
## Altres tecles ## Altres tecles
@@ -63,8 +64,6 @@ El joc està optimitzat per a ser jugat amb un mando de jocs, encara que un dels
2. Descomprimix i executa l'arxiu `coffee_crisis_arcade_edition.exe`. 2. Descomprimix i executa l'arxiu `coffee_crisis_arcade_edition.exe`.
3. Gaudeix del joc! 3. Gaudeix del joc!
![Coffee Crisis Arcade Edition - Gameplay](https://php.sustancia.synology.me/images/ccae/ccae3.png)
## Agraïments ## Agraïments
Vull expressar la meua gratitud a **ChatGPT** i **GitHub Copilot**. Gràcies per ser un suport constant en el desenvolupament d'aquest joc! Vull expressar la meua gratitud a **ChatGPT** i **GitHub Copilot**. Gràcies per ser un suport constant en el desenvolupament d'aquest joc!

61
TODO.md Normal file
View File

@@ -0,0 +1,61 @@
# TODO
## Tareas pendientes
- [ ] Revisar todas las variables static de los métodos para ver si se resetean correctamente
## Mejoras arquitecturales (refactoring)
### Eliminar variables static locales y usar patrones profesionales:
**Opción 1: Máquina de Estados**
```cpp
class GameCompletedState {
bool start_celebrations_done = false;
bool end_celebrations_done = false;
float timer = 0.0f;
public:
void reset() {
start_celebrations_done = false;
end_celebrations_done = false;
timer = 0.0f;
}
void update(float deltaTime) {
timer += deltaTime;
// lógica aquí
}
};
```
**Opción 2: Sistema de Eventos/Callbacks**
```cpp
// Al entrar en COMPLETED state
eventSystem.scheduleEvent(6.0f, []{ startCelebrations(); });
eventSystem.scheduleEvent(14.0f, []{ endCelebrations(); });
```
**Opción 3: Flags como miembros privados**
```cpp
class Game {
private:
struct GameOverState {
bool game_over_triggered = false;
bool start_celebrations_triggered = false;
bool end_celebrations_triggered = false;
void reset() {
game_over_triggered = false;
start_celebrations_triggered = false;
end_celebrations_triggered = false;
}
} game_over_state_;
};
```
**Ventajas:**
- Más fáciles de testear
- Más fáciles de debugear
- Más fáciles de entender y mantener
- No tienen "estado oculto"

View File

@@ -4,9 +4,8 @@
# Variables: ${PREFIX}, ${SYSTEM_FOLDER} # Variables: ${PREFIX}, ${SYSTEM_FOLDER}
# Archivos de configuración del sistema (absolutos y opcionales) # Archivos de configuración del sistema (absolutos y opcionales)
DATA|${SYSTEM_FOLDER}/config.yaml|optional,absolute DATA|${SYSTEM_FOLDER}/config_v2.txt|optional,absolute
DATA|${SYSTEM_FOLDER}/controllers.json|optional,absolute DATA|${SYSTEM_FOLDER}/controllers.json|optional,absolute
DATA|${SYSTEM_FOLDER}/postfx.yaml|optional,absolute
DATA|${SYSTEM_FOLDER}/score.bin|optional,absolute DATA|${SYSTEM_FOLDER}/score.bin|optional,absolute
# Archivos de configuración del juego # Archivos de configuración del juego
@@ -19,183 +18,192 @@ DATA|${PREFIX}/config/pools.txt
DATA|${PREFIX}/config/stages.txt DATA|${PREFIX}/config/stages.txt
# Archivos con los datos de la demo # Archivos con los datos de la demo
DEMODATA|/data/demo/demo1.bin DEMODATA|${PREFIX}/data/demo/demo1.bin
DEMODATA|/data/demo/demo2.bin DEMODATA|${PREFIX}/data/demo/demo2.bin
DEMODATA|/data/demo/demo3.bin DEMODATA|${PREFIX}/data/demo/demo3.bin
# Música # Música
MUSIC|/data/music/congratulations.ogg MUSIC|${PREFIX}/data/music/congratulations.ogg
MUSIC|/data/music/credits.ogg MUSIC|${PREFIX}/data/music/credits.ogg
MUSIC|/data/music/intro.ogg MUSIC|${PREFIX}/data/music/intro.ogg
MUSIC|/data/music/playing.ogg MUSIC|${PREFIX}/data/music/playing.ogg
MUSIC|/data/music/title.ogg MUSIC|${PREFIX}/data/music/title.ogg
# Sonidos # Sonidos
SOUND|/data/sound/balloon_bounce0.wav SOUND|${PREFIX}/data/sound/balloon_bounce0.wav
SOUND|/data/sound/balloon_bounce1.wav SOUND|${PREFIX}/data/sound/balloon_bounce1.wav
SOUND|/data/sound/balloon_bounce2.wav SOUND|${PREFIX}/data/sound/balloon_bounce2.wav
SOUND|/data/sound/balloon_bounce3.wav SOUND|${PREFIX}/data/sound/balloon_bounce3.wav
SOUND|/data/sound/balloon_pop0.wav SOUND|${PREFIX}/data/sound/balloon_pop0.wav
SOUND|/data/sound/balloon_pop1.wav SOUND|${PREFIX}/data/sound/balloon_pop1.wav
SOUND|/data/sound/balloon_pop2.wav SOUND|${PREFIX}/data/sound/balloon_pop2.wav
SOUND|/data/sound/balloon_pop3.wav SOUND|${PREFIX}/data/sound/balloon_pop3.wav
SOUND|/data/sound/bullet1p.wav SOUND|${PREFIX}/data/sound/bullet1p.wav
SOUND|/data/sound/bullet2p.wav SOUND|${PREFIX}/data/sound/bullet2p.wav
SOUND|/data/sound/clock.wav SOUND|${PREFIX}/data/sound/clock.wav
SOUND|/data/sound/coffee_out.wav SOUND|${PREFIX}/data/sound/coffee_out.wav
SOUND|/data/sound/continue_clock.wav SOUND|${PREFIX}/data/sound/continue_clock.wav
SOUND|/data/sound/credit.wav SOUND|${PREFIX}/data/sound/credit.wav
SOUND|/data/sound/debian_drop.wav SOUND|${PREFIX}/data/sound/debian_drop.wav
SOUND|/data/sound/debian_pickup.wav SOUND|${PREFIX}/data/sound/debian_pickup.wav
SOUND|/data/sound/hi_score_achieved.wav SOUND|${PREFIX}/data/sound/hi_score_achieved.wav
SOUND|/data/sound/item_drop.wav SOUND|${PREFIX}/data/sound/item_drop.wav
SOUND|/data/sound/item_pickup.wav SOUND|${PREFIX}/data/sound/item_pickup.wav
SOUND|/data/sound/jump.wav SOUND|${PREFIX}/data/sound/jump.wav
SOUND|/data/sound/logo.wav SOUND|${PREFIX}/data/sound/logo.wav
SOUND|/data/sound/name_input_accept.wav SOUND|${PREFIX}/data/sound/name_input_accept.wav
SOUND|/data/sound/notify.wav SOUND|${PREFIX}/data/sound/notify.wav
SOUND|/data/sound/player_collision.wav SOUND|${PREFIX}/data/sound/player_collision.wav
SOUND|/data/sound/power_ball_explosion.wav SOUND|${PREFIX}/data/sound/power_ball_explosion.wav
SOUND|/data/sound/service_menu_adjust.wav SOUND|${PREFIX}/data/sound/service_menu_adjust.wav
SOUND|/data/sound/service_menu_back.wav SOUND|${PREFIX}/data/sound/service_menu_back.wav
SOUND|/data/sound/service_menu_move.wav SOUND|${PREFIX}/data/sound/service_menu_move.wav
SOUND|/data/sound/service_menu_select.wav SOUND|${PREFIX}/data/sound/service_menu_select.wav
SOUND|/data/sound/stage_change.wav SOUND|${PREFIX}/data/sound/stage_change.wav
SOUND|/data/sound/tabe_hit.wav SOUND|${PREFIX}/data/sound/tabe_hit.wav
SOUND|/data/sound/tabe.wav SOUND|${PREFIX}/data/sound/tabe.wav
SOUND|/data/sound/title.wav SOUND|${PREFIX}/data/sound/title.wav
SOUND|/data/sound/voice_aw_aw_aw.wav SOUND|${PREFIX}/data/sound/voice_aw_aw_aw.wav
SOUND|/data/sound/voice_coffee.wav SOUND|${PREFIX}/data/sound/voice_coffee.wav
SOUND|/data/sound/voice_credit_thankyou.wav SOUND|${PREFIX}/data/sound/voice_credit_thankyou.wav
SOUND|/data/sound/voice_game_over.wav SOUND|${PREFIX}/data/sound/voice_game_over.wav
SOUND|/data/sound/voice_get_ready.wav SOUND|${PREFIX}/data/sound/voice_get_ready.wav
SOUND|/data/sound/voice_no.wav SOUND|${PREFIX}/data/sound/voice_no.wav
SOUND|/data/sound/voice_power_up.wav SOUND|${PREFIX}/data/sound/voice_power_up.wav
SOUND|/data/sound/voice_recover.wav SOUND|${PREFIX}/data/sound/voice_recover.wav
SOUND|/data/sound/voice_thankyou.wav SOUND|${PREFIX}/data/sound/voice_thankyou.wav
SOUND|/data/sound/walk.wav SOUND|${PREFIX}/data/sound/walk.wav
# Shaders OpenGL (Windows/Linux)
DATA|${PREFIX}/data/shaders/crtpi_vertex.glsl
DATA|${PREFIX}/data/shaders/crtpi_fragment.glsl
# Shaders Metal (macOS) - opcionales
DATA|${PREFIX}/data/shaders/crtpi_vertex.metal|optional
DATA|${PREFIX}/data/shaders/crtpi_fragment.metal|optional
# Texturas - Balloons # Texturas - Balloons
ANIMATION|/data/gfx/balloon/balloon0.ani ANIMATION|${PREFIX}/data/gfx/balloon/balloon0.ani
ANIMATION|/data/gfx/balloon/balloon1.ani ANIMATION|${PREFIX}/data/gfx/balloon/balloon1.ani
ANIMATION|/data/gfx/balloon/balloon2.ani ANIMATION|${PREFIX}/data/gfx/balloon/balloon2.ani
ANIMATION|/data/gfx/balloon/balloon3.ani ANIMATION|${PREFIX}/data/gfx/balloon/balloon3.ani
BITMAP|/data/gfx/balloon/balloon0.png BITMAP|${PREFIX}/data/gfx/balloon/balloon0.png
BITMAP|/data/gfx/balloon/balloon1.png BITMAP|${PREFIX}/data/gfx/balloon/balloon1.png
BITMAP|/data/gfx/balloon/balloon2.png BITMAP|${PREFIX}/data/gfx/balloon/balloon2.png
BITMAP|/data/gfx/balloon/balloon3.png BITMAP|${PREFIX}/data/gfx/balloon/balloon3.png
# Texturas - Explosiones # Texturas - Explosiones
ANIMATION|/data/gfx/balloon/explosion0.ani ANIMATION|${PREFIX}/data/gfx/balloon/explosion0.ani
ANIMATION|/data/gfx/balloon/explosion1.ani ANIMATION|${PREFIX}/data/gfx/balloon/explosion1.ani
ANIMATION|/data/gfx/balloon/explosion2.ani ANIMATION|${PREFIX}/data/gfx/balloon/explosion2.ani
ANIMATION|/data/gfx/balloon/explosion3.ani ANIMATION|${PREFIX}/data/gfx/balloon/explosion3.ani
BITMAP|/data/gfx/balloon/explosion0.png BITMAP|${PREFIX}/data/gfx/balloon/explosion0.png
BITMAP|/data/gfx/balloon/explosion1.png BITMAP|${PREFIX}/data/gfx/balloon/explosion1.png
BITMAP|/data/gfx/balloon/explosion2.png BITMAP|${PREFIX}/data/gfx/balloon/explosion2.png
BITMAP|/data/gfx/balloon/explosion3.png BITMAP|${PREFIX}/data/gfx/balloon/explosion3.png
# Texturas - Power Ball # Texturas - Power Ball
ANIMATION|/data/gfx/balloon/powerball.ani ANIMATION|${PREFIX}/data/gfx/balloon/powerball.ani
BITMAP|/data/gfx/balloon/powerball.png BITMAP|${PREFIX}/data/gfx/balloon/powerball.png
# Texturas - Bala # Texturas - Bala
ANIMATION|/data/gfx/bullet/bullet.ani ANIMATION|${PREFIX}/data/gfx/bullet/bullet.ani
BITMAP|/data/gfx/bullet/bullet.png BITMAP|${PREFIX}/data/gfx/bullet/bullet.png
# Texturas - Tabe # Texturas - Tabe
ANIMATION|/data/gfx/tabe/tabe.ani ANIMATION|${PREFIX}/data/gfx/tabe/tabe.ani
BITMAP|/data/gfx/tabe/tabe.png BITMAP|${PREFIX}/data/gfx/tabe/tabe.png
# Texturas - Juego # Texturas - Juego
BITMAP|/data/gfx/game/game_buildings.png BITMAP|${PREFIX}/data/gfx/game/game_buildings.png
BITMAP|/data/gfx/game/game_clouds1.png BITMAP|${PREFIX}/data/gfx/game/game_clouds1.png
BITMAP|/data/gfx/game/game_clouds2.png BITMAP|${PREFIX}/data/gfx/game/game_clouds2.png
ANIMATION|/data/gfx/game/game_grass.ani BITMAP|${PREFIX}/data/gfx/game/game_grass.png
BITMAP|/data/gfx/game/game_grass.png BITMAP|${PREFIX}/data/gfx/game/game_moon.png
BITMAP|/data/gfx/game/game_moon.png BITMAP|${PREFIX}/data/gfx/game/game_power_meter.png
BITMAP|/data/gfx/game/game_power_meter.png BITMAP|${PREFIX}/data/gfx/game/game_sky_colors.png
BITMAP|/data/gfx/game/game_sky_colors.png BITMAP|${PREFIX}/data/gfx/game/game_sun.png
BITMAP|/data/gfx/game/game_sun.png
# Texturas - Intro # Texturas - Intro
BITMAP|/data/gfx/intro/intro1.png BITMAP|${PREFIX}/data/gfx/intro/intro1.png
BITMAP|/data/gfx/intro/intro2.png BITMAP|${PREFIX}/data/gfx/intro/intro2.png
BITMAP|/data/gfx/intro/intro3.png BITMAP|${PREFIX}/data/gfx/intro/intro3.png
BITMAP|/data/gfx/intro/intro4.png BITMAP|${PREFIX}/data/gfx/intro/intro4.png
BITMAP|/data/gfx/intro/intro5.png BITMAP|${PREFIX}/data/gfx/intro/intro5.png
BITMAP|/data/gfx/intro/intro6.png BITMAP|${PREFIX}/data/gfx/intro/intro6.png
# Texturas - Logo # Texturas - Logo
BITMAP|/data/gfx/logo/logo_jailgames_mini.png BITMAP|${PREFIX}/data/gfx/logo/logo_jailgames_mini.png
BITMAP|/data/gfx/logo/logo_jailgames.png BITMAP|${PREFIX}/data/gfx/logo/logo_jailgames.png
BITMAP|/data/gfx/logo/logo_since_1998.png BITMAP|${PREFIX}/data/gfx/logo/logo_since_1998.png
# Texturas - Items # Texturas - Items
ANIMATION|/data/gfx/item/item_clock.ani ANIMATION|${PREFIX}/data/gfx/item/item_clock.ani
ANIMATION|/data/gfx/item/item_coffee_machine.ani ANIMATION|${PREFIX}/data/gfx/item/item_coffee_machine.ani
ANIMATION|/data/gfx/item/item_coffee.ani ANIMATION|${PREFIX}/data/gfx/item/item_coffee.ani
ANIMATION|/data/gfx/item/item_debian.ani ANIMATION|${PREFIX}/data/gfx/item/item_debian.ani
ANIMATION|/data/gfx/item/item_points1_disk.ani ANIMATION|${PREFIX}/data/gfx/item/item_points1_disk.ani
ANIMATION|/data/gfx/item/item_points2_gavina.ani ANIMATION|${PREFIX}/data/gfx/item/item_points2_gavina.ani
ANIMATION|/data/gfx/item/item_points3_pacmar.ani ANIMATION|${PREFIX}/data/gfx/item/item_points3_pacmar.ani
BITMAP|/data/gfx/item/item_clock.png BITMAP|${PREFIX}/data/gfx/item/item_clock.png
BITMAP|/data/gfx/item/item_coffee_machine.png BITMAP|${PREFIX}/data/gfx/item/item_coffee_machine.png
BITMAP|/data/gfx/item/item_coffee.png BITMAP|${PREFIX}/data/gfx/item/item_coffee.png
BITMAP|/data/gfx/item/item_debian.png BITMAP|${PREFIX}/data/gfx/item/item_debian.png
BITMAP|/data/gfx/item/item_points1_disk.png BITMAP|${PREFIX}/data/gfx/item/item_points1_disk.png
BITMAP|/data/gfx/item/item_points2_gavina.png BITMAP|${PREFIX}/data/gfx/item/item_points2_gavina.png
BITMAP|/data/gfx/item/item_points3_pacmar.png BITMAP|${PREFIX}/data/gfx/item/item_points3_pacmar.png
# Texturas - Titulo # Texturas - Titulo
ANIMATION|/data/gfx/title/title_dust.ani ANIMATION|${PREFIX}/data/gfx/title/title_dust.ani
BITMAP|/data/gfx/title/title_arcade_edition.png BITMAP|${PREFIX}/data/gfx/title/title_arcade_edition.png
BITMAP|/data/gfx/title/title_bg_tile.png BITMAP|${PREFIX}/data/gfx/title/title_bg_tile.png
BITMAP|/data/gfx/title/title_coffee.png BITMAP|${PREFIX}/data/gfx/title/title_coffee.png
BITMAP|/data/gfx/title/title_crisis.png BITMAP|${PREFIX}/data/gfx/title/title_crisis.png
BITMAP|/data/gfx/title/title_dust.png BITMAP|${PREFIX}/data/gfx/title/title_dust.png
# Texturas - Jugador 1 # Texturas - Jugador 1
BITMAP|/data/gfx/player/player1_power.png BITMAP|${PREFIX}/data/gfx/player/player1_power.png
BITMAP|/data/gfx/player/player1.gif BITMAP|${PREFIX}/data/gfx/player/player1.gif
PALETTE|/data/gfx/player/player1_coffee1.pal PALETTE|${PREFIX}/data/gfx/player/player1_coffee1.pal
PALETTE|/data/gfx/player/player1_coffee2.pal PALETTE|${PREFIX}/data/gfx/player/player1_coffee2.pal
PALETTE|/data/gfx/player/player1_invencible.pal PALETTE|${PREFIX}/data/gfx/player/player1_invencible.pal
# Texturas - Jugador 2 # Texturas - Jugador 2
BITMAP|/data/gfx/player/player2_power.png BITMAP|${PREFIX}/data/gfx/player/player2_power.png
BITMAP|/data/gfx/player/player2.gif BITMAP|${PREFIX}/data/gfx/player/player2.gif
PALETTE|/data/gfx/player/player2_coffee1.pal PALETTE|${PREFIX}/data/gfx/player/player2_coffee1.pal
PALETTE|/data/gfx/player/player2_coffee2.pal PALETTE|${PREFIX}/data/gfx/player/player2_coffee2.pal
PALETTE|/data/gfx/player/player2_invencible.pal PALETTE|${PREFIX}/data/gfx/player/player2_invencible.pal
# Animaciones del jugador # Animaciones del jugador
ANIMATION|/data/gfx/player/player_power.ani ANIMATION|${PREFIX}/data/gfx/player/player_power.ani
ANIMATION|/data/gfx/player/player1.ani ANIMATION|${PREFIX}/data/gfx/player/player.ani
ANIMATION|/data/gfx/player/player2.ani
# Texturas - Golpe del jugador
BITMAP|${PREFIX}/data/gfx/player/hit.png
# Fuentes de texto # Fuentes de texto
BITMAP|/data/font/04b_25_2x.png BITMAP|${PREFIX}/data/font/04b_25_2x.png
BITMAP|/data/font/04b_25_2x_white.png BITMAP|${PREFIX}/data/font/04b_25_2x_white.png
BITMAP|/data/font/04b_25_flat_2x.png BITMAP|${PREFIX}/data/font/04b_25_flat_2x.png
BITMAP|/data/font/04b_25_flat.png BITMAP|${PREFIX}/data/font/04b_25_flat.png
BITMAP|/data/font/04b_25_grey.png BITMAP|${PREFIX}/data/font/04b_25_grey.png
BITMAP|/data/font/04b_25_metal.png BITMAP|${PREFIX}/data/font/04b_25_metal.png
BITMAP|/data/font/04b_25_reversed_2x.png BITMAP|${PREFIX}/data/font/04b_25_reversed_2x.png
BITMAP|/data/font/04b_25_reversed.png BITMAP|${PREFIX}/data/font/04b_25_reversed.png
BITMAP|/data/font/04b_25_white.png BITMAP|${PREFIX}/data/font/04b_25_white.png
BITMAP|/data/font/04b_25.png BITMAP|${PREFIX}/data/font/04b_25.png
BITMAP|/data/font/8bithud.png BITMAP|${PREFIX}/data/font/8bithud.png
BITMAP|/data/font/aseprite.png BITMAP|${PREFIX}/data/font/aseprite.png
BITMAP|/data/font/smb2_grad.png BITMAP|${PREFIX}/data/font/smb2_grad.png
BITMAP|/data/font/smb2.png BITMAP|${PREFIX}/data/font/smb2.png
FONT|/data/font/04b_25_2x.txt FONT|${PREFIX}/data/font/04b_25_2x.txt
FONT|/data/font/04b_25.txt FONT|${PREFIX}/data/font/04b_25.txt
FONT|/data/font/8bithud.txt FONT|${PREFIX}/data/font/8bithud.txt
FONT|/data/font/aseprite.txt FONT|${PREFIX}/data/font/aseprite.txt
FONT|/data/font/smb2.txt FONT|${PREFIX}/data/font/smb2.txt
# Idiomas # Idiomas
LANG|/data/lang/ba_BA.json LANG|${PREFIX}/data/lang/ba_BA.json
LANG|/data/lang/en_UK.json LANG|${PREFIX}/data/lang/en_UK.json
LANG|/data/lang/es_ES.json LANG|${PREFIX}/data/lang/es_ES.json

View File

@@ -11,6 +11,8 @@ game.play_area.rect.w 320 # Ancho de la zona jugable
game.play_area.rect.h 200 # Alto de la zona jugable game.play_area.rect.h 200 # Alto de la zona jugable
game.name_entry_idle_time 10 # Segundos para introducir el nombre al finalizar la partida si no se pulsa nada game.name_entry_idle_time 10 # Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida
game.hit_stop false # Indica si debe haber un paro cuando el jugador es golpeado por un globo
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
# --- FADE --- # --- FADE ---
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido fade.color 1F2B30 # Color hexadecimal para el efecto de fundido

View File

@@ -2,6 +2,7 @@
# Formato: PARAMETRO VALOR # Formato: PARAMETRO VALOR
# --- GAME --- # --- GAME ---
game.item_size 20 # Tamaño de los items del juego (en píxeles)
game.item_text_outline_color E0E0E0F0 # Color del outline del texto de los items (RGBA hex) game.item_text_outline_color E0E0E0F0 # Color del outline del texto de los items (RGBA hex)
game.width 320 # Ancho de la resolución nativa del juego (en píxeles) game.width 320 # Ancho de la resolución nativa del juego (en píxeles)
game.height 256 # Alto de la resolución nativa del juego (en píxeles) game.height 256 # Alto de la resolución nativa del juego (en píxeles)
@@ -11,6 +12,8 @@ game.play_area.rect.w 320 # Ancho de la zona jugable
game.play_area.rect.h 216 # Alto de la zona jugable game.play_area.rect.h 216 # Alto de la zona jugable
game.name_entry_idle_time 10 # Segundos para introducir el nombre al finalizar la partida si no se pulsa nada game.name_entry_idle_time 10 # Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida game.name_entry_total_time 60 # Segundos totales para introducir el nombre al finalizar la partida
game.hit_stop false # Indica si debe haber un paro cuando el jugador es golpeado por un globo
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
# --- FADE --- # --- FADE ---
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido fade.color 1F2B30 # Color hexadecimal para el efecto de fundido

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -185,7 +185,7 @@
# 122 z # 122 z
5 5
# 123 { # 123 {
7 3
# 124 | # 124 |
2 2
# 125 } # 125 }

View File

@@ -1,9 +0,0 @@
frame_width=320
frame_height=10
[animation]
name=default
speed=0.2
loop=0
frames=0,1,2,1
[/animation]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -2,15 +2,8 @@ frame_width=20
frame_height=20 frame_height=20
[animation] [animation]
name=blink name=default
speed=0.2 speed=0.1333
loop=0 loop=0
frames=0,1 frames=0,0,1
[/animation]
[animation]
name=no-blink
speed=0
loop=-1
frames=1
[/animation] [/animation]

View File

@@ -2,15 +2,8 @@ frame_width=20
frame_height=20 frame_height=20
[animation] [animation]
name=blink name=default
speed=0.2 speed=0.1333
loop=0 loop=0
frames=0,1 frames=0,0,1
[/animation]
[animation]
name=no-blink
speed=0
loop=-1
frames=1
[/animation] [/animation]

View File

@@ -2,15 +2,8 @@ frame_width=20
frame_height=20 frame_height=20
[animation] [animation]
name=blink name=default
speed=0.2 speed=0.1333
loop=0 loop=0
frames=0,1 frames=0,0,1
[/animation]
[animation]
name=no-blink
speed=0
loop=-1
frames=1
[/animation] [/animation]

View File

@@ -2,15 +2,8 @@ frame_width=20
frame_height=20 frame_height=20
[animation] [animation]
name=blink name=default
speed=0.2 speed=0.1333
loop=0 loop=0
frames=0,1 frames=0,0,1
[/animation]
[animation]
name=no-blink
speed=0
loop=-1
frames=1
[/animation] [/animation]

View File

@@ -2,15 +2,8 @@ frame_width=20
frame_height=20 frame_height=20
[animation] [animation]
name=blink name=default
speed=0.2 speed=0.1333
loop=0 loop=0
frames=0,1 frames=0,0,1
[/animation]
[animation]
name=no-blink
speed=0
loop=-1
frames=1
[/animation] [/animation]

View File

@@ -2,15 +2,8 @@ frame_width=20
frame_height=20 frame_height=20
[animation] [animation]
name=blink name=default
speed=0.2 speed=0.1333
loop=0 loop=0
frames=0,1 frames=0,0,1
[/animation]
[animation]
name=no-blink
speed=0
loop=-1
frames=1
[/animation] [/animation]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 696 B

After

Width:  |  Height:  |  Size: 717 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 624 B

After

Width:  |  Height:  |  Size: 720 B

BIN
data/gfx/player/hit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 B

View File

@@ -110,26 +110,26 @@ frames=38,39,40,41
name=celebration name=celebration
speed=0.167 speed=0.167
loop=0 loop=0
frames=42,42,42,43,44,45,44,43,42,43,44,45,44,43,42,43,44,45,44,43,42,46,46,46,46,46,46,47,48,49,50,50,50,50,50,50,49,49,49,50,50,50,49,49,49,48,47,46,46,46 frames=42,42,42,42,42,42,43,44,45,46,46,46,46,46,46,45,45,45,46,46,46,45,45,45,44,43,42,42,42
[/animation] [/animation]
[animation] [animation]
name=dizzy name=dizzy
speed=0.0833 speed=0.0833
loop=0 loop=0
frames=51,52,53,54,55,56,57 frames=47,48,49,50,51,52,53
[/animation] [/animation]
[animation] [animation]
name=recover name=recover
speed=0.05 speed=0.05
loop=-1 loop=-1
frames=58,58,58,58,59,60,61,62,62,62,63,64,65,62,63,64,65,62,63,64,65,66,66,66,66 frames=54,54,54,54,55,56,57,58,58,58,59,60,61,58,59,60,61,58,59,60,61,62,62,62,62
[/animation] [/animation]
[animation] [animation]
name=hello name=hello
speed=0.05 speed=0.05
loop=-1 loop=-1
frames=67,68,69,70,71,72,73,74,75,76,77,77,77,77,77,77,77,77,77,77,77,77,77,78,79,80,81,82,83,84,85,86,86,85,84,83,83,84,85,86,86,85,84,83,83,84,85,86,86,85,84,83,83,84,85,86,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67 frames=63,64,65,66,67,68,69,70,71,72,73,73,73,73,73,73,73,73,73,73,73,73,73,74,75,76,77,78,79,80,81,82,82,81,80,79,79,80,81,82,82,81,80,79,79,80,81,82,82,81,80,79,79,80,81,82,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63
[/animation] [/animation]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,135 +0,0 @@
frame_width=32
frame_height=32
[animation]
name=walk
speed=0.0833
loop=0
frames=0,1,2,3
[/animation]
[animation]
name=stand
speed=0.167
loop=0
frames=4,5,6,7
[/animation]
[animation]
name=walk-fire-side
speed=0.0833
loop=0
frames=8,9,10,11
[/animation]
[animation]
name=walk-recoil-side
speed=0.0833
loop=0
frames=12,13,14,15
[/animation]
[animation]
name=walk-cool-side
speed=0.0833
loop=0
frames=16,17,18,19
[/animation]
[animation]
name=stand-fire-side
speed=0.0833
loop=0
frames=20
[/animation]
[animation]
name=stand-recoil-side
speed=0.0833
loop=0
frames=21
[/animation]
[animation]
name=stand-cool-side
speed=0.0833
loop=0
frames=22
[/animation]
[animation]
name=walk-fire-center
speed=0.0833
loop=0
frames=23,24,25,26
[/animation]
[animation]
name=walk-recoil-center
speed=0.0833
loop=0
frames=27,28,29,30
[/animation]
[animation]
name=walk-cool-center
speed=0.0833
loop=0
frames=31,32,33,34
[/animation]
[animation]
name=stand-fire-center
speed=0.0833
loop=0
frames=35
[/animation]
[animation]
name=stand-recoil-center
speed=0.0833
loop=0
frames=36
[/animation]
[animation]
name=stand-cool-center
speed=0.0833
loop=0
frames=37
[/animation]
[animation]
name=rolling
speed=0.167
loop=0
frames=38,39,40,41
[/animation]
[animation]
name=celebration
speed=0.167
loop=0
frames=47,47,47,47,47,47,48,49,50,51,51,51,51,51,51,50,50,50,51,51,51,50,50,50,49,48,47,47,47,42,42,42,43,44,45,46,45,46,45,46,45,46,45,46,45,46,45,44,43,42
[/animation]
[animation]
name=dizzy
speed=0.0833
loop=0
frames=52,53,54,55,56,57,58
[/animation]
[animation]
name=recover
speed=0.05
loop=-1
frames=59,59,59,59,60,61,62,63,63,63,64,65,66,63,64,65,66,63,64,65,66,67,67,67,67
[/animation]
[animation]
name=hello
speed=0.05
loop=-1
frames=68,69,70,71,72,73,74,75,76,77,78,78,78,78,78,78,78,78,78,78,78,78,78,79,80,81,82,83,84,85,86,87,87,86,85,84,84,85,86,87,87,86,85,84,84,85,86,87,87,86,85,84,84,85,86,87,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68
[/animation]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -21,7 +21,7 @@
"[GAME_TEXT] 2": "Queden ", "[GAME_TEXT] 2": "Queden ",
"[GAME_TEXT] 2A": " fases mes!", "[GAME_TEXT] 2A": " fases mes!",
"[GAME_TEXT] 3": "Ultima fase!", "[GAME_TEXT] 3": "Ultima fase!",
"[GAME_TEXT] 4": "Automatic!", "[GAME_TEXT] 4": "SuperPoder!",
"[GAME_TEXT] 5": "+1 Colp", "[GAME_TEXT] 5": "+1 Colp",
"[GAME_TEXT] 6": "Temps!", "[GAME_TEXT] 6": "Temps!",
"[GAME_TEXT] 7": "Endavant!", "[GAME_TEXT] 7": "Endavant!",
@@ -79,9 +79,7 @@
"[SERVICE_MENU] SHUTDOWN": "Apagar el sistema", "[SERVICE_MENU] SHUTDOWN": "Apagar el sistema",
"[SERVICE_MENU] FULLSCREEN": "Pantalla completa", "[SERVICE_MENU] FULLSCREEN": "Pantalla completa",
"[SERVICE_MENU] WINDOW_SIZE": "Tamany de la finestra", "[SERVICE_MENU] WINDOW_SIZE": "Tamany de la finestra",
"[SERVICE_MENU] POSTFX": "PostFX", "[SERVICE_MENU] SHADERS": "Filtre",
"[SERVICE_MENU] POSTFX_PRESET": "Preset PostFX",
"[SERVICE_MENU] SUPERSAMPLING": "Supermostreig",
"[SERVICE_MENU] VSYNC": "Sincronisme vertical", "[SERVICE_MENU] VSYNC": "Sincronisme vertical",
"[SERVICE_MENU] INTEGER_SCALE": "Escalat sencer", "[SERVICE_MENU] INTEGER_SCALE": "Escalat sencer",
"[SERVICE_MENU] MAIN_VOLUME": "Volumen general", "[SERVICE_MENU] MAIN_VOLUME": "Volumen general",

View File

@@ -20,7 +20,7 @@
"[GAME_TEXT] 2": "", "[GAME_TEXT] 2": "",
"[GAME_TEXT] 2A": " stages left!", "[GAME_TEXT] 2A": " stages left!",
"[GAME_TEXT] 3": "Last stage!", "[GAME_TEXT] 3": "Last stage!",
"[GAME_TEXT] 4": "AutoFire!", "[GAME_TEXT] 4": "PowerUp",
"[GAME_TEXT] 5": "+1 Hit", "[GAME_TEXT] 5": "+1 Hit",
"[GAME_TEXT] 6": "Stop!", "[GAME_TEXT] 6": "Stop!",
"[GAME_TEXT] 7": "Get Ready!", "[GAME_TEXT] 7": "Get Ready!",
@@ -78,9 +78,7 @@
"[SERVICE_MENU] SHUTDOWN": "Shutdown System", "[SERVICE_MENU] SHUTDOWN": "Shutdown System",
"[SERVICE_MENU] FULLSCREEN": "Fullscreen", "[SERVICE_MENU] FULLSCREEN": "Fullscreen",
"[SERVICE_MENU] WINDOW_SIZE": "Window Zoom", "[SERVICE_MENU] WINDOW_SIZE": "Window Zoom",
"[SERVICE_MENU] POSTFX": "PostFX", "[SERVICE_MENU] SHADERS": "Shaders",
"[SERVICE_MENU] POSTFX_PRESET": "PostFX Preset",
"[SERVICE_MENU] SUPERSAMPLING": "Supersampling",
"[SERVICE_MENU] VSYNC": "V-Sync", "[SERVICE_MENU] VSYNC": "V-Sync",
"[SERVICE_MENU] INTEGER_SCALE": "Integer Scale", "[SERVICE_MENU] INTEGER_SCALE": "Integer Scale",
"[SERVICE_MENU] MAIN_VOLUME": "Main Volume", "[SERVICE_MENU] MAIN_VOLUME": "Main Volume",

View File

@@ -20,7 +20,7 @@
"[GAME_TEXT] 2": "!Quedan ", "[GAME_TEXT] 2": "!Quedan ",
"[GAME_TEXT] 2A": " fases!", "[GAME_TEXT] 2A": " fases!",
"[GAME_TEXT] 3": "Ultima fase!", "[GAME_TEXT] 3": "Ultima fase!",
"[GAME_TEXT] 4": "Automatico!", "[GAME_TEXT] 4": "Potenciador",
"[GAME_TEXT] 5": "+1 Golpe", "[GAME_TEXT] 5": "+1 Golpe",
"[GAME_TEXT] 6": "Tiempo!", "[GAME_TEXT] 6": "Tiempo!",
"[GAME_TEXT] 7": "Adelante!", "[GAME_TEXT] 7": "Adelante!",
@@ -78,9 +78,7 @@
"[SERVICE_MENU] SHUTDOWN": "Apagar el sistema", "[SERVICE_MENU] SHUTDOWN": "Apagar el sistema",
"[SERVICE_MENU] FULLSCREEN": "Pantalla completa", "[SERVICE_MENU] FULLSCREEN": "Pantalla completa",
"[SERVICE_MENU] WINDOW_SIZE": "Zoom de ventana", "[SERVICE_MENU] WINDOW_SIZE": "Zoom de ventana",
"[SERVICE_MENU] POSTFX": "PostFX", "[SERVICE_MENU] SHADERS": "Filtro grafico",
"[SERVICE_MENU] POSTFX_PRESET": "Preset PostFX",
"[SERVICE_MENU] SUPERSAMPLING": "Supersampling",
"[SERVICE_MENU] VSYNC": "Sincronismo vertical", "[SERVICE_MENU] VSYNC": "Sincronismo vertical",
"[SERVICE_MENU] INTEGER_SCALE": "Escalado proporcional", "[SERVICE_MENU] INTEGER_SCALE": "Escalado proporcional",
"[SERVICE_MENU] MAIN_VOLUME": "Volumen general", "[SERVICE_MENU] MAIN_VOLUME": "Volumen general",

View File

@@ -0,0 +1,157 @@
#version 330 core
// Configuración
#define SCANLINES
#define MULTISAMPLE
#define GAMMA
//#define FAKE_GAMMA
//#define CURVATURE
//#define SHARPER
#define MASK_TYPE 2
#define CURVATURE_X 0.05
#define CURVATURE_Y 0.1
#define MASK_BRIGHTNESS 0.80
#define SCANLINE_WEIGHT 6.0
#define SCANLINE_GAP_BRIGHTNESS 0.12
#define BLOOM_FACTOR 3.5
#define INPUT_GAMMA 2.4
#define OUTPUT_GAMMA 2.2
// Inputs desde vertex shader
in vec2 vTexCoord;
in float vFilterWidth;
#if defined(CURVATURE)
in vec2 vScreenScale;
#endif
// Output
out vec4 FragColor;
// Uniforms
uniform sampler2D Texture;
uniform vec2 TextureSize;
#if defined(CURVATURE)
vec2 Distort(vec2 coord)
{
vec2 CURVATURE_DISTORTION = vec2(CURVATURE_X, CURVATURE_Y);
vec2 barrelScale = 1.0 - (0.23 * CURVATURE_DISTORTION);
coord *= vScreenScale;
coord -= vec2(0.5);
float rsq = coord.x * coord.x + coord.y * coord.y;
coord += coord * (CURVATURE_DISTORTION * rsq);
coord *= barrelScale;
if (abs(coord.x) >= 0.5 || abs(coord.y) >= 0.5)
coord = vec2(-1.0);
else
{
coord += vec2(0.5);
coord /= vScreenScale;
}
return coord;
}
#endif
float CalcScanLineWeight(float dist)
{
return max(1.0 - dist * dist * SCANLINE_WEIGHT, SCANLINE_GAP_BRIGHTNESS);
}
float CalcScanLine(float dy)
{
float scanLineWeight = CalcScanLineWeight(dy);
#if defined(MULTISAMPLE)
scanLineWeight += CalcScanLineWeight(dy - vFilterWidth);
scanLineWeight += CalcScanLineWeight(dy + vFilterWidth);
scanLineWeight *= 0.3333333;
#endif
return scanLineWeight;
}
void main()
{
#if defined(CURVATURE)
vec2 texcoord = Distort(vTexCoord);
if (texcoord.x < 0.0) {
FragColor = vec4(0.0);
return;
}
#else
vec2 texcoord = vTexCoord;
#endif
vec2 texcoordInPixels = texcoord * TextureSize;
#if defined(SHARPER)
vec2 tempCoord = floor(texcoordInPixels) + 0.5;
vec2 coord = tempCoord / TextureSize;
vec2 deltas = texcoordInPixels - tempCoord;
float scanLineWeight = CalcScanLine(deltas.y);
vec2 signs = sign(deltas);
deltas.x *= 2.0;
deltas = deltas * deltas;
deltas.y = deltas.y * deltas.y;
deltas.x *= 0.5;
deltas.y *= 8.0;
deltas /= TextureSize;
deltas *= signs;
vec2 tc = coord + deltas;
#else
float tempY = floor(texcoordInPixels.y) + 0.5;
float yCoord = tempY / TextureSize.y;
float dy = texcoordInPixels.y - tempY;
float scanLineWeight = CalcScanLine(dy);
float signY = sign(dy);
dy = dy * dy;
dy = dy * dy;
dy *= 8.0;
dy /= TextureSize.y;
dy *= signY;
vec2 tc = vec2(texcoord.x, yCoord + dy);
#endif
vec3 colour = texture(Texture, tc).rgb;
#if defined(SCANLINES)
#if defined(GAMMA)
#if defined(FAKE_GAMMA)
colour = colour * colour;
#else
colour = pow(colour, vec3(INPUT_GAMMA));
#endif
#endif
scanLineWeight *= BLOOM_FACTOR;
colour *= scanLineWeight;
#if defined(GAMMA)
#if defined(FAKE_GAMMA)
colour = sqrt(colour);
#else
colour = pow(colour, vec3(1.0 / OUTPUT_GAMMA));
#endif
#endif
#endif
#if MASK_TYPE == 0
FragColor = vec4(colour, 1.0);
#elif MASK_TYPE == 1
float whichMask = fract(gl_FragCoord.x * 0.5);
vec3 mask;
if (whichMask < 0.5)
mask = vec3(MASK_BRIGHTNESS, 1.0, MASK_BRIGHTNESS);
else
mask = vec3(1.0, MASK_BRIGHTNESS, 1.0);
FragColor = vec4(colour * mask, 1.0);
#elif MASK_TYPE == 2
float whichMask = fract(gl_FragCoord.x * 0.3333333);
vec3 mask = vec3(MASK_BRIGHTNESS, MASK_BRIGHTNESS, MASK_BRIGHTNESS);
if (whichMask < 0.3333333)
mask.x = 1.0;
else if (whichMask < 0.6666666)
mask.y = 1.0;
else
mask.z = 1.0;
FragColor = vec4(colour * mask, 1.0);
#endif
}

View File

@@ -0,0 +1,152 @@
//
// CRT-Pi Fragment Shader - Metal Shading Language
// Portado desde GLSL a MSL para macOS
//
#include <metal_stdlib>
using namespace metal;
// Configuración (equivalente a los #define en GLSL)
constant bool SCANLINES = true;
constant bool MULTISAMPLE = true;
constant bool GAMMA = true;
constant bool FAKE_GAMMA = false;
constant bool CURVATURE = false;
constant bool SHARPER = false;
constant int MASK_TYPE = 2; // 0=none, 1=green/magenta, 2=trinitron
constant float CURVATURE_X = 0.05;
constant float CURVATURE_Y = 0.1;
constant float MASK_BRIGHTNESS = 0.80;
constant float SCANLINE_WEIGHT = 6.0;
constant float SCANLINE_GAP_BRIGHTNESS = 0.12;
constant float BLOOM_FACTOR = 3.5;
constant float INPUT_GAMMA = 2.4;
constant float OUTPUT_GAMMA = 2.2;
// Estructura de entrada (salida del vertex shader)
struct VertexOut {
float4 position [[position]];
float2 texCoord;
float filterWidth;
// float2 screenScale; // Solo si CURVATURE está activo
};
// Uniforms
struct Uniforms {
float2 textureSize;
};
// Función para calcular el peso de la scanline
float CalcScanLineWeight(float dist) {
return max(1.0 - dist * dist * SCANLINE_WEIGHT, SCANLINE_GAP_BRIGHTNESS);
}
// Función para calcular scanline con multisampling
float CalcScanLine(float dy, float filterWidth) {
float scanLineWeight = CalcScanLineWeight(dy);
if (MULTISAMPLE) {
scanLineWeight += CalcScanLineWeight(dy - filterWidth);
scanLineWeight += CalcScanLineWeight(dy + filterWidth);
scanLineWeight *= 0.3333333;
}
return scanLineWeight;
}
// Entry point del fragment shader
fragment float4 fragment_main(VertexOut in [[stage_in]],
texture2d<float> colorTexture [[texture(0)]],
constant Uniforms& uniforms [[buffer(1)]],
sampler textureSampler [[sampler(0)]]) {
float2 texcoord = in.texCoord;
// Si CURVATURE estuviera activo, aquí iría la función Distort()
float2 texcoordInPixels = texcoord * uniforms.textureSize;
float2 tc;
float scanLineWeight;
if (!SHARPER) {
// Modo normal (no SHARPER)
float tempY = floor(texcoordInPixels.y) + 0.5;
float yCoord = tempY / uniforms.textureSize.y;
float dy = texcoordInPixels.y - tempY;
scanLineWeight = CalcScanLine(dy, in.filterWidth);
float signY = sign(dy);
dy = dy * dy;
dy = dy * dy;
dy *= 8.0;
dy /= uniforms.textureSize.y;
dy *= signY;
tc = float2(texcoord.x, yCoord + dy);
} else {
// Modo SHARPER
float2 tempCoord = floor(texcoordInPixels) + 0.5;
float2 coord = tempCoord / uniforms.textureSize;
float2 deltas = texcoordInPixels - tempCoord;
scanLineWeight = CalcScanLine(deltas.y, in.filterWidth);
float2 signs = sign(deltas);
deltas.x *= 2.0;
deltas = deltas * deltas;
deltas.y = deltas.y * deltas.y;
deltas.x *= 0.5;
deltas.y *= 8.0;
deltas /= uniforms.textureSize;
deltas *= signs;
tc = coord + deltas;
}
// Muestrear textura (texture() en GLSL = sample() en MSL)
float3 colour = colorTexture.sample(textureSampler, tc).rgb;
if (SCANLINES) {
if (GAMMA) {
if (FAKE_GAMMA) {
colour = colour * colour;
} else {
colour = pow(colour, float3(INPUT_GAMMA));
}
}
scanLineWeight *= BLOOM_FACTOR;
colour *= scanLineWeight;
if (GAMMA) {
if (FAKE_GAMMA) {
colour = sqrt(colour);
} else {
colour = pow(colour, float3(1.0 / OUTPUT_GAMMA));
}
}
}
// Aplicar máscara CRT
if (MASK_TYPE == 0) {
return float4(colour, 1.0);
} else if (MASK_TYPE == 1) {
// Máscara verde/magenta
float whichMask = fract(in.position.x * 0.5);
float3 mask;
if (whichMask < 0.5) {
mask = float3(MASK_BRIGHTNESS, 1.0, MASK_BRIGHTNESS);
} else {
mask = float3(1.0, MASK_BRIGHTNESS, 1.0);
}
return float4(colour * mask, 1.0);
} else if (MASK_TYPE == 2) {
// Máscara trinitron
float whichMask = fract(in.position.x * 0.3333333);
float3 mask = float3(MASK_BRIGHTNESS, MASK_BRIGHTNESS, MASK_BRIGHTNESS);
if (whichMask < 0.3333333) {
mask.x = 1.0;
} else if (whichMask < 0.6666666) {
mask.y = 1.0;
} else {
mask.z = 1.0;
}
return float4(colour * mask, 1.0);
}
return float4(colour, 1.0);
}

View File

@@ -0,0 +1,48 @@
#version 330 core
// Configuración
#define SCANLINES
#define MULTISAMPLE
#define GAMMA
//#define FAKE_GAMMA
//#define CURVATURE
//#define SHARPER
#define MASK_TYPE 2
#define CURVATURE_X 0.05
#define CURVATURE_Y 0.1
#define MASK_BRIGHTNESS 0.80
#define SCANLINE_WEIGHT 6.0
#define SCANLINE_GAP_BRIGHTNESS 0.12
#define BLOOM_FACTOR 3.5
#define INPUT_GAMMA 2.4
#define OUTPUT_GAMMA 2.2
// Inputs (desde VAO)
layout(location = 0) in vec2 aPosition;
layout(location = 1) in vec2 aTexCoord;
// Outputs al fragment shader
out vec2 vTexCoord;
out float vFilterWidth;
#if defined(CURVATURE)
out vec2 vScreenScale;
#endif
// Uniforms
uniform vec2 TextureSize;
void main()
{
#if defined(CURVATURE)
vScreenScale = vec2(1.0, 1.0);
#endif
// Calcula filterWidth dinámicamente basándose en la altura de la textura
vFilterWidth = (768.0 / TextureSize.y) / 3.0;
// Pasar coordenadas de textura (invertir Y para SDL)
vTexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y) * 1.0001;
// Posición del vértice (ya en espacio de clip [-1, 1])
gl_Position = vec4(aPosition, 0.0, 1.0);
}

View File

@@ -0,0 +1,46 @@
//
// CRT-Pi Vertex Shader - Metal Shading Language
// Portado desde GLSL a MSL para macOS
//
#include <metal_stdlib>
using namespace metal;
// Estructura de entrada del vertex shader (desde el buffer de vértices)
struct VertexIn {
float2 position [[attribute(0)]]; // Posición del vértice
float2 texCoord [[attribute(1)]]; // Coordenadas de textura
};
// Estructura de salida del vertex shader (entrada al fragment shader)
struct VertexOut {
float4 position [[position]]; // Posición en clip space
float2 texCoord; // Coordenadas de textura
float filterWidth; // Ancho del filtro calculado
// float2 screenScale; // Solo si CURVATURE está activo
};
// Uniforms (constantes del shader)
struct Uniforms {
float2 textureSize; // Tamaño de la textura (width, height)
};
// Entry point del vertex shader
vertex VertexOut vertex_main(VertexIn in [[stage_in]],
constant Uniforms& uniforms [[buffer(1)]]) {
VertexOut out;
// Posición del vértice (ya está en espacio de clip [-1, 1])
out.position = float4(in.position, 0.0, 1.0);
// Pasar coordenadas de textura (invertir Y para SDL, igual que en GLSL)
out.texCoord = float2(in.texCoord.x, 1.0 - in.texCoord.y) * 1.0001;
// Calcular filterWidth dinámicamente basándose en la altura de la textura
out.filterWidth = (768.0 / uniforms.textureSize.y) / 3.0;
// Si CURVATURE estuviera activo:
// out.screenScale = float2(1.0, 1.0);
return out;
}

View File

@@ -1,142 +0,0 @@
#version 450
// Vulkan GLSL fragment shader — PostFX effects
// Used for SDL3 GPU API (SPIR-V path, Win/Linux).
// Compile: glslc postfx.frag -o postfx.frag.spv
// xxd -i postfx.frag.spv > ../../source/core/rendering/sdl3gpu/postfx_frag_spv.h
//
// PostFXUniforms must match exactly the C++ struct in sdl3gpu_shader.hpp
// (8 floats, 32 bytes, std140/scalar layout).
layout(location = 0) in vec2 v_uv;
layout(location = 0) out vec4 out_color;
layout(set = 2, binding = 0) uniform sampler2D scene;
layout(set = 3, binding = 0) uniform PostFXUniforms {
float vignette_strength;
float chroma_strength;
float scanline_strength;
float screen_height;
float mask_strength;
float gamma_strength;
float curvature;
float bleeding;
float pixel_scale; // physical pixels per logical pixel (vh / tex_height_)
float time; // seconds since SDL init
float oversample; // supersampling factor (1.0 = off, 3.0 = 3×SS)
float flicker; // 0 = off, 1 = phosphor flicker ~50 Hz — 48 bytes total (3 × 16)
} u;
// YCbCr helpers for NTSC bleeding
vec3 rgb_to_ycc(vec3 rgb) {
return vec3(
0.299*rgb.r + 0.587*rgb.g + 0.114*rgb.b,
-0.169*rgb.r - 0.331*rgb.g + 0.500*rgb.b + 0.5,
0.500*rgb.r - 0.419*rgb.g - 0.081*rgb.b + 0.5
);
}
vec3 ycc_to_rgb(vec3 ycc) {
float y = ycc.x;
float cb = ycc.y - 0.5;
float cr = ycc.z - 0.5;
return clamp(vec3(
y + 1.402*cr,
y - 0.344*cb - 0.714*cr,
y + 1.772*cb
), 0.0, 1.0);
}
void main() {
vec2 uv = v_uv;
// Curvatura barrel CRT
if (u.curvature > 0.0) {
vec2 c = uv - 0.5;
float rsq = dot(c, c);
vec2 dist = vec2(0.05, 0.1) * u.curvature;
vec2 barrelScale = vec2(1.0) - 0.23 * dist;
c += c * (dist * rsq);
c *= barrelScale;
if (abs(c.x) >= 0.5 || abs(c.y) >= 0.5) {
out_color = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
uv = c + 0.5;
}
// Muestra base
vec3 base = texture(scene, uv).rgb;
// Sangrado NTSC — difuminado horizontal de crominancia.
// step = 1 pixel lógico de juego en UV (corrige SS: textureSize.x = game_w * oversample).
vec3 colour;
if (u.bleeding > 0.0) {
float tw = float(textureSize(scene, 0).x);
float step = u.oversample / tw; // 1 pixel lógico en UV
vec3 ycc = rgb_to_ycc(base);
vec3 ycc_l2 = rgb_to_ycc(texture(scene, uv - vec2(2.0*step, 0.0)).rgb);
vec3 ycc_l1 = rgb_to_ycc(texture(scene, uv - vec2(1.0*step, 0.0)).rgb);
vec3 ycc_r1 = rgb_to_ycc(texture(scene, uv + vec2(1.0*step, 0.0)).rgb);
vec3 ycc_r2 = rgb_to_ycc(texture(scene, uv + vec2(2.0*step, 0.0)).rgb);
ycc.yz = (ycc_l2.yz + ycc_l1.yz*2.0 + ycc.yz*2.0 + ycc_r1.yz*2.0 + ycc_r2.yz) / 8.0;
colour = mix(base, ycc_to_rgb(ycc), u.bleeding);
} else {
colour = base;
}
// Aberración cromática (drift animado con time para efecto NTSC real)
float ca = u.chroma_strength * 0.005 * (1.0 + 0.15 * sin(u.time * 7.3));
colour.r = texture(scene, uv + vec2(ca, 0.0)).r;
colour.b = texture(scene, uv - vec2(ca, 0.0)).b;
// Corrección gamma (linealizar antes de scanlines, codificar después)
if (u.gamma_strength > 0.0) {
vec3 lin = pow(colour, vec3(2.4));
colour = mix(colour, lin, u.gamma_strength);
}
// Scanlines — 1 pixel físico oscuro por fila lógica.
// Modelo sustractivo: las filas de scanline se oscurecen, las demás no cambian.
// Esto evita el efecto de sobrebrillo en contenido con colores vivos.
if (u.scanline_strength > 0.0) {
float ps = max(1.0, round(u.pixel_scale));
float frac_in_row = fract(uv.y * u.screen_height);
float row_pos = floor(frac_in_row * ps);
float is_dark = step(ps - 1.0, row_pos);
float scan = mix(1.0, 0.0, is_dark);
colour *= mix(1.0, scan, u.scanline_strength);
}
if (u.gamma_strength > 0.0) {
vec3 enc = pow(colour, vec3(1.0 / 2.2));
colour = mix(colour, enc, u.gamma_strength);
}
// Viñeta
vec2 d = uv - 0.5;
float vignette = 1.0 - dot(d, d) * u.vignette_strength;
colour *= clamp(vignette, 0.0, 1.0);
// Máscara de fósforo RGB — después de scanlines (orden original):
// filas brillantes saturadas → máscara invisible, filas oscuras → RGB visible.
if (u.mask_strength > 0.0) {
float whichMask = fract(gl_FragCoord.x * 0.3333333);
vec3 mask = vec3(0.80);
if (whichMask < 0.3333333)
mask.x = 1.0;
else if (whichMask < 0.6666666)
mask.y = 1.0;
else
mask.z = 1.0;
colour = mix(colour, colour * mask, u.mask_strength);
}
// Parpadeo de fósforo CRT (~50 Hz)
if (u.flicker > 0.0) {
float flicker_wave = sin(u.time * 100.0) * 0.5 + 0.5;
colour *= 1.0 - u.flicker * 0.04 * flicker_wave;
}
out_color = vec4(colour, 1.0);
}

View File

@@ -1,24 +0,0 @@
#version 450
// Vulkan GLSL vertex shader — postfx full-screen triangle
// Used for SDL3 GPU API (SPIR-V path, Win/Linux).
// Compile: glslc postfx.vert -o postfx.vert.spv
// xxd -i postfx.vert.spv > ../../source/core/rendering/sdl3gpu/postfx_vert_spv.h
layout(location = 0) out vec2 v_uv;
void main() {
// Full-screen triangle (no vertex buffer needed)
const vec2 positions[3] = vec2[3](
vec2(-1.0, -1.0),
vec2( 3.0, -1.0),
vec2(-1.0, 3.0)
);
const vec2 uvs[3] = vec2[3](
vec2(0.0, 1.0),
vec2(2.0, 1.0),
vec2(0.0,-1.0)
);
gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);
v_uv = uvs[gl_VertexIndex];
}

43
development_guidelines.md Normal file
View File

@@ -0,0 +1,43 @@
# Directrices de Desarrollo - Coffee Crisis Arcade Edition
## Directrices Principales Confirmadas
### 1. **Sistema Temporal**
- **TODO migrado de frame based a time based**
- **Delta time en segundos (float)**
- **Unidades de tiempo: SOLO segundos** (no frames, no milisegundos)
### 2. **Contadores y Timers**
- **CRECIENTES**: para sistemas con múltiples eventos temporales (timeline)
- Patrón: `elapsed_time += deltaTime; if (elapsed_time >= EVENT_TIME) { /* acción */ }`
- **DECRECIENTES**: para contadores con diferentes valores de inicialización
- Patrón: `timer -= deltaTime; if (timer <= 0.0f) { /* acción */ timer = DURATION; }`
### 3. **Números Mágicos**
- **Definidos en constantes**
- **Preferencia**: cabecera de la clase
- **Excepción**: si es algo local a un método específico
## Problemas Pendientes de Reparación (game.cpp)
### ❌ PENDIENTES
1. **param.fade.post_duration_ms verification** (líneas 89, 1671)
2. **setRotateSpeed verification** (línea 797)
3. **TOTAL_DEMO_DATA - 200 magic number** (línea 1669)
4. **Comprehensive magic number search** - Buscar 100, 150, 200, 250, 300, 400, 500, 1000
### 4. **Velocidades y Aceleraciones**
- **Velocidades**: pixels/segundo
- **Aceleraciones**: pixels/segundo²
### 5. **Documentación de Conversiones**
- **Comentarios explicativos** en cambios críticos de timing
- Documentar conversiones frame→tiempo en el código
### 6. **Patrón de Constantes**
- Crear constantes para valores repetidos (evitar duplicación)
- Nombres descriptivos para constantes de tiempo
---
**Estado**: Directrices completas confirmadas

View File

@@ -1,24 +1,11 @@
#!/bin/bash #!/bin/bash
# Script para ejecutar clang-tidy en múltiples directorios # Script para ejecutar clang-tidy en múltiples directorios
# Uso: ./run_clang-tidy.sh [--fix] # Uso: ./run_clang-tidy.sh
# --fix: Aplica las correcciones automáticamente (opcional)
# Detectar si se pasó el parámetro --fix
FIX_FLAG=""
if [[ "$1" == "--fix" ]]; then
FIX_FLAG="--fix"
echo "Modo: Aplicando correcciones automáticamente (--fix)"
else
echo "Modo: Solo análisis (sin --fix)"
fi
echo
# Lista de rutas donde ejecutar clang-tidy # Lista de rutas donde ejecutar clang-tidy
PATHS=( PATHS=(
"/home/sergio/gitea/coffee_crisis_arcade_edition/source" "/home/sergio/gitea/coffee_crisis_arcade_edition/source"
"/home/sergio/gitea/coffee_crisis_arcade_edition/source/rendering"
"/home/sergio/gitea/coffee_crisis_arcade_edition/source/rendering/opengl"
"/home/sergio/gitea/coffee_crisis_arcade_edition/source/sections" "/home/sergio/gitea/coffee_crisis_arcade_edition/source/sections"
"/home/sergio/gitea/coffee_crisis_arcade_edition/source/ui" "/home/sergio/gitea/coffee_crisis_arcade_edition/source/ui"
) )
@@ -42,8 +29,8 @@ process_directory() {
cd "$dir" || return 1 cd "$dir" || return 1
# Buscar archivos .cpp, .h, .hpp solo en el nivel actual (no subdirectorios) # Buscar archivos .cpp, .h, .hpp solo en el nivel actual (no subdirectorios)
find . -maxdepth 1 \( -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) -print0 | \ find . -maxdepth 1 \( -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) | \
xargs -0 -P4 -I{} bash -c 'echo "Procesando: {}"; clang-tidy {} -p '"$BUILD_DIR"' '"$FIX_FLAG" xargs -P4 -I{} bash -c 'echo "Procesando: {}"; clang-tidy {} -p '"$BUILD_DIR"' --fix'
echo "=== Completado: $dir ===" echo "=== Completado: $dir ==="
echo echo

View File

@@ -15,8 +15,8 @@ cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -S "$BASE_DIR" -B "$BUILD_DIR"
# 🛠️ Ejecutar IWYU con fix_includes.py # 🛠️ Ejecutar IWYU con fix_includes.py
echo "🚀 Ejecutando IWYU..." echo "🚀 Ejecutando IWYU..."
./iwyu_tool.py -p "$BUILD_DIR" -- -Xiwyu --mapping_file="$MAPPING_FILE" -Xiwyu --verbose=3 \ iwyu_tool.py -p "$BUILD_DIR" -- -Xiwyu --mapping_file="$MAPPING_FILE" -Xiwyu --verbose=3 \
| fix_include --update_comments --reorder --nosafe_headers | python3 /usr/bin/fix_includes.py --update_comments --reorder --nosafe_headers
# 🧹 Reemplazar // for por // Para en líneas de #include # 🧹 Reemplazar // for por // Para en líneas de #include
echo "✍️ Corrigiendo comentarios en includes..." echo "✍️ Corrigiendo comentarios en includes..."

BIN
linux_utils/splash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
release/coffee.res Normal file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More