Compare commits
107 Commits
2024-11-27
...
2025-02-07
| Author | SHA1 | Date | |
|---|---|---|---|
| 84595da13a | |||
| 01591175ef | |||
| 29bc4a64fd | |||
| 559210652f | |||
| 44e4ca490d | |||
| 3cebee2ae4 | |||
| 270d7d1848 | |||
| ccf005dce1 | |||
| 5755947ff7 | |||
| 6f594b9a1f | |||
| 7e2021da70 | |||
| 0a9a92d4b7 | |||
| b01763b749 | |||
| 59b9f61d69 | |||
| b9f194a2b1 | |||
| 59936f13eb | |||
| bad0a10328 | |||
| 52a0c2b91f | |||
| f12a456017 | |||
| f39e65afaf | |||
| d3183237df | |||
| 60302004f4 | |||
| e60938cb19 | |||
| 2b3cc719ba | |||
| d01c91ebde | |||
| 7130f2298a | |||
| 380cc17861 | |||
| a5388873e3 | |||
| 28b37af31d | |||
| 4d590f79f5 | |||
| 91c8797d7f | |||
| f207985180 | |||
| a16131335b | |||
| 871e8da642 | |||
| 90b3db8f06 | |||
| 668e8e237a | |||
| 768f466b20 | |||
| 1f8f9b11ed | |||
| 39f61884b0 | |||
| b1193bd8fd | |||
| 7f9e2e53e3 | |||
| 4cf4c8db6f | |||
| cd806363e8 | |||
| 198aa45d59 | |||
| 0711c8dada | |||
| e1aaad0903 | |||
| b53ee12f56 | |||
| 7b6d429bed | |||
| 81ee352553 | |||
| 7b8f16610a | |||
| 06eb05f065 | |||
| bccf4c30de | |||
| 5e817ef1d0 | |||
| eaab646cd3 | |||
| e887c2a2ab | |||
| f573bd02ac | |||
| b586a117c8 | |||
| 08dfaf7641 | |||
| ff7f5ea131 | |||
| 7cc4a2002a | |||
| de81b798b0 | |||
| 5669715285 | |||
| 6531106933 | |||
| 51191b1906 | |||
| 6effeb6154 | |||
| 8c2b1ce649 | |||
| cc4acecc03 | |||
| 40dfc32e84 | |||
| 4cd1d91560 | |||
| e43badd703 | |||
| 71dcf9cf87 | |||
| 3a8521a1da | |||
| 74d9c9a2b9 | |||
| 9532caace8 | |||
| 0bbd14067a | |||
| cfaa143c44 | |||
| e61daeb92e | |||
| d57cc15aee | |||
| de3b18a407 | |||
| 7f444fef33 | |||
| ca18baefd7 | |||
| b8dca0a46f | |||
| ca2c48ea17 | |||
| fb4d0d12db | |||
| fb31445731 | |||
| cf4f0459b3 | |||
| fe0900a686 | |||
| 3367b70cd5 | |||
| 7016849587 | |||
| 301c059a26 | |||
| e3d0145417 | |||
| f0863b3691 | |||
| 80e366b208 | |||
| 3c5bbf2ab0 | |||
| 1aa0dd3864 | |||
| ab45c984a2 | |||
| 020ee81479 | |||
| 0cd96aced5 | |||
| ad32bb7d45 | |||
| c3a5166ee1 | |||
| 687d329d23 | |||
| faba87c06d | |||
| eed45bdbc6 | |||
| 6ed37425bf | |||
| b987d06aca | |||
| 9c9cfdabc2 | |||
| 9f2448753b |
3
.gitignore
vendored
@@ -15,4 +15,5 @@ thumbs.db
|
||||
*score.bin
|
||||
coffee_crisis*
|
||||
debug.txt
|
||||
cppcheck-result*
|
||||
cppcheck-result*
|
||||
desktop.ini
|
||||
|
||||
156
Makefile
@@ -1,59 +1,63 @@
|
||||
# Directorios
|
||||
DIR_ROOT := $(dir $(abspath $(MAKEFILE_LIST)))
|
||||
DIR_SOURCES:= $(addsuffix /, $(DIR_ROOT)source)
|
||||
DIR_BIN := $(addsuffix /, $(DIR_ROOT))
|
||||
DIR_BUILD := $(addsuffix /, $(DIR_ROOT)build)
|
||||
DIR_ROOT := $(dir $(abspath $(MAKEFILE_LIST)))
|
||||
DIR_SOURCES := $(addsuffix /, $(DIR_ROOT)source)
|
||||
DIR_BIN := $(addsuffix /, $(DIR_ROOT))
|
||||
DIR_BUILD := $(addsuffix /, $(DIR_ROOT)build)
|
||||
|
||||
# Variables
|
||||
TARGET_NAME := coffee_crisis_arcade_edition
|
||||
TARGET_FILE := $(DIR_BIN)$(TARGET_NAME)
|
||||
APP_NAME := Coffee Crisis Arcade Edition
|
||||
RELEASE_FOLDER:= ccae_release
|
||||
RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME)
|
||||
VERSION := v0.01
|
||||
TARGET_NAME := coffee_crisis_arcade_edition
|
||||
TARGET_FILE := $(DIR_BIN)$(TARGET_NAME)
|
||||
APP_NAME := Coffee Crisis Arcade Edition
|
||||
RELEASE_FOLDER := ccae_release
|
||||
RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME)
|
||||
RESOURCE_FILE := release/coffee.res
|
||||
VERSION := 2025-02-07
|
||||
|
||||
# Nombres para los ficheros de lanzamiento
|
||||
WINDOWS_RELEASE := $(TARGET_FILE)-$(VERSION)-win32-x64.zip
|
||||
MACOS_INTEL_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-intel.dmg
|
||||
MACOS_APPLE_SILICON_RELEASE:= $(TARGET_FILE)-$(VERSION)-macos-apple-silicon.dmg
|
||||
LINUX_RELEASE := $(TARGET_FILE)-$(VERSION)-linux.tar.gz
|
||||
WINDOWS_RELEASE := $(TARGET_NAME)-$(VERSION)-win32-x64.zip
|
||||
MACOS_INTEL_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-intel.dmg
|
||||
MACOS_APPLE_SILICON_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-apple-silicon.dmg
|
||||
LINUX_RELEASE := $(TARGET_FILE)-$(VERSION)-linux.tar.gz
|
||||
RASPI_RELEASE := $(TARGET_FILE)-$(VERSION)-raspberry.tar.gz
|
||||
|
||||
# Includes
|
||||
INCLUDES:= -I$(DIR_SOURCES)
|
||||
INCLUDES := -I$(DIR_SOURCES)
|
||||
|
||||
# Variables según el sistema operativo
|
||||
ifeq ($(OS),Windows_NT)
|
||||
FixPath = $(subst /,\,$1)
|
||||
SOURCES := source/*.cpp
|
||||
CXXFLAGS:= -std=c++20 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows
|
||||
CXXFLAGS_DEBUG:= -std=c++20 -Wall -g
|
||||
LDFLAGS := -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32
|
||||
RM = del /Q
|
||||
MKD:= mkdir
|
||||
FixPath = $(subst /,\\,$1)
|
||||
SOURCES := source/*.cpp
|
||||
CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows
|
||||
CXXFLAGS_DEBUG := -std=c++20 -Wall -g
|
||||
LDFLAGS := -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32
|
||||
RM := del /Q
|
||||
MKDIR := mkdir
|
||||
else
|
||||
FixPath = $1
|
||||
SOURCES := $(shell find $(DIR_SOURCES) -name '*.cpp')
|
||||
SOURCES := source/*.cpp
|
||||
CXXFLAGS:= -std=c++20 -Wall -Os -ffunction-sections -fdata-sections
|
||||
CXXFLAGS_DEBUG:= -std=c++20 -Wall -g
|
||||
LDFLAGS := -lSDL2
|
||||
RM = rm -f
|
||||
MKD:= mkdir -p
|
||||
UNAME_S := $(shell uname -s)
|
||||
FixPath = $1
|
||||
SOURCES := $(shell find $(DIR_SOURCES) -name '*.cpp')
|
||||
SOURCES := source/*.cpp
|
||||
CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections
|
||||
CXXFLAGS_DEBUG := -std=c++20 -Wall -g
|
||||
LDFLAGS := -lSDL2
|
||||
RMFILE := rm -f
|
||||
RMDIR := rm -rdf
|
||||
MKDIR := mkdir -p
|
||||
UNAME_S := $(shell uname -s)
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
LDFLAGS += -lGL
|
||||
LDFLAGS += -lGL
|
||||
endif
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
CXXFLAGS += -Wno-deprecated
|
||||
CXXFLAGS_DEBUG += -Wno-deprecated
|
||||
LDFLAGS += -framework OpenGL
|
||||
CXXFLAGS += -Wno-deprecated
|
||||
CXXFLAGS_DEBUG += -Wno-deprecated
|
||||
LDFLAGS += -framework OpenGL
|
||||
endif
|
||||
endif
|
||||
|
||||
# Rules
|
||||
# Reglas para compilación
|
||||
windows:
|
||||
@echo off
|
||||
$(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE).exe"
|
||||
windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
|
||||
$(CXX) $(SOURCES) $(RESOURCE_FILE) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE).exe"
|
||||
strip -s -R .comment -R .gnu.version "$(TARGET_FILE).exe" --strip-unneeded
|
||||
|
||||
windows_rec:
|
||||
@@ -80,12 +84,13 @@ windows_release:
|
||||
powershell Copy-Item "release\*.dll" -Destination "$(RELEASE_FOLDER)"
|
||||
|
||||
# Compila
|
||||
$(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE).exe"
|
||||
strip -s -R .comment -R .gnu.version "$(RELEASE_FOLDER)/$(TARGET_FILE).exe" --strip-unneeded
|
||||
windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
|
||||
$(CXX) $(SOURCES) $(RESOURCE_FILE) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE).exe"
|
||||
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE).exe" --strip-unneeded
|
||||
|
||||
# Crea el fichero .zip
|
||||
powershell if (Test-Path $(WINDOWS_RELEASE)) {Remove-Item $(WINDOWS_RELEASE)}
|
||||
powershell Compress-Archive -Path "$(RELEASE_FOLDER)"/* -DestinationPath $(WINDOWS_RELEASE)
|
||||
powershell if (Test-Path "$(WINDOWS_RELEASE)") {Remove-Item "$(WINDOWS_RELEASE)"}
|
||||
powershell Compress-Archive -Path "$(RELEASE_FOLDER)"/* -DestinationPath "$(WINDOWS_RELEASE)"
|
||||
|
||||
# Elimina la carpeta temporal 'RELEASE_FOLDER'
|
||||
powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force}
|
||||
@@ -98,17 +103,17 @@ macos_debug:
|
||||
|
||||
macos_release:
|
||||
# Elimina datos de compilaciones anteriores
|
||||
rm -rdf "$(RELEASE_FOLDER)"
|
||||
rm -rdf Frameworks
|
||||
rm -f tmp.dmg
|
||||
rm -f "$(MACOS_INTEL_RELEASE)"
|
||||
rm -f "$(MACOS_APPLE_SILICON_RELEASE)"
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||
$(RMDIR) Frameworks
|
||||
$(RMFILE) tmp.dmg
|
||||
$(RMFILE) "$(MACOS_INTEL_RELEASE)"
|
||||
$(RMFILE) "$(MACOS_APPLE_SILICON_RELEASE)"
|
||||
|
||||
# Crea la carpeta temporal para hacer el trabajo y las carpetas obligatorias para crear una app de macos
|
||||
mkdir -p "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
|
||||
mkdir -p "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS"
|
||||
mkdir -p "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
||||
mkdir -p Frameworks
|
||||
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
|
||||
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS"
|
||||
$(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
||||
$(MKDIR) Frameworks
|
||||
|
||||
# Copia carpetas y ficheros
|
||||
cp -R data "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
|
||||
@@ -123,24 +128,24 @@ macos_release:
|
||||
ln -s /Applications "$(RELEASE_FOLDER)"/Applications
|
||||
|
||||
# Compila la versión para procesadores Intel
|
||||
$(CXX) $(SOURCES) -D MACOS_BUNDLE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_FILE)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.12
|
||||
$(CXX) $(SOURCES) -D MACOS_BUNDLE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target x86_64-apple-macos10.12
|
||||
|
||||
# Empaqueta el .dmg de la versión Intel
|
||||
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
|
||||
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_INTEL_RELEASE)"
|
||||
rm -f tmp.dmg
|
||||
$(RMFILE) tmp.dmg
|
||||
|
||||
# Compila la versión para procesadores Apple Silicon
|
||||
$(CXX) $(SOURCES) -D MACOS_BUNDLE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_FILE)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11
|
||||
$(CXX) $(SOURCES) -D MACOS_BUNDLE -D SDL_DISABLE_IMMINTRIN_H $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS/$(TARGET_NAME)" -rpath @executable_path/../Frameworks/ -target arm64-apple-macos11
|
||||
|
||||
# Empaqueta el .dmg de la versión Apple Silicon
|
||||
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
|
||||
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_APPLE_SILICON_RELEASE)"
|
||||
rm -f tmp.dmg
|
||||
$(RMFILE) tmp.dmg
|
||||
|
||||
# Elimina las carpetas temporales
|
||||
$(RM) Frameworks
|
||||
$(RM) "$(RELEASE_FOLDER)"
|
||||
$(RMDIR) Frameworks
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
linux:
|
||||
$(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)"
|
||||
@@ -151,10 +156,10 @@ linux_debug:
|
||||
|
||||
linux_release:
|
||||
# Elimina carpetas previas
|
||||
$(RM) "$(RELEASE_FOLDER)"
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
# Crea la carpeta temporal para realizar el lanzamiento
|
||||
mkdir -p "$(RELEASE_FOLDER)"
|
||||
$(MKDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
# Copia ficheros
|
||||
cp -R data "$(RELEASE_FOLDER)"
|
||||
@@ -166,11 +171,11 @@ linux_release:
|
||||
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
|
||||
|
||||
# Empaqueta ficheros
|
||||
$(RM) "$(LINUX_RELEASE)"
|
||||
cd "$(RELEASE_FOLDER)" && tar -czvf "../$(LINUX_RELEASE)" *
|
||||
$(RMFILE) "$(LINUX_RELEASE)"
|
||||
cd "$(RELEASE_FOLDER)" && tar -czvf "$(LINUX_RELEASE)" *
|
||||
|
||||
# Elimina la carpeta temporal
|
||||
$(RM) "$(RELEASE_FOLDER)"
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
raspi:
|
||||
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(TARGET_FILE)
|
||||
@@ -179,12 +184,35 @@ raspi:
|
||||
raspi_debug:
|
||||
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE -D DEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
|
||||
|
||||
anbernic:
|
||||
raspi_release:
|
||||
# Elimina carpetas previas
|
||||
$(RM) "$(RELEASE_FOLDER)"_anbernic
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
# Crea la carpeta temporal para realizar el lanzamiento
|
||||
mkdir -p "$(RELEASE_FOLDER)"_anbernic
|
||||
$(MKDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
# Copia ficheros
|
||||
cp -R data "$(RELEASE_FOLDER)"
|
||||
cp LICENSE "$(RELEASE_FOLDER)"
|
||||
cp README.md "$(RELEASE_FOLDER)"
|
||||
|
||||
# Complia
|
||||
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
|
||||
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
|
||||
|
||||
# Empaqueta ficheros
|
||||
$(RMFILE) "$(LINUX_RELEASE)"
|
||||
cd "$(RELEASE_FOLDER)" && tar -czvf "$(RASPI_RELEASE)" *
|
||||
|
||||
# Elimina la carpeta temporal
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"
|
||||
|
||||
anbernic:
|
||||
# Elimina carpetas previas
|
||||
$(RMDIR) "$(RELEASE_FOLDER)"_anbernic
|
||||
|
||||
# Crea la carpeta temporal para realizar el lanzamiento
|
||||
$(MKDIR) "$(RELEASE_FOLDER)"_anbernic
|
||||
|
||||
# Copia ficheros
|
||||
cp -R data "$(RELEASE_FOLDER)"_anbernic
|
||||
|
||||
74
README.md
@@ -1,39 +1,73 @@
|
||||
# Coffee Crisis Arcade Edition
|
||||
|
||||
Coffee Crisis Arcade Edition es la versió ampliada i millorada del aclamat Coffee Crisis. Preparat per a jugar sense parar amn dos jugadors, nous gràfics i moltes sorpreses mes.
|
||||
**¡La batalla definitiva pel cafè està ací!**
|
||||
|
||||
Coffee Crisis Arcade Edition és una versió ampliada i millorada del aclamat Coffee Crisis. Aquesta versió porta l'acció cooperativa al següent nivell, amb:
|
||||
|
||||
- **Mode multijugador** per a dues persones.
|
||||
- **Nous gràfics** que revitalitzen l'experiència arcade clàssica.
|
||||
- **Moltes sorpreses** per descobrir en cada partida.
|
||||
|
||||
Defensa el teu cafè contra les bambolles gegants en aquest trepidant joc d'arcade! 🍵
|
||||
|
||||
<p align="center">
|
||||
<img src="https://php.sustancia.synology.me/images/ccae_title.png" alt="Titol"
|
||||
<img src="https://php.sustancia.synology.me/images/ccae_title.png" alt="Títol" width="60%" />
|
||||
</p>
|
||||
|
||||
## Controls
|
||||
El joc està optimitzat per a ser jugat amb un mando de jocs, encara que un dels jugadors pot utilitzar el teclat.
|
||||
Les tecles son les següents:
|
||||
|
||||
* **Fletxes**: Mou al personatge
|
||||
* **Q, W, E**: Disparar a la esquerra, al centre i a la dreta respectivament
|
||||
El joc està optimitzat per a ser jugat amb un mando de jocs, encara que un dels jugadors pot utilitzar el teclat.
|
||||
|
||||
### Controls del teclat:
|
||||
- **Fletxes**: Mou al personatge.
|
||||
- **Q, W, E**: Disparar a l'esquerra, al centre i a la dreta, respectivament.
|
||||
|
||||
> Nota: El joc suporta nomes un jugador amb teclat.
|
||||
|
||||
<p align="center">
|
||||
<img src="https://php.sustancia.synology.me/images/ccae1.png" alt="Joc"
|
||||
<img src="https://php.sustancia.synology.me/images/ccae1.png" alt="Joc" width="45%" />
|
||||
<img src="https://php.sustancia.synology.me/images/ccae3.png" alt="Joc" width="45%" />
|
||||
</p>
|
||||
|
||||
## Altres tecles
|
||||
- **Tecla ESC**: Tancar el joc
|
||||
|
||||
- **Tecla F1**: Fa la finestra mes xicoteta
|
||||
|
||||
- **Tecla F2**: Fa la finestra mes gran
|
||||
|
||||
- **Tecla F3**: Alterna entre el mode de pantalla completa i el de finestra
|
||||
|
||||
- **Tecla F4**: Activa o desactiva els shaders
|
||||
|
||||
- **Tecla F10**: Reset
|
||||
| Tecla | Funció |
|
||||
|-------------|----------------------------------------------|
|
||||
| **ESC** | Tancar el joc |
|
||||
| **F1** | Fa la finestra més xicoteta |
|
||||
| **F2** | Fa la finestra més gran |
|
||||
| **F3** | Alterna entre mode de pantalla completa i finestra |
|
||||
| **F4** | Activa o desactiva els shaders |
|
||||
| **F5** | Activa o desactiva l'àudio |
|
||||
| **F6** | Activa o desactiva el dispar automàtic |
|
||||
| **F7** | Canvia l'idioma del joc i reinicia |
|
||||
| **F10** | Reset del joc |
|
||||
|
||||
<p align="center">
|
||||
<img src="https://php.sustancia.synology.me/images/ccae2.png" alt="Joc"
|
||||
<img src="https://php.sustancia.synology.me/images/ccae2.png" alt="Joc" width="50%" />
|
||||
</p>
|
||||
|
||||
## Com instal·lar i jugar
|
||||
|
||||
1. Descarrega el joc des de [l'apartat de llançaments](https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis_arcade_edition/releases).
|
||||
2. Descomprimix i executa l'arxiu `coffee_crisis_arcade_edition.exe`.
|
||||
3. Gaudeix del joc!
|
||||
|
||||
## Agraïments
|
||||
|
||||
Vull expressar la meua gratitud a **ChatGPT** i **GitHub Copilot**. Gràcies per ser un suport constant en el desenvolupament d'aquest joc!
|
||||
|
||||
També vull agrair a tots els jugadors que fan que aquest projecte valgui la pena. 🕹️❤️
|
||||
|
||||
## Com contribuir
|
||||
|
||||
Accepte contribucions! Si tens una idea o vols ajudar:
|
||||
|
||||
1. Fes un fork d'aquest repositori.
|
||||
2. Crea una branca nova amb els teus canvis.
|
||||
3. Fes un pull request.
|
||||
|
||||
## Llicència
|
||||
|
||||
Aquest joc està subjecte a una llicència [MIT](https://opensource.org/licenses/MIT). Consulta el fitxer LICENSE per a més detalls.
|
||||
|
||||
## Agraiments
|
||||
A chatGPT i sobretot a Copilot. Gracies per estar sempre quan vos he necesitat.
|
||||
@@ -1,5 +1,7 @@
|
||||
## GAME
|
||||
game.item_size 20 # Tamaño de los items del juego
|
||||
game.coffee_machine_w 28 # Ancho de la máquina de café
|
||||
game.coffee_machine_h 37 # Alto de la máquina de café
|
||||
game.width 320 # Ancho de la resolucion nativa del juego
|
||||
game.height 240 # Alto de la resolucion nativa del juego
|
||||
game.play_area.rect.x 0 # Rectangulo con la posición de la zona de juego
|
||||
@@ -14,7 +16,7 @@ fade.num_squares_height 120
|
||||
fade.random_squares_delay 1
|
||||
fade.random_squares_mult 500
|
||||
fade.post_duration 80
|
||||
fade.venetian_size 16
|
||||
fade.venetian_size 12
|
||||
|
||||
## SCOREBOARD
|
||||
scoreboard.x 0
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
## GAME
|
||||
game.item_size 20 # Tamaño de los items del juego
|
||||
game.width 320 # Ancho de la resolucion nativa del juego
|
||||
game.height 256 # Alto de la resolucion nativa del juego
|
||||
game.play_area.rect.x 0 # Rectangulo con la posición de la zona de juego
|
||||
game.play_area.rect.y 0 # Rectangulo con la posición de la zona de juego
|
||||
game.play_area.rect.w 320 # Rectangulo con la posición de la zona de juego
|
||||
game.play_area.rect.h 216 # Rectangulo con la posición de la zona de juego
|
||||
game.enter_name_seconds 60 # Duración en segundos para introducir el nombre al finalizar la partida
|
||||
game.item_size 20 # Tamaño de los items del juego
|
||||
game.coffee_machine_w 28 # Ancho de la máquina de café
|
||||
game.coffee_machine_h 37 # Alto de la máquina de café
|
||||
game.width 320 # Ancho de la resolucion nativa del juego
|
||||
game.height 256 # Alto de la resolucion nativa del juego
|
||||
game.play_area.rect.x 0 # Rectangulo con la posición de la zona de juego
|
||||
game.play_area.rect.y 0 # Rectangulo con la posición de la zona de juego
|
||||
game.play_area.rect.w 320 # Rectangulo con la posición de la zona de juego
|
||||
game.play_area.rect.h 216 # Rectangulo con la posición de la zona de juego
|
||||
game.enter_name_seconds 60 # Duración en segundos para introducir el nombre al finalizar la partida
|
||||
|
||||
## FADE
|
||||
fade.num_squares_width 160
|
||||
@@ -14,7 +16,7 @@ fade.num_squares_height 128
|
||||
fade.random_squares_delay 1
|
||||
fade.random_squares_mult 500
|
||||
fade.post_duration 80
|
||||
fade.venetian_size 16
|
||||
fade.venetian_size 12
|
||||
|
||||
## SCOREBOARD
|
||||
scoreboard.x 0
|
||||
|
||||
BIN
data/font/04b_25_grey.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
data/font/04b_25_metal.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
@@ -1,194 +0,0 @@
|
||||
# box width
|
||||
10
|
||||
# box height
|
||||
10
|
||||
# 32 espacio ( )
|
||||
5
|
||||
# 33 !
|
||||
4
|
||||
# 34 "
|
||||
5
|
||||
# 35 #
|
||||
7
|
||||
# 36 $
|
||||
7
|
||||
# 37 %
|
||||
8
|
||||
# 38 &
|
||||
8
|
||||
# 39 '
|
||||
3
|
||||
# 40 (
|
||||
5
|
||||
# 41 )
|
||||
5
|
||||
# 42 *
|
||||
7
|
||||
# 43 +
|
||||
7
|
||||
# 44 ,
|
||||
4
|
||||
# 45 -
|
||||
6
|
||||
# 46 .
|
||||
4
|
||||
# 47 /
|
||||
5
|
||||
# 48 0
|
||||
7
|
||||
# 49 1
|
||||
5
|
||||
# 50 2
|
||||
7
|
||||
# 51 3
|
||||
7
|
||||
# 52 4
|
||||
7
|
||||
# 53 5
|
||||
7
|
||||
# 54 6
|
||||
7
|
||||
# 55 7
|
||||
7
|
||||
# 56 8
|
||||
7
|
||||
# 57 9
|
||||
7
|
||||
# 58 :
|
||||
4
|
||||
# 59 ;
|
||||
4
|
||||
# 60 <
|
||||
6
|
||||
# 61 =
|
||||
6
|
||||
# 62 >
|
||||
6
|
||||
# 63 ?
|
||||
7
|
||||
# 64 @
|
||||
8
|
||||
# 65 A
|
||||
7
|
||||
# 66 B
|
||||
7
|
||||
# 67 C
|
||||
7
|
||||
# 68 D
|
||||
7
|
||||
# 69 E
|
||||
7
|
||||
# 70 F
|
||||
7
|
||||
# 71 G
|
||||
7
|
||||
# 72 H
|
||||
7
|
||||
# 73 I
|
||||
4
|
||||
# 74 J
|
||||
6
|
||||
# 75 K
|
||||
8
|
||||
# 76 L
|
||||
6
|
||||
# 77 M
|
||||
9
|
||||
# 78 N
|
||||
8
|
||||
# 79 O
|
||||
8
|
||||
# 80 P
|
||||
7
|
||||
# 81 Q
|
||||
8
|
||||
# 82 R
|
||||
7
|
||||
# 83 S
|
||||
6
|
||||
# 84 T
|
||||
8
|
||||
# 85 U
|
||||
7
|
||||
# 86 V
|
||||
8
|
||||
# 87 W
|
||||
9
|
||||
# 88 X
|
||||
8
|
||||
# 89 Y
|
||||
8
|
||||
# 90 Z
|
||||
7
|
||||
# 91 [
|
||||
4
|
||||
# 92 \
|
||||
5
|
||||
# 93 ]
|
||||
4
|
||||
# 94 ^
|
||||
5
|
||||
# 95 _
|
||||
8
|
||||
# 96 `
|
||||
4
|
||||
# 97 a
|
||||
7
|
||||
# 98 b
|
||||
7
|
||||
# 99 c
|
||||
6
|
||||
# 100 d
|
||||
7
|
||||
# 101 e
|
||||
7
|
||||
# 102 f
|
||||
5
|
||||
# 103 g
|
||||
7
|
||||
# 104 h
|
||||
7
|
||||
# 105 i
|
||||
4
|
||||
# 106 j
|
||||
5
|
||||
# 107 k
|
||||
7
|
||||
# 108 l
|
||||
4
|
||||
# 109 m
|
||||
10
|
||||
# 110 n
|
||||
7
|
||||
# 111 o
|
||||
7
|
||||
# 112 p
|
||||
7
|
||||
# 113 q
|
||||
7
|
||||
# 114 r
|
||||
6
|
||||
# 115 s
|
||||
6
|
||||
# 116 t
|
||||
5
|
||||
# 117 u
|
||||
7
|
||||
# 118 v
|
||||
7
|
||||
# 119 w
|
||||
9
|
||||
# 120 x
|
||||
7
|
||||
# 121 y
|
||||
7
|
||||
# 122 z
|
||||
7
|
||||
# 123 { -> ñ
|
||||
7
|
||||
# 124 | -> ç
|
||||
7
|
||||
# 125 }
|
||||
0
|
||||
# 126 ~
|
||||
0
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -1,9 +1,9 @@
|
||||
frame_width=46
|
||||
frame_height=46
|
||||
frame_width=49
|
||||
frame_height=49
|
||||
|
||||
[animation]
|
||||
name=powerball
|
||||
speed=10
|
||||
loop=-1
|
||||
frames=0
|
||||
frames=1
|
||||
[/animation]
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
BIN
data/gfx/game/game_moon.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.3 KiB |
BIN
data/gfx/game/game_sun.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
9
data/gfx/item/item_debian.ani
Normal file
@@ -0,0 +1,9 @@
|
||||
frame_width=20
|
||||
frame_height=20
|
||||
|
||||
[animation]
|
||||
name=default
|
||||
speed=10
|
||||
loop=0
|
||||
frames=0,1
|
||||
[/animation]
|
||||
BIN
data/gfx/item/item_debian.png
Normal file
|
After Width: | Height: | Size: 565 B |
|
Before Width: | Height: | Size: 173 B After Width: | Height: | Size: 173 B |
|
Before Width: | Height: | Size: 173 B After Width: | Height: | Size: 173 B |
|
Before Width: | Height: | Size: 173 B |
BIN
data/gfx/player/player1_invencible_palette.gif
Normal file
|
After Width: | Height: | Size: 174 B |
|
Before Width: | Height: | Size: 172 B After Width: | Height: | Size: 172 B |
|
Before Width: | Height: | Size: 172 B After Width: | Height: | Size: 172 B |
|
Before Width: | Height: | Size: 172 B |
BIN
data/gfx/player/player2_invencible_palette.gif
Normal file
|
After Width: | Height: | Size: 174 B |
16
data/gfx/tabe/tabe.ani
Normal file
@@ -0,0 +1,16 @@
|
||||
frame_width=32
|
||||
frame_height=32
|
||||
|
||||
[animation]
|
||||
name=fly
|
||||
speed=2
|
||||
loop=0
|
||||
frames=0,1
|
||||
[/animation]
|
||||
|
||||
[animation]
|
||||
name=hit
|
||||
speed=2
|
||||
loop=0
|
||||
frames=2,3
|
||||
[/animation]
|
||||
BIN
data/gfx/tabe/tabe.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
@@ -32,7 +32,7 @@ IDIOMA
|
||||
[ CANCELAR ]
|
||||
|
||||
## 11 - INSTRUCCIONES
|
||||
OBJECTIU
|
||||
Objectiu
|
||||
|
||||
## 12 - INSTRUCCIONES
|
||||
HAS D'EXPLOTAR
|
||||
@@ -47,7 +47,7 @@ LA DIFICULTAT AUGMENTA
|
||||
A MESURA QUE VAS PUNTUANT
|
||||
|
||||
## 16 - INSTRUCCIONES
|
||||
OBJECTES
|
||||
Objectes
|
||||
|
||||
## 17 - INSTRUCCIONES
|
||||
1.000 PUNTS
|
||||
@@ -359,4 +359,16 @@ SuperPoder!
|
||||
Temps!
|
||||
|
||||
## 120 - SCOREBOARD
|
||||
Puntuacio
|
||||
Puntuacio
|
||||
|
||||
## 121 - CREDITS
|
||||
PROGRAMAT I DISSENYAT PER
|
||||
|
||||
## 122 - CREDITS
|
||||
GRAFICS DIBUIXATS PER
|
||||
|
||||
## 123 - CREDITS
|
||||
MUSICA COMPOSADA PER
|
||||
|
||||
## 124 - CREDITS
|
||||
EFECTES DE SO
|
||||
@@ -359,4 +359,16 @@ PowerUp
|
||||
Stop!
|
||||
|
||||
## 120 - SCOREBOARD
|
||||
Score
|
||||
Score
|
||||
|
||||
## 121 - CREDITS
|
||||
PROGRAMMED AND DESIGNED BY
|
||||
|
||||
## 122 - CREDITS
|
||||
PIXELART DRAWN BY
|
||||
|
||||
## 123 - CREDITS
|
||||
MUSIC COMPOSED BY
|
||||
|
||||
## 124 - CREDITS
|
||||
SOUND EFFECTS
|
||||
@@ -359,4 +359,16 @@ Potenciador
|
||||
Tiempo!
|
||||
|
||||
## 120 - SCOREBOARD
|
||||
Puntuacion
|
||||
Puntuacion
|
||||
|
||||
## 121 - CREDITS
|
||||
PROGRAMADO Y DISE{ADO POR
|
||||
|
||||
## 122 - CREDITS
|
||||
GRAFICOS DIBUJADOS POR
|
||||
|
||||
## 123 - CREDITS
|
||||
MUSICA COMPUESTA POR
|
||||
|
||||
## 124 - CREDITS
|
||||
EFECTOS DE SONIDO
|
||||
234
data/shaders/crtpi_240.glsl
Normal file
@@ -0,0 +1,234 @@
|
||||
/*
|
||||
crt-pi - A Raspberry Pi friendly CRT shader.
|
||||
|
||||
Copyright (C) 2015-2016 davej
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 2 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
|
||||
Notes:
|
||||
|
||||
This shader is designed to work well on Raspberry Pi GPUs (i.e. 1080P @ 60Hz on a game with a 4:3 aspect ratio). It pushes the Pi's GPU hard and enabling some features will slow it down so that it is no longer able to match 1080P @ 60Hz. You will need to overclock your Pi to the fastest setting in raspi-config to get the best results from this shader: 'Pi2' for Pi2 and 'Turbo' for original Pi and Pi Zero. Note: Pi2s are slower at running the shader than other Pis, this seems to be down to Pi2s lower maximum memory speed. Pi2s don't quite manage 1080P @ 60Hz - they drop about 1 in 1000 frames. You probably won't notice this, but if you do, try enabling FAKE_GAMMA.
|
||||
|
||||
SCANLINES enables scanlines. You'll almost certainly want to use it with MULTISAMPLE to reduce moire effects. SCANLINE_WEIGHT defines how wide scanlines are (it is an inverse value so a higher number = thinner lines). SCANLINE_GAP_BRIGHTNESS defines how dark the gaps between the scan lines are. Darker gaps between scan lines make moire effects more likely.
|
||||
|
||||
GAMMA enables gamma correction using the values in INPUT_GAMMA and OUTPUT_GAMMA. FAKE_GAMMA causes it to ignore the values in INPUT_GAMMA and OUTPUT_GAMMA and approximate gamma correction in a way which is faster than true gamma whilst still looking better than having none. You must have GAMMA defined to enable FAKE_GAMMA.
|
||||
|
||||
CURVATURE distorts the screen by CURVATURE_X and CURVATURE_Y. Curvature slows things down a lot.
|
||||
|
||||
By default the shader uses linear blending horizontally. If you find this too blury, enable SHARPER.
|
||||
|
||||
BLOOM_FACTOR controls the increase in width for bright scanlines.
|
||||
|
||||
MASK_TYPE defines what, if any, shadow mask to use. MASK_BRIGHTNESS defines how much the mask type darkens the screen.
|
||||
|
||||
*/
|
||||
|
||||
#pragma parameter CURVATURE_X "Screen curvature - horizontal" 0.10 0.0 1.0 0.01
|
||||
#pragma parameter CURVATURE_Y "Screen curvature - vertical" 0.15 0.0 1.0 0.01
|
||||
#pragma parameter MASK_BRIGHTNESS "Mask brightness" 0.70 0.0 1.0 0.01
|
||||
#pragma parameter SCANLINE_WEIGHT "Scanline weight" 6.0 0.0 15.0 0.1
|
||||
#pragma parameter SCANLINE_GAP_BRIGHTNESS "Scanline gap brightness" 0.12 0.0 1.0 0.01
|
||||
#pragma parameter BLOOM_FACTOR "Bloom factor" 1.5 0.0 5.0 0.01
|
||||
#pragma parameter INPUT_GAMMA "Input gamma" 2.4 0.0 5.0 0.01
|
||||
#pragma parameter OUTPUT_GAMMA "Output gamma" 2.2 0.0 5.0 0.01
|
||||
|
||||
// Haven't put these as parameters as it would slow the code down.
|
||||
#define SCANLINES
|
||||
#define MULTISAMPLE
|
||||
#define GAMMA
|
||||
//#define FAKE_GAMMA
|
||||
//#define CURVATURE
|
||||
//#define SHARPER
|
||||
// MASK_TYPE: 0 = none, 1 = green/magenta, 2 = trinitron(ish)
|
||||
#define MASK_TYPE 2
|
||||
|
||||
|
||||
#ifdef GL_ES
|
||||
#define COMPAT_PRECISION mediump
|
||||
precision mediump float;
|
||||
#else
|
||||
#define COMPAT_PRECISION
|
||||
#endif
|
||||
|
||||
#ifdef PARAMETER_UNIFORM
|
||||
uniform COMPAT_PRECISION float CURVATURE_X;
|
||||
uniform COMPAT_PRECISION float CURVATURE_Y;
|
||||
uniform COMPAT_PRECISION float MASK_BRIGHTNESS;
|
||||
uniform COMPAT_PRECISION float SCANLINE_WEIGHT;
|
||||
uniform COMPAT_PRECISION float SCANLINE_GAP_BRIGHTNESS;
|
||||
uniform COMPAT_PRECISION float BLOOM_FACTOR;
|
||||
uniform COMPAT_PRECISION float INPUT_GAMMA;
|
||||
uniform COMPAT_PRECISION float OUTPUT_GAMMA;
|
||||
#else
|
||||
#define CURVATURE_X 0.05
|
||||
#define CURVATURE_Y 0.1
|
||||
#define MASK_BRIGHTNESS 0.80
|
||||
#define SCANLINE_WEIGHT 6.0
|
||||
#define SCANLINE_GAP_BRIGHTNESS 0.12
|
||||
#define BLOOM_FACTOR 3.5
|
||||
#define INPUT_GAMMA 2.4
|
||||
#define OUTPUT_GAMMA 2.2
|
||||
#endif
|
||||
|
||||
/* COMPATIBILITY
|
||||
- GLSL compilers
|
||||
*/
|
||||
|
||||
//uniform vec2 TextureSize;
|
||||
#if defined(CURVATURE)
|
||||
varying vec2 screenScale;
|
||||
#endif
|
||||
varying vec2 TEX0;
|
||||
varying float filterWidth;
|
||||
|
||||
#if defined(VERTEX)
|
||||
//uniform mat4 MVPMatrix;
|
||||
//attribute vec4 VertexCoord;
|
||||
//attribute vec2 TexCoord;
|
||||
//uniform vec2 InputSize;
|
||||
//uniform vec2 OutputSize;
|
||||
|
||||
void main()
|
||||
{
|
||||
#if defined(CURVATURE)
|
||||
screenScale = vec2(1.0, 1.0); //TextureSize / InputSize;
|
||||
#endif
|
||||
filterWidth = (768.0 / 240.0) / 3.0;
|
||||
TEX0 = vec2(gl_MultiTexCoord0.x, 1.0-gl_MultiTexCoord0.y)*1.0001;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
}
|
||||
#elif defined(FRAGMENT)
|
||||
|
||||
uniform sampler2D Texture;
|
||||
|
||||
#if defined(CURVATURE)
|
||||
vec2 Distort(vec2 coord)
|
||||
{
|
||||
vec2 CURVATURE_DISTORTION = vec2(CURVATURE_X, CURVATURE_Y);
|
||||
// Barrel distortion shrinks the display area a bit, this will allow us to counteract that.
|
||||
vec2 barrelScale = 1.0 - (0.23 * CURVATURE_DISTORTION);
|
||||
coord *= screenScale;
|
||||
coord -= vec2(0.5);
|
||||
float rsq = coord.x * coord.x + coord.y * coord.y;
|
||||
coord += coord * (CURVATURE_DISTORTION * rsq);
|
||||
coord *= barrelScale;
|
||||
if (abs(coord.x) >= 0.5 || abs(coord.y) >= 0.5)
|
||||
coord = vec2(-1.0); // If out of bounds, return an invalid value.
|
||||
else
|
||||
{
|
||||
coord += vec2(0.5);
|
||||
coord /= screenScale;
|
||||
}
|
||||
|
||||
return coord;
|
||||
}
|
||||
#endif
|
||||
|
||||
float CalcScanLineWeight(float dist)
|
||||
{
|
||||
return max(1.0-dist*dist*SCANLINE_WEIGHT, SCANLINE_GAP_BRIGHTNESS);
|
||||
}
|
||||
|
||||
float CalcScanLine(float dy)
|
||||
{
|
||||
float scanLineWeight = CalcScanLineWeight(dy);
|
||||
#if defined(MULTISAMPLE)
|
||||
scanLineWeight += CalcScanLineWeight(dy-filterWidth);
|
||||
scanLineWeight += CalcScanLineWeight(dy+filterWidth);
|
||||
scanLineWeight *= 0.3333333;
|
||||
#endif
|
||||
return scanLineWeight;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 TextureSize = vec2(320.0, 240.0);
|
||||
#if defined(CURVATURE)
|
||||
vec2 texcoord = Distort(TEX0);
|
||||
if (texcoord.x < 0.0)
|
||||
gl_FragColor = vec4(0.0);
|
||||
else
|
||||
#else
|
||||
vec2 texcoord = TEX0;
|
||||
#endif
|
||||
{
|
||||
vec2 texcoordInPixels = texcoord * TextureSize;
|
||||
#if defined(SHARPER)
|
||||
vec2 tempCoord = floor(texcoordInPixels) + 0.5;
|
||||
vec2 coord = tempCoord / TextureSize;
|
||||
vec2 deltas = texcoordInPixels - tempCoord;
|
||||
float scanLineWeight = CalcScanLine(deltas.y);
|
||||
vec2 signs = sign(deltas);
|
||||
deltas.x *= 2.0;
|
||||
deltas = deltas * deltas;
|
||||
deltas.y = deltas.y * deltas.y;
|
||||
deltas.x *= 0.5;
|
||||
deltas.y *= 8.0;
|
||||
deltas /= TextureSize;
|
||||
deltas *= signs;
|
||||
vec2 tc = coord + deltas;
|
||||
#else
|
||||
float tempY = floor(texcoordInPixels.y) + 0.5;
|
||||
float yCoord = tempY / TextureSize.y;
|
||||
float dy = texcoordInPixels.y - tempY;
|
||||
float scanLineWeight = CalcScanLine(dy);
|
||||
float signY = sign(dy);
|
||||
dy = dy * dy;
|
||||
dy = dy * dy;
|
||||
dy *= 8.0;
|
||||
dy /= TextureSize.y;
|
||||
dy *= signY;
|
||||
vec2 tc = vec2(texcoord.x, yCoord + dy);
|
||||
#endif
|
||||
|
||||
vec3 colour = texture2D(Texture, tc).rgb;
|
||||
|
||||
#if defined(SCANLINES)
|
||||
#if defined(GAMMA)
|
||||
#if defined(FAKE_GAMMA)
|
||||
colour = colour * colour;
|
||||
#else
|
||||
colour = pow(colour, vec3(INPUT_GAMMA));
|
||||
#endif
|
||||
#endif
|
||||
scanLineWeight *= BLOOM_FACTOR;
|
||||
colour *= scanLineWeight;
|
||||
|
||||
#if defined(GAMMA)
|
||||
#if defined(FAKE_GAMMA)
|
||||
colour = sqrt(colour);
|
||||
#else
|
||||
colour = pow(colour, vec3(1.0/OUTPUT_GAMMA));
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if MASK_TYPE == 0
|
||||
gl_FragColor = vec4(colour, 1.0);
|
||||
#else
|
||||
#if MASK_TYPE == 1
|
||||
float whichMask = fract((gl_FragCoord.x*1.0001) * 0.5);
|
||||
vec3 mask;
|
||||
if (whichMask < 0.5)
|
||||
mask = vec3(MASK_BRIGHTNESS, 1.0, MASK_BRIGHTNESS);
|
||||
else
|
||||
mask = vec3(1.0, MASK_BRIGHTNESS, 1.0);
|
||||
#elif MASK_TYPE == 2
|
||||
float whichMask = fract((gl_FragCoord.x*1.0001) * 0.3333333);
|
||||
vec3 mask = vec3(MASK_BRIGHTNESS, MASK_BRIGHTNESS, MASK_BRIGHTNESS);
|
||||
if (whichMask < 0.3333333)
|
||||
mask.x = 1.0;
|
||||
else if (whichMask < 0.6666666)
|
||||
mask.y = 1.0;
|
||||
else
|
||||
mask.z = 1.0;
|
||||
#endif
|
||||
|
||||
gl_FragColor = vec4(colour * mask, 1.0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -97,7 +97,6 @@ void main()
|
||||
#if defined(CURVATURE)
|
||||
screenScale = vec2(1.0, 1.0); //TextureSize / InputSize;
|
||||
#endif
|
||||
//filterWidth = (768.0 / 240.0) / 3.0;
|
||||
filterWidth = (768.0 / 256.0) / 3.0;
|
||||
TEX0 = vec2(gl_MultiTexCoord0.x, 1.0-gl_MultiTexCoord0.y)*1.0001;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
BIN
data/sound/continue_clock.wav
Normal file
BIN
data/sound/debian_drop.wav
Normal file
BIN
data/sound/debian_pickup.wav
Normal file
BIN
data/sound/game_start.wav
Normal file
BIN
data/sound/logo.wav
Normal file
BIN
data/sound/tabe.wav
Normal file
BIN
data/sound/tabe_hit.wav
Normal file
BIN
data/sound/voice_coffee.wav
Normal file
BIN
data/sound/voice_get_ready.wav
Normal file
BIN
data/sound/voice_no.wav
Normal file
BIN
data/sound/voice_power_up.wav
Normal file
BIN
data/sound/walk.wav
Normal file
2
release/coffee.rc
Normal file
@@ -0,0 +1,2 @@
|
||||
// coffee.rc
|
||||
IDI_ICON1 ICON "icon.ico"
|
||||
BIN
release/coffee.res
Normal file
BIN
release/icon.ico
Normal file
|
After Width: | Height: | Size: 38 KiB |
@@ -2,12 +2,13 @@
|
||||
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
|
||||
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
|
||||
#include <algorithm> // Para clamp, max
|
||||
#include "moving_sprite.h" // Para MovingSprite
|
||||
#include "param.h" // Para Param, ParamBackground, param
|
||||
#include "resource.h" // Para Resource
|
||||
#include "screen.h" // Para Screen
|
||||
#include "sprite.h" // Para Sprite
|
||||
#include "texture.h" // Para Texture
|
||||
#include <cmath>
|
||||
#include "moving_sprite.h" // Para MovingSprite
|
||||
#include "param.h" // Para Param, ParamBackground, param
|
||||
#include "resource.h" // Para Resource
|
||||
#include "screen.h" // Para Screen
|
||||
#include "sprite.h" // Para Sprite
|
||||
#include "texture.h" // Para Texture
|
||||
|
||||
// Constructor
|
||||
Background::Background()
|
||||
@@ -18,16 +19,22 @@ Background::Background()
|
||||
bottom_clouds_texture_(Resource::get()->getTexture("game_clouds2.png")),
|
||||
grass_texture_(Resource::get()->getTexture("game_grass.png")),
|
||||
gradients_texture_(Resource::get()->getTexture("game_sky_colors.png")),
|
||||
sun_texture_(Resource::get()->getTexture("game_sun.png")),
|
||||
moon_texture_(Resource::get()->getTexture("game_moon.png")),
|
||||
|
||||
rect_({0, 0, gradients_texture_->getWidth() / 2, gradients_texture_->getHeight() / 2}),
|
||||
src_rect_({0, 0, 320, 240}),
|
||||
dst_rect_({0, 0, 320, 240}),
|
||||
base_(rect_.h),
|
||||
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_alpha),
|
||||
alpha_color_text_temp_(param.background.attenuate_alpha)
|
||||
|
||||
{
|
||||
// Precalcula rutas
|
||||
createSunPath();
|
||||
createMoonPath();
|
||||
|
||||
// Inicializa variables
|
||||
{
|
||||
gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
|
||||
@@ -55,9 +62,11 @@ Background::Background()
|
||||
bottom_clouds_sprite_a_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_Rect){0, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight()});
|
||||
bottom_clouds_sprite_b_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_Rect){rect_.w, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight()});
|
||||
|
||||
buildings_sprite_ = std::make_unique<Sprite>(buildings_texture_, 0, 0, buildings_texture_->getWidth(), buildings_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
|
||||
@@ -79,6 +88,8 @@ Background::Background()
|
||||
|
||||
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
|
||||
@@ -88,7 +99,7 @@ Background::Background()
|
||||
// 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(color_);
|
||||
setColor(attenuate_color_);
|
||||
SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_);
|
||||
}
|
||||
|
||||
@@ -103,7 +114,7 @@ Background::~Background()
|
||||
void Background::update()
|
||||
{
|
||||
// Actualiza el valor de alpha_
|
||||
updateAlphaColorText();
|
||||
updateAlphaColorTexture();
|
||||
|
||||
// Actualiza las nubes
|
||||
updateClouds();
|
||||
@@ -114,6 +125,10 @@ void Background::update()
|
||||
// Calcula el valor de alpha_
|
||||
alpha_ = std::max((255 - (int)(255 * transition_)), 0);
|
||||
|
||||
// Mueve el sol
|
||||
sun_sprite_->setPosition(sun_path_.at(sun_index_));
|
||||
moon_sprite_->setPosition(moon_path_.at(moon_index_));
|
||||
|
||||
// Incrementa el contador
|
||||
++counter_;
|
||||
|
||||
@@ -181,6 +196,10 @@ void Background::fillCanvas()
|
||||
// Dibuja el gradiente de fondo
|
||||
renderGradient();
|
||||
|
||||
// Dibuja los astros
|
||||
sun_sprite_->render();
|
||||
moon_sprite_->render();
|
||||
|
||||
// Dibuja las nubes de arriba
|
||||
renderTopClouds();
|
||||
|
||||
@@ -250,13 +269,13 @@ void Background::setPos(SDL_Rect pos)
|
||||
// Establece el color_ de atenuación
|
||||
void Background::setColor(Color color)
|
||||
{
|
||||
color_ = color;
|
||||
attenuate_color_ = color;
|
||||
|
||||
// Colorea la textura
|
||||
auto temp = SDL_GetRenderTarget(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, color_texture_);
|
||||
|
||||
SDL_SetRenderDrawColor(renderer_, color_.r, color_.g, color_.b, 255);
|
||||
SDL_SetRenderDrawColor(renderer_, attenuate_color_.r, attenuate_color_.g, attenuate_color_.b, 255);
|
||||
SDL_RenderClear(renderer_);
|
||||
|
||||
SDL_SetRenderTarget(renderer_, temp);
|
||||
@@ -274,7 +293,7 @@ void Background::setAlpha(int alpha)
|
||||
}
|
||||
|
||||
// Actualiza el valor de alpha_
|
||||
void Background::updateAlphaColorText()
|
||||
void Background::updateAlphaColorTexture()
|
||||
{
|
||||
if (alpha_color_text_ == alpha_color_text_temp_)
|
||||
{
|
||||
@@ -322,4 +341,58 @@ void Background::updateClouds()
|
||||
{
|
||||
bottom_clouds_sprite_b_->setPosX(bottom_clouds_sprite_b_->getWidth());
|
||||
}
|
||||
}
|
||||
|
||||
// Precalcula el vector con el recorrido del sol
|
||||
void Background::createSunPath()
|
||||
{
|
||||
constexpr int CENTER_X = 170;
|
||||
const int center_y = base_ - 80;
|
||||
constexpr int RADIUS = 120;
|
||||
|
||||
// Generar puntos de la curva desde 90 a 180 grados
|
||||
for (double theta = M_PI / 2; theta <= M_PI; theta += 0.01)
|
||||
{
|
||||
int x = CENTER_X + static_cast<int>(RADIUS * cos(theta));
|
||||
int y = center_y - static_cast<int>(RADIUS * sin(theta));
|
||||
sun_path_.push_back({x, y});
|
||||
}
|
||||
|
||||
// Agregar puntos en línea recta después de la curva
|
||||
constexpr int EXTRA_PIXELS = 40;
|
||||
SDL_Point last_point = sun_path_.back();
|
||||
for (int i = 1; i <= EXTRA_PIXELS; ++i)
|
||||
{
|
||||
sun_path_.push_back({last_point.x, last_point.y + i});
|
||||
}
|
||||
}
|
||||
|
||||
// Precalcula el vector con el recorrido de la luna
|
||||
void Background::createMoonPath()
|
||||
{
|
||||
constexpr int CENTER_X = 100;
|
||||
const int center_y = base_ - 50;
|
||||
constexpr int RADIUS = 140;
|
||||
|
||||
// Generar puntos de la curva desde 0 a 90 grados
|
||||
for (double theta = 0; theta <= M_PI / 2; theta += 0.01)
|
||||
{
|
||||
int x = CENTER_X + static_cast<int>(RADIUS * cos(theta));
|
||||
int y = center_y - static_cast<int>(RADIUS * sin(theta));
|
||||
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));
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL_rect.h> // para SDL_Rect
|
||||
#include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture
|
||||
#include <memory> // para unique_ptr, shared_ptr
|
||||
#include "utils.h" // para Color
|
||||
class MovingSprite;
|
||||
class Sprite;
|
||||
class Texture;
|
||||
#include <SDL2/SDL_rect.h> // Para SDL_Rect, SDL_Point
|
||||
#include <SDL2/SDL_render.h> // Para SDL_Texture, SDL_Renderer
|
||||
#include <stddef.h> // Para size_t
|
||||
#include <memory> // Para unique_ptr, shared_ptr
|
||||
#include <vector> // Para vector
|
||||
#include "utils.h" // Para Color
|
||||
class MovingSprite; // lines 7-7
|
||||
class Sprite; // lines 8-8
|
||||
class Texture; // lines 9-9
|
||||
|
||||
/*
|
||||
Esta clase es la encargada de dibujar el fondo que aparece durante la sección
|
||||
@@ -51,6 +53,8 @@ private:
|
||||
std::shared_ptr<Texture> bottom_clouds_texture_; // Textura con las nubes de fondo
|
||||
std::shared_ptr<Texture> grass_texture_; // Textura con la hierba del suelo
|
||||
std::shared_ptr<Texture> gradients_texture_; // Textura con los diferentes colores de fondo del juego
|
||||
std::shared_ptr<Texture> sun_texture_; // Textura con el sol
|
||||
std::shared_ptr<Texture> moon_texture_; // Textura con la luna
|
||||
|
||||
std::unique_ptr<MovingSprite> top_clouds_sprite_a_; // Sprite para las nubes superiores
|
||||
std::unique_ptr<MovingSprite> top_clouds_sprite_b_; // Sprite para las nubes superiores
|
||||
@@ -60,26 +64,32 @@ private:
|
||||
std::unique_ptr<Sprite> buildings_sprite_; // Sprite con los edificios de fondo
|
||||
std::unique_ptr<Sprite> gradient_sprite_; // Sprite con los graficos del degradado de color de fondo
|
||||
std::unique_ptr<Sprite> grass_sprite_; // Sprite para la hierba
|
||||
std::unique_ptr<Sprite> sun_sprite_; // Sprite para el sol
|
||||
std::unique_ptr<Sprite> moon_sprite_; // Sprite para la luna
|
||||
|
||||
SDL_Texture *canvas_; // Textura para componer el fondo
|
||||
SDL_Texture *color_texture_; // Textura para atenuar el fondo
|
||||
|
||||
// Variables
|
||||
SDL_Rect gradient_rect_[4]; // Vector con las coordenadas de los 4 degradados para el cielo
|
||||
SDL_Rect top_clouds_rect_[4]; // Vector con las coordenadas de los 4 nubes de arriba
|
||||
SDL_Rect bottom_clouds_rect_[4]; // Vector con las coordenadas de los 4 nubes de abajo
|
||||
int gradient_number_ = 0; // Indica el número de degradado de fondo que se va a dibujar
|
||||
int alpha_ = 0; // Transparencia entre los dos degradados
|
||||
float clouds_speed_ = 0; // Velocidad a la que se desplazan las nubes
|
||||
float transition_ = 0; // Nivel de transición del fondo 0..1
|
||||
int counter_ = 0; // Contador interno
|
||||
SDL_Rect rect_; // Tamaño del objeto fondo
|
||||
SDL_Rect src_rect_; // Parte del objeto fondo que se va a dibujará en pantalla
|
||||
SDL_Rect dst_rect_; // Posición donde dibujar la parte del objeto fondo que se dibujará en pantalla
|
||||
int base_; // Linea de fondo coincidente con el area inferior de la zona de juego
|
||||
Color color_; // Color para atenuar el fondo
|
||||
int alpha_color_text_; // Alpha para atenuar el fondo
|
||||
int alpha_color_text_temp_; // Valor temporal para hacer la transición de alpha
|
||||
SDL_Rect gradient_rect_[4]; // Vector con las coordenadas de los 4 degradados para el cielo
|
||||
SDL_Rect top_clouds_rect_[4]; // Vector con las coordenadas de los 4 nubes de arriba
|
||||
SDL_Rect bottom_clouds_rect_[4]; // Vector con las coordenadas de los 4 nubes de abajo
|
||||
int gradient_number_ = 0; // Indica el número de degradado de fondo que se va a dibujar
|
||||
int alpha_ = 0; // Transparencia entre los dos degradados
|
||||
float clouds_speed_ = 0; // Velocidad a la que se desplazan las nubes
|
||||
float transition_ = 0; // Nivel de transición del fondo 0..1
|
||||
int counter_ = 0; // Contador interno
|
||||
SDL_Rect rect_; // Tamaño del objeto fondo
|
||||
SDL_Rect src_rect_; // Parte del objeto fondo que se va a dibujará en pantalla
|
||||
SDL_Rect dst_rect_; // Posición donde dibujar la parte del objeto fondo que se dibujará en pantalla
|
||||
int base_; // Linea de fondo coincidente con el area inferior de la zona de juego
|
||||
Color attenuate_color_; // Color para atenuar el fondo
|
||||
int alpha_color_text_; // Alpha para atenuar el fondo
|
||||
int alpha_color_text_temp_; // Valor temporal para hacer la transición de alpha
|
||||
std::vector<SDL_Point> sun_path_; // Vector con el recorrido del sol
|
||||
std::vector<SDL_Point> moon_path_; // Vector con el recorrido de la luna
|
||||
size_t sun_index_ = 0; // Posición del vector del recorrido del sol
|
||||
size_t moon_index_ = 0; // Posición del vector del recorrido de la luna
|
||||
|
||||
// Dibuja el gradiente de fondo
|
||||
void renderGradient();
|
||||
@@ -94,11 +104,17 @@ private:
|
||||
void fillCanvas();
|
||||
|
||||
// Actualiza el valor de alpha
|
||||
void updateAlphaColorText();
|
||||
void updateAlphaColorTexture();
|
||||
|
||||
// Actualiza las nubes
|
||||
void updateClouds();
|
||||
|
||||
// Precalcula el vector con el recorrido del sol
|
||||
void createSunPath();
|
||||
|
||||
// Precalcula el vector con el recorrido de la luna
|
||||
void createMoonPath();
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
Background();
|
||||
@@ -132,4 +148,10 @@ public:
|
||||
|
||||
// Establece la transparencia de la atenuación
|
||||
void setAlpha(int alpha);
|
||||
|
||||
// Establece la posición del sol
|
||||
void setSunProgression(float progress);
|
||||
|
||||
// Establece la posición de la luna
|
||||
void setMoonProgression(float progress);
|
||||
};
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "param.h" // Para Param, param, ParamBalloon, ParamGame
|
||||
#include "sprite.h" // Para Sprite
|
||||
#include "texture.h" // Para Texture
|
||||
#include "resource.h"
|
||||
#include "jail_audio.h"
|
||||
|
||||
// Constructor
|
||||
Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel_x, float speed, Uint16 creation_timer, SDL_Rect play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
|
||||
@@ -36,6 +38,7 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
|
||||
power_ = BALLOON_POWER[index];
|
||||
menace_ = BALLOON_MENACE[index];
|
||||
score_ = BALLOON_SCORE[index];
|
||||
sound_ = BALLOON_SOUND[index];
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -50,14 +53,16 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
|
||||
power_ = BALLOON_POWER[index];
|
||||
menace_ = BALLOON_MENACE[index];
|
||||
score_ = BALLOON_SCORE[index];
|
||||
sound_ = BALLOON_SOUND[index];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case BalloonType::POWERBALL:
|
||||
{
|
||||
const int index = 3;
|
||||
constexpr int index = 3;
|
||||
h_ = w_ = BALLOON_SIZE[4];
|
||||
sound_ = BALLOON_SOUND[3];
|
||||
power_ = score_ = menace_ = 0;
|
||||
|
||||
vy_ = 0;
|
||||
@@ -102,14 +107,27 @@ void Balloon::render()
|
||||
{
|
||||
if (type_ == BalloonType::POWERBALL)
|
||||
{
|
||||
// Renderizado para la PowerBall
|
||||
SDL_Point p = {24, 24};
|
||||
sprite_->setRotatingCenter(&p);
|
||||
sprite_->render();
|
||||
// Renderiza el fondo azul
|
||||
{
|
||||
auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
|
||||
sp->setSpriteClip(0, 0, BALLOON_SIZE[4], BALLOON_SIZE[4]);
|
||||
sp->render();
|
||||
}
|
||||
|
||||
// Renderiza la estrella
|
||||
if (!invulnerable_)
|
||||
{
|
||||
SDL_Point p = {24, 24};
|
||||
sprite_->setRotatingCenter(&p);
|
||||
sprite_->render();
|
||||
}
|
||||
|
||||
// Añade la máscara del borde y los reflejos
|
||||
auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
|
||||
sp->setSpriteClip(BALLOON_SIZE[4], 0, BALLOON_SIZE[4], BALLOON_SIZE[4]);
|
||||
sp->render();
|
||||
{
|
||||
auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
|
||||
sp->setSpriteClip(BALLOON_SIZE[4] * 2, 0, BALLOON_SIZE[4], BALLOON_SIZE[4]);
|
||||
sp->render();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -123,18 +141,8 @@ void Balloon::render()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bouncing_.enabled)
|
||||
{
|
||||
// Renderizado con efecto de bouncing
|
||||
sprite_->setPos(x_ + bouncing_.despX, y_ + bouncing_.despY);
|
||||
sprite_->render();
|
||||
// sprite_->setPos(x_ - bouncing_.despX, y_ - bouncing_.despY);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Renderizado normal
|
||||
sprite_->render();
|
||||
}
|
||||
// Renderizado normal
|
||||
sprite_->render();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,9 +159,10 @@ void Balloon::move()
|
||||
// Colisión en las partes laterales de la zona de juego
|
||||
const int clip = 2;
|
||||
const float min_x = play_area_.x - clip;
|
||||
const float max_x = play_area_.w - w_ + clip;
|
||||
const float max_x = play_area_.x + play_area_.w - w_ + clip;
|
||||
if (x_ < min_x || x_ > max_x)
|
||||
{
|
||||
playSound();
|
||||
x_ = std::clamp(x_, min_x, max_x);
|
||||
vx_ = -vx_;
|
||||
// Activa el efecto de rebote o invierte la rotación
|
||||
@@ -170,24 +179,13 @@ void Balloon::move()
|
||||
// Mueve el globo en vertical
|
||||
y_ += vy_ * speed_;
|
||||
|
||||
// Colisión en la parte superior de la zona de juego excepto para la PowerBall
|
||||
/*if (type_ != BalloonType::POWERBALL)
|
||||
{
|
||||
const int min_y = play_area_.y;
|
||||
if (y_ < min_y)
|
||||
{
|
||||
y_ = min_y;
|
||||
vy_ = -vy_;
|
||||
enableBounce();
|
||||
}
|
||||
}*/
|
||||
|
||||
// Colisión en la parte superior solo si el globo va de subida
|
||||
if (vy_ < 0)
|
||||
{
|
||||
const int min_y = play_area_.y;
|
||||
if (y_ < min_y)
|
||||
{
|
||||
playSound();
|
||||
y_ = min_y;
|
||||
vy_ = -vy_;
|
||||
enableBounce();
|
||||
@@ -195,15 +193,20 @@ void Balloon::move()
|
||||
}
|
||||
|
||||
// Colisión en la parte inferior de la zona de juego
|
||||
const int max_y = play_area_.h - h_;
|
||||
const int max_y = play_area_.y + play_area_.h - h_;
|
||||
if (y_ > max_y)
|
||||
{
|
||||
playSound();
|
||||
y_ = max_y;
|
||||
vy_ = -default_vy_;
|
||||
if (type_ != BalloonType::POWERBALL)
|
||||
{
|
||||
enableBounce();
|
||||
}
|
||||
else
|
||||
{
|
||||
setInvulnerable(false);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -230,12 +233,6 @@ void Balloon::move()
|
||||
}
|
||||
}
|
||||
|
||||
// Deshabilita el globo
|
||||
void Balloon::disable() { enabled_ = false; }
|
||||
|
||||
// Explosiona el globo
|
||||
void Balloon::pop() { disable(); }
|
||||
|
||||
// Actualiza al globo a su posicion, animación y controla los contadores
|
||||
void Balloon::update()
|
||||
{
|
||||
@@ -388,12 +385,10 @@ void Balloon::updateBounce()
|
||||
|
||||
zoomSprite();
|
||||
|
||||
const auto spriteClip = sprite_->getSpriteClip();
|
||||
bouncing_.despX = spriteClip.w * (1.0f - bouncing_.zoomW);
|
||||
bouncing_.despY = spriteClip.h * (1.0f - bouncing_.zoomH);
|
||||
|
||||
if (++bouncing_.counter / bouncing_.speed >= MAX_BOUNCE)
|
||||
{
|
||||
disableBounce();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,4 +407,13 @@ void Balloon::useNormalColor()
|
||||
{
|
||||
use_reversed_colors_ = false;
|
||||
setAnimation();
|
||||
}
|
||||
|
||||
// Reproduce el sonido al rebotar
|
||||
void Balloon::playSound()
|
||||
{
|
||||
if (sound_enabled_)
|
||||
{
|
||||
JA_PlaySound(Resource::get()->getSound(sound_));
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ constexpr int BALLOON_SCORE[] = {50, 100, 200, 400};
|
||||
constexpr int BALLOON_POWER[] = {1, 3, 7, 15};
|
||||
constexpr int BALLOON_MENACE[] = {1, 2, 4, 8};
|
||||
constexpr int BALLOON_SIZE[] = {10, 16, 26, 48, 49};
|
||||
const std::string BALLOON_SOUND[] = {"bubble1.wav", "bubble2.wav", "bubble3.wav", "bubble4.wav"};
|
||||
|
||||
// Tamaños de globo
|
||||
enum class BalloonSize : Uint8
|
||||
@@ -113,6 +114,8 @@ private:
|
||||
float speed_; // Velocidad a la que se mueven los globos
|
||||
Uint8 power_; // Cantidad de poder que alberga el globo
|
||||
SDL_Rect play_area_; // Zona por donde se puede mover el globo
|
||||
std::string sound_; // Archivo de sonido que hace el globo al rebotar
|
||||
bool sound_enabled_ = false; // Indica si ha de sonar el sonido del globo al rebotar
|
||||
|
||||
// Alinea el circulo de colisión con la posición del objeto globo
|
||||
void shiftColliders();
|
||||
@@ -138,6 +141,9 @@ private:
|
||||
// Establece la animación correspondiente
|
||||
void setAnimation();
|
||||
|
||||
// Reproduce el sonido al rebotar
|
||||
void playSound();
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
Balloon(
|
||||
@@ -164,12 +170,6 @@ public:
|
||||
// Actualiza la posición y estados del globo
|
||||
void move();
|
||||
|
||||
// Deshabilita el globo y pone a cero todos los valores
|
||||
void disable();
|
||||
|
||||
// Explosiona el globo
|
||||
void pop();
|
||||
|
||||
// Actualiza al globo a su posicion, animación y controla los contadores
|
||||
void update();
|
||||
|
||||
@@ -208,4 +208,6 @@ public:
|
||||
void setVelY(float vel_y) { vy_ = vel_y; }
|
||||
void setSpeed(float speed) { speed_ = speed; }
|
||||
void setInvulnerable(bool value) { invulnerable_ = value; }
|
||||
void setSound(bool value) { sound_enabled_ = value; }
|
||||
void disable() { enabled_ = false; }
|
||||
};
|
||||
@@ -107,11 +107,18 @@ void BalloonManager::deployBalloonFormation(int stage)
|
||||
last_balloon_deploy_ = formation;
|
||||
|
||||
const auto set = balloon_formations_->getSet(stage, formation);
|
||||
const auto numEnemies = set.number_of_balloons;
|
||||
for (int i = 0; i < numEnemies; ++i)
|
||||
const auto num_enemies = set.number_of_balloons;
|
||||
for (int i = 0; i < num_enemies; ++i)
|
||||
{
|
||||
auto p = set.init[i];
|
||||
createBalloon(p.x, p.y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter);
|
||||
createBalloon(
|
||||
p.x,
|
||||
p.y,
|
||||
p.type,
|
||||
p.size,
|
||||
p.vel_x,
|
||||
balloon_speed_,
|
||||
(creation_time_enabled_) ? p.creation_counter : 0);
|
||||
}
|
||||
|
||||
balloon_deploy_counter_ = 300;
|
||||
@@ -123,8 +130,8 @@ void BalloonManager::deployBalloonFormation(int stage)
|
||||
void BalloonManager::deploySet(int set_number)
|
||||
{
|
||||
const auto set = balloon_formations_->getSet(set_number);
|
||||
const auto numEnemies = set.number_of_balloons;
|
||||
for (int i = 0; i < numEnemies; ++i)
|
||||
const auto num_enemies = set.number_of_balloons;
|
||||
for (int i = 0; i < num_enemies; ++i)
|
||||
{
|
||||
auto p = set.init[i];
|
||||
createBalloon(p.x, p.y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter);
|
||||
@@ -135,8 +142,8 @@ void BalloonManager::deploySet(int set_number)
|
||||
void BalloonManager::deploySet(int set_number, int y)
|
||||
{
|
||||
const auto set = balloon_formations_->getSet(set_number);
|
||||
const auto numEnemies = set.number_of_balloons;
|
||||
for (int i = 0; i < numEnemies; ++i)
|
||||
const auto num_enemies = set.number_of_balloons;
|
||||
for (int i = 0; i < num_enemies; ++i)
|
||||
{
|
||||
auto p = set.init[i];
|
||||
createBalloon(p.x, y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter);
|
||||
@@ -173,49 +180,61 @@ int BalloonManager::calculateScreenPower()
|
||||
// Crea un globo nuevo en el vector de globos
|
||||
std::shared_ptr<Balloon> BalloonManager::createBalloon(float x, int y, BalloonType type, BalloonSize size, float velx, float speed, int creation_timer)
|
||||
{
|
||||
const int index = static_cast<int>(size);
|
||||
balloons_.emplace_back(std::make_shared<Balloon>(x, y, type, size, velx, speed, creation_timer, play_area_, balloon_textures_.at(index), balloon_animations_.at(index)));
|
||||
return balloons_.back();
|
||||
if (can_deploy_balloons_)
|
||||
{
|
||||
const int index = static_cast<int>(size);
|
||||
balloons_.emplace_back(std::make_shared<Balloon>(x, y, type, size, velx, speed, creation_timer, play_area_, balloon_textures_.at(index), balloon_animations_.at(index)));
|
||||
return balloons_.back();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Crea un globo a partir de otro globo
|
||||
void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction)
|
||||
{
|
||||
const float vx = direction == "LEFT" ? BALLOON_VELX_NEGATIVE : BALLOON_VELX_POSITIVE;
|
||||
const auto lower_size = static_cast<BalloonSize>(static_cast<int>(balloon->getSize()) - 1);
|
||||
auto b = createBalloon(0, balloon->getPosY(), balloon->getType(), lower_size, vx, balloon_speed_, 0);
|
||||
const int x = direction == "LEFT" ? balloon->getPosX() + (balloon->getWidth() / 3) : balloon->getPosX() + 2 * (balloon->getWidth() / 3);
|
||||
b->alignTo(x);
|
||||
b->setVelY(b->getType() == BalloonType::BALLOON ? -2.50f : BALLOON_VELX_NEGATIVE * 2.0f);
|
||||
if (balloon->isStopped())
|
||||
if (can_deploy_balloons_)
|
||||
{
|
||||
b->stop();
|
||||
}
|
||||
if (balloon->isUsingReversedColor())
|
||||
{
|
||||
b->useReverseColor();
|
||||
const float vx = direction == "LEFT" ? BALLOON_VELX_NEGATIVE : BALLOON_VELX_POSITIVE;
|
||||
const auto lower_size = static_cast<BalloonSize>(static_cast<int>(balloon->getSize()) - 1);
|
||||
auto b = createBalloon(0, balloon->getPosY(), balloon->getType(), lower_size, vx, balloon_speed_, 0);
|
||||
const int x = direction == "LEFT" ? balloon->getPosX() + (balloon->getWidth() / 3) : balloon->getPosX() + 2 * (balloon->getWidth() / 3);
|
||||
b->alignTo(x);
|
||||
b->setVelY(b->getType() == BalloonType::BALLOON ? -2.50f : BALLOON_VELX_NEGATIVE * 2.0f);
|
||||
if (balloon->isStopped())
|
||||
{
|
||||
b->stop();
|
||||
}
|
||||
if (balloon->isUsingReversedColor())
|
||||
{
|
||||
b->useReverseColor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Crea una PowerBall
|
||||
void BalloonManager::createPowerBall()
|
||||
{
|
||||
constexpr int values = 6;
|
||||
constexpr int pos_y = -BALLOON_SIZE[4];
|
||||
constexpr int creation_time = 0;
|
||||
if (can_deploy_balloons_)
|
||||
{
|
||||
constexpr int values = 6;
|
||||
constexpr int pos_y = -BALLOON_SIZE[4];
|
||||
constexpr int creation_time = 0;
|
||||
|
||||
const auto left = param.game.play_area.rect.x;
|
||||
const auto center = param.game.play_area.center_x - (BALLOON_SIZE[4] / 2);
|
||||
const auto right = param.game.play_area.rect.w - BALLOON_SIZE[4];
|
||||
const auto left = param.game.play_area.rect.x;
|
||||
const auto center = param.game.play_area.center_x - (BALLOON_SIZE[4] / 2);
|
||||
const auto right = param.game.play_area.rect.w - BALLOON_SIZE[4];
|
||||
|
||||
const auto luck = rand() % values;
|
||||
const int x[values] = {left, left, center, center, right, right};
|
||||
const float vx[values] = {BALLOON_VELX_POSITIVE, BALLOON_VELX_POSITIVE, BALLOON_VELX_POSITIVE, BALLOON_VELX_NEGATIVE, BALLOON_VELX_NEGATIVE, BALLOON_VELX_NEGATIVE};
|
||||
const auto luck = rand() % values;
|
||||
const int x[values] = {left, left, center, center, right, right};
|
||||
const float vx[values] = {BALLOON_VELX_POSITIVE, BALLOON_VELX_POSITIVE, BALLOON_VELX_POSITIVE, BALLOON_VELX_NEGATIVE, BALLOON_VELX_NEGATIVE, BALLOON_VELX_NEGATIVE};
|
||||
|
||||
balloons_.emplace_back(std::make_unique<Balloon>(x[luck], pos_y, BalloonType::POWERBALL, BalloonSize::SIZE4, vx[luck], balloon_speed_, creation_time, play_area_, balloon_textures_[4], balloon_animations_[4]));
|
||||
balloons_.emplace_back(std::make_unique<Balloon>(x[luck], pos_y, BalloonType::POWERBALL, BalloonSize::SIZE4, vx[luck], balloon_speed_, creation_time, play_area_, balloon_textures_[4], balloon_animations_[4]));
|
||||
balloons_.back()->setInvulnerable(true);
|
||||
|
||||
power_ball_enabled_ = true;
|
||||
power_ball_counter_ = POWERBALL_COUNTER;
|
||||
power_ball_enabled_ = true;
|
||||
power_ball_counter_ = POWERBALL_COUNTER;
|
||||
}
|
||||
}
|
||||
|
||||
// Establece la velocidad de los globos
|
||||
@@ -251,7 +270,7 @@ int BalloonManager::popBalloon(std::shared_ptr<Balloon> balloon)
|
||||
|
||||
// Agrega la explosión y elimina el globo
|
||||
explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize()));
|
||||
balloon->pop();
|
||||
balloon->disable();
|
||||
}
|
||||
|
||||
return score;
|
||||
@@ -287,7 +306,7 @@ int BalloonManager::destroyBalloon(std::shared_ptr<Balloon> &balloon)
|
||||
|
||||
// Destruye el globo
|
||||
explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize()));
|
||||
balloon->pop();
|
||||
balloon->disable();
|
||||
|
||||
return score;
|
||||
}
|
||||
@@ -302,8 +321,8 @@ int BalloonManager::destroyAllBalloons()
|
||||
}
|
||||
|
||||
balloon_deploy_counter_ = 300;
|
||||
JA_PlaySound(Resource::get()->getSound("powerball.wav"));
|
||||
Screen::get()->flash(flash_color, 100);
|
||||
JA_PlaySound(Resource::get()->getSound("power_ball_explosion.wav"));
|
||||
Screen::get()->flash(flash_color, 3);
|
||||
Screen::get()->shake();
|
||||
|
||||
return score;
|
||||
@@ -366,9 +385,33 @@ void BalloonManager::createTwoBigBalloons()
|
||||
deploySet(1);
|
||||
}
|
||||
|
||||
// Crea una disposición de globos aleatoria
|
||||
void BalloonManager::createRandomBalloons()
|
||||
{
|
||||
const int num_balloons = 2 + rand() % 4;
|
||||
for (int i = 0; i < num_balloons; ++i)
|
||||
{
|
||||
const float x = param.game.game_area.rect.x + (rand() % param.game.game_area.rect.w) - BALLOON_SIZE[3];
|
||||
const int y = param.game.game_area.rect.y + (rand() % 50);
|
||||
const BalloonSize size = static_cast<BalloonSize>(rand() % 4);
|
||||
const float vel_x = (rand() % 2 == 0) ? BALLOON_VELX_POSITIVE : BALLOON_VELX_NEGATIVE;
|
||||
const int creation_counter = 0;
|
||||
createBalloon(x, y, BalloonType::BALLOON, size, vel_x, balloon_speed_, creation_counter);
|
||||
}
|
||||
}
|
||||
|
||||
// Obtiene el nivel de ameza actual generado por los globos
|
||||
int BalloonManager::getMenace()
|
||||
{
|
||||
return std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon)
|
||||
{ return sum + (balloon->isEnabled() ? balloon->getMenace() : 0); });
|
||||
}
|
||||
|
||||
// Establece el sonido de los globos
|
||||
void BalloonManager::setSounds(bool value)
|
||||
{
|
||||
for (auto &balloon : balloons_)
|
||||
{
|
||||
balloon->setSound(value);
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,8 @@ private:
|
||||
int power_ball_counter_ = 0; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
|
||||
int last_balloon_deploy_ = 0; // Guarda cual ha sido la última formación desplegada para no repetir;
|
||||
SDL_Rect play_area_ = param.game.play_area.rect; // Zona por donde se moveran los globos
|
||||
bool creation_time_enabled_ = true; // Indica si los globos se crean con tiempo
|
||||
bool can_deploy_balloons_ = true; // Indica si creará globos
|
||||
|
||||
// Inicializa
|
||||
void init();
|
||||
@@ -108,15 +110,24 @@ public:
|
||||
// Crea dos globos gordos
|
||||
void createTwoBigBalloons();
|
||||
|
||||
// Crea una disposición de globos aleatoria
|
||||
void createRandomBalloons();
|
||||
|
||||
// Obtiene el nivel de ameza actual generado por los globos
|
||||
int getMenace();
|
||||
|
||||
// Establece el sonido de los globos
|
||||
void setSounds(bool value);
|
||||
|
||||
// Getters
|
||||
float getBalloonSpeed() const { return balloon_speed_; }
|
||||
Balloons &getBalloons() { return balloons_; }
|
||||
int getNumBalloons() const { return balloons_.size(); }
|
||||
|
||||
// Setters
|
||||
void setDefaultBalloonSpeed(float speed) { default_balloon_speed_ = speed; }
|
||||
void resetBalloonSpeed() { setBalloonSpeed(default_balloon_speed_); }
|
||||
void setPlayArea(SDL_Rect play_area) { play_area_ = play_area; }
|
||||
void setCreationTimeEnabled(bool value) { creation_time_enabled_ = value; }
|
||||
void setDeployBalloons(bool value) { can_deploy_balloons_ = value; }
|
||||
};
|
||||
@@ -1,55 +1,64 @@
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
// IWYU pragma: no_include <bits/std_abs.h>
|
||||
#include "credits.h"
|
||||
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
|
||||
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT
|
||||
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
|
||||
#include <SDL2/SDL_rect.h> // Para SDL_Rect
|
||||
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
|
||||
#include <algorithm> // Para max, min, clamp
|
||||
#include <cstdlib> // Para abs
|
||||
#include <stdexcept> // Para runtime_error
|
||||
#include <string> // Para basic_string, string
|
||||
#include <vector> // Para vector
|
||||
#include "balloon_manager.h" // Para BalloonManager
|
||||
#include "global_inputs.h" // Para check
|
||||
#include "fade.h" // Para Fade, FadeType, FadeMode
|
||||
#include "global_inputs.h" // Para check, update
|
||||
#include "input.h" // Para Input
|
||||
#include "jail_audio.h" // Para JA_PlayMusic, JA_StopMusic
|
||||
#include "jail_audio.h" // Para JA_GetMusicState, JA_SetMusicVolume
|
||||
#include "lang.h" // Para getText
|
||||
#include "mouse.h" // Para handleEvent
|
||||
#include "param.h" // Para Param, ParamGame, param
|
||||
#include "player.h" // Para Player, PlayerState
|
||||
#include "resource.h" // Para Resource
|
||||
#include "screen.h" // Para Screen
|
||||
#include "section.h" // Para Name, name, Options, options
|
||||
#include "sprite.h" // Para Sprite
|
||||
#include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW
|
||||
#include "texture.h" // Para Texture
|
||||
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
|
||||
#include "utils.h" // Para Color, no_color, shdw_txt_color, Zone
|
||||
#include "player.h"
|
||||
#include "fade.h"
|
||||
#include "utils.h" // Para Color, Zone, shdw_txt_color, no_color
|
||||
|
||||
// Textos
|
||||
constexpr const char TEXT_COPYRIGHT[] = "@2020,2024 JailDesigner";
|
||||
constexpr const char TEXT_COPYRIGHT[] = "@2020,2025 JailDesigner";
|
||||
|
||||
// Constructor
|
||||
Credits::Credits()
|
||||
: balloon_manager_(std::make_unique<BalloonManager>()),
|
||||
text_texture_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
||||
canvas_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
||||
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::DIAGONAL)),
|
||||
fade_in_(std::make_unique<Fade>()),
|
||||
fade_out_(std::make_unique<Fade>())
|
||||
{
|
||||
if (!text_texture_)
|
||||
{
|
||||
throw std::runtime_error("Failed to create SDL texture for text.");
|
||||
}
|
||||
section::name = section::Name::CREDITS;
|
||||
top_black_rect_ = {play_area_.x, 0, play_area_.w, black_bars_size_};
|
||||
bottom_black_rect_ = {play_area_.x, param.game.game_area.rect.h - black_bars_size_, play_area_.w, black_bars_size_};
|
||||
balloon_manager_->setPlayArea(play_area_);
|
||||
|
||||
fade_in_->setColor(fade_color.r, fade_color.g, fade_color.b);
|
||||
fade_in_->setType(FadeType::FULLSCREEN);
|
||||
fade_in_->setPost(50);
|
||||
fade_in_->setPostDuration(50);
|
||||
fade_in_->setMode(FadeMode::IN);
|
||||
fade_in_->activate();
|
||||
|
||||
fade_out_->setColor(0, 0, 0);
|
||||
fade_out_->setType(FadeType::FULLSCREEN);
|
||||
fade_out_->setPost(400);
|
||||
fade_out_->setPostDuration(400);
|
||||
|
||||
initPlayers();
|
||||
SDL_SetTextureBlendMode(text_texture_, SDL_BLENDMODE_BLEND);
|
||||
fillTextTexture();
|
||||
// JA_PlayMusic(Resource::get()->getMusic("credits.ogg"));
|
||||
steps_ = std::abs((top_black_rect_.h - param.game.game_area.center_y - 1) + ((left_black_rect_.w - param.game.game_area.center_x) / 4));
|
||||
}
|
||||
|
||||
@@ -57,7 +66,9 @@ Credits::Credits()
|
||||
Credits::~Credits()
|
||||
{
|
||||
SDL_DestroyTexture(text_texture_);
|
||||
SDL_DestroyTexture(canvas_);
|
||||
resetVolume();
|
||||
JA_StopMusic();
|
||||
}
|
||||
|
||||
// Bucle principal
|
||||
@@ -75,20 +86,29 @@ void Credits::run()
|
||||
// Actualiza las variables
|
||||
void Credits::update()
|
||||
{
|
||||
if (SDL_GetTicks() - ticks_ > ticks_speed_)
|
||||
constexpr Uint32 TICKS_SPEED_ = 15;
|
||||
|
||||
if (SDL_GetTicks() - ticks_ > TICKS_SPEED_)
|
||||
{
|
||||
ticks_ = SDL_GetTicks();
|
||||
tiled_bg_->update();
|
||||
balloon_manager_->update();
|
||||
updateTextureDstRects();
|
||||
throwBalloons();
|
||||
for (auto &player : players_)
|
||||
const int repeat = want_to_pass_ ? 4 : 1;
|
||||
for (int i = 0; i < repeat; ++i)
|
||||
{
|
||||
player->update();
|
||||
tiled_bg_->update();
|
||||
balloon_manager_->update();
|
||||
updateTextureDstRects();
|
||||
throwBalloons();
|
||||
for (auto &player : players_)
|
||||
{
|
||||
player->update();
|
||||
}
|
||||
updateAllFades();
|
||||
++counter_;
|
||||
}
|
||||
updateAllFades();
|
||||
Screen::get()->update();
|
||||
++counter_;
|
||||
globalInputs::update();
|
||||
|
||||
fillCanvas();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,43 +118,11 @@ void Credits::render()
|
||||
// Prepara para empezar a dibujar en la textura de juego
|
||||
Screen::get()->start();
|
||||
|
||||
// Limpia la pantalla
|
||||
Screen::get()->clean();
|
||||
|
||||
// Dibuja el fondo, los globos y los jugadores
|
||||
tiled_bg_->render();
|
||||
balloon_manager_->render();
|
||||
for (auto const &player : players_)
|
||||
{
|
||||
player->render();
|
||||
}
|
||||
|
||||
// Dibuja los titulos de credito
|
||||
SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &credits_rect_src_, &credits_rect_dst_);
|
||||
|
||||
// Dibuja el mini_logo
|
||||
SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_);
|
||||
|
||||
// Dibuja los rectangulos negros
|
||||
// SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0x27, 0x27, 0x36, 255);
|
||||
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 255);
|
||||
SDL_RenderFillRect(Screen::get()->getRenderer(), &top_black_rect_);
|
||||
SDL_RenderFillRect(Screen::get()->getRenderer(), &bottom_black_rect_);
|
||||
SDL_RenderFillRect(Screen::get()->getRenderer(), &left_black_rect_);
|
||||
SDL_RenderFillRect(Screen::get()->getRenderer(), &right_black_rect_);
|
||||
|
||||
// Si el mini_logo está en su destino, lo dibuja encima del resto
|
||||
if (mini_logo_on_position_)
|
||||
{
|
||||
SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_);
|
||||
}
|
||||
|
||||
// Dibuja el fade sobre el resto
|
||||
fade_in_->render();
|
||||
fade_out_->render();
|
||||
// Copia la textura con la zona de juego a la pantalla
|
||||
SDL_RenderCopy(Screen::get()->getRenderer(), canvas_, nullptr, nullptr);
|
||||
|
||||
// Vuelca el contenido del renderizador en pantalla
|
||||
Screen::get()->blit();
|
||||
Screen::get()->render();
|
||||
}
|
||||
|
||||
// Comprueba el manejador de eventos
|
||||
@@ -152,6 +140,9 @@ void Credits::checkEvents()
|
||||
section::options = section::Options::QUIT_FROM_EVENT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Comprueba el cursor
|
||||
Mouse::handleEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +161,6 @@ void Credits::checkInput()
|
||||
{
|
||||
// Si todavía estan los creditos en marcha, se pasan solos a toda pastilla
|
||||
want_to_pass_ = true;
|
||||
ticks_speed_ = 3;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,10 +178,10 @@ void Credits::fillTextTexture()
|
||||
SDL_RenderClear(Screen::get()->getRenderer());
|
||||
|
||||
std::vector<std::string> texts = {
|
||||
"PROGRAMACIO I DISSENY",
|
||||
"GRAFICS",
|
||||
"MUSICA",
|
||||
"SONS",
|
||||
lang::getText(121),
|
||||
lang::getText(122),
|
||||
lang::getText(123),
|
||||
lang::getText(124),
|
||||
"JAILDESIGNER",
|
||||
"JAILDOCTOR (INTRO)",
|
||||
"ERIC MATYAS (SOUNDIMAGE.ORG)",
|
||||
@@ -257,15 +247,58 @@ void Credits::fillTextTexture()
|
||||
y += mini_logo_sprite->getHeight() + 3;
|
||||
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXT_COPYRIGHT, 1, no_color, 1, shdw_txt_color);
|
||||
|
||||
mini_logo_rect_dst_.h = mini_logo_rect_src_.h = mini_logo_sprite->getHeight() + 3 + text->getCharacterSize();
|
||||
|
||||
// Resetea el renderizador
|
||||
SDL_SetRenderTarget(Screen::get()->getRenderer(), nullptr);
|
||||
|
||||
// Actualiza las variables
|
||||
mini_logo_rect_dst_.h = mini_logo_rect_src_.h = mini_logo_sprite->getHeight() + 3 + text->getCharacterSize();
|
||||
credits_rect_dst_.y = param.game.game_area.rect.h;
|
||||
mini_logo_rect_dst_.y = credits_rect_dst_.y + credits_rect_dst_.h + 30;
|
||||
mini_logo_final_pos_ = param.game.game_area.center_y - mini_logo_rect_src_.h / 2;
|
||||
}
|
||||
|
||||
// Dibuja todos los sprites en la textura
|
||||
void Credits::fillCanvas()
|
||||
{
|
||||
// Cambia el destino del renderizador
|
||||
auto temp = SDL_GetRenderTarget(Screen::get()->getRenderer());
|
||||
SDL_SetRenderTarget(Screen::get()->getRenderer(), canvas_);
|
||||
|
||||
// Dibuja el fondo, los globos y los jugadores
|
||||
tiled_bg_->render();
|
||||
balloon_manager_->render();
|
||||
for (auto const &player : players_)
|
||||
{
|
||||
player->render();
|
||||
}
|
||||
|
||||
// Dibuja los titulos de credito
|
||||
SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &credits_rect_src_, &credits_rect_dst_);
|
||||
|
||||
// Dibuja el mini_logo
|
||||
SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_);
|
||||
|
||||
// Dibuja los rectangulos negros
|
||||
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 255);
|
||||
SDL_RenderFillRect(Screen::get()->getRenderer(), &top_black_rect_);
|
||||
SDL_RenderFillRect(Screen::get()->getRenderer(), &bottom_black_rect_);
|
||||
SDL_RenderFillRect(Screen::get()->getRenderer(), &left_black_rect_);
|
||||
SDL_RenderFillRect(Screen::get()->getRenderer(), &right_black_rect_);
|
||||
|
||||
// Si el mini_logo está en su destino, lo dibuja encima de lo anterior
|
||||
if (mini_logo_on_position_)
|
||||
{
|
||||
SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_);
|
||||
}
|
||||
|
||||
// Dibuja el fade sobre el resto de elementos
|
||||
fade_in_->render();
|
||||
fade_out_->render();
|
||||
|
||||
// Deja el renderizador apuntando donde estaba
|
||||
SDL_SetRenderTarget(Screen::get()->getRenderer(), temp);
|
||||
}
|
||||
|
||||
// Actualiza el destino de los rectangulos de las texturas
|
||||
void Credits::updateTextureDstRects()
|
||||
{
|
||||
@@ -312,12 +345,14 @@ void Credits::throwBalloons()
|
||||
const std::vector<int> sets = {0, 63, 25, 67, 17, 75, 13, 50};
|
||||
|
||||
if (counter_ > ((sets.size() - 1) * speed) * 3)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (counter_ % speed == 0)
|
||||
{
|
||||
const int index = (counter_ / speed) % sets.size();
|
||||
balloon_manager_->deploySet(sets.at(index), -50);
|
||||
balloon_manager_->deploySet(sets.at(index), -60);
|
||||
}
|
||||
|
||||
if (counter_ % (speed * 4) == 0 && counter_ > 0)
|
||||
@@ -356,7 +391,7 @@ void Credits::initPlayers()
|
||||
|
||||
// Crea los dos jugadores
|
||||
constexpr int player_width = 30;
|
||||
const int y = play_area_.h - player_width;
|
||||
const int y = play_area_.y + play_area_.h - player_width;
|
||||
constexpr bool demo = false;
|
||||
constexpr int away_distance = 700;
|
||||
players_.emplace_back(std::make_unique<Player>(1, play_area_.x - away_distance - player_width, y, demo, play_area_, player_textures.at(0), player_animations));
|
||||
@@ -443,7 +478,7 @@ void Credits::updateAllFades()
|
||||
fade_out_->update();
|
||||
if (fade_out_->hasEnded())
|
||||
{
|
||||
section::name = section::Name::LOGO;
|
||||
section::name = section::Name::HI_SCORE_TABLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL_rect.h> // Para SDL_Rect
|
||||
#include <SDL2/SDL_render.h> // Para SDL_Texture
|
||||
#include <SDL2/SDL_stdinc.h> // Para Uint32
|
||||
#include <memory> // Para unique_ptr
|
||||
#include "param.h"
|
||||
#include "options.h"
|
||||
class BalloonManager;
|
||||
class TiledBG;
|
||||
class Player;
|
||||
class Fade;
|
||||
#include <memory> // Para unique_ptr, shared_ptr
|
||||
#include <vector> // Para vector
|
||||
#include "options.h" // Para Options, OptionsAudio, OptionsMusic
|
||||
#include "param.h" // Para Param, ParamGame, param
|
||||
#include "utils.h" // Para Zone
|
||||
class BalloonManager; // lines 8-8
|
||||
class Fade; // lines 11-11
|
||||
class Player; // lines 10-10
|
||||
class TiledBG; // lines 9-9
|
||||
|
||||
constexpr int PLAY_AREA_HEIGHT = 200;
|
||||
|
||||
class Credits
|
||||
{
|
||||
@@ -16,24 +21,24 @@ private:
|
||||
// Objetos
|
||||
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
|
||||
SDL_Texture *text_texture_; // Textura con el texto
|
||||
SDL_Texture *canvas_; // Textura donde dibujarlo todo
|
||||
std::unique_ptr<TiledBG> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo
|
||||
std::unique_ptr<Fade> fade_in_; // Objeto para realizar el fundido de entrada
|
||||
std::unique_ptr<Fade> fade_out_; // Objeto para realizar el fundido de salida
|
||||
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
|
||||
|
||||
// Variables
|
||||
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
||||
Uint32 ticks_speed_ = 15; // Velocidad del bucle update
|
||||
Uint32 counter_ = 0; // Contador para la lógica de la clase
|
||||
Uint32 counter_pre_fade_ = 0; // Contador para activar el fundido final
|
||||
Uint32 counter_prevent_endless_ = 0; // Contador para evitar que el juego se quede para siempre en los creditos
|
||||
int black_bars_size_ = 28; // Tamaño de las barras negras
|
||||
int mini_logo_final_pos_ = 0; // Ubicación donde se detiene el minilogo
|
||||
bool fading_ = false; // Indica si se está realizando el fade final
|
||||
bool want_to_pass_ = false; // Indica si el jugador quiere saltarse los titulos de crédito
|
||||
bool mini_logo_on_position_ = false; // Indica si el minilogo ya se ha quedado en su posición
|
||||
int initial_volume_ = options.audio.music.volume; // Volumen actual al crear el objeto
|
||||
int steps_ = 0; // Cantidad de pasos a dar para ir reduciendo el audio
|
||||
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
||||
Uint32 counter_ = 0; // Contador para la lógica de la clase
|
||||
Uint32 counter_pre_fade_ = 0; // Contador para activar el fundido final
|
||||
Uint32 counter_prevent_endless_ = 0; // Contador para evitar que el juego se quede para siempre en los creditos
|
||||
int black_bars_size_ = (param.game.game_area.rect.h - PLAY_AREA_HEIGHT) / 2; // Tamaño de las barras negras
|
||||
int mini_logo_final_pos_ = 0; // Ubicación donde se detiene el minilogo
|
||||
bool fading_ = false; // Indica si se está realizando el fade final
|
||||
bool want_to_pass_ = false; // Indica si el jugador quiere saltarse los titulos de crédito
|
||||
bool mini_logo_on_position_ = false; // Indica si el minilogo ya se ha quedado en su posición
|
||||
int initial_volume_ = options.audio.music.volume; // Volumen actual al crear el objeto
|
||||
int steps_ = 0; // Cantidad de pasos a dar para ir reduciendo el audio
|
||||
|
||||
// Rectangulos
|
||||
SDL_Rect credits_rect_src_ = param.game.game_area.rect; // Rectangulo con el texto de los créditos (origen)
|
||||
@@ -44,8 +49,8 @@ private:
|
||||
param.game.game_area.rect.x,
|
||||
param.game.game_area.rect.y + black_bars_size_,
|
||||
param.game.game_area.rect.w,
|
||||
param.game.game_area.rect.h - black_bars_size_}; // Area visible para los creditos
|
||||
SDL_Rect top_black_rect_ = {play_area_.x, 0, play_area_.w, black_bars_size_}; // Rectangulo negro superior
|
||||
PLAY_AREA_HEIGHT}; // Area visible para los creditos
|
||||
SDL_Rect top_black_rect_ = {play_area_.x, param.game.game_area.rect.y, play_area_.w, black_bars_size_}; // Rectangulo negro superior
|
||||
SDL_Rect bottom_black_rect_ = {play_area_.x, param.game.game_area.rect.h - black_bars_size_, play_area_.w, black_bars_size_}; // Rectangulo negro inferior
|
||||
SDL_Rect left_black_rect_ = {play_area_.x, param.game.game_area.center_y - 1, 0, 2}; // Rectangulo negro situado a la izquierda
|
||||
SDL_Rect right_black_rect_ = {play_area_.x + play_area_.w, param.game.game_area.center_y - 1, 0, 2}; // Rectangulo negro situado a la derecha
|
||||
@@ -65,6 +70,9 @@ private:
|
||||
// Crea la textura con el texto
|
||||
void fillTextTexture();
|
||||
|
||||
// Dibuja todos los sprites en la textura
|
||||
void fillCanvas();
|
||||
|
||||
// Actualiza el destino de los rectangulos de las texturas
|
||||
void updateTextureDstRects();
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// IWYU pragma: no_include <bits/chrono.h>
|
||||
#include "director.h"
|
||||
#include <SDL2/SDL.h> // Para SDL_Init, SDL_Quit, SDL_INIT_EV...
|
||||
#include <SDL2/SDL_audio.h> // Para AUDIO_S16
|
||||
@@ -7,51 +8,42 @@
|
||||
#include <SDL2/SDL_hints.h> // Para SDL_SetHint, SDL_HINT_RENDER_DR...
|
||||
#include <SDL2/SDL_scancode.h> // Para SDL_SCANCODE_0, SDL_SCANCODE_DOWN
|
||||
#include <SDL2/SDL_stdinc.h> // Para SDL_bool, Uint32
|
||||
#include <bits/chrono.h> // Para duration, system_clock
|
||||
#include <errno.h> // Para errno, EEXIST, EACCES, ENAMETOO...
|
||||
#include <stdio.h> // Para printf, perror
|
||||
#include <sys/stat.h> // Para mkdir, stat, S_IRWXU
|
||||
#include <unistd.h> // Para getuid
|
||||
#include <algorithm> // Para min
|
||||
#include <cstdlib> // Para exit, EXIT_FAILURE, size_t, rand
|
||||
#include <iostream> // Para basic_ostream, operator<<, basi...
|
||||
#include <memory> // Para make_unique, unique_ptr
|
||||
#include <stdexcept> // Para runtime_error
|
||||
#include <string> // Para operator+, char_traits, allocator
|
||||
#include <vector> // Para vector
|
||||
#include "asset.h" // Para Asset, AssetType
|
||||
#include "credits.h"
|
||||
#include "dbgtxt.h" // Para dbg_init
|
||||
#include "game.h" // Para Game, GAME_MODE_DEMO_OFF, GAME_...
|
||||
#include "global_inputs.h" // Para init
|
||||
#include "hiscore_table.h" // Para HiScoreTable
|
||||
#include "input.h" // Para Input, InputType
|
||||
#include "instructions.h" // Para Instructions
|
||||
#include "intro.h" // Para Intro
|
||||
#include "jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundV...
|
||||
#include "lang.h" // Para Code, loadFromFile
|
||||
#include "logo.h" // Para Logo
|
||||
#include "manage_hiscore_table.h" // Para ManageHiScoreTable
|
||||
#include "notifier.h" // Para Notifier
|
||||
#include "on_screen_help.h" // Para OnScreenHelp
|
||||
#include "options.h" // Para Options, OptionsController, opt...
|
||||
#include "param.h" // Para Param, ParamGame, param, loadPa...
|
||||
#include "resource.h" // Para Resource
|
||||
#include "screen.h" // Para Screen
|
||||
#include "section.h" // Para Name, Options, name, options
|
||||
#include "title.h" // Para Title
|
||||
#include "utils.h" // Para Overrides, overrides
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <pwd.h> // para getpwuid, passwd
|
||||
#include <pwd.h> // Para getpwuid, passwd
|
||||
#endif
|
||||
|
||||
// Inicia la semilla aleatoria
|
||||
void initRand()
|
||||
{
|
||||
unsigned int seed = static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count());
|
||||
std::srand(seed);
|
||||
}
|
||||
#include <stdio.h> // Para printf, perror
|
||||
#include <sys/stat.h> // Para mkdir, stat, S_IRWXU
|
||||
#include <unistd.h> // Para getuid
|
||||
#include <algorithm> // Para min
|
||||
#include <chrono> // Para chrono
|
||||
#include <cstdlib> // Para exit, EXIT_FAILURE, size_t, rand
|
||||
#include <iostream> // Para basic_ostream, operator<<, basi...
|
||||
#include <memory> // Para make_unique, unique_ptr
|
||||
#include <stdexcept> // Para runtime_error
|
||||
#include <string> // Para operator+, char_traits, allocator
|
||||
#include <vector> // Para vector
|
||||
#include "asset.h" // Para Asset, AssetType
|
||||
#include "credits.h" // Para Credits
|
||||
#include "dbgtxt.h" // Para dbg_init
|
||||
#include "game.h" // Para Game, GAME_MODE_DEMO_OFF, GAME_...
|
||||
#include "hiscore_table.h" // Para HiScoreTable
|
||||
#include "input.h" // Para Input, InputType
|
||||
#include "instructions.h" // Para Instructions
|
||||
#include "intro.h" // Para Intro
|
||||
#include "jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundV...
|
||||
#include "lang.h" // Para Code, loadFromFile
|
||||
#include "logo.h" // Para Logo
|
||||
#include "manage_hiscore_table.h" // Para ManageHiScoreTable
|
||||
#include "notifier.h" // Para Notifier
|
||||
#include "on_screen_help.h" // Para OnScreenHelp
|
||||
#include "options.h" // Para Options, options, OptionsContro...
|
||||
#include "param.h" // Para Param, ParamGame, param, loadPa...
|
||||
#include "resource.h" // Para Resource
|
||||
#include "screen.h" // Para Screen
|
||||
#include "section.h" // Para Name, Options, name, options
|
||||
#include "title.h" // Para Title
|
||||
#include "utils.h" // Para Overrides, overrides
|
||||
|
||||
// Constructor
|
||||
Director::Director(int argc, const char *argv[])
|
||||
@@ -74,42 +66,36 @@ Director::Director(int argc, const char *argv[])
|
||||
|
||||
std::cout << "Game start" << std::endl;
|
||||
|
||||
initRand();
|
||||
// Inicia la semilla aleatoria
|
||||
unsigned int seed = static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count());
|
||||
std::srand(seed);
|
||||
|
||||
// Comprueba los parametros del programa
|
||||
checkProgramArguments(argc, argv);
|
||||
|
||||
// Crea la carpeta del sistema donde guardar datos
|
||||
// Crea la carpeta del sistema donde guardar los datos persistentes
|
||||
createSystemFolder("jailgames");
|
||||
createSystemFolder("jailgames/coffee_crisis_arcade_edition");
|
||||
|
||||
// Crea el objeto que controla los ficheros de recursos
|
||||
Asset::init(executable_path_);
|
||||
init();
|
||||
}
|
||||
|
||||
// Crea el indice de ficheros
|
||||
setFileList();
|
||||
Director::~Director()
|
||||
{
|
||||
close();
|
||||
std::cout << "\nBye!" << std::endl;
|
||||
}
|
||||
|
||||
// Carga el fichero de configuración
|
||||
loadOptionsFile(Asset::get()->get("config.txt"));
|
||||
// Inicializa todo
|
||||
void Director::init()
|
||||
{
|
||||
Asset::init(executable_path_); // Crea el objeto que controla los ficheros de recursos
|
||||
setFileList(); // Crea el indice de ficheros
|
||||
loadOptionsFile(Asset::get()->get("config.txt")); // Carga el fichero de configuración
|
||||
loadParams(); // Carga los parametros
|
||||
loadScoreFile(); // Carga el fichero de puntuaciones
|
||||
|
||||
// Carga los parametros para configurar el juego
|
||||
#ifdef ANBERNIC
|
||||
const std::string paramFilePath = asset->get("param_320x240.txt");
|
||||
#else
|
||||
const std::string paramFilePath = overrides.param_file == "--320x240" ? Asset::get()->get("param_320x240.txt") : Asset::get()->get("param_320x256.txt");
|
||||
#endif
|
||||
loadParamsFromFile(paramFilePath);
|
||||
|
||||
// Carga el fichero de puntuaciones
|
||||
{
|
||||
auto manager = std::make_unique<ManageHiScoreTable>(options.game.hi_score_table);
|
||||
if (overrides.clear_hi_score_table)
|
||||
manager->clear();
|
||||
else
|
||||
manager->loadFromFile(Asset::get()->get("score.bin"));
|
||||
}
|
||||
|
||||
// Inicializa todo
|
||||
// Inicializa y crea el resto de objetos
|
||||
initSDL();
|
||||
initJailAudio();
|
||||
dbg_init(renderer_);
|
||||
@@ -118,12 +104,12 @@ Director::Director(int argc, const char *argv[])
|
||||
Resource::init();
|
||||
Input::init(Asset::get()->get("gamecontrollerdb.txt"));
|
||||
bindInputs();
|
||||
Notifier::init(std::string(), Resource::get()->getText("8bithud"), Asset::get()->get("notify.wav"));
|
||||
Notifier::init(std::string(), Resource::get()->getText("8bithud"));
|
||||
OnScreenHelp::init();
|
||||
globalInputs::init();
|
||||
}
|
||||
|
||||
Director::~Director()
|
||||
// Cierra todo
|
||||
void Director::close()
|
||||
{
|
||||
saveOptionsFile(Asset::get()->get("config.txt"));
|
||||
|
||||
@@ -134,12 +120,42 @@ Director::~Director()
|
||||
Notifier::destroy();
|
||||
OnScreenHelp::destroy();
|
||||
|
||||
JA_Quit();
|
||||
|
||||
SDL_DestroyRenderer(renderer_);
|
||||
SDL_DestroyWindow(window_);
|
||||
|
||||
SDL_Quit();
|
||||
|
||||
std::cout << "\nBye!" << std::endl;
|
||||
#ifdef ARCADE
|
||||
shutdownSystem(section::options == section::Options::QUIT_WITH_CONTROLLER);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Carga los parametros
|
||||
void Director::loadParams()
|
||||
{
|
||||
// Carga los parametros para configurar el juego
|
||||
#ifdef ANBERNIC
|
||||
const std::string paramFilePath = asset->get("param_320x240.txt");
|
||||
#else
|
||||
const std::string paramFilePath = overrides.param_file == "--320x240" ? Asset::get()->get("param_320x240.txt") : Asset::get()->get("param_320x256.txt");
|
||||
#endif
|
||||
loadParamsFromFile(paramFilePath);
|
||||
}
|
||||
|
||||
// Carga el fichero de puntuaciones
|
||||
void Director::loadScoreFile()
|
||||
{
|
||||
auto manager = std::make_unique<ManageHiScoreTable>(options.game.hi_score_table);
|
||||
if (overrides.clear_hi_score_table)
|
||||
{
|
||||
manager->clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
manager->loadFromFile(Asset::get()->get("score.bin"));
|
||||
}
|
||||
}
|
||||
|
||||
// Asigna los botones y teclas al objeto Input
|
||||
@@ -166,7 +182,9 @@ void Director::bindInputs()
|
||||
Input::get()->bindKey(InputType::WINDOW_FULLSCREEN, SDL_SCANCODE_F3);
|
||||
Input::get()->bindKey(InputType::VIDEO_SHADERS, SDL_SCANCODE_F4);
|
||||
Input::get()->bindKey(InputType::MUTE, SDL_SCANCODE_F5);
|
||||
Input::get()->bindKey(InputType::SHOWINFO, SDL_SCANCODE_F6);
|
||||
Input::get()->bindKey(InputType::AUTO_FIRE, SDL_SCANCODE_F6);
|
||||
Input::get()->bindKey(InputType::CHANGE_LANG, SDL_SCANCODE_F7);
|
||||
Input::get()->bindKey(InputType::SHOWINFO, SDL_SCANCODE_F8);
|
||||
Input::get()->bindKey(InputType::RESET, SDL_SCANCODE_F10);
|
||||
|
||||
// Asigna botones a inputs
|
||||
@@ -280,8 +298,15 @@ bool Director::initSDL()
|
||||
}
|
||||
*/
|
||||
|
||||
// Obtiene información sobre la pantalla
|
||||
SDL_DisplayMode DM;
|
||||
SDL_GetCurrentDisplayMode(0, &DM);
|
||||
|
||||
// Calcula el máximo factor de zoom que se puede aplicar a la pantalla
|
||||
options.video.window.max_size = std::min(DM.w / param.game.width, DM.h / param.game.height);
|
||||
options.video.window.size = std::min(options.video.window.size, options.video.window.max_size);
|
||||
|
||||
// Muestra información sobre el tamaño de la pantalla y de la ventana de juego
|
||||
std::cout << "\nCurrent display mode: " << DM.w << "x" << DM.h << " @ " << DM.refresh_rate << "Hz" << std::endl;
|
||||
std::cout << "Window resolution : " << param.game.width << "x" << param.game.height << " x" << options.video.window.size << std::endl;
|
||||
|
||||
@@ -371,19 +396,32 @@ void Director::setFileList()
|
||||
Asset::get()->add(prefix + "/data/sound/bubble3.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/bubble4.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/bullet.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/coffeeout.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/hiscore.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/itemdrop.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/itempickup.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/player_collision.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/stage_change.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/title.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/clock.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/powerball.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/coffee_out.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/continue_clock.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/game_start.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/hi_score_achieved.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/item_drop.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/item_pickup.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/logo.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/notify.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/player_collision.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/power_ball_explosion.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/stage_change.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/tabe.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/title.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/voice_coffee.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/voice_get_ready.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/voice_no.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/voice_power_up.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/walk.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/debian_drop.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/debian_pickup.wav", AssetType::SOUND);
|
||||
Asset::get()->add(prefix + "/data/sound/tabe_hit.wav", AssetType::SOUND);
|
||||
|
||||
// Shaders
|
||||
Asset::get()->add(prefix + "/data/shaders/crtpi.glsl", AssetType::DATA);
|
||||
Asset::get()->add(prefix + "/data/shaders/crtpi_256.glsl", AssetType::DATA);
|
||||
Asset::get()->add(prefix + "/data/shaders/crtpi_240.glsl", AssetType::DATA);
|
||||
|
||||
// Texturas
|
||||
|
||||
@@ -422,6 +460,11 @@ void Director::setFileList()
|
||||
Asset::get()->add(prefix + "/data/gfx/bullet/bullet.png", AssetType::BITMAP);
|
||||
}
|
||||
|
||||
{ // Tabe
|
||||
Asset::get()->add(prefix + "/data/gfx/tabe/tabe.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/gfx/tabe/tabe.ani", AssetType::ANIMATION);
|
||||
}
|
||||
|
||||
{ // Juego
|
||||
Asset::get()->add(prefix + "/data/gfx/game/game_buildings.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/gfx/game/game_clouds1.png", AssetType::BITMAP);
|
||||
@@ -429,6 +472,8 @@ void Director::setFileList()
|
||||
Asset::get()->add(prefix + "/data/gfx/game/game_grass.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/gfx/game/game_power_meter.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/gfx/game/game_sky_colors.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/gfx/game/game_sun.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/gfx/game/game_moon.png", AssetType::BITMAP);
|
||||
}
|
||||
|
||||
{ // Intro
|
||||
@@ -452,6 +497,8 @@ void Director::setFileList()
|
||||
Asset::get()->add(prefix + "/data/gfx/item/item_clock.ani", AssetType::ANIMATION);
|
||||
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.ani", AssetType::ANIMATION);
|
||||
Asset::get()->add(prefix + "/data/gfx/item/item_debian.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/gfx/item/item_debian.ani", AssetType::ANIMATION);
|
||||
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.ani", AssetType::ANIMATION);
|
||||
}
|
||||
@@ -467,17 +514,17 @@ void Director::setFileList()
|
||||
|
||||
{ // Jugador 1
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player1.gif", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player1_one_coffee_palette.pal", AssetType::PALETTE);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player1_two_coffee_palette.pal", AssetType::PALETTE);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player1_all_white_palette.pal", AssetType::PALETTE);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player1_1_coffee_palette.gif", AssetType::PALETTE);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player1_2_coffee_palette.gif", AssetType::PALETTE);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player1_invencible_palette.gif", AssetType::PALETTE);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player1_power.png", AssetType::BITMAP);
|
||||
}
|
||||
|
||||
{ // Jugador 2
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player2.gif", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player2_one_coffee_palette.pal", AssetType::PALETTE);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player2_two_coffee_palette.pal", AssetType::PALETTE);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player2_all_white_palette.pal", AssetType::PALETTE);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player2_1_coffee_palette.gif", AssetType::PALETTE);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player2_2_coffee_palette.gif", AssetType::PALETTE);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player2_invencible_palette.gif", AssetType::PALETTE);
|
||||
Asset::get()->add(prefix + "/data/gfx/player/player2_power.png", AssetType::BITMAP);
|
||||
}
|
||||
|
||||
@@ -489,8 +536,6 @@ void Director::setFileList()
|
||||
// Fuentes de texto
|
||||
Asset::get()->add(prefix + "/data/font/8bithud.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/font/8bithud.txt", AssetType::FONT);
|
||||
Asset::get()->add(prefix + "/data/font/nokia.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/font/nokia.txt", AssetType::FONT);
|
||||
Asset::get()->add(prefix + "/data/font/smb2.gif", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/font/smb2_palette1.pal", AssetType::PALETTE);
|
||||
Asset::get()->add(prefix + "/data/font/smb2.txt", AssetType::FONT);
|
||||
@@ -498,6 +543,8 @@ void Director::setFileList()
|
||||
Asset::get()->add(prefix + "/data/font/04b_25.txt", AssetType::FONT);
|
||||
Asset::get()->add(prefix + "/data/font/04b_25_2x.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/font/04b_25_2x.txt", AssetType::FONT);
|
||||
Asset::get()->add(prefix + "/data/font/04b_25_metal.png", AssetType::BITMAP);
|
||||
Asset::get()->add(prefix + "/data/font/04b_25_grey.png", AssetType::BITMAP);
|
||||
|
||||
// Textos
|
||||
Asset::get()->add(prefix + "/data/lang/es_ES.txt", AssetType::LANG);
|
||||
@@ -655,6 +702,16 @@ void Director::runDemoGame()
|
||||
game->run();
|
||||
}
|
||||
|
||||
// Ejecuta la sección init
|
||||
void Director::runInit()
|
||||
{
|
||||
if (section::options == section::Options::RELOAD)
|
||||
{
|
||||
Resource::get()->reload();
|
||||
}
|
||||
section::name = section::Name::LOGO;
|
||||
}
|
||||
|
||||
int Director::run()
|
||||
{
|
||||
// Bucle principal
|
||||
@@ -663,7 +720,7 @@ int Director::run()
|
||||
switch (section::name)
|
||||
{
|
||||
case section::Name::INIT:
|
||||
section::name = section::Name::LOGO;
|
||||
runInit();
|
||||
break;
|
||||
case section::Name::LOGO:
|
||||
runLogo();
|
||||
@@ -714,11 +771,6 @@ int Director::run()
|
||||
// Habilita de nuevo los std::cout
|
||||
std::cout.rdbuf(orig_buf);
|
||||
#endif
|
||||
#ifdef ARCADE
|
||||
// Comprueba si ha de apagar el sistema
|
||||
if (section::options == section::Options::QUIT_WITH_CONTROLLER)
|
||||
shutdownSystem();
|
||||
#endif
|
||||
|
||||
return (section::options == section::Options::QUIT_WITH_CONTROLLER) ? 1 : 0;
|
||||
}
|
||||
@@ -746,20 +798,23 @@ std::string Director::getLangFile(lang::Code code)
|
||||
|
||||
#ifdef ARCADE
|
||||
// Apaga el sistema
|
||||
void Director::shutdownSystem()
|
||||
void Director::shutdownSystem(bool shouldShutdown)
|
||||
{
|
||||
if (shouldShutdown)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Apaga el sistema en Windows
|
||||
system("shutdown /s /t 0");
|
||||
// Apaga el sistema en Windows
|
||||
system("shutdown /s /t 5");
|
||||
#elif __APPLE__
|
||||
// Apaga el sistema en macOS
|
||||
system("sudo shutdown -h now");
|
||||
// Apaga el sistema en macOS
|
||||
system("sudo shutdown -h +0.1");
|
||||
#elif __linux__
|
||||
// Apaga el sistema en Linux
|
||||
system("shutdown -h now");
|
||||
// Apaga el sistema en Linux
|
||||
system("sleep 5; shutdown -h now");
|
||||
#else
|
||||
// Sistema operativo no compatible
|
||||
#error "Sistema operativo no soportado"
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif // ARCADE
|
||||
|
||||
@@ -67,13 +67,28 @@ private:
|
||||
// Ejecuta el juego en modo demo
|
||||
void runDemoGame();
|
||||
|
||||
// Ejecuta la sección init
|
||||
void runInit();
|
||||
|
||||
// Obtiene una fichero a partir de un lang::Code
|
||||
std::string getLangFile(lang::Code code);
|
||||
#ifdef ARCADE
|
||||
// Apaga el sistema
|
||||
void shutdownSystem();
|
||||
void shutdownSystem(bool shouldShutdown);
|
||||
#endif
|
||||
|
||||
// Inicializa todo
|
||||
void init();
|
||||
|
||||
// Cierra todo
|
||||
void close();
|
||||
|
||||
// Carga los parametros
|
||||
void loadParams();
|
||||
|
||||
// Carga el fichero de puntuaciones
|
||||
void loadScoreFile();
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
Director(int argc, const char *argv[]);
|
||||
|
||||
@@ -1,93 +1,164 @@
|
||||
#include "enter_name.h"
|
||||
#include "utils.h"
|
||||
#include <stddef.h> // Para size_t
|
||||
#include <algorithm> // Para max, min
|
||||
#include <cassert> // Para assert
|
||||
#include <iostream>
|
||||
|
||||
// Constructor
|
||||
EnterName::EnterName()
|
||||
{
|
||||
init();
|
||||
}
|
||||
: character_list_(" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()") {}
|
||||
|
||||
// Inicializa el objeto
|
||||
void EnterName::init()
|
||||
void EnterName::init(const std::string &name)
|
||||
{
|
||||
// Obtiene el puntero al nombre
|
||||
name_ = "A";
|
||||
// No se pasa ningún nombre
|
||||
if (name == "")
|
||||
{
|
||||
name_ = "A";
|
||||
position_ = 0;
|
||||
position_overflow_ = false;
|
||||
}
|
||||
// Se pasa un nombre
|
||||
else
|
||||
{
|
||||
name_ = name;
|
||||
position_ = name_.length();
|
||||
position_overflow_ = position_ >= NAME_LENGHT ? true : false;
|
||||
}
|
||||
|
||||
// Inicia la lista de caracteres permitidos
|
||||
character_list_ = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()";
|
||||
position_ = 0;
|
||||
num_characters_ = static_cast<int>(character_list_.size());
|
||||
|
||||
// Pone la lista de indices para que refleje el nombre
|
||||
updateCharacterIndex();
|
||||
|
||||
// Actualiza el nombre para que ocupe 8 espacios
|
||||
updateName();
|
||||
// Inicializa el vector de indices con el nombre y espacios
|
||||
initCharacterIndex(name_);
|
||||
}
|
||||
|
||||
// Incrementa la posición
|
||||
void EnterName::incPosition()
|
||||
{
|
||||
position_++;
|
||||
position_ = std::min(position_, NAME_LENGHT - 1);
|
||||
checkIfPositionHasBeenUsed();
|
||||
if (position_overflow_)
|
||||
{
|
||||
// Si ya estamos en overflow, no incrementamos más.
|
||||
return;
|
||||
}
|
||||
|
||||
++position_;
|
||||
|
||||
if (position_ >= NAME_LENGHT)
|
||||
{
|
||||
position_ = NAME_LENGHT; // Mantenemos en el índice máximo válido.
|
||||
position_overflow_ = true; // Activamos el flag de overflow.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copiamos el índice del carácter anterior si es posible.
|
||||
if (position_ > 0 && position_ < NAME_LENGHT)
|
||||
{
|
||||
character_index_[position_] = character_index_[position_ - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Si position_ es 0, inicializamos el carácter actual.
|
||||
character_index_[position_] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
updateNameFromCharacterIndex();
|
||||
}
|
||||
|
||||
// Decrementa la posición
|
||||
void EnterName::decPosition()
|
||||
{
|
||||
--position_;
|
||||
position_ = std::max(position_, 0);
|
||||
if (position_overflow_)
|
||||
{
|
||||
// Si estaba en overflow, lo desactivamos y mantenemos position_ en el máximo.
|
||||
position_overflow_ = false;
|
||||
position_ = NAME_LENGHT - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (position_ > 0)
|
||||
{
|
||||
--position_;
|
||||
|
||||
// Limpiamos el carácter siguiente si el índice es válido.
|
||||
if (position_ + 1 < NAME_LENGHT)
|
||||
{
|
||||
character_index_[position_ + 1] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Si position_ es 0, aseguramos que no vaya a ser negativo y limpiamos el carácter actual.
|
||||
position_ = 0;
|
||||
character_index_[position_] = 0;
|
||||
}
|
||||
|
||||
// Si position_ es menor que NAME_LENGHT, aseguramos que el overflow esté desactivado.
|
||||
if (position_ < NAME_LENGHT)
|
||||
{
|
||||
position_overflow_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
updateNameFromCharacterIndex();
|
||||
}
|
||||
|
||||
|
||||
// Incrementa el índice
|
||||
void EnterName::incIndex()
|
||||
{
|
||||
if (position_overflow_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
++character_index_[position_];
|
||||
if (character_index_[position_] >= num_characters_)
|
||||
if (character_index_[position_] >= static_cast<int>(character_list_.size()))
|
||||
{
|
||||
character_index_[position_] = 0;
|
||||
}
|
||||
updateName();
|
||||
updateNameFromCharacterIndex();
|
||||
}
|
||||
|
||||
// Decrementa el índice
|
||||
void EnterName::decIndex()
|
||||
{
|
||||
if (position_overflow_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
--character_index_[position_];
|
||||
if (character_index_[position_] < 0)
|
||||
{
|
||||
character_index_[position_] = num_characters_ - 1;
|
||||
character_index_[position_] = character_list_.size() - 1;
|
||||
}
|
||||
updateName();
|
||||
updateNameFromCharacterIndex();
|
||||
}
|
||||
|
||||
// Actualiza el nombre a partir de la lista de índices
|
||||
void EnterName::updateName()
|
||||
void EnterName::updateNameFromCharacterIndex()
|
||||
{
|
||||
name_.clear();
|
||||
for (int i = 0; i < NAME_LENGHT; ++i)
|
||||
{
|
||||
name_.push_back(character_list_[character_index_[i]]);
|
||||
}
|
||||
name_ = trim(name_);
|
||||
}
|
||||
|
||||
// Actualiza la variable
|
||||
void EnterName::updateCharacterIndex()
|
||||
void EnterName::initCharacterIndex(const std::string &name)
|
||||
{
|
||||
// Rellena de espacios y marca como no usados
|
||||
// Rellena de espacios
|
||||
for (size_t i = 0; i < NAME_LENGHT; ++i)
|
||||
{
|
||||
character_index_[i] = 0;
|
||||
position_has_been_used_[i] = false;
|
||||
}
|
||||
|
||||
// Coloca los índices en función de los caracteres que forman el nombre
|
||||
for (size_t i = 0; i < name_.size(); ++i)
|
||||
for (size_t i = 0; i < name.substr(0, NAME_LENGHT).size(); ++i)
|
||||
{
|
||||
character_index_[i] = findIndex(name_.at(i));
|
||||
position_has_been_used_[i] = true;
|
||||
character_index_[i] = findIndex(name.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,28 +169,4 @@ int EnterName::findIndex(char character) const
|
||||
if (character == character_list_.at(i))
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Obtiene el nombre
|
||||
std::string EnterName::getName() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
// Obtiene la posición que se está editando
|
||||
int EnterName::getPosition() const
|
||||
{
|
||||
return position_;
|
||||
}
|
||||
|
||||
// Comprueba la posición y copia el caracter si es necesario
|
||||
void EnterName::checkIfPositionHasBeenUsed()
|
||||
{
|
||||
auto used = position_has_been_used_[position_];
|
||||
|
||||
if (!used && position_ > 0)
|
||||
character_index_[position_] = character_index_[position_ - 1];
|
||||
|
||||
position_has_been_used_[position_] = true;
|
||||
updateName();
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "utils.h"
|
||||
|
||||
constexpr int NAME_LENGHT = 6;
|
||||
|
||||
@@ -16,25 +17,21 @@ constexpr int NAME_LENGHT = 6;
|
||||
class EnterName
|
||||
{
|
||||
private:
|
||||
std::string character_list_; // Lista de todos los caracteres permitidos
|
||||
std::string name_; // Nombre introducido
|
||||
int position_; // Posición a editar del nombre
|
||||
int num_characters_; // Cantidad de caracteres de la lista de caracteres
|
||||
int character_index_[NAME_LENGHT]; // Indice de la lista para cada uno de los caracteres que forman el nombre
|
||||
bool position_has_been_used_[NAME_LENGHT]; // Indica si en esa posición se ha puesto ya alguna letra. Se utiliza para replicar la letra anterior la primera vez
|
||||
std::string character_list_; // Lista de todos los caracteres permitidos
|
||||
std::string name_; // Nombre introducido
|
||||
int position_ = 0; // Posición a editar del nombre
|
||||
bool position_overflow_ = false; // Indica si hemos incrementado la posición más allá del límite
|
||||
int character_index_[NAME_LENGHT]; // Indice de la lista para cada uno de los caracteres que forman el nombre
|
||||
|
||||
// Actualiza el nombre a partir de la lista de índices
|
||||
void updateName();
|
||||
void updateNameFromCharacterIndex();
|
||||
|
||||
// Actualiza la variable
|
||||
void updateCharacterIndex();
|
||||
void initCharacterIndex(const std::string &name);
|
||||
|
||||
// Encuentra el indice de un caracter en "characterList"
|
||||
int findIndex(char character) const;
|
||||
|
||||
// Comprueba la posición y copia el caracter si es necesario
|
||||
void checkIfPositionHasBeenUsed();
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
EnterName();
|
||||
@@ -43,7 +40,7 @@ public:
|
||||
~EnterName() = default;
|
||||
|
||||
// Inicializa el objeto
|
||||
void init();
|
||||
void init(const std::string &name = "");
|
||||
|
||||
// Incrementa la posición
|
||||
void incPosition();
|
||||
@@ -57,9 +54,9 @@ public:
|
||||
// Decrementa el índice
|
||||
void decIndex();
|
||||
|
||||
// Obtiene el nombre
|
||||
std::string getName() const;
|
||||
|
||||
// Obtiene la posición que se está editando
|
||||
int getPosition() const;
|
||||
// Getters
|
||||
std::string getFinalName() const { return trim(name_.substr(0, position_)); }
|
||||
std::string getCurrentName() const { return trim(name_); }
|
||||
int getPosition() const { return position_; }
|
||||
bool getPositionOverflow() const { return position_overflow_; }
|
||||
};
|
||||
173
source/fade.cpp
@@ -30,15 +30,15 @@ void Fade::init()
|
||||
{
|
||||
type_ = FadeType::CENTER;
|
||||
mode_ = FadeMode::OUT;
|
||||
enabled_ = false;
|
||||
finished_ = false;
|
||||
counter_ = 0;
|
||||
r_ = 0;
|
||||
g_ = 0;
|
||||
b_ = 0;
|
||||
a_ = 0;
|
||||
post_duration_ = 20;
|
||||
post_duration_ = 0;
|
||||
post_counter_ = 0;
|
||||
pre_duration_ = 0;
|
||||
pre_counter_ = 0;
|
||||
num_squares_width_ = param.fade.num_squares_width;
|
||||
num_squares_height_ = param.fade.num_squares_height;
|
||||
fade_random_squares_delay_ = param.fade.random_squares_delay;
|
||||
@@ -48,15 +48,14 @@ void Fade::init()
|
||||
// Resetea algunas variables para volver a hacer el fade sin perder ciertos parametros
|
||||
void Fade::reset()
|
||||
{
|
||||
enabled_ = false;
|
||||
finished_ = false;
|
||||
state_ = FadeState::NOT_ENABLED;
|
||||
counter_ = 0;
|
||||
}
|
||||
|
||||
// Pinta una transición en pantalla
|
||||
void Fade::render()
|
||||
{
|
||||
if (enabled_ || finished_)
|
||||
if (state_ != FadeState::NOT_ENABLED)
|
||||
{
|
||||
SDL_RenderCopy(renderer_, backbuffer_, nullptr, nullptr);
|
||||
}
|
||||
@@ -65,7 +64,20 @@ void Fade::render()
|
||||
// Actualiza las variables internas
|
||||
void Fade::update()
|
||||
{
|
||||
if (enabled_)
|
||||
if (state_ == FadeState::PRE)
|
||||
{
|
||||
// Actualiza el contador
|
||||
if (pre_counter_ == pre_duration_)
|
||||
{
|
||||
state_ = FadeState::FADING;
|
||||
}
|
||||
else
|
||||
{
|
||||
pre_counter_++;
|
||||
}
|
||||
}
|
||||
|
||||
if (state_ == FadeState::FADING)
|
||||
{
|
||||
switch (type_)
|
||||
{
|
||||
@@ -79,7 +91,7 @@ void Fade::update()
|
||||
// Comprueba si ha terminado
|
||||
if (counter_ >= 255 / 4)
|
||||
{
|
||||
finished_ = true;
|
||||
state_ = FadeState::POST;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -100,6 +112,8 @@ void Fade::update()
|
||||
|
||||
SDL_RenderFillRect(renderer_, &rect1_);
|
||||
SDL_RenderFillRect(renderer_, &rect2_);
|
||||
|
||||
value_ = calculateValue(0, counter_, i);
|
||||
}
|
||||
|
||||
// Deja el renderizador como estaba
|
||||
@@ -108,7 +122,7 @@ void Fade::update()
|
||||
// Comprueba si ha terminado
|
||||
if ((counter_ * 4) > param.game.height)
|
||||
{
|
||||
finished_ = true;
|
||||
state_ = FadeState::POST;
|
||||
a_ = 255;
|
||||
}
|
||||
break;
|
||||
@@ -118,10 +132,11 @@ void Fade::update()
|
||||
{
|
||||
if (counter_ % fade_random_squares_delay_ == 0)
|
||||
{
|
||||
// Dibuja sobre el backbuffer_
|
||||
// Cambia el renderizador al backbuffer_ y modifica sus opciones
|
||||
auto temp = SDL_GetRenderTarget(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||
|
||||
SDL_BlendMode blend_mode;
|
||||
SDL_GetRenderDrawBlendMode(renderer_, &blend_mode);
|
||||
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
|
||||
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
||||
|
||||
@@ -133,16 +148,17 @@ void Fade::update()
|
||||
SDL_RenderFillRect(renderer_, &square_[index2]);
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
|
||||
|
||||
// Deja el renderizador como estaba
|
||||
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
|
||||
SDL_SetRenderTarget(renderer_, temp);
|
||||
}
|
||||
|
||||
value_ = calculateValue(0, static_cast<int>(num_squares_width_ * num_squares_height_), static_cast<int>(counter_ * fade_random_squares_mult_ / fade_random_squares_delay_));
|
||||
|
||||
// Comprueba si ha terminado
|
||||
if (counter_ * fade_random_squares_mult_ / fade_random_squares_delay_ >= num_squares_width_ * num_squares_height_)
|
||||
{
|
||||
finished_ = true;
|
||||
state_ = FadeState::POST;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -150,64 +166,88 @@ void Fade::update()
|
||||
|
||||
case FadeType::VENETIAN:
|
||||
{
|
||||
// Counter debe ir de 0 a 150
|
||||
// Counter debe ir de 0 a 150 <-- comprobar si esto es aún cierto
|
||||
if (square_.back().h < param.fade.venetian_size)
|
||||
{
|
||||
// Dibuja sobre el backbuffer_
|
||||
auto temp = SDL_GetRenderTarget(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||
|
||||
SDL_BlendMode blend_mode;
|
||||
SDL_GetRenderDrawBlendMode(renderer_, &blend_mode);
|
||||
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
|
||||
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
||||
for (auto rect : square_)
|
||||
|
||||
// Dibuja el cuadrado correspondiente
|
||||
for (const auto rect : square_)
|
||||
{
|
||||
SDL_RenderFillRect(renderer_, &rect);
|
||||
}
|
||||
|
||||
// Deja el renderizador como estaba
|
||||
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
|
||||
SDL_SetRenderTarget(renderer_, temp);
|
||||
|
||||
const auto h = counter_ / 3;
|
||||
for (int i = 0; i < (int)square_.size(); ++i)
|
||||
// Modifica el tamaño de los rectangulos
|
||||
const auto h = counter_ / 2;
|
||||
for (size_t i = 0; i < square_.size(); ++i)
|
||||
{
|
||||
// A partir del segundo rectangulo se pinta en función del anterior
|
||||
square_[i].h = i == 0 ? h : std::max(square_[i - 1].h - 3, 0);
|
||||
square_.at(i).h = i == 0 ? h : std::max(square_.at(i - 1).h - 2, 0);
|
||||
}
|
||||
|
||||
int completed = 0;
|
||||
for (const auto &square : square_)
|
||||
{
|
||||
if (square.h >= param.fade.venetian_size)
|
||||
{
|
||||
++completed;
|
||||
}
|
||||
}
|
||||
value_ = calculateValue(0, square_.size() - 1, completed);
|
||||
}
|
||||
else
|
||||
{
|
||||
finished_ = true;
|
||||
state_ = FadeState::POST;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (finished_)
|
||||
{
|
||||
// Actualiza el contador
|
||||
post_counter_ == post_duration_ ? enabled_ = false : post_counter_++;
|
||||
|
||||
// Deja el backbuffer_ todo del mismo color
|
||||
cleanBackbuffer(r_, g_, b_, a_);
|
||||
}
|
||||
|
||||
counter_++;
|
||||
}
|
||||
|
||||
if (state_ == FadeState::POST)
|
||||
{
|
||||
// Actualiza el contador
|
||||
if (post_counter_ == post_duration_)
|
||||
{
|
||||
state_ = FadeState::FINISHED;
|
||||
}
|
||||
else
|
||||
{
|
||||
post_counter_++;
|
||||
}
|
||||
|
||||
// Deja el backbuffer_ todo del mismo color
|
||||
cleanBackbuffer(r_, g_, b_, a_);
|
||||
}
|
||||
}
|
||||
|
||||
// Activa el fade
|
||||
void Fade::activate()
|
||||
{
|
||||
// Si ya está habilitado, no hay que volverlo a activar
|
||||
if (enabled_)
|
||||
if (state_ != FadeState::NOT_ENABLED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
enabled_ = true;
|
||||
finished_ = false;
|
||||
state_ = FadeState::PRE;
|
||||
counter_ = 0;
|
||||
post_counter_ = 0;
|
||||
pre_counter_ = 0;
|
||||
|
||||
switch (type_)
|
||||
{
|
||||
@@ -251,12 +291,8 @@ void Fade::activate()
|
||||
}
|
||||
|
||||
// Limpia la textura
|
||||
auto temp = SDL_GetRenderTarget(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||
a_ = mode_ == FadeMode::OUT ? 0 : 255;
|
||||
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
||||
SDL_RenderClear(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, temp);
|
||||
cleanBackbuffer(r_, g_, b_, a_);
|
||||
|
||||
// Deja el color listo para usar
|
||||
a_ = mode_ == FadeMode::OUT ? 255 : 0;
|
||||
@@ -266,12 +302,16 @@ void Fade::activate()
|
||||
|
||||
case FadeType::VENETIAN:
|
||||
{
|
||||
cleanBackbuffer(0, 0, 0, 0);
|
||||
rect1_ = {0, 0, param.game.width, 0};
|
||||
square_.clear();
|
||||
a_ = 255;
|
||||
// Limpia la textura
|
||||
a_ = mode_ == FadeMode::OUT ? 0 : 255;
|
||||
cleanBackbuffer(r_, g_, b_, a_);
|
||||
|
||||
// Deja el color listo para usar
|
||||
a_ = mode_ == FadeMode::OUT ? 255 : 0;
|
||||
|
||||
// Añade los cuadrados al vector
|
||||
square_.clear();
|
||||
rect1_ = {0, 0, param.game.width, 0};
|
||||
const int max = param.game.height / param.fade.venetian_size;
|
||||
|
||||
for (int i = 0; i < max; ++i)
|
||||
@@ -285,31 +325,6 @@ void Fade::activate()
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba si está activo
|
||||
bool Fade::isEnabled() const
|
||||
{
|
||||
return enabled_;
|
||||
}
|
||||
|
||||
// Comprueba si ha terminado la transicion
|
||||
bool Fade::hasEnded() const
|
||||
{
|
||||
// Ha terminado cuando ha finalizado la transición y se ha deshabilitado
|
||||
return !enabled_ && finished_;
|
||||
}
|
||||
|
||||
// Establece el tipo de fade
|
||||
void Fade::setType(FadeType type)
|
||||
{
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
// Establece el modo de fade
|
||||
void Fade::setMode(FadeMode mode)
|
||||
{
|
||||
mode_ = mode;
|
||||
}
|
||||
|
||||
// Establece el color del fade
|
||||
void Fade::setColor(Uint8 r, Uint8 g, Uint8 b)
|
||||
{
|
||||
@@ -318,12 +333,6 @@ void Fade::setColor(Uint8 r, Uint8 g, Uint8 b)
|
||||
b_ = b;
|
||||
}
|
||||
|
||||
// Establece la duración posterior
|
||||
void Fade::setPost(int value)
|
||||
{
|
||||
post_duration_ = value;
|
||||
}
|
||||
|
||||
// Limpia el backbuffer
|
||||
void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
|
||||
{
|
||||
@@ -337,4 +346,20 @@ void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
|
||||
|
||||
// Vuelve a dejar el renderizador como estaba
|
||||
SDL_SetRenderTarget(renderer_, temp);
|
||||
}
|
||||
|
||||
// Calcula el valor del estado del fade
|
||||
int Fade::calculateValue(int min, int max, int current)
|
||||
{
|
||||
if (current < min)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (current > max)
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
|
||||
return static_cast<int>(100.0 * (current - min) / (max - min));
|
||||
}
|
||||
@@ -21,6 +21,16 @@ enum class FadeMode : Uint8
|
||||
OUT = 1,
|
||||
};
|
||||
|
||||
// Estados del objeto
|
||||
enum class FadeState : Uint8
|
||||
{
|
||||
NOT_ENABLED = 0,
|
||||
PRE = 1,
|
||||
FADING = 2,
|
||||
POST = 3,
|
||||
FINISHED = 4,
|
||||
};
|
||||
|
||||
// Clase Fade
|
||||
class Fade
|
||||
{
|
||||
@@ -30,21 +40,23 @@ private:
|
||||
SDL_Texture *backbuffer_; // Textura para usar como backbuffer con SDL_TEXTUREACCESS_TARGET
|
||||
|
||||
// Variables
|
||||
FadeType type_; // Tipo de fade a realizar
|
||||
FadeMode mode_; // Modo de fade a realizar
|
||||
Uint16 counter_; // Contador interno
|
||||
bool enabled_; // Indica si el fade está activo
|
||||
bool finished_; // Indica si ha terminado la transición
|
||||
Uint8 r_, g_, b_, a_; // Colores para el fade
|
||||
SDL_Rect rect1_; // Rectangulo usado para crear los efectos de transición
|
||||
SDL_Rect rect2_; // Rectangulo usado para crear los efectos de transición
|
||||
int num_squares_width_; // Cantidad total de cuadraditos en horizontal para el FadeType::RANDOM_SQUARE
|
||||
int num_squares_height_; // Cantidad total de cuadraditos en vertical para el FadeType::RANDOM_SQUARE
|
||||
std::vector<SDL_Rect> square_; // Vector con los indices de los cuadrados para el FadeType::RANDOM_SQUARE
|
||||
int fade_random_squares_delay_; // Duración entre cada pintado de cuadrados
|
||||
int fade_random_squares_mult_; // Cantidad de cuadrados que se pintaran cada vez
|
||||
int post_duration_; // Duración posterior del fade tras finalizar
|
||||
int post_counter_; // Contador para la duración posterior
|
||||
FadeType type_; // Tipo de fade a realizar
|
||||
FadeMode mode_; // Modo de fade a realizar
|
||||
FadeState state_ = FadeState::NOT_ENABLED; // Estado actual del objeto
|
||||
Uint16 counter_; // Contador interno
|
||||
Uint8 r_, g_, b_, a_; // Colores para el fade
|
||||
SDL_Rect rect1_; // Rectangulo usado para crear los efectos de transición
|
||||
SDL_Rect rect2_; // Rectangulo usado para crear los efectos de transición
|
||||
int num_squares_width_; // Cantidad total de cuadraditos en horizontal para el FadeType::RANDOM_SQUARE
|
||||
int num_squares_height_; // Cantidad total de cuadraditos en vertical para el FadeType::RANDOM_SQUARE
|
||||
std::vector<SDL_Rect> square_; // Vector con los indices de los cuadrados para el FadeType::RANDOM_SQUARE
|
||||
int fade_random_squares_delay_; // Duración entre cada pintado de cuadrados
|
||||
int fade_random_squares_mult_; // Cantidad de cuadrados que se pintaran cada vez
|
||||
int post_duration_ = 0; // Duración posterior del fade tras finalizar
|
||||
int post_counter_ = 0; // Contador para la duración posterior
|
||||
int pre_duration_ = 0; // Duración previa del fade antes de iniciar
|
||||
int pre_counter_ = 0; // Contador para la duración previa
|
||||
int value_ = 0; // Estado actual del fade entre 0 y 100
|
||||
|
||||
// Inicializa las variables
|
||||
void init();
|
||||
@@ -52,6 +64,9 @@ private:
|
||||
// Limpia el backbuffer
|
||||
void cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
||||
|
||||
// Calcula el valor del estado del fade
|
||||
int calculateValue(int min, int max, int current);
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
Fade();
|
||||
@@ -71,21 +86,17 @@ public:
|
||||
// Activa el fade
|
||||
void activate();
|
||||
|
||||
// Comprueba si ha terminado la transicion
|
||||
bool hasEnded() const;
|
||||
|
||||
// Comprueba si está activo
|
||||
bool isEnabled() const;
|
||||
|
||||
// Establece el tipo de fade
|
||||
void setType(FadeType type);
|
||||
|
||||
// Establece el modo de fade
|
||||
void setMode(FadeMode mode);
|
||||
|
||||
// Establece el color del fade
|
||||
void setColor(Uint8 r, Uint8 g, Uint8 b);
|
||||
|
||||
// Establece la duración posterior
|
||||
void setPost(int value);
|
||||
// Getters
|
||||
int getValue() const { return value_; }
|
||||
bool isEnabled() const { return state_ != FadeState::NOT_ENABLED; }
|
||||
bool hasEnded() const { return state_ == FadeState::FINISHED; }
|
||||
|
||||
// Setters
|
||||
void setType(FadeType type) { type_ = type; }
|
||||
void setMode(FadeMode mode) { mode_ = mode; }
|
||||
void setPostDuration(int value) { post_duration_ = value; }
|
||||
void setPreDuration(int value) { pre_duration_ = value; }
|
||||
};
|
||||
783
source/game.cpp
@@ -12,6 +12,7 @@
|
||||
class Asset; // lines 13-13
|
||||
class Background; // lines 14-14
|
||||
class BalloonManager;
|
||||
class Tabe;
|
||||
class Bullet; // lines 15-15
|
||||
class Fade; // lines 16-16
|
||||
class Input; // lines 17-17
|
||||
@@ -65,6 +66,9 @@ private:
|
||||
// Enum
|
||||
enum class GameState
|
||||
{
|
||||
FADE_IN,
|
||||
ENTERING_PLAYER,
|
||||
SHOWING_GET_READY_MESSAGE,
|
||||
PLAYING,
|
||||
COMPLETED,
|
||||
GAME_OVER,
|
||||
@@ -140,8 +144,10 @@ private:
|
||||
std::vector<std::vector<std::string>> item_animations_; // Vector con las animaciones de los items
|
||||
std::vector<std::vector<std::string>> player_animations_; // Vector con las animaciones del jugador
|
||||
|
||||
std::unique_ptr<Fade> fade_; // 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<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
|
||||
std::unique_ptr<Tabe> tabe_; // Objeto para gestionar el Tabe Volaor
|
||||
std::vector<Path> paths_; // Vector con los recorridos precalculados almacenados
|
||||
|
||||
// Variables
|
||||
@@ -164,7 +170,7 @@ private:
|
||||
int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
|
||||
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
|
||||
GameState state_ = GameState::PLAYING; // Estado
|
||||
GameState state_ = GameState::FADE_IN; // Estado
|
||||
#ifdef DEBUG
|
||||
bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados
|
||||
#endif
|
||||
@@ -194,7 +200,7 @@ private:
|
||||
void updateStage();
|
||||
|
||||
// Actualiza el estado de fin de la partida
|
||||
void updateGameOverState();
|
||||
void updateGameStateGameOver();
|
||||
|
||||
// Destruye todos los items
|
||||
void destroyAllItems();
|
||||
@@ -205,11 +211,11 @@ private:
|
||||
// Comprueba la colisión entre el jugador y los items
|
||||
void checkPlayerItemCollision(std::shared_ptr<Player> &player);
|
||||
|
||||
// Comprueba la colisión entre las balas y los globos
|
||||
void checkBulletBalloonCollision();
|
||||
// Comprueba y procesa la colisión de las balas
|
||||
void checkBulletCollision();
|
||||
|
||||
// Mueve las balas activas
|
||||
void moveBullets();
|
||||
void updateBullets();
|
||||
|
||||
// Pinta las balas activas
|
||||
void renderBullets();
|
||||
@@ -304,11 +310,8 @@ private:
|
||||
// Pausa el juego
|
||||
void pause(bool value);
|
||||
|
||||
// Comprueba si la música ha de estar sonando
|
||||
void checkMusicStatus();
|
||||
|
||||
// Añade una puntuación a la tabla de records
|
||||
void addScoreToScoreBoard(const std::string &name, int score);
|
||||
void addScoreToScoreBoard(const std::shared_ptr<Player> &player);
|
||||
|
||||
// Saca del estado de GAME OVER al jugador si el otro está activo
|
||||
void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index);
|
||||
@@ -373,6 +376,9 @@ private:
|
||||
// Reanuda la música
|
||||
void resumeMusic();
|
||||
|
||||
// Hace sonar la música
|
||||
void playMusic();
|
||||
|
||||
// Detiene la música
|
||||
void stopMusic();
|
||||
|
||||
@@ -382,11 +388,20 @@ private:
|
||||
// Actualiza las variables durante el modo de grabación
|
||||
void updateRecording();
|
||||
#endif
|
||||
// Actualiza las variables durante dicho estado
|
||||
void updateGameStateFadeIn();
|
||||
|
||||
// Actualiza las variables durante dicho estado
|
||||
void updateGameStateEnteringPlayer();
|
||||
|
||||
// Actualiza las variables durante dicho estado
|
||||
void updateGameStateShowingGetReadyMessage();
|
||||
|
||||
// Actualiza las variables durante el transcurso normal del juego
|
||||
void updateGame();
|
||||
void updateGameStatePlaying();
|
||||
|
||||
// Gestiona eventos para el estado del final del juego
|
||||
void updateCompletedState();
|
||||
void updateGameStateCompleted();
|
||||
|
||||
// Comprueba el estado del juego
|
||||
void checkState();
|
||||
@@ -403,6 +418,9 @@ private:
|
||||
// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
|
||||
void checkAndUpdateBalloonSpeed();
|
||||
|
||||
// Cambia el estado del juego
|
||||
void setState(GameState state);
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
Game(int playerID, int current_stage, bool demo);
|
||||
|
||||
@@ -5,9 +5,15 @@
|
||||
#include "jail_audio.h" // Para JA_PlaySound
|
||||
#include "param.h" // Para Param, param, ParamGame, ParamTitle
|
||||
#include "resource.h" // Para Resource
|
||||
#include "screen.h" // Para Screen
|
||||
#include "smart_sprite.h" // Para SmartSprite
|
||||
#include "sprite.h" // Para Sprite
|
||||
#include "texture.h" // Para Texture
|
||||
#include "utils.h" // Para Color
|
||||
|
||||
constexpr int ZOOM_FACTOR = 5;
|
||||
constexpr int FLASH_DELAY = 3;
|
||||
constexpr int FLASH_LENGHT = FLASH_DELAY + 3;
|
||||
|
||||
// Constructor
|
||||
GameLogo::GameLogo(int x, int y)
|
||||
@@ -15,36 +21,25 @@ GameLogo::GameLogo(int x, int y)
|
||||
coffee_texture_(Resource::get()->getTexture("title_coffee.png")),
|
||||
crisis_texture_(Resource::get()->getTexture("title_crisis.png")),
|
||||
arcade_edition_texture_(Resource::get()->getTexture("title_arcade_edition.png")),
|
||||
|
||||
dust_left_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Resource::get()->getAnimation("title_dust.ani"))),
|
||||
dust_right_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Resource::get()->getAnimation("title_dust.ani"))),
|
||||
|
||||
coffee_sprite_(std::make_unique<SmartSprite>(coffee_texture_)),
|
||||
crisis_sprite_(std::make_unique<SmartSprite>(crisis_texture_)),
|
||||
|
||||
arcade_edition_sprite_(std::make_unique<Sprite>(arcade_edition_texture_, (param.game.width - arcade_edition_texture_->getWidth()) / 2, param.title.arcade_edition_position, arcade_edition_texture_->getWidth(), arcade_edition_texture_->getHeight())),
|
||||
|
||||
x_(x),
|
||||
y_(y)
|
||||
{
|
||||
// Inicializa las variables
|
||||
init();
|
||||
}
|
||||
y_(y) {}
|
||||
|
||||
// Inicializa las variables
|
||||
void GameLogo::init()
|
||||
{
|
||||
const auto xp = x_ - coffee_sprite_->getWidth() / 2;
|
||||
const auto xp = x_ - coffee_texture_->getWidth() / 2;
|
||||
const auto desp = getInitialVerticalDesp();
|
||||
|
||||
// Variables
|
||||
status_ = Status::DISABLED;
|
||||
shake_.desp = 1;
|
||||
shake_.delay = 2;
|
||||
shake_.lenght = 8;
|
||||
shake_.remaining = shake_.lenght;
|
||||
shake_.counter = shake_.delay;
|
||||
shake_.origin = xp;
|
||||
coffee_crisis_status_ = Status::DISABLED;
|
||||
arcade_edition_status_ = Status::DISABLED;
|
||||
shake_.init(1, 2, 8, xp);
|
||||
zoom_ = 3.0f * ZOOM_FACTOR;
|
||||
|
||||
// Inicializa el bitmap de 'Coffee'
|
||||
coffee_sprite_->setPosX(xp);
|
||||
@@ -90,6 +85,9 @@ void GameLogo::init()
|
||||
dust_left_sprite_->setPosY(y_);
|
||||
dust_left_sprite_->setWidth(16);
|
||||
dust_left_sprite_->setHeight(16);
|
||||
|
||||
// Inicializa el bitmap de 'Arcade Edition'
|
||||
arcade_edition_sprite_->setZoom(zoom_);
|
||||
}
|
||||
|
||||
// Pinta la clase en pantalla
|
||||
@@ -99,8 +97,10 @@ void GameLogo::render()
|
||||
coffee_sprite_->render();
|
||||
crisis_sprite_->render();
|
||||
|
||||
if (status_ == Status::FINISHED)
|
||||
if (arcade_edition_status_ != Status::DISABLED)
|
||||
{
|
||||
arcade_edition_sprite_->render();
|
||||
}
|
||||
|
||||
// Dibuja el polvillo del logo
|
||||
dust_right_sprite_->render();
|
||||
@@ -110,20 +110,22 @@ void GameLogo::render()
|
||||
// Actualiza la lógica de la clase
|
||||
void GameLogo::update()
|
||||
{
|
||||
switch (status_)
|
||||
switch (coffee_crisis_status_)
|
||||
{
|
||||
case Status::MOVING:
|
||||
{
|
||||
coffee_sprite_->update();
|
||||
crisis_sprite_->update();
|
||||
|
||||
// Si los objetos han llegado a su destino, cambiamos de Sección
|
||||
// Si los objetos han llegado a su destino, cambia el estado
|
||||
if (coffee_sprite_->hasFinished() && crisis_sprite_->hasFinished())
|
||||
{
|
||||
status_ = Status::SHAKING;
|
||||
coffee_crisis_status_ = Status::SHAKING;
|
||||
|
||||
// Reproduce el efecto sonoro
|
||||
JA_PlaySound(Resource::get()->getSound("title.wav"));
|
||||
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
|
||||
Screen::get()->shake();
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -131,7 +133,7 @@ void GameLogo::update()
|
||||
|
||||
case Status::SHAKING:
|
||||
{
|
||||
// Agita el logo
|
||||
// Agita "COFFEE CRISIS"
|
||||
if (shake_.remaining > 0)
|
||||
{
|
||||
if (shake_.counter > 0)
|
||||
@@ -151,7 +153,8 @@ void GameLogo::update()
|
||||
{
|
||||
coffee_sprite_->setPosX(shake_.origin);
|
||||
crisis_sprite_->setPosX(shake_.origin + 15);
|
||||
status_ = Status::FINISHED;
|
||||
coffee_crisis_status_ = Status::FINISHED;
|
||||
arcade_edition_status_ = Status::MOVING;
|
||||
}
|
||||
|
||||
dust_right_sprite_->update();
|
||||
@@ -171,19 +174,74 @@ void GameLogo::update()
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (arcade_edition_status_)
|
||||
{
|
||||
case Status::MOVING:
|
||||
{
|
||||
zoom_ -= 0.1f * ZOOM_FACTOR;
|
||||
arcade_edition_sprite_->setZoom(zoom_);
|
||||
if (zoom_ <= 1.0f)
|
||||
{
|
||||
arcade_edition_status_ = Status::SHAKING;
|
||||
zoom_ = 1.0f;
|
||||
arcade_edition_sprite_->setZoom(zoom_);
|
||||
shake_.init(1, 2, 8, arcade_edition_sprite_->getX());
|
||||
JA_PlaySound(Resource::get()->getSound("title.wav"));
|
||||
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
|
||||
Screen::get()->shake();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Status::SHAKING:
|
||||
{
|
||||
// Agita "ARCADE EDITION"
|
||||
if (shake_.remaining > 0)
|
||||
{
|
||||
if (shake_.counter > 0)
|
||||
{
|
||||
shake_.counter--;
|
||||
}
|
||||
else
|
||||
{
|
||||
shake_.counter = shake_.delay;
|
||||
const auto desp = shake_.remaining % 2 == 0 ? shake_.desp * (-1) : shake_.desp;
|
||||
arcade_edition_sprite_->setX(shake_.origin + desp);
|
||||
shake_.remaining--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
arcade_edition_sprite_->setX(shake_.origin);
|
||||
arcade_edition_status_ = Status::FINISHED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (coffee_crisis_status_ == Status::FINISHED &&
|
||||
arcade_edition_status_ == Status::FINISHED &&
|
||||
post_finished_counter_ > 0)
|
||||
{
|
||||
--post_finished_counter_;
|
||||
}
|
||||
}
|
||||
|
||||
// Activa la clase
|
||||
void GameLogo::enable()
|
||||
{
|
||||
init();
|
||||
status_ = Status::MOVING;
|
||||
coffee_crisis_status_ = Status::MOVING;
|
||||
}
|
||||
|
||||
// Indica si ha terminado la animación
|
||||
bool GameLogo::hasFinished() const
|
||||
{
|
||||
return status_ == Status::FINISHED;
|
||||
return post_finished_counter_ == 0;
|
||||
}
|
||||
|
||||
// Recarga las texturas
|
||||
@@ -192,6 +250,7 @@ void GameLogo::reLoad()
|
||||
dust_texture_->reLoad();
|
||||
coffee_texture_->reLoad();
|
||||
crisis_texture_->reLoad();
|
||||
arcade_edition_texture_->reLoad();
|
||||
}
|
||||
|
||||
// Calcula el desplazamiento vertical inicial
|
||||
|
||||
@@ -20,12 +20,30 @@ private:
|
||||
|
||||
struct Shake
|
||||
{
|
||||
int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x
|
||||
int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse
|
||||
int counter; // Contador para el retraso
|
||||
int lenght; // Cantidad de desplazamientos a realizar
|
||||
int remaining; // Cantidad de desplazamientos pendientes a realizar
|
||||
int origin; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
|
||||
int desp = 1; // Pixels de desplazamiento para agitar la pantalla en el eje x
|
||||
int delay = 2; // Retraso entre cada desplazamiento de la pantalla al agitarse
|
||||
int lenght = 8; // Cantidad de desplazamientos a realizar
|
||||
int remaining = lenght; // Cantidad de desplazamientos pendientes a realizar
|
||||
int counter = delay; // Contador para el retraso
|
||||
int origin; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
|
||||
|
||||
// Constructor por defect
|
||||
Shake() = default;
|
||||
|
||||
// Constructor
|
||||
Shake(int d, int de, int l, int o)
|
||||
: desp(d), delay(de), lenght(l), remaining(l), counter(de), origin(o) {}
|
||||
|
||||
// Inicializa los miembros
|
||||
void init(int d, int de, int l, int o)
|
||||
{
|
||||
desp = d;
|
||||
delay = de;
|
||||
lenght = l;
|
||||
remaining = l;
|
||||
counter = de;
|
||||
origin = o;
|
||||
}
|
||||
};
|
||||
|
||||
// Objetos y punteros
|
||||
@@ -43,11 +61,14 @@ private:
|
||||
std::unique_ptr<Sprite> arcade_edition_sprite_; // Sprite con los graficos de "Arcade Edition"
|
||||
|
||||
// Variables
|
||||
int x_; // Posición donde dibujar el logo
|
||||
int y_; // Posición donde dibujar el logo
|
||||
int x_; // Posición donde dibujar el logo
|
||||
int y_; // Posición donde dibujar el logo
|
||||
float zoom_; // Zoom aplicado al texto "ARCADE EDITION"
|
||||
int post_finished_counter_ = 1; // Contador final una vez terminada las animaciones de los logos
|
||||
|
||||
Status status_; // Estado en el que se encuentra la clase
|
||||
Shake shake_; // Estructura para generar el efecto de agitación
|
||||
Status coffee_crisis_status_ = Status::DISABLED; // Estado en el que se encuentra el texto "COFFEE CRISIS"
|
||||
Status arcade_edition_status_ = Status::DISABLED; // Estado en el que se encuentra el texto "ARCADE_EDITION"
|
||||
Shake shake_; // Estructura para generar el efecto de agitación
|
||||
|
||||
// Inicializa las variables
|
||||
void init();
|
||||
|
||||
@@ -1,30 +1,22 @@
|
||||
#include "global_inputs.h"
|
||||
#include <string> // Para operator+, string
|
||||
#include "input.h" // Para Input, InputType, INPUT_DO_NOT_ALLOW_REPEAT
|
||||
#include "jail_audio.h" // Para JA_EnableMusic, JA_EnableSound
|
||||
#include "lang.h" // Para getText
|
||||
#include <string> // Para operator+, string, to_string, basic_string
|
||||
#include <vector> // Para vector
|
||||
#include "asset.h" // Para Asset
|
||||
#include "input.h" // Para Input, InputDeviceToUse, InputType, INPU...
|
||||
#include "jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundVolume
|
||||
#include "lang.h" // Para Code, getText, change, loadFromFile
|
||||
#include "notifier.h" // Para Notifier
|
||||
#include "on_screen_help.h" // Para OnScreenHelp
|
||||
#include "options.h" // Para Options, OptionsAudio, options, OptionsM...
|
||||
#include "options.h" // Para Options, options, OptionsGame, OptionsAudio
|
||||
#include "screen.h" // Para Screen, ScreenVideoMode
|
||||
#include "section.h" // Para Name, Options, name, options
|
||||
#include "utils.h" // Para boolToOnOff, stringInVector
|
||||
#include "screen.h"
|
||||
|
||||
namespace globalInputs
|
||||
{
|
||||
// Variables
|
||||
std::vector<int> service_pressed_counter;
|
||||
|
||||
// Inicializa variables
|
||||
void init()
|
||||
{
|
||||
const auto num_inputs = Input::get()->getNumControllers() + 1;
|
||||
service_pressed_counter.reserve(num_inputs);
|
||||
for (int i = 0; i < num_inputs; ++i)
|
||||
{
|
||||
service_pressed_counter.push_back(0);
|
||||
}
|
||||
}
|
||||
int service_pressed_counter = 0;
|
||||
bool service_pressed = false;
|
||||
|
||||
// Termina
|
||||
void quit(section::Options code)
|
||||
@@ -33,11 +25,13 @@ namespace globalInputs
|
||||
auto code_found = stringInVector(Notifier::get()->getCodes(), exit_code);
|
||||
if (code_found)
|
||||
{
|
||||
// Si la notificación de salir está activa, cambia de sección
|
||||
section::name = section::Name::QUIT;
|
||||
section::options = code;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Si la notificación de salir no está activa, muestra la notificación
|
||||
#ifdef ARCADE
|
||||
const int index = code == section::Options::QUIT_WITH_CONTROLLER ? 116 : 94;
|
||||
Notifier::get()->showText({lang::getText(index), std::string()}, -1, exit_code);
|
||||
@@ -71,6 +65,57 @@ namespace globalInputs
|
||||
Notifier::get()->showText({"Audio " + boolToOnOff(options.audio.enabled)});
|
||||
}
|
||||
|
||||
// Obtiene una fichero a partir de un lang::Code
|
||||
std::string getLangFile(lang::Code code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case lang::Code::ba_BA:
|
||||
return Asset::get()->get("ba_BA.txt");
|
||||
break;
|
||||
case lang::Code::es_ES:
|
||||
return Asset::get()->get("es_ES.txt");
|
||||
break;
|
||||
default:
|
||||
return Asset::get()->get("en_UK.txt");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Obtiene una cadena a partir de un lang::Code
|
||||
std::string getLangName(lang::Code code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case lang::Code::ba_BA:
|
||||
return "ba_BA";
|
||||
break;
|
||||
case lang::Code::es_ES:
|
||||
return "es_ES";
|
||||
break;
|
||||
default:
|
||||
return "en_UK";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cambia el idioma
|
||||
void changeLang()
|
||||
{
|
||||
options.game.language = lang::change(options.game.language);
|
||||
lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language)));
|
||||
section::name = section::Name::INIT;
|
||||
section::options = section::Options::RELOAD;
|
||||
Notifier::get()->showText({getLangName(options.game.language)});
|
||||
}
|
||||
|
||||
// Cambia el modo de disparo
|
||||
void toggleFireMode()
|
||||
{
|
||||
options.game.autofire = !options.game.autofire;
|
||||
Notifier::get()->showText({"Autofire " + boolToOnOff(options.game.autofire)});
|
||||
}
|
||||
|
||||
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
||||
void check()
|
||||
{
|
||||
@@ -125,6 +170,20 @@ namespace globalInputs
|
||||
return;
|
||||
}
|
||||
|
||||
// Autofire
|
||||
if (Input::get()->checkInput(InputType::AUTO_FIRE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
|
||||
{
|
||||
toggleFireMode();
|
||||
return;
|
||||
}
|
||||
|
||||
// Idioma
|
||||
if (Input::get()->checkInput(InputType::CHANGE_LANG, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
|
||||
{
|
||||
changeLang();
|
||||
return;
|
||||
}
|
||||
|
||||
// Shaders
|
||||
if (Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
|
||||
{
|
||||
@@ -143,17 +202,9 @@ namespace globalInputs
|
||||
// OnScreenHelp
|
||||
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
|
||||
{
|
||||
service_pressed_counter[0]++;
|
||||
|
||||
if (service_pressed_counter[0] >= 3000)
|
||||
{
|
||||
OnScreenHelp::get()->toggleState();
|
||||
service_pressed_counter[0] = 0;
|
||||
}
|
||||
service_pressed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
service_pressed_counter[0] = 0;
|
||||
}
|
||||
|
||||
// Mandos
|
||||
@@ -203,18 +254,30 @@ namespace globalInputs
|
||||
// OnScreenHelp
|
||||
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
|
||||
{
|
||||
service_pressed_counter[i + 1]++;
|
||||
|
||||
if (service_pressed_counter[i + 1] >= 3000)
|
||||
{
|
||||
OnScreenHelp::get()->toggleState();
|
||||
service_pressed_counter[i + 1] = 0;
|
||||
}
|
||||
service_pressed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
service_pressed_counter[i + 1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Actualiza variables
|
||||
void update()
|
||||
{
|
||||
if (service_pressed)
|
||||
{
|
||||
++service_pressed_counter;
|
||||
if (service_pressed_counter >= 200)
|
||||
{
|
||||
OnScreenHelp::get()->toggleState();
|
||||
service_pressed_counter = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
service_pressed_counter = 0;
|
||||
}
|
||||
|
||||
service_pressed = false;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
#include <vector>
|
||||
namespace globalInputs
|
||||
{
|
||||
extern std::vector<int> service_pressed_counter;
|
||||
|
||||
// Inicializa variables
|
||||
void init();
|
||||
extern int service_pressed_counter;
|
||||
extern bool service_pressed;
|
||||
|
||||
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
||||
void check();
|
||||
|
||||
// Actualiza variables
|
||||
void update();
|
||||
}
|
||||
@@ -4,22 +4,28 @@
|
||||
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
|
||||
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
|
||||
#include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
|
||||
#include <stdlib.h> // Para rand
|
||||
#include <algorithm> // Para max
|
||||
#include <functional> // Para function
|
||||
#include <vector> // Para vector
|
||||
#include "background.h" // Para Background
|
||||
#include "fade.h" // Para Fade, FadeMode, FadeType
|
||||
#include "global_inputs.h" // Para check
|
||||
#include "global_inputs.h" // Para check, update
|
||||
#include "input.h" // Para Input
|
||||
#include "jail_audio.h" // Para JA_GetMusicState, JA_Music_state
|
||||
#include "lang.h" // Para getText
|
||||
#include "manage_hiscore_table.h" // Para HiScoreEntry
|
||||
#include "mouse.h" // Para handleEvent
|
||||
#include "options.h" // Para Options, OptionsGame, options
|
||||
#include "param.h" // Para Param, param, ParamGame, ParamFade
|
||||
#include "path_sprite.h" // Para PathSprite, Path, PathType
|
||||
#include "resource.h" // Para Resource
|
||||
#include "screen.h" // Para Screen
|
||||
#include "section.h" // Para Name, name, Options, options
|
||||
#include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW
|
||||
#include "utils.h" // Para Color, Zone, fade_color, orange_color
|
||||
#include "section.h" // Para Name, name, Options, options, Attr...
|
||||
#include "sprite.h" // Para Sprite
|
||||
#include "text.h" // Para Text, TEXT_COLOR, TEXT_SHADOW
|
||||
#include "texture.h" // Para Texture
|
||||
#include "utils.h" // Para Color, easeOutQuint, fade_color
|
||||
|
||||
// Constructor
|
||||
HiScoreTable::HiScoreTable()
|
||||
@@ -27,35 +33,26 @@ HiScoreTable::HiScoreTable()
|
||||
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
||||
fade_(std::make_unique<Fade>()),
|
||||
background_(std::make_unique<Background>()),
|
||||
text_(Resource::get()->getText("smb2")),
|
||||
counter_(0),
|
||||
ticks_(0),
|
||||
view_area_({0, 0, param.game.width, param.game.height}),
|
||||
fade_mode_(FadeMode::IN)
|
||||
fade_mode_(FadeMode::IN),
|
||||
background_fade_color_(Color(0, 0, 0))
|
||||
{
|
||||
// Inicializa el resto de variables
|
||||
// Inicializa el resto
|
||||
section::name = section::Name::HI_SCORE_TABLE;
|
||||
|
||||
// Inicializa objetos
|
||||
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
|
||||
background_->setPos(param.game.game_area.rect);
|
||||
background_->setCloudsSpeed(-0.1f);
|
||||
background_->setGradientNumber(1);
|
||||
background_->setTransition(0.8f);
|
||||
fade_->setColor(fade_color.r, fade_color.g, fade_color.b);
|
||||
fade_->setType(FadeType::RANDOM_SQUARE);
|
||||
fade_->setPost(param.fade.post_duration);
|
||||
fade_->setMode(fade_mode_);
|
||||
fade_->activate();
|
||||
|
||||
// Crea el contenido de la textura con la lista de puntuaciones
|
||||
fillTexture();
|
||||
initFade();
|
||||
initBackground();
|
||||
iniEntryColors();
|
||||
createSprites();
|
||||
}
|
||||
|
||||
// Destructor
|
||||
HiScoreTable::~HiScoreTable()
|
||||
{
|
||||
SDL_DestroyTexture(backbuffer_);
|
||||
options.game.clear_last_hi_score_entries();
|
||||
}
|
||||
|
||||
// Actualiza las variables
|
||||
@@ -74,9 +71,15 @@ void HiScoreTable::update()
|
||||
JA_PlayMusic(Resource::get()->getMusic("title.ogg"));
|
||||
}
|
||||
|
||||
// Actualiza las posiciones de los sprites de texto
|
||||
updateSprites();
|
||||
|
||||
// Actualiza el objeto screen
|
||||
Screen::get()->update();
|
||||
|
||||
// Actualiza las variables de globalInputs
|
||||
globalInputs::update();
|
||||
|
||||
// Actualiza el fondo
|
||||
background_->update();
|
||||
|
||||
@@ -88,7 +91,7 @@ void HiScoreTable::update()
|
||||
|
||||
if (counter_ == 150)
|
||||
{
|
||||
background_->setColor(Color(0, 0, 0));
|
||||
background_->setColor(background_fade_color_.darken());
|
||||
background_->setAlpha(96);
|
||||
}
|
||||
|
||||
@@ -96,19 +99,15 @@ void HiScoreTable::update()
|
||||
{
|
||||
fade_->activate();
|
||||
}
|
||||
|
||||
// Dibuja los sprites en la textura
|
||||
fillTexture();
|
||||
}
|
||||
}
|
||||
|
||||
// Crea el contenido de la textura con la lista de puntuaciones
|
||||
// Dibuja los sprites en la textura
|
||||
void HiScoreTable::fillTexture()
|
||||
{
|
||||
// hay 27 letras - 7 de puntos quedan 20 caracteres 20 - name_lenght 0 num_dots
|
||||
constexpr auto max_names = 10;
|
||||
constexpr auto space_between_header = 32;
|
||||
const auto space_between_lines = text_->getCharacterSize() * 2.0f;
|
||||
const auto size = space_between_header + space_between_lines * (max_names - 1) + text_->getCharacterSize();
|
||||
const auto first_line = (param.game.height - size) / 2;
|
||||
|
||||
// Pinta en el backbuffer el texto y los sprites
|
||||
auto temp = SDL_GetRenderTarget(renderer_);
|
||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||
@@ -116,22 +115,12 @@ void HiScoreTable::fillTexture()
|
||||
SDL_RenderClear(renderer_);
|
||||
|
||||
// Escribe el texto: Mejores puntuaciones
|
||||
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, first_line, lang::getText(42), 1, orange_color, 1, shdw_txt_color);
|
||||
header_->render();
|
||||
|
||||
// Escribe los nombres de la tabla de puntuaciones
|
||||
for (int i = 0; i < max_names; ++i)
|
||||
for (auto const &entry : entry_names_)
|
||||
{
|
||||
const auto name_lenght = options.game.hi_score_table[i].name.length();
|
||||
const auto score = format(options.game.hi_score_table[i].score);
|
||||
const auto score_lenght = score.size();
|
||||
const auto num_dots = 25 - name_lenght - score_lenght;
|
||||
std::string dots;
|
||||
for (int j = 0; j < (int)num_dots; ++j)
|
||||
{
|
||||
dots = dots + ".";
|
||||
}
|
||||
const auto line = options.game.hi_score_table[i].name + dots + score;
|
||||
text_->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, (i * space_between_lines) + first_line + space_between_header, line, 1, orange_color, 1, shdw_txt_color);
|
||||
entry->render();
|
||||
}
|
||||
|
||||
// Cambia el destino de renderizado
|
||||
@@ -160,14 +149,12 @@ void HiScoreTable::render()
|
||||
fade_->render();
|
||||
|
||||
// Vuelca el contenido del renderizador en pantalla
|
||||
Screen::get()->blit();
|
||||
Screen::get()->render();
|
||||
}
|
||||
|
||||
// Recarga todas las texturas
|
||||
void HiScoreTable::reloadTextures()
|
||||
{
|
||||
text_->reLoadTexture();
|
||||
fillTexture();
|
||||
}
|
||||
|
||||
// Comprueba los eventos
|
||||
@@ -193,6 +180,9 @@ void HiScoreTable::checkEvents()
|
||||
reloadTextures();
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba el cursor
|
||||
Mouse::handleEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,9 +192,10 @@ void HiScoreTable::checkInput()
|
||||
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
|
||||
if (Input::get()->checkAnyButtonPressed())
|
||||
{
|
||||
JA_StopMusic();
|
||||
// JA_StopMusic();
|
||||
section::name = section::Name::TITLE;
|
||||
section::options = section::Options::TITLE_1;
|
||||
section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -264,4 +255,213 @@ std::string HiScoreTable::format(int number)
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Crea los sprites con los textos
|
||||
void HiScoreTable::createSprites()
|
||||
{
|
||||
auto header_text = Resource::get()->getText("04b_25_grey");
|
||||
auto entry_text = Resource::get()->getText("smb2");
|
||||
|
||||
// Obtiene el tamaño de la textura
|
||||
int backbuffer_width;
|
||||
int backbuffer_height;
|
||||
SDL_QueryTexture(backbuffer_, nullptr, nullptr, &backbuffer_width, &backbuffer_height);
|
||||
|
||||
constexpr int entry_lenght = 22;
|
||||
constexpr int max_names = 10;
|
||||
const int space_between_header = entry_text->getCharacterSize() * 4;
|
||||
const int space_between_lines = entry_text->getCharacterSize() * 2;
|
||||
const int size = space_between_header + space_between_lines * (max_names - 1) + entry_text->getCharacterSize();
|
||||
const int first_line = (param.game.height - size) / 2;
|
||||
|
||||
// Crea el sprite para el texto de cabecera
|
||||
header_ = std::make_unique<Sprite>(header_text->writeDXToTexture(TEXT_COLOR, lang::getText(42), -2, background_fade_color_.getInverse().lighten(25)));
|
||||
header_->setPosition(param.game.game_area.center_x - (header_->getWidth() / 2), first_line);
|
||||
|
||||
// Crea los sprites para las entradas en la tabla de puntuaciones
|
||||
const int animation = rand() % 4;
|
||||
const std::string sample_line(entry_lenght + 3, ' ');
|
||||
auto sample_entry = std::make_unique<Sprite>(entry_text->writeDXToTexture(TEXT_SHADOW, sample_line, 1, orange_color, 1, shdw_txt_color));
|
||||
const auto entry_width = sample_entry->getWidth();
|
||||
for (int i = 0; i < max_names; ++i)
|
||||
{
|
||||
const auto table_position = format(i + 1) + ". ";
|
||||
const auto score = format(options.game.hi_score_table.at(i).score);
|
||||
const auto num_dots = entry_lenght - options.game.hi_score_table.at(i).name.size() - score.size();
|
||||
const auto one_cc = options.game.hi_score_table.at(i).one_credit_complete ? " }" : "";
|
||||
std::string dots;
|
||||
for (int j = 0; j < (int)num_dots; ++j)
|
||||
{
|
||||
dots = dots + ".";
|
||||
}
|
||||
const auto line = table_position + options.game.hi_score_table.at(i).name + dots + score + one_cc;
|
||||
|
||||
entry_names_.emplace_back(std::make_shared<PathSprite>(entry_text->writeDXToTexture(TEXT_SHADOW, line, 1, orange_color, 1, shdw_txt_color)));
|
||||
const int default_pos_x = (backbuffer_width - entry_width) / 2;
|
||||
const int pos_x = (i < 9) ? default_pos_x : default_pos_x - entry_text->getCharacterSize();
|
||||
const int pos_y = (i * space_between_lines) + first_line + space_between_header;
|
||||
constexpr int steps = 80;
|
||||
switch (animation)
|
||||
{
|
||||
case 0: // Ambos lados alternativamente
|
||||
{
|
||||
if (i % 2 == 0)
|
||||
{
|
||||
entry_names_.back()->addPath(-entry_names_.back()->getWidth(), pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
|
||||
entry_names_.back()->setPosition(-entry_names_.back()->getWidth(), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
entry_names_.back()->addPath(backbuffer_width, pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
|
||||
entry_names_.back()->setPosition(backbuffer_width, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: // Entran por la izquierda
|
||||
{
|
||||
entry_names_.back()->addPath(-entry_names_.back()->getWidth(), pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
|
||||
entry_names_.back()->setPosition(-entry_names_.back()->getWidth(), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: // Entran por la derecha
|
||||
{
|
||||
entry_names_.back()->addPath(backbuffer_width, pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
|
||||
entry_names_.back()->setPosition(backbuffer_width, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case 3: // Entran desde la parte inferior
|
||||
{
|
||||
entry_names_.back()->addPath(backbuffer_height, pos_y, PathType::VERTICAL, pos_x, steps, easeOutQuint);
|
||||
entry_names_.back()->setPosition(0, backbuffer_height);
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Actualiza las posiciones de los sprites de texto
|
||||
void HiScoreTable::updateSprites()
|
||||
{
|
||||
constexpr int init_counter = 190;
|
||||
const int counter_between_entries = 16;
|
||||
if (counter_ >= init_counter)
|
||||
{
|
||||
const int counter2 = counter_ - init_counter;
|
||||
if (counter2 % counter_between_entries == 0)
|
||||
{
|
||||
int index = counter2 / counter_between_entries;
|
||||
if (index < static_cast<int>(entry_names_.size()))
|
||||
{
|
||||
entry_names_.at(index)->enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto const &entry : entry_names_)
|
||||
{
|
||||
entry->update();
|
||||
}
|
||||
|
||||
glowEntryNames();
|
||||
}
|
||||
|
||||
// Inicializa el fade
|
||||
void HiScoreTable::initFade()
|
||||
{
|
||||
fade_->setColor(fade_color.r, fade_color.g, fade_color.b);
|
||||
fade_->setType(FadeType::RANDOM_SQUARE);
|
||||
fade_->setPostDuration(param.fade.post_duration);
|
||||
fade_->setMode(fade_mode_);
|
||||
fade_->activate();
|
||||
}
|
||||
|
||||
// Inicializa el fondo
|
||||
void HiScoreTable::initBackground()
|
||||
{
|
||||
background_->setPos(param.game.game_area.rect);
|
||||
background_->setCloudsSpeed(-0.1f);
|
||||
|
||||
const int lucky = rand() % 3;
|
||||
switch (lucky)
|
||||
{
|
||||
case 0: // Fondo verde
|
||||
{
|
||||
background_->setGradientNumber(2);
|
||||
background_->setTransition(0.0f);
|
||||
background_->setSunProgression(1.0f);
|
||||
background_->setMoonProgression(0.0f);
|
||||
background_fade_color_ = green_sky_color;
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: // Fondo naranja
|
||||
{
|
||||
background_->setGradientNumber(1);
|
||||
background_->setTransition(0.0f);
|
||||
background_->setSunProgression(0.65f);
|
||||
background_->setMoonProgression(0.0f);
|
||||
background_fade_color_ = pink_sky_color;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: // Fondo azul
|
||||
{
|
||||
background_->setGradientNumber(0);
|
||||
background_->setTransition(0.0f);
|
||||
background_->setSunProgression(0.0f);
|
||||
background_->setMoonProgression(0.0f);
|
||||
background_fade_color_ = blue_sky_color;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Obtiene un color del vector de colores de entradas
|
||||
Color HiScoreTable::getEntryColor(int counter_)
|
||||
{
|
||||
int cycle_length = entry_colors_.size() * 2 - 2;
|
||||
size_t n = counter_ % cycle_length;
|
||||
|
||||
size_t index;
|
||||
if (n < entry_colors_.size())
|
||||
{
|
||||
index = n; // Avanza: 0,1,2,3
|
||||
}
|
||||
else
|
||||
{
|
||||
index = 2 * (entry_colors_.size() - 1) - n; // Retrocede: 2,1
|
||||
}
|
||||
|
||||
return entry_colors_[index];
|
||||
}
|
||||
|
||||
// Inicializa los colores de las entradas
|
||||
void HiScoreTable::iniEntryColors()
|
||||
{
|
||||
entry_colors_.clear();
|
||||
entry_colors_.emplace_back(background_fade_color_.getInverse().lighten(75));
|
||||
entry_colors_.emplace_back(background_fade_color_.getInverse().lighten(50));
|
||||
entry_colors_.emplace_back(background_fade_color_.getInverse().lighten(25));
|
||||
entry_colors_.emplace_back(background_fade_color_.getInverse());
|
||||
}
|
||||
|
||||
// Hace brillar los nombres de la tabla de records
|
||||
void HiScoreTable::glowEntryNames()
|
||||
{
|
||||
const Color entry_color = getEntryColor(counter_ / 5);
|
||||
for (const auto& entry_index : options.game.last_hi_score_entry)
|
||||
{
|
||||
if (entry_index != -1)
|
||||
{
|
||||
entry_names_.at(entry_index)->getTexture()->setColor(entry_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL_rect.h> // para SDL_Rect
|
||||
#include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture
|
||||
#include <SDL2/SDL_stdinc.h> // para Uint16, Uint32, Uint8
|
||||
#include <memory> // para unique_ptr
|
||||
#include <string> // para string
|
||||
class Background; // lines 8-8
|
||||
class Fade; // lines 9-9
|
||||
class Text; // lines 10-10
|
||||
enum class FadeMode : Uint8; // lines 11-11
|
||||
#include <SDL2/SDL_rect.h> // Para SDL_Rect
|
||||
#include <SDL2/SDL_render.h> // Para SDL_Renderer, SDL_Texture
|
||||
#include <SDL2/SDL_stdinc.h> // Para Uint16, Uint32, Uint8
|
||||
#include <memory> // Para unique_ptr, shared_ptr
|
||||
#include <string> // Para string
|
||||
#include <vector> // Para vector
|
||||
#include "utils.h"
|
||||
class Background; // lines 10-10
|
||||
class Fade; // lines 11-11
|
||||
class PathSprite;
|
||||
class Sprite;
|
||||
enum class FadeMode : Uint8; // lines 13-13
|
||||
struct Path;
|
||||
|
||||
/*
|
||||
Esta clase gestiona un estado del programa. Se encarga de mostrar la tabla con las puntuaciones
|
||||
@@ -31,15 +35,19 @@ private:
|
||||
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||
SDL_Texture *backbuffer_; // Textura para usar como backbuffer
|
||||
|
||||
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
|
||||
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
|
||||
std::shared_ptr<Text> text_; // Objeto para escribir texto
|
||||
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
|
||||
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
|
||||
std::unique_ptr<Sprite> header_; // Sprite con la cabecera del texto
|
||||
std::vector<std::shared_ptr<PathSprite>> entry_names_; // Lista con los spritres de cada uno de los nombres de la tabla de records
|
||||
std::vector<Path> paths_; // Vector con los recorridos precalculados
|
||||
|
||||
// Variables
|
||||
Uint16 counter_; // Contador
|
||||
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
|
||||
SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla
|
||||
FadeMode fade_mode_; // Modo de fade a utilizar
|
||||
Uint16 counter_ = 0; // Contador
|
||||
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
|
||||
SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla
|
||||
FadeMode fade_mode_; // Modo de fade a utilizar
|
||||
Color background_fade_color_; // Color de atenuación del fondo
|
||||
std::vector<Color> entry_colors_; // Colores para destacar las entradas en la tabla
|
||||
|
||||
// Actualiza las variables
|
||||
void update();
|
||||
@@ -56,7 +64,7 @@ private:
|
||||
// Convierte un entero a un string con separadores de miles
|
||||
std::string format(int number);
|
||||
|
||||
// Crea el contenido de la textura con la lista de puntuaciones
|
||||
// Dibuja los sprites en la textura
|
||||
void fillTexture();
|
||||
|
||||
// Recarga todas las texturas
|
||||
@@ -65,6 +73,27 @@ private:
|
||||
// Gestiona el fade
|
||||
void updateFade();
|
||||
|
||||
// Crea los sprites con los textos
|
||||
void createSprites();
|
||||
|
||||
// Actualiza las posiciones de los sprites de texto
|
||||
void updateSprites();
|
||||
|
||||
// Inicializa el fade
|
||||
void initFade();
|
||||
|
||||
// Inicializa el fondo
|
||||
void initBackground();
|
||||
|
||||
// Obtiene un color del vector de colores de entradas
|
||||
Color getEntryColor(int counter_);
|
||||
|
||||
// Inicializa los colores de las entradas
|
||||
void iniEntryColors();
|
||||
|
||||
// Hace brillar los nombres de la tabla de records
|
||||
void glowEntryNames();
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
HiScoreTable();
|
||||
|
||||
@@ -110,9 +110,11 @@ bool Input::checkInput(InputType input, bool repeat, InputDeviceToUse device, in
|
||||
}
|
||||
|
||||
if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_)
|
||||
{
|
||||
if ((device == InputDeviceToUse::CONTROLLER) || (device == InputDeviceToUse::ANY))
|
||||
{
|
||||
success_controller = checkAxisInput(input, controller_index);
|
||||
success_controller = checkAxisInput(input, controller_index, repeat);
|
||||
|
||||
if (!success_controller)
|
||||
{
|
||||
if (repeat)
|
||||
@@ -144,6 +146,7 @@ bool Input::checkInput(InputType input, bool repeat, InputDeviceToUse device, in
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (success_keyboard || success_controller);
|
||||
}
|
||||
@@ -245,7 +248,15 @@ bool Input::discoverGameControllers()
|
||||
}
|
||||
|
||||
std::cout << "\n** LOOKING FOR GAME CONTROLLERS" << std::endl;
|
||||
std::cout << "Gamepads found: " << num_gamepads_ << std::endl;
|
||||
if (num_joysticks_ != num_gamepads_)
|
||||
{
|
||||
std::cout << "Joysticks found: " << num_joysticks_ << std::endl;
|
||||
std::cout << "Gamepads found : " << num_gamepads_ << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Gamepads found: " << num_gamepads_ << std::endl;
|
||||
}
|
||||
|
||||
if (num_gamepads_ > 0)
|
||||
{
|
||||
@@ -371,19 +382,53 @@ InputType Input::to_inputs_e(const std::string &name) const
|
||||
}
|
||||
|
||||
// Comprueba el eje del mando
|
||||
bool Input::checkAxisInput(InputType input, int controller_index) const
|
||||
bool Input::checkAxisInput(InputType input, int controller_index, bool repeat)
|
||||
{
|
||||
// Umbral para considerar el eje como activo
|
||||
const Sint16 threshold = 30000;
|
||||
bool axis_active_now = false;
|
||||
|
||||
switch (input)
|
||||
{
|
||||
case InputType::LEFT:
|
||||
return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) < -30000;
|
||||
axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) < -threshold;
|
||||
break;
|
||||
case InputType::RIGHT:
|
||||
return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) > 30000;
|
||||
axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) > threshold;
|
||||
break;
|
||||
case InputType::UP:
|
||||
return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) < -30000;
|
||||
axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) < -threshold;
|
||||
break;
|
||||
case InputType::DOWN:
|
||||
return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) > 30000;
|
||||
axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) > threshold;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Referencia al binding correspondiente
|
||||
auto &binding = controller_bindings_.at(controller_index).at(static_cast<int>(input));
|
||||
|
||||
if (repeat)
|
||||
{
|
||||
// Si se permite repetir, simplemente devolvemos el estado actual
|
||||
return axis_active_now;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Si no se permite repetir, aplicamos la lógica de transición
|
||||
if (axis_active_now && !binding.axis_active)
|
||||
{
|
||||
// Transición de inactivo a activo
|
||||
binding.axis_active = true;
|
||||
return true;
|
||||
}
|
||||
else if (!axis_active_now && binding.axis_active)
|
||||
{
|
||||
// Transición de activo a inactivo
|
||||
binding.axis_active = false;
|
||||
}
|
||||
// Mantener el estado actual
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -40,9 +40,11 @@ enum class InputType : int
|
||||
VIDEO_SHADERS,
|
||||
RESET,
|
||||
MUTE,
|
||||
CHANGE_LANG,
|
||||
SHOWINFO,
|
||||
CONFIG,
|
||||
SWAP_CONTROLLERS,
|
||||
AUTO_FIRE,
|
||||
|
||||
// Input obligatorio
|
||||
NONE,
|
||||
@@ -79,10 +81,11 @@ private:
|
||||
{
|
||||
SDL_GameControllerButton button; // GameControllerButton asociado
|
||||
bool active; // Indica si está activo
|
||||
bool axis_active; // Estado del eje
|
||||
|
||||
// Constructor
|
||||
explicit ControllerBindings(SDL_GameControllerButton btn = SDL_CONTROLLER_BUTTON_INVALID, bool act = false)
|
||||
: button(btn), active(act) {}
|
||||
explicit ControllerBindings(SDL_GameControllerButton btn = SDL_CONTROLLER_BUTTON_INVALID, bool act = false, bool axis_act = false)
|
||||
: button(btn), active(act), axis_active(axis_act) {}
|
||||
};
|
||||
|
||||
// Variables
|
||||
@@ -97,7 +100,7 @@ private:
|
||||
std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt
|
||||
|
||||
// Comprueba el eje del mando
|
||||
bool checkAxisInput(InputType input, int controller_index = 0) const;
|
||||
bool checkAxisInput(InputType input, int controller_index, bool repeat);
|
||||
|
||||
// Constructor
|
||||
explicit Input(const std::string &game_controller_db_path);
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
#include "texture.h" // Para Texture
|
||||
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
|
||||
#include "utils.h" // Para Color, shdw_txt_color, Zone, no_color
|
||||
#include "mouse.h"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
// Constructor
|
||||
Instructions::Instructions()
|
||||
@@ -41,10 +46,13 @@ Instructions::Instructions()
|
||||
// Inicializa objetos
|
||||
fade_->setColor(fade_color.r, fade_color.g, fade_color.b);
|
||||
fade_->setType(FadeType::FULLSCREEN);
|
||||
fade_->setPost(param.fade.post_duration);
|
||||
fade_->setPostDuration(param.fade.post_duration);
|
||||
fade_->setMode(FadeMode::IN);
|
||||
fade_->activate();
|
||||
|
||||
// Inicializa las líneas con un retraso progresivo de 50 ms
|
||||
lines_ = initializeLines(256);
|
||||
|
||||
// Rellena la textura de texto
|
||||
fillTexture();
|
||||
|
||||
@@ -158,7 +166,6 @@ void Instructions::fillTexture()
|
||||
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor2, lang::getText(16), 1, orange_color, 1, shdw_txt_color);
|
||||
|
||||
const int anchor3 = anchor2 + space_post_header;
|
||||
// const int anchor4 = anchor3 + ((param.game.item_size + text->getCharacterSize()) / 2);
|
||||
text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 0, lang::getText(17), shdw_txt_color);
|
||||
text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 1, lang::getText(18), shdw_txt_color);
|
||||
text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 2, lang::getText(19), shdw_txt_color);
|
||||
@@ -216,20 +223,45 @@ void Instructions::update()
|
||||
// Actualiza el objeto screen
|
||||
Screen::get()->update();
|
||||
|
||||
// Actualiza las variables de globalInputs
|
||||
globalInputs::update();
|
||||
|
||||
// Incrementa el contador
|
||||
counter_++;
|
||||
|
||||
// Actualiza los sprites
|
||||
updateSprites();
|
||||
|
||||
// Establece la ventana del backbuffer
|
||||
view_.y = std::max(0, param.game.height - counter_ + 100);
|
||||
|
||||
// Verifica si view_.y == 0 y gestiona el temporizador
|
||||
if (view_.y == 0)
|
||||
{
|
||||
if (!start_delay_triggered_)
|
||||
{
|
||||
// Activa el temporizador si no ha sido activado
|
||||
start_delay_triggered_ = true;
|
||||
start_delay_time_ = SDL_GetTicks();
|
||||
}
|
||||
else if (SDL_GetTicks() - start_delay_time_ >= 4000)
|
||||
{
|
||||
// Han pasado tres segundos, mover líneas
|
||||
all_lines_off_screen_ = moveLines(lines_, 320, 1.0f, 5);
|
||||
}
|
||||
}
|
||||
|
||||
// Actualiza el mosaico de fondo
|
||||
tiled_bg_->update();
|
||||
|
||||
// Actualiza el objeto "fade"
|
||||
fade_->update();
|
||||
|
||||
// Rellena el backbuffer
|
||||
fillBackbuffer();
|
||||
|
||||
// Comprueba si el contador ha llegado al final
|
||||
if (counter_ == counter_end_)
|
||||
if (all_lines_off_screen_)
|
||||
{
|
||||
section::name = section::Name::TITLE;
|
||||
section::options = section::Options::TITLE_1;
|
||||
@@ -240,9 +272,6 @@ void Instructions::update()
|
||||
// Pinta en pantalla
|
||||
void Instructions::render()
|
||||
{
|
||||
// Rellena el backbuffer
|
||||
fillBackbuffer();
|
||||
|
||||
// Prepara para empezar a dibujar en la textura de juego
|
||||
Screen::get()->start();
|
||||
|
||||
@@ -252,16 +281,16 @@ void Instructions::render()
|
||||
// Dibuja el mosacico de fondo
|
||||
tiled_bg_->render();
|
||||
|
||||
// Establece la ventana del backbuffer
|
||||
view_.y = std::max(0, param.game.height - counter_ + 100);
|
||||
|
||||
// Copia la textura y el backbuffer al renderizador
|
||||
SDL_RenderCopy(renderer_, backbuffer_, nullptr, &view_);
|
||||
if (view_.y == 0)
|
||||
renderLines(renderer_, backbuffer_, lines_);
|
||||
else
|
||||
SDL_RenderCopy(renderer_, backbuffer_, nullptr, &view_);
|
||||
|
||||
fade_->render();
|
||||
|
||||
// Vuelca el contenido del renderizador en pantalla
|
||||
Screen::get()->blit();
|
||||
Screen::get()->render();
|
||||
}
|
||||
|
||||
// Recarga todas las texturas
|
||||
@@ -298,6 +327,9 @@ void Instructions::checkEvents()
|
||||
reloadTextures();
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba el cursor
|
||||
Mouse::handleEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,9 +339,10 @@ void Instructions::checkInput()
|
||||
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
|
||||
if (Input::get()->checkAnyButtonPressed())
|
||||
{
|
||||
JA_StopMusic();
|
||||
// JA_StopMusic();
|
||||
section::name = section::Name::TITLE;
|
||||
section::options = section::Options::TITLE_1;
|
||||
section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -327,4 +360,61 @@ void Instructions::run()
|
||||
checkEvents(); // Tiene que ir antes del render
|
||||
render();
|
||||
}
|
||||
}
|
||||
|
||||
// Método para inicializar las líneas
|
||||
std::vector<Line> Instructions::initializeLines(int height)
|
||||
{
|
||||
std::vector<Line> lines;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
int direction = (y % 2 == 0) ? -1 : 1; // Pares a la izquierda, impares a la derecha
|
||||
lines.emplace_back(y, 0.0f, direction);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
// Método para mover las líneas con suavizado
|
||||
bool Instructions::moveLines(std::vector<Line> &lines, int width, float duration, Uint32 startDelay)
|
||||
{
|
||||
Uint32 currentTime = SDL_GetTicks();
|
||||
bool allLinesOffScreen = true;
|
||||
|
||||
for (auto &line : lines)
|
||||
{
|
||||
// Establecer startTime en el primer cuadro de animación
|
||||
if (line.startTime == 0)
|
||||
{
|
||||
line.startTime = currentTime + line.y * startDelay;
|
||||
}
|
||||
|
||||
float elapsedTime = (currentTime - line.startTime) / 1000.0f; // Convertir a segundos
|
||||
if (elapsedTime < 0)
|
||||
{
|
||||
allLinesOffScreen = false; // Si aún no se debe mover esta línea, no están todas fuera de pantalla
|
||||
continue;
|
||||
}
|
||||
if (elapsedTime >= duration)
|
||||
{
|
||||
continue; // Si la línea ha salido de los límites, no la muevas más
|
||||
}
|
||||
|
||||
float t = elapsedTime / duration;
|
||||
float smoothFactor = easeInOutQuint(t);
|
||||
line.x = line.direction * smoothFactor * width;
|
||||
allLinesOffScreen = false; // Si alguna línea aún se está moviendo, no están todas fuera de pantalla
|
||||
}
|
||||
|
||||
return allLinesOffScreen;
|
||||
}
|
||||
|
||||
// Método para renderizar las líneas
|
||||
void Instructions::renderLines(SDL_Renderer *renderer, SDL_Texture *texture, const std::vector<Line> &lines)
|
||||
{
|
||||
for (const auto &line : lines)
|
||||
{
|
||||
SDL_Rect srcRect = {0, line.y, 320, 1};
|
||||
SDL_Rect dstRect = {static_cast<int>(line.x), line.y, 320, 1};
|
||||
SDL_RenderCopy(renderer, texture, &srcRect, &dstRect);
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,19 @@ class TiledBG; // lines 12-12
|
||||
por la pantalla sobre el mosaico de fondo (gestionado por el correspondiente objeto)
|
||||
*/
|
||||
|
||||
// Estructura para almacenar información de línea
|
||||
struct Line
|
||||
{
|
||||
int y; // Coordenada Y de la línea
|
||||
float x; // Coordenada X inicial (usamos float para mayor precisión en el suavizado)
|
||||
int direction; // Dirección de movimiento: -1 para izquierda, 1 para derecha
|
||||
Uint32 startTime; // Tiempo de inicio del movimiento
|
||||
|
||||
// Constructor de Line
|
||||
Line(int y, float x, int direction)
|
||||
: y(y), x(x), direction(direction), startTime(0) {}
|
||||
};
|
||||
|
||||
// Clase Instructions
|
||||
class Instructions
|
||||
{
|
||||
@@ -40,12 +53,15 @@ private:
|
||||
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
|
||||
|
||||
// Variables
|
||||
int counter_ = 0; // Contador
|
||||
int counter_end_ = 700; // Valor final para el contador
|
||||
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
||||
SDL_Rect view_; // Vista del backbuffer que se va amostrar por pantalla
|
||||
SDL_Point sprite_pos_ = {0, 0}; // Posición del primer sprite
|
||||
int item_space_ = 2; // Espacio entre los items
|
||||
int counter_ = 0; // Contador para manejar el progreso en la pantalla de instrucciones
|
||||
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
||||
SDL_Rect view_; // Vista del backbuffer que se va a mostrar por pantalla
|
||||
SDL_Point sprite_pos_ = {0, 0}; // Posición del primer sprite en la lista
|
||||
int item_space_ = 2; // Espacio entre los items en pantalla
|
||||
std::vector<Line> lines_; // Vector que contiene las líneas animadas en la pantalla
|
||||
bool all_lines_off_screen_ = false; // Indica si todas las líneas han salido de la pantalla
|
||||
Uint32 start_delay_time_ = 0; // Tiempo de inicio del retraso para mover las líneas
|
||||
bool start_delay_triggered_ = false; // Bandera para determinar si el retraso ha comenzado
|
||||
|
||||
// Actualiza las variables
|
||||
void update();
|
||||
@@ -74,6 +90,15 @@ private:
|
||||
// Recarga todas las texturas
|
||||
void reloadTextures();
|
||||
|
||||
// Método para inicializar las líneas
|
||||
std::vector<Line> initializeLines(int height);
|
||||
|
||||
// Método para mover las líneas
|
||||
bool moveLines(std::vector<Line> &lines, int width, float duration, Uint32 startDelay);
|
||||
|
||||
// Método para renderizar las líneas
|
||||
void renderLines(SDL_Renderer *renderer, SDL_Texture *texture, const std::vector<Line> &lines);
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
Instructions();
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
#include "texture.h" // Para Texture
|
||||
#include "utils.h" // Para Zone, BLOCK, Color, bg_color
|
||||
#include "writer.h" // Para Writer
|
||||
#include "mouse.h"
|
||||
|
||||
// Constructor
|
||||
Intro::Intro()
|
||||
: texture_(Resource::get()->getTexture("intro.png")),
|
||||
text_(Resource::get()->getText("nokia"))
|
||||
text_(Resource::get()->getText("04b_25_metal"))
|
||||
{
|
||||
|
||||
// Inicializa variables
|
||||
@@ -96,7 +97,7 @@ Intro::Intro()
|
||||
auto w = std::make_unique<Writer>(text_);
|
||||
w->setPosX(BLOCK * 0);
|
||||
w->setPosY(param.game.height - (BLOCK * 6));
|
||||
w->setKerning(-1);
|
||||
w->setKerning(-2);
|
||||
w->setEnabled(false);
|
||||
w->setFinishedCounter(180);
|
||||
texts_.push_back(std::move(w));
|
||||
@@ -169,13 +170,18 @@ void Intro::checkEvents()
|
||||
case SDL_WINDOWEVENT:
|
||||
{
|
||||
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
|
||||
{
|
||||
reloadTextures();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Comprueba el cursor
|
||||
Mouse::handleEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,6 +388,9 @@ void Intro::update()
|
||||
|
||||
// Actualiza las escenas de la intro
|
||||
updateScenes();
|
||||
|
||||
// Actualiza las variables de globalInputs
|
||||
globalInputs::update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,14 +415,13 @@ void Intro::render()
|
||||
}
|
||||
|
||||
// Vuelca el contenido del renderizador en pantalla
|
||||
Screen::get()->blit();
|
||||
Screen::get()->render();
|
||||
}
|
||||
|
||||
// Bucle principal
|
||||
void Intro::run()
|
||||
{
|
||||
JA_PlayMusic(Resource::get()->getMusic("intro.ogg"), 0);
|
||||
|
||||
while (section::name == section::Name::INTRO)
|
||||
{
|
||||
checkInput();
|
||||
|
||||
@@ -14,10 +14,10 @@ Item::Item(ItemType type, float x, float y, SDL_Rect &play_area, std::shared_ptr
|
||||
{
|
||||
case ItemType::COFFEE_MACHINE:
|
||||
{
|
||||
width_ = 28;
|
||||
height_ = 37;
|
||||
width_ = param.game.coffee_machine_w;
|
||||
height_ = param.game.coffee_machine_h;
|
||||
pos_x_ = ((static_cast<int>(x) + (play_area.w / 2)) % (play_area.w - width_ - 5)) + 2;
|
||||
pos_y_ = -height_;
|
||||
pos_y_ = y;
|
||||
vel_x_ = 0.0f;
|
||||
vel_y_ = -0.1f;
|
||||
accel_y_ = 0.1f;
|
||||
@@ -26,8 +26,8 @@ Item::Item(ItemType type, float x, float y, SDL_Rect &play_area, std::shared_ptr
|
||||
}
|
||||
default:
|
||||
{
|
||||
width_ = 20;
|
||||
height_ = 20;
|
||||
width_ = param.game.item_size;
|
||||
height_ = param.game.item_size;
|
||||
pos_x_ = x;
|
||||
pos_y_ = y;
|
||||
vel_x_ = -1.0f + ((rand() % 5) * 0.5f);
|
||||
|
||||
@@ -22,8 +22,9 @@ enum class ItemType : int
|
||||
PACMAR = 3, /**< Pacman */
|
||||
CLOCK = 4, /**< Reloj */
|
||||
COFFEE = 5, /**< Café */
|
||||
COFFEE_MACHINE = 6,/**< Máquina de café */
|
||||
NONE = 7, /**< Ninguno */
|
||||
DEBIAN = 6, /**< Debian */
|
||||
COFFEE_MACHINE = 7,/**< Máquina de café */
|
||||
NONE = 8, /**< Ninguno */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#ifndef JA_USESDLMIXER
|
||||
|
||||
#include "jail_audio.h"
|
||||
#include <stdint.h> // para uint8_t
|
||||
#include <stdio.h> // para NULL, fseek, fclose, fopen, fread, ftell, FILE
|
||||
#include <stdlib.h> // para free, malloc
|
||||
#include "stb_vorbis.c" // para stb_vorbis_decode_memory
|
||||
#include <SDL2/SDL_rwops.h> // Para SDL_RWFromMem
|
||||
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
|
||||
#include <stdint.h> // Para uint8_t, uint32_t
|
||||
#include <stdio.h> // Para NULL, fseek, fclose, fopen, fread, ftell
|
||||
#include <stdlib.h> // Para free, malloc
|
||||
#include "stb_vorbis.c" // Para stb_vorbis_decode_memory
|
||||
|
||||
#define JA_MAX_SIMULTANEOUS_CHANNELS 5
|
||||
#define JA_MAX_SIMULTANEOUS_CHANNELS 20
|
||||
|
||||
struct JA_Sound_t
|
||||
{
|
||||
@@ -25,6 +26,7 @@ struct JA_Channel_t
|
||||
struct JA_Music_t
|
||||
{
|
||||
int samples{0};
|
||||
Uint32 length{0};
|
||||
int pos{0};
|
||||
int times{0};
|
||||
short *output{NULL};
|
||||
@@ -43,20 +45,43 @@ bool JA_musicEnabled = true;
|
||||
bool JA_soundEnabled = true;
|
||||
SDL_AudioDeviceID sdlAudioDevice = 0;
|
||||
|
||||
bool fading = false;
|
||||
int fade_start_time;
|
||||
int fade_duration;
|
||||
int fade_initial_volume;
|
||||
|
||||
void audioCallback(void *userdata, uint8_t *stream, int len)
|
||||
{
|
||||
SDL_memset(stream, 0, len);
|
||||
if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING)
|
||||
{
|
||||
const int size = SDL_min(len, current_music->samples * 2 - current_music->pos);
|
||||
SDL_MixAudioFormat(stream, (Uint8 *)(current_music->output + current_music->pos), AUDIO_S16, size, JA_musicVolume);
|
||||
current_music->pos += size / 2;
|
||||
int volume = JA_musicVolume;
|
||||
if (fading)
|
||||
{
|
||||
int time = SDL_GetTicks();
|
||||
if (time > (fade_start_time + fade_duration))
|
||||
{
|
||||
fading = false;
|
||||
current_music->pos = 0;
|
||||
current_music->state = JA_MUSIC_STOPPED;
|
||||
volume = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int time_passed = time - fade_start_time;
|
||||
const float percent = (float)time_passed / (float)fade_duration;
|
||||
volume = JA_musicVolume * (1.0 - percent);
|
||||
}
|
||||
}
|
||||
const int size = SDL_min(len, current_music->length - current_music->pos);
|
||||
SDL_MixAudioFormat(stream, (Uint8 *)(current_music->output) + current_music->pos, AUDIO_S16, size, volume);
|
||||
current_music->pos += size;
|
||||
if (size < len)
|
||||
{
|
||||
if (current_music->times != 0)
|
||||
{
|
||||
SDL_MixAudioFormat(stream + size, (Uint8 *)current_music->output, AUDIO_S16, len - size, JA_musicVolume);
|
||||
current_music->pos = (len - size) / 2;
|
||||
SDL_MixAudioFormat(stream + size, (Uint8 *)current_music->output, AUDIO_S16, len - size, volume);
|
||||
current_music->pos = len - size;
|
||||
if (current_music->times > 0)
|
||||
current_music->times--;
|
||||
}
|
||||
@@ -113,10 +138,36 @@ void JA_Quit()
|
||||
sdlAudioDevice = 0;
|
||||
}
|
||||
|
||||
JA_Music_t *JA_LoadMusic(const char *filename)
|
||||
JA_Music_t *JA_LoadMusic(Uint8 *buffer, Uint32 length)
|
||||
{
|
||||
int chan, samplerate;
|
||||
JA_Music_t *music = new JA_Music_t();
|
||||
|
||||
music->samples = stb_vorbis_decode_memory(buffer, length, &chan, &samplerate, &music->output);
|
||||
// [RZC 28/08/22] Abans el descomprimiem mentre el teniem obert
|
||||
// music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output);
|
||||
|
||||
SDL_AudioCVT cvt;
|
||||
SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq);
|
||||
if (cvt.needed)
|
||||
{
|
||||
cvt.len = music->samples * chan * 2;
|
||||
music->length = cvt.len;
|
||||
cvt.buf = (Uint8 *)SDL_malloc(cvt.len * cvt.len_mult);
|
||||
SDL_memcpy(cvt.buf, music->output, cvt.len);
|
||||
SDL_ConvertAudio(&cvt);
|
||||
free(music->output);
|
||||
music->output = (short *)cvt.buf;
|
||||
}
|
||||
music->length = music->samples * chan * 2;
|
||||
music->pos = 0;
|
||||
music->state = JA_MUSIC_STOPPED;
|
||||
|
||||
return music;
|
||||
}
|
||||
|
||||
JA_Music_t *JA_LoadMusic(const char *filename)
|
||||
{
|
||||
// [RZC 28/08/22] Carreguem primer el arxiu en memòria i després el descomprimim. Es algo més rapid.
|
||||
FILE *f = fopen(filename, "rb");
|
||||
fseek(f, 0, SEEK_END);
|
||||
@@ -127,33 +178,16 @@ JA_Music_t *JA_LoadMusic(const char *filename)
|
||||
return NULL;
|
||||
fclose(f);
|
||||
|
||||
JA_Music_t *music = new JA_Music_t();
|
||||
JA_Music_t *music = JA_LoadMusic(buffer, fsize);
|
||||
|
||||
music->samples = stb_vorbis_decode_memory(buffer, fsize, &chan, &samplerate, &music->output);
|
||||
free(buffer);
|
||||
// [RZC 28/08/22] Abans el descomprimiem mentre el teniem obert
|
||||
// music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output);
|
||||
|
||||
SDL_AudioCVT cvt;
|
||||
SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq);
|
||||
if (cvt.needed)
|
||||
{
|
||||
cvt.len = music->samples * chan * 2;
|
||||
cvt.buf = (Uint8 *)SDL_malloc(cvt.len * cvt.len_mult);
|
||||
SDL_memcpy(cvt.buf, music->output, cvt.len);
|
||||
SDL_ConvertAudio(&cvt);
|
||||
free(music->output);
|
||||
music->output = (short *)cvt.buf;
|
||||
}
|
||||
music->pos = 0;
|
||||
music->state = JA_MUSIC_STOPPED;
|
||||
|
||||
return music;
|
||||
}
|
||||
|
||||
void JA_PlayMusic(JA_Music_t *music, const int loop)
|
||||
{
|
||||
if (!JA_musicEnabled || !music)
|
||||
if (!JA_musicEnabled)
|
||||
return;
|
||||
|
||||
if (current_music != NULL)
|
||||
@@ -198,6 +232,19 @@ void JA_StopMusic()
|
||||
current_music->state = JA_MUSIC_STOPPED;
|
||||
}
|
||||
|
||||
void JA_FadeOutMusic(const int milliseconds)
|
||||
{
|
||||
if (!JA_musicEnabled)
|
||||
return;
|
||||
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID)
|
||||
return;
|
||||
|
||||
fading = true;
|
||||
fade_start_time = SDL_GetTicks();
|
||||
fade_duration = milliseconds;
|
||||
fade_initial_volume = JA_musicVolume;
|
||||
}
|
||||
|
||||
JA_Music_state JA_GetMusicState()
|
||||
{
|
||||
if (!JA_musicEnabled)
|
||||
@@ -223,6 +270,20 @@ int JA_SetMusicVolume(int volume)
|
||||
return JA_musicVolume;
|
||||
}
|
||||
|
||||
void JA_SetMusicPosition(float value)
|
||||
{
|
||||
if (!current_music)
|
||||
return;
|
||||
current_music->pos = value * JA_freq;
|
||||
}
|
||||
|
||||
float JA_GetMusicPosition()
|
||||
{
|
||||
if (!current_music)
|
||||
return 0;
|
||||
return float(current_music->pos) / float(JA_freq);
|
||||
}
|
||||
|
||||
void JA_EnableMusic(const bool value)
|
||||
{
|
||||
if (!value && current_music != NULL && current_music->state == JA_MUSIC_PLAYING)
|
||||
@@ -239,6 +300,25 @@ JA_Sound_t *JA_NewSound(Uint8 *buffer, Uint32 length)
|
||||
return sound;
|
||||
}
|
||||
|
||||
JA_Sound_t *JA_LoadSound(uint8_t *buffer, uint32_t size)
|
||||
{
|
||||
JA_Sound_t *sound = new JA_Sound_t();
|
||||
SDL_AudioSpec wavSpec;
|
||||
SDL_LoadWAV_RW(SDL_RWFromMem(buffer, size), 1, &wavSpec, &sound->buffer, &sound->length);
|
||||
|
||||
SDL_AudioCVT cvt;
|
||||
SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq);
|
||||
cvt.len = sound->length;
|
||||
cvt.buf = (Uint8 *)SDL_malloc(cvt.len * cvt.len_mult);
|
||||
SDL_memcpy(cvt.buf, sound->buffer, sound->length);
|
||||
SDL_ConvertAudio(&cvt);
|
||||
SDL_FreeWAV(sound->buffer);
|
||||
sound->buffer = cvt.buf;
|
||||
sound->length = cvt.len_cvt;
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
||||
JA_Sound_t *JA_LoadSound(const char *filename)
|
||||
{
|
||||
JA_Sound_t *sound = new JA_Sound_t();
|
||||
@@ -260,8 +340,8 @@ JA_Sound_t *JA_LoadSound(const char *filename)
|
||||
|
||||
int JA_PlaySound(JA_Sound_t *sound, const int loop)
|
||||
{
|
||||
if (!JA_soundEnabled || !sound)
|
||||
return 0;
|
||||
if (!JA_soundEnabled)
|
||||
return -1;
|
||||
|
||||
int channel = 0;
|
||||
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE)
|
||||
@@ -278,6 +358,21 @@ int JA_PlaySound(JA_Sound_t *sound, const int loop)
|
||||
return channel;
|
||||
}
|
||||
|
||||
int JA_PlaySoundOnChannel(JA_Sound_t *sound, const int channel, const int loop)
|
||||
{
|
||||
if (!JA_soundEnabled)
|
||||
return -1;
|
||||
|
||||
if (channel >= JA_MAX_SIMULTANEOUS_CHANNELS)
|
||||
return -1;
|
||||
|
||||
channels[channel].sound = sound;
|
||||
channels[channel].times = loop;
|
||||
channels[channel].pos = 0;
|
||||
channels[channel].state = JA_CHANNEL_PLAYING;
|
||||
return channel;
|
||||
}
|
||||
|
||||
void JA_DeleteSound(JA_Sound_t *sound)
|
||||
{
|
||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL_audio.h> // para SDL_AudioFormat
|
||||
#include <SDL2/SDL_stdinc.h> // para Uint32, Uint8
|
||||
struct JA_Music_t; // lines 5-5
|
||||
struct JA_Sound_t; // lines 6-6
|
||||
#include <SDL2/SDL_audio.h> // Para SDL_AudioFormat
|
||||
#include <SDL2/SDL_stdinc.h> // Para Uint32, Uint8
|
||||
struct JA_Music_t; // lines 4-4
|
||||
struct JA_Sound_t; // lines 5-5
|
||||
|
||||
enum JA_Channel_state
|
||||
{
|
||||
@@ -26,18 +26,24 @@ void JA_Init(const int freq, const SDL_AudioFormat format, const int channels);
|
||||
void JA_Quit();
|
||||
|
||||
JA_Music_t *JA_LoadMusic(const char *filename);
|
||||
JA_Music_t *JA_LoadMusic(Uint8 *buffer, Uint32 length);
|
||||
void JA_PlayMusic(JA_Music_t *music, const int loop = -1);
|
||||
void JA_PauseMusic();
|
||||
void JA_ResumeMusic();
|
||||
void JA_StopMusic();
|
||||
void JA_FadeOutMusic(const int milliseconds);
|
||||
JA_Music_state JA_GetMusicState();
|
||||
void JA_DeleteMusic(JA_Music_t *music);
|
||||
int JA_SetMusicVolume(int volume);
|
||||
void JA_SetMusicPosition(float value);
|
||||
float JA_GetMusicPosition();
|
||||
void JA_EnableMusic(const bool value);
|
||||
|
||||
JA_Sound_t *JA_NewSound(Uint8 *buffer, Uint32 length);
|
||||
JA_Sound_t *JA_LoadSound(Uint8 *buffer, Uint32 length);
|
||||
JA_Sound_t *JA_LoadSound(const char *filename);
|
||||
int JA_PlaySound(JA_Sound_t *sound, const int loop = 0);
|
||||
int JA_PlaySoundOnChannel(JA_Sound_t *sound, const int channel, const int loop = 0);
|
||||
void JA_PauseChannel(const int channel);
|
||||
void JA_ResumeChannel(const int channel);
|
||||
void JA_StopChannel(const int channel);
|
||||
|
||||
@@ -40,4 +40,12 @@ namespace lang
|
||||
{
|
||||
return texts.at(index);
|
||||
}
|
||||
|
||||
// Cambia el idioma seleccionado al siguiente idioma disponible
|
||||
Code change(Code current_lang)
|
||||
{
|
||||
auto index = static_cast<int>(current_lang);
|
||||
index = (index + 1) % 3;
|
||||
return static_cast<Code>(index);
|
||||
}
|
||||
}
|
||||
@@ -16,4 +16,7 @@ namespace lang
|
||||
|
||||
// Obtiene la cadena de texto del indice
|
||||
std::string getText(int index);
|
||||
|
||||
// Cambia el idioma seleccionado al siguiente idioma disponible
|
||||
Code change(Code current_lang);
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "sprite.h" // Para Sprite
|
||||
#include "texture.h" // Para Texture
|
||||
#include "utils.h" // Para Color, Zone
|
||||
#include "mouse.h"
|
||||
|
||||
// Constructor
|
||||
Logo::Logo()
|
||||
@@ -59,6 +60,7 @@ Logo::~Logo()
|
||||
{
|
||||
jail_texture_->setColor(255, 255, 255);
|
||||
since_texture_->setColor(255, 255, 255);
|
||||
JA_StopChannel(-1);
|
||||
}
|
||||
|
||||
// Recarga todas las texturas
|
||||
@@ -91,6 +93,9 @@ void Logo::checkEvents()
|
||||
reloadTextures();
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba el cursor
|
||||
Mouse::handleEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +105,6 @@ void Logo::checkInput()
|
||||
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
|
||||
if (Input::get()->checkAnyButtonPressed())
|
||||
{
|
||||
JA_StopMusic();
|
||||
section::name = section::Name::TITLE;
|
||||
section::options = section::Options::TITLE_1;
|
||||
return;
|
||||
@@ -113,6 +117,11 @@ void Logo::checkInput()
|
||||
// Gestiona el logo de JAILGAME
|
||||
void Logo::updateJAILGAMES()
|
||||
{
|
||||
if (counter_ == 30)
|
||||
{
|
||||
JA_PlaySound(Resource::get()->getSound("logo.wav"));
|
||||
}
|
||||
|
||||
if (counter_ > 30)
|
||||
{
|
||||
for (int i = 0; i < (int)jail_sprite_.size(); ++i)
|
||||
@@ -195,6 +204,9 @@ void Logo::update()
|
||||
{
|
||||
section::name = section::Name::INTRO;
|
||||
}
|
||||
|
||||
// Actualiza las variables de globalInputs
|
||||
globalInputs::update();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,14 +231,14 @@ void Logo::render()
|
||||
}
|
||||
|
||||
// Vuelca el contenido del renderizador en pantalla
|
||||
Screen::get()->blit();
|
||||
Screen::get()->render();
|
||||
}
|
||||
|
||||
// Bucle para el logo del juego
|
||||
void Logo::run()
|
||||
{
|
||||
// Detiene la música
|
||||
JA_StopMusic();
|
||||
JA_FadeOutMusic(300);
|
||||
|
||||
while (section::name == section::Name::LOGO)
|
||||
{
|
||||
|
||||
@@ -27,7 +27,7 @@ void ManageHiScoreTable::clear()
|
||||
}
|
||||
|
||||
// Añade un elemento a la tabla
|
||||
void ManageHiScoreTable::add(HiScoreEntry entry)
|
||||
int ManageHiScoreTable::add(const HiScoreEntry &entry)
|
||||
{
|
||||
// Añade la entrada a la tabla
|
||||
table_.push_back(entry);
|
||||
@@ -35,8 +35,32 @@ void ManageHiScoreTable::add(HiScoreEntry entry)
|
||||
// Ordena la tabla
|
||||
sort();
|
||||
|
||||
// Encontrar la posición del nuevo elemento
|
||||
auto it = std::find_if(table_.begin(), table_.end(), [&](const HiScoreEntry &e)
|
||||
{ return e.name == entry.name &&
|
||||
e.score == entry.score &&
|
||||
e.one_credit_complete == entry.one_credit_complete; });
|
||||
|
||||
int position = -1;
|
||||
if (it != table_.end())
|
||||
{
|
||||
position = std::distance(table_.begin(), it);
|
||||
}
|
||||
|
||||
// Deja solo las 10 primeras entradas
|
||||
table_.resize(10);
|
||||
if (table_.size() > 10)
|
||||
{
|
||||
table_.resize(10);
|
||||
|
||||
// Si el nuevo elemento quedó fuera del top 10
|
||||
if (position >= 10)
|
||||
{
|
||||
position = -1; // No entró en el top 10
|
||||
}
|
||||
}
|
||||
|
||||
// Devuelve la posición
|
||||
return position;
|
||||
}
|
||||
|
||||
// Ordena la tabla
|
||||
@@ -50,52 +74,55 @@ void ManageHiScoreTable::sort()
|
||||
std::sort(table_.begin(), table_.end(), scoreDescendingComparator);
|
||||
}
|
||||
|
||||
// Carga la tabla con los datos de un fichero
|
||||
// Carga la tabla desde un fichero
|
||||
bool ManageHiScoreTable::loadFromFile(const std::string &file_path)
|
||||
{
|
||||
clear();
|
||||
auto success = true;
|
||||
auto file = SDL_RWFromFile(file_path.c_str(), "r+b");
|
||||
auto file = SDL_RWFromFile(file_path.c_str(), "rb");
|
||||
|
||||
if (file)
|
||||
{
|
||||
std::cout << "Reading file: " << getFileName(file_path) << std::endl;
|
||||
table_.clear(); // Limpia la tabla actual
|
||||
|
||||
for (auto &entry : table_)
|
||||
// Lee el número de entradas en la tabla
|
||||
int tableSize = 0;
|
||||
SDL_RWread(file, &tableSize, sizeof(int), 1);
|
||||
|
||||
// Lee los datos de cada entrada
|
||||
for (int i = 0; i < tableSize; ++i)
|
||||
{
|
||||
HiScoreEntry entry;
|
||||
|
||||
// Lee la puntuación
|
||||
SDL_RWread(file, &entry.score, sizeof(int), 1);
|
||||
|
||||
// Lee el tamaño del nombre y luego el nombre
|
||||
int nameSize = 0;
|
||||
|
||||
if (SDL_RWread(file, &entry.score, sizeof(int), 1) == 0)
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (SDL_RWread(file, &nameSize, sizeof(int), 1) == 0)
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
SDL_RWread(file, &nameSize, sizeof(int), 1);
|
||||
|
||||
std::vector<char> nameBuffer(nameSize + 1);
|
||||
if (SDL_RWread(file, nameBuffer.data(), sizeof(char) * nameSize, 1) == 0)
|
||||
{
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
nameBuffer[nameSize] = '\0';
|
||||
SDL_RWread(file, nameBuffer.data(), nameSize, 1);
|
||||
nameBuffer[nameSize] = '\0'; // Asegurar el fin de la cadena
|
||||
entry.name = std::string(nameBuffer.data());
|
||||
|
||||
// Lee el valor de one_credit_complete
|
||||
int occValue = 0;
|
||||
SDL_RWread(file, &occValue, sizeof(int), 1);
|
||||
entry.one_credit_complete = (occValue != 0);
|
||||
|
||||
// Añade la entrada a la tabla
|
||||
table_.push_back(entry);
|
||||
}
|
||||
|
||||
std::cout << "Reading file: " << getFileName(file_path) << std::endl;
|
||||
SDL_RWclose(file);
|
||||
}
|
||||
|
||||
if (!success)
|
||||
else
|
||||
{
|
||||
clear();
|
||||
std::cout << "Error: Unable to load " << getFileName(file_path) << " file! " << SDL_GetError() << std::endl;
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -107,21 +134,35 @@ bool ManageHiScoreTable::saveToFile(const std::string &file_path)
|
||||
|
||||
if (file)
|
||||
{
|
||||
// Guarda los datos
|
||||
for (int i = 0; i < (int)table_.size(); ++i)
|
||||
// Guarda el número de entradas en la tabla
|
||||
int tableSize = static_cast<int>(table_.size());
|
||||
SDL_RWwrite(file, &tableSize, sizeof(int), 1);
|
||||
|
||||
// Guarda los datos de cada entrada
|
||||
for (int i = 0; i < tableSize; ++i)
|
||||
{
|
||||
SDL_RWwrite(file, &table_.at(i).score, sizeof(int), 1);
|
||||
const int nameSize = (int)table_.at(i).name.size();
|
||||
const HiScoreEntry &entry = table_.at(i);
|
||||
|
||||
// Guarda la puntuación
|
||||
SDL_RWwrite(file, &entry.score, sizeof(int), 1);
|
||||
|
||||
// Guarda el tamaño del nombre y luego el nombre
|
||||
int nameSize = static_cast<int>(entry.name.size());
|
||||
SDL_RWwrite(file, &nameSize, sizeof(int), 1);
|
||||
SDL_RWwrite(file, table_.at(i).name.c_str(), nameSize, 1);
|
||||
SDL_RWwrite(file, entry.name.c_str(), nameSize, 1);
|
||||
|
||||
// Guarda el valor de one_credit_complete como un entero (0 o 1)
|
||||
int occValue = entry.one_credit_complete ? 1 : 0;
|
||||
SDL_RWwrite(file, &occValue, sizeof(int), 1);
|
||||
}
|
||||
|
||||
std::cout << "Writing file: " << getFileName(file_path).c_str() << std::endl;
|
||||
std::cout << "Writing file: " << getFileName(file_path) << std::endl;
|
||||
SDL_RWclose(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Error: Unable to save " << getFileName(file_path).c_str() << " file! " << SDL_GetError() << std::endl;
|
||||
std::cout << "Error: Unable to save " << getFileName(file_path) << " file! " << SDL_GetError() << std::endl;
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
@@ -14,12 +14,13 @@
|
||||
// Estructura para las entradas de la tabla de recirds
|
||||
struct HiScoreEntry
|
||||
{
|
||||
std::string name; // Nombre
|
||||
int score; // Puntuación
|
||||
std::string name; // Nombre
|
||||
int score; // Puntuación
|
||||
bool one_credit_complete; // Indica si se ha conseguido 1CC
|
||||
|
||||
// Constructor
|
||||
explicit HiScoreEntry(const std::string &n = "", int s = 0)
|
||||
: name(n), score(s) {}
|
||||
// Constructor
|
||||
explicit HiScoreEntry(const std::string &n = "", int s = 0, bool occ = false)
|
||||
: name(n.substr(0, 6)), score(s), one_credit_complete(occ) {}
|
||||
};
|
||||
|
||||
// Clase ManageHiScoreTable
|
||||
@@ -44,7 +45,7 @@ public:
|
||||
void clear();
|
||||
|
||||
// Añade un elemento a la tabla
|
||||
void add(HiScoreEntry entry);
|
||||
int add(const HiScoreEntry& entry);
|
||||
|
||||
// Carga la tabla con los datos de un fichero
|
||||
bool loadFromFile(const std::string &file_path);
|
||||
|
||||
35
source/mouse.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "mouse.h"
|
||||
#include <SDL2/SDL_mouse.h> // Para SDL_ShowCursor
|
||||
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
|
||||
|
||||
namespace Mouse
|
||||
{
|
||||
Uint32 cursor_hide_time = 3000; // Tiempo en milisegundos para ocultar el cursor
|
||||
Uint32 last_mouse_move_time = 0; // Última vez que el ratón se movió
|
||||
bool cursor_visible = true; // Estado del cursor
|
||||
|
||||
void handleEvent(const SDL_Event &event)
|
||||
{
|
||||
if (event.type == SDL_MOUSEMOTION)
|
||||
{
|
||||
last_mouse_move_time = SDL_GetTicks();
|
||||
if (!cursor_visible)
|
||||
{
|
||||
#ifndef ARCADE
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
#endif
|
||||
cursor_visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateCursorVisibility()
|
||||
{
|
||||
Uint32 current_time = SDL_GetTicks();
|
||||
if (cursor_visible && (current_time - last_mouse_move_time > cursor_hide_time))
|
||||
{
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
cursor_visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
source/mouse.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL_events.h> // Para SDL_Event
|
||||
#include <SDL2/SDL_stdinc.h> // Para Uint32
|
||||
|
||||
namespace Mouse
|
||||
{
|
||||
extern Uint32 cursor_hide_time; // Tiempo en milisegundos para ocultar el cursor
|
||||
extern Uint32 last_mouse_move_time; // Última vez que el ratón se movió
|
||||
extern bool cursor_visible; // Estado del cursor
|
||||
|
||||
void handleEvent(const SDL_Event &event);
|
||||
void updateCursorVisibility();
|
||||
}
|
||||
@@ -10,14 +10,15 @@
|
||||
#include "sprite.h" // Para Sprite
|
||||
#include "text.h" // Para Text
|
||||
#include "texture.h" // Para Texture
|
||||
#include "resource.h"
|
||||
|
||||
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
|
||||
Notifier *Notifier::notifier_ = nullptr;
|
||||
|
||||
// [SINGLETON] Crearemos el objeto screen con esta función estática
|
||||
void Notifier::init(const std::string &icon_file, std::shared_ptr<Text> text, const std::string &sound_file)
|
||||
void Notifier::init(const std::string &icon_file, std::shared_ptr<Text> text)
|
||||
{
|
||||
Notifier::notifier_ = new Notifier(icon_file, text, sound_file);
|
||||
Notifier::notifier_ = new Notifier(icon_file, text);
|
||||
}
|
||||
|
||||
// [SINGLETON] Destruiremos el objeto screen con esta función estática
|
||||
@@ -33,21 +34,14 @@ Notifier *Notifier::get()
|
||||
}
|
||||
|
||||
// Constructor
|
||||
Notifier::Notifier(std::string icon_file, std::shared_ptr<Text> text, const std::string &sound_file)
|
||||
Notifier::Notifier(std::string icon_file, std::shared_ptr<Text> text)
|
||||
: renderer_(Screen::get()->getRenderer()),
|
||||
icon_texture_(!icon_file.empty() ? std::make_unique<Texture>(renderer_, icon_file) : nullptr),
|
||||
text_(text),
|
||||
bg_color_(param.notification.color),
|
||||
wait_time_(150),
|
||||
stack_(false),
|
||||
has_icons_(!icon_file.empty()),
|
||||
sound_(JA_LoadSound(sound_file.c_str())) {}
|
||||
|
||||
// Destructor
|
||||
Notifier::~Notifier()
|
||||
{
|
||||
JA_DeleteSound(sound_);
|
||||
}
|
||||
has_icons_(!icon_file.empty()) {}
|
||||
|
||||
// Dibuja las notificaciones por pantalla
|
||||
void Notifier::render()
|
||||
@@ -66,7 +60,7 @@ void Notifier::update()
|
||||
// Si la notificación anterior está "saliendo", no hagas nada
|
||||
if (i > 0)
|
||||
{
|
||||
if (notifications_[i - 1].status == NotificationStatus::RISING)
|
||||
if (notifications_[i - 1].state == NotificationStatus::RISING)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -79,15 +73,16 @@ void Notifier::update()
|
||||
{
|
||||
if (param.notification.sound)
|
||||
{
|
||||
if (notifications_[i].status == NotificationStatus::RISING)
|
||||
{ // Reproduce el sonido de la notificación
|
||||
JA_PlaySound(sound_);
|
||||
if (notifications_[i].state == NotificationStatus::RISING)
|
||||
{
|
||||
// Reproduce el sonido de la notificación
|
||||
JA_PlaySound(Resource::get()->getSound("notify.wav"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba los estados
|
||||
if (notifications_[i].status == NotificationStatus::RISING)
|
||||
if (notifications_[i].state == NotificationStatus::RISING)
|
||||
{
|
||||
const float step = ((float)notifications_[i].counter / notifications_[i].travel_dist);
|
||||
const int alpha = 255 * step;
|
||||
@@ -104,21 +99,21 @@ void Notifier::update()
|
||||
|
||||
if (notifications_[i].rect.y == notifications_[i].y)
|
||||
{
|
||||
notifications_[i].status = NotificationStatus::STAY;
|
||||
notifications_[i].state = NotificationStatus::STAY;
|
||||
notifications_[i].texture->setAlpha(255);
|
||||
notifications_[i].counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
else if (notifications_[i].status == NotificationStatus::STAY)
|
||||
else if (notifications_[i].state == NotificationStatus::STAY)
|
||||
{
|
||||
if (notifications_[i].counter == wait_time_)
|
||||
{
|
||||
notifications_[i].status = NotificationStatus::VANISHING;
|
||||
notifications_[i].state = NotificationStatus::VANISHING;
|
||||
notifications_[i].counter = 0;
|
||||
}
|
||||
}
|
||||
else if (notifications_[i].status == NotificationStatus::VANISHING)
|
||||
else if (notifications_[i].state == NotificationStatus::VANISHING)
|
||||
{
|
||||
|
||||
const float step = (notifications_[i].counter / (float)notifications_[i].travel_dist);
|
||||
@@ -136,7 +131,7 @@ void Notifier::update()
|
||||
|
||||
if (notifications_[i].rect.y == notifications_[i].y - notifications_[i].travel_dist)
|
||||
{
|
||||
notifications_[i].status = NotificationStatus::FINISHED;
|
||||
notifications_[i].state = NotificationStatus::FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +146,7 @@ void Notifier::clearFinishedNotifications()
|
||||
{
|
||||
for (int i = (int)notifications_.size() - 1; i >= 0; --i)
|
||||
{
|
||||
if (notifications_[i].status == NotificationStatus::FINISHED)
|
||||
if (notifications_[i].state == NotificationStatus::FINISHED)
|
||||
{
|
||||
notifications_.erase(notifications_.begin() + i);
|
||||
}
|
||||
@@ -307,7 +302,7 @@ void Notifier::clearNotifications()
|
||||
{
|
||||
for (auto ¬ification : notifications_)
|
||||
{
|
||||
notification.status = NotificationStatus::FINISHED;
|
||||
notification.state = NotificationStatus::FINISHED;
|
||||
}
|
||||
|
||||
clearFinishedNotifications();
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL_rect.h> // para SDL_Rect
|
||||
#include <SDL2/SDL_render.h> // para SDL_Renderer
|
||||
#include <memory> // para shared_ptr, unique_ptr
|
||||
#include <string> // para string, basic_string
|
||||
#include <vector> // para vector
|
||||
#include "utils.h" // para Color
|
||||
class Sprite;
|
||||
class Text;
|
||||
class Texture;
|
||||
struct JA_Sound_t; // lines 12-12
|
||||
#include <SDL2/SDL_rect.h> // Para SDL_Rect
|
||||
#include <SDL2/SDL_render.h> // Para SDL_Renderer
|
||||
#include <memory> // Para shared_ptr
|
||||
#include <string> // Para string, basic_string
|
||||
#include <vector> // Para vector
|
||||
#include "utils.h" // Para Color
|
||||
class Sprite; // lines 9-9
|
||||
class Text; // lines 10-10
|
||||
class Texture; // lines 11-11
|
||||
|
||||
class Notifier
|
||||
{
|
||||
@@ -37,7 +36,7 @@ private:
|
||||
std::shared_ptr<Sprite> sprite;
|
||||
std::vector<std::string> texts;
|
||||
int counter;
|
||||
NotificationStatus status;
|
||||
NotificationStatus state;
|
||||
NotificationShape shape;
|
||||
SDL_Rect rect;
|
||||
int y;
|
||||
@@ -46,7 +45,7 @@ private:
|
||||
|
||||
// Constructor
|
||||
explicit Notification()
|
||||
: texture(nullptr), sprite(nullptr), texts(), counter(0), status(NotificationStatus::RISING),
|
||||
: texture(nullptr), sprite(nullptr), texts(), counter(0), state(NotificationStatus::RISING),
|
||||
shape(NotificationShape::SQUARED), rect{0, 0, 0, 0}, y(0), travel_dist(0), code("") {}
|
||||
};
|
||||
|
||||
@@ -62,7 +61,6 @@ private:
|
||||
std::vector<Notification> notifications_; // La lista de notificaciones activas
|
||||
bool stack_; // Indica si las notificaciones se apilan
|
||||
bool has_icons_; // Indica si el notificador tiene textura para iconos
|
||||
JA_Sound_t *sound_; // Sonido a reproducir cuando suena la notificación
|
||||
|
||||
// Elimina las notificaciones finalizadas
|
||||
void clearFinishedNotifications();
|
||||
@@ -73,14 +71,14 @@ private:
|
||||
// [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos notifier desde fuera
|
||||
|
||||
// Constructor
|
||||
Notifier(std::string icon_file, std::shared_ptr<Text> text, const std::string &sound_file);
|
||||
Notifier(std::string icon_file, std::shared_ptr<Text> text);
|
||||
|
||||
// Destructor
|
||||
~Notifier();
|
||||
~Notifier() = default;
|
||||
|
||||
public:
|
||||
// [SINGLETON] Crearemos el objeto notifier con esta función estática
|
||||
static void init(const std::string &icon_file, std::shared_ptr<Text> text, const std::string &sound_file);
|
||||
static void init(const std::string &icon_file, std::shared_ptr<Text> text);
|
||||
|
||||
// [SINGLETON] Destruiremos el objeto notifier con esta función estática
|
||||
static void destroy();
|
||||
|
||||
@@ -44,6 +44,7 @@ void initOptions()
|
||||
options.game.difficulty = GameDifficulty::NORMAL;
|
||||
options.game.language = lang::Code::ba_BA;
|
||||
options.game.autofire = true;
|
||||
options.game.clear_last_hi_score_entries();
|
||||
|
||||
// Opciones de control
|
||||
options.controllers.clear();
|
||||
|
||||
@@ -23,7 +23,8 @@ enum class GameDifficulty
|
||||
// Estructura para las opciones de la ventana
|
||||
struct OptionsWindow
|
||||
{
|
||||
int size; // Contiene el valor por el que se multiplica el tamaño de la ventana
|
||||
int size = 1; // Contiene el valor por el que se multiplica el tamaño de la ventana
|
||||
int max_size = 1; // Tamaño máximo para que el tamaño de la ventana no sea mayor que el tamaño de la pantalla
|
||||
};
|
||||
|
||||
// Estructura con opciones para el video
|
||||
@@ -63,10 +64,18 @@ struct OptionsAudio
|
||||
// Estructura para las opciones del juego
|
||||
struct OptionsGame
|
||||
{
|
||||
GameDifficulty difficulty; // Dificultad del juego
|
||||
lang::Code language; // Idioma usado en el juego
|
||||
bool autofire; // Indica si el jugador ha de pulsar repetidamente para disparar o basta con mantener pulsado
|
||||
std::vector<HiScoreEntry> hi_score_table; // Tabla con las mejores puntuaciones
|
||||
GameDifficulty difficulty; // Dificultad del juego
|
||||
lang::Code language; // Idioma usado en el juego
|
||||
bool autofire; // Indicador de autofire
|
||||
std::vector<HiScoreEntry> hi_score_table; // Tabla de mejores puntuaciones
|
||||
std::vector<int> last_hi_score_entry = { -1, -1 }; // Inicialización directa con dos elementos en -1
|
||||
|
||||
// Método para reiniciar las últimas entradas de puntuación
|
||||
void clear_last_hi_score_entries()
|
||||
{
|
||||
last_hi_score_entry[0] = -1;
|
||||
last_hi_score_entry[1] = -1;
|
||||
}
|
||||
};
|
||||
|
||||
// Estructura para los controles del juego
|
||||
|
||||
@@ -21,6 +21,8 @@ void initParam()
|
||||
param.game.width = 320;
|
||||
param.game.height = 256;
|
||||
param.game.item_size = 20;
|
||||
param.game.coffee_machine_w = 28;
|
||||
param.game.coffee_machine_h = 37;
|
||||
param.game.game_area.rect = {0, 0, param.game.width, param.game.height};
|
||||
param.game.play_area.rect = {0, 0, param.game.width, 216};
|
||||
param.game.enter_name_seconds = 30;
|
||||
@@ -124,6 +126,16 @@ bool setParams(const std::string &var, const std::string &value)
|
||||
param.game.item_size = std::stoi(value);
|
||||
}
|
||||
|
||||
else if (var == "game.coffee_machine_w")
|
||||
{
|
||||
param.game.coffee_machine_w = std::stoi(value);
|
||||
}
|
||||
|
||||
else if (var == "game.coffee_machine_h")
|
||||
{
|
||||
param.game.coffee_machine_h = std::stoi(value);
|
||||
}
|
||||
|
||||
else if (var == "game.play_area.rect.x")
|
||||
{
|
||||
param.game.play_area.rect.x = std::stoi(value);
|
||||
|
||||
@@ -11,6 +11,8 @@ struct ParamGame
|
||||
int width; // Ancho de la resolucion nativa del juego
|
||||
int height; // Alto de la resolucion nativa del juego
|
||||
int item_size; // Tamaño de los items del juego
|
||||
int coffee_machine_w; // Ancho de la máquina de café
|
||||
int coffee_machine_h; // Alto de la máquina de café
|
||||
Zone play_area; // Rectangulo con la posición de la zona de juego
|
||||
Zone game_area; // Rectangulo con las dimensiones del juego
|
||||
int enter_name_seconds; // Duración en segundos para introducir el nombre al finalizar la partida
|
||||
@@ -63,7 +65,8 @@ struct ParamNotification
|
||||
};
|
||||
|
||||
// Estructura para almacenar todos los parámetros del juego
|
||||
struct Param {
|
||||
struct Param
|
||||
{
|
||||
ParamGame game;
|
||||
ParamFade fade;
|
||||
SDL_Rect scoreboard;
|
||||
@@ -72,14 +75,14 @@ struct Param {
|
||||
std::vector<ParamBalloon> balloon;
|
||||
ParamNotification notification;
|
||||
|
||||
Param() : game(), fade(), scoreboard(), title(), background(), notification() {
|
||||
Param() : game(), fade(), scoreboard(), title(), background(), notification()
|
||||
{
|
||||
balloon.reserve(4);
|
||||
}
|
||||
};
|
||||
|
||||
extern Param param;
|
||||
|
||||
|
||||
extern Param param;
|
||||
|
||||
// Establece valores para los parametros a partir de un fichero de texto
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// IWYU pragma: no_include <bits/std_abs.h>
|
||||
#include "path_sprite.h"
|
||||
#include <cstdlib> // Para abs
|
||||
#include <functional> // Para function
|
||||
@@ -95,7 +96,17 @@ void PathSprite::addPath(std::vector<SDL_Point> spots, int waiting_counter)
|
||||
// Habilita el objeto
|
||||
void PathSprite::enable()
|
||||
{
|
||||
if (paths_.size() == 0 || enabled_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
enabled_ = true;
|
||||
|
||||
// Establece la posición
|
||||
auto &path = paths_.at(current_path_);
|
||||
const auto &p = path.spots.at(path.counter);
|
||||
setPosition(p);
|
||||
}
|
||||
|
||||
// Coloca el sprite en los diferentes puntos del recorrido
|
||||
@@ -122,9 +133,13 @@ void PathSprite::moveThroughCurrentPath()
|
||||
if (path.on_destination)
|
||||
{
|
||||
if (path.waiting_counter == 0)
|
||||
{
|
||||
path.finished = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
--path.waiting_counter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,11 +148,15 @@ void PathSprite::goToNextPathOrDie()
|
||||
{
|
||||
// Comprueba si ha terminado el recorrdo actual
|
||||
if (paths_.at(current_path_).finished)
|
||||
{
|
||||
++current_path_;
|
||||
}
|
||||
|
||||
// Comprueba si quedan mas recorridos
|
||||
if (current_path_ >= static_cast<int>(paths_.size()))
|
||||
{
|
||||
enabled_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Indica si ha terminado todos los recorridos
|
||||
|
||||