Compare commits

..

2 Commits

Author SHA1 Message Date
c6c4aebab1 treballant en metal 2025-09-10 23:14:18 +02:00
7f00942517 treballant en metal 2025-09-10 20:44:10 +02:00
740 changed files with 326543 additions and 61989 deletions

View File

@@ -1,7 +1,6 @@
BasedOnStyle: Google
IndentWidth: 4
NamespaceIndentation: All
IndentAccessModifiers: false
IndentAccessModifiers: true
ColumnLimit: 0 # Sin límite de longitud de línea
BreakBeforeBraces: Attach # Llaves en la misma línea
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,4 @@
.vscode/
.claude/
.cache/
.vscode
build/
data/config/config.txt
*.DS_Store
@@ -18,10 +16,4 @@ coffee_crisis*
debug.txt
cppcheck-result*
desktop.ini
dist/
release/windows/coffee.res
resources.pack
# Herramienta pack_resources (todas las plataformas)
tools/pack_resources/pack_resources
tools/pack_resources/pack_resources.exe
ccae_release/

View File

@@ -1,200 +0,0 @@
# CHANGELOG
Historial de canvis i novetats de Coffee Crisis Arcade Edition.
---
## 2026-04-03
- **Nova intro cinematogràfica**: les tarjetes s'llancen des dels costats de la pantalla amb zoom, rotació i rebot, simulant tirar cartes sobre una mesa. Les anteriors ixen despedides girant quan arriba la següent. Sombra amb efecte de perspectiva 2D→3D.
- **Efectes sonors i visuals en la intro**: shake de pantalla i sons configurables a cada impacte de tarjeta.
- **Migració a SDL3 GPU API**: postfx i crtpi migrats a SDL3GPU (Vulkan/Metal/D3D12).
- **Migració de configuració a YAML**: eliminat el format antic, ara tot en YAML.
- **Afegides opcions al Service Menu**.
- **HUD de FPS retocat**, presets per defecte ajustats, finestra a 2x i shader off per defecte.
- **Corregit bug d'input**: revertit un canvi que causava bucle infinit en F3 (pantalla completa) i F12 (service menu) en totes les escenes excepte Game.
- Neteja de codi: eliminades referencies a OpenGL, fitxers GLSL sobrants, normalitzada la carpeta release i el caption de la finestra.
---
## 2025-10-25
- **Migració a delta_time pur** en credits, instructions i hiscore_table. Eliminat un bug que feia que els credits no acabaren mai si no passaves a mà.
- **Corregida deformació subpixel** de textures en instructions i hiscore_table.
- **Detecció de fitxers de puntuació corruptes**.
- **Efecte de pulsos** afegit al scoreboard.
- Al posar nom, el carrusel apareix directament en el caràcter d'acabar si ja havies posat nom abans.
- Integrat jail_audio en la càrrega de resources.pack.
- Pasaeta de linter en múltiples fitxers.
- Nou icon per al joc.
- Corregida la versió release de macOS per a funcionar correctament amb resources.pack.
---
## 2025-08-21
- **Integració amb resources.pack**: textures, animacions, textos, dades de la demo i jail_audio integrats amb ResourceHelper.
- Actualitzat Makefile per a Windows, Linux i macOS.
- Neteja de temporals al acabar.
---
## 2025-08-17
- **Afegit fade RANDOM_SQUARE2** amb timings canviats a mil·lisegons.
- **Outline parametritzat** per als textos dels items.
- **Colors de camiseta parametritzats** per defecte i quan pillen café.
- Creat `defaults.h` amb els valors per defecte de Param.
- Afegit `param_red.txt` amb guardes en setParams.
- Fix: items que es quedaven engantxats a la part de dalt.
- Fix: en el modo demo, assignava cafés al jugador que no jugava.
- Fix: bug en l'estat pre del fade.
- Fix: globos apareixien un frame mal situats al crear-se des d'un pare.
- Afegit suport per a mapejar botons tipus trigger.
---
## 2025-08-10
- **Service Menu complet**: animació d'apertura/tancament, callback per a posar pausa en el joc, refresc visual al canviar mandos.
- **Mandos en calent**: es poden connectar i desconnectar mandos durant el joc, amb notificació visual.
- **PauseManager** afegit al joc.
- **Càrrega de recursos on_demand**.
- Afegit `shutdown.h` i `system_utils.h`.
- Fix: el nom apareixia duplicat en la tabla de records.
- Fix: Game no es desregistrava de ServiceMenu al destruir-se.
- Precàrrega de textures del jugador amb variants de paleta.
- Actualitzats frameworks per a macOS.
---
## 2025-03-25
- **Nova secció Intro** amb escenes seqüencials, animacions de tarjetes i text narratiu.
- **Shaders respecten l'escalat sencer** i SDL_RenderSetLogicalSize en pantalla completa.
- **Tecla per canviar l'integer scale** (F-key).
- Afegit intro03.png i intro04.png.
- Renomenat InputType a InputActions.
- Actualitzat gamecontrollerdb.txt amb mappings de la recreativa.
- Fix: al fer reset des de Game, en Intro no sonava la música.
- Fix: al acabar la partida i vore els records, torna al títol.
- Fix: amb l'àudio mutat, el fade per al soroll de boles el tornava a deixar activat.
---
## 2025-02-07
- **EnterName millorat**: si has omplit tots els slots, apretar una volta mes fixa el nom.
- **Control de repetició per als eixos del joystick**.
- **La tabla de puntuació** mostra amb altre color la puntuació acabada d'afegir i les aconseguides amb 1CC.
- Nova font per a la intro.
- Afegit efecte d'eixida a les instruccions.
- Afegit disparador per a l'aparició de l'enemic nou.
- Duplicada la font 04b_25 per a versió gris i versió negra.
---
## 2025-01-05
- **Optimitzat el circuit de render** en pantalla.
- **Atenuat de pantalla restaurat**: Fade feia dos SDL_SetRenderDrawBlendMode sense restaurar.
- Fix: es podia polsar per a jugar mentre feia el fade cap a la demo.
- Fix: error en la seqüència final de retrocedir en el temps.
- Calibrats els polsos al gust.
- Afegida una lluna i un sol al fondo.
- La powerball ja no es pot destruir fins que no ha fet un rebot.
- Modificada la cadència de foc sense autofire.
- Afegit botó per a activar o desactivar el ratolí.
---
## 2024-12-31
- **Enemic nou** complet: gràfics, comportament, àudio i veus.
- **Fade out sincronitzat** de vídeo i àudio en el títol i el joc.
- **Roidets de col·lisió** per als globos en certs moments.
- La finestra ja es pot fer tan gran com permeta la pantalla (zoom dinàmic).
- Afegides veus al jugador i efectes de so al rebotar quan mor.
- Afegit delay opcional al flash de Screen.
- Afegit botó per activar o desactivar l'autofire.
- Fix: mode demo desactivava els sons permanentment.
- Actualitzat jail_audio.
---
## 2024-12-05
- **Secció Credits acabada** a 320x240 (i per extensió, a qualsevol resolució).
- **Zoom afegit a la classe Sprite** i al subtítol ARCADE EDITION.
- Duplicats fitxers de shaders per a resolucions verticals de 256 i 240.
- Afegit globalInputs::update() a totes les seccions.
- Fix: faltava corregir el flash de destroyAllBalloons().
- Fix: si saltes el logo, talla el so a meitat sonar.
- Canvi d'idioma amb una tecla (i reinicia).
---
## 2024-11-27
- **Secció Credits**: disseny, música, globos amb play_area definida, opció de canviar la paleta al text.
- Afegides traduccions dels credits.
---
## 2024-11-20
- **Nova animació de mort del personatge**: rebots, llengua fora, ulls en X, gràfics de caure derrotat per al segon jugador.
- **Powerball redissenyada**: nous gràfics, nou comportament, ja no mata directament.
- **Globos fills** ja no ixen centrats al pare (evita apilar-se).
- Arreglos en el nom al obtindre la màxima puntuació.
- Acabat BalloonManager.
- CMakeLists.txt crea l'executable en l'arrel del projecte.
- Nova font de text gran amb el doble de definició.
- Fix: paleta verda del primer jugador ajustada a l'original.
---
## 2024-11-03
- **Teclat com a control independent**: ja pot jugar un jugador amb teclat i altre amb mando, o assignar el teclat a qualsevol jugador.
- **Implementat el final del joc** i l'Attract Mode.
- **Nou motor per a textos en pantalla** (game_text amb textures precarregades).
- **Noves animacions** per a deixar de disparar.
- Al redefinir botons, ja no pots repetir botó.
- Fix: l'animació de morir s'actualitzava dos voltes per frame.
- Fix: l'efecte de flash tenia un valor massa xicotet.
---
## 2024-10-28
- **Classe PathSprite completada**: el game_text gasta PathSprites en lloc de SmartSprites.
- **Time stopper redissenyat**.
- La partida sempre comença igual (createTwoBigBalloons).
- Revisades les classes Balloon i Bullet.
- Millorada l'aparició dels game_text.
- Fix: la paleta dels jugadors no s'iniciava correctament.
---
## 2024-10-20
- **Classe Resource creada**: precàrrega de tots els recursos (textures, música, sons, animacions).
- **Paletes de color** per a textures GIF amb shared_ptr.
- Precàrrega i assignació de paletes.
- Implementat comptador per a posar el nom al acabar la partida.
- Classe Notifier independitzada de Screen amb codis identificadors.
- Afegit codi per a apagar el sistema al eixir del joc.
- Fix: globos verds tenien setters mal assignats i velocitat incorrecta.
- Fix: no guardar el fitxer de puntuacions en el mode demo.
---
## 2024-10-14
- **Versió inicial**: clon del repositori de Coffee Crisis, adaptat per a Arcade Edition.
- Pasaeta de include-what-you-use i cppcheck.
- Estandarització de noms segons convencions (CamelCase, camelBack, snake_case).
- Herències de les classes Sprite corregides.
- Canvi a C++ modern amb smart pointers per a la càrrega de surfaces des de GIF.
- Eliminats últims defines i passats a enum class.

101
CLAUDE.md
View File

@@ -1,101 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Coffee Crisis Arcade Edition is a 2-player cooperative arcade shooter built with C++20 and SDL3. Players defend coffee against giant balloons. The game targets Windows, Linux, macOS (Intel/Apple Silicon), Raspberry Pi, and Anbernic handhelds.
## Build Commands
The project uses both CMake and a top-level Makefile. The Makefile is the primary build interface.
### CMake (generates compile_commands.json for IDE/linter support)
```bash
cmake -B build -DCMAKE_BUILD_TYPE=Debug # configure
cmake --build build # build
```
### Makefile (delegates to CMake)
```bash
make # build Release via cmake
make debug # build Debug via cmake
make release # create release package (auto-detects OS)
make linux_release # release tar.gz with resources.pack
make windows_release # release zip for Windows
make macos_release # release dmg for macOS (Intel + Apple Silicon)
make raspi_release # release tar.gz for Raspberry Pi
```
### Tools & Resources
```bash
make pack_tool # compile resource packer
make resources.pack # pack data/ into resources.pack (required for release builds)
make spirv # compile GLSL shaders to SPIR-V headers
```
### Code Quality
```bash
make format # run clang-format on all sources (or: cmake --build build --target format)
make format-check # check formatting without modifying
make tidy # run clang-tidy static analysis (cmake --build build --target tidy)
make tidy-fix # run clang-tidy with auto-fix
```
## Architecture
### Singletons (core systems)
- **Director** (`source/director.hpp`) — Application state machine, orchestrates scene transitions (Logo → Intro → Title → Game → Credits/HiScore → Title)
- **Screen** (`source/screen.hpp`) — Window management, SDL3 GPU rendering pipeline, post-processing effects
- **Resource** (`source/resource.hpp`) — Asset loading/caching with PRELOAD and LAZY_LOAD modes, reads from `resources.pack`
- **Audio** (`source/audio.hpp`) — Music and SFX management
- **Input** (`source/input.hpp`) — Keyboard and gamepad input handling
### Scenes (source/sections/)
Each scene is a self-contained class with update/render lifecycle. Scene flow is managed by Director.
### Entity Managers
- `BalloonManager` / `BulletManager` — Object pool-based entity management
- `Player` — Two-player support (player 1: keyboard, player 2: gamepad)
### Rendering Pipeline
- SDL3 GPU API (Vulkan/Metal/D3D12 backends)
- SPIR-V shaders compiled offline from GLSL (`data/shaders/`) via `glslc`
- Compiled shader headers embedded in `source/rendering/sdl3gpu/postfx_*_spv.h`
- macOS uses Metal (no SPIR-V compilation needed)
### Configuration
- Game parameters: `config/param_320x240.txt`, `config/param_320x256.txt`
- Asset manifest: `config/assets.txt`
- Balloon formations: `config/formations.txt`
- Level definitions: `config/stages.txt`
- Gamepad mappings: `config/gamecontrollerdb.txt`
### External Libraries (header-only/vendored in source/external/)
- nlohmann/json, fkyaml (YAML), stb_image, stb_vorbis, jail_audio
## Code Style
Enforced via `.clang-format` (Google-based) and `.clang-tidy`:
- **Naming conventions**: Classes/structs `CamelCase`, methods/functions `camelBack`, variables/params `snake_case`, private/protected members `snake_case_` (trailing underscore), constants/constexpr `UPPER_CASE`, namespaces `CamelCase`, enum values `UPPER_CASE`
- 4-space indentation, no column limit, braces attach to statement
- clang-tidy treats all warnings as errors
## Conditional Compilation Defines
| Define | Purpose |
|--------|---------|
| `WINDOWS_BUILD` / `LINUX_BUILD` / `MACOS_BUILD` | Platform selection |
| `DEBUG` / `VERBOSE` | Debug output |
| `RELEASE_BUILD` | Release-specific code paths |
| `RECORDING` | Demo recording mode |
| `NO_SHADERS` | Disable shader pipeline (Anbernic) |
| `NO_AUDIO` | Build without audio |
| `ARCADE` | Arcade-specific mode |
| `MACOS_BUNDLE` | macOS .app bundle paths |
| `ANBERNIC` | Anbernic handheld build |
## Language
Code comments are in Spanish/Catalan. Game UI supports multiple languages via JSON files in `data/lang/`.

View File

@@ -6,25 +6,14 @@ project(coffee_crisis_arcade_edition VERSION 2.00)
# Establecer estándar de C++
set(CMAKE_CXX_STANDARD 20)
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 ---
find_package(Git QUIET)
if(GIT_FOUND)
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse --short=7 HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
)
else()
set(GIT_HASH "unknown")
endif()
# Configurar archivo de versión
configure_file(${CMAKE_SOURCE_DIR}/source/version.h.in ${CMAKE_BINARY_DIR}/version.h @ONLY)
# --- 1. LISTA EXPLÍCITA DE FUENTES ---
set(APP_SOURCES
@@ -59,7 +48,6 @@ set(APP_SOURCES
source/balloon_manager.cpp
source/balloon.cpp
source/bullet.cpp
source/bullet_manager.cpp
source/enter_name.cpp
source/explosions.cpp
source/game_logo.cpp
@@ -81,7 +69,6 @@ set(APP_SOURCES
# --- Sprites y Gráficos ---
source/animated_sprite.cpp
source/background.cpp
source/card_sprite.cpp
source/fade.cpp
source/moving_sprite.cpp
source/path_sprite.cpp
@@ -92,7 +79,6 @@ set(APP_SOURCES
# --- Otros ---
source/color.cpp
source/demo.cpp
source/define_buttons.cpp
source/difficulty.cpp
source/input_types.cpp
@@ -106,80 +92,33 @@ set(APP_SOURCES
# Fuentes de librerías de terceros
set(EXTERNAL_SOURCES
source/external/jail_audio.cpp
source/external/jail_shader.cpp
source/external/json.hpp
source/external/gif.cpp
)
# Fuentes del sistema de renderizado
set(RENDERING_SOURCES
source/rendering/sdl3gpu/sdl3gpu_shader.cpp
)
# Añadir archivos específicos para macOS (Metal)
if(APPLE)
list(APPEND EXTERNAL_SOURCES source/external/jail_shader_metal.mm)
endif()
# Añadir jail_audio.cpp solo si el audio está habilitado
if(NOT DISABLE_AUDIO)
list(APPEND EXTERNAL_SOURCES source/external/jail_audio.cpp)
endif()
# Configuración de SDL3
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
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_CRTPI_SRC "${CMAKE_SOURCE_DIR}/data/shaders/crtpi_frag.glsl")
set(SHADER_UPSCALE_SRC "${CMAKE_SOURCE_DIR}/data/shaders/upscale.frag")
set(SHADER_DOWNSCALE_SRC "${CMAKE_SOURCE_DIR}/data/shaders/downscale.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")
set(SHADER_CRTPI_H "${CMAKE_SOURCE_DIR}/source/rendering/sdl3gpu/crtpi_frag_spv.h")
set(SHADER_UPSCALE_H "${CMAKE_SOURCE_DIR}/source/rendering/sdl3gpu/upscale_frag_spv.h")
set(SHADER_DOWNSCALE_H "${CMAKE_SOURCE_DIR}/source/rendering/sdl3gpu/downscale_frag_spv.h")
set(ALL_SHADER_SOURCES "${SHADER_VERT_SRC}" "${SHADER_FRAG_SRC}" "${SHADER_CRTPI_SRC}" "${SHADER_UPSCALE_SRC}" "${SHADER_DOWNSCALE_SRC}")
set(ALL_SHADER_HEADERS "${SHADER_VERT_H}" "${SHADER_FRAG_H}" "${SHADER_CRTPI_H}" "${SHADER_UPSCALE_H}" "${SHADER_DOWNSCALE_H}")
if(GLSLC_EXE)
add_custom_command(
OUTPUT ${ALL_SHADER_HEADERS}
COMMAND "${CMAKE_SOURCE_DIR}/tools/shaders/compile_spirv.sh"
DEPENDS ${ALL_SHADER_SOURCES}
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
COMMENT "Compilando shaders SPIR-V..."
)
add_custom_target(shaders DEPENDS ${ALL_SHADER_HEADERS})
message(STATUS "glslc encontrado: shaders se compilarán automáticamente")
else()
foreach(_h IN LISTS ALL_SHADER_HEADERS)
if(NOT EXISTS "${_h}")
message(FATAL_ERROR
"glslc no encontrado y header SPIR-V no existe: ${_h}\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"
)
endif()
endforeach()
message(STATUS "glslc no encontrado - usando headers SPIR-V precompilados")
endif()
else()
message(STATUS "macOS: shaders SPIR-V omitidos (usa Metal)")
endif()
# --- 2. AÑADIR EJECUTABLE ---
add_executable(${PROJECT_NAME} ${APP_SOURCES} ${EXTERNAL_SOURCES} ${RENDERING_SOURCES})
if(NOT APPLE AND GLSLC_EXE)
add_dependencies(${PROJECT_NAME} shaders)
endif()
add_executable(${PROJECT_NAME} ${APP_SOURCES} ${EXTERNAL_SOURCES})
# --- 3. DIRECTORIOS DE INCLUSIÓN ---
target_include_directories(${PROJECT_NAME} PUBLIC
"${CMAKE_SOURCE_DIR}/source"
"${CMAKE_SOURCE_DIR}/source/external"
"${CMAKE_SOURCE_DIR}/source/rendering"
"${CMAKE_SOURCE_DIR}/source/rendering/sdl3gpu"
"${CMAKE_BINARY_DIR}"
)
# Enlazar la librería SDL3
@@ -194,100 +133,56 @@ target_compile_options(${PROJECT_NAME} PRIVATE $<$<CONFIG:RELEASE>:-Os -ffunctio
# Definir _DEBUG en modo Debug
target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<CONFIG:DEBUG>:_DEBUG>)
# Descomentar la siguiente línea para activar el modo grabación de demos
# target_compile_definitions(${PROJECT_NAME} PRIVATE RECORDING)
# Opción para habilitar/deshabilitar audio
option(DISABLE_AUDIO "Disable audio system" OFF)
# Definir NO_AUDIO si la opción está activada
if(DISABLE_AUDIO)
target_compile_definitions(${PROJECT_NAME} PRIVATE NO_AUDIO)
message(STATUS "Audio deshabilitado - NO_AUDIO definido")
else()
message(STATUS "Audio habilitado")
endif()
# Configuración específica para cada plataforma
if(WIN32)
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)
target_compile_definitions(${PROJECT_NAME} PRIVATE MACOS_BUILD)
if(NOT CMAKE_OSX_ARCHITECTURES)
target_compile_options(${PROJECT_NAME} PRIVATE -Wno-deprecated)
set(CMAKE_OSX_ARCHITECTURES "arm64")
endif()
if(MACOS_BUNDLE)
target_compile_definitions(${PROJECT_NAME} PRIVATE MACOS_BUNDLE)
target_link_options(${PROJECT_NAME} PRIVATE
-framework SDL3
-F ${CMAKE_SOURCE_DIR}/release/macos/frameworks/SDL3.xcframework/macos-arm64_x86_64
-rpath @executable_path/../Frameworks/
)
# Enlazar frameworks de Metal para macOS
find_library(METAL_FRAMEWORK Metal)
find_library(QUARTZCORE_FRAMEWORK QuartzCore)
find_library(COREFOUNDATION_FRAMEWORK CoreFoundation)
find_library(FOUNDATION_FRAMEWORK Foundation)
if(METAL_FRAMEWORK AND QUARTZCORE_FRAMEWORK AND COREFOUNDATION_FRAMEWORK AND FOUNDATION_FRAMEWORK)
target_link_libraries(${PROJECT_NAME} PRIVATE
${METAL_FRAMEWORK}
${QUARTZCORE_FRAMEWORK}
${COREFOUNDATION_FRAMEWORK}
${FOUNDATION_FRAMEWORK})
message(STATUS "Metal frameworks encontrados y enlazados")
else()
message(WARNING "Algunos frameworks de Metal no se encontraron - OpenGL será usado como fallback")
endif()
elseif(UNIX AND NOT APPLE)
target_compile_definitions(${PROJECT_NAME} PRIVATE LINUX_BUILD)
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
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()

495
Makefile
View File

@@ -1,257 +1,269 @@
# ==============================================================================
# DIRECTORIES
# ==============================================================================
# Directorios
DIR_ROOT := $(dir $(abspath $(MAKEFILE_LIST)))
DIR_TOOLS := $(addsuffix /, $(DIR_ROOT)tools)
DIR_SOURCES := $(addsuffix /, $(DIR_ROOT)source)
DIR_BIN := $(addsuffix /, $(DIR_ROOT))
DIR_BUILD := $(addsuffix /, $(DIR_ROOT)build)
# ==============================================================================
# TARGET NAMES
# ==============================================================================
# Variables
TARGET_NAME := coffee_crisis_arcade_edition
TARGET_FILE := $(DIR_ROOT)$(TARGET_NAME)
TARGET_FILE := $(DIR_BIN)$(TARGET_NAME)
APP_NAME := Coffee Crisis Arcade Edition
DIST_DIR := dist
RELEASE_FOLDER := dist/_tmp
RELEASE_FOLDER := ccae_release
RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME)
RESOURCE_FILE := release/windows/coffee.res
RESOURCE_FILE := release/coffee.res
# ==============================================================================
# TOOLS
# ==============================================================================
DIR_PACK_TOOL := $(DIR_TOOLS)pack_resources
SHADER_SCRIPT := $(DIR_ROOT)tools/shaders/compile_spirv.sh
# ==============================================================================
# VERSION (fecha actual)
# ==============================================================================
# Versión automática basada en la fecha actual (específica por SO)
ifeq ($(OS),Windows_NT)
VERSION := $(shell powershell -Command "Get-Date -Format 'yyyy-MM-dd'")
else
VERSION := $(shell date +%Y-%m-%d)
endif
# ==============================================================================
# SHELL (Windows usa cmd.exe)
# ==============================================================================
# Variables específicas para Windows (usando APP_NAME)
ifeq ($(OS),Windows_NT)
SHELL := cmd.exe
endif
# ==============================================================================
# WINDOWS-SPECIFIC VARIABLES
# ==============================================================================
ifeq ($(OS),Windows_NT)
WIN_TARGET_FILE := $(DIR_ROOT)$(APP_NAME)
WIN_TARGET_FILE := $(DIR_BIN)$(APP_NAME)
WIN_RELEASE_FILE := $(RELEASE_FOLDER)/$(APP_NAME)
else
WIN_TARGET_FILE := $(TARGET_FILE)
WIN_RELEASE_FILE := $(RELEASE_FILE)
endif
# ==============================================================================
# RELEASE NAMES
# ==============================================================================
WINDOWS_RELEASE := $(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-win32-x64.zip
MACOS_INTEL_RELEASE := $(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-macos-intel.dmg
MACOS_APPLE_SILICON_RELEASE := $(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-macos-apple-silicon.dmg
LINUX_RELEASE := $(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-linux.tar.gz
RASPI_RELEASE := $(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-raspberry.tar.gz
# Nombres para los ficheros de lanzamiento
WINDOWS_RELEASE := $(TARGET_NAME)-$(VERSION)-win32-x64.zip
MACOS_INTEL_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-intel.dmg
MACOS_APPLE_SILICON_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-apple-silicon.dmg
LINUX_RELEASE := $(TARGET_FILE)-$(VERSION)-linux.tar.gz
RASPI_RELEASE := $(TARGET_FILE)-$(VERSION)-raspberry.tar.gz
# ==============================================================================
# PLATAFORMA
# ==============================================================================
# Lista completa de archivos fuente (basada en CMakeLists.txt)
APP_SOURCES := \
source/animated_sprite.cpp \
source/asset.cpp \
source/audio.cpp \
source/background.cpp \
source/balloon_formations.cpp \
source/balloon_manager.cpp \
source/balloon.cpp \
source/bullet.cpp \
source/color.cpp \
source/define_buttons.cpp \
source/difficulty.cpp \
source/director.cpp \
source/enter_name.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/global_events.cpp \
source/global_inputs.cpp \
source/input_types.cpp \
source/input.cpp \
source/item.cpp \
source/lang.cpp \
source/main.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/resource.cpp \
source/resource_helper.cpp \
source/resource_loader.cpp \
source/resource_pack.cpp \
source/scoreboard.cpp \
source/screen.cpp \
source/sections/credits.cpp \
source/sections/game.cpp \
source/sections/hiscore_table.cpp \
source/sections/instructions.cpp \
source/sections/intro.cpp \
source/sections/logo.cpp \
source/sections/title.cpp \
source/shutdown.cpp \
source/smart_sprite.cpp \
source/sprite.cpp \
source/stage.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/writer.cpp
# Includes
INCLUDES := -Isource -Isource/external
# Variables según el sistema operativo
ifeq ($(OS),Windows_NT)
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_DEBUG := -std=c++20 -Wall -g -D_DEBUG -DWINDOWS_BUILD
LDFLAGS := -lmingw32 -lws2_32 -lSDL3 -lopengl32
RM := del /Q
MKDIR := mkdir
else
FixPath = $1
CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections
CXXFLAGS_DEBUG := -std=c++20 -Wall -g -D_DEBUG
LDFLAGS := -lSDL3
RMFILE := rm -f
RMDIR := rm -rdf
MKDIR := mkdir -p
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
CXXFLAGS += -DLINUX_BUILD
LDFLAGS += -lGL
endif
# ==============================================================================
# COMPILACIÓN CON CMAKE
# ==============================================================================
all:
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
@cmake --build build
debug:
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
@cmake --build build
# ==============================================================================
# RELEASE AUTOMÁTICO (detecta SO)
# ==============================================================================
release:
ifeq ($(OS),Windows_NT)
@"$(MAKE)" windows_release
else
ifeq ($(UNAME_S),Darwin)
@$(MAKE) macos_release
else
@$(MAKE) linux_release
CXXFLAGS += -Wno-deprecated -DMACOS_BUILD
CXXFLAGS_DEBUG += -Wno-deprecated -DMACOS_BUILD
LDFLAGS += -framework OpenGL
# Configurar arquitectura (por defecto arm64, como en CMake)
CXXFLAGS += -arch arm64
CXXFLAGS_DEBUG += -arch arm64
endif
endif
# ==============================================================================
# REGLAS PARA HERRAMIENTA DE EMPAQUETADO Y RESOURCES.PACK
# ==============================================================================
pack_tool:
@$(MAKE) -C $(DIR_PACK_TOOL)
# Reglas para compilación
windows:
@echo off
@echo Compilando para Windows con nombre: "$(APP_NAME).exe"
windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
$(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
resources.pack:
@$(MAKE) -C $(DIR_PACK_TOOL) pack
windows_rec:
@echo off
@echo Compilando version de grabacion para Windows: "$(APP_NAME)_rec.exe"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DRECORDING $(CXXFLAGS) $(LDFLAGS) -o "$(WIN_TARGET_FILE)_rec.exe"
# ==============================================================================
# COMPILACIÓN DE SHADERS
# ==============================================================================
spirv:
@echo "Compilando shaders SPIR-V..."
$(SHADER_SCRIPT)
windows_debug:
@echo off
@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"
# ==============================================================================
# COMPILACIÓN PARA WINDOWS (RELEASE)
# ==============================================================================
windows_release:
@$(MAKE) resources.pack
@echo off
@echo Creando release para Windows - Version: $(VERSION)
# Compila con cmake
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
@cmake --build build
# Crea carpeta de distribución y carpeta temporal 'RELEASE_FOLDER'
@powershell -Command "if (-not (Test-Path '$(DIST_DIR)')) {New-Item '$(DIST_DIR)' -ItemType Directory}"
@powershell -Command "if (Test-Path '$(RELEASE_FOLDER)') {Remove-Item '$(RELEASE_FOLDER)' -Recurse -Force}"
@powershell -Command "if (-not (Test-Path '$(RELEASE_FOLDER)')) {New-Item '$(RELEASE_FOLDER)' -ItemType Directory}"
# Crea carpeta temporal 'RELEASE_FOLDER'
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}
# Copia la carpeta 'config' y el archivo 'resources.pack'
@powershell -Command "Copy-Item -Path 'config' -Destination '$(RELEASE_FOLDER)' -recurse -Force"
@powershell -Command "Copy-Item -Path 'resources.pack' -Destination '$(RELEASE_FOLDER)'"
powershell Copy-Item -Path "config" -Destination "$(RELEASE_FOLDER)" -recurse -Force
powershell Copy-Item -Path "resources.pack" -Destination "$(RELEASE_FOLDER)"
# Copia los ficheros que estan en la raíz del proyecto
@powershell -Command "Copy-Item 'LICENSE' -Destination '$(RELEASE_FOLDER)'"
@powershell -Command "Copy-Item 'README.md' -Destination '$(RELEASE_FOLDER)'"
@powershell -Command "Copy-Item 'release\windows\dll\*.dll' -Destination '$(RELEASE_FOLDER)'"
@powershell -Command "Copy-Item -Path '$(TARGET_FILE)' -Destination '\"$(WIN_RELEASE_FILE).exe\"'"
powershell Copy-Item "LICENSE" -Destination "$(RELEASE_FOLDER)"
powershell Copy-Item "README.md" -Destination "$(RELEASE_FOLDER)"
powershell Copy-Item "release\*.dll" -Destination "$(RELEASE_FOLDER)"
# Compila
windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
$(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
# Crea el fichero .zip
@powershell -Command "if (Test-Path '$(WINDOWS_RELEASE)') {Remove-Item '$(WINDOWS_RELEASE)'}"
@powershell -Command "Compress-Archive -Path '$(RELEASE_FOLDER)/*' -DestinationPath '$(WINDOWS_RELEASE)'"
powershell if (Test-Path "$(WINDOWS_RELEASE)") {Remove-Item "$(WINDOWS_RELEASE)"}
powershell Compress-Archive -Path "$(RELEASE_FOLDER)"/* -DestinationPath "$(WINDOWS_RELEASE)"
@echo Release creado: $(WINDOWS_RELEASE)
# Elimina la carpeta temporal 'RELEASE_FOLDER'
@powershell -Command "if (Test-Path '$(RELEASE_FOLDER)') {Remove-Item '$(RELEASE_FOLDER)' -Recurse -Force}"
powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force}
macos:
@echo "Compilando para macOS: $(TARGET_NAME)"
$(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)"
macos_debug:
@echo "Compilando version debug para macOS: $(TARGET_NAME)_debug"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
# ==============================================================================
# COMPILACIÓN PARA MACOS (RELEASE)
# ==============================================================================
macos_release:
@$(MAKE) resources.pack
@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)
# Compila la versión para procesadores Intel con cmake
@cmake -S . -B build/intel -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_OSX_DEPLOYMENT_TARGET=10.15 -DMACOS_BUNDLE=ON
@cmake --build build/intel
# Elimina datos de compilaciones anteriores
$(RMDIR) "$(RELEASE_FOLDER)"
$(RMDIR) Frameworks
$(RMFILE) tmp.dmg
$(RMFILE) "$(DIST_DIR)"/rw.*
$(RMFILE) "$(MACOS_INTEL_RELEASE)"
$(RMFILE) "$(MACOS_APPLE_SILICON_RELEASE)"
# Crea la carpeta de distribución y la carpeta temporal con las carpetas obligatorias para una app macOS
$(MKDIR) "$(DIST_DIR)"
# Crea la carpeta temporal para hacer el trabajo y las carpetas obligatorias para crear una app de macos
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS"
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
$(MKDIR) Frameworks
# Copia carpetas y ficheros
cp -R config "$(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 release/icons/*.icns "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
cp release/macos/Info.plist "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents"
cp -R release/frameworks/SDL3.xcframework "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
cp -R release/frameworks/SDL3.xcframework Frameworks
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 README.md "$(RELEASE_FOLDER)"
# Copia el ejecutable Intel al bundle
cp "$(TARGET_FILE)" "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)"
# Crea enlaces
ln -s /Applications "$(RELEASE_FOLDER)"/Applications
# Compila la versión para procesadores Intel
ifdef ENABLE_MACOS_X86_64
$(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
codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app"
# Empaqueta el .dmg de la versión Intel con create-dmg
@echo "Creando DMG Intel con iconos de 96x96..."
create-dmg \
--volname "$(APP_NAME)" \
--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
# Empaqueta el .dmg de la versión Intel
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_INTEL_RELEASE)"
$(RMFILE) tmp.dmg
@echo "Release Intel creado: $(MACOS_INTEL_RELEASE)"
endif
# Compila la versión para procesadores Apple Silicon con cmake
@cmake -S . -B build/arm -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_OSX_DEPLOYMENT_TARGET=11.0 -DMACOS_BUNDLE=ON
@cmake --build build/arm
cp "$(TARGET_FILE)" "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)"
# Compila la versión para procesadores Apple Silicon
$(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
codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app"
# Empaqueta el .dmg de la versión Apple Silicon con create-dmg
@echo "Creando DMG Apple Silicon con iconos de 96x96..."
create-dmg \
--volname "$(APP_NAME)" \
--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
# Empaqueta el .dmg de la versión Apple Silicon
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_APPLE_SILICON_RELEASE)"
$(RMFILE) tmp.dmg
@echo "Release Apple Silicon creado: $(MACOS_APPLE_SILICON_RELEASE)"
# Elimina las carpetas temporales
$(RMDIR) Frameworks
$(RMDIR) "$(RELEASE_FOLDER)"
$(RMDIR) build/intel
$(RMDIR) build/arm
$(RMFILE) "$(DIST_DIR)"/rw.*
# ==============================================================================
# COMPILACIÓN PARA LINUX (RELEASE)
# ==============================================================================
linux:
@echo "Compilando para Linux: $(TARGET_NAME)"
$(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)"
strip -s -R .comment -R .gnu.version "$(TARGET_FILE)" --strip-unneeded
linux_debug:
@echo "Compilando version debug para Linux: $(TARGET_NAME)_debug"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
linux_release:
@$(MAKE) resources.pack
@echo "Creando release para Linux - Version: $(VERSION)"
# Compila con cmake
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
@cmake --build build
# Elimina carpeta temporal previa y la recrea (crea dist/ si no existe)
# Elimina carpetas previas
$(RMDIR) "$(RELEASE_FOLDER)"
# Crea la carpeta temporal para realizar el lanzamiento
$(MKDIR) "$(RELEASE_FOLDER)"
# Copia ficheros
@@ -259,7 +271,9 @@ linux_release:
cp resources.pack "$(RELEASE_FOLDER)"
cp LICENSE "$(RELEASE_FOLDER)"
cp README.md "$(RELEASE_FOLDER)"
cp "$(TARGET_FILE)" "$(RELEASE_FILE)"
# Compila
$(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
# Empaqueta ficheros
@@ -270,18 +284,9 @@ linux_release:
# Elimina la carpeta temporal
$(RMDIR) "$(RELEASE_FOLDER)"
# ==============================================================================
# COMPILACIÓN PARA LINUX (RELEASE CON INTEGRACIÓN DESKTOP)
# ==============================================================================
linux_release_desktop:
@$(MAKE) resources.pack
@echo "Creando release con integracion desktop para Linux - Version: $(VERSION)"
# Compila con cmake
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
@cmake --build build
# Elimina carpetas previas y recrea (crea dist/ si no existe)
# Elimina carpetas previas
$(RMDIR) "$(RELEASE_FOLDER)"
# Crea la estructura de directorios estándar para Linux
@@ -297,8 +302,8 @@ linux_release_desktop:
cp LICENSE "$(RELEASE_FOLDER)/$(TARGET_NAME)/"
cp README.md "$(RELEASE_FOLDER)/$(TARGET_NAME)/"
# Copia el ejecutable
cp "$(TARGET_FILE)" "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin/$(TARGET_NAME)"
# Compila el ejecutable
$(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
# Crea el archivo .desktop
@@ -316,22 +321,25 @@ linux_release_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
@if [ -f "release/icons/icon.png" ]; then \
@if [ -f "release/icon.png" ]; 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"; \
echo "Icono redimensionado de release/icons/icon.png (usando ImageMagick)"; \
magick "release/icon.png" -resize 256x256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
echo "Icono redimensionado de release/icon.png (usando ImageMagick)"; \
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"; \
echo "Icono redimensionado de release/icons/icon.png (usando ImageMagick legacy)"; \
convert "release/icon.png" -resize 256x256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
echo "Icono redimensionado de release/icon.png (usando ImageMagick legacy)"; \
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; \
echo "Icono redimensionado de release/icons/icon.png (usando ffmpeg)"; \
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/icon.png (usando ffmpeg)"; \
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)"; \
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 \
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
# Crea script de instalación
@@ -364,27 +372,29 @@ linux_release_desktop:
chmod +x "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
# Empaqueta ficheros
$(RMFILE) "$(DIST_DIR)/$(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz"
tar -czvf "$(DIST_DIR)/$(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"
$(RMFILE) "$(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz"
tar -czvf "$(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz" -C "$(RELEASE_FOLDER)" .
@echo "Release con integracion desktop creado: $(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz"
@echo "Para instalar: extraer y ejecutar ./$(TARGET_NAME)/install.sh"
# Elimina la carpeta temporal
$(RMDIR) "$(RELEASE_FOLDER)"
# ==============================================================================
# COMPILACIÓN PARA RASPBERRY PI (RELEASE)
# ==============================================================================
raspi:
@echo "Compilando para Raspberry Pi: $(TARGET_NAME)"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(TARGET_FILE)
strip -s -R .comment -R .gnu.version $(TARGET_FILE) --strip-unneeded
raspi_debug:
@echo "Compilando version debug para Raspberry Pi: $(TARGET_NAME)_debug"
$(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE -DDEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
raspi_release:
@$(MAKE) resources.pack
@echo "Creando release para Raspberry Pi - Version: $(VERSION)"
# Compila con cmake
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
@cmake --build build
# Elimina carpetas previas y recrea (crea dist/ si no existe)
# Elimina carpetas previas
$(RMDIR) "$(RELEASE_FOLDER)"
# Crea la carpeta temporal para realizar el lanzamiento
$(MKDIR) "$(RELEASE_FOLDER)"
# Copia ficheros
@@ -392,7 +402,9 @@ raspi_release:
cp resources.pack "$(RELEASE_FOLDER)"
cp LICENSE "$(RELEASE_FOLDER)"
cp README.md "$(RELEASE_FOLDER)"
cp "$(TARGET_FILE)" "$(RELEASE_FILE)"
# Compila
$(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
# Empaqueta ficheros
@@ -403,60 +415,49 @@ raspi_release:
# Elimina la carpeta temporal
$(RMDIR) "$(RELEASE_FOLDER)"
# ==============================================================================
# CODE QUALITY (delegados a cmake)
# ==============================================================================
format:
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
@cmake --build build --target format
anbernic:
@echo "Compilando para Anbernic: $(TARGET_NAME)"
# Elimina carpetas previas
$(RMDIR) "$(RELEASE_FOLDER)"_anbernic
format-check:
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
@cmake --build build --target format-check
# Crea la carpeta temporal para realizar el lanzamiento
$(MKDIR) "$(RELEASE_FOLDER)"_anbernic
tidy:
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
@cmake --build build --target tidy
# Copia ficheros
cp -R config "$(RELEASE_FOLDER)"_anbernic
cp resources.pack "$(RELEASE_FOLDER)"_anbernic
tidy-fix:
@cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
@cmake --build build --target tidy-fix
# Compila
$(CXX) $(APP_SOURCES) $(INCLUDES) -DANBERNIC -DNO_SHADERS -DARCADE -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(RELEASE_FOLDER)_anbernic/$(TARGET_NAME)
# ==============================================================================
# REGLAS ESPECIALES
# ==============================================================================
# Opción para deshabilitar audio (equivalente a la opción DISABLE_AUDIO de CMake)
no_audio:
@echo "Compilando sin audio: $(TARGET_NAME)_no_audio"
$(CXX) $(filter-out source/external/jail_audio.cpp,$(APP_SOURCES)) $(INCLUDES) -DNO_AUDIO $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)_no_audio"
# Regla para mostrar la versión actual
show_version:
@echo "Version actual: $(VERSION)"
# Regla de ayuda
help:
@echo "Makefile para Coffee Crisis Arcade Edition"
@echo "Comandos disponibles:"
@echo ""
@echo " Compilacion:"
@echo " make - Compilar con cmake (Release)"
@echo " make debug - Compilar con cmake (Debug)"
@echo ""
@echo " Release:"
@echo " make release - Crear release (detecta SO automaticamente)"
@echo " make windows_release - Crear release para Windows"
@echo " make linux_release - Crear release basico para Linux"
@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 ""
@echo " Herramientas:"
@echo " make spirv - Compilar shaders SPIR-V"
@echo " make pack_tool - Compilar herramienta de empaquetado"
@echo " make resources.pack - Generar pack de recursos desde data/"
@echo ""
@echo " Calidad de codigo:"
@echo " make format - Formatear codigo con clang-format"
@echo " make format-check - Verificar formato sin modificar"
@echo " make tidy - Analisis estatico con clang-tidy"
@echo " make tidy-fix - Analisis estatico con auto-fix"
@echo ""
@echo " Otros:"
@echo " make show_version - Mostrar version actual ($(VERSION))"
@echo " make help - Mostrar esta ayuda"
@echo " windows - Compilar para Windows"
@echo " windows_debug - Compilar debug para Windows"
@echo " windows_release - Crear release completo para Windows"
@echo " linux - Compilar para Linux"
@echo " linux_debug - Compilar debug para Linux"
@echo " linux_release - Crear release basico para Linux"
@echo " linux_release_desktop - Crear release con integracion desktop para Linux"
@echo " macos - Compilar para macOS"
@echo " macos_debug - Compilar debug para macOS"
@echo " macos_release - Crear release completo para macOS"
@echo " raspi - Compilar para Raspberry Pi"
@echo " raspi_release - Crear release completo para Raspberry Pi"
@echo " anbernic - Compilar para Anbernic"
@echo " no_audio - Compilar sin sistema de audio"
@echo " show_version - Mostrar version actual ($(VERSION))"
@echo " 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: 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

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
<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í!
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.
![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
@@ -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`.
3. Gaudeix del joc!
![Coffee Crisis Arcade Edition - Gameplay](https://php.sustancia.synology.me/images/ccae/ccae3.png)
## 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!

View File

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

View File

@@ -8,270 +8,270 @@
formation: 0
# Dos enemigos BALLOON3 uno a cada extremo
X3_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.0000
X3_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.0000
X3_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0
X3_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0
formation: 1
# Dos enemigos BALLOON3 uno a cada cuarto. Ambos van hacia el centro
X3_25, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.0000
X3_75, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.0000
X3_25, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0
X3_75, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0
formation: 2
# Cuatro enemigos BALLOON1 uno detrás del otro. A la izquierda y hacia el centro
X1_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.5000
X1_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.3333
X1_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.1667
X1_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.0000
X1_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 30
X1_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 20
X1_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 10
X1_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0
formation: 3
# Cuatro enemigos BALLOON1 uno detrás del otro. A la derecha y hacia el centro
X1_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.5000
X1_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.3333
X1_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.1667
X1_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.0000
X1_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 30
X1_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 20
X1_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 10
X1_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0
formation: 4
# Tres enemigos BALLOON2. 0, 25, 50. Hacia la derecha
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.3333
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.1667
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.0000
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 20
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 10
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0
formation: 5
# Tres enemigos BALLOON2. 50, 75, 100. Hacia la izquierda
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.3333
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.1667
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.0000
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 20
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 10
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0
formation: 6
# Tres enemigos BALLOON2. 0, 0, 0. Hacia la derecha
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.3333
X2_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.1667
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.0000
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 20
X2_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 10
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0
formation: 7
# Tres enemigos BALLOON2. 100, 100, 100. Hacia la izquierda
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.3333
X2_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.1667
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.0000
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 20
X2_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 10
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0
formation: 8
# Seis enemigos BALLOON0. 0, 0, 0, 0, 0, 0. Hacia la derecha
X0_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.8333
X0_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.6667
X0_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.5000
X0_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.3333
X0_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.1667
X0_0, 5, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.0000
X0_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 50
X0_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 40
X0_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 30
X0_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 20
X0_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 10
X0_0, 5, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0
formation: 9
# Seis enemigos BALLOON0. 100, 100, 100, 100, 100, 100. Hacia la izquierda
X0_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.8333
X0_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.6667
X0_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.5000
X0_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.3333
X0_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.1667
X0_100, -5, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.0000
X0_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 50
X0_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 40
X0_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 30
X0_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 20
X0_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 10
X0_100, -5, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0
formation: 10
# Tres enemigos BALLOON3 seguidos desde la izquierda. Hacia la derecha
X3_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.5000
X3_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.2500
X3_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.0000
X3_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 30
X3_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 15
X3_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0
formation: 11
# Tres enemigos BALLOON3 seguidos desde la derecha. Hacia la izquierda
X3_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.5000
X3_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.2500
X3_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.0000
X3_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 30
X3_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 15
X3_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0
formation: 12
# Seis enemigos BALLOON1 uno detrás del otro. A la izquierda y hacia el centro
X1_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.8333
X1_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.6667
X1_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.5000
X1_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.3333
X1_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.1667
X1_0, 5, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.0000
X1_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 50
X1_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 40
X1_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 30
X1_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 20
X1_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 10
X1_0, 5, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0
formation: 13
# Seis enemigos BALLOON1 uno detrás del otro. A la derecha y hacia el centro
X1_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.8333
X1_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.6667
X1_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.5000
X1_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.3333
X1_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.1667
X1_100, -5, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.0000
X1_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 50
X1_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 40
X1_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 30
X1_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 20
X1_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 10
X1_100, -5, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0
formation: 14
# Cinco enemigos BALLOON2. Hacia la derecha. Separados
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.6667
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.5000
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.3333
X2_0, 6, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.1667
X2_0, 8, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.0000
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 40
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 30
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 20
X2_0, 6, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 10
X2_0, 8, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0
formation: 15
# Cinco enemigos BALLOON2. Hacia la izquierda. Separados
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.6667
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.5000
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.3333
X2_100, -6, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.1667
X2_100, -8, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.0000
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 40
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 30
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 20
X2_100, -6, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 10
X2_100, -8, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0
formation: 16
# Cinco enemigos BALLOON2. Hacia la derecha. Juntos
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.6667
X2_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.5000
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.3333
X2_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.1667
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.0000
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 40
X2_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 30
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 20
X2_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 10
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0
formation: 17
# Cinco enemigos BALLOON2. Hacia la izquierda. Juntos
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.6667
X2_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.5000
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.3333
X2_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.1667
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.0000
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 40
X2_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 30
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 20
X2_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 10
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0
formation: 18
# Doce enemigos BALLOON0. Hacia la derecha. Juntos
X0_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.8333
X0_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.6667
X0_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.5000
X0_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.3333
X0_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.1667
X0_0, 5, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.0000
X0_0, 6, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.8333
X0_0, 7, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.6667
X0_0, 8, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.5000
X0_0, 9, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.3333
X0_0, 10, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.1667
X0_0, 11, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.0000
X0_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 110
X0_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 100
X0_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 90
X0_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 80
X0_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 70
X0_0, 5, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 60
X0_0, 6, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 50
X0_0, 7, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 40
X0_0, 8, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 30
X0_0, 9, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 20
X0_0, 10, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 10
X0_0, 11, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0
formation: 19
# Doce enemigos BALLOON0. Hacia la izquierda. Juntos
X0_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.8333
X0_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.6667
X0_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.5000
X0_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.3333
X0_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.1667
X0_100, -5, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.0000
X0_100, -6, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.8333
X0_100, -7, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.6667
X0_100, -8, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.5000
X0_100, -9, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.3333
X0_100, -10, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.1667
X0_100, -11, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.0000
X0_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 110
X0_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 100
X0_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 90
X0_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 80
X0_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 70
X0_100, -5, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 60
X0_100, -6, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 50
X0_100, -7, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 40
X0_100, -8, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 30
X0_100, -9, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 20
X0_100, -10, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 10
X0_100, -11, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0
formation: 20
# Cuatro enemigos BALLOON3 seguidos desde la izquierda/derecha. Simétricos
X3_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.0000
X3_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0.0000
X3_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.0000
X3_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0.0000
X3_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0
X3_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, EXTRALARGE, 0
X3_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0
X3_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, EXTRALARGE, 0
formation: 21
# Diez enemigos BALLOON1 uno detrás del otro. Izquierda/derecha. Simétricos
X1_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.2000
X1_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.1500
X1_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.1000
X1_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.0500
X1_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0.0000
X1_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.2000
X1_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.1500
X1_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.1000
X1_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.0500
X1_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0.0000
X1_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 12
X1_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 9
X1_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 6
X1_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 3
X1_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, MEDIUM, 0
X1_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 12
X1_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 9
X1_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 6
X1_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 3
X1_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, MEDIUM, 0
formation: 22
# Diez enemigos BALLOON2. Hacia la derecha/izquierda. Separados. Simétricos
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.6667
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.5000
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.3333
X2_0, 6, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.1667
X2_0, 8, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.0000
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.6667
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.5000
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.3333
X2_100, -6, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.1667
X2_100, -8, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.0000
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 40
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 30
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 20
X2_0, 6, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 10
X2_0, 8, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 40
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 30
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 20
X2_100, -6, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 10
X2_100, -8, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0
formation: 23
# Diez enemigos BALLOON2. Hacia la derecha. Juntos. Simétricos
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.6667
X2_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.5000
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.3333
X2_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.1667
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0.0000
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.6667
X2_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.5000
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.3333
X2_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.1667
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0.0000
X2_0, 0, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 40
X2_0, 1, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 30
X2_0, 2, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 20
X2_0, 3, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 10
X2_0, 4, DEFAULT_POS_Y, RIGHT, BALLOON, LARGE, 0
X2_100, 0, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 40
X2_100, -1, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 30
X2_100, -2, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 20
X2_100, -3, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 10
X2_100, -4, DEFAULT_POS_Y, LEFT, BALLOON, LARGE, 0
formation: 24
# Treinta enemigos BALLOON0. Del centro hacia los extremos. Juntos. Simétricos
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.0000
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.0833
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.1667
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.2500
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.3333
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.4167
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.5000
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.5833
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.6667
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.7500
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.8333
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.9167
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.0000
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.0833
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.1667
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.0000
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.0833
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.1667
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.2500
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.3333
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.4167
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.5000
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.5833
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.6667
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.7500
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.8333
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.9167
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.0000
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.0833
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.1667
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 5
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 10
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 15
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 20
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 25
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 30
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 35
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 40
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 45
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 50
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 55
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 60
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 65
X0_50, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 70
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 5
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 10
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 15
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 20
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 25
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 30
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 35
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 40
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 45
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 50
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 55
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 60
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 65
X0_50, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 70
formation: 25
# Treinta enemigos BALLOON0. Del centro hacia adentro. Juntos. Simétricos
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.1667
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.0833
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 1.0000
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.9167
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.8333
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.7500
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.6667
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.5833
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.5000
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.4167
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.3333
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.2500
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.1667
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.0833
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0.0000
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.1667
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.0833
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 1.0000
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.9167
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.8333
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.7500
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.6667
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.5833
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.5000
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.4167
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.3333
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.2500
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.1667
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.0833
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0.0000
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 70
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 65
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 60
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 55
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 50
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 45
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 40
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 35
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 30
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 25
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 20
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 15
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 10
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 5
X0_50 + 20, 0, DEFAULT_POS_Y, LEFT, BALLOON, SMALL, 0
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 70
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 65
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 60
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 55
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 50
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 45
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 40
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 35
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 30
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 25
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 20
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 15
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 10
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 5
X0_50 - 20, 0, DEFAULT_POS_Y, RIGHT, BALLOON, SMALL, 0

View File

@@ -2,6 +2,7 @@
# Formato: PARAMETRO VALOR
# --- 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.width 320 # Ancho de la resolución nativa del juego (en píxeles)
game.height 240 # 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 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_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.color 1F2B30 # Color hexadecimal para el efecto de fundido
@@ -37,7 +40,7 @@ scoreboard.skip_countdown_value 8 # Valor para saltar la cuenta atrás (
# --- TITLE ---
title.press_start_position 180 # Posición Y del texto "Press Start"
title.title_duration 14 # Duración de la pantalla de título (segundos)
title.title_duration 800 # Duración de la pantalla de título (frames)
title.arcade_edition_position 123 # Posición Y del subtítulo "Arcade Edition"
title.title_c_c_position 80 # Posición Y del título principal
title.bg_color 41526F # Color de fondo en la sección titulo
@@ -45,15 +48,15 @@ title.bg_color 41526F # Color de fondo en la sección titulo
# --- BACKGROUND ---
background.attenuate_color FFFFFF00 # Color de atenuación del fondo (RGBA hexadecimal)
# --- BALLOONS --- (deltaTime en segundos: vel en pixels/s, grav en pixels/s²)
balloon.settings[0].vel 165.0f # Velocidad inicial del globo 1 (pixels/s)
balloon.settings[0].grav 320.0f # Gravedad aplicada al globo 1 (pixels/s²)
balloon.settings[1].vel 222.0f # Velocidad inicial del globo 2 (pixels/s)
balloon.settings[1].grav 360.0f # Gravedad aplicada al globo 2 (pixels/s²)
balloon.settings[2].vel 282.0f # Velocidad inicial del globo 3 (pixels/s)
balloon.settings[2].grav 360.0f # Gravedad aplicada al globo 3 (pixels/s²)
balloon.settings[3].vel 327.0f # Velocidad inicial del globo 4 (pixels/s)
balloon.settings[3].grav 360.0f # Gravedad aplicada al globo 4 (pixels/s²)
# --- BALLOONS ---
balloon.settings[0].vel 2.75f # Velocidad inicial del globo 1
balloon.settings[0].grav 0.09f # Gravedad aplicada al globo 1
balloon.settings[1].vel 3.70f # Velocidad inicial del globo 2
balloon.settings[1].grav 0.10f # Gravedad aplicada al globo 2
balloon.settings[2].vel 4.70f # Velocidad inicial del globo 3
balloon.settings[2].grav 0.10f # Gravedad aplicada al globo 3
balloon.settings[3].vel 5.45f # Velocidad inicial del globo 4
balloon.settings[3].grav 0.10f # Gravedad aplicada al globo 4
balloon.color[0] blue # Color de creación del globo normal
balloon.color[1] orange # Color del globo normal
@@ -90,7 +93,7 @@ service_menu.window_message.text_safety_margin 15.0f # Margen de segu
service_menu.window_message.animation_duration 0.3f # Duración de animaciones de ventanas (segundos)
# --- INTRO ---
intro.bg_color 41526F # Color de fondo de la intro
intro.bg_color 4664BD # Color de fondo de la intro
intro.card_color CBDBFC # Color de las tarjetas en la intro
intro.shadow_color 00000080 # Color de la sombra de las tarjetas en la intro
intro.text_distance_from_bottom 48 # Posicion del texto

View File

@@ -2,6 +2,7 @@
# Formato: PARAMETRO VALOR
# --- 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.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)
@@ -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.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.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.color 1F2B30 # Color hexadecimal para el efecto de fundido
@@ -37,7 +40,7 @@ scoreboard.skip_countdown_value 8 # Valor para saltar la cuenta atrás (
# --- TITLE ---
title.press_start_position 180 # Posición Y del texto "Press Start"
title.title_duration 14 # Duración de la pantalla de título (segundos)
title.title_duration 800 # Duración de la pantalla de título (frames)
title.arcade_edition_position 123 # Posición Y del subtítulo "Arcade Edition"
title.title_c_c_position 80 # Posición Y del título principal
title.bg_color 41526F # Color de fondo en la sección titulo
@@ -45,15 +48,15 @@ title.bg_color 41526F # Color de fondo en la sección titulo
# --- BACKGROUND ---
background.attenuate_color FFFFFF00 # Color de atenuación del fondo (RGBA hexadecimal)
# --- BALLOONS --- (deltaTime en segundos: vel en pixels/s, grav en pixels/s²)
balloon.settings[0].vel 165.0f # Velocidad inicial del globo 1 (pixels/s)
balloon.settings[0].grav 320.0f # Gravedad aplicada al globo 1 (pixels/s²)
balloon.settings[1].vel 222.0f # Velocidad inicial del globo 2 (pixels/s)
balloon.settings[1].grav 360.0f # Gravedad aplicada al globo 2 (pixels/s²)
balloon.settings[2].vel 282.0f # Velocidad inicial del globo 3 (pixels/s)
balloon.settings[2].grav 360.0f # Gravedad aplicada al globo 3 (pixels/s²)
balloon.settings[3].vel 327.0f # Velocidad inicial del globo 4 (pixels/s)
balloon.settings[3].grav 360.0f # Gravedad aplicada al globo 4 (pixels/s²)
# --- BALLOONS ---
balloon.settings[0].vel 2.75f # Velocidad inicial del globo 1
balloon.settings[0].grav 0.09f # Gravedad aplicada al globo 1
balloon.settings[1].vel 3.70f # Velocidad inicial del globo 2
balloon.settings[1].grav 0.10f # Gravedad aplicada al globo 2
balloon.settings[2].vel 4.70f # Velocidad inicial del globo 3
balloon.settings[2].grav 0.10f # Gravedad aplicada al globo 3
balloon.settings[3].vel 5.45f # Velocidad inicial del globo 4
balloon.settings[3].grav 0.10f # Gravedad aplicada al globo 4
balloon.color[0] blue # Color de creación del globo normal
balloon.color[1] orange # Color del globo normal
@@ -90,7 +93,7 @@ service_menu.window_message.text_safety_margin 15.0f # Margen de segu
service_menu.window_message.animation_duration 0.3f # Duración de animaciones de ventanas (segundos)
# --- INTRO ---
intro.bg_color 41526F # Color de fondo de la intro
intro.bg_color 4664BD # Color de fondo de la intro
intro.card_color CBDBFC # Color de las tarjetas en la intro
intro.shadow_color 00000080 # Color de la sombra de las tarjetas en la intro
intro.text_distance_from_bottom 48 # Posición del texto desde la parte inferior

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

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
5
# 123 {
7
3
# 124 |
2
# 125 }

View File

@@ -3,28 +3,28 @@ frame_height=10
[animation]
name=orange
speed=0.1667
speed=10
loop=0
frames=0,1,2,3,4,5,6,7,8,9
[/animation]
[animation]
name=blue
speed=0.3333
speed=20
loop=0
frames=10,11,12,13,14,15,16,17,18,19
[/animation]
[animation]
name=green
speed=0.1667
speed=10
loop=0
frames=20,21,22,23,24,25,26,27,28,29
[/animation]
[animation]
name=red
speed=0.3333
speed=20
loop=0
frames=30,31,32,33,34,35,36,37,38,39
[/animation]

View File

@@ -3,28 +3,28 @@ frame_height=16
[animation]
name=orange
speed=0.1667
speed=10
loop=0
frames=0,1,2,3,4,5,6,7,8,9
[/animation]
[animation]
name=blue
speed=0.3333
speed=20
loop=0
frames=10,11,12,13,14,15,16,17,18,19
[/animation]
[animation]
name=green
speed=0.1667
speed=10
loop=0
frames=20,21,22,23,24,25,26,27,28,29
[/animation]
[animation]
name=red
speed=0.3333
speed=20
loop=0
frames=30,31,32,33,34,35,36,37,38,39
[/animation]

View File

@@ -3,28 +3,28 @@ frame_height=26
[animation]
name=orange
speed=0.1667
speed=10
loop=0
frames=0,1,2,3,4,5,6,7,8,9
[/animation]
[animation]
name=blue
speed=0.3333
speed=20
loop=0
frames=10,11,12,13,14,15,16,17,18,19
[/animation]
[animation]
name=green
speed=0.1667
speed=10
loop=0
frames=20,21,22,23,24,25,26,27,28,29
[/animation]
[animation]
name=red
speed=0.3333
speed=20
loop=0
frames=30,31,32,33,34,35,36,37,38,39
[/animation]

View File

@@ -3,28 +3,28 @@ frame_height=48
[animation]
name=orange
speed=0.1667
speed=10
loop=0
frames=0,1,2,3,4,5,6,7,8,9
[/animation]
[animation]
name=blue
speed=0.3333
speed=20
loop=0
frames=10,11,12,13,14,15,16,17,18,19
[/animation]
[animation]
name=green
speed=0.1667
speed=10
loop=0
frames=20,21,22,23,24,25,26,27,28,29
[/animation]
[animation]
name=red
speed=0.3333
speed=20
loop=0
frames=30,31,32,33,34,35,36,37,38,39
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=10
[animation]
name=default
speed=0.0833
speed=5
loop=-1
frames=0,1,2,3,4,5,6,7,8,9
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=16
[animation]
name=default
speed=0.0833
speed=5
loop=-1
frames=0,1,2,3,4,5,6,7,8,9
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=26
[animation]
name=default
speed=0.0833
speed=5
loop=-1
frames=0,1,2,3,4,5,6,7,8,9
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=48
[animation]
name=default
speed=0.0833
speed=5
loop=-1
frames=0,1,2,3,4,5,6,7,8,9
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=49
[animation]
name=powerball
speed=0.0167
speed=10
loop=-1
frames=1
[/animation]

View File

@@ -2,85 +2,43 @@ frame_width=12
frame_height=12
[animation]
name=yellow_up
speed=20
loop=-1
frames=0
name=normal_up
speed=5
loop=0
frames=0,1,2
[/animation]
[animation]
name=yellow_left
speed=20
loop=-1
frames=1
name=normal_left
speed=5
loop=0
frames=3,4,5,5,4,3
[/animation]
[animation]
name=yellow_right
speed=20
loop=-1
frames=2
name=normal_right
speed=5
loop=0
frames=6,7,8,8,7,6
[/animation]
[animation]
name=green_up
speed=20
loop=-1
frames=3
name=powered_up
speed=5
loop=0
frames=9,10,11,11,10,9
[/animation]
[animation]
name=green_left
speed=20
loop=-1
frames=4
name=powered_left
speed=5
loop=0
frames=12,13,14,14,13,12
[/animation]
[animation]
name=green_right
speed=20
loop=-1
frames=5
[/animation]
[animation]
name=red_up
speed=20
loop=-1
frames=6
[/animation]
[animation]
name=red_left
speed=20
loop=-1
frames=7
[/animation]
[animation]
name=red_right
speed=20
loop=-1
frames=8
[/animation]
[animation]
name=purple_up
speed=20
loop=-1
frames=9
[/animation]
[animation]
name=purple_left
speed=20
loop=-1
frames=10
[/animation]
[animation]
name=purple_right
speed=20
loop=-1
frames=11
name=powered_right
speed=5
loop=0
frames=15,16,17,17,26,15
[/animation]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

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
[animation]
name=blink
speed=0.2
name=default
speed=8
loop=0
frames=0,1
[/animation]
[animation]
name=no-blink
speed=0
loop=-1
frames=1
frames=0,0,1
[/animation]

View File

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

View File

@@ -3,7 +3,7 @@ frame_height=39
[animation]
name=default
speed=0.1
speed=6
loop=0
frames=0,1,2,3,4,5,6,7,8
[/animation]

View File

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

View File

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

View File

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

View File

@@ -2,15 +2,8 @@ frame_width=20
frame_height=20
[animation]
name=blink
speed=0.2
name=default
speed=8
loop=0
frames=0,1
[/animation]
[animation]
name=no-blink
speed=0
loop=-1
frames=1
frames=0,0,1
[/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

@@ -3,133 +3,133 @@ frame_height=32
[animation]
name=walk
speed=0.0833
speed=5
loop=0
frames=0,1,2,3
[/animation]
[animation]
name=stand
speed=0.167
speed=10
loop=0
frames=4,5,6,7
[/animation]
[animation]
name=walk-fire-side
speed=0.0833
speed=5
loop=0
frames=8,9,10,11
[/animation]
[animation]
name=walk-recoil-side
speed=0.0833
speed=5
loop=0
frames=12,13,14,15
[/animation]
[animation]
name=walk-cool-side
speed=0.0833
speed=5
loop=0
frames=16,17,18,19
[/animation]
[animation]
name=stand-fire-side
speed=0.0833
speed=5
loop=0
frames=20
[/animation]
[animation]
name=stand-recoil-side
speed=0.0833
speed=5
loop=0
frames=21
[/animation]
[animation]
name=stand-cool-side
speed=0.0833
speed=5
loop=0
frames=22
[/animation]
[animation]
name=walk-fire-center
speed=0.0833
speed=5
loop=0
frames=23,24,25,26
[/animation]
[animation]
name=walk-recoil-center
speed=0.0833
speed=5
loop=0
frames=27,28,29,30
[/animation]
[animation]
name=walk-cool-center
speed=0.0833
speed=5
loop=0
frames=31,32,33,34
[/animation]
[animation]
name=stand-fire-center
speed=0.0833
speed=5
loop=0
frames=35
[/animation]
[animation]
name=stand-recoil-center
speed=0.0833
speed=5
loop=0
frames=36
[/animation]
[animation]
name=stand-cool-center
speed=0.0833
speed=5
loop=0
frames=37
[/animation]
[animation]
name=rolling
speed=0.167
speed=10
loop=0
frames=38,39,40,41
[/animation]
[animation]
name=celebration
speed=0.167
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
speed=10
loop=-1
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]
name=dizzy
speed=0.0833
speed=5
loop=0
frames=51,52,53,54,55,56,57
frames=47,48,49,50,51,52,53
[/animation]
[animation]
name=recover
speed=0.05
speed=3
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]
name=hello
speed=0.05
speed=3
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]

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

@@ -3,7 +3,7 @@ frame_height=44
[animation]
name=default
speed=0.0833
speed=5
loop=0
frames=0,1,2,3
[/animation]

View File

@@ -3,14 +3,14 @@ frame_height=32
[animation]
name=fly
speed=0.0333
speed=2
loop=0
frames=0,1
[/animation]
[animation]
name=hit
speed=0.0333
speed=2
loop=0
frames=2,3
[/animation]

View File

@@ -3,7 +3,7 @@ frame_height=16
[animation]
name=default
speed=0.1333
speed=8
loop=-1
frames=0,1,2,3,4,5,6
[/animation]

View File

@@ -21,13 +21,12 @@
"[GAME_TEXT] 2": "Queden ",
"[GAME_TEXT] 2A": " fases mes!",
"[GAME_TEXT] 3": "Ultima fase!",
"[GAME_TEXT] 4": "Automatic!",
"[GAME_TEXT] 4": "SuperPoder!",
"[GAME_TEXT] 5": "+1 Colp",
"[GAME_TEXT] 6": "Temps!",
"[GAME_TEXT] 7": "Endavant!",
"[GAME_TEXT] 8": "1.000.000 de punts!",
"[GAME_TEXT] THANK_YOU": "Gracies!",
"[GAME_TEXT] NEW_RECORD": "Nou record!",
"[HIGHSCORE_TABLE] CAPTION": "Millors puntuacions",
@@ -79,10 +78,7 @@
"[SERVICE_MENU] SHUTDOWN": "Apagar el sistema",
"[SERVICE_MENU] FULLSCREEN": "Pantalla completa",
"[SERVICE_MENU] WINDOW_SIZE": "Tamany de la finestra",
"[SERVICE_MENU] SHADER": "Shader",
"[SERVICE_MENU] SHADER_DISABLED": "Desactivat",
"[SERVICE_MENU] SHADER_PRESET": "Preset",
"[SERVICE_MENU] SUPERSAMPLING": "Supermostreig",
"[SERVICE_MENU] SHADERS": "Filtre",
"[SERVICE_MENU] VSYNC": "Sincronisme vertical",
"[SERVICE_MENU] INTEGER_SCALE": "Escalat sencer",
"[SERVICE_MENU] MAIN_VOLUME": "Volumen general",

View File

@@ -20,13 +20,12 @@
"[GAME_TEXT] 2": "",
"[GAME_TEXT] 2A": " stages left!",
"[GAME_TEXT] 3": "Last stage!",
"[GAME_TEXT] 4": "AutoFire!",
"[GAME_TEXT] 4": "PowerUp",
"[GAME_TEXT] 5": "+1 Hit",
"[GAME_TEXT] 6": "Stop!",
"[GAME_TEXT] 7": "Get Ready!",
"[GAME_TEXT] 8": "1,000,000 points!",
"[GAME_TEXT] THANK_YOU": "Thank you!",
"[GAME_TEXT] NEW_RECORD": "New record!",
"[HIGHSCORE_TABLE] CAPTION": "Best scores",
@@ -78,10 +77,7 @@
"[SERVICE_MENU] SHUTDOWN": "Shutdown System",
"[SERVICE_MENU] FULLSCREEN": "Fullscreen",
"[SERVICE_MENU] WINDOW_SIZE": "Window Zoom",
"[SERVICE_MENU] SHADER": "Shader",
"[SERVICE_MENU] SHADER_DISABLED": "Disabled",
"[SERVICE_MENU] SHADER_PRESET": "Preset",
"[SERVICE_MENU] SUPERSAMPLING": "Supersampling",
"[SERVICE_MENU] SHADERS": "Shaders",
"[SERVICE_MENU] VSYNC": "V-Sync",
"[SERVICE_MENU] INTEGER_SCALE": "Integer Scale",
"[SERVICE_MENU] MAIN_VOLUME": "Main Volume",

View File

@@ -20,13 +20,12 @@
"[GAME_TEXT] 2": "!Quedan ",
"[GAME_TEXT] 2A": " fases!",
"[GAME_TEXT] 3": "Ultima fase!",
"[GAME_TEXT] 4": "Automatico!",
"[GAME_TEXT] 4": "Potenciador",
"[GAME_TEXT] 5": "+1 Golpe",
"[GAME_TEXT] 6": "Tiempo!",
"[GAME_TEXT] 7": "Adelante!",
"[GAME_TEXT] 8": "1.000.000 de puntos!",
"[GAME_TEXT] THANK_YOU": "Gracias!",
"[GAME_TEXT] NEW_RECORD": "Nuevo record!",
"[HIGHSCORE_TABLE] CAPTION": "Mejores puntuaciones",
@@ -78,10 +77,7 @@
"[SERVICE_MENU] SHUTDOWN": "Apagar el sistema",
"[SERVICE_MENU] FULLSCREEN": "Pantalla completa",
"[SERVICE_MENU] WINDOW_SIZE": "Zoom de ventana",
"[SERVICE_MENU] SHADER": "Shader",
"[SERVICE_MENU] SHADER_DISABLED": "Desactivado",
"[SERVICE_MENU] SHADER_PRESET": "Preset",
"[SERVICE_MENU] SUPERSAMPLING": "Supersampling",
"[SERVICE_MENU] SHADERS": "Filtro grafico",
"[SERVICE_MENU] VSYNC": "Sincronismo vertical",
"[SERVICE_MENU] INTEGER_SCALE": "Escalado proporcional",
"[SERVICE_MENU] MAIN_VOLUME": "Volumen general",

Binary file not shown.

234
data/shaders/crtpi_240.glsl Normal file
View File

@@ -0,0 +1,234 @@
/*
crt-pi - A Raspberry Pi friendly CRT shader.
Copyright (C) 2015-2016 davej
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.
Notes:
This shader is designed to work well on Raspberry Pi GPUs (i.e. 1080P @ 60Hz on a game with a 4:3 aspect ratio). It pushes the Pi's GPU hard and enabling some features will slow it down so that it is no longer able to match 1080P @ 60Hz. You will need to overclock your Pi to the fastest setting in raspi-config to get the best results from this shader: 'Pi2' for Pi2 and 'Turbo' for original Pi and Pi Zero. Note: Pi2s are slower at running the shader than other Pis, this seems to be down to Pi2s lower maximum memory speed. Pi2s don't quite manage 1080P @ 60Hz - they drop about 1 in 1000 frames. You probably won't notice this, but if you do, try enabling FAKE_GAMMA.
SCANLINES enables scanlines. You'll almost certainly want to use it with MULTISAMPLE to reduce moire effects. SCANLINE_WEIGHT defines how wide scanlines are (it is an inverse value so a higher number = thinner lines). SCANLINE_GAP_BRIGHTNESS defines how dark the gaps between the scan lines are. Darker gaps between scan lines make moire effects more likely.
GAMMA enables gamma correction using the values in INPUT_GAMMA and OUTPUT_GAMMA. FAKE_GAMMA causes it to ignore the values in INPUT_GAMMA and OUTPUT_GAMMA and approximate gamma correction in a way which is faster than true gamma whilst still looking better than having none. You must have GAMMA defined to enable FAKE_GAMMA.
CURVATURE distorts the screen by CURVATURE_X and CURVATURE_Y. Curvature slows things down a lot.
By default the shader uses linear blending horizontally. If you find this too blury, enable SHARPER.
BLOOM_FACTOR controls the increase in width for bright scanlines.
MASK_TYPE defines what, if any, shadow mask to use. MASK_BRIGHTNESS defines how much the mask type darkens the screen.
*/
#pragma parameter CURVATURE_X "Screen curvature - horizontal" 0.10 0.0 1.0 0.01
#pragma parameter CURVATURE_Y "Screen curvature - vertical" 0.15 0.0 1.0 0.01
#pragma parameter MASK_BRIGHTNESS "Mask brightness" 0.70 0.0 1.0 0.01
#pragma parameter SCANLINE_WEIGHT "Scanline weight" 6.0 0.0 15.0 0.1
#pragma parameter SCANLINE_GAP_BRIGHTNESS "Scanline gap brightness" 0.12 0.0 1.0 0.01
#pragma parameter BLOOM_FACTOR "Bloom factor" 1.5 0.0 5.0 0.01
#pragma parameter INPUT_GAMMA "Input gamma" 2.4 0.0 5.0 0.01
#pragma parameter OUTPUT_GAMMA "Output gamma" 2.2 0.0 5.0 0.01
// Haven't put these as parameters as it would slow the code down.
#define SCANLINES
#define MULTISAMPLE
#define GAMMA
//#define FAKE_GAMMA
//#define CURVATURE
//#define SHARPER
// MASK_TYPE: 0 = none, 1 = green/magenta, 2 = trinitron(ish)
#define MASK_TYPE 2
#ifdef GL_ES
#define COMPAT_PRECISION mediump
precision mediump float;
#else
#define COMPAT_PRECISION
#endif
#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float CURVATURE_X;
uniform COMPAT_PRECISION float CURVATURE_Y;
uniform COMPAT_PRECISION float MASK_BRIGHTNESS;
uniform COMPAT_PRECISION float SCANLINE_WEIGHT;
uniform COMPAT_PRECISION float SCANLINE_GAP_BRIGHTNESS;
uniform COMPAT_PRECISION float BLOOM_FACTOR;
uniform COMPAT_PRECISION float INPUT_GAMMA;
uniform COMPAT_PRECISION float OUTPUT_GAMMA;
#else
#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
#endif
/* COMPATIBILITY
- GLSL compilers
*/
//uniform vec2 TextureSize;
#if defined(CURVATURE)
varying vec2 screenScale;
#endif
varying vec2 TEX0;
varying float filterWidth;
#if defined(VERTEX)
//uniform mat4 MVPMatrix;
//attribute vec4 VertexCoord;
//attribute vec2 TexCoord;
//uniform vec2 InputSize;
//uniform vec2 OutputSize;
void main()
{
#if defined(CURVATURE)
screenScale = vec2(1.0, 1.0); //TextureSize / InputSize;
#endif
filterWidth = (768.0 / 240.0) / 3.0;
TEX0 = vec2(gl_MultiTexCoord0.x, 1.0-gl_MultiTexCoord0.y)*1.0001;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
#elif defined(FRAGMENT)
uniform sampler2D Texture;
#if defined(CURVATURE)
vec2 Distort(vec2 coord)
{
vec2 CURVATURE_DISTORTION = vec2(CURVATURE_X, CURVATURE_Y);
// Barrel distortion shrinks the display area a bit, this will allow us to counteract that.
vec2 barrelScale = 1.0 - (0.23 * CURVATURE_DISTORTION);
coord *= screenScale;
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); // If out of bounds, return an invalid value.
else
{
coord += vec2(0.5);
coord /= screenScale;
}
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-filterWidth);
scanLineWeight += CalcScanLineWeight(dy+filterWidth);
scanLineWeight *= 0.3333333;
#endif
return scanLineWeight;
}
void main()
{
vec2 TextureSize = vec2(320.0, 240.0);
#if defined(CURVATURE)
vec2 texcoord = Distort(TEX0);
if (texcoord.x < 0.0)
gl_FragColor = vec4(0.0);
else
#else
vec2 texcoord = TEX0;
#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 = texture2D(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
gl_FragColor = vec4(colour, 1.0);
#else
#if MASK_TYPE == 1
float whichMask = fract((gl_FragCoord.x*1.0001) * 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);
#elif MASK_TYPE == 2
float whichMask = fract((gl_FragCoord.x*1.0001) * 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;
#endif
gl_FragColor = vec4(colour * mask, 1.0);
#endif
}
}
#endif

View File

@@ -0,0 +1,185 @@
/*
crt-pi - A Raspberry Pi friendly CRT shader.
Metal Shading Language version converted from GLSL
Copyright (C) 2015-2016 davej
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.
*/
#include <metal_stdlib>
using namespace metal;
// Haven't put these as parameters as it would slow the code down.
#define SCANLINES
#define MULTISAMPLE
#define GAMMA
//#define FAKE_GAMMA
//#define CURVATURE
//#define SHARPER
// MASK_TYPE: 0 = none, 1 = green/magenta, 2 = trinitron(ish)
#define MASK_TYPE 2
// Constants
#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
struct VertexIn {
float4 position [[attribute(0)]];
float2 texcoord [[attribute(1)]];
};
struct VertexOut {
float4 position [[position]];
float2 TEX0;
#if defined(CURVATURE)
float2 screenScale;
#endif
float filterWidth;
};
vertex VertexOut vertex_main(VertexIn in [[stage_in]]) {
VertexOut out;
#if defined(CURVATURE)
out.screenScale = float2(1.0, 1.0);
#endif
out.filterWidth = (768.0 / 240.0) / 3.0;
out.TEX0 = float2(in.texcoord.x, 1.0 - in.texcoord.y) * 1.0001;
out.position = in.position;
return out;
}
#if defined(CURVATURE)
float2 Distort(float2 coord, float2 screenScale) {
float2 CURVATURE_DISTORTION = float2(CURVATURE_X, CURVATURE_Y);
// Barrel distortion shrinks the display area a bit, this will allow us to counteract that.
float2 barrelScale = 1.0 - (0.23 * CURVATURE_DISTORTION);
coord *= screenScale;
coord -= float2(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 = float2(-1.0); // If out of bounds, return an invalid value.
else {
coord += float2(0.5);
coord /= screenScale;
}
return coord;
}
#endif
float CalcScanLineWeight(float dist) {
return max(1.0 - dist * dist * SCANLINE_WEIGHT, SCANLINE_GAP_BRIGHTNESS);
}
float CalcScanLine(float dy, float filterWidth) {
float scanLineWeight = CalcScanLineWeight(dy);
#if defined(MULTISAMPLE)
scanLineWeight += CalcScanLineWeight(dy - filterWidth);
scanLineWeight += CalcScanLineWeight(dy + filterWidth);
scanLineWeight *= 0.3333333;
#endif
return scanLineWeight;
}
fragment float4 fragment_main(VertexOut in [[stage_in]],
texture2d<float> Texture [[texture(0)]],
sampler textureSampler [[sampler(0)]]) {
float2 TextureSize = float2(320.0, 240.0);
#if defined(CURVATURE)
float2 texcoord = Distort(in.TEX0, in.screenScale);
if (texcoord.x < 0.0)
return float4(0.0);
else
#else
float2 texcoord = in.TEX0;
#endif
{
float2 texcoordInPixels = texcoord * TextureSize;
#if defined(SHARPER)
float2 tempCoord = floor(texcoordInPixels) + 0.5;
float2 coord = tempCoord / TextureSize;
float2 deltas = texcoordInPixels - tempCoord;
float 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 /= TextureSize;
deltas *= signs;
float2 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, in.filterWidth);
float signY = sign(dy);
dy = dy * dy;
dy = dy * dy;
dy *= 8.0;
dy /= TextureSize.y;
dy *= signY;
float2 tc = float2(texcoord.x, yCoord + dy);
#endif
float3 colour = Texture.sample(textureSampler, tc).rgb;
#if defined(SCANLINES)
#if defined(GAMMA)
#if defined(FAKE_GAMMA)
colour = colour * colour;
#else
colour = pow(colour, float3(INPUT_GAMMA));
#endif
#endif
scanLineWeight *= BLOOM_FACTOR;
colour *= scanLineWeight;
#if defined(GAMMA)
#if defined(FAKE_GAMMA)
colour = sqrt(colour);
#else
colour = pow(colour, float3(1.0/OUTPUT_GAMMA));
#endif
#endif
#endif
#if MASK_TYPE == 0
return float4(colour, 1.0);
#else
#if MASK_TYPE == 1
float whichMask = fract((in.position.x * 1.0001) * 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);
#elif MASK_TYPE == 2
float whichMask = fract((in.position.x * 1.0001) * 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;
#endif
return float4(colour * mask, 1.0);
#endif
}
}

234
data/shaders/crtpi_256.glsl Normal file
View File

@@ -0,0 +1,234 @@
/*
crt-pi - A Raspberry Pi friendly CRT shader.
Copyright (C) 2015-2016 davej
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.
Notes:
This shader is designed to work well on Raspberry Pi GPUs (i.e. 1080P @ 60Hz on a game with a 4:3 aspect ratio). It pushes the Pi's GPU hard and enabling some features will slow it down so that it is no longer able to match 1080P @ 60Hz. You will need to overclock your Pi to the fastest setting in raspi-config to get the best results from this shader: 'Pi2' for Pi2 and 'Turbo' for original Pi and Pi Zero. Note: Pi2s are slower at running the shader than other Pis, this seems to be down to Pi2s lower maximum memory speed. Pi2s don't quite manage 1080P @ 60Hz - they drop about 1 in 1000 frames. You probably won't notice this, but if you do, try enabling FAKE_GAMMA.
SCANLINES enables scanlines. You'll almost certainly want to use it with MULTISAMPLE to reduce moire effects. SCANLINE_WEIGHT defines how wide scanlines are (it is an inverse value so a higher number = thinner lines). SCANLINE_GAP_BRIGHTNESS defines how dark the gaps between the scan lines are. Darker gaps between scan lines make moire effects more likely.
GAMMA enables gamma correction using the values in INPUT_GAMMA and OUTPUT_GAMMA. FAKE_GAMMA causes it to ignore the values in INPUT_GAMMA and OUTPUT_GAMMA and approximate gamma correction in a way which is faster than true gamma whilst still looking better than having none. You must have GAMMA defined to enable FAKE_GAMMA.
CURVATURE distorts the screen by CURVATURE_X and CURVATURE_Y. Curvature slows things down a lot.
By default the shader uses linear blending horizontally. If you find this too blury, enable SHARPER.
BLOOM_FACTOR controls the increase in width for bright scanlines.
MASK_TYPE defines what, if any, shadow mask to use. MASK_BRIGHTNESS defines how much the mask type darkens the screen.
*/
#pragma parameter CURVATURE_X "Screen curvature - horizontal" 0.10 0.0 1.0 0.01
#pragma parameter CURVATURE_Y "Screen curvature - vertical" 0.15 0.0 1.0 0.01
#pragma parameter MASK_BRIGHTNESS "Mask brightness" 0.70 0.0 1.0 0.01
#pragma parameter SCANLINE_WEIGHT "Scanline weight" 6.0 0.0 15.0 0.1
#pragma parameter SCANLINE_GAP_BRIGHTNESS "Scanline gap brightness" 0.12 0.0 1.0 0.01
#pragma parameter BLOOM_FACTOR "Bloom factor" 1.5 0.0 5.0 0.01
#pragma parameter INPUT_GAMMA "Input gamma" 2.4 0.0 5.0 0.01
#pragma parameter OUTPUT_GAMMA "Output gamma" 2.2 0.0 5.0 0.01
// Haven't put these as parameters as it would slow the code down.
#define SCANLINES
#define MULTISAMPLE
#define GAMMA
//#define FAKE_GAMMA
//#define CURVATURE
//#define SHARPER
// MASK_TYPE: 0 = none, 1 = green/magenta, 2 = trinitron(ish)
#define MASK_TYPE 2
#ifdef GL_ES
#define COMPAT_PRECISION mediump
precision mediump float;
#else
#define COMPAT_PRECISION
#endif
#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float CURVATURE_X;
uniform COMPAT_PRECISION float CURVATURE_Y;
uniform COMPAT_PRECISION float MASK_BRIGHTNESS;
uniform COMPAT_PRECISION float SCANLINE_WEIGHT;
uniform COMPAT_PRECISION float SCANLINE_GAP_BRIGHTNESS;
uniform COMPAT_PRECISION float BLOOM_FACTOR;
uniform COMPAT_PRECISION float INPUT_GAMMA;
uniform COMPAT_PRECISION float OUTPUT_GAMMA;
#else
#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
#endif
/* COMPATIBILITY
- GLSL compilers
*/
//uniform vec2 TextureSize;
#if defined(CURVATURE)
varying vec2 screenScale;
#endif
varying vec2 TEX0;
varying float filterWidth;
#if defined(VERTEX)
//uniform mat4 MVPMatrix;
//attribute vec4 VertexCoord;
//attribute vec2 TexCoord;
//uniform vec2 InputSize;
//uniform vec2 OutputSize;
void main()
{
#if defined(CURVATURE)
screenScale = vec2(1.0, 1.0); //TextureSize / InputSize;
#endif
filterWidth = (768.0 / 256.0) / 3.0;
TEX0 = vec2(gl_MultiTexCoord0.x, 1.0-gl_MultiTexCoord0.y)*1.0001;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
#elif defined(FRAGMENT)
uniform sampler2D Texture;
#if defined(CURVATURE)
vec2 Distort(vec2 coord)
{
vec2 CURVATURE_DISTORTION = vec2(CURVATURE_X, CURVATURE_Y);
// Barrel distortion shrinks the display area a bit, this will allow us to counteract that.
vec2 barrelScale = 1.0 - (0.23 * CURVATURE_DISTORTION);
coord *= screenScale;
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); // If out of bounds, return an invalid value.
else
{
coord += vec2(0.5);
coord /= screenScale;
}
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-filterWidth);
scanLineWeight += CalcScanLineWeight(dy+filterWidth);
scanLineWeight *= 0.3333333;
#endif
return scanLineWeight;
}
void main()
{
vec2 TextureSize = vec2(320.0, 256.0);
#if defined(CURVATURE)
vec2 texcoord = Distort(TEX0);
if (texcoord.x < 0.0)
gl_FragColor = vec4(0.0);
else
#else
vec2 texcoord = TEX0;
#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 = texture2D(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
gl_FragColor = vec4(colour, 1.0);
#else
#if MASK_TYPE == 1
float whichMask = fract((gl_FragCoord.x*1.0001) * 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);
#elif MASK_TYPE == 2
float whichMask = fract((gl_FragCoord.x*1.0001) * 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;
#endif
gl_FragColor = vec4(colour * mask, 1.0);
#endif
}
}
#endif

View File

@@ -0,0 +1,185 @@
/*
crt-pi - A Raspberry Pi friendly CRT shader.
Metal Shading Language version converted from GLSL
Copyright (C) 2015-2016 davej
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
any later version.
*/
#include <metal_stdlib>
using namespace metal;
// Haven't put these as parameters as it would slow the code down.
#define SCANLINES
#define MULTISAMPLE
#define GAMMA
//#define FAKE_GAMMA
//#define CURVATURE
//#define SHARPER
// MASK_TYPE: 0 = none, 1 = green/magenta, 2 = trinitron(ish)
#define MASK_TYPE 2
// Constants
#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
struct VertexIn {
float4 position [[attribute(0)]];
float2 texcoord [[attribute(1)]];
};
struct VertexOut {
float4 position [[position]];
float2 TEX0;
#if defined(CURVATURE)
float2 screenScale;
#endif
float filterWidth;
};
vertex VertexOut vertex_main(VertexIn in [[stage_in]]) {
VertexOut out;
#if defined(CURVATURE)
out.screenScale = float2(1.0, 1.0);
#endif
out.filterWidth = (768.0 / 256.0) / 3.0;
out.TEX0 = float2(in.texcoord.x, 1.0 - in.texcoord.y) * 1.0001;
out.position = in.position;
return out;
}
#if defined(CURVATURE)
float2 Distort(float2 coord, float2 screenScale) {
float2 CURVATURE_DISTORTION = float2(CURVATURE_X, CURVATURE_Y);
// Barrel distortion shrinks the display area a bit, this will allow us to counteract that.
float2 barrelScale = 1.0 - (0.23 * CURVATURE_DISTORTION);
coord *= screenScale;
coord -= float2(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 = float2(-1.0); // If out of bounds, return an invalid value.
else {
coord += float2(0.5);
coord /= screenScale;
}
return coord;
}
#endif
float CalcScanLineWeight(float dist) {
return max(1.0 - dist * dist * SCANLINE_WEIGHT, SCANLINE_GAP_BRIGHTNESS);
}
float CalcScanLine(float dy, float filterWidth) {
float scanLineWeight = CalcScanLineWeight(dy);
#if defined(MULTISAMPLE)
scanLineWeight += CalcScanLineWeight(dy - filterWidth);
scanLineWeight += CalcScanLineWeight(dy + filterWidth);
scanLineWeight *= 0.3333333;
#endif
return scanLineWeight;
}
fragment float4 fragment_main(VertexOut in [[stage_in]],
texture2d<float> Texture [[texture(0)]],
sampler textureSampler [[sampler(0)]]) {
float2 TextureSize = float2(320.0, 256.0);
#if defined(CURVATURE)
float2 texcoord = Distort(in.TEX0, in.screenScale);
if (texcoord.x < 0.0)
return float4(0.0);
else
#else
float2 texcoord = in.TEX0;
#endif
{
float2 texcoordInPixels = texcoord * TextureSize;
#if defined(SHARPER)
float2 tempCoord = floor(texcoordInPixels) + 0.5;
float2 coord = tempCoord / TextureSize;
float2 deltas = texcoordInPixels - tempCoord;
float 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 /= TextureSize;
deltas *= signs;
float2 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, in.filterWidth);
float signY = sign(dy);
dy = dy * dy;
dy = dy * dy;
dy *= 8.0;
dy /= TextureSize.y;
dy *= signY;
float2 tc = float2(texcoord.x, yCoord + dy);
#endif
float3 colour = Texture.sample(textureSampler, tc).rgb;
#if defined(SCANLINES)
#if defined(GAMMA)
#if defined(FAKE_GAMMA)
colour = colour * colour;
#else
colour = pow(colour, float3(INPUT_GAMMA));
#endif
#endif
scanLineWeight *= BLOOM_FACTOR;
colour *= scanLineWeight;
#if defined(GAMMA)
#if defined(FAKE_GAMMA)
colour = sqrt(colour);
#else
colour = pow(colour, float3(1.0/OUTPUT_GAMMA));
#endif
#endif
#endif
#if MASK_TYPE == 0
return float4(colour, 1.0);
#else
#if MASK_TYPE == 1
float whichMask = fract((in.position.x * 1.0001) * 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);
#elif MASK_TYPE == 2
float whichMask = fract((in.position.x * 1.0001) * 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;
#endif
return float4(colour * mask, 1.0);
#endif
}
}

View File

@@ -1,152 +0,0 @@
#version 450
// Vulkan GLSL fragment shader — CRT-Pi PostFX
// Algoritmo de scanlines continuas con pesos gaussianos, bloom y máscara de fósforo.
// Basado en el shader CRT-Pi original (GLSL 3.3), portado a GLSL 4.50 con parámetros uniformes.
//
// Compile: glslc -fshader-stage=frag --target-env=vulkan1.0 crtpi_frag.glsl -o crtpi_frag.spv
// xxd -i crtpi_frag.spv > ../../source/core/rendering/sdl3gpu/crtpi_frag_spv.h
layout(location = 0) in vec2 v_uv;
layout(location = 0) out vec4 out_color;
layout(set = 2, binding = 0) uniform sampler2D Texture;
layout(set = 3, binding = 0) uniform CrtPiBlock {
// vec4 #0
float scanline_weight; // Ajuste gaussiano de scanlines (default 6.0)
float scanline_gap_brightness; // Brillo mínimo entre scanlines (default 0.12)
float bloom_factor; // Factor de brillo en zonas iluminadas (default 3.5)
float input_gamma; // Gamma de entrada — linealización (default 2.4)
// vec4 #1
float output_gamma; // Gamma de salida — codificación (default 2.2)
float mask_brightness; // Brillo sub-píxeles de la máscara (default 0.80)
float curvature_x; // Distorsión barrel eje X (default 0.05)
float curvature_y; // Distorsión barrel eje Y (default 0.10)
// vec4 #2
int mask_type; // 0=ninguna, 1=verde/magenta, 2=RGB fósforo
int enable_scanlines; // 0 = off, 1 = on
int enable_multisample; // 0 = off, 1 = on (antialiasing analítico de scanlines)
int enable_gamma; // 0 = off, 1 = on
// vec4 #3
int enable_curvature; // 0 = off, 1 = on
int enable_sharper; // 0 = off, 1 = on
float texture_width; // Ancho del canvas lógico en píxeles
float texture_height; // Alto del canvas lógico en píxeles
} u;
// Distorsión barrel CRT
vec2 distort(vec2 coord, vec2 screen_scale) {
vec2 curvature = vec2(u.curvature_x, u.curvature_y);
vec2 barrel_scale = 1.0 - (0.23 * curvature);
coord *= screen_scale;
coord -= vec2(0.5);
float rsq = coord.x * coord.x + coord.y * coord.y;
coord += coord * (curvature * rsq);
coord *= barrel_scale;
if (abs(coord.x) >= 0.5 || abs(coord.y) >= 0.5) {
return vec2(-1.0); // fuera de pantalla
}
coord += vec2(0.5);
coord /= screen_scale;
return coord;
}
float calcScanLineWeight(float dist) {
return max(1.0 - dist * dist * u.scanline_weight, u.scanline_gap_brightness);
}
float calcScanLine(float dy, float filter_width) {
float weight = calcScanLineWeight(dy);
if (u.enable_multisample != 0) {
weight += calcScanLineWeight(dy - filter_width);
weight += calcScanLineWeight(dy + filter_width);
weight *= 0.3333333;
}
return weight;
}
void main() {
vec2 tex_size = vec2(u.texture_width, u.texture_height);
// filterWidth: equivalente al original (768.0 / TextureSize.y) / 3.0
float filter_width = (768.0 / u.texture_height) / 3.0;
vec2 texcoord = v_uv;
// Curvatura barrel opcional
if (u.enable_curvature != 0) {
texcoord = distort(texcoord, vec2(1.0, 1.0));
if (texcoord.x < 0.0) {
out_color = vec4(0.0, 0.0, 0.0, 1.0);
return;
}
}
vec2 texcoord_in_pixels = texcoord * tex_size;
vec2 tc;
float scan_line_weight;
if (u.enable_sharper != 0) {
// Modo SHARPER: filtrado bicúbico-like con subpixel sharpen
vec2 temp_coord = floor(texcoord_in_pixels) + 0.5;
tc = temp_coord / tex_size;
vec2 deltas = texcoord_in_pixels - temp_coord;
scan_line_weight = calcScanLine(deltas.y, filter_width);
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 /= tex_size;
deltas *= signs;
tc = tc + deltas;
} else {
// Modo estándar
float temp_y = floor(texcoord_in_pixels.y) + 0.5;
float y_coord = temp_y / tex_size.y;
float dy = texcoord_in_pixels.y - temp_y;
scan_line_weight = calcScanLine(dy, filter_width);
float sign_y = sign(dy);
dy = dy * dy;
dy = dy * dy;
dy *= 8.0;
dy /= tex_size.y;
dy *= sign_y;
tc = vec2(texcoord.x, y_coord + dy);
}
vec3 colour = texture(Texture, tc).rgb;
if (u.enable_scanlines != 0) {
if (u.enable_gamma != 0) {
colour = pow(colour, vec3(u.input_gamma));
}
colour *= scan_line_weight * u.bloom_factor;
if (u.enable_gamma != 0) {
colour = pow(colour, vec3(1.0 / u.output_gamma));
}
}
// Máscara de fósforo
if (u.mask_type == 1) {
float which_mask = fract(gl_FragCoord.x * 0.5);
vec3 mask = (which_mask < 0.5)
? vec3(u.mask_brightness, 1.0, u.mask_brightness)
: vec3(1.0, u.mask_brightness, 1.0);
colour *= mask;
} else if (u.mask_type == 2) {
float which_mask = fract(gl_FragCoord.x * 0.3333333);
vec3 mask = vec3(u.mask_brightness);
if (which_mask < 0.3333333)
mask.x = 1.0;
else if (which_mask < 0.6666666)
mask.y = 1.0;
else
mask.z = 1.0;
colour *= mask;
}
out_color = vec4(colour, 1.0);
}

View File

@@ -1,48 +0,0 @@
#version 450
layout(location = 0) in vec2 v_uv;
layout(location = 0) out vec4 out_color;
layout(set = 2, binding = 0) uniform sampler2D source;
layout(set = 3, binding = 0) uniform DownscaleUniforms {
int algorithm; // 0 = Lanczos2 (ventana 2, ±2 taps), 1 = Lanczos3 (ventana 3, ±3 taps)
float pad0;
float pad1;
float pad2;
} u;
// Kernel Lanczos normalizado: sinc(t) * sinc(t/a) para |t| < a, 0 fuera.
float lanczos(float t, float a) {
t = abs(t);
if (t < 0.0001) { return 1.0; }
if (t >= a) { return 0.0; }
const float PI = 3.14159265358979;
float pt = PI * t;
return (a * sin(pt) * sin(pt / a)) / (pt * pt);
}
void main() {
vec2 src_size = vec2(textureSize(source, 0));
// Posición en coordenadas de texel (centros de texel en N+0.5)
vec2 p = v_uv * src_size;
vec2 p_floor = floor(p);
float a = (u.algorithm == 0) ? 2.0 : 3.0;
int win = int(a);
vec4 color = vec4(0.0);
float weight_sum = 0.0;
for (int j = -win; j <= win; j++) {
for (int i = -win; i <= win; i++) {
// Centro del texel (i,j) relativo a p_floor
vec2 tap_center = p_floor + vec2(float(i), float(j)) + 0.5;
vec2 offset = tap_center - p;
float w = lanczos(offset.x, a) * lanczos(offset.y, a);
color += texture(source, tap_center / src_size) * w;
weight_sum += w;
}
}
out_color = (weight_sum > 0.0) ? (color / weight_sum) : vec4(0.0, 0.0, 0.0, 1.0);
}

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];
}

View File

@@ -1,15 +0,0 @@
#version 450
// Vulkan GLSL fragment shader — Nearest-neighbour upscale pass
// Used as the first render pass when supersampling is active.
// Compile: glslc upscale.frag -o upscale.frag.spv
// xxd -i upscale.frag.spv > ../../source/core/rendering/sdl3gpu/upscale_frag_spv.h
layout(location = 0) in vec2 v_uv;
layout(location = 0) out vec4 out_color;
layout(set = 2, binding = 0) uniform sampler2D scene;
void main() {
out_color = texture(scene, v_uv);
}

Binary file not shown.

BIN
data/sound/click-2.wav Normal file

Binary file not shown.

BIN
data/sound/click-3.wav Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,24 +1,11 @@
#!/bin/bash
# Script para ejecutar clang-tidy en múltiples directorios
# Uso: ./run_clang-tidy.sh [--fix]
# --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
# Uso: ./run_clang-tidy.sh
# Lista de rutas donde ejecutar clang-tidy
PATHS=(
"/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/ui"
)
@@ -42,8 +29,8 @@ process_directory() {
cd "$dir" || return 1
# Buscar archivos .cpp, .h, .hpp solo en el nivel actual (no subdirectorios)
find . -maxdepth 1 \( -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) -print0 | \
xargs -0 -P4 -I{} bash -c 'echo "Procesando: {}"; clang-tidy {} -p '"$BUILD_DIR"' '"$FIX_FLAG"
find . -maxdepth 1 \( -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) | \
xargs -P4 -I{} bash -c 'echo "Procesando: {}"; clang-tidy {} -p '"$BUILD_DIR"' --fix'
echo "=== Completado: $dir ==="
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
echo "🚀 Ejecutando IWYU..."
./iwyu_tool.py -p "$BUILD_DIR" -- -Xiwyu --mapping_file="$MAPPING_FILE" -Xiwyu --verbose=3 \
| fix_include --update_comments --reorder --nosafe_headers
iwyu_tool.py -p "$BUILD_DIR" -- -Xiwyu --mapping_file="$MAPPING_FILE" -Xiwyu --verbose=3 \
| python3 /usr/bin/fix_includes.py --update_comments --reorder --nosafe_headers
# 🧹 Reemplazar // for por // Para en líneas de #include
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