Compare commits
136 Commits
v1.09
...
f08b2f9193
| Author | SHA1 | Date | |
|---|---|---|---|
| f08b2f9193 | |||
| 3680ff3935 | |||
| 99893a0c83 | |||
| c5cfb518a2 | |||
| 1041aaf385 | |||
| c207b456f5 | |||
| 7cd596a0b9 | |||
| 89a7f197a6 | |||
| fda22dd5f2 | |||
| 70d6cbfaf8 | |||
| 95dd6b4f70 | |||
| 633936c6e8 | |||
| 95b82e5f62 | |||
| ead3265bfc | |||
| 8bf9da5fb6 | |||
| cd836862c0 | |||
| acdad8295a | |||
| f14a1075ab | |||
| 31c84f9676 | |||
| 9e8c5e13df | |||
| de8c714132 | |||
| da65777a5b | |||
| 70b76edcbf | |||
| 6af2d72ea8 | |||
| 5f47c88770 | |||
| 3179a08dac | |||
| b1dca32a5b | |||
| aacb14149f | |||
| cdb9bde6aa | |||
| 5d8811026d | |||
| 231dcd4b3b | |||
| 17101a3da1 | |||
| 87370dd11d | |||
| fc17131455 | |||
| 0c87612a17 | |||
| 96506988b6 | |||
| c7b07e9351 | |||
| 6d2a116d15 | |||
| d1acc59319 | |||
| 0388adfed8 | |||
| 342177a751 | |||
| fdea094e26 | |||
| 2eadd7d8df | |||
| 51330db998 | |||
| df4965a84b | |||
| 8f49e442de | |||
| 9676e5bc2f | |||
| 545d471654 | |||
| 9db902c024 | |||
| 7fe2523221 | |||
| d5ff840445 | |||
| fb5fee02e9 | |||
| 9a4b3b04a5 | |||
| e811cf0a1d | |||
| e4a08d2ec7 | |||
| 7c102e42cc | |||
| 78c5333144 | |||
| c3415fd106 | |||
| 428fe664bd | |||
| 0f8de0d8b5 | |||
| 2ee2d5c45d | |||
| b8cde79107 | |||
| 0667e2105b | |||
| f438e8946b | |||
| 68c97610fb | |||
| 7746b679b4 | |||
| 73008992e0 | |||
| d4acb38c05 | |||
| 7aae9fb5e6 | |||
| a63066bd68 | |||
| 0de6117ca0 | |||
| a43967c279 | |||
| 15ecc10d8b | |||
| 0a5996f220 | |||
| 64ee2d1e45 | |||
| 40dcbabfe8 | |||
| a14f6fcf6f | |||
| 7b3f82aa34 | |||
| 3a36bf6530 | |||
| 195d812d2a | |||
| fdb85ac393 | |||
| d4e3995d71 | |||
| b885aa8c9e | |||
| 9cf0891a04 | |||
| 09ac952404 | |||
| 529bfb5e3a | |||
| ce88596d35 | |||
| 6c3e231d51 | |||
| ae5c511988 | |||
| 9eaf3bc134 | |||
| ff309168ef | |||
| c5c312fc51 | |||
| 34d34a5d91 | |||
| d339fb13b0 | |||
| d0e06e30c9 | |||
| 982db7f75b | |||
| 68e03ac1b0 | |||
| 537150365b | |||
| 12e27a1062 | |||
| 72efa0dc46 | |||
| f2bfc970bc | |||
| 60c926a9c9 | |||
| 10debde847 | |||
| 5cc163dd14 | |||
| 241732752a | |||
| 5a8747cc4b | |||
| 70a50f5117 | |||
| d41b0cb31c | |||
| 33038e8509 | |||
| 57481a1e97 | |||
| 05f91b2a94 | |||
| c4033e3663 | |||
| b940d627d6 | |||
| b320030547 | |||
| d7e0178602 | |||
| c9e75ad5c8 | |||
| 8f1d1df5d6 | |||
| db3a0d7263 | |||
| 636b91ae6f | |||
| 4b820ad6b7 | |||
| a4db80e116 | |||
| 2ebb285a27 | |||
| d05f18ce2d | |||
| 0d74a8a29f | |||
| cdf0b0a694 | |||
| 82f0992116 | |||
| b1ba5e67dc | |||
| 193dac708f | |||
| cd96be80f9 | |||
| aca2be98af | |||
| 360ebfd2e6 | |||
| 5c371e7517 | |||
| 31cded15cc | |||
| 3562b139c3 | |||
| c2040d3ded | |||
| b34f4dda42 |
21
.clang-format
Normal file
@@ -0,0 +1,21 @@
|
||||
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: DontAlign
|
||||
AlignAfterOpenBracket: DontAlign
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
ContinuationIndentWidth: 4
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
Cpp11BracedListStyle: true
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
AllowAllConstructorInitializersOnNextLine: false
|
||||
PackConstructorInitializers: Never
|
||||
AllowAllArgumentsOnNextLine: false
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
83
.clang-tidy
Normal file
@@ -0,0 +1,83 @@
|
||||
Checks:
|
||||
- readability-*
|
||||
- modernize-*
|
||||
- performance-*
|
||||
- bugprone-unchecked-optional-access
|
||||
- bugprone-sizeof-expression
|
||||
- bugprone-suspicious-missing-comma
|
||||
- bugprone-suspicious-index
|
||||
- bugprone-undefined-memory-manipulation
|
||||
- bugprone-use-after-move
|
||||
- bugprone-out-of-bound-access
|
||||
- -readability-identifier-length
|
||||
- -readability-magic-numbers
|
||||
- -bugprone-narrowing-conversions
|
||||
- -performance-enum-size
|
||||
- -performance-inefficient-string-concatenation
|
||||
- -bugprone-integer-division
|
||||
- -bugprone-easily-swappable-parameters
|
||||
|
||||
WarningsAsErrors: '*'
|
||||
# Solo incluir archivos de tu código fuente
|
||||
HeaderFilterRegex: '^source/(sections|ui)/.*'
|
||||
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 }
|
||||
|
||||
# Variables estáticas privadas como miembros privados
|
||||
- { key: readability-identifier-naming.StaticVariableCase, value: lower_case }
|
||||
- { key: readability-identifier-naming.StaticVariableSuffix, value: _ }
|
||||
|
||||
# Constantes estáticas sin sufijo
|
||||
- { key: readability-identifier-naming.StaticConstantCase, value: UPPER_CASE }
|
||||
|
||||
# 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 }
|
||||
|
||||
# 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 }
|
||||
6
.gitignore
vendored
@@ -1,4 +1,4 @@
|
||||
.vscode
|
||||
.vscode/
|
||||
*data/config/config.txt
|
||||
*stats.txt
|
||||
*.DS_Store
|
||||
@@ -11,8 +11,8 @@ thumbs.db
|
||||
*.zip
|
||||
*.app
|
||||
*_debug*
|
||||
sync_jail_engine.sh
|
||||
jaildoctors_dilemma*
|
||||
todo
|
||||
build/
|
||||
linux_utils/
|
||||
linux_utils/
|
||||
.claude/
|
||||
141
BUGS_PLAYER_REWRITE.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# BUGS DETECTADOS - Reescritura Player
|
||||
|
||||
**Fecha:** 2025-10-30
|
||||
**Commit funcional de referencia:** `7cd596a0b9876c75ff75efc13708a2ca00c8cfcd`
|
||||
**Estado:** La reescritura según PLAYER_MECHANICS.md ha introducido múltiples regresiones
|
||||
|
||||
---
|
||||
|
||||
## 🐛 BUGS CRÍTICOS DETECTADOS
|
||||
|
||||
### 2. **Salto recto en rampa: atraviesa la rampa al caer**
|
||||
- **Descripción:** Si el jugador salta verticalmente (sin movimiento horizontal) estando en una rampa, al caer atraviesa la rampa
|
||||
- **Estado esperado:** Salto recto (vx_ == 0) debería pegarse a la rampa al descender
|
||||
- **Regla violada:** PLAYER_MECHANICS.md líneas 386-391 - "JUMPING con vx_ == 0 se PEGA a la rampa"
|
||||
- **Posible causa:** Lógica en `moveVerticalDown()` no detecta correctamente el caso vx_ == 0
|
||||
|
||||
---
|
||||
|
||||
### 4. **No suena al saltar**
|
||||
- **Descripción:** Los sonidos de salto no se reproducen
|
||||
- **Estado esperado:** Sonidos progresivos basados en distancia vertical
|
||||
- **Posible causa:**
|
||||
- `y_prev_` no se inicializa correctamente
|
||||
- Sistema de detección de cambio de índice no funciona
|
||||
- `last_grounded_position_` no se actualiza en el momento correcto
|
||||
|
||||
---
|
||||
|
||||
### 5. **No suena al caer**
|
||||
- **Descripción:** Los sonidos de caída no se reproducen
|
||||
- **Estado esperado:** Sonidos progresivos basados en distancia vertical caída
|
||||
- **Posible causa:** Similar al bug #4, sistema distance-based no detecta cambios
|
||||
|
||||
---
|
||||
|
||||
### 6. **Caer desde precipicio con inercia sobre rampa: resbala en estado FALLING**
|
||||
- **Descripción:** Al caer con inercia horizontal sobre una rampa, el jugador resbala en lugar de pegarse
|
||||
- **Estado esperado:** FALLING siempre debe tener `vx_ = 0` y pegarse a rampas
|
||||
- **Regla violada:** PLAYER_MECHANICS.md línea 147 - "FALLING se PEGA a TODAS las rampas"
|
||||
- **Posible causa:** `vx_` no se establece a 0 correctamente en transición a FALLING, o se ejecuta después del movimiento horizontal
|
||||
|
||||
---
|
||||
|
||||
### 7. **No muere al caer desde gran altura**
|
||||
- **Descripción:** El jugador puede caer desde cualquier altura sin morir
|
||||
- **Estado esperado:** Caída > 32 píxeles (4 tiles) debería matar al jugador
|
||||
- **Regla violada:** PLAYER_MECHANICS.md líneas 158-178
|
||||
- **Posible causa:**
|
||||
- La verificación de muerte en `moveVerticalDown()` no se ejecuta
|
||||
- `previous_state_` no es FALLING cuando debería
|
||||
- Cálculo de `FALL_DISTANCE` es incorrecto
|
||||
|
||||
---
|
||||
|
||||
### 8. **No muere al caer sobre conveyor belt desde altura**
|
||||
- **Descripción:** El jugador puede caer sobre una conveyor belt desde cualquier altura sin morir
|
||||
- **Estado esperado:** Caída > 32 píxeles sobre conveyor belt también debería matar
|
||||
- **Regla violada:** PLAYER_MECHANICS.md líneas 158-178
|
||||
- **Posible causa:**
|
||||
- La verificación de muerte solo está en la rama de suelo normal (`checkTopSurfaces`)
|
||||
- Posiblemente necesita estar también cuando aterriza en `checkAutoSurfaces`
|
||||
- Podría ser un subcaso del bug #7
|
||||
|
||||
---
|
||||
|
||||
## 🔍 ANÁLISIS PRELIMINAR
|
||||
|
||||
### Problema raíz principal: **Orden de ejecución**
|
||||
|
||||
El orden actual es:
|
||||
```cpp
|
||||
move() {
|
||||
y_prev_ = y_;
|
||||
applyGravity();
|
||||
updateStateAndVelocity(); // ← Cambia estado y DEBERÍA cambiar vx_
|
||||
moveHorizontal(); // ← Aplica vx_ (que puede ser incorrecto)
|
||||
moveVertical();
|
||||
updateColliderGeometry();
|
||||
}
|
||||
```
|
||||
|
||||
**Problema:** `updateStateAndVelocity()` puede cambiar el estado a FALLING y establecer `vx_ = 0`, pero esto ocurre DENTRO del switch que solo se ejecuta DESPUÉS de que `previous_state_` ya esté establecido. En el código actual, cuando se hace la transición STANDING → FALLING, `setState()` NO establece `vx_ = 0` (se supone que lo hace `updateStateAndVelocity()`), pero esto puede no ejecutarse hasta el siguiente frame.
|
||||
|
||||
### Problema raíz secundario: **setState() incompleto**
|
||||
|
||||
En el commit funcional (`7cd596a0b9876c75ff75efc13708a2ca00c8cfcd`), `setState()` probablemente establecía TODAS las variables necesarias inmediatamente. En la reescritura actual, se delegó parte de esta responsabilidad a `updateStateAndVelocity()`, creando una desincronización.
|
||||
|
||||
---
|
||||
|
||||
## 📋 PLAN DE SOLUCIÓN
|
||||
|
||||
### Opción A: Volver al commit funcional y refactorizar con cuidado
|
||||
1. Hacer `git diff` entre commit funcional y actual
|
||||
2. Identificar QUÉ funcionaba en el original
|
||||
3. Aplicar solo los cambios necesarios (eliminar `jumping_time_`, unificar variables)
|
||||
4. Mantener la lógica de setState() completa
|
||||
|
||||
### Opción B: Corregir bugs uno por uno en código actual
|
||||
1. Arreglar `setState()` para que establezca TODAS las variables inmediatamente
|
||||
2. Revisar orden de ejecución en `move()`
|
||||
3. Depurar sistema de sonidos
|
||||
4. Probar cada bug individualmente
|
||||
|
||||
### Opción C: Híbrido
|
||||
1. Extraer lógica funcional del commit 7cd596a
|
||||
2. Aplicar solo las correcciones de PLAYER_MECHANICS.md que no rompen funcionalidad:
|
||||
- Cambiar `jump_init_pos_` → `last_grounded_position_` (con cuidado)
|
||||
- Eliminar `jumping_time_` (secundario, no crítico)
|
||||
- Implementar sistema de sonidos distance-based (después de que todo funcione)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 RECOMENDACIÓN
|
||||
|
||||
**Opción C (Híbrido)** parece la más sensata:
|
||||
|
||||
1. Revertir a un punto funcional
|
||||
2. Aplicar cambios incrementales uno por uno
|
||||
3. Testear después de cada cambio
|
||||
4. No hacer cambios arquitecturales grandes (mantener `updateState()` y `updateVelocity()` separados si funcionaba así)
|
||||
|
||||
---
|
||||
|
||||
## 📝 NOTAS ADICIONALES
|
||||
|
||||
- El commit `7cd596a` funciona perfecto según el usuario, aunque el código sea "caótico"
|
||||
- **Lección aprendida:** Refactorizar código funcional sin tests automáticos es peligroso
|
||||
- La sincronización estado-velocidad es más sutil de lo que parecía
|
||||
- PLAYER_MECHANICS.md puede tener asunciones incorrectas sobre el orden de ejecución óptimo
|
||||
|
||||
---
|
||||
|
||||
## ✅ PRÓXIMOS PASOS
|
||||
|
||||
1. Comparar código actual vs commit 7cd596a
|
||||
2. Identificar diferencias críticas en:
|
||||
- `setState()`
|
||||
- `move()`
|
||||
- `updateState()`/`updateVelocity()`
|
||||
- Transiciones de estado
|
||||
3. Decidir estrategia: revertir completo, revertir parcial, o corregir in-place
|
||||
788
CLAUDE.md
Normal file
@@ -0,0 +1,788 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
---
|
||||
|
||||
# JailDoctor's Dilemma - Codebase Architecture Guide
|
||||
|
||||
## Overview
|
||||
|
||||
**JailDoctor's Dilemma** is a retro-style 2D puzzle platformer game built in C++20 using SDL3 for graphics and audio. The game features 60+ rooms, collectible items, enemies, and an achievement system. It targets multiple platforms (Windows, macOS, Linux) with a focus on retro aesthetics and precise collision detection.
|
||||
|
||||
**Language:** C++20
|
||||
**Graphics:** SDL3, OpenGL
|
||||
**Audio:** SDL3 + custom jail_audio library
|
||||
**Build:** CMake 3.10+
|
||||
**Game Canvas:** 256x192 pixels (retro resolution)
|
||||
|
||||
---
|
||||
|
||||
## Build Commands
|
||||
|
||||
### Initial Setup & Build
|
||||
```bash
|
||||
# From project root
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
### Rebuild After Changes
|
||||
```bash
|
||||
# From build directory
|
||||
cmake --build .
|
||||
|
||||
# Or from project root
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
### Clean Build
|
||||
```bash
|
||||
# From build directory
|
||||
cmake --build . --clean-first
|
||||
|
||||
# Or from project root
|
||||
cmake --build build --clean-first
|
||||
```
|
||||
|
||||
### Run the Game
|
||||
```bash
|
||||
# Executable is placed in project root
|
||||
./jaildoctors_dilemma
|
||||
```
|
||||
|
||||
**Important:** The build directory is `/Users/sergio/Gitea/jaildoctors_dilemma/build` and the output executable is placed in the project root directory.
|
||||
|
||||
### Linter (clang-tidy)
|
||||
|
||||
**IMPORTANT:** Always run the linter on specific files, NOT on the entire project, to avoid long execution times and errors in unrelated files.
|
||||
|
||||
```bash
|
||||
# Analyze a specific file (RECOMMENDED)
|
||||
tools/linter/run_clang-tidy.sh source/game/entities/player.cpp
|
||||
|
||||
# Analyze multiple specific files
|
||||
tools/linter/run_clang-tidy.sh source/game/entities/player.cpp source/game/entities/enemy.cpp
|
||||
|
||||
# Apply fixes automatically to a specific file
|
||||
tools/linter/run_clang-tidy.sh --fix source/game/entities/player.cpp
|
||||
|
||||
# Analyze entire project (SLOW, may have errors in defaults.hpp)
|
||||
tools/linter/run_clang-tidy.sh
|
||||
```
|
||||
|
||||
**Note:** Running the linter on the entire project can produce errors in files like `defaults.hpp` that are unrelated to your changes. Always target specific files you're working on.
|
||||
|
||||
---
|
||||
|
||||
## 1. High-Level Architecture Overview
|
||||
|
||||
The architecture follows a **layered, modular design** with clear separation of concerns:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ Application Layer │
|
||||
│ (Director, Scene Manager) │
|
||||
└─────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────┐
|
||||
│ Game Logic Layer │
|
||||
│ (Game Scene, Entities, Gameplay) │
|
||||
└─────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────┐
|
||||
│ Core Systems Layer │
|
||||
│ (Rendering, Audio, Input, Resources)│
|
||||
└─────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────┐
|
||||
│ SDL3 & External Libraries │
|
||||
│ (jail_audio, stb_image, stb_vorbis) │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Key Design Principles
|
||||
|
||||
- **Singleton Pattern:** Core systems (Director, Screen, Audio, Input, Resource, Asset) use singleton pattern for global access
|
||||
- **Scene-Based Architecture:** Game flow managed through discrete scenes (Logo, Title, Loading, Game, Ending, etc.)
|
||||
- **Component-Based Entities:** Player, enemies, and items are discrete entities with render/update patterns
|
||||
- **Resource Management:** All assets (textures, sounds, animations, tilemaps) cached through Resource singleton
|
||||
- **Delta Time:** Frame-rate independent physics using DeltaTimer class
|
||||
|
||||
---
|
||||
|
||||
## 2. Directory Structure
|
||||
|
||||
```
|
||||
source/
|
||||
├── core/ # Core engine systems
|
||||
│ ├── audio/ # Audio management
|
||||
│ │ └── audio.hpp/cpp # Audio singleton (music, sounds, volumes)
|
||||
│ ├── input/ # Input handling
|
||||
│ │ ├── input.hpp/cpp # Input manager (keyboard, gamepad)
|
||||
│ │ ├── global_inputs.hpp # Global input state
|
||||
│ │ └── mouse.hpp # Mouse input
|
||||
│ ├── rendering/ # Graphics rendering
|
||||
│ │ ├── screen.hpp/cpp # Screen/window singleton, SDL renderer
|
||||
│ │ ├── surface.hpp/cpp # 8-bit indexed color surface abstraction
|
||||
│ │ ├── surface_sprite.hpp # Static sprite rendering
|
||||
│ │ ├── surface_animated_sprite.hpp # Animated sprite with frame data
|
||||
│ │ ├── surface_moving_sprite.hpp # Moving sprite with velocity
|
||||
│ │ ├── texture.hpp/cpp # SDL texture wrapper
|
||||
│ │ ├── text.hpp/cpp # Text rendering system
|
||||
│ │ ├── gif.hpp/cpp # GIF image loader
|
||||
│ │ ├── opengl/ # OpenGL shader backend
|
||||
│ │ │ └── opengl_shader.hpp/cpp # CRT shader effects
|
||||
│ │ └── shader_backend.hpp # Abstract shader interface
|
||||
│ ├── resources/ # Asset & Resource management
|
||||
│ │ ├── asset.hpp/cpp # Asset registry (file path mapping)
|
||||
│ │ └── resource.hpp/cpp # Resource singleton (loads/caches assets)
|
||||
│ └── system/ # System management
|
||||
│ ├── director.hpp/cpp # Main application controller
|
||||
│ ├── debug.hpp/cpp # Debug info overlay
|
||||
│ └── global_events.hpp/cpp # Global event broadcasting
|
||||
├── game/ # Game-specific logic
|
||||
│ ├── entities/ # Game objects
|
||||
│ │ ├── player.hpp/cpp # Player entity with physics
|
||||
│ │ ├── enemy.hpp/cpp # Enemy entities
|
||||
│ │ └── item.hpp/cpp # Collectible items
|
||||
│ ├── gameplay/ # Core gameplay systems
|
||||
│ │ ├── room.hpp/cpp # Room/level logic, tilemap, collision
|
||||
│ │ ├── room_tracker.hpp/cpp # Tracks visited rooms
|
||||
│ │ ├── scoreboard.hpp/cpp # Score display & data
|
||||
│ │ ├── item_tracker.hpp/cpp # Tracks collected items
|
||||
│ │ ├── stats.hpp/cpp # Game statistics
|
||||
│ │ └── cheevos.hpp/cpp # Achievement system
|
||||
│ ├── scenes/ # Game scenes (flow states)
|
||||
│ │ ├── logo.hpp/cpp # JailGames logo screen
|
||||
│ │ ├── loading_screen.hpp/cpp # Resource loading progress
|
||||
│ │ ├── title.hpp/cpp # Title screen & menus
|
||||
│ │ ├── game.hpp/cpp # Main gameplay loop
|
||||
│ │ ├── game_over.hpp/cpp # Game over screen
|
||||
│ │ ├── ending.hpp/cpp # Ending sequence 1
|
||||
│ │ ├── ending2.hpp/cpp # Ending sequence 2
|
||||
│ │ └── credits.hpp/cpp # Credits screen
|
||||
│ ├── ui/ # User interface
|
||||
│ │ └── notifier.hpp/cpp # Achievement/notification display
|
||||
│ ├── options.hpp/cpp # Game configuration/options
|
||||
│ ├── scene_manager.hpp # Scene flow state machine
|
||||
│ ├── defaults.hpp # Game defaults constants
|
||||
│ └── gameplay.hpp # Gameplay constants
|
||||
├── external/ # Third-party libraries
|
||||
│ ├── jail_audio.hpp/cpp # Custom audio library
|
||||
│ ├── jail_audio.h # C interface for jail_audio
|
||||
│ ├── stb_image.h # Image loading library
|
||||
│ └── stb_vorbis.h # OGG Vorbis audio decoding
|
||||
├── utils/ # Utility code
|
||||
│ ├── delta_timer.hpp/cpp # Frame-rate independent timing
|
||||
│ ├── defines.hpp # Game constants (resolutions, block sizes)
|
||||
│ └── utils.hpp/cpp # Helper functions (colors, math)
|
||||
└── main.cpp # Application entry point
|
||||
|
||||
data/ # Game assets
|
||||
├── font/ # Bitmap fonts + descriptors
|
||||
├── palette/ # Color palettes (.pal files)
|
||||
├── shaders/ # GLSL vertex/fragment shaders
|
||||
├── room/ # Tilemaps & room definitions (01.tmx-60.tmx)
|
||||
├── tilesets/ # Tileset graphics
|
||||
├── enemies/ # Enemy sprites & animations
|
||||
├── player/ # Player sprites & animations
|
||||
├── items/ # Item sprite sheets
|
||||
├── music/ # Background music (OGG)
|
||||
├── sound/ # Sound effects (WAV)
|
||||
├── logo/ # Logo images
|
||||
├── loading/ # Loading screen graphics
|
||||
├── title/ # Title screen graphics
|
||||
├── ending/ # Ending sequence images
|
||||
└── credits/ # Credits screen assets
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Key Architectural Patterns
|
||||
|
||||
### 3.1 Singleton Pattern (Core Systems)
|
||||
|
||||
Most core systems use thread-safe singleton pattern:
|
||||
|
||||
```cpp
|
||||
class Screen {
|
||||
private:
|
||||
static Screen* screen_; // Singleton instance
|
||||
Screen(); // Private constructor
|
||||
~Screen();
|
||||
public:
|
||||
static void init(); // Creates singleton
|
||||
static void destroy(); // Destroys singleton
|
||||
static Screen* get(); // Accesses singleton
|
||||
};
|
||||
```
|
||||
|
||||
**Singleton Systems:**
|
||||
- `Screen` - Rendering, window management, palette/shader effects
|
||||
- `Input` - Keyboard & gamepad input binding and checking
|
||||
- `Audio` - Music and sound effect playback
|
||||
- `Resource` - Asset loading, caching, streaming
|
||||
- `Asset` - Asset path registry and verification
|
||||
- `Director` - Main application controller
|
||||
- `Cheevos` - Achievement state management
|
||||
- `Debug` - Debug information overlay
|
||||
|
||||
### 3.2 Scene-Based State Machine
|
||||
|
||||
The game uses a scene manager to control application flow:
|
||||
|
||||
```cpp
|
||||
// namespace SceneManager
|
||||
enum class Scene {
|
||||
LOGO, LOADING_SCREEN, TITLE, CREDITS, GAME, DEMO,
|
||||
GAME_OVER, ENDING, ENDING2, QUIT
|
||||
};
|
||||
|
||||
inline Scene current = Scene::LOGO; // Global scene state
|
||||
inline Options options = ...; // Transition options
|
||||
```
|
||||
|
||||
**Scene Hierarchy:**
|
||||
- Each scene runs its own update/render loop
|
||||
- `Director` switches between scenes based on `SceneManager::current`
|
||||
- Scenes can request transitions via `SceneManager::current` assignment
|
||||
|
||||
### 3.3 Entity-Component Pattern (Simplified)
|
||||
|
||||
Entities (Player, Enemies, Items) have:
|
||||
- **Update** - Logic, physics, animation
|
||||
- **Render** - Draw to screen surface
|
||||
- **Collision** - Hit detection (player collides with room, enemies, items)
|
||||
|
||||
### 3.4 Surface-Based Rendering Pipeline
|
||||
|
||||
The rendering system uses a **8-bit indexed color** pipeline:
|
||||
|
||||
```
|
||||
SurfaceData (pixel buffer)
|
||||
↓
|
||||
Surface (palette + rendering operations)
|
||||
↓
|
||||
SDL_Texture (GPU texture)
|
||||
↓
|
||||
SDL_Renderer (to SDL_Window)
|
||||
↓
|
||||
Display
|
||||
```
|
||||
|
||||
**Key Components:**
|
||||
- `Surface` - 8-bit indexed pixel buffer with palette support
|
||||
- `SurfaceSprite` - Renders a fixed region of a surface
|
||||
- `SurfaceAnimatedSprite` - Frame-based animation on top of sprite
|
||||
- `SurfaceMovingSprite` - Adds velocity/position to animated sprite
|
||||
- Supports color replacement, palette swapping, and shader effects (CRT)
|
||||
|
||||
### 3.5 Tile-Based Collision System
|
||||
|
||||
Rooms use a sophisticated collision detection system:
|
||||
|
||||
```cpp
|
||||
class Room {
|
||||
std::vector<LineHorizontal> bottom_floors_; // Ground surfaces
|
||||
std::vector<LineHorizontal> top_floors_; // Ceiling surfaces
|
||||
std::vector<LineVertical> left_walls_; // Left walls
|
||||
std::vector<LineVertical> right_walls_; // Right walls
|
||||
std::vector<LineDiagonal> left_slopes_; // Ramps going left
|
||||
std::vector<LineDiagonal> right_slopes_; // Ramps going right
|
||||
std::vector<LineHorizontal> conveyor_belt_floors_; // Moving platforms
|
||||
};
|
||||
```
|
||||
|
||||
**Collision Detection:**
|
||||
- Player has collision points and "feet" points for fine-grained detection
|
||||
- Room provides `check*Surfaces()` methods for collision resolution
|
||||
- Supports ramps, slopes, conveyor belts, and auto-surfaces
|
||||
- Enemies have axis-aligned bounding boxes
|
||||
|
||||
### 3.6 Sprite Animation System
|
||||
|
||||
Animation is data-driven:
|
||||
|
||||
```cpp
|
||||
struct AnimationData {
|
||||
std::string name;
|
||||
std::vector<SDL_FRect> frames; // Frame rectangles
|
||||
int speed; // Milliseconds per frame
|
||||
int loop; // Frame to return to (-1 = no loop)
|
||||
bool completed;
|
||||
int current_frame;
|
||||
int counter;
|
||||
};
|
||||
|
||||
// Loaded from .ani files (list of animation names)
|
||||
// Rendered with SurfaceAnimatedSprite
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. System Interactions & Data Flow
|
||||
|
||||
### 4.1 Application Lifecycle
|
||||
|
||||
```
|
||||
main()
|
||||
↓
|
||||
Director::Director() [Initialization]
|
||||
├─ Options::init() - Load game configuration
|
||||
├─ Asset::init() - Register asset paths
|
||||
├─ Screen::init() - Create window, SDL renderer
|
||||
├─ Audio::init() - Initialize SDL audio
|
||||
├─ Input::init() - Bind keyboard/gamepad controls
|
||||
├─ Resource::init() - Load all game resources
|
||||
└─ Cheevos::init() - Load achievement state
|
||||
|
||||
Director::run() [Main loop]
|
||||
├─ while (SceneManager::current != QUIT)
|
||||
│ ├─ Logo::run()
|
||||
│ ├─ LoadingScreen::run()
|
||||
│ ├─ Title::run()
|
||||
│ ├─ Game::run()
|
||||
│ ├─ Ending::run()
|
||||
│ └─ ...
|
||||
└─ return 0
|
||||
|
||||
Director::~Director() [Cleanup]
|
||||
├─ Options::saveToFile() - Save game settings
|
||||
├─ Resource::destroy()
|
||||
├─ Audio::destroy()
|
||||
├─ Input::destroy()
|
||||
├─ Screen::destroy()
|
||||
└─ Asset::destroy()
|
||||
```
|
||||
|
||||
### 4.2 Game Scene Flow (Core Gameplay Loop)
|
||||
|
||||
```cpp
|
||||
Game::run() {
|
||||
while (game is running) {
|
||||
// Update
|
||||
Input::checkInput() - Get player commands
|
||||
Player::update() - Physics, animation, collision
|
||||
Room::update() - Enemy AI, animated tiles
|
||||
checkCollisions() - Player vs enemies, items, room
|
||||
checkGameOver() - Win/lose conditions
|
||||
|
||||
// Render
|
||||
Screen::start() - Prepare for drawing
|
||||
Room::renderMap() - Draw tilemap
|
||||
Room::renderEnemies() - Draw enemy sprites
|
||||
Room::renderItems() - Draw item sprites
|
||||
Player::render() - Draw player sprite
|
||||
renderScoreboard() - Draw HUD
|
||||
Screen::render() - Flush to GPU
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 Resource Loading & Caching
|
||||
|
||||
```
|
||||
Director::setFileList()
|
||||
├─ Asset::add(file, type) - Register all assets
|
||||
└─ Asset::check() - Verify files exist
|
||||
|
||||
Game Scene initialization
|
||||
└─ Resource::init() - Loads all resources
|
||||
├─ loadSounds() - WAV files
|
||||
├─ loadMusics() - OGG files
|
||||
├─ loadSurfaces() - GIF/PNG images
|
||||
├─ loadAnimations() - .ani animation definitions
|
||||
├─ loadTileMaps() - .room tilemap data
|
||||
└─ loadRooms() - Room metadata
|
||||
|
||||
During gameplay
|
||||
└─ Resource::get*(name) - Return cached resource
|
||||
```
|
||||
|
||||
### 4.4 Input Flow
|
||||
|
||||
```
|
||||
SDL_Event (from OS)
|
||||
↓
|
||||
Input::checkInput(action)
|
||||
├─ Check keyboard bindings - SDL_Scancode → InputAction
|
||||
├─ Check gamepad bindings - SDL_GamepadButton → InputAction
|
||||
└─ Return true if action active
|
||||
|
||||
Game logic uses checked inputs
|
||||
└─ Player responds to actions
|
||||
```
|
||||
|
||||
### 4.5 Audio Control Flow
|
||||
|
||||
```
|
||||
Game code
|
||||
├─ Audio::playMusic(name, loop)
|
||||
├─ Audio::playSound(name, group)
|
||||
└─ Audio::stopMusic()
|
||||
↓
|
||||
Audio [wrapper/manager]
|
||||
├─ Resource::getMusic(name)
|
||||
├─ Resource::getSound(name)
|
||||
└─ jail_audio C library
|
||||
└─ SDL3 Audio device
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Important Design Patterns & Conventions
|
||||
|
||||
### 5.1 Naming Conventions
|
||||
|
||||
**Classes:**
|
||||
- `PascalCase` for classes: `Player`, `Room`, `Screen`, `Director`
|
||||
- Suffix `Sprite` for sprite classes: `SurfaceSprite`, `SurfaceAnimatedSprite`
|
||||
|
||||
**Methods:**
|
||||
- `get*()` for getters: `getWidth()`, `getRect()`
|
||||
- `set*()` for setters: `setColor()`, `setPos()`
|
||||
- `check*()` for boolean checks: `checkInput()`, `checkCollision()`
|
||||
- `update()` for game logic updates
|
||||
- `render()` for drawing
|
||||
|
||||
**Variables:**
|
||||
- `snake_case` for member variables with `_` suffix: `x_`, `y_`, `sprite_`
|
||||
- `UPPER_CASE` for constants: `BLOCK`, `MAX_VY`, `WIDTH`
|
||||
- Private members: `private_member_`
|
||||
|
||||
**Structs for Data:**
|
||||
- `XxxData` suffix: `PlayerData`, `RoomData`, `AnimationData`
|
||||
- Used as initialization structures passed to constructors
|
||||
|
||||
### 5.2 Memory Management
|
||||
|
||||
- **Smart Pointers:** Uses `std::shared_ptr` for shared ownership (Surfaces, Sprites, Rooms)
|
||||
- **Unique Pointers:** Uses `std::unique_ptr` for sole ownership (Director, local objects)
|
||||
- **Raw Pointers:** Minimal use, mainly for singleton access or SDL objects
|
||||
- **Static Allocation:** Singletons use static pointer pattern for RAII
|
||||
|
||||
### 5.3 Frame-Independent Physics
|
||||
|
||||
Uses `DeltaTimer` for delta time calculation:
|
||||
|
||||
```cpp
|
||||
// In game loop
|
||||
float delta = deltaTimer.tick(); // Get seconds since last frame
|
||||
|
||||
// Apply to physics
|
||||
player.vy_ += gravity * delta;
|
||||
player.y_ += player.vy_ * delta;
|
||||
```
|
||||
|
||||
Provides **time scaling** for slow-motion effects.
|
||||
|
||||
### 5.4 Palette System
|
||||
|
||||
- 8-bit indexed color (256 colors per palette)
|
||||
- Multiple palettes can be loaded and swapped
|
||||
- `Surface::setPalette()` changes rendering colors
|
||||
- Supports color replacement per-render: `renderWithColorReplace()`
|
||||
- CRT shader effects can modify colors in real-time
|
||||
|
||||
### 5.5 Configuration System
|
||||
|
||||
Game settings stored in configuration file:
|
||||
|
||||
```cpp
|
||||
namespace Options {
|
||||
inline Video video{}; // Screen resolution, fullscreen, etc.
|
||||
inline Audio audio{}; // Music/sound volumes
|
||||
inline Notification notifications{};
|
||||
inline Cheat cheats{}; // Cheat codes
|
||||
inline ControlScheme keys{}; // Control mapping
|
||||
inline Stats stats{}; // Game statistics
|
||||
}
|
||||
|
||||
Options::loadFromFile(path); // Load from config.txt
|
||||
Options::saveToFile(path); // Save on exit
|
||||
```
|
||||
|
||||
### 5.6 Achievement System
|
||||
|
||||
```cpp
|
||||
struct Achievement {
|
||||
int id;
|
||||
std::string caption;
|
||||
std::string description;
|
||||
int icon;
|
||||
bool completed;
|
||||
bool obtainable;
|
||||
};
|
||||
|
||||
Cheevos::unlock(id); // Unlock achievement
|
||||
Cheevos::setUnobtainable(id); // Lock achievement
|
||||
Cheevos::saveToFile(); // Persist state
|
||||
```
|
||||
|
||||
Achievements trigger notifications on unlock.
|
||||
|
||||
---
|
||||
|
||||
## 6. Technology Stack
|
||||
|
||||
### Core Technologies
|
||||
|
||||
| Component | Technology | Version | Role |
|
||||
|-----------|-----------|---------|------|
|
||||
| **Graphics** | SDL3 | Latest | Window, rendering, input |
|
||||
| **GPU Rendering** | OpenGL | 3.2+ | Shader effects (CRT) |
|
||||
| **Audio** | SDL3 Audio | Latest | Audio device, mixing |
|
||||
| **Audio Decoding** | jail_audio (custom) | 1.x | OGG/WAV playback |
|
||||
| **Image Loading** | stb_image | v2.x | PNG/GIF image loading |
|
||||
| **Audio Decoding** | stb_vorbis | v1.x | OGG Vorbis support |
|
||||
| **Language** | C++ | C++20 | Standard library features |
|
||||
| **Build System** | CMake | 3.10+ | Cross-platform building |
|
||||
|
||||
### C++ Features Used
|
||||
|
||||
- **Smart Pointers:** `std::shared_ptr`, `std::unique_ptr`
|
||||
- **Standard Containers:** `std::vector`, `std::array`
|
||||
- **Modern Features:** `std::move`, lambda functions, constexpr
|
||||
- **Namespaces:** Extensive use for organization
|
||||
- **Inline Variables:** C++17 `inline` for global game state
|
||||
|
||||
### Platform Support
|
||||
|
||||
- **Windows:** MinGW/MSVC with SDL3
|
||||
- **macOS:** Apple Clang, arm64 architecture, OpenGL
|
||||
- **Linux:** GCC with SDL3 and OpenGL
|
||||
|
||||
---
|
||||
|
||||
## 7. Key Classes & Their Responsibilities
|
||||
|
||||
### Core System Classes
|
||||
|
||||
| Class | Purpose | Pattern |
|
||||
|-------|---------|---------|
|
||||
| `Director` | Main application controller, scene manager | Singleton |
|
||||
| `Screen` | Rendering, window, palette management | Singleton |
|
||||
| `Input` | Keyboard & gamepad input | Singleton |
|
||||
| `Audio` | Music and SFX playback | Singleton |
|
||||
| `Resource` | Asset caching and loading | Singleton |
|
||||
| `Asset` | Asset path registry | Singleton |
|
||||
| `Debug` | Debug overlay information | Singleton |
|
||||
| `globalEvents` | Global SDL event handling (quit, device reset, mouse) | Namespace |
|
||||
|
||||
### Game Logic Classes
|
||||
|
||||
| Class | Purpose |
|
||||
|-------|---------|
|
||||
| `Game` | Main gameplay scene, orchestrates update/render |
|
||||
| `Player` | Player entity with physics and animation |
|
||||
| `Room` | Level data, collision detection, tilemap rendering |
|
||||
| `Enemy` | Enemy entity behavior and rendering |
|
||||
| `Item` | Collectible items |
|
||||
| `Scoreboard` | HUD display data |
|
||||
| `Cheevos` | Achievement unlock and state |
|
||||
| `ItemTracker` | Tracks collected items |
|
||||
| `RoomTracker` | Tracks visited rooms |
|
||||
|
||||
### Rendering Classes
|
||||
|
||||
| Class | Purpose |
|
||||
|-------|---------|
|
||||
| `Surface` | 8-bit indexed color pixel buffer with palette |
|
||||
| `SurfaceSprite` | Renders a sprite region |
|
||||
| `SurfaceAnimatedSprite` | Frame-based animation rendering |
|
||||
| `SurfaceMovingSprite` | Sprite with velocity/position |
|
||||
| `Text` | Text rendering system |
|
||||
| `OpenGLShader` | Shader compilation and effects |
|
||||
|
||||
### Utility Classes
|
||||
|
||||
| Class | Purpose |
|
||||
|-------|---------|
|
||||
| `DeltaTimer` | Frame-rate independent timing |
|
||||
|
||||
---
|
||||
|
||||
## 8. Common Development Workflows
|
||||
|
||||
### Adding a New Input Action
|
||||
|
||||
1. Add to `InputAction` enum in `core/input/input.hpp`
|
||||
2. Bind in `Director::initInput()`:
|
||||
```cpp
|
||||
Input::get()->bindKey(InputAction::NEW_ACTION, SDL_SCANCODE_X);
|
||||
```
|
||||
3. Check in game code:
|
||||
```cpp
|
||||
if (Input::get()->checkInput(InputAction::NEW_ACTION)) {
|
||||
// Handle action
|
||||
}
|
||||
```
|
||||
|
||||
### Adding a New Scene
|
||||
|
||||
1. Create class inheriting appropriate base (usually standalone `run()` method)
|
||||
2. Add to `SceneManager::Scene` enum
|
||||
3. Implement in `Director::run()` switch statement
|
||||
4. Set `SceneManager::current` to transition
|
||||
|
||||
### Adding Game Assets
|
||||
|
||||
1. Place file in `data/` directory
|
||||
2. Register in `Director::setFileList()`:
|
||||
```cpp
|
||||
Asset::get()->add("/data/path/file.ext", AssetType::TYPE);
|
||||
```
|
||||
3. Resource loads automatically during `Resource::init()`
|
||||
4. Access via: `Resource::get()->getSurface("name")`
|
||||
|
||||
### Modifying Collision Detection
|
||||
|
||||
1. Update `Room::setBottomSurfaces()`, `setLeftSlopes()`, etc.
|
||||
2. Modify Player collision point generation in `Player::updateColliderPoints()`
|
||||
3. Adjust tile classification in `TileType` enum
|
||||
4. Test with debug visualization (F12 key)
|
||||
|
||||
---
|
||||
|
||||
## 9. Debug Features
|
||||
|
||||
### Available at Runtime
|
||||
|
||||
- **F12** - Toggle debug info overlay (FPS, player position, collision points)
|
||||
- **F1/F2** - Decrease/increase window zoom
|
||||
- **F3** - Toggle fullscreen mode
|
||||
- **F4** - Toggle shader effects
|
||||
- **F5/F6** - Next/previous palette
|
||||
- **F7** - Toggle integer scaling
|
||||
- **M** - Toggle music
|
||||
- **B** - Toggle border display
|
||||
- **P** - Pause game
|
||||
|
||||
### Debug Mode Compilation
|
||||
|
||||
In debug builds (`#ifdef DEBUG`), renders:
|
||||
- Player collision boxes
|
||||
- Collision point visualization
|
||||
- Debug information overlay
|
||||
- Special debug event handling
|
||||
|
||||
---
|
||||
|
||||
## 10. Performance Considerations
|
||||
|
||||
### Optimization Points
|
||||
|
||||
1. **Rendering:** Uses indexed color (8-bit) to reduce memory bandwidth
|
||||
2. **Surfaces:** Shared smart pointers reduce copying
|
||||
3. **Collision:** Pre-computed tile surface lists avoid per-frame searches
|
||||
4. **Animation:** Frame-based animation reduces computation vs. bone systems
|
||||
5. **Audio:** Cached music and sound effects, no runtime decoding
|
||||
6. **Delta Time:** Frame-rate independent logic for smooth gameplay
|
||||
|
||||
### Known Limitations
|
||||
|
||||
- Single-threaded architecture (SDL3 requires single-thread rendering)
|
||||
- Surfaces stored entirely in CPU memory (not GPU-side textures)
|
||||
- Palette system requires full surface redraw when changing colors
|
||||
|
||||
---
|
||||
|
||||
## 11. File Format Reference
|
||||
|
||||
### Animation Files (.ani)
|
||||
List of animation names, one per line:
|
||||
```
|
||||
default
|
||||
jump
|
||||
run
|
||||
fall
|
||||
```
|
||||
|
||||
### Room Data Files (.room)
|
||||
Key-value pairs defining room properties:
|
||||
```
|
||||
number=01
|
||||
name=Starting Room
|
||||
bg_color=0x000000
|
||||
border_color=0xFF00FF
|
||||
...
|
||||
```
|
||||
|
||||
### Tilemap Files (.tmx)
|
||||
Tiled map format with tileset and collision data.
|
||||
|
||||
### Palette Files (.pal)
|
||||
Binary 256-color palette format (256 × 4 bytes RGBA).
|
||||
|
||||
---
|
||||
|
||||
## 12. Quick Reference: Main Entry Points
|
||||
|
||||
### For Graphics Issues
|
||||
- `Screen::render()` - Main rendering method
|
||||
- `Screen::setPalete()` - Palette application
|
||||
- `Surface` class - Pixel buffer operations
|
||||
|
||||
### For Input Issues
|
||||
- `Input::checkInput()` - Input state checking
|
||||
- `Director::initInput()` - Binding configuration
|
||||
|
||||
### For Audio Issues
|
||||
- `Audio::playMusic()` - Music playback
|
||||
- `Audio::playSound()` - SFX playback
|
||||
- `jail_audio` library - Low-level audio operations
|
||||
|
||||
### For Game Logic
|
||||
- `Game::run()` - Main game loop
|
||||
- `Room` class - Collision and level logic
|
||||
- `Player::update()` - Physics and movement
|
||||
|
||||
### For Asset Management
|
||||
- `Asset::add()` - Asset registration
|
||||
- `Resource::load()` - Asset loading
|
||||
- `Director::setFileList()` - Complete asset registry
|
||||
|
||||
---
|
||||
|
||||
## 13. Future Enhancement Points
|
||||
|
||||
### Identified Areas for Expansion
|
||||
|
||||
1. **Network Play:** Stats upload to online service
|
||||
2. **More Scenes:** Additional game modes
|
||||
3. **Custom Rooms:** Level editor integration
|
||||
4. **Audio Streaming:** Background music without loading entire file
|
||||
5. **Particle System:** Visual effects for pickups/collisions
|
||||
6. **Controller Feedback:** Haptic feedback for game events
|
||||
7. **Accessibility:** Font scaling, color-blind modes, key remapping UI
|
||||
|
||||
---
|
||||
|
||||
## Development Notes
|
||||
|
||||
- **Language:** All code comments and some variable names are in Spanish (maintaining original author style)
|
||||
- **Compilation:** Use CMake - automatically handles platform differences
|
||||
- **Performance Profiling:** Use debug overlay (F12) for basic metrics; consider external profilers for deeper analysis
|
||||
- **Common Warnings:** The codebase has been cleaned of the `struct`/`class` forward declaration inconsistency warnings that previously appeared
|
||||
|
||||
### Important Code Consistency Rules
|
||||
|
||||
1. **Forward Declarations:** Always use `class` for forward declarations of classes defined with `class` (not `struct`). The `Surface` class is defined as `class Surface` in `surface.hpp:57`, so all forward declarations must use `class Surface;`
|
||||
|
||||
2. **Singleton Pattern:** When creating new singletons, follow the existing pattern:
|
||||
- Private static instance pointer
|
||||
- Private constructor/destructor
|
||||
- Public `init()`, `destroy()`, and `get()` methods
|
||||
|
||||
3. **Delta Time:** Always use `DeltaTimer` for frame-rate independent physics calculations
|
||||
|
||||
4. **Memory Management:** Prefer `std::shared_ptr` for shared resources (Surfaces, Sprites) and `std::unique_ptr` for sole ownership
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** November 2022 (per README)
|
||||
**Original Author:** JailDesigner
|
||||
**Repository:** Gitea (internal)
|
||||
171
CMakeLists.txt
@@ -3,83 +3,160 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
project(jaildoctors_dilemma VERSION 1.00)
|
||||
|
||||
# Configuración de compilador para MinGW en Windows, si es necesario
|
||||
if(WIN32 AND NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
|
||||
set(CMAKE_CXX_COMPILER "g++")
|
||||
set(CMAKE_C_COMPILER "gcc")
|
||||
endif()
|
||||
|
||||
# Establecer estándar de C++
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
|
||||
# Configuración global de flags de compilación
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Os -ffunction-sections -fdata-sections")
|
||||
# Exportar comandos de compilación para herramientas de análisis
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# Define el directorio de los archivos fuente
|
||||
set(DIR_SOURCES "${CMAKE_SOURCE_DIR}/source")
|
||||
# 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)
|
||||
|
||||
# Cargar todos los archivos fuente en DIR_SOURCES
|
||||
file(GLOB SOURCES "${DIR_SOURCES}/*.cpp")
|
||||
|
||||
# Verificar si se encontraron archivos fuente
|
||||
if(NOT SOURCES)
|
||||
message(FATAL_ERROR "No se encontraron archivos fuente en ${DIR_SOURCES}. Verifica que el directorio existe y contiene archivos .cpp.")
|
||||
endif()
|
||||
|
||||
# Configuración de SDL2
|
||||
find_package(SDL2 REQUIRED)
|
||||
if(SDL2_FOUND)
|
||||
message(STATUS "SDL2 encontrado: ${SDL2_INCLUDE_DIRS}")
|
||||
include_directories(${SDL2_INCLUDE_DIRS})
|
||||
link_directories(${SDL2_LIBDIR})
|
||||
# --- 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()
|
||||
message(FATAL_ERROR "SDL2 no encontrado")
|
||||
set(GIT_HASH "unknown")
|
||||
endif()
|
||||
|
||||
# Incluye rutas de SDL2 obtenidas con pkg-config
|
||||
include_directories(/usr/local/include /usr/local/include/SDL2)
|
||||
link_directories(/usr/local/lib)
|
||||
# Configurar archivo de versión
|
||||
configure_file(${CMAKE_SOURCE_DIR}/source/version.h.in ${CMAKE_BINARY_DIR}/version.h @ONLY)
|
||||
|
||||
# Definir las bibliotecas comunes
|
||||
set(LIBS SDL2)
|
||||
# --- 1. LISTA EXPLÍCITA DE FUENTES ---
|
||||
set(APP_SOURCES
|
||||
# Core - Audio
|
||||
source/core/audio/audio.cpp
|
||||
|
||||
# Configuración común de salida de ejecutables en el directorio raíz
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
# Core - Input
|
||||
source/core/input/global_inputs.cpp
|
||||
source/core/input/input.cpp
|
||||
source/core/input/mouse.cpp
|
||||
|
||||
# Añadir ejecutable principal
|
||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||
# Core - Rendering
|
||||
source/core/rendering/gif.cpp
|
||||
source/core/rendering/screen.cpp
|
||||
source/core/rendering/surface.cpp
|
||||
source/core/rendering/surface_animated_sprite.cpp
|
||||
source/core/rendering/surface_moving_sprite.cpp
|
||||
source/core/rendering/surface_sprite.cpp
|
||||
source/core/rendering/text.cpp
|
||||
source/core/rendering/texture.cpp
|
||||
|
||||
# Añadir definiciones de compilación dependiendo del tipo de build
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<CONFIG:DEBUG>:DEBUG VERBOSE>)
|
||||
# Core - Resources
|
||||
source/core/resources/asset.cpp
|
||||
source/core/resources/resource.cpp
|
||||
|
||||
# Enlazar bibliotecas
|
||||
target_link_libraries(${PROJECT_NAME} ${LIBS})
|
||||
# Core - System
|
||||
source/core/system/debug.cpp
|
||||
source/core/system/director.cpp
|
||||
source/core/system/global_events.cpp
|
||||
|
||||
# Game - Entities
|
||||
source/game/entities/enemy.cpp
|
||||
source/game/entities/item.cpp
|
||||
source/game/entities/player.cpp
|
||||
|
||||
# Game - Configuration
|
||||
source/game/options.cpp
|
||||
|
||||
# Game - Gameplay
|
||||
source/game/gameplay/cheevos.cpp
|
||||
source/game/gameplay/item_tracker.cpp
|
||||
source/game/gameplay/room.cpp
|
||||
source/game/gameplay/room_tracker.cpp
|
||||
source/game/gameplay/scoreboard.cpp
|
||||
source/game/gameplay/stats.cpp
|
||||
|
||||
# Game - Scenes
|
||||
source/game/scenes/credits.cpp
|
||||
source/game/scenes/ending.cpp
|
||||
source/game/scenes/ending2.cpp
|
||||
source/game/scenes/game.cpp
|
||||
source/game/scenes/game_over.cpp
|
||||
source/game/scenes/loading_screen.cpp
|
||||
source/game/scenes/logo.cpp
|
||||
source/game/scenes/title.cpp
|
||||
|
||||
# Game - UI
|
||||
source/game/ui/notifier.cpp
|
||||
|
||||
# Utils
|
||||
source/utils/delta_timer.cpp
|
||||
source/utils/utils.cpp
|
||||
|
||||
# Main
|
||||
source/main.cpp
|
||||
)
|
||||
|
||||
# Fuentes de librerías de terceros
|
||||
set(EXTERNAL_SOURCES
|
||||
source/external/jail_audio.cpp
|
||||
)
|
||||
|
||||
# Fuentes del sistema de renderizado
|
||||
set(RENDERING_SOURCES
|
||||
source/core/rendering/opengl/opengl_shader.cpp
|
||||
)
|
||||
|
||||
# Configuración de SDL3
|
||||
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
|
||||
message(STATUS "SDL3 encontrado: ${SDL3_INCLUDE_DIRS}")
|
||||
|
||||
# --- 2. AÑADIR EJECUTABLE ---
|
||||
add_executable(${PROJECT_NAME} ${APP_SOURCES} ${EXTERNAL_SOURCES} ${RENDERING_SOURCES})
|
||||
|
||||
# --- 3. DIRECTORIOS DE INCLUSIÓN ---
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC
|
||||
"${CMAKE_SOURCE_DIR}/source"
|
||||
"${CMAKE_BINARY_DIR}"
|
||||
)
|
||||
|
||||
# Enlazar la librería SDL3
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE SDL3::SDL3)
|
||||
|
||||
|
||||
# --- 4. CONFIGURACIÓN PLATAFORMAS Y COMPILADOR ---
|
||||
# Configuración de flags de compilación
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wall)
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE $<$<CONFIG:RELEASE>:-Os -ffunction-sections -fdata-sections>)
|
||||
|
||||
# Definir _DEBUG en modo Debug
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE $<$<CONFIG:DEBUG>:_DEBUG>)
|
||||
|
||||
# Configuración específica para cada plataforma
|
||||
if(WIN32)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE WINDOWS_BUILD)
|
||||
target_link_libraries(${PROJECT_NAME} mingw32 opengl32 gdi32 winmm imm32 ole32 version)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE ws2_32 mingw32 opengl32)
|
||||
elseif(APPLE)
|
||||
set(LIBS ${LIBS} "-framework OpenGL")
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE MACOS_BUILD)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated")
|
||||
# Configurar compilación para Apple Silicon
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE -Wno-deprecated)
|
||||
set(CMAKE_OSX_ARCHITECTURES "arm64")
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
set(LIBS ${LIBS} GL)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE LINUX_BUILD)
|
||||
target_link_libraries(${PROJECT_NAME} ${LIBS})
|
||||
endif()
|
||||
|
||||
# Añadir OpenGL a las bibliotecas enlazadas
|
||||
# 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} ${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})
|
||||
4
Makefile
@@ -2,7 +2,7 @@ executable = jaildoctors_dilemma
|
||||
source = source/*.cpp
|
||||
appName = JailDoctor's Dilemma
|
||||
releaseFolder = jdd_release
|
||||
version = v1.09
|
||||
version = v1.10
|
||||
|
||||
# Release names
|
||||
windowsRelease = $(executable)-$(version)-win32-x64.zip
|
||||
@@ -90,7 +90,7 @@ macos_release:
|
||||
ln -s /Applications "$(releaseFolder)"/Applications
|
||||
|
||||
# Build INTEL
|
||||
clang++ $(source) -D MACOS_BUNDLE -std=$(cpp_standard) -Wall -Os -framework SDL2 -F ./Frameworks -framework OpenGL -Wno-deprecated -ffunction-sections -fdata-sections -o "$(releaseFolder)/$(appName).app/Contents/MacOS/$(executable)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.12
|
||||
clang++ $(source) -D MACOS_BUNDLE -std=$(cpp_standard) -Wall -Os -framework SDL2 -F ./Frameworks -framework OpenGL -Wno-deprecated -ffunction-sections -fdata-sections -o "$(releaseFolder)/$(appName).app/Contents/MacOS/$(executable)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.15
|
||||
|
||||
# Build INTEL DMG
|
||||
hdiutil create tmp.dmg -ov -volname "$(appName)" -fs HFS+ -srcfolder "$(releaseFolder)"
|
||||
|
||||
1529
PLAYER_MECHANICS.md
Normal file
49
PLAYER_RULES.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Reglas para la clase Player
|
||||
|
||||
## Estados
|
||||
|
||||
El jugador tiene tres estados diferenciados:
|
||||
- STANDING
|
||||
- JUMPING
|
||||
- FALLING
|
||||
|
||||
## Puntos de colision
|
||||
|
||||
El jugador tiene un rectabgulo que lo delimita. Se obtiene con getRect()
|
||||
Tiene ademas dos puntos en un vector de puntos llamado feet_ con el punto inferior izquierdo y el inferior derecho
|
||||
Tiene otros dos puntos llamados under_feet_ que son los puntos inmediatamente inferiores a los puntos en feet_. Se usan para saber SOBRE qué tipo de superficie esta el jugador o si bajo solo tiene aire
|
||||
Tiene otros 8 puntos (el jugador ocupa dos tiles en vertical del mapa, los tiles son de 8 pixeles) que son las 4 esquinas de los dos rectangulos de 8px que formarian al jugador. Se usa para comprobar si el jugador está tocando algun tile de los que matan
|
||||
|
||||
## Comprobar colisiones con el mapa
|
||||
Esto es un poco marciano pero, el jugador genera un rectangulo de proyeccion. Digamos que si se va a mover 3 pixeles hacia la derecha, el rectangulo de proyeccion es el rectangulo que cubre la superficie entre donde está el jugador y donde estará el jugador. Se usa para ver si ese rectangulo (que suele ser de ancho o alto 1, ya que el jugador no llega a moverse mas de un pixel cada vez) colisiona con alguna superficie del mapa. En caso de colision se devuelve el punto de colision y se recoloca al jugador en ese punto. Eso para las superficies rectas.
|
||||
|
||||
## Reglas
|
||||
A continuacion las reglas que se han de cumplir para el jugador en todo momento
|
||||
- Si está STANDING -> vy_ = 0;
|
||||
- Si no tiene suelo debajo y no está JUMPING -> FALLING
|
||||
- Si está JUMPING y tropieza contra el techo -> FALLING
|
||||
- Si está FALLING -> vx_ = 0
|
||||
- Si está STANDING y tropieza lateralmente con una Slope, se pega a la slope
|
||||
- Si esta FALLING y tiene una Slope bajo los pies, se pega a la slope
|
||||
- La unica forma de atravesar una Slope es en estado JUMPING y con vx_ != 0
|
||||
- Si salta, se guarda la posicion inicial en Y, si durante el salto está mas bajo de Y (es decir, el valor de y pasa a ser superior al inicial) -> FALLING
|
||||
|
||||
## Tipos de superficies
|
||||
Hay tres tipos de superficies:
|
||||
- Suelo normal
|
||||
- Suelo tipo conveyor belt
|
||||
- Rampas
|
||||
|
||||
## Reglas explicadas de manera mas abierta
|
||||
Debido a que las reglas anteriores pueden sonar confusas y ser incompletas, se describen aqui con lenguaje mas natural:
|
||||
- El jugador camina sobre las superficies
|
||||
- Si tiene los dos pies sobre el aire -> cae
|
||||
- El jugador sube y baja por las rampas
|
||||
- La unica forma de atravesar las rampas es saltando sobre ellas en movimiento
|
||||
- Un salto recto o una caida (las caidas siempre son rectas) hacen aterrizar al jugador sobre las rampas
|
||||
- Las conveyor belt desplazan al jugador en la direccion de la conveyor belt
|
||||
- El jugador cuando esta siendo desplazado por una conveyor belt, no puede cambiar de direccion
|
||||
- Solo puede saltar y la propia inercia le hace saltar en movimiento
|
||||
- Hay una excepcion en las conveyor belts y es que cuando el jugador cae sobre ellas, puede mantener la direccion que tenia el jugador. En el momento que el jugador deja de estar pulsando una direccion, ya se acopla al movimiento de la conveyor belt y no puede cambiar de direccion
|
||||
- El jugador deja de estar ligado al movimiento de la conveyor belt cuando sus dos pies ya no la tienen debajo, bien porque hay suelo o bien porque hay aire -> cae
|
||||
- El jugador no puede cambiar de direccion en el aire
|
||||
14
README.md
@@ -1,8 +1,8 @@
|
||||
# JailDoctor's Dilemma
|
||||
|
||||
JailDoc és un Jailer. Als Jailers els agrada començar projectes. A ningú li agrada acabar-los. Els Jailers viuen a la Jail. A la Jail s'hi va a començar projectes. A la Jail s'hi va a ensenyar els projectes. A la Jail s'hi va a aprendre com començar nous projectes. A la Jail s'hi va a ajudar els companys a començar nous projectes.
|
||||
<img src="https://php.sustancia.synology.me/images/jdd/jaildoctors_dilemma_cover_web.png" width="300" align="left" style="margin-right: 20px; margin-bottom: 10px;" alt="JailDoctor's Dilemma Cover">
|
||||
|
||||

|
||||
JailDoc és un Jailer. Als Jailers els agrada començar projectes. A ningú li agrada acabar-los. Els Jailers viuen a la Jail. A la Jail s'hi va a començar projectes. A la Jail s'hi va a ensenyar els projectes. A la Jail s'hi va a aprendre com començar nous projectes. A la Jail s'hi va a ajudar els companys a començar nous projectes.
|
||||
|
||||
JailDoc és un Jailer destacat entre els Jailers. Té més projectes començats que ningú i és qui més ajuda als altres a iniciar els seus.
|
||||
|
||||
@@ -10,6 +10,8 @@ Però un dia, va passar una cosa inesperada. Algú va acabar un projecte. Algú
|
||||
|
||||
Això va fer que JailDoc prenguera una decisió: acabaria i lliuraria un dels seus projectes. Però, quin? *JailBattle*? *Sigmasuá*? *Calculín Doom*? Quin dilema! Finalment, es va arromangar i va decidir acabar i lliurar **tots** els seus projectes inacabats. Ho aconseguirà?
|
||||
|
||||
<br clear="left">
|
||||
|
||||
---
|
||||
|
||||
## Jugabilitat
|
||||
@@ -36,9 +38,11 @@ El joc permet tant l'ús del teclat com d'un comandament. Les tecles per a jugar
|
||||
- **Tecla F1**: Disminueix la mida de la finestra.
|
||||
- **Tecla F2**: Augmenta la mida de la finestra.
|
||||
- **Tecla F3**: Alterna entre el mode de pantalla completa i el mode finestra.
|
||||
- **Tecla F4**: Activa o desactiva els shaders
|
||||
- **Tecla F5**: Canvia la paleta de colors del joc.
|
||||
- **Tecla B**: Activa o desactiva el marge de colors en mode finestra.
|
||||
- **Tecla F4**: Activa o desactiva els shaders.
|
||||
- **Tecla F5**: Estableix la següent paleta de colors.
|
||||
- **Tecla F6**: Estableix la paleta de colors prèvia.
|
||||
- **Tecla F7**: Activa o desactiva el escalat exacte.
|
||||
- **Tecla B**: Activa o desactiva el marge de colors.
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
tileSetFile=shine.gif
|
||||
frame_width=8
|
||||
frame_height=8
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=6
|
||||
speed=0.1000
|
||||
loop=-1
|
||||
frames=0,1,2,3,4,5,6,7
|
||||
[/animation]
|
||||
BIN
data/credits/shine.gif
Normal file
|
After Width: | Height: | Size: 107 B |
|
Before Width: | Height: | Size: 148 B |
BIN
data/ending/ending1.gif
Normal file
|
After Width: | Height: | Size: 1014 B |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
BIN
data/ending/ending2.gif
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.3 KiB |
BIN
data/ending/ending3.gif
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
BIN
data/ending/ending4.gif
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
BIN
data/ending/ending5.gif
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=abad.gif
|
||||
frame_width=8
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=8
|
||||
speed=0.1333
|
||||
loop=0
|
||||
frames=0,1,2
|
||||
[/animation]
|
||||
BIN
data/enemies/abad.gif
Normal file
|
After Width: | Height: | Size: 130 B |
|
Before Width: | Height: | Size: 267 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=abad_bell.gif
|
||||
frame_width=16
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=4
|
||||
speed=0.0667
|
||||
loop=0
|
||||
frames=0,1,2,3,4,5,6,7,8,9
|
||||
[/animation]
|
||||
BIN
data/enemies/abad_bell.gif
Normal file
|
After Width: | Height: | Size: 384 B |
|
Before Width: | Height: | Size: 555 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=amstrad_cs.gif
|
||||
frame_width=8
|
||||
frame_height=8
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=4
|
||||
speed=0.0667
|
||||
loop=0
|
||||
frames=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
|
||||
[/animation]
|
||||
|
||||
BIN
data/enemies/amstrad_cs.gif
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=arounders_door.gif
|
||||
frame_width=16
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=8
|
||||
speed=0.1333
|
||||
loop=0
|
||||
frames=0,1,2,3,3,3,3,3,3,3,3,3,3,3,3,2,1,0,0,0
|
||||
[/animation]
|
||||
BIN
data/enemies/arounders_door.gif
Normal file
|
After Width: | Height: | Size: 198 B |
|
Before Width: | Height: | Size: 250 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=arounders_machine.gif
|
||||
frame_width=16
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=4
|
||||
speed=0.0667
|
||||
loop=0
|
||||
frames=0,1,2,3
|
||||
[/animation]
|
||||
BIN
data/enemies/arounders_machine.gif
Normal file
|
After Width: | Height: | Size: 195 B |
|
Before Width: | Height: | Size: 234 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=bat.gif
|
||||
frame_width=9
|
||||
frame_height=7
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=3
|
||||
speed=0.0500
|
||||
loop=0
|
||||
frames=0,1
|
||||
[/animation]
|
||||
BIN
data/enemies/bat.gif
Normal file
|
After Width: | Height: | Size: 86 B |
|
Before Width: | Height: | Size: 134 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=batman.gif
|
||||
frame_width=8
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=8
|
||||
speed=0.1333
|
||||
loop=0
|
||||
frames=0,1,2,3
|
||||
[/animation]
|
||||
BIN
data/enemies/batman.gif
Normal file
|
After Width: | Height: | Size: 146 B |
|
Before Width: | Height: | Size: 241 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=batman_bell.gif
|
||||
frame_width=16
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=6
|
||||
speed=0.1000
|
||||
loop=0
|
||||
frames=0,1,2,3,4,5
|
||||
[/animation]
|
||||
BIN
data/enemies/batman_bell.gif
Normal file
|
After Width: | Height: | Size: 267 B |
|
Before Width: | Height: | Size: 415 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=batman_fire.gif
|
||||
frame_width=16
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=4
|
||||
speed=0.0667
|
||||
loop=0
|
||||
frames=0,1,2,3
|
||||
[/animation]
|
||||
BIN
data/enemies/batman_fire.gif
Normal file
|
After Width: | Height: | Size: 213 B |
|
Before Width: | Height: | Size: 343 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=bell.gif
|
||||
frame_width=16
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=6
|
||||
speed=0.1000
|
||||
loop=0
|
||||
frames=0,1,2,3,4,5,6,7,8,9,10,11
|
||||
[/animation]
|
||||
BIN
data/enemies/bell.gif
Normal file
|
After Width: | Height: | Size: 412 B |
|
Before Width: | Height: | Size: 509 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=bin.gif
|
||||
frame_width=16
|
||||
frame_height=8
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=10
|
||||
speed=0.1667
|
||||
loop=0
|
||||
frames=0,1,2,3,4
|
||||
[/animation]
|
||||
BIN
data/enemies/bin.gif
Normal file
|
After Width: | Height: | Size: 146 B |
|
Before Width: | Height: | Size: 174 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=bird.gif
|
||||
frame_width=16
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=8
|
||||
speed=0.1333
|
||||
loop=0
|
||||
frames=0,1,2,3
|
||||
[/animation]
|
||||
BIN
data/enemies/bird.gif
Normal file
|
After Width: | Height: | Size: 195 B |
|
Before Width: | Height: | Size: 306 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=breakout.gif
|
||||
frame_width=24
|
||||
frame_height=32
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=6
|
||||
speed=0.1000
|
||||
loop=0
|
||||
frames=0,1,2,3,4,5,6,7,6,5,4,3,2,1
|
||||
[/animation]
|
||||
BIN
data/enemies/breakout.gif
Normal file
|
After Width: | Height: | Size: 195 B |
|
Before Width: | Height: | Size: 180 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=bry.gif
|
||||
frame_width=10
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=6
|
||||
speed=0.1000
|
||||
loop=0
|
||||
frames=0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5,4,5
|
||||
[/animation]
|
||||
BIN
data/enemies/bry.gif
Normal file
|
After Width: | Height: | Size: 208 B |
|
Before Width: | Height: | Size: 253 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=chip.gif
|
||||
frame_width=8
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=8
|
||||
speed=0.1333
|
||||
loop=0
|
||||
frames=0,1,2,3
|
||||
[/animation]
|
||||
BIN
data/enemies/chip.gif
Normal file
|
After Width: | Height: | Size: 146 B |
|
Before Width: | Height: | Size: 208 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=code.gif
|
||||
frame_width=16
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=6
|
||||
speed=0.1000
|
||||
loop=0
|
||||
frames=0,1,2,3
|
||||
[/animation]
|
||||
BIN
data/enemies/code.gif
Normal file
|
After Width: | Height: | Size: 198 B |
|
Before Width: | Height: | Size: 319 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=congo.gif
|
||||
frame_width=8
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=6
|
||||
speed=0.1000
|
||||
loop=0
|
||||
frames=0,1,2,3
|
||||
[/animation]
|
||||
BIN
data/enemies/congo.gif
Normal file
|
After Width: | Height: | Size: 145 B |
|
Before Width: | Height: | Size: 231 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=crosshair.gif
|
||||
frame_width=16
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=6
|
||||
speed=0.1000
|
||||
loop=0
|
||||
frames=0,1,2,3
|
||||
[/animation]
|
||||
BIN
data/enemies/crosshair.gif
Normal file
|
After Width: | Height: | Size: 213 B |
|
Before Width: | Height: | Size: 288 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=demon.gif
|
||||
frame_width=16
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=8
|
||||
speed=0.1333
|
||||
loop=0
|
||||
frames=0,1,2,3
|
||||
[/animation]
|
||||
BIN
data/enemies/demon.gif
Normal file
|
After Width: | Height: | Size: 213 B |
|
Before Width: | Height: | Size: 329 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=dimallas.gif
|
||||
frame_width=16
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=8
|
||||
speed=0.1333
|
||||
loop=0
|
||||
frames=0,1,2,3
|
||||
[/animation]
|
||||
BIN
data/enemies/dimallas.gif
Normal file
|
After Width: | Height: | Size: 212 B |
|
Before Width: | Height: | Size: 298 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=dong.gif
|
||||
frame_width=22
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=6
|
||||
speed=0.1000
|
||||
loop=0
|
||||
frames=0,1,2,3,4,5
|
||||
[/animation]
|
||||
BIN
data/enemies/dong.gif
Normal file
|
After Width: | Height: | Size: 355 B |
|
Before Width: | Height: | Size: 630 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=elsa.gif
|
||||
frame_width=16
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=6
|
||||
speed=0.1000
|
||||
loop=0
|
||||
frames=0,1,2,3,4,5
|
||||
[/animation]
|
||||
BIN
data/enemies/elsa.gif
Normal file
|
After Width: | Height: | Size: 236 B |
|
Before Width: | Height: | Size: 310 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=floppy.gif
|
||||
frame_width=16
|
||||
frame_height=16
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=8
|
||||
speed=0.1333
|
||||
loop=0
|
||||
frames=0,1,2,3
|
||||
[/animation]
|
||||
BIN
data/enemies/floppy.gif
Normal file
|
After Width: | Height: | Size: 210 B |
|
Before Width: | Height: | Size: 271 B |
@@ -1,9 +1,10 @@
|
||||
tileSetFile=flying_arounder.gif
|
||||
frame_width=7
|
||||
frame_height=7
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=10
|
||||
speed=0.1667
|
||||
loop=0
|
||||
frames=0
|
||||
[/animation]
|
||||
BIN
data/enemies/flying_arounder.gif
Normal file
|
After Width: | Height: | Size: 73 B |
|
Before Width: | Height: | Size: 122 B |