arreglos varios pa que JailDoc puga tastar com va açò

This commit is contained in:
2026-04-16 17:53:07 +02:00
parent 4da00d81c2
commit 6ea50cf35e
17 changed files with 322 additions and 104 deletions

99
.gitignore vendored
View File

@@ -1,27 +1,104 @@
.cache/ # ─── OS: macOS ─────────────────────────────────────────────
*data/config/config.yaml
*.DS_Store *.DS_Store
.AppleDouble
.LSOverride
._*
.Spotlight-V100
.Trashes
.fseventsd
.DocumentRevisions-V100
.TemporaryItems
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# ─── OS: Windows ───────────────────────────────────────────
thumbs.db thumbs.db
Thumbs.db Thumbs.db
ehthumbs.db
ehthumbs_vista.db
desktop.ini desktop.ini
$RECYCLE.BIN/
*.lnk
# ─── OS: Linux ─────────────────────────────────────────────
*~
.directory
.Trash-*
.nfs*
# ─── Editores / IDEs ───────────────────────────────────────
# Vim
*.swp
*.swo
*.swn
# Emacs
\#*\#
.\#*
# JetBrains
.idea/
*.iml
# Sublime
*.sublime-workspace
*.sublime-project
# VSCode — settings.json del proyecto sí se versiona
.vscode/*
!.vscode/settings.json
# ─── Claude Code ───────────────────────────────────────────
.claude/settings.local.json
.cache/
# ─── Build / CMake ─────────────────────────────────────────
build/
cmake-build-*/
CMakeCache.txt
CMakeFiles/
CMakeScripts/
cmake_install.cmake
compile_commands.json
*.o
*.obj
*.a
*.lib
*.so
*.so.*
*.dylib
*.dll
*.d
# ─── Ejecutables del juego ─────────────────────────────────
*.exe *.exe
*_macos *_macos
*_linux *_linux
*.dmg
*.tar.gz
*.zip
*.app *.app
*_debug* *_debug*
projecte_2026* projecte_2026*
build/ _projecte_2026
source/version.h
resources.pack # ─── Tools generados ───────────────────────────────────────
tools/pack_resources/pack_resources tools/pack_resources/pack_resources
tools/pack_resources/pack_resources.exe tools/pack_resources/pack_resources.exe
tools/pack_resources/pack_tool tools/pack_resources/pack_tool
tools/pack_resources/pack_tool.exe tools/pack_resources/pack_tool.exe
resources.pack
# ─── Config de usuario (runtime) ───────────────────────────
*data/config/config.yaml
source/version.h
*.res *.res
# ─── Distribución ──────────────────────────────────────────
*.dmg
*.tar.gz
*.zip
dist/ dist/
.claude/settings.local.json
_projecte_2026 # ─── Logs / temporales ─────────────────────────────────────
screenshots/ *.log
*.tmp
*.bak
*.orig
*.rej
# ─── Capturas ──────────────────────────────────────────────
screenshots/

View File

@@ -210,10 +210,8 @@ assets:
player: player:
BITMAP: BITMAP:
- ${PREFIX}/data/player/player.gif - ${PREFIX}/data/player/player.gif
- ${PREFIX}/data/player/player_game_over.gif
ANIMATION: ANIMATION:
- ${PREFIX}/data/player/player.yaml - ${PREFIX}/data/player/player.yaml
- ${PREFIX}/data/player/player_game_over.yaml
# ITEMS # ITEMS
items: items:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 281 B

After

Width:  |  Height:  |  Size: 660 B

View File

@@ -5,4 +5,6 @@ frameHeight: 16
animations: animations:
- name: default - name: default
frames: [0] speed: [2.0, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03, 0.03]
loopFrom: 0
frames: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

View File

@@ -56,11 +56,6 @@ tilemap:
- [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 3, 0, 0, 0, 0, 0, 0] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 3, 0, 0, 0, 0, 0, 0]
- [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 3, 0, 0, 0, 0, 0] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 3, 0, 0, 0, 0, 0]
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
# Llaves en esta habitación
keys:
- animation: key1.yaml
id: "1"
position: {x: 23, y: 11}
# Puertas en esta habitación # Puertas en esta habitación
doors: doors:

View File

@@ -27,11 +27,11 @@ tilemap:
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, 266, 266, 266, 266, 266, 266, 266, 266, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 169, 169] - [-1, -1, -1, -1, -1, -1, -1, -1, -1, 266, 266, 266, 266, 266, 266, 266, 266, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 169, 169]
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 169, 169] - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 169, 169]
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 169, 169] - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 169, 169]
- [160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 169, 169] - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 169, 169]
- [191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 175, 175, 175, 175, 175, 175, 175, 191, 191, 169, 169] - [-1, -1, -1, -1, -1, -1, 268, 268, 268, 268, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 175, 175, 175, 175, 175, 175, 175, -1, -1, 169, 169]
- [165, 167, 184, 165, 166, 165, 175, 175, 175, 175, 184, 184, 166, 166, 184, 165, 167, 184, 165, 165, 184, 184, 170, 170, 170, 170, 170, 165, 184, 165, 169, 169] - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 170, 170, 170, 170, 170, -1, -1, -1, 169, 169]
- [211, 210, 180, 180, 180, 211, 170, 170, 170, 170, 210, 210, 180, 210, 210, 210, 180, 180, 211, 210, 211, 210, 170, 134, 170, 134, 170, 211, 210, 180, 169, 169] - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 170, 134, 170, 134, 170, -1, -1, -1, 169, 169]
- [187, 187, 187, 187, 332, 187, 170, 170, 170, 170, 187, 187, 187, 332, 332, 187, 187, 187, 187, 332, 187, 187, 170, 170, 170, 170, 170, 187, 187, 332, 169, 169] - [-1, -1, -1, -1, 308, -1, -1, -1, -1, -1, -1, -1, -1, 308, 308, -1, -1, -1, -1, 308, -1, -1, 170, 170, 170, 170, 170, -1, -1, 308, 169, 169]
- [169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169] - [169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169]
# Mapa de colisiones (0 = vacio, 1 = solido) # Mapa de colisiones (0 = vacio, 1 = solido)
collision: collision:
@@ -51,8 +51,8 @@ tilemap:
- [-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] - [-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
- [-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] - [-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
- [-1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] - [-1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
- [0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 1] - [0, 0, 0, 0, 0, 0, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 1, 1]
- [0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] - [0, 0, 0, 0, 0, 0, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
- [0, 0, 0, 0, 0, 0, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] - [0, 0, 0, 0, 0, 0, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

View File

@@ -56,3 +56,9 @@ tilemap:
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1] - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1] - [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1, 1]
# Llaves en esta habitación
keys:
- animation: key1.yaml
id: "1"
position: {x: 22, y: 3}

View File

@@ -37,22 +37,22 @@ tilemap:
collision: collision:
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] - [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] - [1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
- [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1] - [1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
- [0, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - [1, 0, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 1] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 1]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 1, 1] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 1, 1]
- [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 1, 1, 1] - [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 1, 1, 1]
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
- [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

View File

@@ -7,7 +7,7 @@ zones:
- name: neighborhood - name: neighborhood
tileSetFile: neighborhood.gif tileSetFile: neighborhood.gif
music: 574070_KUVO_Farewell_to_school.ogg music: 574070_KUVO_Farewell_to_school.ogg
bgColor: 7 bgColor: 0
- name: cave - name: cave
tileSetFile: cave.gif tileSetFile: cave.gif

View File

@@ -8,7 +8,7 @@
#include <string.h> // Para strcpy, strlen #include <string.h> // Para strcpy, strlen
#define STB_VORBIS_HEADER_ONLY #define STB_VORBIS_HEADER_ONLY
#include "external/stb_vorbis.h" // Para stb_vorbis_decode_memory #include "external/stb_vorbis.h" // Para stb_vorbis_open_memory i streaming
// --- Public Enums --- // --- Public Enums ---
enum JA_Channel_state { JA_CHANNEL_INVALID, enum JA_Channel_state { JA_CHANNEL_INVALID,
@@ -43,12 +43,16 @@ struct JA_Channel_t {
struct JA_Music_t { struct JA_Music_t {
SDL_AudioSpec spec{SDL_AUDIO_S16, 2, 48000}; SDL_AudioSpec spec{SDL_AUDIO_S16, 2, 48000};
Uint32 length{0};
Uint8* buffer{nullptr}; // OGG comprimit en memòria. Propietat nostra; es copia des del fitxer una
// sola vegada en JA_LoadMusic i es descomprimix en chunks per streaming.
Uint8* ogg_data{nullptr};
Uint32 ogg_length{0};
stb_vorbis* vorbis{nullptr}; // Handle del decoder, viu tot el cicle del JA_Music_t
char* filename{nullptr}; char* filename{nullptr};
int pos{0}; int times{0}; // Loops restants (-1 = infinit, 0 = un sol play)
int times{0};
SDL_AudioStream* stream{nullptr}; SDL_AudioStream* stream{nullptr};
JA_Music_state state{JA_MUSIC_INVALID}; JA_Music_state state{JA_MUSIC_INVALID};
}; };
@@ -88,6 +92,73 @@ inline void JA_StopChannel(const int channel);
inline int JA_PlaySoundOnChannel(JA_Sound_t* sound, const int channel, const int loop = 0, const int group = 0); inline int JA_PlaySoundOnChannel(JA_Sound_t* sound, const int channel, const int loop = 0, const int group = 0);
inline void JA_CrossfadeMusic(JA_Music_t* music, int crossfade_ms, int loop = -1); inline void JA_CrossfadeMusic(JA_Music_t* music, int crossfade_ms, int loop = -1);
// --- Music streaming internals ---
// Bytes-per-sample per canal (sempre s16)
static constexpr int JA_MUSIC_BYTES_PER_SAMPLE = 2;
// Quants shorts decodifiquem per crida a get_samples_short_interleaved.
// 8192 shorts = 4096 samples/channel en estèreo ≈ 85ms de so a 48kHz.
static constexpr int JA_MUSIC_CHUNK_SHORTS = 8192;
// Umbral d'audio per davant del cursor de reproducció. Mantenim ≥ 0.5 s a
// l'SDL_AudioStream per absorbir jitter de frame i evitar underruns.
static constexpr float JA_MUSIC_LOW_WATER_SECONDS = 0.5f;
// Decodifica un chunk del vorbis i el volca a l'stream. Retorna samples
// decodificats per canal (0 = EOF de l'stream vorbis).
inline int JA_FeedMusicChunk(JA_Music_t* music) {
if (!music || !music->vorbis || !music->stream) return 0;
short chunk[JA_MUSIC_CHUNK_SHORTS];
const int channels = music->spec.channels;
const int samples_per_channel = stb_vorbis_get_samples_short_interleaved(
music->vorbis,
channels,
chunk,
JA_MUSIC_CHUNK_SHORTS);
if (samples_per_channel <= 0) return 0;
const int bytes = samples_per_channel * channels * JA_MUSIC_BYTES_PER_SAMPLE;
SDL_PutAudioStreamData(music->stream, chunk, bytes);
return samples_per_channel;
}
// Reompli l'stream fins que tinga ≥ JA_MUSIC_LOW_WATER_SECONDS bufferats.
// En arribar a EOF del vorbis, aplica el loop (times) o deixa drenar.
inline void JA_PumpMusic(JA_Music_t* music) {
if (!music || !music->vorbis || !music->stream) return;
const int bytes_per_second = music->spec.freq * music->spec.channels * JA_MUSIC_BYTES_PER_SAMPLE;
const int low_water_bytes = static_cast<int>(JA_MUSIC_LOW_WATER_SECONDS * static_cast<float>(bytes_per_second));
while (SDL_GetAudioStreamAvailable(music->stream) < low_water_bytes) {
const int decoded = JA_FeedMusicChunk(music);
if (decoded > 0) continue;
// EOF: si queden loops, rebobinar; si no, tallar i deixar drenar.
if (music->times != 0) {
stb_vorbis_seek_start(music->vorbis);
if (music->times > 0) music->times--;
} else {
break;
}
}
}
// Pre-carrega `duration_ms` de so dins l'stream actual abans que l'stream
// siga robat per outgoing_music (crossfade o fade-out). Imprescindible amb
// streaming: l'stream robat no es pot re-alimentar perquè perd la referència
// al seu vorbis decoder. No aplica loop — si el vorbis s'esgota abans, parem.
inline void JA_PreFillOutgoing(JA_Music_t* music, int duration_ms) {
if (!music || !music->vorbis || !music->stream) return;
const int bytes_per_second = music->spec.freq * music->spec.channels * JA_MUSIC_BYTES_PER_SAMPLE;
const int needed_bytes = static_cast<int>((static_cast<int64_t>(duration_ms) * bytes_per_second) / 1000);
while (SDL_GetAudioStreamAvailable(music->stream) < needed_bytes) {
const int decoded = JA_FeedMusicChunk(music);
if (decoded <= 0) break; // EOF: deixem drenar el que hi haja
}
}
// --- Core Functions --- // --- Core Functions ---
inline void JA_Update() { inline void JA_Update() {
@@ -120,14 +191,11 @@ inline void JA_Update() {
} }
} }
// Buffering de musica en loop // Streaming: rellenem l'stream fins al low-water-mark i parem si el
if (current_music->times != 0) { // vorbis s'ha esgotat i no queden loops.
if ((Uint32)SDL_GetAudioStreamAvailable(current_music->stream) < (current_music->length / 2)) { JA_PumpMusic(current_music);
SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length); if (current_music->times == 0 && SDL_GetAudioStreamAvailable(current_music->stream) == 0) {
} JA_StopMusic();
if (current_music->times > 0) current_music->times--;
} else {
if (SDL_GetAudioStreamAvailable(current_music->stream) == 0) JA_StopMusic();
} }
} }
@@ -172,19 +240,31 @@ inline void JA_Quit() {
// --- Music Functions --- // --- Music Functions ---
inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) { inline JA_Music_t* JA_LoadMusic(const Uint8* buffer, Uint32 length) {
JA_Music_t* music = new JA_Music_t(); if (!buffer || length == 0) return nullptr;
int chan, samplerate; // Còpia del OGG comprimit: stb_vorbis llig de forma persistent aquesta
short* output; // memòria mentre el handle estiga viu, així que hem de posseir-la nosaltres.
music->length = stb_vorbis_decode_memory(buffer, length, &chan, &samplerate, &output) * chan * 2; Uint8* ogg_copy = static_cast<Uint8*>(SDL_malloc(length));
if (!ogg_copy) return nullptr;
SDL_memcpy(ogg_copy, buffer, length);
music->spec.channels = chan; int error = 0;
music->spec.freq = samplerate; stb_vorbis* vorbis = stb_vorbis_open_memory(ogg_copy, static_cast<int>(length), &error, nullptr);
if (!vorbis) {
SDL_free(ogg_copy);
SDL_Log("JA_LoadMusic: stb_vorbis_open_memory failed (error %d)", error);
return nullptr;
}
auto* music = new JA_Music_t();
music->ogg_data = ogg_copy;
music->ogg_length = length;
music->vorbis = vorbis;
const stb_vorbis_info info = stb_vorbis_get_info(vorbis);
music->spec.channels = info.channels;
music->spec.freq = static_cast<int>(info.sample_rate);
music->spec.format = SDL_AUDIO_S16; music->spec.format = SDL_AUDIO_S16;
music->buffer = static_cast<Uint8*>(SDL_malloc(music->length));
SDL_memcpy(music->buffer, output, music->length);
free(output);
music->pos = 0;
music->state = JA_MUSIC_STOPPED; music->state = JA_MUSIC_STOPPED;
return music; return music;
@@ -223,23 +303,29 @@ inline JA_Music_t* JA_LoadMusic(const char* filename) {
} }
inline void JA_PlayMusic(JA_Music_t* music, const int loop = -1) { inline void JA_PlayMusic(JA_Music_t* music, const int loop = -1) {
if (!JA_musicEnabled || !music) return; // Añadida comprobación de music if (!JA_musicEnabled || !music || !music->vorbis) return;
JA_StopMusic(); JA_StopMusic();
current_music = music; current_music = music;
current_music->pos = 0;
current_music->state = JA_MUSIC_PLAYING; current_music->state = JA_MUSIC_PLAYING;
current_music->times = loop; current_music->times = loop;
// Rebobinem l'stream de vorbis al principi. Cobreix tant play-per-primera-
// vegada com replays/canvis de track que tornen a la mateixa pista.
stb_vorbis_seek_start(current_music->vorbis);
current_music->stream = SDL_CreateAudioStream(&current_music->spec, &JA_audioSpec); current_music->stream = SDL_CreateAudioStream(&current_music->spec, &JA_audioSpec);
if (!current_music->stream) { // Comprobar creación de stream if (!current_music->stream) {
SDL_Log("Failed to create audio stream!"); SDL_Log("Failed to create audio stream!");
current_music->state = JA_MUSIC_STOPPED; current_music->state = JA_MUSIC_STOPPED;
return; return;
} }
if (!SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length)) printf("[ERROR] SDL_PutAudioStreamData failed!\n");
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume); SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume);
// Pre-cargem el buffer abans de bindejar per evitar un underrun inicial.
JA_PumpMusic(current_music);
if (!SDL_BindAudioStream(sdlAudioDevice, current_music->stream)) printf("[ERROR] SDL_BindAudioStream failed!\n"); if (!SDL_BindAudioStream(sdlAudioDevice, current_music->stream)) printf("[ERROR] SDL_BindAudioStream failed!\n");
} }
@@ -276,12 +362,16 @@ inline void JA_StopMusic() {
if (!current_music || current_music->state == JA_MUSIC_INVALID || current_music->state == JA_MUSIC_STOPPED) return; if (!current_music || current_music->state == JA_MUSIC_INVALID || current_music->state == JA_MUSIC_STOPPED) return;
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED; current_music->state = JA_MUSIC_STOPPED;
if (current_music->stream) { if (current_music->stream) {
SDL_DestroyAudioStream(current_music->stream); SDL_DestroyAudioStream(current_music->stream);
current_music->stream = nullptr; current_music->stream = nullptr;
} }
// Deixem el handle de vorbis viu — es tanca en JA_DeleteMusic.
// Rebobinem perquè un futur JA_PlayMusic comence des del principi.
if (current_music->vorbis) {
stb_vorbis_seek_start(current_music->vorbis);
}
} }
inline void JA_FadeOutMusic(const int milliseconds) { inline void JA_FadeOutMusic(const int milliseconds) {
@@ -294,19 +384,23 @@ inline void JA_FadeOutMusic(const int milliseconds) {
outgoing_music.stream = nullptr; outgoing_music.stream = nullptr;
} }
// Pre-omplim l'stream amb `milliseconds` de so: un cop robat, ja no
// tindrà accés al vorbis decoder i només podrà drenar el que tinga.
JA_PreFillOutgoing(current_music, milliseconds);
// Robar el stream del current_music al outgoing // Robar el stream del current_music al outgoing
outgoing_music.stream = current_music->stream; outgoing_music.stream = current_music->stream;
outgoing_music.fade = {true, SDL_GetTicks(), milliseconds, JA_musicVolume}; outgoing_music.fade = {true, SDL_GetTicks(), milliseconds, JA_musicVolume};
// Dejar current_music sin stream (ya lo tiene outgoing) // Dejar current_music sin stream (ya lo tiene outgoing)
current_music->stream = nullptr; current_music->stream = nullptr;
current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED; current_music->state = JA_MUSIC_STOPPED;
if (current_music->vorbis) stb_vorbis_seek_start(current_music->vorbis);
incoming_fade.active = false; incoming_fade.active = false;
} }
inline void JA_CrossfadeMusic(JA_Music_t* music, const int crossfade_ms, const int loop) { inline void JA_CrossfadeMusic(JA_Music_t* music, const int crossfade_ms, const int loop) {
if (!JA_musicEnabled || !music) return; if (!JA_musicEnabled || !music || !music->vorbis) return;
// Destruir outgoing anterior si existe (crossfade durante crossfade) // Destruir outgoing anterior si existe (crossfade durante crossfade)
if (outgoing_music.stream) { if (outgoing_music.stream) {
@@ -315,28 +409,32 @@ inline void JA_CrossfadeMusic(JA_Music_t* music, const int crossfade_ms, const i
outgoing_music.fade.active = false; outgoing_music.fade.active = false;
} }
// Robar el stream de la musica actual al outgoing para el fade-out // Robar el stream de la musica actual al outgoing para el fade-out.
// Pre-omplim amb `crossfade_ms` de so perquè no es quede en silenci
// abans d'acabar el fade (l'stream robat ja no pot alimentar-se).
if (current_music && current_music->state == JA_MUSIC_PLAYING && current_music->stream) { if (current_music && current_music->state == JA_MUSIC_PLAYING && current_music->stream) {
JA_PreFillOutgoing(current_music, crossfade_ms);
outgoing_music.stream = current_music->stream; outgoing_music.stream = current_music->stream;
outgoing_music.fade = {true, SDL_GetTicks(), crossfade_ms, JA_musicVolume}; outgoing_music.fade = {true, SDL_GetTicks(), crossfade_ms, JA_musicVolume};
current_music->stream = nullptr; current_music->stream = nullptr;
current_music->state = JA_MUSIC_STOPPED; current_music->state = JA_MUSIC_STOPPED;
if (current_music->vorbis) stb_vorbis_seek_start(current_music->vorbis);
} }
// Iniciar la nueva pista con gain=0 (el fade-in la sube gradualmente) // Iniciar la nueva pista con gain=0 (el fade-in la sube gradualmente)
current_music = music; current_music = music;
current_music->pos = 0;
current_music->state = JA_MUSIC_PLAYING; current_music->state = JA_MUSIC_PLAYING;
current_music->times = loop; current_music->times = loop;
stb_vorbis_seek_start(current_music->vorbis);
current_music->stream = SDL_CreateAudioStream(&current_music->spec, &JA_audioSpec); current_music->stream = SDL_CreateAudioStream(&current_music->spec, &JA_audioSpec);
if (!current_music->stream) { if (!current_music->stream) {
SDL_Log("Failed to create audio stream for crossfade!"); SDL_Log("Failed to create audio stream for crossfade!");
current_music->state = JA_MUSIC_STOPPED; current_music->state = JA_MUSIC_STOPPED;
return; return;
} }
SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length);
SDL_SetAudioStreamGain(current_music->stream, 0.0f); SDL_SetAudioStreamGain(current_music->stream, 0.0f);
JA_PumpMusic(current_music); // pre-carrega abans de bindejar
SDL_BindAudioStream(sdlAudioDevice, current_music->stream); SDL_BindAudioStream(sdlAudioDevice, current_music->stream);
// Configurar fade-in // Configurar fade-in
@@ -356,8 +454,9 @@ inline void JA_DeleteMusic(JA_Music_t* music) {
JA_StopMusic(); JA_StopMusic();
current_music = nullptr; current_music = nullptr;
} }
SDL_free(music->buffer);
if (music->stream) SDL_DestroyAudioStream(music->stream); if (music->stream) SDL_DestroyAudioStream(music->stream);
if (music->vorbis) stb_vorbis_close(music->vorbis);
SDL_free(music->ogg_data);
free(music->filename); // filename se libera aquí free(music->filename); // filename se libera aquí
delete music; delete music;
} }
@@ -370,17 +469,14 @@ inline float JA_SetMusicVolume(float volume) {
return JA_musicVolume; return JA_musicVolume;
} }
inline void JA_SetMusicPosition(float value) { inline void JA_SetMusicPosition(float /*value*/) {
if (!current_music) return; // No implementat amb el backend de streaming. Mai va arribar a usar-se
current_music->pos = value * current_music->spec.freq; // en el codi existent, així que es manté com a stub.
// Nota: Esta implementación de 'pos' no parece usarse en JA_Update para
// el streaming. El streaming siempre parece empezar desde el principio.
} }
inline float JA_GetMusicPosition() { inline float JA_GetMusicPosition() {
if (!current_music) return 0; // Veure nota a JA_SetMusicPosition.
return float(current_music->pos) / float(current_music->spec.freq); return 0.0f;
// Nota: Ver `JA_SetMusicPosition`
} }
inline void JA_EnableMusic(const bool value) { inline void JA_EnableMusic(const bool value) {
@@ -568,4 +664,4 @@ inline float JA_SetVolume(float volume) {
float v = JA_SetMusicVolume(volume); float v = JA_SetMusicVolume(volume);
JA_SetSoundVolume(v, -1); // Aplicar a todos los grupos de sonido JA_SetSoundVolume(v, -1); // Aplicar a todos los grupos de sonido
return v; return v;
} }

View File

@@ -492,6 +492,7 @@ namespace Resource {
// Muestra el progreso de carga // Muestra el progreso de carga
void Cache::renderProgress() { void Cache::renderProgress() {
if (!Options::loading.show_progress) { return; }
constexpr float X_PADDING = 60.0F; constexpr float X_PADDING = 60.0F;
constexpr float Y_PADDING = 10.0F; constexpr float Y_PADDING = 10.0F;
constexpr float BAR_HEIGHT = 5.0F; constexpr float BAR_HEIGHT = 5.0F;

View File

@@ -115,14 +115,14 @@ static auto sceneToString(SceneManager::Scene scene) -> std::string {
// Carga la configuración de debug desde debug.yaml // Carga la configuración de debug desde debug.yaml
void Debug::loadFromFile() { void Debug::loadFromFile() {
// Inicializar con valores de release por defecto // Inicializar con valores por defecto de debug
spawn_settings_.room = Defaults::Game::Room::INITIAL; spawn_settings_.room = "902.yaml";
spawn_settings_.spawn_x = Defaults::Game::Player::SPAWN_X; spawn_settings_.spawn_x = 24 * Tile::SIZE;
spawn_settings_.spawn_y = Defaults::Game::Player::SPAWN_Y; spawn_settings_.spawn_y = 13 * Tile::SIZE;
spawn_settings_.flip = Defaults::Game::Player::SPAWN_FLIP; spawn_settings_.flip = Flip::LEFT;
initial_scene_ = SceneManager::Scene::GAME; initial_scene_ = SceneManager::Scene::GAME;
lazy_loading_ = false; lazy_loading_ = false;
render_info_enabled_ = false; render_info_enabled_ = true;
std::ifstream file(debug_file_path_); std::ifstream file(debug_file_path_);
if (!file.good()) { if (!file.good()) {
@@ -166,14 +166,14 @@ void Debug::loadFromFile() {
render_info_enabled_ = yaml["render_info"].get_value<bool>(); render_info_enabled_ = yaml["render_info"].get_value<bool>();
} }
} catch (...) { } catch (...) {
// YAML inválido: resetear a defaults y sobreescribir // YAML inválido: resetear a defaults de debug y sobreescribir
spawn_settings_.room = Defaults::Game::Room::INITIAL; spawn_settings_.room = "902.yaml";
spawn_settings_.spawn_x = Defaults::Game::Player::SPAWN_X; spawn_settings_.spawn_x = 24 * Tile::SIZE;
spawn_settings_.spawn_y = Defaults::Game::Player::SPAWN_Y; spawn_settings_.spawn_y = 13 * Tile::SIZE;
spawn_settings_.flip = Defaults::Game::Player::SPAWN_FLIP; spawn_settings_.flip = Flip::LEFT;
initial_scene_ = SceneManager::Scene::GAME; initial_scene_ = SceneManager::Scene::GAME;
lazy_loading_ = false; lazy_loading_ = false;
render_info_enabled_ = false; render_info_enabled_ = true;
saveToFile(); saveToFile();
return; return;
} }

View File

@@ -18,7 +18,7 @@ namespace Defaults::Canvas {
} // namespace Defaults::Canvas } // namespace Defaults::Canvas
namespace Defaults::Window { namespace Defaults::Window {
constexpr int ZOOM = 2; // Zoom de la ventana por defecto constexpr int ZOOM = 3; // Zoom de la ventana por defecto
} // namespace Defaults::Window } // namespace Defaults::Window
namespace Defaults::Video { namespace Defaults::Video {
@@ -114,6 +114,10 @@ namespace Defaults::Console {
constexpr Uint8 COMMAND_COLOR = 9; // Color del texto que escribe el usuario constexpr Uint8 COMMAND_COLOR = 9; // Color del texto que escribe el usuario
} // namespace Defaults::Console } // namespace Defaults::Console
namespace Defaults::Loading {
constexpr bool SHOW_PROGRESS = false; // Por defecto no mostrar la barra de carga de recursos
} // namespace Defaults::Loading
namespace Defaults::Localization { namespace Defaults::Localization {
constexpr const char* LANGUAGE = "ca"; // Idioma por defecto (en = inglés, ca = catalán) constexpr const char* LANGUAGE = "ca"; // Idioma por defecto (en = inglés, ca = catalán)
} // namespace Defaults::Localization } // namespace Defaults::Localization

View File

@@ -1,12 +1,15 @@
#include "game/entities/key.hpp" #include "game/entities/key.hpp"
#include <cmath> // Para std::sin
#include "core/rendering/sprite/animated_sprite.hpp" // Para AnimatedSprite #include "core/rendering/sprite/animated_sprite.hpp" // Para AnimatedSprite
#include "core/resources/resource_cache.hpp" // Para Resource #include "core/resources/resource_cache.hpp" // Para Resource
// Constructor: carga la animación, posiciona el sprite y crea el collider // Constructor: carga la animación, posiciona el sprite y crea el collider
Key::Key(const Data& data) Key::Key(const Data& data)
: sprite_(std::make_shared<AnimatedSprite>(Resource::Cache::get()->getAnimationData(data.animation_path))), : sprite_(std::make_shared<AnimatedSprite>(Resource::Cache::get()->getAnimationData(data.animation_path))),
id_(data.id) { id_(data.id),
base_y_(data.y) {
sprite_->setPosX(data.x); sprite_->setPosX(data.x);
sprite_->setPosY(data.y); sprite_->setPosY(data.y);
sprite_->setCurrentAnimation("default"); sprite_->setCurrentAnimation("default");
@@ -18,17 +21,22 @@ void Key::render() {
sprite_->render(); sprite_->render();
} }
// Avanza la animación de la llave // Avanza la animación de la llave y aplica el movimiento flotante sinusoidal
void Key::update(float delta_time) { void Key::update(float delta_time) {
if (is_paused_) { if (is_paused_) {
return; return;
} }
sprite_->animate(delta_time); sprite_->animate(delta_time);
// Oscilacion sinusoidal sincronizada (mismo tiempo global para todas las llaves)
const float t = static_cast<float>(SDL_GetTicks()) / 1000.0F;
const float offset = std::sin(t * 2.0F * SDL_PI_F / FLOAT_PERIOD_S) * FLOAT_AMPLITUDE;
sprite_->setPosY(base_y_ + offset);
} }
// Posición actual (para registrar pickup en KeyTracker) // Posición base (el collider y el tracker usan la posición sin oscilación)
auto Key::getPos() const -> SDL_FPoint { auto Key::getPos() const -> SDL_FPoint {
return SDL_FPoint{.x = sprite_->getX(), .y = sprite_->getY()}; return SDL_FPoint{.x = sprite_->getX(), .y = base_y_};
} }
#ifdef _DEBUG #ifdef _DEBUG
@@ -36,6 +44,7 @@ auto Key::getPos() const -> SDL_FPoint {
void Key::setPosition(float x, float y) { void Key::setPosition(float x, float y) {
sprite_->setPosX(x); sprite_->setPosX(x);
sprite_->setPosY(y); sprite_->setPosY(y);
base_y_ = y;
collider_ = sprite_->getRect(); collider_ = sprite_->getRect();
} }
#endif #endif

View File

@@ -24,6 +24,9 @@ class Key {
float y{0.0F}; // Posición Y en píxeles float y{0.0F}; // Posición Y en píxeles
}; };
static constexpr float FLOAT_PERIOD_S = 2.0F; // Segundos por ciclo sinusoidal (todas las llaves sincronizadas)
static constexpr float FLOAT_AMPLITUDE = 2.0F; // Amplitud en píxeles
explicit Key(const Data& data); explicit Key(const Data& data);
~Key() = default; ~Key() = default;
@@ -44,5 +47,6 @@ class Key {
std::shared_ptr<AnimatedSprite> sprite_; // Sprite animado de la llave std::shared_ptr<AnimatedSprite> sprite_; // Sprite animado de la llave
SDL_FRect collider_{}; // Rectángulo de colisión SDL_FRect collider_{}; // Rectángulo de colisión
std::string id_; // Identificador std::string id_; // Identificador
float base_y_{0.0F}; // Posición Y base (el sprite oscila alrededor)
bool is_paused_{false}; // Indica si la llave está pausada bool is_paused_{false}; // Indica si la llave está pausada
}; };

View File

@@ -631,6 +631,19 @@ namespace Options {
} }
} }
// Carga configuración de la pantalla de carga de recursos desde YAML
void loadLoadingConfigFromYaml(const fkyaml::node& yaml) {
if (!yaml.contains("loading")) { return; }
const auto& l = yaml["loading"];
if (l.contains("show_progress")) {
try {
loading.show_progress = l["show_progress"].get_value<bool>();
} catch (...) { /* @INTENTIONAL: campo yaml ausente o malformado → dejar default */
}
}
}
// Carga configuración de idioma desde YAML // Carga configuración de idioma desde YAML
void loadLocalizationFromYaml(const fkyaml::node& yaml) { void loadLocalizationFromYaml(const fkyaml::node& yaml) {
if (yaml.contains("localization")) { if (yaml.contains("localization")) {
@@ -696,6 +709,7 @@ namespace Options {
loadKioskConfigFromYaml(yaml); loadKioskConfigFromYaml(yaml);
loadLocalizationFromYaml(yaml); loadLocalizationFromYaml(yaml);
loadConsoleConfigFromYaml(yaml); loadConsoleConfigFromYaml(yaml);
loadLoadingConfigFromYaml(yaml);
std::cout << "Config file loaded successfully\n\n"; std::cout << "Config file loaded successfully\n\n";
@@ -832,6 +846,12 @@ namespace Options {
file << " text: \"" << kiosk.text << "\"\n"; file << " text: \"" << kiosk.text << "\"\n";
file << " infinite_lives: " << (kiosk.infinite_lives ? "true" : "false") << "\n"; file << " infinite_lives: " << (kiosk.infinite_lives ? "true" : "false") << "\n";
// LOADING
file << "\n";
file << "# LOADING (pantalla de carga de recursos)\n";
file << "loading:\n";
file << " show_progress: " << (loading.show_progress ? "true" : "false") << " # mostrar barra de progreso al cargar recursos\n";
// LOCALIZATION // LOCALIZATION
file << "\n"; file << "\n";
file << "# LOCALIZATION (en = English, ca = Catalan)\n"; file << "# LOCALIZATION (en = English, ca = Catalan)\n";

View File

@@ -138,6 +138,11 @@ namespace Options {
float height{Defaults::Canvas::HEIGHT}; // Alto de la resolucion del juego float height{Defaults::Canvas::HEIGHT}; // Alto de la resolucion del juego
}; };
// Estructura para las opciones de la pantalla de carga de recursos
struct Loading {
bool show_progress{Defaults::Loading::SHOW_PROGRESS}; // Mostrar barra de progreso al cargar recursos
};
// Estructura para las opciones visuales de la consola en pantalla // Estructura para las opciones visuales de la consola en pantalla
struct Console { struct Console {
bool transparent{Defaults::Console::TRANSPARENT}; // true = sin fondo, false = sólida bool transparent{Defaults::Console::TRANSPARENT}; // true = sin fondo, false = sólida
@@ -191,6 +196,7 @@ namespace Options {
inline GamepadControls gamepad_controls{}; // Botones del gamepad usados para jugar inline GamepadControls gamepad_controls{}; // Botones del gamepad usados para jugar
inline Kiosk kiosk{}; // Opciones del modo kiosko inline Kiosk kiosk{}; // Opciones del modo kiosko
inline Console console{}; // Opciones visuales de la consola en pantalla inline Console console{}; // Opciones visuales de la consola en pantalla
inline Loading loading{}; // Opciones de la pantalla de carga de recursos
// Idioma del juego (establecido al inicio, sin cambio en caliente) // Idioma del juego (establecido al inicio, sin cambio en caliente)
inline std::string language{Defaults::Localization::LANGUAGE}; inline std::string language{Defaults::Localization::LANGUAGE};