Compare commits

106 Commits

Author SHA1 Message Date
482dc3de54 Afegit global_events.cpp 2025-03-10 23:24:00 +01:00
9d98d3ea6a Passat gif.c a gif.cpp
Afegit reloadTextures a Resources
2025-03-10 22:38:23 +01:00
9c1b3c45b0 Demana confirmació per a canviar el idioma amb les tecles ràpides
Demana confirmació per reiniciar
2025-03-10 21:22:32 +01:00
79b2917112 Pots pasar quan mostra el nom que has introdiut apretant qualsevol botó de disparar 2025-03-10 20:13:38 +01:00
c88a277cba Si no poses cap nom, tria un nom de jailer al azar 2025-03-10 19:59:21 +01:00
e0c10f83d6 Codi preparat per als dibuixets nous per a la intro 2025-03-09 18:30:14 +01:00
72cb39da78 canvi de pc 2025-03-08 22:23:40 +01:00
9f8d1fbcd7 Eliminat el logo de RetroWeekend per falta de temps i pq era lleig 2025-03-08 20:17:31 +01:00
e523692e99 Els sprites de la intro ja apareixen i desapareixen com en el CC original 2025-03-08 17:47:13 +01:00
83bdd67cee No se perque ha aparegunt un SDL_Destroy(mi_textura) que no es meu i te pinta de que se l'ha inventat el autocompletar de la IA i estava pegant explosions en Linux 2025-03-08 17:27:06 +01:00
66e5105c84 Actualitzat README.md 2025-03-08 17:19:56 +01:00
f8449ea6d1 Afegida politica al fitxer CMakeLists.txt 2025-03-08 10:16:08 +01:00
f43d18e6f0 Arreglos tontos de codi 2025-02-23 09:12:15 +01:00
a42141ebd7 canvi de pc 2025-02-21 19:45:58 +01:00
29c85fecad canvi de pc 2025-02-21 18:26:32 +01:00
04ff428aa0 Treballant en el segon logo 2025-02-07 14:55:34 +01:00
84595da13a EnterName: si has plenat tots els slots de lletres, apretar una volta mes el de fixar lletra fixa el nom 2025-02-07 14:15:18 +01:00
01591175ef Pos pense que ja està tot apanyat lo de EnterName i Scoreboard 2025-02-07 13:45:07 +01:00
29bc4a64fd Afegit position_overflow_ per a EnterName i poder plenar tots els slots de lletres 2025-02-07 12:31:59 +01:00
559210652f Treballant en scoreboard::fillPanelTextures 2025-02-06 20:58:15 +01:00
44e4ca490d canvi de pc
treballant en enter name
2025-02-06 14:59:25 +01:00
3cebee2ae4 Implementat control de repetició per als eixos del joystick 2025-02-06 12:36:16 +01:00
270d7d1848 Duplicada la font 04b_25 per a tindre versió gris i versió negra. La gris es la que es por modular amb colors.
Eliminada la font nokia que ja no s'estava utilitzant.
Optimitzada la càrrega de fonts al permetre reutilitzar fitxers .txt de altres fonts
2025-02-06 10:31:32 +01:00
ccf005dce1 Afegit el disparador per a la aparició del enemic nou 2025-02-06 09:59:58 +01:00
5755947ff7 La tabla de puntuació ja mostra amb altre color la puntuació que s'acaba d'afegir
fix: la tabla de punts no guardava a disc el estat de 1CC de cada entrada
2025-02-05 22:52:19 +01:00
6f594b9a1f La tabla de puntuacions ja mostra aquelles aconseguides amb 1CC 2025-02-05 15:15:48 +01:00
7e2021da70 canvi de pc 2025-02-05 10:17:49 +01:00
0a9a92d4b7 El text de la tabla de puntuacion ja ix centrat i el "diferent" es el que fa 10 2025-02-05 09:45:30 +01:00
b01763b749 Dels credits ja passa a la tabla de puntuacions 2025-01-26 21:15:13 +01:00
59b9f61d69 Font nova per a la intro 2025-01-26 21:05:43 +01:00
b9f194a2b1 Afegit efecte d'eixida a les instruccions 2025-01-26 20:16:43 +01:00
59936f13eb Arreglos estetics i de colorets en hiscore_table.cpp 2025-01-26 17:48:10 +01:00
bad0a10328 Ja es mouen els sprites en hiscore_table.cpp, falta decidir-se per un disseny concret 2025-01-25 22:57:49 +01:00
52a0c2b91f Treballant en la nova tabla de records: ja pinta amb sprites 2025-01-25 21:17:45 +01:00
f12a456017 Alguns arreglos en updateTimeStopped() 2025-01-25 18:51:39 +01:00
f39e65afaf Ja no se que he tocat i qué no, cosetes del malo nou 2025-01-25 18:47:06 +01:00
d3183237df Estandaritzats els noms dels fitxers de audio
Eliminat el soroll de TNT que feia ANYS que no existía
2025-01-25 18:15:49 +01:00
60302004f4 Afegits efectes de audio nous
Retocats alguns efectes de audio al afagar items per a no solapar dos audios
2025-01-25 18:11:24 +01:00
e60938cb19 El malo nou ja suca cosetes, falta ajustar un poc els paràmetres 2025-01-25 17:41:45 +01:00
2b3cc719ba Fix del fix: aaaara si que lleva el garbage de la zona negra. Havia posat el clean() on no tocava 2025-01-25 13:14:25 +01:00
d01c91ebde Fix: m'havia carregat el shakeEffect() de la pantalla quan havia shaders, i de paso he vist que el que tenbia fet shakejava també les notificacions i els menus de debug. Ale, ja està tot arreglaet.
Fix: tampoc estava netejant la pantalla, pensava que no feia falta, pero quan SDL replena de negre la finestra en pantalla completa, havia gorrinades
2025-01-24 20:20:50 +01:00
7130f2298a Merge branch 'main' of https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis_arcade_edition 2025-01-24 10:44:58 +01:00
380cc17861 Fix: ara apaga el sistem al final del tot, almenys quan ja ha escrit la configuració a disc 2025-01-24 10:43:00 +01:00
a5388873e3 Actualizar README.md 2025-01-05 15:47:51 +01:00
28b37af31d Actualitzada la data de la versió 2025-01-05 14:38:48 +01:00
4d590f79f5 fix: es podia pulsar per a jugar mentre feia el fade cap a la demo 2025-01-05 14:36:38 +01:00
91c8797d7f Screen: optimitzat el circuit de render en pantalla 2025-01-05 14:17:49 +01:00
f207985180 Retocs en el punter del ratolí per al mode ARCADE 2025-01-05 13:44:10 +01:00
a16131335b hi_score_table: actualitzat el fondo amb els elements nous 2025-01-05 13:41:09 +01:00
871e8da642 Corregit el timing de la música en la animació inicial del joc 2025-01-05 13:27:45 +01:00
90b3db8f06 El atenuat de pantalla torna a funcionar. Fade feia dos SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE); que mai tornava a restaurar 2025-01-05 13:07:20 +01:00
668e8e237a Actualitzat README.md 2025-01-05 12:52:14 +01:00
768f466b20 canviat blit() per render() 2025-01-05 10:45:05 +01:00
1f8f9b11ed Segona pasaeta de IWYU 2025-01-05 10:36:17 +01:00
39f61884b0 Pasaeta de IWYU 2025-01-05 10:22:20 +01:00
b1193bd8fd fix: error en la seqüència final de retrocedir en el temps 2025-01-05 09:51:33 +01:00
7f9e2e53e3 Optimitzat el renderitzat dels credits 2025-01-05 09:44:08 +01:00
4cf4c8db6f fix: arreglada la acceleració dels credits sense dependre de vsync 2025-01-05 09:31:57 +01:00
cd806363e8 Modificat el color dels nuvols de la última pantalla
debug: opció de no crear mes globos
2025-01-05 09:22:30 +01:00
198aa45d59 Afegida una lluna i un sol al fondo 2025-01-05 07:32:30 +01:00
0711c8dada fix: al fer el init de stage no es buidava el vector i cada volta afegia mes stages 2025-01-05 07:29:33 +01:00
e1aaad0903 fix: Havia deixat comentat un IF fent proves 2025-01-04 17:01:24 +01:00
b53ee12f56 La powerball ja no es pot destruir fins que no ha fet un rebot 2025-01-04 16:57:50 +01:00
7b6d429bed fix: un vuelo rasante havia trencat els credits 2025-01-04 14:27:37 +01:00
81ee352553 Afegit un lock per evitar que es puga incrementar el poder de la fase
Es necesita almenys un jugador viu per a poder incrementar el poder de la fase
2025-01-04 14:09:10 +01:00
7b8f16610a Afegits estats al fade
Afegida opció de prefade
El modo demo ja comença a meitat del "meollo"
2025-01-04 13:40:22 +01:00
06eb05f065 Canviat un poc el color del segon cel 2025-01-04 12:44:24 +01:00
bccf4c30de Modificada la cadencia de foc sense autofire i arreglades un poc les animacions de cool_down i cooling 2025-01-04 10:47:26 +01:00
5e817ef1d0 Afegit el tamany de la coffee_machine als parametres 2025-01-04 10:04:49 +01:00
eaab646cd3 Modificades les paletes de invulnerabilitat 2025-01-04 09:21:58 +01:00
e887c2a2ab Afegida la opció de crear els globos sense temps de creació en el balloon_manager
Modificat el mode demo per a que la primera oleada estiga ja creada
2025-01-04 00:42:57 +01:00
f573bd02ac El case de les variables en mouse.cpp i mouse.h era incorrecte 2025-01-03 23:57:45 +01:00
b586a117c8 Afegit mouse.cpp per amagar el cursor quan no està moventse 2025-01-03 23:35:48 +01:00
08dfaf7641 Errors tipografics en varios comentaris 2025-01-03 22:48:45 +01:00
ff7f5ea131 Modificada la seqëncia d'inici per a que la musica començe antes 2025-01-03 22:13:46 +01:00
7cc4a2002a Modificat el copyright de 2024 a 2025 2025-01-03 22:04:29 +01:00
de81b798b0 Afegit custom fadeout de so sincronitzat amb el fadeout de video per a quan acaba la partida 2025-01-03 22:02:48 +01:00
5669715285 Input mostra també el numero de joysticks que ha trobat 2025-01-03 21:29:22 +01:00
6531106933 Quedaven mes SDL_Log en jail_audio 2025-01-03 21:28:55 +01:00
51191b1906 Eliminat SDL_Log 2025-01-03 21:21:52 +01:00
6effeb6154 Quan el jugador moria podia quedarse engantxat rebotant en les vores
So aleatori en els rebots del jugador al morir
2025-01-03 20:36:18 +01:00
8c2b1ce649 Separats els estats de joc completat i joc acabat del estat joc jugantse
Al completar el joc, el missatge de game over ja no ix fins que desapareixen els textos anteriors
2025-01-03 19:53:09 +01:00
cc4acecc03 Afegits sons de caminar i de comptador de continuar
Afegits estats al joc i al jugador per a escenificar el inici de la partida
2025-01-03 19:19:22 +01:00
40dfc32e84 Actualitzada la data de la versió 2024-12-31 10:23:01 +01:00
4cd1d91560 Actualitzat jail_audio 2024-12-30 20:08:08 +01:00
e43badd703 Merge branch 'main' of https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis_arcade_edition 2024-12-30 20:06:04 +01:00
71dcf9cf87 Afegit coffee.res, coffee.rc i icon.ico per a tindre iconet en windows 2024-12-30 19:56:35 +01:00
3a8521a1da Arreglat windows_release en Makefile 2024-12-30 19:56:00 +01:00
74d9c9a2b9 Commit per a vore qué està passant amb la música 2024-12-30 19:07:13 +01:00
9532caace8 Arreglades les release de windows, linux i raspberry 2024-12-30 13:44:09 +01:00
0bbd14067a Text::writeToTexture no deixava el renderitzador com estava 2024-12-30 13:43:12 +01:00
cfaa143c44 Actualitzat jail_audio 2024-12-30 13:30:06 +01:00
e61daeb92e Modificats els grafics del enemic nou
Afegits nous audios i veus
Completat el comportament del enemic nou
Ampliat el numero máxim de sons simultanis
2024-12-28 21:23:04 +01:00
d57cc15aee Treballant en el enemic nou 2024-12-27 13:38:07 +01:00
de3b18a407 Posat ordre en el Attract Mode 2024-12-26 13:58:25 +01:00
7f444fef33 Fix: mil minibugs relacionats amb el audio 2024-12-26 10:39:48 +01:00
ca18baefd7 Fix: el modo demo desactivava els sons i ja no s'activaven mai mes 2024-12-26 10:05:41 +01:00
b8dca0a46f Fet el fade out del title de video i audio i el fade in del joc de video i audio
Actualitzat jail_audio a la última versió
2024-12-26 10:03:02 +01:00
ca2c48ea17 Au, paca casa. M'he quedat a mitjes fent un fade de audio sincronitzat amb el fade de video en el titol 2024-12-23 13:56:11 +01:00
fb4d0d12db Afegits roidets de colisió per als globos per a certs moments 2024-12-23 12:37:19 +01:00
fb31445731 Comprova al iniciar que el tamany de finestra no siga mes gran que el tamany de la pantalla 2024-12-23 11:22:26 +01:00
cf4f0459b3 Es pot fer la finestra tan gran com deixe la pantalla, es a dir, el factor de zoom ja no va de 1 a 4 sino de 1 a X 2024-12-23 11:13:14 +01:00
fe0900a686 Afegides veus al jugador
Afegit efectes de so al rebotar el jugador quan mor
2024-12-15 20:00:35 +01:00
3367b70cd5 Afegit delay opcional al flash de la classe Screen 2024-12-09 20:06:59 +01:00
7016849587 FIX: afegit StopChannel en lloc de PauseChannel en el destructor del Logo
Retocada la animació del logo del joc en Title
2024-12-09 19:08:22 +01:00
301c059a26 Afegit botó per activar o desactivar el autofire 2024-12-05 12:24:18 +01:00
146 changed files with 4006 additions and 2372 deletions

1
.gitignore vendored
View File

@@ -16,3 +16,4 @@ thumbs.db
coffee_crisis* coffee_crisis*
debug.txt debug.txt
cppcheck-result* cppcheck-result*
desktop.ini

View File

@@ -3,6 +3,9 @@
cmake_minimum_required(VERSION 3.10) cmake_minimum_required(VERSION 3.10)
project(coffee_crisis_arcade_edition VERSION 0.01) project(coffee_crisis_arcade_edition VERSION 0.01)
# Establece las políticas
cmake_policy(SET CMP0072 NEW)
# Configuración de compilador para MinGW en Windows, si es necesario # Configuración de compilador para MinGW en Windows, si es necesario
if(WIN32 AND NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC") if(WIN32 AND NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_CXX_COMPILER "g++") set(CMAKE_CXX_COMPILER "g++")

100
Makefile
View File

@@ -10,26 +10,28 @@ TARGET_FILE := $(DIR_BIN)$(TARGET_NAME)
APP_NAME := Coffee Crisis Arcade Edition APP_NAME := Coffee Crisis Arcade Edition
RELEASE_FOLDER := ccae_release RELEASE_FOLDER := ccae_release
RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME) RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME)
VERSION := v0.01 RESOURCE_FILE := release/coffee.res
VERSION := 2025-02-07
# Nombres para los ficheros de lanzamiento # Nombres para los ficheros de lanzamiento
WINDOWS_RELEASE := $(TARGET_FILE)-$(VERSION)-win32-x64.zip WINDOWS_RELEASE := $(TARGET_NAME)-$(VERSION)-win32-x64.zip
MACOS_INTEL_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-intel.dmg MACOS_INTEL_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-intel.dmg
MACOS_APPLE_SILICON_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-apple-silicon.dmg MACOS_APPLE_SILICON_RELEASE := $(TARGET_FILE)-$(VERSION)-macos-apple-silicon.dmg
LINUX_RELEASE := $(TARGET_FILE)-$(VERSION)-linux.tar.gz LINUX_RELEASE := $(TARGET_FILE)-$(VERSION)-linux.tar.gz
RASPI_RELEASE := $(TARGET_FILE)-$(VERSION)-raspberry.tar.gz
# Includes # Includes
INCLUDES := -I$(DIR_SOURCES) INCLUDES := -I$(DIR_SOURCES)
# Variables según el sistema operativo # Variables según el sistema operativo
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
FixPath = $(subst /,\,$1) FixPath = $(subst /,\\,$1)
SOURCES := source/*.cpp SOURCES := source/*.cpp
CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows 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 CXXFLAGS_DEBUG := -std=c++20 -Wall -g
LDFLAGS := -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32 LDFLAGS := -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32
RM = del /Q RM := del /Q
MKD:= mkdir MKDIR := mkdir
else else
FixPath = $1 FixPath = $1
SOURCES := $(shell find $(DIR_SOURCES) -name '*.cpp') SOURCES := $(shell find $(DIR_SOURCES) -name '*.cpp')
@@ -37,8 +39,9 @@ else
CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections CXXFLAGS := -std=c++20 -Wall -Os -ffunction-sections -fdata-sections
CXXFLAGS_DEBUG := -std=c++20 -Wall -g CXXFLAGS_DEBUG := -std=c++20 -Wall -g
LDFLAGS := -lSDL2 LDFLAGS := -lSDL2
RM = rm -f RMFILE := rm -f
MKD:= mkdir -p RMDIR := rm -rdf
MKDIR := mkdir -p
UNAME_S := $(shell uname -s) UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux) ifeq ($(UNAME_S),Linux)
LDFLAGS += -lGL LDFLAGS += -lGL
@@ -50,10 +53,11 @@ else
endif endif
endif endif
# Rules # Reglas para compilación
windows: windows:
@echo off @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 strip -s -R .comment -R .gnu.version "$(TARGET_FILE).exe" --strip-unneeded
windows_rec: windows_rec:
@@ -80,12 +84,13 @@ windows_release:
powershell Copy-Item "release\*.dll" -Destination "$(RELEASE_FOLDER)" powershell Copy-Item "release\*.dll" -Destination "$(RELEASE_FOLDER)"
# Compila # Compila
$(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE).exe" windres release/coffee.rc -O coff -o $(RESOURCE_FILE)
strip -s -R .comment -R .gnu.version "$(RELEASE_FOLDER)/$(TARGET_FILE).exe" --strip-unneeded $(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 # Crea el fichero .zip
powershell if (Test-Path $(WINDOWS_RELEASE)) {Remove-Item $(WINDOWS_RELEASE)} powershell if (Test-Path "$(WINDOWS_RELEASE)") {Remove-Item "$(WINDOWS_RELEASE)"}
powershell Compress-Archive -Path "$(RELEASE_FOLDER)"/* -DestinationPath $(WINDOWS_RELEASE) powershell Compress-Archive -Path "$(RELEASE_FOLDER)"/* -DestinationPath "$(WINDOWS_RELEASE)"
# Elimina la carpeta temporal 'RELEASE_FOLDER' # Elimina la carpeta temporal 'RELEASE_FOLDER'
powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force} powershell if (Test-Path "$(RELEASE_FOLDER)") {Remove-Item "$(RELEASE_FOLDER)" -Recurse -Force}
@@ -98,17 +103,17 @@ macos_debug:
macos_release: macos_release:
# Elimina datos de compilaciones anteriores # Elimina datos de compilaciones anteriores
rm -rdf "$(RELEASE_FOLDER)" $(RMDIR) "$(RELEASE_FOLDER)"
rm -rdf Frameworks $(RMDIR) Frameworks
rm -f tmp.dmg $(RMFILE) tmp.dmg
rm -f "$(MACOS_INTEL_RELEASE)" $(RMFILE) "$(MACOS_INTEL_RELEASE)"
rm -f "$(MACOS_APPLE_SILICON_RELEASE)" $(RMFILE) "$(MACOS_APPLE_SILICON_RELEASE)"
# Crea la carpeta temporal para hacer el trabajo y las carpetas obligatorias para crear una app de macos # 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) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Frameworks"
mkdir -p "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS" $(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/MacOS"
mkdir -p "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources" $(MKDIR) "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
mkdir -p Frameworks $(MKDIR) Frameworks
# Copia carpetas y ficheros # Copia carpetas y ficheros
cp -R data "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources" cp -R data "$(RELEASE_FOLDER)/$(APP_NAME).app/Contents/Resources"
@@ -123,24 +128,24 @@ macos_release:
ln -s /Applications "$(RELEASE_FOLDER)"/Applications ln -s /Applications "$(RELEASE_FOLDER)"/Applications
# Compila la versión para procesadores Intel # 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 # Empaqueta el .dmg de la versión Intel
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)" hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_INTEL_RELEASE)" hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_INTEL_RELEASE)"
rm -f tmp.dmg $(RMFILE) tmp.dmg
# Compila la versión para procesadores Apple Silicon # 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 # Empaqueta el .dmg de la versión Apple Silicon
hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)" hdiutil create tmp.dmg -ov -volname "$(APP_NAME)" -fs HFS+ -srcfolder "$(RELEASE_FOLDER)"
hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_APPLE_SILICON_RELEASE)" hdiutil convert tmp.dmg -format UDZO -o "$(MACOS_APPLE_SILICON_RELEASE)"
rm -f tmp.dmg $(RMFILE) tmp.dmg
# Elimina las carpetas temporales # Elimina las carpetas temporales
$(RM) Frameworks $(RMDIR) Frameworks
$(RM) "$(RELEASE_FOLDER)" $(RMDIR) "$(RELEASE_FOLDER)"
linux: linux:
$(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)" $(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(TARGET_FILE)"
@@ -151,10 +156,10 @@ linux_debug:
linux_release: linux_release:
# Elimina carpetas previas # Elimina carpetas previas
$(RM) "$(RELEASE_FOLDER)" $(RMDIR) "$(RELEASE_FOLDER)"
# Crea la carpeta temporal para realizar el lanzamiento # Crea la carpeta temporal para realizar el lanzamiento
mkdir -p "$(RELEASE_FOLDER)" $(MKDIR) "$(RELEASE_FOLDER)"
# Copia ficheros # Copia ficheros
cp -R data "$(RELEASE_FOLDER)" cp -R data "$(RELEASE_FOLDER)"
@@ -166,11 +171,11 @@ linux_release:
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
# Empaqueta ficheros # Empaqueta ficheros
$(RM) "$(LINUX_RELEASE)" $(RMFILE) "$(LINUX_RELEASE)"
cd "$(RELEASE_FOLDER)" && tar -czvf "../$(LINUX_RELEASE)" * cd "$(RELEASE_FOLDER)" && tar -czvf "$(LINUX_RELEASE)" *
# Elimina la carpeta temporal # Elimina la carpeta temporal
$(RM) "$(RELEASE_FOLDER)" $(RMDIR) "$(RELEASE_FOLDER)"
raspi: raspi:
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(TARGET_FILE) $(CXX) $(SOURCES) -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(TARGET_FILE)
@@ -179,12 +184,35 @@ raspi:
raspi_debug: raspi_debug:
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE -D DEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug" $(CXX) $(SOURCES) -D ARCADE -D VERBOSE -D DEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
anbernic: raspi_release:
# Elimina carpetas previas # Elimina carpetas previas
$(RM) "$(RELEASE_FOLDER)"_anbernic $(RMDIR) "$(RELEASE_FOLDER)"
# Crea la carpeta temporal para realizar el lanzamiento # 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 # Copia ficheros
cp -R data "$(RELEASE_FOLDER)"_anbernic cp -R data "$(RELEASE_FOLDER)"_anbernic

View File

@@ -1,43 +1,73 @@
# Coffee Crisis Arcade Edition # 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"> <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/ccae_title.png" alt="Títol" width="60%" />
</p> </p>
## Controls ## 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 El joc està optimitzat per a ser jugat amb un mando de jocs, encara que un dels jugadors pot utilitzar el teclat.
* **Q, W, E**: Disparar a la esquerra, al centre i a la dreta respectivament
### 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"> <p align="center">
<img src="https://php.sustancia.synology.me/images/ccae1.png" alt="Joc" <img src="https://php.sustancia.synology.me/images/ccae/ccae1.png" alt="Joc" width="45%" />
<img src="https://php.sustancia.synology.me/images/ccae/ccae3.png" alt="Joc" width="45%" />
</p> </p>
## Altres tecles ## Altres tecles
- **Tecla ESC**: Tancar el joc
- **Tecla F1**: Fa la finestra mes xicoteta | Tecla | Funció |
|-------------|----------------------------------------------|
- **Tecla F2**: Fa la finestra mes gran | **ESC** | Tancar el joc |
| **F1** | Fa la finestra més xicoteta |
- **Tecla F3**: Alterna entre el mode de pantalla completa i el de finestra | **F2** | Fa la finestra més gran |
| **F3** | Alterna entre mode de pantalla completa i finestra |
- **Tecla F4**: Activa o desactiva els shaders | **F4** | Activa o desactiva els shaders |
| **F5** | Activa o desactiva l'àudio |
- **Tecla F5**: Activa o desactiva l'audio | **F6** | Activa o desactiva el dispar automàtic |
| **F7** | Canvia l'idioma del joc i reinicia |
- **Tecla F6**: Canvia el idioma del joc i reinicia | **F10** | Reset del joc |
- **Tecla F10**: Reset
<p align="center"> <p align="center">
<img src="https://php.sustancia.synology.me/images/ccae2.png" alt="Joc" <img src="https://php.sustancia.synology.me/images/ccae/ccae2.png" alt="Joc" width="50%" />
</p> </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.

View File

@@ -1,5 +1,7 @@
## GAME ## GAME
game.item_size 20 # Tamaño de los items del juego 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.width 320 # Ancho de la resolucion nativa del juego
game.height 240 # Alto 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 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_delay 1
fade.random_squares_mult 500 fade.random_squares_mult 500
fade.post_duration 80 fade.post_duration 80
fade.venetian_size 16 fade.venetian_size 12
## SCOREBOARD ## SCOREBOARD
scoreboard.x 0 scoreboard.x 0

View File

@@ -1,5 +1,7 @@
## GAME ## GAME
game.item_size 20 # Tamaño de los items del juego 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.width 320 # Ancho de la resolucion nativa del juego
game.height 256 # Alto 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.x 0 # Rectangulo con la posición de la zona de juego
@@ -14,7 +16,7 @@ fade.num_squares_height 128
fade.random_squares_delay 1 fade.random_squares_delay 1
fade.random_squares_mult 500 fade.random_squares_mult 500
fade.post_duration 80 fade.post_duration 80
fade.venetian_size 16 fade.venetian_size 12
## SCOREBOARD ## SCOREBOARD
scoreboard.x 0 scoreboard.x 0

BIN
data/font/04b_25_grey.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
data/font/04b_25_metal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,9 +1,9 @@
frame_width=46 frame_width=49
frame_height=46 frame_height=49
[animation] [animation]
name=powerball name=powerball
speed=10 speed=10
loop=-1 loop=-1
frames=0 frames=1
[/animation] [/animation]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

BIN
data/gfx/game/game_moon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
data/gfx/game/game_sun.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

BIN
data/gfx/intro/intro1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
data/gfx/intro/intro2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
data/gfx/intro/intro3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
data/gfx/intro/intro4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
data/gfx/intro/intro5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
data/gfx/intro/intro6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -0,0 +1,9 @@
frame_width=20
frame_height=20
[animation]
name=default
speed=10
loop=0
frames=0,1
[/animation]

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

16
data/gfx/tabe/tabe.ani Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -32,7 +32,7 @@ IDIOMA
[ CANCELAR ] [ CANCELAR ]
## 11 - INSTRUCCIONES ## 11 - INSTRUCCIONES
OBJECTIU Objectiu
## 12 - INSTRUCCIONES ## 12 - INSTRUCCIONES
HAS D'EXPLOTAR HAS D'EXPLOTAR
@@ -47,7 +47,7 @@ LA DIFICULTAT AUGMENTA
A MESURA QUE VAS PUNTUANT A MESURA QUE VAS PUNTUANT
## 16 - INSTRUCCIONES ## 16 - INSTRUCCIONES
OBJECTES Objectes
## 17 - INSTRUCCIONES ## 17 - INSTRUCCIONES
1.000 PUNTS 1.000 PUNTS
@@ -372,3 +372,12 @@ MUSICA COMPOSADA PER
## 124 - CREDITS ## 124 - CREDITS
EFECTES DE SO EFECTES DE SO
## 125 - NOTIFICACIONES
Torna a polsar per reiniciar
## 126 - NOTIFICACIONES
Torna a polsar per canviar el idioma a
## 127 - NOTIFICACIONES
Idioma canviat a

View File

@@ -372,3 +372,12 @@ MUSIC COMPOSED BY
## 124 - CREDITS ## 124 - CREDITS
SOUND EFFECTS SOUND EFFECTS
## 125 - NOTIFICACIONES
Press again to reset
## 126 - NOTIFICACIONES
Press again to change languaje to
## 127 - NOTIFICACIONES
Language set to

View File

@@ -372,3 +372,12 @@ MUSICA COMPUESTA POR
## 124 - CREDITS ## 124 - CREDITS
EFECTOS DE SONIDO EFECTOS DE SONIDO
## 125 - NOTIFICACIONES
Vuelve a pulsar para reiniciar
## 126 - NOTIFICACIONES
Vuelve a pulsar para cambiar el idioma a
## 127 - NOTIFICACIONES
Idioma cambiado a

Binary file not shown.

BIN
data/sound/debian_drop.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
data/sound/game_start.wav Normal file

Binary file not shown.

BIN
data/sound/tabe.wav Normal file

Binary file not shown.

BIN
data/sound/tabe_hit.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
data/sound/voice_coffee.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
data/sound/voice_no.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
data/sound/walk.wav Normal file

Binary file not shown.

2
release/coffee.rc Normal file
View File

@@ -0,0 +1,2 @@
// coffee.rc
IDI_ICON1 ICON "icon.ico"

BIN
release/coffee.res Normal file

Binary file not shown.

BIN
release/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -56,13 +56,13 @@ private:
~Asset() = default; ~Asset() = default;
public: public:
// [SINGLETON] Crearemos el objeto screen con esta función estática // [SINGLETON] Crearemos el objeto con esta función estática
static void init(const std::string &executable_path); static void init(const std::string &executable_path);
// [SINGLETON] Destruiremos el objeto screen con esta función estática // [SINGLETON] Destruiremos el objeto con esta función estática
static void destroy(); static void destroy();
// [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él // [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
static Asset *get(); static Asset *get();
// Añade un elemento a la lista // Añade un elemento a la lista

View File

@@ -2,6 +2,7 @@
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <algorithm> // Para clamp, max #include <algorithm> // Para clamp, max
#include <cmath>
#include "moving_sprite.h" // Para MovingSprite #include "moving_sprite.h" // Para MovingSprite
#include "param.h" // Para Param, ParamBackground, param #include "param.h" // Para Param, ParamBackground, param
#include "resource.h" // Para Resource #include "resource.h" // Para Resource
@@ -18,16 +19,22 @@ Background::Background()
bottom_clouds_texture_(Resource::get()->getTexture("game_clouds2.png")), bottom_clouds_texture_(Resource::get()->getTexture("game_clouds2.png")),
grass_texture_(Resource::get()->getTexture("game_grass.png")), grass_texture_(Resource::get()->getTexture("game_grass.png")),
gradients_texture_(Resource::get()->getTexture("game_sky_colors.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}), rect_({0, 0, gradients_texture_->getWidth() / 2, gradients_texture_->getHeight() / 2}),
src_rect_({0, 0, 320, 240}), src_rect_({0, 0, 320, 240}),
dst_rect_({0, 0, 320, 240}), dst_rect_({0, 0, 320, 240}),
base_(rect_.h), 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_(param.background.attenuate_alpha),
alpha_color_text_temp_(param.background.attenuate_alpha) alpha_color_text_temp_(param.background.attenuate_alpha)
{ {
// Precalcula rutas
createSunPath();
createMoonPath();
// Inicializa variables // Inicializa variables
{ {
gradient_rect_[0] = {0, 0, rect_.w, rect_.h}; 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_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()}); 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); 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); 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 // Inicializa objetos
@@ -79,6 +88,8 @@ Background::Background()
buildings_sprite_->setY(base_ - buildings_sprite_->getHeight()); buildings_sprite_->setY(base_ - buildings_sprite_->getHeight());
grass_sprite_->setY(base_ - grass_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 // Crea la textura para componer el fondo
@@ -88,7 +99,7 @@ Background::Background()
// Crea la textura para atenuar el fondo // Crea la textura para atenuar el fondo
color_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h); color_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND);
setColor(color_); setColor(attenuate_color_);
SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_); SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_);
} }
@@ -103,7 +114,7 @@ Background::~Background()
void Background::update() void Background::update()
{ {
// Actualiza el valor de alpha_ // Actualiza el valor de alpha_
updateAlphaColorText(); updateAlphaColorTexture();
// Actualiza las nubes // Actualiza las nubes
updateClouds(); updateClouds();
@@ -114,6 +125,10 @@ void Background::update()
// Calcula el valor de alpha_ // Calcula el valor de alpha_
alpha_ = std::max((255 - (int)(255 * transition_)), 0); alpha_ = std::max((255 - (int)(255 * transition_)), 0);
// Mueve el sol
sun_sprite_->setPosition(sun_path_.at(sun_index_));
moon_sprite_->setPosition(moon_path_.at(moon_index_));
// Incrementa el contador // Incrementa el contador
++counter_; ++counter_;
@@ -181,6 +196,10 @@ void Background::fillCanvas()
// Dibuja el gradiente de fondo // Dibuja el gradiente de fondo
renderGradient(); renderGradient();
// Dibuja los astros
sun_sprite_->render();
moon_sprite_->render();
// Dibuja las nubes de arriba // Dibuja las nubes de arriba
renderTopClouds(); renderTopClouds();
@@ -207,16 +226,6 @@ void Background::render()
SDL_RenderCopy(renderer_, color_texture_, &src_rect_, &dst_rect_); SDL_RenderCopy(renderer_, color_texture_, &src_rect_, &dst_rect_);
} }
// Vuelve a cargar las texturas
void Background::reloadTextures()
{
buildings_texture_->reLoad();
top_clouds_texture_->reLoad();
bottom_clouds_texture_->reLoad();
grass_texture_->reLoad();
gradients_texture_->reLoad();
}
// Ajusta el valor de la variable // Ajusta el valor de la variable
void Background::setCloudsSpeed(float value) void Background::setCloudsSpeed(float value)
{ {
@@ -250,13 +259,13 @@ void Background::setPos(SDL_Rect pos)
// Establece el color_ de atenuación // Establece el color_ de atenuación
void Background::setColor(Color color) void Background::setColor(Color color)
{ {
color_ = color; attenuate_color_ = color;
// Colorea la textura // Colorea la textura
auto temp = SDL_GetRenderTarget(renderer_); auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, color_texture_); 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_RenderClear(renderer_);
SDL_SetRenderTarget(renderer_, temp); SDL_SetRenderTarget(renderer_, temp);
@@ -274,7 +283,7 @@ void Background::setAlpha(int alpha)
} }
// Actualiza el valor de alpha_ // Actualiza el valor de alpha_
void Background::updateAlphaColorText() void Background::updateAlphaColorTexture()
{ {
if (alpha_color_text_ == alpha_color_text_temp_) if (alpha_color_text_ == alpha_color_text_temp_)
{ {
@@ -323,3 +332,57 @@ void Background::updateClouds()
bottom_clouds_sprite_b_->setPosX(bottom_clouds_sprite_b_->getWidth()); 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));
}

View File

@@ -1,12 +1,14 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // para SDL_Rect #include <SDL2/SDL_rect.h> // Para SDL_Rect, SDL_Point
#include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // Para SDL_Texture, SDL_Renderer
#include <memory> // para unique_ptr, shared_ptr #include <stddef.h> // Para size_t
#include "utils.h" // para Color #include <memory> // Para unique_ptr, shared_ptr
class MovingSprite; #include <vector> // Para vector
class Sprite; #include "utils.h" // Para Color
class Texture; 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 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> 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> 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> 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_a_; // Sprite para las nubes superiores
std::unique_ptr<MovingSprite> top_clouds_sprite_b_; // Sprite para las nubes superiores std::unique_ptr<MovingSprite> top_clouds_sprite_b_; // Sprite para las nubes superiores
@@ -60,6 +64,8 @@ private:
std::unique_ptr<Sprite> buildings_sprite_; // Sprite con los edificios de fondo 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> 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> 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 *canvas_; // Textura para componer el fondo
SDL_Texture *color_texture_; // Textura para atenuar el fondo SDL_Texture *color_texture_; // Textura para atenuar el fondo
@@ -77,9 +83,13 @@ private:
SDL_Rect src_rect_; // Parte del objeto fondo que se va a dibujará en pantalla 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 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 int base_; // Linea de fondo coincidente con el area inferior de la zona de juego
Color color_; // Color para atenuar el fondo Color attenuate_color_; // Color para atenuar el fondo
int alpha_color_text_; // Alpha 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 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 // Dibuja el gradiente de fondo
void renderGradient(); void renderGradient();
@@ -94,11 +104,17 @@ private:
void fillCanvas(); void fillCanvas();
// Actualiza el valor de alpha // Actualiza el valor de alpha
void updateAlphaColorText(); void updateAlphaColorTexture();
// Actualiza las nubes // Actualiza las nubes
void updateClouds(); void updateClouds();
// Precalcula el vector con el recorrido del sol
void createSunPath();
// Precalcula el vector con el recorrido de la luna
void createMoonPath();
public: public:
// Constructor // Constructor
Background(); Background();
@@ -115,9 +131,6 @@ public:
// Establece la posición del objeto // Establece la posición del objeto
void setPos(SDL_Rect pos); void setPos(SDL_Rect pos);
// Vuelve a cargar las texturas
void reloadTextures();
// Ajusta el valor de la variable // Ajusta el valor de la variable
void setCloudsSpeed(float value); void setCloudsSpeed(float value);
@@ -132,4 +145,10 @@ public:
// Establece la transparencia de la atenuación // Establece la transparencia de la atenuación
void setAlpha(int alpha); 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);
}; };

View File

@@ -5,6 +5,8 @@
#include "param.h" // Para Param, param, ParamBalloon, ParamGame #include "param.h" // Para Param, param, ParamBalloon, ParamGame
#include "sprite.h" // Para Sprite #include "sprite.h" // Para Sprite
#include "texture.h" // Para Texture #include "texture.h" // Para Texture
#include "resource.h"
#include "jail_audio.h"
// Constructor // 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) 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]; power_ = BALLOON_POWER[index];
menace_ = BALLOON_MENACE[index]; menace_ = BALLOON_MENACE[index];
score_ = BALLOON_SCORE[index]; score_ = BALLOON_SCORE[index];
sound_ = BALLOON_SOUND[index];
break; break;
} }
@@ -50,14 +53,16 @@ Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel
power_ = BALLOON_POWER[index]; power_ = BALLOON_POWER[index];
menace_ = BALLOON_MENACE[index]; menace_ = BALLOON_MENACE[index];
score_ = BALLOON_SCORE[index]; score_ = BALLOON_SCORE[index];
sound_ = BALLOON_SOUND[index];
break; break;
} }
case BalloonType::POWERBALL: case BalloonType::POWERBALL:
{ {
const int index = 3; constexpr int index = 3;
h_ = w_ = BALLOON_SIZE[4]; h_ = w_ = BALLOON_SIZE[4];
sound_ = BALLOON_SOUND[3];
power_ = score_ = menace_ = 0; power_ = score_ = menace_ = 0;
vy_ = 0; vy_ = 0;
@@ -102,16 +107,28 @@ void Balloon::render()
{ {
if (type_ == BalloonType::POWERBALL) if (type_ == BalloonType::POWERBALL)
{ {
// Renderizado para la PowerBall // 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}; SDL_Point p = {24, 24};
sprite_->setRotatingCenter(&p); sprite_->setRotatingCenter(&p);
sprite_->render(); sprite_->render();
}
// Añade la máscara del borde y los reflejos // Añade la máscara del borde y los reflejos
{
auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition()); auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
sp->setSpriteClip(BALLOON_SIZE[4], 0, BALLOON_SIZE[4], BALLOON_SIZE[4]); sp->setSpriteClip(BALLOON_SIZE[4] * 2, 0, BALLOON_SIZE[4], BALLOON_SIZE[4]);
sp->render(); sp->render();
} }
}
else else
{ {
// Renderizado para el resto de globos // Renderizado para el resto de globos
@@ -145,6 +162,7 @@ void Balloon::move()
const float max_x = play_area_.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) if (x_ < min_x || x_ > max_x)
{ {
playSound();
x_ = std::clamp(x_, min_x, max_x); x_ = std::clamp(x_, min_x, max_x);
vx_ = -vx_; vx_ = -vx_;
// Activa el efecto de rebote o invierte la rotación // Activa el efecto de rebote o invierte la rotación
@@ -161,24 +179,13 @@ void Balloon::move()
// Mueve el globo en vertical // Mueve el globo en vertical
y_ += vy_ * speed_; 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 // Colisión en la parte superior solo si el globo va de subida
if (vy_ < 0) if (vy_ < 0)
{ {
const int min_y = play_area_.y; const int min_y = play_area_.y;
if (y_ < min_y) if (y_ < min_y)
{ {
playSound();
y_ = min_y; y_ = min_y;
vy_ = -vy_; vy_ = -vy_;
enableBounce(); enableBounce();
@@ -189,12 +196,17 @@ void Balloon::move()
const int max_y = play_area_.y + play_area_.h - h_; const int max_y = play_area_.y + play_area_.h - h_;
if (y_ > max_y) if (y_ > max_y)
{ {
playSound();
y_ = max_y; y_ = max_y;
vy_ = -default_vy_; vy_ = -default_vy_;
if (type_ != BalloonType::POWERBALL) if (type_ != BalloonType::POWERBALL)
{ {
enableBounce(); enableBounce();
} }
else
{
setInvulnerable(false);
}
} }
/* /*
@@ -221,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 // Actualiza al globo a su posicion, animación y controla los contadores
void Balloon::update() void Balloon::update()
{ {
@@ -402,3 +408,12 @@ void Balloon::useNormalColor()
use_reversed_colors_ = false; use_reversed_colors_ = false;
setAnimation(); setAnimation();
} }
// Reproduce el sonido al rebotar
void Balloon::playSound()
{
if (sound_enabled_)
{
JA_PlaySound(Resource::get()->getSound(sound_));
}
}

View File

@@ -17,6 +17,7 @@ constexpr int BALLOON_SCORE[] = {50, 100, 200, 400};
constexpr int BALLOON_POWER[] = {1, 3, 7, 15}; constexpr int BALLOON_POWER[] = {1, 3, 7, 15};
constexpr int BALLOON_MENACE[] = {1, 2, 4, 8}; constexpr int BALLOON_MENACE[] = {1, 2, 4, 8};
constexpr int BALLOON_SIZE[] = {10, 16, 26, 48, 49}; 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 // Tamaños de globo
enum class BalloonSize : Uint8 enum class BalloonSize : Uint8
@@ -113,6 +114,8 @@ private:
float speed_; // Velocidad a la que se mueven los globos float speed_; // Velocidad a la que se mueven los globos
Uint8 power_; // Cantidad de poder que alberga el globo Uint8 power_; // Cantidad de poder que alberga el globo
SDL_Rect play_area_; // Zona por donde se puede mover 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 // Alinea el circulo de colisión con la posición del objeto globo
void shiftColliders(); void shiftColliders();
@@ -138,6 +141,9 @@ private:
// Establece la animación correspondiente // Establece la animación correspondiente
void setAnimation(); void setAnimation();
// Reproduce el sonido al rebotar
void playSound();
public: public:
// Constructor // Constructor
Balloon( Balloon(
@@ -164,12 +170,6 @@ public:
// Actualiza la posición y estados del globo // Actualiza la posición y estados del globo
void move(); 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 // Actualiza al globo a su posicion, animación y controla los contadores
void update(); void update();
@@ -208,4 +208,6 @@ public:
void setVelY(float vel_y) { vy_ = vel_y; } void setVelY(float vel_y) { vy_ = vel_y; }
void setSpeed(float speed) { speed_ = speed; } void setSpeed(float speed) { speed_ = speed; }
void setInvulnerable(bool value) { invulnerable_ = value; } void setInvulnerable(bool value) { invulnerable_ = value; }
void setSound(bool value) { sound_enabled_ = value; }
void disable() { enabled_ = false; }
}; };

View File

@@ -107,11 +107,18 @@ void BalloonManager::deployBalloonFormation(int stage)
last_balloon_deploy_ = formation; last_balloon_deploy_ = formation;
const auto set = balloon_formations_->getSet(stage, formation); const auto set = balloon_formations_->getSet(stage, formation);
const auto numEnemies = set.number_of_balloons; const auto num_enemies = set.number_of_balloons;
for (int i = 0; i < numEnemies; ++i) for (int i = 0; i < num_enemies; ++i)
{ {
auto p = set.init[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; balloon_deploy_counter_ = 300;
@@ -123,8 +130,8 @@ void BalloonManager::deployBalloonFormation(int stage)
void BalloonManager::deploySet(int set_number) void BalloonManager::deploySet(int set_number)
{ {
const auto set = balloon_formations_->getSet(set_number); const auto set = balloon_formations_->getSet(set_number);
const auto numEnemies = set.number_of_balloons; const auto num_enemies = set.number_of_balloons;
for (int i = 0; i < numEnemies; ++i) for (int i = 0; i < num_enemies; ++i)
{ {
auto p = set.init[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_, p.creation_counter);
@@ -135,8 +142,8 @@ void BalloonManager::deploySet(int set_number)
void BalloonManager::deploySet(int set_number, int y) void BalloonManager::deploySet(int set_number, int y)
{ {
const auto set = balloon_formations_->getSet(set_number); const auto set = balloon_formations_->getSet(set_number);
const auto numEnemies = set.number_of_balloons; const auto num_enemies = set.number_of_balloons;
for (int i = 0; i < numEnemies; ++i) for (int i = 0; i < num_enemies; ++i)
{ {
auto p = set.init[i]; auto p = set.init[i];
createBalloon(p.x, y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter); createBalloon(p.x, y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter);
@@ -172,14 +179,21 @@ int BalloonManager::calculateScreenPower()
// Crea un globo nuevo en el vector de globos // 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) std::shared_ptr<Balloon> BalloonManager::createBalloon(float x, int y, BalloonType type, BalloonSize size, float velx, float speed, int creation_timer)
{
if (can_deploy_balloons_)
{ {
const int index = static_cast<int>(size); 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))); 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 balloons_.back();
} }
return nullptr;
}
// Crea un globo a partir de otro globo // Crea un globo a partir de otro globo
void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction) void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction)
{
if (can_deploy_balloons_)
{ {
const float vx = direction == "LEFT" ? BALLOON_VELX_NEGATIVE : BALLOON_VELX_POSITIVE; const float vx = direction == "LEFT" ? BALLOON_VELX_NEGATIVE : BALLOON_VELX_POSITIVE;
const auto lower_size = static_cast<BalloonSize>(static_cast<int>(balloon->getSize()) - 1); const auto lower_size = static_cast<BalloonSize>(static_cast<int>(balloon->getSize()) - 1);
@@ -196,9 +210,12 @@ void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon> &balloon,
b->useReverseColor(); b->useReverseColor();
} }
} }
}
// Crea una PowerBall // Crea una PowerBall
void BalloonManager::createPowerBall() void BalloonManager::createPowerBall()
{
if (can_deploy_balloons_)
{ {
constexpr int values = 6; constexpr int values = 6;
constexpr int pos_y = -BALLOON_SIZE[4]; constexpr int pos_y = -BALLOON_SIZE[4];
@@ -213,10 +230,12 @@ void BalloonManager::createPowerBall()
const float vx[values] = {BALLOON_VELX_POSITIVE, BALLOON_VELX_POSITIVE, BALLOON_VELX_POSITIVE, BALLOON_VELX_NEGATIVE, BALLOON_VELX_NEGATIVE, BALLOON_VELX_NEGATIVE}; 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_enabled_ = true;
power_ball_counter_ = POWERBALL_COUNTER; power_ball_counter_ = POWERBALL_COUNTER;
} }
}
// Establece la velocidad de los globos // Establece la velocidad de los globos
void BalloonManager::setBalloonSpeed(float speed) void BalloonManager::setBalloonSpeed(float speed)
@@ -251,7 +270,7 @@ int BalloonManager::popBalloon(std::shared_ptr<Balloon> balloon)
// Agrega la explosión y elimina el globo // Agrega la explosión y elimina el globo
explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize())); explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize()));
balloon->pop(); balloon->disable();
} }
return score; return score;
@@ -287,7 +306,7 @@ int BalloonManager::destroyBalloon(std::shared_ptr<Balloon> &balloon)
// Destruye el globo // Destruye el globo
explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize())); explosions_->add(balloon->getPosX(), balloon->getPosY(), static_cast<int>(balloon->getSize()));
balloon->pop(); balloon->disable();
return score; return score;
} }
@@ -302,7 +321,7 @@ int BalloonManager::destroyAllBalloons()
} }
balloon_deploy_counter_ = 300; balloon_deploy_counter_ = 300;
JA_PlaySound(Resource::get()->getSound("powerball.wav")); JA_PlaySound(Resource::get()->getSound("power_ball_explosion.wav"));
Screen::get()->flash(flash_color, 3); Screen::get()->flash(flash_color, 3);
Screen::get()->shake(); Screen::get()->shake();
@@ -351,24 +370,39 @@ void BalloonManager::normalColorsToAllBalloons()
} }
} }
// Recarga las texturas
void BalloonManager::reLoad()
{
for (auto &texture : balloon_textures_)
{
texture->reLoad();
}
}
// Crea dos globos gordos // Crea dos globos gordos
void BalloonManager::createTwoBigBalloons() void BalloonManager::createTwoBigBalloons()
{ {
deploySet(1); 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 // Obtiene el nivel de ameza actual generado por los globos
int BalloonManager::getMenace() int BalloonManager::getMenace()
{ {
return std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon) return std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon)
{ return sum + (balloon->isEnabled() ? balloon->getMenace() : 0); }); { 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);
}
}

View File

@@ -33,6 +33,8 @@ private:
int power_ball_counter_ = 0; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra 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; 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 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 // Inicializa
void init(); void init();
@@ -102,21 +104,27 @@ public:
// Cambia el color de todos los globos // Cambia el color de todos los globos
void normalColorsToAllBalloons(); void normalColorsToAllBalloons();
// Recarga las texturas
void reLoad();
// Crea dos globos gordos // Crea dos globos gordos
void createTwoBigBalloons(); void createTwoBigBalloons();
// Crea una disposición de globos aleatoria
void createRandomBalloons();
// Obtiene el nivel de ameza actual generado por los globos // Obtiene el nivel de ameza actual generado por los globos
int getMenace(); int getMenace();
// Establece el sonido de los globos
void setSounds(bool value);
// Getters // Getters
float getBalloonSpeed() const { return balloon_speed_; } float getBalloonSpeed() const { return balloon_speed_; }
Balloons &getBalloons() { return balloons_; } Balloons &getBalloons() { return balloons_; }
int getNumBalloons() const { return balloons_.size(); }
// Setters // Setters
void setDefaultBalloonSpeed(float speed) { default_balloon_speed_ = speed; } void setDefaultBalloonSpeed(float speed) { default_balloon_speed_ = speed; }
void resetBalloonSpeed() { setBalloonSpeed(default_balloon_speed_); } void resetBalloonSpeed() { setBalloonSpeed(default_balloon_speed_); }
void setPlayArea(SDL_Rect play_area) { play_area_ = play_area; } 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; }
}; };

View File

@@ -1,35 +1,40 @@
// IWYU pragma: no_include <bits/std_abs.h>
#include "credits.h" #include "credits.h"
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT #include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888 #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 <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <algorithm> #include <algorithm> // Para max, min, clamp
#include <cstdlib> #include <cstdlib> // Para abs
#include <stdexcept> // Para runtime_error
#include <string> // Para basic_string, string #include <string> // Para basic_string, string
#include <vector> // Para vector #include <vector> // Para vector
#include "balloon_manager.h" // Para BalloonManager #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 "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 "global_events.h" // Para handleEvent
#include "param.h" // Para Param, ParamGame, param #include "param.h" // Para Param, ParamGame, param
#include "player.h" // Para Player, PlayerState
#include "resource.h" // Para Resource #include "resource.h" // Para Resource
#include "screen.h" // Para Screen #include "screen.h" // Para Screen
#include "section.h" // Para Name, name, Options, options #include "section.h" // Para Name, name, Options, options
#include "sprite.h" // Para Sprite
#include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW #include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW
#include "texture.h" // Para Texture
#include "tiled_bg.h" // Para TiledBG, TiledBGMode #include "tiled_bg.h" // Para TiledBG, TiledBGMode
#include "utils.h" // Para Color, no_color, shdw_txt_color, Zone #include "utils.h" // Para Color, Zone, shdw_txt_color, no_color
#include "player.h"
#include "fade.h"
#include "lang.h"
// Textos // Textos
constexpr const char TEXT_COPYRIGHT[] = "@2020,2024 JailDesigner"; constexpr const char TEXT_COPYRIGHT[] = "@2020,2025 JailDesigner";
// Constructor // Constructor
Credits::Credits() Credits::Credits()
: balloon_manager_(std::make_unique<BalloonManager>()), : 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)), 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)), tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::DIAGONAL)),
fade_in_(std::make_unique<Fade>()), fade_in_(std::make_unique<Fade>()),
fade_out_(std::make_unique<Fade>()) fade_out_(std::make_unique<Fade>())
@@ -39,19 +44,17 @@ Credits::Credits()
throw std::runtime_error("Failed to create SDL texture for text."); throw std::runtime_error("Failed to create SDL texture for text.");
} }
section::name = section::Name::CREDITS; 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_); balloon_manager_->setPlayArea(play_area_);
fade_in_->setColor(fade_color.r, fade_color.g, fade_color.b); fade_in_->setColor(fade_color.r, fade_color.g, fade_color.b);
fade_in_->setType(FadeType::FULLSCREEN); fade_in_->setType(FadeType::FULLSCREEN);
fade_in_->setPost(50); fade_in_->setPostDuration(50);
fade_in_->setMode(FadeMode::IN); fade_in_->setMode(FadeMode::IN);
fade_in_->activate(); fade_in_->activate();
fade_out_->setColor(0, 0, 0); fade_out_->setColor(0, 0, 0);
fade_out_->setType(FadeType::FULLSCREEN); fade_out_->setType(FadeType::FULLSCREEN);
fade_out_->setPost(400); fade_out_->setPostDuration(400);
initPlayers(); initPlayers();
SDL_SetTextureBlendMode(text_texture_, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(text_texture_, SDL_BLENDMODE_BLEND);
@@ -63,7 +66,9 @@ Credits::Credits()
Credits::~Credits() Credits::~Credits()
{ {
SDL_DestroyTexture(text_texture_); SDL_DestroyTexture(text_texture_);
SDL_DestroyTexture(canvas_);
resetVolume(); resetVolume();
JA_StopMusic();
} }
// Bucle principal // Bucle principal
@@ -81,9 +86,14 @@ void Credits::run()
// Actualiza las variables // Actualiza las variables
void Credits::update() void Credits::update()
{ {
if (SDL_GetTicks() - ticks_ > ticks_speed_) constexpr Uint32 TICKS_SPEED_ = 15;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED_)
{ {
ticks_ = SDL_GetTicks(); ticks_ = SDL_GetTicks();
const int repeat = want_to_pass_ ? 4 : 1;
for (int i = 0; i < repeat; ++i)
{
tiled_bg_->update(); tiled_bg_->update();
balloon_manager_->update(); balloon_manager_->update();
updateTextureDstRects(); updateTextureDstRects();
@@ -93,9 +103,12 @@ void Credits::update()
player->update(); player->update();
} }
updateAllFades(); updateAllFades();
++counter_;
}
Screen::get()->update(); Screen::get()->update();
globalInputs::update(); globalInputs::update();
++counter_;
fillCanvas();
} }
} }
@@ -105,59 +118,20 @@ void Credits::render()
// Prepara para empezar a dibujar en la textura de juego // Prepara para empezar a dibujar en la textura de juego
Screen::get()->start(); Screen::get()->start();
// Limpia la pantalla // Copia la textura con la zona de juego a la pantalla
Screen::get()->clean(); SDL_RenderCopy(Screen::get()->getRenderer(), canvas_, nullptr, nullptr);
// 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();
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
Screen::get()->blit(); Screen::get()->render();
} }
// Comprueba el manejador de eventos // Comprueba el manejador de eventos
void Credits::checkEvents() void Credits::checkEvents()
{ {
SDL_Event event; SDL_Event event;
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
// Evento de salida de la aplicación globalEvents::check(event);
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
} }
} }
@@ -176,7 +150,6 @@ void Credits::checkInput()
{ {
// Si todavía estan los creditos en marcha, se pasan solos a toda pastilla // Si todavía estan los creditos en marcha, se pasan solos a toda pastilla
want_to_pass_ = true; want_to_pass_ = true;
ticks_speed_ = 1;
} }
} }
@@ -273,6 +246,48 @@ void Credits::fillTextTexture()
mini_logo_final_pos_ = param.game.game_area.center_y - mini_logo_rect_src_.h / 2; 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 // Actualiza el destino de los rectangulos de las texturas
void Credits::updateTextureDstRects() void Credits::updateTextureDstRects()
{ {
@@ -452,7 +467,7 @@ void Credits::updateAllFades()
fade_out_->update(); fade_out_->update();
if (fade_out_->hasEnded()) if (fade_out_->hasEnded())
{ {
section::name = section::Name::LOGO; section::name = section::Name::HI_SCORE_TABLE;
} }
} }

View File

@@ -1,14 +1,17 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_render.h> // Para SDL_Texture #include <SDL2/SDL_render.h> // Para SDL_Texture
#include <SDL2/SDL_stdinc.h> // Para Uint32 #include <SDL2/SDL_stdinc.h> // Para Uint32
#include <memory> // Para unique_ptr #include <memory> // Para unique_ptr, shared_ptr
#include "param.h" #include <vector> // Para vector
#include "options.h" #include "options.h" // Para Options, OptionsAudio, OptionsMusic
class BalloonManager; #include "param.h" // Para Param, ParamGame, param
class TiledBG; #include "utils.h" // Para Zone
class Player; class BalloonManager; // lines 8-8
class Fade; class Fade; // lines 11-11
class Player; // lines 10-10
class TiledBG; // lines 9-9
constexpr int PLAY_AREA_HEIGHT = 200; constexpr int PLAY_AREA_HEIGHT = 200;
@@ -18,6 +21,7 @@ private:
// Objetos // Objetos
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
SDL_Texture *text_texture_; // Textura con el texto 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<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_in_; // Objeto para realizar el fundido de entrada
std::unique_ptr<Fade> fade_out_; // Objeto para realizar el fundido de salida std::unique_ptr<Fade> fade_out_; // Objeto para realizar el fundido de salida
@@ -25,7 +29,6 @@ private:
// Variables // Variables
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa 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_ = 0; // Contador para la lógica de la clase
Uint32 counter_pre_fade_ = 0; // Contador para activar el fundido final 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 Uint32 counter_prevent_endless_ = 0; // Contador para evitar que el juego se quede para siempre en los creditos
@@ -67,6 +70,9 @@ private:
// Crea la textura con el texto // Crea la textura con el texto
void fillTextTexture(); void fillTextTexture();
// Dibuja todos los sprites en la textura
void fillCanvas();
// Actualiza el destino de los rectangulos de las texturas // Actualiza el destino de los rectangulos de las texturas
void updateTextureDstRects(); void updateTextureDstRects();

View File

@@ -62,32 +62,11 @@ void DefineButtons::bindButtons()
} }
// Comprueba los eventos // Comprueba los eventos
void DefineButtons::checkEvents() void DefineButtons::checkEvents(const SDL_Event &event)
{ {
if (enabled_) if (enabled_ && event.type == SDL_CONTROLLERBUTTONDOWN)
{
SDL_Event event;
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_WITH_KEYBOARD;
break;
}
case SDL_CONTROLLERBUTTONDOWN:
{ {
doControllerButtonDown(event.cbutton); doControllerButtonDown(event.cbutton);
break;
}
default:
break;
}
}
} }
} }

View File

@@ -67,7 +67,7 @@ public:
void render(); void render();
// Comprueba los eventos // Comprueba los eventos
void checkEvents(); void checkEvents(const SDL_Event &event);
// Habilita el objeto // Habilita el objeto
bool enable(int index); bool enable(int index);

View File

@@ -8,12 +8,15 @@
#include <SDL2/SDL_hints.h> // Para SDL_SetHint, SDL_HINT_RENDER_DR... #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_scancode.h> // Para SDL_SCANCODE_0, SDL_SCANCODE_DOWN
#include <SDL2/SDL_stdinc.h> // Para SDL_bool, Uint32 #include <SDL2/SDL_stdinc.h> // Para SDL_bool, Uint32
#include <chrono> // Para duration, system_clock
#include <errno.h> // Para errno, EEXIST, EACCES, ENAMETOO... #include <errno.h> // Para errno, EEXIST, EACCES, ENAMETOO...
#ifndef _WIN32
#include <pwd.h> // Para getpwuid, passwd
#endif
#include <stdio.h> // Para printf, perror #include <stdio.h> // Para printf, perror
#include <sys/stat.h> // Para mkdir, stat, S_IRWXU #include <sys/stat.h> // Para mkdir, stat, S_IRWXU
#include <unistd.h> // Para getuid #include <unistd.h> // Para getuid
#include <algorithm> // Para min #include <algorithm> // Para min
#include <chrono> // Para chrono
#include <cstdlib> // Para exit, EXIT_FAILURE, size_t, rand #include <cstdlib> // Para exit, EXIT_FAILURE, size_t, rand
#include <iostream> // Para basic_ostream, operator<<, basi... #include <iostream> // Para basic_ostream, operator<<, basi...
#include <memory> // Para make_unique, unique_ptr #include <memory> // Para make_unique, unique_ptr
@@ -24,7 +27,6 @@
#include "credits.h" // Para Credits #include "credits.h" // Para Credits
#include "dbgtxt.h" // Para dbg_init #include "dbgtxt.h" // Para dbg_init
#include "game.h" // Para Game, GAME_MODE_DEMO_OFF, GAME_... #include "game.h" // Para Game, GAME_MODE_DEMO_OFF, GAME_...
#include "global_inputs.h" // Para init
#include "hiscore_table.h" // Para HiScoreTable #include "hiscore_table.h" // Para HiScoreTable
#include "input.h" // Para Input, InputType #include "input.h" // Para Input, InputType
#include "instructions.h" // Para Instructions #include "instructions.h" // Para Instructions
@@ -35,7 +37,7 @@
#include "manage_hiscore_table.h" // Para ManageHiScoreTable #include "manage_hiscore_table.h" // Para ManageHiScoreTable
#include "notifier.h" // Para Notifier #include "notifier.h" // Para Notifier
#include "on_screen_help.h" // Para OnScreenHelp #include "on_screen_help.h" // Para OnScreenHelp
#include "options.h" // Para Options, OptionsController, opt... #include "options.h" // Para Options, options, OptionsContro...
#include "param.h" // Para Param, ParamGame, param, loadPa... #include "param.h" // Para Param, ParamGame, param, loadPa...
#include "resource.h" // Para Resource #include "resource.h" // Para Resource
#include "screen.h" // Para Screen #include "screen.h" // Para Screen
@@ -43,10 +45,6 @@
#include "title.h" // Para Title #include "title.h" // Para Title
#include "utils.h" // Para Overrides, overrides #include "utils.h" // Para Overrides, overrides
#ifndef _WIN32
#include <pwd.h> // para getpwuid, passwd
#endif
// Constructor // Constructor
Director::Director(int argc, const char *argv[]) Director::Director(int argc, const char *argv[])
{ {
@@ -103,6 +101,7 @@ void Director::init()
dbg_init(renderer_); dbg_init(renderer_);
lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language))); lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language)));
Screen::init(window_, renderer_); Screen::init(window_, renderer_);
SDL_ShowCursor(SDL_DISABLE);
Resource::init(); Resource::init();
Input::init(Asset::get()->get("gamecontrollerdb.txt")); Input::init(Asset::get()->get("gamecontrollerdb.txt"));
bindInputs(); bindInputs();
@@ -128,6 +127,10 @@ void Director::close()
SDL_DestroyWindow(window_); SDL_DestroyWindow(window_);
SDL_Quit(); SDL_Quit();
#ifdef ARCADE
shutdownSystem(section::options == section::Options::QUIT_WITH_CONTROLLER);
#endif
} }
// Carga los parametros // Carga los parametros
@@ -180,8 +183,9 @@ void Director::bindInputs()
Input::get()->bindKey(InputType::WINDOW_FULLSCREEN, SDL_SCANCODE_F3); Input::get()->bindKey(InputType::WINDOW_FULLSCREEN, SDL_SCANCODE_F3);
Input::get()->bindKey(InputType::VIDEO_SHADERS, SDL_SCANCODE_F4); Input::get()->bindKey(InputType::VIDEO_SHADERS, SDL_SCANCODE_F4);
Input::get()->bindKey(InputType::MUTE, SDL_SCANCODE_F5); Input::get()->bindKey(InputType::MUTE, SDL_SCANCODE_F5);
Input::get()->bindKey(InputType::CHANGE_LANG, SDL_SCANCODE_F6); Input::get()->bindKey(InputType::AUTO_FIRE, SDL_SCANCODE_F6);
Input::get()->bindKey(InputType::SHOWINFO, SDL_SCANCODE_F7); 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); Input::get()->bindKey(InputType::RESET, SDL_SCANCODE_F10);
// Asigna botones a inputs // Asigna botones a inputs
@@ -295,8 +299,15 @@ bool Director::initSDL()
} }
*/ */
// Obtiene información sobre la pantalla
SDL_DisplayMode DM; SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode(0, &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 << "\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; std::cout << "Window resolution : " << param.game.width << "x" << param.game.height << " x" << options.video.window.size << std::endl;
@@ -306,12 +317,10 @@ bool Director::initSDL()
std::cout << "Warning: texture filtering not enabled!\n"; std::cout << "Warning: texture filtering not enabled!\n";
} }
#ifndef NO_SHADERS
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl")) if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"))
{ {
std::cout << "Warning: opengl not enabled!\n"; std::cout << "Warning: opengl not enabled!\n";
} }
#endif
// Crea la ventana // Crea la ventana
window_ = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, param.game.width * options.video.window.size, param.game.height * options.video.window.size, SDL_WINDOW_HIDDEN); window_ = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, param.game.width * options.video.window.size, param.game.height * options.video.window.size, SDL_WINDOW_HIDDEN);
@@ -329,10 +338,8 @@ bool Director::initSDL()
flags = SDL_RENDERER_PRESENTVSYNC; flags = SDL_RENDERER_PRESENTVSYNC;
} }
#ifndef NO_SHADERS
// La aceleración se activa según el define // La aceleración se activa según el define
flags = flags | SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE; flags = flags | SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
#endif
renderer_ = SDL_CreateRenderer(window_, -1, flags); renderer_ = SDL_CreateRenderer(window_, -1, flags);
@@ -386,17 +393,28 @@ void Director::setFileList()
Asset::get()->add(prefix + "/data/sound/bubble3.wav", AssetType::SOUND); 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/bubble4.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/bullet.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/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/notify.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/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 // Shaders
Asset::get()->add(prefix + "/data/shaders/crtpi_256.glsl", AssetType::DATA); Asset::get()->add(prefix + "/data/shaders/crtpi_256.glsl", AssetType::DATA);
@@ -439,6 +457,11 @@ void Director::setFileList()
Asset::get()->add(prefix + "/data/gfx/bullet/bullet.png", AssetType::BITMAP); 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 { // Juego
Asset::get()->add(prefix + "/data/gfx/game/game_buildings.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/game/game_buildings.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_clouds1.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/game/game_clouds1.png", AssetType::BITMAP);
@@ -446,10 +469,17 @@ void Director::setFileList()
Asset::get()->add(prefix + "/data/gfx/game/game_grass.png", AssetType::BITMAP); 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_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_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 { // Intro
Asset::get()->add(prefix + "/data/gfx/intro/intro.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/intro/intro1.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/intro/intro2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/intro/intro3.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/intro/intro4.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/intro/intro5.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/intro/intro6.png", AssetType::BITMAP);
} }
{ // Logo { // Logo
@@ -469,6 +499,8 @@ void Director::setFileList()
Asset::get()->add(prefix + "/data/gfx/item/item_clock.ani", AssetType::ANIMATION); 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.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.ani", AssetType::ANIMATION); 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.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.ani", AssetType::ANIMATION);
} }
@@ -484,17 +516,17 @@ void Director::setFileList()
{ // Jugador 1 { // Jugador 1
Asset::get()->add(prefix + "/data/gfx/player/player1.gif", AssetType::BITMAP); 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_1_coffee_palette.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_two_coffee_palette.pal", AssetType::PALETTE); Asset::get()->add(prefix + "/data/gfx/player/player1_2_coffee_palette.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_all_white_palette.pal", 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); Asset::get()->add(prefix + "/data/gfx/player/player1_power.png", AssetType::BITMAP);
} }
{ // Jugador 2 { // Jugador 2
Asset::get()->add(prefix + "/data/gfx/player/player2.gif", AssetType::BITMAP); 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_1_coffee_palette.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_two_coffee_palette.pal", AssetType::PALETTE); Asset::get()->add(prefix + "/data/gfx/player/player2_2_coffee_palette.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_all_white_palette.pal", 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); Asset::get()->add(prefix + "/data/gfx/player/player2_power.png", AssetType::BITMAP);
} }
@@ -506,8 +538,6 @@ void Director::setFileList()
// Fuentes de texto // Fuentes de texto
Asset::get()->add(prefix + "/data/font/8bithud.png", AssetType::BITMAP); 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/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.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/smb2_palette1.pal", AssetType::PALETTE); Asset::get()->add(prefix + "/data/font/smb2_palette1.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/font/smb2.txt", AssetType::FONT); Asset::get()->add(prefix + "/data/font/smb2.txt", AssetType::FONT);
@@ -515,6 +545,8 @@ void Director::setFileList()
Asset::get()->add(prefix + "/data/font/04b_25.txt", AssetType::FONT); 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.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/04b_25_2x.txt", AssetType::FONT); 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 // Textos
Asset::get()->add(prefix + "/data/lang/es_ES.txt", AssetType::LANG); Asset::get()->add(prefix + "/data/lang/es_ES.txt", AssetType::LANG);
@@ -523,8 +555,10 @@ void Director::setFileList()
// Si falta algun fichero, sale del programa // Si falta algun fichero, sale del programa
if (!Asset::get()->check()) if (!Asset::get()->check())
{
throw std::runtime_error("Falta algun fichero"); throw std::runtime_error("Falta algun fichero");
} }
}
// Comprueba los parametros del programa // Comprueba los parametros del programa
void Director::checkProgramArguments(int argc, const char *argv[]) void Director::checkProgramArguments(int argc, const char *argv[])
@@ -741,11 +775,6 @@ int Director::run()
// Habilita de nuevo los std::cout // Habilita de nuevo los std::cout
std::cout.rdbuf(orig_buf); std::cout.rdbuf(orig_buf);
#endif #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; return (section::options == section::Options::QUIT_WITH_CONTROLLER) ? 1 : 0;
} }
@@ -773,20 +802,23 @@ std::string Director::getLangFile(lang::Code code)
#ifdef ARCADE #ifdef ARCADE
// Apaga el sistema // Apaga el sistema
void Director::shutdownSystem() void Director::shutdownSystem(bool shouldShutdown)
{
if (shouldShutdown)
{ {
#ifdef _WIN32 #ifdef _WIN32
// Apaga el sistema en Windows // Apaga el sistema en Windows
system("shutdown /s /t 0"); system("shutdown /s /t 5");
#elif __APPLE__ #elif __APPLE__
// Apaga el sistema en macOS // Apaga el sistema en macOS
system("sudo shutdown -h now"); system("sudo shutdown -h +0.1");
#elif __linux__ #elif __linux__
// Apaga el sistema en Linux // Apaga el sistema en Linux
system("shutdown -h now"); system("sleep 5; shutdown -h now");
#else #else
// Sistema operativo no compatible // Sistema operativo no compatible
#error "Sistema operativo no soportado" #error "Sistema operativo no soportado"
#endif #endif
} }
}
#endif // ARCADE #endif // ARCADE

View File

@@ -74,7 +74,7 @@ private:
std::string getLangFile(lang::Code code); std::string getLangFile(lang::Code code);
#ifdef ARCADE #ifdef ARCADE
// Apaga el sistema // Apaga el sistema
void shutdownSystem(); void shutdownSystem(bool shouldShutdown);
#endif #endif
// Inicializa todo // Inicializa todo

View File

@@ -1,93 +1,163 @@
#include "enter_name.h" #include "enter_name.h"
#include "utils.h"
#include <stddef.h> // Para size_t #include <stddef.h> // Para size_t
#include <algorithm> // Para max, min #include <algorithm> // Para max, min
#include <cassert> // Para assert
#include <iostream>
// Constructor // Constructor
EnterName::EnterName() EnterName::EnterName()
{ : character_list_(" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()") {}
init();
}
// Inicializa el objeto // Inicializa el objeto
void EnterName::init() void EnterName::init(const std::string &name)
{
// No se pasa ningún nombre
if (name.empty())
{ {
// Obtiene el puntero al nombre
name_ = "A"; name_ = "A";
// Inicia la lista de caracteres permitidos
character_list_ = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()";
position_ = 0; position_ = 0;
num_characters_ = static_cast<int>(character_list_.size()); position_overflow_ = false;
}
// Se pasa un nombre
else
{
name_ = name;
position_ = name_.length();
position_overflow_ = position_ >= MAX_NAME_LENGHT ? true : false;
}
// Pone la lista de indices para que refleje el nombre // Inicializa el vector de indices con el nombre y espacios
updateCharacterIndex(); initCharacterIndex(name_);
// Actualiza el nombre para que ocupe 8 espacios
updateName();
} }
// Incrementa la posición // Incrementa la posición
void EnterName::incPosition() void EnterName::incPosition()
{ {
position_++; if (position_overflow_)
position_ = std::min(position_, NAME_LENGHT - 1); {
checkIfPositionHasBeenUsed(); // Si ya estamos en overflow, no incrementamos más.
return;
}
++position_;
if (position_ >= MAX_NAME_LENGHT)
{
position_ = MAX_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_ < MAX_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 // Decrementa la posición
void EnterName::decPosition() void EnterName::decPosition()
{
if (position_overflow_)
{
// Si estaba en overflow, lo desactivamos y mantenemos position_ en el máximo.
position_overflow_ = false;
position_ = MAX_NAME_LENGHT - 1;
}
else
{
if (position_ > 0)
{ {
--position_; --position_;
position_ = std::max(position_, 0);
// Limpiamos el carácter siguiente si el índice es válido.
if (position_ + 1 < MAX_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_ < MAX_NAME_LENGHT)
{
position_overflow_ = false;
}
}
updateNameFromCharacterIndex();
} }
// Incrementa el índice // Incrementa el índice
void EnterName::incIndex() void EnterName::incIndex()
{ {
if (position_overflow_)
{
return;
}
++character_index_[position_]; ++character_index_[position_];
if (character_index_[position_] >= num_characters_) if (character_index_[position_] >= static_cast<int>(character_list_.size()))
{ {
character_index_[position_] = 0; character_index_[position_] = 0;
} }
updateName(); updateNameFromCharacterIndex();
} }
// Decrementa el índice // Decrementa el índice
void EnterName::decIndex() void EnterName::decIndex()
{ {
if (position_overflow_)
{
return;
}
--character_index_[position_]; --character_index_[position_];
if (character_index_[position_] < 0) 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 // Actualiza el nombre a partir de la lista de índices
void EnterName::updateName() void EnterName::updateNameFromCharacterIndex()
{ {
name_.clear(); name_.clear();
for (int i = 0; i < NAME_LENGHT; ++i) for (int i = 0; i < MAX_NAME_LENGHT; ++i)
{ {
name_.push_back(character_list_[character_index_[i]]); name_.push_back(character_list_[character_index_[i]]);
} }
name_ = trim(name_);
} }
// Actualiza la variable // 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) for (size_t i = 0; i < MAX_NAME_LENGHT; ++i)
{ {
character_index_[i] = 0; character_index_[i] = 0;
position_has_been_used_[i] = false;
} }
// Coloca los índices en función de los caracteres que forman el nombre // 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, MAX_NAME_LENGHT).size(); ++i)
{ {
character_index_[i] = findIndex(name_.at(i)); character_index_[i] = findIndex(name.at(i));
position_has_been_used_[i] = true;
} }
} }
@@ -95,31 +165,11 @@ void EnterName::updateCharacterIndex()
int EnterName::findIndex(char character) const int EnterName::findIndex(char character) const
{ {
for (size_t i = 0; i < character_list_.size(); ++i) for (size_t i = 0; i < character_list_.size(); ++i)
{
if (character == character_list_.at(i)) if (character == character_list_.at(i))
{
return i; return i;
}
}
return 0; 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();
}

View File

@@ -1,8 +1,9 @@
#pragma once #pragma once
#include <string> #include <string>
#include "utils.h"
constexpr int NAME_LENGHT = 6; constexpr int MAX_NAME_LENGHT = 6;
/* /*
Un array, "characterList", contiene la lista de caracteres Un array, "characterList", contiene la lista de caracteres
@@ -18,23 +19,19 @@ class EnterName
private: private:
std::string character_list_; // Lista de todos los caracteres permitidos std::string character_list_; // Lista de todos los caracteres permitidos
std::string name_; // Nombre introducido std::string name_; // Nombre introducido
int position_; // Posición a editar del nombre int position_ = 0; // Posición a editar del nombre
int num_characters_; // Cantidad de caracteres de la lista de caracteres 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 int character_index_[MAX_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
// Actualiza el nombre a partir de la lista de índices // Actualiza el nombre a partir de la lista de índices
void updateName(); void updateNameFromCharacterIndex();
// Actualiza la variable // Actualiza la variable
void updateCharacterIndex(); void initCharacterIndex(const std::string &name);
// Encuentra el indice de un caracter en "characterList" // Encuentra el indice de un caracter en "characterList"
int findIndex(char character) const; int findIndex(char character) const;
// Comprueba la posición y copia el caracter si es necesario
void checkIfPositionHasBeenUsed();
public: public:
// Constructor // Constructor
EnterName(); EnterName();
@@ -43,7 +40,7 @@ public:
~EnterName() = default; ~EnterName() = default;
// Inicializa el objeto // Inicializa el objeto
void init(); void init(const std::string &name = "");
// Incrementa la posición // Incrementa la posición
void incPosition(); void incPosition();
@@ -57,9 +54,9 @@ public:
// Decrementa el índice // Decrementa el índice
void decIndex(); void decIndex();
// Obtiene el nombre // Getters
std::string getName() const; std::string getFinalName() const { return trim(name_.substr(0, position_)); }
std::string getCurrentName() const { return trim(name_); }
// Obtiene la posición que se está editando int getPosition() const { return position_; }
int getPosition() const; bool getPositionOverflow() const { return position_overflow_; }
}; };

View File

@@ -30,15 +30,15 @@ void Fade::init()
{ {
type_ = FadeType::CENTER; type_ = FadeType::CENTER;
mode_ = FadeMode::OUT; mode_ = FadeMode::OUT;
enabled_ = false;
finished_ = false;
counter_ = 0; counter_ = 0;
r_ = 0; r_ = 0;
g_ = 0; g_ = 0;
b_ = 0; b_ = 0;
a_ = 0; a_ = 0;
post_duration_ = 20; post_duration_ = 0;
post_counter_ = 0; post_counter_ = 0;
pre_duration_ = 0;
pre_counter_ = 0;
num_squares_width_ = param.fade.num_squares_width; num_squares_width_ = param.fade.num_squares_width;
num_squares_height_ = param.fade.num_squares_height; num_squares_height_ = param.fade.num_squares_height;
fade_random_squares_delay_ = param.fade.random_squares_delay; 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 // Resetea algunas variables para volver a hacer el fade sin perder ciertos parametros
void Fade::reset() void Fade::reset()
{ {
enabled_ = false; state_ = FadeState::NOT_ENABLED;
finished_ = false;
counter_ = 0; counter_ = 0;
} }
// Pinta una transición en pantalla // Pinta una transición en pantalla
void Fade::render() void Fade::render()
{ {
if (enabled_ || finished_) if (state_ != FadeState::NOT_ENABLED)
{ {
SDL_RenderCopy(renderer_, backbuffer_, nullptr, nullptr); SDL_RenderCopy(renderer_, backbuffer_, nullptr, nullptr);
} }
@@ -65,7 +64,20 @@ void Fade::render()
// Actualiza las variables internas // Actualiza las variables internas
void Fade::update() 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_) switch (type_)
{ {
@@ -79,7 +91,7 @@ void Fade::update()
// Comprueba si ha terminado // Comprueba si ha terminado
if (counter_ >= 255 / 4) if (counter_ >= 255 / 4)
{ {
finished_ = true; state_ = FadeState::POST;
} }
break; break;
@@ -100,6 +112,8 @@ void Fade::update()
SDL_RenderFillRect(renderer_, &rect1_); SDL_RenderFillRect(renderer_, &rect1_);
SDL_RenderFillRect(renderer_, &rect2_); SDL_RenderFillRect(renderer_, &rect2_);
value_ = calculateValue(0, counter_, i);
} }
// Deja el renderizador como estaba // Deja el renderizador como estaba
@@ -108,7 +122,7 @@ void Fade::update()
// Comprueba si ha terminado // Comprueba si ha terminado
if ((counter_ * 4) > param.game.height) if ((counter_ * 4) > param.game.height)
{ {
finished_ = true; state_ = FadeState::POST;
a_ = 255; a_ = 255;
} }
break; break;
@@ -118,10 +132,11 @@ void Fade::update()
{ {
if (counter_ % fade_random_squares_delay_ == 0) 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_); auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, backbuffer_); SDL_SetRenderTarget(renderer_, backbuffer_);
SDL_BlendMode blend_mode;
SDL_GetRenderDrawBlendMode(renderer_, &blend_mode);
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE); SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_); SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
@@ -133,16 +148,17 @@ void Fade::update()
SDL_RenderFillRect(renderer_, &square_[index2]); SDL_RenderFillRect(renderer_, &square_[index2]);
} }
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
// Deja el renderizador como estaba // Deja el renderizador como estaba
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
SDL_SetRenderTarget(renderer_, temp); 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 // Comprueba si ha terminado
if (counter_ * fade_random_squares_mult_ / fade_random_squares_delay_ >= num_squares_width_ * num_squares_height_) if (counter_ * fade_random_squares_mult_ / fade_random_squares_delay_ >= num_squares_width_ * num_squares_height_)
{ {
finished_ = true; state_ = FadeState::POST;
} }
break; break;
@@ -150,64 +166,88 @@ void Fade::update()
case FadeType::VENETIAN: 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) if (square_.back().h < param.fade.venetian_size)
{ {
// Dibuja sobre el backbuffer_ // Dibuja sobre el backbuffer_
auto temp = SDL_GetRenderTarget(renderer_); auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, backbuffer_); 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_); SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
for (auto rect : square_)
// Dibuja el cuadrado correspondiente
for (const auto rect : square_)
{ {
SDL_RenderFillRect(renderer_, &rect); SDL_RenderFillRect(renderer_, &rect);
} }
// Deja el renderizador como estaba // Deja el renderizador como estaba
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
SDL_SetRenderTarget(renderer_, temp); SDL_SetRenderTarget(renderer_, temp);
const auto h = counter_ / 3; // Modifica el tamaño de los rectangulos
for (int i = 0; i < (int)square_.size(); ++i) 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 // 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 else
{ {
finished_ = true; state_ = FadeState::POST;
} }
break; break;
} }
default:
break;
}
counter_++;
} }
if (finished_) if (state_ == FadeState::POST)
{ {
// Actualiza el contador // Actualiza el contador
post_counter_ == post_duration_ ? enabled_ = false : post_counter_++; if (post_counter_ == post_duration_)
{
state_ = FadeState::FINISHED;
}
else
{
post_counter_++;
}
// Deja el backbuffer_ todo del mismo color // Deja el backbuffer_ todo del mismo color
cleanBackbuffer(r_, g_, b_, a_); cleanBackbuffer(r_, g_, b_, a_);
} }
counter_++;
}
} }
// Activa el fade // Activa el fade
void Fade::activate() void Fade::activate()
{ {
// Si ya está habilitado, no hay que volverlo a activar // Si ya está habilitado, no hay que volverlo a activar
if (enabled_) if (state_ != FadeState::NOT_ENABLED)
{ {
return; return;
} }
enabled_ = true; state_ = FadeState::PRE;
finished_ = false;
counter_ = 0; counter_ = 0;
post_counter_ = 0; post_counter_ = 0;
pre_counter_ = 0;
switch (type_) switch (type_)
{ {
@@ -251,12 +291,8 @@ void Fade::activate()
} }
// Limpia la textura // Limpia la textura
auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, backbuffer_);
a_ = mode_ == FadeMode::OUT ? 0 : 255; a_ = mode_ == FadeMode::OUT ? 0 : 255;
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_); cleanBackbuffer(r_, g_, b_, a_);
SDL_RenderClear(renderer_);
SDL_SetRenderTarget(renderer_, temp);
// Deja el color listo para usar // Deja el color listo para usar
a_ = mode_ == FadeMode::OUT ? 255 : 0; a_ = mode_ == FadeMode::OUT ? 255 : 0;
@@ -266,12 +302,16 @@ void Fade::activate()
case FadeType::VENETIAN: case FadeType::VENETIAN:
{ {
cleanBackbuffer(0, 0, 0, 0); // Limpia la textura
rect1_ = {0, 0, param.game.width, 0}; a_ = mode_ == FadeMode::OUT ? 0 : 255;
square_.clear(); cleanBackbuffer(r_, g_, b_, a_);
a_ = 255;
// Deja el color listo para usar
a_ = mode_ == FadeMode::OUT ? 255 : 0;
// Añade los cuadrados al vector // 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; const int max = param.game.height / param.fade.venetian_size;
for (int i = 0; i < max; ++i) 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 // Establece el color del fade
void Fade::setColor(Uint8 r, Uint8 g, Uint8 b) void Fade::setColor(Uint8 r, Uint8 g, Uint8 b)
{ {
@@ -318,12 +333,6 @@ void Fade::setColor(Uint8 r, Uint8 g, Uint8 b)
b_ = b; b_ = b;
} }
// Establece la duración posterior
void Fade::setPost(int value)
{
post_duration_ = value;
}
// Limpia el backbuffer // Limpia el backbuffer
void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a) void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{ {
@@ -338,3 +347,19 @@ void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
// Vuelve a dejar el renderizador como estaba // Vuelve a dejar el renderizador como estaba
SDL_SetRenderTarget(renderer_, temp); 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));
}

View File

@@ -21,6 +21,16 @@ enum class FadeMode : Uint8
OUT = 1, OUT = 1,
}; };
// Estados del objeto
enum class FadeState : Uint8
{
NOT_ENABLED = 0,
PRE = 1,
FADING = 2,
POST = 3,
FINISHED = 4,
};
// Clase Fade // Clase Fade
class Fade class Fade
{ {
@@ -32,9 +42,8 @@ private:
// Variables // Variables
FadeType type_; // Tipo de fade a realizar FadeType type_; // Tipo de fade a realizar
FadeMode mode_; // Modo de fade a realizar FadeMode mode_; // Modo de fade a realizar
FadeState state_ = FadeState::NOT_ENABLED; // Estado actual del objeto
Uint16 counter_; // Contador interno 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 Uint8 r_, g_, b_, a_; // Colores para el fade
SDL_Rect rect1_; // Rectangulo usado para crear los efectos de transición SDL_Rect rect1_; // Rectangulo usado para crear los efectos de transición
SDL_Rect rect2_; // Rectangulo usado para crear los efectos de transición SDL_Rect rect2_; // Rectangulo usado para crear los efectos de transición
@@ -43,8 +52,11 @@ private:
std::vector<SDL_Rect> square_; // Vector con los indices de los cuadrados 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_delay_; // Duración entre cada pintado de cuadrados
int fade_random_squares_mult_; // Cantidad de cuadrados que se pintaran cada vez 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_duration_ = 0; // Duración posterior del fade tras finalizar
int post_counter_; // Contador para la duración posterior 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 // Inicializa las variables
void init(); void init();
@@ -52,6 +64,9 @@ private:
// Limpia el backbuffer // Limpia el backbuffer
void cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a); 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: public:
// Constructor // Constructor
Fade(); Fade();
@@ -71,21 +86,17 @@ public:
// Activa el fade // Activa el fade
void activate(); 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 // Establece el color del fade
void setColor(Uint8 r, Uint8 g, Uint8 b); void setColor(Uint8 r, Uint8 g, Uint8 b);
// Establece la duración posterior // Getters
void setPost(int value); 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; }
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,7 @@
#include <SDL2/SDL_render.h> // Para SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // Para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // Para Uint32, Uint8 #include <SDL2/SDL_stdinc.h> // Para Uint32, Uint8
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_KEYDOWN
#include <memory> // Para shared_ptr, unique_ptr #include <memory> // Para shared_ptr, unique_ptr
#include <string> // Para string #include <string> // Para string
#include <vector> // Para vector #include <vector> // Para vector
@@ -12,6 +13,7 @@
class Asset; // lines 13-13 class Asset; // lines 13-13
class Background; // lines 14-14 class Background; // lines 14-14
class BalloonManager; class BalloonManager;
class Tabe;
class Bullet; // lines 15-15 class Bullet; // lines 15-15
class Fade; // lines 16-16 class Fade; // lines 16-16
class Input; // lines 17-17 class Input; // lines 17-17
@@ -65,6 +67,9 @@ private:
// Enum // Enum
enum class GameState enum class GameState
{ {
FADE_IN,
ENTERING_PLAYER,
SHOWING_GET_READY_MESSAGE,
PLAYING, PLAYING,
COMPLETED, COMPLETED,
GAME_OVER, GAME_OVER,
@@ -140,8 +145,10 @@ private:
std::vector<std::vector<std::string>> item_animations_; // Vector con las animaciones de los items 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::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<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 std::vector<Path> paths_; // Vector con los recorridos precalculados almacenados
// Variables // Variables
@@ -164,9 +171,12 @@ private:
int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases 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_current_ = 0; // Nivel de amenaza actual
int menace_threshold_ = 0; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos int menace_threshold_ = 0; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos
GameState state_ = GameState::PLAYING; // Estado GameState state_ = GameState::FADE_IN; // Estado
#ifdef DEBUG #ifdef DEBUG
bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados
// Comprueba los eventos en el modo DEBUG
void checkDebugEvents(const SDL_Event &event);
#endif #endif
// Actualiza el juego // Actualiza el juego
@@ -194,7 +204,7 @@ private:
void updateStage(); void updateStage();
// Actualiza el estado de fin de la partida // Actualiza el estado de fin de la partida
void updateGameOverState(); void updateGameStateGameOver();
// Destruye todos los items // Destruye todos los items
void destroyAllItems(); void destroyAllItems();
@@ -205,11 +215,11 @@ private:
// Comprueba la colisión entre el jugador y los items // Comprueba la colisión entre el jugador y los items
void checkPlayerItemCollision(std::shared_ptr<Player> &player); void checkPlayerItemCollision(std::shared_ptr<Player> &player);
// Comprueba la colisión entre las balas y los globos // Comprueba y procesa la colisión de las balas
void checkBulletBalloonCollision(); void checkBulletCollision();
// Mueve las balas activas // Mueve las balas activas
void moveBullets(); void updateBullets();
// Pinta las balas activas // Pinta las balas activas
void renderBullets(); void renderBullets();
@@ -292,9 +302,6 @@ private:
// Comprueba si todos los jugadores han terminado de jugar // Comprueba si todos los jugadores han terminado de jugar
bool allPlayersAreNotPlaying(); bool allPlayersAreNotPlaying();
// Recarga las texturas
void reloadTextures();
// Actualiza el marcador // Actualiza el marcador
void updateScoreboard(); void updateScoreboard();
@@ -304,11 +311,8 @@ private:
// Pausa el juego // Pausa el juego
void pause(bool value); 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 // 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 // Saca del estado de GAME OVER al jugador si el otro está activo
void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index); void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index);
@@ -373,6 +377,9 @@ private:
// Reanuda la música // Reanuda la música
void resumeMusic(); void resumeMusic();
// Hace sonar la música
void playMusic();
// Detiene la música // Detiene la música
void stopMusic(); void stopMusic();
@@ -382,11 +389,20 @@ private:
// Actualiza las variables durante el modo de grabación // Actualiza las variables durante el modo de grabación
void updateRecording(); void updateRecording();
#endif #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 // Actualiza las variables durante el transcurso normal del juego
void updateGame(); void updateGameStatePlaying();
// Gestiona eventos para el estado del final del juego // Gestiona eventos para el estado del final del juego
void updateCompletedState(); void updateGameStateCompleted();
// Comprueba el estado del juego // Comprueba el estado del juego
void checkState(); void checkState();
@@ -403,6 +419,9 @@ private:
// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase // Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
void checkAndUpdateBalloonSpeed(); void checkAndUpdateBalloonSpeed();
// Cambia el estado del juego
void setState(GameState state);
public: public:
// Constructor // Constructor
Game(int playerID, int current_stage, bool demo); Game(int playerID, int current_stage, bool demo);

View File

@@ -5,9 +5,15 @@
#include "jail_audio.h" // Para JA_PlaySound #include "jail_audio.h" // Para JA_PlaySound
#include "param.h" // Para Param, param, ParamGame, ParamTitle #include "param.h" // Para Param, param, ParamGame, ParamTitle
#include "resource.h" // Para Resource #include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "smart_sprite.h" // Para SmartSprite #include "smart_sprite.h" // Para SmartSprite
#include "sprite.h" // Para Sprite #include "sprite.h" // Para Sprite
#include "texture.h" // Para Texture #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 // Constructor
GameLogo::GameLogo(int x, int y) GameLogo::GameLogo(int x, int y)
@@ -32,15 +38,8 @@ void GameLogo::init()
// Variables // Variables
coffee_crisis_status_ = Status::DISABLED; coffee_crisis_status_ = Status::DISABLED;
arcade_edition_status_ = Status::DISABLED; arcade_edition_status_ = Status::DISABLED;
shake_.init(1, 2, 8, xp);
shake_.desp = 1; zoom_ = 3.0f * ZOOM_FACTOR;
shake_.delay = 2;
shake_.lenght = 8;
shake_.remaining = shake_.lenght;
shake_.counter = shake_.delay;
shake_.origin = xp;
zoom_ = 3.0f;
// Inicializa el bitmap de 'Coffee' // Inicializa el bitmap de 'Coffee'
coffee_sprite_->setPosX(xp); coffee_sprite_->setPosX(xp);
@@ -122,10 +121,11 @@ void GameLogo::update()
if (coffee_sprite_->hasFinished() && crisis_sprite_->hasFinished()) if (coffee_sprite_->hasFinished() && crisis_sprite_->hasFinished())
{ {
coffee_crisis_status_ = Status::SHAKING; coffee_crisis_status_ = Status::SHAKING;
arcade_edition_status_ = Status::MOVING;
// Reproduce el efecto sonoro // Reproduce el efecto sonoro
JA_PlaySound(Resource::get()->getSound("title.wav")); JA_PlaySound(Resource::get()->getSound("title.wav"));
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
Screen::get()->shake();
} }
break; break;
@@ -133,7 +133,7 @@ void GameLogo::update()
case Status::SHAKING: case Status::SHAKING:
{ {
// Agita el logo // Agita "COFFEE CRISIS"
if (shake_.remaining > 0) if (shake_.remaining > 0)
{ {
if (shake_.counter > 0) if (shake_.counter > 0)
@@ -154,6 +154,7 @@ void GameLogo::update()
coffee_sprite_->setPosX(shake_.origin); coffee_sprite_->setPosX(shake_.origin);
crisis_sprite_->setPosX(shake_.origin + 15); crisis_sprite_->setPosX(shake_.origin + 15);
coffee_crisis_status_ = Status::FINISHED; coffee_crisis_status_ = Status::FINISHED;
arcade_edition_status_ = Status::MOVING;
} }
dust_right_sprite_->update(); dust_right_sprite_->update();
@@ -178,12 +179,42 @@ void GameLogo::update()
{ {
case Status::MOVING: case Status::MOVING:
{ {
zoom_ -= 0.1f; zoom_ -= 0.1f * ZOOM_FACTOR;
arcade_edition_sprite_->setZoom(zoom_); arcade_edition_sprite_->setZoom(zoom_);
if (zoom_ <= 1.0f) if (zoom_ <= 1.0f)
{ {
arcade_edition_status_ = Status::FINISHED; arcade_edition_status_ = Status::SHAKING;
zoom_ = 1.0f; 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; break;
} }
@@ -191,6 +222,13 @@ void GameLogo::update()
default: default:
break; break;
} }
if (coffee_crisis_status_ == Status::FINISHED &&
arcade_edition_status_ == Status::FINISHED &&
post_finished_counter_ > 0)
{
--post_finished_counter_;
}
} }
// Activa la clase // Activa la clase
@@ -203,16 +241,7 @@ void GameLogo::enable()
// Indica si ha terminado la animación // Indica si ha terminado la animación
bool GameLogo::hasFinished() const bool GameLogo::hasFinished() const
{ {
return coffee_crisis_status_ == Status::FINISHED && arcade_edition_status_ == Status::FINISHED; return post_finished_counter_ == 0;
}
// Recarga las texturas
void GameLogo::reLoad()
{
dust_texture_->reLoad();
coffee_texture_->reLoad();
crisis_texture_->reLoad();
arcade_edition_texture_->reLoad();
} }
// Calcula el desplazamiento vertical inicial // Calcula el desplazamiento vertical inicial

View File

@@ -20,12 +20,30 @@ private:
struct Shake struct Shake
{ {
int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x int desp = 1; // Pixels de desplazamiento para agitar la pantalla en el eje x
int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse int delay = 2; // Retraso entre cada desplazamiento de la pantalla al agitarse
int counter; // Contador para el retraso int lenght = 8; // Cantidad de desplazamientos a realizar
int lenght; // Cantidad de desplazamientos a realizar int remaining = lenght; // Cantidad de desplazamientos pendientes a realizar
int remaining; // 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 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 // Objetos y punteros
@@ -46,6 +64,7 @@ private:
int x_; // Posición donde dibujar el logo int x_; // Posición donde dibujar el logo
int y_; // Posición donde dibujar el logo int y_; // Posición donde dibujar el logo
float zoom_; // Zoom aplicado al texto "ARCADE EDITION" float zoom_; // Zoom aplicado al texto "ARCADE EDITION"
int post_finished_counter_ = 1; // Contador final una vez terminada las animaciones de los logos
Status coffee_crisis_status_ = Status::DISABLED; // Estado en el que se encuentra el texto "COFFEE CRISIS" 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" Status arcade_edition_status_ = Status::DISABLED; // Estado en el que se encuentra el texto "ARCADE_EDITION"
@@ -75,7 +94,4 @@ public:
// Indica si ha terminado la animación // Indica si ha terminado la animación
bool hasFinished() const; bool hasFinished() const;
// Recarga las texturas
void reLoad();
}; };

View File

@@ -1,93 +1,6 @@
#include <stdio.h> #include "gif.h"
#include <stdlib.h> #include <stdio.h> // for NULL, fprintf, stderr
#include <string.h> #include <stdlib.h> // for malloc, realloc, exit, calloc, free
#include <fcntl.h>
#define EXTENSION_INTRODUCER 0x21
#define IMAGE_DESCRIPTOR 0x2C
#define TRAILER 0x3B
#define GRAPHIC_CONTROL 0xF9
#define APPLICATION_EXTENSION 0xFF
#define COMMENT_EXTENSION 0xFE
#define PLAINTEXT_EXTENSION 0x01
#define READ(dst, size) memcpy(dst, buffer, size); buffer += size
typedef struct
{
unsigned short width;
unsigned short height;
unsigned char fields;
unsigned char background_color_index;
unsigned char pixel_aspect_ratio;
}
screen_descriptor_t;
typedef struct
{
unsigned char r;
unsigned char g;
unsigned char b;
}
rgb;
typedef struct
{
unsigned short image_left_position;
unsigned short image_top_position;
unsigned short image_width;
unsigned short image_height;
unsigned char fields;
}
image_descriptor_t;
typedef struct
{
unsigned char byte;
int prev;
int len;
}
dictionary_entry_t;
typedef struct
{
unsigned char extension_code;
unsigned char block_size;
}
extension_t;
typedef struct
{
unsigned char fields;
unsigned short delay_time;
unsigned char transparent_color_index;
}
graphic_control_extension_t;
typedef struct
{
unsigned char application_id[ 8 ];
unsigned char version[ 3 ];
}
application_extension_t;
typedef struct
{
unsigned short left;
unsigned short top;
unsigned short width;
unsigned short height;
unsigned char cell_width;
unsigned char cell_height;
unsigned char foreground_color;
unsigned char background_color;
}
plaintext_extension_t;
//static unsigned short width = 0;
//static unsigned short height = 0;
//static unsigned char* uncompressed_data = NULL;
void uncompress( int code_length, void uncompress( int code_length,
const unsigned char *input, const unsigned char *input,
@@ -105,7 +18,6 @@ void uncompress( int code_length,
int stop_code; // one more than clear code int stop_code; // one more than clear code
int match_len; int match_len;
clear_code = 1 << ( code_length ); clear_code = 1 << ( code_length );
stop_code = clear_code + 1; stop_code = clear_code + 1;
// To handle clear codes // To handle clear codes
@@ -142,7 +54,7 @@ void uncompress( int code_length,
{ {
code = 0x0; code = 0x0;
// Always read one more bit than the code length // Always read one more bit than the code length
for ( i = 0; i < ( code_length + 1 ); ++i ) for ( i = 0; i < ( code_length + 1 ); i++ )
{ {
// This is different than in the file read example; that // This is different than in the file read example; that
// was a call to "next_bit" // was a call to "next_bit"

66
source/gif.h Normal file
View File

@@ -0,0 +1,66 @@
#pragma once
#include <stdint.h> // for uint32_t
#include <string.h> // for memcpy
#define EXTENSION_INTRODUCER 0x21
#define IMAGE_DESCRIPTOR 0x2C
#define TRAILER 0x3B
#define GRAPHIC_CONTROL 0xF9
#define APPLICATION_EXTENSION 0xFF
#define COMMENT_EXTENSION 0xFE
#define PLAINTEXT_EXTENSION 0x01
#define READ(dst, size) memcpy(dst, buffer, size); buffer += size
typedef struct {
unsigned short width;
unsigned short height;
unsigned char fields;
unsigned char background_color_index;
unsigned char pixel_aspect_ratio;
} screen_descriptor_t;
typedef struct {
unsigned char r, g, b;
} rgb;
typedef struct {
unsigned short image_left_position;
unsigned short image_top_position;
unsigned short image_width;
unsigned short image_height;
unsigned char fields;
} image_descriptor_t;
typedef struct {
unsigned char byte;
int prev;
int len;
} dictionary_entry_t;
typedef struct {
unsigned char extension_code;
unsigned char block_size;
} extension_t;
typedef struct {
unsigned char fields;
unsigned short delay_time;
unsigned char transparent_color_index;
} graphic_control_extension_t;
typedef struct {
unsigned char application_id[8];
unsigned char version[3];
} application_extension_t;
typedef struct {
unsigned short left, top, width, height;
unsigned char cell_width, cell_height;
unsigned char foreground_color, background_color;
} plaintext_extension_t;
void uncompress(int code_length, const unsigned char *input, int input_length, unsigned char *out);
uint32_t* LoadPalette(unsigned char *buffer);
unsigned char* LoadGif(unsigned char *buffer, unsigned short* w, unsigned short* h);

32
source/global_events.cpp Normal file
View File

@@ -0,0 +1,32 @@
#include "global_events.h"
#include "section.h"
#include "mouse.h"
#include "resource.h"
namespace globalEvents
{
// Comprueba los eventos que se pueden producir en cualquier sección del juego
void check(const SDL_Event &event)
{
switch (event.type)
{
case SDL_QUIT: // Evento de salida de la aplicación
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
return;
case SDL_RENDER_DEVICE_RESET:
case SDL_RENDER_TARGETS_RESET:
Resource::get()->reloadTextures();
break;
case SDL_WINDOWEVENT:
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
Resource::get()->reloadTextures();
}
break;
default:
break;
}
Mouse::handleEvent(event);
}
}

9
source/global_events.h Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
#include <SDL2/SDL_events.h>
namespace globalEvents
{
// Comprueba los eventos que se pueden producir en cualquier sección del juego
void check(const SDL_Event &event);
}

View File

@@ -1,15 +1,16 @@
#include "global_inputs.h" #include "global_inputs.h"
#include <string> // Para operator+, string #include <string> // Para operator+, string, to_string, basic_string
#include "input.h" // Para Input, InputType, INPUT_DO_NOT_ALLOW_REPEAT #include <vector> // Para vector
#include "asset.h" #include "asset.h" // Para Asset
#include "jail_audio.h" // Para JA_EnableMusic, JA_EnableSound #include "input.h" // Para Input, InputDeviceToUse, InputType, INPU...
#include "lang.h" // Para getText #include "jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundVolume
#include "lang.h" // Para Code, getText, change, loadFromFile
#include "notifier.h" // Para Notifier #include "notifier.h" // Para Notifier
#include "on_screen_help.h" // Para OnScreenHelp #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 "section.h" // Para Name, Options, name, options
#include "utils.h" // Para boolToOnOff, stringInVector #include "utils.h" // Para boolToOnOff, stringInVector
#include "screen.h"
namespace globalInputs namespace globalInputs
{ {
@@ -20,9 +21,8 @@ namespace globalInputs
// Termina // Termina
void quit(section::Options code) void quit(section::Options code)
{ {
const std::string exit_code = "QUIT"; const std::string CODE = "QUIT";
auto code_found = stringInVector(Notifier::get()->getCodes(), exit_code); if (Notifier::get()->checkCode(CODE))
if (code_found)
{ {
// Si la notificación de salir está activa, cambia de sección // Si la notificación de salir está activa, cambia de sección
section::name = section::Name::QUIT; section::name = section::Name::QUIT;
@@ -32,19 +32,27 @@ namespace globalInputs
{ {
// Si la notificación de salir no está activa, muestra la notificación // Si la notificación de salir no está activa, muestra la notificación
#ifdef ARCADE #ifdef ARCADE
const int index = code == section::Options::QUIT_WITH_CONTROLLER ? 116 : 94; const int INDEX = code == section::Options::QUIT_WITH_CONTROLLER ? 116 : 94;
Notifier::get()->showText({lang::getText(index), std::string()}, -1, exit_code); Notifier::get()->showText({lang::getText(INDEX), std::string()}, -1, CODE);
#else #else
Notifier::get()->showText({lang::getText(94), std::string()}, -1, exit_code); Notifier::get()->show({lang::getText(94), std::string()}, -1, CODE);
#endif #endif
} }
} }
// Reinicia // Reinicia
void reset() void reset()
{
const std::string CODE = "RESET";
if (Notifier::get()->checkCode(CODE))
{ {
section::name = section::Name::INIT; section::name = section::Name::INIT;
Notifier::get()->showText({"Reset"}); Notifier::get()->show({"Reset"});
}
else
{
Notifier::get()->show({lang::getText(125), std::string()}, -1, CODE);
}
} }
// Activa o desactiva el audio // Activa o desactiva el audio
@@ -61,7 +69,7 @@ namespace globalInputs
JA_SetMusicVolume(0); JA_SetMusicVolume(0);
JA_SetSoundVolume(0); JA_SetSoundVolume(0);
} }
Notifier::get()->showText({"Audio " + boolToOnOff(options.audio.enabled)}); Notifier::get()->show({"Audio " + boolToOnOff(options.audio.enabled)});
} }
// Obtiene una fichero a partir de un lang::Code // Obtiene una fichero a partir de un lang::Code
@@ -87,13 +95,13 @@ namespace globalInputs
switch (code) switch (code)
{ {
case lang::Code::ba_BA: case lang::Code::ba_BA:
return "ba_BA"; return " \"ba_BA\"";
break; break;
case lang::Code::es_ES: case lang::Code::es_ES:
return "es_ES"; return " \"es_ES\"";
break; break;
default: default:
return "en_UK"; return " \"en_UK\"";
break; break;
} }
} }
@@ -101,11 +109,27 @@ namespace globalInputs
// Cambia el idioma // Cambia el idioma
void changeLang() void changeLang()
{ {
options.game.language = lang::change(options.game.language); const std::string CODE = "LANG";
if (Notifier::get()->checkCode(CODE))
{
options.game.language = lang::getNextLangCode(options.game.language);
lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language))); lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language)));
section::name = section::Name::INIT; section::name = section::Name::INIT;
section::options = section::Options::RELOAD; section::options = section::Options::RELOAD;
Notifier::get()->showText({getLangName(options.game.language)}); Notifier::get()->show({lang::getText(127) + getLangName(options.game.language)});
}
else
{
const auto NEXT = lang::getNextLangCode(options.game.language);
Notifier::get()->show({lang::getText(126) + getLangName(NEXT), std::string()}, -1, CODE);
}
}
// Cambia el modo de disparo
void toggleFireMode()
{
options.game.autofire = !options.game.autofire;
Notifier::get()->show({"Autofire " + boolToOnOff(options.game.autofire)});
} }
// Comprueba los inputs que se pueden introducir en cualquier sección del juego // Comprueba los inputs que se pueden introducir en cualquier sección del juego
@@ -119,7 +143,7 @@ namespace globalInputs
{ {
Screen::get()->toggleVideoMode(); Screen::get()->toggleVideoMode();
const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen"; const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen";
Notifier::get()->showText({mode + " mode"}); Notifier::get()->show({mode + " mode"});
return; return;
} }
@@ -128,7 +152,7 @@ namespace globalInputs
{ {
Screen::get()->decWindowSize(); Screen::get()->decWindowSize();
const std::string size = std::to_string(options.video.window.size); const std::string size = std::to_string(options.video.window.size);
Notifier::get()->showText({"Window size x" + size}); Notifier::get()->show({"Window size x" + size});
return; return;
} }
@@ -137,7 +161,7 @@ namespace globalInputs
{ {
Screen::get()->incWindowSize(); Screen::get()->incWindowSize();
const std::string size = std::to_string(options.video.window.size); const std::string size = std::to_string(options.video.window.size);
Notifier::get()->showText({"Window size x" + size}); Notifier::get()->show({"Window size x" + size});
return; return;
} }
#endif #endif
@@ -162,6 +186,13 @@ namespace globalInputs
return; return;
} }
// Autofire
if (Input::get()->checkInput(InputType::AUTO_FIRE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
toggleFireMode();
return;
}
// Idioma // Idioma
if (Input::get()->checkInput(InputType::CHANGE_LANG, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD)) if (Input::get()->checkInput(InputType::CHANGE_LANG, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{ {

View File

@@ -1,4 +1,3 @@
#include <vector>
namespace globalInputs namespace globalInputs
{ {
extern int service_pressed_counter; extern int service_pressed_counter;

View File

@@ -4,22 +4,28 @@
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks #include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED #include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <stdlib.h> // Para rand
#include <algorithm> // Para max #include <algorithm> // Para max
#include <functional> // Para function
#include <vector> // Para vector #include <vector> // Para vector
#include "background.h" // Para Background #include "background.h" // Para Background
#include "fade.h" // Para Fade, FadeMode, FadeType #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 "input.h" // Para Input
#include "jail_audio.h" // Para JA_GetMusicState, JA_Music_state #include "jail_audio.h" // Para JA_GetMusicState, JA_Music_state
#include "lang.h" // Para getText #include "lang.h" // Para getText
#include "manage_hiscore_table.h" // Para HiScoreEntry #include "manage_hiscore_table.h" // Para HiScoreEntry
#include "global_events.h" // Para handleEvent
#include "options.h" // Para Options, OptionsGame, options #include "options.h" // Para Options, OptionsGame, options
#include "param.h" // Para Param, param, ParamGame, ParamFade #include "param.h" // Para Param, param, ParamGame, ParamFade
#include "path_sprite.h" // Para PathSprite, Path, PathType
#include "resource.h" // Para Resource #include "resource.h" // Para Resource
#include "screen.h" // Para Screen #include "screen.h" // Para Screen
#include "section.h" // Para Name, name, Options, options #include "section.h" // Para Name, name, Options, options, Attr...
#include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW #include "sprite.h" // Para Sprite
#include "utils.h" // Para Color, Zone, fade_color, orange_color #include "text.h" // Para Text, TEXT_COLOR, TEXT_SHADOW
#include "texture.h" // Para Texture
#include "utils.h" // Para Color, easeOutQuint, fade_color
// Constructor // Constructor
HiScoreTable::HiScoreTable() HiScoreTable::HiScoreTable()
@@ -27,35 +33,26 @@ HiScoreTable::HiScoreTable()
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
fade_(std::make_unique<Fade>()), fade_(std::make_unique<Fade>()),
background_(std::make_unique<Background>()), background_(std::make_unique<Background>()),
text_(Resource::get()->getText("smb2")),
counter_(0), counter_(0),
ticks_(0), ticks_(0),
view_area_({0, 0, param.game.width, param.game.height}), 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; section::name = section::Name::HI_SCORE_TABLE;
// Inicializa objetos
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
background_->setPos(param.game.game_area.rect); initFade();
background_->setCloudsSpeed(-0.1f); initBackground();
background_->setGradientNumber(1); iniEntryColors();
background_->setTransition(0.8f); createSprites();
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();
} }
// Destructor // Destructor
HiScoreTable::~HiScoreTable() HiScoreTable::~HiScoreTable()
{ {
SDL_DestroyTexture(backbuffer_); SDL_DestroyTexture(backbuffer_);
options.game.clear_last_hi_score_entries();
} }
// Actualiza las variables // Actualiza las variables
@@ -74,6 +71,9 @@ void HiScoreTable::update()
JA_PlayMusic(Resource::get()->getMusic("title.ogg")); JA_PlayMusic(Resource::get()->getMusic("title.ogg"));
} }
// Actualiza las posiciones de los sprites de texto
updateSprites();
// Actualiza el objeto screen // Actualiza el objeto screen
Screen::get()->update(); Screen::get()->update();
@@ -91,7 +91,7 @@ void HiScoreTable::update()
if (counter_ == 150) if (counter_ == 150)
{ {
background_->setColor(Color(0, 0, 0)); background_->setColor(background_fade_color_.darken());
background_->setAlpha(96); background_->setAlpha(96);
} }
@@ -99,19 +99,15 @@ void HiScoreTable::update()
{ {
fade_->activate(); 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() 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 // Pinta en el backbuffer el texto y los sprites
auto temp = SDL_GetRenderTarget(renderer_); auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, backbuffer_); SDL_SetRenderTarget(renderer_, backbuffer_);
@@ -119,22 +115,12 @@ void HiScoreTable::fillTexture()
SDL_RenderClear(renderer_); SDL_RenderClear(renderer_);
// Escribe el texto: Mejores puntuaciones // 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 // 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(); entry->render();
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);
} }
// Cambia el destino de renderizado // Cambia el destino de renderizado
@@ -163,39 +149,16 @@ void HiScoreTable::render()
fade_->render(); fade_->render();
// Vuelca el contenido del renderizador en pantalla // 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 // Comprueba los eventos
void HiScoreTable::checkEvents() void HiScoreTable::checkEvents()
{ {
// Comprueba los eventos que hay en la cola
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
// Evento de salida de la aplicación globalEvents::check(event);
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
// Comprueba si se ha cambiado el tamaño de la ventana
else if (event.type == SDL_WINDOWEVENT)
{
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
reloadTextures();
}
}
} }
} }
@@ -205,9 +168,10 @@ void HiScoreTable::checkInput()
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar) // Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
if (Input::get()->checkAnyButtonPressed()) if (Input::get()->checkAnyButtonPressed())
{ {
JA_StopMusic(); // JA_StopMusic();
section::name = section::Name::TITLE; section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1; section::options = section::Options::TITLE_1;
section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
return; return;
} }
@@ -268,3 +232,212 @@ std::string HiScoreTable::format(int number)
return result; 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);
}
}
}

View File

@@ -1,14 +1,18 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // para SDL_Rect #include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // Para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // para Uint16, Uint32, Uint8 #include <SDL2/SDL_stdinc.h> // Para Uint16, Uint32, Uint8
#include <memory> // para unique_ptr #include <memory> // Para unique_ptr, shared_ptr
#include <string> // para string #include <string> // Para string
class Background; // lines 8-8 #include <vector> // Para vector
class Fade; // lines 9-9 #include "utils.h"
class Text; // lines 10-10 class Background; // lines 10-10
enum class FadeMode : Uint8; // lines 11-11 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 Esta clase gestiona un estado del programa. Se encarga de mostrar la tabla con las puntuaciones
@@ -33,13 +37,17 @@ private:
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
std::shared_ptr<Text> text_; // Objeto para escribir texto 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 // Variables
Uint16 counter_; // Contador Uint16 counter_ = 0; // Contador
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla
FadeMode fade_mode_; // Modo de fade a utilizar 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 // Actualiza las variables
void update(); void update();
@@ -56,15 +64,33 @@ private:
// Convierte un entero a un string con separadores de miles // Convierte un entero a un string con separadores de miles
std::string format(int number); std::string format(int number);
// Crea el contenido de la textura con la lista de puntuaciones // Dibuja los sprites en la textura
void fillTexture(); void fillTexture();
// Recarga todas las texturas
void reloadTextures();
// Gestiona el fade // Gestiona el fade
void updateFade(); 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: public:
// Constructor // Constructor
HiScoreTable(); HiScoreTable();

View File

@@ -9,22 +9,22 @@
#include <unordered_map> // Para unordered_map, operator==, _Node_cons... #include <unordered_map> // Para unordered_map, operator==, _Node_cons...
#include <utility> // Para pair #include <utility> // Para pair
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // [SINGLETON]
Input *Input::input_ = nullptr; Input *Input::input_ = nullptr;
// [SINGLETON] Crearemos el objeto input con esta función estática // [SINGLETON] Crearemos el objeto con esta función estática
void Input::init(const std::string &game_controller_db_path) void Input::init(const std::string &game_controller_db_path)
{ {
Input::input_ = new Input(game_controller_db_path); Input::input_ = new Input(game_controller_db_path);
} }
// [SINGLETON] Destruiremos el objeto input con esta función estática // [SINGLETON] Destruiremos el objeto con esta función estática
void Input::destroy() void Input::destroy()
{ {
delete Input::input_; delete Input::input_;
} }
// [SINGLETON] Con este método obtenemos el objeto input y podemos trabajar con él // [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
Input *Input::get() Input *Input::get()
{ {
return Input::input_; return Input::input_;
@@ -110,9 +110,11 @@ bool Input::checkInput(InputType input, bool repeat, InputDeviceToUse device, in
} }
if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_) if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_)
{
if ((device == InputDeviceToUse::CONTROLLER) || (device == InputDeviceToUse::ANY)) if ((device == InputDeviceToUse::CONTROLLER) || (device == InputDeviceToUse::ANY))
{ {
success_controller = checkAxisInput(input, controller_index); success_controller = checkAxisInput(input, controller_index, repeat);
if (!success_controller) if (!success_controller)
{ {
if (repeat) if (repeat)
@@ -144,6 +146,7 @@ bool Input::checkInput(InputType input, bool repeat, InputDeviceToUse device, in
} }
} }
} }
}
return (success_keyboard || success_controller); return (success_keyboard || success_controller);
} }
@@ -245,7 +248,15 @@ bool Input::discoverGameControllers()
} }
std::cout << "\n** LOOKING FOR GAME CONTROLLERS" << std::endl; std::cout << "\n** LOOKING FOR GAME CONTROLLERS" << std::endl;
if (num_joysticks_ != num_gamepads_)
{
std::cout << "Joysticks found: " << num_joysticks_ << std::endl;
std::cout << "Gamepads found : " << num_gamepads_ << std::endl; std::cout << "Gamepads found : " << num_gamepads_ << std::endl;
}
else
{
std::cout << "Gamepads found: " << num_gamepads_ << std::endl;
}
if (num_gamepads_ > 0) if (num_gamepads_ > 0)
{ {
@@ -371,19 +382,53 @@ InputType Input::to_inputs_e(const std::string &name) const
} }
// Comprueba el eje del mando // 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) switch (input)
{ {
case InputType::LEFT: 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: 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: 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: 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: default:
return false; 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;
}
} }

View File

@@ -44,6 +44,7 @@ enum class InputType : int
SHOWINFO, SHOWINFO,
CONFIG, CONFIG,
SWAP_CONTROLLERS, SWAP_CONTROLLERS,
AUTO_FIRE,
// Input obligatorio // Input obligatorio
NONE, NONE,
@@ -63,7 +64,7 @@ enum class InputDeviceToUse : int
class Input class Input
{ {
private: private:
// [SINGLETON] Objeto screen privado para Don Melitón // [SINGLETON] Objeto privado
static Input *input_; static Input *input_;
struct KeyBindings struct KeyBindings
@@ -80,10 +81,11 @@ private:
{ {
SDL_GameControllerButton button; // GameControllerButton asociado SDL_GameControllerButton button; // GameControllerButton asociado
bool active; // Indica si está activo bool active; // Indica si está activo
bool axis_active; // Estado del eje
// Constructor // Constructor
explicit ControllerBindings(SDL_GameControllerButton btn = SDL_CONTROLLER_BUTTON_INVALID, bool act = false) explicit ControllerBindings(SDL_GameControllerButton btn = SDL_CONTROLLER_BUTTON_INVALID, bool act = false, bool axis_act = false)
: button(btn), active(act) {} : button(btn), active(act), axis_active(axis_act) {}
}; };
// Variables // Variables
@@ -98,7 +100,7 @@ private:
std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt
// Comprueba el eje del mando // Comprueba el eje del mando
bool checkAxisInput(InputType input, int controller_index = 0) const; bool checkAxisInput(InputType input, int controller_index, bool repeat);
// Constructor // Constructor
explicit Input(const std::string &game_controller_db_path); explicit Input(const std::string &game_controller_db_path);
@@ -107,13 +109,13 @@ private:
~Input() = default; ~Input() = default;
public: public:
// [SINGLETON] Crearemos el objeto screen con esta función estática // [SINGLETON] Crearemos el objeto con esta función estática
static void init(const std::string &game_controller_db_path); static void init(const std::string &game_controller_db_path);
// [SINGLETON] Destruiremos el objeto screen con esta función estática // [SINGLETON] Destruiremos el objeto con esta función estática
static void destroy(); static void destroy();
// [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él // [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
static Input *get(); static Input *get();
// Asigna inputs a teclas // Asigna inputs a teclas

View File

@@ -20,6 +20,11 @@
#include "texture.h" // Para Texture #include "texture.h" // Para Texture
#include "tiled_bg.h" // Para TiledBG, TiledBGMode #include "tiled_bg.h" // Para TiledBG, TiledBGMode
#include "utils.h" // Para Color, shdw_txt_color, Zone, no_color #include "utils.h" // Para Color, shdw_txt_color, Zone, no_color
#include "global_events.h"
#include <SDL2/SDL.h>
#include <vector>
#include <cmath>
// Constructor // Constructor
Instructions::Instructions() Instructions::Instructions()
@@ -41,10 +46,13 @@ Instructions::Instructions()
// Inicializa objetos // Inicializa objetos
fade_->setColor(fade_color.r, fade_color.g, fade_color.b); fade_->setColor(fade_color.r, fade_color.g, fade_color.b);
fade_->setType(FadeType::FULLSCREEN); fade_->setType(FadeType::FULLSCREEN);
fade_->setPost(param.fade.post_duration); fade_->setPostDuration(param.fade.post_duration);
fade_->setMode(FadeMode::IN); fade_->setMode(FadeMode::IN);
fade_->activate(); fade_->activate();
// Inicializa las líneas con un retraso progresivo de 50 ms
lines_ = initializeLines(256);
// Rellena la textura de texto // Rellena la textura de texto
fillTexture(); 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); 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 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 * 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 * 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); text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 2, lang::getText(19), shdw_txt_color);
@@ -225,14 +232,36 @@ void Instructions::update()
// Actualiza los sprites // Actualiza los sprites
updateSprites(); 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 // Actualiza el mosaico de fondo
tiled_bg_->update(); tiled_bg_->update();
// Actualiza el objeto "fade" // Actualiza el objeto "fade"
fade_->update(); fade_->update();
// Rellena el backbuffer
fillBackbuffer();
// Comprueba si el contador ha llegado al final // Comprueba si el contador ha llegado al final
if (counter_ == counter_end_) if (all_lines_off_screen_)
{ {
section::name = section::Name::TITLE; section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1; section::options = section::Options::TITLE_1;
@@ -243,9 +272,6 @@ void Instructions::update()
// Pinta en pantalla // Pinta en pantalla
void Instructions::render() void Instructions::render()
{ {
// Rellena el backbuffer
fillBackbuffer();
// Prepara para empezar a dibujar en la textura de juego // Prepara para empezar a dibujar en la textura de juego
Screen::get()->start(); Screen::get()->start();
@@ -255,52 +281,25 @@ void Instructions::render()
// Dibuja el mosacico de fondo // Dibuja el mosacico de fondo
tiled_bg_->render(); 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 // Copia la textura y el backbuffer al renderizador
if (view_.y == 0)
renderLines(renderer_, backbuffer_, lines_);
else
SDL_RenderCopy(renderer_, backbuffer_, nullptr, &view_); SDL_RenderCopy(renderer_, backbuffer_, nullptr, &view_);
fade_->render(); fade_->render();
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
Screen::get()->blit(); Screen::get()->render();
}
// Recarga todas las texturas
void Instructions::reloadTextures()
{
for (auto &texture : item_textures_)
{
texture->reLoad();
}
text_->reLoadTexture();
fillTexture();
} }
// Comprueba los eventos // Comprueba los eventos
void Instructions::checkEvents() void Instructions::checkEvents()
{ {
// Comprueba los eventos que hay en la cola
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
// Evento de salida de la aplicación globalEvents::check(event);
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
// Comprueba si se ha cambiado el tamaño de la ventana
else if (event.type == SDL_WINDOWEVENT)
{
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
reloadTextures();
}
}
} }
} }
@@ -310,9 +309,10 @@ void Instructions::checkInput()
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar) // Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
if (Input::get()->checkAnyButtonPressed()) if (Input::get()->checkAnyButtonPressed())
{ {
JA_StopMusic(); // JA_StopMusic();
section::name = section::Name::TITLE; section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1; section::options = section::Options::TITLE_1;
section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
return; return;
} }
@@ -331,3 +331,60 @@ void Instructions::run()
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);
}
}

View File

@@ -24,6 +24,19 @@ class TiledBG; // lines 12-12
por la pantalla sobre el mosaico de fondo (gestionado por el correspondiente objeto) 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 // Clase Instructions
class Instructions class Instructions
{ {
@@ -40,12 +53,15 @@ private:
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
// Variables // Variables
int counter_ = 0; // Contador int counter_ = 0; // Contador para manejar el progreso en la pantalla de instrucciones
int counter_end_ = 700; // Valor final para el contador
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa 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_Rect view_; // Vista del backbuffer que se va a mostrar por pantalla
SDL_Point sprite_pos_ = {0, 0}; // Posición del primer sprite SDL_Point sprite_pos_ = {0, 0}; // Posición del primer sprite en la lista
int item_space_ = 2; // Espacio entre los items 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 // Actualiza las variables
void update(); void update();
@@ -71,8 +87,14 @@ private:
// Actualiza los sprites // Actualiza los sprites
void updateSprites(); void updateSprites();
// Recarga todas las texturas // Método para inicializar las líneas
void reloadTextures(); 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: public:
// Constructor // Constructor

View File

@@ -16,166 +16,147 @@
#include "texture.h" // Para Texture #include "texture.h" // Para Texture
#include "utils.h" // Para Zone, BLOCK, Color, bg_color #include "utils.h" // Para Zone, BLOCK, Color, bg_color
#include "writer.h" // Para Writer #include "writer.h" // Para Writer
#include "global_events.h"
#include <array>
// Constructor // Constructor
Intro::Intro() Intro::Intro()
: texture_(Resource::get()->getTexture("intro.png")),
text_(Resource::get()->getText("nokia"))
{ {
// Inicializa variables // Inicializa variables
section::name = section::Name::INTRO; section::name = section::Name::INTRO;
section::options = section::Options::NONE; section::options = section::Options::NONE;
const std::array<std::string, 6> BITMAP_LIST = {
"intro1.png",
"intro2.png",
"intro3.png",
"intro4.png",
"intro5.png",
"intro6.png"};
auto texture = Resource::get()->getTexture(BITMAP_LIST.front());
const int BITMAP_WIDTH = texture->getWidth();
const int BITMAP_HEIGHT = texture->getHeight();
// Inicializa los bitmaps de la intro // Inicializa los bitmaps de la intro
constexpr int totalBitmaps = 6; constexpr int TOTAL_BITMAPS = 6;
for (int i = 0; i < totalBitmaps; ++i) for (int i = 0; i < TOTAL_BITMAPS; ++i)
{ {
auto ss = std::make_unique<SmartSprite>(texture_); auto ss = std::make_unique<SmartSprite>(Resource::get()->getTexture(BITMAP_LIST.at(i)));
ss->setWidth(128); ss->setWidth(BITMAP_WIDTH);
ss->setHeight(96); ss->setHeight(BITMAP_HEIGHT);
ss->setSpriteClip(0, 0, BITMAP_WIDTH, BITMAP_HEIGHT);
ss->setFinishedCounter(20); ss->setFinishedCounter(20);
ss->setDestX(param.game.game_area.center_x - 64); ss->setDestX(param.game.game_area.center_x - (BITMAP_WIDTH / 2));
ss->setDestY(param.game.game_area.first_quarter_y - 24); ss->setDestY(param.game.game_area.first_quarter_y - (BITMAP_HEIGHT / 4));
bitmaps_.push_back(std::move(ss)); bitmaps_.push_back(std::move(ss));
} }
bitmaps_[0]->setPosX(-128); bitmaps_.at(0)->setPosX(-BITMAP_WIDTH);
bitmaps_[0]->setPosY(param.game.game_area.first_quarter_y - 24); bitmaps_.at(0)->setPosY(param.game.game_area.first_quarter_y - (BITMAP_HEIGHT / 4));
bitmaps_[0]->setVelX(0.0f); bitmaps_.at(0)->setVelX(0.0f);
bitmaps_[0]->setVelY(0.0f); bitmaps_.at(0)->setVelY(0.0f);
bitmaps_[0]->setAccelX(0.6f); bitmaps_.at(0)->setAccelX(0.6f);
bitmaps_[0]->setAccelY(0.0f); bitmaps_.at(0)->setAccelY(0.0f);
bitmaps_[0]->setSpriteClip(0, 0, 128, 96);
bitmaps_[1]->setPosX(param.game.width); bitmaps_.at(1)->setPosX(param.game.width);
bitmaps_[1]->setPosY(param.game.game_area.first_quarter_y - 24); bitmaps_.at(1)->setPosY(param.game.game_area.first_quarter_y - (BITMAP_HEIGHT / 4));
bitmaps_[1]->setVelX(-1.0f); bitmaps_.at(1)->setVelX(-1.0f);
bitmaps_[1]->setVelY(0.0f); bitmaps_.at(1)->setVelY(0.0f);
bitmaps_[1]->setAccelX(-0.3f); bitmaps_.at(1)->setAccelX(-0.3f);
bitmaps_[1]->setAccelY(0.0f); bitmaps_.at(1)->setAccelY(0.0f);
bitmaps_[1]->setSpriteClip(128, 0, 128, 96);
bitmaps_[2]->setPosX(param.game.game_area.center_x - 64); bitmaps_.at(2)->setPosX(param.game.game_area.center_x - (BITMAP_WIDTH / 2));
bitmaps_[2]->setPosY(-96); bitmaps_.at(2)->setPosY(-BITMAP_HEIGHT);
bitmaps_[2]->setVelX(0.0f); bitmaps_.at(2)->setVelX(0.0f);
bitmaps_[2]->setVelY(3.0f); bitmaps_.at(2)->setVelY(3.0f);
bitmaps_[2]->setAccelX(0.1f); bitmaps_.at(2)->setAccelX(0.1f);
bitmaps_[2]->setAccelY(0.3f); bitmaps_.at(2)->setAccelY(0.3f);
bitmaps_[2]->setSpriteClip(0, 96, 128, 96); bitmaps_.at(2)->setFinishedCounter(250);
bitmaps_[2]->setFinishedCounter(250);
bitmaps_[3]->setPosX(param.game.game_area.center_x - 64); bitmaps_.at(3)->setPosX(param.game.game_area.center_x - (BITMAP_WIDTH / 2));
bitmaps_[3]->setPosY(param.game.height); bitmaps_.at(3)->setPosY(param.game.height);
bitmaps_[3]->setVelX(0.0f); bitmaps_.at(3)->setVelX(0.0f);
bitmaps_[3]->setVelY(-0.7f); bitmaps_.at(3)->setVelY(-0.7f);
bitmaps_[3]->setAccelX(0.0f); bitmaps_.at(3)->setAccelX(0.0f);
bitmaps_[3]->setAccelY(0.0f); bitmaps_.at(3)->setAccelY(0.0f);
bitmaps_[3]->setSpriteClip(128, 96, 128, 96);
bitmaps_[4]->setPosX(param.game.game_area.center_x - 64); bitmaps_.at(4)->setPosX(param.game.game_area.center_x - (BITMAP_WIDTH / 2));
bitmaps_[4]->setPosY(-96); bitmaps_.at(4)->setPosY(-BITMAP_HEIGHT);
bitmaps_[4]->setVelX(0.0f); bitmaps_.at(4)->setVelX(0.0f);
bitmaps_[4]->setVelY(3.0f); bitmaps_.at(4)->setVelY(3.0f);
bitmaps_[4]->setAccelX(0.1f); bitmaps_.at(4)->setAccelX(0.1f);
bitmaps_[4]->setAccelY(0.3f); bitmaps_.at(4)->setAccelY(0.3f);
bitmaps_[4]->setSpriteClip(0, 192, 128, 96);
bitmaps_[5]->setPosX(param.game.width); bitmaps_.at(5)->setPosX(param.game.width);
bitmaps_[5]->setPosY(param.game.game_area.first_quarter_y - 24); bitmaps_.at(5)->setPosY(param.game.game_area.first_quarter_y - (BITMAP_HEIGHT / 4));
bitmaps_[5]->setVelX(-0.7f); bitmaps_.at(5)->setVelX(-0.7f);
bitmaps_[5]->setVelY(0.0f); bitmaps_.at(5)->setVelY(0.0f);
bitmaps_[5]->setAccelX(0.0f); bitmaps_.at(5)->setAccelX(0.0f);
bitmaps_[5]->setAccelY(0.0f); bitmaps_.at(5)->setAccelY(0.0f);
bitmaps_[5]->setSpriteClip(128, 192, 128, 96);
// Inicializa los textos de la intro // Inicializa los textos de la intro
constexpr int totalTexts = 9; constexpr int TOTAL_TEXTS = 9;
for (int i = 0; i < totalTexts; ++i) for (int i = 0; i < TOTAL_TEXTS; ++i)
{ {
auto w = std::make_unique<Writer>(text_); auto w = std::make_unique<Writer>(Resource::get()->getText("04b_25_metal"));
w->setPosX(BLOCK * 0); w->setPosX(BLOCK * 0);
w->setPosY(param.game.height - (BLOCK * 6)); w->setPosY(param.game.height - (BLOCK * 6));
w->setKerning(-1); w->setKerning(-2);
w->setEnabled(false); w->setEnabled(false);
w->setFinishedCounter(180); w->setFinishedCounter(180);
texts_.push_back(std::move(w)); texts_.push_back(std::move(w));
} }
// Un dia qualsevol de l'any 2000 // Un dia qualsevol de l'any 2000
texts_[0]->setCaption(lang::getText(27)); texts_.at(0)->setCaption(lang::getText(27));
texts_[0]->setSpeed(8); texts_.at(0)->setSpeed(8);
// Tot esta tranquil a la UPV // Tot esta tranquil a la UPV
texts_[1]->setCaption(lang::getText(28)); texts_.at(1)->setCaption(lang::getText(28));
texts_[1]->setSpeed(8); texts_.at(1)->setSpeed(8);
// Fins que un desaprensiu... // Fins que un desaprensiu...
texts_[2]->setCaption(lang::getText(29)); texts_.at(2)->setCaption(lang::getText(29));
texts_[2]->setSpeed(12); texts_.at(2)->setSpeed(12);
// HEY! ME ANE A FERME UN CORTAET... // HEY! ME ANE A FERME UN CORTAET...
texts_[3]->setCaption(lang::getText(30)); texts_.at(3)->setCaption(lang::getText(30));
texts_[3]->setSpeed(8); texts_.at(3)->setSpeed(8);
// UAAAAAAAAAAAAA!!! // UAAAAAAAAAAAAA!!!
texts_[4]->setCaption(lang::getText(31)); texts_.at(4)->setCaption(lang::getText(31));
texts_[4]->setSpeed(1); texts_.at(4)->setSpeed(1);
// Espera un moment... // Espera un moment...
texts_[5]->setCaption(lang::getText(32)); texts_.at(5)->setCaption(lang::getText(32));
texts_[5]->setSpeed(16); texts_.at(5)->setSpeed(16);
// Si resulta que no tinc solt! // Si resulta que no tinc solt!
texts_[6]->setCaption(lang::getText(33)); texts_.at(6)->setCaption(lang::getText(33));
texts_[6]->setSpeed(2); texts_.at(6)->setSpeed(2);
// MERDA DE MAQUINA! // MERDA DE MAQUINA!
texts_[7]->setCaption(lang::getText(34)); texts_.at(7)->setCaption(lang::getText(34));
texts_[7]->setSpeed(3); texts_.at(7)->setSpeed(3);
// Blop... blop... blop... // Blop... blop... blop...
texts_[8]->setCaption(lang::getText(35)); texts_.at(8)->setCaption(lang::getText(35));
texts_[8]->setSpeed(16); texts_.at(8)->setSpeed(16);
for (auto &text : texts_) for (auto &text : texts_)
{
text->center(param.game.game_area.center_x); text->center(param.game.game_area.center_x);
} }
// Recarga todas las texturas
void Intro::reloadTextures()
{
texture_->reLoad();
text_->reLoadTexture();
} }
// Comprueba los eventos // Comprueba los eventos
void Intro::checkEvents() void Intro::checkEvents()
{ {
SDL_Event event; SDL_Event event;
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
switch (event.type) globalEvents::check(event);
{
case SDL_QUIT:
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
case SDL_WINDOWEVENT:
{
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
reloadTextures();
break;
}
default:
break;
}
} }
} }
@@ -409,14 +390,13 @@ void Intro::render()
} }
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
Screen::get()->blit(); Screen::get()->render();
} }
// Bucle principal // Bucle principal
void Intro::run() void Intro::run()
{ {
JA_PlayMusic(Resource::get()->getMusic("intro.ogg"), 0); JA_PlayMusic(Resource::get()->getMusic("intro.ogg"), 0);
while (section::name == section::Name::INTRO) while (section::name == section::Name::INTRO)
{ {
checkInput(); checkInput();

View File

@@ -18,9 +18,6 @@ class Intro
{ {
private: private:
// Objetos // Objetos
std::shared_ptr<Texture> texture_; // Textura con los graficos
std::shared_ptr<Text> text_; // Textos de la intro
std::vector<std::unique_ptr<SmartSprite>> bitmaps_; // Vector con los sprites inteligentes para los dibujos de la intro std::vector<std::unique_ptr<SmartSprite>> bitmaps_; // Vector con los sprites inteligentes para los dibujos de la intro
std::vector<std::unique_ptr<Writer>> texts_; // Textos de la intro std::vector<std::unique_ptr<Writer>> texts_; // Textos de la intro
@@ -43,9 +40,6 @@ private:
// Actualiza las escenas de la intro // Actualiza las escenas de la intro
void updateScenes(); void updateScenes();
// Recarga todas las texturas
void reloadTextures();
public: public:
// Constructor // Constructor
Intro(); Intro();

View File

@@ -14,10 +14,10 @@ Item::Item(ItemType type, float x, float y, SDL_Rect &play_area, std::shared_ptr
{ {
case ItemType::COFFEE_MACHINE: case ItemType::COFFEE_MACHINE:
{ {
width_ = 28; width_ = param.game.coffee_machine_w;
height_ = 37; height_ = param.game.coffee_machine_h;
pos_x_ = ((static_cast<int>(x) + (play_area.w / 2)) % (play_area.w - width_ - 5)) + 2; 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_x_ = 0.0f;
vel_y_ = -0.1f; vel_y_ = -0.1f;
accel_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: default:
{ {
width_ = 20; width_ = param.game.item_size;
height_ = 20; height_ = param.game.item_size;
pos_x_ = x; pos_x_ = x;
pos_y_ = y; pos_y_ = y;
vel_x_ = -1.0f + ((rand() % 5) * 0.5f); vel_x_ = -1.0f + ((rand() % 5) * 0.5f);

View File

@@ -22,8 +22,9 @@ enum class ItemType : int
PACMAR = 3, /**< Pacman */ PACMAR = 3, /**< Pacman */
CLOCK = 4, /**< Reloj */ CLOCK = 4, /**< Reloj */
COFFEE = 5, /**< Café */ COFFEE = 5, /**< Café */
COFFEE_MACHINE = 6,/**< Máquina de café */ DEBIAN = 6, /**< Debian */
NONE = 7, /**< Ninguno */ COFFEE_MACHINE = 7,/**< Máquina de café */
NONE = 8, /**< Ninguno */
}; };
/** /**

View File

@@ -1,12 +1,13 @@
#ifndef JA_USESDLMIXER #ifndef JA_USESDLMIXER
#include "jail_audio.h" #include "jail_audio.h"
#include <stdint.h> // para uint8_t #include <SDL2/SDL_rwops.h> // Para SDL_RWFromMem
#include <stdio.h> // para NULL, fseek, fclose, fopen, fread, ftell, FILE #include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <stdlib.h> // para free, malloc #include <stdint.h> // Para uint8_t, uint32_t
#include "stb_vorbis.c" // para stb_vorbis_decode_memory #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 struct JA_Sound_t
{ {
@@ -25,6 +26,7 @@ struct JA_Channel_t
struct JA_Music_t struct JA_Music_t
{ {
int samples{0}; int samples{0};
Uint32 length{0};
int pos{0}; int pos{0};
int times{0}; int times{0};
short *output{NULL}; short *output{NULL};
@@ -43,20 +45,43 @@ bool JA_musicEnabled = true;
bool JA_soundEnabled = true; bool JA_soundEnabled = true;
SDL_AudioDeviceID sdlAudioDevice = 0; 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) void audioCallback(void *userdata, uint8_t *stream, int len)
{ {
SDL_memset(stream, 0, len); SDL_memset(stream, 0, len);
if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING) if (current_music != NULL && current_music->state == JA_MUSIC_PLAYING)
{ {
const int size = SDL_min(len, current_music->samples * 2 - current_music->pos); int volume = JA_musicVolume;
SDL_MixAudioFormat(stream, (Uint8 *)(current_music->output + current_music->pos), AUDIO_S16, size, JA_musicVolume); if (fading)
current_music->pos += size / 2; {
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 (size < len)
{ {
if (current_music->times != 0) if (current_music->times != 0)
{ {
SDL_MixAudioFormat(stream + size, (Uint8 *)current_music->output, AUDIO_S16, len - size, JA_musicVolume); SDL_MixAudioFormat(stream + size, (Uint8 *)current_music->output, AUDIO_S16, len - size, volume);
current_music->pos = (len - size) / 2; current_music->pos = len - size;
if (current_music->times > 0) if (current_music->times > 0)
current_music->times--; current_music->times--;
} }
@@ -113,10 +138,36 @@ void JA_Quit()
sdlAudioDevice = 0; sdlAudioDevice = 0;
} }
JA_Music_t *JA_LoadMusic(const char *filename) JA_Music_t *JA_LoadMusic(Uint8 *buffer, Uint32 length)
{ {
int chan, samplerate; 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. // [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"); FILE *f = fopen(filename, "rb");
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
@@ -127,33 +178,16 @@ JA_Music_t *JA_LoadMusic(const char *filename)
return NULL; return NULL;
fclose(f); 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); 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; return music;
} }
void JA_PlayMusic(JA_Music_t *music, const int loop) void JA_PlayMusic(JA_Music_t *music, const int loop)
{ {
if (!JA_musicEnabled || !music) if (!JA_musicEnabled)
return; return;
if (current_music != NULL) if (current_music != NULL)
@@ -198,6 +232,19 @@ void JA_StopMusic()
current_music->state = JA_MUSIC_STOPPED; 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() JA_Music_state JA_GetMusicState()
{ {
if (!JA_musicEnabled) if (!JA_musicEnabled)
@@ -223,6 +270,20 @@ int JA_SetMusicVolume(int volume)
return JA_musicVolume; 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) void JA_EnableMusic(const bool value)
{ {
if (!value && current_music != NULL && current_music->state == JA_MUSIC_PLAYING) 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; 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 *JA_LoadSound(const char *filename)
{ {
JA_Sound_t *sound = new JA_Sound_t(); 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) int JA_PlaySound(JA_Sound_t *sound, const int loop)
{ {
if (!JA_soundEnabled || !sound) if (!JA_soundEnabled)
return 0; return -1;
int channel = 0; int channel = 0;
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) 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; 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) void JA_DeleteSound(JA_Sound_t *sound)
{ {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)

View File

@@ -1,9 +1,9 @@
#pragma once #pragma once
#include <SDL2/SDL_audio.h> // para SDL_AudioFormat #include <SDL2/SDL_audio.h> // Para SDL_AudioFormat
#include <SDL2/SDL_stdinc.h> // para Uint32, Uint8 #include <SDL2/SDL_stdinc.h> // Para Uint32, Uint8
struct JA_Music_t; // lines 5-5 struct JA_Music_t; // lines 4-4
struct JA_Sound_t; // lines 6-6 struct JA_Sound_t; // lines 5-5
enum JA_Channel_state enum JA_Channel_state
{ {
@@ -26,18 +26,24 @@ void JA_Init(const int freq, const SDL_AudioFormat format, const int channels);
void JA_Quit(); void JA_Quit();
JA_Music_t *JA_LoadMusic(const char *filename); 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_PlayMusic(JA_Music_t *music, const int loop = -1);
void JA_PauseMusic(); void JA_PauseMusic();
void JA_ResumeMusic(); void JA_ResumeMusic();
void JA_StopMusic(); void JA_StopMusic();
void JA_FadeOutMusic(const int milliseconds);
JA_Music_state JA_GetMusicState(); JA_Music_state JA_GetMusicState();
void JA_DeleteMusic(JA_Music_t *music); void JA_DeleteMusic(JA_Music_t *music);
int JA_SetMusicVolume(int volume); int JA_SetMusicVolume(int volume);
void JA_SetMusicPosition(float value);
float JA_GetMusicPosition();
void JA_EnableMusic(const bool value); void JA_EnableMusic(const bool value);
JA_Sound_t *JA_NewSound(Uint8 *buffer, Uint32 length); 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); JA_Sound_t *JA_LoadSound(const char *filename);
int JA_PlaySound(JA_Sound_t *sound, const int loop = 0); 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_PauseChannel(const int channel);
void JA_ResumeChannel(const int channel); void JA_ResumeChannel(const int channel);
void JA_StopChannel(const int channel); void JA_StopChannel(const int channel);

View File

@@ -1,5 +1,3 @@
#ifndef NO_SHADERS
#include "jail_shader.h" #include "jail_shader.h"
#include <SDL2/SDL_rect.h> // para SDL_Point #include <SDL2/SDL_rect.h> // para SDL_Point
#include <stdlib.h> // para NULL, free, malloc, exit #include <stdlib.h> // para NULL, free, malloc, exit
@@ -248,4 +246,3 @@ namespace shader
} }
} }
} }
#endif

Some files were not shown because too many files have changed in this diff Show More