Compare commits
26 Commits
2025-08-10
...
1ced698093
| Author | SHA1 | Date | |
|---|---|---|---|
| 1ced698093 | |||
| 2a4c47a6ca | |||
| 6102504d32 | |||
| a123b3aa93 | |||
| 81d486f2d3 | |||
| 0c10898bdc | |||
| a3cd404545 | |||
| 5c708fc60a | |||
| 960ee367df | |||
| a7519fc372 | |||
| a983269080 | |||
| 3964503f1c | |||
| 8fcb7d1eb5 | |||
| 3e68afa4be | |||
| ca6edcccc0 | |||
| a388005968 | |||
| ea7628259a | |||
| a13e024934 | |||
| 4cc5102d70 | |||
| b2139d8e06 | |||
| ea3e704d34 | |||
| d5ab5748a7 | |||
| e950eb335d | |||
| e667063767 | |||
| 3534e4cc54 | |||
| 685b04c840 |
171
Makefile
@@ -11,7 +11,22 @@ APP_NAME := Coffee Crisis Arcade Edition
|
|||||||
RELEASE_FOLDER := ccae_release
|
RELEASE_FOLDER := ccae_release
|
||||||
RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME)
|
RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME)
|
||||||
RESOURCE_FILE := release/coffee.res
|
RESOURCE_FILE := release/coffee.res
|
||||||
VERSION := 2025-08-10
|
|
||||||
|
# Versión automática basada en la fecha actual (específica por SO)
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
VERSION := $(shell powershell -Command "Get-Date -Format 'yyyy-MM-dd'")
|
||||||
|
else
|
||||||
|
VERSION := $(shell date +%Y-%m-%d)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Variables específicas para Windows (usando APP_NAME)
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
WIN_TARGET_FILE := $(DIR_BIN)$(APP_NAME)
|
||||||
|
WIN_RELEASE_FILE := $(RELEASE_FOLDER)/$(APP_NAME)
|
||||||
|
else
|
||||||
|
WIN_TARGET_FILE := $(TARGET_FILE)
|
||||||
|
WIN_RELEASE_FILE := $(RELEASE_FILE)
|
||||||
|
endif
|
||||||
|
|
||||||
# Nombres para los ficheros de lanzamiento
|
# Nombres para los ficheros de lanzamiento
|
||||||
WINDOWS_RELEASE := $(TARGET_NAME)-$(VERSION)-win32-x64.zip
|
WINDOWS_RELEASE := $(TARGET_NAME)-$(VERSION)-win32-x64.zip
|
||||||
@@ -120,20 +135,24 @@ endif
|
|||||||
# Reglas para compilación
|
# Reglas para compilación
|
||||||
windows:
|
windows:
|
||||||
@echo off
|
@echo off
|
||||||
|
@echo Compilando para Windows con nombre: "$(APP_NAME).exe"
|
||||||
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 "$(TARGET_FILE).exe"
|
$(CXX) $(APP_SOURCES) $(RESOURCE_FILE) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(WIN_TARGET_FILE).exe"
|
||||||
strip -s -R .comment -R .gnu.version "$(TARGET_FILE).exe" --strip-unneeded
|
strip -s -R .comment -R .gnu.version "$(WIN_TARGET_FILE).exe" --strip-unneeded
|
||||||
|
|
||||||
windows_rec:
|
windows_rec:
|
||||||
@echo off
|
@echo off
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DRECORDING $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)_rec.exe"
|
@echo Compilando version de grabacion para Windows: "$(APP_NAME)_rec.exe"
|
||||||
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DRECORDING $(CXXFLAGS) $(LDFLAGS) -o "$(WIN_TARGET_FILE)_rec.exe"
|
||||||
|
|
||||||
windows_debug:
|
windows_debug:
|
||||||
@echo off
|
@echo off
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_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"
|
||||||
|
|
||||||
windows_release:
|
windows_release:
|
||||||
@echo off
|
@echo off
|
||||||
|
@echo Creando release para Windows - Version: $(VERSION)
|
||||||
|
|
||||||
# Crea carpeta temporal 'RELEASE_FOLDER'
|
# Crea carpeta temporal 'RELEASE_FOLDER'
|
||||||
powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force}
|
powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force}
|
||||||
@@ -149,23 +168,27 @@ windows_release:
|
|||||||
|
|
||||||
# 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 "$(RELEASE_FILE).exe"
|
$(CXX) $(APP_SOURCES) $(RESOURCE_FILE) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(WIN_RELEASE_FILE).exe"
|
||||||
strip -s -R .comment -R .gnu.version "$(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
|
||||||
powershell if (Test-Path "$(WINDOWS_RELEASE)") {Remove-Item "$(WINDOWS_RELEASE)"}
|
powershell if (Test-Path "$(WINDOWS_RELEASE)") {Remove-Item "$(WINDOWS_RELEASE)"}
|
||||||
powershell Compress-Archive -Path "$(RELEASE_FOLDER)"/* -DestinationPath "$(WINDOWS_RELEASE)"
|
powershell Compress-Archive -Path "$(RELEASE_FOLDER)"/* -DestinationPath "$(WINDOWS_RELEASE)"
|
||||||
|
@echo Release creado: $(WINDOWS_RELEASE)
|
||||||
|
|
||||||
# Elimina la carpeta temporal 'RELEASE_FOLDER'
|
# Elimina la carpeta temporal 'RELEASE_FOLDER'
|
||||||
powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force}
|
powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force}
|
||||||
|
|
||||||
macos:
|
macos:
|
||||||
|
@echo "Compilando para macOS: $(TARGET_NAME)"
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)"
|
$(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)"
|
||||||
|
|
||||||
macos_debug:
|
macos_debug:
|
||||||
|
@echo "Compilando version debug para macOS: $(TARGET_NAME)_debug"
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
||||||
|
|
||||||
macos_release:
|
macos_release:
|
||||||
|
@echo "Creando release para macOS - Version: $(VERSION)"
|
||||||
# Elimina datos de compilaciones anteriores
|
# Elimina datos de compilaciones anteriores
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
$(RMDIR) Frameworks
|
$(RMDIR) Frameworks
|
||||||
@@ -202,6 +225,7 @@ ifdef ENABLE_MACOS_X86_64
|
|||||||
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
|
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
|
||||||
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_INTEL_RELEASE)"
|
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_INTEL_RELEASE)"
|
||||||
$(RMFILE) tmp.dmg
|
$(RMFILE) tmp.dmg
|
||||||
|
@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
|
||||||
@@ -214,19 +238,23 @@ endif
|
|||||||
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
|
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
|
||||||
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_APPLE_SILICON_RELEASE)"
|
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_APPLE_SILICON_RELEASE)"
|
||||||
$(RMFILE) tmp.dmg
|
$(RMFILE) tmp.dmg
|
||||||
|
@echo "Release Apple Silicon creado: $(MACOS_APPLE_SILICON_RELEASE)"
|
||||||
|
|
||||||
# Elimina las carpetas temporales
|
# Elimina las carpetas temporales
|
||||||
$(RMDIR) Frameworks
|
$(RMDIR) Frameworks
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
linux:
|
linux:
|
||||||
|
@echo "Compilando para Linux: $(TARGET_NAME)"
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)"
|
$(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)"
|
||||||
strip -s -R .comment -R .gnu.version "$(TARGET_FILE)" --strip-unneeded
|
strip -s -R .comment -R .gnu.version "$(TARGET_FILE)" --strip-unneeded
|
||||||
|
|
||||||
linux_debug:
|
linux_debug:
|
||||||
|
@echo "Compilando version debug para Linux: $(TARGET_NAME)_debug"
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DDEBUG -DVERBOSE $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
||||||
|
|
||||||
linux_release:
|
linux_release:
|
||||||
|
@echo "Creando release para Linux - Version: $(VERSION)"
|
||||||
# Elimina carpetas previas
|
# Elimina carpetas previas
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
@@ -245,18 +273,117 @@ linux_release:
|
|||||||
# Empaqueta ficheros
|
# Empaqueta ficheros
|
||||||
$(RMFILE) "$(LINUX_RELEASE)"
|
$(RMFILE) "$(LINUX_RELEASE)"
|
||||||
tar -czvf "$(LINUX_RELEASE)" -C "$(RELEASE_FOLDER)" .
|
tar -czvf "$(LINUX_RELEASE)" -C "$(RELEASE_FOLDER)" .
|
||||||
|
@echo "Release creado: $(LINUX_RELEASE)"
|
||||||
|
|
||||||
|
# Elimina la carpeta temporal
|
||||||
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
|
linux_release_desktop:
|
||||||
|
@echo "Creando release con integracion desktop para Linux - Version: $(VERSION)"
|
||||||
|
# Elimina carpetas previas
|
||||||
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
|
# Crea la estructura de directorios estándar para Linux
|
||||||
|
$(MKDIR) "$(RELEASE_FOLDER)/$(TARGET_NAME)"
|
||||||
|
$(MKDIR) "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin"
|
||||||
|
$(MKDIR) "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications"
|
||||||
|
$(MKDIR) "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps"
|
||||||
|
$(MKDIR) "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/$(TARGET_NAME)"
|
||||||
|
|
||||||
|
# Copia ficheros del juego
|
||||||
|
cp -R data "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/$(TARGET_NAME)/"
|
||||||
|
cp LICENSE "$(RELEASE_FOLDER)/$(TARGET_NAME)/"
|
||||||
|
cp README.md "$(RELEASE_FOLDER)/$(TARGET_NAME)/"
|
||||||
|
|
||||||
|
# Compila el ejecutable
|
||||||
|
$(CXX) $(APP_SOURCES) $(INCLUDES) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin/$(TARGET_NAME)"
|
||||||
|
strip -s -R .comment -R .gnu.version "$(RELEASE_FOLDER)/$(TARGET_NAME)/bin/$(TARGET_NAME)" --strip-unneeded
|
||||||
|
|
||||||
|
# Crea el archivo .desktop
|
||||||
|
@echo '[Desktop Entry]' > "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
|
||||||
|
@echo 'Version=1.0' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
|
||||||
|
@echo 'Type=Application' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
|
||||||
|
@echo 'Name=$(APP_NAME)' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
|
||||||
|
@echo 'Comment=Arcade action game - defend Earth from alien invasion!' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
|
||||||
|
@echo 'Exec=/opt/$(TARGET_NAME)/bin/$(TARGET_NAME)' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
|
||||||
|
@echo 'Icon=$(TARGET_NAME)' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
|
||||||
|
@echo 'Path=/opt/$(TARGET_NAME)/share/$(TARGET_NAME)' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
|
||||||
|
@echo 'Terminal=false' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
|
||||||
|
@echo 'StartupNotify=true' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
|
||||||
|
@echo 'Categories=Game;ArcadeGame;' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
|
||||||
|
@echo 'Keywords=arcade;action;shooter;retro;' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop"
|
||||||
|
|
||||||
|
# Copia el icono (si existe) y lo redimensiona si es necesario
|
||||||
|
@if [ -f "release/icon.png" ]; then \
|
||||||
|
if command -v magick >/dev/null 2>&1; then \
|
||||||
|
magick "release/icon.png" -resize 256x256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
|
||||||
|
echo "Icono redimensionado de release/icon.png (usando ImageMagick)"; \
|
||||||
|
elif command -v convert >/dev/null 2>&1; then \
|
||||||
|
convert "release/icon.png" -resize 256x256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
|
||||||
|
echo "Icono redimensionado de release/icon.png (usando ImageMagick legacy)"; \
|
||||||
|
elif command -v ffmpeg >/dev/null 2>&1; then \
|
||||||
|
ffmpeg -i "release/icon.png" -vf scale=256:256 "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png" -y -loglevel quiet; \
|
||||||
|
echo "Icono redimensionado de release/icon.png (usando ffmpeg)"; \
|
||||||
|
else \
|
||||||
|
cp "release/icon.png" "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
|
||||||
|
echo "Icono copiado sin redimensionar (instalar ImageMagick o ffmpeg para redimensionado automatico)"; \
|
||||||
|
fi; \
|
||||||
|
elif [ -f "release/coffee.png" ]; then \
|
||||||
|
cp "release/coffee.png" "$(RELEASE_FOLDER)/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png"; \
|
||||||
|
echo "Icono copiado desde release/coffee.png"; \
|
||||||
|
else \
|
||||||
|
echo "Advertencia: No se encontró release/icon.png ni release/coffee.png - crear icono manualmente"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Crea script de instalación
|
||||||
|
@echo '#!/bin/bash' > "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'echo "Instalando $(APP_NAME)..."' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'sudo mkdir -p /opt/$(TARGET_NAME)' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'sudo cp -R bin /opt/$(TARGET_NAME)/' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'sudo cp -R share /opt/$(TARGET_NAME)/' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'sudo cp LICENSE /opt/$(TARGET_NAME)/' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'sudo cp README.md /opt/$(TARGET_NAME)/' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'sudo mkdir -p /usr/share/applications' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'sudo mkdir -p /usr/share/icons/hicolor/256x256/apps' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'sudo cp /opt/$(TARGET_NAME)/share/applications/$(TARGET_NAME).desktop /usr/share/applications/' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'sudo cp /opt/$(TARGET_NAME)/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png /usr/share/icons/hicolor/256x256/apps/' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'sudo update-desktop-database /usr/share/applications 2>/dev/null || true' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'sudo gtk-update-icon-cache /usr/share/icons/hicolor 2>/dev/null || true' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'echo "$(APP_NAME) instalado correctamente!"' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
@echo 'echo "Ya puedes encontrarlo en el menu de aplicaciones en la categoria Juegos."' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
chmod +x "$(RELEASE_FOLDER)/$(TARGET_NAME)/install.sh"
|
||||||
|
|
||||||
|
# Crea script de desinstalación
|
||||||
|
@echo '#!/bin/bash' > "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
|
||||||
|
@echo 'echo "Desinstalando $(APP_NAME)..."' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
|
||||||
|
@echo 'sudo rm -rf /opt/$(TARGET_NAME)' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
|
||||||
|
@echo 'sudo rm -f /usr/share/applications/$(TARGET_NAME).desktop' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
|
||||||
|
@echo 'sudo rm -f /usr/share/icons/hicolor/256x256/apps/$(TARGET_NAME).png' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
|
||||||
|
@echo 'sudo update-desktop-database /usr/share/applications 2>/dev/null || true' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
|
||||||
|
@echo 'sudo gtk-update-icon-cache /usr/share/icons/hicolor 2>/dev/null || true' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
|
||||||
|
@echo 'echo "$(APP_NAME) desinstalado correctamente."' >> "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
|
||||||
|
chmod +x "$(RELEASE_FOLDER)/$(TARGET_NAME)/uninstall.sh"
|
||||||
|
|
||||||
|
# Empaqueta ficheros
|
||||||
|
$(RMFILE) "$(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz"
|
||||||
|
tar -czvf "$(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz" -C "$(RELEASE_FOLDER)" .
|
||||||
|
@echo "Release con integracion desktop creado: $(TARGET_NAME)-$(VERSION)-linux-desktop.tar.gz"
|
||||||
|
@echo "Para instalar: extraer y ejecutar ./$(TARGET_NAME)/install.sh"
|
||||||
|
|
||||||
# Elimina la carpeta temporal
|
# Elimina la carpeta temporal
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
raspi:
|
raspi:
|
||||||
|
@echo "Compilando para Raspberry Pi: $(TARGET_NAME)"
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(TARGET_FILE)
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(TARGET_FILE)
|
||||||
strip -s -R .comment -R .gnu.version $(TARGET_FILE) --strip-unneeded
|
strip -s -R .comment -R .gnu.version $(TARGET_FILE) --strip-unneeded
|
||||||
|
|
||||||
raspi_debug:
|
raspi_debug:
|
||||||
|
@echo "Compilando version debug para Raspberry Pi: $(TARGET_NAME)_debug"
|
||||||
$(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE -DDEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
$(CXX) $(APP_SOURCES) $(INCLUDES) -DVERBOSE -DDEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
||||||
|
|
||||||
raspi_release:
|
raspi_release:
|
||||||
|
@echo "Creando release para Raspberry Pi - Version: $(VERSION)"
|
||||||
# Elimina carpetas previas
|
# Elimina carpetas previas
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
@@ -275,11 +402,13 @@ raspi_release:
|
|||||||
# Empaqueta ficheros
|
# Empaqueta ficheros
|
||||||
$(RMFILE) "$(RASPI_RELEASE)"
|
$(RMFILE) "$(RASPI_RELEASE)"
|
||||||
tar -czvf "$(RASPI_RELEASE)" -C "$(RELEASE_FOLDER)" .
|
tar -czvf "$(RASPI_RELEASE)" -C "$(RELEASE_FOLDER)" .
|
||||||
|
@echo "Release creado: $(RASPI_RELEASE)"
|
||||||
|
|
||||||
# Elimina la carpeta temporal
|
# Elimina la carpeta temporal
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||||
|
|
||||||
anbernic:
|
anbernic:
|
||||||
|
@echo "Compilando para Anbernic: $(TARGET_NAME)"
|
||||||
# Elimina carpetas previas
|
# Elimina carpetas previas
|
||||||
$(RMDIR) "$(RELEASE_FOLDER)"_anbernic
|
$(RMDIR) "$(RELEASE_FOLDER)"_anbernic
|
||||||
|
|
||||||
@@ -294,6 +423,32 @@ anbernic:
|
|||||||
|
|
||||||
# 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:
|
||||||
|
@echo "Compilando sin audio: $(TARGET_NAME)_no_audio"
|
||||||
$(CXX) $(filter-out source/external/jail_audio.cpp,$(APP_SOURCES)) $(INCLUDES) -DNO_AUDIO $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)_no_audio"
|
$(CXX) $(filter-out source/external/jail_audio.cpp,$(APP_SOURCES)) $(INCLUDES) -DNO_AUDIO $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)_no_audio"
|
||||||
|
|
||||||
.PHONY: windows windows_rec windows_debug windows_release macos macos_debug macos_release linux linux_debug linux_release raspi raspi_debug raspi_release anbernic no_audio
|
# Regla para mostrar la versión actual
|
||||||
|
show_version:
|
||||||
|
@echo "Version actual: $(VERSION)"
|
||||||
|
|
||||||
|
# Regla de ayuda
|
||||||
|
help:
|
||||||
|
@echo "Makefile para Coffee Crisis Arcade Edition"
|
||||||
|
@echo "Comandos disponibles:"
|
||||||
|
@echo " windows - Compilar para Windows"
|
||||||
|
@echo " windows_debug - Compilar debug para Windows"
|
||||||
|
@echo " windows_release - Crear release completo para Windows"
|
||||||
|
@echo " linux - Compilar para Linux"
|
||||||
|
@echo " linux_debug - Compilar debug para Linux"
|
||||||
|
@echo " linux_release - Crear release basico para Linux"
|
||||||
|
@echo " linux_release_desktop - Crear release con integracion desktop para Linux"
|
||||||
|
@echo " macos - Compilar para macOS"
|
||||||
|
@echo " macos_debug - Compilar debug para macOS"
|
||||||
|
@echo " macos_release - Crear release completo para macOS"
|
||||||
|
@echo " raspi - Compilar para Raspberry Pi"
|
||||||
|
@echo " raspi_release - Crear release completo para Raspberry Pi"
|
||||||
|
@echo " anbernic - Compilar para Anbernic"
|
||||||
|
@echo " no_audio - Compilar sin sistema de audio"
|
||||||
|
@echo " show_version - Mostrar version actual ($(VERSION))"
|
||||||
|
@echo " help - Mostrar esta ayuda"
|
||||||
|
|
||||||
|
.PHONY: 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
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Coffee Crisis - Asset Configuration
|
# Coffee Crisis Arcade Edition - Asset Configuration
|
||||||
# Formato: TIPO|RUTA [|OPCIONES]
|
# Formato: TIPO|RUTA [|OPCIONES]
|
||||||
# Opciones: optional, absolute (separadas por comas)
|
# Opciones: optional, absolute (separadas por comas)
|
||||||
# Variables: ${PREFIX}, ${SYSTEM_FOLDER}
|
# Variables: ${PREFIX}, ${SYSTEM_FOLDER}
|
||||||
@@ -9,33 +9,35 @@ DATA|${SYSTEM_FOLDER}/controllers.json|optional,absolute
|
|||||||
DATA|${SYSTEM_FOLDER}/score.bin|optional,absolute
|
DATA|${SYSTEM_FOLDER}/score.bin|optional,absolute
|
||||||
|
|
||||||
# Archivos de configuración del juego
|
# Archivos de configuración del juego
|
||||||
|
DATA|${PREFIX}/data/config/formations.txt
|
||||||
|
DATA|${PREFIX}/data/config/gamecontrollerdb.txt
|
||||||
DATA|${PREFIX}/data/config/param_320x240.txt
|
DATA|${PREFIX}/data/config/param_320x240.txt
|
||||||
DATA|${PREFIX}/data/config/param_320x256.txt
|
DATA|${PREFIX}/data/config/param_320x256.txt
|
||||||
|
DATA|${PREFIX}/data/config/pools.txt
|
||||||
|
DATA|${PREFIX}/data/config/stages.txt
|
||||||
DEMODATA|${PREFIX}/data/config/demo1.bin
|
DEMODATA|${PREFIX}/data/config/demo1.bin
|
||||||
DEMODATA|${PREFIX}/data/config/demo2.bin
|
DEMODATA|${PREFIX}/data/config/demo2.bin
|
||||||
DATA|${PREFIX}/data/config/gamecontrollerdb.txt
|
|
||||||
DATA|${PREFIX}/data/config/formations.txt
|
|
||||||
DATA|${PREFIX}/data/config/pools.txt
|
|
||||||
|
|
||||||
# Música
|
# Música
|
||||||
|
MUSIC|${PREFIX}/data/music/credits.ogg
|
||||||
MUSIC|${PREFIX}/data/music/intro.ogg
|
MUSIC|${PREFIX}/data/music/intro.ogg
|
||||||
MUSIC|${PREFIX}/data/music/playing.ogg
|
MUSIC|${PREFIX}/data/music/playing.ogg
|
||||||
MUSIC|${PREFIX}/data/music/title.ogg
|
MUSIC|${PREFIX}/data/music/title.ogg
|
||||||
MUSIC|${PREFIX}/data/music/credits.ogg
|
|
||||||
|
|
||||||
# Sonidos
|
# Sonidos
|
||||||
SOUND|${PREFIX}/data/sound/balloon_pop0.wav
|
|
||||||
SOUND|${PREFIX}/data/sound/balloon_pop1.wav
|
|
||||||
SOUND|${PREFIX}/data/sound/balloon_pop2.wav
|
|
||||||
SOUND|${PREFIX}/data/sound/balloon_pop3.wav
|
|
||||||
SOUND|${PREFIX}/data/sound/balloon_bounce0.wav
|
SOUND|${PREFIX}/data/sound/balloon_bounce0.wav
|
||||||
SOUND|${PREFIX}/data/sound/balloon_bounce1.wav
|
SOUND|${PREFIX}/data/sound/balloon_bounce1.wav
|
||||||
SOUND|${PREFIX}/data/sound/balloon_bounce2.wav
|
SOUND|${PREFIX}/data/sound/balloon_bounce2.wav
|
||||||
SOUND|${PREFIX}/data/sound/balloon_bounce3.wav
|
SOUND|${PREFIX}/data/sound/balloon_bounce3.wav
|
||||||
|
SOUND|${PREFIX}/data/sound/balloon_pop0.wav
|
||||||
|
SOUND|${PREFIX}/data/sound/balloon_pop1.wav
|
||||||
|
SOUND|${PREFIX}/data/sound/balloon_pop2.wav
|
||||||
|
SOUND|${PREFIX}/data/sound/balloon_pop3.wav
|
||||||
SOUND|${PREFIX}/data/sound/bullet.wav
|
SOUND|${PREFIX}/data/sound/bullet.wav
|
||||||
SOUND|${PREFIX}/data/sound/clock.wav
|
SOUND|${PREFIX}/data/sound/clock.wav
|
||||||
SOUND|${PREFIX}/data/sound/coffee_out.wav
|
SOUND|${PREFIX}/data/sound/coffee_out.wav
|
||||||
SOUND|${PREFIX}/data/sound/continue_clock.wav
|
SOUND|${PREFIX}/data/sound/continue_clock.wav
|
||||||
|
SOUND|${PREFIX}/data/sound/credit.wav
|
||||||
SOUND|${PREFIX}/data/sound/debian_drop.wav
|
SOUND|${PREFIX}/data/sound/debian_drop.wav
|
||||||
SOUND|${PREFIX}/data/sound/debian_pickup.wav
|
SOUND|${PREFIX}/data/sound/debian_pickup.wav
|
||||||
SOUND|${PREFIX}/data/sound/hi_score_achieved.wav
|
SOUND|${PREFIX}/data/sound/hi_score_achieved.wav
|
||||||
@@ -54,7 +56,9 @@ SOUND|${PREFIX}/data/sound/tabe_hit.wav
|
|||||||
SOUND|${PREFIX}/data/sound/tabe.wav
|
SOUND|${PREFIX}/data/sound/tabe.wav
|
||||||
SOUND|${PREFIX}/data/sound/title.wav
|
SOUND|${PREFIX}/data/sound/title.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_aw_aw_aw.wav
|
SOUND|${PREFIX}/data/sound/voice_aw_aw_aw.wav
|
||||||
|
SOUND|${PREFIX}/data/sound/voice_brbrbr.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_coffee.wav
|
SOUND|${PREFIX}/data/sound/voice_coffee.wav
|
||||||
|
SOUND|${PREFIX}/data/sound/voice_credit_thankyou.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_get_ready.wav
|
SOUND|${PREFIX}/data/sound/voice_get_ready.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_no.wav
|
SOUND|${PREFIX}/data/sound/voice_no.wav
|
||||||
SOUND|${PREFIX}/data/sound/voice_power_up.wav
|
SOUND|${PREFIX}/data/sound/voice_power_up.wav
|
||||||
@@ -62,50 +66,50 @@ SOUND|${PREFIX}/data/sound/voice_thankyou.wav
|
|||||||
SOUND|${PREFIX}/data/sound/walk.wav
|
SOUND|${PREFIX}/data/sound/walk.wav
|
||||||
|
|
||||||
# Shaders
|
# Shaders
|
||||||
DATA|${PREFIX}/data/shaders/crtpi_256.glsl
|
|
||||||
DATA|${PREFIX}/data/shaders/crtpi_240.glsl
|
DATA|${PREFIX}/data/shaders/crtpi_240.glsl
|
||||||
|
DATA|${PREFIX}/data/shaders/crtpi_256.glsl
|
||||||
|
|
||||||
# Texturas - Balloons
|
# Texturas - Balloons
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/balloon0.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/balloon0.ani
|
ANIMATION|${PREFIX}/data/gfx/balloon/balloon0.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/balloon1.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/balloon1.ani
|
ANIMATION|${PREFIX}/data/gfx/balloon/balloon1.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/balloon2.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/balloon2.ani
|
ANIMATION|${PREFIX}/data/gfx/balloon/balloon2.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/balloon3.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/balloon3.ani
|
ANIMATION|${PREFIX}/data/gfx/balloon/balloon3.ani
|
||||||
|
BITMAP|${PREFIX}/data/gfx/balloon/balloon0.png
|
||||||
|
BITMAP|${PREFIX}/data/gfx/balloon/balloon1.png
|
||||||
|
BITMAP|${PREFIX}/data/gfx/balloon/balloon2.png
|
||||||
|
BITMAP|${PREFIX}/data/gfx/balloon/balloon3.png
|
||||||
|
|
||||||
# Texturas - Explosiones
|
# Texturas - Explosiones
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/explosion0.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/explosion0.ani
|
ANIMATION|${PREFIX}/data/gfx/balloon/explosion0.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/explosion1.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/explosion1.ani
|
ANIMATION|${PREFIX}/data/gfx/balloon/explosion1.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/explosion2.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/explosion2.ani
|
ANIMATION|${PREFIX}/data/gfx/balloon/explosion2.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/explosion3.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/explosion3.ani
|
ANIMATION|${PREFIX}/data/gfx/balloon/explosion3.ani
|
||||||
|
BITMAP|${PREFIX}/data/gfx/balloon/explosion0.png
|
||||||
|
BITMAP|${PREFIX}/data/gfx/balloon/explosion1.png
|
||||||
|
BITMAP|${PREFIX}/data/gfx/balloon/explosion2.png
|
||||||
|
BITMAP|${PREFIX}/data/gfx/balloon/explosion3.png
|
||||||
|
|
||||||
# Texturas - Power Ball
|
# Texturas - Power Ball
|
||||||
BITMAP|${PREFIX}/data/gfx/balloon/powerball.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/balloon/powerball.ani
|
ANIMATION|${PREFIX}/data/gfx/balloon/powerball.ani
|
||||||
|
BITMAP|${PREFIX}/data/gfx/balloon/powerball.png
|
||||||
|
|
||||||
# Texturas - Bala
|
# Texturas - Bala
|
||||||
BITMAP|${PREFIX}/data/gfx/bullet/bullet.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/bullet/bullet.ani
|
ANIMATION|${PREFIX}/data/gfx/bullet/bullet.ani
|
||||||
|
BITMAP|${PREFIX}/data/gfx/bullet/bullet.png
|
||||||
|
|
||||||
# Texturas - Tabe
|
# Texturas - Tabe
|
||||||
BITMAP|${PREFIX}/data/gfx/tabe/tabe.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/tabe/tabe.ani
|
ANIMATION|${PREFIX}/data/gfx/tabe/tabe.ani
|
||||||
|
BITMAP|${PREFIX}/data/gfx/tabe/tabe.png
|
||||||
|
|
||||||
# Texturas - Juego
|
# Texturas - Juego
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_buildings.png
|
BITMAP|${PREFIX}/data/gfx/game/game_buildings.png
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_clouds1.png
|
BITMAP|${PREFIX}/data/gfx/game/game_clouds1.png
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_clouds2.png
|
BITMAP|${PREFIX}/data/gfx/game/game_clouds2.png
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_grass.png
|
BITMAP|${PREFIX}/data/gfx/game/game_grass.png
|
||||||
|
BITMAP|${PREFIX}/data/gfx/game/game_moon.png
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_power_meter.png
|
BITMAP|${PREFIX}/data/gfx/game/game_power_meter.png
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_sky_colors.png
|
BITMAP|${PREFIX}/data/gfx/game/game_sky_colors.png
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_sun.png
|
BITMAP|${PREFIX}/data/gfx/game/game_sun.png
|
||||||
BITMAP|${PREFIX}/data/gfx/game/game_moon.png
|
|
||||||
|
|
||||||
# Texturas - Intro
|
# Texturas - Intro
|
||||||
BITMAP|${PREFIX}/data/gfx/intro/intro1.png
|
BITMAP|${PREFIX}/data/gfx/intro/intro1.png
|
||||||
@@ -116,75 +120,75 @@ BITMAP|${PREFIX}/data/gfx/intro/intro5.png
|
|||||||
BITMAP|${PREFIX}/data/gfx/intro/intro6.png
|
BITMAP|${PREFIX}/data/gfx/intro/intro6.png
|
||||||
|
|
||||||
# Texturas - Logo
|
# Texturas - Logo
|
||||||
BITMAP|${PREFIX}/data/gfx/logo/logo_jailgames.png
|
|
||||||
BITMAP|${PREFIX}/data/gfx/logo/logo_jailgames_mini.png
|
BITMAP|${PREFIX}/data/gfx/logo/logo_jailgames_mini.png
|
||||||
|
BITMAP|${PREFIX}/data/gfx/logo/logo_jailgames.png
|
||||||
BITMAP|${PREFIX}/data/gfx/logo/logo_since_1998.png
|
BITMAP|${PREFIX}/data/gfx/logo/logo_since_1998.png
|
||||||
|
|
||||||
# Texturas - Items
|
# Texturas - Items
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_points1_disk.png
|
ANIMATION|${PREFIX}/data/gfx/item/item_clock.ani
|
||||||
|
ANIMATION|${PREFIX}/data/gfx/item/item_coffee_machine.ani
|
||||||
|
ANIMATION|${PREFIX}/data/gfx/item/item_coffee.ani
|
||||||
|
ANIMATION|${PREFIX}/data/gfx/item/item_debian.ani
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_points1_disk.ani
|
ANIMATION|${PREFIX}/data/gfx/item/item_points1_disk.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_points2_gavina.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_points2_gavina.ani
|
ANIMATION|${PREFIX}/data/gfx/item/item_points2_gavina.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_points3_pacmar.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_points3_pacmar.ani
|
ANIMATION|${PREFIX}/data/gfx/item/item_points3_pacmar.ani
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_clock.png
|
BITMAP|${PREFIX}/data/gfx/item/item_clock.png
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_clock.ani
|
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_coffee.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_coffee.ani
|
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_debian.png
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_debian.ani
|
|
||||||
BITMAP|${PREFIX}/data/gfx/item/item_coffee_machine.png
|
BITMAP|${PREFIX}/data/gfx/item/item_coffee_machine.png
|
||||||
ANIMATION|${PREFIX}/data/gfx/item/item_coffee_machine.ani
|
BITMAP|${PREFIX}/data/gfx/item/item_coffee.png
|
||||||
|
BITMAP|${PREFIX}/data/gfx/item/item_debian.png
|
||||||
|
BITMAP|${PREFIX}/data/gfx/item/item_points1_disk.png
|
||||||
|
BITMAP|${PREFIX}/data/gfx/item/item_points2_gavina.png
|
||||||
|
BITMAP|${PREFIX}/data/gfx/item/item_points3_pacmar.png
|
||||||
|
|
||||||
# Texturas - Titulo
|
# Texturas - Titulo
|
||||||
|
ANIMATION|${PREFIX}/data/gfx/title/title_dust.ani
|
||||||
|
BITMAP|${PREFIX}/data/gfx/title/title_arcade_edition.png
|
||||||
BITMAP|${PREFIX}/data/gfx/title/title_bg_tile.png
|
BITMAP|${PREFIX}/data/gfx/title/title_bg_tile.png
|
||||||
BITMAP|${PREFIX}/data/gfx/title/title_coffee.png
|
BITMAP|${PREFIX}/data/gfx/title/title_coffee.png
|
||||||
BITMAP|${PREFIX}/data/gfx/title/title_crisis.png
|
BITMAP|${PREFIX}/data/gfx/title/title_crisis.png
|
||||||
BITMAP|${PREFIX}/data/gfx/title/title_arcade_edition.png
|
|
||||||
BITMAP|${PREFIX}/data/gfx/title/title_dust.png
|
BITMAP|${PREFIX}/data/gfx/title/title_dust.png
|
||||||
ANIMATION|${PREFIX}/data/gfx/title/title_dust.ani
|
|
||||||
|
|
||||||
# Texturas - Jugador 1
|
# Texturas - Jugador 1
|
||||||
|
BITMAP|${PREFIX}/data/gfx/player/player1_power.png
|
||||||
BITMAP|${PREFIX}/data/gfx/player/player1.gif
|
BITMAP|${PREFIX}/data/gfx/player/player1.gif
|
||||||
PALETTE|${PREFIX}/data/gfx/player/player1_coffee1.pal
|
PALETTE|${PREFIX}/data/gfx/player/player1_coffee1.pal
|
||||||
PALETTE|${PREFIX}/data/gfx/player/player1_coffee2.pal
|
PALETTE|${PREFIX}/data/gfx/player/player1_coffee2.pal
|
||||||
PALETTE|${PREFIX}/data/gfx/player/player1_invencible.pal
|
PALETTE|${PREFIX}/data/gfx/player/player1_invencible.pal
|
||||||
BITMAP|${PREFIX}/data/gfx/player/player1_power.png
|
|
||||||
|
|
||||||
# Texturas - Jugador 2
|
# Texturas - Jugador 2
|
||||||
|
BITMAP|${PREFIX}/data/gfx/player/player2_power.png
|
||||||
BITMAP|${PREFIX}/data/gfx/player/player2.gif
|
BITMAP|${PREFIX}/data/gfx/player/player2.gif
|
||||||
PALETTE|${PREFIX}/data/gfx/player/player2_coffee1.pal
|
PALETTE|${PREFIX}/data/gfx/player/player2_coffee1.pal
|
||||||
PALETTE|${PREFIX}/data/gfx/player/player2_coffee2.pal
|
PALETTE|${PREFIX}/data/gfx/player/player2_coffee2.pal
|
||||||
PALETTE|${PREFIX}/data/gfx/player/player2_invencible.pal
|
PALETTE|${PREFIX}/data/gfx/player/player2_invencible.pal
|
||||||
BITMAP|${PREFIX}/data/gfx/player/player2_power.png
|
|
||||||
|
|
||||||
# Animaciones del jugador
|
# Animaciones del jugador
|
||||||
ANIMATION|${PREFIX}/data/gfx/player/player.ani
|
|
||||||
ANIMATION|${PREFIX}/data/gfx/player/player_power.ani
|
ANIMATION|${PREFIX}/data/gfx/player/player_power.ani
|
||||||
|
ANIMATION|${PREFIX}/data/gfx/player/player.ani
|
||||||
|
|
||||||
# Texturas - Golpe del jugador
|
# Texturas - Golpe del jugador
|
||||||
BITMAP|${PREFIX}/data/gfx/player/hit.png
|
BITMAP|${PREFIX}/data/gfx/player/hit.png
|
||||||
|
|
||||||
# Fuentes de texto
|
# Fuentes de texto
|
||||||
BITMAP|${PREFIX}/data/font/8bithud.png
|
|
||||||
FONT|${PREFIX}/data/font/8bithud.txt
|
|
||||||
BITMAP|${PREFIX}/data/font/aseprite.png
|
|
||||||
FONT|${PREFIX}/data/font/aseprite.txt
|
|
||||||
BITMAP|${PREFIX}/data/font/smb2.png
|
|
||||||
BITMAP|${PREFIX}/data/font/smb2_grad.png
|
|
||||||
FONT|${PREFIX}/data/font/smb2.txt
|
|
||||||
BITMAP|${PREFIX}/data/font/04b_25.png
|
|
||||||
FONT|${PREFIX}/data/font/04b_25.txt
|
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_2x.png
|
BITMAP|${PREFIX}/data/font/04b_25_2x.png
|
||||||
FONT|${PREFIX}/data/font/04b_25_2x.txt
|
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_metal.png
|
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_grey.png
|
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_flat.png
|
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_reversed.png
|
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_flat_2x.png
|
BITMAP|${PREFIX}/data/font/04b_25_flat_2x.png
|
||||||
|
BITMAP|${PREFIX}/data/font/04b_25_flat.png
|
||||||
|
BITMAP|${PREFIX}/data/font/04b_25_grey.png
|
||||||
|
BITMAP|${PREFIX}/data/font/04b_25_metal.png
|
||||||
BITMAP|${PREFIX}/data/font/04b_25_reversed_2x.png
|
BITMAP|${PREFIX}/data/font/04b_25_reversed_2x.png
|
||||||
|
BITMAP|${PREFIX}/data/font/04b_25_reversed.png
|
||||||
|
BITMAP|${PREFIX}/data/font/04b_25.png
|
||||||
|
BITMAP|${PREFIX}/data/font/8bithud.png
|
||||||
|
BITMAP|${PREFIX}/data/font/aseprite.png
|
||||||
|
BITMAP|${PREFIX}/data/font/smb2_grad.png
|
||||||
|
BITMAP|${PREFIX}/data/font/smb2.png
|
||||||
|
FONT|${PREFIX}/data/font/04b_25_2x.txt
|
||||||
|
FONT|${PREFIX}/data/font/04b_25.txt
|
||||||
|
FONT|${PREFIX}/data/font/8bithud.txt
|
||||||
|
FONT|${PREFIX}/data/font/aseprite.txt
|
||||||
|
FONT|${PREFIX}/data/font/smb2.txt
|
||||||
|
|
||||||
# Idiomas
|
# Idiomas
|
||||||
LANG|${PREFIX}/data/lang/es_ES.json
|
LANG|${PREFIX}/data/lang/ba_BA.json
|
||||||
LANG|${PREFIX}/data/lang/en_UK.json
|
LANG|${PREFIX}/data/lang/en_UK.json
|
||||||
LANG|${PREFIX}/data/lang/ba_BA.json
|
LANG|${PREFIX}/data/lang/es_ES.json
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Archivo de configuración de formaciones de globos
|
# Coffee Crisis Arcade Edition - Archivo de configuración de formaciones de globos
|
||||||
# Formato por línea: x, desp, y, vel_x, tipo, tamaño, retraso_tiempo_creacion
|
# Formato por línea: x, desp, y, vel_x, tipo, tamaño, retraso_tiempo_creacion
|
||||||
# Variables disponibles:
|
# Variables disponibles:
|
||||||
# X0_0, X0_50, X0_100, X1_0, X1_100, X2_0, X2_100, X3_0, X3_100
|
# X0_0, X0_50, X0_100, X1_0, X1_100, X2_0, X2_100, X3_0, X3_100
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
## --- GAME ---
|
# Coffee Crisis Arcade Edition - Fichero de parametros
|
||||||
|
# Formato: PARAMETRO VALOR
|
||||||
|
|
||||||
|
# --- GAME ---
|
||||||
game.item_size 20 # Tamaño de los items del juego (en píxeles)
|
game.item_size 20 # Tamaño de los items del juego (en píxeles)
|
||||||
game.width 320 # Ancho de la resolución nativa del juego (en píxeles)
|
game.width 320 # Ancho de la resolución nativa del juego (en píxeles)
|
||||||
game.height 240 # Alto de la resolución nativa del juego (en píxeles)
|
game.height 240 # Alto de la resolución nativa del juego (en píxeles)
|
||||||
@@ -11,7 +14,7 @@ game.name_entry_total_time 60 # Segundos totales para introducir el nombre
|
|||||||
game.hit_stop false # Indica si debe haber un paro cuando el jugador es golpeado por un globo
|
game.hit_stop false # Indica si debe haber un paro cuando el jugador es golpeado por un globo
|
||||||
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
|
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
|
||||||
|
|
||||||
## --- FADE ---
|
# --- FADE ---
|
||||||
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido
|
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido
|
||||||
fade.num_squares_width 160 # Número de cuadrados en el eje X para el fundido
|
fade.num_squares_width 160 # Número de cuadrados en el eje X para el fundido
|
||||||
fade.num_squares_height 120 # Número de cuadrados en el eje Y para el fundido
|
fade.num_squares_height 120 # Número de cuadrados en el eje Y para el fundido
|
||||||
@@ -20,7 +23,7 @@ fade.random_squares_mult 500 # Multiplicador para la velocidad de aparici
|
|||||||
fade.post_duration 80 # Duración tras el fundido (frames)
|
fade.post_duration 80 # Duración tras el fundido (frames)
|
||||||
fade.venetian_size 12 # Tamaño de las bandas para el efecto veneciano (en píxeles)
|
fade.venetian_size 12 # Tamaño de las bandas para el efecto veneciano (en píxeles)
|
||||||
|
|
||||||
## --- SCOREBOARD ---
|
# --- SCOREBOARD ---
|
||||||
scoreboard.rect.x 0 # Posición X del marcador
|
scoreboard.rect.x 0 # Posición X del marcador
|
||||||
scoreboard.rect.y 216 # Posición Y del marcador
|
scoreboard.rect.y 216 # Posición Y del marcador
|
||||||
scoreboard.rect.w 320 # Ancho del marcador
|
scoreboard.rect.w 320 # Ancho del marcador
|
||||||
@@ -35,17 +38,17 @@ scoreboard.text_color1 FFFFFF # Color principal del texto del marcad
|
|||||||
scoreboard.text_color2 FFFFFF # Color secundario del texto del marcador
|
scoreboard.text_color2 FFFFFF # Color secundario del texto del marcador
|
||||||
scoreboard.skip_countdown_value 8 # Valor para saltar la cuenta atrás (segundos)
|
scoreboard.skip_countdown_value 8 # Valor para saltar la cuenta atrás (segundos)
|
||||||
|
|
||||||
## --- TITLE ---
|
# --- TITLE ---
|
||||||
title.press_start_position 180 # Posición Y del texto "Press Start"
|
title.press_start_position 180 # Posición Y del texto "Press Start"
|
||||||
title.title_duration 800 # Duración de la pantalla de título (frames)
|
title.title_duration 800 # Duración de la pantalla de título (frames)
|
||||||
title.arcade_edition_position 123 # Posición Y del subtítulo "Arcade Edition"
|
title.arcade_edition_position 123 # Posición Y del subtítulo "Arcade Edition"
|
||||||
title.title_c_c_position 80 # Posición Y del título principal
|
title.title_c_c_position 80 # Posición Y del título principal
|
||||||
title.bg_color 41526F # Color de fondo en la sección titulo
|
title.bg_color 41526F # Color de fondo en la sección titulo
|
||||||
|
|
||||||
## --- BACKGROUND ---
|
# --- BACKGROUND ---
|
||||||
background.attenuate_color FFFFFF00 # Color de atenuación del fondo (RGBA hexadecimal)
|
background.attenuate_color FFFFFF00 # Color de atenuación del fondo (RGBA hexadecimal)
|
||||||
|
|
||||||
## --- BALLOONS ---
|
# --- BALLOONS ---
|
||||||
balloon.settings[0].vel 2.75f # Velocidad inicial del globo 1
|
balloon.settings[0].vel 2.75f # Velocidad inicial del globo 1
|
||||||
balloon.settings[0].grav 0.09f # Gravedad aplicada al globo 1
|
balloon.settings[0].grav 0.09f # Gravedad aplicada al globo 1
|
||||||
balloon.settings[1].vel 3.70f # Velocidad inicial del globo 2
|
balloon.settings[1].vel 3.70f # Velocidad inicial del globo 2
|
||||||
@@ -62,28 +65,71 @@ balloon.color[3] green # Color del globo que rebota
|
|||||||
|
|
||||||
balloon.bouncing_sound false # Indica si los globos hacer sonido al rebotar
|
balloon.bouncing_sound false # Indica si los globos hacer sonido al rebotar
|
||||||
|
|
||||||
## --- NOTIFICATION ---
|
# --- NOTIFICATION ---
|
||||||
notification.pos_v TOP # Posición vertical de la notificación (TOP/BOTTOM)
|
notification.pos_v TOP # Posición vertical de la notificación (TOP/BOTTOM)
|
||||||
notification.pos_h LEFT # Posición horizontal de la notificación (LEFT/RIGHT)
|
notification.pos_h LEFT # Posición horizontal de la notificación (LEFT/RIGHT)
|
||||||
notification.sound false # ¿La notificación reproduce sonido?
|
notification.sound false # ¿La notificación reproduce sonido?
|
||||||
notification.color 303030 # Color de fondo de la notificación (hexadecimal)
|
notification.color 303030 # Color de fondo de la notificación (hexadecimal)
|
||||||
|
|
||||||
## --- SERVICE MENU ---
|
# --- SERVICE MENU ---
|
||||||
service_menu.title_color 99FF62 # Color del título del menú de servicio
|
service_menu.title_color 99FF62 # Color del título del menú de servicio
|
||||||
service_menu.text_color FFFFFF # Color del texto del menú de servicio
|
service_menu.text_color FFFFFF # Color del texto del menú de servicio
|
||||||
service_menu.selected_color FFDC44 # Color de la opción seleccionada en el menú de servicio
|
service_menu.selected_color FFDC44 # Color de la opción seleccionada en el menú de servicio
|
||||||
service_menu.bg_color 003000F5 # Color de fondo del menú de servicio (RGBA hexadecimal)
|
service_menu.bg_color 000F00F5 # Color de fondo del menú de servicio (RGBA hexadecimal)
|
||||||
service_menu.drop_shadow false # ¿El menú de servicio tiene sombra?
|
service_menu.drop_shadow false # ¿El menú de servicio tiene sombra?
|
||||||
|
|
||||||
## --- INTRO ---
|
service_menu.window_message.bg_color 141E32F0 # Color de fondo de ventanas de mensaje (RGBA hexadecimal)
|
||||||
|
service_menu.window_message.border_color 6496C8FF # Color del borde de ventanas de mensaje (RGBA hexadecimal)
|
||||||
|
service_menu.window_message.title_color 6496C8FF # Color del título en ventanas de mensaje (RGBA hexadecimal)
|
||||||
|
service_menu.window_message.text_color DCDCDCFF # Color del texto en ventanas de mensaje (RGBA hexadecimal)
|
||||||
|
service_menu.window_message.padding 15.0f # Espaciado interno de ventanas de mensaje (píxeles)
|
||||||
|
service_menu.window_message.line_spacing 5.0f # Espaciado entre líneas de texto (píxeles)
|
||||||
|
service_menu.window_message.title_separator_spacing 10.0f # Espaciado entre título y contenido (píxeles)
|
||||||
|
service_menu.window_message.min_width 250.0f # Ancho mínimo de ventanas de mensaje (píxeles)
|
||||||
|
service_menu.window_message.min_height 32.0f # Alto mínimo de ventanas de mensaje (píxeles)
|
||||||
|
service_menu.window_message.max_width_ratio 0.8f # Ratio máximo de ancho respecto a pantalla (0.0-1.0)
|
||||||
|
service_menu.window_message.max_height_ratio 0.8f # Ratio máximo de alto respecto a pantalla (0.0-1.0)
|
||||||
|
service_menu.window_message.text_safety_margin 15.0f # Margen de seguridad para el texto (píxeles)
|
||||||
|
service_menu.window_message.animation_duration 0.3f # Duración de animaciones de ventanas (segundos)
|
||||||
|
|
||||||
|
# --- INTRO ---
|
||||||
intro.bg_color 4664BD # Color de fondo de la intro
|
intro.bg_color 4664BD # Color de fondo de la intro
|
||||||
intro.card_color CBDBFC # Color de las tarjetas en la intro
|
intro.card_color CBDBFC # Color de las tarjetas en la intro
|
||||||
intro.shadow_color 00000080 # Color de la sombra de las tarjetas en la intro
|
intro.shadow_color 00000080 # Color de la sombra de las tarjetas en la intro
|
||||||
intro.text_distance_from_bottom 48 # Posicion del texto
|
intro.text_distance_from_bottom 48 # Posicion del texto
|
||||||
|
|
||||||
## --- DEBUG ---
|
# --- DEBUG ---
|
||||||
debug.color 00FFFF # Color para elementos de depuración
|
debug.color 00FFFF # Color para elementos de depuración
|
||||||
|
|
||||||
## --- RESOURCE ---
|
# --- RESOURCE ---
|
||||||
resource.color FFFFFF # Color de recurso 1
|
resource.color FFFFFF # Color de recurso 1
|
||||||
resource.color FFFFFF # Color de recurso 2
|
resource.color FFFFFF # Color de recurso 2
|
||||||
|
|
||||||
|
# --- TABE ---
|
||||||
|
tabe.min_spawn_time 2.0f # Tiempo mínimo en minutos para que aparezca el Tabe
|
||||||
|
tabe.max_spawn_time 3.0f # Tiempo máximo en minutos para que aparezca el Tabe
|
||||||
|
|
||||||
|
# --- PLAYER ---
|
||||||
|
# Jugador 1 - Camiseta con 1 café
|
||||||
|
player.one_coffee_shirt[0].darkest 3D9C70FF # Tono más oscuro - bordes y contornos (Jugador 1, 1 café)
|
||||||
|
player.one_coffee_shirt[0].dark 4FA370FF # Tono oscuro - sombras (Jugador 1, 1 café)
|
||||||
|
player.one_coffee_shirt[0].base 5DDE70FF # Tono principal - color base (Jugador 1, 1 café)
|
||||||
|
player.one_coffee_shirt[0].light 7DF25CFF # Tono claro - zonas iluminadas (Jugador 1, 1 café)
|
||||||
|
|
||||||
|
# Jugador 1 - Camiseta con 2 cafés
|
||||||
|
player.two_coffee_shirt[0].darkest D6A41AFF # Tono más oscuro - bordes y contornos (Jugador 1, 2 cafés)
|
||||||
|
player.two_coffee_shirt[0].dark E3AE1BFF # Tono oscuro - sombras (Jugador 1, 2 cafés)
|
||||||
|
player.two_coffee_shirt[0].base EFB71DFF # Tono principal - color base (Jugador 1, 2 cafés)
|
||||||
|
player.two_coffee_shirt[0].light FCC11EFF # Tono claro - zonas iluminadas (Jugador 1, 2 cafés)
|
||||||
|
|
||||||
|
# Jugador 2 - Camiseta con 1 café
|
||||||
|
player.one_coffee_shirt[1].darkest 2E8B57FF # Tono más oscuro - bordes y contornos (Jugador 2, 1 café)
|
||||||
|
player.one_coffee_shirt[1].dark 3CB371FF # Tono oscuro - sombras (Jugador 2, 1 café)
|
||||||
|
player.one_coffee_shirt[1].base 48D181FF # Tono principal - color base (Jugador 2, 1 café)
|
||||||
|
player.one_coffee_shirt[1].light 55EF8DFF # Tono claro - zonas iluminadas (Jugador 2, 1 café)
|
||||||
|
|
||||||
|
# Jugador 2 - Camiseta con 2 cafés
|
||||||
|
player.two_coffee_shirt[1].darkest E08500FF # Tono más oscuro - bordes y contornos (Jugador 2, 2 cafés)
|
||||||
|
player.two_coffee_shirt[1].dark FA7D00FF # Tono oscuro - sombras (Jugador 2, 2 cafés)
|
||||||
|
player.two_coffee_shirt[1].base FAA200FF # Tono principal - color base (Jugador 2, 2 cafés)
|
||||||
|
player.two_coffee_shirt[1].light FA8500FF # Tono claro - zonas iluminadas (Jugador 2, 2 cafés)
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
## --- GAME ---
|
# Coffee Crisis Arcade Edition - Fichero de parametros
|
||||||
|
# Formato: PARAMETRO VALOR
|
||||||
|
|
||||||
|
# --- GAME ---
|
||||||
game.item_size 20 # Tamaño de los items del juego (en píxeles)
|
game.item_size 20 # Tamaño de los items del juego (en píxeles)
|
||||||
game.width 320 # Ancho de la resolución nativa del juego (en píxeles)
|
game.width 320 # Ancho de la resolución nativa del juego (en píxeles)
|
||||||
game.height 256 # Alto de la resolución nativa del juego (en píxeles)
|
game.height 256 # Alto de la resolución nativa del juego (en píxeles)
|
||||||
@@ -11,7 +14,7 @@ game.name_entry_total_time 60 # Segundos totales para introducir el nombre
|
|||||||
game.hit_stop false # Indica si debe haber un paro cuando el jugador es golpeado por un globo
|
game.hit_stop false # Indica si debe haber un paro cuando el jugador es golpeado por un globo
|
||||||
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
|
game.hit_stop_ms 500 # Cantidad de milisegundos que dura el hit_stop
|
||||||
|
|
||||||
## --- FADE ---
|
# --- FADE ---
|
||||||
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido
|
fade.color 1F2B30 # Color hexadecimal para el efecto de fundido
|
||||||
fade.num_squares_width 160 # Número de cuadrados en el eje X para el fundido
|
fade.num_squares_width 160 # Número de cuadrados en el eje X para el fundido
|
||||||
fade.num_squares_height 128 # Número de cuadrados en el eje Y para el fundido
|
fade.num_squares_height 128 # Número de cuadrados en el eje Y para el fundido
|
||||||
@@ -20,7 +23,7 @@ fade.random_squares_mult 500 # Multiplicador para la velocidad de aparici
|
|||||||
fade.post_duration 80 # Duración tras el fundido (frames)
|
fade.post_duration 80 # Duración tras el fundido (frames)
|
||||||
fade.venetian_size 12 # Tamaño de las bandas para el efecto veneciano (en píxeles)
|
fade.venetian_size 12 # Tamaño de las bandas para el efecto veneciano (en píxeles)
|
||||||
|
|
||||||
## --- SCOREBOARD ---
|
# --- SCOREBOARD ---
|
||||||
scoreboard.rect.x 0 # Posición X del marcador
|
scoreboard.rect.x 0 # Posición X del marcador
|
||||||
scoreboard.rect.y 216 # Posición Y del marcador
|
scoreboard.rect.y 216 # Posición Y del marcador
|
||||||
scoreboard.rect.w 320 # Ancho del marcador
|
scoreboard.rect.w 320 # Ancho del marcador
|
||||||
@@ -35,17 +38,17 @@ scoreboard.text_color1 FFFFFF # Color principal del texto del marcad
|
|||||||
scoreboard.text_color2 FFFFFF # Color secundario del texto del marcador
|
scoreboard.text_color2 FFFFFF # Color secundario del texto del marcador
|
||||||
scoreboard.skip_countdown_value 8 # Valor para saltar la cuenta atrás (segundos)
|
scoreboard.skip_countdown_value 8 # Valor para saltar la cuenta atrás (segundos)
|
||||||
|
|
||||||
## --- TITLE ---
|
# --- TITLE ---
|
||||||
title.press_start_position 180 # Posición Y del texto "Press Start"
|
title.press_start_position 180 # Posición Y del texto "Press Start"
|
||||||
title.title_duration 800 # Duración de la pantalla de título (frames)
|
title.title_duration 800 # Duración de la pantalla de título (frames)
|
||||||
title.arcade_edition_position 123 # Posición Y del subtítulo "Arcade Edition"
|
title.arcade_edition_position 123 # Posición Y del subtítulo "Arcade Edition"
|
||||||
title.title_c_c_position 80 # Posición Y del título principal
|
title.title_c_c_position 80 # Posición Y del título principal
|
||||||
title.bg_color 41526F # Color de fondo en la sección titulo
|
title.bg_color 41526F # Color de fondo en la sección titulo
|
||||||
|
|
||||||
## --- BACKGROUND ---
|
# --- BACKGROUND ---
|
||||||
background.attenuate_color FFFFFF00 # Color de atenuación del fondo (RGBA hexadecimal)
|
background.attenuate_color FFFFFF00 # Color de atenuación del fondo (RGBA hexadecimal)
|
||||||
|
|
||||||
## --- BALLOONS ---
|
# --- BALLOONS ---
|
||||||
balloon.settings[0].vel 2.75f # Velocidad inicial del globo 1
|
balloon.settings[0].vel 2.75f # Velocidad inicial del globo 1
|
||||||
balloon.settings[0].grav 0.09f # Gravedad aplicada al globo 1
|
balloon.settings[0].grav 0.09f # Gravedad aplicada al globo 1
|
||||||
balloon.settings[1].vel 3.70f # Velocidad inicial del globo 2
|
balloon.settings[1].vel 3.70f # Velocidad inicial del globo 2
|
||||||
@@ -62,28 +65,70 @@ balloon.color[3] green # Color del globo que rebota
|
|||||||
|
|
||||||
balloon.bouncing_sound false # Indica si los globos hacer sonido al rebotar
|
balloon.bouncing_sound false # Indica si los globos hacer sonido al rebotar
|
||||||
|
|
||||||
## --- NOTIFICATION ---
|
# --- NOTIFICATION ---
|
||||||
notification.pos_v TOP # Posición vertical de la notificación (TOP/BOTTOM)
|
notification.pos_v TOP # Posición vertical de la notificación (TOP/BOTTOM)
|
||||||
notification.pos_h LEFT # Posición horizontal de la notificación (LEFT/RIGHT)
|
notification.pos_h LEFT # Posición horizontal de la notificación (LEFT/RIGHT)
|
||||||
notification.sound false # ¿La notificación reproduce sonido?
|
notification.sound false # ¿La notificación reproduce sonido?
|
||||||
notification.color 303030 # Color de fondo de la notificación (hexadecimal)
|
notification.color 303030 # Color de fondo de la notificación (hexadecimal)
|
||||||
|
|
||||||
## --- SERVICE MENU ---
|
# --- SERVICE MENU ---
|
||||||
service_menu.title_color 99FF62 # Color del título del menú de servicio
|
service_menu.title_color 99FF62 # Color del título del menú de servicio
|
||||||
service_menu.text_color FFFFFF # Color del texto del menú de servicio
|
service_menu.text_color FFFFFF # Color del texto del menú de servicio
|
||||||
service_menu.selected_color FFDC44 # Color de la opción seleccionada en el menú de servicio
|
service_menu.selected_color FFDC44 # Color de la opción seleccionada en el menú de servicio
|
||||||
service_menu.bg_color 000F00F5 # Color de fondo del menú de servicio (RGBA hexadecimal)
|
service_menu.bg_color 000F00F5 # Color de fondo del menú de servicio (RGBA hexadecimal)
|
||||||
service_menu.drop_shadow false # ¿El menú de servicio tiene sombra?
|
service_menu.drop_shadow false # ¿El menú de servicio tiene sombra?
|
||||||
|
|
||||||
## --- INTRO ---
|
service_menu.window_message.bg_color 141E32F0 # Color de fondo de ventanas de mensaje (RGBA hexadecimal)
|
||||||
intro.bg_color 4664BD # Color de fondo de la intro
|
service_menu.window_message.border_color 6496C8FF # Color del borde de ventanas de mensaje (RGBA hexadecimal)
|
||||||
intro.card_color CBDBFC # Color de las tarjetas en la intro
|
service_menu.window_message.title_color 6496C8FF # Color del título en ventanas de mensaje (RGBA hexadecimal)
|
||||||
intro.shadow_color 00000080 # Color de la sombra de las tarjetas en la intro
|
service_menu.window_message.text_color DCDCDCFF # Color del texto en ventanas de mensaje (RGBA hexadecimal)
|
||||||
intro.text_distance_from_bottom 48 # Posicion del texto
|
service_menu.window_message.padding 15.0f # Espaciado interno de ventanas de mensaje (píxeles)
|
||||||
|
service_menu.window_message.line_spacing 5.0f # Espaciado entre líneas de texto (píxeles)
|
||||||
|
service_menu.window_message.title_separator_spacing 10.0f # Espaciado entre título y contenido (píxeles)
|
||||||
|
service_menu.window_message.min_width 250.0f # Ancho mínimo de ventanas de mensaje (píxeles)
|
||||||
|
service_menu.window_message.min_height 32.0f # Alto mínimo de ventanas de mensaje (píxeles)
|
||||||
|
service_menu.window_message.max_width_ratio 0.8f # Ratio máximo de ancho respecto a pantalla (0.0-1.0)
|
||||||
|
service_menu.window_message.max_height_ratio 0.8f # Ratio máximo de alto respecto a pantalla (0.0-1.0)
|
||||||
|
service_menu.window_message.text_safety_margin 15.0f # Margen de seguridad para el texto (píxeles)
|
||||||
|
service_menu.window_message.animation_duration 0.3f # Duración de animaciones de ventanas (segundos)
|
||||||
|
|
||||||
## --- DEBUG ---
|
# --- INTRO ---
|
||||||
|
intro.bg_color 4664BD # Color de fondo de la intro
|
||||||
|
intro.card_color CBDBFC # Color de las tarjetas en la intro
|
||||||
|
intro.shadow_color 00000080 # Color de la sombra de las tarjetas en la intro
|
||||||
|
intro.text_distance_from_bottom 48 # Posición del texto desde la parte inferior
|
||||||
|
|
||||||
|
# --- DEBUG ---
|
||||||
debug.color 00FFFF # Color para elementos de depuración
|
debug.color 00FFFF # Color para elementos de depuración
|
||||||
|
|
||||||
## --- RESOURCE ---
|
# --- RESOURCE ---
|
||||||
resource.color FFFFFF # Color de recurso 1
|
resource.color FFFFFF # Color de recursos
|
||||||
resource.color FFFFFF # Color de recurso 2
|
|
||||||
|
# --- TABE ---
|
||||||
|
tabe.min_spawn_time 2.0f # Tiempo mínimo en segundos para que aparezca el Tabe
|
||||||
|
tabe.max_spawn_time 3.0f # Tiempo máximo en segundos para que aparezca el Tabe
|
||||||
|
|
||||||
|
# --- PLAYER ---
|
||||||
|
# Jugador 1 - Camiseta con 1 café
|
||||||
|
player.one_coffee_shirt[0].darkest 3D9C70FF # Tono más oscuro - bordes y contornos (Jugador 1, 1 café)
|
||||||
|
player.one_coffee_shirt[0].dark 4FA370FF # Tono oscuro - sombras (Jugador 1, 1 café)
|
||||||
|
player.one_coffee_shirt[0].base 5DDE70FF # Tono principal - color base (Jugador 1, 1 café)
|
||||||
|
player.one_coffee_shirt[0].light 7DF25CFF # Tono claro - zonas iluminadas (Jugador 1, 1 café)
|
||||||
|
|
||||||
|
# Jugador 1 - Camiseta con 2 cafés
|
||||||
|
player.two_coffee_shirt[0].darkest D6A41AFF # Tono más oscuro - bordes y contornos (Jugador 1, 2 cafés)
|
||||||
|
player.two_coffee_shirt[0].dark E3AE1BFF # Tono oscuro - sombras (Jugador 1, 2 cafés)
|
||||||
|
player.two_coffee_shirt[0].base EFB71DFF # Tono principal - color base (Jugador 1, 2 cafés)
|
||||||
|
player.two_coffee_shirt[0].light FCC11EFF # Tono claro - zonas iluminadas (Jugador 1, 2 cafés)
|
||||||
|
|
||||||
|
# Jugador 2 - Camiseta con 1 café
|
||||||
|
player.one_coffee_shirt[1].darkest 2E8B57FF # Tono más oscuro - bordes y contornos (Jugador 2, 1 café)
|
||||||
|
player.one_coffee_shirt[1].dark 3CB371FF # Tono oscuro - sombras (Jugador 2, 1 café)
|
||||||
|
player.one_coffee_shirt[1].base 48D181FF # Tono principal - color base (Jugador 2, 1 café)
|
||||||
|
player.one_coffee_shirt[1].light 55EF8DFF # Tono claro - zonas iluminadas (Jugador 2, 1 café)
|
||||||
|
|
||||||
|
# Jugador 2 - Camiseta con 2 cafés
|
||||||
|
player.two_coffee_shirt[1].darkest E08500FF # Tono más oscuro - bordes y contornos (Jugador 2, 2 cafés)
|
||||||
|
player.two_coffee_shirt[1].dark FA7D00FF # Tono oscuro - sombras (Jugador 2, 2 cafés)
|
||||||
|
player.two_coffee_shirt[1].base FAA200FF # Tono principal - color base (Jugador 2, 2 cafés)
|
||||||
|
player.two_coffee_shirt[1].light FA8500FF # Tono claro - zonas iluminadas (Jugador 2, 2 cafés)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Archivo de configuración de pools de formaciones de globos
|
# Coffee Crisis Arcade Edition - Archivo de configuración de pools de formaciones de globos
|
||||||
# Formato: POOL: <id> FORMATIONS: <id1>, <id2>, <id3>, ...
|
# Formato: POOL: <id> FORMATIONS: <id1>, <id2>, <id3>, ...
|
||||||
# Los IDs de formación pueden repetirse
|
# Los IDs de formación pueden repetirse
|
||||||
# Los pools no necesitan estar ordenados ni ser consecutivos
|
# Los pools no necesitan estar ordenados ni ser consecutivos
|
||||||
|
|||||||
19
data/config/stages.txt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# Coffee Crisis Arcade Edition - Archivo de configuración de fases
|
||||||
|
# Formato: power_to_complete,min_menace,max_menace,name
|
||||||
|
# Líneas que empiezan con # son comentarios y se ignoran
|
||||||
|
|
||||||
|
# Fases iniciales - Tutorial y aprendizaje
|
||||||
|
200, 11, 19, Tutorial
|
||||||
|
300, 15, 23, Primeros pasos
|
||||||
|
|
||||||
|
# Fases intermedias - Incremento de dificultad
|
||||||
|
400, 19, 27, Intensificación
|
||||||
|
400, 19, 27, Persistencia
|
||||||
|
400, 23, 31, Desafío medio
|
||||||
|
400, 23, 31, Resistencia
|
||||||
|
|
||||||
|
# Fases avanzadas - Desafío final
|
||||||
|
600, 27, 35, Aproximación final
|
||||||
|
600, 27, 35, Penúltimo obstáculo
|
||||||
|
700, 31, 39, Clímax
|
||||||
|
950, 35, 47, Maestría
|
||||||
@@ -120,9 +120,16 @@ loop=0
|
|||||||
frames=47,48,49,50,51,52,53
|
frames=47,48,49,50,51,52,53
|
||||||
[/animation]
|
[/animation]
|
||||||
|
|
||||||
|
[animation]
|
||||||
|
name=recover
|
||||||
|
speed=3
|
||||||
|
loop=-1
|
||||||
|
frames=54,54,54,54,55,56,57,58,58,58,59,60,61,58,59,60,61,58,59,60,61,62,62,62,62
|
||||||
|
[/animation]
|
||||||
|
|
||||||
[animation]
|
[animation]
|
||||||
name=hello
|
name=hello
|
||||||
speed=3
|
speed=3
|
||||||
loop=-1
|
loop=-1
|
||||||
frames=54,55,56,57,58,59,60,61,62,63,64,64,64,64,64,64,64,64,64,64,64,64,64,65,66,67,68,69,70,71,72,73,73,72,71,70,70,71,72,73,73,72,71,70,70,71,72,73,73,72,71,70,70,71,72,73,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54
|
frames=63,64,65,66,67,68,69,70,71,72,73,73,73,73,73,73,73,73,73,73,73,73,73,74,75,76,77,78,79,80,81,82,82,81,80,79,79,80,81,82,82,81,80,79,79,80,81,82,82,81,80,79,79,80,81,82,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63
|
||||||
[/animation]
|
[/animation]
|
||||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 16 KiB |
@@ -26,6 +26,7 @@
|
|||||||
"[GAME_TEXT] 6": "Temps!",
|
"[GAME_TEXT] 6": "Temps!",
|
||||||
"[GAME_TEXT] 7": "Endavant!",
|
"[GAME_TEXT] 7": "Endavant!",
|
||||||
"[GAME_TEXT] 8": "1.000.000 de punts!",
|
"[GAME_TEXT] 8": "1.000.000 de punts!",
|
||||||
|
"[GAME_TEXT] THANK_YOU": "Gracies!",
|
||||||
|
|
||||||
"[HIGHSCORE_TABLE] CAPTION": "Millors puntuacions",
|
"[HIGHSCORE_TABLE] CAPTION": "Millors puntuacions",
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
"[GAME_TEXT] 6": "Stop!",
|
"[GAME_TEXT] 6": "Stop!",
|
||||||
"[GAME_TEXT] 7": "Get Ready!",
|
"[GAME_TEXT] 7": "Get Ready!",
|
||||||
"[GAME_TEXT] 8": "1,000,000 points!",
|
"[GAME_TEXT] 8": "1,000,000 points!",
|
||||||
|
"[GAME_TEXT] THANK_YOU": "Thank you!",
|
||||||
|
|
||||||
"[HIGHSCORE_TABLE] CAPTION": "Best scores",
|
"[HIGHSCORE_TABLE] CAPTION": "Best scores",
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
"[GAME_TEXT] 6": "Tiempo!",
|
"[GAME_TEXT] 6": "Tiempo!",
|
||||||
"[GAME_TEXT] 7": "Adelante!",
|
"[GAME_TEXT] 7": "Adelante!",
|
||||||
"[GAME_TEXT] 8": "1.000.000 de puntos!",
|
"[GAME_TEXT] 8": "1.000.000 de puntos!",
|
||||||
|
"[GAME_TEXT] THANK_YOU": "Gracias!",
|
||||||
|
|
||||||
"[HIGHSCORE_TABLE] CAPTION": "Mejores puntuaciones",
|
"[HIGHSCORE_TABLE] CAPTION": "Mejores puntuaciones",
|
||||||
|
|
||||||
|
|||||||
BIN
data/sound/credit.wav
Normal file
BIN
data/sound/voice_brbrbr.wav
Normal file
BIN
data/sound/voice_credit_thankyou.wav
Normal file
150
release/create_icons.py
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def check_dependencies():
|
||||||
|
"""Verifica que ImageMagick esté instalado"""
|
||||||
|
try:
|
||||||
|
subprocess.run(['magick', '--version'], capture_output=True, check=True)
|
||||||
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||||
|
print("Error: ImageMagick no está instalado o no se encuentra en el PATH")
|
||||||
|
print("Instala ImageMagick desde: https://imagemagick.org/script/download.php")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Verificar iconutil solo en macOS
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
try:
|
||||||
|
# iconutil no tiene --version, mejor usar which o probar con -h
|
||||||
|
result = subprocess.run(['which', 'iconutil'], capture_output=True, check=True)
|
||||||
|
if result.returncode == 0:
|
||||||
|
print("✓ iconutil disponible - se crearán archivos .ico e .icns")
|
||||||
|
except (subprocess.CalledProcessError, FileNotFoundError):
|
||||||
|
print("Error: iconutil no está disponible (solo funciona en macOS)")
|
||||||
|
print("Solo se creará el archivo .ico")
|
||||||
|
else:
|
||||||
|
print("ℹ️ Sistema no-macOS detectado - solo se creará archivo .ico")
|
||||||
|
|
||||||
|
|
||||||
|
def create_icons(input_file):
|
||||||
|
"""Crea archivos .icns e .ico a partir de un PNG"""
|
||||||
|
|
||||||
|
# Verificar que el archivo existe
|
||||||
|
if not os.path.isfile(input_file):
|
||||||
|
print(f"Error: El archivo {input_file} no existe.")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Obtener información del archivo
|
||||||
|
file_path = Path(input_file)
|
||||||
|
file_dir = file_path.parent
|
||||||
|
file_name = file_path.stem # Nombre sin extensión
|
||||||
|
file_extension = file_path.suffix
|
||||||
|
|
||||||
|
if file_extension.lower() not in ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']:
|
||||||
|
print(f"Advertencia: {file_extension} puede no ser compatible. Se recomienda usar PNG.")
|
||||||
|
|
||||||
|
# Crear archivo .ico usando el método simplificado
|
||||||
|
ico_output = file_dir / f"{file_name}.ico"
|
||||||
|
try:
|
||||||
|
print(f"Creando {ico_output}...")
|
||||||
|
subprocess.run([
|
||||||
|
'magick', str(input_file),
|
||||||
|
'-define', 'icon:auto-resize=256,128,64,48,32,16',
|
||||||
|
str(ico_output)
|
||||||
|
], check=True)
|
||||||
|
print(f"✓ Archivo .ico creado: {ico_output}")
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error creando archivo .ico: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Crear archivo .icns (solo en macOS)
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
try:
|
||||||
|
# Crear carpeta temporal para iconset
|
||||||
|
temp_folder = file_dir / "icon.iconset"
|
||||||
|
|
||||||
|
# Eliminar carpeta temporal si existe
|
||||||
|
if temp_folder.exists():
|
||||||
|
shutil.rmtree(temp_folder)
|
||||||
|
|
||||||
|
# Crear carpeta temporal
|
||||||
|
temp_folder.mkdir(parents=True)
|
||||||
|
|
||||||
|
# Definir los tamaños y nombres de archivo para .icns
|
||||||
|
icon_sizes = [
|
||||||
|
(16, "icon_16x16.png"),
|
||||||
|
(32, "icon_16x16@2x.png"),
|
||||||
|
(32, "icon_32x32.png"),
|
||||||
|
(64, "icon_32x32@2x.png"),
|
||||||
|
(128, "icon_128x128.png"),
|
||||||
|
(256, "icon_128x128@2x.png"),
|
||||||
|
(256, "icon_256x256.png"),
|
||||||
|
(512, "icon_256x256@2x.png"),
|
||||||
|
(512, "icon_512x512.png"),
|
||||||
|
(1024, "icon_512x512@2x.png")
|
||||||
|
]
|
||||||
|
|
||||||
|
print("Generando imágenes para .icns...")
|
||||||
|
# Crear cada tamaño de imagen
|
||||||
|
for size, output_name in icon_sizes:
|
||||||
|
output_path = temp_folder / output_name
|
||||||
|
subprocess.run([
|
||||||
|
'magick', str(input_file),
|
||||||
|
'-resize', f'{size}x{size}',
|
||||||
|
str(output_path)
|
||||||
|
], check=True)
|
||||||
|
|
||||||
|
# Crear archivo .icns usando iconutil
|
||||||
|
icns_output = file_dir / f"{file_name}.icns"
|
||||||
|
print(f"Creando {icns_output}...")
|
||||||
|
subprocess.run([
|
||||||
|
'iconutil', '-c', 'icns',
|
||||||
|
str(temp_folder),
|
||||||
|
'-o', str(icns_output)
|
||||||
|
], check=True)
|
||||||
|
|
||||||
|
# Limpiar carpeta temporal
|
||||||
|
if temp_folder.exists():
|
||||||
|
shutil.rmtree(temp_folder)
|
||||||
|
|
||||||
|
print(f"✓ Archivo .icns creado: {icns_output}")
|
||||||
|
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error creando archivo .icns: {e}")
|
||||||
|
# Limpiar carpeta temporal en caso de error
|
||||||
|
if temp_folder.exists():
|
||||||
|
shutil.rmtree(temp_folder)
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
print("ℹ️ Archivo .icns no creado (solo disponible en macOS)")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Función principal"""
|
||||||
|
# Verificar argumentos
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print(f"Uso: {sys.argv[0]} ARCHIVO")
|
||||||
|
print("Ejemplo: python3 create_icons.py imagen.png")
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
input_file = sys.argv[1]
|
||||||
|
|
||||||
|
# Verificar dependencias
|
||||||
|
check_dependencies()
|
||||||
|
|
||||||
|
# Crear iconos
|
||||||
|
if create_icons(input_file):
|
||||||
|
print("\n✅ Proceso completado exitosamente")
|
||||||
|
else:
|
||||||
|
print("\n❌ El proceso falló")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
BIN
release/icon.ico
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 128 KiB |
BIN
release/icon.png
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 438 KiB |
@@ -52,7 +52,7 @@ AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const Animation
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el índice de la animación a partir del nombre
|
// Obtiene el índice de la animación a partir del nombre
|
||||||
auto AnimatedSprite::getIndex(const std::string& name) -> int {
|
auto AnimatedSprite::getAnimationIndex(const std::string& name) -> int {
|
||||||
auto iterator = animation_indices_.find(name);
|
auto iterator = animation_indices_.find(name);
|
||||||
if (iterator != animation_indices_.end()) {
|
if (iterator != animation_indices_.end()) {
|
||||||
// Si se encuentra la animación en el mapa, devuelve su índice
|
// Si se encuentra la animación en el mapa, devuelve su índice
|
||||||
@@ -101,7 +101,7 @@ auto AnimatedSprite::animationIsCompleted() -> bool {
|
|||||||
|
|
||||||
// Establece la animacion actual
|
// Establece la animacion actual
|
||||||
void AnimatedSprite::setCurrentAnimation(const std::string& name, bool reset) {
|
void AnimatedSprite::setCurrentAnimation(const std::string& name, bool reset) {
|
||||||
const auto NEW_ANIMATION = getIndex(name);
|
const auto NEW_ANIMATION = getAnimationIndex(name);
|
||||||
if (current_animation_ != NEW_ANIMATION) {
|
if (current_animation_ != NEW_ANIMATION) {
|
||||||
const auto OLD_ANIMATION = current_animation_;
|
const auto OLD_ANIMATION = current_animation_;
|
||||||
current_animation_ = NEW_ANIMATION;
|
current_animation_ = NEW_ANIMATION;
|
||||||
|
|||||||
@@ -56,17 +56,18 @@ class AnimatedSprite : public MovingSprite {
|
|||||||
void update() override; // Actualiza la animación
|
void update() override; // Actualiza la animación
|
||||||
|
|
||||||
// --- Control de animaciones ---
|
// --- Control de animaciones ---
|
||||||
void setCurrentAnimation(const std::string& name = "default", bool reset = true); // Establece la animación por nombre
|
void setCurrentAnimation(const std::string& name = "default", bool reset = true); // Establece la animación por nombre
|
||||||
void setCurrentAnimation(int index = 0, bool reset = true); // Establece la animación por índice
|
void setCurrentAnimation(int index = 0, bool reset = true); // Establece la animación por índice
|
||||||
void resetAnimation(); // Reinicia la animación actual
|
void resetAnimation(); // Reinicia la animación actual
|
||||||
void setAnimationSpeed(size_t value); // Establece la velocidad de la animación
|
void setAnimationSpeed(size_t value); // Establece la velocidad de la animación
|
||||||
auto getAnimationSpeed() const -> size_t { return animations_[current_animation_].speed; } // Obtiene la velocidad de la animación actual
|
auto getAnimationSpeed() const -> size_t { return animations_[current_animation_].speed; } // Obtiene la velocidad de la animación actual
|
||||||
void animtionPause() { animations_[current_animation_].paused = true; } // Detiene la animación
|
void animtionPause() { animations_[current_animation_].paused = true; } // Detiene la animación
|
||||||
void animationResume() { animations_[current_animation_].paused = false; } // Reanuda la animación
|
void animationResume() { animations_[current_animation_].paused = false; } // Reanuda la animación
|
||||||
|
auto getCurrentAnimationFrame() const -> size_t { return animations_[current_animation_].current_frame; } // Obtiene el numero de frame de la animación actual
|
||||||
|
|
||||||
// --- Consultas ---
|
// --- Consultas ---
|
||||||
auto animationIsCompleted() -> bool; // Comprueba si la animación ha terminado
|
auto animationIsCompleted() -> bool; // Comprueba si la animación ha terminado
|
||||||
auto getIndex(const std::string& name) -> int; // Obtiene el índice de una animación por nombre
|
auto getAnimationIndex(const std::string& name) -> int; // Obtiene el índice de una animación por nombre
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// --- Datos de animación ---
|
// --- Datos de animación ---
|
||||||
|
|||||||
@@ -14,8 +14,12 @@
|
|||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Background::Background()
|
Background::Background(float total_progress_to_complete)
|
||||||
: renderer_(Screen::get()->getRenderer()),
|
: total_progress_to_complete_(total_progress_to_complete),
|
||||||
|
progress_per_stage_(total_progress_to_complete_ / STAGES),
|
||||||
|
sun_completion_progress_(total_progress_to_complete_ * SUN_COMPLETION_FACTOR),
|
||||||
|
|
||||||
|
renderer_(Screen::get()->getRenderer()),
|
||||||
|
|
||||||
buildings_texture_(Resource::get()->getTexture("game_buildings.png")),
|
buildings_texture_(Resource::get()->getTexture("game_buildings.png")),
|
||||||
top_clouds_texture_(Resource::get()->getTexture("game_clouds1.png")),
|
top_clouds_texture_(Resource::get()->getTexture("game_clouds1.png")),
|
||||||
@@ -28,81 +32,16 @@ Background::Background()
|
|||||||
rect_(SDL_FRect{0, 0, static_cast<float>(gradients_texture_->getWidth() / 2), static_cast<float>(gradients_texture_->getHeight() / 2)}),
|
rect_(SDL_FRect{0, 0, static_cast<float>(gradients_texture_->getWidth() / 2), static_cast<float>(gradients_texture_->getHeight() / 2)}),
|
||||||
src_rect_({0, 0, 320, 240}),
|
src_rect_({0, 0, 320, 240}),
|
||||||
dst_rect_({0, 0, 320, 240}),
|
dst_rect_({0, 0, 320, 240}),
|
||||||
base_(rect_.h),
|
|
||||||
attenuate_color_(Color(param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b)),
|
attenuate_color_(Color(param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b)),
|
||||||
alpha_color_text_(param.background.attenuate_color.a),
|
|
||||||
alpha_color_text_temp_(param.background.attenuate_color.a)
|
|
||||||
|
|
||||||
{
|
alpha_color_texture_(param.background.attenuate_color.a),
|
||||||
// Precalcula rutas
|
previous_alpha_color_texture_(param.background.attenuate_color.a),
|
||||||
createSunPath();
|
base_(rect_.h) {
|
||||||
createMoonPath();
|
initializePaths();
|
||||||
|
initializeRects();
|
||||||
// Inicializa variables
|
initializeSprites();
|
||||||
{
|
initializeSpriteProperties();
|
||||||
gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
|
initializeTextures();
|
||||||
gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h};
|
|
||||||
gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h};
|
|
||||||
gradient_rect_[3] = {rect_.w, rect_.h, rect_.w, rect_.h};
|
|
||||||
|
|
||||||
const float TOP_CLOUDS_TEXTURE_HEIGHT = top_clouds_texture_->getHeight() / 4;
|
|
||||||
const float BOTTOM_CLOUDS_TEXTURE_HEIGHT = bottom_clouds_texture_->getHeight() / 4;
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
top_clouds_rect_[i] = {0, i * TOP_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(top_clouds_texture_->getWidth()), TOP_CLOUDS_TEXTURE_HEIGHT};
|
|
||||||
bottom_clouds_rect_[i] = {0, i * BOTTOM_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(bottom_clouds_texture_->getWidth()), BOTTOM_CLOUDS_TEXTURE_HEIGHT};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crea los sprites
|
|
||||||
{
|
|
||||||
const float TOP_CLOUDS_Y = base_ - 165;
|
|
||||||
const float BOTTOM_CLOUDS_Y = base_ - 101;
|
|
||||||
|
|
||||||
top_clouds_sprite_a_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_FRect){0, TOP_CLOUDS_Y, rect_.w, static_cast<float>(top_clouds_texture_->getHeight())});
|
|
||||||
top_clouds_sprite_b_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_FRect){rect_.w, TOP_CLOUDS_Y, rect_.w, static_cast<float>(top_clouds_texture_->getHeight())});
|
|
||||||
|
|
||||||
bottom_clouds_sprite_a_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_FRect){0, BOTTOM_CLOUDS_Y, rect_.w, static_cast<float>(bottom_clouds_texture_->getHeight())});
|
|
||||||
bottom_clouds_sprite_b_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_FRect){rect_.w, BOTTOM_CLOUDS_Y, rect_.w, static_cast<float>(bottom_clouds_texture_->getHeight())});
|
|
||||||
|
|
||||||
buildings_sprite_ = std::make_unique<Sprite>(buildings_texture_);
|
|
||||||
gradient_sprite_ = std::make_unique<Sprite>(gradients_texture_, 0, 0, rect_.w, rect_.h);
|
|
||||||
grass_sprite_ = std::make_unique<Sprite>(grass_texture_, 0, 0, grass_texture_->getWidth(), grass_texture_->getHeight() / 2);
|
|
||||||
sun_sprite_ = std::make_unique<Sprite>(sun_texture_);
|
|
||||||
moon_sprite_ = std::make_unique<Sprite>(moon_texture_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa objetos
|
|
||||||
{
|
|
||||||
constexpr float TOP_CLOUDS_SPEED = 0.1F;
|
|
||||||
constexpr float BOTTOM_CLOUDS_SPEED = 0.05F;
|
|
||||||
|
|
||||||
top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
|
|
||||||
top_clouds_sprite_a_->setVelX(-TOP_CLOUDS_SPEED);
|
|
||||||
|
|
||||||
top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
|
|
||||||
top_clouds_sprite_b_->setVelX(-TOP_CLOUDS_SPEED);
|
|
||||||
|
|
||||||
bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
|
|
||||||
bottom_clouds_sprite_a_->setVelX(-BOTTOM_CLOUDS_SPEED);
|
|
||||||
|
|
||||||
bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
|
|
||||||
bottom_clouds_sprite_b_->setVelX(-BOTTOM_CLOUDS_SPEED);
|
|
||||||
|
|
||||||
buildings_sprite_->setY(base_ - buildings_sprite_->getHeight());
|
|
||||||
grass_sprite_->setY(base_ - grass_sprite_->getHeight());
|
|
||||||
sun_sprite_->setPosition(sun_path_.front());
|
|
||||||
moon_sprite_->setPosition(moon_path_.front());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crea la textura para componer el fondo
|
|
||||||
canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
|
|
||||||
SDL_SetTextureBlendMode(canvas_, SDL_BLENDMODE_BLEND);
|
|
||||||
|
|
||||||
// Crea la textura para atenuar el fondo
|
|
||||||
color_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
|
|
||||||
SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND);
|
|
||||||
setColor(attenuate_color_);
|
|
||||||
SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
@@ -111,9 +50,88 @@ Background::~Background() {
|
|||||||
SDL_DestroyTexture(color_texture_);
|
SDL_DestroyTexture(color_texture_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inicializa las rutas del sol y la luna
|
||||||
|
void Background::initializePaths() {
|
||||||
|
createSunPath();
|
||||||
|
createMoonPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicializa los rectángulos de gradientes y nubes
|
||||||
|
void Background::initializeRects() {
|
||||||
|
gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
|
||||||
|
gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h};
|
||||||
|
gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h};
|
||||||
|
gradient_rect_[3] = {rect_.w, rect_.h, rect_.w, rect_.h};
|
||||||
|
|
||||||
|
const float TOP_CLOUDS_TEXTURE_HEIGHT = top_clouds_texture_->getHeight() / 4;
|
||||||
|
const float BOTTOM_CLOUDS_TEXTURE_HEIGHT = bottom_clouds_texture_->getHeight() / 4;
|
||||||
|
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
top_clouds_rect_[i] = {0, i * TOP_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(top_clouds_texture_->getWidth()), TOP_CLOUDS_TEXTURE_HEIGHT};
|
||||||
|
bottom_clouds_rect_[i] = {0, i * BOTTOM_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(bottom_clouds_texture_->getWidth()), BOTTOM_CLOUDS_TEXTURE_HEIGHT};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crea los sprites
|
||||||
|
void Background::initializeSprites() {
|
||||||
|
const float TOP_CLOUDS_Y = base_ - 165;
|
||||||
|
const float BOTTOM_CLOUDS_Y = base_ - 101;
|
||||||
|
|
||||||
|
top_clouds_sprite_a_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_FRect){0, TOP_CLOUDS_Y, rect_.w, static_cast<float>(top_clouds_texture_->getHeight())});
|
||||||
|
top_clouds_sprite_b_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_FRect){rect_.w, TOP_CLOUDS_Y, rect_.w, static_cast<float>(top_clouds_texture_->getHeight())});
|
||||||
|
|
||||||
|
bottom_clouds_sprite_a_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_FRect){0, BOTTOM_CLOUDS_Y, rect_.w, static_cast<float>(bottom_clouds_texture_->getHeight())});
|
||||||
|
bottom_clouds_sprite_b_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_FRect){rect_.w, BOTTOM_CLOUDS_Y, rect_.w, static_cast<float>(bottom_clouds_texture_->getHeight())});
|
||||||
|
|
||||||
|
buildings_sprite_ = std::make_unique<Sprite>(buildings_texture_);
|
||||||
|
gradient_sprite_ = std::make_unique<Sprite>(gradients_texture_, 0, 0, rect_.w, rect_.h);
|
||||||
|
grass_sprite_ = std::make_unique<Sprite>(grass_texture_, 0, 0, grass_texture_->getWidth(), grass_texture_->getHeight() / 2);
|
||||||
|
sun_sprite_ = std::make_unique<Sprite>(sun_texture_);
|
||||||
|
moon_sprite_ = std::make_unique<Sprite>(moon_texture_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configura las propiedades iniciales de los sprites
|
||||||
|
void Background::initializeSpriteProperties() {
|
||||||
|
constexpr float TOP_CLOUDS_SPEED = 0.1F;
|
||||||
|
constexpr float BOTTOM_CLOUDS_SPEED = 0.05F;
|
||||||
|
|
||||||
|
top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
|
||||||
|
top_clouds_sprite_a_->setVelX(-TOP_CLOUDS_SPEED);
|
||||||
|
|
||||||
|
top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
|
||||||
|
top_clouds_sprite_b_->setVelX(-TOP_CLOUDS_SPEED);
|
||||||
|
|
||||||
|
bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
|
||||||
|
bottom_clouds_sprite_a_->setVelX(-BOTTOM_CLOUDS_SPEED);
|
||||||
|
|
||||||
|
bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
|
||||||
|
bottom_clouds_sprite_b_->setVelX(-BOTTOM_CLOUDS_SPEED);
|
||||||
|
|
||||||
|
buildings_sprite_->setY(base_ - buildings_sprite_->getHeight());
|
||||||
|
grass_sprite_->setY(base_ - grass_sprite_->getHeight());
|
||||||
|
sun_sprite_->setPosition(sun_path_.front());
|
||||||
|
moon_sprite_->setPosition(moon_path_.front());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inicializa las texturas de renderizado
|
||||||
|
void Background::initializeTextures() {
|
||||||
|
canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
|
||||||
|
SDL_SetTextureBlendMode(canvas_, SDL_BLENDMODE_BLEND);
|
||||||
|
|
||||||
|
color_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
|
||||||
|
SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND);
|
||||||
|
setColor(attenuate_color_);
|
||||||
|
SDL_SetTextureAlphaMod(color_texture_, alpha_color_texture_);
|
||||||
|
}
|
||||||
|
|
||||||
// Actualiza la lógica del objeto
|
// Actualiza la lógica del objeto
|
||||||
void Background::update() {
|
void Background::update() {
|
||||||
// Actualiza el valor de alpha_
|
// Actualiza la progresión y calcula transiciones
|
||||||
|
if (!manual_mode_) {
|
||||||
|
updateProgression();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza el valor de alpha
|
||||||
updateAlphaColorTexture();
|
updateAlphaColorTexture();
|
||||||
|
|
||||||
// Actualiza las nubes
|
// Actualiza las nubes
|
||||||
@@ -122,10 +140,10 @@ void Background::update() {
|
|||||||
// Calcula el frame de la hierba
|
// Calcula el frame de la hierba
|
||||||
grass_sprite_->setSpriteClip(0, (10 * (counter_ / 20 % 2)), 320, 10);
|
grass_sprite_->setSpriteClip(0, (10 * (counter_ / 20 % 2)), 320, 10);
|
||||||
|
|
||||||
// Calcula el valor de alpha_
|
// Calcula el valor de alpha
|
||||||
alpha_ = std::max((255 - (int)(255 * transition_)), 0);
|
alpha_ = std::max((255 - (int)(255 * transition_)), 0);
|
||||||
|
|
||||||
// Mueve el sol
|
// Mueve el sol y la luna según la progresión
|
||||||
sun_sprite_->setPosition(sun_path_.at(sun_index_));
|
sun_sprite_->setPosition(sun_path_.at(sun_index_));
|
||||||
moon_sprite_->setPosition(moon_path_.at(moon_index_));
|
moon_sprite_->setPosition(moon_path_.at(moon_index_));
|
||||||
|
|
||||||
@@ -136,6 +154,190 @@ void Background::update() {
|
|||||||
fillCanvas();
|
fillCanvas();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Incrementa la progresión interna
|
||||||
|
void Background::incrementProgress(float amount) {
|
||||||
|
if (state_ == State::NORMAL) {
|
||||||
|
float old_progress = progress_;
|
||||||
|
progress_ += amount;
|
||||||
|
progress_ = std::min(progress_, total_progress_to_complete_);
|
||||||
|
|
||||||
|
// Notifica el cambio si hay callback y el progreso cambió
|
||||||
|
if (progress_callback_ && progress_ != old_progress) {
|
||||||
|
progress_callback_(progress_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establece la progresión absoluta
|
||||||
|
void Background::setProgress(float absolute_progress) {
|
||||||
|
float old_progress = progress_;
|
||||||
|
progress_ = std::clamp(absolute_progress, 0.0f, total_progress_to_complete_);
|
||||||
|
|
||||||
|
// Notifica el cambio si hay callback y el progreso cambió
|
||||||
|
if (progress_callback_ && progress_ != old_progress) {
|
||||||
|
progress_callback_(progress_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cambia el estado del fondo
|
||||||
|
void Background::setState(State new_state) {
|
||||||
|
state_ = new_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reinicia la progresión
|
||||||
|
void Background::reset() {
|
||||||
|
float old_progress = progress_;
|
||||||
|
progress_ = 0.0f;
|
||||||
|
state_ = State::NORMAL;
|
||||||
|
manual_mode_ = false;
|
||||||
|
gradient_number_ = 0;
|
||||||
|
transition_ = 0.0f;
|
||||||
|
sun_index_ = 0;
|
||||||
|
moon_index_ = 0;
|
||||||
|
|
||||||
|
// Notifica el cambio si hay callback
|
||||||
|
if (progress_callback_ && progress_ != old_progress) {
|
||||||
|
progress_callback_(progress_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activa/desactiva el modo manual
|
||||||
|
void Background::setManualMode(bool manual) {
|
||||||
|
manual_mode_ = manual;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establece callback para sincronización automática
|
||||||
|
void Background::setProgressCallback(ProgressCallback callback) {
|
||||||
|
progress_callback_ = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Elimina el callback
|
||||||
|
void Background::removeProgressCallback() {
|
||||||
|
progress_callback_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ajusta la velocidad de las nubes
|
||||||
|
void Background::setCloudsSpeed(float value) {
|
||||||
|
clouds_speed_ = value;
|
||||||
|
|
||||||
|
// En modo manual, aplicar la velocidad directamente
|
||||||
|
// Las nubes inferiores van a la mitad de velocidad que las superiores
|
||||||
|
top_clouds_sprite_a_->setVelX(value);
|
||||||
|
top_clouds_sprite_b_->setVelX(value);
|
||||||
|
bottom_clouds_sprite_a_->setVelX(value / 2.0f);
|
||||||
|
bottom_clouds_sprite_b_->setVelX(value / 2.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establece el degradado de fondo
|
||||||
|
void Background::setGradientNumber(int value) {
|
||||||
|
gradient_number_ = value % STAGES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ajusta la transición entre texturas
|
||||||
|
void Background::setTransition(float value) {
|
||||||
|
transition_ = std::clamp(value, 0.0F, 1.0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establece la posición del sol
|
||||||
|
void Background::setSunProgression(float progress) {
|
||||||
|
progress = std::clamp(progress, 0.0F, 1.0F);
|
||||||
|
sun_index_ = static_cast<size_t>(progress * (sun_path_.size() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establece la posición de la luna
|
||||||
|
void Background::setMoonProgression(float progress) {
|
||||||
|
progress = std::clamp(progress, 0.0F, 1.0F);
|
||||||
|
moon_index_ = static_cast<size_t>(progress * (moon_path_.size() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza la progresión y calcula las transiciones
|
||||||
|
void Background::updateProgression() {
|
||||||
|
// Si el juego está completado, reduce la progresión gradualmente
|
||||||
|
if (state_ == State::COMPLETED) {
|
||||||
|
if (progress_ > MINIMUM_COMPLETED_PROGRESS) {
|
||||||
|
progress_ -= COMPLETED_REDUCTION_RATE;
|
||||||
|
} else {
|
||||||
|
progress_ = MINIMUM_COMPLETED_PROGRESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcula la transición de los diferentes fondos
|
||||||
|
const float gradient_number_float = std::min(progress_ / progress_per_stage_, 3.0F);
|
||||||
|
const float percent = gradient_number_float - static_cast<int>(gradient_number_float);
|
||||||
|
|
||||||
|
gradient_number_ = static_cast<size_t>(gradient_number_float);
|
||||||
|
transition_ = percent;
|
||||||
|
|
||||||
|
// Calcula la posición del sol
|
||||||
|
const float sun_progression = std::min(progress_ / sun_completion_progress_, 1.0f);
|
||||||
|
sun_index_ = static_cast<size_t>(sun_progression * (sun_path_.size() - 1));
|
||||||
|
|
||||||
|
// Calcula la posición de la luna
|
||||||
|
const float moon_progression = std::min(progress_ / total_progress_to_complete_, 1.0f);
|
||||||
|
moon_index_ = static_cast<size_t>(moon_progression * (moon_path_.size() - 1));
|
||||||
|
|
||||||
|
// Actualiza la velocidad de las nubes
|
||||||
|
updateCloudsSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza la velocidad de las nubes según el estado y progresión
|
||||||
|
void Background::updateCloudsSpeed() {
|
||||||
|
// Cálculo de velocidad según progreso
|
||||||
|
constexpr float CLOUDS_INITIAL_SPEED = 0.05F;
|
||||||
|
constexpr float CLOUDS_FINAL_SPEED = 2.00F - CLOUDS_INITIAL_SPEED;
|
||||||
|
|
||||||
|
// Velocidad base según progreso (de -0.05 a -2.00)
|
||||||
|
float base_clouds_speed = (-CLOUDS_INITIAL_SPEED) +
|
||||||
|
(-CLOUDS_FINAL_SPEED * (progress_ / total_progress_to_complete_));
|
||||||
|
|
||||||
|
// En estado completado, las nubes se ralentizan gradualmente
|
||||||
|
if (state_ == State::COMPLETED) {
|
||||||
|
float completion_factor = (progress_ - MINIMUM_COMPLETED_PROGRESS) /
|
||||||
|
(total_progress_to_complete_ - MINIMUM_COMPLETED_PROGRESS);
|
||||||
|
completion_factor = std::max(0.1f, completion_factor);
|
||||||
|
base_clouds_speed *= completion_factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aplicar velocidades diferentes para nubes superiores e inferiores
|
||||||
|
const float top_clouds_speed = base_clouds_speed;
|
||||||
|
const float bottom_clouds_speed = base_clouds_speed / 2.0f;
|
||||||
|
|
||||||
|
// Aplicar las velocidades a los sprites correspondientes
|
||||||
|
top_clouds_sprite_a_->setVelX(top_clouds_speed);
|
||||||
|
top_clouds_sprite_b_->setVelX(top_clouds_speed);
|
||||||
|
bottom_clouds_sprite_a_->setVelX(bottom_clouds_speed);
|
||||||
|
bottom_clouds_sprite_b_->setVelX(bottom_clouds_speed);
|
||||||
|
|
||||||
|
// Guardar la velocidad principal
|
||||||
|
clouds_speed_ = top_clouds_speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualiza las nubes
|
||||||
|
void Background::updateClouds() {
|
||||||
|
// Mueve las nubes
|
||||||
|
top_clouds_sprite_a_->update();
|
||||||
|
top_clouds_sprite_b_->update();
|
||||||
|
bottom_clouds_sprite_a_->update();
|
||||||
|
bottom_clouds_sprite_b_->update();
|
||||||
|
|
||||||
|
// Calcula el offset de las nubes
|
||||||
|
if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth()) {
|
||||||
|
top_clouds_sprite_a_->setPosX(top_clouds_sprite_a_->getWidth());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (top_clouds_sprite_b_->getPosX() < -top_clouds_sprite_b_->getWidth()) {
|
||||||
|
top_clouds_sprite_b_->setPosX(top_clouds_sprite_b_->getWidth());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bottom_clouds_sprite_a_->getPosX() < -bottom_clouds_sprite_a_->getWidth()) {
|
||||||
|
bottom_clouds_sprite_a_->setPosX(bottom_clouds_sprite_a_->getWidth());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bottom_clouds_sprite_b_->getPosX() < -bottom_clouds_sprite_b_->getWidth()) {
|
||||||
|
bottom_clouds_sprite_b_->setPosX(bottom_clouds_sprite_b_->getWidth());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Dibuja el gradiente de fondo
|
// Dibuja el gradiente de fondo
|
||||||
void Background::renderGradient() {
|
void Background::renderGradient() {
|
||||||
// Dibuja el gradiente de detras
|
// Dibuja el gradiente de detras
|
||||||
@@ -221,21 +423,6 @@ void Background::render() {
|
|||||||
SDL_RenderTexture(renderer_, color_texture_, &src_rect_, &dst_rect_);
|
SDL_RenderTexture(renderer_, color_texture_, &src_rect_, &dst_rect_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ajusta el valor de la variable
|
|
||||||
void Background::setCloudsSpeed(float value) {
|
|
||||||
clouds_speed_ = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajusta el valor de la variable
|
|
||||||
void Background::setGradientNumber(int value) {
|
|
||||||
gradient_number_ = value % 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ajusta el valor de la variable
|
|
||||||
void Background::setTransition(float value) {
|
|
||||||
transition_ = std::clamp(value, 0.0F, 1.0F);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Establece la posición del objeto
|
// Establece la posición del objeto
|
||||||
void Background::setPos(SDL_FRect pos) {
|
void Background::setPos(SDL_FRect pos) {
|
||||||
dst_rect_ = pos;
|
dst_rect_ = pos;
|
||||||
@@ -247,7 +434,7 @@ void Background::setPos(SDL_FRect pos) {
|
|||||||
src_rect_.h = pos.h;
|
src_rect_.h = pos.h;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el color_ de atenuación
|
// Establece el color de atenuación
|
||||||
void Background::setColor(Color color) {
|
void Background::setColor(Color color) {
|
||||||
attenuate_color_ = color;
|
attenuate_color_ = color;
|
||||||
|
|
||||||
@@ -264,52 +451,20 @@ void Background::setColor(Color color) {
|
|||||||
// Establece la transparencia de la atenuación
|
// Establece la transparencia de la atenuación
|
||||||
void Background::setAlpha(int alpha) {
|
void Background::setAlpha(int alpha) {
|
||||||
// Evita que se asignen valores fuera de rango
|
// Evita que se asignen valores fuera de rango
|
||||||
alpha_ = std::clamp(alpha, 0, 255);
|
alpha = std::clamp(alpha, 0, 255);
|
||||||
|
|
||||||
// Guarda el valor actual y establece el nuevo valor
|
// Guarda el valor actual y establece el nuevo valor
|
||||||
alpha_color_text_temp_ = alpha_color_text_;
|
previous_alpha_color_texture_ = alpha_color_texture_;
|
||||||
alpha_color_text_ = alpha_;
|
alpha_color_texture_ = alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el valor de alpha_
|
// Actualiza el valor de alpha
|
||||||
void Background::updateAlphaColorTexture() {
|
void Background::updateAlphaColorTexture() {
|
||||||
if (alpha_color_text_ == alpha_color_text_temp_) {
|
if (alpha_color_texture_ == previous_alpha_color_texture_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
alpha_color_text_ > alpha_color_text_temp_ ? ++alpha_color_text_temp_ : --alpha_color_text_temp_;
|
alpha_color_texture_ > previous_alpha_color_texture_ ? ++previous_alpha_color_texture_ : --previous_alpha_color_texture_;
|
||||||
SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_temp_);
|
SDL_SetTextureAlphaMod(color_texture_, previous_alpha_color_texture_);
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza las nubes
|
|
||||||
void Background::updateClouds() {
|
|
||||||
// Aplica la velocidad calculada a las nubes
|
|
||||||
top_clouds_sprite_a_->setVelX(clouds_speed_);
|
|
||||||
top_clouds_sprite_b_->setVelX(clouds_speed_);
|
|
||||||
bottom_clouds_sprite_a_->setVelX(clouds_speed_ / 2);
|
|
||||||
bottom_clouds_sprite_b_->setVelX(clouds_speed_ / 2);
|
|
||||||
|
|
||||||
// Mueve las nubes
|
|
||||||
top_clouds_sprite_a_->update();
|
|
||||||
top_clouds_sprite_b_->update();
|
|
||||||
bottom_clouds_sprite_a_->update();
|
|
||||||
bottom_clouds_sprite_b_->update();
|
|
||||||
|
|
||||||
// Calcula el offset de las nubes
|
|
||||||
if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth()) {
|
|
||||||
top_clouds_sprite_a_->setPosX(top_clouds_sprite_a_->getWidth());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (top_clouds_sprite_b_->getPosX() < -top_clouds_sprite_b_->getWidth()) {
|
|
||||||
top_clouds_sprite_b_->setPosX(top_clouds_sprite_b_->getWidth());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bottom_clouds_sprite_a_->getPosX() < -bottom_clouds_sprite_a_->getWidth()) {
|
|
||||||
bottom_clouds_sprite_a_->setPosX(bottom_clouds_sprite_a_->getWidth());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bottom_clouds_sprite_b_->getPosX() < -bottom_clouds_sprite_b_->getWidth()) {
|
|
||||||
bottom_clouds_sprite_b_->setPosX(bottom_clouds_sprite_b_->getWidth());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Precalcula el vector con el recorrido del sol
|
// Precalcula el vector con el recorrido del sol
|
||||||
@@ -343,26 +498,22 @@ void Background::createMoonPath() {
|
|||||||
const float CENTER_Y = base_ - 50;
|
const float CENTER_Y = base_ - 50;
|
||||||
constexpr float RADIUS = 140;
|
constexpr float RADIUS = 140;
|
||||||
|
|
||||||
// Generar puntos de la curva desde 0 a 90 grados
|
|
||||||
constexpr double STEP = 0.01;
|
constexpr double STEP = 0.01;
|
||||||
const int NUM_STEPS = static_cast<int>((M_PI / 2 - 0) / STEP) + 1;
|
const int NUM_STEPS = static_cast<int>((M_PI / 2) / STEP) + 1;
|
||||||
|
|
||||||
|
constexpr float FREEZE_PERCENTAGE = 0.2f; // Porcentaje final del recorrido que se mantiene fijo
|
||||||
|
|
||||||
|
const int FREEZE_START_INDEX = static_cast<int>(NUM_STEPS * (1.0f - FREEZE_PERCENTAGE));
|
||||||
|
|
||||||
for (int i = 0; i < NUM_STEPS; ++i) {
|
for (int i = 0; i < NUM_STEPS; ++i) {
|
||||||
double theta = 0 + i * STEP;
|
double theta = i * STEP;
|
||||||
float x = CENTER_X + (RADIUS * cos(theta));
|
float x = CENTER_X + (RADIUS * cos(theta));
|
||||||
float y = CENTER_Y - (RADIUS * sin(theta));
|
float y = CENTER_Y - (RADIUS * sin(theta));
|
||||||
moon_path_.push_back({x, y});
|
|
||||||
|
if (i >= FREEZE_START_INDEX && !moon_path_.empty()) {
|
||||||
|
moon_path_.push_back(moon_path_.back()); // Repite el último punto válido
|
||||||
|
} else {
|
||||||
|
moon_path_.push_back({x, y});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece la posición del sol
|
|
||||||
void Background::setSunProgression(float progress) {
|
|
||||||
progress = std::clamp(progress, 0.0F, 1.0F);
|
|
||||||
sun_index_ = static_cast<size_t>(progress * (sun_path_.size() - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Establece la posición de la luna
|
|
||||||
void Background::setMoonProgression(float progress) {
|
|
||||||
progress = std::clamp(progress, 0.0F, 1.0F);
|
|
||||||
moon_index_ = static_cast<size_t>(progress * (moon_path_.size() - 1));
|
|
||||||
}
|
|
||||||
@@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FRect, SDL_FPoint, SDL_Texture, SDL_Renderer
|
#include <SDL3/SDL.h> // Para SDL_FRect, SDL_FPoint, SDL_Texture, SDL_Renderer
|
||||||
|
|
||||||
#include <array> // Para array
|
#include <array> // Para array
|
||||||
#include <cstddef> // Para size_t
|
#include <cstddef> // Para size_t
|
||||||
#include <memory> // Para unique_ptr, shared_ptr
|
#include <functional> // Para std::function
|
||||||
#include <vector> // Para vector
|
#include <memory> // Para unique_ptr, shared_ptr
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "color.h" // Para Color
|
#include "color.h" // Para Color
|
||||||
|
|
||||||
@@ -16,21 +17,29 @@ class Texture;
|
|||||||
/*
|
/*
|
||||||
Esta clase gestiona el fondo que aparece en la sección jugable.
|
Esta clase gestiona el fondo que aparece en la sección jugable.
|
||||||
|
|
||||||
Usa una textura compuesta y una capa superior con un color sólido cuya opacidad es ajustable.
|
Maneja internamente su progresión a través de diferentes estados del día/noche,
|
||||||
Su área total está definida por "rect", pero solo se pinta la región "srcRect" en la pantalla en "dstRect".
|
controlando las transiciones entre gradientes, posiciones del sol/luna y velocidad de nubes.
|
||||||
|
|
||||||
|
Estados:
|
||||||
|
- NORMAL: Progresión normal del día
|
||||||
|
- COMPLETED: Reducción gradual de la actividad (nubes más lentas)
|
||||||
|
|
||||||
Métodos clave:
|
Métodos clave:
|
||||||
- setCloudsSpeed(float value) -> Define la velocidad de las nubes
|
- incrementProgress() -> Avanza la progresión del fondo
|
||||||
- setGradientNumber(int value) -> Ajusta el índice del color de cielo
|
- setState() -> Cambia el estado del fondo
|
||||||
- setTransition(float value) -> Configura la transición entre texturas
|
- setColor/setAlpha -> Efectos de atenuación
|
||||||
- setColor(Color color) -> Aplica un color de atenuación
|
|
||||||
- setAlpha(int alpha) -> Ajusta la transparencia de la capa de atenuación
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Background {
|
class Background {
|
||||||
public:
|
public:
|
||||||
|
// Enumeración de estados
|
||||||
|
enum class State {
|
||||||
|
NORMAL,
|
||||||
|
COMPLETED
|
||||||
|
};
|
||||||
|
|
||||||
// Constructor y Destructor
|
// Constructor y Destructor
|
||||||
Background();
|
Background(float total_progress_to_complete = 6100.0f);
|
||||||
~Background();
|
~Background();
|
||||||
|
|
||||||
// Actualización y renderizado
|
// Actualización y renderizado
|
||||||
@@ -40,20 +49,46 @@ class Background {
|
|||||||
// Configuración de posición
|
// Configuración de posición
|
||||||
void setPos(SDL_FRect pos); // Establece la posición del objeto
|
void setPos(SDL_FRect pos); // Establece la posición del objeto
|
||||||
|
|
||||||
// Configuración de animaciones y efectos
|
// Control de progresión
|
||||||
void setCloudsSpeed(float value); // Ajusta la velocidad de desplazamiento de las nubes
|
void incrementProgress(float amount = 1.0f); // Incrementa la progresión interna
|
||||||
void setGradientNumber(int value); // Establece el degradado de fondo a usar
|
void setProgress(float absolute_progress); // Establece la progresión absoluta
|
||||||
void setTransition(float value); // Ajusta la transición entre texturas de fondo
|
void setState(State new_state); // Cambia el estado del fondo
|
||||||
|
void reset(); // Reinicia la progresión
|
||||||
|
|
||||||
|
// Sistema de callback para sincronización automática
|
||||||
|
using ProgressCallback = std::function<void(float)>;
|
||||||
|
void setProgressCallback(ProgressCallback callback); // Establece callback para sincronización
|
||||||
|
void removeProgressCallback(); // Elimina el callback
|
||||||
|
|
||||||
|
// Configuración manual (para uso fuera del juego principal)
|
||||||
|
void setManualMode(bool manual); // Activa/desactiva el modo manual
|
||||||
|
void setCloudsSpeed(float value); // Ajusta la velocidad de las nubes
|
||||||
|
void setGradientNumber(int value); // Establece el degradado de fondo
|
||||||
|
void setTransition(float value); // Ajusta la transición entre texturas
|
||||||
|
void setSunProgression(float progress); // Establece la posición del sol
|
||||||
|
void setMoonProgression(float progress); // Establece la posición de la luna
|
||||||
|
|
||||||
// Configuración de efectos visuales
|
// Configuración de efectos visuales
|
||||||
void setColor(Color color); // Establece el color de atenuación
|
void setColor(Color color); // Establece el color de atenuación
|
||||||
void setAlpha(int alpha); // Ajusta la transparencia del fondo
|
void setAlpha(int alpha); // Ajusta la transparencia del fondo
|
||||||
|
|
||||||
// Configuración del sol y la luna
|
// Getters para información del estado
|
||||||
void setSunProgression(float progress); // Establece la posición del sol
|
float getProgress() const { return progress_; }
|
||||||
void setMoonProgression(float progress); // Establece la posición de la luna
|
State getState() const { return state_; }
|
||||||
|
int getCurrentGradient() const { return static_cast<int>(gradient_number_); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Constantes de configuración
|
||||||
|
static constexpr size_t STAGES = 4;
|
||||||
|
static constexpr float COMPLETED_REDUCTION_RATE = 25.0f;
|
||||||
|
static constexpr float MINIMUM_COMPLETED_PROGRESS = 200.0f;
|
||||||
|
static constexpr float SUN_COMPLETION_FACTOR = 0.5f; // El sol completa su recorrido a la mitad del progreso total
|
||||||
|
|
||||||
|
// Configuración paramétrica
|
||||||
|
const float total_progress_to_complete_;
|
||||||
|
const float progress_per_stage_;
|
||||||
|
const float sun_completion_progress_;
|
||||||
|
|
||||||
// Objetos y punteros
|
// Objetos y punteros
|
||||||
SDL_Renderer *renderer_; // Renderizador de la ventana
|
SDL_Renderer *renderer_; // Renderizador de la ventana
|
||||||
|
|
||||||
@@ -81,34 +116,51 @@ class Background {
|
|||||||
SDL_Texture *canvas_; // Textura para componer el fondo
|
SDL_Texture *canvas_; // Textura para componer el fondo
|
||||||
SDL_Texture *color_texture_; // Textura para atenuar el fondo
|
SDL_Texture *color_texture_; // Textura para atenuar el fondo
|
||||||
|
|
||||||
// Variables de control
|
// Variables de estado y progresión
|
||||||
std::array<SDL_FRect, 4> gradient_rect_;
|
State state_ = State::NORMAL;
|
||||||
std::array<SDL_FRect, 4> top_clouds_rect_;
|
float progress_ = 0.0f; // Progresión interna (0 a total_progress_to_complete_)
|
||||||
std::array<SDL_FRect, 4> bottom_clouds_rect_;
|
bool manual_mode_ = false; // Si está en modo manual, no actualiza automáticamente
|
||||||
int gradient_number_ = 0;
|
ProgressCallback progress_callback_; // Callback para notificar cambios de progreso
|
||||||
int alpha_ = 0;
|
|
||||||
float clouds_speed_ = 0;
|
// Variables de renderizado
|
||||||
float transition_ = 0;
|
SDL_FRect rect_; // Tamaño del objeto
|
||||||
int counter_ = 0;
|
SDL_FRect src_rect_; // Parte del objeto para copiar en pantalla
|
||||||
SDL_FRect rect_;
|
SDL_FRect dst_rect_; // Posición en pantalla donde se copia el objeto
|
||||||
SDL_FRect src_rect_;
|
std::array<SDL_FRect, STAGES> gradient_rect_; // Fondos degradados
|
||||||
SDL_FRect dst_rect_;
|
std::array<SDL_FRect, 4> top_clouds_rect_; // Nubes superiores
|
||||||
int base_;
|
std::array<SDL_FRect, 4> bottom_clouds_rect_; // Nubes inferiores
|
||||||
Color attenuate_color_;
|
Color attenuate_color_; // Color de atenuación
|
||||||
int alpha_color_text_;
|
|
||||||
int alpha_color_text_temp_;
|
std::vector<SDL_FPoint> sun_path_; // Recorrido del sol
|
||||||
std::vector<SDL_FPoint> sun_path_;
|
std::vector<SDL_FPoint> moon_path_; // Recorrido de la luna
|
||||||
std::vector<SDL_FPoint> moon_path_;
|
|
||||||
size_t sun_index_ = 0;
|
float clouds_speed_ = 0; // Velocidad de las nubes
|
||||||
size_t moon_index_ = 0;
|
float transition_ = 0; // Porcentaje de transición
|
||||||
|
|
||||||
|
size_t gradient_number_ = 0; // Índice de fondo degradado
|
||||||
|
size_t counter_ = 0; // Contador interno
|
||||||
|
size_t alpha_color_texture_ = 0; // Transparencia de atenuación
|
||||||
|
size_t previous_alpha_color_texture_ = 0; // Transparencia anterior
|
||||||
|
size_t sun_index_ = 0; // Índice del recorrido del sol
|
||||||
|
size_t moon_index_ = 0; // Índice del recorrido de la luna
|
||||||
|
int base_ = 0; // Posición base del fondo
|
||||||
|
|
||||||
|
Uint8 alpha_ = 0; // Transparencia entre fases
|
||||||
|
|
||||||
// Métodos internos
|
// Métodos internos
|
||||||
void renderGradient(); // Dibuja el gradiente de fondo
|
void initializePaths(); // Inicializa las rutas del sol y la luna
|
||||||
void renderTopClouds(); // Dibuja las nubes superiores
|
void initializeRects(); // Inicializa los rectángulos de gradientes y nubes
|
||||||
void renderBottomClouds(); // Dibuja las nubes inferiores
|
void initializeSprites(); // Crea los sprites
|
||||||
void fillCanvas(); // Compone todos los elementos en la textura
|
void initializeSpriteProperties(); // Configura las propiedades iniciales de los sprites
|
||||||
void updateAlphaColorTexture(); // Actualiza el alpha de la textura de atenuación
|
void initializeTextures(); // Inicializa las texturas de renderizado
|
||||||
void updateClouds(); // Actualiza el movimiento de las nubes
|
void updateProgression(); // Actualiza la progresión y calcula transiciones
|
||||||
void createSunPath(); // Precalcula el recorrido del sol
|
void updateCloudsSpeed(); // Actualiza la velocidad de las nubes según el estado
|
||||||
void createMoonPath(); // Precalcula el recorrido de la luna
|
void renderGradient(); // Dibuja el gradiente de fondo
|
||||||
};
|
void renderTopClouds(); // Dibuja las nubes superiores
|
||||||
|
void renderBottomClouds(); // Dibuja las nubes inferiores
|
||||||
|
void fillCanvas(); // Compone todos los elementos en la textura
|
||||||
|
void updateAlphaColorTexture(); // Actualiza el alpha de la textura de atenuación
|
||||||
|
void updateClouds(); // Actualiza el movimiento de las nubes
|
||||||
|
void createSunPath(); // Precalcula el recorrido del sol
|
||||||
|
void createMoonPath(); // Precalcula el recorrido de la luna
|
||||||
|
};
|
||||||
@@ -95,10 +95,9 @@ Balloon::Balloon(float x, float y, Type type, Size size, float vel_x, float spee
|
|||||||
|
|
||||||
// Centra el globo en la posición X
|
// Centra el globo en la posición X
|
||||||
void Balloon::alignTo(int x) {
|
void Balloon::alignTo(int x) {
|
||||||
x_ = static_cast<float>(x - (w_ / 2));
|
const float MIN_X = play_area_.x;
|
||||||
const int MIN_X = play_area_.x;
|
const float MAX_X = play_area_.w - w_;
|
||||||
const int MAX_X = play_area_.w - w_;
|
x_ = std::clamp(x - (w_ / 2), MIN_X, MAX_X);
|
||||||
x_ = std::clamp(x_, static_cast<float>(MIN_X), static_cast<float>(MAX_X));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pinta el globo en la pantalla
|
// Pinta el globo en la pantalla
|
||||||
|
|||||||
@@ -12,13 +12,14 @@
|
|||||||
#include "param.h" // Para Param, ParamGame, param
|
#include "param.h" // Para Param, ParamGame, param
|
||||||
#include "resource.h" // Para Resource
|
#include "resource.h" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "screen.h" // Para Screen
|
||||||
#include "stage.h" // Para addPower
|
#include "stage_interface.h" // Para IStageInfo
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
BalloonManager::BalloonManager()
|
BalloonManager::BalloonManager(IStageInfo *stage_info)
|
||||||
: explosions_(std::make_unique<Explosions>()),
|
: explosions_(std::make_unique<Explosions>()),
|
||||||
balloon_formations_(std::make_unique<BalloonFormations>()) { init(); }
|
balloon_formations_(std::make_unique<BalloonFormations>()),
|
||||||
|
stage_info_(stage_info) { init(); }
|
||||||
|
|
||||||
// Inicializa
|
// Inicializa
|
||||||
void BalloonManager::init() {
|
void BalloonManager::init() {
|
||||||
@@ -110,7 +111,7 @@ void BalloonManager::deployRandomFormation(int stage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reinicia el contador para el próximo despliegue
|
// Reinicia el contador para el próximo despliegue
|
||||||
balloon_deploy_counter_ = 300;
|
balloon_deploy_counter_ = DEFAULT_BALLOON_DEPLOY_COUNTER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,23 +175,22 @@ void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon> &balloon,
|
|||||||
const auto SIZE = static_cast<Balloon::Size>(static_cast<int>(balloon->getSize()) - 1);
|
const auto SIZE = static_cast<Balloon::Size>(static_cast<int>(balloon->getSize()) - 1);
|
||||||
const int PARENT_HEIGHT = balloon->getHeight();
|
const int PARENT_HEIGHT = balloon->getHeight();
|
||||||
const int CHILD_HEIGHT = Balloon::WIDTH.at(static_cast<int>(balloon->getSize()) - 1);
|
const int CHILD_HEIGHT = Balloon::WIDTH.at(static_cast<int>(balloon->getSize()) - 1);
|
||||||
const int Y = balloon->getPosY() + (PARENT_HEIGHT - CHILD_HEIGHT) / 2;
|
const int CHILD_WIDTH = CHILD_HEIGHT;
|
||||||
const int X = direction == "LEFT" ? balloon->getPosX() + (balloon->getWidth() / 3) : balloon->getPosX() + 2 * (balloon->getWidth() / 3);
|
const float Y = balloon->getPosY() + ((PARENT_HEIGHT - CHILD_HEIGHT) / 2);
|
||||||
|
float x = direction == "LEFT" ? balloon->getPosX() + (balloon->getWidth() / 3) : balloon->getPosX() + (2 * (balloon->getWidth() / 3));
|
||||||
|
const float MIN_X = play_area_.x;
|
||||||
|
const float MAX_X = play_area_.w - CHILD_WIDTH;
|
||||||
|
x = std::clamp(x - (CHILD_WIDTH / 2), MIN_X, MAX_X);
|
||||||
|
|
||||||
// Crea el globo
|
// Crea el globo
|
||||||
auto b = createBalloon(0, Y, balloon->getType(), SIZE, VX, balloon_speed_, 0);
|
auto b = createBalloon(x, Y, balloon->getType(), SIZE, VX, balloon_speed_, 0);
|
||||||
|
|
||||||
// Establece parametros
|
// Establece parametros
|
||||||
b->alignTo(X);
|
|
||||||
b->setVelY(b->getType() == Balloon::Type::BALLOON ? -2.50F : Balloon::VELX_NEGATIVE * 2.0F);
|
b->setVelY(b->getType() == Balloon::Type::BALLOON ? -2.50F : Balloon::VELX_NEGATIVE * 2.0F);
|
||||||
|
|
||||||
// Herencia de estados
|
// Herencia de estados
|
||||||
if (balloon->isStopped()) {
|
if (balloon->isStopped()) { b->stop(); }
|
||||||
b->stop();
|
if (balloon->isUsingReversedColor()) { b->useReverseColor(); }
|
||||||
}
|
|
||||||
if (balloon->isUsingReversedColor()) {
|
|
||||||
b->useReverseColor();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +227,7 @@ void BalloonManager::setBalloonSpeed(float speed) {
|
|||||||
|
|
||||||
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
|
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
|
||||||
auto BalloonManager::popBalloon(std::shared_ptr<Balloon> balloon) -> int {
|
auto BalloonManager::popBalloon(std::shared_ptr<Balloon> balloon) -> int {
|
||||||
Stage::addPower(1);
|
stage_info_->addPower(1);
|
||||||
int score = 0;
|
int score = 0;
|
||||||
|
|
||||||
if (balloon->getType() == Balloon::Type::POWERBALL) {
|
if (balloon->getType() == Balloon::Type::POWERBALL) {
|
||||||
@@ -274,7 +274,7 @@ auto BalloonManager::destroyBalloon(std::shared_ptr<Balloon> &balloon) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Aumenta el poder de la fase
|
// Aumenta el poder de la fase
|
||||||
Stage::addPower(balloon->getPower());
|
stage_info_->addPower(balloon->getPower());
|
||||||
|
|
||||||
// Destruye el globo
|
// Destruye el globo
|
||||||
explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize()));
|
explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize()));
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "balloon_formations.h" // Para BalloonFormations
|
#include "balloon_formations.h" // Para BalloonFormations
|
||||||
#include "explosions.h" // Para Explosions
|
#include "explosions.h" // Para Explosions
|
||||||
#include "param.h" // Para Param, ParamGame, param
|
#include "param.h" // Para Param, ParamGame, param
|
||||||
|
#include "stage_interface.h" // Para IStageInfo
|
||||||
#include "utils.h" // Para Zone
|
#include "utils.h" // Para Zone
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
@@ -22,7 +23,7 @@ using Balloons = std::vector<std::shared_ptr<Balloon>>;
|
|||||||
class BalloonManager {
|
class BalloonManager {
|
||||||
public:
|
public:
|
||||||
// Constructor y Destructor
|
// Constructor y Destructor
|
||||||
BalloonManager();
|
BalloonManager(IStageInfo *stage_info);
|
||||||
~BalloonManager() = default;
|
~BalloonManager() = default;
|
||||||
|
|
||||||
// Actualización y Renderizado
|
// Actualización y Renderizado
|
||||||
@@ -80,6 +81,8 @@ class BalloonManager {
|
|||||||
[[nodiscard]] auto getNumBalloons() const -> int { return balloons_.size(); }
|
[[nodiscard]] auto getNumBalloons() const -> int { return balloons_.size(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static const int DEFAULT_BALLOON_DEPLOY_COUNTER = 300;
|
||||||
|
|
||||||
Balloons balloons_; // Vector con los globos activos
|
Balloons balloons_; // Vector con los globos activos
|
||||||
std::unique_ptr<Explosions> explosions_; // Objeto para gestionar explosiones
|
std::unique_ptr<Explosions> explosions_; // Objeto para gestionar explosiones
|
||||||
std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para manejar formaciones enemigas
|
std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para manejar formaciones enemigas
|
||||||
@@ -103,6 +106,7 @@ class BalloonManager {
|
|||||||
bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar
|
bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar
|
||||||
bool poping_sound_enabled_ = true; // Si debe sonar el globo al explotar
|
bool poping_sound_enabled_ = true; // Si debe sonar el globo al explotar
|
||||||
bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido
|
bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido
|
||||||
|
IStageInfo *stage_info_; // Informacion de la pantalla actual
|
||||||
|
|
||||||
// Metodos privados
|
// Metodos privados
|
||||||
void init();
|
void init();
|
||||||
|
|||||||
@@ -81,6 +81,14 @@ struct Color {
|
|||||||
|
|
||||||
return Color(new_r, new_g, new_b, new_a);
|
return Color(new_r, new_g, new_b, new_a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convierte el color a un entero de 32 bits en formato RGBA
|
||||||
|
[[nodiscard]] constexpr auto toUint32() const -> Uint32 {
|
||||||
|
return (static_cast<Uint32>(r) << 24) |
|
||||||
|
(static_cast<Uint32>(g) << 16) |
|
||||||
|
(static_cast<Uint32>(b) << 8) |
|
||||||
|
static_cast<Uint32>(a);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Estructura para definir un color HSV
|
// Estructura para definir un color HSV
|
||||||
|
|||||||
180
source/defaults.h
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include "color.h"
|
||||||
|
#include "ui/notifier.h" // Para Notifier::Position
|
||||||
|
|
||||||
|
// Configuración centralizada con todos los valores por defecto del juego
|
||||||
|
namespace GameDefaults {
|
||||||
|
|
||||||
|
// --- GAME ---
|
||||||
|
namespace Game {
|
||||||
|
constexpr float WIDTH = 320.0f;
|
||||||
|
constexpr float HEIGHT = 256.0f;
|
||||||
|
constexpr float ITEM_SIZE = 20.0f;
|
||||||
|
constexpr int NAME_ENTRY_IDLE_TIME = 10;
|
||||||
|
constexpr int NAME_ENTRY_TOTAL_TIME = 60;
|
||||||
|
constexpr bool HIT_STOP = false;
|
||||||
|
constexpr int HIT_STOP_MS = 500;
|
||||||
|
|
||||||
|
// Play area por defecto
|
||||||
|
constexpr float PLAY_AREA_X = 0.0f;
|
||||||
|
constexpr float PLAY_AREA_Y = 0.0f;
|
||||||
|
constexpr float PLAY_AREA_W = 320.0f;
|
||||||
|
constexpr float PLAY_AREA_H = 216.0f;
|
||||||
|
} // namespace Game
|
||||||
|
|
||||||
|
// --- FADE ---
|
||||||
|
namespace Fade {
|
||||||
|
constexpr const char* COLOR = "1F2B30";
|
||||||
|
constexpr float NUM_SQUARES_WIDTH = 160.0f;
|
||||||
|
constexpr float NUM_SQUARES_HEIGHT = 128.0f;
|
||||||
|
constexpr int RANDOM_SQUARES_DELAY = 1;
|
||||||
|
constexpr int RANDOM_SQUARES_MULT = 500;
|
||||||
|
constexpr int POST_DURATION = 80;
|
||||||
|
constexpr float VENETIAN_SIZE = 12.0f;
|
||||||
|
} // namespace Fade
|
||||||
|
|
||||||
|
// --- SCOREBOARD ---
|
||||||
|
namespace Scoreboard {
|
||||||
|
constexpr float RECT_X = 0.0f;
|
||||||
|
constexpr float RECT_Y = 216.0f;
|
||||||
|
constexpr float RECT_W = 320.0f;
|
||||||
|
constexpr float RECT_H = 40.0f;
|
||||||
|
constexpr bool SEPARATOR_AUTOCOLOR = true;
|
||||||
|
constexpr const char* SEPARATOR_COLOR = "0D1A2B";
|
||||||
|
constexpr const char* EASY_COLOR = "4B692F";
|
||||||
|
constexpr const char* NORMAL_COLOR = "2E3F47";
|
||||||
|
constexpr const char* HARD_COLOR = "76428A";
|
||||||
|
constexpr bool TEXT_AUTOCOLOR = true;
|
||||||
|
constexpr const char* TEXT_COLOR1 = "FFFFFF";
|
||||||
|
constexpr const char* TEXT_COLOR2 = "FFFFFF";
|
||||||
|
constexpr int SKIP_COUNTDOWN_VALUE = 8;
|
||||||
|
} // namespace Scoreboard
|
||||||
|
|
||||||
|
// --- TITLE ---
|
||||||
|
namespace Title {
|
||||||
|
constexpr int PRESS_START_POSITION = 180;
|
||||||
|
constexpr int DURATION = 800;
|
||||||
|
constexpr int ARCADE_EDITION_POSITION = 123;
|
||||||
|
constexpr int TITLE_C_C_POSITION = 80;
|
||||||
|
constexpr const char* BG_COLOR = "41526F";
|
||||||
|
} // namespace Title
|
||||||
|
|
||||||
|
// --- BACKGROUND ---
|
||||||
|
namespace Background {
|
||||||
|
constexpr const char* ATTENUATE_COLOR = "FFFFFF00";
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- BALLOONS ---
|
||||||
|
namespace Balloon {
|
||||||
|
// Configuración de física para cada nivel de globo
|
||||||
|
struct BalloonSettings {
|
||||||
|
float vel;
|
||||||
|
float grav;
|
||||||
|
constexpr BalloonSettings(float v, float g) : vel(v), grav(g) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<BalloonSettings, 4> SETTINGS = {{
|
||||||
|
BalloonSettings(2.75f, 0.09f), // Globo 0
|
||||||
|
BalloonSettings(3.70f, 0.10f), // Globo 1
|
||||||
|
BalloonSettings(4.70f, 0.10f), // Globo 2
|
||||||
|
BalloonSettings(5.45f, 0.10f) // Globo 3
|
||||||
|
}};
|
||||||
|
|
||||||
|
constexpr std::array<const char*, 4> COLORS = {
|
||||||
|
"blue", "orange", "red", "green"};
|
||||||
|
|
||||||
|
constexpr bool BOUNCING_SOUND = false;
|
||||||
|
} // namespace Balloon
|
||||||
|
|
||||||
|
// --- NOTIFICATION ---
|
||||||
|
namespace Notification {
|
||||||
|
constexpr Notifier::Position POS_V = Notifier::Position::TOP;
|
||||||
|
constexpr Notifier::Position POS_H = Notifier::Position::LEFT;
|
||||||
|
constexpr bool SOUND = false;
|
||||||
|
constexpr const char* COLOR = "303030";
|
||||||
|
} // namespace Notification
|
||||||
|
|
||||||
|
// --- SERVICE MENU ---
|
||||||
|
namespace ServiceMenu {
|
||||||
|
constexpr const char* TITLE_COLOR = "99FF62";
|
||||||
|
constexpr const char* TEXT_COLOR = "FFFFFF";
|
||||||
|
constexpr const char* SELECTED_COLOR = "FFDC44";
|
||||||
|
constexpr const char* BG_COLOR = "000F00F5";
|
||||||
|
constexpr bool DROP_SHADOW = false;
|
||||||
|
|
||||||
|
// WindowMessage defaults
|
||||||
|
namespace WindowMessage {
|
||||||
|
constexpr const char* BG_COLOR = "141E32F0"; // Color(20, 30, 50, 240)
|
||||||
|
constexpr const char* BORDER_COLOR = "6496C8FF"; // Color(100, 150, 200, 255)
|
||||||
|
constexpr const char* TITLE_COLOR = "6496C8FF"; // Color(100, 150, 200, 255)
|
||||||
|
constexpr const char* TEXT_COLOR = "DCDCDCFF"; // Color(220, 220, 220, 255)
|
||||||
|
constexpr float PADDING = 15.0f;
|
||||||
|
constexpr float LINE_SPACING = 5.0f;
|
||||||
|
constexpr float TITLE_SEPARATOR_SPACING = 10.0f; // Cambiado a float
|
||||||
|
constexpr float MIN_WIDTH = 250.0f;
|
||||||
|
constexpr float MIN_HEIGHT = 32.0f; // Cambiado a float
|
||||||
|
constexpr float MAX_WIDTH_RATIO = 0.8f; // Nuevo
|
||||||
|
constexpr float MAX_HEIGHT_RATIO = 0.8f; // Nuevo
|
||||||
|
constexpr float TEXT_SAFETY_MARGIN = 15.0f;
|
||||||
|
constexpr float ANIMATION_DURATION = 0.3f;
|
||||||
|
} // namespace WindowMessage
|
||||||
|
} // namespace ServiceMenu
|
||||||
|
|
||||||
|
// --- INTRO ---
|
||||||
|
namespace Intro {
|
||||||
|
constexpr const char* BG_COLOR = "4664BD";
|
||||||
|
constexpr const char* CARD_COLOR = "CBDBFC";
|
||||||
|
constexpr const char* SHADOW_COLOR = "00000080";
|
||||||
|
constexpr int TEXT_DISTANCE_FROM_BOTTOM = 48;
|
||||||
|
} // namespace Intro
|
||||||
|
|
||||||
|
// --- DEBUG ---
|
||||||
|
namespace Debug {
|
||||||
|
constexpr const char* COLOR = "00FFFF";
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- RESOURCE ---
|
||||||
|
namespace Resource {
|
||||||
|
constexpr const char* COLOR = "FFFFFF";
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- TABE ---
|
||||||
|
namespace Tabe {
|
||||||
|
constexpr float MIN_SPAWN_TIME = 2.0f;
|
||||||
|
constexpr float MAX_SPAWN_TIME = 3.0f;
|
||||||
|
} // namespace Tabe
|
||||||
|
|
||||||
|
// --- PLAYER ---
|
||||||
|
namespace Player {
|
||||||
|
namespace OneCoffeeShirt {
|
||||||
|
// Player 0 (Jugador 1)
|
||||||
|
constexpr const char* PLAYER0_DARKEST = "3D9C70FF"; // 61, 156, 112, 255
|
||||||
|
constexpr const char* PLAYER0_DARK = "4FA370FF"; // 79, 163, 112, 255
|
||||||
|
constexpr const char* PLAYER0_BASE = "5DDE70FF"; // 93, 222, 112, 255
|
||||||
|
constexpr const char* PLAYER0_LIGHT = "7DF25CFF"; // 125, 242, 92, 255
|
||||||
|
|
||||||
|
// Player 1 (Jugador 2)
|
||||||
|
constexpr const char* PLAYER1_DARKEST = "2E8B57FF"; // 46, 139, 87, 255
|
||||||
|
constexpr const char* PLAYER1_DARK = "3CB371FF"; // 60, 179, 113, 255
|
||||||
|
constexpr const char* PLAYER1_BASE = "48D181FF"; // 72, 209, 129, 255
|
||||||
|
constexpr const char* PLAYER1_LIGHT = "55EF8DFF"; // 85, 239, 141, 255
|
||||||
|
} // namespace OneCoffeeShirt
|
||||||
|
|
||||||
|
namespace TwoCoffeeShirt {
|
||||||
|
// Player 0 (Jugador 1)
|
||||||
|
constexpr const char* PLAYER0_DARKEST = "D6A41AFF"; // 214, 164, 26, 255
|
||||||
|
constexpr const char* PLAYER0_DARK = "E3AE1BFF"; // 227, 174, 27, 255
|
||||||
|
constexpr const char* PLAYER0_BASE = "EFB71DFF"; // 239, 183, 29, 255
|
||||||
|
constexpr const char* PLAYER0_LIGHT = "FCC11EFF"; // 252, 193, 30, 255
|
||||||
|
|
||||||
|
// Player 1 (Jugador 2)
|
||||||
|
constexpr const char* PLAYER1_DARKEST = "E08500FF"; // 224, 133, 0, 255
|
||||||
|
constexpr const char* PLAYER1_DARK = "FA7D00FF"; // 250, 125, 0, 255
|
||||||
|
constexpr const char* PLAYER1_BASE = "FAA200FF"; // 250, 162, 0, 255
|
||||||
|
constexpr const char* PLAYER1_LIGHT = "FA8500FF"; // 250, 133, 0, 255
|
||||||
|
} // namespace TwoCoffeeShirt
|
||||||
|
} // namespace Player
|
||||||
|
} // namespace GameDefaults
|
||||||
@@ -24,20 +24,7 @@ DefineButtons::DefineButtons()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Crear la ventana de mensaje
|
// Crear la ventana de mensaje
|
||||||
WindowMessage::Config config;
|
WindowMessage::Config config(param.service_menu.window_message);
|
||||||
config.bg_color = Color{20, 30, 50, 240}; // Fondo azul oscuro semi-transparente
|
|
||||||
config.border_color = Color{100, 150, 200, 255}; // Borde azul claro
|
|
||||||
config.title_color = Color{100, 150, 200, 255}; // Titulo azul claro
|
|
||||||
config.text_color = Color{220, 220, 220, 255}; // Texto gris claro
|
|
||||||
config.padding = 15.0F;
|
|
||||||
config.line_spacing = 5.0F;
|
|
||||||
config.title_separator_spacing = 15;
|
|
||||||
config.min_width = 250.0F;
|
|
||||||
config.text_safety_margin = 15.0F;
|
|
||||||
config.min_width = 100;
|
|
||||||
config.min_height = 32;
|
|
||||||
config.animation_duration = 0.3F;
|
|
||||||
|
|
||||||
auto text_renderer = Resource::get()->getText("04b_25_flat");
|
auto text_renderer = Resource::get()->getText("04b_25_flat");
|
||||||
window_message_ = std::make_unique<WindowMessage>(
|
window_message_ = std::make_unique<WindowMessage>(
|
||||||
text_renderer,
|
text_renderer,
|
||||||
@@ -85,6 +72,9 @@ void DefineButtons::handleEvents(const SDL_Event &event) {
|
|||||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||||
checkEnd();
|
checkEnd();
|
||||||
break;
|
break;
|
||||||
|
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||||
|
doControllerAxisMotion(event.gaxis);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -99,6 +89,8 @@ auto DefineButtons::enable(Options::Gamepad *options_gamepad) -> bool {
|
|||||||
index_button_ = 0;
|
index_button_ = 0;
|
||||||
message_shown_ = false;
|
message_shown_ = false;
|
||||||
closing_ = false;
|
closing_ = false;
|
||||||
|
l2_was_pressed_ = false;
|
||||||
|
r2_was_pressed_ = false;
|
||||||
clearButtons();
|
clearButtons();
|
||||||
updateWindowMessage();
|
updateWindowMessage();
|
||||||
|
|
||||||
@@ -117,6 +109,8 @@ void DefineButtons::disable() {
|
|||||||
finished_ = false;
|
finished_ = false;
|
||||||
message_shown_ = false;
|
message_shown_ = false;
|
||||||
closing_ = false;
|
closing_ = false;
|
||||||
|
l2_was_pressed_ = false;
|
||||||
|
r2_was_pressed_ = false;
|
||||||
|
|
||||||
if (window_message_) {
|
if (window_message_) {
|
||||||
window_message_->hide();
|
window_message_->hide();
|
||||||
@@ -138,6 +132,56 @@ void DefineButtons::doControllerButtonDown(const SDL_GamepadButtonEvent &event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DefineButtons::doControllerAxisMotion(const SDL_GamepadAxisEvent &event) {
|
||||||
|
auto gamepad = input_->getGamepad(event.which);
|
||||||
|
|
||||||
|
if (!gamepad || gamepad != options_gamepad_->instance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Solo manejamos L2 y R2 como botones con lógica de transición
|
||||||
|
if (event.axis == SDL_GAMEPAD_AXIS_LEFT_TRIGGER) {
|
||||||
|
bool l2_is_pressed_now = event.value > 16384;
|
||||||
|
|
||||||
|
// Solo actuar en la transición de no presionado a presionado
|
||||||
|
if (l2_is_pressed_now && !l2_was_pressed_) {
|
||||||
|
const auto TRIGGER_BUTTON = Input::TRIGGER_L2_AS_BUTTON;
|
||||||
|
if (checkTriggerNotInUse(TRIGGER_BUTTON)) {
|
||||||
|
buttons_.at(index_button_).button = TRIGGER_BUTTON;
|
||||||
|
incIndexButton();
|
||||||
|
updateWindowMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detectar liberación del trigger para llamar checkEnd()
|
||||||
|
if (!l2_is_pressed_now && l2_was_pressed_) {
|
||||||
|
checkEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
l2_was_pressed_ = l2_is_pressed_now;
|
||||||
|
|
||||||
|
} else if (event.axis == SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) {
|
||||||
|
bool r2_is_pressed_now = event.value > 16384;
|
||||||
|
|
||||||
|
// Solo actuar en la transición de no presionado a presionado
|
||||||
|
if (r2_is_pressed_now && !r2_was_pressed_) {
|
||||||
|
const auto TRIGGER_BUTTON = Input::TRIGGER_R2_AS_BUTTON;
|
||||||
|
if (checkTriggerNotInUse(TRIGGER_BUTTON)) {
|
||||||
|
buttons_.at(index_button_).button = TRIGGER_BUTTON;
|
||||||
|
incIndexButton();
|
||||||
|
updateWindowMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detectar liberación del trigger para llamar checkEnd()
|
||||||
|
if (!r2_is_pressed_now && r2_was_pressed_) {
|
||||||
|
checkEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
r2_was_pressed_ = r2_is_pressed_now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DefineButtons::bindButtons(Options::Gamepad *options_gamepad) {
|
void DefineButtons::bindButtons(Options::Gamepad *options_gamepad) {
|
||||||
for (const auto &button : buttons_) {
|
for (const auto &button : buttons_) {
|
||||||
Input::bindGameControllerButton(options_gamepad->instance, button.action, button.button);
|
Input::bindGameControllerButton(options_gamepad->instance, button.action, button.button);
|
||||||
@@ -161,6 +205,12 @@ auto DefineButtons::checkButtonNotInUse(SDL_GamepadButton button) -> bool {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto DefineButtons::checkTriggerNotInUse(SDL_GamepadButton trigger_button) -> bool {
|
||||||
|
return std::ranges::all_of(buttons_, [trigger_button](const auto &b) {
|
||||||
|
return b.button != trigger_button;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void DefineButtons::clearButtons() {
|
void DefineButtons::clearButtons() {
|
||||||
buttons_.clear();
|
buttons_.clear();
|
||||||
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_LEFT"), Input::Action::FIRE_LEFT, SDL_GAMEPAD_BUTTON_INVALID);
|
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_LEFT"), Input::Action::FIRE_LEFT, SDL_GAMEPAD_BUTTON_INVALID);
|
||||||
|
|||||||
@@ -60,12 +60,16 @@ class DefineButtons {
|
|||||||
bool finished_ = false; // Flag para indicar si ha terminado
|
bool finished_ = false; // Flag para indicar si ha terminado
|
||||||
bool closing_ = false; // Flag para indicar que está cerrando
|
bool closing_ = false; // Flag para indicar que está cerrando
|
||||||
bool message_shown_ = false; // Flag para indicar que ya mostró el mensaje
|
bool message_shown_ = false; // Flag para indicar que ya mostró el mensaje
|
||||||
|
bool l2_was_pressed_ = false; // Estado anterior del trigger L2
|
||||||
|
bool r2_was_pressed_ = false; // Estado anterior del trigger R2
|
||||||
|
|
||||||
// Métodos
|
// Métodos
|
||||||
void incIndexButton();
|
void incIndexButton();
|
||||||
void doControllerButtonDown(const SDL_GamepadButtonEvent &event);
|
void doControllerButtonDown(const SDL_GamepadButtonEvent &event);
|
||||||
|
void doControllerAxisMotion(const SDL_GamepadAxisEvent &event);
|
||||||
void bindButtons(Options::Gamepad *options_gamepad);
|
void bindButtons(Options::Gamepad *options_gamepad);
|
||||||
auto checkButtonNotInUse(SDL_GamepadButton button) -> bool;
|
auto checkButtonNotInUse(SDL_GamepadButton button) -> bool;
|
||||||
|
auto checkTriggerNotInUse(SDL_GamepadButton trigger_button) -> bool;
|
||||||
void clearButtons();
|
void clearButtons();
|
||||||
void checkEnd();
|
void checkEnd();
|
||||||
void updateWindowMessage();
|
void updateWindowMessage();
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ void handleInputEvents(const SDL_Event &event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba los eventos que se pueden producir en cualquier sección del juego
|
// Comprueba los eventos que se pueden producir en cualquier sección del juego
|
||||||
void check(const SDL_Event &event) {
|
void handle(const SDL_Event &event) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case SDL_EVENT_QUIT: // Evento de salida de la aplicación
|
case SDL_EVENT_QUIT: // Evento de salida de la aplicación
|
||||||
Section::name = Section::Name::QUIT;
|
Section::name = Section::Name::QUIT;
|
||||||
|
|||||||
@@ -4,5 +4,5 @@
|
|||||||
|
|
||||||
namespace GlobalEvents {
|
namespace GlobalEvents {
|
||||||
// Comprueba los eventos que se pueden producir en cualquier sección del juego
|
// Comprueba los eventos que se pueden producir en cualquier sección del juego
|
||||||
void check(const SDL_Event &event);
|
void handle(const SDL_Event &event);
|
||||||
} // namespace GlobalEvents
|
} // namespace GlobalEvents
|
||||||
@@ -65,6 +65,10 @@ auto Input::checkAction(Action action, bool repeat, bool check_keyboard, std::sh
|
|||||||
if (gamepad != nullptr) {
|
if (gamepad != nullptr) {
|
||||||
success_controller = checkAxisInput(action, gamepad, repeat);
|
success_controller = checkAxisInput(action, gamepad, repeat);
|
||||||
|
|
||||||
|
if (!success_controller) {
|
||||||
|
success_controller = checkTriggerInput(action, gamepad, repeat);
|
||||||
|
}
|
||||||
|
|
||||||
if (!success_controller) {
|
if (!success_controller) {
|
||||||
if (repeat) { // El usuario quiere saber si está pulsada (estado mantenido)
|
if (repeat) { // El usuario quiere saber si está pulsada (estado mantenido)
|
||||||
success_controller = gamepad->bindings[action].is_held;
|
success_controller = gamepad->bindings[action].is_held;
|
||||||
@@ -243,6 +247,54 @@ auto Input::checkAxisInput(Action action, std::shared_ptr<Gamepad> gamepad, bool
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Comprueba los triggers del mando como botones digitales
|
||||||
|
auto Input::checkTriggerInput(Action action, std::shared_ptr<Gamepad> gamepad, bool repeat) -> bool {
|
||||||
|
// Solo manejamos botones específicos que pueden ser triggers
|
||||||
|
if (gamepad->bindings[action].button != SDL_GAMEPAD_BUTTON_INVALID) {
|
||||||
|
// Solo procesamos L2 y R2 como triggers
|
||||||
|
SDL_GamepadButton button = gamepad->bindings[action].button;
|
||||||
|
|
||||||
|
// Verificar si el botón mapeado corresponde a un trigger virtual
|
||||||
|
// (Para esto necesitamos valores especiales que representen L2/R2 como botones)
|
||||||
|
bool trigger_active_now = false;
|
||||||
|
|
||||||
|
// Usamos constantes especiales para L2 y R2 como botones
|
||||||
|
if (button == TRIGGER_L2_AS_BUTTON) { // L2 como botón
|
||||||
|
Sint16 trigger_value = SDL_GetGamepadAxis(gamepad->pad, SDL_GAMEPAD_AXIS_LEFT_TRIGGER);
|
||||||
|
trigger_active_now = trigger_value > TRIGGER_THRESHOLD;
|
||||||
|
} else if (button == TRIGGER_R2_AS_BUTTON) { // R2 como botón
|
||||||
|
Sint16 trigger_value = SDL_GetGamepadAxis(gamepad->pad, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER);
|
||||||
|
trigger_active_now = trigger_value > TRIGGER_THRESHOLD;
|
||||||
|
} else {
|
||||||
|
return false; // No es un trigger
|
||||||
|
}
|
||||||
|
|
||||||
|
// Referencia al binding correspondiente
|
||||||
|
auto &binding = gamepad->bindings[action];
|
||||||
|
|
||||||
|
if (repeat) {
|
||||||
|
// Si se permite repetir, simplemente devolvemos el estado actual
|
||||||
|
return trigger_active_now;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si no se permite repetir, aplicamos la lógica de transición
|
||||||
|
if (trigger_active_now && !binding.trigger_active) {
|
||||||
|
// Transición de inactivo a activo
|
||||||
|
binding.trigger_active = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!trigger_active_now && binding.trigger_active) {
|
||||||
|
// Transición de activo a inactivo
|
||||||
|
binding.trigger_active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mantener el estado actual
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Input::addGamepadMappingsFromFile() {
|
void Input::addGamepadMappingsFromFile() {
|
||||||
if (SDL_AddGamepadMappingsFromFile(gamepad_mappings_file_.c_str()) < 0) {
|
if (SDL_AddGamepadMappingsFromFile(gamepad_mappings_file_.c_str()) < 0) {
|
||||||
std::cout << "Error, could not load " << gamepad_mappings_file_.c_str() << " file: " << SDL_GetError() << std::endl;
|
std::cout << "Error, could not load " << gamepad_mappings_file_.c_str() << " file: " << SDL_GetError() << std::endl;
|
||||||
@@ -280,6 +332,7 @@ void Input::resetInputStates() {
|
|||||||
for (auto &binding : gamepad->bindings) {
|
for (auto &binding : gamepad->bindings) {
|
||||||
binding.second.is_held = false;
|
binding.second.is_held = false;
|
||||||
binding.second.just_pressed = false;
|
binding.second.just_pressed = false;
|
||||||
|
binding.second.trigger_active = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ class Input {
|
|||||||
static constexpr bool CHECK_KEYBOARD = true;
|
static constexpr bool CHECK_KEYBOARD = true;
|
||||||
static constexpr bool DO_NOT_CHECK_KEYBOARD = false;
|
static constexpr bool DO_NOT_CHECK_KEYBOARD = false;
|
||||||
|
|
||||||
|
// Constantes para triggers como botones
|
||||||
|
static constexpr SDL_GamepadButton TRIGGER_L2_AS_BUTTON = static_cast<SDL_GamepadButton>(100);
|
||||||
|
static constexpr SDL_GamepadButton TRIGGER_R2_AS_BUTTON = static_cast<SDL_GamepadButton>(101);
|
||||||
|
|
||||||
// Alias para mantener compatibilidad con el código existente
|
// Alias para mantener compatibilidad con el código existente
|
||||||
using Action = InputAction;
|
using Action = InputAction;
|
||||||
|
|
||||||
@@ -39,9 +43,10 @@ class Input {
|
|||||||
bool is_held; // Está pulsada ahora mismo
|
bool is_held; // Está pulsada ahora mismo
|
||||||
bool just_pressed; // Se acaba de pulsar en este fotograma
|
bool just_pressed; // Se acaba de pulsar en este fotograma
|
||||||
bool axis_active; // Estado del eje
|
bool axis_active; // Estado del eje
|
||||||
|
bool trigger_active; // Estado del trigger como botón digital
|
||||||
|
|
||||||
ButtonState(SDL_GamepadButton btn = SDL_GAMEPAD_BUTTON_INVALID, bool is_held = false, bool just_pressed = false, bool axis_act = false)
|
ButtonState(SDL_GamepadButton btn = SDL_GAMEPAD_BUTTON_INVALID, bool is_held = false, bool just_pressed = false, bool axis_act = false)
|
||||||
: button(btn), is_held(is_held), just_pressed(just_pressed), axis_active(axis_act) {}
|
: button(btn), is_held(is_held), just_pressed(just_pressed), axis_active(axis_act), trigger_active(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Keyboard {
|
struct Keyboard {
|
||||||
@@ -178,6 +183,7 @@ class Input {
|
|||||||
private:
|
private:
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr Sint16 AXIS_THRESHOLD = 30000;
|
static constexpr Sint16 AXIS_THRESHOLD = 30000;
|
||||||
|
static constexpr Sint16 TRIGGER_THRESHOLD = 16384; // Umbral para triggers (aproximadamente 50% del rango)
|
||||||
static constexpr std::array<Action, 4> BUTTON_INPUTS = {Action::FIRE_LEFT, Action::FIRE_CENTER, Action::FIRE_RIGHT, Action::START}; // Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
|
static constexpr std::array<Action, 4> BUTTON_INPUTS = {Action::FIRE_LEFT, Action::FIRE_CENTER, Action::FIRE_RIGHT, Action::START}; // Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
|
||||||
|
|
||||||
// --- Variables internas ---
|
// --- Variables internas ---
|
||||||
@@ -190,6 +196,7 @@ class Input {
|
|||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void initSDLGamePad();
|
void initSDLGamePad();
|
||||||
static auto checkAxisInput(Action action, std::shared_ptr<Gamepad> gamepad, bool repeat) -> bool;
|
static auto checkAxisInput(Action action, std::shared_ptr<Gamepad> gamepad, bool repeat) -> bool;
|
||||||
|
static auto checkTriggerInput(Action action, std::shared_ptr<Gamepad> gamepad, bool repeat) -> bool;
|
||||||
auto addGamepad(int device_index) -> std::string;
|
auto addGamepad(int device_index) -> std::string;
|
||||||
auto removeGamepad(SDL_JoystickID id) -> std::string;
|
auto removeGamepad(SDL_JoystickID id) -> std::string;
|
||||||
void addGamepadMappingsFromFile();
|
void addGamepadMappingsFromFile();
|
||||||
|
|||||||
@@ -73,7 +73,9 @@ const std::unordered_map<SDL_GamepadButton, std::string> BUTTON_TO_STRING = {
|
|||||||
{SDL_GAMEPAD_BUTTON_DPAD_UP, "DPAD_UP"},
|
{SDL_GAMEPAD_BUTTON_DPAD_UP, "DPAD_UP"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_DOWN, "DPAD_DOWN"},
|
{SDL_GAMEPAD_BUTTON_DPAD_DOWN, "DPAD_DOWN"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_LEFT, "DPAD_LEFT"},
|
{SDL_GAMEPAD_BUTTON_DPAD_LEFT, "DPAD_LEFT"},
|
||||||
{SDL_GAMEPAD_BUTTON_DPAD_RIGHT, "DPAD_RIGHT"}};
|
{SDL_GAMEPAD_BUTTON_DPAD_RIGHT, "DPAD_RIGHT"},
|
||||||
|
{static_cast<SDL_GamepadButton>(100), "L2_AS_BUTTON"},
|
||||||
|
{static_cast<SDL_GamepadButton>(101), "R2_AS_BUTTON"}};
|
||||||
|
|
||||||
const std::unordered_map<std::string, SDL_GamepadButton> STRING_TO_BUTTON = {
|
const std::unordered_map<std::string, SDL_GamepadButton> STRING_TO_BUTTON = {
|
||||||
{"WEST", SDL_GAMEPAD_BUTTON_WEST},
|
{"WEST", SDL_GAMEPAD_BUTTON_WEST},
|
||||||
@@ -87,7 +89,9 @@ const std::unordered_map<std::string, SDL_GamepadButton> STRING_TO_BUTTON = {
|
|||||||
{"DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP},
|
{"DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP},
|
||||||
{"DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN},
|
{"DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN},
|
||||||
{"DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT},
|
{"DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT},
|
||||||
{"DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT}};
|
{"DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT},
|
||||||
|
{"L2_AS_BUTTON", static_cast<SDL_GamepadButton>(100)},
|
||||||
|
{"R2_AS_BUTTON", static_cast<SDL_GamepadButton>(101)}};
|
||||||
|
|
||||||
const std::unordered_map<InputAction, InputAction> ACTION_TO_ACTION = {
|
const std::unordered_map<InputAction, InputAction> ACTION_TO_ACTION = {
|
||||||
{InputAction::SM_SELECT, InputAction::FIRE_LEFT},
|
{InputAction::SM_SELECT, InputAction::FIRE_LEFT},
|
||||||
|
|||||||
@@ -101,14 +101,11 @@ auto saveToFile() -> bool {
|
|||||||
|
|
||||||
// Opciones de ventana
|
// Opciones de ventana
|
||||||
file << "## WINDOW\n";
|
file << "## WINDOW\n";
|
||||||
file << "\n";
|
|
||||||
|
|
||||||
file << "window.zoom=" << window.zoom << "\n";
|
file << "window.zoom=" << window.zoom << "\n";
|
||||||
|
|
||||||
// Opciones de video
|
// Opciones de video
|
||||||
file << "## VIDEO\n";
|
file << "\n## VIDEO\n";
|
||||||
file << "## video.scale_mode [" << static_cast<int>(SDL_ScaleMode::SDL_SCALEMODE_NEAREST) << ": nearest, " << static_cast<int>(SDL_ScaleMode::SDL_SCALEMODE_LINEAR) << ": lineal]\n";
|
file << "## video.scale_mode [" << static_cast<int>(SDL_ScaleMode::SDL_SCALEMODE_NEAREST) << ": nearest, " << static_cast<int>(SDL_ScaleMode::SDL_SCALEMODE_LINEAR) << ": lineal]\n";
|
||||||
file << "\n";
|
|
||||||
|
|
||||||
file << "video.fullscreen=" << boolToString(video.fullscreen) << "\n";
|
file << "video.fullscreen=" << boolToString(video.fullscreen) << "\n";
|
||||||
file << "video.scale_mode=" << static_cast<int>(video.scale_mode) << "\n";
|
file << "video.scale_mode=" << static_cast<int>(video.scale_mode) << "\n";
|
||||||
@@ -117,9 +114,8 @@ auto saveToFile() -> bool {
|
|||||||
file << "video.shaders=" << boolToString(video.shaders) << "\n";
|
file << "video.shaders=" << boolToString(video.shaders) << "\n";
|
||||||
|
|
||||||
// Opciones de audio
|
// Opciones de audio
|
||||||
file << "\n\n## AUDIO\n";
|
file << "\n## AUDIO\n";
|
||||||
file << "## volume [0 .. 100]\n";
|
file << "## volume [0 .. 100]\n";
|
||||||
file << "\n";
|
|
||||||
|
|
||||||
file << "audio.enabled=" << boolToString(audio.enabled) << "\n";
|
file << "audio.enabled=" << boolToString(audio.enabled) << "\n";
|
||||||
file << "audio.volume=" << audio.volume << "\n";
|
file << "audio.volume=" << audio.volume << "\n";
|
||||||
@@ -129,10 +125,9 @@ auto saveToFile() -> bool {
|
|||||||
file << "audio.sound.volume=" << audio.sound.volume << "\n";
|
file << "audio.sound.volume=" << audio.sound.volume << "\n";
|
||||||
|
|
||||||
// Opciones del juego
|
// Opciones del juego
|
||||||
file << "\n\n## GAME\n";
|
file << "\n## GAME\n";
|
||||||
file << "## game.language [0: spanish, 1: valencian, 2: english]\n";
|
file << "## game.language [0: spanish, 1: valencian, 2: english]\n";
|
||||||
file << "## game.difficulty [" << static_cast<int>(Difficulty::Code::EASY) << ": easy, " << static_cast<int>(Difficulty::Code::NORMAL) << ": normal, " << static_cast<int>(Difficulty::Code::HARD) << ": hard]\n";
|
file << "## game.difficulty [" << static_cast<int>(Difficulty::Code::EASY) << ": easy, " << static_cast<int>(Difficulty::Code::NORMAL) << ": normal, " << static_cast<int>(Difficulty::Code::HARD) << ": hard]\n";
|
||||||
file << "\n";
|
|
||||||
|
|
||||||
file << "game.language=" << static_cast<int>(settings.language) << "\n";
|
file << "game.language=" << static_cast<int>(settings.language) << "\n";
|
||||||
file << "game.difficulty=" << static_cast<int>(settings.difficulty) << "\n";
|
file << "game.difficulty=" << static_cast<int>(settings.difficulty) << "\n";
|
||||||
@@ -140,11 +135,11 @@ auto saveToFile() -> bool {
|
|||||||
file << "game.shutdown_enabled=" << boolToString(settings.shutdown_enabled) << "\n";
|
file << "game.shutdown_enabled=" << boolToString(settings.shutdown_enabled) << "\n";
|
||||||
|
|
||||||
// Opciones de mandos
|
// Opciones de mandos
|
||||||
file << "\n\n## CONTROLLERS\n";
|
file << "\n## CONTROLLERS\n";
|
||||||
gamepad_manager.saveToFile(file);
|
gamepad_manager.saveToFile(file);
|
||||||
|
|
||||||
// Opciones de teclado
|
// Opciones de teclado
|
||||||
file << "\n\n## KEYBOARD\n";
|
file << "\n## KEYBOARD\n";
|
||||||
file << "keyboard.player=" << static_cast<int>(keyboard.player_id) << "\n";
|
file << "keyboard.player=" << static_cast<int>(keyboard.player_id) << "\n";
|
||||||
|
|
||||||
// Cierra el fichero
|
// Cierra el fichero
|
||||||
|
|||||||
385
source/param.cpp
@@ -2,101 +2,50 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_LogCategory, SDL_LogError, SDL_LogInfo
|
#include <SDL3/SDL.h> // Para SDL_LogCategory, SDL_LogError, SDL_LogInfo
|
||||||
|
|
||||||
#include <fstream> // Para basic_istream, basic_ifstream, ifstream
|
#include <fstream> // Para basic_istream, basic_ifstream, ifstream
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <sstream> // Para basic_istringstream
|
#include <sstream> // Para basic_istringstream
|
||||||
#include <stdexcept> // Para runtime_error
|
#include <stdexcept> // Para runtime_error
|
||||||
#include <string> // Para operator==, stoi, char_traits, string, ope...
|
#include <string> // Para operator==, stoi, char_traits, string, ope...
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "ui/notifier.h" // Para Notifier::Position
|
||||||
|
|
||||||
|
// Variable global - ahora se inicializa automáticamente con valores por defecto
|
||||||
Param param;
|
Param param;
|
||||||
|
|
||||||
// Calcula variables a partir de otras variables
|
// Declaraciones de funciones privadas
|
||||||
void precalculateZones();
|
namespace {
|
||||||
|
auto setParams(const std::string& var, const std::string& value) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
// Asigna variables a partir de dos cadenas
|
// Implementación del método privado de Param
|
||||||
auto setParams(const std::string& var, const std::string& value) -> bool;
|
void Param::precalculateZones() {
|
||||||
|
// playArea - cálculos basados en el rectángulo actual
|
||||||
|
game.play_area.center_x = game.play_area.rect.w / 2;
|
||||||
|
game.play_area.first_quarter_x = game.play_area.rect.w / 4;
|
||||||
|
game.play_area.third_quarter_x = game.play_area.rect.w / 4 * 3;
|
||||||
|
game.play_area.center_y = game.play_area.rect.h / 2;
|
||||||
|
game.play_area.first_quarter_y = game.play_area.rect.h / 4;
|
||||||
|
game.play_area.third_quarter_y = game.play_area.rect.h / 4 * 3;
|
||||||
|
|
||||||
// Establece valores por defecto a las variables
|
// gameArea - cálculos basados en width y height actuales
|
||||||
void initParam() {
|
game.game_area.rect = {0, 0, game.width, game.height};
|
||||||
// GAME
|
game.game_area.center_x = game.game_area.rect.w / 2;
|
||||||
param.game.width = 320;
|
game.game_area.first_quarter_x = game.game_area.rect.w / 4;
|
||||||
param.game.height = 256;
|
game.game_area.third_quarter_x = game.game_area.rect.w / 4 * 3;
|
||||||
param.game.item_size = 20;
|
game.game_area.center_y = game.game_area.rect.h / 2;
|
||||||
param.game.game_area.rect = {0, 0, param.game.width, param.game.height};
|
game.game_area.first_quarter_y = game.game_area.rect.h / 4;
|
||||||
param.game.play_area.rect = {0, 0, param.game.width, 216};
|
game.game_area.third_quarter_y = game.game_area.rect.h / 4 * 3;
|
||||||
param.game.name_entry_idle_time = 10;
|
|
||||||
param.game.name_entry_total_time = 60;
|
|
||||||
param.game.speed = 15;
|
|
||||||
param.game.hit_stop = true;
|
|
||||||
param.game.hit_stop_ms = 300;
|
|
||||||
precalculateZones();
|
|
||||||
|
|
||||||
// SCOREBOARD
|
|
||||||
param.scoreboard.rect = {0, 216, param.game.width, 40};
|
|
||||||
param.scoreboard.separator_autocolor = false;
|
|
||||||
param.scoreboard.separator_color = Color();
|
|
||||||
param.scoreboard.easy_color = Color();
|
|
||||||
param.scoreboard.normal_color = Color();
|
|
||||||
param.scoreboard.hard_color = Color();
|
|
||||||
param.scoreboard.text_autocolor = false;
|
|
||||||
param.scoreboard.text_color1 = Color();
|
|
||||||
param.scoreboard.text_color2 = Color();
|
|
||||||
param.scoreboard.skip_countdown_value = 8;
|
|
||||||
|
|
||||||
// FADE
|
|
||||||
param.fade.num_squares_width = param.game.width / 2;
|
|
||||||
param.fade.num_squares_height = param.game.height / 2;
|
|
||||||
param.fade.random_squares_delay = 1;
|
|
||||||
param.fade.random_squares_mult = 500;
|
|
||||||
param.fade.post_duration = 80;
|
|
||||||
param.fade.venetian_size = 16;
|
|
||||||
|
|
||||||
// TITLE
|
|
||||||
param.title.press_start_position = 160;
|
|
||||||
param.title.title_duration = 800;
|
|
||||||
param.title.arcade_edition_position = 123;
|
|
||||||
param.title.title_c_c_position = 11;
|
|
||||||
param.title.bg_color = Color(255, 255, 255);
|
|
||||||
|
|
||||||
// BACKGROUND
|
|
||||||
param.background.attenuate_color = Color(255, 255, 255, 0);
|
|
||||||
|
|
||||||
// BALLOONS
|
|
||||||
param.balloon.settings.at(0) = ParamBalloon::Settings(0.09F, 2.60F);
|
|
||||||
param.balloon.settings.at(1) = ParamBalloon::Settings(0.10F, 3.50F);
|
|
||||||
param.balloon.settings.at(2) = ParamBalloon::Settings(0.10F, 4.50F);
|
|
||||||
param.balloon.settings.at(3) = ParamBalloon::Settings(0.10F, 4.95F);
|
|
||||||
|
|
||||||
param.balloon.color.at(0) = "blue";
|
|
||||||
param.balloon.color.at(1) = "orange";
|
|
||||||
param.balloon.color.at(2) = "red";
|
|
||||||
param.balloon.color.at(3) = "green";
|
|
||||||
|
|
||||||
param.balloon.bouncing_sound = false;
|
|
||||||
|
|
||||||
// NOTIFICATION
|
|
||||||
param.notification.pos_v = NotifyPosition::TOP;
|
|
||||||
param.notification.pos_h = NotifyPosition::LEFT;
|
|
||||||
param.notification.sound = false;
|
|
||||||
param.notification.color = Color(48, 48, 48);
|
|
||||||
|
|
||||||
// INTRO
|
|
||||||
param.intro.bg_color = Color::fromHex("543149");
|
|
||||||
param.intro.card_color = Color::fromHex("CBDBFC");
|
|
||||||
param.intro.shadow_color = Color::fromHex("00000080");
|
|
||||||
param.intro.text_distance_from_bottom = 48;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carga los parámetros desde un archivo
|
// Carga los parámetros desde un archivo
|
||||||
void loadParamsFromFile(const std::string& file_path) {
|
void loadParamsFromFile(const std::string& file_path) {
|
||||||
// Inicializa los parámetros con valores por defecto
|
// Los parámetros ya están inicializados con valores por defecto
|
||||||
initParam();
|
// Solo necesitamos abrir el archivo y sobrescribir los valores que aparezcan
|
||||||
|
|
||||||
// Abre el archivo
|
|
||||||
std::ifstream file(file_path);
|
std::ifstream file(file_path);
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo abrir el archivo %s", file_path.c_str());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo abrir el archivo %s", file_path.c_str());
|
||||||
@@ -106,8 +55,9 @@ void loadParamsFromFile(const std::string& file_path) {
|
|||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\nReading file: %s", getFileName(file_path).c_str());
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\nReading file: %s", getFileName(file_path).c_str());
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
std::string param1;
|
std::string param_name;
|
||||||
std::string param2;
|
std::string param_value;
|
||||||
|
|
||||||
while (std::getline(file, line)) {
|
while (std::getline(file, line)) {
|
||||||
// Elimina comentarios
|
// Elimina comentarios
|
||||||
auto comment_pos = line.find('#');
|
auto comment_pos = line.find('#');
|
||||||
@@ -117,145 +67,168 @@ void loadParamsFromFile(const std::string& file_path) {
|
|||||||
|
|
||||||
// Usa un stream para separar palabras
|
// Usa un stream para separar palabras
|
||||||
std::istringstream iss(line);
|
std::istringstream iss(line);
|
||||||
if (iss >> param1 >> param2) {
|
if (iss >> param_name >> param_value) {
|
||||||
if (!setParams(param1, param2)) {
|
if (!setParams(param_name, param_value)) {
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Parámetro desconocido: %s", param1.c_str());
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Parámetro desconocido: %s", param_name.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cierra el archivo
|
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
// Realiza cálculos adicionales después de cargar los parámetros
|
// Recalcula las zonas después de cargar todos los parámetros
|
||||||
precalculateZones();
|
param.precalculateZones();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto setParams(const std::string& var, const std::string& value) -> bool {
|
// Implementación local de setParams
|
||||||
static const std::unordered_map<std::string, std::function<void(const std::string&)>> INT_PARAMS = {
|
namespace {
|
||||||
{"game.width", [](const std::string& v) { param.game.width = std::stoi(v); }},
|
auto setParams(const std::string& var, const std::string& value) -> bool {
|
||||||
{"game.height", [](const std::string& v) { param.game.height = std::stoi(v); }},
|
// Mapas estáticos para diferentes tipos de parámetros
|
||||||
{"game.item_size", [](const std::string& v) { param.game.item_size = std::stoi(v); }},
|
static const std::unordered_map<std::string, std::function<void(const std::string&)>> INT_PARAMS = {
|
||||||
{"game.play_area.rect.x", [](const std::string& v) { param.game.play_area.rect.x = std::stoi(v); }},
|
{"game.width", [](const std::string& v) { param.game.width = std::stoi(v); }},
|
||||||
{"game.play_area.rect.y", [](const std::string& v) { param.game.play_area.rect.y = std::stoi(v); }},
|
{"game.height", [](const std::string& v) { param.game.height = std::stoi(v); }},
|
||||||
{"game.play_area.rect.w", [](const std::string& v) { param.game.play_area.rect.w = std::stoi(v); }},
|
{"game.item_size", [](const std::string& v) { param.game.item_size = std::stoi(v); }},
|
||||||
{"game.play_area.rect.h", [](const std::string& v) { param.game.play_area.rect.h = std::stoi(v); }},
|
{"game.play_area.rect.x", [](const std::string& v) { param.game.play_area.rect.x = std::stoi(v); }},
|
||||||
{"game.name_entry_idle_time", [](const std::string& v) { param.game.name_entry_idle_time = std::stoi(v); }},
|
{"game.play_area.rect.y", [](const std::string& v) { param.game.play_area.rect.y = std::stoi(v); }},
|
||||||
{"game.name_entry_total_time", [](const std::string& v) { param.game.name_entry_total_time = std::stoi(v); }},
|
{"game.play_area.rect.w", [](const std::string& v) { param.game.play_area.rect.w = std::stoi(v); }},
|
||||||
{"game.hit_stop_ms", [](const std::string& v) { param.game.hit_stop_ms = std::stoi(v); }},
|
{"game.play_area.rect.h", [](const std::string& v) { param.game.play_area.rect.h = std::stoi(v); }},
|
||||||
{"fade.num_squares_width", [](const std::string& v) { param.fade.num_squares_width = std::stoi(v); }},
|
{"game.name_entry_idle_time", [](const std::string& v) { param.game.name_entry_idle_time = std::stoi(v); }},
|
||||||
{"fade.num_squares_height", [](const std::string& v) { param.fade.num_squares_height = std::stoi(v); }},
|
{"game.name_entry_total_time", [](const std::string& v) { param.game.name_entry_total_time = std::stoi(v); }},
|
||||||
{"fade.random_squares_delay", [](const std::string& v) { param.fade.random_squares_delay = std::stoi(v); }},
|
{"game.hit_stop_ms", [](const std::string& v) { param.game.hit_stop_ms = std::stoi(v); }},
|
||||||
{"fade.random_squares_mult", [](const std::string& v) { param.fade.random_squares_mult = std::stoi(v); }},
|
{"fade.num_squares_width", [](const std::string& v) { param.fade.num_squares_width = std::stoi(v); }},
|
||||||
{"fade.post_duration", [](const std::string& v) { param.fade.post_duration = std::stoi(v); }},
|
{"fade.num_squares_height", [](const std::string& v) { param.fade.num_squares_height = std::stoi(v); }},
|
||||||
{"fade.venetian_size", [](const std::string& v) { param.fade.venetian_size = std::stoi(v); }},
|
{"fade.random_squares_delay", [](const std::string& v) { param.fade.random_squares_delay = std::stoi(v); }},
|
||||||
{"scoreboard.rect.x", [](const std::string& v) { param.scoreboard.rect.x = std::stoi(v); }},
|
{"fade.random_squares_mult", [](const std::string& v) { param.fade.random_squares_mult = std::stoi(v); }},
|
||||||
{"scoreboard.rect.y", [](const std::string& v) { param.scoreboard.rect.y = std::stoi(v); }},
|
{"fade.post_duration", [](const std::string& v) { param.fade.post_duration = std::stoi(v); }},
|
||||||
{"scoreboard.rect.w", [](const std::string& v) { param.scoreboard.rect.w = std::stoi(v); }},
|
{"fade.venetian_size", [](const std::string& v) { param.fade.venetian_size = std::stoi(v); }},
|
||||||
{"scoreboard.rect.h", [](const std::string& v) { param.scoreboard.rect.h = std::stoi(v); }},
|
{"scoreboard.rect.x", [](const std::string& v) { param.scoreboard.rect.x = std::stoi(v); }},
|
||||||
{"scoreboard.skip_countdown_value", [](const std::string& v) { param.scoreboard.skip_countdown_value = std::stoi(v); }},
|
{"scoreboard.rect.y", [](const std::string& v) { param.scoreboard.rect.y = std::stoi(v); }},
|
||||||
{"title.press_start_position", [](const std::string& v) { param.title.press_start_position = std::stoi(v); }},
|
{"scoreboard.rect.w", [](const std::string& v) { param.scoreboard.rect.w = std::stoi(v); }},
|
||||||
{"title.title_duration", [](const std::string& v) { param.title.title_duration = std::stoi(v); }},
|
{"scoreboard.rect.h", [](const std::string& v) { param.scoreboard.rect.h = std::stoi(v); }},
|
||||||
{"title.arcade_edition_position", [](const std::string& v) { param.title.arcade_edition_position = std::stoi(v); }},
|
{"scoreboard.skip_countdown_value", [](const std::string& v) { param.scoreboard.skip_countdown_value = std::stoi(v); }},
|
||||||
{"title.title_c_c_position", [](const std::string& v) { param.title.title_c_c_position = std::stoi(v); }},
|
{"title.press_start_position", [](const std::string& v) { param.title.press_start_position = std::stoi(v); }},
|
||||||
{"intro.text_distance_from_bottom", [](const std::string& v) { param.intro.text_distance_from_bottom = std::stoi(v); }}};
|
{"title.title_duration", [](const std::string& v) { param.title.title_duration = std::stoi(v); }},
|
||||||
|
{"title.arcade_edition_position", [](const std::string& v) { param.title.arcade_edition_position = std::stoi(v); }},
|
||||||
|
{"title.title_c_c_position", [](const std::string& v) { param.title.title_c_c_position = std::stoi(v); }},
|
||||||
|
{"intro.text_distance_from_bottom", [](const std::string& v) { param.intro.text_distance_from_bottom = std::stoi(v); }}
|
||||||
|
};
|
||||||
|
|
||||||
static const std::unordered_map<std::string, std::function<void(const std::string&)>> COLOR_PARAMS = {
|
static const std::unordered_map<std::string, std::function<void(const std::string&)>> COLOR_PARAMS = {
|
||||||
{"fade.color", [](const std::string& v) { param.fade.color = Color::fromHex(v); }},
|
{"fade.color", [](const std::string& v) { param.fade.color = Color::fromHex(v); }},
|
||||||
{"scoreboard.separator_color", [](const std::string& v) { param.scoreboard.separator_color = Color::fromHex(v); }},
|
{"scoreboard.separator_color", [](const std::string& v) { param.scoreboard.separator_color = Color::fromHex(v); }},
|
||||||
{"scoreboard.easy_color", [](const std::string& v) { param.scoreboard.easy_color = Color::fromHex(v); }},
|
{"scoreboard.easy_color", [](const std::string& v) { param.scoreboard.easy_color = Color::fromHex(v); }},
|
||||||
{"scoreboard.normal_color", [](const std::string& v) { param.scoreboard.normal_color = Color::fromHex(v); }},
|
{"scoreboard.normal_color", [](const std::string& v) { param.scoreboard.normal_color = Color::fromHex(v); }},
|
||||||
{"scoreboard.hard_color", [](const std::string& v) { param.scoreboard.hard_color = Color::fromHex(v); }},
|
{"scoreboard.hard_color", [](const std::string& v) { param.scoreboard.hard_color = Color::fromHex(v); }},
|
||||||
{"scoreboard.text_color1", [](const std::string& v) { param.scoreboard.text_color1 = Color::fromHex(v); }},
|
{"scoreboard.text_color1", [](const std::string& v) { param.scoreboard.text_color1 = Color::fromHex(v); }},
|
||||||
{"scoreboard.text_color2", [](const std::string& v) { param.scoreboard.text_color2 = Color::fromHex(v); }},
|
{"scoreboard.text_color2", [](const std::string& v) { param.scoreboard.text_color2 = Color::fromHex(v); }},
|
||||||
{"title.bg_color", [](const std::string& v) { param.title.bg_color = Color::fromHex(v); }},
|
{"title.bg_color", [](const std::string& v) { param.title.bg_color = Color::fromHex(v); }},
|
||||||
{"background.attenuate_color", [](const std::string& v) { param.background.attenuate_color = Color::fromHex(v); }},
|
{"background.attenuate_color", [](const std::string& v) { param.background.attenuate_color = Color::fromHex(v); }},
|
||||||
{"notification.color", [](const std::string& v) { param.notification.color = Color::fromHex(v); }},
|
{"notification.color", [](const std::string& v) { param.notification.color = Color::fromHex(v); }},
|
||||||
{"service_menu.title_color", [](const std::string& v) { param.service_menu.title_color = Color::fromHex(v); }},
|
{"service_menu.title_color", [](const std::string& v) { param.service_menu.title_color = Color::fromHex(v); }},
|
||||||
{"service_menu.text_color", [](const std::string& v) { param.service_menu.text_color = Color::fromHex(v); }},
|
{"service_menu.text_color", [](const std::string& v) { param.service_menu.text_color = Color::fromHex(v); }},
|
||||||
{"service_menu.selected_color", [](const std::string& v) { param.service_menu.selected_color = Color::fromHex(v); }},
|
{"service_menu.selected_color", [](const std::string& v) { param.service_menu.selected_color = Color::fromHex(v); }},
|
||||||
{"service_menu.bg_color", [](const std::string& v) { param.service_menu.bg_color = Color::fromHex(v); }},
|
{"service_menu.bg_color", [](const std::string& v) { param.service_menu.bg_color = Color::fromHex(v); }},
|
||||||
{"intro.bg_color", [](const std::string& v) { param.intro.bg_color = Color::fromHex(v); }},
|
{"service_menu.window_message.bg_color", [](const std::string& v) { param.service_menu.window_message.bg_color = Color::fromHex(v); }},
|
||||||
{"intro.card_color", [](const std::string& v) { param.intro.card_color = Color::fromHex(v); }},
|
{"service_menu.window_message.border_color", [](const std::string& v) { param.service_menu.window_message.border_color = Color::fromHex(v); }},
|
||||||
{"intro.shadow_color", [](const std::string& v) { param.intro.shadow_color = Color::fromHex(v); }},
|
{"service_menu.window_message.title_color", [](const std::string& v) { param.service_menu.window_message.title_color = Color::fromHex(v); }},
|
||||||
{"debug.color", [](const std::string& v) { param.debug.color = Color::fromHex(v); }},
|
{"service_menu.window_message.text_color", [](const std::string& v) { param.service_menu.window_message.text_color = Color::fromHex(v); }},
|
||||||
{"resource.color", [](const std::string& v) { param.resource.color = Color::fromHex(v); }}};
|
{"intro.bg_color", [](const std::string& v) { param.intro.bg_color = Color::fromHex(v); }},
|
||||||
|
{"intro.card_color", [](const std::string& v) { param.intro.card_color = Color::fromHex(v); }},
|
||||||
|
{"intro.shadow_color", [](const std::string& v) { param.intro.shadow_color = Color::fromHex(v); }},
|
||||||
|
{"debug.color", [](const std::string& v) { param.debug.color = Color::fromHex(v); }},
|
||||||
|
{"resource.color", [](const std::string& v) { param.resource.color = Color::fromHex(v); }},
|
||||||
|
{"player.one_coffee_shirt[0].darkest", [](const std::string& v) { param.player.one_coffee_shirt[0].darkest = Color::fromHex(v); }},
|
||||||
|
{"player.one_coffee_shirt[0].dark", [](const std::string& v) { param.player.one_coffee_shirt[0].dark = Color::fromHex(v); }},
|
||||||
|
{"player.one_coffee_shirt[0].base", [](const std::string& v) { param.player.one_coffee_shirt[0].base = Color::fromHex(v); }},
|
||||||
|
{"player.one_coffee_shirt[0].light", [](const std::string& v) { param.player.one_coffee_shirt[0].light = Color::fromHex(v); }},
|
||||||
|
{"player.one_coffee_shirt[1].darkest", [](const std::string& v) { param.player.one_coffee_shirt[1].darkest = Color::fromHex(v); }},
|
||||||
|
{"player.one_coffee_shirt[1].dark", [](const std::string& v) { param.player.one_coffee_shirt[1].dark = Color::fromHex(v); }},
|
||||||
|
{"player.one_coffee_shirt[1].base", [](const std::string& v) { param.player.one_coffee_shirt[1].base = Color::fromHex(v); }},
|
||||||
|
{"player.one_coffee_shirt[1].light", [](const std::string& v) { param.player.one_coffee_shirt[1].light = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[0].darkest", [](const std::string& v) { param.player.two_coffee_shirt[0].darkest = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[0].dark", [](const std::string& v) { param.player.two_coffee_shirt[0].dark = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[0].base", [](const std::string& v) { param.player.two_coffee_shirt[0].base = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[0].light", [](const std::string& v) { param.player.two_coffee_shirt[0].light = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[1].darkest", [](const std::string& v) { param.player.two_coffee_shirt[1].darkest = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[1].dark", [](const std::string& v) { param.player.two_coffee_shirt[1].dark = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[1].base", [](const std::string& v) { param.player.two_coffee_shirt[1].base = Color::fromHex(v); }},
|
||||||
|
{"player.two_coffee_shirt[1].light", [](const std::string& v) { param.player.two_coffee_shirt[1].light = Color::fromHex(v); }}
|
||||||
|
};
|
||||||
|
|
||||||
static const std::unordered_map<std::string, std::function<void(const std::string&)>> BOOL_PARAMS = {
|
static const std::unordered_map<std::string, std::function<void(const std::string&)>> BOOL_PARAMS = {
|
||||||
{"game.hit_stop", [](const std::string& v) { param.game.hit_stop = stringToBool(v); }},
|
{"game.hit_stop", [](const std::string& v) { param.game.hit_stop = stringToBool(v); }},
|
||||||
{"scoreboard.separator_autocolor", [](const std::string& v) { param.scoreboard.separator_autocolor = stringToBool(v); }},
|
{"scoreboard.separator_autocolor", [](const std::string& v) { param.scoreboard.separator_autocolor = stringToBool(v); }},
|
||||||
{"scoreboard.text_autocolor", [](const std::string& v) { param.scoreboard.text_autocolor = stringToBool(v); }},
|
{"scoreboard.text_autocolor", [](const std::string& v) { param.scoreboard.text_autocolor = stringToBool(v); }},
|
||||||
{"balloon.bouncing_sound", [](const std::string& v) { param.balloon.bouncing_sound = stringToBool(v); }},
|
{"balloon.bouncing_sound", [](const std::string& v) { param.balloon.bouncing_sound = stringToBool(v); }},
|
||||||
{"notification.sound", [](const std::string& v) { param.notification.sound = stringToBool(v); }},
|
{"notification.sound", [](const std::string& v) { param.notification.sound = stringToBool(v); }},
|
||||||
{"service_menu.drop_shadow", [](const std::string& v) { param.service_menu.drop_shadow = stringToBool(v); }}};
|
{"service_menu.drop_shadow", [](const std::string& v) { param.service_menu.drop_shadow = stringToBool(v); }}
|
||||||
|
};
|
||||||
|
|
||||||
static const std::unordered_map<std::string, std::function<void(const std::string&)>> FLOAT_PARAMS = {
|
static const std::unordered_map<std::string, std::function<void(const std::string&)>> FLOAT_PARAMS = {
|
||||||
{"balloon.settings[0].vel", [](const std::string& v) { param.balloon.settings.at(0).vel = std::stof(v); }},
|
{"balloon.settings[0].vel", [](const std::string& v) { param.balloon.settings.at(0).vel = std::stof(v); }},
|
||||||
{"balloon.settings[0].grav", [](const std::string& v) { param.balloon.settings.at(0).grav = std::stof(v); }},
|
{"balloon.settings[0].grav", [](const std::string& v) { param.balloon.settings.at(0).grav = std::stof(v); }},
|
||||||
{"balloon.settings[1].vel", [](const std::string& v) { param.balloon.settings.at(1).vel = std::stof(v); }},
|
{"balloon.settings[1].vel", [](const std::string& v) { param.balloon.settings.at(1).vel = std::stof(v); }},
|
||||||
{"balloon.settings[1].grav", [](const std::string& v) { param.balloon.settings.at(1).grav = std::stof(v); }},
|
{"balloon.settings[1].grav", [](const std::string& v) { param.balloon.settings.at(1).grav = std::stof(v); }},
|
||||||
{"balloon.settings[2].vel", [](const std::string& v) { param.balloon.settings.at(2).vel = std::stof(v); }},
|
{"balloon.settings[2].vel", [](const std::string& v) { param.balloon.settings.at(2).vel = std::stof(v); }},
|
||||||
{"balloon.settings[2].grav", [](const std::string& v) { param.balloon.settings.at(2).grav = std::stof(v); }},
|
{"balloon.settings[2].grav", [](const std::string& v) { param.balloon.settings.at(2).grav = std::stof(v); }},
|
||||||
{"balloon.settings[3].vel", [](const std::string& v) { param.balloon.settings.at(3).vel = std::stof(v); }},
|
{"balloon.settings[3].vel", [](const std::string& v) { param.balloon.settings.at(3).vel = std::stof(v); }},
|
||||||
{"balloon.settings[3].grav", [](const std::string& v) { param.balloon.settings.at(3).grav = std::stof(v); }}};
|
{"balloon.settings[3].grav", [](const std::string& v) { param.balloon.settings.at(3).grav = std::stof(v); }},
|
||||||
|
{"tabe.min_spawn_time", [](const std::string& v) { param.tabe.min_spawn_time = std::stof(v); }},
|
||||||
|
{"tabe.max_spawn_time", [](const std::string& v) { param.tabe.max_spawn_time = std::stof(v); }},
|
||||||
|
{"service_menu.window_message.padding", [](const std::string& v) { param.service_menu.window_message.padding = std::stof(v); }},
|
||||||
|
{"service_menu.window_message.line_spacing", [](const std::string& v) { param.service_menu.window_message.line_spacing = std::stof(v); }},
|
||||||
|
{"service_menu.window_message.title_separator_spacing", [](const std::string& v) { param.service_menu.window_message.title_separator_spacing = std::stof(v); }},
|
||||||
|
{"service_menu.window_message.min_width", [](const std::string& v) { param.service_menu.window_message.min_width = std::stof(v); }},
|
||||||
|
{"service_menu.window_message.min_height", [](const std::string& v) { param.service_menu.window_message.min_height = std::stof(v); }},
|
||||||
|
{"service_menu.window_message.max_width_ratio", [](const std::string& v) { param.service_menu.window_message.max_width_ratio = std::stof(v); }},
|
||||||
|
{"service_menu.window_message.max_height_ratio", [](const std::string& v) { param.service_menu.window_message.max_height_ratio = std::stof(v); }},
|
||||||
|
{"service_menu.window_message.text_safety_margin", [](const std::string& v) { param.service_menu.window_message.text_safety_margin = std::stof(v); }},
|
||||||
|
{"service_menu.window_message.animation_duration", [](const std::string& v) { param.service_menu.window_message.animation_duration = std::stof(v); }}
|
||||||
|
};
|
||||||
|
|
||||||
static const std::unordered_map<std::string, std::function<void(const std::string&)>> STRING_PARAMS = {
|
static const std::unordered_map<std::string, std::function<void(const std::string&)>> INT_PARAMS_EXTRA = {
|
||||||
{"balloon.color[0]", [](const std::string& v) { param.balloon.color.at(0) = v; }},
|
};
|
||||||
{"balloon.color[1]", [](const std::string& v) { param.balloon.color.at(1) = v; }},
|
|
||||||
{"balloon.color[2]", [](const std::string& v) { param.balloon.color.at(2) = v; }},
|
|
||||||
{"balloon.color[3]", [](const std::string& v) { param.balloon.color.at(3) = v; }}};
|
|
||||||
|
|
||||||
// Intentar cada mapa de parámetros
|
static const std::unordered_map<std::string, std::function<void(const std::string&)>> STRING_PARAMS = {
|
||||||
auto try_map = [&](const auto& param_map) -> bool {
|
{"balloon.color[0]", [](const std::string& v) { param.balloon.color.at(0) = v; }},
|
||||||
auto it = param_map.find(var);
|
{"balloon.color[1]", [](const std::string& v) { param.balloon.color.at(1) = v; }},
|
||||||
if (it != param_map.end()) {
|
{"balloon.color[2]", [](const std::string& v) { param.balloon.color.at(2) = v; }},
|
||||||
it->second(value);
|
{"balloon.color[3]", [](const std::string& v) { param.balloon.color.at(3) = v; }}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Lambda para intentar cada mapa de parámetros
|
||||||
|
auto try_map = [&](const auto& param_map) -> bool {
|
||||||
|
auto it = param_map.find(var);
|
||||||
|
if (it != param_map.end()) {
|
||||||
|
it->second(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Intentar con todos los mapas
|
||||||
|
if (try_map(INT_PARAMS) || try_map(COLOR_PARAMS) || try_map(BOOL_PARAMS) ||
|
||||||
|
try_map(FLOAT_PARAMS) || try_map(STRING_PARAMS)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (try_map(INT_PARAMS) || try_map(COLOR_PARAMS) || try_map(BOOL_PARAMS) ||
|
// Casos especiales que necesitan lógica personalizada
|
||||||
try_map(FLOAT_PARAMS) || try_map(STRING_PARAMS)) {
|
if (var == "notification.pos_h") {
|
||||||
return true;
|
if (value == "LEFT") {
|
||||||
}
|
param.notification.pos_h = Notifier::Position::LEFT;
|
||||||
|
} else if (value == "MIDDLE") {
|
||||||
// Casos especiales que necesitan lógica personalizada
|
param.notification.pos_h = Notifier::Position::MIDDLE;
|
||||||
if (var == "notification.pos_h") {
|
} else {
|
||||||
if (value == "LEFT") {
|
param.notification.pos_h = Notifier::Position::RIGHT;
|
||||||
param.notification.pos_h = NotifyPosition::LEFT;
|
}
|
||||||
} else if (value == "MIDDLE") {
|
return true;
|
||||||
param.notification.pos_h = NotifyPosition::MIDDLE;
|
|
||||||
} else {
|
|
||||||
param.notification.pos_h = NotifyPosition::RIGHT;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
if (var == "notification.pos_v") {
|
||||||
|
param.notification.pos_v = value == "TOP" ? Notifier::Position::TOP : Notifier::Position::BOTTOM;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // Parámetro no encontrado
|
||||||
}
|
}
|
||||||
|
|
||||||
if (var == "notification.pos_v") {
|
|
||||||
param.notification.pos_v = value == "TOP" ? NotifyPosition::TOP : NotifyPosition::BOTTOM;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // Parámetro no encontrado
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calcula variables a partir de otras variables
|
|
||||||
void precalculateZones() {
|
|
||||||
// playArea
|
|
||||||
param.game.play_area.center_x = param.game.play_area.rect.w / 2;
|
|
||||||
param.game.play_area.first_quarter_x = param.game.play_area.rect.w / 4;
|
|
||||||
param.game.play_area.third_quarter_x = param.game.play_area.rect.w / 4 * 3;
|
|
||||||
param.game.play_area.center_y = param.game.play_area.rect.h / 2;
|
|
||||||
param.game.play_area.first_quarter_y = param.game.play_area.rect.h / 4;
|
|
||||||
param.game.play_area.third_quarter_y = param.game.play_area.rect.h / 4 * 3;
|
|
||||||
|
|
||||||
// gameArea
|
|
||||||
param.game.game_area.rect = {0, 0, param.game.width, param.game.height};
|
|
||||||
param.game.game_area.center_x = param.game.game_area.rect.w / 2;
|
|
||||||
param.game.game_area.first_quarter_x = param.game.game_area.rect.w / 4;
|
|
||||||
param.game.game_area.third_quarter_x = param.game.game_area.rect.w / 4 * 3;
|
|
||||||
param.game.game_area.center_y = param.game.game_area.rect.h / 2;
|
|
||||||
param.game.game_area.first_quarter_y = param.game.game_area.rect.h / 4;
|
|
||||||
param.game.game_area.third_quarter_y = param.game.game_area.rect.h / 4 * 3;
|
|
||||||
}
|
}
|
||||||
231
source/param.h
@@ -5,134 +5,223 @@
|
|||||||
#include <array> // Para array
|
#include <array> // Para array
|
||||||
#include <string> // Para basic_string, string
|
#include <string> // Para basic_string, string
|
||||||
|
|
||||||
#include "color.h" // Para Color, NotifyPosition (ptr only), Zone
|
#include "color.h" // Para Color, Zone
|
||||||
|
#include "defaults.h" // Para los valores por defecto
|
||||||
|
#include "ui/notifier.h" // Para Notifier::Position
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
// --- Parámetros del juego ---
|
// --- Parámetros del juego ---
|
||||||
struct ParamGame {
|
struct ParamGame {
|
||||||
float width; // Ancho de la resolución nativa del juego
|
float width = GameDefaults::Game::WIDTH;
|
||||||
float height; // Alto de la resolución nativa del juego
|
float height = GameDefaults::Game::HEIGHT;
|
||||||
float item_size; // Tamaño de los ítems del juego
|
float item_size = GameDefaults::Game::ITEM_SIZE;
|
||||||
Zone play_area; // Rectángulo con la posición de la zona de juego
|
Zone play_area{}; // Se inicializa en el constructor de Param
|
||||||
Zone game_area; // Rectángulo con las dimensiones del juego
|
Zone game_area{}; // Se inicializa en el constructor de Param
|
||||||
int name_entry_idle_time; // Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
|
int name_entry_idle_time = GameDefaults::Game::NAME_ENTRY_IDLE_TIME;
|
||||||
int name_entry_total_time; // Segundos totales para introducir el nombre al finalizar la partida
|
int name_entry_total_time = GameDefaults::Game::NAME_ENTRY_TOTAL_TIME;
|
||||||
Uint32 speed; // Velocidad a la que transcurre el juego
|
Uint32 speed = 15; // Este valor no estaba en el archivo de configuración
|
||||||
bool hit_stop; // Indica si debe haber un paro cuando el jugador es golpeado por un globo
|
bool hit_stop = GameDefaults::Game::HIT_STOP;
|
||||||
Uint32 hit_stop_ms; // Cantidad de milisegundos que dura el hit_stop
|
Uint32 hit_stop_ms = GameDefaults::Game::HIT_STOP_MS;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros del fade ---
|
// --- Parámetros del fade ---
|
||||||
struct ParamFade {
|
struct ParamFade {
|
||||||
Color color; // Color del fade
|
Color color = Color::fromHex(GameDefaults::Fade::COLOR);
|
||||||
float num_squares_width; // Cantidad total de cuadraditos en horizontal para el FadeType::RANDOM_SQUARE
|
float num_squares_width = GameDefaults::Fade::NUM_SQUARES_WIDTH;
|
||||||
float num_squares_height; // Cantidad total de cuadraditos en vertical para el FadeType::RANDOM_SQUARE
|
float num_squares_height = GameDefaults::Fade::NUM_SQUARES_HEIGHT;
|
||||||
int random_squares_delay; // Duración entre cada pintado de cuadrados
|
int random_squares_delay = GameDefaults::Fade::RANDOM_SQUARES_DELAY;
|
||||||
int random_squares_mult; // Cantidad de cuadrados que se pintarán cada vez
|
int random_squares_mult = GameDefaults::Fade::RANDOM_SQUARES_MULT;
|
||||||
int post_duration; // Duración final del fade
|
int post_duration = GameDefaults::Fade::POST_DURATION;
|
||||||
float venetian_size; // Altura de los rectángulos para FadeType::VENETIAN
|
float venetian_size = GameDefaults::Fade::VENETIAN_SIZE;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros de la pantalla de título ---
|
// --- Parámetros de la pantalla de título ---
|
||||||
struct ParamTitle {
|
struct ParamTitle {
|
||||||
int press_start_position; // Posición del texto para empezar a jugar
|
int press_start_position = GameDefaults::Title::PRESS_START_POSITION;
|
||||||
int title_duration; // Tiempo de inactividad del título
|
int title_duration = GameDefaults::Title::DURATION;
|
||||||
int arcade_edition_position; // Posición del bitmap "Arcade Edition"
|
int arcade_edition_position = GameDefaults::Title::ARCADE_EDITION_POSITION;
|
||||||
int title_c_c_position; // Posición del bitmap "Coffee Crisis"
|
int title_c_c_position = GameDefaults::Title::TITLE_C_C_POSITION;
|
||||||
Color bg_color; // Color para los tiles de fondo
|
Color bg_color = Color::fromHex(GameDefaults::Title::BG_COLOR);
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros del fondo ---
|
// --- Parámetros del fondo ---
|
||||||
struct ParamBackground {
|
struct ParamBackground {
|
||||||
Color attenuate_color; // Color para atenuar el fondo
|
Color attenuate_color = Color::fromHex(GameDefaults::Background::ATTENUATE_COLOR);
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros de los globos ---
|
// --- Parámetros de los globos ---
|
||||||
struct ParamBalloon {
|
struct ParamBalloon {
|
||||||
struct Settings {
|
struct Settings {
|
||||||
float grav; // Aceleración en el eje Y. Modifica la velocidad
|
float grav;
|
||||||
float vel; // Velocidad inicial al rebotar contra el suelo
|
float vel;
|
||||||
|
|
||||||
// Constructor
|
// Constructor por defecto
|
||||||
explicit Settings(float grav_val = 0.0F, float vel_val = 0.0F)
|
constexpr Settings(float grav_val = 0.0f, float vel_val = 0.0f)
|
||||||
: grav(grav_val), vel(vel_val) {}
|
: grav(grav_val), vel(vel_val) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::array<Settings, 4> settings;
|
// Inicialización con los valores por defecto desde GameDefaults
|
||||||
std::array<std::string, 4> color;
|
std::array<Settings, 4> settings = {{Settings(GameDefaults::Balloon::SETTINGS[0].grav, GameDefaults::Balloon::SETTINGS[0].vel),
|
||||||
bool bouncing_sound; // Indica si los globos hacer sonido al rebotar
|
Settings(GameDefaults::Balloon::SETTINGS[1].grav, GameDefaults::Balloon::SETTINGS[1].vel),
|
||||||
|
Settings(GameDefaults::Balloon::SETTINGS[2].grav, GameDefaults::Balloon::SETTINGS[2].vel),
|
||||||
|
Settings(GameDefaults::Balloon::SETTINGS[3].grav, GameDefaults::Balloon::SETTINGS[3].vel)}};
|
||||||
|
|
||||||
|
std::array<std::string, 4> color = {{GameDefaults::Balloon::COLORS[0],
|
||||||
|
GameDefaults::Balloon::COLORS[1],
|
||||||
|
GameDefaults::Balloon::COLORS[2],
|
||||||
|
GameDefaults::Balloon::COLORS[3]}};
|
||||||
|
|
||||||
|
bool bouncing_sound = GameDefaults::Balloon::BOUNCING_SOUND;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros de las notificaciones ---
|
// --- Parámetros de las notificaciones ---
|
||||||
struct ParamNotification {
|
struct ParamNotification {
|
||||||
NotifyPosition pos_h; // Ubicación horizontal de las notificaciones en pantalla
|
Notifier::Position pos_h = GameDefaults::Notification::POS_H;
|
||||||
NotifyPosition pos_v; // Ubicación vertical de las notificaciones en pantalla
|
Notifier::Position pos_v = GameDefaults::Notification::POS_V;
|
||||||
bool sound; // Indica si las notificaciones suenan
|
bool sound = GameDefaults::Notification::SOUND;
|
||||||
Color color; // Color de las notificaciones
|
Color color = Color::fromHex(GameDefaults::Notification::COLOR);
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros del marcador ---
|
// --- Parámetros del marcador ---
|
||||||
struct ParamScoreboard {
|
struct ParamScoreboard {
|
||||||
SDL_FRect rect; // Posición y tamaño del marcador
|
SDL_FRect rect = {
|
||||||
bool separator_autocolor; // El separado establece su color de forma automatica
|
GameDefaults::Scoreboard::RECT_X,
|
||||||
Color separator_color; // Color del separador si se pone de forma manual
|
GameDefaults::Scoreboard::RECT_Y,
|
||||||
Color easy_color; // Color del marcador segun la dificultad
|
GameDefaults::Scoreboard::RECT_W,
|
||||||
Color normal_color; // Color del marcador segun la dificultad
|
GameDefaults::Scoreboard::RECT_H};
|
||||||
Color hard_color; // Color del marcador segun la dificultad
|
bool separator_autocolor = GameDefaults::Scoreboard::SEPARATOR_AUTOCOLOR;
|
||||||
bool text_autocolor; // El texto establece su color de forma automatica
|
Color separator_color = Color::fromHex(GameDefaults::Scoreboard::SEPARATOR_COLOR);
|
||||||
Color text_color1; // Color del texto
|
Color easy_color = Color::fromHex(GameDefaults::Scoreboard::EASY_COLOR);
|
||||||
Color text_color2; // Color del texto
|
Color normal_color = Color::fromHex(GameDefaults::Scoreboard::NORMAL_COLOR);
|
||||||
int skip_countdown_value; // Valor a partir del cual se puede saltar la cuenta atras
|
Color hard_color = Color::fromHex(GameDefaults::Scoreboard::HARD_COLOR);
|
||||||
|
bool text_autocolor = GameDefaults::Scoreboard::TEXT_AUTOCOLOR;
|
||||||
|
Color text_color1 = Color::fromHex(GameDefaults::Scoreboard::TEXT_COLOR1);
|
||||||
|
Color text_color2 = Color::fromHex(GameDefaults::Scoreboard::TEXT_COLOR2);
|
||||||
|
int skip_countdown_value = GameDefaults::Scoreboard::SKIP_COUNTDOWN_VALUE;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros del menú de servicio ---
|
// --- Parámetros del menú de servicio ---
|
||||||
struct ParamServiceMenu {
|
struct ParamServiceMenu {
|
||||||
Color title_color;
|
Color title_color = Color::fromHex(GameDefaults::ServiceMenu::TITLE_COLOR);
|
||||||
Color text_color;
|
Color text_color = Color::fromHex(GameDefaults::ServiceMenu::TEXT_COLOR);
|
||||||
Color selected_color;
|
Color selected_color = Color::fromHex(GameDefaults::ServiceMenu::SELECTED_COLOR);
|
||||||
Color bg_color;
|
Color bg_color = Color::fromHex(GameDefaults::ServiceMenu::BG_COLOR);
|
||||||
bool drop_shadow;
|
bool drop_shadow = GameDefaults::ServiceMenu::DROP_SHADOW;
|
||||||
|
|
||||||
|
// Configuración para ventanas de mensaje
|
||||||
|
struct WindowMessage {
|
||||||
|
Color bg_color = Color::fromHex(GameDefaults::ServiceMenu::WindowMessage::BG_COLOR);
|
||||||
|
Color border_color = Color::fromHex(GameDefaults::ServiceMenu::WindowMessage::BORDER_COLOR);
|
||||||
|
Color title_color = Color::fromHex(GameDefaults::ServiceMenu::WindowMessage::TITLE_COLOR);
|
||||||
|
Color text_color = Color::fromHex(GameDefaults::ServiceMenu::WindowMessage::TEXT_COLOR);
|
||||||
|
float padding = GameDefaults::ServiceMenu::WindowMessage::PADDING;
|
||||||
|
float line_spacing = GameDefaults::ServiceMenu::WindowMessage::LINE_SPACING;
|
||||||
|
float title_separator_spacing = GameDefaults::ServiceMenu::WindowMessage::TITLE_SEPARATOR_SPACING;
|
||||||
|
float min_width = GameDefaults::ServiceMenu::WindowMessage::MIN_WIDTH;
|
||||||
|
float min_height = GameDefaults::ServiceMenu::WindowMessage::MIN_HEIGHT;
|
||||||
|
float max_width_ratio = GameDefaults::ServiceMenu::WindowMessage::MAX_WIDTH_RATIO;
|
||||||
|
float max_height_ratio = GameDefaults::ServiceMenu::WindowMessage::MAX_HEIGHT_RATIO;
|
||||||
|
float text_safety_margin = GameDefaults::ServiceMenu::WindowMessage::TEXT_SAFETY_MARGIN;
|
||||||
|
float animation_duration = GameDefaults::ServiceMenu::WindowMessage::ANIMATION_DURATION;
|
||||||
|
} window_message;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros de la intro ---
|
// --- Parámetros de la intro ---
|
||||||
struct ParamIntro {
|
struct ParamIntro {
|
||||||
Color bg_color;
|
Color bg_color = Color::fromHex(GameDefaults::Intro::BG_COLOR);
|
||||||
Color card_color;
|
Color card_color = Color::fromHex(GameDefaults::Intro::CARD_COLOR);
|
||||||
Color shadow_color;
|
Color shadow_color = Color::fromHex(GameDefaults::Intro::SHADOW_COLOR);
|
||||||
int text_distance_from_bottom;
|
int text_distance_from_bottom = GameDefaults::Intro::TEXT_DISTANCE_FROM_BOTTOM;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros para Debug ---
|
// --- Parámetros para Debug ---
|
||||||
struct ParamDebug {
|
struct ParamDebug {
|
||||||
Color color;
|
Color color = Color::fromHex(GameDefaults::Debug::COLOR);
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros para Resource ---
|
// --- Parámetros para Resource ---
|
||||||
struct ParamResource {
|
struct ParamResource {
|
||||||
Color color;
|
Color color = Color::fromHex(GameDefaults::Resource::COLOR);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Parámetros para Tabe ---
|
||||||
|
struct ParamTabe {
|
||||||
|
float min_spawn_time = GameDefaults::Tabe::MIN_SPAWN_TIME;
|
||||||
|
float max_spawn_time = GameDefaults::Tabe::MAX_SPAWN_TIME;
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Parámetros del Jugador ---
|
||||||
|
struct ParamPlayer {
|
||||||
|
// Configuración de camisetas del jugador
|
||||||
|
struct Shirt {
|
||||||
|
Color darkest; // Tono más oscuro - bordes y contornos
|
||||||
|
Color dark; // Tono oscuro - sombras
|
||||||
|
Color base; // Tono principal - color base de la camiseta
|
||||||
|
Color light; // Tono claro - zonas iluminadas/highlights
|
||||||
|
|
||||||
|
// Constructor por defecto
|
||||||
|
Shirt() = default;
|
||||||
|
|
||||||
|
// Constructor con tonalidades específicas
|
||||||
|
Shirt(const Color& darkest_tone, const Color& dark_tone, const Color& base_tone, const Color& light_tone)
|
||||||
|
: darkest(darkest_tone), dark(dark_tone), base(base_tone), light(light_tone) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Inicialización con valores por defecto
|
||||||
|
std::array<Shirt, 2> one_coffee_shirt = {{Shirt(Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_DARKEST),
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_DARK),
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_BASE),
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER0_LIGHT)),
|
||||||
|
Shirt(Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_DARKEST),
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_DARK),
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_BASE),
|
||||||
|
Color::fromHex(GameDefaults::Player::OneCoffeeShirt::PLAYER1_LIGHT))}};
|
||||||
|
|
||||||
|
std::array<Shirt, 2> two_coffee_shirt = {{Shirt(Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_DARKEST),
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_DARK),
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_BASE),
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER0_LIGHT)),
|
||||||
|
Shirt(Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_DARKEST),
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_DARK),
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_BASE),
|
||||||
|
Color::fromHex(GameDefaults::Player::TwoCoffeeShirt::PLAYER1_LIGHT))}};
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estructura principal para almacenar todos los parámetros del juego ---
|
// --- Estructura principal para almacenar todos los parámetros del juego ---
|
||||||
struct Param {
|
struct Param {
|
||||||
ParamGame game; // Parámetros del juego
|
ParamGame game;
|
||||||
ParamFade fade; // Parámetros del fade
|
ParamFade fade;
|
||||||
ParamScoreboard scoreboard; // Rectángulo del marcador
|
ParamScoreboard scoreboard;
|
||||||
ParamTitle title; // Parámetros de la pantalla de título
|
ParamTitle title;
|
||||||
ParamBackground background; // Parámetros del fondo
|
ParamBackground background;
|
||||||
ParamBalloon balloon; // Parámetros de los globos
|
ParamBalloon balloon;
|
||||||
ParamNotification notification; // Parámetros de las notificaciones
|
ParamNotification notification;
|
||||||
ParamServiceMenu service_menu; // Parámetros del menú de servicio
|
ParamServiceMenu service_menu;
|
||||||
ParamIntro intro; // Parámetros de la intro
|
ParamIntro intro;
|
||||||
ParamDebug debug; // Parámetros para Debug
|
ParamDebug debug;
|
||||||
ParamResource resource; // Parámetros para Resource
|
ParamResource resource;
|
||||||
|
ParamTabe tabe;
|
||||||
|
ParamPlayer player;
|
||||||
|
|
||||||
// Constructor
|
// Constructor que inicializa las zonas que dependen de otros valores
|
||||||
Param()
|
Param() {
|
||||||
: game(), fade(), scoreboard(), title(), background(), balloon(), notification(), service_menu(), intro(), debug(), resource() {}
|
// Inicializar play_area usando los valores por defecto
|
||||||
|
game.play_area.rect = {
|
||||||
|
GameDefaults::Game::PLAY_AREA_X,
|
||||||
|
GameDefaults::Game::PLAY_AREA_Y,
|
||||||
|
GameDefaults::Game::PLAY_AREA_W,
|
||||||
|
GameDefaults::Game::PLAY_AREA_H};
|
||||||
|
|
||||||
|
// Las zonas calculadas se inicializarán en precalculateZones()
|
||||||
|
precalculateZones();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función pública para recalcular zonas (necesaria después de cambiar parámetros)
|
||||||
|
void precalculateZones();
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Variable global con los parámetros del juego ---
|
// --- Variable global con los parámetros del juego ---
|
||||||
extern Param param;
|
extern Param param;
|
||||||
|
|
||||||
// --- Funciones globales ---
|
// --- Funciones globales ---
|
||||||
void loadParamsFromFile(const std::string &file_path); // Establece valores para los parámetros a partir de un fichero de texto
|
void loadParamsFromFile(const std::string& file_path);
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "param.h" // Para Param, ParamGame, param
|
#include "param.h" // Para Param, ParamGame, param
|
||||||
#include "scoreboard.h" // Para Scoreboard
|
#include "scoreboard.h" // Para Scoreboard
|
||||||
#include "stage.h" // Para power_can_be_added
|
#include "stage.h" // Para power_can_be_added
|
||||||
|
#include "stage_interface.h" // Para IStageInfo
|
||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -26,6 +27,7 @@ Player::Player(const Config &config)
|
|||||||
enter_name_(std::make_unique<EnterName>()),
|
enter_name_(std::make_unique<EnterName>()),
|
||||||
hi_score_table_(config.hi_score_table),
|
hi_score_table_(config.hi_score_table),
|
||||||
glowing_entry_(config.glowing_entry),
|
glowing_entry_(config.glowing_entry),
|
||||||
|
stage_info_(config.stage_info),
|
||||||
play_area_(*config.play_area),
|
play_area_(*config.play_area),
|
||||||
id_(config.id),
|
id_(config.id),
|
||||||
default_pos_x_(config.x),
|
default_pos_x_(config.x),
|
||||||
@@ -73,9 +75,6 @@ void Player::init() {
|
|||||||
// Establece la posición del sprite
|
// Establece la posición del sprite
|
||||||
player_sprite_->clear();
|
player_sprite_->clear();
|
||||||
shiftSprite();
|
shiftSprite();
|
||||||
|
|
||||||
// Selecciona un frame para pintar
|
|
||||||
// player_sprite_->setCurrentAnimation("stand");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actua en consecuencia de la entrada recibida
|
// Actua en consecuencia de la entrada recibida
|
||||||
@@ -179,6 +178,9 @@ void Player::move() {
|
|||||||
case State::WAITING:
|
case State::WAITING:
|
||||||
handleWaitingMovement();
|
handleWaitingMovement();
|
||||||
break;
|
break;
|
||||||
|
case State::RECOVER:
|
||||||
|
handleRecoverMovement();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -196,6 +198,11 @@ void Player::handlePlayingMovement() {
|
|||||||
shiftSprite();
|
shiftSprite();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::handleRecoverMovement() {
|
||||||
|
if (player_sprite_->getCurrentAnimationFrame() == 10) { playSound("voice_brbrbr.wav"); }
|
||||||
|
if (player_sprite_->animationIsCompleted()) { setPlayingState(State::RESPAWNING); }
|
||||||
|
}
|
||||||
|
|
||||||
void Player::handleRollingMovement() {
|
void Player::handleRollingMovement() {
|
||||||
handleRollingBoundaryCollision();
|
handleRollingBoundaryCollision();
|
||||||
handleRollingGroundCollision();
|
handleRollingGroundCollision();
|
||||||
@@ -218,8 +225,6 @@ void Player::handleRollingGroundCollision() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const float VEL_Y = player_sprite_->getVelY();
|
|
||||||
// if (VEL_Y >= 0.0F && VEL_Y < 2.0F) {
|
|
||||||
if (player_sprite_->getVelY() < 2.0F) {
|
if (player_sprite_->getVelY() < 2.0F) {
|
||||||
handleRollingStop();
|
handleRollingStop();
|
||||||
} else {
|
} else {
|
||||||
@@ -463,6 +468,9 @@ void Player::setAnimation() {
|
|||||||
player_sprite_->setFlip(flipMode);
|
player_sprite_->setFlip(flipMode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case State::RECOVER:
|
||||||
|
player_sprite_->setCurrentAnimation("recover");
|
||||||
|
break;
|
||||||
case State::WAITING:
|
case State::WAITING:
|
||||||
case State::GAME_OVER:
|
case State::GAME_OVER:
|
||||||
player_sprite_->setCurrentAnimation("hello");
|
player_sprite_->setCurrentAnimation("hello");
|
||||||
@@ -588,10 +596,10 @@ void Player::update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Incrementa la puntuación del jugador
|
// Incrementa la puntuación del jugador
|
||||||
void Player::addScore(int score, int last_hi_score_entry) {
|
void Player::addScore(int score, int lowest_hi_score_entry) {
|
||||||
if (isPlaying()) {
|
if (isPlaying()) {
|
||||||
score_ += score;
|
score_ += score;
|
||||||
qualifies_for_high_score_ = score_ > last_hi_score_entry;
|
qualifies_for_high_score_ = score_ > lowest_hi_score_entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -625,6 +633,9 @@ void Player::setPlayingState(State state) {
|
|||||||
playing_state_ = state;
|
playing_state_ = state;
|
||||||
|
|
||||||
switch (playing_state_) {
|
switch (playing_state_) {
|
||||||
|
case State::RECOVER: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
case State::RESPAWNING: {
|
case State::RESPAWNING: {
|
||||||
playSound("voice_thankyou.wav");
|
playSound("voice_thankyou.wav");
|
||||||
setPlayingState(State::PLAYING);
|
setPlayingState(State::PLAYING);
|
||||||
@@ -635,7 +646,7 @@ void Player::setPlayingState(State state) {
|
|||||||
init();
|
init();
|
||||||
setInvulnerable(true);
|
setInvulnerable(true);
|
||||||
setScoreboardMode(Scoreboard::Mode::SCORE);
|
setScoreboardMode(Scoreboard::Mode::SCORE);
|
||||||
Stage::power_can_be_added = true;
|
stage_info_->canCollectPower();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::CONTINUE: {
|
case State::CONTINUE: {
|
||||||
@@ -690,7 +701,7 @@ void Player::setPlayingState(State state) {
|
|||||||
case State::TITLE_ANIMATION: {
|
case State::TITLE_ANIMATION: {
|
||||||
// Activa la animación de rodar
|
// Activa la animación de rodar
|
||||||
player_sprite_->setCurrentAnimation("walk");
|
player_sprite_->setCurrentAnimation("walk");
|
||||||
playSound("voice_thankyou.wav");
|
playSound("voice_credit_thankyou.wav");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case State::TITLE_HIDDEN: {
|
case State::TITLE_HIDDEN: {
|
||||||
@@ -929,7 +940,6 @@ void Player::playSound(const std::string &name) const {
|
|||||||
|
|
||||||
// Indica si se puede dibujar el objeto
|
// Indica si se puede dibujar el objeto
|
||||||
auto Player::isRenderable() const -> bool {
|
auto Player::isRenderable() const -> bool {
|
||||||
// return !isGameOver() && !isTitleHidden();
|
|
||||||
return !isTitleHidden();
|
return !isTitleHidden();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -947,4 +957,9 @@ void Player::addScoreToScoreBoard() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
manager->saveToFile(Asset::get()->get("score.bin"));
|
manager->saveToFile(Asset::get()->get("score.bin"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Player::addCredit() {
|
||||||
|
++credits_used_;
|
||||||
|
playSound("credit.wav");
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "input.h" // Para Input
|
#include "input.h" // Para Input
|
||||||
#include "manage_hiscore_table.h" // Para Table
|
#include "manage_hiscore_table.h" // Para Table
|
||||||
#include "scoreboard.h" // Para Scoreboard
|
#include "scoreboard.h" // Para Scoreboard
|
||||||
|
#include "stage_interface.h" // Para IStageInfo
|
||||||
#include "utils.h" // Para Circle
|
#include "utils.h" // Para Circle
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
@@ -71,7 +72,8 @@ class Player {
|
|||||||
CREDITS, // Estado para mostrar los créditos del juego
|
CREDITS, // Estado para mostrar los créditos del juego
|
||||||
TITLE_ANIMATION, // Animacion para el titulo
|
TITLE_ANIMATION, // Animacion para el titulo
|
||||||
TITLE_HIDDEN, // Animacion para el titulo
|
TITLE_HIDDEN, // Animacion para el titulo
|
||||||
RESPAWNING, // Tras continuar y volver al juego
|
RECOVER, // Al aceptar continuar
|
||||||
|
RESPAWNING, // Tras continuar y dar las gracias, otorga inmunidad y vuelve al juego
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Config {
|
struct Config {
|
||||||
@@ -82,8 +84,9 @@ class Player {
|
|||||||
SDL_FRect *play_area; // Usamos puntero para mantener la referencia
|
SDL_FRect *play_area; // Usamos puntero para mantener la referencia
|
||||||
std::vector<std::shared_ptr<Texture>> texture;
|
std::vector<std::shared_ptr<Texture>> texture;
|
||||||
std::vector<std::vector<std::string>> animations;
|
std::vector<std::vector<std::string>> animations;
|
||||||
Table *hi_score_table; // También como puntero para referencia
|
Table *hi_score_table; // También como puntero para referencia
|
||||||
int *glowing_entry; // Puntero para mantener la referencia
|
int *glowing_entry; // Puntero para mantener la referencia
|
||||||
|
IStageInfo *stage_info; // Puntero para el gestor de pantallas
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
@@ -111,9 +114,9 @@ class Player {
|
|||||||
void updateCooldown(); // Actualiza el cooldown de disparo
|
void updateCooldown(); // Actualiza el cooldown de disparo
|
||||||
|
|
||||||
// --- Puntuación y marcador ---
|
// --- Puntuación y marcador ---
|
||||||
void addScore(int score, int last_hi_score_entry); // Añade puntos
|
void addScore(int score, int lowest_hi_score_entry); // Añade puntos
|
||||||
void incScoreMultiplier(); // Incrementa el multiplicador
|
void incScoreMultiplier(); // Incrementa el multiplicador
|
||||||
void decScoreMultiplier(); // Decrementa el multiplicador
|
void decScoreMultiplier(); // Decrementa el multiplicador
|
||||||
|
|
||||||
// --- Estados de juego ---
|
// --- Estados de juego ---
|
||||||
void setPlayingState(State state); // Cambia el estado de juego
|
void setPlayingState(State state); // Cambia el estado de juego
|
||||||
@@ -181,8 +184,8 @@ class Player {
|
|||||||
void setScoreBoardPanel(Scoreboard::Id panel) { scoreboard_panel_ = panel; }
|
void setScoreBoardPanel(Scoreboard::Id panel) { scoreboard_panel_ = panel; }
|
||||||
void setScoreMultiplier(float value) { score_multiplier_ = value; }
|
void setScoreMultiplier(float value) { score_multiplier_ = value; }
|
||||||
void setWalkingState(State state) { walking_state_ = state; }
|
void setWalkingState(State state) { walking_state_ = state; }
|
||||||
void addCredit() { ++credits_used_; }
|
|
||||||
|
void addCredit();
|
||||||
void setGamepad(std::shared_ptr<Input::Gamepad> gamepad) { gamepad_ = gamepad; }
|
void setGamepad(std::shared_ptr<Input::Gamepad> gamepad) { gamepad_ = gamepad; }
|
||||||
[[nodiscard]] auto getGamepad() const -> std::shared_ptr<Input::Gamepad> { return gamepad_; }
|
[[nodiscard]] auto getGamepad() const -> std::shared_ptr<Input::Gamepad> { return gamepad_; }
|
||||||
void setUsesKeyboard(bool value) { uses_keyboard_ = value; }
|
void setUsesKeyboard(bool value) { uses_keyboard_ = value; }
|
||||||
@@ -204,6 +207,7 @@ class Player {
|
|||||||
std::shared_ptr<Input::Gamepad> gamepad_ = nullptr; // Dispositivo asociado
|
std::shared_ptr<Input::Gamepad> gamepad_ = nullptr; // Dispositivo asociado
|
||||||
Table *hi_score_table_ = nullptr; // Tabla de máximas puntuaciones
|
Table *hi_score_table_ = nullptr; // Tabla de máximas puntuaciones
|
||||||
int *glowing_entry_ = nullptr; // Entrada de la tabla de puntuaciones para hacerla brillar
|
int *glowing_entry_ = nullptr; // Entrada de la tabla de puntuaciones para hacerla brillar
|
||||||
|
IStageInfo *stage_info_; // Informacion de la pantalla actual
|
||||||
std::string name_; // Nombre del jugador
|
std::string name_; // Nombre del jugador
|
||||||
std::string last_enter_name_; // Último nombre introducido en la tabla de puntuaciones
|
std::string last_enter_name_; // Último nombre introducido en la tabla de puntuaciones
|
||||||
|
|
||||||
@@ -277,6 +281,7 @@ class Player {
|
|||||||
void transitionToCooling(); // Cambia el estado actual al de enfriamiento (por ejemplo, tras una ráfaga o sobrecalentamiento)
|
void transitionToCooling(); // Cambia el estado actual al de enfriamiento (por ejemplo, tras una ráfaga o sobrecalentamiento)
|
||||||
void completeCooling(); // Finaliza el proceso de enfriamiento y restablece el estado listo para disparar
|
void completeCooling(); // Finaliza el proceso de enfriamiento y restablece el estado listo para disparar
|
||||||
void handlePlayingMovement(); // Gestiona el movimiento del personaje u objeto durante el estado de juego activo
|
void handlePlayingMovement(); // Gestiona el movimiento del personaje u objeto durante el estado de juego activo
|
||||||
|
void handleRecoverMovement(); // Comprueba si ha acabado la animación
|
||||||
void handleRollingMovement(); // Actualiza la lógica de movimiento de "rodar" (posiblemente tras impacto o acción especial)
|
void handleRollingMovement(); // Actualiza la lógica de movimiento de "rodar" (posiblemente tras impacto o acción especial)
|
||||||
void handleRollingBoundaryCollision(); // Detecta y maneja colisiones del objeto rodante con los límites de la pantalla
|
void handleRollingBoundaryCollision(); // Detecta y maneja colisiones del objeto rodante con los límites de la pantalla
|
||||||
void handleRollingGroundCollision(); // Gestiona la interacción del objeto rodante con el suelo (rebotes, frenado, etc.)
|
void handleRollingGroundCollision(); // Gestiona la interacción del objeto rodante con el suelo (rebotes, frenado, etc.)
|
||||||
|
|||||||
@@ -531,16 +531,19 @@ void Resource::createPlayerTextures() {
|
|||||||
|
|
||||||
// Configuración de jugadores y sus paletas
|
// Configuración de jugadores y sus paletas
|
||||||
struct PlayerConfig {
|
struct PlayerConfig {
|
||||||
std::string base_texture;
|
std::string base_texture;
|
||||||
std::vector<std::string> palette_files;
|
std::vector<std::string> palette_files;
|
||||||
std::string name_prefix;
|
std::string name_prefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<PlayerConfig> players = {
|
std::vector<PlayerConfig> players = {
|
||||||
{"player1.gif", {"player1_coffee1.pal", "player1_coffee2.pal", "player1_invencible.pal"}, "player1"},
|
{"player1.gif", {"player1_coffee1.pal", "player1_coffee2.pal", "player1_invencible.pal"}, "player1"},
|
||||||
{"player2.gif", {"player2_coffee1.pal", "player2_coffee2.pal", "player2_invencible.pal"}, "player2"}};
|
{"player2.gif", {"player2_coffee1.pal", "player2_coffee2.pal", "player2_invencible.pal"}, "player2"}};
|
||||||
|
|
||||||
for (const auto &player : players) {
|
// Bucle principal modificado para usar un índice (player_idx)
|
||||||
|
for (size_t player_idx = 0; player_idx < players.size(); ++player_idx) {
|
||||||
|
const auto &player = players[player_idx]; // Obtenemos el jugador actual
|
||||||
|
|
||||||
// Encontrar el archivo original de la textura
|
// Encontrar el archivo original de la textura
|
||||||
std::string texture_file_path;
|
std::string texture_file_path;
|
||||||
auto texture_list = Asset::get()->getListByType(Asset::Type::BITMAP);
|
auto texture_list = Asset::get()->getListByType(Asset::Type::BITMAP);
|
||||||
@@ -567,6 +570,17 @@ void Resource::createPlayerTextures() {
|
|||||||
texture_copy->addPaletteFromPalFile(Asset::get()->get(player.palette_files[1]));
|
texture_copy->addPaletteFromPalFile(Asset::get()->get(player.palette_files[1]));
|
||||||
texture_copy->addPaletteFromPalFile(Asset::get()->get(player.palette_files[2]));
|
texture_copy->addPaletteFromPalFile(Asset::get()->get(player.palette_files[2]));
|
||||||
|
|
||||||
|
// Añade los colores establecidos en param.player usando el índice del jugador (player_idx)
|
||||||
|
texture_copy->setPaletteColor(1, 16, param.player.one_coffee_shirt[player_idx].darkest.toUint32());
|
||||||
|
texture_copy->setPaletteColor(1, 17, param.player.one_coffee_shirt[player_idx].dark.toUint32());
|
||||||
|
texture_copy->setPaletteColor(1, 18, param.player.one_coffee_shirt[player_idx].base.toUint32());
|
||||||
|
texture_copy->setPaletteColor(1, 19, param.player.one_coffee_shirt[player_idx].light.toUint32());
|
||||||
|
|
||||||
|
texture_copy->setPaletteColor(2, 16, param.player.two_coffee_shirt[player_idx].darkest.toUint32());
|
||||||
|
texture_copy->setPaletteColor(2, 17, param.player.two_coffee_shirt[player_idx].dark.toUint32());
|
||||||
|
texture_copy->setPaletteColor(2, 18, param.player.two_coffee_shirt[player_idx].base.toUint32());
|
||||||
|
texture_copy->setPaletteColor(2, 19, param.player.two_coffee_shirt[player_idx].light.toUint32());
|
||||||
|
|
||||||
// Cambiar a la paleta específica (índice i+1 porque 0 es la original)
|
// Cambiar a la paleta específica (índice i+1 porque 0 es la original)
|
||||||
texture_copy->setPalette(i + 1);
|
texture_copy->setPalette(i + 1);
|
||||||
|
|
||||||
|
|||||||
@@ -140,7 +140,6 @@ class Resource {
|
|||||||
void loadEssentialResources(); // Carga recursos esenciales en modo lazy
|
void loadEssentialResources(); // Carga recursos esenciales en modo lazy
|
||||||
void loadEssentialTextures(); // Carga solo las texturas esenciales (fuentes)
|
void loadEssentialTextures(); // Carga solo las texturas esenciales (fuentes)
|
||||||
void loadTextFilesQuiet(); // Carga ficheros de texto sin mostrar progreso (para modo lazy)
|
void loadTextFilesQuiet(); // Carga ficheros de texto sin mostrar progreso (para modo lazy)
|
||||||
// void addPalettes(); // Añade paletas a las texturas
|
|
||||||
void createPlayerTextures(); // Crea las texturas de jugadores con todas sus variantes de paleta
|
void createPlayerTextures(); // Crea las texturas de jugadores con todas sus variantes de paleta
|
||||||
void createTextTextures(); // Crea las texturas a partir de los datos cargados
|
void createTextTextures(); // Crea las texturas a partir de los datos cargados
|
||||||
void createText(); // Crea los objetos de texto
|
void createText(); // Crea los objetos de texto
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ void Scoreboard::renderGameOverMode() {
|
|||||||
|
|
||||||
void Scoreboard::renderStageInfoMode() {
|
void Scoreboard::renderStageInfoMode() {
|
||||||
// STAGE
|
// STAGE
|
||||||
text_scoreboard_->writeDX(Text::CENTER | Text::COLOR, slot4_1_.x, slot4_1_.y, Lang::getText("[SCOREBOARD] 5") + std::to_string(stage_), 1, text_color1_);
|
text_scoreboard_->writeDX(Text::CENTER | Text::COLOR, slot4_1_.x, slot4_1_.y, Lang::getText("[SCOREBOARD] 5") + " " + std::to_string(stage_), 1, text_color1_);
|
||||||
|
|
||||||
// POWERMETER
|
// POWERMETER
|
||||||
power_meter_sprite_->setSpriteClip(0, 0, 40, 7);
|
power_meter_sprite_->setSpriteClip(0, 0, 40, 7);
|
||||||
@@ -310,9 +310,6 @@ void Scoreboard::renderShowNameMode(size_t panel_index) {
|
|||||||
|
|
||||||
/* TEXTO CENTRADO */
|
/* TEXTO CENTRADO */
|
||||||
text_scoreboard_->writeDX(Text::CENTER | Text::COLOR, slot4_4_.x, slot4_4_.y, record_name_.at(panel_index), 1, getColorLikeKnightRider(name_colors_, loop_counter_ / 5));
|
text_scoreboard_->writeDX(Text::CENTER | Text::COLOR, slot4_4_.x, slot4_4_.y, record_name_.at(panel_index), 1, getColorLikeKnightRider(name_colors_, loop_counter_ / 5));
|
||||||
|
|
||||||
/* TEXTO A LA IZQUIERDA */
|
|
||||||
// text_scoreboard_->writeColored(enter_name_pos_.x, enter_name_pos_.y, record_name_.at(panelIndex), getColorLikeKnightRider(name_colors_, loop_counter_ / 5));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scoreboard::renderGameCompletedMode(size_t panel_index) {
|
void Scoreboard::renderGameCompletedMode(size_t panel_index) {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ constexpr std::string_view TEXT_COPYRIGHT = "@2020,2025 JailDesigner";
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Credits::Credits()
|
Credits::Credits()
|
||||||
: balloon_manager_(std::make_unique<BalloonManager>()),
|
: balloon_manager_(std::make_unique<BalloonManager>(nullptr)),
|
||||||
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::DIAGONAL)),
|
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::DIAGONAL)),
|
||||||
fade_in_(std::make_unique<Fade>()),
|
fade_in_(std::make_unique<Fade>()),
|
||||||
fade_out_(std::make_unique<Fade>()),
|
fade_out_(std::make_unique<Fade>()),
|
||||||
@@ -124,7 +124,7 @@ void Credits::render() {
|
|||||||
void Credits::checkEvents() {
|
void Credits::checkEvents() {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
GlobalEvents::check(event);
|
GlobalEvents::handle(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,7 +258,6 @@ void Credits::fillCanvas() {
|
|||||||
SDL_RenderFillRect(Screen::get()->getRenderer(), &right_black_rect_);
|
SDL_RenderFillRect(Screen::get()->getRenderer(), &right_black_rect_);
|
||||||
|
|
||||||
// Dibuja el rectangulo rojo
|
// Dibuja el rectangulo rojo
|
||||||
// SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0xFF, 0, 0, 0xFF);
|
|
||||||
const Color COLOR = color_.LIGHTEN();
|
const Color COLOR = color_.LIGHTEN();
|
||||||
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), COLOR.r, COLOR.g, COLOR.b, 0xFF);
|
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), COLOR.r, COLOR.g, COLOR.b, 0xFF);
|
||||||
SDL_RenderRect(Screen::get()->getRenderer(), &border_rect_);
|
SDL_RenderRect(Screen::get()->getRenderer(), &border_rect_);
|
||||||
@@ -474,9 +473,6 @@ void Credits::resetVolume() const {
|
|||||||
|
|
||||||
// Cambia el color del fondo
|
// Cambia el color del fondo
|
||||||
void Credits::cycleColors() {
|
void Credits::cycleColors() {
|
||||||
// constexpr int UPPER_LIMIT = 255; // Límite superior
|
|
||||||
// constexpr int LOWER_LIMIT = 80; // Límite inferior
|
|
||||||
|
|
||||||
constexpr int UPPER_LIMIT = 140; // Límite superior
|
constexpr int UPPER_LIMIT = 140; // Límite superior
|
||||||
constexpr int LOWER_LIMIT = 30; // Límite inferior
|
constexpr int LOWER_LIMIT = 30; // Límite inferior
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
#include "ui/service_menu.h" // Para ServiceMenu
|
#include "ui/service_menu.h" // Para ServiceMenu
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
#include <iostream> // Para Notifier
|
#include <iostream> // Para std::cout
|
||||||
|
|
||||||
#include "ui/notifier.h" // Para Notifier
|
#include "ui/notifier.h" // Para Notifier
|
||||||
#endif
|
#endif
|
||||||
@@ -52,12 +52,13 @@ Game::Game(Player::Id player_id, int current_stage, bool demo)
|
|||||||
: renderer_(Screen::get()->getRenderer()),
|
: renderer_(Screen::get()->getRenderer()),
|
||||||
screen_(Screen::get()),
|
screen_(Screen::get()),
|
||||||
input_(Input::get()),
|
input_(Input::get()),
|
||||||
background_(std::make_unique<Background>()),
|
|
||||||
canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.play_area.rect.w, param.game.play_area.rect.h)),
|
canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.play_area.rect.w, param.game.play_area.rect.h)),
|
||||||
pause_manager_(std::make_unique<PauseManager>([this](bool is_paused) { onPauseStateChanged(is_paused); })),
|
pause_manager_(std::make_unique<PauseManager>([this](bool is_paused) { onPauseStateChanged(is_paused); })),
|
||||||
|
stage_manager_(std::make_unique<StageManager>()),
|
||||||
|
balloon_manager_(std::make_unique<BalloonManager>(stage_manager_.get())),
|
||||||
|
background_(std::make_unique<Background>(stage_manager_->getTotalPowerNeededToCompleteGame())),
|
||||||
fade_in_(std::make_unique<Fade>()),
|
fade_in_(std::make_unique<Fade>()),
|
||||||
fade_out_(std::make_unique<Fade>()),
|
fade_out_(std::make_unique<Fade>()),
|
||||||
balloon_manager_(std::make_unique<BalloonManager>()),
|
|
||||||
tabe_(std::make_unique<Tabe>()),
|
tabe_(std::make_unique<Tabe>()),
|
||||||
hit_(Hit(Resource::get()->getTexture("hit.png"))) {
|
hit_(Hit(Resource::get()->getTexture("hit.png"))) {
|
||||||
// Pasa variables
|
// Pasa variables
|
||||||
@@ -66,8 +67,9 @@ Game::Game(Player::Id player_id, int current_stage, bool demo)
|
|||||||
// Otras variables
|
// Otras variables
|
||||||
Section::name = Section::Name::GAME;
|
Section::name = Section::Name::GAME;
|
||||||
Section::options = Section::Options::NONE;
|
Section::options = Section::Options::NONE;
|
||||||
Stage::init();
|
stage_manager_->initialize(Asset::get()->get("stages.txt"));
|
||||||
Stage::number = current_stage;
|
stage_manager_->setPowerChangeCallback([this](int amount) { background_->incrementProgress(amount); });
|
||||||
|
stage_manager_->jumpToStage(current_stage);
|
||||||
|
|
||||||
// Asigna texturas y animaciones
|
// Asigna texturas y animaciones
|
||||||
setResources();
|
setResources();
|
||||||
@@ -99,7 +101,6 @@ Game::Game(Player::Id player_id, int current_stage, bool demo)
|
|||||||
initDifficultyVars();
|
initDifficultyVars();
|
||||||
initDemo(player_id);
|
initDemo(player_id);
|
||||||
initPaths();
|
initPaths();
|
||||||
setTotalPower();
|
|
||||||
|
|
||||||
// Registra callbacks
|
// Registra callbacks
|
||||||
ServiceMenu::get()->setStateChangeCallback([this](bool is_active) {
|
ServiceMenu::get()->setStateChangeCallback([this](bool is_active) {
|
||||||
@@ -108,15 +109,6 @@ Game::Game(Player::Id player_id, int current_stage, bool demo)
|
|||||||
pause_manager_->setServiceMenuPause(is_active);
|
pause_manager_->setServiceMenuPause(is_active);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
// Si se empieza en una fase que no es la primera
|
|
||||||
if (!demo_.enabled) {
|
|
||||||
for (int i = 0; i < Stage::number; ++i) {
|
|
||||||
Stage::total_power += Stage::get(i).power_to_complete;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Game::~Game() {
|
Game::~Game() {
|
||||||
@@ -262,33 +254,60 @@ void Game::renderPlayers() {
|
|||||||
|
|
||||||
// Comprueba si hay cambio de fase y actualiza las variables
|
// Comprueba si hay cambio de fase y actualiza las variables
|
||||||
void Game::updateStage() {
|
void Game::updateStage() {
|
||||||
if (Stage::power >= Stage::get(Stage::number).power_to_complete) {
|
if (!stage_manager_->isCurrentStageCompleted()) {
|
||||||
// Cambio de fase
|
return; // No hay cambio de fase
|
||||||
Stage::power = Stage::get(Stage::number).power_to_complete - Stage::power;
|
}
|
||||||
++Stage::number;
|
|
||||||
playSound("stage_change.wav");
|
|
||||||
balloon_manager_->resetBalloonSpeed();
|
|
||||||
screen_->flash(FLASH_COLOR, 3);
|
|
||||||
screen_->shake();
|
|
||||||
|
|
||||||
// Escribe el texto por pantalla
|
// Calcular poder sobrante antes de avanzar
|
||||||
if (Stage::number < 10) {
|
int power_overflow = 0;
|
||||||
std::vector<Path> paths = {paths_.at(2), paths_.at(3)};
|
auto current_stage = stage_manager_->getCurrentStage();
|
||||||
if (Stage::number == 9) {
|
if (current_stage.has_value()) {
|
||||||
createMessage(paths, Resource::get()->getTexture("game_text_last_stage"));
|
int current_power = stage_manager_->getCurrentPower();
|
||||||
} else {
|
int power_needed = current_stage->getPowerToComplete();
|
||||||
auto text = Resource::get()->getText("04b_25_2x");
|
power_overflow = current_power - power_needed; // Poder que sobra
|
||||||
const std::string CAPTION = Lang::getText("[GAME_TEXT] 2") + std::to_string(10 - Stage::number) + Lang::getText("[GAME_TEXT] 2A");
|
}
|
||||||
createMessage(paths, text->writeToTexture(CAPTION, 1, -4));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modifica el color de fondo al llegar a la Fase 10
|
// Intentar avanzar a la siguiente fase
|
||||||
if (Stage::number == 9) {
|
if (!stage_manager_->advanceToNextStage()) {
|
||||||
background_->setColor(Color(0xdd, 0x19, 0x1d).DARKEN());
|
// No se pudo avanzar (probablemente juego completado)
|
||||||
background_->setAlpha(96);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aplicar el poder sobrante a la nueva fase
|
||||||
|
if (power_overflow > 0) {
|
||||||
|
stage_manager_->addPower(power_overflow);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Efectos de cambio de fase
|
||||||
|
playSound("stage_change.wav");
|
||||||
|
balloon_manager_->resetBalloonSpeed();
|
||||||
|
screen_->flash(FLASH_COLOR, 3);
|
||||||
|
screen_->shake();
|
||||||
|
|
||||||
|
// Obtener datos de la nueva fase
|
||||||
|
size_t current_stage_index = stage_manager_->getCurrentStageIndex();
|
||||||
|
size_t total_stages = stage_manager_->getTotalStages();
|
||||||
|
|
||||||
|
// Escribir texto por pantalla
|
||||||
|
if (current_stage_index < total_stages) { // No es la última fase
|
||||||
|
std::vector<Path> paths = {paths_.at(2), paths_.at(3)};
|
||||||
|
|
||||||
|
if (current_stage_index == total_stages - 1) { // Penúltima fase (será la última)
|
||||||
|
createMessage(paths, Resource::get()->getTexture("game_text_last_stage"));
|
||||||
|
} else {
|
||||||
|
auto text = Resource::get()->getText("04b_25_2x");
|
||||||
|
const std::string CAPTION = Lang::getText("[GAME_TEXT] 2") +
|
||||||
|
std::to_string(total_stages - current_stage_index) +
|
||||||
|
Lang::getText("[GAME_TEXT] 2A");
|
||||||
|
createMessage(paths, text->writeToTexture(CAPTION, 1, -4));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Modificar color de fondo en la última fase
|
||||||
|
if (current_stage_index == total_stages - 1) { // Última fase
|
||||||
|
background_->setColor(Color(0xdd, 0x19, 0x1d).DARKEN());
|
||||||
|
background_->setAlpha(96);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el estado de fin de la partida
|
// Actualiza el estado de fin de la partida
|
||||||
@@ -330,11 +349,9 @@ void Game::updateGameStateGameOver() {
|
|||||||
|
|
||||||
if (fade_out_->hasEnded()) {
|
if (fade_out_->hasEnded()) {
|
||||||
if (game_completed_counter_ > 0) {
|
if (game_completed_counter_ > 0) {
|
||||||
// Los jugadores han completado el juego
|
Section::name = Section::Name::CREDITS; // Los jugadores han completado el juego
|
||||||
Section::name = Section::Name::CREDITS;
|
|
||||||
} else {
|
} else {
|
||||||
// La partida ha terminado con la derrota de los jugadores
|
Section::name = Section::Name::HI_SCORE_TABLE; // La partida ha terminado con la derrota de los jugadores
|
||||||
Section::name = Section::Name::HI_SCORE_TABLE;
|
|
||||||
}
|
}
|
||||||
Section::options = Section::Options::HI_SCORE_AFTER_PLAYING;
|
Section::options = Section::Options::HI_SCORE_AFTER_PLAYING;
|
||||||
if (Options::audio.enabled) {
|
if (Options::audio.enabled) {
|
||||||
@@ -362,13 +379,11 @@ void Game::updateGameStateCompleted() {
|
|||||||
|
|
||||||
// Para la música y elimina todos los globos e items
|
// Para la música y elimina todos los globos e items
|
||||||
if (game_completed_counter_ == 0) {
|
if (game_completed_counter_ == 0) {
|
||||||
stopMusic();
|
stopMusic(); // Detiene la música
|
||||||
Stage::number = 9; // Deja el valor dentro de los limites
|
|
||||||
balloon_manager_->destroyAllBalloons(); // Destruye a todos los globos
|
balloon_manager_->destroyAllBalloons(); // Destruye a todos los globos
|
||||||
playSound("power_ball_explosion.wav");
|
playSound("power_ball_explosion.wav"); // Sonido de destruir todos los globos
|
||||||
destroyAllItems(); // Destruye todos los items
|
destroyAllItems(); // Destruye todos los items
|
||||||
Stage::power = 0; // Vuelve a dejar el poder a cero, por lo que hubiera podido subir al destruir todos los globos
|
background_->setAlpha(0); // Elimina el tono rojo de las últimas pantallas
|
||||||
background_->setAlpha(0); // Elimina el tono rojo de las últimas pantallas
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comienza las celebraciones
|
// Comienza las celebraciones
|
||||||
@@ -409,8 +424,9 @@ void Game::updateGameStateCompleted() {
|
|||||||
|
|
||||||
// Comprueba el estado del juego
|
// Comprueba el estado del juego
|
||||||
void Game::checkState() {
|
void Game::checkState() {
|
||||||
if (state_ != State::COMPLETED && Stage::number == 10) {
|
if (state_ != State::COMPLETED && stage_manager_->isGameCompleted()) {
|
||||||
setState(State::COMPLETED);
|
setState(State::COMPLETED);
|
||||||
|
background_->setState(Background::State::COMPLETED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state_ != State::GAME_OVER && allPlayersAreGameOver()) {
|
if (state_ != State::GAME_OVER && allPlayersAreGameOver()) {
|
||||||
@@ -523,11 +539,11 @@ void Game::checkBulletCollision() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (checkBulletTabeCollision(bullet)) {
|
if (checkBulletTabeCollision(bullet)) {
|
||||||
break; // Exit early if bullet hit Tabe
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkBulletBalloonCollision(bullet)) {
|
if (checkBulletBalloonCollision(bullet)) {
|
||||||
break; // Exit early if bullet hit balloon
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -608,13 +624,12 @@ void Game::handleItemDrop(std::shared_ptr<Balloon> balloon, std::shared_ptr<Play
|
|||||||
|
|
||||||
// Maneja la destrucción del globo y puntuación
|
// Maneja la destrucción del globo y puntuación
|
||||||
void Game::handleBalloonDestruction(std::shared_ptr<Balloon> balloon, std::shared_ptr<Player> player) {
|
void Game::handleBalloonDestruction(std::shared_ptr<Balloon> balloon, std::shared_ptr<Player> player) {
|
||||||
evaluateAndSetMenace();
|
|
||||||
|
|
||||||
if (player->isPlaying()) {
|
if (player->isPlaying()) {
|
||||||
auto const SCORE = balloon_manager_->popBalloon(balloon) * player->getScoreMultiplier() * difficulty_score_multiplier_;
|
auto const SCORE = balloon_manager_->popBalloon(balloon) * player->getScoreMultiplier() * difficulty_score_multiplier_;
|
||||||
player->addScore(SCORE, Options::settings.hi_score_table.back().score);
|
player->addScore(SCORE, Options::settings.hi_score_table.back().score);
|
||||||
player->incScoreMultiplier();
|
player->incScoreMultiplier();
|
||||||
}
|
}
|
||||||
|
setMenace();
|
||||||
updateHiScore();
|
updateHiScore();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -852,8 +867,7 @@ void Game::renderPathSprites() {
|
|||||||
// Acciones a realizar cuando el jugador colisiona con un globo
|
// Acciones a realizar cuando el jugador colisiona con un globo
|
||||||
void Game::handlePlayerCollision(std::shared_ptr<Player> &player, std::shared_ptr<Balloon> &balloon) {
|
void Game::handlePlayerCollision(std::shared_ptr<Player> &player, std::shared_ptr<Balloon> &balloon) {
|
||||||
if (!player->isPlaying() || player->isInvulnerable()) {
|
if (!player->isPlaying() || player->isInvulnerable()) {
|
||||||
// Si no está jugando o tiene inmunidad, no hace nada
|
return; // Si no está jugando o tiene inmunidad, no hace nada
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si tiene cafes
|
// Si tiene cafes
|
||||||
@@ -876,7 +890,7 @@ void Game::handlePlayerCollision(std::shared_ptr<Player> &player, std::shared_pt
|
|||||||
player->setPlayingState(Player::State::ROLLING);
|
player->setPlayingState(Player::State::ROLLING);
|
||||||
sendPlayerToTheBack(player);
|
sendPlayerToTheBack(player);
|
||||||
if (allPlayersAreNotPlaying()) {
|
if (allPlayersAreNotPlaying()) {
|
||||||
Stage::power_can_be_added = false; // No se puede subir poder de fase si no hay nadie jugando
|
stage_manager_->disablePowerCollection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -961,36 +975,12 @@ void Game::updateGameStates() {
|
|||||||
|
|
||||||
// Actualiza el fondo
|
// Actualiza el fondo
|
||||||
void Game::updateBackground() {
|
void Game::updateBackground() {
|
||||||
// Si el juego está completado, se reduce la velocidad de las nubes
|
|
||||||
if (state_ == State::COMPLETED) {
|
|
||||||
Stage::total_power = (Stage::total_power > 200) ? (Stage::total_power - 25) : 200;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calcula la velocidad en función de los globos explotados y el total de globos a explotar para acabar el juego
|
|
||||||
constexpr float CLOUDS_INITIAL_SPEED = 0.05F;
|
|
||||||
constexpr float CLOUDS_FINAL_SPEED = 2.00F - CLOUDS_INITIAL_SPEED;
|
|
||||||
const float CLOUDS_SPEED = (-CLOUDS_INITIAL_SPEED) + (-CLOUDS_FINAL_SPEED * (static_cast<float>(Stage::total_power) / total_power_to_complete_game_));
|
|
||||||
background_->setCloudsSpeed(CLOUDS_SPEED);
|
|
||||||
|
|
||||||
// Calcula la transición de los diferentes fondos
|
|
||||||
constexpr float NUM = 1525.0F; // total_power_to_complete div 4
|
|
||||||
const float GRADIENT_NUMBER = std::min(Stage::total_power / NUM, 3.0F);
|
|
||||||
const float PERCENT = GRADIENT_NUMBER - static_cast<int>(GRADIENT_NUMBER);
|
|
||||||
background_->setGradientNumber(static_cast<int>(GRADIENT_NUMBER));
|
|
||||||
background_->setTransition(PERCENT);
|
|
||||||
|
|
||||||
// Calcula la posición del sol
|
|
||||||
constexpr float SUN_FINAL_POWER = NUM * 2;
|
|
||||||
background_->setSunProgression(Stage::total_power / SUN_FINAL_POWER);
|
|
||||||
background_->setMoonProgression(Stage::total_power / static_cast<float>(total_power_to_complete_game_));
|
|
||||||
|
|
||||||
// Actualiza el objeto
|
|
||||||
background_->update();
|
background_->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja los elementos de la zona de juego en su textura
|
// Dibuja los elementos de la zona de juego en su textura
|
||||||
void Game::fillCanvas() {
|
void Game::fillCanvas() {
|
||||||
// Dibujamos el contenido de la zona de juego en su textura
|
// Dibuja el contenido de la zona de juego en su textura
|
||||||
auto *temp = SDL_GetRenderTarget(renderer_);
|
auto *temp = SDL_GetRenderTarget(renderer_);
|
||||||
SDL_SetRenderTarget(renderer_, canvas_);
|
SDL_SetRenderTarget(renderer_, canvas_);
|
||||||
|
|
||||||
@@ -1029,7 +1019,7 @@ void Game::run() {
|
|||||||
checkInput();
|
checkInput();
|
||||||
#endif
|
#endif
|
||||||
update();
|
update();
|
||||||
checkEvents(); // Tiene que ir antes del render
|
handleEvents(); // Tiene que ir antes del render
|
||||||
render();
|
render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1090,7 +1080,7 @@ void Game::initPaths() {
|
|||||||
// Actualiza las variables de ayuda
|
// Actualiza las variables de ayuda
|
||||||
void Game::updateHelper() {
|
void Game::updateHelper() {
|
||||||
// Solo ofrece ayuda cuando la amenaza es elevada
|
// Solo ofrece ayuda cuando la amenaza es elevada
|
||||||
if (menace_current_ > 15) {
|
if (menace_ > 15) {
|
||||||
helper_.need_coffee = true;
|
helper_.need_coffee = true;
|
||||||
helper_.need_coffee_machine = true;
|
helper_.need_coffee_machine = true;
|
||||||
for (const auto &player : players_) {
|
for (const auto &player : players_) {
|
||||||
@@ -1135,7 +1125,7 @@ auto Game::allPlayersAreNotPlaying() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba los eventos que hay en cola
|
// Comprueba los eventos que hay en cola
|
||||||
void Game::checkEvents() {
|
void Game::handleEvents() {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
@@ -1152,9 +1142,9 @@ void Game::checkEvents() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
checkDebugEvents(event);
|
handleDebugEvents(event);
|
||||||
#endif
|
#endif
|
||||||
GlobalEvents::check(event);
|
GlobalEvents::handle(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1166,12 +1156,11 @@ void Game::updateScoreboard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resto de marcador
|
// Resto de marcador
|
||||||
scoreboard_->setStage(Stage::number + 1);
|
scoreboard_->setStage(stage_manager_->getCurrentStageIndex() + 1);
|
||||||
scoreboard_->setPower((float)Stage::power / (float)Stage::get(Stage::number).power_to_complete);
|
scoreboard_->setPower(stage_manager_->getCurrentStageProgressFraction());
|
||||||
scoreboard_->setHiScore(hi_score_.score);
|
scoreboard_->setHiScore(hi_score_.score);
|
||||||
scoreboard_->setHiScoreName(hi_score_.name);
|
scoreboard_->setHiScoreName(hi_score_.name);
|
||||||
|
|
||||||
// Lógica del marcador
|
|
||||||
scoreboard_->update();
|
scoreboard_->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1411,7 +1400,7 @@ void Game::handleFireInputs(const std::shared_ptr<Player> &player, bool autofire
|
|||||||
// Maneja la continuación del jugador cuando no está jugando, permitiendo que continúe si se pulsa el botón de inicio.
|
// Maneja la continuación del jugador cuando no está jugando, permitiendo que continúe si se pulsa el botón de inicio.
|
||||||
void Game::handlePlayerContinueInput(const std::shared_ptr<Player> &player) {
|
void Game::handlePlayerContinueInput(const std::shared_ptr<Player> &player) {
|
||||||
if (input_->checkAction(Input::Action::START, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) {
|
if (input_->checkAction(Input::Action::START, Input::DO_NOT_ALLOW_REPEAT, player->getUsesKeyboard(), player->getGamepad())) {
|
||||||
player->setPlayingState(Player::State::RESPAWNING);
|
player->setPlayingState(Player::State::RECOVER);
|
||||||
player->addCredit();
|
player->addCredit();
|
||||||
sendPlayerToTheFront(player);
|
sendPlayerToTheFront(player);
|
||||||
}
|
}
|
||||||
@@ -1488,12 +1477,7 @@ void Game::initDemo(Player::Id player_id) {
|
|||||||
constexpr auto NUM_DEMOS = 3;
|
constexpr auto NUM_DEMOS = 3;
|
||||||
const auto DEMO = rand() % NUM_DEMOS;
|
const auto DEMO = rand() % NUM_DEMOS;
|
||||||
constexpr std::array<int, NUM_DEMOS> STAGES = {0, 3, 5};
|
constexpr std::array<int, NUM_DEMOS> STAGES = {0, 3, 5};
|
||||||
Stage::number = STAGES[DEMO];
|
stage_manager_->jumpToStage(STAGES.at(DEMO));
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el numero de globos explotados según la fase del modo demostración
|
|
||||||
for (int i = 0; i < Stage::number; ++i) {
|
|
||||||
Stage::total_power += Stage::get(i).power_to_complete;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activa o no al otro jugador
|
// Activa o no al otro jugador
|
||||||
@@ -1529,14 +1513,6 @@ void Game::initDemo(Player::Id player_id) {
|
|||||||
demo_.counter = 0;
|
demo_.counter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calcula el poder total necesario para completar el juego
|
|
||||||
void Game::setTotalPower() {
|
|
||||||
total_power_to_complete_game_ = 0;
|
|
||||||
for (const auto &stage : Stage::stages) {
|
|
||||||
total_power_to_complete_game_ += stage.power_to_complete;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa el marcador
|
// Inicializa el marcador
|
||||||
void Game::initScoreboard() {
|
void Game::initScoreboard() {
|
||||||
scoreboard_->setPos(param.scoreboard.rect);
|
scoreboard_->setPos(param.scoreboard.rect);
|
||||||
@@ -1596,6 +1572,7 @@ void Game::initPlayers(Player::Id player_id) {
|
|||||||
config_player1.animations = player_animations_;
|
config_player1.animations = player_animations_;
|
||||||
config_player1.hi_score_table = &Options::settings.hi_score_table;
|
config_player1.hi_score_table = &Options::settings.hi_score_table;
|
||||||
config_player1.glowing_entry = &Options::settings.glowing_entries.at(static_cast<int>(Player::Id::PLAYER1) - 1);
|
config_player1.glowing_entry = &Options::settings.glowing_entries.at(static_cast<int>(Player::Id::PLAYER1) - 1);
|
||||||
|
config_player1.stage_info = stage_manager_.get();
|
||||||
|
|
||||||
auto player1 = std::make_unique<Player>(config_player1);
|
auto player1 = std::make_unique<Player>(config_player1);
|
||||||
player1->setScoreBoardPanel(Scoreboard::Id::LEFT);
|
player1->setScoreBoardPanel(Scoreboard::Id::LEFT);
|
||||||
@@ -1616,6 +1593,7 @@ void Game::initPlayers(Player::Id player_id) {
|
|||||||
config_player2.animations = player_animations_;
|
config_player2.animations = player_animations_;
|
||||||
config_player2.hi_score_table = &Options::settings.hi_score_table;
|
config_player2.hi_score_table = &Options::settings.hi_score_table;
|
||||||
config_player2.glowing_entry = &Options::settings.glowing_entries.at(static_cast<int>(Player::Id::PLAYER2) - 1);
|
config_player2.glowing_entry = &Options::settings.glowing_entries.at(static_cast<int>(Player::Id::PLAYER2) - 1);
|
||||||
|
config_player2.stage_info = stage_manager_.get();
|
||||||
|
|
||||||
auto player2 = std::make_unique<Player>(config_player2);
|
auto player2 = std::make_unique<Player>(config_player2);
|
||||||
player2->setScoreBoardPanel(Scoreboard::Id::RIGHT);
|
player2->setScoreBoardPanel(Scoreboard::Id::RIGHT);
|
||||||
@@ -1720,7 +1698,7 @@ void Game::updateGameStateFadeIn() {
|
|||||||
if (fade_in_->hasEnded()) {
|
if (fade_in_->hasEnded()) {
|
||||||
setState(State::ENTERING_PLAYER);
|
setState(State::ENTERING_PLAYER);
|
||||||
balloon_manager_->createTwoBigBalloons();
|
balloon_manager_->createTwoBigBalloons();
|
||||||
evaluateAndSetMenace();
|
setMenace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1755,7 +1733,7 @@ void Game::updateGameStateShowingGetReadyMessage() {
|
|||||||
void Game::updateGameStatePlaying() {
|
void Game::updateGameStatePlaying() {
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
if (auto_pop_balloons_) {
|
if (auto_pop_balloons_) {
|
||||||
Stage::addPower(5);
|
stage_manager_->addPower(5);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
updatePlayers();
|
updatePlayers();
|
||||||
@@ -1789,25 +1767,31 @@ void Game::cleanVectors() {
|
|||||||
|
|
||||||
// Gestiona el nivel de amenaza
|
// Gestiona el nivel de amenaza
|
||||||
void Game::updateMenace() {
|
void Game::updateMenace() {
|
||||||
if (state_ == State::PLAYING) {
|
if (state_ != State::PLAYING) {
|
||||||
const auto STAGE = Stage::get(Stage::number);
|
return;
|
||||||
const float PERCENT = Stage::power / STAGE.power_to_complete;
|
}
|
||||||
const int DIFFERENCE = STAGE.max_menace - STAGE.min_menace;
|
|
||||||
|
|
||||||
// Aumenta el nivel de amenaza en función de la puntuación
|
auto current_stage = stage_manager_->getCurrentStage();
|
||||||
menace_threshold_ = STAGE.min_menace + (DIFFERENCE * PERCENT);
|
if (!current_stage.has_value()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Si el nivel de amenza es inferior al umbral
|
const auto &stage = current_stage.value();
|
||||||
if (menace_current_ < menace_threshold_) {
|
const double fraction = stage_manager_->getCurrentStageProgressFraction();
|
||||||
balloon_manager_->deployRandomFormation(Stage::number); // Crea una formación aleatoria de globos
|
const int difference = stage.getMaxMenace() - stage.getMinMenace();
|
||||||
evaluateAndSetMenace(); // Recalcula el nivel de amenaza con el nuevo globo
|
|
||||||
}
|
// Aumenta el nivel de amenaza en función del progreso de la fase
|
||||||
|
menace_threshold_ = stage.getMinMenace() + (difference * fraction);
|
||||||
|
|
||||||
|
if (menace_ < menace_threshold_) {
|
||||||
|
balloon_manager_->deployRandomFormation(stage_manager_->getCurrentStageIndex());
|
||||||
|
setMenace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calcula y establece el valor de amenaza en funcion de los globos activos
|
// Calcula y establece el valor de amenaza en funcion de los globos activos
|
||||||
void Game::evaluateAndSetMenace() {
|
void Game::setMenace() {
|
||||||
menace_current_ = balloon_manager_->getMenace();
|
menace_ = balloon_manager_->getMenace();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
|
// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
|
||||||
@@ -1816,7 +1800,7 @@ void Game::checkAndUpdateBalloonSpeed() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float PERCENT = static_cast<float>(Stage::power) / Stage::get(Stage::number).power_to_complete;
|
const float PERCENT = stage_manager_->getCurrentStageProgressFraction();
|
||||||
constexpr std::array<float, 4> THRESHOLDS = {0.2F, 0.4F, 0.6F, 0.8F};
|
constexpr std::array<float, 4> THRESHOLDS = {0.2F, 0.4F, 0.6F, 0.8F};
|
||||||
|
|
||||||
for (size_t i = 0; i < std::size(THRESHOLDS); ++i) {
|
for (size_t i = 0; i < std::size(THRESHOLDS); ++i) {
|
||||||
@@ -1890,14 +1874,13 @@ void Game::onPauseStateChanged(bool is_paused) {
|
|||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
// Comprueba los eventos en el modo DEBUG
|
// Comprueba los eventos en el modo DEBUG
|
||||||
void Game::checkDebugEvents(const SDL_Event &event) {
|
void Game::handleDebugEvents(const SDL_Event &event) {
|
||||||
static int formation_id_ = 0;
|
static int formation_id_ = 0;
|
||||||
if (event.type == SDL_EVENT_KEY_DOWN && static_cast<int>(event.key.repeat) == 0) {
|
if (event.type == SDL_EVENT_KEY_DOWN && static_cast<int>(event.key.repeat) == 0) {
|
||||||
switch (event.key.key) {
|
switch (event.key.key) {
|
||||||
case SDLK_1: // Crea una powerball
|
case SDLK_1: // Crea una powerball
|
||||||
{
|
{
|
||||||
// balloon_manager_->createPowerBall();
|
balloon_manager_->createPowerBall();
|
||||||
// throwCoffee(players_.at(0)->getPosX() + (players_.at(0)->getWidth() / 2), players_.at(0)->getPosY() + (players_.at(0)->getHeight() / 2));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SDLK_2: // Activa o desactiva la aparición de globos
|
case SDLK_2: // Activa o desactiva la aparición de globos
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "path_sprite.h" // Para PathSprite, Path
|
#include "path_sprite.h" // Para PathSprite, Path
|
||||||
#include "player.h" // Para Player
|
#include "player.h" // Para Player
|
||||||
#include "smart_sprite.h" // Para SmartSprite
|
#include "smart_sprite.h" // Para SmartSprite
|
||||||
|
#include "stage.h" // Para StageManager
|
||||||
#include "utils.h" // Para Demo
|
#include "utils.h" // Para Demo
|
||||||
|
|
||||||
class Background;
|
class Background;
|
||||||
@@ -100,8 +101,6 @@ class Game {
|
|||||||
Input *input_; // Manejador de entrada
|
Input *input_; // Manejador de entrada
|
||||||
Scoreboard *scoreboard_; // Objeto para dibujar el marcador
|
Scoreboard *scoreboard_; // Objeto para dibujar el marcador
|
||||||
|
|
||||||
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
|
|
||||||
|
|
||||||
SDL_Texture *canvas_; // Textura para dibujar la zona de juego
|
SDL_Texture *canvas_; // Textura para dibujar la zona de juego
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
|
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
|
||||||
@@ -119,9 +118,11 @@ class Game {
|
|||||||
std::vector<std::vector<std::string>> player_animations_; // Vector con las animaciones del jugador
|
std::vector<std::vector<std::string>> player_animations_; // Vector con las animaciones del jugador
|
||||||
|
|
||||||
std::unique_ptr<PauseManager> pause_manager_; // Objeto para gestionar la pausa
|
std::unique_ptr<PauseManager> pause_manager_; // Objeto para gestionar la pausa
|
||||||
|
std::unique_ptr<StageManager> stage_manager_; // Objeto para gestionar las fases
|
||||||
|
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
|
||||||
|
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
|
||||||
std::unique_ptr<Fade> fade_in_; // Objeto para renderizar fades
|
std::unique_ptr<Fade> fade_in_; // Objeto para renderizar fades
|
||||||
std::unique_ptr<Fade> fade_out_; // Objeto para renderizar fades
|
std::unique_ptr<Fade> fade_out_; // Objeto para renderizar fades
|
||||||
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
|
|
||||||
std::unique_ptr<Tabe> tabe_; // Objeto para gestionar el Tabe Volaor
|
std::unique_ptr<Tabe> tabe_; // Objeto para gestionar el Tabe Volaor
|
||||||
std::vector<Path> paths_; // Vector con los recorridos precalculados almacenados
|
std::vector<Path> paths_; // Vector con los recorridos precalculados almacenados
|
||||||
|
|
||||||
@@ -141,8 +142,7 @@ class Game {
|
|||||||
int game_completed_counter_ = 0; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más globos
|
int game_completed_counter_ = 0; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más globos
|
||||||
int game_over_counter_ = GAME_OVER_COUNTER; // Contador para el estado de fin de partida
|
int game_over_counter_ = GAME_OVER_COUNTER; // Contador para el estado de fin de partida
|
||||||
int time_stopped_counter_ = 0; // Temporizador para llevar la cuenta del tiempo detenido
|
int time_stopped_counter_ = 0; // Temporizador para llevar la cuenta del tiempo detenido
|
||||||
int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
|
int menace_ = 0; // Nivel de amenaza actual
|
||||||
int menace_current_ = 0; // Nivel de amenaza actual
|
|
||||||
int menace_threshold_ = 0; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos
|
int menace_threshold_ = 0; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos
|
||||||
State state_ = State::FADE_IN; // Estado
|
State state_ = State::FADE_IN; // Estado
|
||||||
std::vector<std::shared_ptr<Player>> players_to_put_at_back_;
|
std::vector<std::shared_ptr<Player>> players_to_put_at_back_;
|
||||||
@@ -156,7 +156,7 @@ class Game {
|
|||||||
// --- Ciclo principal del juego ---
|
// --- Ciclo principal del juego ---
|
||||||
void update(); // Actualiza la lógica principal del juego
|
void update(); // Actualiza la lógica principal del juego
|
||||||
void render(); // Renderiza todos los elementos del juego
|
void render(); // Renderiza todos los elementos del juego
|
||||||
void checkEvents(); // Procesa los eventos del sistema en cola
|
void handleEvents(); // Procesa los eventos del sistema en cola
|
||||||
void checkState(); // Verifica y actualiza el estado actual del juego
|
void checkState(); // Verifica y actualiza el estado actual del juego
|
||||||
void setState(State state); // Cambia el estado del juego
|
void setState(State state); // Cambia el estado del juego
|
||||||
void cleanVectors(); // Limpia vectores de elementos deshabilitados
|
void cleanVectors(); // Limpia vectores de elementos deshabilitados
|
||||||
@@ -263,8 +263,8 @@ class Game {
|
|||||||
void initDifficultyVars(); // Inicializa variables de dificultad
|
void initDifficultyVars(); // Inicializa variables de dificultad
|
||||||
|
|
||||||
// --- Sistema de amenaza ---
|
// --- Sistema de amenaza ---
|
||||||
void updateMenace(); // Gestiona el nivel de amenaza del juego
|
void updateMenace(); // Gestiona el nivel de amenaza del juego
|
||||||
void evaluateAndSetMenace(); // Calcula y establece amenaza según globos activos
|
void setMenace(); // Calcula y establece amenaza según globos activos
|
||||||
|
|
||||||
// --- Puntuación y marcador ---
|
// --- Puntuación y marcador ---
|
||||||
void updateHiScore(); // Actualiza el récord máximo si es necesario
|
void updateHiScore(); // Actualiza el récord máximo si es necesario
|
||||||
@@ -300,6 +300,6 @@ class Game {
|
|||||||
|
|
||||||
// --- Depuración (solo en modo DEBUG) ---
|
// --- Depuración (solo en modo DEBUG) ---
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
void checkDebugEvents(const SDL_Event &event); // Comprueba los eventos en el modo DEBUG
|
void handleDebugEvents(const SDL_Event &event); // Comprueba los eventos en el modo DEBUG
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -108,7 +108,7 @@ void HiScoreTable::fillTexture() {
|
|||||||
void HiScoreTable::checkEvents() {
|
void HiScoreTable::checkEvents() {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
GlobalEvents::check(event);
|
GlobalEvents::handle(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ void Instructions::render() {
|
|||||||
void Instructions::checkEvents() {
|
void Instructions::checkEvents() {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
GlobalEvents::check(event);
|
GlobalEvents::handle(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ Intro::Intro()
|
|||||||
void Intro::checkEvents() {
|
void Intro::checkEvents() {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
GlobalEvents::check(event);
|
GlobalEvents::handle(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ void Intro::updateScene5() {
|
|||||||
|
|
||||||
// Acaba la ultima imagen
|
// Acaba la ultima imagen
|
||||||
if (card_sprites_.at(5)->hasFinished() && texts_.at(8)->hasFinished()) {
|
if (card_sprites_.at(5)->hasFinished() && texts_.at(8)->hasFinished()) {
|
||||||
state_ = IntroState::POST;
|
state_ = State::POST;
|
||||||
state_start_time_ = SDL_GetTicks();
|
state_start_time_ = SDL_GetTicks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,13 +215,13 @@ void Intro::update() {
|
|||||||
tiled_bg_->update(); // Actualiza el fondo
|
tiled_bg_->update(); // Actualiza el fondo
|
||||||
|
|
||||||
switch (state_) {
|
switch (state_) {
|
||||||
case IntroState::SCENES:
|
case State::SCENES:
|
||||||
updateSprites();
|
updateSprites();
|
||||||
updateTexts();
|
updateTexts();
|
||||||
updateScenes();
|
updateScenes();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IntroState::POST:
|
case State::POST:
|
||||||
updatePostState();
|
updatePostState();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -240,13 +240,13 @@ void Intro::render() {
|
|||||||
tiled_bg_->render(); // Dibuja el fondo
|
tiled_bg_->render(); // Dibuja el fondo
|
||||||
|
|
||||||
switch (state_) {
|
switch (state_) {
|
||||||
case IntroState::SCENES: {
|
case State::SCENES: {
|
||||||
renderTextRect();
|
renderTextRect();
|
||||||
renderSprites();
|
renderSprites();
|
||||||
renderTexts();
|
renderTexts();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IntroState::POST:
|
case State::POST:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -479,7 +479,7 @@ void Intro::updatePostState() {
|
|||||||
const Uint32 ELAPSED_TIME = SDL_GetTicks() - state_start_time_;
|
const Uint32 ELAPSED_TIME = SDL_GetTicks() - state_start_time_;
|
||||||
|
|
||||||
switch (post_state_) {
|
switch (post_state_) {
|
||||||
case IntroPostState::STOP_BG:
|
case PostState::STOP_BG:
|
||||||
// EVENTO: Detiene el fondo después de 1 segundo
|
// EVENTO: Detiene el fondo después de 1 segundo
|
||||||
if (ELAPSED_TIME >= 1000) {
|
if (ELAPSED_TIME >= 1000) {
|
||||||
tiled_bg_->stopGracefully();
|
tiled_bg_->stopGracefully();
|
||||||
@@ -493,12 +493,12 @@ void Intro::updatePostState() {
|
|||||||
|
|
||||||
// Cambia de estado si el fondo se ha detenido y recuperado el color
|
// Cambia de estado si el fondo se ha detenido y recuperado el color
|
||||||
if (tiled_bg_->isStopped() && bg_color_.IS_EQUAL_TO(param.title.bg_color)) {
|
if (tiled_bg_->isStopped() && bg_color_.IS_EQUAL_TO(param.title.bg_color)) {
|
||||||
post_state_ = IntroPostState::END;
|
post_state_ = PostState::END;
|
||||||
state_start_time_ = SDL_GetTicks();
|
state_start_time_ = SDL_GetTicks();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IntroPostState::END:
|
case PostState::END:
|
||||||
// Finaliza la intro después de 1 segundo
|
// Finaliza la intro después de 1 segundo
|
||||||
if (ELAPSED_TIME >= 1000) {
|
if (ELAPSED_TIME >= 1000) {
|
||||||
Audio::get()->stopMusic();
|
Audio::get()->stopMusic();
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ class Intro {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Estados internos ---
|
// --- Estados internos ---
|
||||||
enum class IntroState {
|
enum class State {
|
||||||
SCENES,
|
SCENES,
|
||||||
POST,
|
POST,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class IntroPostState {
|
enum class PostState {
|
||||||
STOP_BG,
|
STOP_BG,
|
||||||
END,
|
END,
|
||||||
};
|
};
|
||||||
@@ -43,15 +43,14 @@ class Intro {
|
|||||||
std::vector<std::unique_ptr<PathSprite>> shadow_sprites_; // Vector con los sprites inteligentes para las sombras
|
std::vector<std::unique_ptr<PathSprite>> shadow_sprites_; // Vector con los sprites inteligentes para las sombras
|
||||||
std::vector<std::unique_ptr<Writer>> texts_; // Textos de la intro
|
std::vector<std::unique_ptr<Writer>> texts_; // Textos de la intro
|
||||||
std::unique_ptr<TiledBG> tiled_bg_; // Fondo en mosaico
|
std::unique_ptr<TiledBG> tiled_bg_; // Fondo en mosaico
|
||||||
// std::unique_ptr<Sprite> shadow_square_for_text_; // Sprite
|
|
||||||
|
|
||||||
// --- Variables ---
|
// --- Variables ---
|
||||||
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
||||||
int scene_ = 0; // Indica qué escena está activa
|
int scene_ = 0; // Indica qué escena está activa
|
||||||
IntroState state_ = IntroState::SCENES; // Estado principal de la intro
|
State state_ = State::SCENES; // Estado principal de la intro
|
||||||
IntroPostState post_state_ = IntroPostState::STOP_BG; // Estado POST
|
PostState post_state_ = PostState::STOP_BG; // Estado POST
|
||||||
Uint32 state_start_time_; // Tiempo de inicio del estado actual
|
Uint32 state_start_time_; // Tiempo de inicio del estado actual
|
||||||
Color bg_color_ = param.intro.bg_color; // Color de fondo
|
Color bg_color_ = param.intro.bg_color; // Color de fondo
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void update(); // Actualiza las variables del objeto
|
void update(); // Actualiza las variables del objeto
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ Logo::~Logo() {
|
|||||||
void Logo::checkEvents() {
|
void Logo::checkEvents() {
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event)) {
|
while (SDL_PollEvent(&event)) {
|
||||||
GlobalEvents::check(event);
|
GlobalEvents::handle(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ void Title::checkEvents() {
|
|||||||
handleKeyDownEvent(event);
|
handleKeyDownEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalEvents::check(event);
|
GlobalEvents::handle(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
329
source/stage.cpp
@@ -1,43 +1,300 @@
|
|||||||
#include "stage.h"
|
#include "stage.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include <algorithm> // Para min
|
// Implementación de StageData
|
||||||
#include <vector> // Para vector
|
StageData::StageData(int power_to_complete, int min_menace, int max_menace, const std::string& name)
|
||||||
|
: power_to_complete_(power_to_complete), min_menace_(min_menace),
|
||||||
|
max_menace_(max_menace), name_(name), status_(StageStatus::LOCKED) {}
|
||||||
|
|
||||||
namespace Stage {
|
// Implementación de StageManager
|
||||||
|
StageManager::StageManager()
|
||||||
std::vector<Stage> stages; // Variable con los datos de cada pantalla
|
: current_power_(0), total_power_(0), current_stage_index_(0),
|
||||||
int power = 0; // Poder acumulado en la fase
|
power_collection_state_(PowerCollectionState::ENABLED),
|
||||||
int total_power = 0; // Poder total necesario para completar el juego
|
power_change_callback_(nullptr) {
|
||||||
int number = 0; // Fase actual
|
initialize();
|
||||||
bool power_can_be_added = true; // Habilita la recolecta de poder
|
|
||||||
|
|
||||||
// Devuelve una fase
|
|
||||||
auto get(int index) -> Stage { return stages.at(std::min(9, index)); }
|
|
||||||
|
|
||||||
// Inicializa las variables del namespace Stage
|
|
||||||
void init() {
|
|
||||||
stages.clear();
|
|
||||||
stages.emplace_back(200, 7 + (4 * 1), 7 + (4 * 3));
|
|
||||||
stages.emplace_back(300, 7 + (4 * 2), 7 + (4 * 4));
|
|
||||||
stages.emplace_back(600, 7 + (4 * 3), 7 + (4 * 5));
|
|
||||||
stages.emplace_back(600, 7 + (4 * 3), 7 + (4 * 5));
|
|
||||||
stages.emplace_back(600, 7 + (4 * 4), 7 + (4 * 6));
|
|
||||||
stages.emplace_back(600, 7 + (4 * 4), 7 + (4 * 6));
|
|
||||||
stages.emplace_back(650, 7 + (4 * 5), 7 + (4 * 7));
|
|
||||||
stages.emplace_back(750, 7 + (4 * 5), 7 + (4 * 7));
|
|
||||||
stages.emplace_back(850, 7 + (4 * 6), 7 + (4 * 8));
|
|
||||||
stages.emplace_back(950, 7 + (4 * 7), 7 + (4 * 10));
|
|
||||||
|
|
||||||
power = 0;
|
|
||||||
total_power = 0;
|
|
||||||
number = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Añade poder
|
void StageManager::initialize() {
|
||||||
void addPower(int amount) {
|
stages_.clear();
|
||||||
if (power_can_be_added) {
|
createDefaultStages();
|
||||||
power += amount;
|
reset();
|
||||||
total_power += amount;
|
}
|
||||||
|
|
||||||
|
void StageManager::initialize(const std::string& stages_file) {
|
||||||
|
stages_.clear();
|
||||||
|
|
||||||
|
// Intentar cargar desde archivo, si falla usar valores predeterminados
|
||||||
|
if (!loadStagesFromFile(stages_file)) {
|
||||||
|
createDefaultStages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset();
|
||||||
}
|
}
|
||||||
} // namespace Stage
|
|
||||||
|
void StageManager::reset() {
|
||||||
|
current_power_ = 0;
|
||||||
|
total_power_ = 0;
|
||||||
|
current_stage_index_ = 0;
|
||||||
|
power_collection_state_ = PowerCollectionState::ENABLED;
|
||||||
|
updateStageStatuses();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StageManager::createDefaultStages() {
|
||||||
|
// Crear las 10 fases predeterminadas con dificultad progresiva
|
||||||
|
stages_.emplace_back(200, 7 + (4 * 1), 7 + (4 * 3), "Tutorial");
|
||||||
|
stages_.emplace_back(300, 7 + (4 * 2), 7 + (4 * 4), "Primeros pasos");
|
||||||
|
stages_.emplace_back(600, 7 + (4 * 3), 7 + (4 * 5), "Intensificación");
|
||||||
|
stages_.emplace_back(600, 7 + (4 * 3), 7 + (4 * 5), "Persistencia");
|
||||||
|
stages_.emplace_back(600, 7 + (4 * 4), 7 + (4 * 6), "Desafío medio");
|
||||||
|
stages_.emplace_back(600, 7 + (4 * 4), 7 + (4 * 6), "Resistencia");
|
||||||
|
stages_.emplace_back(650, 7 + (4 * 5), 7 + (4 * 7), "Aproximación final");
|
||||||
|
stages_.emplace_back(750, 7 + (4 * 5), 7 + (4 * 7), "Penúltimo obstáculo");
|
||||||
|
stages_.emplace_back(850, 7 + (4 * 6), 7 + (4 * 8), "Clímax");
|
||||||
|
stages_.emplace_back(950, 7 + (4 * 7), 7 + (4 * 10), "Maestría");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StageManager::loadStagesFromFile(const std::string& filename) {
|
||||||
|
std::ifstream file(filename);
|
||||||
|
if (!file.is_open()) {
|
||||||
|
return false; // No se pudo abrir el archivo
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
// Ignorar líneas vacías y comentarios (líneas que empiezan con #)
|
||||||
|
if (line.empty() || line[0] == '#') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parsear línea: power_to_complete,min_menace,max_menace,name
|
||||||
|
std::stringstream ss(line);
|
||||||
|
std::string token;
|
||||||
|
std::vector<std::string> tokens;
|
||||||
|
|
||||||
|
// Dividir por comas
|
||||||
|
while (std::getline(ss, token, ',')) {
|
||||||
|
// Eliminar espacios en blanco al inicio y final
|
||||||
|
token.erase(0, token.find_first_not_of(" \t"));
|
||||||
|
token.erase(token.find_last_not_of(" \t") + 1);
|
||||||
|
tokens.push_back(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verificar que tenemos exactamente 4 campos
|
||||||
|
if (tokens.size() != 4) {
|
||||||
|
// Error de formato, continuar con la siguiente línea
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Convertir a enteros los primeros tres campos
|
||||||
|
int power_to_complete = std::stoi(tokens[0]);
|
||||||
|
int min_menace = std::stoi(tokens[1]);
|
||||||
|
int max_menace = std::stoi(tokens[2]);
|
||||||
|
std::string name = tokens[3];
|
||||||
|
|
||||||
|
// Validar valores
|
||||||
|
if (power_to_complete <= 0 || min_menace < 0 || max_menace < min_menace) {
|
||||||
|
continue; // Valores inválidos, saltar línea
|
||||||
|
}
|
||||||
|
|
||||||
|
// Crear y añadir la fase
|
||||||
|
stages_.emplace_back(power_to_complete, min_menace, max_menace, name);
|
||||||
|
|
||||||
|
} catch (const std::exception&) {
|
||||||
|
// Error de conversión, continuar con la siguiente línea
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
// Verificar que se cargó al menos una fase
|
||||||
|
return !stages_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StageManager::advanceToNextStage() {
|
||||||
|
if (!isCurrentStageCompleted() || current_stage_index_ >= stages_.size() - 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_stage_index_++;
|
||||||
|
current_power_ = 0; // Reiniciar poder para la nueva fase
|
||||||
|
updateStageStatuses();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StageManager::jumpToStage(size_t target_stage_index) {
|
||||||
|
if (!validateStageIndex(target_stage_index)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcular el poder acumulado hasta la fase objetivo
|
||||||
|
int accumulated_power = 0;
|
||||||
|
for (size_t i = 0; i < target_stage_index; ++i) {
|
||||||
|
accumulated_power += stages_[i].getPowerToComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualizar estado
|
||||||
|
current_stage_index_ = target_stage_index;
|
||||||
|
current_power_ = 0; // Comenzar la fase objetivo sin poder
|
||||||
|
total_power_ = accumulated_power; // Poder total como si se hubieran completado las anteriores
|
||||||
|
|
||||||
|
updateStageStatuses();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StageManager::subtractPower(int amount) {
|
||||||
|
if (amount <= 0 || current_power_ < amount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_power_ -= amount;
|
||||||
|
updateStageStatuses();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StageManager::enablePowerCollection() {
|
||||||
|
power_collection_state_ = PowerCollectionState::ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StageManager::disablePowerCollection() {
|
||||||
|
power_collection_state_ = PowerCollectionState::DISABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<StageData> StageManager::getCurrentStage() const {
|
||||||
|
return getStage(current_stage_index_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<StageData> StageManager::getStage(size_t index) const {
|
||||||
|
if (!validateStageIndex(index)) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return stages_[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StageManager::isCurrentStageCompleted() const {
|
||||||
|
auto current_stage = getCurrentStage();
|
||||||
|
if (!current_stage.has_value()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return current_power_ >= current_stage->getPowerToComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StageManager::isGameCompleted() const {
|
||||||
|
return current_stage_index_ >= stages_.size() - 1 && isCurrentStageCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
double StageManager::getProgressPercentage() const {
|
||||||
|
if (stages_.empty()) return 0.0;
|
||||||
|
|
||||||
|
int total_power_needed = getTotalPowerNeededToCompleteGame();
|
||||||
|
if (total_power_needed == 0) return 100.0;
|
||||||
|
|
||||||
|
return (static_cast<double>(total_power_) / total_power_needed) * 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double StageManager::getCurrentStageProgressPercentage() const {
|
||||||
|
return getCurrentStageProgressFraction() * 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double StageManager::getCurrentStageProgressFraction() const {
|
||||||
|
auto current_stage = getCurrentStage();
|
||||||
|
if (!current_stage.has_value()) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int power_needed = current_stage->getPowerToComplete();
|
||||||
|
if (power_needed == 0) {
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Devuelve una fracción entre 0.0 y 1.0
|
||||||
|
double fraction = static_cast<double>(current_power_) / power_needed;
|
||||||
|
return std::min(fraction, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StageManager::getPowerNeededForCurrentStage() const {
|
||||||
|
auto current_stage = getCurrentStage();
|
||||||
|
if (!current_stage.has_value()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::max(0, current_stage->getPowerToComplete() - current_power_);
|
||||||
|
}
|
||||||
|
|
||||||
|
int StageManager::getTotalPowerNeededToCompleteGame() const {
|
||||||
|
int total_power_needed = 0;
|
||||||
|
for (const auto& stage : stages_) {
|
||||||
|
total_power_needed += stage.getPowerToComplete();
|
||||||
|
}
|
||||||
|
return total_power_needed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implementación de la interfaz IStageInfo
|
||||||
|
bool StageManager::canCollectPower() const {
|
||||||
|
return power_collection_state_ == PowerCollectionState::ENABLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StageManager::addPower(int amount) {
|
||||||
|
if (amount <= 0 || !canCollectPower()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_power_ += amount;
|
||||||
|
total_power_ += amount;
|
||||||
|
|
||||||
|
// Ejecutar callback si está registrado
|
||||||
|
if (power_change_callback_) {
|
||||||
|
power_change_callback_(amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verificar si se completó la fase actual
|
||||||
|
if (isCurrentStageCompleted()) {
|
||||||
|
auto current_stage = getCurrentStage();
|
||||||
|
if (current_stage.has_value()) {
|
||||||
|
stages_[current_stage_index_].setStatus(StageStatus::COMPLETED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateStageStatuses();
|
||||||
|
}
|
||||||
|
|
||||||
|
int StageManager::getCurrentMenaceLevel() const {
|
||||||
|
auto current_stage = getCurrentStage();
|
||||||
|
if (!current_stage.has_value()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return current_stage->getMinMenace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gestión de callbacks
|
||||||
|
void StageManager::setPowerChangeCallback(PowerChangeCallback callback) {
|
||||||
|
power_change_callback_ = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StageManager::removePowerChangeCallback() {
|
||||||
|
power_change_callback_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Métodos privados
|
||||||
|
bool StageManager::validateStageIndex(size_t index) const {
|
||||||
|
return index < stages_.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StageManager::updateStageStatuses() {
|
||||||
|
// Actualizar el estado de cada fase según su posición relativa a la actual
|
||||||
|
for (size_t i = 0; i < stages_.size(); ++i) {
|
||||||
|
if (i < current_stage_index_) {
|
||||||
|
stages_[i].setStatus(StageStatus::COMPLETED);
|
||||||
|
} else if (i == current_stage_index_) {
|
||||||
|
stages_[i].setStatus(StageStatus::IN_PROGRESS);
|
||||||
|
} else {
|
||||||
|
stages_[i].setStatus(StageStatus::LOCKED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
132
source/stage.h
@@ -1,33 +1,111 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector> // Para vector
|
#include "stage_interface.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
/*
|
// --- Estados posibles para la recolección de poder ---
|
||||||
Namespace Stage: gestiona los datos y operaciones de las fases del juego.
|
enum class PowerCollectionState {
|
||||||
Permite consultar y modificar el poder necesario, la amenaza y el estado de cada fase.
|
ENABLED, // Recolección habilitada
|
||||||
*/
|
DISABLED // Recolección deshabilitada
|
||||||
|
|
||||||
namespace Stage {
|
|
||||||
// --- Estructura con los datos de una fase ---
|
|
||||||
struct Stage {
|
|
||||||
int power_to_complete; // Cantidad de poder que se necesita para completar la fase
|
|
||||||
int min_menace; // Umbral mínimo de amenaza de la fase
|
|
||||||
int max_menace; // Umbral máximo de amenaza de la fase
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
Stage(int power_to_complete, int min_menace, int max_menace)
|
|
||||||
: power_to_complete(power_to_complete), min_menace(min_menace), max_menace(max_menace) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Variables globales del estado de las fases ---
|
// --- Estados posibles para una fase del juego ---
|
||||||
extern std::vector<Stage> stages; // Vector con los datos de cada pantalla
|
enum class StageStatus {
|
||||||
extern int power; // Poder acumulado en la fase actual
|
LOCKED, // Fase bloqueada
|
||||||
extern int total_power; // Poder total necesario para completar el juego
|
IN_PROGRESS, // Fase en progreso
|
||||||
extern int number; // Índice de la fase actual
|
COMPLETED // Fase completada
|
||||||
extern bool power_can_be_added; // Indica si se puede añadir poder a la fase
|
};
|
||||||
|
|
||||||
// --- Funciones principales ---
|
// --- Representa los datos de una fase del juego ---
|
||||||
auto get(int index) -> Stage; // Devuelve una fase por índice
|
class StageData {
|
||||||
void init(); // Inicializa las variables del namespace Stage
|
private:
|
||||||
void addPower(int amount); // Añade poder a la fase actual
|
int power_to_complete_; // Poder necesario para completar la fase
|
||||||
} // namespace Stage
|
int min_menace_; // Nivel mínimo de amenaza
|
||||||
|
int max_menace_; // Nivel máximo de amenaza
|
||||||
|
std::string name_; // Nombre de la fase
|
||||||
|
StageStatus status_; // Estado actual de la fase
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructor de una fase
|
||||||
|
StageData(int power_to_complete, int min_menace, int max_menace, const std::string& name = "");
|
||||||
|
|
||||||
|
// --- Getters ---
|
||||||
|
int getPowerToComplete() const { return power_to_complete_; }
|
||||||
|
int getMinMenace() const { return min_menace_; }
|
||||||
|
int getMaxMenace() const { return max_menace_; }
|
||||||
|
const std::string& getName() const { return name_; }
|
||||||
|
StageStatus getStatus() const { return status_; }
|
||||||
|
|
||||||
|
// --- Setters ---
|
||||||
|
void setStatus(StageStatus status) { status_ = status; }
|
||||||
|
|
||||||
|
// --- Utilidades ---
|
||||||
|
bool isCompleted() const { return status_ == StageStatus::COMPLETED; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Gestor principal del sistema de fases del juego ---
|
||||||
|
class StageManager : public IStageInfo {
|
||||||
|
private:
|
||||||
|
std::vector<StageData> stages_; // Lista de todas las fases
|
||||||
|
int current_power_; // Poder actual en la fase activa
|
||||||
|
int total_power_; // Poder total acumulado en todo el juego
|
||||||
|
size_t current_stage_index_; // Índice de la fase actual
|
||||||
|
PowerCollectionState power_collection_state_; // Estado de recolección de poder
|
||||||
|
|
||||||
|
public:
|
||||||
|
using PowerChangeCallback = std::function<void(int)>;
|
||||||
|
|
||||||
|
StageManager();
|
||||||
|
|
||||||
|
// --- Métodos principales del juego ---
|
||||||
|
void initialize(); // Inicializa el gestor de fases
|
||||||
|
void initialize(const std::string& stages_file); // Inicializa con archivo personalizado
|
||||||
|
void reset(); // Reinicia el progreso del juego
|
||||||
|
bool advanceToNextStage(); // Avanza a la siguiente fase
|
||||||
|
|
||||||
|
// --- Gestión de poder ---
|
||||||
|
bool subtractPower(int amount); // Resta poder de la fase actual
|
||||||
|
void enablePowerCollection(); // Habilita la recolección de poder
|
||||||
|
void disablePowerCollection(); // Deshabilita la recolección de poder
|
||||||
|
|
||||||
|
// --- Navegación ---
|
||||||
|
bool jumpToStage(size_t target_stage_index); // Salta a una fase específica
|
||||||
|
|
||||||
|
// --- Consultas de estado ---
|
||||||
|
std::optional<StageData> getCurrentStage() const; // Obtiene la fase actual
|
||||||
|
std::optional<StageData> getStage(size_t index) const; // Obtiene una fase específica
|
||||||
|
size_t getCurrentStageIndex() const { return current_stage_index_; }
|
||||||
|
int getCurrentPower() const { return current_power_; }
|
||||||
|
int getTotalPower() const { return total_power_; }
|
||||||
|
int getTotalPowerNeededToCompleteGame() const; // Poder total necesario para completar el juego
|
||||||
|
size_t getTotalStages() const { return stages_.size(); }
|
||||||
|
|
||||||
|
// --- Seguimiento de progreso ---
|
||||||
|
bool isCurrentStageCompleted() const; // Verifica si la fase actual está completada
|
||||||
|
bool isGameCompleted() const; // Verifica si el juego está completado
|
||||||
|
double getProgressPercentage() const; // Progreso total del juego (0-100%)
|
||||||
|
double getCurrentStageProgressPercentage() const; // Progreso de la fase actual (0-100%)
|
||||||
|
double getCurrentStageProgressFraction() const; // Progreso de la fase actual (0.0-1.0)
|
||||||
|
int getPowerNeededForCurrentStage() const; // Poder restante para completar la fase actual
|
||||||
|
|
||||||
|
// --- Gestión de callbacks ---
|
||||||
|
void setPowerChangeCallback(PowerChangeCallback callback); // Establece callback para cambios de poder
|
||||||
|
void removePowerChangeCallback(); // Elimina callback de cambios de poder
|
||||||
|
|
||||||
|
// --- Implementación de la interfaz IStageInfo ---
|
||||||
|
bool canCollectPower() const override;
|
||||||
|
void addPower(int amount) override;
|
||||||
|
int getCurrentMenaceLevel() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PowerChangeCallback power_change_callback_; // Callback para notificar cambios de poder
|
||||||
|
|
||||||
|
// --- Métodos privados ---
|
||||||
|
void createDefaultStages(); // Crea las fases predeterminadas del juego
|
||||||
|
bool loadStagesFromFile(const std::string& filename); // Carga fases desde archivo
|
||||||
|
bool validateStageIndex(size_t index) const; // Valida que un índice de fase sea válido
|
||||||
|
void updateStageStatuses(); // Actualiza los estados de todas las fases
|
||||||
|
};
|
||||||
18
source/stage_interface.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interfaz para acceso a información de fases.
|
||||||
|
* Proporciona una API mínima para componentes que necesitan interactuar con datos de fases
|
||||||
|
* sin requerir acceso a toda la funcionalidad de StageManager.
|
||||||
|
*/
|
||||||
|
class IStageInfo {
|
||||||
|
public:
|
||||||
|
virtual ~IStageInfo() = default;
|
||||||
|
|
||||||
|
// Interfaz de recolección de poder
|
||||||
|
virtual bool canCollectPower() const = 0;
|
||||||
|
virtual void addPower(int amount) = 0;
|
||||||
|
|
||||||
|
// Ajuste de comportamiento del gameplay
|
||||||
|
virtual int getCurrentMenaceLevel() const = 0;
|
||||||
|
};
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
// Constructor
|
// Constructor
|
||||||
Tabe::Tabe()
|
Tabe::Tabe()
|
||||||
: sprite_(std::make_unique<AnimatedSprite>(Resource::get()->getTexture("tabe.png"), Resource::get()->getAnimation("tabe.ani"))),
|
: sprite_(std::make_unique<AnimatedSprite>(Resource::get()->getTexture("tabe.png"), Resource::get()->getAnimation("tabe.ani"))),
|
||||||
timer_(Timer(2.5F, 4.0F)) {}
|
timer_(Timer(param.tabe.min_spawn_time, param.tabe.max_spawn_time)) {}
|
||||||
|
|
||||||
// Actualiza la lógica
|
// Actualiza la lógica
|
||||||
void Tabe::update() {
|
void Tabe::update() {
|
||||||
|
|||||||
@@ -73,8 +73,6 @@ auto Texture::loadFromFile(const std::string &file_path) -> bool {
|
|||||||
|
|
||||||
int pitch;
|
int pitch;
|
||||||
SDL_PixelFormat pixel_format;
|
SDL_PixelFormat pixel_format;
|
||||||
|
|
||||||
// STBI_rgb_alpha (RGBA)
|
|
||||||
pitch = 4 * width;
|
pitch = 4 * width;
|
||||||
pixel_format = SDL_PIXELFORMAT_RGBA32;
|
pixel_format = SDL_PIXELFORMAT_RGBA32;
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ class MenuRenderer {
|
|||||||
size_t max_menu_width_ = 0;
|
size_t max_menu_width_ = 0;
|
||||||
size_t max_menu_height_ = 0;
|
size_t max_menu_height_ = 0;
|
||||||
|
|
||||||
// --- Estructuras de Animación (inspirado en WindowMessage) ---
|
// --- Estructuras de Animación ---
|
||||||
struct ResizeAnimation {
|
struct ResizeAnimation {
|
||||||
bool active = false;
|
bool active = false;
|
||||||
float start_width, start_height;
|
float start_width, start_height;
|
||||||
|
|||||||
@@ -49,16 +49,14 @@ void Notifier::update() {
|
|||||||
if (!shouldProcessNotification(i)) {
|
if (!shouldProcessNotification(i)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
processNotification(i);
|
processNotification(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearFinishedNotifications();
|
clearFinishedNotifications();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Notifier::shouldProcessNotification(int index) const -> bool {
|
auto Notifier::shouldProcessNotification(int index) const -> bool {
|
||||||
// Si la notificación anterior está "saliendo", no hagas nada
|
// Si la notificación anterior está "saliendo", no hagas nada
|
||||||
return index <= 0 || notifications_[index - 1].state != NotificationStatus::RISING;
|
return index <= 0 || notifications_[index - 1].state != State::RISING;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notifier::processNotification(int index) {
|
void Notifier::processNotification(int index) {
|
||||||
@@ -74,7 +72,7 @@ void Notifier::playNotificationSoundIfNeeded(const Notification& notification) {
|
|||||||
// Hace sonar la notificación en el primer frame
|
// Hace sonar la notificación en el primer frame
|
||||||
if (notification.counter == 1 &&
|
if (notification.counter == 1 &&
|
||||||
param.notification.sound &&
|
param.notification.sound &&
|
||||||
notification.state == NotificationStatus::RISING) {
|
notification.state == State::RISING) {
|
||||||
Audio::get()->playSound("notify.wav", Audio::Group::INTERFACE);
|
Audio::get()->playSound("notify.wav", Audio::Group::INTERFACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,13 +81,13 @@ void Notifier::updateNotificationState(int index) {
|
|||||||
auto& notification = notifications_[index];
|
auto& notification = notifications_[index];
|
||||||
|
|
||||||
switch (notification.state) {
|
switch (notification.state) {
|
||||||
case NotificationStatus::RISING:
|
case State::RISING:
|
||||||
handleRisingState(index);
|
handleRisingState(index);
|
||||||
break;
|
break;
|
||||||
case NotificationStatus::STAY:
|
case State::STAY:
|
||||||
handleStayState(index);
|
handleStayState(index);
|
||||||
break;
|
break;
|
||||||
case NotificationStatus::VANISHING:
|
case State::VANISHING:
|
||||||
handleVanishingState(index);
|
handleVanishingState(index);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -103,7 +101,7 @@ void Notifier::handleRisingState(int index) {
|
|||||||
const float STEP = (float)notification.counter / notification.travel_dist;
|
const float STEP = (float)notification.counter / notification.travel_dist;
|
||||||
const int ALPHA = 255 * STEP;
|
const int ALPHA = 255 * STEP;
|
||||||
|
|
||||||
moveNotificationVertically(notification, param.notification.pos_v == NotifyPosition::TOP ? 1 : -1);
|
moveNotificationVertically(notification, param.notification.pos_v == Position::TOP ? 1 : -1);
|
||||||
notification.texture->setAlpha(ALPHA);
|
notification.texture->setAlpha(ALPHA);
|
||||||
|
|
||||||
if (notification.rect.y == notification.y) {
|
if (notification.rect.y == notification.y) {
|
||||||
@@ -115,7 +113,7 @@ void Notifier::handleStayState(int index) {
|
|||||||
auto& notification = notifications_[index];
|
auto& notification = notifications_[index];
|
||||||
|
|
||||||
if (notification.counter == wait_time_) {
|
if (notification.counter == wait_time_) {
|
||||||
notification.state = NotificationStatus::VANISHING;
|
notification.state = State::VANISHING;
|
||||||
notification.counter = 0;
|
notification.counter = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,11 +124,11 @@ void Notifier::handleVanishingState(int index) {
|
|||||||
const float STEP = notification.counter / (float)notification.travel_dist;
|
const float STEP = notification.counter / (float)notification.travel_dist;
|
||||||
const int ALPHA = 255 * (1 - STEP);
|
const int ALPHA = 255 * (1 - STEP);
|
||||||
|
|
||||||
moveNotificationVertically(notification, param.notification.pos_v == NotifyPosition::TOP ? -1 : 1);
|
moveNotificationVertically(notification, param.notification.pos_v == Position::TOP ? -1 : 1);
|
||||||
notification.texture->setAlpha(ALPHA);
|
notification.texture->setAlpha(ALPHA);
|
||||||
|
|
||||||
if (notification.rect.y == notification.y - notification.travel_dist) {
|
if (notification.rect.y == notification.y - notification.travel_dist) {
|
||||||
notification.state = NotificationStatus::FINISHED;
|
notification.state = State::FINISHED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +138,7 @@ void Notifier::moveNotificationVertically(Notification& notification, int direct
|
|||||||
|
|
||||||
void Notifier::transitionToStayState(int index) {
|
void Notifier::transitionToStayState(int index) {
|
||||||
auto& notification = notifications_[index];
|
auto& notification = notifications_[index];
|
||||||
notification.state = NotificationStatus::STAY;
|
notification.state = State::STAY;
|
||||||
notification.texture->setAlpha(255);
|
notification.texture->setAlpha(255);
|
||||||
notification.counter = 0;
|
notification.counter = 0;
|
||||||
}
|
}
|
||||||
@@ -148,7 +146,7 @@ void Notifier::transitionToStayState(int index) {
|
|||||||
// Elimina las notificaciones finalizadas
|
// Elimina las notificaciones finalizadas
|
||||||
void Notifier::clearFinishedNotifications() {
|
void Notifier::clearFinishedNotifications() {
|
||||||
for (int i = (int)notifications_.size() - 1; i >= 0; --i) {
|
for (int i = (int)notifications_.size() - 1; i >= 0; --i) {
|
||||||
if (notifications_[i].state == NotificationStatus::FINISHED) {
|
if (notifications_[i].state == State::FINISHED) {
|
||||||
notifications_.erase(notifications_.begin() + i);
|
notifications_.erase(notifications_.begin() + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,20 +183,20 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string&
|
|||||||
const int ICON_SPACE = icon >= 0 ? ICON_SIZE + PADDING_IN_H : 0;
|
const int ICON_SPACE = icon >= 0 ? ICON_SIZE + PADDING_IN_H : 0;
|
||||||
const float WIDTH = text_->length(longest) + (PADDING_IN_H * 2) + ICON_SPACE;
|
const float WIDTH = text_->length(longest) + (PADDING_IN_H * 2) + ICON_SPACE;
|
||||||
const float HEIGHT = (text_->getCharacterSize() * texts.size()) + (PADDING_IN_V * 2);
|
const float HEIGHT = (text_->getCharacterSize() * texts.size()) + (PADDING_IN_V * 2);
|
||||||
const auto SHAPE = NotificationShape::SQUARED;
|
const auto SHAPE = Shape::SQUARED;
|
||||||
|
|
||||||
// Posición horizontal
|
// Posición horizontal
|
||||||
float desp_h = 0;
|
float desp_h = 0;
|
||||||
switch (param.notification.pos_h) {
|
switch (param.notification.pos_h) {
|
||||||
case NotifyPosition::LEFT:
|
case Position::LEFT:
|
||||||
desp_h = PADDING_OUT;
|
desp_h = PADDING_OUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NotifyPosition::MIDDLE:
|
case Position::MIDDLE:
|
||||||
desp_h = ((param.game.width / 2) - (WIDTH / 2));
|
desp_h = ((param.game.width / 2) - (WIDTH / 2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NotifyPosition::RIGHT:
|
case Position::RIGHT:
|
||||||
desp_h = param.game.width - WIDTH - PADDING_OUT;
|
desp_h = param.game.width - WIDTH - PADDING_OUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -208,13 +206,13 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string&
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Posición vertical
|
// Posición vertical
|
||||||
const int DESP_V = (param.notification.pos_v == NotifyPosition::TOP) ? PADDING_OUT : (param.game.height - HEIGHT - PADDING_OUT);
|
const int DESP_V = (param.notification.pos_v == Position::TOP) ? PADDING_OUT : (param.game.height - HEIGHT - PADDING_OUT);
|
||||||
|
|
||||||
// Offset
|
// Offset
|
||||||
const auto TRAVEL_DIST = HEIGHT + PADDING_OUT;
|
const auto TRAVEL_DIST = HEIGHT + PADDING_OUT;
|
||||||
auto offset = notifications_.empty()
|
auto offset = notifications_.empty()
|
||||||
? DESP_V
|
? DESP_V
|
||||||
: notifications_.back().y + (param.notification.pos_v == NotifyPosition::TOP ? TRAVEL_DIST : -TRAVEL_DIST);
|
: notifications_.back().y + (param.notification.pos_v == Position::TOP ? TRAVEL_DIST : -TRAVEL_DIST);
|
||||||
|
|
||||||
// Crea la notificacion
|
// Crea la notificacion
|
||||||
Notification n;
|
Notification n;
|
||||||
@@ -225,7 +223,7 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string&
|
|||||||
n.travel_dist = TRAVEL_DIST;
|
n.travel_dist = TRAVEL_DIST;
|
||||||
n.texts = texts;
|
n.texts = texts;
|
||||||
n.shape = SHAPE;
|
n.shape = SHAPE;
|
||||||
const float POS_Y = offset + (param.notification.pos_v == NotifyPosition::TOP ? -TRAVEL_DIST : TRAVEL_DIST);
|
const float POS_Y = offset + (param.notification.pos_v == Position::TOP ? -TRAVEL_DIST : TRAVEL_DIST);
|
||||||
n.rect = {desp_h, POS_Y, WIDTH, HEIGHT};
|
n.rect = {desp_h, POS_Y, WIDTH, HEIGHT};
|
||||||
|
|
||||||
// Crea la textura
|
// Crea la textura
|
||||||
@@ -239,7 +237,7 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string&
|
|||||||
// Dibuja el fondo de la notificación
|
// Dibuja el fondo de la notificación
|
||||||
SDL_SetRenderDrawColor(renderer_, bg_color_.r, bg_color_.g, bg_color_.b, 255);
|
SDL_SetRenderDrawColor(renderer_, bg_color_.r, bg_color_.g, bg_color_.b, 255);
|
||||||
SDL_FRect rect;
|
SDL_FRect rect;
|
||||||
if (SHAPE == NotificationShape::ROUNDED) {
|
if (SHAPE == Shape::ROUNDED) {
|
||||||
rect = {4, 0, WIDTH - (4 * 2), HEIGHT};
|
rect = {4, 0, WIDTH - (4 * 2), HEIGHT};
|
||||||
SDL_RenderFillRect(renderer_, &rect);
|
SDL_RenderFillRect(renderer_, &rect);
|
||||||
|
|
||||||
@@ -253,7 +251,7 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string&
|
|||||||
SDL_RenderFillRect(renderer_, &rect);
|
SDL_RenderFillRect(renderer_, &rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (SHAPE == NotificationShape::SQUARED) {
|
else if (SHAPE == Shape::SQUARED) {
|
||||||
SDL_RenderClear(renderer_);
|
SDL_RenderClear(renderer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,7 +291,7 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string&
|
|||||||
// Finaliza y elimnina todas las notificaciones activas
|
// Finaliza y elimnina todas las notificaciones activas
|
||||||
void Notifier::clearAllNotifications() {
|
void Notifier::clearAllNotifications() {
|
||||||
for (auto& notification : notifications_) {
|
for (auto& notification : notifications_) {
|
||||||
notification.state = NotificationStatus::FINISHED;
|
notification.state = State::FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearFinishedNotifications();
|
clearFinishedNotifications();
|
||||||
|
|||||||
@@ -16,6 +16,15 @@ class Texture;
|
|||||||
// --- Clase Notifier: gestiona las notificaciones en pantalla (singleton) ---
|
// --- Clase Notifier: gestiona las notificaciones en pantalla (singleton) ---
|
||||||
class Notifier {
|
class Notifier {
|
||||||
public:
|
public:
|
||||||
|
// Posiciones de las notificaciones
|
||||||
|
enum class Position {
|
||||||
|
TOP,
|
||||||
|
BOTTOM,
|
||||||
|
LEFT,
|
||||||
|
MIDDLE,
|
||||||
|
RIGHT,
|
||||||
|
};
|
||||||
|
|
||||||
// --- Métodos de singleton ---
|
// --- Métodos de singleton ---
|
||||||
static void init(const std::string &icon_file, std::shared_ptr<Text> text); // Inicializa el singleton
|
static void init(const std::string &icon_file, std::shared_ptr<Text> text); // Inicializa el singleton
|
||||||
static void destroy(); // Libera el singleton
|
static void destroy(); // Libera el singleton
|
||||||
@@ -33,30 +42,30 @@ class Notifier {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Tipos internos ---
|
// --- Tipos internos ---
|
||||||
enum class NotificationStatus {
|
enum class State {
|
||||||
RISING,
|
RISING,
|
||||||
STAY,
|
STAY,
|
||||||
VANISHING,
|
VANISHING,
|
||||||
FINISHED,
|
FINISHED,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class NotificationShape {
|
enum class Shape {
|
||||||
ROUNDED,
|
ROUNDED,
|
||||||
SQUARED,
|
SQUARED,
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estructura Notification ---
|
// --- Estructura Notification ---
|
||||||
struct Notification {
|
struct Notification {
|
||||||
std::shared_ptr<Texture> texture; // Textura de la notificación
|
std::shared_ptr<Texture> texture; // Textura de la notificación
|
||||||
std::shared_ptr<Sprite> sprite; // Sprite asociado
|
std::shared_ptr<Sprite> sprite; // Sprite asociado
|
||||||
std::vector<std::string> texts; // Textos a mostrar
|
std::vector<std::string> texts; // Textos a mostrar
|
||||||
int counter{0}; // Contador de tiempo
|
int counter{0}; // Contador de tiempo
|
||||||
NotificationStatus state{NotificationStatus::RISING}; // Estado de la notificación
|
State state{State::RISING}; // Estado de la notificación
|
||||||
NotificationShape shape{NotificationShape::SQUARED}; // Forma de la notificación
|
Shape shape{Shape::SQUARED}; // Forma de la notificación
|
||||||
SDL_FRect rect; // Rectángulo de la notificación
|
SDL_FRect rect; // Rectángulo de la notificación
|
||||||
int y{0}; // Posición vertical
|
int y{0}; // Posición vertical
|
||||||
int travel_dist{0}; // Distancia a recorrer
|
int travel_dist{0}; // Distancia a recorrer
|
||||||
std::string code; // Código identificador de la notificación
|
std::string code; // Código identificador de la notificación
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
explicit Notification()
|
explicit Notification()
|
||||||
|
|||||||
@@ -127,7 +127,6 @@ void ServiceMenu::moveBack() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Si estamos en la pantalla principal, llamamos a toggle() para cerrar con animación.
|
// Si estamos en la pantalla principal, llamamos a toggle() para cerrar con animación.
|
||||||
// toggle() ya reproduce el sonido, por lo que no es necesario aquí.
|
|
||||||
toggle();
|
toggle();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,7 +565,6 @@ void ServiceMenu::handleEvent(const SDL_Event &event) {
|
|||||||
// Si DefineButtons está activo, que maneje todos los eventos
|
// Si DefineButtons está activo, que maneje todos los eventos
|
||||||
if (define_buttons_ && define_buttons_->isEnabled()) {
|
if (define_buttons_ && define_buttons_->isEnabled()) {
|
||||||
define_buttons_->handleEvents(event);
|
define_buttons_->handleEvents(event);
|
||||||
// return; // No procesar otros eventos mientras DefineButtons está activo
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "color.h" // Para Color
|
#include "color.h" // Para Color
|
||||||
|
#include "param.h" // Para param
|
||||||
#include "text.h" // Para Text
|
#include "text.h" // Para Text
|
||||||
|
|
||||||
class WindowMessage {
|
class WindowMessage {
|
||||||
@@ -43,9 +44,26 @@ class WindowMessage {
|
|||||||
|
|
||||||
// Constructor con valores por defecto
|
// Constructor con valores por defecto
|
||||||
Config()
|
Config()
|
||||||
: bg_color{40, 40, 60, 220}, border_color{100, 100, 120, 255}, title_color{255, 255, 255, 255}, text_color{200, 200, 200, 255}
|
: bg_color{40, 40, 60, 220},
|
||||||
|
border_color{100, 100, 120, 255},
|
||||||
|
title_color{255, 255, 255, 255},
|
||||||
|
text_color{200, 200, 200, 255} {}
|
||||||
|
|
||||||
{}
|
// Constructor que convierte desde ParamServiceMenu::WindowMessage
|
||||||
|
Config(const ParamServiceMenu::WindowMessage& param_config)
|
||||||
|
: bg_color(param_config.bg_color),
|
||||||
|
border_color(param_config.border_color),
|
||||||
|
title_color(param_config.title_color),
|
||||||
|
text_color(param_config.text_color),
|
||||||
|
padding(param_config.padding),
|
||||||
|
line_spacing(param_config.line_spacing),
|
||||||
|
title_separator_spacing(param_config.title_separator_spacing),
|
||||||
|
min_width(param_config.min_width),
|
||||||
|
min_height(param_config.min_height),
|
||||||
|
max_width_ratio(param_config.max_width_ratio),
|
||||||
|
max_height_ratio(param_config.max_height_ratio),
|
||||||
|
text_safety_margin(param_config.text_safety_margin),
|
||||||
|
animation_duration(param_config.animation_duration) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
WindowMessage(
|
WindowMessage(
|
||||||
|
|||||||
@@ -29,15 +29,6 @@ struct Circle {
|
|||||||
: x(x_coord), y(y_coord), r(radius) {}
|
: x(x_coord), y(y_coord), r(radius) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Posiciones de las notificaciones
|
|
||||||
enum class NotifyPosition {
|
|
||||||
TOP,
|
|
||||||
BOTTOM,
|
|
||||||
LEFT,
|
|
||||||
MIDDLE,
|
|
||||||
RIGHT,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura para datos de la demo
|
// Estructura para datos de la demo
|
||||||
struct DemoKeys {
|
struct DemoKeys {
|
||||||
Uint8 left;
|
Uint8 left;
|
||||||
|
|||||||