Compare commits
23 Commits
1c3d59d678
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| c610065fe0 | |||
| d2be113c4e | |||
| 052bb063df | |||
| 9d974438b3 | |||
| b9fe376f2a | |||
| 0c05f6d5b6 | |||
| 39125ee57c | |||
| 7ebeeebaaf | |||
| c6c7b63f6d | |||
| 7959baeed9 | |||
| 5d1c6c6d99 | |||
| 145d1e3fc0 | |||
| 4679255d60 | |||
| 3cfb65320c | |||
| 636e4d932a | |||
| 9979f31b4a | |||
| 6190b35349 | |||
| fd4136a882 | |||
| 5362c5b022 | |||
| 357b5d5977 | |||
| f50ad68f10 | |||
| 155a7d038d | |||
| 4b732c189c |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -18,6 +18,9 @@ debug.txt
|
|||||||
cppcheck-result*
|
cppcheck-result*
|
||||||
desktop.ini
|
desktop.ini
|
||||||
ccae_release/
|
ccae_release/
|
||||||
|
Frameworks/
|
||||||
resources.pack
|
resources.pack
|
||||||
tools/pack_resources.cpp
|
|
||||||
pack_resources.cpp
|
# Herramienta pack_resources (todas las plataformas)
|
||||||
|
tools/pack_resources
|
||||||
|
tools/pack_resources.exe
|
||||||
|
|||||||
89
Makefile
89
Makefile
@@ -150,7 +150,7 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
# Reglas para herramienta de empaquetado y resources.pack
|
# Reglas para herramienta de empaquetado y resources.pack
|
||||||
$(PACK_TOOL): $(PACK_SOURCES)
|
$(PACK_TOOL): FORCE
|
||||||
@echo "Compilando herramienta de empaquetado..."
|
@echo "Compilando herramienta de empaquetado..."
|
||||||
$(PACK_CXX) -std=c++20 -Wall -Os $(PACK_INCLUDES) $(PACK_SOURCES) -o $(PACK_TOOL)
|
$(PACK_CXX) -std=c++20 -Wall -Os $(PACK_INCLUDES) $(PACK_SOURCES) -o $(PACK_TOOL)
|
||||||
@echo "✓ Herramienta de empaquetado lista: $(PACK_TOOL)"
|
@echo "✓ Herramienta de empaquetado lista: $(PACK_TOOL)"
|
||||||
@@ -180,7 +180,9 @@ windows_debug:
|
|||||||
@echo Compilando version debug para Windows: "$(APP_NAME)_debug.exe"
|
@echo Compilando version debug para Windows: "$(APP_NAME)_debug.exe"
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(WIN_TARGET_FILE)_debug.exe"
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(WIN_TARGET_FILE)_debug.exe"
|
||||||
|
|
||||||
windows_release: resources.pack
|
windows_release:
|
||||||
|
@$(MAKE) pack_tool
|
||||||
|
@$(MAKE) resources.pack
|
||||||
@echo off
|
@echo off
|
||||||
@echo Creando release para Windows - Version: $(VERSION)
|
@echo Creando release para Windows - Version: $(VERSION)
|
||||||
|
|
||||||
@@ -199,7 +201,7 @@ windows_release: resources.pack
|
|||||||
|
|
||||||
# Compila
|
# Compila
|
||||||
windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
|
windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
|
||||||
$(CXX) $(APP_SOURCES) $(RESOURCE_FILE) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(WIN_RELEASE_FILE).exe"
|
$(CXX) $(APP_SOURCES) $(RESOURCE_FILE) $(INCLUDES) -DRELEASE_BUILD $(CXXFLAGS) $(LDFLAGS) -o "$(WIN_RELEASE_FILE).exe"
|
||||||
strip -s -R .comment -R .gnu.version "$(WIN_RELEASE_FILE).exe" --strip-unneeded
|
strip -s -R .comment -R .gnu.version "$(WIN_RELEASE_FILE).exe" --strip-unneeded
|
||||||
|
|
||||||
# Crea el fichero .zip
|
# Crea el fichero .zip
|
||||||
@@ -218,8 +220,14 @@ macos_debug:
|
|||||||
@echo "Compilando version debug para macOS: $(TARGET_NAME)_debug"
|
@echo "Compilando version debug para macOS: $(TARGET_NAME)_debug"
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
||||||
|
|
||||||
macos_release: resources.pack
|
macos_release:
|
||||||
|
@$(MAKE) pack_tool
|
||||||
|
@$(MAKE) resources.pack
|
||||||
@echo "Creando release para macOS - Version: $(VERSION)"
|
@echo "Creando release para macOS - Version: $(VERSION)"
|
||||||
|
|
||||||
|
# Verificar e instalar create-dmg si es necesario
|
||||||
|
@which create-dmg > /dev/null || (echo "Instalando create-dmg..." && brew install create-dmg)
|
||||||
|
|
||||||
# Elimina datos de compilaciones anteriores
|
# Elimina datos de compilaciones anteriores
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
$(RMDIR) Frameworks
|
$(RMDIR) Frameworks
|
||||||
@@ -243,33 +251,52 @@ macos_release: resources.pack
|
|||||||
cp LICENSE "$(RELEASE_FOLDER)"
|
cp LICENSE "$(RELEASE_FOLDER)"
|
||||||
cp README.md "$(RELEASE_FOLDER)"
|
cp README.md "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
# Crea enlaces
|
|
||||||
ln -s /Applications "$(RELEASE_FOLDER)"/Applications
|
|
||||||
|
|
||||||
# Compila la versión para procesadores Intel
|
# Compila la versión para procesadores Intel
|
||||||
ifdef ENABLE_MACOS_X86_64
|
ifdef ENABLE_MACOS_X86_64
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DMACOS_BUNDLE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.15
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DMACOS_BUNDLE -DRELEASE_BUILD $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.15
|
||||||
|
|
||||||
# Firma la aplicación
|
# Firma la aplicación
|
||||||
codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app"
|
codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app"
|
||||||
|
|
||||||
# Empaqueta el .dmg de la versión Intel
|
# Empaqueta el .dmg de la versión Intel con create-dmg
|
||||||
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
|
@echo "Creando DMG Intel con iconos de 96x96..."
|
||||||
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_INTEL_RELEASE)"
|
create-dmg \
|
||||||
$(RMFILE) tmp.dmg
|
--volname "$(APP_NAME)" \
|
||||||
|
--window-pos 200 120 \
|
||||||
|
--window-size 720 300 \
|
||||||
|
--icon-size 96 \
|
||||||
|
--text-size 12 \
|
||||||
|
--icon "$(APP_NAME).app" 278 102 \
|
||||||
|
--icon "LICENSE" 441 102 \
|
||||||
|
--icon "README.md" 604 102 \
|
||||||
|
--app-drop-link 115 102 \
|
||||||
|
--hide-extension "$(APP_NAME).app" \
|
||||||
|
"$(MACOS_INTEL_RELEASE)" \
|
||||||
|
"$(RELEASE_FOLDER)" || true
|
||||||
@echo "Release Intel creado: $(MACOS_INTEL_RELEASE)"
|
@echo "Release Intel creado: $(MACOS_INTEL_RELEASE)"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Compila la versión para procesadores Apple Silicon
|
# Compila la versión para procesadores Apple Silicon
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DMACOS_BUNDLE -DSDL_DISABLE_IMMINTRIN_H $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DMACOS_BUNDLE -DRELEASE_BUILD -DSDL_DISABLE_IMMINTRIN_H $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11
|
||||||
|
|
||||||
# Firma la aplicación
|
# Firma la aplicación
|
||||||
codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app"
|
codesign --deep --force --sign - --timestamp=none "$(RELEASE_FOLDER)/$(APP_NAME).app"
|
||||||
|
|
||||||
# Empaqueta el .dmg de la versión Apple Silicon
|
# Empaqueta el .dmg de la versión Apple Silicon con create-dmg
|
||||||
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
|
@echo "Creando DMG Apple Silicon con iconos de 96x96..."
|
||||||
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_APPLE_SILICON_RELEASE)"
|
create-dmg \
|
||||||
$(RMFILE) tmp.dmg
|
--volname "$(APP_NAME)" \
|
||||||
|
--window-pos 200 120 \
|
||||||
|
--window-size 720 300 \
|
||||||
|
--icon-size 96 \
|
||||||
|
--text-size 12 \
|
||||||
|
--icon "$(APP_NAME).app" 278 102 \
|
||||||
|
--icon "LICENSE" 441 102 \
|
||||||
|
--icon "README.md" 604 102 \
|
||||||
|
--app-drop-link 115 102 \
|
||||||
|
--hide-extension "$(APP_NAME).app" \
|
||||||
|
"$(MACOS_APPLE_SILICON_RELEASE)" \
|
||||||
|
"$(RELEASE_FOLDER)" || true
|
||||||
@echo "Release Apple Silicon creado: $(MACOS_APPLE_SILICON_RELEASE)"
|
@echo "Release Apple Silicon creado: $(MACOS_APPLE_SILICON_RELEASE)"
|
||||||
|
|
||||||
# Elimina las carpetas temporales
|
# Elimina las carpetas temporales
|
||||||
@@ -285,7 +312,9 @@ linux_debug:
|
|||||||
@echo "Compilando version debug para Linux: $(TARGET_NAME)_debug"
|
@echo "Compilando version debug para Linux: $(TARGET_NAME)_debug"
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
||||||
|
|
||||||
linux_release: resources.pack
|
linux_release:
|
||||||
|
@$(MAKE) pack_tool
|
||||||
|
@$(MAKE) resources.pack
|
||||||
@echo "Creando release para Linux - Version: $(VERSION)"
|
@echo "Creando release para Linux - Version: $(VERSION)"
|
||||||
# Elimina carpetas previas
|
# Elimina carpetas previas
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
@@ -300,7 +329,7 @@ linux_release: resources.pack
|
|||||||
cp README.md "$(RELEASE_FOLDER)"
|
cp README.md "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
# Compila
|
# Compila
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DRELEASE_BUILD $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
|
||||||
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
|
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
|
||||||
|
|
||||||
# Empaqueta ficheros
|
# Empaqueta ficheros
|
||||||
@@ -311,7 +340,9 @@ linux_release: resources.pack
|
|||||||
# Elimina la carpeta temporal
|
# Elimina la carpeta temporal
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
linux_release_desktop: resources.pack
|
linux_release_desktop:
|
||||||
|
@$(MAKE) pack_tool
|
||||||
|
@$(MAKE) resources.pack
|
||||||
@echo "Creando release con integracion desktop para Linux - Version: $(VERSION)"
|
@echo "Creando release con integracion desktop para Linux - Version: $(VERSION)"
|
||||||
# Elimina carpetas previas
|
# Elimina carpetas previas
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
@@ -330,7 +361,7 @@ linux_release_desktop: resources.pack
|
|||||||
cp README.md "$(RELEASE_FOLDER)/$(TARGET_NAME)/"
|
cp README.md "$(RELEASE_FOLDER)/$(TARGET_NAME)/"
|
||||||
|
|
||||||
# Compila el ejecutable
|
# Compila el ejecutable
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin/$(TARGET_NAME)"
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DRELEASE_BUILD $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin/$(TARGET_NAME)"
|
||||||
strip -s -R .comment -R .gnu.version "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin/$(TARGET_NAME)" --strip-unneeded
|
strip -s -R .comment -R .gnu.version "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin/$(TARGET_NAME)" --strip-unneeded
|
||||||
|
|
||||||
# Crea el archivo .desktop
|
# Crea el archivo .desktop
|
||||||
@@ -416,7 +447,9 @@ raspi_debug:
|
|||||||
@echo "Compilando version debug para Raspberry Pi: $(TARGET_NAME)_debug"
|
@echo "Compilando version debug para Raspberry Pi: $(TARGET_NAME)_debug"
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE -DDEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE -DDEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
||||||
|
|
||||||
raspi_release: resources.pack
|
raspi_release:
|
||||||
|
@$(MAKE) pack_tool
|
||||||
|
@$(MAKE) resources.pack
|
||||||
@echo "Creando release para Raspberry Pi - Version: $(VERSION)"
|
@echo "Creando release para Raspberry Pi - Version: $(VERSION)"
|
||||||
# Elimina carpetas previas
|
# Elimina carpetas previas
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
@@ -431,7 +464,7 @@ raspi_release: resources.pack
|
|||||||
cp README.md "$(RELEASE_FOLDER)"
|
cp README.md "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
# Compila
|
# Compila
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DRELEASE_BUILD -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
|
||||||
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
|
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
|
||||||
|
|
||||||
# Empaqueta ficheros
|
# Empaqueta ficheros
|
||||||
@@ -442,7 +475,9 @@ raspi_release: resources.pack
|
|||||||
# Elimina la carpeta temporal
|
# Elimina la carpeta temporal
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
anbernic: resources.pack
|
anbernic:
|
||||||
|
@$(MAKE) pack_tool
|
||||||
|
@$(MAKE) resources.pack
|
||||||
@echo "Compilando para Anbernic: $(TARGET_NAME)"
|
@echo "Compilando para Anbernic: $(TARGET_NAME)"
|
||||||
# Elimina carpetas previas
|
# Elimina carpetas previas
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"_anbernic
|
$(RMDIR) "$(RELEASE_FOLDER)"_anbernic
|
||||||
@@ -455,7 +490,7 @@ anbernic: resources.pack
|
|||||||
cp resources.pack "$(RELEASE_FOLDER)"_anbernic
|
cp resources.pack "$(RELEASE_FOLDER)"_anbernic
|
||||||
|
|
||||||
# Compila
|
# Compila
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DANBERNIC -DNO_SHADERS -DARCADE -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(RELEASE_FOLDER)_anbernic/$(TARGET_NAME)
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DRELEASE_BUILD -DANBERNIC -DNO_SHADERS -DARCADE -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(RELEASE_FOLDER)_anbernic/$(TARGET_NAME)
|
||||||
|
|
||||||
# Opción para deshabilitar audio (equivalente a la opción DISABLE_AUDIO de CMake)
|
# Opción para deshabilitar audio (equivalente a la opción DISABLE_AUDIO de CMake)
|
||||||
no_audio:
|
no_audio:
|
||||||
@@ -489,4 +524,6 @@ help:
|
|||||||
@echo " show_version - Mostrar version actual ($(VERSION))"
|
@echo " show_version - Mostrar version actual ($(VERSION))"
|
||||||
@echo " help - Mostrar esta ayuda"
|
@echo " help - Mostrar esta ayuda"
|
||||||
|
|
||||||
.PHONY: windows windows_rec windows_debug windows_release macos macos_debug macos_release linux linux_debug linux_release linux_release_desktop raspi raspi_debug raspi_release anbernic no_audio show_version help pack_tool
|
.PHONY: windows windows_rec windows_debug windows_release macos macos_debug macos_release linux linux_debug linux_release linux_release_desktop raspi raspi_debug raspi_release anbernic no_audio show_version help pack_tool resources.pack
|
||||||
|
|
||||||
|
FORCE:
|
||||||
13
README.md
13
README.md
@@ -1,6 +1,8 @@
|
|||||||
# Coffee Crisis Arcade Edition
|
<div align="center">
|
||||||
|
<img src="https://php.sustancia.synology.me/images/ccae/coffee_crisis_arcade_edition_cover_web.png" width="600" alt="Coffee Crisis Cover">
|
||||||
|
</div>
|
||||||
|
|
||||||
<img src="https://php.sustancia.synology.me/images/ccae/coffee_crisis_arcade_edition_cover_web.png" width="300" align="left" style="margin-right: 20px; margin-bottom: 10px;" alt="Coffee Crisis Cover">
|
# Coffee Crisis Arcade Edition
|
||||||
|
|
||||||
## ¡La batalla definitiva pel cafè està ací!
|
## ¡La batalla definitiva pel cafè està ací!
|
||||||
|
|
||||||
@@ -35,10 +37,7 @@ El joc està optimitzat per a ser jugat amb un mando de jocs, encara que un dels
|
|||||||
|
|
||||||
> Nota: El joc suporta nomes un jugador amb teclat.
|
> Nota: El joc suporta nomes un jugador amb teclat.
|
||||||
|
|
||||||
<p align="center">
|

|
||||||
<img src="https://php.sustancia.synology.me/images/ccae/ccae1.png" alt="Joc" width="45%" />
|
|
||||||
<img src="https://php.sustancia.synology.me/images/ccae/ccae3.png" alt="Joc" width="45%" />
|
|
||||||
</p>
|
|
||||||
|
|
||||||
## Altres tecles
|
## Altres tecles
|
||||||
|
|
||||||
@@ -64,6 +63,8 @@ El joc està optimitzat per a ser jugat amb un mando de jocs, encara que un dels
|
|||||||
2. Descomprimix i executa l'arxiu `coffee_crisis_arcade_edition.exe`.
|
2. Descomprimix i executa l'arxiu `coffee_crisis_arcade_edition.exe`.
|
||||||
3. Gaudeix del joc!
|
3. Gaudeix del joc!
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Agraïments
|
## Agraïments
|
||||||
|
|
||||||
Vull expressar la meua gratitud a **ChatGPT** i **GitHub Copilot**. Gràcies per ser un suport constant en el desenvolupament d'aquest joc!
|
Vull expressar la meua gratitud a **ChatGPT** i **GitHub Copilot**. Gràcies per ser un suport constant en el desenvolupament d'aquest joc!
|
||||||
|
|||||||
@@ -18,191 +18,191 @@ DATA|${PREFIX}/config/pools.txt
|
|||||||
DATA|${PREFIX}/config/stages.txt
|
DATA|${PREFIX}/config/stages.txt
|
||||||
|
|
||||||
# Archivos con los datos de la demo
|
# Archivos con los datos de la demo
|
||||||
DEMODATA|${PREFIX}/data/demo/demo1.bin
|
DEMODATA|/data/demo/demo1.bin
|
||||||
DEMODATA|${PREFIX}/data/demo/demo2.bin
|
DEMODATA|/data/demo/demo2.bin
|
||||||
DEMODATA|${PREFIX}/data/demo/demo3.bin
|
DEMODATA|/data/demo/demo3.bin
|
||||||
|
|
||||||
# Música
|
# Música
|
||||||
MUSIC|${PREFIX}/data/music/congratulations.ogg
|
MUSIC|/data/music/congratulations.ogg
|
||||||
MUSIC|${PREFIX}/data/music/credits.ogg
|
MUSIC|/data/music/credits.ogg
|
||||||
MUSIC|${PREFIX}/data/music/intro.ogg
|
MUSIC|/data/music/intro.ogg
|
||||||
MUSIC|${PREFIX}/data/music/playing.ogg
|
MUSIC|/data/music/playing.ogg
|
||||||
MUSIC|${PREFIX}/data/music/title.ogg
|
MUSIC|/data/music/title.ogg
|
||||||
|
|
||||||
# Sonidos
|
# Sonidos
|
||||||
SOUND|${PREFIX}/data/sound/balloon_bounce0.wav
|
SOUND|/data/sound/balloon_bounce0.wav
|
||||||
SOUND|${PREFIX}/data/sound/balloon_bounce1.wav
|
SOUND|/data/sound/balloon_bounce1.wav
|
||||||
SOUND|${PREFIX}/data/sound/balloon_bounce2.wav
|
SOUND|/data/sound/balloon_bounce2.wav
|
||||||
SOUND|${PREFIX}/data/sound/balloon_bounce3.wav
|
SOUND|/data/sound/balloon_bounce3.wav
|
||||||
SOUND|${PREFIX}/data/sound/balloon_pop0.wav
|
SOUND|/data/sound/balloon_pop0.wav
|
||||||
SOUND|${PREFIX}/data/sound/balloon_pop1.wav
|
SOUND|/data/sound/balloon_pop1.wav
|
||||||
SOUND|${PREFIX}/data/sound/balloon_pop2.wav
|
SOUND|/data/sound/balloon_pop2.wav
|
||||||
SOUND|${PREFIX}/data/sound/balloon_pop3.wav
|
SOUND|/data/sound/balloon_pop3.wav
|
||||||
SOUND|${PREFIX}/data/sound/bullet1p.wav
|
SOUND|/data/sound/bullet1p.wav
|
||||||
SOUND|${PREFIX}/data/sound/bullet2p.wav
|
SOUND|/data/sound/bullet2p.wav
|
||||||
SOUND|${PREFIX}/data/sound/clock.wav
|
SOUND|/data/sound/clock.wav
|
||||||
SOUND|${PREFIX}/data/sound/coffee_out.wav
|
SOUND|/data/sound/coffee_out.wav
|
||||||
SOUND|${PREFIX}/data/sound/continue_clock.wav
|
SOUND|/data/sound/continue_clock.wav
|
||||||
SOUND|${PREFIX}/data/sound/credit.wav
|
SOUND|/data/sound/credit.wav
|
||||||
SOUND|${PREFIX}/data/sound/debian_drop.wav
|
SOUND|/data/sound/debian_drop.wav
|
||||||
SOUND|${PREFIX}/data/sound/debian_pickup.wav
|
SOUND|/data/sound/debian_pickup.wav
|
||||||
SOUND|${PREFIX}/data/sound/hi_score_achieved.wav
|
SOUND|/data/sound/hi_score_achieved.wav
|
||||||
SOUND|${PREFIX}/data/sound/item_drop.wav
|
SOUND|/data/sound/item_drop.wav
|
||||||
SOUND|${PREFIX}/data/sound/item_pickup.wav
|
SOUND|/data/sound/item_pickup.wav
|
||||||
SOUND|${PREFIX}/data/sound/jump.wav
|
SOUND|/data/sound/jump.wav
|
||||||
SOUND|${PREFIX}/data/sound/logo.wav
|
SOUND|/data/sound/logo.wav
|
||||||
SOUND|${PREFIX}/data/sound/name_input_accept.wav
|
SOUND|/data/sound/name_input_accept.wav
|
||||||
SOUND|${PREFIX}/data/sound/notify.wav
|
SOUND|/data/sound/notify.wav
|
||||||
SOUND|${PREFIX}/data/sound/player_collision.wav
|
SOUND|/data/sound/player_collision.wav
|
||||||
SOUND|${PREFIX}/data/sound/power_ball_explosion.wav
|
SOUND|/data/sound/power_ball_explosion.wav
|
||||||
SOUND|${PREFIX}/data/sound/service_menu_adjust.wav
|
SOUND|/data/sound/service_menu_adjust.wav
|
||||||
SOUND|${PREFIX}/data/sound/service_menu_back.wav
|
SOUND|/data/sound/service_menu_back.wav
|
||||||
SOUND|${PREFIX}/data/sound/service_menu_move.wav
|
SOUND|/data/sound/service_menu_move.wav
|
||||||
SOUND|${PREFIX}/data/sound/service_menu_select.wav
|
SOUND|/data/sound/service_menu_select.wav
|
||||||
SOUND|${PREFIX}/data/sound/stage_change.wav
|
SOUND|/data/sound/stage_change.wav
|
||||||
SOUND|${PREFIX}/data/sound/tabe_hit.wav
|
SOUND|/data/sound/tabe_hit.wav
|
||||||
SOUND|${PREFIX}/data/sound/tabe.wav
|
SOUND|/data/sound/tabe.wav
|
||||||
SOUND|${PREFIX}/data/sound/title.wav
|
SOUND|/data/sound/title.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_aw_aw_aw.wav
|
SOUND|/data/sound/voice_aw_aw_aw.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_coffee.wav
|
SOUND|/data/sound/voice_coffee.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_credit_thankyou.wav
|
SOUND|/data/sound/voice_credit_thankyou.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_game_over.wav
|
SOUND|/data/sound/voice_game_over.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_get_ready.wav
|
SOUND|/data/sound/voice_get_ready.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_no.wav
|
SOUND|/data/sound/voice_no.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_power_up.wav
|
SOUND|/data/sound/voice_power_up.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_recover.wav
|
SOUND|/data/sound/voice_recover.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_thankyou.wav
|
SOUND|/data/sound/voice_thankyou.wav
|
||||||
SOUND|${PREFIX}/data/sound/walk.wav
|
SOUND|/data/sound/walk.wav
|
||||||
|
|
||||||
# Shaders OpenGL Desktop 3.3 (Windows/Linux)
|
# Shaders OpenGL Desktop 3.3 (Windows/Linux)
|
||||||
DATA|${PREFIX}/data/shaders/crtpi_vertex.glsl
|
DATA|/data/shaders/crtpi_vertex.glsl
|
||||||
DATA|${PREFIX}/data/shaders/crtpi_fragment.glsl
|
DATA|/data/shaders/crtpi_fragment.glsl
|
||||||
|
|
||||||
# Shaders OpenGL ES 3.0 (Raspberry Pi) - opcionales
|
# Shaders OpenGL ES 3.0 (Raspberry Pi) - opcionales
|
||||||
DATA|${PREFIX}/data/shaders/crtpi_vertex_es.glsl|optional
|
DATA|/data/shaders/crtpi_vertex_es.glsl|optional
|
||||||
DATA|${PREFIX}/data/shaders/crtpi_fragment_es.glsl|optional
|
DATA|/data/shaders/crtpi_fragment_es.glsl|optional
|
||||||
|
|
||||||
# Texturas - Balloons
|
# Texturas - Balloons
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/balloon0.ani
|
ANIMATION|/data/gfx/balloon/balloon0.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/balloon1.ani
|
ANIMATION|/data/gfx/balloon/balloon1.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/balloon2.ani
|
ANIMATION|/data/gfx/balloon/balloon2.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/balloon3.ani
|
ANIMATION|/data/gfx/balloon/balloon3.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/balloon0.png
|
BITMAP|/data/gfx/balloon/balloon0.png
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/balloon1.png
|
BITMAP|/data/gfx/balloon/balloon1.png
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/balloon2.png
|
BITMAP|/data/gfx/balloon/balloon2.png
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/balloon3.png
|
BITMAP|/data/gfx/balloon/balloon3.png
|
||||||
|
|
||||||
# Texturas - Explosiones
|
# Texturas - Explosiones
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/explosion0.ani
|
ANIMATION|/data/gfx/balloon/explosion0.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/explosion1.ani
|
ANIMATION|/data/gfx/balloon/explosion1.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/explosion2.ani
|
ANIMATION|/data/gfx/balloon/explosion2.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/explosion3.ani
|
ANIMATION|/data/gfx/balloon/explosion3.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/explosion0.png
|
BITMAP|/data/gfx/balloon/explosion0.png
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/explosion1.png
|
BITMAP|/data/gfx/balloon/explosion1.png
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/explosion2.png
|
BITMAP|/data/gfx/balloon/explosion2.png
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/explosion3.png
|
BITMAP|/data/gfx/balloon/explosion3.png
|
||||||
|
|
||||||
# Texturas - Power Ball
|
# Texturas - Power Ball
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/powerball.ani
|
ANIMATION|/data/gfx/balloon/powerball.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/powerball.png
|
BITMAP|/data/gfx/balloon/powerball.png
|
||||||
|
|
||||||
# Texturas - Bala
|
# Texturas - Bala
|
||||||
ANIMATION|${PREFIX}/data/gfx/bullet/bullet.ani
|
ANIMATION|/data/gfx/bullet/bullet.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/bullet/bullet.png
|
BITMAP|/data/gfx/bullet/bullet.png
|
||||||
|
|
||||||
# Texturas - Tabe
|
# Texturas - Tabe
|
||||||
ANIMATION|${PREFIX}/data/gfx/tabe/tabe.ani
|
ANIMATION|/data/gfx/tabe/tabe.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/tabe/tabe.png
|
BITMAP|/data/gfx/tabe/tabe.png
|
||||||
|
|
||||||
# Texturas - Juego
|
# Texturas - Juego
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_buildings.png
|
BITMAP|/data/gfx/game/game_buildings.png
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_clouds1.png
|
BITMAP|/data/gfx/game/game_clouds1.png
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_clouds2.png
|
BITMAP|/data/gfx/game/game_clouds2.png
|
||||||
ANIMATION|${PREFIX}/data/gfx/game/game_grass.ani
|
ANIMATION|/data/gfx/game/game_grass.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_grass.png
|
BITMAP|/data/gfx/game/game_grass.png
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_moon.png
|
BITMAP|/data/gfx/game/game_moon.png
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_power_meter.png
|
BITMAP|/data/gfx/game/game_power_meter.png
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_sky_colors.png
|
BITMAP|/data/gfx/game/game_sky_colors.png
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_sun.png
|
BITMAP|/data/gfx/game/game_sun.png
|
||||||
|
|
||||||
# Texturas - Intro
|
# Texturas - Intro
|
||||||
BITMAP|${PREFIX}/data/gfx/intro/intro1.png
|
BITMAP|/data/gfx/intro/intro1.png
|
||||||
BITMAP|${PREFIX}/data/gfx/intro/intro2.png
|
BITMAP|/data/gfx/intro/intro2.png
|
||||||
BITMAP|${PREFIX}/data/gfx/intro/intro3.png
|
BITMAP|/data/gfx/intro/intro3.png
|
||||||
BITMAP|${PREFIX}/data/gfx/intro/intro4.png
|
BITMAP|/data/gfx/intro/intro4.png
|
||||||
BITMAP|${PREFIX}/data/gfx/intro/intro5.png
|
BITMAP|/data/gfx/intro/intro5.png
|
||||||
BITMAP|${PREFIX}/data/gfx/intro/intro6.png
|
BITMAP|/data/gfx/intro/intro6.png
|
||||||
|
|
||||||
# Texturas - Logo
|
# Texturas - Logo
|
||||||
BITMAP|${PREFIX}/data/gfx/logo/logo_jailgames_mini.png
|
BITMAP|/data/gfx/logo/logo_jailgames_mini.png
|
||||||
BITMAP|${PREFIX}/data/gfx/logo/logo_jailgames.png
|
BITMAP|/data/gfx/logo/logo_jailgames.png
|
||||||
BITMAP|${PREFIX}/data/gfx/logo/logo_since_1998.png
|
BITMAP|/data/gfx/logo/logo_since_1998.png
|
||||||
|
|
||||||
# Texturas - Items
|
# Texturas - Items
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_clock.ani
|
ANIMATION|/data/gfx/item/item_clock.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_coffee_machine.ani
|
ANIMATION|/data/gfx/item/item_coffee_machine.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_coffee.ani
|
ANIMATION|/data/gfx/item/item_coffee.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_debian.ani
|
ANIMATION|/data/gfx/item/item_debian.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_points1_disk.ani
|
ANIMATION|/data/gfx/item/item_points1_disk.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_points2_gavina.ani
|
ANIMATION|/data/gfx/item/item_points2_gavina.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_points3_pacmar.ani
|
ANIMATION|/data/gfx/item/item_points3_pacmar.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_clock.png
|
BITMAP|/data/gfx/item/item_clock.png
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_coffee_machine.png
|
BITMAP|/data/gfx/item/item_coffee_machine.png
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_coffee.png
|
BITMAP|/data/gfx/item/item_coffee.png
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_debian.png
|
BITMAP|/data/gfx/item/item_debian.png
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_points1_disk.png
|
BITMAP|/data/gfx/item/item_points1_disk.png
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_points2_gavina.png
|
BITMAP|/data/gfx/item/item_points2_gavina.png
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_points3_pacmar.png
|
BITMAP|/data/gfx/item/item_points3_pacmar.png
|
||||||
|
|
||||||
# Texturas - Titulo
|
# Texturas - Titulo
|
||||||
ANIMATION|${PREFIX}/data/gfx/title/title_dust.ani
|
ANIMATION|/data/gfx/title/title_dust.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/title/title_arcade_edition.png
|
BITMAP|/data/gfx/title/title_arcade_edition.png
|
||||||
BITMAP|${PREFIX}/data/gfx/title/title_bg_tile.png
|
BITMAP|/data/gfx/title/title_bg_tile.png
|
||||||
BITMAP|${PREFIX}/data/gfx/title/title_coffee.png
|
BITMAP|/data/gfx/title/title_coffee.png
|
||||||
BITMAP|${PREFIX}/data/gfx/title/title_crisis.png
|
BITMAP|/data/gfx/title/title_crisis.png
|
||||||
BITMAP|${PREFIX}/data/gfx/title/title_dust.png
|
BITMAP|/data/gfx/title/title_dust.png
|
||||||
|
|
||||||
# Texturas - Jugador 1
|
# Texturas - Jugador 1
|
||||||
BITMAP|${PREFIX}/data/gfx/player/player1_power.png
|
BITMAP|/data/gfx/player/player1_power.png
|
||||||
BITMAP|${PREFIX}/data/gfx/player/player1.gif
|
BITMAP|/data/gfx/player/player1.gif
|
||||||
PALETTE|${PREFIX}/data/gfx/player/player1_coffee1.pal
|
PALETTE|/data/gfx/player/player1_coffee1.pal
|
||||||
PALETTE|${PREFIX}/data/gfx/player/player1_coffee2.pal
|
PALETTE|/data/gfx/player/player1_coffee2.pal
|
||||||
PALETTE|${PREFIX}/data/gfx/player/player1_invencible.pal
|
PALETTE|/data/gfx/player/player1_invencible.pal
|
||||||
|
|
||||||
# Texturas - Jugador 2
|
# Texturas - Jugador 2
|
||||||
BITMAP|${PREFIX}/data/gfx/player/player2_power.png
|
BITMAP|/data/gfx/player/player2_power.png
|
||||||
BITMAP|${PREFIX}/data/gfx/player/player2.gif
|
BITMAP|/data/gfx/player/player2.gif
|
||||||
PALETTE|${PREFIX}/data/gfx/player/player2_coffee1.pal
|
PALETTE|/data/gfx/player/player2_coffee1.pal
|
||||||
PALETTE|${PREFIX}/data/gfx/player/player2_coffee2.pal
|
PALETTE|/data/gfx/player/player2_coffee2.pal
|
||||||
PALETTE|${PREFIX}/data/gfx/player/player2_invencible.pal
|
PALETTE|/data/gfx/player/player2_invencible.pal
|
||||||
|
|
||||||
# Animaciones del jugador
|
# Animaciones del jugador
|
||||||
ANIMATION|${PREFIX}/data/gfx/player/player_power.ani
|
ANIMATION|/data/gfx/player/player_power.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/player/player1.ani
|
ANIMATION|/data/gfx/player/player1.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/player/player2.ani
|
ANIMATION|/data/gfx/player/player2.ani
|
||||||
|
|
||||||
# Fuentes de texto
|
# Fuentes de texto
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_2x.png
|
BITMAP|/data/font/04b_25_2x.png
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_2x_white.png
|
BITMAP|/data/font/04b_25_2x_white.png
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_flat_2x.png
|
BITMAP|/data/font/04b_25_flat_2x.png
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_flat.png
|
BITMAP|/data/font/04b_25_flat.png
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_grey.png
|
BITMAP|/data/font/04b_25_grey.png
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_metal.png
|
BITMAP|/data/font/04b_25_metal.png
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_reversed_2x.png
|
BITMAP|/data/font/04b_25_reversed_2x.png
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_reversed.png
|
BITMAP|/data/font/04b_25_reversed.png
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_white.png
|
BITMAP|/data/font/04b_25_white.png
|
||||||
BITMAP|${PREFIX}/data/font/04b_25.png
|
BITMAP|/data/font/04b_25.png
|
||||||
BITMAP|${PREFIX}/data/font/8bithud.png
|
BITMAP|/data/font/8bithud.png
|
||||||
BITMAP|${PREFIX}/data/font/aseprite.png
|
BITMAP|/data/font/aseprite.png
|
||||||
BITMAP|${PREFIX}/data/font/smb2_grad.png
|
BITMAP|/data/font/smb2_grad.png
|
||||||
BITMAP|${PREFIX}/data/font/smb2.png
|
BITMAP|/data/font/smb2.png
|
||||||
FONT|${PREFIX}/data/font/04b_25_2x.txt
|
FONT|/data/font/04b_25_2x.txt
|
||||||
FONT|${PREFIX}/data/font/04b_25.txt
|
FONT|/data/font/04b_25.txt
|
||||||
FONT|${PREFIX}/data/font/8bithud.txt
|
FONT|/data/font/8bithud.txt
|
||||||
FONT|${PREFIX}/data/font/aseprite.txt
|
FONT|/data/font/aseprite.txt
|
||||||
FONT|${PREFIX}/data/font/smb2.txt
|
FONT|/data/font/smb2.txt
|
||||||
|
|
||||||
# Idiomas
|
# Idiomas
|
||||||
LANG|${PREFIX}/data/lang/ba_BA.json
|
LANG|/data/lang/ba_BA.json
|
||||||
LANG|${PREFIX}/data/lang/en_UK.json
|
LANG|/data/lang/en_UK.json
|
||||||
LANG|${PREFIX}/data/lang/es_ES.json
|
LANG|/data/lang/es_ES.json
|
||||||
@@ -1,7 +1,18 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Script para ejecutar clang-tidy en múltiples directorios
|
# Script para ejecutar clang-tidy en múltiples directorios
|
||||||
# Uso: ./run_clang-tidy.sh
|
# Uso: ./run_clang-tidy.sh [--fix]
|
||||||
|
# --fix: Aplica las correcciones automáticamente (opcional)
|
||||||
|
|
||||||
|
# Detectar si se pasó el parámetro --fix
|
||||||
|
FIX_FLAG=""
|
||||||
|
if [[ "$1" == "--fix" ]]; then
|
||||||
|
FIX_FLAG="--fix"
|
||||||
|
echo "Modo: Aplicando correcciones automáticamente (--fix)"
|
||||||
|
else
|
||||||
|
echo "Modo: Solo análisis (sin --fix)"
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
|
||||||
# Lista de rutas donde ejecutar clang-tidy
|
# Lista de rutas donde ejecutar clang-tidy
|
||||||
PATHS=(
|
PATHS=(
|
||||||
@@ -31,8 +42,8 @@ process_directory() {
|
|||||||
cd "$dir" || return 1
|
cd "$dir" || return 1
|
||||||
|
|
||||||
# Buscar archivos .cpp, .h, .hpp solo en el nivel actual (no subdirectorios)
|
# Buscar archivos .cpp, .h, .hpp solo en el nivel actual (no subdirectorios)
|
||||||
find . -maxdepth 1 \( -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) | \
|
find . -maxdepth 1 \( -name '*.cpp' -o -name '*.h' -o -name '*.hpp' \) -print0 | \
|
||||||
xargs -P4 -I{} bash -c 'echo "Procesando: {}"; clang-tidy {} -p '"$BUILD_DIR"' --fix'
|
xargs -0 -P4 -I{} bash -c 'echo "Procesando: {}"; clang-tidy {} -p '"$BUILD_DIR"' '"$FIX_FLAG"
|
||||||
|
|
||||||
echo "=== Completado: $dir ==="
|
echo "=== Completado: $dir ==="
|
||||||
echo
|
echo
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
BIN
release/icon.ico
BIN
release/icon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 134 KiB |
BIN
release/icon.png
BIN
release/icon.png
Binary file not shown.
|
Before Width: | Height: | Size: 438 KiB After Width: | Height: | Size: 504 KiB |
@@ -197,8 +197,12 @@ auto Asset::check() const -> bool {
|
|||||||
|
|
||||||
// Comprueba que existe un fichero
|
// Comprueba que existe un fichero
|
||||||
auto Asset::checkFile(const std::string& path) const -> bool {
|
auto Asset::checkFile(const std::string& path) const -> bool {
|
||||||
// Construir ruta del pack usando executable_path_
|
// Construir ruta del pack usando executable_path_ (misma lógica que Director::init)
|
||||||
|
#ifdef MACOS_BUNDLE
|
||||||
|
std::string pack_path = executable_path_ + "../Resources/resources.pack";
|
||||||
|
#else
|
||||||
std::string pack_path = executable_path_ + "resources.pack";
|
std::string pack_path = executable_path_ + "resources.pack";
|
||||||
|
#endif
|
||||||
bool pack_exists = std::filesystem::exists(pack_path);
|
bool pack_exists = std::filesystem::exists(pack_path);
|
||||||
|
|
||||||
if (pack_exists) {
|
if (pack_exists) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
bool AssetIntegrated::resource_pack_enabled_ = false;
|
bool AssetIntegrated::resource_pack_enabled = false;
|
||||||
|
|
||||||
void AssetIntegrated::initWithResourcePack(const std::string& executable_path,
|
void AssetIntegrated::initWithResourcePack(const std::string& executable_path,
|
||||||
const std::string& resource_pack_path) {
|
const std::string& resource_pack_path) {
|
||||||
@@ -14,29 +14,29 @@ void AssetIntegrated::initWithResourcePack(const std::string& executable_path,
|
|||||||
// Inicializar ResourceLoader
|
// Inicializar ResourceLoader
|
||||||
auto& loader = ResourceLoader::getInstance();
|
auto& loader = ResourceLoader::getInstance();
|
||||||
if (loader.initialize(resource_pack_path, true)) {
|
if (loader.initialize(resource_pack_path, true)) {
|
||||||
resource_pack_enabled_ = true;
|
resource_pack_enabled = true;
|
||||||
std::cout << "Asset system initialized with resource pack: " << resource_pack_path << std::endl;
|
std::cout << "Asset system initialized with resource pack: " << resource_pack_path << '\n';
|
||||||
} else {
|
} else {
|
||||||
resource_pack_enabled_ = false;
|
resource_pack_enabled = false;
|
||||||
std::cout << "Asset system initialized in fallback mode (filesystem)" << std::endl;
|
std::cout << "Asset system initialized in fallback mode (filesystem)" << '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> AssetIntegrated::loadFile(const std::string& filename) {
|
auto AssetIntegrated::loadFile(const std::string& filename) -> std::vector<uint8_t> {
|
||||||
if (shouldUseResourcePack(filename) && resource_pack_enabled_) {
|
if (shouldUseResourcePack(filename) && resource_pack_enabled) {
|
||||||
// Intentar cargar del pack de recursos
|
// Intentar cargar del pack de recursos
|
||||||
auto& loader = ResourceLoader::getInstance();
|
auto& loader = ResourceLoader::getInstance();
|
||||||
|
|
||||||
// Convertir ruta completa a ruta relativa para el pack
|
// Convertir ruta completa a ruta relativa para el pack
|
||||||
std::string relativePath = filename;
|
std::string relative_path = filename;
|
||||||
|
|
||||||
// Si la ruta contiene "data/", extraer la parte relativa
|
// Si la ruta contiene "data/", extraer la parte relativa
|
||||||
size_t dataPos = filename.find("data/");
|
size_t data_pos = filename.find("data/");
|
||||||
if (dataPos != std::string::npos) {
|
if (data_pos != std::string::npos) {
|
||||||
relativePath = filename.substr(dataPos + 5); // +5 para saltar "data/"
|
relative_path = filename.substr(data_pos + 5); // +5 para saltar "data/"
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = loader.loadResource(relativePath);
|
auto data = loader.loadResource(relative_path);
|
||||||
if (!data.empty()) {
|
if (!data.empty()) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@@ -45,34 +45,34 @@ std::vector<uint8_t> AssetIntegrated::loadFile(const std::string& filename) {
|
|||||||
// Fallback: cargar del filesystem
|
// Fallback: cargar del filesystem
|
||||||
std::ifstream file(filename, std::ios::binary | std::ios::ate);
|
std::ifstream file(filename, std::ios::binary | std::ios::ate);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
std::cerr << "Error: Could not open file: " << filename << std::endl;
|
std::cerr << "Error: Could not open file: " << filename << '\n';
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::streamsize fileSize = file.tellg();
|
std::streamsize file_size = file.tellg();
|
||||||
file.seekg(0, std::ios::beg);
|
file.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
std::vector<uint8_t> data(fileSize);
|
std::vector<uint8_t> data(file_size);
|
||||||
if (!file.read(reinterpret_cast<char*>(data.data()), fileSize)) {
|
if (!file.read(reinterpret_cast<char*>(data.data()), file_size)) {
|
||||||
std::cerr << "Error: Could not read file: " << filename << std::endl;
|
std::cerr << "Error: Could not read file: " << filename << '\n';
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssetIntegrated::fileExists(const std::string& filename) const {
|
auto AssetIntegrated::fileExists(const std::string& filename) -> bool {
|
||||||
if (shouldUseResourcePack(filename) && resource_pack_enabled_) {
|
if (shouldUseResourcePack(filename) && resource_pack_enabled) {
|
||||||
auto& loader = ResourceLoader::getInstance();
|
auto& loader = ResourceLoader::getInstance();
|
||||||
|
|
||||||
// Convertir ruta completa a ruta relativa para el pack
|
// Convertir ruta completa a ruta relativa para el pack
|
||||||
std::string relativePath = filename;
|
std::string relative_path = filename;
|
||||||
size_t dataPos = filename.find("data/");
|
size_t data_pos = filename.find("data/");
|
||||||
if (dataPos != std::string::npos) {
|
if (data_pos != std::string::npos) {
|
||||||
relativePath = filename.substr(dataPos + 5);
|
relative_path = filename.substr(data_pos + 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loader.resourceExists(relativePath)) {
|
if (loader.resourceExists(relative_path)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,24 +81,24 @@ bool AssetIntegrated::fileExists(const std::string& filename) const {
|
|||||||
return std::filesystem::exists(filename);
|
return std::filesystem::exists(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string AssetIntegrated::getSystemPath(const std::string& filename) const {
|
auto AssetIntegrated::getSystemPath(const std::string& filename) -> std::string {
|
||||||
// Los archivos de sistema/config siempre van al filesystem
|
// Los archivos de sistema/config siempre van al filesystem
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssetIntegrated::shouldUseResourcePack(const std::string& filepath) const {
|
auto AssetIntegrated::shouldUseResourcePack(const std::string& filepath) -> bool {
|
||||||
// Los archivos que NO van al pack:
|
// Los archivos que NO van al pack:
|
||||||
// - Archivos de config/ (ahora están fuera de data/)
|
// - Archivos de config/ (ahora están fuera de data/)
|
||||||
// - Archivos con absolute=true en assets.txt
|
// - Archivos con absolute=true en assets.txt
|
||||||
// - Archivos de sistema (${SYSTEM_FOLDER})
|
// - Archivos de sistema (${SYSTEM_FOLDER})
|
||||||
|
|
||||||
if (filepath.find("/config/") != std::string::npos ||
|
if (filepath.find("/config/") != std::string::npos ||
|
||||||
filepath.find("config/") == 0) {
|
filepath.starts_with("config/")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filepath.find("/data/") != std::string::npos ||
|
if (filepath.find("/data/") != std::string::npos ||
|
||||||
filepath.find("data/") == 0) {
|
filepath.starts_with("data/")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,17 +13,17 @@ class AssetIntegrated : public Asset {
|
|||||||
const std::string& resource_pack_path = "resources.pack");
|
const std::string& resource_pack_path = "resources.pack");
|
||||||
|
|
||||||
// Carga un archivo usando ResourceLoader como primera opción
|
// Carga un archivo usando ResourceLoader como primera opción
|
||||||
auto loadFile(const std::string& filename) -> std::vector<uint8_t>;
|
static auto loadFile(const std::string& filename) -> std::vector<uint8_t>;
|
||||||
|
|
||||||
// Verifica si un archivo existe (pack o filesystem)
|
// Verifica si un archivo existe (pack o filesystem)
|
||||||
auto fileExists(const std::string& filename) const -> bool;
|
static auto fileExists(const std::string& filename) -> bool;
|
||||||
|
|
||||||
// Obtiene la ruta completa para archivos del sistema/config
|
// Obtiene la ruta completa para archivos del sistema/config
|
||||||
auto getSystemPath(const std::string& filename) const -> std::string;
|
static auto getSystemPath(const std::string& filename) -> std::string;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool resource_pack_enabled;
|
static bool resource_pack_enabled;
|
||||||
|
|
||||||
// Determina si un archivo debe cargarse del pack o del filesystem
|
// Determina si un archivo debe cargarse del pack o del filesystem
|
||||||
auto shouldUseResourcePack(const std::string& filepath) const -> bool;
|
static auto shouldUseResourcePack(const std::string& filepath) -> bool;
|
||||||
};
|
};
|
||||||
@@ -514,10 +514,10 @@ void Background::updateAlphaColorTexture(float delta_time) {
|
|||||||
|
|
||||||
// 4. Actualiza el valor entero solo si ha cambiado lo suficiente
|
// 4. Actualiza el valor entero solo si ha cambiado lo suficiente
|
||||||
// Usamos std::round para un redondeo más natural.
|
// Usamos std::round para un redondeo más natural.
|
||||||
const auto new_alpha = static_cast<size_t>(std::round(current_alpha_float_));
|
const auto NEW_ALPHA = static_cast<size_t>(std::round(current_alpha_float_));
|
||||||
|
|
||||||
if (new_alpha != previous_alpha_color_texture_) {
|
if (NEW_ALPHA != previous_alpha_color_texture_) {
|
||||||
previous_alpha_color_texture_ = new_alpha;
|
previous_alpha_color_texture_ = NEW_ALPHA;
|
||||||
// SDL espera un Uint8 (0-255), así que hacemos un cast seguro.
|
// SDL espera un Uint8 (0-255), así que hacemos un cast seguro.
|
||||||
SDL_SetTextureAlphaMod(color_texture_, static_cast<Uint8>(previous_alpha_color_texture_));
|
SDL_SetTextureAlphaMod(color_texture_, static_cast<Uint8>(previous_alpha_color_texture_));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
#include <SDL3/SDL.h> // Para SDL_FRect
|
#include <SDL3/SDL.h> // Para SDL_FRect
|
||||||
|
|
||||||
#include <functional> // Para function
|
#include <functional> // Para function
|
||||||
|
#include <list> // Para list
|
||||||
#include <memory> // Para shared_ptr
|
#include <memory> // Para shared_ptr
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
#include <list> // Para list
|
|
||||||
|
|
||||||
#include "bullet.hpp" // for Bullet
|
#include "bullet.hpp" // for Bullet
|
||||||
|
|
||||||
@@ -71,6 +71,6 @@ class BulletManager {
|
|||||||
OutOfBoundsCallback out_of_bounds_callback_; // Callback para balas fuera de límites
|
OutOfBoundsCallback out_of_bounds_callback_; // Callback para balas fuera de límites
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void processBulletUpdate(const std::shared_ptr<Bullet>& bullet, float delta_time); // Procesa actualización individual
|
void processBulletUpdate(const std::shared_ptr<Bullet>& bullet, float delta_time); // Procesa actualización individual
|
||||||
auto isBulletOutOfBounds(const std::shared_ptr<Bullet>& bullet) const -> bool; // Verifica si la bala está fuera de límites
|
[[nodiscard]] auto isBulletOutOfBounds(const std::shared_ptr<Bullet>& bullet) const -> bool; // Verifica si la bala está fuera de límites
|
||||||
};
|
};
|
||||||
@@ -1,24 +1,27 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm> // Para std::max
|
||||||
|
|
||||||
class Cooldown {
|
class Cooldown {
|
||||||
public:
|
public:
|
||||||
Cooldown(float first_delay_s = 0.0f, float repeat_delay_s = 0.0f)
|
Cooldown(float first_delay_s = 0.0F, float repeat_delay_s = 0.0F)
|
||||||
: first_delay_s_(first_delay_s), repeat_delay_s_(repeat_delay_s),
|
: first_delay_s_(first_delay_s), repeat_delay_s_(repeat_delay_s) {}
|
||||||
remaining_s_(0.0f), held_before_(false) {}
|
|
||||||
|
|
||||||
// Llamar cada frame con delta en segundos (float)
|
// Llamar cada frame con delta en segundos (float)
|
||||||
void update(float delta_s) {
|
void update(float delta_s) {
|
||||||
if (remaining_s_ <= 0.0f) {
|
if (remaining_s_ <= 0.0F) {
|
||||||
remaining_s_ = 0.0f;
|
remaining_s_ = 0.0F;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
remaining_s_ -= delta_s;
|
remaining_s_ -= delta_s;
|
||||||
if (remaining_s_ < 0.0f) remaining_s_ = 0.0f;
|
remaining_s_ = std::max(remaining_s_, 0.0F);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Llamar cuando el input está activo. Devuelve true si debe ejecutarse la acción ahora.
|
// Llamar cuando el input está activo. Devuelve true si debe ejecutarse la acción ahora.
|
||||||
bool tryConsumeOnHeld() {
|
auto tryConsumeOnHeld() -> bool {
|
||||||
if (remaining_s_ > 0.0f) return false;
|
if (remaining_s_ > 0.0F) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
float delay = held_before_ ? repeat_delay_s_ : first_delay_s_;
|
float delay = held_before_ ? repeat_delay_s_ : first_delay_s_;
|
||||||
remaining_s_ = delay;
|
remaining_s_ = delay;
|
||||||
@@ -29,17 +32,17 @@ public:
|
|||||||
// Llamar cuando el input se suelta
|
// Llamar cuando el input se suelta
|
||||||
void onReleased() {
|
void onReleased() {
|
||||||
held_before_ = false;
|
held_before_ = false;
|
||||||
remaining_s_ = 0.0f;
|
remaining_s_ = 0.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const { return remaining_s_ == 0.0f; }
|
[[nodiscard]] auto empty() const -> bool { return remaining_s_ == 0.0F; }
|
||||||
|
|
||||||
// Fuerza un valor en segundos (útil para tests o resets)
|
// Fuerza un valor en segundos (útil para tests o resets)
|
||||||
void forceSet(float seconds) { remaining_s_ = seconds > 0.0f ? seconds : 0.0f; }
|
void forceSet(float seconds) { remaining_s_ = seconds > 0.0F ? seconds : 0.0F; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float first_delay_s_;
|
float first_delay_s_;
|
||||||
float repeat_delay_s_;
|
float repeat_delay_s_;
|
||||||
float remaining_s_;
|
float remaining_s_{0.0F};
|
||||||
bool held_before_;
|
bool held_before_{false};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ Director::Director(int argc, std::span<char*> argv) {
|
|||||||
Section::name = Section::Name::GAME;
|
Section::name = Section::Name::GAME;
|
||||||
Section::options = Section::Options::GAME_PLAY_1P;
|
Section::options = Section::Options::GAME_PLAY_1P;
|
||||||
#elif _DEBUG
|
#elif _DEBUG
|
||||||
Section::name = Section::Name::HI_SCORE_TABLE;
|
Section::name = Section::Name::GAME;
|
||||||
Section::options = Section::Options::GAME_PLAY_1P;
|
Section::options = Section::Options::GAME_PLAY_1P;
|
||||||
#else // NORMAL GAME
|
#else // NORMAL GAME
|
||||||
Section::name = Section::Name::LOGO;
|
Section::name = Section::Name::LOGO;
|
||||||
@@ -81,11 +81,22 @@ void Director::init() {
|
|||||||
// Configuración inicial de parametros
|
// Configuración inicial de parametros
|
||||||
Asset::init(executable_path_); // Inicializa el sistema de gestión de archivos
|
Asset::init(executable_path_); // Inicializa el sistema de gestión de archivos
|
||||||
|
|
||||||
|
// Determinar ruta del pack según la plataforma
|
||||||
#ifdef MACOS_BUNDLE
|
#ifdef MACOS_BUNDLE
|
||||||
ResourceHelper::initializeResourceSystem(executable_path_ + "../Resources/resources.pack");
|
std::string pack_path = executable_path_ + "../Resources/resources.pack";
|
||||||
#else
|
#else
|
||||||
ResourceHelper::initializeResourceSystem(executable_path_ + "resources.pack");
|
std::string pack_path = executable_path_ + "resources.pack";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Inicializar sistema de recursos con o sin fallback según el tipo de build
|
||||||
|
#ifdef RELEASE_BUILD
|
||||||
|
// Release: Sin fallback - Solo resources.pack (estricto)
|
||||||
|
ResourceHelper::initializeResourceSystem(pack_path, false);
|
||||||
|
#else
|
||||||
|
// Desarrollo: Con fallback - Puede usar data/ si falta el pack (flexible)
|
||||||
|
ResourceHelper::initializeResourceSystem(pack_path, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
loadAssets(); // Crea el índice de archivos
|
loadAssets(); // Crea el índice de archivos
|
||||||
|
|
||||||
Logger::section("INIT INPUT");
|
Logger::section("INIT INPUT");
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ auto EnterName::getSelectedCharacter(int offset) const -> std::string {
|
|||||||
index += size;
|
index += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::string(1, character_list_[index]);
|
return {1, character_list_[index]};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Devuelve el carrusel completo de caracteres centrado en el seleccionado
|
// Devuelve el carrusel completo de caracteres centrado en el seleccionado
|
||||||
|
|||||||
@@ -130,12 +130,7 @@ void Fade::updatePostState() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Mantener el estado final del fade
|
// Mantener el estado final del fade
|
||||||
Uint8 post_alpha = a_;
|
Uint8 post_alpha = (mode_ == Mode::OUT) ? 255 : 0;
|
||||||
if (type_ == Type::RANDOM_SQUARE2 || type_ == Type::DIAGONAL) {
|
|
||||||
post_alpha = (mode_ == Mode::OUT) ? 255 : 0;
|
|
||||||
} else {
|
|
||||||
post_alpha = (mode_ == Mode::OUT) ? 255 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanBackbuffer(r_, g_, b_, post_alpha);
|
cleanBackbuffer(r_, g_, b_, post_alpha);
|
||||||
}
|
}
|
||||||
@@ -145,7 +140,7 @@ void Fade::updateFullscreenFade() {
|
|||||||
float progress = std::min(static_cast<float>(elapsed_time) / fading_duration_, 1.0F);
|
float progress = std::min(static_cast<float>(elapsed_time) / fading_duration_, 1.0F);
|
||||||
|
|
||||||
// Modifica la transparencia basada en el progreso
|
// Modifica la transparencia basada en el progreso
|
||||||
Uint8 current_alpha = static_cast<Uint8>(progress * 255.0f);
|
auto current_alpha = static_cast<Uint8>(progress * 255.0F);
|
||||||
a_ = (mode_ == Mode::OUT) ? current_alpha : 255 - current_alpha;
|
a_ = (mode_ == Mode::OUT) ? current_alpha : 255 - current_alpha;
|
||||||
SDL_SetTextureAlphaMod(backbuffer_, a_);
|
SDL_SetTextureAlphaMod(backbuffer_, a_);
|
||||||
|
|
||||||
@@ -162,10 +157,10 @@ void Fade::updateCenterFade() {
|
|||||||
float progress = std::min(static_cast<float>(elapsed_time) / fading_duration_, 1.0F);
|
float progress = std::min(static_cast<float>(elapsed_time) / fading_duration_, 1.0F);
|
||||||
|
|
||||||
// Calcula la altura de las barras
|
// Calcula la altura de las barras
|
||||||
float rect_height = progress * (param.game.height / 2.0f);
|
float rect_height = progress * (param.game.height / 2.0F);
|
||||||
|
|
||||||
if (mode_ == Mode::IN) {
|
if (mode_ == Mode::IN) {
|
||||||
rect_height = (param.game.height / 2.0f) - rect_height;
|
rect_height = (param.game.height / 2.0F) - rect_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
rect1_.h = rect_height;
|
rect1_.h = rect_height;
|
||||||
@@ -228,14 +223,14 @@ void Fade::updateRandomSquare2Fade() {
|
|||||||
squares_to_activate = total_squares;
|
squares_to_activate = total_squares;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < squares_to_activate; ++i) {
|
for (int i = 0; i < squares_to_activate; ++i) {
|
||||||
if (square_age_[i] == -1) square_age_[i] = elapsed_time;
|
if (square_age_[i] == -1) {square_age_[i] = elapsed_time;}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
squares_to_activate = total_squares;
|
squares_to_activate = total_squares;
|
||||||
float activation_progress = static_cast<float>(elapsed_time) / activation_time;
|
float activation_progress = static_cast<float>(elapsed_time) / activation_time;
|
||||||
int squares_starting_transition = std::min(total_squares, std::max(1, static_cast<int>(activation_progress * total_squares)));
|
int squares_starting_transition = std::min(total_squares, std::max(1, static_cast<int>(activation_progress * total_squares)));
|
||||||
for (int i = 0; i < squares_starting_transition; ++i) {
|
for (int i = 0; i < squares_starting_transition; ++i) {
|
||||||
if (square_age_[i] == -1) square_age_[i] = elapsed_time;
|
if (square_age_[i] == -1) {square_age_[i] = elapsed_time;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,8 +447,8 @@ void Fade::activate() {
|
|||||||
// Ahora, inicializamos la modulación de alfa correctamente:
|
// Ahora, inicializamos la modulación de alfa correctamente:
|
||||||
// - IN: Empieza opaco (255) y se desvanece a transparente.
|
// - IN: Empieza opaco (255) y se desvanece a transparente.
|
||||||
// - OUT: Empieza transparente (0) y se desvanece a opaco.
|
// - OUT: Empieza transparente (0) y se desvanece a opaco.
|
||||||
const Uint8 initial_alpha = (mode_ == Mode::IN) ? 255 : 0;
|
const Uint8 INITIAL_ALPHA = (mode_ == Mode::IN) ? 255 : 0;
|
||||||
SDL_SetTextureAlphaMod(backbuffer_, initial_alpha);
|
SDL_SetTextureAlphaMod(backbuffer_, INITIAL_ALPHA);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,7 +504,7 @@ void Fade::activate() {
|
|||||||
|
|
||||||
case Type::VENETIAN: {
|
case Type::VENETIAN: {
|
||||||
square_.clear();
|
square_.clear();
|
||||||
rect1_ = {.x = 0, .y = 0, .w = param.game.width, .h = (mode_ == Mode::OUT) ? 0.0f : static_cast<float>(param.fade.venetian_size)};
|
rect1_ = {.x = 0, .y = 0, .w = param.game.width, .h = (mode_ == Mode::OUT) ? 0.0F : param.fade.venetian_size};
|
||||||
const int MAX = param.game.height / param.fade.venetian_size;
|
const int MAX = param.game.height / param.fade.venetian_size;
|
||||||
for (int i = 0; i < MAX; ++i) {
|
for (int i = 0; i < MAX; ++i) {
|
||||||
rect1_.y = i * param.fade.venetian_size;
|
rect1_.y = i * param.fade.venetian_size;
|
||||||
@@ -546,7 +541,11 @@ void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
|
|||||||
|
|
||||||
// Calcula el valor del estado del fade
|
// Calcula el valor del estado del fade
|
||||||
auto Fade::calculateValue(int min, int max, int current) -> int {
|
auto Fade::calculateValue(int min, int max, int current) -> int {
|
||||||
if (current <= min) return 0;
|
if (current <= min) {
|
||||||
if (current >= max) return 100;
|
return 0;
|
||||||
|
}
|
||||||
|
if (current >= max) {
|
||||||
|
return 100;
|
||||||
|
}
|
||||||
return static_cast<int>(100.0 * (current - min) / (max - min));
|
return static_cast<int>(100.0 * (current - min) / (max - min));
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <SDL3/SDL.h> // Para SDL_ReadIO, SDL_WriteIO, SDL_CloseIO, SDL_GetError, SDL_IOFromFile, SDL_LogError, SDL_LogCategory, SDL_LogInfo
|
#include <SDL3/SDL.h> // Para SDL_ReadIO, SDL_WriteIO, SDL_CloseIO, SDL_GetError, SDL_IOFromFile, SDL_LogError, SDL_LogCategory, SDL_LogInfo
|
||||||
|
|
||||||
#include <algorithm> // Para __sort_fn, sort
|
#include <algorithm> // Para __sort_fn, sort
|
||||||
|
#include <array> // Para array
|
||||||
#include <functional> // Para identity
|
#include <functional> // Para identity
|
||||||
#include <iterator> // Para distance
|
#include <iterator> // Para distance
|
||||||
#include <ranges> // Para __find_if_fn, find_if
|
#include <ranges> // Para __find_if_fn, find_if
|
||||||
@@ -109,117 +110,41 @@ auto ManageHiScoreTable::loadFromFile(const std::string& file_path) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Table temp_table; // Tabla temporal para no corromper la actual si hay errores
|
// Validar header (magic number + version + table size)
|
||||||
bool success = true;
|
if (!validateMagicNumber(file, file_path)) {
|
||||||
|
|
||||||
// Validación 1: Verificar magic number "CCAE"
|
|
||||||
char magic[4];
|
|
||||||
if (SDL_ReadIO(file, magic, 4) != 4 || magic[0] != 'C' || magic[1] != 'C' || magic[2] != 'A' || magic[3] != 'E') {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid magic number in %s - file may be corrupted or old format", getFileName(file_path).c_str());
|
|
||||||
SDL_CloseIO(file);
|
SDL_CloseIO(file);
|
||||||
clear();
|
clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validación 2: Verificar versión del formato
|
if (!validateVersion(file, file_path)) {
|
||||||
int version = 0;
|
|
||||||
if (SDL_ReadIO(file, &version, sizeof(int)) != sizeof(int)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read version in %s", getFileName(file_path).c_str());
|
|
||||||
SDL_CloseIO(file);
|
SDL_CloseIO(file);
|
||||||
clear();
|
clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version != FILE_VERSION) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Unsupported file version %d in %s (expected %d)", version, getFileName(file_path).c_str(), FILE_VERSION);
|
|
||||||
SDL_CloseIO(file);
|
|
||||||
clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validación 3: Leer y validar tamaño de la tabla
|
|
||||||
int table_size = 0;
|
int table_size = 0;
|
||||||
if (SDL_ReadIO(file, &table_size, sizeof(int)) != sizeof(int)) {
|
if (!readTableSize(file, file_path, table_size)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read table size in %s", getFileName(file_path).c_str());
|
|
||||||
SDL_CloseIO(file);
|
SDL_CloseIO(file);
|
||||||
clear();
|
clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (table_size < 0 || table_size > MAX_TABLE_SIZE) {
|
// Leer todas las entradas
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid table size %d in %s (expected 0-%d)", table_size, getFileName(file_path).c_str(), MAX_TABLE_SIZE);
|
Table temp_table;
|
||||||
SDL_CloseIO(file);
|
bool success = true;
|
||||||
clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Leer cada entrada con validaciones
|
|
||||||
for (int i = 0; i < table_size; ++i) {
|
for (int i = 0; i < table_size; ++i) {
|
||||||
HiScoreEntry entry;
|
HiScoreEntry entry;
|
||||||
|
if (!readEntry(file, file_path, i, entry)) {
|
||||||
// Validación 4: Leer y validar puntuación
|
|
||||||
if (SDL_ReadIO(file, &entry.score, sizeof(int)) != sizeof(int)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read score for entry %d in %s", i, getFileName(file_path).c_str());
|
|
||||||
success = false;
|
success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.score < 0 || entry.score > MAX_SCORE) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid score %d for entry %d in %s", entry.score, i, getFileName(file_path).c_str());
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validación 5: Leer y validar tamaño del nombre
|
|
||||||
int name_size = 0;
|
|
||||||
if (SDL_ReadIO(file, &name_size, sizeof(int)) != sizeof(int)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read name size for entry %d in %s", i, getFileName(file_path).c_str());
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name_size < 0 || name_size > MAX_NAME_SIZE) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid name size %d for entry %d in %s", name_size, i, getFileName(file_path).c_str());
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Leer el nombre
|
|
||||||
std::vector<char> name_buffer(name_size + 1);
|
|
||||||
if (SDL_ReadIO(file, name_buffer.data(), name_size) != static_cast<size_t>(name_size)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read name for entry %d in %s", i, getFileName(file_path).c_str());
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
name_buffer[name_size] = '\0';
|
|
||||||
entry.name = std::string(name_buffer.data());
|
|
||||||
|
|
||||||
// Validación 6: Leer one_credit_complete
|
|
||||||
int occ_value = 0;
|
|
||||||
if (SDL_ReadIO(file, &occ_value, sizeof(int)) != sizeof(int)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read one_credit_complete for entry %d in %s", i, getFileName(file_path).c_str());
|
|
||||||
success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
entry.one_credit_complete = (occ_value != 0);
|
|
||||||
|
|
||||||
temp_table.push_back(entry);
|
temp_table.push_back(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validación 7: Verificar checksum
|
// Verificar checksum
|
||||||
if (success) {
|
if (success) {
|
||||||
unsigned int stored_checksum = 0;
|
success = verifyChecksum(file, file_path, temp_table);
|
||||||
if (SDL_ReadIO(file, &stored_checksum, sizeof(unsigned int)) != sizeof(unsigned int)) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read checksum in %s", getFileName(file_path).c_str());
|
|
||||||
success = false;
|
|
||||||
} else {
|
|
||||||
unsigned int calculated_checksum = calculateChecksum(temp_table);
|
|
||||||
if (stored_checksum != calculated_checksum) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Checksum mismatch in %s (stored: 0x%08X, calculated: 0x%08X) - file is corrupted",
|
|
||||||
getFileName(file_path).c_str(), stored_checksum, calculated_checksum);
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_CloseIO(file);
|
SDL_CloseIO(file);
|
||||||
@@ -236,6 +161,104 @@ auto ManageHiScoreTable::loadFromFile(const std::string& file_path) -> bool {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Métodos auxiliares privados para loadFromFile
|
||||||
|
|
||||||
|
auto ManageHiScoreTable::validateMagicNumber(SDL_IOStream* file, const std::string& file_path) -> bool {
|
||||||
|
std::array<char, 4> magic;
|
||||||
|
if (SDL_ReadIO(file, magic.data(), 4) != 4 || magic[0] != 'C' || magic[1] != 'C' || magic[2] != 'A' || magic[3] != 'E') {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid magic number in %s - file may be corrupted or old format", getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ManageHiScoreTable::validateVersion(SDL_IOStream* file, const std::string& file_path) -> bool {
|
||||||
|
int version = 0;
|
||||||
|
if (SDL_ReadIO(file, &version, sizeof(int)) != sizeof(int)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read version in %s", getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version != FILE_VERSION) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Unsupported file version %d in %s (expected %d)", version, getFileName(file_path).c_str(), FILE_VERSION);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ManageHiScoreTable::readTableSize(SDL_IOStream* file, const std::string& file_path, int& table_size) -> bool {
|
||||||
|
if (SDL_ReadIO(file, &table_size, sizeof(int)) != sizeof(int)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read table size in %s", getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (table_size < 0 || table_size > MAX_TABLE_SIZE) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid table size %d in %s (expected 0-%d)", table_size, getFileName(file_path).c_str(), MAX_TABLE_SIZE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ManageHiScoreTable::readEntry(SDL_IOStream* file, const std::string& file_path, int index, HiScoreEntry& entry) -> bool {
|
||||||
|
// Leer y validar puntuación
|
||||||
|
if (SDL_ReadIO(file, &entry.score, sizeof(int)) != sizeof(int)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read score for entry %d in %s", index, getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.score < 0 || entry.score > MAX_SCORE) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid score %d for entry %d in %s", entry.score, index, getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leer y validar tamaño del nombre
|
||||||
|
int name_size = 0;
|
||||||
|
if (SDL_ReadIO(file, &name_size, sizeof(int)) != sizeof(int)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read name size for entry %d in %s", index, getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name_size < 0 || name_size > MAX_NAME_SIZE) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid name size %d for entry %d in %s", name_size, index, getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leer el nombre
|
||||||
|
std::vector<char> name_buffer(name_size + 1);
|
||||||
|
if (SDL_ReadIO(file, name_buffer.data(), name_size) != static_cast<size_t>(name_size)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read name for entry %d in %s", index, getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
name_buffer[name_size] = '\0';
|
||||||
|
entry.name = std::string(name_buffer.data());
|
||||||
|
|
||||||
|
// Leer one_credit_complete
|
||||||
|
int occ_value = 0;
|
||||||
|
if (SDL_ReadIO(file, &occ_value, sizeof(int)) != sizeof(int)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read one_credit_complete for entry %d in %s", index, getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
entry.one_credit_complete = (occ_value != 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ManageHiScoreTable::verifyChecksum(SDL_IOStream* file, const std::string& file_path, const Table& temp_table) -> bool {
|
||||||
|
unsigned int stored_checksum = 0;
|
||||||
|
if (SDL_ReadIO(file, &stored_checksum, sizeof(unsigned int)) != sizeof(unsigned int)) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot read checksum in %s", getFileName(file_path).c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int calculated_checksum = calculateChecksum(temp_table);
|
||||||
|
if (stored_checksum != calculated_checksum) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Checksum mismatch in %s (stored: 0x%08X, calculated: 0x%08X) - file is corrupted",
|
||||||
|
getFileName(file_path).c_str(), stored_checksum, calculated_checksum);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Calcula checksum de la tabla
|
// Calcula checksum de la tabla
|
||||||
auto ManageHiScoreTable::calculateChecksum(const Table& table) -> unsigned int {
|
auto ManageHiScoreTable::calculateChecksum(const Table& table) -> unsigned int {
|
||||||
unsigned int checksum = 0x12345678; // Magic seed
|
unsigned int checksum = 0x12345678; // Magic seed
|
||||||
@@ -250,7 +273,7 @@ auto ManageHiScoreTable::calculateChecksum(const Table& table) -> unsigned int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Checksum de one_credit_complete
|
// Checksum de one_credit_complete
|
||||||
checksum = ((checksum << 5) + checksum) + (entry.one_credit_complete ? 1u : 0u);
|
checksum = ((checksum << 5) + checksum) + (entry.one_credit_complete ? 1U : 0U);
|
||||||
}
|
}
|
||||||
|
|
||||||
return checksum;
|
return checksum;
|
||||||
@@ -263,8 +286,8 @@ auto ManageHiScoreTable::saveToFile(const std::string& file_path) -> bool {
|
|||||||
|
|
||||||
if (file != nullptr) {
|
if (file != nullptr) {
|
||||||
// Escribe magic number "CCAE"
|
// Escribe magic number "CCAE"
|
||||||
const char magic[4] = {'C', 'C', 'A', 'E'};
|
constexpr std::array<char, 4> MAGIC = {'C', 'C', 'A', 'E'};
|
||||||
SDL_WriteIO(file, magic, 4);
|
SDL_WriteIO(file, MAGIC.data(), 4);
|
||||||
|
|
||||||
// Escribe versión del formato
|
// Escribe versión del formato
|
||||||
int version = FILE_VERSION;
|
int version = FILE_VERSION;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h> // Para SDL_IOStream
|
||||||
|
|
||||||
#include <string> // Para std::string
|
#include <string> // Para std::string
|
||||||
#include <vector> // Para std::vector
|
#include <vector> // Para std::vector
|
||||||
|
|
||||||
@@ -45,6 +47,13 @@ class ManageHiScoreTable {
|
|||||||
Table& table_; // Referencia a la tabla con los records
|
Table& table_; // Referencia a la tabla con los records
|
||||||
|
|
||||||
// --- Métodos privados ---
|
// --- Métodos privados ---
|
||||||
void sort(); // Ordena la tabla
|
void sort(); // Ordena la tabla
|
||||||
static auto calculateChecksum(const Table& table) -> unsigned int; // Calcula checksum de la tabla
|
static auto calculateChecksum(const Table& table) -> unsigned int; // Calcula checksum de la tabla
|
||||||
|
|
||||||
|
// Métodos auxiliares para loadFromFile
|
||||||
|
static auto validateMagicNumber(SDL_IOStream* file, const std::string& file_path) -> bool;
|
||||||
|
static auto validateVersion(SDL_IOStream* file, const std::string& file_path) -> bool;
|
||||||
|
static auto readTableSize(SDL_IOStream* file, const std::string& file_path, int& table_size) -> bool;
|
||||||
|
static auto readEntry(SDL_IOStream* file, const std::string& file_path, int index, HiScoreEntry& entry) -> bool;
|
||||||
|
static auto verifyChecksum(SDL_IOStream* file, const std::string& file_path, const Table& temp_table) -> bool;
|
||||||
};
|
};
|
||||||
@@ -55,62 +55,70 @@ void PathSprite::render() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determina el tipo de centrado basado en el tipo de path
|
||||||
|
auto PathSprite::determineCenteringType(const Path& path, bool centered) -> PathCentered {
|
||||||
|
if (!centered) {
|
||||||
|
return PathCentered::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.is_point_path) {
|
||||||
|
// Lógica de centrado para paths por PUNTOS
|
||||||
|
if (!path.spots.empty()) {
|
||||||
|
// Si X es constante, es un path Vertical, centramos en X
|
||||||
|
return (path.spots.back().x == path.spots.front().x) ? PathCentered::ON_X : PathCentered::ON_Y;
|
||||||
|
}
|
||||||
|
return PathCentered::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lógica de centrado para paths GENERADOS
|
||||||
|
// Si el tipo es Vertical, centramos en X
|
||||||
|
return (path.type == PathType::VERTICAL) ? PathCentered::ON_X : PathCentered::ON_Y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aplica centrado en el eje X (para paths verticales)
|
||||||
|
void PathSprite::centerPathOnX(Path& path, float offset) {
|
||||||
|
if (path.is_point_path) {
|
||||||
|
const float X_BASE = !path.spots.empty() ? path.spots.front().x : 0.0F;
|
||||||
|
const float X = X_BASE - offset;
|
||||||
|
for (auto& spot : path.spots) {
|
||||||
|
spot.x = X;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Es un path generado, ajustamos la posición fija (que es X)
|
||||||
|
path.fixed_pos -= offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aplica centrado en el eje Y (para paths horizontales)
|
||||||
|
void PathSprite::centerPathOnY(Path& path, float offset) {
|
||||||
|
if (path.is_point_path) {
|
||||||
|
const float Y_BASE = !path.spots.empty() ? path.spots.front().y : 0.0F;
|
||||||
|
const float Y = Y_BASE - offset;
|
||||||
|
for (auto& spot : path.spots) {
|
||||||
|
spot.y = Y;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Es un path generado, ajustamos la posición fija (que es Y)
|
||||||
|
path.fixed_pos -= offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Añade un recorrido
|
// Añade un recorrido
|
||||||
void PathSprite::addPath(Path path, bool centered) {
|
void PathSprite::addPath(Path path, bool centered) {
|
||||||
PathCentered path_centered = PathCentered::NONE;
|
PathCentered path_centered = determineCenteringType(path, centered);
|
||||||
|
|
||||||
if (centered) {
|
|
||||||
if (path.is_point_path) {
|
|
||||||
// Lógica de centrado para paths por PUNTOS (como antes)
|
|
||||||
if (!path.spots.empty()) {
|
|
||||||
// Si X es constante, es un path Vertical, centramos en X
|
|
||||||
path_centered = (path.spots.back().x == path.spots.front().x) ? PathCentered::ON_X : PathCentered::ON_Y;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Lógica de centrado para paths GENERADOS (por duración)
|
|
||||||
// Si el tipo es Vertical, centramos en X
|
|
||||||
path_centered = (path.type == PathType::VERTICAL) ? PathCentered::ON_X : PathCentered::ON_Y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (path_centered) {
|
switch (path_centered) {
|
||||||
case PathCentered::ON_X: {
|
case PathCentered::ON_X:
|
||||||
// Centrar en el eje X (para paths Verticales)
|
centerPathOnX(path, pos_.w / 2.0F);
|
||||||
const float X_OFFSET = pos_.w / 2.0F; // Asume que pos_.w está inicializado por el constructor de Sprite
|
|
||||||
if (path.is_point_path) {
|
|
||||||
const float X_BASE = !path.spots.empty() ? path.spots.front().x : 0.0F;
|
|
||||||
const float X = X_BASE - X_OFFSET;
|
|
||||||
for (auto& spot : path.spots) {
|
|
||||||
spot.x = X;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Es un path generado, ajustamos la posición fija (que es X)
|
|
||||||
path.fixed_pos -= X_OFFSET;
|
|
||||||
}
|
|
||||||
paths_.emplace_back(std::move(path)); // Usamos std::move
|
|
||||||
break;
|
break;
|
||||||
}
|
case PathCentered::ON_Y:
|
||||||
case PathCentered::ON_Y: {
|
centerPathOnY(path, pos_.h / 2.0F);
|
||||||
// Centrar en el eje Y (para paths Horizontales)
|
|
||||||
const float Y_OFFSET = pos_.h / 2.0F; // Asume que pos_.h está inicializado
|
|
||||||
if (path.is_point_path) {
|
|
||||||
const float Y_BASE = !path.spots.empty() ? path.spots.front().y : 0.0F;
|
|
||||||
const float Y = Y_BASE - Y_OFFSET;
|
|
||||||
for (auto& spot : path.spots) {
|
|
||||||
spot.y = Y;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Es un path generado, ajustamos la posición fija (que es Y)
|
|
||||||
path.fixed_pos -= Y_OFFSET;
|
|
||||||
}
|
|
||||||
paths_.emplace_back(std::move(path)); // Usamos std::move
|
|
||||||
break;
|
break;
|
||||||
}
|
case PathCentered::NONE:
|
||||||
default:
|
|
||||||
// Sin centrado
|
|
||||||
paths_.emplace_back(std::move(path)); // Usamos std::move
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
paths_.emplace_back(std::move(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Añade un recorrido generado (en segundos)
|
// Añade un recorrido generado (en segundos)
|
||||||
|
|||||||
@@ -93,4 +93,9 @@ class PathSprite : public Sprite {
|
|||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void moveThroughCurrentPath(float delta_time); // Coloca el sprite en los diferentes puntos del recorrido
|
void moveThroughCurrentPath(float delta_time); // Coloca el sprite en los diferentes puntos del recorrido
|
||||||
void goToNextPathOrDie(); // Cambia de recorrido o finaliza
|
void goToNextPathOrDie(); // Cambia de recorrido o finaliza
|
||||||
|
|
||||||
|
// --- Métodos auxiliares para addPath ---
|
||||||
|
[[nodiscard]] static auto determineCenteringType(const Path& path, bool centered) -> PathCentered; // Determina el tipo de centrado
|
||||||
|
static void centerPathOnX(Path& path, float offset); // Aplica centrado en el eje X
|
||||||
|
static void centerPathOnY(Path& path, float offset); // Aplica centrado en el eje Y
|
||||||
};
|
};
|
||||||
@@ -124,62 +124,84 @@ void Player::setInputPlaying(Input::Action action) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gestiona la adición de un carácter o la confirmación del nombre.
|
||||||
|
void Player::handleNameCharacterAddition() {
|
||||||
|
if (enter_name_->endCharSelected()) {
|
||||||
|
confirmNameEntry();
|
||||||
|
} else {
|
||||||
|
enter_name_->addCharacter();
|
||||||
|
playSound("service_menu_select.wav");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gestiona la eliminación del último carácter.
|
||||||
|
void Player::handleNameCharacterRemoval() {
|
||||||
|
if (!enter_name_->nameIsEmpty()) {
|
||||||
|
enter_name_->removeLastCharacter();
|
||||||
|
playSound("service_menu_back.wav");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gestiona el movimiento del cursor de selección de letras (izquierda/derecha).
|
||||||
|
void Player::handleNameSelectionMove(Input::Action action) {
|
||||||
|
if (isShowingName() || enter_name_->nameIsFull()) {
|
||||||
|
return; // No hacer nada si se muestra el nombre o si está lleno
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cooldown_->tryConsumeOnHeld()) {
|
||||||
|
if (action == Input::Action::RIGHT) {
|
||||||
|
enter_name_->incIndex();
|
||||||
|
} else {
|
||||||
|
enter_name_->decIndex();
|
||||||
|
}
|
||||||
|
playSound("service_menu_move.wav");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirma el nombre introducido y cambia el estado del jugador.
|
||||||
|
void Player::confirmNameEntry() {
|
||||||
|
last_enter_name_ = getRecordName();
|
||||||
|
setPlayingState(Player::State::SHOWING_NAME);
|
||||||
|
playSound("name_input_accept.wav");
|
||||||
|
}
|
||||||
|
|
||||||
// Procesa inputs para cuando está introduciendo el nombre
|
// Procesa inputs para cuando está introduciendo el nombre
|
||||||
void Player::setInputEnteringName(Input::Action action) {
|
void Player::setInputEnteringName(Input::Action action) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case Input::Action::FIRE_LEFT: // Añade una letra
|
case Input::Action::FIRE_LEFT:
|
||||||
if (isShowingName()) {
|
if (isShowingName()) {
|
||||||
passShowingName();
|
passShowingName();
|
||||||
} else {
|
} else {
|
||||||
if (enter_name_->endCharSelected()) {
|
handleNameCharacterAddition();
|
||||||
last_enter_name_ = getRecordName();
|
|
||||||
setPlayingState(Player::State::SHOWING_NAME);
|
|
||||||
playSound("name_input_accept.wav");
|
|
||||||
} else {
|
|
||||||
enter_name_->addCharacter();
|
|
||||||
playSound("service_menu_select.wav");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Input::Action::FIRE_CENTER: // Borra una letra
|
|
||||||
|
case Input::Action::FIRE_CENTER:
|
||||||
if (isShowingName()) {
|
if (isShowingName()) {
|
||||||
passShowingName();
|
passShowingName();
|
||||||
} else {
|
} else {
|
||||||
if (!enter_name_->nameIsEmpty()) {
|
handleNameCharacterRemoval();
|
||||||
enter_name_->removeLastCharacter();
|
|
||||||
playSound("service_menu_back.wav");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Input::Action::RIGHT:
|
|
||||||
if (!isShowingName() && !enter_name_->nameIsFull()) {
|
|
||||||
if (cooldown_->tryConsumeOnHeld()) {
|
|
||||||
enter_name_->incIndex();
|
|
||||||
playSound("service_menu_move.wav");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Input::Action::LEFT:
|
|
||||||
if (!isShowingName() && !enter_name_->nameIsFull()) {
|
|
||||||
if (cooldown_->tryConsumeOnHeld()) {
|
|
||||||
enter_name_->decIndex();
|
|
||||||
playSound("service_menu_move.wav");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Input::Action::START:
|
case Input::Action::START:
|
||||||
if (isShowingName()) {
|
if (isShowingName()) {
|
||||||
passShowingName();
|
passShowingName();
|
||||||
} else {
|
} else {
|
||||||
last_enter_name_ = getRecordName();
|
confirmNameEntry();
|
||||||
setPlayingState(Player::State::SHOWING_NAME);
|
|
||||||
playSound("name_input_accept.wav");
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Input::Action::RIGHT:
|
||||||
|
case Input::Action::LEFT:
|
||||||
|
handleNameSelectionMove(action);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
cooldown_->onReleased();
|
cooldown_->onReleased();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
name_entry_idle_time_accumulator_ = 0.0F;
|
name_entry_idle_time_accumulator_ = 0.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -394,6 +394,12 @@ class Player {
|
|||||||
void handleWaitingMovement(float delta_time); // Animación del jugador saludando
|
void handleWaitingMovement(float delta_time); // Animación del jugador saludando
|
||||||
void updateWalkingStateForCredits(); // Actualiza estado de caminata en créditos
|
void updateWalkingStateForCredits(); // Actualiza estado de caminata en créditos
|
||||||
|
|
||||||
|
// --- Introducción de nombre ---
|
||||||
|
void handleNameCharacterAddition();
|
||||||
|
void handleNameCharacterRemoval();
|
||||||
|
void handleNameSelectionMove(Input::Action action);
|
||||||
|
void confirmNameEntry();
|
||||||
|
|
||||||
// --- Utilidades de animación ---
|
// --- Utilidades de animación ---
|
||||||
[[nodiscard]] auto computeAnimation() const -> std::pair<std::string, SDL_FlipMode>; // Calcula animación de movimiento y disparo
|
[[nodiscard]] auto computeAnimation() const -> std::pair<std::string, SDL_FlipMode>; // Calcula animación de movimiento y disparo
|
||||||
};
|
};
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -15,7 +16,7 @@ OpenGLShader::~OpenGLShader() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
bool OpenGLShader::initGLExtensions() {
|
auto OpenGLShader::initGLExtensions() -> bool {
|
||||||
glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader");
|
glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader");
|
||||||
glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource");
|
glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource");
|
||||||
glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader");
|
glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader");
|
||||||
@@ -42,13 +43,13 @@ bool OpenGLShader::initGLExtensions() {
|
|||||||
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)SDL_GL_GetProcAddress("glVertexAttribPointer");
|
glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)SDL_GL_GetProcAddress("glVertexAttribPointer");
|
||||||
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray");
|
glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)SDL_GL_GetProcAddress("glEnableVertexAttribArray");
|
||||||
|
|
||||||
return glCreateShader && glShaderSource && glCompileShader && glGetShaderiv &&
|
return (glCreateShader != nullptr) && (glShaderSource != nullptr) && (glCompileShader != nullptr) && (glGetShaderiv != nullptr) &&
|
||||||
glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram &&
|
(glGetShaderInfoLog != nullptr) && (glDeleteShader != nullptr) && (glAttachShader != nullptr) && (glCreateProgram != nullptr) &&
|
||||||
glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog &&
|
(glLinkProgram != nullptr) && (glValidateProgram != nullptr) && (glGetProgramiv != nullptr) && (glGetProgramInfoLog != nullptr) &&
|
||||||
glUseProgram && glDeleteProgram && glGetUniformLocation && glUniform2f &&
|
(glUseProgram != nullptr) && (glDeleteProgram != nullptr) && (glGetUniformLocation != nullptr) && (glUniform2f != nullptr) &&
|
||||||
glGenVertexArrays && glBindVertexArray && glDeleteVertexArrays &&
|
(glGenVertexArrays != nullptr) && (glBindVertexArray != nullptr) && (glDeleteVertexArrays != nullptr) &&
|
||||||
glGenBuffers && glBindBuffer && glBufferData && glDeleteBuffers &&
|
(glGenBuffers != nullptr) && (glBindBuffer != nullptr) && (glBufferData != nullptr) && (glDeleteBuffers != nullptr) &&
|
||||||
glVertexAttribPointer && glEnableVertexAttribArray;
|
(glVertexAttribPointer != nullptr) && (glEnableVertexAttribArray != nullptr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -62,7 +63,7 @@ void OpenGLShader::checkGLError(const char* operation) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint OpenGLShader::compileShader(const std::string& source, GLenum shader_type) {
|
auto OpenGLShader::compileShader(const std::string& source, GLenum shader_type) -> GLuint {
|
||||||
if (source.empty()) {
|
if (source.empty()) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"ERROR: El código fuente del shader está vacío");
|
"ERROR: El código fuente del shader está vacío");
|
||||||
@@ -76,8 +77,8 @@ GLuint OpenGLShader::compileShader(const std::string& source, GLenum shader_type
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* sources[1] = {source.c_str()};
|
std::array<const char*, 1> sources = {source.c_str()};
|
||||||
glShaderSource(shader_id, 1, sources, nullptr);
|
glShaderSource(shader_id, 1, sources.data(), nullptr);
|
||||||
checkGLError("glShaderSource");
|
checkGLError("glShaderSource");
|
||||||
|
|
||||||
glCompileShader(shader_id);
|
glCompileShader(shader_id);
|
||||||
@@ -105,7 +106,7 @@ GLuint OpenGLShader::compileShader(const std::string& source, GLenum shader_type
|
|||||||
return shader_id;
|
return shader_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint OpenGLShader::linkProgram(GLuint vertex_shader, GLuint fragment_shader) {
|
auto OpenGLShader::linkProgram(GLuint vertex_shader, GLuint fragment_shader) -> GLuint {
|
||||||
GLuint program = glCreateProgram();
|
GLuint program = glCreateProgram();
|
||||||
if (program == 0) {
|
if (program == 0) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
@@ -149,28 +150,28 @@ GLuint OpenGLShader::linkProgram(GLuint vertex_shader, GLuint fragment_shader) {
|
|||||||
void OpenGLShader::createQuadGeometry() {
|
void OpenGLShader::createQuadGeometry() {
|
||||||
// Datos del quad: posición (x, y) + coordenadas de textura (u, v)
|
// Datos del quad: posición (x, y) + coordenadas de textura (u, v)
|
||||||
// Formato: x, y, u, v
|
// Formato: x, y, u, v
|
||||||
float vertices[] = {
|
std::array<float, 16> vertices = {
|
||||||
// Posición // TexCoords
|
// Posición // TexCoords
|
||||||
-1.0f,
|
-1.0F,
|
||||||
-1.0f,
|
-1.0F,
|
||||||
0.0f,
|
0.0F,
|
||||||
0.0f, // Inferior izquierda
|
0.0F, // Inferior izquierda
|
||||||
1.0f,
|
1.0F,
|
||||||
-1.0f,
|
-1.0F,
|
||||||
1.0f,
|
1.0F,
|
||||||
0.0f, // Inferior derecha
|
0.0F, // Inferior derecha
|
||||||
1.0f,
|
1.0F,
|
||||||
1.0f,
|
1.0F,
|
||||||
1.0f,
|
1.0F,
|
||||||
1.0f, // Superior derecha
|
1.0F, // Superior derecha
|
||||||
-1.0f,
|
-1.0F,
|
||||||
1.0f,
|
1.0F,
|
||||||
0.0f,
|
0.0F,
|
||||||
1.0f // Superior izquierda
|
1.0F // Superior izquierda
|
||||||
};
|
};
|
||||||
|
|
||||||
// Índices para dibujar el quad con dos triángulos
|
// Índices para dibujar el quad con dos triángulos
|
||||||
unsigned int indices[] = {
|
std::array<unsigned int, 6> indices = {
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
2, // Primer triángulo
|
2, // Primer triángulo
|
||||||
@@ -187,22 +188,22 @@ void OpenGLShader::createQuadGeometry() {
|
|||||||
// Generar y configurar VBO
|
// Generar y configurar VBO
|
||||||
glGenBuffers(1, &vbo_);
|
glGenBuffers(1, &vbo_);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
glBindBuffer(GL_ARRAY_BUFFER, vbo_);
|
||||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices.data(), GL_STATIC_DRAW);
|
||||||
checkGLError("glBufferData(VBO)");
|
checkGLError("glBufferData(VBO)");
|
||||||
|
|
||||||
// Generar y configurar EBO
|
// Generar y configurar EBO
|
||||||
glGenBuffers(1, &ebo_);
|
glGenBuffers(1, &ebo_);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo_);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices.data(), GL_STATIC_DRAW);
|
||||||
checkGLError("glBufferData(EBO)");
|
checkGLError("glBufferData(EBO)");
|
||||||
|
|
||||||
// Atributo 0: Posición (2 floats)
|
// Atributo 0: Posición (2 floats)
|
||||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), nullptr);
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
checkGLError("glVertexAttribPointer(position)");
|
checkGLError("glVertexAttribPointer(position)");
|
||||||
|
|
||||||
// Atributo 1: Coordenadas de textura (2 floats)
|
// Atributo 1: Coordenadas de textura (2 floats)
|
||||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), static_cast<const void*>(static_cast<const char*>(nullptr) + 2 * sizeof(float)));
|
||||||
glEnableVertexAttribArray(1);
|
glEnableVertexAttribArray(1);
|
||||||
checkGLError("glVertexAttribPointer(texcoord)");
|
checkGLError("glVertexAttribPointer(texcoord)");
|
||||||
|
|
||||||
@@ -211,8 +212,10 @@ void OpenGLShader::createQuadGeometry() {
|
|||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint OpenGLShader::getTextureID(SDL_Texture* texture) {
|
auto OpenGLShader::getTextureID(SDL_Texture* texture) -> GLuint {
|
||||||
if (!texture) return 1;
|
if (texture == nullptr) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
|
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
|
||||||
GLuint texture_id = 0;
|
GLuint texture_id = 0;
|
||||||
@@ -237,15 +240,15 @@ GLuint OpenGLShader::getTextureID(SDL_Texture* texture) {
|
|||||||
return texture_id;
|
return texture_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLShader::init(SDL_Window* window,
|
auto OpenGLShader::init(SDL_Window* window,
|
||||||
SDL_Texture* texture,
|
SDL_Texture* texture,
|
||||||
const std::string& vertex_source,
|
const std::string& vertex_source,
|
||||||
const std::string& fragment_source) {
|
const std::string& fragment_source) -> bool {
|
||||||
window_ = window;
|
window_ = window;
|
||||||
back_buffer_ = texture;
|
back_buffer_ = texture;
|
||||||
renderer_ = SDL_GetRenderer(window);
|
renderer_ = SDL_GetRenderer(window);
|
||||||
|
|
||||||
if (!renderer_) {
|
if (renderer_ == nullptr) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"Error: No se pudo obtener el renderer");
|
"Error: No se pudo obtener el renderer");
|
||||||
return false;
|
return false;
|
||||||
@@ -276,10 +279,10 @@ bool OpenGLShader::init(SDL_Window* window,
|
|||||||
|
|
||||||
// Verificar que es OpenGL
|
// Verificar que es OpenGL
|
||||||
const char* renderer_name = SDL_GetRendererName(renderer_);
|
const char* renderer_name = SDL_GetRendererName(renderer_);
|
||||||
if (!renderer_name || strncmp(renderer_name, "opengl", 6) != 0) {
|
if ((renderer_name == nullptr) || strncmp(renderer_name, "opengl", 6) != 0) {
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"Renderer no es OpenGL: %s",
|
"Renderer no es OpenGL: %s",
|
||||||
renderer_name ? renderer_name : "unknown");
|
(renderer_name != nullptr) ? renderer_name : "unknown");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,8 +308,12 @@ bool OpenGLShader::init(SDL_Window* window,
|
|||||||
if (vertex_shader == 0 || fragment_shader == 0) {
|
if (vertex_shader == 0 || fragment_shader == 0) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"Error al compilar shaders");
|
"Error al compilar shaders");
|
||||||
if (vertex_shader != 0) glDeleteShader(vertex_shader);
|
if (vertex_shader != 0) {
|
||||||
if (fragment_shader != 0) glDeleteShader(fragment_shader);
|
glDeleteShader(vertex_shader);
|
||||||
|
}
|
||||||
|
if (fragment_shader != 0) {
|
||||||
|
glDeleteShader(fragment_shader);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,15 +377,16 @@ void OpenGLShader::render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obtener tamaño actual de ventana (puede haber cambiado)
|
// Obtener tamaño actual de ventana (puede haber cambiado)
|
||||||
int current_width, current_height;
|
int current_width;
|
||||||
|
int current_height;
|
||||||
SDL_GetWindowSize(window_, ¤t_width, ¤t_height);
|
SDL_GetWindowSize(window_, ¤t_width, ¤t_height);
|
||||||
|
|
||||||
// Guardar estados OpenGL
|
// Guardar estados OpenGL
|
||||||
GLint old_program;
|
GLint old_program;
|
||||||
glGetIntegerv(GL_CURRENT_PROGRAM, &old_program);
|
glGetIntegerv(GL_CURRENT_PROGRAM, &old_program);
|
||||||
|
|
||||||
GLint old_viewport[4];
|
std::array<GLint, 4> old_viewport{};
|
||||||
glGetIntegerv(GL_VIEWPORT, old_viewport);
|
glGetIntegerv(GL_VIEWPORT, old_viewport.data());
|
||||||
|
|
||||||
GLboolean was_texture_enabled = glIsEnabled(GL_TEXTURE_2D);
|
GLboolean was_texture_enabled = glIsEnabled(GL_TEXTURE_2D);
|
||||||
GLint old_texture;
|
GLint old_texture;
|
||||||
@@ -403,7 +411,8 @@ void OpenGLShader::render() {
|
|||||||
checkGLError("glUseProgram");
|
checkGLError("glUseProgram");
|
||||||
|
|
||||||
// Configurar viewport (obtener tamaño lógico de SDL)
|
// Configurar viewport (obtener tamaño lógico de SDL)
|
||||||
int logical_w, logical_h;
|
int logical_w;
|
||||||
|
int logical_h;
|
||||||
SDL_RendererLogicalPresentation mode;
|
SDL_RendererLogicalPresentation mode;
|
||||||
SDL_GetRenderLogicalPresentation(renderer_, &logical_w, &logical_h, &mode);
|
SDL_GetRenderLogicalPresentation(renderer_, &logical_w, &logical_h, &mode);
|
||||||
|
|
||||||
@@ -413,14 +422,16 @@ void OpenGLShader::render() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calcular viewport considerando aspect ratio
|
// Calcular viewport considerando aspect ratio
|
||||||
int viewport_x = 0, viewport_y = 0;
|
int viewport_x = 0;
|
||||||
int viewport_w = current_width, viewport_h = current_height;
|
int viewport_y = 0;
|
||||||
|
int viewport_w = current_width;
|
||||||
|
int viewport_h = current_height;
|
||||||
|
|
||||||
if (mode == SDL_LOGICAL_PRESENTATION_INTEGER_SCALE) {
|
if (mode == SDL_LOGICAL_PRESENTATION_INTEGER_SCALE) {
|
||||||
int scale_x = current_width / logical_w;
|
int scale_x = current_width / logical_w;
|
||||||
int scale_y = current_height / logical_h;
|
int scale_y = current_height / logical_h;
|
||||||
int scale = (scale_x < scale_y) ? scale_x : scale_y;
|
int scale = (scale_x < scale_y) ? scale_x : scale_y;
|
||||||
if (scale < 1) scale = 1;
|
scale = std::max(scale, 1);
|
||||||
|
|
||||||
viewport_w = logical_w * scale;
|
viewport_w = logical_w * scale;
|
||||||
viewport_h = logical_h * scale;
|
viewport_h = logical_h * scale;
|
||||||
@@ -444,7 +455,7 @@ void OpenGLShader::render() {
|
|||||||
|
|
||||||
// Dibujar quad usando VAO
|
// Dibujar quad usando VAO
|
||||||
glBindVertexArray(vao_);
|
glBindVertexArray(vao_);
|
||||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
|
||||||
checkGLError("glDrawElements");
|
checkGLError("glDrawElements");
|
||||||
|
|
||||||
// Presentar
|
// Presentar
|
||||||
@@ -453,7 +464,7 @@ void OpenGLShader::render() {
|
|||||||
// Restaurar estados OpenGL
|
// Restaurar estados OpenGL
|
||||||
glUseProgram(old_program);
|
glUseProgram(old_program);
|
||||||
glBindTexture(GL_TEXTURE_2D, old_texture);
|
glBindTexture(GL_TEXTURE_2D, old_texture);
|
||||||
if (!was_texture_enabled) {
|
if (was_texture_enabled == 0U) {
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
}
|
}
|
||||||
glBindVertexArray(old_vao);
|
glBindVertexArray(old_vao);
|
||||||
|
|||||||
@@ -23,24 +23,24 @@ class OpenGLShader : public ShaderBackend {
|
|||||||
OpenGLShader() = default;
|
OpenGLShader() = default;
|
||||||
~OpenGLShader() override;
|
~OpenGLShader() override;
|
||||||
|
|
||||||
bool init(SDL_Window* window,
|
auto init(SDL_Window* window,
|
||||||
SDL_Texture* texture,
|
SDL_Texture* texture,
|
||||||
const std::string& vertex_source,
|
const std::string& vertex_source,
|
||||||
const std::string& fragment_source) override;
|
const std::string& fragment_source) -> bool override;
|
||||||
|
|
||||||
void render() override;
|
void render() override;
|
||||||
void setTextureSize(float width, float height) override;
|
void setTextureSize(float width, float height) override;
|
||||||
void cleanup() override;
|
void cleanup() final;
|
||||||
bool isHardwareAccelerated() const override { return is_initialized_; }
|
[[nodiscard]] auto isHardwareAccelerated() const -> bool override { return is_initialized_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Funciones auxiliares
|
// Funciones auxiliares
|
||||||
bool initGLExtensions();
|
auto initGLExtensions() -> bool;
|
||||||
GLuint compileShader(const std::string& source, GLenum shader_type);
|
auto compileShader(const std::string& source, GLenum shader_type) -> GLuint;
|
||||||
GLuint linkProgram(GLuint vertex_shader, GLuint fragment_shader);
|
auto linkProgram(GLuint vertex_shader, GLuint fragment_shader) -> GLuint;
|
||||||
void createQuadGeometry();
|
void createQuadGeometry();
|
||||||
GLuint getTextureID(SDL_Texture* texture);
|
static auto getTextureID(SDL_Texture* texture) -> GLuint;
|
||||||
void checkGLError(const char* operation);
|
static void checkGLError(const char* operation);
|
||||||
|
|
||||||
// Estado SDL
|
// Estado SDL
|
||||||
SDL_Window* window_ = nullptr;
|
SDL_Window* window_ = nullptr;
|
||||||
@@ -59,8 +59,8 @@ class OpenGLShader : public ShaderBackend {
|
|||||||
// Tamaños
|
// Tamaños
|
||||||
int window_width_ = 0;
|
int window_width_ = 0;
|
||||||
int window_height_ = 0;
|
int window_height_ = 0;
|
||||||
float texture_width_ = 0.0f;
|
float texture_width_ = 0.0F;
|
||||||
float texture_height_ = 0.0f;
|
float texture_height_ = 0.0F;
|
||||||
|
|
||||||
// Estado
|
// Estado
|
||||||
bool is_initialized_ = false;
|
bool is_initialized_ = false;
|
||||||
|
|||||||
@@ -26,33 +26,16 @@
|
|||||||
struct JA_Music_t; // lines 11-11
|
struct JA_Music_t; // lines 11-11
|
||||||
struct JA_Sound_t; // lines 12-12
|
struct JA_Sound_t; // lines 12-12
|
||||||
|
|
||||||
// Helper para cargar archivos de audio desde pack o filesystem
|
// Helper para cargar archivos de audio desde pack o filesystem en memoria
|
||||||
namespace {
|
namespace {
|
||||||
auto createTempAudioFile(const std::string& file_path, std::vector<std::string>& temp_files_tracker) -> std::string {
|
struct AudioData {
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
std::string filepath;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto loadAudioData(const std::string& file_path) -> AudioData {
|
||||||
auto resource_data = ResourceHelper::loadFile(file_path);
|
auto resource_data = ResourceHelper::loadFile(file_path);
|
||||||
if (!resource_data.empty()) {
|
return AudioData{.data = std::move(resource_data), .filepath = file_path};
|
||||||
// Crear archivo temporal
|
|
||||||
std::string temp_dir;
|
|
||||||
#ifdef _WIN32
|
|
||||||
temp_dir = std::getenv("TEMP") ? std::getenv("TEMP") : "C:\\temp";
|
|
||||||
#else
|
|
||||||
temp_dir = "/tmp";
|
|
||||||
#endif
|
|
||||||
std::string temp_path = temp_dir + "/ccae_audio_" + std::to_string(std::hash<std::string>{}(file_path));
|
|
||||||
std::ofstream temp_file(temp_path, std::ios::binary);
|
|
||||||
if (!temp_file) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Cannot create temp file %s", temp_path.c_str());
|
|
||||||
return file_path;
|
|
||||||
}
|
|
||||||
temp_file.write(reinterpret_cast<const char*>(resource_data.data()), resource_data.size());
|
|
||||||
temp_file.close();
|
|
||||||
|
|
||||||
// Agregar a la lista de archivos temporales para limpieza posterior
|
|
||||||
temp_files_tracker.push_back(temp_path);
|
|
||||||
|
|
||||||
return temp_path;
|
|
||||||
}
|
|
||||||
return file_path; // Usar ruta original si no está en pack
|
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@@ -92,7 +75,6 @@ Resource::Resource(LoadingMode mode)
|
|||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
Resource::~Resource() {
|
Resource::~Resource() {
|
||||||
cleanupTempAudioFiles();
|
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,8 +317,12 @@ auto Resource::loadSoundLazy(const std::string& name) -> JA_Sound_t* {
|
|||||||
auto sound_list = Asset::get()->getListByType(Asset::Type::SOUND);
|
auto sound_list = Asset::get()->getListByType(Asset::Type::SOUND);
|
||||||
for (const auto& file : sound_list) {
|
for (const auto& file : sound_list) {
|
||||||
if (getFileName(file) == name) {
|
if (getFileName(file) == name) {
|
||||||
std::string audio_path = createTempAudioFile(file, Resource::get()->temp_audio_files_);
|
auto audio_data = loadAudioData(file);
|
||||||
return JA_LoadSound(audio_path.c_str());
|
if (!audio_data.data.empty()) {
|
||||||
|
return JA_LoadSound(audio_data.data.data(), audio_data.data.size());
|
||||||
|
}
|
||||||
|
// Fallback a cargar desde disco si no está en pack
|
||||||
|
return JA_LoadSound(file.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -347,8 +333,12 @@ auto Resource::loadMusicLazy(const std::string& name) -> JA_Music_t* {
|
|||||||
auto music_list = Asset::get()->getListByType(Asset::Type::MUSIC);
|
auto music_list = Asset::get()->getListByType(Asset::Type::MUSIC);
|
||||||
for (const auto& file : music_list) {
|
for (const auto& file : music_list) {
|
||||||
if (getFileName(file) == name) {
|
if (getFileName(file) == name) {
|
||||||
std::string audio_path = createTempAudioFile(file, Resource::get()->temp_audio_files_);
|
auto audio_data = loadAudioData(file);
|
||||||
return JA_LoadMusic(audio_path.c_str());
|
if (!audio_data.data.empty()) {
|
||||||
|
return JA_LoadMusic(audio_data.data.data(), audio_data.data.size());
|
||||||
|
}
|
||||||
|
// Fallback a cargar desde disco si no está en pack
|
||||||
|
return JA_LoadMusic(file.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -484,8 +474,15 @@ void Resource::loadSounds() {
|
|||||||
for (const auto& l : list) {
|
for (const auto& l : list) {
|
||||||
auto name = getFileName(l);
|
auto name = getFileName(l);
|
||||||
updateLoadingProgress(name);
|
updateLoadingProgress(name);
|
||||||
std::string audio_path = createTempAudioFile(l, temp_audio_files_);
|
auto audio_data = loadAudioData(l);
|
||||||
sounds_.emplace_back(name, JA_LoadSound(audio_path.c_str()));
|
JA_Sound_t* sound = nullptr;
|
||||||
|
if (!audio_data.data.empty()) {
|
||||||
|
sound = JA_LoadSound(audio_data.data.data(), audio_data.data.size());
|
||||||
|
} else {
|
||||||
|
// Fallback a cargar desde disco si no está en pack
|
||||||
|
sound = JA_LoadSound(l.c_str());
|
||||||
|
}
|
||||||
|
sounds_.emplace_back(name, sound);
|
||||||
Logger::dots("Sound : ", name, "[ LOADED ]");
|
Logger::dots("Sound : ", name, "[ LOADED ]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -500,8 +497,15 @@ void Resource::loadMusics() {
|
|||||||
for (const auto& l : list) {
|
for (const auto& l : list) {
|
||||||
auto name = getFileName(l);
|
auto name = getFileName(l);
|
||||||
updateLoadingProgress(name);
|
updateLoadingProgress(name);
|
||||||
std::string audio_path = createTempAudioFile(l, temp_audio_files_);
|
auto audio_data = loadAudioData(l);
|
||||||
musics_.emplace_back(name, JA_LoadMusic(audio_path.c_str()));
|
JA_Music_t* music = nullptr;
|
||||||
|
if (!audio_data.data.empty()) {
|
||||||
|
music = JA_LoadMusic(audio_data.data.data(), audio_data.data.size());
|
||||||
|
} else {
|
||||||
|
// Fallback a cargar desde disco si no está en pack
|
||||||
|
music = JA_LoadMusic(l.c_str());
|
||||||
|
}
|
||||||
|
musics_.emplace_back(name, music);
|
||||||
Logger::dots("Music : ", name, "[ LOADED ]");
|
Logger::dots("Music : ", name, "[ LOADED ]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -901,18 +905,3 @@ void Resource::updateLoadingProgress(std::string name) {
|
|||||||
void Resource::updateProgressBar() {
|
void Resource::updateProgressBar() {
|
||||||
loading_full_rect_.w = loading_wired_rect_.w * loading_count_.getPercentage();
|
loading_full_rect_.w = loading_wired_rect_.w * loading_count_.getPercentage();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limpia archivos temporales de audio
|
|
||||||
void Resource::cleanupTempAudioFiles() {
|
|
||||||
for (const auto& temp_path : temp_audio_files_) {
|
|
||||||
try {
|
|
||||||
if (std::filesystem::exists(temp_path)) {
|
|
||||||
std::filesystem::remove(temp_path);
|
|
||||||
// SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Removed temp audio file: %s", temp_path.c_str());
|
|
||||||
}
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to remove temp audio file %s: %s", temp_path.c_str(), e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
temp_audio_files_.clear();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -146,9 +146,6 @@ class Resource {
|
|||||||
SDL_FRect loading_wired_rect_;
|
SDL_FRect loading_wired_rect_;
|
||||||
SDL_FRect loading_full_rect_;
|
SDL_FRect loading_full_rect_;
|
||||||
|
|
||||||
// --- Archivos temporales ---
|
|
||||||
std::vector<std::string> temp_audio_files_; // Rutas de archivos temporales de audio para limpieza
|
|
||||||
|
|
||||||
// --- Métodos internos de carga y gestión ---
|
// --- Métodos internos de carga y gestión ---
|
||||||
void loadSounds(); // Carga los sonidos
|
void loadSounds(); // Carga los sonidos
|
||||||
void loadMusics(); // Carga las músicas
|
void loadMusics(); // Carga las músicas
|
||||||
@@ -167,7 +164,6 @@ class Resource {
|
|||||||
void load(); // Carga todos los recursos
|
void load(); // Carga todos los recursos
|
||||||
void clearSounds(); // Vacía el vector de sonidos
|
void clearSounds(); // Vacía el vector de sonidos
|
||||||
void clearMusics(); // Vacía el vector de músicas
|
void clearMusics(); // Vacía el vector de músicas
|
||||||
void cleanupTempAudioFiles(); // Limpia archivos temporales de audio
|
|
||||||
|
|
||||||
// --- Métodos para carga perezosa ---
|
// --- Métodos para carga perezosa ---
|
||||||
void initResourceLists(); // Inicializa las listas de recursos sin cargar el contenido
|
void initResourceLists(); // Inicializa las listas de recursos sin cargar el contenido
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
namespace ResourceHelper {
|
namespace ResourceHelper {
|
||||||
static bool resource_system_initialized = false;
|
static bool resource_system_initialized = false;
|
||||||
|
|
||||||
auto initializeResourceSystem(const std::string& pack_file) -> bool {
|
auto initializeResourceSystem(const std::string& pack_file, bool enable_fallback) -> bool {
|
||||||
auto& loader = ResourceLoader::getInstance();
|
auto& loader = ResourceLoader::getInstance();
|
||||||
resource_system_initialized = loader.initialize(pack_file, true);
|
resource_system_initialized = loader.initialize(pack_file, enable_fallback);
|
||||||
|
|
||||||
if (resource_system_initialized) {
|
if (resource_system_initialized) {
|
||||||
std::cout << "Resource system initialized with pack: " << pack_file << '\n';
|
std::cout << "Resource system initialized with pack: " << pack_file << '\n';
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
// Helper functions para integrar ResourceLoader con el sistema existente
|
// Helper functions para integrar ResourceLoader con el sistema existente
|
||||||
namespace ResourceHelper {
|
namespace ResourceHelper {
|
||||||
// Inicializa ResourceLoader (llamar al inicio del programa)
|
// Inicializa ResourceLoader (llamar al inicio del programa)
|
||||||
auto initializeResourceSystem(const std::string& pack_file = "resources.pack") -> bool;
|
auto initializeResourceSystem(const std::string& pack_file = "resources.pack", bool enable_fallback = true) -> bool;
|
||||||
|
|
||||||
// Cierra ResourceLoader
|
// Cierra ResourceLoader
|
||||||
void shutdownResourceSystem();
|
void shutdownResourceSystem();
|
||||||
|
|||||||
@@ -24,22 +24,22 @@ ResourceLoader::~ResourceLoader() {
|
|||||||
shutdown();
|
shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ResourceLoader::initialize(const std::string& packFile, bool enable_fallback) -> bool {
|
auto ResourceLoader::initialize(const std::string& pack_file, bool enable_fallback) -> bool {
|
||||||
shutdown();
|
shutdown();
|
||||||
|
|
||||||
fallback_to_files_ = enable_fallback;
|
fallback_to_files_ = enable_fallback;
|
||||||
pack_path_ = packFile;
|
pack_path_ = pack_file;
|
||||||
|
|
||||||
if (std::filesystem::exists(packFile)) {
|
if (std::filesystem::exists(pack_file)) {
|
||||||
resource_pack_ = new ResourcePack();
|
resource_pack_ = new ResourcePack();
|
||||||
if (resource_pack_->loadPack(packFile)) {
|
if (resource_pack_->loadPack(pack_file)) {
|
||||||
std::cout << "Resource pack loaded successfully: " << packFile << '\n';
|
std::cout << "Resource pack loaded successfully: " << pack_file << '\n';
|
||||||
std::cout << "Resources available: " << resource_pack_->getResourceCount() << '\n';
|
std::cout << "Resources available: " << resource_pack_->getResourceCount() << '\n';
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
delete resource_pack_;
|
delete resource_pack_;
|
||||||
resource_pack_ = nullptr;
|
resource_pack_ = nullptr;
|
||||||
std::cerr << "Failed to load resource pack: " << packFile << std::endl;
|
std::cerr << "Failed to load resource pack: " << pack_file << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fallback_to_files_) {
|
if (fallback_to_files_) {
|
||||||
@@ -47,7 +47,7 @@ auto ResourceLoader::initialize(const std::string& packFile, bool enable_fallbac
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cerr << "Resource pack not found and fallback disabled: " << packFile << '\n';
|
std::cerr << "Resource pack not found and fallback disabled: " << pack_file << '\n';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,6 @@ class ResourceLoader {
|
|||||||
[[nodiscard]] auto getAvailableResources() const -> std::vector<std::string>;
|
[[nodiscard]] auto getAvailableResources() const -> std::vector<std::string>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto loadFromFile(const std::string& filename) -> std::vector<uint8_t>;
|
static auto loadFromFile(const std::string& filename) -> std::vector<uint8_t>;
|
||||||
static auto getDataPath(const std::string& filename) -> std::string;
|
static auto getDataPath(const std::string& filename) -> std::string;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "resource_pack.hpp"
|
#include "resource_pack.hpp"
|
||||||
|
|
||||||
#include <algorithm> // Para replace
|
#include <algorithm> // Para replace
|
||||||
|
#include <array> // Para array
|
||||||
#include <filesystem> // Para path, recursive_directory_iterator, directory_entry, exists, relative
|
#include <filesystem> // Para path, recursive_directory_iterator, directory_entry, exists, relative
|
||||||
#include <fstream> // Para basic_ifstream, basic_ostream, basic_ofstream, operator<<, basic_ios, basic_istream::read, basic_ostream::write, endl, ios, basic_istream, ifstream, operator|, basic_istream::seekg, basic_istream::tellg, ofstream, streamsize
|
#include <fstream> // Para basic_ifstream, basic_ostream, basic_ofstream, operator<<, basic_ios, basic_istream::read, basic_ostream::write, endl, ios, basic_istream, ifstream, operator|, basic_istream::seekg, basic_istream::tellg, ofstream, streamsize
|
||||||
#include <iostream> // Para cerr
|
#include <iostream> // Para cerr
|
||||||
@@ -44,9 +45,9 @@ auto ResourcePack::loadPack(const std::string& pack_file) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
char header[4];
|
std::array<char, 4> header;
|
||||||
file.read(header, 4);
|
file.read(header.data(), 4);
|
||||||
if (std::string(header, 4) != "CCAE") {
|
if (std::string(header.data(), 4) != "CCAE") {
|
||||||
std::cerr << "Error: Invalid pack file format" << '\n';
|
std::cerr << "Error: Invalid pack file format" << '\n';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class ResourcePack {
|
|||||||
|
|
||||||
static auto calculateChecksum(const std::vector<uint8_t>& data) -> uint32_t;
|
static auto calculateChecksum(const std::vector<uint8_t>& data) -> uint32_t;
|
||||||
static void encryptData(std::vector<uint8_t>& data, const std::string& key);
|
static void encryptData(std::vector<uint8_t>& data, const std::string& key);
|
||||||
void decryptData(std::vector<uint8_t>& data, const std::string& key);
|
static void decryptData(std::vector<uint8_t>& data, const std::string& key);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ResourcePack();
|
ResourcePack();
|
||||||
|
|||||||
@@ -107,27 +107,30 @@ void Scoreboard::setCarouselAnimation(Id id, int selected_index, EnterName* ente
|
|||||||
|
|
||||||
// ===== Inicialización (primera vez) =====
|
// ===== Inicialización (primera vez) =====
|
||||||
if (carousel_prev_index_.at(idx) == -1) {
|
if (carousel_prev_index_.at(idx) == -1) {
|
||||||
carousel_position_.at(idx) = static_cast<float>(selected_index);
|
carousel_position_.at(idx) = static_cast<float>(selected_index);
|
||||||
carousel_target_.at(idx) = static_cast<float>(selected_index);
|
carousel_target_.at(idx) = static_cast<float>(selected_index);
|
||||||
carousel_prev_index_.at(idx) = selected_index;
|
carousel_prev_index_.at(idx) = selected_index;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int prev_index = carousel_prev_index_.at(idx);
|
int prev_index = carousel_prev_index_.at(idx);
|
||||||
if (selected_index == prev_index) {
|
if (selected_index == prev_index) {
|
||||||
return; // nada que hacer
|
return; // nada que hacer
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== Bloquear si aún animando =====
|
// ===== Bloquear si aún animando =====
|
||||||
if (std::abs(carousel_position_.at(idx) - carousel_target_.at(idx)) > 0.01f) {
|
if (std::abs(carousel_position_.at(idx) - carousel_target_.at(idx)) > 0.01F) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== Calcular salto circular =====
|
// ===== Calcular salto circular =====
|
||||||
int delta = selected_index - prev_index;
|
int delta = selected_index - prev_index;
|
||||||
const int LIST_SIZE = static_cast<int>(enter_name_ptr->getCharacterList().size());
|
const int LIST_SIZE = static_cast<int>(enter_name_ptr->getCharacterList().size());
|
||||||
if (delta > LIST_SIZE / 2) delta -= LIST_SIZE;
|
if (delta > LIST_SIZE / 2) {
|
||||||
else if (delta < -LIST_SIZE / 2) delta += LIST_SIZE;
|
delta -= LIST_SIZE;
|
||||||
|
} else if (delta < -LIST_SIZE / 2) {
|
||||||
|
delta += LIST_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
// ===== Alinear posición actual antes de moverse =====
|
// ===== Alinear posición actual antes de moverse =====
|
||||||
carousel_position_.at(idx) = std::round(carousel_position_.at(idx));
|
carousel_position_.at(idx) = std::round(carousel_position_.at(idx));
|
||||||
@@ -141,8 +144,8 @@ void Scoreboard::setCarouselAnimation(Id id, int selected_index, EnterName* ente
|
|||||||
} else {
|
} else {
|
||||||
// Movimiento largo → animado pero limitado en tiempo
|
// Movimiento largo → animado pero limitado en tiempo
|
||||||
// Normalizamos el salto para que visualmente tarde como mucho el doble
|
// Normalizamos el salto para que visualmente tarde como mucho el doble
|
||||||
const float MAX_DURATION_FACTOR = 2.0f; // máximo 2x la duración de una letra
|
const float MAX_DURATION_FACTOR = 2.0F; // máximo 2x la duración de una letra
|
||||||
const float SPEED_SCALE = std::min(1.0f, MAX_DURATION_FACTOR / static_cast<float>(ABS_DELTA));
|
const float SPEED_SCALE = std::min(1.0F, MAX_DURATION_FACTOR / static_cast<float>(ABS_DELTA));
|
||||||
|
|
||||||
// Guardamos el destino real
|
// Guardamos el destino real
|
||||||
float target = std::round(carousel_position_.at(idx)) + static_cast<float>(delta);
|
float target = std::round(carousel_position_.at(idx)) + static_cast<float>(delta);
|
||||||
@@ -257,7 +260,7 @@ void Scoreboard::updateCarouselAnimation(float delta_time) {
|
|||||||
} else {
|
} else {
|
||||||
// Forzar al target exacto cuando estamos muy cerca
|
// Forzar al target exacto cuando estamos muy cerca
|
||||||
carousel_position_.at(i) = carousel_target_.at(i);
|
carousel_position_.at(i) = carousel_target_.at(i);
|
||||||
carousel_speed_scale_.at(i) = 1.0f; // restaurar velocidad normal
|
carousel_speed_scale_.at(i) = 1.0F; // restaurar velocidad normal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,7 +305,7 @@ void Scoreboard::updatePanelPulses(float delta_time) {
|
|||||||
// Desactivar el pulso si ha terminado
|
// Desactivar el pulso si ha terminado
|
||||||
if (pulse.elapsed_s >= pulse.duration_s) {
|
if (pulse.elapsed_s >= pulse.duration_s) {
|
||||||
pulse.active = false;
|
pulse.active = false;
|
||||||
pulse.elapsed_s = 0.0f;
|
pulse.elapsed_s = 0.0F;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -311,7 +314,7 @@ void Scoreboard::updatePanelPulses(float delta_time) {
|
|||||||
void Scoreboard::triggerPanelPulse(Id id, float duration_s) {
|
void Scoreboard::triggerPanelPulse(Id id, float duration_s) {
|
||||||
auto idx = static_cast<size_t>(id);
|
auto idx = static_cast<size_t>(id);
|
||||||
panel_pulse_.at(idx).active = true;
|
panel_pulse_.at(idx).active = true;
|
||||||
panel_pulse_.at(idx).elapsed_s = 0.0f;
|
panel_pulse_.at(idx).elapsed_s = 0.0F;
|
||||||
panel_pulse_.at(idx).duration_s = duration_s;
|
panel_pulse_.at(idx).duration_s = duration_s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +384,7 @@ void Scoreboard::fillPanelTextures() {
|
|||||||
|
|
||||||
// Interpolar entre color base y color aclarado
|
// Interpolar entre color base y color aclarado
|
||||||
Color target_color = color_.LIGHTEN(PANEL_PULSE_LIGHTEN_AMOUNT);
|
Color target_color = color_.LIGHTEN(PANEL_PULSE_LIGHTEN_AMOUNT);
|
||||||
//Color target_color = color_.INVERSE();
|
// Color target_color = color_.INVERSE();
|
||||||
background_color = color_.LERP(target_color, pulse_intensity);
|
background_color = color_.LERP(target_color, pulse_intensity);
|
||||||
background_color.a = 255; // Opaco durante el pulso
|
background_color.a = 255; // Opaco durante el pulso
|
||||||
}
|
}
|
||||||
@@ -737,7 +740,7 @@ void Scoreboard::renderCarousel(size_t panel_index, int center_x, int y) {
|
|||||||
constexpr int HALF_VISIBLE = CAROUSEL_VISIBLE_LETTERS / 2; // 4 letras a cada lado
|
constexpr int HALF_VISIBLE = CAROUSEL_VISIBLE_LETTERS / 2; // 4 letras a cada lado
|
||||||
|
|
||||||
// Posición flotante actual del carrusel (índice en la lista de caracteres)
|
// Posición flotante actual del carrusel (índice en la lista de caracteres)
|
||||||
float CAROUSEL_POS = carousel_position_.at(panel_index);
|
float carousel_pos = carousel_position_.at(panel_index);
|
||||||
const int CHAR_LIST_SIZE = static_cast<int>(char_list.size());
|
const int CHAR_LIST_SIZE = static_cast<int>(char_list.size());
|
||||||
|
|
||||||
// Calcular ancho promedio de una letra (asumimos ancho uniforme)
|
// Calcular ancho promedio de una letra (asumimos ancho uniforme)
|
||||||
@@ -745,17 +748,17 @@ void Scoreboard::renderCarousel(size_t panel_index, int center_x, int y) {
|
|||||||
const int CHAR_STEP = AVG_CHAR_WIDTH + EXTRA_SPACING;
|
const int CHAR_STEP = AVG_CHAR_WIDTH + EXTRA_SPACING;
|
||||||
|
|
||||||
// --- Corrección visual de residuales flotantes (evita “baile”) ---
|
// --- Corrección visual de residuales flotantes (evita “baile”) ---
|
||||||
float frac = CAROUSEL_POS - std::floor(CAROUSEL_POS);
|
float frac = carousel_pos - std::floor(carousel_pos);
|
||||||
if (frac > 0.999f || frac < 0.001f) {
|
if (frac > 0.999F || frac < 0.001F) {
|
||||||
CAROUSEL_POS = std::round(CAROUSEL_POS);
|
carousel_pos = std::round(carousel_pos);
|
||||||
frac = 0.0f;
|
frac = 0.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float FRACTIONAL_OFFSET = frac;
|
const float FRACTIONAL_OFFSET = frac;
|
||||||
const int PIXEL_OFFSET = static_cast<int>(FRACTIONAL_OFFSET * CHAR_STEP + 0.5f);
|
const int PIXEL_OFFSET = static_cast<int>((FRACTIONAL_OFFSET * CHAR_STEP) + 0.5F);
|
||||||
|
|
||||||
// Índice base en la lista de caracteres (posición central)
|
// Índice base en la lista de caracteres (posición central)
|
||||||
const int BASE_INDEX = static_cast<int>(std::floor(CAROUSEL_POS));
|
const int BASE_INDEX = static_cast<int>(std::floor(carousel_pos));
|
||||||
|
|
||||||
// Calcular posición X inicial (centrar las 9 letras visibles)
|
// Calcular posición X inicial (centrar las 9 letras visibles)
|
||||||
int start_x = center_x - (HALF_VISIBLE * CHAR_STEP) - (AVG_CHAR_WIDTH / 2) - PIXEL_OFFSET;
|
int start_x = center_x - (HALF_VISIBLE * CHAR_STEP) - (AVG_CHAR_WIDTH / 2) - PIXEL_OFFSET;
|
||||||
@@ -770,24 +773,27 @@ void Scoreboard::renderCarousel(size_t panel_index, int center_x, int y) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- Calcular distancia circular correcta (corregido el bug de wrap) ---
|
// --- Calcular distancia circular correcta (corregido el bug de wrap) ---
|
||||||
float normalized_pos = std::fmod(CAROUSEL_POS, static_cast<float>(CHAR_LIST_SIZE));
|
float normalized_pos = std::fmod(carousel_pos, static_cast<float>(CHAR_LIST_SIZE));
|
||||||
if (normalized_pos < 0.0f) normalized_pos += static_cast<float>(CHAR_LIST_SIZE);
|
if (normalized_pos < 0.0F) {
|
||||||
|
normalized_pos += static_cast<float>(CHAR_LIST_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
float diff = std::abs(static_cast<float>(char_index) - normalized_pos);
|
float diff = std::abs(static_cast<float>(char_index) - normalized_pos);
|
||||||
if (diff > static_cast<float>(CHAR_LIST_SIZE) / 2.0f)
|
if (diff > static_cast<float>(CHAR_LIST_SIZE) / 2.0F) {
|
||||||
diff = static_cast<float>(CHAR_LIST_SIZE) - diff;
|
diff = static_cast<float>(CHAR_LIST_SIZE) - diff;
|
||||||
|
}
|
||||||
|
|
||||||
const float distance_from_center = diff;
|
const float DISTANCE_FROM_CENTER = diff;
|
||||||
|
|
||||||
// --- Seleccionar color con LERP según la distancia ---
|
// --- Seleccionar color con LERP según la distancia ---
|
||||||
Color letter_color;
|
Color letter_color;
|
||||||
if (distance_from_center < 0.5F) {
|
if (DISTANCE_FROM_CENTER < 0.5F) {
|
||||||
// Letra central → transiciona hacia animated_color_
|
// Letra central → transiciona hacia animated_color_
|
||||||
float lerp_to_animated = distance_from_center / 0.5F; // 0.0 a 1.0
|
float lerp_to_animated = DISTANCE_FROM_CENTER / 0.5F; // 0.0 a 1.0
|
||||||
letter_color = animated_color_.LERP(text_color1_, lerp_to_animated);
|
letter_color = animated_color_.LERP(text_color1_, lerp_to_animated);
|
||||||
} else {
|
} else {
|
||||||
// Letras alejadas → degradan hacia color_ base
|
// Letras alejadas → degradan hacia color_ base
|
||||||
float base_lerp = (distance_from_center - 0.5F) / (HALF_VISIBLE - 0.5F);
|
float base_lerp = (DISTANCE_FROM_CENTER - 0.5F) / (HALF_VISIBLE - 0.5F);
|
||||||
base_lerp = std::min(base_lerp, 1.0F);
|
base_lerp = std::min(base_lerp, 1.0F);
|
||||||
const float LERP_FACTOR = base_lerp * 0.85F;
|
const float LERP_FACTOR = base_lerp * 0.85F;
|
||||||
letter_color = text_color1_.LERP(color_, LERP_FACTOR);
|
letter_color = text_color1_.LERP(color_, LERP_FACTOR);
|
||||||
|
|||||||
@@ -51,8 +51,8 @@ class Scoreboard {
|
|||||||
|
|
||||||
struct PanelPulse {
|
struct PanelPulse {
|
||||||
bool active = false; // Si el pulso está activo
|
bool active = false; // Si el pulso está activo
|
||||||
float elapsed_s = 0.0f; // Tiempo transcurrido desde el inicio
|
float elapsed_s = 0.0F; // Tiempo transcurrido desde el inicio
|
||||||
float duration_s = 0.5f; // Duración total del pulso
|
float duration_s = 0.5F; // Duración total del pulso
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Métodos de singleton ---
|
// --- Métodos de singleton ---
|
||||||
@@ -80,7 +80,7 @@ class Scoreboard {
|
|||||||
void setScore(Id id, int score) { score_.at(static_cast<size_t>(id)) = score; }
|
void setScore(Id id, int score) { score_.at(static_cast<size_t>(id)) = score; }
|
||||||
void setSelectorPos(Id id, int pos) { selector_pos_.at(static_cast<size_t>(id)) = pos; }
|
void setSelectorPos(Id id, int pos) { selector_pos_.at(static_cast<size_t>(id)) = pos; }
|
||||||
void setStage(int stage) { stage_ = stage; }
|
void setStage(int stage) { stage_ = stage; }
|
||||||
void triggerPanelPulse(Id id, float duration_s = 0.5f); // Activa un pulso en el panel especificado
|
void triggerPanelPulse(Id id, float duration_s = 0.5F); // Activa un pulso en el panel especificado
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
@@ -117,8 +117,8 @@ class Scoreboard {
|
|||||||
int time_counter_ = 0; // Contador de segundos
|
int time_counter_ = 0; // Contador de segundos
|
||||||
Uint32 name_color_index_ = 0; // Índice actual del color en el ciclo de animación del nombre
|
Uint32 name_color_index_ = 0; // Índice actual del color en el ciclo de animación del nombre
|
||||||
Uint64 name_color_last_update_ = 0; // Último tick de actualización del color del nombre
|
Uint64 name_color_last_update_ = 0; // Último tick de actualización del color del nombre
|
||||||
float power_ = 0; // Poder actual de la fase
|
float power_ = 0.0F; // Poder actual de la fase
|
||||||
std::array<float, static_cast<size_t>(Id::SIZE)> carousel_speed_scale_ = {1.0f, 1.0f, 1.0f};
|
std::array<float, static_cast<size_t>(Id::SIZE)> carousel_speed_scale_ = {1.0F, 1.0F, 1.0F};
|
||||||
|
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr int CAROUSEL_VISIBLE_LETTERS = 9;
|
static constexpr int CAROUSEL_VISIBLE_LETTERS = 9;
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ void Credits::run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza las variables (time-based)
|
// Actualiza las variables (time-based puro - sin conversión frame-based)
|
||||||
void Credits::update(float delta_time) {
|
void Credits::update(float delta_time) {
|
||||||
const float MULTIPLIER = want_to_pass_ ? FAST_FORWARD_MULTIPLIER : 1.0F;
|
const float MULTIPLIER = want_to_pass_ ? FAST_FORWARD_MULTIPLIER : 1.0F;
|
||||||
const float ADJUSTED_DELTA_TIME = delta_time * MULTIPLIER;
|
const float ADJUSTED_DELTA_TIME = delta_time * MULTIPLIER;
|
||||||
@@ -99,10 +99,6 @@ void Credits::update(float delta_time) {
|
|||||||
updatePlayers(ADJUSTED_DELTA_TIME);
|
updatePlayers(ADJUSTED_DELTA_TIME);
|
||||||
updateAllFades(ADJUSTED_DELTA_TIME);
|
updateAllFades(ADJUSTED_DELTA_TIME);
|
||||||
|
|
||||||
// Convertir deltaTime a equivalente de frames (60fps)
|
|
||||||
const float FRAME_FACTOR = ADJUSTED_DELTA_TIME * 60.0F;
|
|
||||||
counter_ += FRAME_FACTOR;
|
|
||||||
|
|
||||||
fillCanvas();
|
fillCanvas();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,7 +266,7 @@ void Credits::fillCanvas() {
|
|||||||
SDL_SetRenderTarget(Screen::get()->getRenderer(), temp);
|
SDL_SetRenderTarget(Screen::get()->getRenderer(), temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el destino de los rectangulos de las texturas (time-based)
|
// Actualiza el destino de los rectangulos de las texturas (time-based puro)
|
||||||
void Credits::updateTextureDstRects(float delta_time) {
|
void Credits::updateTextureDstRects(float delta_time) {
|
||||||
constexpr float TEXTURE_UPDATE_INTERVAL_S = 10.0F / 60.0F; // ~0.167s (cada 10 frames)
|
constexpr float TEXTURE_UPDATE_INTERVAL_S = 10.0F / 60.0F; // ~0.167s (cada 10 frames)
|
||||||
credits_state_.texture_accumulator += delta_time;
|
credits_state_.texture_accumulator += delta_time;
|
||||||
@@ -284,34 +280,45 @@ void Credits::updateTextureDstRects(float delta_time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba la posición de la textura con el mini_logo
|
// Comprueba la posición de la textura con el mini_logo
|
||||||
if (mini_logo_rect_dst_.y == mini_logo_final_pos_) {
|
if (mini_logo_rect_dst_.y <= static_cast<float>(mini_logo_final_pos_)) {
|
||||||
|
// Forzar posición exacta para evitar problemas de comparación float
|
||||||
|
mini_logo_rect_dst_.y = static_cast<float>(mini_logo_final_pos_);
|
||||||
mini_logo_on_position_ = true;
|
mini_logo_on_position_ = true;
|
||||||
|
|
||||||
// Si el jugador quiere pasar los titulos de credito, el fade se inicia solo
|
|
||||||
if (want_to_pass_) {
|
|
||||||
fading_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Se activa el contador para evitar que la sección sea infinita
|
|
||||||
if (counter_prevent_endless_ == 1000) {
|
|
||||||
fading_ = true;
|
|
||||||
} else {
|
|
||||||
++counter_prevent_endless_;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
--mini_logo_rect_dst_.y;
|
--mini_logo_rect_dst_.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Acumular tiempo desde que el logo llegó a su posición (fuera del if para que se ejecute cada frame)
|
||||||
|
if (mini_logo_on_position_) {
|
||||||
|
time_since_logo_positioned_ += delta_time;
|
||||||
|
|
||||||
|
// Timeout para evitar que la sección sea infinita
|
||||||
|
if (time_since_logo_positioned_ >= MAX_TIME_AFTER_LOGO_S) {
|
||||||
|
fading_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si el jugador quiere pasar los titulos de credito, el fade se inicia solo
|
||||||
|
if (want_to_pass_) {
|
||||||
|
fading_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tira globos al escenario (time-based)
|
// Tira globos al escenario (time-based puro)
|
||||||
void Credits::throwBalloons(float delta_time) {
|
void Credits::throwBalloons(float delta_time) {
|
||||||
constexpr int SPEED = 200;
|
constexpr int SPEED = 200;
|
||||||
|
constexpr size_t NUM_SETS = 8; // Tamaño del vector SETS
|
||||||
const std::vector<int> SETS = {0, 63, 25, 67, 17, 75, 13, 50};
|
const std::vector<int> SETS = {0, 63, 25, 67, 17, 75, 13, 50};
|
||||||
constexpr float BALLOON_INTERVAL_S = SPEED / 60.0F; // ~3.33s (cada 200 frames)
|
constexpr float BALLOON_INTERVAL_S = SPEED / 60.0F; // ~3.33s (cada 200 frames)
|
||||||
constexpr float POWERBALL_INTERVAL_S = (SPEED * 4) / 60.0F; // ~13.33s (cada 800 frames)
|
constexpr float POWERBALL_INTERVAL_S = (SPEED * 4) / 60.0F; // ~13.33s (cada 800 frames)
|
||||||
|
constexpr float MAX_BALLOON_TIME_S = ((NUM_SETS - 1) * SPEED * 3) / 60.0F; // Tiempo máximo para lanzar globos
|
||||||
|
|
||||||
if (counter_ > ((SETS.size() - 1) * SPEED) * 3) {
|
// Acumular tiempo total de globos
|
||||||
|
elapsed_time_balloons_ += delta_time;
|
||||||
|
|
||||||
|
// Detener lanzamiento después del tiempo límite
|
||||||
|
if (elapsed_time_balloons_ > MAX_BALLOON_TIME_S) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,11 +327,11 @@ void Credits::throwBalloons(float delta_time) {
|
|||||||
|
|
||||||
if (credits_state_.balloon_accumulator >= BALLOON_INTERVAL_S) {
|
if (credits_state_.balloon_accumulator >= BALLOON_INTERVAL_S) {
|
||||||
credits_state_.balloon_accumulator -= BALLOON_INTERVAL_S;
|
credits_state_.balloon_accumulator -= BALLOON_INTERVAL_S;
|
||||||
const int INDEX = (static_cast<int>(counter_ / SPEED)) % SETS.size();
|
const int INDEX = (static_cast<int>(elapsed_time_balloons_ * 60.0F / SPEED)) % SETS.size();
|
||||||
balloon_manager_->deployFormation(SETS.at(INDEX), -60);
|
balloon_manager_->deployFormation(SETS.at(INDEX), -60);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (credits_state_.powerball_accumulator >= POWERBALL_INTERVAL_S && counter_ > 0) {
|
if (credits_state_.powerball_accumulator >= POWERBALL_INTERVAL_S && elapsed_time_balloons_ > 0.0F) {
|
||||||
credits_state_.powerball_accumulator -= POWERBALL_INTERVAL_S;
|
credits_state_.powerball_accumulator -= POWERBALL_INTERVAL_S;
|
||||||
balloon_manager_->createPowerBall();
|
balloon_manager_->createPowerBall();
|
||||||
}
|
}
|
||||||
@@ -402,8 +409,8 @@ void Credits::initPlayers() {
|
|||||||
|
|
||||||
// Actualiza los rectangulos negros (time-based)
|
// Actualiza los rectangulos negros (time-based)
|
||||||
void Credits::updateBlackRects(float delta_time) {
|
void Credits::updateBlackRects(float delta_time) {
|
||||||
if (!initialized_) return;
|
if (!initialized_) { return; }
|
||||||
if (delta_time < 0.0f) delta_time = 0.0f;
|
delta_time = std::max(delta_time, 0.0F);
|
||||||
|
|
||||||
// Fase vertical: hasta que ambos rects verticales estén exactos en su target
|
// Fase vertical: hasta que ambos rects verticales estén exactos en su target
|
||||||
if (!vertical_done_) {
|
if (!vertical_done_) {
|
||||||
@@ -413,34 +420,34 @@ void Credits::updateBlackRects(float delta_time) {
|
|||||||
|
|
||||||
// top
|
// top
|
||||||
int prev_top_h = static_cast<int>(top_black_rect_.h);
|
int prev_top_h = static_cast<int>(top_black_rect_.h);
|
||||||
top_black_rect_.h = std::min(top_black_rect_.h + 1.0f,
|
top_black_rect_.h = std::min(top_black_rect_.h + 1.0F,
|
||||||
static_cast<float>(param.game.game_area.center_y - 1));
|
static_cast<float>(param.game.game_area.center_y - 1));
|
||||||
int top_delta = static_cast<int>(top_black_rect_.h) - prev_top_h;
|
int top_delta = static_cast<int>(top_black_rect_.h) - prev_top_h;
|
||||||
|
|
||||||
// bottom
|
// bottom
|
||||||
int prev_bottom_h = static_cast<int>(bottom_black_rect_.h);
|
int prev_bottom_h = static_cast<int>(bottom_black_rect_.h);
|
||||||
int prev_bottom_y = static_cast<int>(bottom_black_rect_.y);
|
int prev_bottom_y = static_cast<int>(bottom_black_rect_.y);
|
||||||
bottom_black_rect_.h = bottom_black_rect_.h + 1.0f;
|
bottom_black_rect_.h = bottom_black_rect_.h + 1.0F;
|
||||||
bottom_black_rect_.y = std::max(bottom_black_rect_.y - 1.0f,
|
bottom_black_rect_.y = std::max(bottom_black_rect_.y - 1.0F,
|
||||||
static_cast<float>(param.game.game_area.center_y + 1));
|
static_cast<float>(param.game.game_area.center_y + 1));
|
||||||
int bottom_steps_by_h = static_cast<int>(bottom_black_rect_.h) - prev_bottom_h;
|
int bottom_steps_by_h = static_cast<int>(bottom_black_rect_.h) - prev_bottom_h;
|
||||||
int bottom_steps_by_y = prev_bottom_y - static_cast<int>(bottom_black_rect_.y);
|
int bottom_steps_by_y = prev_bottom_y - static_cast<int>(bottom_black_rect_.y);
|
||||||
int bottom_steps = std::max(0, std::max(bottom_steps_by_h, bottom_steps_by_y));
|
int bottom_steps = std::max({0, bottom_steps_by_h, bottom_steps_by_y});
|
||||||
|
|
||||||
int steps_done = top_delta + bottom_steps;
|
int steps_done = top_delta + bottom_steps;
|
||||||
if (steps_done > 0) {
|
if (steps_done > 0) {
|
||||||
current_step_ = std::max(0.0f, current_step_ - static_cast<float>(steps_done));
|
current_step_ = std::max(0.0F, current_step_ - static_cast<float>(steps_done));
|
||||||
float vol_f = initial_volume_ * (current_step_ / static_cast<float>(total_steps_));
|
float vol_f = initial_volume_ * (current_step_ / static_cast<float>(total_steps_));
|
||||||
int vol_i = static_cast<int>(std::clamp(vol_f, 0.0f, static_cast<float>(initial_volume_)));
|
int vol_i = static_cast<int>(std::clamp(vol_f, 0.0F, static_cast<float>(initial_volume_)));
|
||||||
Audio::get()->setMusicVolume(vol_i); // usa tu API de audio aquí
|
Audio::get()->setMusicVolume(vol_i); // usa tu API de audio aquí
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si han alcanzado los objetivos, fijarlos exactamente y marcar done
|
// Si han alcanzado los objetivos, fijarlos exactamente y marcar done
|
||||||
bool top_at_target = static_cast<int>(top_black_rect_.h) == param.game.game_area.center_y - 1;
|
bool top_at_target = static_cast<int>(top_black_rect_.h) == param.game.game_area.center_y - 1.0F;
|
||||||
bool bottom_at_target = static_cast<int>(bottom_black_rect_.y) == param.game.game_area.center_y + 1;
|
bool bottom_at_target = static_cast<int>(bottom_black_rect_.y) == param.game.game_area.center_y + 1.0F;
|
||||||
if (top_at_target && bottom_at_target) {
|
if (top_at_target && bottom_at_target) {
|
||||||
top_black_rect_.h = static_cast<float>(param.game.game_area.center_y - 1);
|
top_black_rect_.h = param.game.game_area.center_y - 1.0F;
|
||||||
bottom_black_rect_.y = static_cast<float>(param.game.game_area.center_y + 1);
|
bottom_black_rect_.y = param.game.game_area.center_y + 1.0F;
|
||||||
vertical_done_ = true;
|
vertical_done_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -453,28 +460,28 @@ void Credits::updateBlackRects(float delta_time) {
|
|||||||
if (!horizontal_done_) {
|
if (!horizontal_done_) {
|
||||||
int prev_left_w = static_cast<int>(left_black_rect_.w);
|
int prev_left_w = static_cast<int>(left_black_rect_.w);
|
||||||
left_black_rect_.w = std::min(left_black_rect_.w + static_cast<float>(HORIZONTAL_SPEED),
|
left_black_rect_.w = std::min(left_black_rect_.w + static_cast<float>(HORIZONTAL_SPEED),
|
||||||
static_cast<float>(param.game.game_area.center_x));
|
param.game.game_area.center_x);
|
||||||
int left_gain = static_cast<int>(left_black_rect_.w) - prev_left_w;
|
int left_gain = static_cast<int>(left_black_rect_.w) - prev_left_w;
|
||||||
|
|
||||||
int prev_right_x = static_cast<int>(right_black_rect_.x);
|
int prev_right_x = static_cast<int>(right_black_rect_.x);
|
||||||
right_black_rect_.w = right_black_rect_.w + static_cast<float>(HORIZONTAL_SPEED);
|
right_black_rect_.w = right_black_rect_.w + static_cast<float>(HORIZONTAL_SPEED);
|
||||||
right_black_rect_.x = std::max(right_black_rect_.x - static_cast<float>(HORIZONTAL_SPEED),
|
right_black_rect_.x = std::max(right_black_rect_.x - static_cast<float>(HORIZONTAL_SPEED),
|
||||||
static_cast<float>(param.game.game_area.center_x));
|
param.game.game_area.center_x);
|
||||||
int right_move = prev_right_x - static_cast<int>(right_black_rect_.x);
|
int right_move = prev_right_x - static_cast<int>(right_black_rect_.x);
|
||||||
|
|
||||||
int steps_done = left_gain + right_move;
|
int steps_done = left_gain + right_move;
|
||||||
if (steps_done > 0) {
|
if (steps_done > 0) {
|
||||||
current_step_ = std::max(0.0f, current_step_ - static_cast<float>(steps_done));
|
current_step_ = std::max(0.0F, current_step_ - static_cast<float>(steps_done));
|
||||||
float vol_f = initial_volume_ * (current_step_ / static_cast<float>(total_steps_));
|
float vol_f = initial_volume_ * (current_step_ / static_cast<float>(total_steps_));
|
||||||
int vol_i = static_cast<int>(std::clamp(vol_f, 0.0f, static_cast<float>(initial_volume_)));
|
int vol_i = static_cast<int>(std::clamp(vol_f, 0.0F, static_cast<float>(initial_volume_)));
|
||||||
Audio::get()->setMusicVolume(vol_i); // usa tu API de audio aquí
|
Audio::get()->setMusicVolume(vol_i); // usa tu API de audio aquí
|
||||||
}
|
}
|
||||||
|
|
||||||
bool left_at_target = static_cast<int>(left_black_rect_.w) == param.game.game_area.center_x;
|
bool left_at_target = static_cast<int>(left_black_rect_.w) == param.game.game_area.center_x;
|
||||||
bool right_at_target = static_cast<int>(right_black_rect_.x) == param.game.game_area.center_x;
|
bool right_at_target = static_cast<int>(right_black_rect_.x) == param.game.game_area.center_x;
|
||||||
if (left_at_target && right_at_target) {
|
if (left_at_target && right_at_target) {
|
||||||
left_black_rect_.w = static_cast<float>(param.game.game_area.center_x);
|
left_black_rect_.w = param.game.game_area.center_x;
|
||||||
right_black_rect_.x = static_cast<float>(param.game.game_area.center_x);
|
right_black_rect_.x = param.game.game_area.center_x;
|
||||||
horizontal_done_ = true;
|
horizontal_done_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,24 +492,27 @@ void Credits::updateBlackRects(float delta_time) {
|
|||||||
// Fase final: ya completado el movimiento de rects
|
// Fase final: ya completado el movimiento de rects
|
||||||
Audio::get()->setMusicVolume(0);
|
Audio::get()->setMusicVolume(0);
|
||||||
// Audio::get()->stopMusic(); // opcional, si quieres parar la reproducción
|
// Audio::get()->stopMusic(); // opcional, si quieres parar la reproducción
|
||||||
if (counter_pre_fade_ >= 400.0f) {
|
|
||||||
if (fade_out_) fade_out_->activate();
|
// Usar segundos puros en lugar de frames equivalentes
|
||||||
|
if (counter_pre_fade_ >= PRE_FADE_DELAY_S) {
|
||||||
|
if (fade_out_) {
|
||||||
|
fade_out_->activate();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const float frame_increment = delta_time * FRAMES_PER_SECOND;
|
counter_pre_fade_ += delta_time;
|
||||||
counter_pre_fade_ += frame_increment;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el rectangulo del borde
|
// Actualiza el rectangulo del borde
|
||||||
void Credits::updateBorderRect() {
|
void Credits::updateBorderRect() {
|
||||||
border_rect_.x = left_black_rect_.x + left_black_rect_.w;
|
border_rect_.x = left_black_rect_.x + left_black_rect_.w;
|
||||||
border_rect_.y = top_black_rect_.y + top_black_rect_.h - 1;
|
border_rect_.y = top_black_rect_.y + top_black_rect_.h - 1.0F;
|
||||||
|
|
||||||
float raw_w = right_black_rect_.x - border_rect_.x;
|
float raw_w = right_black_rect_.x - border_rect_.x;
|
||||||
float raw_h = bottom_black_rect_.y - border_rect_.y + 1.0f;
|
float raw_h = bottom_black_rect_.y - border_rect_.y + 1.0F;
|
||||||
|
|
||||||
border_rect_.w = std::max(0.0f, raw_w);
|
border_rect_.w = std::max(0.0F, raw_w);
|
||||||
border_rect_.h = std::max(0.0f, raw_h);
|
border_rect_.h = std::max(0.0F, raw_h);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el estado de fade (time-based)
|
// Actualiza el estado de fade (time-based)
|
||||||
@@ -604,25 +614,25 @@ void Credits::renderPlayers() {
|
|||||||
void Credits::initVars() {
|
void Credits::initVars() {
|
||||||
// Inicialización segura de rects tal y como los mostraste
|
// Inicialización segura de rects tal y como los mostraste
|
||||||
top_black_rect_ = {
|
top_black_rect_ = {
|
||||||
play_area_.x,
|
.x = play_area_.x,
|
||||||
param.game.game_area.rect.y,
|
.y = param.game.game_area.rect.y,
|
||||||
play_area_.w,
|
.w = play_area_.w,
|
||||||
black_bars_size_};
|
.h = black_bars_size_};
|
||||||
bottom_black_rect_ = {
|
bottom_black_rect_ = {
|
||||||
play_area_.x,
|
.x = play_area_.x,
|
||||||
param.game.game_area.rect.h - black_bars_size_,
|
.y = param.game.game_area.rect.h - black_bars_size_,
|
||||||
play_area_.w,
|
.w = play_area_.w,
|
||||||
black_bars_size_};
|
.h = black_bars_size_};
|
||||||
left_black_rect_ = {
|
left_black_rect_ = {
|
||||||
play_area_.x,
|
.x = play_area_.x,
|
||||||
param.game.game_area.center_y - 1,
|
.y = param.game.game_area.center_y - 1.0F,
|
||||||
0,
|
.w = 0.0F,
|
||||||
2};
|
.h = 2.0F};
|
||||||
right_black_rect_ = {
|
right_black_rect_ = {
|
||||||
play_area_.x + play_area_.w,
|
.x = play_area_.x + play_area_.w,
|
||||||
param.game.game_area.center_y - 1,
|
.y = param.game.game_area.center_y - 1.0F,
|
||||||
0,
|
.w = 0.0F,
|
||||||
2};
|
.h = 2.0F};
|
||||||
|
|
||||||
initialized_ = false;
|
initialized_ = false;
|
||||||
|
|
||||||
@@ -651,10 +661,10 @@ void Credits::initVars() {
|
|||||||
|
|
||||||
void Credits::startCredits() {
|
void Credits::startCredits() {
|
||||||
// Guardar iniciales (enteros para contar "pasos" por píxel)
|
// Guardar iniciales (enteros para contar "pasos" por píxel)
|
||||||
init_top_h = static_cast<int>(top_black_rect_.h);
|
init_top_h_ = static_cast<int>(top_black_rect_.h);
|
||||||
init_bottom_y = static_cast<int>(bottom_black_rect_.y);
|
init_bottom_y_ = static_cast<int>(bottom_black_rect_.y);
|
||||||
init_left_w = static_cast<int>(left_black_rect_.w);
|
init_left_w_ = static_cast<int>(left_black_rect_.w);
|
||||||
init_right_x = static_cast<int>(right_black_rect_.x);
|
init_right_x_ = static_cast<int>(right_black_rect_.x);
|
||||||
|
|
||||||
// Objetivos
|
// Objetivos
|
||||||
int top_target_h = param.game.game_area.center_y - 1;
|
int top_target_h = param.game.game_area.center_y - 1;
|
||||||
@@ -663,34 +673,38 @@ void Credits::startCredits() {
|
|||||||
int right_target_x = param.game.game_area.center_x;
|
int right_target_x = param.game.game_area.center_x;
|
||||||
|
|
||||||
// Pasos verticales
|
// Pasos verticales
|
||||||
int pasos_top = std::max(0, top_target_h - init_top_h);
|
int pasos_top = std::max(0, top_target_h - init_top_h_);
|
||||||
int pasos_bottom = std::max(0, init_bottom_y - bottom_target_y);
|
int pasos_bottom = std::max(0, init_bottom_y_ - bottom_target_y);
|
||||||
|
|
||||||
// Pasos horizontales. right se mueve a velocidad HORIZONTAL_SPEED, contamos pasos como unidades de movimiento equivalentes
|
// Pasos horizontales. right se mueve a velocidad HORIZONTAL_SPEED, contamos pasos como unidades de movimiento equivalentes
|
||||||
int pasos_left = std::max(0, left_target_w - init_left_w);
|
int pasos_left = std::max(0, left_target_w - init_left_w_);
|
||||||
int dx_right = std::max(0, init_right_x - right_target_x);
|
int dx_right = std::max(0, init_right_x_ - right_target_x);
|
||||||
int pasos_right = (dx_right + (HORIZONTAL_SPEED - 1)) / HORIZONTAL_SPEED; // ceil
|
int pasos_right = (dx_right + (HORIZONTAL_SPEED - 1)) / HORIZONTAL_SPEED; // ceil
|
||||||
|
|
||||||
total_steps_ = pasos_top + pasos_bottom + pasos_left + pasos_right;
|
total_steps_ = pasos_top + pasos_bottom + pasos_left + pasos_right;
|
||||||
if (total_steps_ <= 0) total_steps_ = 1;
|
if (total_steps_ <= 0) {
|
||||||
|
total_steps_ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
current_step_ = static_cast<float>(total_steps_);
|
current_step_ = static_cast<float>(total_steps_);
|
||||||
|
|
||||||
// Reiniciar contadores y estado
|
// Reiniciar contadores y estado
|
||||||
credits_state_.black_rect_accumulator = 0.0f;
|
credits_state_.black_rect_accumulator = 0.0F;
|
||||||
counter_pre_fade_ = 0.0f;
|
counter_pre_fade_ = 0.0F;
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
|
|
||||||
// Asegurar volumen inicial consistente
|
// Asegurar volumen inicial consistente
|
||||||
if (steps_ <= 0) steps_ = 1;
|
if (steps_ <= 0) {
|
||||||
|
steps_ = 1;
|
||||||
|
}
|
||||||
float vol_f = initial_volume_ * (current_step_ / static_cast<float>(total_steps_));
|
float vol_f = initial_volume_ * (current_step_ / static_cast<float>(total_steps_));
|
||||||
setVolume(static_cast<int>(std::clamp(vol_f, 0.0f, static_cast<float>(initial_volume_))));
|
setVolume(static_cast<int>(std::clamp(vol_f, 0.0F, static_cast<float>(initial_volume_))));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja el rectángulo del borde si es visible
|
// Dibuja el rectángulo del borde si es visible
|
||||||
void Credits::drawBorderRect() {
|
void Credits::drawBorderRect() {
|
||||||
// Umbral: cualquier valor menor que 1 píxel no se considera visible
|
// Umbral: cualquier valor menor que 1 píxel no se considera visible
|
||||||
constexpr float VISIBLE_THRESHOLD = 1.0f;
|
constexpr float VISIBLE_THRESHOLD = 1.0F;
|
||||||
if (border_rect_.w < VISIBLE_THRESHOLD || border_rect_.h < VISIBLE_THRESHOLD) {
|
if (border_rect_.w < VISIBLE_THRESHOLD || border_rect_.h < VISIBLE_THRESHOLD) {
|
||||||
return; // no dibujar
|
return; // no dibujar
|
||||||
}
|
}
|
||||||
@@ -701,10 +715,10 @@ void Credits::drawBorderRect() {
|
|||||||
|
|
||||||
// Convertir a enteros de forma conservadora para evitar líneas de 1px por redondeo extraño
|
// Convertir a enteros de forma conservadora para evitar líneas de 1px por redondeo extraño
|
||||||
SDL_Rect r;
|
SDL_Rect r;
|
||||||
r.x = static_cast<int>(std::floor(border_rect_.x + 0.5f));
|
r.x = static_cast<int>(std::floor(border_rect_.x + 0.5F));
|
||||||
r.y = static_cast<int>(std::floor(border_rect_.y + 0.5f));
|
r.y = static_cast<int>(std::floor(border_rect_.y + 0.5F));
|
||||||
r.w = static_cast<int>(std::max(0.0f, std::floor(border_rect_.w + 0.5f)));
|
r.w = static_cast<int>(std::max(0.0F, std::floor(border_rect_.w + 0.5F)));
|
||||||
r.h = static_cast<int>(std::max(0.0f, std::floor(border_rect_.h + 0.5f)));
|
r.h = static_cast<int>(std::max(0.0F, std::floor(border_rect_.h + 0.5F)));
|
||||||
|
|
||||||
if (r.w > 0 && r.h > 0) {
|
if (r.w > 0 && r.h > 0) {
|
||||||
SDL_RenderRect(Screen::get()->getRenderer(), &border_rect_);
|
SDL_RenderRect(Screen::get()->getRenderer(), &border_rect_);
|
||||||
|
|||||||
@@ -32,12 +32,13 @@ class Credits {
|
|||||||
void initVars(); // Inicializa variables
|
void initVars(); // Inicializa variables
|
||||||
void startCredits(); // Inicializa mas variables
|
void startCredits(); // Inicializa mas variables
|
||||||
|
|
||||||
// --- Constantes de clase ---
|
// --- Constantes de clase (time-based) ---
|
||||||
static constexpr int PLAY_AREA_HEIGHT = 200;
|
static constexpr int PLAY_AREA_HEIGHT = 200;
|
||||||
static constexpr float FAST_FORWARD_MULTIPLIER = 6.0F;
|
static constexpr float FAST_FORWARD_MULTIPLIER = 6.0F;
|
||||||
static constexpr float BLACK_RECT_INTERVAL_S = 4.0F / 60.0F; // ~0.0667s
|
static constexpr float BLACK_RECT_INTERVAL_S = 4.0F / 60.0F; // ~0.0667s (cada 4 frames a 60fps)
|
||||||
static constexpr float FRAMES_PER_SECOND = 60.0F;
|
|
||||||
static constexpr int HORIZONTAL_SPEED = 2;
|
static constexpr int HORIZONTAL_SPEED = 2;
|
||||||
|
static constexpr float MAX_TIME_AFTER_LOGO_S = 20.0F;
|
||||||
|
static constexpr float PRE_FADE_DELAY_S = 8.0F;
|
||||||
|
|
||||||
// --- Objetos principales ---
|
// --- Objetos principales ---
|
||||||
std::unique_ptr<BalloonManager> balloon_manager_; // Gestión de globos
|
std::unique_ptr<BalloonManager> balloon_manager_; // Gestión de globos
|
||||||
@@ -50,20 +51,20 @@ class Credits {
|
|||||||
SDL_Texture* text_texture_; // Textura con el texto de créditos
|
SDL_Texture* text_texture_; // Textura con el texto de créditos
|
||||||
SDL_Texture* canvas_; // Textura donde se dibuja todo
|
SDL_Texture* canvas_; // Textura donde se dibuja todo
|
||||||
|
|
||||||
// --- Temporización y contadores ---
|
// --- Temporización (time-based puro) ---
|
||||||
Uint64 last_time_ = 0; // Último tiempo registrado para deltaTime
|
Uint64 last_time_ = 0; // Último tiempo registrado para deltaTime
|
||||||
float counter_ = 0.0F; // Contador principal de lógica
|
float elapsed_time_balloons_ = 0.0F; // Tiempo acumulado para lanzamiento de globos (segundos)
|
||||||
float counter_pre_fade_ = 0.0F; // Activación del fundido final
|
float counter_pre_fade_ = 0.0F; // Tiempo antes de activar fundido final (segundos)
|
||||||
float counter_prevent_endless_ = 0.0F; // Prevención de bucle infinito
|
float time_since_logo_positioned_ = 0.0F; // Tiempo desde que el logo llegó a su posición (segundos)
|
||||||
float current_step_ = 0.0F;
|
float current_step_ = 0.0F;
|
||||||
int total_steps_ = 1;
|
int total_steps_ = 1;
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
|
|
||||||
// --- Guardar estados iniciales para cálculo de pasos ---
|
// --- Guardar estados iniciales para cálculo de pasos ---
|
||||||
int init_top_h = 0;
|
int init_top_h_ = 0;
|
||||||
int init_bottom_y = 0;
|
int init_bottom_y_ = 0;
|
||||||
int init_left_w = 0;
|
int init_left_w_ = 0;
|
||||||
int init_right_x = 0;
|
int init_right_x_ = 0;
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
bool fading_ = false; // Estado del fade final
|
bool fading_ = false; // Estado del fade final
|
||||||
|
|||||||
@@ -551,19 +551,18 @@ void Game::handleTabeHitEffects() {
|
|||||||
|
|
||||||
// Maneja la colisión entre bala y globos
|
// Maneja la colisión entre bala y globos
|
||||||
auto Game::checkBulletBalloonCollision(const std::shared_ptr<Bullet>& bullet) -> bool {
|
auto Game::checkBulletBalloonCollision(const std::shared_ptr<Bullet>& bullet) -> bool {
|
||||||
for (auto& balloon : balloon_manager_->getBalloons()) {
|
return std::ranges::any_of(balloon_manager_->getBalloons(), [this, &bullet](auto& balloon) {
|
||||||
if (!balloon->isEnabled() || balloon->isInvulnerable()) {
|
if (!balloon->isEnabled() || balloon->isInvulnerable()) {
|
||||||
continue;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!checkCollision(balloon->getCollider(), bullet->getCollider())) {
|
if (!checkCollision(balloon->getCollider(), bullet->getCollider())) {
|
||||||
continue;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
processBalloonHit(bullet, balloon);
|
processBalloonHit(bullet, balloon);
|
||||||
return true;
|
return true;
|
||||||
}
|
});
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Procesa el impacto en un globo
|
// Procesa el impacto en un globo
|
||||||
@@ -1961,68 +1960,87 @@ void Game::handleGameOverEvents() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construye (una vez) el drawList a partir del vector principal
|
// Construye (una vez) el draw_list a partir del vector principal
|
||||||
// drawList almacena punteros a los elementos y queda reservado
|
// draw_list almacena punteros a los elementos y queda reservado
|
||||||
void Game::buildPlayerDrawList(const Players& elements, Players& drawList) {
|
void Game::buildPlayerDrawList(const Players& elements, Players& draw_list) {
|
||||||
drawList.clear();
|
draw_list.clear();
|
||||||
drawList.reserve(elements.size());
|
draw_list.reserve(elements.size());
|
||||||
for (const auto& e : elements) drawList.push_back(e); // copia el shared_ptr
|
for (const auto& e : elements) {
|
||||||
std::stable_sort(drawList.begin(), drawList.end(), [](const std::shared_ptr<Player>& a, const std::shared_ptr<Player>& b) {
|
draw_list.push_back(e); // copia el shared_ptr
|
||||||
|
}
|
||||||
|
std::ranges::stable_sort(draw_list, [](const std::shared_ptr<Player>& a, const std::shared_ptr<Player>& b) {
|
||||||
return a->getZOrder() < b->getZOrder();
|
return a->getZOrder() < b->getZOrder();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza drawList tras cambios en los z_order. Implementación simple:
|
// Actualiza draw_list tras cambios en los z_order. Implementación simple:
|
||||||
// reordena drawList según los z_order actuales. Llamar cuando cambian z_order
|
// reordena draw_list según los z_order actuales. Llamar cuando cambian z_order
|
||||||
void Game::updatePlayerDrawList(const Players& elements, Players& drawList) {
|
void Game::updatePlayerDrawList(const Players& elements, Players& draw_list) {
|
||||||
// Si drawList está vacío o su tamaño no coincide, reconstruirlo.
|
// Si draw_list está vacío o su tamaño no coincide, reconstruirlo.
|
||||||
if (drawList.size() != elements.size()) {
|
if (draw_list.size() != elements.size()) {
|
||||||
buildPlayerDrawList(elements, drawList);
|
buildPlayerDrawList(elements, draw_list);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Dado que apuntan a los mismos elementos, basta ordenar por los z_order actuales.
|
// Dado que apuntan a los mismos elementos, basta ordenar por los z_order actuales.
|
||||||
std::stable_sort(drawList.begin(), drawList.end(), [](const std::shared_ptr<Player>& a, const std::shared_ptr<Player>& b) {
|
std::ranges::stable_sort(draw_list, [](const std::shared_ptr<Player>& a, const std::shared_ptr<Player>& b) {
|
||||||
return a->getZOrder() < b->getZOrder();
|
return a->getZOrder() < b->getZOrder();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja en el orden definido por drawList
|
// Dibuja en el orden definido por draw_list
|
||||||
void Game::renderPlayerDrawList(const Players& drawList) {
|
void Game::renderPlayerDrawList(const Players& draw_list) {
|
||||||
for (const auto& e : drawList) e->render();
|
for (const auto& e : draw_list) {
|
||||||
|
e->render();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Operaciones sobre z_order que mantienen la invariante y actualizan drawList.
|
// Operaciones sobre z_order que mantienen la invariante y actualizan draw_list.
|
||||||
auto Game::findPlayerIndex(const Players& elems, const std::shared_ptr<Player>& who) -> size_t {
|
auto Game::findPlayerIndex(const Players& elems, const std::shared_ptr<Player>& who) -> size_t {
|
||||||
for (size_t i = 0; i < elems.size(); ++i)
|
for (size_t i = 0; i < elems.size(); ++i) {
|
||||||
if (elems[i] == who) return static_cast<int>(i); // compara shared_ptr directamente
|
if (elems[i] == who) {
|
||||||
|
return static_cast<int>(i); // compara shared_ptr directamente
|
||||||
|
}
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::sendPlayerToBack(Players& elements, const std::shared_ptr<Player>& who, Players& drawList) {
|
void Game::sendPlayerToBack(Players& elements, const std::shared_ptr<Player>& who, Players& draw_list) {
|
||||||
int idx = findPlayerIndex(elements, who);
|
int idx = findPlayerIndex(elements, who);
|
||||||
if (idx < 0) return; // no encontrado
|
if (idx < 0) {
|
||||||
const int oldZ = elements[idx]->getZOrder();
|
return; // no encontrado
|
||||||
if (oldZ <= 0) return;
|
}
|
||||||
|
const int OLD_Z = elements[idx]->getZOrder();
|
||||||
|
if (OLD_Z <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (auto& p : elements) {
|
for (auto& p : elements) {
|
||||||
int z = p->getZOrder();
|
int z = p->getZOrder();
|
||||||
if (z < oldZ) p->setZOrder(z + 1);
|
if (z < OLD_Z) {
|
||||||
|
p->setZOrder(z + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
elements[idx]->setZOrder(0);
|
elements[idx]->setZOrder(0);
|
||||||
updatePlayerDrawList(elements, drawList);
|
updatePlayerDrawList(elements, draw_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::bringPlayerToFront(Players& elements, const std::shared_ptr<Player>& who, Players& drawList) {
|
void Game::bringPlayerToFront(Players& elements, const std::shared_ptr<Player>& who, Players& draw_list) {
|
||||||
int idx = findPlayerIndex(elements, who);
|
int idx = findPlayerIndex(elements, who);
|
||||||
if (idx < 0) return; // no encontrado
|
if (idx < 0) {
|
||||||
const int oldZ = elements[idx]->getZOrder();
|
return; // no encontrado
|
||||||
|
}
|
||||||
|
const int OLD_Z = elements[idx]->getZOrder();
|
||||||
const int N = static_cast<int>(elements.size());
|
const int N = static_cast<int>(elements.size());
|
||||||
if (oldZ >= N - 1) return;
|
if (OLD_Z >= N - 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (auto& p : elements) {
|
for (auto& p : elements) {
|
||||||
int z = p->getZOrder();
|
int z = p->getZOrder();
|
||||||
if (z > oldZ) p->setZOrder(z - 1);
|
if (z > OLD_Z) {
|
||||||
|
p->setZOrder(z - 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
elements[idx]->setZOrder(N - 1);
|
elements[idx]->setZOrder(N - 1);
|
||||||
updatePlayerDrawList(elements, drawList);
|
updatePlayerDrawList(elements, draw_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
|||||||
@@ -336,12 +336,12 @@ class Game {
|
|||||||
void playSound(const std::string& name) const; // Reproduce un efecto de sonido específico
|
void playSound(const std::string& name) const; // Reproduce un efecto de sonido específico
|
||||||
|
|
||||||
// --- Gestion y dibujado de jugadores en z-order ---
|
// --- Gestion y dibujado de jugadores en z-order ---
|
||||||
void buildPlayerDrawList(const Players& elements, Players& drawList); // Construye el drawList a partir del vector principal
|
static void buildPlayerDrawList(const Players& elements, Players& draw_list); // Construye el draw_list a partir del vector principal
|
||||||
void updatePlayerDrawList(const Players& elements, Players& drawList); // Actualiza drawList tras cambios en los z_order
|
static void updatePlayerDrawList(const Players& elements, Players& draw_list); // Actualiza draw_list tras cambios en los z_order
|
||||||
void renderPlayerDrawList(const Players& drawList); // Dibuja en el orden definido
|
static void renderPlayerDrawList(const Players& draw_list); // Dibuja en el orden definido
|
||||||
static auto findPlayerIndex(const Players& elems, const std::shared_ptr<Player>& who) -> size_t;
|
static auto findPlayerIndex(const Players& elems, const std::shared_ptr<Player>& who) -> size_t;
|
||||||
void sendPlayerToBack(Players& elements, const std::shared_ptr<Player>& who, Players& drawList); // Envia al jugador al fondo de la pantalla
|
static void sendPlayerToBack(Players& elements, const std::shared_ptr<Player>& who, Players& draw_list); // Envia al jugador al fondo de la pantalla
|
||||||
void bringPlayerToFront(Players& elements, const std::shared_ptr<Player>& who, Players& drawList); // Envia al jugador al frente de la pantalla
|
static void bringPlayerToFront(Players& elements, const std::shared_ptr<Player>& who, Players& draw_list); // Envia al jugador al frente de la pantalla
|
||||||
|
|
||||||
// --- Varios ---
|
// --- Varios ---
|
||||||
void onPauseStateChanged(bool is_paused);
|
void onPauseStateChanged(bool is_paused);
|
||||||
|
|||||||
@@ -285,6 +285,30 @@ void Text::writeCentered(int x, int y, const std::string& text, int kerning, int
|
|||||||
write(x, y, text, kerning, length);
|
write(x, y, text, kerning, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Renderiza sombra del texto
|
||||||
|
void Text::renderShadow(int x, int y, const std::string& text, Color shadow_color, int kerning, int length, Uint8 shadow_distance) {
|
||||||
|
if (white_sprite_) {
|
||||||
|
writeColoredWithSprite(white_sprite_.get(), x + shadow_distance, y + shadow_distance, text, shadow_color, kerning, length);
|
||||||
|
} else {
|
||||||
|
writeColored(x + shadow_distance, y + shadow_distance, text, shadow_color, kerning, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Renderiza stroke sólido (método tradicional para stroke sin alpha)
|
||||||
|
void Text::renderSolidStroke(int x, int y, const std::string& text, Color stroke_color, int kerning, int length, Uint8 shadow_distance) {
|
||||||
|
for (int dist = 1; dist <= shadow_distance; ++dist) {
|
||||||
|
for (int dy = -dist; dy <= dist; ++dy) {
|
||||||
|
for (int dx = -dist; dx <= dist; ++dx) {
|
||||||
|
if (white_sprite_) {
|
||||||
|
writeColoredWithSprite(white_sprite_.get(), x + dx, y + dy, text, stroke_color, kerning, length);
|
||||||
|
} else {
|
||||||
|
writeColored(x + dx, y + dy, text, stroke_color, kerning, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Escribe texto con extras
|
// Escribe texto con extras
|
||||||
void Text::writeDX(Uint8 flags, int x, int y, const std::string& text, int kerning, Color text_color, Uint8 shadow_distance, Color shadow_color, int length) {
|
void Text::writeDX(Uint8 flags, int x, int y, const std::string& text, int kerning, Color text_color, Uint8 shadow_distance, Color shadow_color, int length) {
|
||||||
const auto CENTERED = ((flags & Text::CENTER) == Text::CENTER);
|
const auto CENTERED = ((flags & Text::CENTER) == Text::CENTER);
|
||||||
@@ -297,11 +321,7 @@ void Text::writeDX(Uint8 flags, int x, int y, const std::string& text, int kerni
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (SHADOWED) {
|
if (SHADOWED) {
|
||||||
if (white_sprite_) {
|
renderShadow(x, y, text, shadow_color, kerning, length, shadow_distance);
|
||||||
writeColoredWithSprite(white_sprite_.get(), x + shadow_distance, y + shadow_distance, text, shadow_color, kerning, length);
|
|
||||||
} else {
|
|
||||||
writeColored(x + shadow_distance, y + shadow_distance, text, shadow_color, kerning, length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (STROKED) {
|
if (STROKED) {
|
||||||
@@ -310,17 +330,7 @@ void Text::writeDX(Uint8 flags, int x, int y, const std::string& text, int kerni
|
|||||||
writeStrokeWithAlpha(x, y, text, kerning, shadow_color, shadow_distance, length);
|
writeStrokeWithAlpha(x, y, text, kerning, shadow_color, shadow_distance, length);
|
||||||
} else {
|
} else {
|
||||||
// Método tradicional para stroke sólido
|
// Método tradicional para stroke sólido
|
||||||
for (int dist = 1; dist <= shadow_distance; ++dist) {
|
renderSolidStroke(x, y, text, shadow_color, kerning, length, shadow_distance);
|
||||||
for (int dy = -dist; dy <= dist; ++dy) {
|
|
||||||
for (int dx = -dist; dx <= dist; ++dx) {
|
|
||||||
if (white_sprite_) {
|
|
||||||
writeColoredWithSprite(white_sprite_.get(), x + dx, y + dy, text, shadow_color, kerning, length);
|
|
||||||
} else {
|
|
||||||
writeColored(x + dx, y + dy, text, shadow_color, kerning, length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ class Text {
|
|||||||
// --- Métodos privados ---
|
// --- Métodos privados ---
|
||||||
void writeColoredWithSprite(Sprite* sprite, int x, int y, const std::string& text, Color color, int kerning = 1, int length = -1); // Escribe con un sprite específico
|
void writeColoredWithSprite(Sprite* sprite, int x, int y, const std::string& text, Color color, int kerning = 1, int length = -1); // Escribe con un sprite específico
|
||||||
void writeStrokeWithAlpha(int x, int y, const std::string& text, int kerning, Color stroke_color, Uint8 shadow_distance, int length = -1); // Escribe stroke con alpha correcto
|
void writeStrokeWithAlpha(int x, int y, const std::string& text, int kerning, Color stroke_color, Uint8 shadow_distance, int length = -1); // Escribe stroke con alpha correcto
|
||||||
|
void renderShadow(int x, int y, const std::string& text, Color shadow_color, int kerning, int length, Uint8 shadow_distance); // Renderiza sombra del texto
|
||||||
|
void renderSolidStroke(int x, int y, const std::string& text, Color stroke_color, int kerning, int length, Uint8 shadow_distance); // Renderiza stroke sólido
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ void UIMessage::updateAnimation(float delta_time) {
|
|||||||
float t = animation_timer_ / ANIMATION_DURATION_S;
|
float t = animation_timer_ / ANIMATION_DURATION_S;
|
||||||
|
|
||||||
// Clamp t entre 0 y 1
|
// Clamp t entre 0 y 1
|
||||||
t = std::min(t, 1.0f);
|
t = std::min(t, 1.0F);
|
||||||
|
|
||||||
if (target_y_ > start_y_) {
|
if (target_y_ > start_y_) {
|
||||||
// Animación de entrada (ease out cubic)
|
// Animación de entrada (ease out cubic)
|
||||||
|
|||||||
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
#include "../source/resource_pack.h"
|
#include "../source/resource_pack.hpp"
|
||||||
#include "../build/version.h" // Para Version::APP_NAME
|
#include "../build/version.h" // Para Version::APP_NAME
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|||||||
Reference in New Issue
Block a user