Compare commits

116 Commits

Author SHA1 Message Date
e0e82ee273 Retocs en Texture::loadPaletteFromFile 2024-11-03 20:43:52 +01:00
371c477d0d Varios arreglos 2024-11-03 20:28:01 +01:00
f29eb2f411 Les notificacions ara accepten un vector de cadenes en lloc de una o dos cadenes 2024-11-03 18:12:46 +01:00
69a92cba66 Apanyats alguns bugs que quedaven respecte a lo del teclat 2024-11-03 17:25:31 +01:00
86cd7b0f16 Ja es pot gastar el teclat com a control independent del primer mando
Ja pot jugar un jugador amb teclat i altre amb mando
Es pot asignar el teclat a qualsevol dels dos jugadors
Continua podentse gastar mando i teclat a l'hora per al mateix jugador
2024-11-03 11:07:58 +01:00
a1ccb6102a Abans de clavar-li ma a Input 2024-11-01 20:01:17 +01:00
2dd8bbbbf7 Moguts els checkInputs de Screen a GlobalInputs 2024-11-01 19:07:19 +01:00
c66cc965f1 define_buttons ja acaba be de definir els buttons 2024-11-01 18:39:10 +01:00
0757f63b73 Eliminat checkModInput 2024-11-01 18:20:18 +01:00
80a110e1d7 Abans de llevar checkInputMod 2024-11-01 16:48:03 +01:00
cd68c5ffea Al redefinir botons, ja no pots repetir botó. Util per als qui tenim la ma tremolosa i apretem dos voltes sense voler 2024-11-01 14:32:27 +01:00
f786cb7776 Implementat el final del joc 2024-11-01 13:05:11 +01:00
2e0d27a95c Modificats parámetres 2024-11-01 12:56:09 +01:00
861a9411d3 Nous textos 2024-11-01 12:55:37 +01:00
da27fde366 Millores en la gestió del "mute" en el joc 2024-11-01 07:55:37 +01:00
c6e2368e82 Noves animacions per a deixar de disparar 2024-10-31 23:32:11 +01:00
30dfa4c545 Treballant en el final del joc 2024-10-31 11:58:01 +01:00
7e2691e33e Finalitzat el Attract Mode 2024-10-30 21:29:23 +01:00
7e918e99f7 Arreglat un include 2024-10-30 13:15:30 +01:00
2aa3f827cb Arreglada la animació de morir, que s'updatava dos voltes per frame 2024-10-30 10:15:53 +01:00
06899d95a8 Arreglat el efecte de flash. Estava passant-li un valor massa xicotet 2024-10-30 09:45:57 +01:00
20c51d0796 Acabat el nou motor per a textos en pantalla 2024-10-30 09:25:28 +01:00
b43782786a Modificades les linux_utils 2024-10-30 09:25:12 +01:00
15554c449f Nuevos textos para el game_text 2024-10-30 08:19:32 +01:00
ba05eab79e Reduida la dependencia de PathSprite a Sprite
Treballant en els missatges de text que ixen durant la partida
2024-10-29 20:05:05 +01:00
d83c05bad4 El game_text dels items ja son textures generades i precarregades 2024-10-29 16:04:14 +01:00
e2abf835f9 Afegida nova tipografia 04b_25
Eliminades tipografies que no s'utilitzaven
La classe Text ara pot tornar una textura amb el text
2024-10-29 15:22:19 +01:00
59e2865a4a El game_text ara gasta PathSprites en lloc d'SmartSprites
fix: la paleta dels jugadors no s'iniciava correctament
2024-10-28 22:09:28 +01:00
787cb6366f Pasaeta de include-what-you-use
Acabada de perfilar la classe PathSprite
Menjeades declaracions de utils.h als fitxers que toca
2024-10-28 20:45:24 +01:00
0fe371653a commit de me ane cap a casa 2024-10-28 13:51:26 +01:00
2cffe8dfc9 Merge branch 'main' of https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis_arcade_edition 2024-10-27 22:28:47 +01:00
1dd96cfaff Completada la classe PathSprite 2024-10-27 22:28:44 +01:00
d054e188b6 fix: alguns minibugs tontos 2024-10-27 19:04:05 +01:00
ca6ff71a46 Actualitzat README.MD 2024-10-27 18:46:42 +01:00
b90ac65cfc Eliminats warnings que nomes es veuen al compilar en macos/linux 2024-10-27 17:45:49 +01:00
759adbf6fd Actualitzat README.MD 2024-10-27 17:09:40 +01:00
71f76fda05 Redissenyat el time stopper 2024-10-27 13:36:00 +01:00
ddfb3672ea Afegida la funció createTwoBigBalloons() per a que la partida sempre comence igual 2024-10-26 18:16:23 +02:00
6235d0b684 Revisada la classe Balloon 2024-10-26 18:08:04 +02:00
f750997b34 Revisant la classe Balloon 2024-10-26 14:13:08 +02:00
de2a29b669 Ajustado el game_text para que se dibuje siempre en pantalla, sin clipping 2024-10-26 12:23:04 +02:00
f99f908c11 Revisant la classe Balloon 2024-10-26 11:38:08 +02:00
d44bfd51de Balloon: inicialitzades variables en la declaració 2024-10-26 09:09:19 +02:00
4f095ab018 Repasada la classe Bullet 2024-10-26 09:01:32 +02:00
bffd2bdace . 2024-10-26 08:11:30 +02:00
24d09a2e3c Millorada la aparició dels game_text 2024-10-24 22:16:57 +02:00
caf191672e Posat ordre en el constructor de Game 2024-10-24 22:08:53 +02:00
43e7b83403 Continue arreglant cosetes amb cppcheck 2024-10-24 20:36:30 +02:00
a5c72a0f65 Collons, que m'havien stagejat no se que.. ara si, arreglada la carrega d'animacions 2024-10-24 19:58:45 +02:00
ca464b2e81 Arreglada la cárrega d'animacions 2024-10-24 19:58:25 +02:00
f26ecbd969 Canviat el final de linea als scripts de linux 2024-10-24 18:14:33 +02:00
018bb68f9a Canviat el nom de la carpeta a linux_utils 2024-10-24 17:59:50 +02:00
f36ff3d7fe Actualitzats scripts de linux_utils 2024-10-24 17:53:24 +02:00
8f33308f8d . 2024-10-24 14:03:12 +02:00
8c98430b68 . 2024-10-23 22:18:46 +02:00
6e2f80d8ce . 2024-10-23 18:29:52 +02:00
95478134dd Merdetes en la faena, básicament arreglar uns quants iniciadors de variables en les clases 2024-10-23 14:00:19 +02:00
528533fd9b Au, a casa 2024-10-22 13:56:50 +02:00
5df85e1b1a Pasaeta de cppcheck, ale 2024-10-22 09:24:19 +02:00
1d0c2e01a5 Varios arreglos d'estil en el codi i llevar metodes que ja no servien 2024-10-21 22:47:00 +02:00
236d6f58b6 Nous gràfics per al game_text 2024-10-21 19:29:54 +02:00
898b551e06 Paletes noves per al primer café dels jugadors 2024-10-21 18:09:34 +02:00
84238032e0 Afegits uns overrides pa agafar parametres per linea de comandos 2024-10-21 17:46:05 +02:00
2cb22ed013 fix: els globos tenien un parell de setters mal asignats per culpa de buscar y reemplazar
fix: els globos verds s'inicialitzaven amb vy = 0 per gastar abs en lloc de fabs
fix: corregit un bug milenari que de sempre havia creat els balloons verds al popar al pare amb la meitat de velocitat en y. Lo que jo no se es com anava res. Supose que ara el joc serà un poc mes xungo. Quan rebotaven en el piso ja se'ls posava la velocitat bona (crec)
2024-10-20 22:58:15 +02:00
a3a583deb7 Precàrrega dels fitxers amb dades per al mode demostració 2024-10-20 21:23:04 +02:00
b263e0c4be Modificada la estructura on es guarden els datos de la demo 2024-10-20 20:43:03 +02:00
3bf61fc758 fix: no guardar el fitxer de puntuacions en el modo demo 2024-10-20 19:40:09 +02:00
2377815c02 Amb les textures en memoria i compartides ja no puc fer el trick de canvi de paleta per a la flama del segon jugador tal i com està plantejat el codi. Arreglat creant una segona textura 2024-10-20 19:38:28 +02:00
7434869894 Corregit un fallo amagat baix un ifdef ARCADE. Ja he posat que estiga definit per defecte pa que no torne a passar 2024-10-20 15:43:10 +02:00
848d61b5c0 He fet un "manolete" i he pasat a c++ i smartpointers la cárrega de surfaces desde gif. Sembla que no ha petat res
Precárrega i asignació de paletes a les textures
Ara si algú toca una paleta, que siga conscient que la textura es compartida durant tot el joc
2024-10-20 15:36:04 +02:00
cbc9b3f071 Eliminats els últimes defines i passats a enum class 2024-10-20 12:07:55 +02:00
8bca5095da Modificats, estructurats i ben formatats alguns missatges de consola
Canvis en els codis d'eixida del programa
2024-10-20 11:37:26 +02:00
a4b4e188cd Precàrrega de tots els recursos al inici del joc
8.000.000 de cherrypickings que he anat fent pel codi
2024-10-20 11:06:10 +02:00
f23dcae5b6 Creada la classe Resource
Afegida la musica i els sons a Resource
2024-10-19 10:07:14 +02:00
b879673bc2 Mes merdes que faltaven del merge 2024-10-18 17:10:06 +02:00
a8701dbebc Merge branch 'main' of https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis_arcade_edition 2024-10-18 16:53:53 +02:00
afe835914e Revisada la carrega de recursos en game.cpp 2024-10-18 14:07:25 +02:00
808f1595e9 Treballant en la càrrega de animacions desde fitxers 2024-10-17 21:02:28 +02:00
8e8346b2ab Li he demanat a la IA que revente Game::checkInput() que aixo si que era un monstruo amb sombreret i pajarita 2024-10-17 20:05:26 +02:00
1da8f33a5e Llevats tots els ifdef VERBOSE i redirigit cout a null_stream 2024-10-17 19:31:44 +02:00
50a376e582 Comença a estar tot mes o menos be el desaguisao de les classes Sprite. Encara algunes animacions sembla que van massa ràpides 2024-10-17 19:26:39 +02:00
59de566c5b commit de acabar la jornada laboral 2024-10-17 13:57:41 +02:00
db884cb422 Commit de vesprà tirada a la brossa 2024-10-16 22:35:19 +02:00
5585f996cb A vore si el helper ja funciona com toca 2024-10-16 13:29:16 +02:00
24556eeaa8 Implementat contador per a posar el nom al acabar la partida 2024-10-16 09:18:22 +02:00
dbffda491f Retocat l'aspecte visual de les notificacions 2024-10-15 22:56:24 +02:00
53f5f3f8b0 Ja comprova la notificació d'eixir per diferenciarla de la resta
En ARCADE la notificació diferencia si vas a eixir o a apagar el sistema
2024-10-15 20:40:45 +02:00
e0faa0890e Afegides noves cadenes de text 2024-10-15 20:12:16 +02:00
de6508c37c Don Melitonitzada la classe Notifier e independitzada de la classe Screen
Ara es poden afegir codis a les notificacions per identificarles
2024-10-15 20:09:09 +02:00
e99c2c5265 fix: faltava el nom de la classe en shutdownSystem() 2024-10-15 18:58:10 +02:00
942924c65c Afegit codi per apagar el sistema al eixir del joc 2024-10-15 18:24:19 +02:00
089da99b5b Afegida la funció getNewPosition a la classe Screen per a respectar la posició de la finestra al canviarla de tamany 2024-10-15 18:12:16 +02:00
3fdd60c9e2 Treballant en els game_texts 2024-10-15 14:02:37 +02:00
3b9885ab03 Commit de Boromir 2024-10-14 22:33:45 +02:00
39a8c992e1 Ja duplica la ultima lletra al posar el nom 2024-10-14 17:12:07 +02:00
9825c7fb9b Pasaeta de include-what-you-use 2024-10-13 21:58:36 +02:00
d0a6e4c572 Afegits destructors virtuals en les classes Sprite 2024-10-13 21:23:15 +02:00
7c876e1d4d Acabat amb cppcheck
Arreglades les herencies de les classes Sprite
2024-10-13 21:00:33 +02:00
809c10048e Commit pa poder tornar a passar el cppcheck 2024-10-13 19:39:43 +02:00
babf02226c Mes recomanacions de cppcheck 2024-10-13 19:26:27 +02:00
46540ad7c3 Optimitzat el tema de comparacions i asignacions de strings buits. Mes que optimitzat, ara està mes mono 2024-10-13 14:25:05 +02:00
ba7c44ad06 Actualitzat Makefile 2024-10-13 14:24:15 +02:00
46b19ee82f Mes recomanacions de cppcheck aplicades
Abans de tocar unes cosetes de strings buits
2024-10-13 13:49:00 +02:00
b2122ac239 Eliminats fitxers que s'havien colat 2024-10-13 11:04:50 +02:00
c11a868289 Afegides recomanacions de cppcheck
Optimitzada la funció updateBalloonSpeed() i eliminades funcions sobrants o redundants
2024-10-13 11:03:50 +02:00
22d457285d Modificat .gitignore 2024-10-13 11:03:00 +02:00
b060f21696 Arreglades les herencies de Sprite
Abans de llevar mil coses que sobren i replantejar-se estes 4 classes
2024-10-13 10:01:07 +02:00
33ea8d90ca Acabat de renamar, encara que he descobert cosetes i tindré que fer altra pasaeta
Actualitzat stb_image.h a la última versió
2024-10-12 22:25:43 +02:00
cce14dba4d Mes renames. Mes ordre. 2024-10-12 12:03:19 +02:00
101e375fd3 Variables renombrades en input.cpp 2024-10-12 11:01:42 +02:00
4ef759772a game.cpp renombrat 2024-10-12 09:15:20 +02:00
07714aabc3 Abans de renombrar game.cpp 2024-10-12 07:26:41 +02:00
d50cf23721 Abans de renombrar player.cpp 2024-10-11 21:58:59 +02:00
3a6950f3a4 Menudo puto lio de renamar coses, a vore si tot va quedant al lloc que els structs i els enums estan revolant i duplicats per tots llocs 2024-10-11 20:12:50 +02:00
a9ca23138d Continuem estandaritzant noms 2024-10-11 13:54:43 +02:00
e1fa1d2102 Canviades certes opcions a parametres i afegides noves opcions 2024-10-11 09:03:57 +02:00
139 changed files with 13601 additions and 13987 deletions

1
.gitignore vendored
View File

@@ -15,3 +15,4 @@ thumbs.db
*score.bin *score.bin
coffee_crisis* coffee_crisis*
debug.txt debug.txt
cppcheck-result*

View File

@@ -25,8 +25,8 @@ INCLUDES:= -I$(DIR_SOURCES)
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
FixPath = $(subst /,\,$1) FixPath = $(subst /,\,$1)
SOURCES := source/*.cpp SOURCES := source/*.cpp
CXXFLAGS:= -std=c++14 -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++14 -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 MKD:= mkdir
@@ -34,8 +34,8 @@ else
FixPath = $1 FixPath = $1
SOURCES := $(shell find $(DIR_SOURCES) -name '*.cpp') SOURCES := $(shell find $(DIR_SOURCES) -name '*.cpp')
SOURCES := source/*.cpp SOURCES := source/*.cpp
CXXFLAGS:= -std=c++14 -Wall -Os -ffunction-sections -fdata-sections CXXFLAGS:= -std=c++20 -Wall -Os -ffunction-sections -fdata-sections
CXXFLAGS_DEBUG:= -std=c++14 -Wall -g CXXFLAGS_DEBUG:= -std=c++20 -Wall -g
LDFLAGS := -lSDL2 LDFLAGS := -lSDL2
RM = rm -f RM = rm -f
MKD:= mkdir -p MKD:= mkdir -p

View File

@@ -1,67 +1,39 @@
# Coffee Crisis # Coffee Crisis Arcade Edition
Coffee Crisis es un juego arcade que pondrá a prueba tus reflejos. Empezado durante el verano de 2020 y terminado un año despues, en el verano de 2021. Intenta conseguir todos los puntos que puedas con una sola vida a traves de los 10 niveles de juego y ayuda a Bal1 a defender la UPV de la invasión de la cafeína esférica y saltarina. 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.
![alt text](https://php.sustancia.synology.me/images/cc1.png) <p align="center">
<img src="https://php.sustancia.synology.me/images/ccae_title.png" alt="Titol"
</p>
## Teclado ## Controls
El juego se maneja con teclado, aunque tambien se puede conectar un mando de control. El joc està optimitzat per a ser jugat amb un mando de jocs, encara que un dels jugadors pot utilitzar el teclat.
Las teclas son las siguientes: Les tecles son les següents:
* **Cursores**: Mover al personaje, moverse por los menus * **Fletxes**: Mou al personatge
* **Q, W, E**: Disparar a la izquierda, al centro y a la derecha respectivamente * **Q, W, E**: Disparar a la esquerra, al centre i a la dreta respectivament
* **ESCAPE**: Pone en pausa el juego durante la partida. Sale de los menus. Cierra el juego
* **ENTER**: Acepta las opciones en los menus
![alt text](https://php.sustancia.synology.me/images/cc2.png) <p align="center">
<img src="https://php.sustancia.synology.me/images/ccae1.png" alt="Joc"
</p>
## Compilar ## Altres tecles
- **Tecla ESC**: Tancar el joc
Para compilar el código se necesitan tener las librerías SDL instaladas en el sistema y el compilador g++. - **Tecla F1**: Fa la finestra mes xicoteta
En Linux: - **Tecla F2**: Fa la finestra mes gran
```bash
sudo apt install libsdl2-dev g++
```
En macOS se pueden instalar fácilmente con [brew](https://brew.sh): - **Tecla F3**: Alterna entre el mode de pantalla completa i el de finestra
```bash
brew install sdl2 g++
```
Una vez instaladas las librerías SDL, se puede compilar utilizando el fichero Makefile suministrado. - **Tecla F4**: Activa o desactiva els shaders
En Linux: - **Tecla F10**: Reset
```bash
make linux
```
En macOS: <p align="center">
```bash <img src="https://php.sustancia.synology.me/images/ccae2.png" alt="Joc"
make macos </p>
```
![alt text](https://php.sustancia.synology.me/images/cc3.png)
## Como ejecutar
Para ejecutar el juego hay que escribir en la terminal la orden que se muestra a continuación. ## Agraiments
A chatGPT i sobretot a Copilot. Gracies per estar sempre quan vos he necesitat.
En Linux:
```bash
./coffee_crisis_linux
```
En macOS:
```bash
./coffee_crisis_macos
```
En macOS tambien puedes hacer doble click sobre el archivo coffee_crisis_macos
## Agradecimientos
A los jailers y a la jail. Y entre ellos, a JailDoctor por estar siempre ahí apoyándonos/obligándonos a sacar un Jailgame más.
Y por supuesto a ti por estar aquí.
## Licencia
Usa el código para lo que quieras: aprender, reirte, curiosear... excepto para sacar beneficio económico. Si lo consigues, por favor avísame y vamos a medias.

View File

@@ -1,11 +1,12 @@
## GAME ## GAME
game.item_size 20 game.item_size 20 # Tamaño de los items del juego
game.width 320 game.width 320 # Ancho de la resolucion nativa del juego
game.height 240 game.height 240 # Alto de la resolucion nativa del juego
game.play_area.rect.x 0 game.play_area.rect.x 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.y 0 game.play_area.rect.y 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.w 320 game.play_area.rect.w 320 # Rectangulo con la posición de la zona de juego
game.play_area.rect.h 200 game.play_area.rect.h 200 # Rectangulo con la posición de la zona de juego
game.enter_name_seconds 60 # Duración en segundos para introducir el nombre al finalizar la partida
## FADE ## FADE
fade.num_squares_width 160 fade.num_squares_width 160
@@ -42,3 +43,11 @@ balloon_3.vel 4.70f
balloon_3.grav 0.10f balloon_3.grav 0.10f
balloon_4.vel 5.45f balloon_4.vel 5.45f
balloon_4.grav 0.10f balloon_4.grav 0.10f
## NOTIFICATION
notification.pos_v TOP
notification.pos_h LEFT
notification.sound false
notification.color.r 48
notification.color.g 48
notification.color.b 48

View File

@@ -1,11 +1,12 @@
## GAME ## GAME
game.item_size 20 game.item_size 20 # Tamaño de los items del juego
game.width 320 game.width 320 # Ancho de la resolucion nativa del juego
game.height 256 game.height 256 # Alto de la resolucion nativa del juego
game.play_area.rect.x 0 game.play_area.rect.x 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.y 0 game.play_area.rect.y 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.w 320 game.play_area.rect.w 320 # Rectangulo con la posición de la zona de juego
game.play_area.rect.h 216 game.play_area.rect.h 216 # Rectangulo con la posición de la zona de juego
game.enter_name_seconds 60 # Duración en segundos para introducir el nombre al finalizar la partida
## FADE ## FADE
fade.num_squares_width 160 fade.num_squares_width 160
@@ -42,3 +43,11 @@ balloon_3.vel 4.70f
balloon_3.grav 0.10f balloon_3.grav 0.10f
balloon_4.vel 5.45f balloon_4.vel 5.45f
balloon_4.grav 0.10f balloon_4.grav 0.10f
## NOTIFICATION
notification.pos_v TOP
notification.pos_h LEFT
notification.sound false
notification.color.r 48
notification.color.g 48
notification.color.b 48

BIN
data/font/04b_25.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -1,194 +1,194 @@
# box width # box width
10 14
# box height # box height
10 14
# 32 espacio ( ) # 32 espacio ( )
5 8
# 33 ! # 33 !
4 5
# 34 " # 34 "
5 8
# 35 # # 35
7 10
# 36 $ # 36 $
7 10
# 37 % # 37 %
8 9
# 38 & # 38 &
8 11
# 39 ' # 39 '
3 5
# 40 ( # 40 (
5 7
# 41 ) # 41 )
5 7
# 42 * # 42 *
7 7
# 43 + # 43 +
7 9
# 44 , # 44 ,
4 5
# 45 - # 45 -
6 9
# 46 . # 46 .
4 5
# 47 / # 47 /
5 12
# 48 0 # 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 8
# 65 A # 49 1
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 6
# 50 2
8
# 51 3
8
# 52 4
8
# 53 5
8
# 54 6
8
# 55 7
8
# 56 8
8
# 57 9
8
# 58 :
5
# 59 ;
5
# 60 <
8
# 61 =
8
# 62 >
8
# 63 ?
8
# 64 @
11
# 65 A
8
# 66 B
8
# 67 C
8
# 68 D
8
# 69 E
8
# 70 F
8
# 71 G
8
# 72 H
8
# 73 I
5
# 74 J
8
# 75 K # 75 K
8 8
# 76 L # 76 L
6 8
# 77 M # 77 M
9 11
# 78 N # 78 N
8 8
# 79 O # 79 O
8 8
# 80 P # 80 P
7 8
# 81 Q # 81 Q
8 8
# 82 R # 82 R
7
# 83 S
6
# 84 T
8 8
# 83 S
8
# 84 T
9
# 85 U # 85 U
7 8
# 86 V # 86 V
8 8
# 87 W # 87 W
9 11
# 88 X # 88 X
8 8
# 89 Y # 89 Y
8 8
# 90 Z # 90 Z
7
# 91 [
4
# 92 \
5
# 93 ]
4
# 94 ^
5
# 95 _
8 8
# 91 [
7
# 92 \
11
# 93 ]
7
# 94 ^
6
# 95 _
7
# 96 ` # 96 `
4 6
# 97 a # 97 a
7 8
# 98 b # 98 b
7 8
# 99 c # 99 c
6 8
# 100 d # 100 d
7 8
# 101 e # 101 e
7 8
# 102 f # 102 f
5 8
# 103 g # 103 g
7 8
# 104 h # 104 h
7 8
# 105 i # 105 i
4 5
# 106 j # 106 j
5 8
# 107 k # 107 k
7 8
# 108 l # 108 l
4 8
# 109 m # 109 m
10 11
# 110 n # 110 n
7 8
# 111 o # 111 o
7 8
# 112 p # 112 p
7 8
# 113 q # 113 q
7 8
# 114 r # 114 r
6 8
# 115 s # 115 s
6 8
# 116 t # 116 t
5
# 117 u
7
# 118 v
7
# 119 w
9 9
# 117 u
8
# 118 v
8
# 119 w
11
# 120 x # 120 x
7 8
# 121 y # 121 y
7 8
# 122 z # 122 z
7 8
# 123 { -> ñ # 123 {
7 1
# 124 | -> ç # 124 |
7 1
# 125 } # 125 }
0 1
# 126 ~ # 126 ~
0 1

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -1,194 +0,0 @@
# box width
20
# box height
20
# 32 espacio ( )
8
# 33 !
8
# 34 "
10
# 35 #
14
# 36 $
14
# 37 %
16
# 38 &
16
# 39 '
6
# 40 (
10
# 41 )
10
# 42 *
14
# 43 +
14
# 44 ,
8
# 45 -
12
# 46 .
8
# 47 /
10
# 48 0
14
# 49 1
10
# 50 2
14
# 51 6
14
# 52 8
14
# 53 10
14
# 54 12
14
# 55 14
14
# 56 16
14
# 57 18
14
# 58 :
8
# 59 ;
8
# 60 <
12
# 61 =
12
# 62 >
12
# 63 ?
14
# 64 @
16
# 65 A
14
# 66 B
14
# 67 C
14
# 68 D
14
# 69 E
14
# 70 F
14
# 71 G
14
# 72 H
14
# 73 I
8
# 74 J
12
# 75 K
16
# 76 L
12
# 77 M
18
# 78 N
16
# 79 O
16
# 80 P
14
# 81 Q
16
# 82 R
14
# 83 S
12
# 84 T
16
# 85 U
14
# 86 V
16
# 87 W
18
# 88 X
16
# 89 Y
16
# 90 Z
14
# 91 [
8
# 92 \
10
# 93 ]
8
# 94 ^
10
# 95 _
16
# 96 `
8
# 97 a
14
# 98 b
14
# 99 c
12
# 100 d
14
# 101 e
14
# 102 f
10
# 103 g
14
# 104 h
14
# 105 i
8
# 106 j
10
# 107 k
14
# 108 l
8
# 109 m
20
# 110 n
14
# 111 o
14
# 112 p
14
# 113 q
14
# 114 r
12
# 115 s
12
# 116 t
10
# 117 u
14
# 118 v
14
# 119 w
18
# 120 x
14
# 121 y
14
# 122 z
14
# 123 { -> ñ
14
# 124 | -> ç
14
# 125 }
0
# 126 ~
0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -1,194 +0,0 @@
# box width
16
# box height
16
# 32 espacio ( )
16
# 33 !
16
# 34 "
16
# 35 #
16
# 36 $
16
# 37 %
16
# 38 &
16
# 39 '
16
# 40 (
16
# 41 )
16
# 42 *
16
# 43 +
16
# 44 ,
16
# 45 -
16
# 46 .
16
# 47 /
16
# 48 0
16
# 49 1
16
# 50 2
16
# 51 3
16
# 52 4
16
# 53 5
16
# 54 6
16
# 55 7
16
# 56 8
16
# 57 9
16
# 58 :
16
# 59 ;
16
# 60 <
16
# 61 =
16
# 62 >
16
# 63 ?
16
# 64 @
16
# 65 A
16
# 66 B
16
# 67 C
16
# 68 D
16
# 69 E
16
# 70 F
16
# 71 G
16
# 72 H
16
# 73 I
16
# 74 J
16
# 75 K
16
# 76 L
16
# 77 M
16
# 78 N
16
# 79 O
16
# 80 P
16
# 81 Q
16
# 82 R
16
# 83 S
16
# 84 T
16
# 85 U
16
# 86 V
16
# 87 W
16
# 88 X
16
# 89 Y
16
# 90 Z
16
# 91 [
16
# 92 \
16
# 93 ]
16
# 94 ^
16
# 95 _
16
# 96 `
16
# 97 a
16
# 98 b
16
# 99 c
16
# 100 d
16
# 101 e
16
# 102 f
16
# 103 g
16
# 104 h
16
# 105 i
16
# 106 j
16
# 107 k
16
# 108 l
16
# 109 m
16
# 110 n
16
# 111 o
16
# 112 p
16
# 113 q
16
# 114 r
16
# 115 s
16
# 116 t
16
# 117 u
16
# 118 v
16
# 119 w
16
# 120 x
16
# 121 y
16
# 122 z
16
# 123 {
16
# 124 |
16
# 125 }
16
# 126 ~
16

View File

Before

Width:  |  Height:  |  Size: 84 B

After

Width:  |  Height:  |  Size: 84 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 935 B

View File

@@ -23,29 +23,64 @@ frames=8,9,10,11
[/animation] [/animation]
[animation] [animation]
name=stand-sideshoot name=walk-sideshoot-cooldown
speed=5 speed=5
loop=0 loop=0
frames=12,13,14,15 frames=12,13,14,15
[/animation] [/animation]
[animation] [animation]
name=walk-centershoot name=stand-sideshoot
speed=5 speed=5
loop=0 loop=0
frames=16,17,18,19 frames=16,17,18,19
[/animation] [/animation]
[animation] [animation]
name=stand-centershoot name=stand-sideshoot-cooldown
speed=5
loop=0
frames=15
[/animation]
[animation]
name=walk-centershoot
speed=5 speed=5
loop=0 loop=0
frames=20,21,22,23 frames=20,21,22,23
[/animation] [/animation]
[animation] [animation]
name=death name=walk-centershoot-cooldown
speed=15 speed=5
loop=0 loop=0
frames=24,25,26,27 frames=24,25,26,27
[/animation] [/animation]
[animation]
name=stand-centershoot
speed=5
loop=0
frames=28,29,30,31
[/animation]
[animation]
name=stand-centershoot-cooldown
speed=5
loop=0
frames=27
[/animation]
[animation]
name=death
speed=10
loop=0
frames=32,33,34,35
[/animation]
[animation]
name=celebration
speed=10
loop=-1
frames=36,36,36,36,36,36,37,38,39,40,40,40,40,40,40,39,39,39,40,40,40,39,39,39,38,37,36,36,36
[/animation]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 944 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 B

View File

@@ -206,7 +206,7 @@ NORMAL
DIFICIL DIFICIL
## 69 - MENU DE OPCIONES ## 69 - MENU DE OPCIONES
TECLAT Teclat
## 70 - MENU DE OPCIONES ## 70 - MENU DE OPCIONES
MANDO MANDO
@@ -281,7 +281,7 @@ MODE FORA DE LINEA
TAULER DE PUNTS TAULER DE PUNTS
## 94 - NOTIFICACIONES ## 94 - NOTIFICACIONES
Torna a polsar per eixir ... Torna a polsar per eixir
## 95 - DEFINE BUTTONS ## 95 - DEFINE BUTTONS
Disparar cap a l'esquerra Disparar cap a l'esquerra
@@ -345,3 +345,18 @@ Per favor
## 115 - MARCADOR ## 115 - MARCADOR
espere espere
## 116 - NOTIFICACIONES
Torna a polsar per apagar el sistema
## 117 - GAME TEXT
SuperPoder!
## 118 - GAME TEXT
+1 Colp
## 119 - GAME TEXT
Temps!
## 120 - SCOREBOARD
Puntuacio

View File

@@ -206,7 +206,7 @@ NORMAL
HARD HARD
## 69 - MENU DE OPCIONES ## 69 - MENU DE OPCIONES
KEYBOARD Keyboard
## 70 - MENU DE OPCIONES ## 70 - MENU DE OPCIONES
GAME CONTROLLER GAME CONTROLLER
@@ -345,3 +345,18 @@ Please
## 115 - MARCADOR ## 115 - MARCADOR
wait wait
## 116 - NOTIFICACIONES
Press again to shutdown system
## 117 - GAME TEXT
PowerUp
## 118 - GAME TEXT
+1 Hit
## 119 - GAME TEXT
Stop!
## 120 - SCOREBOARD
Score

View File

@@ -206,7 +206,7 @@ NORMAL
DIFICIL DIFICIL
## 69 - MENU DE OPCIONES ## 69 - MENU DE OPCIONES
TECLADO Teclado
## 70 - MENU DE OPCIONES ## 70 - MENU DE OPCIONES
MANDO MANDO
@@ -345,3 +345,18 @@ Por favor
## 115 - MARCADOR ## 115 - MARCADOR
espere espere
## 94 - NOTIFICACIONES
Pulsa otra vez para apagar el sistema
## 117 - GAME TEXT
Potenciador
## 118 - GAME TEXT
+1 Golpe
## 119 - GAME TEXT
Tiempo!
## 120 - SCOREBOARD
Puntuacion

View File

@@ -1,10 +0,0 @@
#!/bin/bash
SOURCEPATH=../source/
for i in "$SOURCEPATH"/*.cpp
do
include-what-you-use -D DEBUG -D VERBOSE -std=c++14 -Wall "$i"
read -p "Presiona cualquier tecla para continuar..."
clear
done

View File

@@ -1,3 +0,0 @@
#!/bin/bash
valgrind --suppressions=valgrind_exceptions --leak-check=full ~/coffee_crisis_arcade_edition/coffee_crisis_arcade_edition_debug > ~/coffee_crisis_arcade_edition/debug.txt 2>&1

View File

View File

@@ -0,0 +1,8 @@
#!/bin/bash
SOURCEPATH=../source/
for i in "$SOURCEPATH"/*.cpp
do
include-what-you-use -D DEBUG -D VERBOSE -std=c++20 -Wall "$i"
done

View File

@@ -0,0 +1,10 @@
#!/bin/bash
SOURCEPATH=../source/
for i in "$SOURCEPATH"/*.cpp
do
include-what-you-use -D DEBUG -D VERBOSE -std=c++20 -Wall "$i"
read -r -p "Presiona cualquier tecla para continuar..."
clear
done

View File

@@ -0,0 +1,8 @@
*:/home/sergio/gitea/coffee_crisis_arcade_edition/source/stb*
*:/home/sergio/gitea/coffee_crisis_arcade_edition/source/gif.c
*:/home/sergio/gitea/coffee_crisis_arcade_edition/source/jail*
*:/usr/include/*
*:../source/stb*
*:../source/gif.c
*:../source/jail*
*:/usr/include/*

View File

View File

@@ -0,0 +1,53 @@
#!/bin/bash
# Función para mostrar el uso del script
mostrar_uso() {
echo "Uso: $0 [-o opción]"
echo "Opciones:"
echo " w Ejecutar cppcheck con warning, style, performance"
echo " a Ejecutar cppcheck con todas las opciones habilitadas"
echo " u Ejecutar cppcheck para unusedFunction"
}
# Inicializar las variables
opcion=""
# Procesar las opciones
while getopts "o:" opt; do
case $opt in
o)
opcion=$OPTARG
;;
*)
mostrar_uso
exit 1
;;
esac
done
# Ejecutar según la opción seleccionada
case $opcion in
w)
cppcheck --force --enable=warning,style,performance --std=c++20 \
--suppressions-list=./cppcheck_suppressions \
../source/ \
2>./cppcheck-result-warning-style-performance.txt
;;
a)
cppcheck --force --enable=all -I /usr/include --std=c++20 \
--suppress=missingIncludeSystem \
--suppressions-list=./cppcheck_suppressions \
../source/ \
2>./cppcheck-result-all.txt
;;
u)
cppcheck --enable=style --std=c++20 \
--suppressions-list=./cppcheck_suppressions \
../source/ \
2>./cppcheck-result-unusedFunction.txt
;;
*)
mostrar_uso
exit 1
;;
esac

View File

@@ -0,0 +1,6 @@
#!/bin/bash
valgrind --suppressions=valgrind_exceptions \
--leak-check=full \
~/coffee_crisis_arcade_edition/coffee_crisis_arcade_edition_debug \
> ~/coffee_crisis_arcade_edition/debug.txt 2>&1

View File

@@ -1,211 +1,63 @@
#include "animated_sprite.h" #include "animated_sprite.h"
#include <fstream> // for basic_ostream, operator<<, basic_istream, basic... #include <stddef.h> // Para size_t
#include <iostream> // for cout #include <fstream> // Para basic_ostream, basic_istream, operator<<, basic...
#include <sstream> // for basic_stringstream #include <iostream> // Para cout, cerr
#include "texture.h" // for Texture #include <sstream> // Para basic_stringstream
#include <stdexcept> // Para runtime_error
#include "texture.h" // Para Texture
#include "utils.h" // Para printWithDots
// Carga la animación desde un fichero // Carga las animaciones en un vector(Animations) desde un fichero
AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string file_path) AnimationsFileBuffer loadAnimationsFromFile(const std::string &file_path)
{ {
// Inicializa variables
AnimatedFile af;
af.texture = texture;
auto frames_per_row = 0;
auto frame_width = 0;
auto frame_height = 0;
auto max_tiles = 0;
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
std::ifstream file(file_path); std::ifstream file(file_path);
if (!file)
{
std::cerr << "Error: Fichero no encontrado " << file_path << std::endl;
throw std::runtime_error("Fichero no encontrado: " + file_path);
}
printWithDots("Animation : ", file_path.substr(file_path.find_last_of("\\/") + 1), "[ LOADED ]");
std::vector<std::string> buffer;
std::string line; std::string line;
while (std::getline(file, line))
// El fichero se puede abrir
if (file.good())
{ {
// Procesa el fichero linea a linea if (!line.empty())
#ifdef VERBOSE buffer.push_back(line);
std::cout << "Animation loaded: " << file_name << std::endl;
#endif
while (std::getline(file, line))
{
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
Animation buffer;
buffer.counter = 0;
buffer.current_frame = 0;
buffer.completed = false;
do
{
std::getline(file, line);
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "name")
{
buffer.name = line.substr(pos + 1, line.length());
}
else if (line.substr(0, pos) == "speed")
{
buffer.speed = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "loop")
{
buffer.loop = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frames")
{
// Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length()));
std::string tmp;
SDL_Rect rect = {0, 0, frame_width, frame_height};
while (getline(ss, tmp, ','))
{
// Comprueba que el tile no sea mayor que el maximo indice permitido
const auto num_tile = std::stoi(tmp) > max_tiles ? 0 : std::stoi(tmp);
rect.x = (num_tile % frames_per_row) * frame_width;
rect.y = (num_tile / frames_per_row) * frame_height;
buffer.frames.push_back(rect);
}
}
else
{
#ifdef VERBOSE
std::cout << "Warning: file " << file_name.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
#endif
}
}
} while (line != "[/animation]");
// Añade la animación al vector de animaciones
af.animations.push_back(buffer);
}
// En caso contrario se parsea el fichero para buscar las variables y los valores
else
{
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "frames_per_row")
{
frames_per_row = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_width")
{
frame_width = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_height")
{
frame_height = std::stoi(line.substr(pos + 1, line.length()));
}
else
{
#ifdef VERBOSE
std::cout << "Warning: file " << file_name.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
#endif
}
// Normaliza valores
if (frames_per_row == 0 && frame_width > 0)
{
frames_per_row = texture->getWidth() / frame_width;
}
if (max_tiles == 0 && frame_width > 0 && frame_height > 0)
{
const auto w = texture->getWidth() / frame_width;
const auto h = texture->getHeight() / frame_height;
max_tiles = w * h;
}
}
}
}
// Cierra el fichero
file.close();
}
// El fichero no se puede abrir
else
{
#ifdef VERBOSE
std::cout << "Warning: Unable to open " << file_name.c_str() << " file" << std::endl;
#endif
} }
return af; return buffer;
} }
// Constructor // Constructor
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, std::string file, std::vector<std::string> *buffer) AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path)
: MovingSprite(texture)
{ {
// Copia los punteros
setTexture(texture);
// Carga las animaciones // Carga las animaciones
if (file != "") if (!file_path.empty())
{ {
AnimatedFile as = loadAnimationFromFile(texture, file); AnimationsFileBuffer v = loadAnimationsFromFile(file_path);
loadFromAnimationsFileBuffer(v);
// Copia los datos de las animaciones
for (auto animation : as.animations)
{
animations_.push_back(animation);
}
} }
else if (buffer)
{
loadFromVector(buffer);
}
// Inicializa variables
current_animation_ = 0;
} }
// Constructor // Constructor
AnimatedSprite::AnimatedSprite(AnimatedFile *animation) AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer &animations)
: MovingSprite(texture)
{ {
// Copia los punteros if (!animations.empty())
setTexture(animation->texture);
// Inicializa variables
current_animation_ = 0;
// Copia los datos de las animaciones
for (auto a : animation->animations)
{ {
animations_.push_back(a); loadFromAnimationsFileBuffer(animations);
} }
} }
// Destructor
AnimatedSprite::~AnimatedSprite()
{
animations_.clear();
}
// Obtiene el indice de la animación a partir del nombre // Obtiene el indice de la animación a partir del nombre
int AnimatedSprite::getIndex(std::string name) int AnimatedSprite::getIndex(const std::string &name)
{ {
auto index = -1; auto index = -1;
for (auto a : animations_) for (const auto &a : animations_)
{ {
index++; index++;
if (a.name == name) if (a.name == name)
@@ -213,16 +65,14 @@ int AnimatedSprite::getIndex(std::string name)
return index; return index;
} }
} }
#ifdef VERBOSE
std::cout << "** Warning: could not find \"" << name.c_str() << "\" animation" << std::endl; std::cout << "** Warning: could not find \"" << name.c_str() << "\" animation" << std::endl;
#endif
return -1; return -1;
} }
// Calcula el frame correspondiente a la animación // Calcula el frame correspondiente a la animación
void AnimatedSprite::animate() void AnimatedSprite::animate()
{ {
if (!enabled_ || animations_[current_animation_].speed == 0) if (animations_[current_animation_].speed == 0)
{ {
return; return;
} }
@@ -256,233 +106,14 @@ void AnimatedSprite::animate()
} }
} }
// Obtiene el número de frames de la animación actual
int AnimatedSprite::getNumFrames()
{
return (int)animations_[current_animation_].frames.size();
}
// Establece el frame actual de la animación
void AnimatedSprite::setCurrentFrame(int num)
{
// Descarta valores fuera de rango
if (num >= (int)animations_[current_animation_].frames.size())
{
num = 0;
}
// Cambia el valor de la variable
animations_[current_animation_].current_frame = num;
animations_[current_animation_].counter = 0;
// Escoge el frame correspondiente de la animación
setSpriteClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]);
}
// Establece el valor del contador
void AnimatedSprite::setAnimationCounter(std::string name, int num)
{
animations_[getIndex(name)].counter = num;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(std::string name, int speed)
{
animations_[getIndex(name)].counter = speed;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(int index, int speed)
{
animations_[index].counter = speed;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(std::string name, int loop)
{
animations_[getIndex(name)].loop = loop;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(int index, int loop)
{
animations_[index].loop = loop;
}
// Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(std::string name, bool value)
{
animations_[getIndex(name)].completed = value;
}
// OLD - Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(int index, bool value)
{
animations_[index].completed = value;
}
// Comprueba si ha terminado la animación // Comprueba si ha terminado la animación
bool AnimatedSprite::animationIsCompleted() bool AnimatedSprite::animationIsCompleted()
{ {
return animations_[current_animation_].completed; return animations_[current_animation_].completed;
} }
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(std::string name, Uint8 index)
{
return animations_[getIndex(name)].frames[index];
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF)
{
return animations_[indexA].frames[indexF];
}
// Carga la animación desde un vector
bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
{
// Inicializa variables
auto frames_per_row = 0;
auto frame_width = 0;
auto frame_height = 0;
auto max_tiles = 0;
// Indicador de éxito en el proceso
auto success = true;
std::string line;
// Recorre todo el vector
auto index = 0;
while (index < (int)source->size())
{
// Lee desde el vector
line = source->at(index);
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
Animation buffer;
buffer.counter = 0;
buffer.current_frame = 0;
buffer.completed = false;
do
{
// Aumenta el indice para leer la siguiente linea
index++;
line = source->at(index);
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "name")
{
buffer.name = line.substr(pos + 1, line.length());
}
else if (line.substr(0, pos) == "speed")
{
buffer.speed = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "loop")
{
buffer.loop = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frames")
{
// Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length()));
std::string tmp;
SDL_Rect rect = {0, 0, frame_width, frame_height};
while (getline(ss, tmp, ','))
{
// Comprueba que el tile no sea mayor que el maximo indice permitido
const int num_tile = std::stoi(tmp) > max_tiles ? 0 : std::stoi(tmp);
rect.x = (num_tile % frames_per_row) * frame_width;
rect.y = (num_tile / frames_per_row) * frame_height;
buffer.frames.push_back(rect);
}
}
else
{
#ifdef VERBOSE
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
#endif
success = false;
}
}
} while (line != "[/animation]");
// Añade la animación al vector de animaciones
animations_.push_back(buffer);
}
// En caso contrario se parsea el fichero para buscar las variables y los valores
else
{
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "frames_per_row")
{
frames_per_row = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_width")
{
frame_width = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_height")
{
frame_height = std::stoi(line.substr(pos + 1, line.length()));
}
else
{
#ifdef VERBOSE
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
#endif
success = false;
}
// Normaliza valores
if (frames_per_row == 0 && frame_width > 0)
{
frames_per_row = texture_->getWidth() / frame_width;
}
if (max_tiles == 0 && frame_width > 0 && frame_height > 0)
{
const int w = texture_->getWidth() / frame_width;
const int h = texture_->getHeight() / frame_height;
max_tiles = w * h;
}
}
}
// Una vez procesada la linea, aumenta el indice para pasar a la siguiente
index++;
}
// Pone un valor por defecto
setRect({0, 0, frame_width, frame_height});
return success;
}
// Establece la animacion actual // Establece la animacion actual
void AnimatedSprite::setCurrentAnimation(std::string name) void AnimatedSprite::setCurrentAnimation(const std::string &name)
{ {
const auto new_animation = getIndex(name); const auto new_animation = getIndex(name);
if (current_animation_ != new_animation) if (current_animation_ != new_animation)
@@ -510,26 +141,8 @@ void AnimatedSprite::setCurrentAnimation(int index)
// Actualiza las variables del objeto // Actualiza las variables del objeto
void AnimatedSprite::update() void AnimatedSprite::update()
{ {
if (enabled_) animate();
{ MovingSprite::update();
animate();
MovingSprite::update();
}
}
// Establece el rectangulo para un frame de una animación
void AnimatedSprite::setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h)
{
animations_[index_animation].frames.push_back({x, y, w, h});
}
// OLD - Establece el contador para todas las animaciones
void AnimatedSprite::setAnimationCounter(int value)
{
for (auto &a : animations_)
{
a.counter = value;
}
} }
// Reinicia la animación // Reinicia la animación
@@ -539,3 +152,99 @@ void AnimatedSprite::resetAnimation()
animations_[current_animation_].counter = 0; animations_[current_animation_].counter = 0;
animations_[current_animation_].completed = false; animations_[current_animation_].completed = false;
} }
// Carga la animación desde un vector de cadenas
void AnimatedSprite::loadFromAnimationsFileBuffer(const AnimationsFileBuffer &source)
{
int frame_width = 1;
int frame_height = 1;
int frames_per_row = 1;
int max_tiles = 1;
size_t index = 0;
while (index < source.size())
{
std::string line = source.at(index);
// Parsea el fichero para buscar variables y valores
if (line != "[animation]")
{
// Encuentra la posición del caracter '='
size_t pos = line.find("=");
// Procesa las dos subcadenas
if (pos != std::string::npos)
{
std::string key = line.substr(0, pos);
int value = std::stoi(line.substr(pos + 1));
if (key == "frame_width")
frame_width = value;
else if (key == "frame_height")
frame_height = value;
else
std::cout << "Warning: unknown parameter " << key << std::endl;
frames_per_row = texture_->getWidth() / frame_width;
const int w = texture_->getWidth() / frame_width;
const int h = texture_->getHeight() / frame_height;
max_tiles = w * h;
}
}
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
Animation animation;
do
{
index++;
line = source.at(index);
size_t pos = line.find("=");
if (pos != std::string::npos)
{
std::string key = line.substr(0, pos);
std::string value = line.substr(pos + 1);
if (key == "name")
animation.name = value;
else if (key == "speed")
animation.speed = std::stoi(value);
else if (key == "loop")
animation.loop = std::stoi(value);
else if (key == "frames")
{
// Se introducen los valores separados por comas en un vector
std::stringstream ss(value);
std::string tmp;
SDL_Rect rect = {0, 0, frame_width, frame_height};
while (getline(ss, tmp, ','))
{
// Comprueba que el tile no sea mayor que el maximo indice permitido
const int num_tile = std::stoi(tmp);
if (num_tile <= max_tiles)
{
rect.x = (num_tile % frames_per_row) * frame_width;
rect.y = (num_tile / frames_per_row) * frame_height;
animation.frames.emplace_back(rect);
}
}
}
else
std::cout << "Warning: unknown parameter " << key << std::endl;
}
} while (line != "[/animation]");
// Añade la animación al vector de animaciones
animations_.emplace_back(animation);
}
// Una vez procesada la linea, aumenta el indice para pasar a la siguiente
index++;
}
// Pone un valor por defecto
setWidth(frame_width);
setHeight(frame_height);
}

View File

@@ -1,12 +1,11 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint8 #include <memory> // Para shared_ptr
#include <string> // for string, basic_string #include <string> // Para string
#include <vector> // for vector #include <vector> // Para vector
#include "moving_sprite.h" // for MovingSprite #include "moving_sprite.h" // Para MovingSprite
#include "texture.h" class Texture; // lines 9-9
#include <memory>
struct Animation struct Animation
{ {
@@ -17,82 +16,51 @@ struct Animation
bool completed; // Indica si ha finalizado la animación bool completed; // Indica si ha finalizado la animación
int current_frame; // Frame actual int current_frame; // Frame actual
int counter; // Contador para las animaciones int counter; // Contador para las animaciones
Animation() : name(std::string()), speed(5), loop(0), completed(false), current_frame(0), counter(0) {}
}; };
struct AnimatedFile using AnimationsFileBuffer = std::vector<std::string>;
{
std::vector<Animation> animations; // Vector con las diferentes animaciones
std::shared_ptr<Texture> texture; // Textura con los graficos para el sprite
};
// Carga la animación desde un fichero // Carga las animaciones en un vector(Animations) desde un fichero
AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string filePath); AnimationsFileBuffer loadAnimationsFromFile(const std::string &file_path);
class AnimatedSprite : public MovingSprite class AnimatedSprite : public MovingSprite
{ {
private: protected:
// Variables // Variables
std::vector<Animation> animations_; // Vector con las diferentes animaciones std::vector<Animation> animations_; // Vector con las diferentes animaciones
int current_animation_; // Animacion activa int current_animation_ = 0; // Animacion activa
public:
// Constructor
AnimatedSprite(std::shared_ptr<Texture> texture = nullptr, std::string file = "", std::vector<std::string> *buffer = nullptr);
AnimatedSprite(AnimatedFile *animation);
// Destructor
~AnimatedSprite();
// Calcula el frame correspondiente a la animación actual // Calcula el frame correspondiente a la animación actual
void animate(); void animate();
// Obtiene el número de frames de la animación actual // Carga la animación desde un vector de cadenas
int getNumFrames(); void loadFromAnimationsFileBuffer(const AnimationsFileBuffer &source);
// Establece el frame actual de la animación public:
void setCurrentFrame(int num); // Constructor
AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path);
AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer &animations);
explicit AnimatedSprite(std::shared_ptr<Texture> texture)
: MovingSprite(texture) {}
// Establece el valor del contador // Destructor
void setAnimationCounter(std::string name, int num); virtual ~AnimatedSprite() = default;
// Establece la velocidad de una animación // Actualiza las variables del objeto
void setAnimationSpeed(std::string name, int speed); void update() override;
void setAnimationSpeed(int index, int speed);
// Establece el frame al que vuelve la animación al finalizar
void setAnimationLoop(std::string name, int loop);
void setAnimationLoop(int index, int loop);
// Establece el valor de la variable
void setAnimationCompleted(std::string name, bool value);
void setAnimationCompleted(int index, bool value);
// Comprueba si ha terminado la animación // Comprueba si ha terminado la animación
bool animationIsCompleted(); bool animationIsCompleted();
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect getAnimationClip(std::string name = "default", Uint8 index = 0);
SDL_Rect getAnimationClip(int indexA = 0, Uint8 indexF = 0);
// Obtiene el indice de la animación a partir del nombre // Obtiene el indice de la animación a partir del nombre
int getIndex(std::string name); int getIndex(const std::string &name);
// Carga la animación desde un vector
bool loadFromVector(std::vector<std::string> *source);
// Establece la animacion actual // Establece la animacion actual
void setCurrentAnimation(std::string name = "default"); void setCurrentAnimation(const std::string &name = "default");
void setCurrentAnimation(int index = 0); void setCurrentAnimation(int index = 0);
// Actualiza las variables del objeto
void update();
// OLD - Establece el rectangulo para un frame de una animación
void setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h);
// OLD - Establece el contador para todas las animaciones
void setAnimationCounter(int value);
// Reinicia la animación // Reinicia la animación
void resetAnimation(); void resetAnimation();
}; };

View File

@@ -1,68 +1,56 @@
#include "asset.h" #include "asset.h"
#include <SDL2/SDL_rwops.h> // for SDL_RWFromFile, SDL_RWclose, SDL_RWops #include <algorithm> // Para find_if, max
#include <SDL2/SDL_stdinc.h> // for SDL_max #include <fstream> // Para basic_ostream, operator<<, basic_ifstream, endl
#include <stddef.h> // for size_t #include <iostream> // Para cout
#include <iostream> // for basic_ostream, operator<<, cout, endl #include <string> // Para allocator, char_traits, string, operator+, oper...
#include "utils.h" // Para getFileName, printWithDots
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Asset *Asset::asset = nullptr; Asset *Asset::asset_ = nullptr;
// [SINGLETON] Crearemos el objeto asset con esta función estática // [SINGLETON] Crearemos el objeto asset con esta función estática
void Asset::init(std::string executable_path) void Asset::init(const std::string &executable_path)
{ {
Asset::asset = new Asset(executable_path); Asset::asset_ = new Asset(executable_path);
} }
// [SINGLETON] Destruiremos el objeto asset con esta función estática // [SINGLETON] Destruiremos el objeto asset con esta función estática
void Asset::destroy() void Asset::destroy()
{ {
delete Asset::asset; delete Asset::asset_;
} }
// [SINGLETON] Con este método obtenemos el objeto asset y podemos trabajar con él // [SINGLETON] Con este método obtenemos el objeto asset y podemos trabajar con él
Asset *Asset::get() Asset *Asset::get()
{ {
return Asset::asset; return Asset::asset_;
}
// Constructor
Asset::Asset(std::string executable_path)
{
executable_path_ = executable_path.substr(0, executable_path.find_last_of("\\/"));
longest_name_ = 0;
} }
// Añade un elemento a la lista // Añade un elemento a la lista
void Asset::add(std::string file, AssetType type, bool required, bool absolute) void Asset::add(const std::string &file, AssetType type, bool required, bool absolute)
{ {
AssetItem ai; file_list_.emplace_back(absolute ? file : executable_path_ + file, type, required);
ai.file = absolute ? file : executable_path_ + file; longest_name_ = std::max(longest_name_, static_cast<int>(file_list_.back().file.size()));
ai.type = type;
ai.required = required;
file_list_.push_back(ai);
const std::string file_name = file.substr(file.find_last_of("\\/") + 1);
longest_name_ = SDL_max(longest_name_, file_name.size());
} }
// Devuelve el fichero de un elemento de la lista a partir de una cadena // Devuelve la ruta completa a un fichero a partir de una cadena
std::string Asset::get(std::string text) const std::string Asset::get(const std::string &text) const
{ {
for (auto f : file_list_) auto it = std::find_if(file_list_.begin(), file_list_.end(),
[&text](const auto &f)
{
return getFileName(f.file) == text;
});
if (it != file_list_.end())
{ {
const size_t last_index = f.file.find_last_of("/") + 1; return it->file;
const std::string file = f.file.substr(last_index, std::string::npos); }
else
if (file == text) {
{ std::cout << "Warning: file " << text << " not found" << std::endl;
return f.file; return "";
}
} }
#ifdef VERBOSE
std::cout << "Warning: file " << text.c_str() << " not found" << std::endl;
#endif
return "";
} }
// Comprueba que existen todos los elementos // Comprueba que existen todos los elementos
@@ -70,12 +58,10 @@ bool Asset::check() const
{ {
bool success = true; bool success = true;
#ifdef VERBOSE std::cout << "\n** CHECKING FILES" << std::endl;
std::cout << "\n** Checking files" << std::endl;
std::cout << "Executable path is: " << executable_path_ << std::endl; // std::cout << "Executable path is: " << executable_path_ << std::endl;
std::cout << "Sample filepath: " << file_list_.back().file << std::endl; // std::cout << "Sample filepath: " << file_list_.back().file << std::endl;
#endif
// Comprueba la lista de ficheros clasificandolos por tipo // Comprueba la lista de ficheros clasificandolos por tipo
for (int type = 0; type < static_cast<int>(AssetType::MAX_ASSET_TYPE); ++type) for (int type = 0; type < static_cast<int>(AssetType::MAX_ASSET_TYPE); ++type)
@@ -83,7 +69,7 @@ bool Asset::check() const
// Comprueba si hay ficheros de ese tipo // Comprueba si hay ficheros de ese tipo
bool any = false; bool any = false;
for (auto f : file_list_) for (const auto &f : file_list_)
{ {
if (f.required && f.type == static_cast<AssetType>(type)) if (f.required && f.type == static_cast<AssetType>(type))
{ {
@@ -94,95 +80,77 @@ bool Asset::check() const
// Si hay ficheros de ese tipo, comprueba si existen // Si hay ficheros de ese tipo, comprueba si existen
if (any) if (any)
{ {
#ifdef VERBOSE std::cout << "\n>> " << getTypeName(static_cast<AssetType>(type)).c_str() << " FILES" << std::endl;
std::cout << "\n>> " << getTypeName(type).c_str() << " FILES" << std::endl;
#endif
for (auto f : file_list_) for (const auto &f : file_list_)
{ {
if (f.required && f.type == static_cast<AssetType>(type)) if (f.required && f.type == static_cast<AssetType>(type))
{ {
success &= checkFile(f.file); success &= checkFile(f.file);
} }
} }
if (success)
std::cout << " All files are OK." << std::endl;
} }
} }
// Resultado // Resultado
#ifdef VERBOSE std::cout << (success ? "\n** CHECKING FILES COMPLETED.\n" : "\n** CHECKING FILES FAILED.\n") << std::endl;
std::cout << (success ? "\n** All files OK.\n" : "\n** A file is missing. Exiting.\n") << std::endl;
#endif
return success; return success;
} }
// Comprueba que existe un fichero // Comprueba que existe un fichero
bool Asset::checkFile(std::string path) const bool Asset::checkFile(const std::string &path) const
{ {
bool success = false; std::ifstream file(path);
std::string result = "ERROR"; bool success = file.good();
file.close();
// Comprueba si existe el fichero if (!success)
const std::string file_name = path.substr(path.find_last_of("\\/") + 1); printWithDots("Checking file : ", getFileName(path), "[ ERROR ]");
SDL_RWops *file = SDL_RWFromFile(path.c_str(), "rb");
if (file != nullptr)
{
result = "OK";
success = true;
SDL_RWclose(file);
}
#ifdef VERBOSE
std::cout.setf(std::ios::left, std::ios::adjustfield);
std::cout << "Checking file: ";
std::cout.width(longest_name_ + 2);
std::cout.fill('.');
std::cout << file_name + " ";
std::cout << " [" + result + "]" << std::endl;
#endif
return success; return success;
} }
// Devuelve el nombre del tipo de recurso // Devuelve el nombre del tipo de recurso
std::string Asset::getTypeName(int type) const std::string Asset::getTypeName(AssetType type) const
{ {
switch (type) switch (type)
{ {
case static_cast<int>(AssetType::BITMAP): case AssetType::BITMAP:
return "BITMAP"; return "BITMAP";
break; break;
case static_cast<int>(AssetType::MUSIC): case AssetType::MUSIC:
return "MUSIC"; return "MUSIC";
break; break;
case static_cast<int>(AssetType::SOUND): case AssetType::SOUND:
return "SOUND"; return "SOUND";
break; break;
case static_cast<int>(AssetType::FONT): case AssetType::FONT:
return "FONT"; return "FONT";
break; break;
case static_cast<int>(AssetType::LANG): case AssetType::LANG:
return "LANG"; return "LANG";
break; break;
case static_cast<int>(AssetType::DATA): case AssetType::DATA:
return "DATA"; return "DATA";
break; break;
case static_cast<int>(AssetType::ANIMATION): case AssetType::ANIMATION:
return "ANIMATION"; return "ANIMATION";
break; break;
case static_cast<int>(AssetType::PALETTE): case AssetType::PALETTE:
return "PALETTE"; return "PALETTE";
break; break;
case static_cast<int>(AssetType::ITEM): case AssetType::ITEM:
return "ITEM"; return "ITEM";
break; break;

View File

@@ -1,9 +1,10 @@
#pragma once #pragma once
#include <string> // for string, basic_string #include <string> // para string, basic_string
#include <vector> // for vector #include <vector> // para vector
#include "utils.h"
enum class AssetType enum class AssetType : int
{ {
BITMAP, BITMAP,
MUSIC, MUSIC,
@@ -22,37 +23,41 @@ class Asset
{ {
private: private:
// [SINGLETON] Objeto asset privado para Don Melitón // [SINGLETON] Objeto asset privado para Don Melitón
static Asset *asset; static Asset *asset_;
// Estructura para definir un item // Estructura para definir un item
struct AssetItem struct AssetItem
{ {
std::string file; // Ruta del fichero desde la raiz del directorio std::string file; // Ruta del fichero desde la raíz del directorio
enum AssetType type; // Indica el tipo de recurso AssetType type; // Indica el tipo de recurso
bool required; // Indica si es un fichero que debe de existir bool required; // Indica si es un fichero que debe de existir
// bool absolute; // Indica si la ruta que se ha proporcionado es una ruta absoluta
// Constructor
AssetItem(const std::string &filePath, AssetType assetType, bool isRequired)
: file(filePath), type(assetType), required(isRequired) {}
}; };
// Variables // Variables
int longest_name_; // Contiene la longitud del nombre de fichero mas largo int longest_name_ = 0; // Contiene la longitud del nombre de fichero mas largo
std::vector<AssetItem> file_list_; // Listado con todas las rutas a los ficheros std::vector<AssetItem> file_list_; // Listado con todas las rutas a los ficheros
std::string executable_path_; // Ruta al ejecutable std::string executable_path_; // Ruta al ejecutable
// Comprueba que existe un fichero // Comprueba que existe un fichero
bool checkFile(std::string executable_path) const; bool checkFile(const std::string &path) const;
// Devuelve el nombre del tipo de recurso // Devuelve el nombre del tipo de recurso
std::string getTypeName(int type) const; std::string getTypeName(AssetType type) const;
// Constructor // Constructor
Asset(std::string path); explicit Asset(const std::string &executable_path)
: executable_path_(getPath(executable_path)) {}
// Destructor // Destructor
~Asset() = default; ~Asset() = default;
public: public:
// [SINGLETON] Crearemos el objeto screen con esta función estática // [SINGLETON] Crearemos el objeto screen con esta función estática
static void init(std::string path); static void init(const std::string &executable_path);
// [SINGLETON] Destruiremos el objeto screen con esta función estática // [SINGLETON] Destruiremos el objeto screen con esta función estática
static void destroy(); static void destroy();
@@ -61,10 +66,10 @@ public:
static Asset *get(); static Asset *get();
// Añade un elemento a la lista // Añade un elemento a la lista
void add(std::string file, AssetType type, bool required = true, bool absolute = false); void add(const std::string &file, AssetType type, bool required = true, bool absolute = false);
// Devuelve un elemento de la lista a partir de una cadena // Devuelve la ruta completa a un fichero a partir de una cadena
std::string get(std::string text) const; std::string get(const std::string &text) const;
// Comprueba que existen todos los elementos // Comprueba que existen todos los elementos
bool check() const; bool check() const;

View File

@@ -1,79 +1,92 @@
#include "background.h" #include "background.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <algorithm> // for max, min #include <algorithm> // Para clamp, max
#include <string> // for basic_string #include "moving_sprite.h" // Para MovingSprite
#include "asset.h" // for Asset #include "param.h" // Para Param, ParamBackground, param
#include "param.h" // for param #include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "sprite.h" // Para Sprite
#include "texture.h" // Para Texture
// Constructor // Constructor
Background::Background(SDL_Renderer *renderer) Background::Background()
: renderer_(renderer) : renderer_(Screen::get()->getRenderer()),
buildings_texture_(Resource::get()->getTexture("game_buildings.png")),
top_clouds_texture_(Resource::get()->getTexture("game_clouds1.png")),
bottom_clouds_texture_(Resource::get()->getTexture("game_clouds2.png")),
grass_texture_(Resource::get()->getTexture("game_grass.png")),
gradients_texture_(Resource::get()->getTexture("game_sky_colors.png")),
rect_({0, 0, gradients_texture_->getWidth() / 2, gradients_texture_->getHeight() / 2}),
src_rect_({0, 0, 320, 240}),
dst_rect_({0, 0, 320, 240}),
base_(rect_.h),
color_(Color(param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b)),
alpha_color_text_(param.background.attenuate_alpha),
alpha_color_text_temp_(param.background.attenuate_alpha)
{ {
// Carga las texturas
buildings_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("game_buildings.png"));
top_clouds_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("game_clouds1.png"));
bottom_clouds_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("game_clouds2.png"));
grass_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("game_grass.png"));
gradients_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("game_sky_colors.png"));
// Inicializa variables // Inicializa variables
gradient_number_ = 0;
alpha_ = 0;
clouds_speed_ = 0;
transition_ = 0;
counter_ = 0;
rect_ = {0, 0, gradients_texture_->getWidth() / 2, gradients_texture_->getHeight() / 2};
src_rect_ = {0, 0, 320, 240};
dst_rect_ = {0, 0, 320, 240};
base_ = rect_.h;
color_ = {param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b};
alpha_color_text_ = alpha_color_text_temp_ = param.background.attenuate_alpha;
gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h};
gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h};
gradient_rect_[3] = {rect_.w, rect_.h, rect_.w, rect_.h};
const int top_clouds_texture_height = top_clouds_texture_->getHeight() / 4;
const int bottom_clouds_texture_height = bottom_clouds_texture_->getHeight() / 4;
for (int i = 0; i < 4; ++i)
{ {
top_clouds_rect_[i] = {0, i * top_clouds_texture_height, top_clouds_texture_->getWidth(), top_clouds_texture_height}; gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
bottom_clouds_rect_[i] = {0, i * bottom_clouds_texture_height, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_height}; gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h};
gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h};
gradient_rect_[3] = {rect_.w, rect_.h, rect_.w, rect_.h};
const int top_clouds_texture_height = top_clouds_texture_->getHeight() / 4;
const int bottom_clouds_texture_height = bottom_clouds_texture_->getHeight() / 4;
for (int i = 0; i < 4; ++i)
{
top_clouds_rect_[i] = {0, i * top_clouds_texture_height, top_clouds_texture_->getWidth(), top_clouds_texture_height};
bottom_clouds_rect_[i] = {0, i * bottom_clouds_texture_height, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_height};
}
} }
// Crea los sprites // Crea los sprites
const int top_clouds_y = base_ - 165; {
const int bottom_clouds_y = base_ - 101; const int top_clouds_y = base_ - 165;
constexpr float top_clouds_speed = 0.1f; const int bottom_clouds_y = base_ - 101;
constexpr float bottom_clouds_speed = 0.05f;
top_clouds_sprite_a_ = std::make_unique<MovingSprite>(0, top_clouds_y, rect_.w, top_clouds_texture_->getHeight(), -top_clouds_speed, 0.0f, 0.0f, 0.0f, top_clouds_texture_);
top_clouds_sprite_b_ = std::make_unique<MovingSprite>(rect_.w, top_clouds_y, rect_.w, top_clouds_texture_->getHeight(), -top_clouds_speed, 0.0f, 0.0f, 0.0f, top_clouds_texture_);
bottom_clouds_sprite_a_ = std::make_unique<MovingSprite>(0, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight(), -bottom_clouds_speed, 0.0f, 0.0f, 0.0f, bottom_clouds_texture_); top_clouds_sprite_a_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_Rect){0, top_clouds_y, rect_.w, top_clouds_texture_->getHeight()});
bottom_clouds_sprite_b_ = std::make_unique<MovingSprite>(rect_.w, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight(), -bottom_clouds_speed, 0.0f, 0.0f, 0.0f, bottom_clouds_texture_); top_clouds_sprite_b_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_Rect){rect_.w, top_clouds_y, rect_.w, top_clouds_texture_->getHeight()});
buildings_sprite_ = std::make_unique<Sprite>(0, 0, buildings_texture_->getWidth(), buildings_texture_->getHeight(), buildings_texture_); bottom_clouds_sprite_a_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_Rect){0, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight()});
gradient_sprite_ = std::make_unique<Sprite>(0, 0, rect_.w, rect_.h, gradients_texture_); bottom_clouds_sprite_b_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_Rect){rect_.w, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight()});
grass_sprite_ = std::make_unique<Sprite>(0, 0, grass_texture_->getWidth(), grass_texture_->getHeight() / 2, grass_texture_);
buildings_sprite_ = std::make_unique<Sprite>(buildings_texture_, 0, 0, buildings_texture_->getWidth(), buildings_texture_->getHeight());
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);
}
// Inicializa objetos // Inicializa objetos
top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight()); {
top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight()); constexpr float top_clouds_speed = 0.1f;
bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight()); constexpr float bottom_clouds_speed = 0.05f;
bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
buildings_sprite_->setPosY(base_ - buildings_sprite_->getHeight()); top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
grass_sprite_->setPosY(base_ - grass_sprite_->getHeight()); top_clouds_sprite_a_->setVelX(-top_clouds_speed);
top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
top_clouds_sprite_b_->setVelX(-top_clouds_speed);
bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
bottom_clouds_sprite_a_->setVelX(-bottom_clouds_speed);
bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
bottom_clouds_sprite_b_->setVelX(-bottom_clouds_speed);
buildings_sprite_->setY(base_ - buildings_sprite_->getHeight());
grass_sprite_->setY(base_ - grass_sprite_->getHeight());
}
// Crea la textura para componer el fondo // Crea la textura para componer el fondo
canvas_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h); canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(canvas_, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(canvas_, SDL_BLENDMODE_BLEND);
// 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(color_);
SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_); SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_);
@@ -102,20 +115,21 @@ void Background::update()
alpha_ = std::max((255 - (int)(255 * transition_)), 0); alpha_ = std::max((255 - (int)(255 * transition_)), 0);
// Incrementa el contador // Incrementa el contador
counter_++; ++counter_;
// Compone todos los elementos del fondo en la textura
fillCanvas(); fillCanvas();
} }
// Dibuja el gradiente de fondo // Dibuja el gradiente de fondo
void Background::renderGradient() void Background::renderGradient()
{ {
// Dibuja el gradiente 2 // Dibuja el gradiente de detras
gradients_texture_->setAlpha(255); gradients_texture_->setAlpha(255);
gradient_sprite_->setSpriteClip(gradient_rect_[(gradient_number_ + 1) % 4]); gradient_sprite_->setSpriteClip(gradient_rect_[(gradient_number_ + 1) % 4]);
gradient_sprite_->render(); gradient_sprite_->render();
// Dibuja el gradiente 1 con una opacidad cada vez menor // Dibuja el gradiente de delante con una opacidad cada vez menor
gradients_texture_->setAlpha(alpha_); gradients_texture_->setAlpha(alpha_);
gradient_sprite_->setSpriteClip(gradient_rect_[gradient_number_]); gradient_sprite_->setSpriteClip(gradient_rect_[gradient_number_]);
gradient_sprite_->render(); gradient_sprite_->render();
@@ -124,36 +138,36 @@ void Background::renderGradient()
// Dibuja las nubes de arriba // Dibuja las nubes de arriba
void Background::renderTopClouds() void Background::renderTopClouds()
{ {
// Dibuja el primer conjunto de nubes // Dibuja el primer conjunto de nubes, las de detras
top_clouds_texture_->setAlpha(255); top_clouds_texture_->setAlpha(255);
top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]); top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]);
top_clouds_sprite_a_->render();
top_clouds_sprite_b_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]); top_clouds_sprite_b_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]);
top_clouds_sprite_a_->render();
top_clouds_sprite_b_->render(); top_clouds_sprite_b_->render();
// Dibuja el segundo conjunto de nubes // Dibuja el segundo conjunto de nubes, las de delante
top_clouds_texture_->setAlpha(alpha_); top_clouds_texture_->setAlpha(alpha_);
top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[gradient_number_]); top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[gradient_number_]);
top_clouds_sprite_a_->render();
top_clouds_sprite_b_->setSpriteClip(top_clouds_rect_[gradient_number_]); top_clouds_sprite_b_->setSpriteClip(top_clouds_rect_[gradient_number_]);
top_clouds_sprite_a_->render();
top_clouds_sprite_b_->render(); top_clouds_sprite_b_->render();
} }
// Dibuja las nubes de abajo // Dibuja las nubes de abajo
void Background::renderBottomClouds() void Background::renderBottomClouds()
{ {
// Dibuja el primer conjunto de nubes // Dibuja el primer conjunto de nubes, las de detras
bottom_clouds_texture_->setAlpha(255); bottom_clouds_texture_->setAlpha(255);
bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]); bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]);
bottom_clouds_sprite_a_->render();
bottom_clouds_sprite_b_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]); bottom_clouds_sprite_b_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]);
bottom_clouds_sprite_a_->render();
bottom_clouds_sprite_b_->render(); bottom_clouds_sprite_b_->render();
// Dibuja el segundo conjunto de nubes // Dibuja el segundo conjunto de nubes, las de delante
bottom_clouds_texture_->setAlpha(alpha_); bottom_clouds_texture_->setAlpha(alpha_);
bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[gradient_number_]); bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[gradient_number_]);
bottom_clouds_sprite_a_->render();
bottom_clouds_sprite_b_->setSpriteClip(bottom_clouds_rect_[gradient_number_]); bottom_clouds_sprite_b_->setSpriteClip(bottom_clouds_rect_[gradient_number_]);
bottom_clouds_sprite_a_->render();
bottom_clouds_sprite_b_->render(); bottom_clouds_sprite_b_->render();
} }
@@ -218,9 +232,7 @@ void Background::setGradientNumber(int value)
// Ajusta el valor de la variable // Ajusta el valor de la variable
void Background::setTransition(float value) void Background::setTransition(float value)
{ {
value = std::min(value, 1.0f); transition_ = std::clamp(value, 0.0f, 1.0f);
value = std::max(value, 0.0f);
transition_ = value;
} }
// Establece la posición del objeto // Establece la posición del objeto
@@ -235,18 +247,6 @@ void Background::setPos(SDL_Rect pos)
src_rect_.h = pos.h; src_rect_.h = pos.h;
} }
// Ajusta el valor de la variable
void Background::setSrcRect(SDL_Rect value)
{
src_rect_ = value;
}
// Ajusta el valor de la variable
void Background::setDstRect(SDL_Rect value)
{
dst_rect_ = value;
}
// Establece el color_ de atenuación // Establece el color_ de atenuación
void Background::setColor(Color color) void Background::setColor(Color color)
{ {
@@ -266,13 +266,10 @@ void Background::setColor(Color color)
void Background::setAlpha(int alpha) void Background::setAlpha(int alpha)
{ {
// Evita que se asignen valores fuera de rango // Evita que se asignen valores fuera de rango
alpha_ = std::min(alpha, 255); alpha_ = std::clamp(alpha, 0, 255);
alpha_ = std::max(alpha, 0);
// Guarda el valor actual // Guarda el valor actual y establece el nuevo valor
alpha_color_text_temp_ = alpha_color_text_; alpha_color_text_temp_ = alpha_color_text_;
// Establece el nuevo valor
alpha_color_text_ = alpha_; alpha_color_text_ = alpha_;
} }
@@ -300,10 +297,10 @@ void Background::updateClouds()
bottom_clouds_sprite_b_->setVelX(clouds_speed_ / 2); bottom_clouds_sprite_b_->setVelX(clouds_speed_ / 2);
// Mueve las nubes // Mueve las nubes
top_clouds_sprite_a_->move(); top_clouds_sprite_a_->update();
top_clouds_sprite_b_->move(); top_clouds_sprite_b_->update();
bottom_clouds_sprite_a_->move(); bottom_clouds_sprite_a_->update();
bottom_clouds_sprite_b_->move(); bottom_clouds_sprite_b_->update();
// Calcula el offset de las nubes // Calcula el offset de las nubes
if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth()) if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth())

View File

@@ -1,12 +1,12 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture
#include "utils.h" // for Color #include <memory> // para unique_ptr, shared_ptr
#include "moving_sprite.h" #include "utils.h" // para Color
#include "sprite.h" class MovingSprite;
#include "texture.h" class Sprite;
#include <memory> class Texture;
/* /*
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
@@ -32,12 +32,6 @@
- setTransition(float value) - setTransition(float value)
Porcentaje (entre 0.0f (textura actual) y 1.0f (textura siguiente)) para mostrar entre la textura de fondo actual y la siguiente Porcentaje (entre 0.0f (textura actual) y 1.0f (textura siguiente)) para mostrar entre la textura de fondo actual y la siguiente
- setSrcRect(SDL_Rect value)
Rectangulo de la textura de fondo que se desea mostrar
- setDstRecr(SDL_Rect value)
Rectangulo de destino donde se mostrará el rectángulo antrior. Automaticamente modifica srcRect para coincidor en tamaño con el destino.
- setColor(Color color) - setColor(Color color)
Establece el color de la textura de superposición Establece el color de la textura de superposición
@@ -74,11 +68,11 @@ private:
SDL_Rect gradient_rect_[4]; // Vector con las coordenadas de los 4 degradados para el cielo SDL_Rect gradient_rect_[4]; // Vector con las coordenadas de los 4 degradados para el cielo
SDL_Rect top_clouds_rect_[4]; // Vector con las coordenadas de los 4 nubes de arriba SDL_Rect top_clouds_rect_[4]; // Vector con las coordenadas de los 4 nubes de arriba
SDL_Rect bottom_clouds_rect_[4]; // Vector con las coordenadas de los 4 nubes de abajo SDL_Rect bottom_clouds_rect_[4]; // Vector con las coordenadas de los 4 nubes de abajo
int gradient_number_; // Indica el número de degradado de fondo que se va a dibujar int gradient_number_ = 0; // Indica el número de degradado de fondo que se va a dibujar
int alpha_; // Transparencia entre los dos degradados int alpha_ = 0; // Transparencia entre los dos degradados
float clouds_speed_; // Velocidad a la que se desplazan las nubes float clouds_speed_ = 0; // Velocidad a la que se desplazan las nubes
float transition_; // Nivel de transición del fondo 0..1 float transition_ = 0; // Nivel de transición del fondo 0..1
int counter_; // Contador interno int counter_ = 0; // Contador interno
SDL_Rect rect_; // Tamaño del objeto fondo SDL_Rect rect_; // Tamaño del objeto fondo
SDL_Rect src_rect_; // Parte del objeto fondo que se va a dibujará en pantalla SDL_Rect 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
@@ -107,7 +101,7 @@ private:
public: public:
// Constructor // Constructor
Background(SDL_Renderer *renderer); Background();
// Destructor // Destructor
~Background(); ~Background();
@@ -133,12 +127,6 @@ public:
// Ajusta el valor de la variable // Ajusta el valor de la variable
void setTransition(float value); void setTransition(float value);
// Ajusta el valor de la variable
void setSrcRect(SDL_Rect value);
// Ajusta el valor de la variable
void setDstRect(SDL_Rect value);
// Establece el color de atenuación // Establece el color de atenuación
void setColor(Color color); void setColor(Color color);

File diff suppressed because it is too large Load Diff

View File

@@ -1,42 +1,38 @@
#pragma once #pragma once
#include <SDL2/SDL_stdinc.h> // for Uint8, Uint16, Uint32 #include <SDL2/SDL_stdinc.h> // Para Uint8, Uint16, Uint32
#include <string> // for string #include <memory> // Para shared_ptr, unique_ptr
#include <vector> // for vector #include <string> // Para string
#include <memory> #include <vector> // Para vector
#include "utils.h" // for Circle #include "animated_sprite.h" // Para AnimatedSprite
#include "animated_sprite.h" #include "utils.h" // Para Circle
#include "texture.h" class Texture; // lines 10-10
// Cantidad de elementos del vector con los valores de la deformación del globo al rebotar // Cantidad de elementos del vector con los valores de la deformación del globo al rebotar
constexpr int MAX_BOUNCE = 10; constexpr int MAX_BOUNCE = 10;
// Tipos de globo
constexpr int BALLOON_1 = 1;
constexpr int BALLOON_2 = 2;
constexpr int BALLOON_3 = 3;
constexpr int BALLOON_4 = 4;
constexpr int HEXAGON_1 = 5;
constexpr int HEXAGON_2 = 6;
constexpr int HEXAGON_3 = 7;
constexpr int HEXAGON_4 = 8;
constexpr int POWER_BALL = 9;
// Puntos de globo // Puntos de globo
constexpr int BALLOON_SCORE_1 = 50; constexpr int BALLOON_SCORE[] = {50, 100, 200, 400};
constexpr int BALLOON_SCORE_2 = 100; constexpr int BALLOON_POWER[] = {1, 3, 7, 15};
constexpr int BALLOON_SCORE_3 = 200; constexpr int BALLOON_MENACE[] = {1, 2, 4, 8};
constexpr int BALLOON_SCORE_4 = 400; constexpr int BALLOON_SIZE[] = {10, 16, 26, 46};
// Tamaños de globo // Tamaños de globo
constexpr int BALLOON_SIZE_1 = 1; enum class BalloonSize : Uint8
constexpr int BALLOON_SIZE_2 = 2; {
constexpr int BALLOON_SIZE_3 = 3; SIZE1 = 0,
constexpr int BALLOON_SIZE_4 = 4; SIZE2 = 1,
SIZE3 = 2,
SIZE4 = 3,
};
// Clases de globo // Clases de globo
constexpr int BALLOON_CLASS = 0; enum class BalloonType : Uint8
constexpr int HEXAGON_CLASS = 1; {
BALLOON = 0,
FLOATER = 1,
POWERBALL = 2,
};
// Velocidad del globo // Velocidad del globo
constexpr float BALLOON_VELX_POSITIVE = 0.7f; constexpr float BALLOON_VELX_POSITIVE = 0.7f;
@@ -47,21 +43,8 @@ constexpr int BALLOON_MOVING_ANIMATION = 0;
constexpr int BALLOON_POP_ANIMATION = 1; constexpr int BALLOON_POP_ANIMATION = 1;
constexpr int BALLOON_BORN_ANIMATION = 2; constexpr int BALLOON_BORN_ANIMATION = 2;
// Cantidad posible de globos
constexpr int MAX_BALLOONS = 100;
// Velocidades a las que se mueven los globos // Velocidades a las que se mueven los globos
constexpr float BALLOON_SPEED_1 = 0.60f; constexpr float BALLOON_SPEED[] = {0.60f, 0.70f, 0.80f, 0.90f, 1.00f};
constexpr float BALLOON_SPEED_2 = 0.70f;
constexpr float BALLOON_SPEED_3 = 0.80f;
constexpr float BALLOON_SPEED_4 = 0.90f;
constexpr float BALLOON_SPEED_5 = 1.00f;
// Tamaño de los globos
constexpr int BALLOON_WIDTH_1 = 10;
constexpr int BALLOON_WIDTH_2 = 16;
constexpr int BALLOON_WIDTH_3 = 26;
constexpr int BALLOON_WIDTH_4 = 46;
// PowerBall // PowerBall
constexpr int POWERBALL_SCREENPOWER_MINIMUM = 10; constexpr int POWERBALL_SCREENPOWER_MINIMUM = 10;
@@ -71,61 +54,78 @@ constexpr int POWERBALL_COUNTER = 8;
class Balloon class Balloon
{ {
private: private:
// Estructura para las variables para el efecto de los rebotes // Estructura para el efecto de los rebotes en los globos
struct Bouncing struct Bouncing
{ {
bool enabled; // Si el efecto está activo bool enabled = false; // Si el efecto está activo
Uint8 counter; // Countador para el efecto Uint8 counter = 0; // Contador para el efecto
Uint8 speed; // Velocidad a la que transcurre el efecto Uint8 speed = 2; // Velocidad a la que transcurre el efecto
float zoomW; // Zoom aplicado a la anchura float zoomW = 1.0f; // Zoom aplicado a la anchura
float zoomH; // Zoom aplicado a la altura float zoomH = 1.0f; // Zoom aplicado a la altura
float despX; // Desplazamiento de pixeles en el eje X antes de pintar el objeto con zoom float despX = 0.0f; // Desplazamiento de pixeles en el eje X antes de pintar el objeto con zoom
float despY; // Desplazamiento de pixeles en el eje Y antes de pintar el objeto con zoom float despY = 0.0f; // Desplazamiento de pixeles en el eje Y antes de pintar el objeto con zoom
std::vector<float> w; // Vector con los valores de zoom para el ancho del globo
std::vector<float> h; // Vector con los valores de zoom para el alto del globo float w[MAX_BOUNCE] = {1.10f, 1.05f, 1.00f, 0.95f, 0.90f, 0.95f, 1.00f, 1.02f, 1.05f, 1.02f}; // Vector con los valores de zoom para el ancho del globo
}; float h[MAX_BOUNCE] = {0.90f, 0.95f, 1.00f, 1.05f, 1.10f, 1.05f, 1.00f, 0.98f, 0.95f, 0.98f}; // Vector con los valores de zoom para el alto del globo
// Constructor por defecto
Bouncing() = default;
// Método reset
void reset()
{
counter = 0;
zoomW = 1.0f;
zoomH = 1.0f;
despX = 0.0f;
despY = 0.0f;
}
} bouncing_;
// Objetos y punteros // Objetos y punteros
std::unique_ptr<AnimatedSprite> sprite_; // Sprite del objeto globo std::unique_ptr<AnimatedSprite> sprite_; // Sprite del objeto globo
// Variables // Variables
float pos_x_; // Posición en el eje X float x_; // Posición en el eje X
float pos_y_; // Posición en el eje Y float y_; // Posición en el eje Y
Uint8 width_; // Ancho Uint8 w_; // Ancho
Uint8 height_; // Alto Uint8 h_; // Alto
float vel_x_; // Velocidad en el eje X. Cantidad de pixeles a desplazarse float vx_; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
float vel_y_; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse float vy_; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
float gravity_; // Aceleración en el eje Y. Modifica la velocidad float gravity_; // Aceleración en el eje Y. Modifica la velocidad
float default_vel_y_; // Velocidad inicial que tienen al rebotar contra el suelo float default_vy_; // Velocidad inicial que tienen al rebotar contra el suelo
float max_vel_y_; // Máxima velocidad que puede alcanzar el objeto en el eje Y float max_vy_; // Máxima velocidad que puede alcanzar el objeto en el eje Y
bool being_created_; // Indica si el globo se está creando bool being_created_; // Indica si el globo se está creando
bool blinking_; // Indica si el globo está intermitente bool enabled_ = true; // Indica si el globo esta activo
bool enabled_; // Indica si el globo esta activo bool invulnerable_; // Indica si el globo es invulnerable
bool invulnerable_; // Indica si el globo es invulnerable bool stopped_; // Indica si el globo está parado
bool stopped_; // Indica si el globo está parado bool use_reversed_colors_ = false; // Indica si se ha de usar el color secundario del globo como color principal
bool visible_; // Indica si el globo es visible Circle collider_; // Circulo de colisión del objeto
Circle collider_; // Circulo de colisión del objeto Uint16 creation_counter_; // Temporizador para controlar el estado "creandose"
Uint16 creation_counter_; // Temporizador para controlar el estado "creandose" Uint16 creation_counter_ini_; // Valor inicial para el temporizador para controlar el estado "creandose"
Uint16 creation_counter_ini_; // Valor inicial para el temporizador para controlar el estado "creandose" Uint16 score_; // Puntos que da el globo al ser destruido
Uint16 score_; // Puntos que da el globo al ser destruido BalloonType type_; // Clase de globo
Uint16 stopped_counter_; // Contador para controlar el estado "parado" BalloonSize size_; // Tamaño del globo
Uint8 kind_; // Tipo de globo Uint8 menace_; // Cantidad de amenaza que genera el globo
Uint8 menace_; // Cantidad de amenaza que genera el globo Uint32 counter_ = 0; // Contador interno
Uint32 counter_; // Contador interno float travel_y_ = 1.0f; // Distancia que ha de recorrer el globo en el eje Y antes de que se le aplique la gravedad
float travel_y_; // Distancia que ha de recorrer el globo en el eje Y antes de que se le aplique la gravedad 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 size_; // Tamaño del globo
Uint8 power_; // Cantidad de poder que alberga el globo
Bouncing bouncing_; // Contiene las variables para el efecto de rebote
// 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 updateColliders(); void shiftColliders();
// Alinea el sprite con la posición del objeto globo
void shiftSprite();
// Establece el nivel de zoom del sprite
void zoomSprite();
// Activa el efecto // Activa el efecto
void bounceStart(); void enableBounce();
// Detiene el efecto // Detiene el efecto
void bounceStop(); void disableBounce();
// Aplica el efecto // Aplica el efecto
void updateBounce(); void updateBounce();
@@ -134,20 +134,17 @@ private:
void updateState(); void updateState();
// Establece la animación correspondiente // Establece la animación correspondiente
void updateAnimation(); void setAnimation();
// Establece el valor de la variable
void setBeingCreated(bool value);
public: public:
// Constructor // Constructor
Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr<Texture> texture, std::vector<std::string> *animation); Balloon(float x, float y, BalloonType type, BalloonSize size, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation);
// Destructor // Destructor
~Balloon() = default; ~Balloon() = default;
// Centra el globo en la posición X // Centra el globo en la posición X
void allignTo(int x); void alignTo(int x);
// Pinta el globo en la pantalla // Pinta el globo en la pantalla
void render(); void render();
@@ -164,87 +161,38 @@ public:
// 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();
// Comprueba si el globo está habilitado // Detiene el globo
bool isEnabled() const; void stop();
// Obtiene del valor de la variable // Pone el globo en movimiento
void start();
// Pone el color alternativo en el globo
void useReverseColor();
// Pone el color normal en el globo
void useNormalColor();
// Getters
float getPosX() const; float getPosX() const;
// Obtiene del valor de la variable
float getPosY() const; float getPosY() const;
// Obtiene del valor de la variable
float getVelY() const;
// Obtiene del valor de la variable
int getWidth() const; int getWidth() const;
// Obtiene del valor de la variable
int getHeight() const; int getHeight() const;
BalloonSize getSize() const;
// Establece el valor de la variable BalloonType getType() const;
void setVelY(float vel_y);
// Establece el valor de la variable
void setSpeed(float speed);
// Obtiene del valor de la variable
int getKind() const;
// Obtiene del valor de la variable
Uint8 getSize() const;
// Obtiene la clase a la que pertenece el globo
Uint8 getClass() const;
// Establece el valor de la variable
void setStop(bool value);
// Obtiene del valor de la variable
bool isStopped() const;
// Establece el valor de la variable
void setBlink(bool value);
// Obtiene del valor de la variable
bool isBlinking() const;
// Establece el valor de la variable
void setVisible(bool value);
// Obtiene del valor de la variable
bool isVisible() const;
// Establece el valor de la variable
void setInvulnerable(bool value);
// Obtiene del valor de la variable
bool isInvulnerable() const;
// Obtiene del valor de la variable
bool isBeingCreated() const;
// Establece el valor de la variable
void setStoppedTimer(Uint16 time);
// Obtiene del valor de la variable
Uint16 getStoppedTimer() const;
// Obtiene del valor de la variable
Uint16 getScore() const; Uint16 getScore() const;
// Obtiene el circulo de colisión
Circle &getCollider(); Circle &getCollider();
// Obtiene le valor de la variable
Uint8 getMenace() const; Uint8 getMenace() const;
// Obtiene le valor de la variable
Uint8 getPower() const; Uint8 getPower() const;
bool isStopped() const;
// Indica si el globo se puede explotar bool isInvulnerable() const;
bool isBeingCreated() const;
bool isEnabled() const;
bool isUsingReversedColor();
bool canBePopped() const; bool canBePopped() const;
// Indica si el globo se puede destruir // Setters
bool canBeDestroyed() const; void setVelY(float vel_y);
void setSpeed(float speed);
void setInvulnerable(bool value);
}; };

View File

@@ -0,0 +1,715 @@
#include "balloon_formations.h"
#include "balloon.h" // para BALLOON_VELX_NEGATIVE, BALLOON_VELX_POSITIVE
#include "param.h" // para param
#include "utils.h" // para ParamGame, Param, Zone, BLOCK
// Constructor
BalloonFormations::BalloonFormations()
{
initBalloonFormations();
initBalloonFormationPools();
initGameStages();
}
// Inicializa las formaciones enemigas
void BalloonFormations::initBalloonFormations()
{
constexpr int y4 = -BLOCK;
const int x4_0 = param.game.play_area.rect.x;
const int x4_100 = param.game.play_area.rect.w - BALLOON_SIZE[3];
constexpr int y3 = -BLOCK;
const int x3_0 = param.game.play_area.rect.x;
const int x3_100 = param.game.play_area.rect.w - BALLOON_SIZE[2];
constexpr int y2 = -BLOCK;
const int x2_0 = param.game.play_area.rect.x;
const int x2_100 = param.game.play_area.rect.w - BALLOON_SIZE[1];
constexpr int y1 = -BLOCK;
const int x1_0 = param.game.play_area.rect.x;
const int x1_50 = param.game.play_area.center_x - (BALLOON_SIZE[0] / 2);
const int x1_100 = param.game.play_area.rect.w - BALLOON_SIZE[0];
// Inicializa a cero las variables
for (int j = 0; j < NUMBER_OF_BALLOON_FORMATIONS; ++j)
{
balloon_formation_[j].number_of_balloons = 0;
for (int i = 0; i < MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION; ++i)
{
balloon_formation_[j].init[i] = BalloonFormationParams();
}
}
constexpr int CREATION_TIME = 300;
int inc_x = 0;
int inc_time = 0;
int j = 0;
// #00 - Dos enemigos BALLOON4 uno a cada extremo
j = 0;
balloon_formation_[j].number_of_balloons = 2;
inc_x = x4_100;
inc_time = 0;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x4_0 + (i * inc_x);
balloon_formation_[j].init[i].y = y4;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE * (((i % 2) * 2) - 1);
balloon_formation_[j].init[i].size = BalloonSize::SIZE4;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME + (inc_time * i);
}
// #01 - Dos enemigos BALLOON4 uno a cada cuarto. Ambos van hacia el centro
j = 1;
balloon_formation_[j].number_of_balloons = 2;
inc_x = param.game.play_area.center_x;
inc_time = 0;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = param.game.play_area.first_quarter_x - (BALLOON_SIZE[3] / 2) + (i * inc_x);
balloon_formation_[j].init[i].y = y4;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE * (((i % 2) * 2) - 1);
balloon_formation_[j].init[i].size = BalloonSize::SIZE4;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME + (inc_time * i);
}
// #02 - Cuatro enemigos BALLOON2 uno detras del otro. A la izquierda y hacia el centro
j = 2;
balloon_formation_[j].number_of_balloons = 4;
inc_x = BALLOON_SIZE[1] + 1;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x2_0 + (i * inc_x);
balloon_formation_[j].init[i].y = y2;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE2;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #03 - Cuatro enemigos BALLOON2 uno detras del otro. A la derecha y hacia el centro
j = 3;
balloon_formation_[j].number_of_balloons = 4;
inc_x = BALLOON_SIZE[1] + 1;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x2_100 - (i * inc_x);
balloon_formation_[j].init[i].y = y2;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE2;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #04 - Tres enemigos BALLOON3. 0, 25, 50. Hacia la derecha
j = 4;
balloon_formation_[j].number_of_balloons = 3;
inc_x = BALLOON_SIZE[2] * 2;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x3_0 + (i * inc_x);
balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE3;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #05 - Tres enemigos BALLOON3. 50, 75, 100. Hacia la izquierda
j = 5;
balloon_formation_[j].number_of_balloons = 3;
inc_x = BALLOON_SIZE[2] * 2;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x3_100 - (i * inc_x);
balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE3;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #06 - Tres enemigos BALLOON3. 0, 0, 0. Hacia la derecha
j = 6;
balloon_formation_[j].number_of_balloons = 3;
inc_x = BALLOON_SIZE[2] + 1;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x3_0 + (i * inc_x);
balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE3;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #07 - Tres enemigos BALLOON3. 100, 100, 100. Hacia la izquierda
j = 7;
balloon_formation_[j].number_of_balloons = 3;
inc_x = BALLOON_SIZE[2] + 1;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x3_100 - (i * inc_x);
balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE3;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #08 - Seis enemigos BALLOON1. 0, 0, 0, 0, 0, 0. Hacia la derecha
j = 8;
balloon_formation_[j].number_of_balloons = 6;
inc_x = BALLOON_SIZE[0] + 1;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x1_0 + (i * inc_x);
balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE1;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #09 - Seis enemigos BALLOON1. 100, 100, 100, 100, 100, 100. Hacia la izquierda
j = 9;
balloon_formation_[j].number_of_balloons = 6;
inc_x = BALLOON_SIZE[0] + 1;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x1_100 - (i * inc_x);
balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE1;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #10 - Tres enemigos BALLOON4 seguidos desde la izquierda
j = 10;
balloon_formation_[j].number_of_balloons = 3;
inc_x = BALLOON_SIZE[3] + 1;
inc_time = 15;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x4_0 + (i * inc_x);
balloon_formation_[j].init[i].y = y4;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE4;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #11 - Tres enemigos BALLOON4 seguidos desde la derecha
j = 11;
balloon_formation_[j].number_of_balloons = 3;
inc_x = BALLOON_SIZE[3] + 1;
inc_time = 15;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x4_100 - (i * inc_x);
balloon_formation_[j].init[i].y = y4;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE4;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #12 - Seis enemigos BALLOON2 uno detras del otro. A la izquierda y hacia el centro
j = 12;
balloon_formation_[j].number_of_balloons = 6;
inc_x = BALLOON_SIZE[1] + 1;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x2_0 + (i * inc_x);
balloon_formation_[j].init[i].y = y2;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE2;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #13 - Seis enemigos BALLOON2 uno detras del otro. A la derecha y hacia el centro
j = 13;
balloon_formation_[j].number_of_balloons = 6;
inc_x = BALLOON_SIZE[1] + 1;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x2_100 - (i * inc_x);
balloon_formation_[j].init[i].y = y2;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE2;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #14 - Cinco enemigos BALLOON3. Hacia la derecha. Separados
j = 14;
balloon_formation_[j].number_of_balloons = 5;
inc_x = BALLOON_SIZE[2] * 2;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x3_0 + (i * inc_x);
balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE3;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #15 - Cinco enemigos BALLOON3. Hacia la izquierda. Separados
j = 15;
balloon_formation_[j].number_of_balloons = 5;
inc_x = BALLOON_SIZE[2] * 2;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x3_100 - (i * inc_x);
balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE3;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #16 - Cinco enemigos BALLOON3. Hacia la derecha. Juntos
j = 16;
balloon_formation_[j].number_of_balloons = 5;
inc_x = BALLOON_SIZE[2] + 1;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x3_0 + (i * inc_x);
balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE3;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #17 - Cinco enemigos BALLOON3. Hacia la izquierda. Juntos
j = 17;
balloon_formation_[j].number_of_balloons = 5;
inc_x = BALLOON_SIZE[2] + 1;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x3_100 - (i * inc_x);
balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE3;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #18 - Doce enemigos BALLOON1. Hacia la derecha. Juntos
j = 18;
balloon_formation_[j].number_of_balloons = 12;
inc_x = BALLOON_SIZE[0] + 1;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x1_0 + (i * inc_x);
balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE1;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #19 - Doce enemigos BALLOON1. Hacia la izquierda. Juntos
j = 19;
balloon_formation_[j].number_of_balloons = 12;
inc_x = BALLOON_SIZE[0] + 1;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
balloon_formation_[j].init[i].x = x1_100 - (i * inc_x);
balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].size = BalloonSize::SIZE1;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #20 - Dos enemigos BALLOON4 seguidos desde la izquierda/derecha. Simetricos
j = 20;
balloon_formation_[j].number_of_balloons = 4;
inc_x = BALLOON_SIZE[3] + 1;
inc_time = 0;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
const int half = balloon_formation_[j].number_of_balloons / 2;
if (i < half)
{
balloon_formation_[j].init[i].x = x4_0 + (i * inc_x);
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
}
else
{
balloon_formation_[j].init[i].x = x4_100 - ((i - half) * inc_x);
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
}
balloon_formation_[j].init[i].y = y4;
balloon_formation_[j].init[i].size = BalloonSize::SIZE4;
balloon_formation_[j].init[i].creation_counter = CREATION_TIME + (inc_time * i);
}
// #21 - Diez enemigos BALLOON2 uno detras del otro. Izquierda/derecha. Simetricos
j = 21;
balloon_formation_[j].number_of_balloons = 10;
inc_x = BALLOON_SIZE[1] + 1;
inc_time = 3;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
const int half = balloon_formation_[j].number_of_balloons / 2;
if (i < half)
{
balloon_formation_[j].init[i].x = x2_0 + (i * inc_x);
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * i);
}
else
{
balloon_formation_[j].init[i].x = x2_100 - ((i - half) * inc_x);
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * (i - half));
}
balloon_formation_[j].init[i].y = y2;
balloon_formation_[j].init[i].size = BalloonSize::SIZE2;
}
// #22 - Diez enemigos BALLOON3. Hacia la derecha/izquierda. Separados. Simetricos
j = 22;
balloon_formation_[j].number_of_balloons = 10;
inc_x = BALLOON_SIZE[2] * 2;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
const int half = balloon_formation_[j].number_of_balloons / 2;
if (i < half)
{
balloon_formation_[j].init[i].x = x3_0 + (i * inc_x);
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * i);
}
else
{
balloon_formation_[j].init[i].x = x3_100 - ((i - half) * inc_x);
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * (i - half));
}
balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].size = BalloonSize::SIZE3;
}
// #23 - Diez enemigos BALLOON3. Hacia la derecha. Juntos. Simetricos
j = 23;
balloon_formation_[j].number_of_balloons = 10;
inc_x = BALLOON_SIZE[2] + 1;
inc_time = 10;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
const int half = balloon_formation_[j].number_of_balloons / 2;
if (i < half)
{
balloon_formation_[j].init[i].x = x3_0 + (i * inc_x);
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * i);
}
else
{
balloon_formation_[j].init[i].x = x3_100 - ((i - half) * inc_x);
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * (i - half));
}
balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].size = BalloonSize::SIZE3;
}
// #24 - Treinta enemigos BALLOON1. Del centro hacia los extremos. Juntos. Simetricos
j = 24;
balloon_formation_[j].number_of_balloons = 30;
inc_time = 5;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
const int half = balloon_formation_[j].number_of_balloons / 2;
if (i < half)
{
balloon_formation_[j].init[i].x = x1_50;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) + (inc_time * i);
}
else
{
balloon_formation_[j].init[i].x = x1_50;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) + (inc_time * (i - half));
}
balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].size = BalloonSize::SIZE1;
}
// #25 - Treinta enemigos BALLOON1. Del centro hacia adentro. Juntos. Simetricos
j = 25;
balloon_formation_[j].number_of_balloons = 30;
inc_time = 5;
for (int i = 0; i < balloon_formation_[j].number_of_balloons; i++)
{
const int half = balloon_formation_[j].number_of_balloons / 2;
if (i < half)
{
balloon_formation_[j].init[i].x = x1_50 + 20;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * i);
}
else
{
balloon_formation_[j].init[i].x = x1_50 - 20;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * (i - half));
}
balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].size = BalloonSize::SIZE1;
}
// Crea las mismas formaciones pero con hexagonos a partir de la posición 50 del vector
for (int k = 0; k < j + 1; k++)
{
balloon_formation_[k + 50].number_of_balloons = balloon_formation_[k].number_of_balloons;
for (int i = 0; i < balloon_formation_[k + 50].number_of_balloons; i++)
{
balloon_formation_[k + 50].init[i].x = balloon_formation_[k].init[i].x;
balloon_formation_[k + 50].init[i].y = balloon_formation_[k].init[i].y;
balloon_formation_[k + 50].init[i].vel_x = balloon_formation_[k].init[i].vel_x;
balloon_formation_[k + 50].init[i].creation_counter = balloon_formation_[k].init[i].creation_counter;
balloon_formation_[k + 50].init[i].size = balloon_formation_[k].init[i].size;
balloon_formation_[k + 50].init[i].type = BalloonType::FLOATER;
}
}
// TEST
balloon_formation_[99].number_of_balloons = 4;
balloon_formation_[99].init[0].x = 10;
balloon_formation_[99].init[0].y = y1;
balloon_formation_[99].init[0].vel_x = 0;
balloon_formation_[99].init[0].size = BalloonSize::SIZE1;
balloon_formation_[99].init[0].creation_counter = 200;
balloon_formation_[99].init[1].x = 50;
balloon_formation_[99].init[1].y = y1;
balloon_formation_[99].init[1].vel_x = 0;
balloon_formation_[99].init[1].size = BalloonSize::SIZE2;
balloon_formation_[99].init[1].creation_counter = 200;
balloon_formation_[99].init[2].x = 90;
balloon_formation_[99].init[2].y = y1;
balloon_formation_[99].init[2].vel_x = 0;
balloon_formation_[99].init[2].size = BalloonSize::SIZE3;
balloon_formation_[99].init[2].creation_counter = 200;
balloon_formation_[99].init[3].x = 140;
balloon_formation_[99].init[3].y = y1;
balloon_formation_[99].init[3].vel_x = 0;
balloon_formation_[99].init[3].size = BalloonSize::SIZE4;
balloon_formation_[99].init[3].creation_counter = 200;
}
// Inicializa los conjuntos de formaciones
void BalloonFormations::initBalloonFormationPools()
{
// EnemyPool #0
balloon_formation_pool_[0].set[0] = balloon_formation_[0];
balloon_formation_pool_[0].set[1] = balloon_formation_[1];
balloon_formation_pool_[0].set[2] = balloon_formation_[2];
balloon_formation_pool_[0].set[3] = balloon_formation_[3];
balloon_formation_pool_[0].set[4] = balloon_formation_[4];
balloon_formation_pool_[0].set[5] = balloon_formation_[5];
balloon_formation_pool_[0].set[6] = balloon_formation_[6];
balloon_formation_pool_[0].set[7] = balloon_formation_[7];
balloon_formation_pool_[0].set[8] = balloon_formation_[8];
balloon_formation_pool_[0].set[9] = balloon_formation_[9];
// EnemyPool #1
balloon_formation_pool_[1].set[0] = balloon_formation_[10];
balloon_formation_pool_[1].set[1] = balloon_formation_[11];
balloon_formation_pool_[1].set[2] = balloon_formation_[12];
balloon_formation_pool_[1].set[3] = balloon_formation_[13];
balloon_formation_pool_[1].set[4] = balloon_formation_[14];
balloon_formation_pool_[1].set[5] = balloon_formation_[15];
balloon_formation_pool_[1].set[6] = balloon_formation_[16];
balloon_formation_pool_[1].set[7] = balloon_formation_[17];
balloon_formation_pool_[1].set[8] = balloon_formation_[18];
balloon_formation_pool_[1].set[9] = balloon_formation_[19];
// EnemyPool #2
balloon_formation_pool_[2].set[0] = balloon_formation_[0];
balloon_formation_pool_[2].set[1] = balloon_formation_[1];
balloon_formation_pool_[2].set[2] = balloon_formation_[2];
balloon_formation_pool_[2].set[3] = balloon_formation_[3];
balloon_formation_pool_[2].set[4] = balloon_formation_[4];
balloon_formation_pool_[2].set[5] = balloon_formation_[55];
balloon_formation_pool_[2].set[6] = balloon_formation_[56];
balloon_formation_pool_[2].set[7] = balloon_formation_[57];
balloon_formation_pool_[2].set[8] = balloon_formation_[58];
balloon_formation_pool_[2].set[9] = balloon_formation_[59];
// EnemyPool #3
balloon_formation_pool_[3].set[0] = balloon_formation_[50];
balloon_formation_pool_[3].set[1] = balloon_formation_[51];
balloon_formation_pool_[3].set[2] = balloon_formation_[52];
balloon_formation_pool_[3].set[3] = balloon_formation_[53];
balloon_formation_pool_[3].set[4] = balloon_formation_[54];
balloon_formation_pool_[3].set[5] = balloon_formation_[5];
balloon_formation_pool_[3].set[6] = balloon_formation_[6];
balloon_formation_pool_[3].set[7] = balloon_formation_[7];
balloon_formation_pool_[3].set[8] = balloon_formation_[8];
balloon_formation_pool_[3].set[9] = balloon_formation_[9];
// EnemyPool #4
balloon_formation_pool_[4].set[0] = balloon_formation_[60];
balloon_formation_pool_[4].set[1] = balloon_formation_[61];
balloon_formation_pool_[4].set[2] = balloon_formation_[62];
balloon_formation_pool_[4].set[3] = balloon_formation_[63];
balloon_formation_pool_[4].set[4] = balloon_formation_[64];
balloon_formation_pool_[4].set[5] = balloon_formation_[65];
balloon_formation_pool_[4].set[6] = balloon_formation_[66];
balloon_formation_pool_[4].set[7] = balloon_formation_[67];
balloon_formation_pool_[4].set[8] = balloon_formation_[68];
balloon_formation_pool_[4].set[9] = balloon_formation_[69];
// EnemyPool #5
balloon_formation_pool_[5].set[0] = balloon_formation_[10];
balloon_formation_pool_[5].set[1] = balloon_formation_[61];
balloon_formation_pool_[5].set[2] = balloon_formation_[12];
balloon_formation_pool_[5].set[3] = balloon_formation_[63];
balloon_formation_pool_[5].set[4] = balloon_formation_[14];
balloon_formation_pool_[5].set[5] = balloon_formation_[65];
balloon_formation_pool_[5].set[6] = balloon_formation_[16];
balloon_formation_pool_[5].set[7] = balloon_formation_[67];
balloon_formation_pool_[5].set[8] = balloon_formation_[18];
balloon_formation_pool_[5].set[9] = balloon_formation_[69];
// EnemyPool #6
balloon_formation_pool_[6].set[0] = balloon_formation_[60];
balloon_formation_pool_[6].set[1] = balloon_formation_[11];
balloon_formation_pool_[6].set[2] = balloon_formation_[62];
balloon_formation_pool_[6].set[3] = balloon_formation_[13];
balloon_formation_pool_[6].set[4] = balloon_formation_[64];
balloon_formation_pool_[6].set[5] = balloon_formation_[15];
balloon_formation_pool_[6].set[6] = balloon_formation_[66];
balloon_formation_pool_[6].set[7] = balloon_formation_[17];
balloon_formation_pool_[6].set[8] = balloon_formation_[68];
balloon_formation_pool_[6].set[9] = balloon_formation_[19];
// EnemyPool #7
balloon_formation_pool_[7].set[0] = balloon_formation_[20];
balloon_formation_pool_[7].set[1] = balloon_formation_[21];
balloon_formation_pool_[7].set[2] = balloon_formation_[22];
balloon_formation_pool_[7].set[3] = balloon_formation_[23];
balloon_formation_pool_[7].set[4] = balloon_formation_[24];
balloon_formation_pool_[7].set[5] = balloon_formation_[65];
balloon_formation_pool_[7].set[6] = balloon_formation_[66];
balloon_formation_pool_[7].set[7] = balloon_formation_[67];
balloon_formation_pool_[7].set[8] = balloon_formation_[68];
balloon_formation_pool_[7].set[9] = balloon_formation_[69];
// EnemyPool #8
balloon_formation_pool_[8].set[0] = balloon_formation_[70];
balloon_formation_pool_[8].set[1] = balloon_formation_[71];
balloon_formation_pool_[8].set[2] = balloon_formation_[72];
balloon_formation_pool_[8].set[3] = balloon_formation_[73];
balloon_formation_pool_[8].set[4] = balloon_formation_[74];
balloon_formation_pool_[8].set[5] = balloon_formation_[15];
balloon_formation_pool_[8].set[6] = balloon_formation_[16];
balloon_formation_pool_[8].set[7] = balloon_formation_[17];
balloon_formation_pool_[8].set[8] = balloon_formation_[18];
balloon_formation_pool_[8].set[9] = balloon_formation_[19];
// EnemyPool #9
balloon_formation_pool_[9].set[0] = balloon_formation_[20];
balloon_formation_pool_[9].set[1] = balloon_formation_[21];
balloon_formation_pool_[9].set[2] = balloon_formation_[22];
balloon_formation_pool_[9].set[3] = balloon_formation_[23];
balloon_formation_pool_[9].set[4] = balloon_formation_[24];
balloon_formation_pool_[9].set[5] = balloon_formation_[70];
balloon_formation_pool_[9].set[6] = balloon_formation_[71];
balloon_formation_pool_[9].set[7] = balloon_formation_[72];
balloon_formation_pool_[9].set[8] = balloon_formation_[73];
balloon_formation_pool_[9].set[9] = balloon_formation_[74];
}
// Inicializa las fases del juego
void BalloonFormations::initGameStages()
{
// STAGE 1
stage_[0].number = 1;
stage_[0].power_to_complete = 200;
stage_[0].min_menace = 7 + (4 * 1);
stage_[0].max_menace = 7 + (4 * 3);
stage_[0].balloon_pool = balloon_formation_pool_[0];
// STAGE 2
stage_[1].number = 2;
stage_[1].power_to_complete = 300;
stage_[1].min_menace = 7 + (4 * 2);
stage_[1].max_menace = 7 + (4 * 4);
stage_[1].balloon_pool = balloon_formation_pool_[1];
// STAGE 3
stage_[2].number = 3;
stage_[2].power_to_complete = 600;
stage_[2].min_menace = 7 + (4 * 3);
stage_[2].max_menace = 7 + (4 * 5);
stage_[2].balloon_pool = balloon_formation_pool_[2];
// STAGE 4
stage_[3].number = 4;
stage_[3].power_to_complete = 600;
stage_[3].min_menace = 7 + (4 * 3);
stage_[3].max_menace = 7 + (4 * 5);
stage_[3].balloon_pool = balloon_formation_pool_[3];
// STAGE 5
stage_[4].number = 5;
stage_[4].power_to_complete = 600;
stage_[4].min_menace = 7 + (4 * 4);
stage_[4].max_menace = 7 + (4 * 6);
stage_[4].balloon_pool = balloon_formation_pool_[4];
// STAGE 6
stage_[5].number = 6;
stage_[5].power_to_complete = 600;
stage_[5].min_menace = 7 + (4 * 4);
stage_[5].max_menace = 7 + (4 * 6);
stage_[5].balloon_pool = balloon_formation_pool_[5];
// STAGE 7
stage_[6].number = 7;
stage_[6].power_to_complete = 650;
stage_[6].min_menace = 7 + (4 * 5);
stage_[6].max_menace = 7 + (4 * 7);
stage_[6].balloon_pool = balloon_formation_pool_[6];
// STAGE 8
stage_[7].number = 8;
stage_[7].power_to_complete = 750;
stage_[7].min_menace = 7 + (4 * 5);
stage_[7].max_menace = 7 + (4 * 7);
stage_[7].balloon_pool = balloon_formation_pool_[7];
// STAGE 9
stage_[8].number = 9;
stage_[8].power_to_complete = 850;
stage_[8].min_menace = 7 + (4 * 6);
stage_[8].max_menace = 7 + (4 * 8);
stage_[8].balloon_pool = balloon_formation_pool_[8];
// STAGE 10
stage_[9].number = 10;
stage_[9].power_to_complete = 950;
stage_[9].min_menace = 7 + (4 * 7);
stage_[9].max_menace = 7 + (4 * 10);
stage_[9].balloon_pool = balloon_formation_pool_[9];
}
// Devuelve una fase
Stage BalloonFormations::getStage(int index) const
{
return stage_[index];
}

View File

@@ -0,0 +1,75 @@
#pragma once
#include "balloon.h"
constexpr int NUMBER_OF_BALLOON_FORMATIONS = 100;
constexpr int MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION = 50;
constexpr int NUMBER_OF_SETS_PER_POOL = 10;
constexpr int NUMBER_OF_STAGES = 10;
// Estructuras
struct BalloonFormationParams
{
int x = 0; // Posición en el eje X donde crear el globo
int y = 0; // Posición en el eje Y donde crear el globo
float vel_x = 0.0f; // Velocidad inicial en el eje X
BalloonType type = BalloonType::BALLOON; // Tipo de globo
BalloonSize size = BalloonSize::SIZE1; // Tamaño de globo
int creation_counter = 0; // Temporizador para la creación del globo
// Constructor por defecto
BalloonFormationParams() = default;
// Constructor con parámetros
BalloonFormationParams(int x_val, int y_val, float vel_x_val, BalloonType type_val, BalloonSize size_val, int creation_counter_val)
: x(x_val), y(y_val), vel_x(vel_x_val), type(type_val), size(size_val), creation_counter(creation_counter_val) {}
};
struct BalloonFormationUnit // Contiene la información de una formación enemiga
{
int number_of_balloons; // Cantidad de globos que forman la formación
BalloonFormationParams init[MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION]; // Vector con todas las inicializaciones de los globos de la formación
};
struct BalloonFormationPool
{
BalloonFormationUnit set[NUMBER_OF_SETS_PER_POOL]; // Conjunto de formaciones de globos
};
struct Stage // Contiene todas las variables relacionadas con una fase
{
BalloonFormationPool balloon_pool; // El conjunto de formaciones de globos de la fase
int power_to_complete; // Cantidad de poder que se necesita para completar la fase
int max_menace; // Umbral máximo de amenaza de la fase
int min_menace; // Umbral mínimo de amenaza de la fase
int number; // Número de fase
};
// Clase BalloonFormations, para gestionar las formaciones de globos
class BalloonFormations
{
private:
// Variables
Stage stage_[NUMBER_OF_STAGES]; // Variable con los datos de cada pantalla
BalloonFormationUnit balloon_formation_[NUMBER_OF_BALLOON_FORMATIONS]; // Vector con todas las formaciones enemigas
BalloonFormationPool balloon_formation_pool_[NUMBER_OF_STAGES]; // Variable con los diferentes conjuntos de formaciones enemigas
// Inicializa las formaciones enemigas
void initBalloonFormations();
// Inicializa los conjuntos de formaciones
void initBalloonFormationPools();
// Inicializa las fases del juego
void initGameStages();
public:
// Constructor
BalloonFormations();
// Destructor
~BalloonFormations() = default;
// Devuelve una fase
Stage getStage(int index) const;
};

View File

@@ -1,29 +1,27 @@
#include "bullet.h" #include "bullet.h"
#include "param.h" // for param #include <SDL2/SDL_rect.h> // Para SDL_Rect
#include "sprite.h" // for Sprite #include <memory> // Para unique_ptr, make_unique, shared_ptr
#include <memory> // for std::unique_ptr #include "param.h" // Para Param, ParamGame, param
#include "sprite.h" // Para Sprite
// Constantes evaluables en tiempo de compilación class Texture; // lines 5-5
constexpr int BULLET_WIDTH = 12;
constexpr int BULLET_HEIGHT = 12;
constexpr int BULLET_VELY = -3;
constexpr int BULLET_VELX_LEFT = -2;
constexpr int BULLET_VELX_RIGHT = 2;
// Constructor // Constructor
Bullet::Bullet(int x, int y, BulletType kind_, bool poweredUp, int owner, SDL_Rect *play_area, std::shared_ptr<Texture> texture) Bullet::Bullet(int x, int y, BulletType bullet_type, bool powered_up, int owner, std::shared_ptr<Texture> texture)
: pos_x_(x), pos_y_(y), width_(BULLET_WIDTH), height_(BULLET_HEIGHT), vel_x_(0), vel_y_(BULLET_VELY), : sprite_(std::make_unique<Sprite>(texture, SDL_Rect{x, y, BULLET_WIDTH_, BULLET_HEIGHT_})),
kind_(kind_), owner_(owner), play_area_(play_area) pos_x_(x),
pos_y_(y),
bullet_type_(bullet_type),
owner_(owner)
{ {
vel_x_ = (kind_ == BulletType::LEFT) ? BULLET_VELX_LEFT : (kind_ == BulletType::RIGHT) ? BULLET_VELX_RIGHT vel_x_ = (bullet_type_ == BulletType::LEFT) ? BULLET_VEL_X_LEFT_
: 0; : (bullet_type_ == BulletType::RIGHT) ? BULLET_VEL_X_RIGHT_
: 0;
auto sprite_offset = poweredUp ? 3 : 0; int sprite_offset = powered_up ? 3 : 0;
auto kind_index = static_cast<int>(kind_); int offset = (static_cast<int>(bullet_type) + sprite_offset) * BULLET_WIDTH_;
sprite_ = std::make_unique<Sprite>(SDL_Rect{x, y, BULLET_WIDTH, BULLET_HEIGHT}, texture); sprite_->setSpriteClip(offset, 0, BULLET_WIDTH_, BULLET_HEIGHT_);
sprite_->setSpriteClip((kind_index + sprite_offset) * width_, 0, sprite_->getWidth(), sprite_->getHeight());
collider_.r = width_ / 2; collider_.r = BULLET_WIDTH_ / 2;
shiftColliders(); shiftColliders();
} }
@@ -37,21 +35,20 @@ void Bullet::render()
BulletMoveStatus Bullet::move() BulletMoveStatus Bullet::move()
{ {
pos_x_ += vel_x_; pos_x_ += vel_x_;
if (pos_x_ < param.game.play_area.rect.x - width_ || pos_x_ > play_area_->w) if (pos_x_ < param.game.play_area.rect.x - BULLET_WIDTH_ || pos_x_ > param.game.play_area.rect.w)
{ {
disable(); disable();
return BulletMoveStatus::OUT; return BulletMoveStatus::OUT;
} }
pos_y_ += vel_y_; pos_y_ += BULLET_VEL_Y_;
if (pos_y_ < param.game.play_area.rect.y - height_) if (pos_y_ < param.game.play_area.rect.y - BULLET_HEIGHT_)
{ {
disable(); disable();
return BulletMoveStatus::OUT; return BulletMoveStatus::OUT;
} }
sprite_->setPosX(pos_x_); shiftSprite();
sprite_->setPosY(pos_y_);
shiftColliders(); shiftColliders();
return BulletMoveStatus::OK; return BulletMoveStatus::OK;
@@ -59,42 +56,12 @@ BulletMoveStatus Bullet::move()
bool Bullet::isEnabled() const bool Bullet::isEnabled() const
{ {
return kind_ != BulletType::NULL_TYPE; return bullet_type_ != BulletType::NONE;
} }
void Bullet::disable() void Bullet::disable()
{ {
kind_ = BulletType::NULL_TYPE; bullet_type_ = BulletType::NONE;
}
int Bullet::getPosX() const
{
return pos_x_;
}
int Bullet::getPosY() const
{
return pos_y_;
}
void Bullet::setPosX(int x)
{
pos_x_ = x;
}
void Bullet::setPosY(int y)
{
pos_y_ = y;
}
int Bullet::getVelY() const
{
return vel_y_;
}
BulletType Bullet::getKind() const
{
return kind_;
} }
int Bullet::getOwner() const int Bullet::getOwner() const
@@ -112,3 +79,9 @@ void Bullet::shiftColliders()
collider_.x = pos_x_ + collider_.r; collider_.x = pos_x_ + collider_.r;
collider_.y = pos_y_ + collider_.r; collider_.y = pos_y_ + collider_.r;
} }
void Bullet::shiftSprite()
{
sprite_->setX(pos_x_);
sprite_->setY(pos_y_);
}

View File

@@ -1,22 +1,21 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_stdinc.h> // Para Uint8
#include <SDL2/SDL_stdinc.h> // for Uint8 #include <memory> // Para shared_ptr, unique_ptr
#include <memory> // for unique_ptr #include "sprite.h" // Para Sprite
#include "sprite.h" // for Sprite #include "utils.h" // Para Circle
#include "utils.h" // for Circle class Texture; // lines 8-8
#include "texture.h" // lines 9-9
// Enumeración para los diferentes tipos de balas // Tipos de balas
enum class BulletType enum class BulletType : Uint8
{ {
UP, UP,
LEFT, LEFT,
RIGHT, RIGHT,
NULL_TYPE NONE
}; };
// Enumeración para los resultados del movimiento de la bala // Resultado del movimiento de la bala
enum class BulletMoveStatus : Uint8 enum class BulletMoveStatus : Uint8
{ {
OK = 0, OK = 0,
@@ -27,23 +26,29 @@ enum class BulletMoveStatus : Uint8
class Bullet class Bullet
{ {
private: private:
int pos_x_; // Posición en el eje X // Constantes
int pos_y_; // Posición en el eje Y static constexpr int BULLET_WIDTH_ = 12;
Uint8 width_; // Ancho del objeto static constexpr int BULLET_HEIGHT_ = 12;
Uint8 height_; // Alto del objeto static constexpr int BULLET_VEL_Y_ = -3;
int vel_x_; // Velocidad en el eje X static constexpr int BULLET_VEL_X_LEFT_ = -2;
int vel_y_; // Velocidad en el eje Y static constexpr int BULLET_VEL_X_RIGHT_ = 2;
BulletType kind_; // Tipo de objeto
int owner_; // Identificador del dueño del objeto
Circle collider_; // Círculo de colisión del objeto
SDL_Rect *play_area_; // Rectángulo con la zona de juego
std::unique_ptr<Sprite> sprite_; // Sprite con los gráficos y métodos de pintado std::unique_ptr<Sprite> sprite_; // Sprite con los gráficos y métodos de pintado
int pos_x_; // Posición en el eje X
int pos_y_; // Posición en el eje Y
int vel_x_; // Velocidad en el eje X
BulletType bullet_type_; // Tipo de objeto
int owner_; // Identificador del dueño del objeto
Circle collider_; // Círculo de colisión del objeto
void shiftColliders(); // Alinea el círculo de colisión con el objeto void shiftColliders(); // Alinea el círculo de colisión con el objeto
void shiftSprite(); // Alinea el sprite con el objeto
public: public:
// Constructor // Constructor
Bullet(int x, int y, BulletType kind, bool powered_up, int owner, SDL_Rect *play_area, std::shared_ptr<Texture> texture); Bullet(int x, int y, BulletType bullet_type, bool powered_up, int owner, std::shared_ptr<Texture> texture);
// Destructor // Destructor
~Bullet() = default; ~Bullet() = default;
@@ -60,17 +65,7 @@ public:
// Deshabilita el objeto // Deshabilita el objeto
void disable(); void disable();
// Obtiene la posición
int getPosX() const;
int getPosY() const;
// Establece la posición
void setPosX(int x);
void setPosY(int y);
// Obtiene parámetros // Obtiene parámetros
int getVelY() const;
BulletType getKind() const;
int getOwner() const; int getOwner() const;
Circle &getCollider(); Circle &getCollider();
}; };

View File

@@ -1,7 +1,7 @@
#include "dbgtxt.h" #include "dbgtxt.h"
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_rwops.h> // for SDL_RWFromMem #include <SDL2/SDL_rwops.h> // para SDL_RWFromMem
#include <SDL2/SDL_surface.h> // for SDL_LoadBMP_RW #include <SDL2/SDL_surface.h> // para SDL_LoadBMP_RW
namespace namespace
{ {

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_render.h> // para SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint8 #include <SDL2/SDL_stdinc.h> // para Uint8
void dbg_init(SDL_Renderer *renderer); void dbg_init(SDL_Renderer *renderer);
void dbg_print(int x, int y, const char *text, Uint8 r, Uint8 g, Uint8 b); void dbg_print(int x, int y, const char *text, Uint8 r, Uint8 g, Uint8 b);

View File

@@ -1,115 +1,91 @@
#include "define_buttons.h" #include "define_buttons.h"
#include "lang.h" // for getText #include <utility> // Para move
#include "options.h" // for options #include "input.h" // Para Input, InputType
#include "param.h" // for param #include "lang.h" // Para getText
#include "section.h" // for name, name_e, options, options_e #include "options.h" // Para OptionsController, Options, options
#include "text.h" // for Text #include "param.h" // Para Param, param, ParamGame, ParamTitle
#include "utils.h" // for OptionsController, Options, Param, ParamGame #include "section.h" // Para Name, Options, name, options
#include "text.h" // Para Text
// Constructor // Constructor
DefineButtons::DefineButtons(std::unique_ptr<Text> text) DefineButtons::DefineButtons(std::unique_ptr<Text> text_)
: text(std::move(text)) : input_(Input::get()),
text_(std::move(text_))
{ {
// Copia punteros a los objetos
input = Input::get();
// Inicializa variables // Inicializa variables
enabled = false; x_ = param.game.width / 2;
x = param.game.width / 2; y_ = param.title.press_start_position;
y = param.title.press_start_position;
indexController = 0;
indexButton = 0;
buttons.clear(); clearButtons();
db_button_t button;
button.label = lang::getText(95); for (int i = 0; i < input_->getNumControllers(); ++i)
button.input = input_fire_left;
button.button = SDL_CONTROLLER_BUTTON_X;
buttons.push_back(button);
button.label = lang::getText(96);
button.input = input_fire_center;
button.button = SDL_CONTROLLER_BUTTON_Y;
buttons.push_back(button);
button.label = lang::getText(97);
button.input = input_fire_right;
button.button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
buttons.push_back(button);
button.label = lang::getText(98);
button.input = input_start;
button.button = SDL_CONTROLLER_BUTTON_START;
buttons.push_back(button);
button.label = lang::getText(99);
button.input = input_exit;
button.button = SDL_CONTROLLER_BUTTON_BACK;
buttons.push_back(button);
for (int i = 0; i < input->getNumControllers(); ++i)
{ {
controllerNames.push_back(input->getControllerName(i)); controller_names_.emplace_back(input_->getControllerName(i));
} }
} }
// Dibuja el objeto en pantalla // Dibuja el objeto en pantalla
void DefineButtons::render() void DefineButtons::render()
{ {
if (enabled) if (enabled_)
{ {
text->writeCentered(x, y - 10, lang::getText(100) + std::to_string(options.controller[indexController].player_id)); text_->writeCentered(x_, y_ - 10, lang::getText(100) + std::to_string(options.controllers.at(index_controller_).player_id));
text->writeCentered(x, y, controllerNames[indexController]); text_->writeCentered(x_, y_, controller_names_.at(index_controller_));
text->writeCentered(x, y + 10, buttons[indexButton].label); text_->writeCentered(x_, y_ + 10, buttons_.at(index_button_).label);
} }
} }
// Comprueba el botón que se ha pulsado // Comprueba el botón que se ha pulsado
void DefineButtons::doControllerButtonDown(SDL_ControllerButtonEvent *event) void DefineButtons::doControllerButtonDown(const SDL_ControllerButtonEvent &event)
{ {
int i = input->getJoyIndex(event->which); // Solo pilla botones del mando que toca
if (input_->getJoyIndex(event.which) != static_cast<int>(index_controller_))
// Solo pillamos botones del mando que toca
if (i != indexController)
{ {
return; return;
} }
buttons[indexButton].button = (SDL_GameControllerButton)event->button; const auto button = static_cast<SDL_GameControllerButton>(event.button);
incIndexButton(); if (checkButtonNotInUse(button))
}
// Asigna los botones definidos al input
void DefineButtons::bindButtons()
{
for (int i = 0; i < (int)buttons.size(); ++i)
{ {
input->bindGameControllerButton(indexController, buttons[i].input, buttons[i].button); buttons_.at(index_button_).button = button;
incIndexButton();
} }
} }
// Comprueba las entradas // Asigna los botones definidos al input_
void DefineButtons::checkInput() void DefineButtons::bindButtons()
{ {
if (enabled) for (const auto &button : buttons_)
{
input_->bindGameControllerButton(index_controller_, button.input, button.button);
}
}
// Comprueba los eventos
void DefineButtons::checkEvents()
{
if (enabled_)
{ {
SDL_Event event; SDL_Event event;
// Comprueba los eventos que hay en la cola // Comprueba los eventos que hay en la cola
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
// Evento de salida de la aplicación switch (event.type)
if (event.type == SDL_QUIT)
{ {
section::name = section::NAME_QUIT; case SDL_QUIT:
section::options = section::OPTIONS_QUIT_NORMAL; {
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_WITH_KEYBOARD;
break; break;
} }
case SDL_CONTROLLERBUTTONDOWN:
if (event.type == SDL_CONTROLLERBUTTONDOWN)
{ {
doControllerButtonDown(&event.cbutton); doControllerButtonDown(event.cbutton);
break;
}
default:
break;
} }
} }
} }
@@ -118,11 +94,12 @@ void DefineButtons::checkInput()
// Habilita el objeto // Habilita el objeto
bool DefineButtons::enable(int index) bool DefineButtons::enable(int index)
{ {
if (index < input->getNumControllers()) if (index < input_->getNumControllers())
{ {
enabled = true; enabled_ = true;
indexController = index; index_controller_ = index;
indexButton = 0; index_button_ = 0;
clearButtons();
return true; return true;
} }
@@ -130,31 +107,24 @@ bool DefineButtons::enable(int index)
} }
// Comprueba si está habilitado // Comprueba si está habilitado
bool DefineButtons::isEnabled() bool DefineButtons::isEnabled() { return enabled_; }
{
return enabled;
}
// Incrementa el indice de los botones // Incrementa el indice de los botones
void DefineButtons::incIndexButton() void DefineButtons::incIndexButton()
{ {
indexButton++; ++index_button_;
// Comprueba si ha finalizado // Comprueba si ha finalizado
if (indexButton == (int)buttons.size()) if (index_button_ == buttons_.size())
{ {
// Asigna los botones definidos al input // Asigna los botones definidos al input_
bindButtons(); bindButtons();
// Guarda los cambios en las opciones // Guarda los cambios en las opciones
saveBindingsToOptions(); saveBindingsToOptions();
input->allActive(indexController); // Deshabilita
enabled_ = false;
// Reinicia variables
indexButton = 0;
indexController = 0;
enabled = false;
} }
} }
@@ -162,17 +132,34 @@ void DefineButtons::incIndexButton()
void DefineButtons::saveBindingsToOptions() void DefineButtons::saveBindingsToOptions()
{ {
// Modifica las opciones para colocar los valores asignados // Modifica las opciones para colocar los valores asignados
options.controller[indexController].name = input->getControllerName(indexController); auto &controller = options.controllers.at(index_controller_);
for (int j = 0; j < (int)options.controller[indexController].inputs.size(); ++j) controller.name = input_->getControllerName(index_controller_);
for (size_t j = 0; j < controller.inputs.size(); ++j)
{ {
options.controller[indexController].buttons[j] = input->getControllerBinding(indexController, options.controller[indexController].inputs[j]); controller.buttons.at(j) = input_->getControllerBinding(index_controller_, controller.inputs.at(j));
} }
} }
// Intercambia los jugadores asignados a los dos primeros mandos // Comprueba que un botón no esté ya asignado
void DefineButtons::swapControllers() bool DefineButtons::checkButtonNotInUse(SDL_GameControllerButton button)
{ {
const int temp = options.controller[0].player_id; for (const auto &b : buttons_)
options.controller[0].player_id = options.controller[1].player_id; {
options.controller[1].player_id = temp; if (b.button == button)
{
return false;
}
}
return true;
}
// Limpia la asignación de botones
void DefineButtons::clearButtons()
{
buttons_.clear();
buttons_.emplace_back(lang::getText(95), InputType::FIRE_LEFT, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(96), InputType::FIRE_CENTER, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(97), InputType::FIRE_RIGHT, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(98), InputType::START, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(99), InputType::SERVICE, SDL_CONTROLLER_BUTTON_INVALID);
} }

View File

@@ -1,18 +1,24 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_ControllerButtonEvent #include <SDL2/SDL_events.h> // Para SDL_ControllerButtonEvent
#include <SDL2/SDL_gamecontroller.h> // for SDL_GameControllerButton #include <SDL2/SDL_gamecontroller.h> // Para SDL_GameControllerButton
#include <string> // for string, basic_string #include <stddef.h> // Para size_t
#include <vector> // for vector #include <memory> // Para shared_ptr, unique_ptr
#include "input.h" // for inputs_e #include <string> // Para string
#include "text.h" #include <vector> // Para vector
#include <memory> class Input; // lines 8-8
class Text; // lines 9-9
enum class InputType : int; // lines 10-10
struct db_button_t struct DefineButtonsButton
{ {
std::string label; // Texto en pantalla para el botón std::string label; // Texto en pantalla para el botón
inputs_e input; // Input asociado InputType input; // Input asociado
SDL_GameControllerButton button; // Botón del mando correspondiente SDL_GameControllerButton button; // Botón del mando correspondiente
// Constructor
DefineButtonsButton(const std::string &lbl, InputType inp, SDL_GameControllerButton btn)
: label(lbl), input(inp), button(btn) {}
}; };
// Clase Bullet // Clase Bullet
@@ -20,23 +26,23 @@ class DefineButtons
{ {
private: private:
// Objetos // Objetos
Input *input; // Objeto pata gestionar la entrada Input *input_; // Objeto pata gestionar la entrada
std::shared_ptr<Text> text; // Objeto para escribir texto std::shared_ptr<Text> text_; // Objeto para escribir texto
// Variables // Variables
bool enabled; // Indica si el objeto está habilitado bool enabled_ = false; // Indica si el objeto está habilitado
int x; // Posición donde dibujar el texto int x_; // Posición donde dibujar el texto
int y; // Posición donde dibujar el texto int y_; // Posición donde dibujar el texto
std::vector<db_button_t> buttons; // Vector con las nuevas definiciones de botones/acciones std::vector<DefineButtonsButton> buttons_; // Vector con las nuevas definiciones de botones/acciones
int indexController; // Indice del controlador a reasignar size_t index_controller_ = 0; // Indice del controlador a reasignar
int indexButton; // Indice para saber qué bot´çon se está definiendo size_t index_button_ = 0; // Indice para saber qué botón se está definiendo
std::vector<std::string> controllerNames; // Nombres de los mandos std::vector<std::string> controller_names_; // Nombres de los mandos
// Incrementa el indice de los botones // Incrementa el indice de los botones
void incIndexButton(); void incIndexButton();
// Comprueba el botón que se ha pulsado // Comprueba el botón que se ha pulsado
void doControllerButtonDown(SDL_ControllerButtonEvent *event); void doControllerButtonDown(const SDL_ControllerButtonEvent &event);
// Asigna los botones definidos al input // Asigna los botones definidos al input
void bindButtons(); void bindButtons();
@@ -44,9 +50,15 @@ private:
// Guarda los cambios en las opciones // Guarda los cambios en las opciones
void saveBindingsToOptions(); void saveBindingsToOptions();
// Comprueba que un botón no esté ya asignado
bool checkButtonNotInUse(SDL_GameControllerButton button);
// Limpia la asignación de botones
void clearButtons();
public: public:
// Constructor // Constructor
DefineButtons(std::unique_ptr<Text> text); explicit DefineButtons(std::unique_ptr<Text> text);
// Destructor // Destructor
~DefineButtons() = default; ~DefineButtons() = default;
@@ -54,15 +66,12 @@ public:
// Dibuja el objeto en pantalla // Dibuja el objeto en pantalla
void render(); void render();
// Comprueba las entradas // Comprueba los eventos
void checkInput(); void checkEvents();
// Habilita el objeto // Habilita el objeto
bool enable(int index); bool enable(int index);
// Comprueba si está habilitado // Comprueba si está habilitado
bool isEnabled(); bool isEnabled();
// Intercambia los jugadores asignados a los dos primeros mandos
void swapControllers();
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,29 @@
#pragma once #pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_render.h> // Para SDL_Renderer
#include <SDL2/SDL_video.h> // for SDL_Window #include <SDL2/SDL_video.h> // Para SDL_Window
#include <string> // for string, basic_string #include <string> // Para string
#include <vector> // for vector namespace lang
#include "lang.h" // for lang_e {
#include "utils.h" // for MusicFile, SoundFile enum class Code : int;
} // lines 9-9
// Textos // Textos
#define WINDOW_CAPTION "Coffee Crisis Arcade Edition" constexpr char WINDOW_CAPTION[] = "Coffee Crisis Arcade Edition";
class Director class Director
{ {
private: private:
// Objetos y punteros // Objetos y punteros
SDL_Window *window; // La ventana donde dibujamos SDL_Window *window_; // La ventana donde dibujamos
SDL_Renderer *renderer; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
#ifndef VERBOSE
std::streambuf *orig_buf; // Puntero al buffer de flujo original para restaurar std::cout
#endif
// Variables // Variables
std::string executablePath; // Path del ejecutable std::string executable_path_; // Path del ejecutable
std::string systemFolder; // Carpeta del sistema donde guardar datos std::string system_folder_; // Carpeta del sistema donde guardar datos
std::string paramFileArgument; // Argumento para gestionar el fichero con los parametros del programa
std::vector<SoundFile> sounds; // Vector con los sonidos
std::vector<MusicFile> musics; // Vector con las musicas
// Inicializa jail_audio // Inicializa jail_audio
void initJailAudio(); void initJailAudio();
@@ -30,26 +31,17 @@ private:
// Arranca SDL y crea la ventana // Arranca SDL y crea la ventana
bool initSDL(); bool initSDL();
// Inicializa el objeto input // Asigna los botones y teclas al objeto Input
void initInput(); void bindInputs();
// Carga los parametros para configurar el juego
void loadParams(std::string filepath);
// Crea el indice de ficheros // Crea el indice de ficheros
bool setFileList(); void setFileList();
// Carga los sonidos del juego
void loadSounds();
// Carga las musicas del juego
void loadMusics();
// Comprueba los parametros del programa // Comprueba los parametros del programa
void checkProgramArguments(int argc, char *argv[]); void checkProgramArguments(int argc, const char *argv[]);
// Crea la carpeta del sistema donde guardar datos // Crea la carpeta del sistema donde guardar datos
void createSystemFolder(std::string folder); void createSystemFolder(const std::string &folder);
// Ejecuta la sección con el logo // Ejecuta la sección con el logo
void runLogo(); void runLogo();
@@ -72,12 +64,16 @@ private:
// Ejecuta el juego en modo demo // Ejecuta el juego en modo demo
void runDemoGame(); void runDemoGame();
// Obtiene una fichero a partir de un lang_e // Obtiene una fichero a partir de un lang::Code
std::string getLangFile(lang::lang_e lang); std::string getLangFile(lang::Code code);
#ifdef ARCADE
// Apaga el sistema
void shutdownSystem();
#endif
public: public:
// Constructor // Constructor
Director(int argc, char *argv[]); Director(int argc, const char *argv[]);
// Destructor // Destructor
~Director(); ~Director();

View File

@@ -1,720 +0,0 @@
#include "enemy_formations.h"
#include "balloon.h" // for BALLOON_VELX_NEGATIVE, BALLOON_VELX_POSITIVE
#include "param.h" // for param
#include "utils.h" // for ParamGame, Param, Zone, BLOCK
// Constructor
EnemyFormations::EnemyFormations()
{
initEnemyFormations();
initEnemyPools();
initGameStages();
}
// Inicializa las formaciones enemigas
void EnemyFormations::initEnemyFormations()
{
const int y4 = -BLOCK;
const int x4_0 = param.game.play_area.rect.x;
const int x4_100 = param.game.play_area.rect.w - BALLOON_WIDTH_4;
const int y3 = -BLOCK;
const int x3_0 = param.game.play_area.rect.x;
const int x3_100 = param.game.play_area.rect.w - BALLOON_WIDTH_3;
const int y2 = -BLOCK;
const int x2_0 = param.game.play_area.rect.x;
const int x2_100 = param.game.play_area.rect.w - BALLOON_WIDTH_2;
const int y1 = -BLOCK;
const int x1_0 = param.game.play_area.rect.x;
const int x1_50 = param.game.play_area.center_x - (BALLOON_WIDTH_1 / 2);
const int x1_100 = param.game.play_area.rect.w - BALLOON_WIDTH_1;
// Inicializa a cero las variables
for (int i = 0; i < NUMBER_OF_ENEMY_FORMATIONS; i++)
{
enemyFormation[i].numberOfEnemies = 0;
for (int j = 0; j < MAX_NUMBER_OF_ENEMIES_IN_A_FORMATION; j++)
{
enemyFormation[i].init[j].x = 0;
enemyFormation[i].init[j].y = 0;
enemyFormation[i].init[j].velX = 0;
enemyFormation[i].init[j].kind = 0;
enemyFormation[i].init[j].creationCounter = 0;
}
}
const int creationTime = 300;
int incX = 0;
int incTime = 0;
int j = 0;
// #00 - Dos enemigos BALLOON4 uno a cada extremo
j = 0;
enemyFormation[j].numberOfEnemies = 2;
incX = x4_100;
incTime = 0;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x4_0 + (i * incX);
enemyFormation[j].init[i].y = y4;
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE * (((i % 2) * 2) - 1);
enemyFormation[j].init[i].kind = BALLOON_4;
enemyFormation[j].init[i].creationCounter = creationTime + (incTime * i);
}
// #01 - Dos enemigos BALLOON4 uno a cada cuarto. Ambos van hacia el centro
j = 1;
enemyFormation[j].numberOfEnemies = 2;
incX = param.game.play_area.center_x;
incTime = 0;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = param.game.play_area.first_quarter_x - (BALLOON_WIDTH_4 / 2) + (i * incX);
enemyFormation[j].init[i].y = y4;
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE * (((i % 2) * 2) - 1);
enemyFormation[j].init[i].kind = BALLOON_4;
enemyFormation[j].init[i].creationCounter = creationTime + (incTime * i);
}
// #02 - Cuatro enemigos BALLOON2 uno detras del otro. A la izquierda y hacia el centro
j = 2;
enemyFormation[j].numberOfEnemies = 4;
incX = BALLOON_WIDTH_2 + 1;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x2_0 + (i * incX);
enemyFormation[j].init[i].y = y2;
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].kind = BALLOON_2;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #03 - Cuatro enemigos BALLOON2 uno detras del otro. A la derecha y hacia el centro
j = 3;
enemyFormation[j].numberOfEnemies = 4;
incX = BALLOON_WIDTH_2 + 1;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x2_100 - (i * incX);
enemyFormation[j].init[i].y = y2;
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].kind = BALLOON_2;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #04 - Tres enemigos BALLOON3. 0, 25, 50. Hacia la derecha
j = 4;
enemyFormation[j].numberOfEnemies = 3;
incX = BALLOON_WIDTH_3 * 2;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x3_0 + (i * incX);
enemyFormation[j].init[i].y = y3;
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].kind = BALLOON_3;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #05 - Tres enemigos BALLOON3. 50, 75, 100. Hacia la izquierda
j = 5;
enemyFormation[j].numberOfEnemies = 3;
incX = BALLOON_WIDTH_3 * 2;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x3_100 - (i * incX);
enemyFormation[j].init[i].y = y3;
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].kind = BALLOON_3;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #06 - Tres enemigos BALLOON3. 0, 0, 0. Hacia la derecha
j = 6;
enemyFormation[j].numberOfEnemies = 3;
incX = BALLOON_WIDTH_3 + 1;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x3_0 + (i * incX);
enemyFormation[j].init[i].y = y3;
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].kind = BALLOON_3;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #07 - Tres enemigos BALLOON3. 100, 100, 100. Hacia la izquierda
j = 7;
enemyFormation[j].numberOfEnemies = 3;
incX = BALLOON_WIDTH_3 + 1;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x3_100 - (i * incX);
enemyFormation[j].init[i].y = y3;
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].kind = BALLOON_3;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #08 - Seis enemigos BALLOON1. 0, 0, 0, 0, 0, 0. Hacia la derecha
j = 8;
enemyFormation[j].numberOfEnemies = 6;
incX = BALLOON_WIDTH_1 + 1;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x1_0 + (i * incX);
enemyFormation[j].init[i].y = y1;
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].kind = BALLOON_1;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #09 - Seis enemigos BALLOON1. 100, 100, 100, 100, 100, 100. Hacia la izquierda
j = 9;
enemyFormation[j].numberOfEnemies = 6;
incX = BALLOON_WIDTH_1 + 1;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x1_100 - (i * incX);
enemyFormation[j].init[i].y = y1;
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].kind = BALLOON_1;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #10 - Tres enemigos BALLOON4 seguidos desde la izquierda
j = 10;
enemyFormation[j].numberOfEnemies = 3;
incX = BALLOON_WIDTH_4 + 1;
incTime = 15;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x4_0 + (i * incX);
enemyFormation[j].init[i].y = y4;
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].kind = BALLOON_4;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #11 - Tres enemigos BALLOON4 seguidos desde la derecha
j = 11;
enemyFormation[j].numberOfEnemies = 3;
incX = BALLOON_WIDTH_4 + 1;
incTime = 15;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x4_100 - (i * incX);
enemyFormation[j].init[i].y = y4;
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].kind = BALLOON_4;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #12 - Seis enemigos BALLOON2 uno detras del otro. A la izquierda y hacia el centro
j = 12;
enemyFormation[j].numberOfEnemies = 6;
incX = BALLOON_WIDTH_2 + 1;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x2_0 + (i * incX);
enemyFormation[j].init[i].y = y2;
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].kind = BALLOON_2;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #13 - Seis enemigos BALLOON2 uno detras del otro. A la derecha y hacia el centro
j = 13;
enemyFormation[j].numberOfEnemies = 6;
incX = BALLOON_WIDTH_2 + 1;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x2_100 - (i * incX);
enemyFormation[j].init[i].y = y2;
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].kind = BALLOON_2;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #14 - Cinco enemigos BALLOON3. Hacia la derecha. Separados
j = 14;
enemyFormation[j].numberOfEnemies = 5;
incX = BALLOON_WIDTH_3 * 2;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x3_0 + (i * incX);
enemyFormation[j].init[i].y = y3;
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].kind = BALLOON_3;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #15 - Cinco enemigos BALLOON3. Hacia la izquierda. Separados
j = 15;
enemyFormation[j].numberOfEnemies = 5;
incX = BALLOON_WIDTH_3 * 2;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x3_100 - (i * incX);
enemyFormation[j].init[i].y = y3;
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].kind = BALLOON_3;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #16 - Cinco enemigos BALLOON3. Hacia la derecha. Juntos
j = 16;
enemyFormation[j].numberOfEnemies = 5;
incX = BALLOON_WIDTH_3 + 1;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x3_0 + (i * incX);
enemyFormation[j].init[i].y = y3;
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].kind = BALLOON_3;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #17 - Cinco enemigos BALLOON3. Hacia la izquierda. Juntos
j = 17;
enemyFormation[j].numberOfEnemies = 5;
incX = BALLOON_WIDTH_3 + 1;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x3_100 - (i * incX);
enemyFormation[j].init[i].y = y3;
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].kind = BALLOON_3;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #18 - Doce enemigos BALLOON1. Hacia la derecha. Juntos
j = 18;
enemyFormation[j].numberOfEnemies = 12;
incX = BALLOON_WIDTH_1 + 1;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x1_0 + (i * incX);
enemyFormation[j].init[i].y = y1;
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].kind = BALLOON_1;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #19 - Doce enemigos BALLOON1. Hacia la izquierda. Juntos
j = 19;
enemyFormation[j].numberOfEnemies = 12;
incX = BALLOON_WIDTH_1 + 1;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = x1_100 - (i * incX);
enemyFormation[j].init[i].y = y1;
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].kind = BALLOON_1;
enemyFormation[j].init[i].creationCounter = creationTime - (incTime * i);
}
// #20 - Dos enemigos BALLOON4 seguidos desde la izquierda/derecha. Simetricos
j = 20;
enemyFormation[j].numberOfEnemies = 4;
incX = BALLOON_WIDTH_4 + 1;
incTime = 0;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
const int half = enemyFormation[j].numberOfEnemies / 2;
if (i < half)
{
enemyFormation[j].init[i].x = x4_0 + (i * incX);
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
}
else
{
enemyFormation[j].init[i].x = x4_100 - ((i - half) * incX);
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
}
enemyFormation[j].init[i].y = y4;
enemyFormation[j].init[i].kind = BALLOON_4;
enemyFormation[j].init[i].creationCounter = creationTime + (incTime * i);
}
// #21 - Diez enemigos BALLOON2 uno detras del otro. Izquierda/derecha. Simetricos
j = 21;
enemyFormation[j].numberOfEnemies = 10;
incX = BALLOON_WIDTH_2 + 1;
incTime = 3;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
const int half = enemyFormation[j].numberOfEnemies / 2;
if (i < half)
{
enemyFormation[j].init[i].x = x2_0 + (i * incX);
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * i);
}
else
{
enemyFormation[j].init[i].x = x2_100 - ((i - half) * incX);
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * (i - half));
}
enemyFormation[j].init[i].y = y2;
enemyFormation[j].init[i].kind = BALLOON_2;
}
// #22 - Diez enemigos BALLOON3. Hacia la derecha/izquierda. Separados. Simetricos
j = 22;
enemyFormation[j].numberOfEnemies = 10;
incX = BALLOON_WIDTH_3 * 2;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
const int half = enemyFormation[j].numberOfEnemies / 2;
if (i < half)
{
enemyFormation[j].init[i].x = x3_0 + (i * incX);
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * i);
}
else
{
enemyFormation[j].init[i].x = x3_100 - ((i - half) * incX);
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * (i - half));
}
enemyFormation[j].init[i].y = y3;
enemyFormation[j].init[i].kind = BALLOON_3;
}
// #23 - Diez enemigos BALLOON3. Hacia la derecha. Juntos. Simetricos
j = 23;
enemyFormation[j].numberOfEnemies = 10;
incX = BALLOON_WIDTH_3 + 1;
incTime = 10;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
const int half = enemyFormation[j].numberOfEnemies / 2;
if (i < half)
{
enemyFormation[j].init[i].x = x3_0 + (i * incX);
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * i);
}
else
{
enemyFormation[j].init[i].x = x3_100 - ((i - half) * incX);
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * (i - half));
}
enemyFormation[j].init[i].y = y3;
enemyFormation[j].init[i].kind = BALLOON_3;
}
// #24 - Treinta enemigos BALLOON1. Del centro hacia los extremos. Juntos. Simetricos
j = 24;
enemyFormation[j].numberOfEnemies = 30;
incX = 0;
incTime = 5;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
const int half = enemyFormation[j].numberOfEnemies / 2;
if (i < half)
{
enemyFormation[j].init[i].x = x1_50;
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].creationCounter = (creationTime) + (incTime * i);
}
else
{
enemyFormation[j].init[i].x = x1_50;
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].creationCounter = (creationTime) + (incTime * (i - half));
}
enemyFormation[j].init[i].y = y1;
enemyFormation[j].init[i].kind = BALLOON_1;
}
// #25 - Treinta enemigos BALLOON1. Del centro hacia adentro. Juntos. Simetricos
j = 25;
enemyFormation[j].numberOfEnemies = 30;
incX = BALLOON_WIDTH_1 + 1;
incTime = 5;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
const int half = enemyFormation[j].numberOfEnemies / 2;
if (i < half)
{
enemyFormation[j].init[i].x = x1_50 + 20;
enemyFormation[j].init[i].velX = BALLOON_VELX_NEGATIVE;
enemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * i);
}
else
{
enemyFormation[j].init[i].x = x1_50 - 20;
enemyFormation[j].init[i].velX = BALLOON_VELX_POSITIVE;
enemyFormation[j].init[i].creationCounter = (creationTime) - (incTime * (i - half));
}
enemyFormation[j].init[i].y = y1;
enemyFormation[j].init[i].kind = BALLOON_1;
}
// Crea las mismas formaciones pero con hexagonos a partir de la posición 50 del vector
for (int k = 0; k < j + 1; k++)
{
enemyFormation[k + 50].numberOfEnemies = enemyFormation[k].numberOfEnemies;
for (int i = 0; i < enemyFormation[k + 50].numberOfEnemies; i++)
{
enemyFormation[k + 50].init[i].x = enemyFormation[k].init[i].x;
enemyFormation[k + 50].init[i].y = enemyFormation[k].init[i].y;
enemyFormation[k + 50].init[i].velX = enemyFormation[k].init[i].velX;
enemyFormation[k + 50].init[i].creationCounter = enemyFormation[k].init[i].creationCounter;
enemyFormation[k + 50].init[i].kind = enemyFormation[k].init[i].kind + 4;
}
}
// TEST
enemyFormation[99].numberOfEnemies = 4;
enemyFormation[99].init[0].x = 10;
enemyFormation[99].init[0].y = y1;
enemyFormation[99].init[0].velX = 0;
enemyFormation[99].init[0].kind = BALLOON_1;
enemyFormation[99].init[0].creationCounter = 200;
enemyFormation[99].init[1].x = 50;
enemyFormation[99].init[1].y = y1;
enemyFormation[99].init[1].velX = 0;
enemyFormation[99].init[1].kind = BALLOON_2;
enemyFormation[99].init[1].creationCounter = 200;
enemyFormation[99].init[2].x = 90;
enemyFormation[99].init[2].y = y1;
enemyFormation[99].init[2].velX = 0;
enemyFormation[99].init[2].kind = BALLOON_3;
enemyFormation[99].init[2].creationCounter = 200;
enemyFormation[99].init[3].x = 140;
enemyFormation[99].init[3].y = y1;
enemyFormation[99].init[3].velX = 0;
enemyFormation[99].init[3].kind = BALLOON_4;
enemyFormation[99].init[3].creationCounter = 200;
}
// Inicializa los conjuntos de formaciones
void EnemyFormations::initEnemyPools()
{
// EnemyPool #0
enemyPool[0].set[0] = &enemyFormation[0];
enemyPool[0].set[1] = &enemyFormation[1];
enemyPool[0].set[2] = &enemyFormation[2];
enemyPool[0].set[3] = &enemyFormation[3];
enemyPool[0].set[4] = &enemyFormation[4];
enemyPool[0].set[5] = &enemyFormation[5];
enemyPool[0].set[6] = &enemyFormation[6];
enemyPool[0].set[7] = &enemyFormation[7];
enemyPool[0].set[8] = &enemyFormation[8];
enemyPool[0].set[9] = &enemyFormation[9];
// EnemyPool #1
enemyPool[1].set[0] = &enemyFormation[10];
enemyPool[1].set[1] = &enemyFormation[11];
enemyPool[1].set[2] = &enemyFormation[12];
enemyPool[1].set[3] = &enemyFormation[13];
enemyPool[1].set[4] = &enemyFormation[14];
enemyPool[1].set[5] = &enemyFormation[15];
enemyPool[1].set[6] = &enemyFormation[16];
enemyPool[1].set[7] = &enemyFormation[17];
enemyPool[1].set[8] = &enemyFormation[18];
enemyPool[1].set[9] = &enemyFormation[19];
// EnemyPool #2
enemyPool[2].set[0] = &enemyFormation[0];
enemyPool[2].set[1] = &enemyFormation[1];
enemyPool[2].set[2] = &enemyFormation[2];
enemyPool[2].set[3] = &enemyFormation[3];
enemyPool[2].set[4] = &enemyFormation[4];
enemyPool[2].set[5] = &enemyFormation[55];
enemyPool[2].set[6] = &enemyFormation[56];
enemyPool[2].set[7] = &enemyFormation[57];
enemyPool[2].set[8] = &enemyFormation[58];
enemyPool[2].set[9] = &enemyFormation[59];
// EnemyPool #3
enemyPool[3].set[0] = &enemyFormation[50];
enemyPool[3].set[1] = &enemyFormation[51];
enemyPool[3].set[2] = &enemyFormation[52];
enemyPool[3].set[3] = &enemyFormation[53];
enemyPool[3].set[4] = &enemyFormation[54];
enemyPool[3].set[5] = &enemyFormation[5];
enemyPool[3].set[6] = &enemyFormation[6];
enemyPool[3].set[7] = &enemyFormation[7];
enemyPool[3].set[8] = &enemyFormation[8];
enemyPool[3].set[9] = &enemyFormation[9];
// EnemyPool #4
enemyPool[4].set[0] = &enemyFormation[60];
enemyPool[4].set[1] = &enemyFormation[61];
enemyPool[4].set[2] = &enemyFormation[62];
enemyPool[4].set[3] = &enemyFormation[63];
enemyPool[4].set[4] = &enemyFormation[64];
enemyPool[4].set[5] = &enemyFormation[65];
enemyPool[4].set[6] = &enemyFormation[66];
enemyPool[4].set[7] = &enemyFormation[67];
enemyPool[4].set[8] = &enemyFormation[68];
enemyPool[4].set[9] = &enemyFormation[69];
// EnemyPool #5
enemyPool[5].set[0] = &enemyFormation[10];
enemyPool[5].set[1] = &enemyFormation[61];
enemyPool[5].set[2] = &enemyFormation[12];
enemyPool[5].set[3] = &enemyFormation[63];
enemyPool[5].set[4] = &enemyFormation[14];
enemyPool[5].set[5] = &enemyFormation[65];
enemyPool[5].set[6] = &enemyFormation[16];
enemyPool[5].set[7] = &enemyFormation[67];
enemyPool[5].set[8] = &enemyFormation[18];
enemyPool[5].set[9] = &enemyFormation[69];
// EnemyPool #6
enemyPool[6].set[0] = &enemyFormation[60];
enemyPool[6].set[1] = &enemyFormation[11];
enemyPool[6].set[2] = &enemyFormation[62];
enemyPool[6].set[3] = &enemyFormation[13];
enemyPool[6].set[4] = &enemyFormation[64];
enemyPool[6].set[5] = &enemyFormation[15];
enemyPool[6].set[6] = &enemyFormation[66];
enemyPool[6].set[7] = &enemyFormation[17];
enemyPool[6].set[8] = &enemyFormation[68];
enemyPool[6].set[9] = &enemyFormation[19];
// EnemyPool #7
enemyPool[7].set[0] = &enemyFormation[20];
enemyPool[7].set[1] = &enemyFormation[21];
enemyPool[7].set[2] = &enemyFormation[22];
enemyPool[7].set[3] = &enemyFormation[23];
enemyPool[7].set[4] = &enemyFormation[24];
enemyPool[7].set[5] = &enemyFormation[65];
enemyPool[7].set[6] = &enemyFormation[66];
enemyPool[7].set[7] = &enemyFormation[67];
enemyPool[7].set[8] = &enemyFormation[68];
enemyPool[7].set[9] = &enemyFormation[69];
// EnemyPool #8
enemyPool[8].set[0] = &enemyFormation[70];
enemyPool[8].set[1] = &enemyFormation[71];
enemyPool[8].set[2] = &enemyFormation[72];
enemyPool[8].set[3] = &enemyFormation[73];
enemyPool[8].set[4] = &enemyFormation[74];
enemyPool[8].set[5] = &enemyFormation[15];
enemyPool[8].set[6] = &enemyFormation[16];
enemyPool[8].set[7] = &enemyFormation[17];
enemyPool[8].set[8] = &enemyFormation[18];
enemyPool[8].set[9] = &enemyFormation[19];
// EnemyPool #9
enemyPool[9].set[0] = &enemyFormation[20];
enemyPool[9].set[1] = &enemyFormation[21];
enemyPool[9].set[2] = &enemyFormation[22];
enemyPool[9].set[3] = &enemyFormation[23];
enemyPool[9].set[4] = &enemyFormation[24];
enemyPool[9].set[5] = &enemyFormation[70];
enemyPool[9].set[6] = &enemyFormation[71];
enemyPool[9].set[7] = &enemyFormation[72];
enemyPool[9].set[8] = &enemyFormation[73];
enemyPool[9].set[9] = &enemyFormation[74];
}
// Inicializa las fases del juego
void EnemyFormations::initGameStages()
{
// STAGE 1
stage[0].number = 1;
stage[0].powerToComplete = 200;
stage[0].minMenace = 7 + (4 * 1);
stage[0].maxMenace = 7 + (4 * 3);
stage[0].enemyPool = &enemyPool[0];
// STAGE 2
stage[1].number = 2;
stage[1].powerToComplete = 300;
stage[1].minMenace = 7 + (4 * 2);
stage[1].maxMenace = 7 + (4 * 4);
stage[1].enemyPool = &enemyPool[1];
// STAGE 3
stage[2].number = 3;
stage[2].powerToComplete = 600;
stage[2].minMenace = 7 + (4 * 3);
stage[2].maxMenace = 7 + (4 * 5);
stage[2].enemyPool = &enemyPool[2];
// STAGE 4
stage[3].number = 4;
stage[3].powerToComplete = 600;
stage[3].minMenace = 7 + (4 * 3);
stage[3].maxMenace = 7 + (4 * 5);
stage[3].enemyPool = &enemyPool[3];
// STAGE 5
stage[4].number = 5;
stage[4].powerToComplete = 600;
stage[4].minMenace = 7 + (4 * 4);
stage[4].maxMenace = 7 + (4 * 6);
stage[4].enemyPool = &enemyPool[4];
// STAGE 6
stage[5].number = 6;
stage[5].powerToComplete = 600;
stage[5].minMenace = 7 + (4 * 4);
stage[5].maxMenace = 7 + (4 * 6);
stage[5].enemyPool = &enemyPool[5];
// STAGE 7
stage[6].number = 7;
stage[6].powerToComplete = 650;
stage[6].minMenace = 7 + (4 * 5);
stage[6].maxMenace = 7 + (4 * 7);
stage[6].enemyPool = &enemyPool[6];
// STAGE 8
stage[7].number = 8;
stage[7].powerToComplete = 750;
stage[7].minMenace = 7 + (4 * 5);
stage[7].maxMenace = 7 + (4 * 7);
stage[7].enemyPool = &enemyPool[7];
// STAGE 9
stage[8].number = 9;
stage[8].powerToComplete = 850;
stage[8].minMenace = 7 + (4 * 6);
stage[8].maxMenace = 7 + (4 * 8);
stage[8].enemyPool = &enemyPool[8];
// STAGE 10
stage[9].number = 10;
stage[9].powerToComplete = 950;
stage[9].minMenace = 7 + (4 * 7);
stage[9].maxMenace = 7 + (4 * 10);
stage[9].enemyPool = &enemyPool[9];
}
// Devuelve una fase
stage_t EnemyFormations::getStage(int index) const
{
return stage[index];
}

View File

@@ -1,63 +0,0 @@
#pragma once
#define NUMBER_OF_ENEMY_FORMATIONS 100
#define MAX_NUMBER_OF_ENEMIES_IN_A_FORMATION 50
// Estructuras
struct enemyInits_t
{
int x; // Posición en el eje X donde crear al enemigo
int y; // Posición en el eje Y donde crear al enemigo
float velX; // Velocidad inicial en el eje X
int kind; // Tipo de enemigo
int creationCounter; // Temporizador para la creación del enemigo
};
struct enemyFormation_t // Contiene la información de una formación enemiga
{
int numberOfEnemies; // Cantidad de enemigos que forman la formación
enemyInits_t init[MAX_NUMBER_OF_ENEMIES_IN_A_FORMATION]; // Vector con todas las inicializaciones de los enemigos de la formación
};
struct enemyPool_t
{
enemyFormation_t *set[10]; // Conjunto de formaciones enemigas
};
struct stage_t // Contiene todas las variables relacionadas con una fase
{
enemyPool_t *enemyPool; // El conjunto de formaciones enemigas de la fase
int powerToComplete; // Cantidad de poder que se necesita para completar la fase
int maxMenace; // Umbral máximo de amenaza de la fase
int minMenace; // Umbral mínimo de amenaza de la fase
int number; // Número de fase
};
// Clase EnemyFormations, para gestionar las formaciones enemigas
class EnemyFormations
{
private:
// Variables
stage_t stage[10]; // Variable con los datos de cada pantalla
enemyFormation_t enemyFormation[NUMBER_OF_ENEMY_FORMATIONS]; // Vector con todas las formaciones enemigas
enemyPool_t enemyPool[10]; // Variable con los diferentes conjuntos de formaciones enemigas
// Inicializa las formaciones enemigas
void initEnemyFormations();
// Inicializa los conjuntos de formaciones
void initEnemyPools();
// Inicializa las fases del juego
void initGameStages();
public:
// Constructor
EnemyFormations();
// Destructor
~EnemyFormations() = default;
// Devuelve una fase
stage_t getStage(int index) const;
};

View File

@@ -1,5 +1,6 @@
#include "enter_name.h" #include "enter_name.h"
#include <algorithm> // for max, min #include <stddef.h> // Para size_t
#include <algorithm> // Para max, min
// Constructor // Constructor
EnterName::EnterName() EnterName::EnterName()
@@ -11,12 +12,12 @@ EnterName::EnterName()
void EnterName::init() void EnterName::init()
{ {
// Obtiene el puntero al nombre // Obtiene el puntero al nombre
name = "A"; name_ = "A";
// Inicia la lista de caracteres permitidos // Inicia la lista de caracteres permitidos
characterList = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()"; character_list_ = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()";
pos = 0; position_ = 0;
numCharacters = (int)characterList.size(); num_characters_ = static_cast<int>(character_list_.size());
// Pone la lista de indices para que refleje el nombre // Pone la lista de indices para que refleje el nombre
updateCharacterIndex(); updateCharacterIndex();
@@ -26,26 +27,27 @@ void EnterName::init()
} }
// Incrementa la posición // Incrementa la posición
void EnterName::incPos() void EnterName::incPosition()
{ {
pos++; position_++;
pos = std::min(pos, NAME_LENGHT - 1); position_ = std::min(position_, NAME_LENGHT - 1);
checkIfPositionHasBeenUsed();
} }
// Decrementa la posición // Decrementa la posición
void EnterName::decPos() void EnterName::decPosition()
{ {
pos--; --position_;
pos = std::max(pos, 0); position_ = std::max(position_, 0);
} }
// Incrementa el índice // Incrementa el índice
void EnterName::incIndex() void EnterName::incIndex()
{ {
++characterIndex[pos]; ++character_index_[position_];
if (characterIndex[pos] >= numCharacters) if (character_index_[position_] >= num_characters_)
{ {
characterIndex[pos] = 0; character_index_[position_] = 0;
} }
updateName(); updateName();
} }
@@ -53,61 +55,71 @@ void EnterName::incIndex()
// Decrementa el índice // Decrementa el índice
void EnterName::decIndex() void EnterName::decIndex()
{ {
--characterIndex[pos]; --character_index_[position_];
if (characterIndex[pos] < 0) if (character_index_[position_] < 0)
{ {
characterIndex[pos] = numCharacters - 1; character_index_[position_] = num_characters_ - 1;
} }
updateName(); updateName();
} }
// Actualiza la variable // Actualiza el nombre a partir de la lista de índices
void EnterName::updateName() void EnterName::updateName()
{ {
name.clear(); name_.clear();
for (int i = 0; i < NAME_LENGHT; ++i) for (int i = 0; i < NAME_LENGHT; ++i)
{ {
name.push_back(characterList[characterIndex[i]]); name_.push_back(character_list_[character_index_[i]]);
} }
} }
// Actualiza la variable // Actualiza la variable
void EnterName::updateCharacterIndex() void EnterName::updateCharacterIndex()
{ {
// Rellena de espacios // Rellena de espacios y marca como no usados
for (int i = 0; i < NAME_LENGHT; ++i) for (size_t i = 0; i < NAME_LENGHT; ++i)
{ {
characterIndex[i] = 0; character_index_[i] = 0;
position_has_been_used_[i] = false;
} }
// Coloca los índices en funcion de los caracteres que forman el nombre // Coloca los índices en función de los caracteres que forman el nombre
for (int i = 0; i < (int)name.size(); ++i) for (size_t i = 0; i < name_.size(); ++i)
{ {
characterIndex[i] = findIndex(name.at(i)); character_index_[i] = findIndex(name_.at(i));
position_has_been_used_[i] = true;
} }
} }
// Encuentra el indice de un caracter en "characterList" // Encuentra el indice de un caracter en "character_list_"
int EnterName::findIndex(char character) int EnterName::findIndex(char character) const
{ {
for (int i = 0; i < (int)characterList.size(); ++i) for (size_t i = 0; i < character_list_.size(); ++i)
{ if (character == character_list_.at(i))
if (character == characterList[i])
{
return i; return i;
}
}
return 0; return 0;
} }
// Obtiene el nombre // Obtiene el nombre
std::string EnterName::getName() const std::string EnterName::getName() const
{ {
return name; return name_;
} }
// Obtiene la posición que se está editando // Obtiene la posición que se está editando
int EnterName::getPos() const int EnterName::getPosition() const
{ {
return pos; 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

@@ -2,7 +2,7 @@
#include <string> #include <string>
#define NAME_LENGHT 8 constexpr int NAME_LENGHT = 8;
/* /*
Un array, "characterList", contiene la lista de caracteres Un array, "characterList", contiene la lista de caracteres
@@ -16,20 +16,24 @@
class EnterName class EnterName
{ {
private: private:
std::string characterList; // 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 pos; // Posición a editar del nombre int position_; // Posición a editar del nombre
int numCharacters; // Cantidad de caracteres de la lista de caracteres int num_characters_; // Cantidad de caracteres de la lista de caracteres
int characterIndex[NAME_LENGHT]; // Indice de la lista para cada uno de los caracteres que forman el nombre int character_index_[NAME_LENGHT]; // Indice de la lista para cada uno de los caracteres que forman el nombre
bool position_has_been_used_[NAME_LENGHT]; // Indica si en esa posición se ha puesto ya alguna letra. Se utiliza para replicar la letra anterior la primera vez
// Actualiza la variable // Actualiza el nombre a partir de la lista de índices
void updateName(); void updateName();
// Actualiza la variable // Actualiza la variable
void updateCharacterIndex(); void updateCharacterIndex();
// Encuentra el indice de un caracter en "characterList" // Encuentra el indice de un caracter en "characterList"
int findIndex(char character); int findIndex(char character) const;
// Comprueba la posición y copia el caracter si es necesario
void checkIfPositionHasBeenUsed();
public: public:
// Constructor // Constructor
@@ -42,10 +46,10 @@ public:
void init(); void init();
// Incrementa la posición // Incrementa la posición
void incPos(); void incPosition();
// Decrementa la posición // Decrementa la posición
void decPos(); void decPosition();
// Incrementa el índice // Incrementa el índice
void incIndex(); void incIndex();
@@ -57,5 +61,5 @@ public:
std::string getName() const; std::string getName() const;
// Obtiene la posición que se está editando // Obtiene la posición que se está editando
int getPos() const; int getPosition() const;
}; };

View File

@@ -1,24 +1,11 @@
#include "explosions.h" #include "explosions.h"
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // Para AnimatedSprite
class Texture; class Texture; // lines 4-4
// Constructor
Explosions::Explosions()
{
textures.clear();
explosions.clear();
}
// Destructor
Explosions::~Explosions()
{
explosions.clear();
}
// Actualiza la lógica de la clase // Actualiza la lógica de la clase
void Explosions::update() void Explosions::update()
{ {
for (auto &explosion : explosions) for (auto &explosion : explosions_)
{ {
explosion->update(); explosion->update();
} }
@@ -30,41 +17,36 @@ void Explosions::update()
// Dibuja el objeto en pantalla // Dibuja el objeto en pantalla
void Explosions::render() void Explosions::render()
{ {
for (auto &explosion : explosions) for (auto &explosion : explosions_)
{ {
explosion->render(); explosion->render();
} }
} }
// Añade texturas al objeto // Añade texturas al objeto
void Explosions::addTexture(int size, std::shared_ptr<Texture> texture, std::vector<std::string> *animation) void Explosions::addTexture(int size, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
{ {
explosion_texture_t temp; textures_.emplace_back(ExplosionTexture(size, texture, animation));
temp.size = size;
temp.texture = texture;
temp.animation = animation;
textures.push_back(temp);
} }
// Añade una explosión // Añade una explosión
void Explosions::add(int x, int y, int size) void Explosions::add(int x, int y, int size)
{ {
const int index = getIndexBySize(size); const auto index = getIndexBySize(size);
auto sprite = std::make_unique<AnimatedSprite>(textures[index].texture, "", textures[index].animation); explosions_.emplace_back(std::make_unique<AnimatedSprite>(textures_[index].texture, textures_[index].animation));
sprite->setPos(x, y); explosions_.back()->setPos(x, y);
explosions.push_back(std::move(sprite));
} }
// Vacia el vector de elementos finalizados // Vacia el vector de elementos finalizados
void Explosions::freeExplosions() void Explosions::freeExplosions()
{ {
if (explosions.empty() == false) if (explosions_.empty() == false)
{ {
for (int i = explosions.size() - 1; i >= 0; --i) for (int i = explosions_.size() - 1; i >= 0; --i)
{ {
if (explosions[i]->animationIsCompleted()) if (explosions_[i]->animationIsCompleted())
{ {
explosions.erase(explosions.begin() + i); explosions_.erase(explosions_.begin() + i);
} }
} }
} }
@@ -73,9 +55,9 @@ void Explosions::freeExplosions()
// Busca una textura a partir del tamaño // Busca una textura a partir del tamaño
int Explosions::getIndexBySize(int size) int Explosions::getIndexBySize(int size)
{ {
for (int i = 0; i < (int)textures.size();++i) for (int i = 0; i < (int)textures_.size(); ++i)
{ {
if (size == textures[i].size) if (size == textures_[i].size)
{ {
return i; return i;
} }

View File

@@ -1,16 +1,20 @@
#pragma once #pragma once
#include <string> // for string #include <memory> // Para unique_ptr, shared_ptr
#include <vector> // for vector #include <string> // Para string
#include "animated_sprite.h" #include <vector> // Para vector
#include <memory> #include "animated_sprite.h" // Para AnimatedSprite
#include "texture.h" class Texture; // lines 7-7
struct explosion_texture_t struct ExplosionTexture
{ {
std::shared_ptr<Texture>texture; // Textura para la explosión int size; // Tamaño de la explosión
std::vector<std::string> *animation; // Animación para la textura std::shared_ptr<Texture> texture; // Textura para la explosión
int size; // Tamaño de la explosión std::vector<std::string> animation; // Animación para la textura
// Constructor
ExplosionTexture(int sz, std::shared_ptr<Texture> tex, const std::vector<std::string> &anim)
: size(sz), texture(tex), animation(anim) {}
}; };
// Clase explosions // Clase explosions
@@ -18,8 +22,8 @@ class Explosions
{ {
private: private:
// Variables // Variables
std::vector<explosion_texture_t> textures; // Vector con las texturas a utilizar std::vector<ExplosionTexture> textures_; // Vector con las texturas a utilizar
std::vector<std::unique_ptr<AnimatedSprite>> explosions; // Lista con todas las explosiones std::vector<std::unique_ptr<AnimatedSprite>> explosions_; // Lista con todas las explosiones
// Vacia el vector de elementos finalizados // Vacia el vector de elementos finalizados
void freeExplosions(); void freeExplosions();
@@ -29,10 +33,10 @@ private:
public: public:
// Constructor // Constructor
Explosions(); Explosions() = default;
// Destructor // Destructor
~Explosions(); ~Explosions() = default;
// Actualiza la lógica de la clase // Actualiza la lógica de la clase
void update(); void update();
@@ -41,7 +45,7 @@ public:
void render(); void render();
// Añade texturas al objeto // Añade texturas al objeto
void addTexture(int size, std::shared_ptr<Texture> texture, std::vector<std::string> *animation); void addTexture(int size, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation);
// Añade una explosión // Añade una explosión
void add(int x, int y, int size); void add(int x, int y, int size);

View File

@@ -1,18 +1,18 @@
#include "fade.h" #include "fade.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND, SDL_BLENDMODE_NONE #include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND, SDL_BLENDMODE_NONE
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <stdlib.h> // for rand #include <stdlib.h> // Para rand
#include <algorithm> // for min, max #include <algorithm> // Para min, max
#include "param.h" // for param #include "param.h" // Para Param, param, ParamGame, ParamFade
#include "utils.h" // for Param, ParamGame, ParamFade #include "screen.h" // Para Screen
// Constructor // Constructor
Fade::Fade(SDL_Renderer *renderer) Fade::Fade()
: renderer(renderer) : renderer_(Screen::get()->getRenderer())
{ {
// Crea la textura donde dibujar el fade // Crea la textura donde dibujar el fade
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);
SDL_SetTextureBlendMode(backbuffer, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
// Inicializa las variables // Inicializa las variables
init(); init();
@@ -21,64 +21,65 @@ Fade::Fade(SDL_Renderer *renderer)
// Destructor // Destructor
Fade::~Fade() Fade::~Fade()
{ {
SDL_DestroyTexture(backbuffer); SDL_DestroyTexture(backbuffer_);
backbuffer = nullptr; backbuffer_ = nullptr;
} }
// Inicializa las variables // Inicializa las variables
void Fade::init() void Fade::init()
{ {
type = FadeType::CENTER; type_ = FadeType::CENTER;
mode = FadeMode::OUT; mode_ = FadeMode::OUT;
enabled = false; enabled_ = false;
finished = false; finished_ = false;
counter = 0; counter_ = 0;
r = 0; r_ = 0;
g = 0; g_ = 0;
b = 0; b_ = 0;
postDuration = 20; a_ = 0;
postCounter = 0; post_duration_ = 20;
numSquaresWidth = param.fade.num_squares_width; post_counter_ = 0;
numSquaresHeight = param.fade.num_squares_height; num_squares_width_ = param.fade.num_squares_width;
fadeRandomSquaresDelay = param.fade.random_squares_delay; num_squares_height_ = param.fade.num_squares_height;
fadeRandomSquaresMult = param.fade.random_squares_mult; fade_random_squares_delay_ = param.fade.random_squares_delay;
fade_random_squares_mult_ = param.fade.random_squares_mult;
} }
// 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; enabled_ = false;
finished = false; 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 (enabled_ || finished_)
{ {
SDL_RenderCopy(renderer, backbuffer, nullptr, nullptr); SDL_RenderCopy(renderer_, backbuffer_, nullptr, nullptr);
} }
} }
// Actualiza las variables internas // Actualiza las variables internas
void Fade::update() void Fade::update()
{ {
if (enabled) if (enabled_)
{ {
switch (type) switch (type_)
{ {
case FadeType::FULLSCREEN: case FadeType::FULLSCREEN:
{ {
// Modifica la transparencia // Modifica la transparencia
a = mode == FadeMode::OUT ? std::min(counter * 4, 255) : 255 - std::min(counter * 4, 255); a_ = mode_ == FadeMode::OUT ? std::min(counter_ * 4, 255) : 255 - std::min(counter_ * 4, 255);
SDL_SetTextureAlphaMod(backbuffer, a); SDL_SetTextureAlphaMod(backbuffer_, a_);
// Comprueba si ha terminado // Comprueba si ha terminado
if (counter >= 255 / 4) if (counter_ >= 255 / 4)
{ {
finished = true; finished_ = true;
} }
break; break;
@@ -86,62 +87,62 @@ void Fade::update()
case FadeType::CENTER: case FadeType::CENTER:
{ {
// 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_SetRenderDrawColor(renderer, r, g, b, a); SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
for (int i = 0; i < counter; i++) for (int i = 0; i < counter_; i++)
{ {
rect1.h = rect2.h = i * 4; rect1_.h = rect2_.h = i * 4;
rect2.y = param.game.height - (i * 4); rect2_.y = param.game.height - (i * 4);
SDL_RenderFillRect(renderer, &rect1); SDL_RenderFillRect(renderer_, &rect1_);
SDL_RenderFillRect(renderer, &rect2); SDL_RenderFillRect(renderer_, &rect2_);
} }
// Deja el renderizador como estaba // Deja el renderizador como estaba
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
// Comprueba si ha terminado // Comprueba si ha terminado
if ((counter * 4) > param.game.height) if ((counter_ * 4) > param.game.height)
{ {
finished = true; finished_ = true;
a = 255; a_ = 255;
} }
break; break;
} }
case FadeType::RANDOM_SQUARE: case FadeType::RANDOM_SQUARE:
{ {
if (counter % fadeRandomSquaresDelay == 0) if (counter_ % fade_random_squares_delay_ == 0)
{ {
// 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_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_);
// Dibuja el cuadrado correspondiente // Dibuja el cuadrado correspondiente
const int index = std::min(counter / fadeRandomSquaresDelay, (numSquaresWidth * numSquaresHeight) - 1); const int index = std::min(counter_ / fade_random_squares_delay_, (num_squares_width_ * num_squares_height_) - 1);
for (int i = 0; i < fadeRandomSquaresMult; ++i) for (int i = 0; i < fade_random_squares_mult_; ++i)
{ {
const int index2 = std::min(index * fadeRandomSquaresMult + i, (int)square.size() - 1); const int index2 = std::min(index * fade_random_squares_mult_ + i, (int)square_.size() - 1);
SDL_RenderFillRect(renderer, &square[index2]); SDL_RenderFillRect(renderer_, &square_[index2]);
} }
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
// Deja el renderizador como estaba // Deja el renderizador como estaba
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
} }
// Comprueba si ha terminado // Comprueba si ha terminado
if (counter * fadeRandomSquaresMult / fadeRandomSquaresDelay >= numSquaresWidth * numSquaresHeight) if (counter_ * fade_random_squares_mult_ / fade_random_squares_delay_ >= num_squares_width_ * num_squares_height_)
{ {
finished = true; finished_ = true;
} }
break; break;
@@ -150,47 +151,47 @@ void Fade::update()
case FadeType::VENETIAN: case FadeType::VENETIAN:
{ {
// Counter debe ir de 0 a 150 // Counter debe ir de 0 a 150
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_SetRenderDrawColor(renderer, r, g, b, a); SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
for (auto rect : square) for (auto rect : square_)
{ {
SDL_RenderFillRect(renderer, &rect); SDL_RenderFillRect(renderer_, &rect);
} }
// Deja el renderizador como estaba // Deja el renderizador como estaba
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
const auto h = counter / 3; const auto h = counter_ / 3;
for (int i = 0; i < (int)square.size(); ++i) for (int i = 0; i < (int)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_[i].h = i == 0 ? h : std::max(square_[i - 1].h - 3, 0);
} }
} }
else else
{ {
finished = true; finished_ = true;
} }
break; break;
} }
} }
if (finished) if (finished_)
{ {
// Actualiza el contador // Actualiza el contador
postCounter == postDuration ? enabled = false : postCounter++; post_counter_ == post_duration_ ? enabled_ = false : 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++; counter_++;
} }
} }
@@ -198,67 +199,67 @@ void Fade::update()
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 (enabled_)
{ {
return; return;
} }
enabled = true; enabled_ = true;
finished = false; finished_ = false;
counter = 0; counter_ = 0;
postCounter = 0; post_counter_ = 0;
switch (type) switch (type_)
{ {
case FadeType::FULLSCREEN: case FadeType::FULLSCREEN:
{ {
// Pinta el backbuffer de color sólido // Pinta el backbuffer_ de color sólido
cleanBackbuffer(r, g, b, 255); cleanBackbuffer(r_, g_, b_, 255);
break; break;
} }
case FadeType::CENTER: case FadeType::CENTER:
{ {
rect1 = {0, 0, param.game.width, 0}; rect1_ = {0, 0, param.game.width, 0};
rect2 = {0, 0, param.game.width, 0}; rect2_ = {0, 0, param.game.width, 0};
a = 64; a_ = 64;
break; break;
} }
case FadeType::RANDOM_SQUARE: case FadeType::RANDOM_SQUARE:
{ {
rect1 = {0, 0, param.game.width / numSquaresWidth, param.game.height / numSquaresHeight}; rect1_ = {0, 0, param.game.width / num_squares_width_, param.game.height / num_squares_height_};
square.clear(); square_.clear();
// Añade los cuadrados al vector // Añade los cuadrados al vector
for (int i = 0; i < numSquaresWidth * numSquaresHeight; ++i) for (int i = 0; i < num_squares_width_ * num_squares_height_; ++i)
{ {
rect1.x = (i % numSquaresWidth) * rect1.w; rect1_.x = (i % num_squares_width_) * rect1_.w;
rect1.y = (i / numSquaresWidth) * rect1.h; rect1_.y = (i / num_squares_width_) * rect1_.h;
square.push_back(rect1); square_.push_back(rect1_);
} }
// Desordena el vector de cuadrados // Desordena el vector de cuadrados
auto num = numSquaresWidth * numSquaresHeight; auto num = num_squares_width_ * num_squares_height_;
while (num > 1) while (num > 1)
{ {
auto num_arreu = rand() % num; auto num_arreu = rand() % num;
SDL_Rect temp = square[num_arreu]; SDL_Rect temp = square_[num_arreu];
square[num_arreu] = square[num - 1]; square_[num_arreu] = square_[num - 1];
square[num - 1] = temp; square_[num - 1] = temp;
num--; num--;
} }
// Limpia la textura // Limpia la textura
auto *temp = SDL_GetRenderTarget(renderer); auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer, backbuffer); SDL_SetRenderTarget(renderer_, backbuffer_);
a = mode == FadeMode::OUT ? 0 : 255; a_ = mode_ == FadeMode::OUT ? 0 : 255;
SDL_SetRenderDrawColor(renderer, r, g, b, a); SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
SDL_SetRenderTarget(renderer, temp); 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;
break; break;
} }
@@ -266,17 +267,17 @@ void Fade::activate()
case FadeType::VENETIAN: case FadeType::VENETIAN:
{ {
cleanBackbuffer(0, 0, 0, 0); cleanBackbuffer(0, 0, 0, 0);
rect1 = {0, 0, param.game.width, 0}; rect1_ = {0, 0, param.game.width, 0};
square.clear(); square_.clear();
a = 255; a_ = 255;
// Añade los cuadrados al vector // Añade los cuadrados al vector
const int max = param.game.height / param.fade.venetian_size; const int max = param.game.height / param.fade.venetian_size;
for (int i = 0; i < max; ++i) for (int i = 0; i < max; ++i)
{ {
rect1.y = i * param.fade.venetian_size; rect1_.y = i * param.fade.venetian_size;
square.push_back(rect1); square_.push_back(rect1_);
} }
break; break;
@@ -287,53 +288,53 @@ void Fade::activate()
// Comprueba si está activo // Comprueba si está activo
bool Fade::isEnabled() const bool Fade::isEnabled() const
{ {
return enabled; return enabled_;
} }
// Comprueba si ha terminado la transicion // Comprueba si ha terminado la transicion
bool Fade::hasEnded() const bool Fade::hasEnded() const
{ {
// Ha terminado cuando ha finalizado la transición y se ha deshabilitado // Ha terminado cuando ha finalizado la transición y se ha deshabilitado
return !enabled && finished; return !enabled_ && finished_;
} }
// Establece el tipo de fade // Establece el tipo de fade
void Fade::setType(FadeType type) void Fade::setType(FadeType type)
{ {
this->type = type; type_ = type;
} }
// Establece el modo de fade // Establece el modo de fade
void Fade::setMode(FadeMode mode) void Fade::setMode(FadeMode mode)
{ {
this->mode = 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)
{ {
this->r = r; r_ = r;
this->g = g; g_ = g;
this->b = b; b_ = b;
} }
// Establece la duración posterior // Establece la duración posterior
void Fade::setPost(int value) void Fade::setPost(int value)
{ {
postDuration = 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)
{ {
// Dibujamos sobre el backbuffer // Dibujamos sobre el backbuffer_
auto *temp = SDL_GetRenderTarget(renderer); auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer, backbuffer); SDL_SetRenderTarget(renderer_, backbuffer_);
// Pintamos la textura con el color del fade // Pintamos la textura con el color del fade
SDL_SetRenderDrawColor(renderer, r, g, b, a); SDL_SetRenderDrawColor(renderer_, r, g, b, a);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
// Vuelve a dejar el renderizador como estaba // Vuelve a dejar el renderizador como estaba
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
} }

View File

@@ -1,12 +1,12 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint8, Uint16 #include <SDL2/SDL_stdinc.h> // para Uint8, Uint16
#include <vector> // for vector #include <vector> // para vector
// Tipos de fundido // Tipos de fundido
enum class FadeType enum class FadeType : Uint8
{ {
FULLSCREEN = 0, FULLSCREEN = 0,
CENTER = 1, CENTER = 1,
@@ -15,7 +15,7 @@ enum class FadeType
}; };
// Modos de fundido // Modos de fundido
enum class FadeMode enum class FadeMode : Uint8
{ {
IN = 0, IN = 0,
OUT = 1, OUT = 1,
@@ -26,25 +26,25 @@ class Fade
{ {
private: private:
// Objetos y punteros // Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
SDL_Texture *backbuffer; // Textura para usar como backbuffer con SDL_TEXTUREACCESS_TARGET SDL_Texture *backbuffer_; // Textura para usar como backbuffer con SDL_TEXTUREACCESS_TARGET
// 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
Uint16 counter; // Contador interno Uint16 counter_; // Contador interno
bool enabled; // Indica si el fade está activo bool enabled_; // Indica si el fade está activo
bool finished; // Indica si ha terminado la transición 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
int numSquaresWidth; // Cantidad total de cuadraditos en horizontal para el FadeType::RANDOM_SQUARE int num_squares_width_; // Cantidad total de cuadraditos en horizontal para el FadeType::RANDOM_SQUARE
int numSquaresHeight; // Cantidad total de cuadraditos en vertical para el FadeType::RANDOM_SQUARE int num_squares_height_; // Cantidad total de cuadraditos en vertical para el FadeType::RANDOM_SQUARE
std::vector<SDL_Rect> square; // Vector con los indices de los cuadrados para el FadeType::RANDOM_SQUARE std::vector<SDL_Rect> square_; // Vector con los indices de los cuadrados para el FadeType::RANDOM_SQUARE
int fadeRandomSquaresDelay; // Duración entre cada pintado de cuadrados int fade_random_squares_delay_; // Duración entre cada pintado de cuadrados
int fadeRandomSquaresMult; // Cantidad de cuadrados que se pintaran cada vez int fade_random_squares_mult_; // Cantidad de cuadrados que se pintaran cada vez
int postDuration; // Duración posterior del fade tras finalizar int post_duration_; // Duración posterior del fade tras finalizar
int postCounter; // Contador para la duración posterior int post_counter_; // Contador para la duración posterior
// Inicializa las variables // Inicializa las variables
void init(); void init();
@@ -54,7 +54,7 @@ private:
public: public:
// Constructor // Constructor
Fade(SDL_Renderer *renderer); Fade();
// Destructor // Destructor
~Fade(); ~Fade();

File diff suppressed because it is too large Load Diff

View File

@@ -1,56 +1,38 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event #include <SDL2/SDL_render.h> // Para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture #include <SDL2/SDL_stdinc.h> // Para Uint32, Uint8
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <memory> // Para shared_ptr, unique_ptr
#include <string> // for string #include <string> // Para string
#include <vector> // for vector #include <vector> // Para vector
#include "section.h" // for options_e #include "balloon.h" // Para Balloon
#include "utils.h" // for DemoKeys, Color, HiScoreEntry #include "manage_hiscore_table.h" // Para HiScoreEntry
#include <memory> #include "options.h" // Para Options, OptionsGame, options
#include "asset.h" // lines 11-11 #include "player.h" // Para Player
#include "background.h" // lines 12-12 #include "utils.h" // Para Demo
#include "balloon.h" // lines 13-13 class Asset; // lines 14-14
#include "bullet.h" // lines 14-14 class Background; // lines 15-15
#include "enemy_formations.h" // lines 15-15 class BalloonFormations; // lines 16-16
#include "explosions.h" // lines 16-16 class Bullet; // lines 17-17
#include "fade.h" // lines 17-17 class Explosions; // lines 18-18
#include "input.h" // lines 18-18 class Fade; // lines 19-19
#include "item.h" // lines 19-19 class Input; // lines 20-20
#include "player.h" // lines 20-20 class Item; // lines 21-21
#include "scoreboard.h" // lines 21-21 class PathSprite; // lines 22-22
#include "screen.h" // lines 22-22 class Scoreboard; // lines 23-23
#include "smart_sprite.h" // lines 23-23 class Screen; // lines 24-24
#include "text.h" // lines 24-24 class SmartSprite; // lines 25-25
#include "texture.h" // lines 24-24 class Texture; // lines 27-27
enum class BulletType; enum class BulletType : Uint8; // lines 28-28
struct JA_Music_t; // lines 26-26 enum class ItemType; // lines 29-29
struct JA_Sound_t; // lines 27-27 struct Path;
#define GAME_MODE_DEMO_OFF false // Modo demo
#define GAME_MODE_DEMO_ON true constexpr bool GAME_MODE_DEMO_OFF = false;
constexpr bool GAME_MODE_DEMO_ON = true;
// Cantidad de elementos a escribir en los ficheros de datos // Cantidad de elementos a escribir en los ficheros de datos
#define TOTAL_SCORE_DATA 3 constexpr int TOTAL_SCORE_DATA = 3;
#define TOTAL_DEMO_DATA 2000
// Contadores
#define STAGE_COUNTER 200
#define HELP_COUNTER 1000
#define GAME_COMPLETED_START_FADE 500
#define GAME_COMPLETED_END 700
// Porcentaje de aparición de los objetos
#define ITEM_POINTS_1_DISK_ODDS 10
#define ITEM_POINTS_2_GAVINA_ODDS 6
#define ITEM_POINTS_3_PACMAR_ODDS 3
#define ITEM_CLOCK_ODDS 5
#define ITEM_COFFEE_ODDS 5
#define ITEM_POWER_BALL_ODDS 0
#define ITEM_COFFEE_MACHINE_ODDS 4
// Valores para las variables asociadas a los objetos
#define TIME_STOPPED_COUNTER 300
/* /*
Esta clase gestiona un estado del programa. Se encarga de toda la parte en la Esta clase gestiona un estado del programa. Se encarga de toda la parte en la
@@ -82,129 +64,126 @@ struct JA_Sound_t; // lines 27-27
class Game class Game
{ {
private: private:
struct helper_t // Enum
enum class GameState
{ {
bool needCoffee; // Indica si se necesitan cafes PLAYING,
bool needCoffeeMachine; // Indica si se necesita PowerUp COMPLETED,
bool needPowerBall; // Indica si se necesita una PowerBall GAME_OVER,
int counter; // Contador para no dar ayudas consecutivas
int itemPoints1Odds; // Probabilidad de aparición del objeto
int itemPoints2Odds; // Probabilidad de aparición del objeto
int itemPoints3Odds; // Probabilidad de aparición del objeto
int itemClockOdds; // Probabilidad de aparición del objeto
int itemCoffeeOdds; // Probabilidad de aparición del objeto
int itemCoffeeMachineOdds; // Probabilidad de aparición del objeto
}; };
struct demo_t // Contadores
static constexpr int HELP_COUNTER_ = 1000;
static constexpr int GAME_COMPLETED_START_FADE_ = 500;
static constexpr int GAME_COMPLETED_END_ = 700;
static constexpr int GAME_OVER_COUNTER_ = 350;
static constexpr int TIME_STOPPED_COUNTER_ = 360;
// Porcentaje de aparición de los objetos
static constexpr int ITEM_POINTS_1_DISK_ODDS_ = 10;
static constexpr int ITEM_POINTS_2_GAVINA_ODDS_ = 6;
static constexpr int ITEM_POINTS_3_PACMAR_ODDS_ = 3;
static constexpr int ITEM_CLOCK_ODDS_ = 5;
static constexpr int ITEM_COFFEE_ODDS_ = 5;
static constexpr int ITEM_POWER_BALL_ODDS_ = 0;
static constexpr int ITEM_COFFEE_MACHINE_ODDS_ = 4;
// Estructuras
struct Helper
{ {
bool enabled; // Indica si está activo el modo demo bool need_coffee; // Indica si se necesitan cafes
bool recording; // Indica si está activado el modo para grabar la demo bool need_coffee_machine; // Indica si se necesita PowerUp
int counter; // Contador para el modo demo bool need_power_ball; // Indica si se necesita una PowerBall
DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo int counter; // Contador para no dar ayudas consecutivas
DemoKeys dataFile[2][TOTAL_DEMO_DATA]; // Vector con diferentes sets de datos con los movimientos para la demo int item_disk_odds; // Probabilidad de aparición del objeto
int item_gavina_odds; // Probabilidad de aparición del objeto
int item_pacmar_odds; // Probabilidad de aparición del objeto
int item_clock_odds; // Probabilidad de aparición del objeto
int item_coffee_odds; // Probabilidad de aparición del objeto
int item_coffee_machine_odds; // Probabilidad de aparición del objeto
// Constructor con valores predeterminados
Helper()
: need_coffee(false),
need_coffee_machine(false),
need_power_ball(false),
counter(HELP_COUNTER_),
item_disk_odds(ITEM_POINTS_1_DISK_ODDS_),
item_gavina_odds(ITEM_POINTS_2_GAVINA_ODDS_),
item_pacmar_odds(ITEM_POINTS_3_PACMAR_ODDS_),
item_clock_odds(ITEM_CLOCK_ODDS_),
item_coffee_odds(ITEM_COFFEE_ODDS_),
item_coffee_machine_odds(ITEM_COFFEE_MACHINE_ODDS_) {}
}; };
// Objetos y punteros // Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
Screen *screen; // Objeto encargado de dibujar en pantalla Screen *screen_; // Objeto encargado de dibujar en pantalla
Asset *asset; // Objeto que gestiona todos los ficheros de recursos Asset *asset_; // Objeto que gestiona todos los ficheros de recursos
Input *input; // Manejador de entrada Input *input_; // Manejador de entrada
Scoreboard *scoreboard; // Objeto para dibujar el marcador Scoreboard *scoreboard_; // Objeto para dibujar el marcador
std::unique_ptr<Background> background; // Objeto para dibujar el fondo del juego std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
std::unique_ptr<Explosions> explosions; // Objeto para dibujar explosiones std::unique_ptr<Explosions> explosions_; // Objeto para dibujar explosiones
std::unique_ptr<EnemyFormations> enemyFormations; // Objeto para gestionar las oleadas enemigas std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para gestionar las oleadas enemigas
SDL_Texture *canvas; // Textura para dibujar la zona de juego SDL_Texture *canvas_; // Textura para dibujar la zona de juego
std::vector<std::shared_ptr<Player>> players; // Vector con los jugadores std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
std::vector<std::shared_ptr<Balloon>> balloons; // Vector con los globos std::vector<std::shared_ptr<Balloon>> balloons_; // Vector con los globos
std::vector<std::unique_ptr<Bullet>> bullets; // Vector con las balas std::vector<std::unique_ptr<Bullet>> bullets_; // Vector con las balas
std::vector<std::unique_ptr<Item>> items; // Vector con los items std::vector<std::unique_ptr<Item>> items_; // Vector con los items
std::vector<SmartSprite *> smartSprites; // Vector con los smartsprites std::vector<std::unique_ptr<SmartSprite>> smart_sprites_; // Vector con los smartsprites
std::vector<std::unique_ptr<PathSprite>> path_sprites_; // Vector con los smartsprites
std::shared_ptr<Texture> bulletTexture; // Textura para las balas std::shared_ptr<Texture> bullet_texture_; // Textura para las balas
std::vector<std::shared_ptr<Texture>> itemTextures; // Vector con las texturas de los items std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
std::vector<std::shared_ptr<Texture>> balloonTextures; // Vector con las texturas de los globos std::vector<std::shared_ptr<Texture>> balloon_textures_; // Vector con las texturas de los globos
std::vector<std::shared_ptr<Texture>> explosionsTextures; // Vector con las texturas de las explosiones std::vector<std::shared_ptr<Texture>> explosions_textures_; // Vector con las texturas de las explosiones
std::vector<std::shared_ptr<Texture>> player1Textures; // Vector con las texturas del jugador std::vector<std::vector<std::shared_ptr<Texture>>> player_textures_; // Vector con todas las texturas de los jugadores;
std::vector<std::shared_ptr<Texture>> player2Textures; // Vector con las texturas del jugador
std::vector<std::vector<std::shared_ptr<Texture>>> playerTextures; // Vector con todas las texturas de los jugadores;
std::shared_ptr<Texture> gameTextTexture; // Textura para los sprites con textos std::vector<std::shared_ptr<Texture>> game_text_textures_; // Vector con las texturas para los sprites con textos
std::vector<std::vector<std::string> *> itemAnimations; // 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> *> playerAnimations; // Vector con las animaciones del jugador std::vector<std::vector<std::string>> player_animations_; // Vector con las animaciones del jugador
std::vector<std::vector<std::string> *> balloonAnimations; // Vector con las animaciones de los globos std::vector<std::vector<std::string>> balloon_animations_; // Vector con las animaciones de los globos
std::vector<std::vector<std::string> *> explosionsAnimations; // Vector con las animaciones de las explosiones std::vector<std::vector<std::string>> explosions_animations_; // Vector con las animaciones de las explosiones
std::unique_ptr<Text> text; // Fuente para los textos del juego std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
std::unique_ptr<Text> textBig; // Fuente de texto grande std::vector<Path> paths_; // Vector con los recorridos precalculados almacenados
std::unique_ptr<Text> textNokia2; // Otra fuente de texto para mensajes
std::unique_ptr<Text> textNokiaBig2; // Y la versión en grande
std::unique_ptr<Fade> fade; // Objeto para renderizar fades
std::unique_ptr<SDL_Event> eventHandler; // Manejador de eventos
std::shared_ptr<SmartSprite> n1000Sprite; // Sprite con el texto 1.000
std::shared_ptr<SmartSprite> n2500Sprite; // Sprite con el texto 2.500
std::shared_ptr<SmartSprite> n5000Sprite; // Sprite con el texto 5.000
JA_Sound_t *balloonSound; // Sonido para la explosión del globo
JA_Sound_t *bulletSound; // Sonido para los disparos
JA_Sound_t *playerCollisionSound; // Sonido para la colisión del jugador con un enemigo
JA_Sound_t *hiScoreSound; // Sonido para cuando se alcanza la máxima puntuación
JA_Sound_t *itemDropSound; // Sonido para cuando se genera un item
JA_Sound_t *itemPickUpSound; // Sonido para cuando se recoge un item
JA_Sound_t *coffeeOutSound; // Sonido para cuando el jugador pierde el café al recibir un impacto
JA_Sound_t *stageChangeSound; // Sonido para cuando se cambia de fase
JA_Sound_t *bubble1Sound; // Sonido para cuando el jugador muere
JA_Sound_t *bubble2Sound; // Sonido para cuando el jugador muere
JA_Sound_t *bubble3Sound; // Sonido para cuando el jugador muere
JA_Sound_t *bubble4Sound; // Sonido para cuando el jugador muere
JA_Sound_t *clockSound; // Sonido para cuando se detiene el tiempo con el item reloj
JA_Sound_t *powerBallSound; // Sonido para cuando se explota una Power Ball
JA_Sound_t *coffeeMachineSound; // Sonido para cuando la máquina de café toca el suelo
JA_Music_t *music; // Musica de fondo
// Variables // Variables
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa HiScoreEntry hi_score_ = HiScoreEntry(
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa options.game.hi_score_table[0].name,
bool hiScoreAchieved; // Indica si se ha superado la puntuación máxima options.game.hi_score_table[0].score); // Máxima puntuación y nombre de quien la ostenta
HiScoreEntry hiScore; // Máxima puntuación y nombre de quien la ostenta
int currentStage; // Indica la fase actual int current_stage_; // Indica la fase actual
int stageBitmapCounter; // Contador para el tiempo visible del texto de Stage Demo demo_; // Variable con todas las variables relacionadas con el modo demo
float stageBitmapPath[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto GameDifficulty difficulty_ = options.game.difficulty; // Dificultad del juego
float getReadyBitmapPath[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto Helper helper_; // Variable para gestionar las ayudas
int gameOverCounter; // Contador para el estado de fin de partida Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
int menaceCurrent; // Nivel de amenaza actual bool coffee_machine_enabled_ = false; // Indica si hay una máquina de café en el terreno de juego
int menaceThreshold; // 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 bool hi_score_achieved_ = false; // Indica si se ha superado la puntuación máxima
bool timeStopped; // Indica si el tiempo está detenido bool paused_ = false; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade)
int timeStoppedCounter; // Temporizador para llevar la cuenta del tiempo detenido bool power_ball_enabled_ = false; // Indica si hay una powerball ya activa
int counter; // Contador para el juego float balloon_speed_; // Velocidad a la que se mueven los enemigos
int balloonsPopped; // Lleva la cuenta de los globos explotados float default_balloon_speed_; // Velocidad base de los enemigos, sin incrementar
int lastEnemyDeploy; // Guarda cual ha sido la última formación desplegada para no repetir; float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
int enemyDeployCounter; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero int balloon_deploy_counter_ = 0; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero
float enemySpeed; // Velocidad a la que se mueven los enemigos int balloons_popped_ = 0; // Lleva la cuenta de los globos explotados
float defaultEnemySpeed; // Velocidad base de los enemigos, sin incrementar int counter_ = 0; // Contador para el juego
helper_t helper; // Variable para gestionar las ayudas int current_power_ = 0; // Poder actual almacenado para completar la fase
bool powerBallEnabled; // Indica si hay una powerball ya activa int game_completed_counter_ = 0; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos
int powerBallCounter; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra int game_over_counter_ = GAME_OVER_COUNTER_; // Contador para el estado de fin de partida
bool coffeeMachineEnabled; // Indica si hay una máquina de café en el terreno de juego int last_balloon_deploy_ = 0; // Guarda cual ha sido la última formación desplegada para no repetir;
bool gameCompleted; // Indica si se ha completado la partida, llegando al final de la ultima pantalla int menace_current_ = 0; // Nivel de amenaza actual
int gameCompletedCounter; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos 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
GameDifficulty difficulty; // Dificultad del juego int power_ball_counter_ = 0; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
float difficultyScoreMultiplier; // Multiplicador de puntos en función de la dificultad int time_stopped_counter_ = 0; // Temporizador para llevar la cuenta del tiempo detenido
Color difficultyColor; // Color asociado a la dificultad int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
int lastStageReached; // Contiene el número de la última pantalla que se ha alcanzado GameState state_ = GameState::PLAYING; // Estado
demo_t demo; // Variable con todas las variables relacionadas con el modo demo
int totalPowerToCompleteGame; // La suma del poder necesario para completar todas las fases
bool paused; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade)
int currentPower; // Poder actual almacenado para completar la fase
#ifdef DEBUG #ifdef DEBUG
bool autoPopBalloons; // Si es true, incrementa automaticamente los globos explotados bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados
#endif #endif
// Actualiza el juego // Actualiza el juego
@@ -216,23 +195,11 @@ private:
// Comprueba los eventos que hay en cola // Comprueba los eventos que hay en cola
void checkEvents(); void checkEvents();
// Inicializa las variables necesarias para la sección 'Game' // Asigna texturas y animaciones
void init(int playerID); void setResources();
// Carga los recursos necesarios para la sección 'Game'
void loadMedia();
// Libera los recursos previamente cargados
void unloadMedia();
// Carga el fichero de datos para la demo
bool loadDemoFile(std::string filePath, DemoKeys (*dataFile)[TOTAL_DEMO_DATA]);
#ifdef RECORDING
// Guarda el fichero de datos para la demo
bool saveDemoFile(std::string filePath);
#endif
// Crea una formación de enemigos // Crea una formación de enemigos
void deployEnemyFormation(); void deployBalloonFormation();
// Aumenta el poder de la fase // Aumenta el poder de la fase
void increaseStageCurrentPower(int power); void increaseStageCurrentPower(int power);
@@ -250,7 +217,7 @@ private:
void updateStage(); void updateStage();
// Actualiza el estado de fin de la partida // Actualiza el estado de fin de la partida
void updateGameOver(); void updateGameOverState();
// Actualiza los globos // Actualiza los globos
void updateBalloons(); void updateBalloons();
@@ -259,7 +226,10 @@ private:
void renderBalloons(); void renderBalloons();
// Crea un globo nuevo en el vector de globos // Crea un globo nuevo en el vector de globos
std::shared_ptr<Balloon> createBalloon(float x, int y, int kind, float velx, float speed, int stoppedcounter); std::shared_ptr<Balloon> createBalloon(float x, int y, BalloonType type, BalloonSize size, float velx, float speed, int stopped_counter);
// Crea un globo a partir de otro globo
void createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction);
// Crea una PowerBall // Crea una PowerBall
void createPowerBall(); void createPowerBall();
@@ -267,14 +237,8 @@ private:
// Establece la velocidad de los globos // Establece la velocidad de los globos
void setBalloonSpeed(float speed); void setBalloonSpeed(float speed);
// Incrementa la velocidad de los globos
void incBalloonSpeed();
// Decrementa la velocidad de los globos
void decBalloonSpeed();
// 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 updateBalloonSpeed(); void checkAndUpdateBalloonSpeed();
// Explosiona un globo. Lo destruye y crea otros dos si es el caso // Explosiona un globo. Lo destruye y crea otros dos si es el caso
void popBalloon(std::shared_ptr<Balloon> balloon); void popBalloon(std::shared_ptr<Balloon> balloon);
@@ -282,20 +246,23 @@ private:
// Explosiona un globo. Lo destruye // Explosiona un globo. Lo destruye
void destroyBalloon(std::shared_ptr<Balloon> &balloon); void destroyBalloon(std::shared_ptr<Balloon> &balloon);
// Explosiona todos los globos
void popAllBalloons();
// Destruye todos los globos // Destruye todos los globos
void destroyAllBalloons(); void destroyAllBalloons();
// Destruye todos los items
void destroyAllItems();
// Detiene todos los globos // Detiene todos los globos
void stopAllBalloons(int time); void stopAllBalloons();
// Pone en marcha todos los globos // Pone en marcha todos los globos
void startAllBalloons(); void startAllBalloons();
// Obtiene el número de globos activos // Cambia el color de todos los globos
int countBalloons(); void reverseColorsToAllBalloons();
// Cambia el color de todos los globos
void normalColorsToAllBalloons();
// Vacia el vector de globos // Vacia el vector de globos
void freeBalloons(); void freeBalloons();
@@ -316,7 +283,7 @@ private:
void renderBullets(); void renderBullets();
// Crea un objeto bala // Crea un objeto bala
void createBullet(int x, int y, BulletType kind, bool poweredUp, int owner); void createBullet(int x, int y, BulletType kind, bool powered_up, int owner);
// Vacia el vector de balas // Vacia el vector de balas
void freeBullets(); void freeBullets();
@@ -328,55 +295,52 @@ private:
void renderItems(); void renderItems();
// Devuelve un item en función del azar // Devuelve un item en función del azar
int dropItem(); ItemType dropItem();
// Crea un objeto item // Crea un objeto item
void createItem(int kind, float x, float y); void createItem(ItemType type, float x, float y);
// Vacia el vector de items // Vacia el vector de items
void freeItems(); void freeItems();
// Crea un objeto SmartSprite // Crea un objeto PathSprite
void createItemScoreSprite(int x, int y, std::shared_ptr<SmartSprite> sprite); void createItemText(int x, std::shared_ptr<Texture> texture);
// Crea un objeto PathSprite
void createMessage(const std::vector<Path> &paths, std::shared_ptr<Texture> texture);
// Vacia el vector de smartsprites // Vacia el vector de smartsprites
void freeSmartSprites(); void freeSmartSprites();
// Crea un SmartSprite para arrojar el item café al recibir un impacto // Vacia el vector de pathsprites
void freePathSprites();
// Crea un SpriteSmart para arrojar el item café al recibir un impacto
void throwCoffee(int x, int y); void throwCoffee(int x, int y);
// Actualiza los SmartSprites // Actualiza los SpriteSmarts
void updateSmartSprites(); void updateSmartSprites();
// Pinta los SmartSprites activos // Pinta los SpriteSmarts activos
void renderSmartSprites(); void renderSmartSprites();
// Actualiza los PathSprites
void updatePathSprites();
// Pinta los PathSprites activos
void renderPathSprites();
// Acciones a realizar cuando el jugador muere // Acciones a realizar cuando el jugador muere
void killPlayer(std::shared_ptr<Player> &player); void killPlayer(std::shared_ptr<Player> &player);
// Calcula y establece el valor de amenaza en funcion de los globos activos // Calcula y establece el valor de amenaza en funcion de los globos activos
void evaluateAndSetMenace(); void evaluateAndSetMenace();
// Obtiene el valor de la variable
int getMenace() const;
// Establece el valor de la variable
void setTimeStopped(bool value);
// Obtiene el valor de la variable
bool isTimeStopped() const;
// Establece el valor de la variable
void setTimeStoppedCounter(int value);
// Incrementa el valor de la variable
void incTimeStoppedCounter(int value);
// Actualiza la variable EnemyDeployCounter // Actualiza la variable EnemyDeployCounter
void updateEnemyDeployCounter(); void updateBalloonDeployCounter();
// Actualiza y comprueba el valor de la variable // Actualiza y comprueba el valor de la variable
void updateTimeStoppedCounter(); void updateTimeStopped();
// Gestiona el nivel de amenaza // Gestiona el nivel de amenaza
void updateMenace(); void updateMenace();
@@ -384,11 +348,8 @@ private:
// Actualiza el fondo // Actualiza el fondo
void updateBackground(); void updateBackground();
// Gestiona la entrada durante el juego // Inicializa las variables que contienen puntos de ruta para mover objetos
void checkInput(); void initPaths();
// Pinta diferentes mensajes en la pantalla
void renderMessages();
// Habilita el efecto del item de detener el tiempo // Habilita el efecto del item de detener el tiempo
void enableTimeStopItem(); void enableTimeStopItem();
@@ -402,12 +363,6 @@ private:
// Calcula el poder actual de los globos en pantalla // Calcula el poder actual de los globos en pantalla
int calculateScreenPower(); int calculateScreenPower();
// Inicializa las variables que contienen puntos de ruta para mover objetos
void initPaths();
// Actualiza el tramo final de juego, una vez completado
void updateGameCompleted();
// Actualiza las variables de ayuda // Actualiza las variables de ayuda
void updateHelper(); void updateHelper();
@@ -420,12 +375,6 @@ private:
// Comprueba si todos los jugadores han terminado de jugar // Comprueba si todos los jugadores han terminado de jugar
bool allPlayersAreNotPlaying(); bool allPlayersAreNotPlaying();
// Carga las animaciones
void loadAnimations(std::string filePath, std::vector<std::string> *buffer);
// Elimina todos los objetos contenidos en vectores
void deleteAllVectorObjects();
// Recarga las texturas // Recarga las texturas
void reloadTextures(); void reloadTextures();
@@ -442,10 +391,10 @@ private:
void checkMusicStatus(); void checkMusicStatus();
// Añade una puntuación a la tabla de records // Añade una puntuación a la tabla de records
void addScoreToScoreBoard(std::string name, int score); void addScoreToScoreBoard(const std::string &name, int score);
// 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 activePlayerIndex, int inactivePlayerIndex); void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index);
// Comprueba el estado de juego de los jugadores // Comprueba el estado de juego de los jugadores
void checkPlayersStatusPlaying(); void checkPlayersStatusPlaying();
@@ -456,9 +405,87 @@ private:
// Obtiene un controlador a partir del "id" del jugador // Obtiene un controlador a partir del "id" del jugador
int getController(int playerId); int getController(int playerId);
// Gestiona la entrada durante el juego
void checkInput();
// Verifica si alguno de los controladores ha solicitado una pausa y actualiza el estado de pausa del juego.
void checkPauseInput();
// Gestiona las entradas de los jugadores en el modo demo, incluyendo movimientos y disparos automáticos.
void handleDemoMode();
// Procesa las entradas para un jugador específico durante el modo demo.
void handleDemoPlayerInput(const std::shared_ptr<Player> &player, int index);
// Maneja el disparo de un jugador, incluyendo la creación de balas y la gestión del tiempo de espera entre disparos.
void handleFireInput(const std::shared_ptr<Player> &player, BulletType bulletType);
// Gestiona las entradas de todos los jugadores en el modo normal (fuera del modo demo).
void handlePlayersInput();
// Maneja las entradas de movimiento y disparo para un jugador en modo normal.
void handleNormalPlayerInput(const std::shared_ptr<Player> &player);
// Procesa las entradas de disparo del jugador, permitiendo disparos automáticos si está habilitado.
void handleFireInputs(const std::shared_ptr<Player> &player, bool autofire, int controllerIndex);
// Maneja la continuación del jugador cuando no está jugando, permitiendo que continúe si se pulsa el botón de inicio.
void handlePlayerContinue(const std::shared_ptr<Player> &player);
// Procesa las entradas para la introducción del nombre del jugador.
void handleNameInput(const std::shared_ptr<Player> &player);
// Inicializa las variables para el modo DEMO
void initDemo(int player_id);
// Calcula el poder total necesario para completar el juego
void setTotalPower();
// Inicializa el marcador
void initScoreboard();
// Inicializa las opciones relacionadas con la dificultad
void initDifficultyVars();
// Inicializa los jugadores
void initPlayers(int player_id);
// Crea dos globos gordos
void createTwoBigBalloons();
// Pausa la música
void pauseMusic();
// Reanuda la música
void resumeMusic();
// Detiene la música
void stopMusic();
// Actualiza las variables durante el modo demo
void updateDemo();
#ifdef RECORDING
// Actualiza las variables durante el modo de grabación
void updateRecording();
#endif
// Actualiza las variables durante el transcurso normal del juego
void updateGame();
// Actualiza las variables durante el transcurso del final del juego
void updateCompletedGame();
// Gestiona eventos para el estado del final del juego
void updateCompletedState();
// Comprueba el estado del juego
void checkState();
// Vacía los vectores de elementos deshabilitados
void cleanVectors();
public: public:
// Constructor // Constructor
Game(int playerID, int currentStage, bool demo, JA_Music_t *music); Game(int playerID, int current_stage, bool demo);
// Destructor // Destructor
~Game(); ~Game();

View File

@@ -1,178 +1,175 @@
#include "game_logo.h" #include "game_logo.h"
#include <algorithm> // for max #include <SDL2/SDL_render.h> // Para SDL_FLIP_HORIZONTAL
#include <string> // for basic_string #include <algorithm> // Para max
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // Para AnimatedSprite
#include "asset.h" // for Asset #include "jail_audio.h" // Para JA_PlaySound
#include "jail_audio.h" // for JA_DeleteSound, JA_LoadSound, JA_PlaySound #include "param.h" // Para Param, param, ParamGame, ParamTitle
#include "param.h" // for param #include "resource.h" // Para Resource
#include "screen.h" // for Screen #include "smart_sprite.h" // Para SmartSprite
#include "smart_sprite.h" // for SmartSprite #include "sprite.h" // Para Sprite
#include "sprite.h" // for Sprite #include "texture.h" // Para Texture
#include "texture.h" // for Texture
#include "utils.h" // for Param, ParamGame, ParamTitle
// Constructor // Constructor
GameLogo::GameLogo(int x, int y) GameLogo::GameLogo(int x, int y)
: x(x), y(y) : dust_texture_(Resource::get()->getTexture("title_dust.png")),
coffee_texture_(Resource::get()->getTexture("title_coffee.png")),
crisis_texture_(Resource::get()->getTexture("title_crisis.png")),
arcade_edition_texture_(Resource::get()->getTexture("title_arcade_edition.png")),
dust_left_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Resource::get()->getAnimation("title_dust.ani"))),
dust_right_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Resource::get()->getAnimation("title_dust.ani"))),
coffee_sprite_(std::make_unique<SmartSprite>(coffee_texture_)),
crisis_sprite_(std::make_unique<SmartSprite>(crisis_texture_)),
arcade_edition_sprite_(std::make_unique<Sprite>(arcade_edition_texture_, (param.game.width - arcade_edition_texture_->getWidth()) / 2, param.title.arcade_edition_position, arcade_edition_texture_->getWidth(), arcade_edition_texture_->getHeight())),
x_(x),
y_(y)
{ {
// Crea los objetos
dustTexture = std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_dust.png"));
coffeeTexture = std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_coffee.png"));
crisisTexture = std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_crisis.png"));
arcadeEditionTexture = std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_arcade_edition.png"));
coffeeSprite = std::make_unique<SmartSprite>(coffeeTexture);
crisisSprite = std::make_unique<SmartSprite>(crisisTexture);
arcadeEditionSprite = std::make_unique<Sprite>((param.game.width - arcadeEditionTexture->getWidth()) / 2, param.title.arcade_edition_position, arcadeEditionTexture->getWidth(), arcadeEditionTexture->getHeight(), arcadeEditionTexture);
dustLSprite = std::make_unique<AnimatedSprite>(dustTexture, Asset::get()->get("title_dust.ani"));
dustRSprite = std::make_unique<AnimatedSprite>(dustTexture, Asset::get()->get("title_dust.ani"));
// Sonidos
crashSound = JA_LoadSound(Asset::get()->get("title.wav").c_str());
// Inicializa las variables // Inicializa las variables
init(); init();
} }
// Destructor
GameLogo::~GameLogo()
{
JA_DeleteSound(crashSound);
}
// Inicializa las variables // Inicializa las variables
void GameLogo::init() void GameLogo::init()
{ {
const auto xp = x - coffeeSprite->getWidth() / 2; const auto xp = x_ - coffee_sprite_->getWidth() / 2;
const auto desp = getInitialVerticalDesp(); const auto desp = getInitialVerticalDesp();
// Variables // Variables
status = Status::DISABLED; status_ = Status::DISABLED;
shake.desp = 1; shake_.desp = 1;
shake.delay = 2; shake_.delay = 2;
shake.lenght = 8; shake_.lenght = 8;
shake.remaining = shake.lenght; shake_.remaining = shake_.lenght;
shake.counter = shake.delay; shake_.counter = shake_.delay;
shake.origin = xp; shake_.origin = xp;
// Inicializa el bitmap de 'Coffee' // Inicializa el bitmap de 'Coffee'
coffeeSprite->init(); coffee_sprite_->setPosX(xp);
coffeeSprite->setPosX(xp); coffee_sprite_->setPosY(y_ - coffee_texture_->getHeight() - desp);
coffeeSprite->setPosY(y - coffeeTexture->getHeight() - desp); coffee_sprite_->setWidth(coffee_texture_->getWidth());
coffeeSprite->setWidth(coffeeTexture->getWidth()); coffee_sprite_->setHeight(coffee_texture_->getHeight());
coffeeSprite->setHeight(coffeeTexture->getHeight()); coffee_sprite_->setVelX(0.0f);
coffeeSprite->setVelX(0.0f); coffee_sprite_->setVelY(2.5f);
coffeeSprite->setVelY(2.5f); coffee_sprite_->setAccelX(0.0f);
coffeeSprite->setAccelX(0.0f); coffee_sprite_->setAccelY(0.1f);
coffeeSprite->setAccelY(0.1f); coffee_sprite_->setSpriteClip(0, 0, coffee_texture_->getWidth(), coffee_texture_->getHeight());
coffeeSprite->setSpriteClip(0, 0, coffeeTexture->getWidth(), coffeeTexture->getHeight()); coffee_sprite_->setEnabled(true);
coffeeSprite->setEnabled(true); coffee_sprite_->setFinishedCounter(0);
coffeeSprite->setFinishedCounter(0); coffee_sprite_->setDestX(xp);
coffeeSprite->setDestX(xp); coffee_sprite_->setDestY(y_ - coffee_texture_->getHeight());
coffeeSprite->setDestY(y - coffeeTexture->getHeight());
// Inicializa el bitmap de 'Crisis' // Inicializa el bitmap de 'Crisis'
crisisSprite->init(); crisis_sprite_->setPosX(xp + 15);
crisisSprite->setPosX(xp + 15); crisis_sprite_->setPosY(y_ + desp);
crisisSprite->setPosY(y + desp); crisis_sprite_->setWidth(crisis_texture_->getWidth());
crisisSprite->setWidth(crisisTexture->getWidth()); crisis_sprite_->setHeight(crisis_texture_->getHeight());
crisisSprite->setHeight(crisisTexture->getHeight()); crisis_sprite_->setVelX(0.0f);
crisisSprite->setVelX(0.0f); crisis_sprite_->setVelY(-2.5f);
crisisSprite->setVelY(-2.5f); crisis_sprite_->setAccelX(0.0f);
crisisSprite->setAccelX(0.0f); crisis_sprite_->setAccelY(-0.1f);
crisisSprite->setAccelY(-0.1f); crisis_sprite_->setSpriteClip(0, 0, crisis_texture_->getWidth(), crisis_texture_->getHeight());
crisisSprite->setSpriteClip(0, 0, crisisTexture->getWidth(), crisisTexture->getHeight()); crisis_sprite_->setEnabled(true);
crisisSprite->setEnabled(true); crisis_sprite_->setFinishedCounter(0);
crisisSprite->setFinishedCounter(0); crisis_sprite_->setDestX(xp + 15);
crisisSprite->setDestX(xp + 15); crisis_sprite_->setDestY(y_);
crisisSprite->setDestY(y);
// Inicializa el bitmap de 'DustRight' // Inicializa el bitmap de 'DustRight'
dustRSprite->resetAnimation(); dust_right_sprite_->resetAnimation();
dustRSprite->setPosX(coffeeSprite->getPosX() + coffeeSprite->getWidth()); dust_right_sprite_->setPosX(coffee_sprite_->getPosX() + coffee_sprite_->getWidth());
dustRSprite->setPosY(y); dust_right_sprite_->setPosY(y_);
dustRSprite->setWidth(16); dust_right_sprite_->setWidth(16);
dustRSprite->setHeight(16); dust_right_sprite_->setHeight(16);
dustRSprite->setFlip(SDL_FLIP_HORIZONTAL); dust_right_sprite_->setFlip(SDL_FLIP_HORIZONTAL);
// Inicializa el bitmap de 'DustLeft' // Inicializa el bitmap de 'DustLeft'
dustLSprite->resetAnimation(); dust_left_sprite_->resetAnimation();
dustLSprite->setPosX(coffeeSprite->getPosX() - 16); dust_left_sprite_->setPosX(coffee_sprite_->getPosX() - 16);
dustLSprite->setPosY(y); dust_left_sprite_->setPosY(y_);
dustLSprite->setWidth(16); dust_left_sprite_->setWidth(16);
dustLSprite->setHeight(16); dust_left_sprite_->setHeight(16);
} }
// Pinta la clase en pantalla // Pinta la clase en pantalla
void GameLogo::render() void GameLogo::render()
{ {
// Dibuja el logo // Dibuja el logo
coffeeSprite->render(); coffee_sprite_->render();
crisisSprite->render(); crisis_sprite_->render();
if (status == Status::FINISHED) if (status_ == Status::FINISHED)
{ arcade_edition_sprite_->render();
arcadeEditionSprite->render();
}
// Dibuja el polvillo del logo // Dibuja el polvillo del logo
dustRSprite->render(); dust_right_sprite_->render();
dustLSprite->render(); dust_left_sprite_->render();
} }
// Actualiza la lógica de la clase // Actualiza la lógica de la clase
void GameLogo::update() void GameLogo::update()
{ {
if (status == Status::MOVING) switch (status_)
{ {
coffeeSprite->update(); case Status::MOVING:
crisisSprite->update(); {
coffee_sprite_->update();
crisis_sprite_->update();
// Si los objetos han llegado a su destino, cambiamos de Sección // Si los objetos han llegado a su destino, cambiamos de Sección
if (coffeeSprite->hasFinished() && crisisSprite->hasFinished()) if (coffee_sprite_->hasFinished() && crisis_sprite_->hasFinished())
{ {
status = Status::SHAKING; status_ = Status::SHAKING;
// Reproduce el efecto sonoro // Reproduce el efecto sonoro
JA_PlaySound(crashSound); JA_PlaySound(Resource::get()->getSound("title.wav"));
} }
break;
} }
else if (status == Status::SHAKING) case Status::SHAKING:
{ {
// Agita el logo // Agita el logo
if (shake.remaining > 0) if (shake_.remaining > 0)
{ {
if (shake.counter > 0) if (shake_.counter > 0)
{ {
shake.counter--; shake_.counter--;
} }
else else
{ {
shake.counter = shake.delay; shake_.counter = shake_.delay;
const auto desp = shake.remaining % 2 == 0 ? shake.desp * (-1) : shake.desp; const auto desp = shake_.remaining % 2 == 0 ? shake_.desp * (-1) : shake_.desp;
coffeeSprite->setPosX(shake.origin + desp); coffee_sprite_->setPosX(shake_.origin + desp);
crisisSprite->setPosX(shake.origin + desp + 15); crisis_sprite_->setPosX(shake_.origin + desp + 15);
shake.remaining--; shake_.remaining--;
} }
} }
else else
{ {
coffeeSprite->setPosX(shake.origin); coffee_sprite_->setPosX(shake_.origin);
crisisSprite->setPosX(shake.origin + 15); crisis_sprite_->setPosX(shake_.origin + 15);
status = Status::FINISHED; status_ = Status::FINISHED;
} }
dustRSprite->update(); dust_right_sprite_->update();
dustLSprite->update(); dust_left_sprite_->update();
break;
} }
else if (status == Status::FINISHED) case Status::FINISHED:
{ {
dustRSprite->update(); dust_right_sprite_->update();
dustLSprite->update(); dust_left_sprite_->update();
break;
}
default:
break;
} }
} }
@@ -180,28 +177,28 @@ void GameLogo::update()
void GameLogo::enable() void GameLogo::enable()
{ {
init(); init();
status = Status::MOVING; status_ = Status::MOVING;
} }
// Indica si ha terminado la animación // Indica si ha terminado la animación
bool GameLogo::hasFinished() const bool GameLogo::hasFinished() const
{ {
return status == Status::FINISHED; return status_ == Status::FINISHED;
} }
// Recarga las texturas // Recarga las texturas
void GameLogo::reLoad() void GameLogo::reLoad()
{ {
dustTexture->reLoad(); dust_texture_->reLoad();
coffeeTexture->reLoad(); coffee_texture_->reLoad();
crisisTexture->reLoad(); crisis_texture_->reLoad();
} }
// Calcula el desplazamiento vertical inicial // Calcula el desplazamiento vertical inicial
int GameLogo::getInitialVerticalDesp() int GameLogo::getInitialVerticalDesp()
{ {
auto despUp = y; auto desp_up = y_;
auto despDown = param.game.height - y; auto desp_down = param.game.height - y_;
return std::max(despUp, despDown); return std::max(desp_up, desp_down);
} }

View File

@@ -1,46 +1,22 @@
#pragma once #pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <memory> // Para unique_ptr, shared_ptr
#include <memory> #include "animated_sprite.h" // Para AnimatedSprite
#include "smart_sprite.h" // Para SmartSprite
#include "texture.h" #include "sprite.h" // Para Sprite
#include "animated_sprite.h" class Texture; // lines 7-7
#include "smart_sprite.h"
#include "sprite.h"
struct JA_Sound_t;
// Clase GameLogo // Clase GameLogo
class GameLogo class GameLogo
{ {
private: private:
// Objetos y punteros
std::shared_ptr<Texture> dustTexture; // Textura con los graficos del polvo
std::shared_ptr<Texture> coffeeTexture; // Textura con los graficos de la palabra "COFFEE"
std::shared_ptr<Texture> crisisTexture; // Textura con los graficos de la plabra "CRISIS"
std::shared_ptr<Texture> arcadeEditionTexture; // Textura con los graficos de "Arcade Edition"
std::unique_ptr<AnimatedSprite> dustLSprite; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
std::unique_ptr<AnimatedSprite> dustRSprite; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
std::unique_ptr<SmartSprite> coffeeSprite; // Sprite con la palabra "COFFEE" para la pantalla de titulo
std::unique_ptr<SmartSprite> crisisSprite; // Sprite con la palabra "CRISIS" para la pantalla de titulo
std::unique_ptr<Sprite> arcadeEditionSprite; // Sprite con los graficos de "Arcade Edition"
JA_Sound_t *crashSound; // Sonido con el impacto del título
// Variables
int x; // Posición donde dibujar el logo
int y; // Posición donde dibujar el logo
enum class Status enum class Status
{ {
DISABLED, DISABLED,
MOVING, MOVING,
SHAKING, SHAKING,
FINISHED, FINISHED,
} status; // Estado en el que se encuentra la clase };
struct Shake struct Shake
{ {
@@ -50,7 +26,28 @@ private:
int lenght; // Cantidad de desplazamientos a realizar int lenght; // Cantidad de desplazamientos a realizar
int remaining; // Cantidad de desplazamientos pendientes a realizar int remaining; // Cantidad de desplazamientos pendientes a realizar
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
} shake; // Estructura para generar el efecto de agitación };
// Objetos y punteros
std::shared_ptr<Texture> dust_texture_; // Textura con los graficos del polvo
std::shared_ptr<Texture> coffee_texture_; // Textura con los graficos de la palabra "COFFEE"
std::shared_ptr<Texture> crisis_texture_; // Textura con los graficos de la plabra "CRISIS"
std::shared_ptr<Texture> arcade_edition_texture_; // Textura con los graficos de "Arcade Edition"
std::unique_ptr<AnimatedSprite> dust_left_sprite_; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
std::unique_ptr<AnimatedSprite> dust_right_sprite_; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
std::unique_ptr<SmartSprite> coffee_sprite_; // Sprite con la palabra "COFFEE" para la pantalla de titulo
std::unique_ptr<SmartSprite> crisis_sprite_; // Sprite con la palabra "CRISIS" para la pantalla de titulo
std::unique_ptr<Sprite> arcade_edition_sprite_; // Sprite con los graficos de "Arcade Edition"
// Variables
int x_; // Posición donde dibujar el logo
int y_; // Posición donde dibujar el logo
Status status_; // Estado en el que se encuentra la clase
Shake shake_; // Estructura para generar el efecto de agitación
// Inicializa las variables // Inicializa las variables
void init(); void init();
@@ -63,7 +60,7 @@ public:
GameLogo(int x, int y); GameLogo(int x, int y);
// Destructor // Destructor
~GameLogo(); ~GameLogo() = default;
// Pinta la clase en pantalla // Pinta la clase en pantalla
void render(); void render();

View File

@@ -1,136 +1,219 @@
#include "global_inputs.h" #include "global_inputs.h"
#include <string> // for basic_string, operator+ #include <string> // Para operator+, string
#include "input.h" // for Input, inputs_e, INPUT_DO_NOT_ALLOW_REPEAT #include "input.h" // Para Input, InputType, INPUT_DO_NOT_ALLOW_REPEAT
#include "jail_audio.h" // for JA_EnableMusic, JA_EnableSound #include "jail_audio.h" // Para JA_EnableMusic, JA_EnableSound
#include "lang.h" // for getText #include "lang.h" // Para getText
#include "options.h" // for options #include "notifier.h" // Para Notifier
#include "on_screen_help.h" #include "on_screen_help.h" // Para OnScreenHelp
#include "screen.h" // for Screen #include "options.h" // Para Options, OptionsAudio, options, OptionsM...
#include "section.h" // for options_e, name, name_e, options #include "section.h" // Para Name, Options, name, options
#include "utils.h" // for OptionsAudio, Options, OptionsMusic, boolToOnOff #include "utils.h" // Para boolToOnOff, stringInVector
#include "screen.h"
namespace globalInputs namespace globalInputs
{ {
// Variables // Variables
std::vector<int> servicePressedCounter; std::vector<int> service_pressed_counter;
// Inicializa variables // Inicializa variables
void init() void init()
{ {
const auto numInputs = Input::get()->getNumControllers() + 1; const auto num_inputs = Input::get()->getNumControllers() + 1;
servicePressedCounter.reserve(numInputs); service_pressed_counter.reserve(num_inputs);
for (int i = 0; i < numInputs; ++i) for (int i = 0; i < num_inputs; ++i)
{ {
servicePressedCounter.push_back(0); service_pressed_counter.push_back(0);
} }
} }
// Termina // Termina
void quit(section::options_e code) void quit(section::Options code)
{ {
if (Screen::get()->notificationsAreActive()) const std::string exit_code = "QUIT";
auto code_found = stringInVector(Notifier::get()->getCodes(), exit_code);
if (code_found)
{ {
section::name = section::NAME_QUIT; section::name = section::Name::QUIT;
section::options = code; section::options = code;
} }
else else
{ {
Screen::get()->showNotification(lang::getText(94)); #ifdef ARCADE
const int index = code == section::Options::QUIT_WITH_CONTROLLER ? 116 : 94;
Notifier::get()->showText({lang::getText(index), std::string()}, -1, exit_code);
#else
Notifier::get()->showText({lang::getText(94), std::string()}, -1, exit_code);
#endif
} }
} }
// Reinicia // Reinicia
void reset() void reset()
{ {
section::name = section::NAME_INIT; section::name = section::Name::INIT;
Screen::get()->showNotification("Reset"); Notifier::get()->showText({"Reset"});
} }
// Activa o desactiva el audio // Activa o desactiva el audio
void switchAudio() void toggleAudio()
{ {
options.audio.sound.enabled = options.audio.music.enabled = !options.audio.music.enabled; options.audio.enabled = !options.audio.enabled;
JA_EnableMusic(options.audio.music.enabled); if (options.audio.enabled)
JA_EnableSound(options.audio.sound.enabled); {
Screen::get()->showNotification("Audio " + boolToOnOff(options.audio.music.enabled)); JA_SetMusicVolume(to_JA_volume(options.audio.music.volume));
JA_SetSoundVolume(to_JA_volume(options.audio.sound.volume));
}
else
{
JA_SetMusicVolume(0);
JA_SetSoundVolume(0);
}
Notifier::get()->showText({"Audio " + boolToOnOff(options.audio.enabled)});
} }
// 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
void check() void check()
{ {
// Comprueba si se sale con el teclado // Teclado
if (Input::get()->checkInput(input_exit, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
quit(section::OPTIONS_QUIT_NORMAL); #ifndef ARCADE
return; // Comprueba el teclado para cambiar entre pantalla completa y ventana
} if (Input::get()->checkInput(InputType::WINDOW_FULLSCREEN, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
// Comprueba si se va a resetear el juego
else if (Input::get()->checkInput(input_reset, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{
reset();
return;
}
else if (Input::get()->checkInput(input_mute, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{
switchAudio();
return;
}
else if (Input::get()->checkInput(input_service, INPUT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{
servicePressedCounter[0]++;
if (servicePressedCounter[0] >= 3000)
{ {
OnScreenHelp::get()->toggleState(); Screen::get()->toggleVideoMode();
servicePressedCounter[0] = 0; const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen";
} Notifier::get()->showText({mode + " mode"});
return;
}
else
{
servicePressedCounter[0] = 0;
}
for (int i = 0; i < Input::get()->getNumControllers(); ++i)
{
// Comprueba si se sale con el mando
if (Input::get()->checkModInput(input_service, input_exit, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{
quit(section::OPTIONS_QUIT_SHUTDOWN);
return; return;
} }
// Comprueba si se va a resetear el juego // Comprueba el teclado para decrementar el tamaño de la ventana
else if (Input::get()->checkModInput(input_service, input_reset, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkInput(InputType::WINDOW_DEC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->decWindowSize();
const std::string size = std::to_string(options.video.window.size);
Notifier::get()->showText({"Window size x" + size});
return;
}
// Comprueba el teclado para incrementar el tamaño de la ventana
if (Input::get()->checkInput(InputType::WINDOW_INC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->incWindowSize();
const std::string size = std::to_string(options.video.window.size);
Notifier::get()->showText({"Window size x" + size});
return;
}
#endif
// Salir
if (Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
quit(section::Options::QUIT_WITH_KEYBOARD);
return;
}
// Reset
if (Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{ {
reset(); reset();
return; return;
} }
// Comprueba si se va a activar o desactivar el audio // Audio
else if (Input::get()->checkModInput(input_service, input_mute, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{ {
switchAudio(); toggleAudio();
return; return;
} }
if (Input::get()->checkInput(input_service, INPUT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) // Shaders
if (Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{ {
servicePressedCounter[i + 1]++; Screen::get()->toggleShaders();
return;
}
if (servicePressedCounter[i + 1] >= 3000) #ifdef DEBUG
// Comprueba el teclado para mostrar la información de debug
if (Input::get()->checkInput(InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->toggleDebugInfo();
return;
}
#endif
// OnScreenHelp
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
service_pressed_counter[0]++;
if (service_pressed_counter[0] >= 3000)
{ {
OnScreenHelp::get()->toggleState(); OnScreenHelp::get()->toggleState();
servicePressedCounter[i + 1] = 0; service_pressed_counter[0] = 0;
} }
return; return;
} }
else
service_pressed_counter[0] = 0;
}
// Mandos
{
for (int i = 0; i < Input::get()->getNumControllers(); ++i)
{ {
servicePressedCounter[i + 1] = 0; // Salir
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
quit(section::Options::QUIT_WITH_CONTROLLER);
return;
}
// Reset
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
reset();
return;
}
// Audio
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
toggleAudio();
return;
}
// Shaders
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
Screen::get()->toggleShaders();
return;
}
#ifdef DEBUG
// Debug Info
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
Screen::get()->toggleDebugInfo();
return;
}
#endif
// OnScreenHelp
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
service_pressed_counter[i + 1]++;
if (service_pressed_counter[i + 1] >= 3000)
{
OnScreenHelp::get()->toggleState();
service_pressed_counter[i + 1] = 0;
}
return;
}
service_pressed_counter[i + 1] = 0;
} }
} }
} }

View File

@@ -1,7 +1,7 @@
#include <vector> #include <vector>
namespace globalInputs namespace globalInputs
{ {
extern std::vector<int> servicePressedCounter; extern std::vector<int> service_pressed_counter;
// Inicializa variables // Inicializa variables
void init(); void init();

View File

@@ -1,58 +1,52 @@
#include "hiscore_table.h" #include "hiscore_table.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED #include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <algorithm> // for max #include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <vector> // for vector #include <algorithm> // Para max
#include "asset.h" // for Asset #include <vector> // Para vector
#include "background.h" // for Background #include "background.h" // Para Background
#include "global_inputs.h" // for globalInputs::check #include "fade.h" // Para Fade, FadeMode, FadeType
#include "input.h" // for Input #include "global_inputs.h" // Para check
#include "jail_audio.h" // for JA_GetMusicState, JA_Music_state #include "input.h" // Para Input
#include "lang.h" // for getText #include "jail_audio.h" // Para JA_GetMusicState, JA_Music_state
#include "options.h" // for options #include "lang.h" // Para getText
#include "param.h" // for param #include "manage_hiscore_table.h" // Para HiScoreEntry
#include "screen.h" // for Screen #include "options.h" // Para Options, OptionsGame, options
#include "text.h" // for Text, TXT_CENTER, TXT_SHADOW, TXT_COLOR #include "param.h" // Para Param, param, ParamGame, ParamFade
#include "utils.h" // for Param, ParamGame, HiScoreEntry #include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.h" // Para Name, name, Options, options
#include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW
#include "utils.h" // Para Color, Zone, fade_color, orange_color
// Constructor // Constructor
HiScoreTable::HiScoreTable(JA_Music_t *music) HiScoreTable::HiScoreTable()
: music(music) : renderer_(Screen::get()->getRenderer()),
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
fade_(std::make_unique<Fade>()),
background_(std::make_unique<Background>()),
text_(std::make_unique<Text>(Resource::get()->getTexture("smb2.gif"), Resource::get()->getTextFile("smb2.txt"))),
counter_(0),
ticks_(0),
view_area_({0, 0, param.game.width, param.game.height}),
fade_mode_(FadeMode::IN)
{ {
// Copia punteros // Inicializa el resto de variables
renderer = Screen::get()->getRenderer(); section::name = section::Name::HI_SCORE_TABLE;
// Objetos
eventHandler = std::make_unique<SDL_Event>();
fade = std::make_unique<Fade>(renderer);
background = std::make_unique<Background>(renderer);
text = std::make_unique<Text>(Asset::get()->get("smb2.gif"), Asset::get()->get("smb2.txt"), renderer);
// Crea un backbuffer para el renderizador
backbuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);
SDL_SetTextureBlendMode(backbuffer, SDL_BLENDMODE_BLEND);
// Inicializa variables
section::name = section::NAME_HI_SCORE_TABLE;
ticks = 0;
ticksSpeed = 15;
counter = 0;
counterEnd = 800;
viewArea = {0, 0, param.game.width, param.game.height};
fadeMode = FadeMode::IN;
// Inicializa objetos // Inicializa objetos
background->setPos(param.game.game_area.rect); SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
background->setCloudsSpeed(-0.1f); background_->setPos(param.game.game_area.rect);
background->setGradientNumber(1); background_->setCloudsSpeed(-0.1f);
background->setTransition(0.8f); background_->setGradientNumber(1);
fade->setColor(fade_color.r, fade_color.g, fade_color.b); background_->setTransition(0.8f);
fade->setType(FadeType::RANDOM_SQUARE); fade_->setColor(fade_color.r, fade_color.g, fade_color.b);
fade->setPost(param.fade.post_duration); fade_->setType(FadeType::RANDOM_SQUARE);
fade->setMode(fadeMode); fade_->setPost(param.fade.post_duration);
fade->activate(); fade_->setMode(fade_mode_);
fade_->activate();
// Crea el contenido de la textura con la lista de puntuaciones // Crea el contenido de la textura con la lista de puntuaciones
fillTexture(); fillTexture();
@@ -61,45 +55,46 @@ HiScoreTable::HiScoreTable(JA_Music_t *music)
// Destructor // Destructor
HiScoreTable::~HiScoreTable() HiScoreTable::~HiScoreTable()
{ {
SDL_DestroyTexture(backbuffer); SDL_DestroyTexture(backbuffer_);
} }
// Actualiza las variables // Actualiza las variables
void HiScoreTable::update() void HiScoreTable::update()
{ {
// Actualiza las variables constexpr int TICKS_SPEED = 15;
if (SDL_GetTicks() - ticks > ticksSpeed)
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
{ {
// Actualiza el contador de ticks // Actualiza el contador de ticks
ticks = SDL_GetTicks(); ticks_ = SDL_GetTicks();
// Mantiene la música sonando // Mantiene la música sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{ {
JA_PlayMusic(music); JA_PlayMusic(Resource::get()->getMusic("title.ogg"));
} }
// Actualiza el objeto screen // Actualiza el objeto screen
Screen::get()->update(); Screen::get()->update();
// Actualiza el fondo // Actualiza el fondo
background->update(); background_->update();
// Gestiona el fade // Gestiona el fade
updateFade(); updateFade();
// Gestiona el contador y sus eventos // Gestiona el contador y sus eventos
counter++; counter_++;
if (counter == 150) if (counter_ == 150)
{ {
background->setColor({0, 0, 0}); background_->setColor(Color(0, 0, 0));
background->setAlpha(96); background_->setAlpha(96);
} }
if (counter == counterEnd) if (counter_ == COUNTER_END_)
{ {
fade->activate(); fade_->activate();
} }
} }
} }
@@ -107,40 +102,40 @@ void HiScoreTable::update()
// Crea el contenido de la textura con la lista de puntuaciones // Crea el contenido de la textura con la lista de puntuaciones
void HiScoreTable::fillTexture() void HiScoreTable::fillTexture()
{ {
// hay 27 letras - 7 de puntos quedan 20 caracteres 20 - nameLenght 0 numDots // hay 27 letras - 7 de puntos quedan 20 caracteres 20 - name_lenght 0 num_dots
constexpr auto maxNames = 10; constexpr auto max_names = 10;
constexpr auto spaceBetweenHeader = 32; constexpr auto space_between_header = 32;
const auto spaceBetweenLines = text->getCharacterSize() * 2.0f; const auto space_between_lines = text_->getCharacterSize() * 2.0f;
const auto size = spaceBetweenHeader + spaceBetweenLines * (maxNames - 1) + text->getCharacterSize(); const auto size = space_between_header + space_between_lines * (max_names - 1) + text_->getCharacterSize();
const auto firstLine = (param.game.height - size) / 2; 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_);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
// Escribe el texto: Mejores puntuaciones // Escribe el texto: Mejores puntuaciones
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, param.game.game_area.center_x, firstLine, lang::getText(42), 1, orange_color, 1, shdw_txt_color); 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);
// Escribe los nombres de la tabla de puntuaciones // Escribe los nombres de la tabla de puntuaciones
for (int i = 0; i < maxNames; ++i) for (int i = 0; i < max_names; ++i)
{ {
const auto nameLenght = options.game.hi_score_table[i].name.length(); const auto name_lenght = options.game.hi_score_table[i].name.length();
const auto score = format(options.game.hi_score_table[i].score); const auto score = format(options.game.hi_score_table[i].score);
const auto scoreLenght = score.size(); const auto score_lenght = score.size();
const auto numDots = 25 - nameLenght - scoreLenght; const auto num_dots = 25 - name_lenght - score_lenght;
std::string dots = ""; std::string dots;
for (int j = 0; j < (int)numDots; ++j) for (int j = 0; j < (int)num_dots; ++j)
{ {
dots = dots + "."; dots = dots + ".";
} }
const auto line = options.game.hi_score_table[i].name + dots + score; const auto line = options.game.hi_score_table[i].name + dots + score;
text->writeDX(TXT_CENTER | TXT_SHADOW, param.game.game_area.center_x, (i * spaceBetweenLines) + firstLine + spaceBetweenHeader, line, 1, orange_color, 1, shdw_txt_color); 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
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
} }
// Pinta en pantalla // Pinta en pantalla
@@ -153,16 +148,16 @@ void HiScoreTable::render()
Screen::get()->clean(bg_color); Screen::get()->clean(bg_color);
// Pinta el fondo // Pinta el fondo
background->render(); background_->render();
// Establece la ventana del backbuffer // Establece la ventana del backbuffer
viewArea.y = std::max(0, param.game.height - counter + 100); view_area_.y = std::max(0, param.game.height - counter_ + 100);
// Copia el backbuffer al renderizador // Copia el backbuffer al renderizador
SDL_RenderCopy(renderer, backbuffer, nullptr, &viewArea); SDL_RenderCopy(renderer_, backbuffer_, nullptr, &view_area_);
// Renderiza el fade // Renderiza el fade
fade->render(); fade_->render();
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
Screen::get()->blit(); Screen::get()->blit();
@@ -171,7 +166,7 @@ void HiScoreTable::render()
// Recarga todas las texturas // Recarga todas las texturas
void HiScoreTable::reloadTextures() void HiScoreTable::reloadTextures()
{ {
text->reLoadTexture(); text_->reLoadTexture();
fillTexture(); fillTexture();
} }
@@ -179,19 +174,21 @@ void HiScoreTable::reloadTextures()
void HiScoreTable::checkEvents() void HiScoreTable::checkEvents()
{ {
// Comprueba los eventos que hay en la cola // Comprueba los eventos que hay en la cola
while (SDL_PollEvent(eventHandler.get()) != 0) SDL_Event event;
while (SDL_PollEvent(&event))
{ {
// Evento de salida de la aplicación // Evento de salida de la aplicación
if (eventHandler->type == SDL_QUIT) if (event.type == SDL_QUIT)
{ {
section::name = section::NAME_QUIT; section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break; break;
} }
// Comprueba si se ha cambiado el tamaño de la ventana // Comprueba si se ha cambiado el tamaño de la ventana
else if (eventHandler->type == SDL_WINDOWEVENT) else if (event.type == SDL_WINDOWEVENT)
{ {
if (eventHandler->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{ {
reloadTextures(); reloadTextures();
} }
@@ -206,14 +203,11 @@ void HiScoreTable::checkInput()
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;
return; return;
} }
// Comprueba el input para el resto de objetos
Screen::get()->checkInput();
// 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
globalInputs::check(); globalInputs::check();
} }
@@ -221,7 +215,7 @@ void HiScoreTable::checkInput()
// Bucle para la pantalla de instrucciones // Bucle para la pantalla de instrucciones
void HiScoreTable::run() void HiScoreTable::run()
{ {
while (section::name == section::NAME_HI_SCORE_TABLE) while (section::name == section::Name::HI_SCORE_TABLE)
{ {
checkInput(); checkInput();
update(); update();
@@ -233,18 +227,18 @@ void HiScoreTable::run()
// Gestiona el fade // Gestiona el fade
void HiScoreTable::updateFade() void HiScoreTable::updateFade()
{ {
fade->update(); fade_->update();
if (fade->hasEnded() && fadeMode == FadeMode::IN) if (fade_->hasEnded() && fade_mode_ == FadeMode::IN)
{ {
fade->reset(); fade_->reset();
fadeMode = FadeMode::OUT; fade_mode_ = FadeMode::OUT;
fade->setMode(fadeMode); fade_->setMode(fade_mode_);
} }
if (fade->hasEnded() && fadeMode == FadeMode::OUT) if (fade_->hasEnded() && fade_mode_ == FadeMode::OUT)
{ {
section::name = section::NAME_INSTRUCTIONS; section::name = section::Name::INSTRUCTIONS;
} }
} }
@@ -255,7 +249,7 @@ std::string HiScoreTable::format(int number)
const std::string score = std::to_string(number); const std::string score = std::to_string(number);
auto index = (int)score.size() - 1; auto index = (int)score.size() - 1;
std::string result = ""; std::string result;
auto i = 0; auto i = 0;
while (index >= 0) while (index >= 0)
{ {

View File

@@ -1,17 +1,14 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event #include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture #include <SDL2/SDL_stdinc.h> // para Uint16, Uint32, Uint8
#include <SDL2/SDL_stdinc.h> // for Uint16, Uint32 #include <memory> // para unique_ptr
#include <memory> #include <string> // para string
#include <string> // for string class Background; // lines 8-8
#include "fade.h" class Fade; // lines 9-9
#include "section.h" // for options_e class Text; // lines 10-10
#include "background.h" enum class FadeMode : Uint8; // lines 11-11
#include "text.h"
struct JA_Music_t;
/* /*
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
@@ -27,23 +24,22 @@ struct JA_Music_t;
class HiScoreTable class HiScoreTable
{ {
private: private:
// Objetos y punteros // Constantes
SDL_Renderer *renderer; // El renderizador de la ventana static constexpr Uint16 COUNTER_END_ = 800; // Valor final para el contador
SDL_Texture *backbuffer; // Textura para usar como backbuffer
JA_Music_t *music; // Musica de fondo
std::unique_ptr<Fade> fade; // Objeto para renderizar fades // Objetos y punteros
std::unique_ptr<Background> background; // Objeto para dibujar el fondo del juego SDL_Renderer *renderer_; // El renderizador de la ventana
std::unique_ptr<SDL_Event> eventHandler; // Manejador de eventos SDL_Texture *backbuffer_; // Textura para usar como backbuffer
std::unique_ptr<Text> text; // Objeto para escribir texto
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
std::unique_ptr<Text> text_; // Objeto para escribir texto
// Variables // Variables
Uint16 counter; // Contador Uint16 counter_; // Contador
Uint16 counterEnd; // Valor final para el 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
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa FadeMode fade_mode_; // Modo de fade a utilizar
SDL_Rect viewArea; // Parte de la textura que se muestra en pantalla
FadeMode fadeMode; // Modo de fade a utilizar
// Actualiza las variables // Actualiza las variables
void update(); void update();
@@ -71,7 +67,7 @@ private:
public: public:
// Constructor // Constructor
HiScoreTable(JA_Music_t *music); HiScoreTable();
// Destructor // Destructor
~HiScoreTable(); ~HiScoreTable();

View File

@@ -1,350 +1,165 @@
#include "input.h" #include "input.h"
#include <SDL2/SDL.h> // for SDL_INIT_GAMECONTROLLER, SDL_InitSubS... #include <SDL2/SDL.h> // Para SDL_INIT_GAMECONTROLLER, SDL_InitSubS...
#include <SDL2/SDL_error.h> // for SDL_GetError #include <SDL2/SDL_error.h> // Para SDL_GetError
#include <SDL2/SDL_events.h> // for SDL_ENABLE #include <SDL2/SDL_events.h> // Para SDL_ENABLE
#include <SDL2/SDL_keyboard.h> // for SDL_GetKeyboardState #include <SDL2/SDL_keyboard.h> // Para SDL_GetKeyboardState
#include <iostream> // for basic_ostream, operator<<, cout, basi... #include <algorithm> // Para find
#include <iostream> // Para basic_ostream, operator<<, cout, endl
#include <iterator> // Para distance
#include <unordered_map> // Para unordered_map, operator==, _Node_cons...
#include <utility> // Para pair
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Input *Input::input = nullptr; Input *Input::input_ = nullptr;
// [SINGLETON] Crearemos el objeto input con esta función estática // [SINGLETON] Crearemos el objeto input con esta función estática
void Input::init(std::string dbPath) void Input::init(const std::string &game_controller_db_path)
{ {
Input::input = new Input(dbPath); Input::input_ = new Input(game_controller_db_path);
} }
// [SINGLETON] Destruiremos el objeto input con esta función estática // [SINGLETON] Destruiremos el objeto input 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 input y podemos trabajar con él
Input *Input::get() Input *Input::get()
{ {
return Input::input; return Input::input_;
} }
// Constructor // Constructor
Input::Input(std::string dbPath) Input::Input(const std::string &game_controller_db_path)
: dbPath(dbPath) : game_controller_db_path_(game_controller_db_path)
{ {
// Inicializa variables
verbose = false;
enabled = true;
// Busca si hay mandos conectados // Busca si hay mandos conectados
discoverGameControllers(); discoverGameControllers();
// Inicializa las vectores // Inicializa los vectores
keyBindings_t kb; key_bindings_.resize(static_cast<int>(InputType::NUMBER_OF_INPUTS), KeyBindings());
kb.scancode = 0; controller_bindings_.resize(num_gamepads_, std::vector<ControllerBindings>(static_cast<int>(InputType::NUMBER_OF_INPUTS), ControllerBindings()));
kb.active = false;
keyBindings.resize(input_number_of_inputs, kb);
GameControllerBindings_t gcb;
gcb.button = SDL_CONTROLLER_BUTTON_INVALID;
gcb.active = false;
gameControllerBindings.resize(numGamepads);
for (int i = 0; i < numGamepads; ++i)
{
gameControllerBindings[i].resize(input_number_of_inputs, gcb);
}
// Listado de los inputs usados para jugar, excluyendo botones para la interfaz
gameInputs.clear();
gameInputs.push_back(input_fire_left);
gameInputs.push_back(input_fire_center);
gameInputs.push_back(input_fire_right);
gameInputs.push_back(input_up);
gameInputs.push_back(input_down);
gameInputs.push_back(input_left);
gameInputs.push_back(input_right);
// Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas // Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
buttonInputs.clear(); button_inputs_ = {InputType::FIRE_LEFT, InputType::FIRE_CENTER, InputType::FIRE_RIGHT, InputType::START};
buttonInputs.push_back(input_fire_left);
buttonInputs.push_back(input_fire_center);
buttonInputs.push_back(input_fire_right);
buttonInputs.push_back(input_start);
}
// Destructor
Input::~Input()
{
}
// Actualiza el estado del objeto
void Input::update()
{
if (disabledUntil == d_keyPressed && !checkAnyInput())
{
enable();
}
} }
// Asigna inputs a teclas // Asigna inputs a teclas
void Input::bindKey(inputs_e input, SDL_Scancode code) void Input::bindKey(InputType input, SDL_Scancode code)
{ {
keyBindings[input].scancode = code; key_bindings_.at(static_cast<int>(input)).scancode = code;
} }
// Asigna inputs a botones del mando // Asigna inputs a botones del mando
void Input::bindGameControllerButton(int index, inputs_e input, SDL_GameControllerButton button) void Input::bindGameControllerButton(int controller_index, InputType input, SDL_GameControllerButton button)
{ {
if (index < numGamepads) if (controller_index < num_gamepads_)
{ {
gameControllerBindings[index][input].button = button; controller_bindings_.at(controller_index).at(static_cast<int>(input)).button = button;
} }
} }
// Asigna inputs a botones del mando // Asigna inputs a botones del mando
void Input::bindGameControllerButton(int index, inputs_e inputTarget, inputs_e inputSource) void Input::bindGameControllerButton(int controller_index, InputType input_target, InputType input_source)
{ {
if (index < numGamepads) if (controller_index < num_gamepads_)
{ {
gameControllerBindings[index][inputTarget].button = gameControllerBindings[index][inputSource].button; controller_bindings_.at(controller_index).at(static_cast<int>(input_target)).button = controller_bindings_.at(controller_index).at(static_cast<int>(input_source)).button;
} }
} }
// Comprueba si un input esta activo // Comprueba si un input esta activo
bool Input::checkInput(inputs_e input, bool repeat, int device, int index) bool Input::checkInput(InputType input, bool repeat, InputDeviceToUse device, int controller_index)
{ {
if (!enabled) bool success_keyboard = false;
{ bool success_controller = false;
return false; const int input_index = static_cast<int>(input);
}
bool successKeyboard = false; if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY)
bool successGameController = false;
if (device == INPUT_USE_ANY)
{
index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
{ {
const Uint8 *keyStates = SDL_GetKeyboardState(nullptr); const Uint8 *keyStates = SDL_GetKeyboardState(nullptr);
if (repeat) if (repeat)
{ {
if (keyStates[keyBindings[input].scancode] != 0) success_keyboard = keyStates[key_bindings_[input_index].scancode] != 0;
{
successKeyboard = true;
}
else
{
successKeyboard = false;
}
} }
else else
{ {
if (!keyBindings[input].active) if (!key_bindings_[input_index].active)
{ {
if (keyStates[keyBindings[input].scancode] != 0) if (keyStates[key_bindings_[input_index].scancode] != 0)
{ {
keyBindings[input].active = true; key_bindings_[input_index].active = true;
successKeyboard = true; success_keyboard = true;
} }
else else
{ {
successKeyboard = false; success_keyboard = false;
} }
} }
else else
{ {
if (keyStates[keyBindings[input].scancode] == 0) if (keyStates[key_bindings_[input_index].scancode] == 0)
{ {
keyBindings[input].active = false; key_bindings_[input_index].active = false;
successKeyboard = false;
}
else
{
successKeyboard = false;
} }
success_keyboard = false;
} }
} }
} }
if (gameControllerFound() && index < numGamepads) if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_)
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY)) if ((device == InputDeviceToUse::CONTROLLER) || (device == InputDeviceToUse::ANY))
{ {
successGameController = checkAxisInput(input, index); success_controller = checkAxisInput(input, controller_index);
if (!successGameController) if (!success_controller)
{ {
if (repeat) if (repeat)
{ {
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) != 0) success_controller = SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) != 0;
{
successGameController = true;
}
else
{
successGameController = false;
}
} }
else else
{ {
if (!gameControllerBindings[index][input].active) if (!controller_bindings_.at(controller_index).at(input_index).active)
{ {
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) != 0) if (SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) != 0)
{ {
gameControllerBindings[index][input].active = true; controller_bindings_.at(controller_index).at(input_index).active = true;
successGameController = true; success_controller = true;
} }
else else
{ {
successGameController = false; success_controller = false;
} }
} }
else else
{ {
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) == 0) if (SDL_GameControllerGetButton(connected_controllers_.at(controller_index), controller_bindings_.at(controller_index).at(input_index).button) == 0)
{ {
gameControllerBindings[index][input].active = false; controller_bindings_.at(controller_index).at(input_index).active = false;
successGameController = false;
}
else
{
successGameController = false;
} }
success_controller = false;
} }
} }
} }
} }
return (successKeyboard || successGameController); return (success_keyboard || success_controller);
}
// Comprueba si un input con modificador esta activo
bool Input::checkModInput(inputs_e inputMod, inputs_e input, bool repeat, int device, int index)
{
if (!enabled || index >= numGamepads || !checkInput(inputMod, INPUT_ALLOW_REPEAT, device, index))
{
return false;
}
bool successKeyboard = false;
bool successGameController = false;
if (device == INPUT_USE_ANY)
{
index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
{
const Uint8 *keyStates = SDL_GetKeyboardState(nullptr);
if (repeat)
{
if (keyStates[keyBindings[input].scancode] != 0)
{
successKeyboard = true;
}
else
{
successKeyboard = false;
}
}
else
{
if (!keyBindings[input].active)
{
if (keyStates[keyBindings[input].scancode] != 0)
{
keyBindings[input].active = true;
successKeyboard = true;
}
else
{
successKeyboard = false;
}
}
else
{
if (keyStates[keyBindings[input].scancode] == 0)
{
keyBindings[input].active = false;
successKeyboard = false;
}
else
{
successKeyboard = false;
}
}
}
}
if (gameControllerFound() && index < numGamepads)
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY))
{
successGameController = checkAxisInput(input, index);
if (!successGameController)
{
if (repeat)
{
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) != 0)
{
successGameController = true;
}
else
{
successGameController = false;
}
}
else
{
if (!gameControllerBindings[index][input].active)
{
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) != 0)
{
gameControllerBindings[index][input].active = true;
successGameController = true;
}
else
{
successGameController = false;
}
}
else
{
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) == 0)
{
gameControllerBindings[index][input].active = false;
successGameController = false;
}
else
{
successGameController = false;
}
}
}
}
}
return (successKeyboard || successGameController);
} }
// Comprueba si hay almenos un input activo // Comprueba si hay almenos un input activo
bool Input::checkAnyInput(int device, int index) bool Input::checkAnyInput(InputDeviceToUse device, int controller_index)
{ {
if (device == INPUT_USE_ANY) if (device == InputDeviceToUse::KEYBOARD || device == InputDeviceToUse::ANY)
{
index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
{ {
const Uint8 *mKeystates = SDL_GetKeyboardState(nullptr); const Uint8 *mKeystates = SDL_GetKeyboardState(nullptr);
for (int i = 0; i < (int)keyBindings.size(); ++i) for (int i = 0; i < (int)key_bindings_.size(); ++i)
{ {
if (mKeystates[keyBindings[i].scancode] != 0 && !keyBindings[i].active) if (mKeystates[key_bindings_[i].scancode] != 0 && !key_bindings_[i].active)
{ {
keyBindings[i].active = true; key_bindings_[i].active = true;
return true; return true;
} }
} }
@@ -352,13 +167,13 @@ bool Input::checkAnyInput(int device, int index)
if (gameControllerFound()) if (gameControllerFound())
{ {
if (device == INPUT_USE_GAMECONTROLLER || device == INPUT_USE_ANY) if (device == InputDeviceToUse::CONTROLLER || device == InputDeviceToUse::ANY)
{ {
for (int i = 0; i < (int)gameControllerBindings.size(); ++i) for (int i = 0; i < (int)controller_bindings_.size(); ++i)
{ {
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][i].button) != 0 && !gameControllerBindings[index][i].active) if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][i].button) != 0 && !controller_bindings_[controller_index][i].active)
{ {
gameControllerBindings[index][i].active = true; controller_bindings_[controller_index][i].active = true;
return true; return true;
} }
} }
@@ -372,24 +187,24 @@ bool Input::checkAnyInput(int device, int index)
int Input::checkAnyButtonPressed(bool repeat) int Input::checkAnyButtonPressed(bool repeat)
{ {
// Si está pulsado el botón de servicio, ningún botón se puede considerar pulsado // Si está pulsado el botón de servicio, ningún botón se puede considerar pulsado
if (checkInput(input_service, INPUT_ALLOW_REPEAT, INPUT_USE_ANY)) if (checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::ANY))
{ {
return 0; return 0;
} }
// Solo comprueba los botones definidos previamente // Solo comprueba los botones definidos previamente
for (auto bi : buttonInputs) for (auto bi : button_inputs_)
{ {
// Comprueba el teclado // Comprueba el teclado
if (checkInput(bi, repeat, INPUT_USE_KEYBOARD)) if (checkInput(bi, repeat, InputDeviceToUse::KEYBOARD))
{ {
return 1; return 1;
} }
// Comprueba los mandos // Comprueba los mandos
for (int i = 0; i < numGamepads; ++i) for (int i = 0; i < num_gamepads_; ++i)
{ {
if (checkInput(bi, repeat, INPUT_USE_GAMECONTROLLER, i)) if (checkInput(bi, repeat, InputDeviceToUse::CONTROLLER, i))
{ {
return i + 1; return i + 1;
} }
@@ -409,113 +224,72 @@ bool Input::discoverGameControllers()
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
} }
if (SDL_GameControllerAddMappingsFromFile(dbPath.c_str()) < 0) if (SDL_GameControllerAddMappingsFromFile(game_controller_db_path_.c_str()) < 0)
{ {
if (verbose) std::cout << "Error, could not load " << game_controller_db_path_.c_str() << " file: " << SDL_GetError() << std::endl;
{
std::cout << "Error, could not load " << dbPath.c_str() << " file: " << SDL_GetError() << std::endl;
}
} }
numJoysticks = SDL_NumJoysticks(); num_joysticks_ = SDL_NumJoysticks();
numGamepads = 0; num_gamepads_ = 0;
// Cuenta el número de mandos // Cuenta el número de mandos
joysticks.clear(); joysticks_.clear();
for (int i = 0; i < numJoysticks; ++i) for (int i = 0; i < num_joysticks_; ++i)
{ {
SDL_Joystick *joy = SDL_JoystickOpen(i); auto joy = SDL_JoystickOpen(i);
joysticks.push_back(joy); joysticks_.push_back(joy);
if (SDL_IsGameController(i)) if (SDL_IsGameController(i))
{ {
numGamepads++; num_gamepads_++;
} }
} }
if (verbose) std::cout << "\n** LOOKING FOR GAME CONTROLLERS" << std::endl;
{ std::cout << "Gamepads found: " << num_gamepads_ << std::endl;
std::cout << "\nChecking for game controllers...\n";
std::cout << numJoysticks << " joysticks found, " << numGamepads << " are gamepads\n";
}
if (numGamepads > 0) if (num_gamepads_ > 0)
{ {
found = true; found = true;
for (int i = 0; i < numGamepads; i++) for (int i = 0; i < num_gamepads_; i++)
{ {
// Abre el mando y lo añade a la lista // Abre el mando y lo añade a la lista
SDL_GameController *pad = SDL_GameControllerOpen(i); auto pad = SDL_GameControllerOpen(i);
if (SDL_GameControllerGetAttached(pad) == 1) if (SDL_GameControllerGetAttached(pad) == 1)
{ {
connectedControllers.push_back(pad); connected_controllers_.push_back(pad);
const std::string separator(" #"); const std::string name = SDL_GameControllerNameForIndex(i);
std::string name = SDL_GameControllerNameForIndex(i); std::cout << "#" << i << ": " << name << std::endl;
if (verbose) controller_names_.push_back(name);
{
std::cout << name << std::endl;
}
controllerNames.push_back(name);
} }
else else
{ {
if (verbose) std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
{
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
}
} }
} }
SDL_GameControllerEventState(SDL_ENABLE); SDL_GameControllerEventState(SDL_ENABLE);
} }
std::cout << "\n** FINISHED LOOKING FOR GAME CONTROLLERS" << std::endl;
return found; return found;
} }
// Comprueba si hay algun mando conectado // Comprueba si hay algun mando conectado
bool Input::gameControllerFound() bool Input::gameControllerFound() { return num_gamepads_ > 0 ? true : false; }
{
return numGamepads > 0 ? true : false;
}
// Obten el nombre de un mando de juego // Obten el nombre de un mando de juego
std::string Input::getControllerName(int index) const std::string Input::getControllerName(int controller_index) const { return num_gamepads_ > 0 ? controller_names_.at(controller_index) : std::string(); }
{
return numGamepads > 0 ? controllerNames[index] : "";
}
// Obten el número de mandos conectados // Obten el número de mandos conectados
int Input::getNumControllers() const int Input::getNumControllers() const { return num_gamepads_; }
{
return numGamepads;
}
// Establece si ha de mostrar mensajes
void Input::setVerbose(bool value)
{
verbose = value;
}
// Deshabilita las entradas durante un periodo de tiempo
void Input::disableUntil(i_disable_e value)
{
disabledUntil = value;
enabled = false;
}
// Hablita las entradas
void Input::enable()
{
enabled = true;
disabledUntil = d_notDisabled;
}
// Obtiene el indice del controlador a partir de un event.id // Obtiene el indice del controlador a partir de un event.id
int Input::getJoyIndex(int id) const int Input::getJoyIndex(int id) const
{ {
for (int i = 0; i < numJoysticks; ++i) for (int i = 0; i < num_joysticks_; ++i)
{ {
if (SDL_JoystickInstanceID(joysticks[i]) == id) if (SDL_JoystickInstanceID(joysticks_[i]) == id)
{ {
return i; return i;
} }
@@ -524,160 +298,92 @@ int Input::getJoyIndex(int id) const
} }
// Muestra por consola los controles asignados // Muestra por consola los controles asignados
void Input::printBindings(int device, int index) const void Input::printBindings(InputDeviceToUse device, int controller_index) const
{ {
if (device == INPUT_USE_ANY || device == INPUT_USE_KEYBOARD) if (device == InputDeviceToUse::ANY || device == InputDeviceToUse::KEYBOARD)
{ {
return; return;
} }
if (device == INPUT_USE_GAMECONTROLLER) if (device == InputDeviceToUse::CONTROLLER)
{ {
if (index >= numGamepads) if (controller_index >= num_gamepads_)
{ {
return; return;
} }
// Muestra el nombre del mando // Muestra el nombre del mando
std::cout << "\n" std::cout << "\n" + controller_names_.at(controller_index) << std::endl;
<< controllerNames[index] << std::endl;
// Muestra los botones asignados // Muestra los botones asignados
for (auto bi : buttonInputs) for (auto bi : button_inputs_)
{ {
std::cout << to_string(bi) << " : " << gameControllerBindings[index][bi].button << std::endl; std::cout << to_string(bi) << " : " << controller_bindings_.at(controller_index).at(static_cast<int>(bi)).button << std::endl;
} }
} }
} }
// Obtiene el SDL_GameControllerButton asignado a un input // Obtiene el SDL_GameControllerButton asignado a un input
SDL_GameControllerButton Input::getControllerBinding(int index, inputs_e input) const SDL_GameControllerButton Input::getControllerBinding(int controller_index, InputType input) const
{ {
return gameControllerBindings[index][input].button; return controller_bindings_[controller_index][static_cast<int>(input)].button;
} }
// Obtiene el indice a partir del nombre del mando // Obtiene el indice a partir del nombre del mando
int Input::getIndexByName(std::string name) const int Input::getIndexByName(const std::string &name) const
{ {
for (int i = 0; i < numGamepads; ++i) auto it = std::find(controller_names_.begin(), controller_names_.end(), name);
{ return it != controller_names_.end() ? std::distance(controller_names_.begin(), it) : -1;
if (controllerNames[i] == name)
{
return i;
}
}
return -1;
} }
// Convierte un inputs_e a std::string // Convierte un InputType a std::string
std::string Input::to_string(inputs_e input) const std::string Input::to_string(InputType input) const
{ {
if (input == input_fire_left) switch (input)
{ {
case InputType::FIRE_LEFT:
return "input_fire_left"; return "input_fire_left";
} case InputType::FIRE_CENTER:
if (input == input_fire_center)
{
return "input_fire_center"; return "input_fire_center";
} case InputType::FIRE_RIGHT:
if (input == input_fire_right)
{
return "input_fire_right"; return "input_fire_right";
} case InputType::START:
if (input == input_start)
{
return "input_start"; return "input_start";
} case InputType::SERVICE:
if (input == input_service)
{
return "input_service"; return "input_service";
default:
return "";
} }
return "";
} }
// Convierte un std::string a inputs_e // Convierte un std::string a InputType
inputs_e Input::to_inputs_e(std::string name) const InputType Input::to_inputs_e(const std::string &name) const
{ {
if (name == "input_fire_left") static const std::unordered_map<std::string, InputType> inputMap = {
{ {"input_fire_left", InputType::FIRE_LEFT},
return input_fire_left; {"input_fire_center", InputType::FIRE_CENTER},
} {"input_fire_right", InputType::FIRE_RIGHT},
{"input_start", InputType::START},
{"input_service", InputType::SERVICE}};
if (name == "input_fire_center") auto it = inputMap.find(name);
{ return it != inputMap.end() ? it->second : InputType::NONE;
return input_fire_center;
}
if (name == "input_fire_right")
{
return input_fire_right;
}
if (name == "input_start")
{
return input_start;
}
if (name == "input_service")
{
return input_service;
}
return input_null;
}
// Activa todos los inputs. Sirve para evitar inputs sin repeticiones pero que ya vienen pulsados cuando checkInput no estaba monitorizando
void Input::allActive(int index)
{
for (int i = 0; i < (int)buttonInputs.size(); ++i)
{
gameControllerBindings[index][i].active = true;
}
} }
// Comprueba el eje del mando // Comprueba el eje del mando
bool Input::checkAxisInput(inputs_e input, int index) const bool Input::checkAxisInput(InputType input, int controller_index) const
{ {
bool success = false;
switch (input) switch (input)
{ {
case input_left: case InputType::LEFT:
if (SDL_GameControllerGetAxis(connectedControllers[index], SDL_CONTROLLER_AXIS_LEFTX) < -30000) return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) < -30000;
{ case InputType::RIGHT:
success = true; return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) > 30000;
} case InputType::UP:
break; return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) < -30000;
case InputType::DOWN:
case input_right: return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) > 30000;
if (SDL_GameControllerGetAxis(connectedControllers[index], SDL_CONTROLLER_AXIS_LEFTX) > 30000)
{
success = true;
}
break;
case input_up:
if (SDL_GameControllerGetAxis(connectedControllers[index], SDL_CONTROLLER_AXIS_LEFTY) < -30000)
{
success = true;
}
break;
case input_down:
if (SDL_GameControllerGetAxis(connectedControllers[index], SDL_CONTROLLER_AXIS_LEFTY) > 30000)
{
success = true;
}
break;
default: default:
break; return false;
} }
return success;
} }

View File

@@ -1,113 +1,113 @@
#pragma once #pragma once
#include <SDL2/SDL_gamecontroller.h> // for SDL_GameControllerButton, SDL_G... #include <SDL2/SDL_gamecontroller.h> // para SDL_GameControllerButton, SDL_G...
#include <SDL2/SDL_joystick.h> // for SDL_Joystick #include <SDL2/SDL_joystick.h> // para SDL_Joystick
#include <SDL2/SDL_scancode.h> // for SDL_Scancode #include <SDL2/SDL_scancode.h> // para SDL_Scancode
#include <SDL2/SDL_stdinc.h> // for Uint8 #include <SDL2/SDL_stdinc.h> // para Uint8
#include <string> // for string, basic_string #include <string> // para string, basic_string
#include <vector> // for vector #include <vector> // para vector
/* /*
connectedControllers es un vector donde estan todos los mandos encontrados [0 .. n] connectedControllers es un vector donde estan todos los mandos encontrados [0 .. n]
checkInput requiere de un indice para comprobar las pulsaciónes de un controlador en concreto [0 .. n] checkInput requiere de un indice para comprobar las pulsaciónes de un controlador en concreto [0 .. n]
device contiene el tipo de dispositivo a comprobar: device contiene el tipo de dispositivo a comprobar:
INPUT_USE_KEYBOARD solo mirará el teclado InputDeviceToUse::KEYBOARD solo mirará el teclado
INPUT_USE_GAMECONTROLLER solo mirará el controlador especificado (Si no se especifica, el primero) InputDeviceToUse::CONTROLLER solo mirará el controlador especificado (Si no se especifica, el primero)
INPUT_USE_ANY mirará tanto el teclado como el PRIMER controlador InputDeviceToUse::ANY mirará tanto el teclado como el PRIMER controlador
*/ */
enum inputs_e enum class InputType : int
{ {
// Inputs de movimiento // Inputs de movimiento
input_up, UP,
input_down, DOWN,
input_left, LEFT,
input_right, RIGHT,
// Inputs personalizados // Inputs personalizados
input_fire_left, FIRE_LEFT,
input_fire_center, FIRE_CENTER,
input_fire_right, FIRE_RIGHT,
input_start, START,
// Inputs de control // Inputs de control
input_exit, EXIT,
input_pause, PAUSE,
input_service, SERVICE,
input_window_fullscreen, WINDOW_FULLSCREEN,
input_window_inc_size, WINDOW_INC_SIZE,
input_window_dec_size, WINDOW_DEC_SIZE,
input_video_shaders, VIDEO_SHADERS,
input_reset, RESET,
input_mute, MUTE,
input_showinfo, SHOWINFO,
input_config, CONFIG,
input_swap_controllers, SWAP_CONTROLLERS,
// Input obligatorio // Input obligatorio
input_null, NONE,
input_number_of_inputs, NUMBER_OF_INPUTS,
}; };
#define INPUT_ALLOW_REPEAT true constexpr bool INPUT_ALLOW_REPEAT = true;
#define INPUT_DO_NOT_ALLOW_REPEAT false constexpr bool INPUT_DO_NOT_ALLOW_REPEAT = false;
#define INPUT_USE_KEYBOARD 0 enum class InputDeviceToUse : int
#define INPUT_USE_GAMECONTROLLER 1
#define INPUT_USE_ANY 2
enum i_disable_e
{ {
d_notDisabled, KEYBOARD = 0,
d_forever, CONTROLLER = 1,
d_keyPressed ANY = 2,
}; };
class Input class Input
{ {
private: private:
// [SINGLETON] Objeto screen privado para Don Melitón // [SINGLETON] Objeto screen privado para Don Melitón
static Input *input; static Input *input_;
struct keyBindings_t struct KeyBindings
{ {
Uint8 scancode; // Scancode asociado Uint8 scancode; // Scancode asociado
bool active; // Indica si está activo bool active; // Indica si está activo
// Constructor
explicit KeyBindings(Uint8 sc = 0, bool act = false)
: scancode(sc), active(act) {}
}; };
struct GameControllerBindings_t struct ControllerBindings
{ {
SDL_GameControllerButton button; // GameControllerButton asociado SDL_GameControllerButton button; // GameControllerButton asociado
bool active; // Indica si está activo bool active; // Indica si está activo
// Constructor
explicit ControllerBindings(SDL_GameControllerButton btn = SDL_CONTROLLER_BUTTON_INVALID, bool act = false)
: button(btn), active(act) {}
}; };
// Variables // Variables
std::vector<SDL_GameController *> connectedControllers; // Vector con todos los mandos conectados std::vector<SDL_GameController *> connected_controllers_; // Vector con todos los mandos conectados
std::vector<SDL_Joystick *> joysticks; // Vector con todos los joysticks conectados std::vector<SDL_Joystick *> joysticks_; // Vector con todos los joysticks conectados
std::vector<keyBindings_t> keyBindings; // Vector con las teclas asociadas a los inputs predefinidos std::vector<KeyBindings> key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<std::vector<GameControllerBindings_t>> gameControllerBindings; // Vector con los botones asociadas a los inputs predefinidos para cada mando std::vector<std::vector<ControllerBindings>> controller_bindings_; // Vector con los botones asociadas a los inputs predefinidos para cada mando
std::vector<std::string> controllerNames; // Vector con los nombres de los mandos std::vector<std::string> controller_names_; // Vector con los nombres de los mandos
std::vector<inputs_e> gameInputs; // Inputs usados para jugar, normalmente direcciones y botones std::vector<InputType> button_inputs_; // Inputs asignados al jugador y a botones, excluyendo direcciones
std::vector<inputs_e> buttonInputs; // Inputs asignados al jugador y a botones, excluyendo direcciones int num_joysticks_ = 0; // Número de joysticks conectados
int numJoysticks; // Número de joysticks conectados int num_gamepads_ = 0; // Número de mandos conectados
int numGamepads; // Número de mandos conectados std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt
std::string dbPath; // Ruta al archivo gamecontrollerdb.txt
bool verbose; // Indica si ha de mostrar mensajes
i_disable_e disabledUntil; // Tiempo que esta deshabilitado
bool enabled; // Indica si está habilitado
// Comprueba el eje del mando // Comprueba el eje del mando
bool checkAxisInput(inputs_e input, int index = 0) const; bool checkAxisInput(InputType input, int controller_index = 0) const;
// Constructor // Constructor
Input(std::string dbPath); explicit Input(const std::string &game_controller_db_path);
// Destructor // Destructor
~Input(); ~Input() = default;
public: public:
// [SINGLETON] Crearemos el objeto screen con esta función estática // [SINGLETON] Crearemos el objeto screen con esta función estática
static void init(std::string dbPath); 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 screen con esta función estática
static void destroy(); static void destroy();
@@ -115,24 +115,18 @@ public:
// [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él // [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él
static Input *get(); static Input *get();
// Actualiza el estado del objeto
void update();
// Asigna inputs a teclas // Asigna inputs a teclas
void bindKey(inputs_e input, SDL_Scancode code); void bindKey(InputType input, SDL_Scancode code);
// Asigna inputs a botones del mando // Asigna inputs a botones del mando
void bindGameControllerButton(int index, inputs_e input, SDL_GameControllerButton button); void bindGameControllerButton(int controller_index, InputType input, SDL_GameControllerButton button);
void bindGameControllerButton(int index, inputs_e inputTarget, inputs_e inputSource); void bindGameControllerButton(int controller_index, InputType inputTarget, InputType inputSource);
// Comprueba si un input esta activo // Comprueba si un input esta activo
bool checkInput(inputs_e input, bool repeat = true, int device = INPUT_USE_ANY, int index = 0); bool checkInput(InputType input, bool repeat = true, InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0);
// Comprueba si un input con modificador esta activo
bool checkModInput(inputs_e inputMod, inputs_e input, bool repeat = true, int device = INPUT_USE_ANY, int index = 0);
// Comprueba si hay almenos un input activo // Comprueba si hay almenos un input activo
bool checkAnyInput(int device = INPUT_USE_ANY, int index = 0); bool checkAnyInput(InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0);
// Comprueba si hay algún botón pulsado // Comprueba si hay algún botón pulsado
int checkAnyButtonPressed(bool repeat = INPUT_DO_NOT_ALLOW_REPEAT); int checkAnyButtonPressed(bool repeat = INPUT_DO_NOT_ALLOW_REPEAT);
@@ -147,35 +141,23 @@ public:
int getNumControllers() const; int getNumControllers() const;
// Obten el nombre de un mando de juego // Obten el nombre de un mando de juego
std::string getControllerName(int index) const; std::string getControllerName(int controller_index) const;
// Establece si ha de mostrar mensajes
void setVerbose(bool value);
// Deshabilita las entradas durante un periodo de tiempo
void disableUntil(i_disable_e value);
// Hablita las entradas
void enable();
// Obtiene el indice del controlador a partir de un event.id // Obtiene el indice del controlador a partir de un event.id
int getJoyIndex(int id) const; int getJoyIndex(int id) const;
// Muestra por consola los controles asignados // Muestra por consola los controles asignados
void printBindings(int device = INPUT_USE_KEYBOARD, int index = 0) const; void printBindings(InputDeviceToUse device = InputDeviceToUse::KEYBOARD, int controller_index = 0) const;
// Obtiene el SDL_GameControllerButton asignado a un input // Obtiene el SDL_GameControllerButton asignado a un input
SDL_GameControllerButton getControllerBinding(int index, inputs_e input) const; SDL_GameControllerButton getControllerBinding(int controller_index, InputType input) const;
// Convierte un inputs_e a std::string // Convierte un InputType a std::string
std::string to_string(inputs_e input) const; std::string to_string(InputType input) const;
// Convierte un std::string a inputs_e // Convierte un std::string a InputType
inputs_e to_inputs_e(std::string name) const; InputType to_inputs_e(const std::string &name) const;
// Obtiene el indice a partir del nombre del mando // Obtiene el indice a partir del nombre del mando
int getIndexByName(std::string name) const; int getIndexByName(const std::string &name) const;
// Activa todos los inputs. Sirve para evitar inputs sin repeticiones pero que ya vienen pulsados cuando checkInput no estaba monitorizando
void allActive(int index);
}; };

View File

@@ -1,63 +1,51 @@
#include "instructions.h" #include "instructions.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED #include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <algorithm> // for max #include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <string> // for basic_string #include <algorithm> // Para max
#include "asset.h" // for Asset #include <utility> // Para move
#include "fade.h" // for Fade, FadeType::FULLSCREEN, FadeMode::IN #include "fade.h" // Para Fade, FadeMode, FadeType
#include "global_inputs.h" // for globalInputs::check #include "global_inputs.h" // Para check
#include "input.h" // for Input #include "input.h" // Para Input
#include "jail_audio.h" // for JA_GetMusicState, JA_Music_state #include "jail_audio.h" // Para JA_GetMusicState, JA_Music_state
#include "lang.h" // for getText #include "lang.h" // Para getText
#include "param.h" // for param #include "param.h" // Para Param, param, ParamGame, ParamFade
#include "screen.h" // for Screen #include "resource.h" // Para Resource
#include "section.h" // for name, name_e, options, options_e #include "screen.h" // Para Screen
#include "sprite.h" // for Sprite #include "section.h" // Para Name, name, Options, options
#include "text.h" // for Text, TXT_CENTER, TXT_COLOR, TXT_SHADOW #include "sprite.h" // Para Sprite
#include "texture.h" // for Texture #include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR, TEXT_...
#include "tiled_bg.h" // for Tiledbg, TILED_MODE_STATIC #include "texture.h" // Para Texture
#include "utils.h" // for Param, ParamGame, Color, shdwT... #include "tiled_bg.h" // Para TiledBG, TiledBGMode
struct JA_Music_t; #include "utils.h" // Para Color, shdw_txt_color, Zone, no_color
// Constructor // Constructor
Instructions::Instructions(JA_Music_t *music) Instructions::Instructions()
: music(music) : renderer_(Screen::get()->getRenderer()),
texture_(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)),
text_(std::make_unique<Text>(Resource::get()->getTexture("smb2.gif"), Resource::get()->getTextFile("smb2.txt"))),
tiled_bg_(std::make_unique<TiledBG>((SDL_Rect){0, 0, param.game.width, param.game.height}, TiledBGMode::STATIC)),
fade_(std::make_unique<Fade>())
{ {
// Copia los punteros
renderer = Screen::get()->getRenderer();
// Crea objetos
eventHandler = std::make_unique<SDL_Event>();
text = std::make_unique<Text>(Asset::get()->get("smb2.gif"), Asset::get()->get("smb2.txt"), renderer);
tiledbg = std::make_unique<Tiledbg>(Asset::get()->get("title_bg_tile.png"), (SDL_Rect){0, 0, param.game.width, param.game.height}, TILED_MODE_STATIC);
fade = std::make_unique<Fade>(renderer);
// Crea un backbuffer para el renderizador // Crea un backbuffer para el renderizador
backbuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height); SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
SDL_SetTextureBlendMode(backbuffer, SDL_BLENDMODE_BLEND);
// Crea una textura para el texto fijo // Crea una textura para el texto fijo
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height); SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
// Inicializa variables // Inicializa variables
section::name = section::NAME_INSTRUCTIONS; section::name = section::Name::INSTRUCTIONS;
ticks = 0; view_ = {0, 0, param.game.width, param.game.height};
ticksSpeed = 15;
counter = 0;
counterEnd = 700;
view = {0, 0, param.game.width, param.game.height};
spritePos = {0, 0};
itemSpace = 2;
// 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_->setPost(param.fade.post_duration);
fade->setMode(FadeMode::IN); fade_->setMode(FadeMode::IN);
fade->activate(); fade_->activate();
// Rellena la textura de texto // Rellena la textura de texto
fillTexture(); fillTexture();
@@ -69,190 +57,182 @@ Instructions::Instructions(JA_Music_t *music)
// Destructor // Destructor
Instructions::~Instructions() Instructions::~Instructions()
{ {
itemTextures.clear(); item_textures_.clear();
sprites.clear(); sprites_.clear();
SDL_DestroyTexture(backbuffer); SDL_DestroyTexture(backbuffer_);
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture_);
} }
// Inicializa los sprites de los items // Inicializa los sprites de los items
void Instructions::iniSprites() void Instructions::iniSprites()
{ {
// Inicializa las texturas // Inicializa las texturas
auto item1 = std::make_shared<Texture>(renderer, Asset::get()->get("item_points1_disk.png")); item_textures_.emplace_back(Resource::get()->getTexture("item_points1_disk.png"));
itemTextures.push_back(item1); item_textures_.emplace_back(Resource::get()->getTexture("item_points2_gavina.png"));
item_textures_.emplace_back(Resource::get()->getTexture("item_points3_pacmar.png"));
auto item2 = std::make_shared<Texture>(renderer, Asset::get()->get("item_points2_gavina.png")); item_textures_.emplace_back(Resource::get()->getTexture("item_clock.png"));
itemTextures.push_back(item2); item_textures_.emplace_back(Resource::get()->getTexture("item_coffee.png"));
auto item3 = std::make_shared<Texture>(renderer, Asset::get()->get("item_points3_pacmar.png"));
itemTextures.push_back(item3);
auto item4 = std::make_shared<Texture>(renderer, Asset::get()->get("item_clock.png"));
itemTextures.push_back(item4);
auto item5 = std::make_shared<Texture>(renderer, Asset::get()->get("item_coffee.png"));
itemTextures.push_back(item5);
// Inicializa los sprites // Inicializa los sprites
for (int i = 0; i < (int)itemTextures.size(); ++i) for (int i = 0; i < (int)item_textures_.size(); ++i)
{ {
auto sprite = std::make_unique<Sprite>(0, 0, param.game.item_size, param.game.item_size, itemTextures[i]); auto sprite = std::make_unique<Sprite>(item_textures_[i], 0, 0, param.game.item_size, param.game.item_size);
sprite->setPos((SDL_Point){spritePos.x, spritePos.y + ((param.game.item_size + itemSpace) * i)}); sprite->setPosition((SDL_Point){sprite_pos_.x, sprite_pos_.y + ((param.game.item_size + item_space_) * i)});
sprites.push_back(std::move(sprite)); sprites_.push_back(std::move(sprite));
} }
} }
// Actualiza los sprites // Actualiza los sprites
void Instructions::updateSprites() void Instructions::updateSprites()
{ {
SDL_Rect srcRect = {0, 0, param.game.item_size, param.game.item_size}; SDL_Rect src_rect = {0, 0, param.game.item_size, param.game.item_size};
// Disquito // Disquito
srcRect.y = param.game.item_size * (((counter + 12) / 36) % 2); src_rect.y = param.game.item_size * (((counter_ + 12) / 36) % 2);
sprites[0]->setSpriteClip(srcRect); sprites_[0]->setSpriteClip(src_rect);
// Gavineixon // Gavina
srcRect.y = param.game.item_size * (((counter + 9) / 36) % 2); src_rect.y = param.game.item_size * (((counter_ + 9) / 36) % 2);
sprites[1]->setSpriteClip(srcRect); sprites_[1]->setSpriteClip(src_rect);
// Pacmar // Pacmar
srcRect.y = param.game.item_size * (((counter + 6) / 36) % 2); src_rect.y = param.game.item_size * (((counter_ + 6) / 36) % 2);
sprites[2]->setSpriteClip(srcRect); sprites_[2]->setSpriteClip(src_rect);
// Time Stopper // Time Stopper
srcRect.y = param.game.item_size * (((counter + 3) / 36) % 2); src_rect.y = param.game.item_size * (((counter_ + 3) / 36) % 2);
sprites[3]->setSpriteClip(srcRect); sprites_[3]->setSpriteClip(src_rect);
// Coffee // Coffee
srcRect.y = param.game.item_size * (((counter + 0) / 36) % 2); src_rect.y = param.game.item_size * (((counter_ + 0) / 36) % 2);
sprites[4]->setSpriteClip(srcRect); sprites_[4]->setSpriteClip(src_rect);
} }
// Rellena la textura de texto // Rellena la textura de texto
void Instructions::fillTexture() void Instructions::fillTexture()
{ {
const int despX = param.game.item_size + 8; const int desp_x = param.game.item_size + 8;
// Modifica el renderizador para pintar en la textura // Modifica el renderizador para pintar en la textura
SDL_Texture *temp = SDL_GetRenderTarget(renderer); auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer, texture); SDL_SetRenderTarget(renderer_, texture_);
// Limpia la textura // Limpia la textura
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
// Constantes // Constantes
const int numLines = 4; constexpr int num_lines = 4;
const int numItemLines = 4; constexpr int num_item_lines = 4;
const int numPostHeaders = 2; constexpr int num_post_headers = 2;
const int numPreHeaders = 1; constexpr int num_pre_headers = 1;
const int spacePostHeader = 20; constexpr int space_post_header = 20;
const int spacePreHeader = 28; constexpr int space_pre_header = 28;
const int spaceBetweenLines = text->getCharacterSize() * 1.5f; const int space_between_lines = text_->getCharacterSize() * 1.5f;
const int spaceBetweenItemLines = param.game.item_size + itemSpace; const int space_between_item_lines = param.game.item_size + item_space_;
const int spaceNewParagraph = spaceBetweenLines * 0.5f; const int space_new_paragraph = space_between_lines * 0.5f;
const int size = (numLines * spaceBetweenLines) + (numItemLines * spaceBetweenItemLines) + (numPostHeaders * spacePostHeader) + (numPreHeaders * spacePreHeader) + (spaceNewParagraph); const int size = (num_lines * space_between_lines) + (num_item_lines * space_between_item_lines) + (num_post_headers * space_post_header) + (num_pre_headers * space_pre_header) + (space_new_paragraph);
const int firstLine = (param.game.height - size) / 2; const int first_line = (param.game.height - size) / 2;
// Calcula cual es el texto más largo de las descripciones de los items // Calcula cual es el texto más largo de las descripciones de los items
int lenght = 0; int lenght = 0;
for (int i = 17; i <= 21; ++i) for (int i = 17; i <= 21; ++i)
{ {
const int l = text->lenght(lang::getText(i)); const int l = text_->lenght(lang::getText(i));
lenght = l > lenght ? l : lenght; lenght = l > lenght ? l : lenght;
} }
const int anchorItem = (param.game.width - (lenght + despX)) / 2; const int anchor_item = (param.game.width - (lenght + desp_x)) / 2;
// Escribe el texto de las instrucciones // Escribe el texto de las instrucciones
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, param.game.game_area.center_x, firstLine, lang::getText(11), 1, orange_color, 1, shdw_txt_color); text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, first_line, lang::getText(11), 1, orange_color, 1, shdw_txt_color);
const int anchor1 = firstLine + spacePostHeader; const int anchor1 = first_line + space_post_header;
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, param.game.game_area.center_x, anchor1 + spaceBetweenLines * 0, lang::getText(12), 1, no_color, 1, shdw_txt_color); text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_between_lines * 0, lang::getText(12), 1, no_color, 1, shdw_txt_color);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, param.game.game_area.center_x, anchor1 + spaceBetweenLines * 1, lang::getText(13), 1, no_color, 1, shdw_txt_color); text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_between_lines * 1, lang::getText(13), 1, no_color, 1, shdw_txt_color);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, param.game.game_area.center_x, anchor1 + spaceNewParagraph + spaceBetweenLines * 2, lang::getText(14), 1, no_color, 1, shdw_txt_color); text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_new_paragraph + space_between_lines * 2, lang::getText(14), 1, no_color, 1, shdw_txt_color);
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, param.game.game_area.center_x, anchor1 + spaceNewParagraph + spaceBetweenLines * 3, lang::getText(15), 1, no_color, 1, shdw_txt_color); text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_new_paragraph + space_between_lines * 3, lang::getText(15), 1, no_color, 1, shdw_txt_color);
// Escribe el texto de los objetos y sus puntos // Escribe el texto de los objetos y sus puntos
const int anchor2 = anchor1 + spacePreHeader + spaceNewParagraph + spaceBetweenLines * 3; const int anchor2 = anchor1 + space_pre_header + space_new_paragraph + space_between_lines * 3;
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_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 + spacePostHeader; const int anchor3 = anchor2 + space_post_header;
// const int anchor4 = anchor3 + ((param.game.item_size + text->getCharacterSize()) / 2); // const int anchor4 = anchor3 + ((param.game.item_size + text->getCharacterSize()) / 2);
text->writeShadowed(anchorItem + despX, anchor3 + spaceBetweenItemLines * 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(anchorItem + despX, anchor3 + spaceBetweenItemLines * 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(anchorItem + despX, anchor3 + spaceBetweenItemLines * 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);
text->writeShadowed(anchorItem + despX, anchor3 + spaceBetweenItemLines * 3, lang::getText(20), shdw_txt_color); text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 3, lang::getText(20), shdw_txt_color);
text->writeShadowed(anchorItem + despX, anchor3 + spaceBetweenItemLines * 4, lang::getText(21), shdw_txt_color); text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 4, lang::getText(21), shdw_txt_color);
// Deja el renderizador como estaba // Deja el renderizador como estaba
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
// Da valor a la variable // Da valor a la variable
spritePos.x = anchorItem; sprite_pos_.x = anchor_item;
spritePos.y = anchor3 - ((param.game.item_size - text->getCharacterSize()) / 2); sprite_pos_.y = anchor3 - ((param.game.item_size - text_->getCharacterSize()) / 2);
} }
// Rellena el backbuffer // Rellena el backbuffer
void Instructions::fillBackbuffer() void Instructions::fillBackbuffer()
{ {
// Modifica el renderizador para pintar en la textura // Modifica el renderizador para pintar en la textura
SDL_Texture *temp = SDL_GetRenderTarget(renderer); auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer, backbuffer); SDL_SetRenderTarget(renderer_, backbuffer_);
// Limpia la textura // Limpia la textura
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
// Coloca el texto de fondo // Coloca el texto de fondo
SDL_RenderCopy(renderer, texture, nullptr, nullptr); SDL_RenderCopy(renderer_, texture_, nullptr, nullptr);
// Dibuja los sprites // Dibuja los sprites
for (auto &sprite : sprites) for (auto &sprite : sprites_)
{ {
sprite->render(); sprite->render();
} }
// Deja el renderizador como estaba // Deja el renderizador como estaba
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
} }
// Actualiza las variables // Actualiza las variables
void Instructions::update() void Instructions::update()
{ {
// Actualiza las variables constexpr int TICKS_SPEED = 15;
if (SDL_GetTicks() - ticks > ticksSpeed)
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
{ {
// Actualiza el contador de ticks // Actualiza el contador de ticks
ticks = SDL_GetTicks(); ticks_ = SDL_GetTicks();
// Mantiene la música sonando // Mantiene la música sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
JA_PlayMusic(music); JA_PlayMusic(Resource::get()->getMusic("title.ogg"));
// Actualiza el objeto screen // Actualiza el objeto screen
Screen::get()->update(); Screen::get()->update();
// Incrementa el contador // Incrementa el contador
counter++; counter_++;
// Actualiza los sprites // Actualiza los sprites
updateSprites(); updateSprites();
// Actualiza el mosaico de fondo // Actualiza el mosaico de fondo
tiledbg->update(); tiled_bg_->update();
// Actualiza el objeto "fade" // Actualiza el objeto "fade"
fade->update(); fade_->update();
// Comprueba si el contador ha llegado al final // Comprueba si el contador ha llegado al final
if (counter == counterEnd) if (counter_ == counter_end_)
{ {
section::name = section::NAME_TITLE; section::name = section::Name::TITLE;
section::options = section::OPTIONS_TITLE_1; section::options = section::Options::TITLE_1;
} }
} }
} }
@@ -270,15 +250,15 @@ void Instructions::render()
Screen::get()->clean(bg_color); Screen::get()->clean(bg_color);
// Dibuja el mosacico de fondo // Dibuja el mosacico de fondo
tiledbg->render(); tiled_bg_->render();
// Establece la ventana del backbuffer // Establece la ventana del backbuffer
view.y = std::max(0, param.game.height - counter + 100); 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
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()->blit();
@@ -287,11 +267,11 @@ void Instructions::render()
// Recarga todas las texturas // Recarga todas las texturas
void Instructions::reloadTextures() void Instructions::reloadTextures()
{ {
for (auto &tex : itemTextures) for (auto &texture : item_textures_)
{ {
tex->reLoad(); texture->reLoad();
} }
text->reLoadTexture(); text_->reLoadTexture();
fillTexture(); fillTexture();
} }
@@ -299,19 +279,21 @@ void Instructions::reloadTextures()
void Instructions::checkEvents() void Instructions::checkEvents()
{ {
// Comprueba los eventos que hay en la cola // Comprueba los eventos que hay en la cola
while (SDL_PollEvent(eventHandler.get()) != 0) SDL_Event event;
while (SDL_PollEvent(&event))
{ {
// Evento de salida de la aplicación // Evento de salida de la aplicación
if (eventHandler->type == SDL_QUIT) if (event.type == SDL_QUIT)
{ {
section::name = section::NAME_QUIT; section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break; break;
} }
// Comprueba si se ha cambiado el tamaño de la ventana // Comprueba si se ha cambiado el tamaño de la ventana
else if (eventHandler->type == SDL_WINDOWEVENT) else if (event.type == SDL_WINDOWEVENT)
{ {
if (eventHandler->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{ {
reloadTextures(); reloadTextures();
} }
@@ -326,14 +308,11 @@ void Instructions::checkInput()
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;
return; return;
} }
// Comprueba el input para el resto de objetos
Screen::get()->checkInput();
// 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
globalInputs::check(); globalInputs::check();
} }
@@ -341,7 +320,7 @@ void Instructions::checkInput()
// Bucle para la pantalla de instrucciones // Bucle para la pantalla de instrucciones
void Instructions::run() void Instructions::run()
{ {
while (section::name == section::NAME_INSTRUCTIONS) while (section::name == section::Name::INSTRUCTIONS)
{ {
checkInput(); checkInput();
update(); update();

View File

@@ -1,17 +1,15 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event #include <SDL2/SDL_rect.h> // Para SDL_Point, SDL_Rect
#include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect #include <SDL2/SDL_render.h> // Para SDL_Texture, SDL_Renderer
#include <SDL2/SDL_render.h> // for SDL_Texture, SDL_Renderer #include <SDL2/SDL_stdinc.h> // Para Uint32
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <memory> // Para unique_ptr, shared_ptr
#include <vector> // for vector #include <vector> // Para vector
#include <memory> class Fade; // lines 8-8
#include "fade.h" class Sprite; // lines 9-9
#include "sprite.h" class Text; // lines 10-10
#include "text.h" class Texture; // lines 11-11
#include "texture.h" class TiledBG; // lines 12-12
#include "tiled_bg.h"
struct JA_Music_t;
/* /*
Esta clase gestiona un estado del programa. Se encarga de poner en pantalla Esta clase gestiona un estado del programa. Se encarga de poner en pantalla
@@ -31,26 +29,23 @@ class Instructions
{ {
private: private:
// Objetos y punteros // Objetos y punteros
std::vector<std::shared_ptr<Texture>> itemTextures; // Vector con las texturas de los items SDL_Renderer *renderer_; // El renderizador de la ventana
std::vector<std::unique_ptr<Sprite>> sprites; // Vector con los sprites de los items SDL_Texture *texture_; // Textura fija con el texto
std::unique_ptr<SDL_Event> eventHandler; // Manejador de eventos SDL_Texture *backbuffer_; // Textura para usar como backbuffer
std::unique_ptr<Text> text; // Objeto para escribir texto
std::unique_ptr<Tiledbg> tiledbg; // Objeto para dibujar el mosaico animado de fondo
std::unique_ptr<Fade> fade; // Objeto para renderizar fades
SDL_Renderer *renderer; // El renderizador de la ventana std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
JA_Music_t *music; // Musica de fondo std::vector<std::unique_ptr<Sprite>> sprites_; // Vector con los sprites de los items
SDL_Texture *texture; // Textura fija con el texto std::unique_ptr<Text> text_; // Objeto para escribir texto
SDL_Texture *backbuffer; // Textura para usar como backbuffer std::unique_ptr<TiledBG> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
// Variables // Variables
int counter; // Contador int counter_ = 0; // Contador
int counterEnd; // Valor final para el contador int counter_end_ = 700; // Valor final para el contador
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa SDL_Rect view_; // Vista del backbuffer que se va amostrar por pantalla
SDL_Rect view; // Vista del backbuffer que se va amostrar por pantalla SDL_Point sprite_pos_ = {0, 0}; // Posición del primer sprite
SDL_Point spritePos; // Posición del primer sprite int item_space_ = 2; // Espacio entre los items
int itemSpace; // Espacio entre los items
// Actualiza las variables // Actualiza las variables
void update(); void update();
@@ -81,7 +76,7 @@ private:
public: public:
// Constructor // Constructor
Instructions(JA_Music_t *music); Instructions();
// Destructor // Destructor
~Instructions(); ~Instructions();

View File

@@ -1,163 +1,152 @@
#include "intro.h" #include "intro.h"
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED #include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <string> // for basic_string #include <utility> // Para move
#include "asset.h" // for Asset #include "global_inputs.h" // Para check
#include "global_inputs.h" // for globalInputs::check #include "input.h" // Para Input
#include "input.h" // for Input #include "jail_audio.h" // Para JA_StopMusic, JA_PlayMusic
#include "jail_audio.h" // for JA_StopMusic, JA_PlayMusic #include "lang.h" // Para getText
#include "lang.h" // for getText #include "param.h" // Para Param, ParamGame, param
#include "param.h" // for param #include "resource.h" // Para Resource
#include "screen.h" // for Screen #include "screen.h" // Para Screen
#include "section.h" // for name, name_e, options, options_e #include "section.h" // Para Name, name, Options, options
#include "smart_sprite.h" // for SmartSprite #include "smart_sprite.h" // Para SmartSprite
#include "text.h" // for Text #include "text.h" // Para Text
#include "texture.h" // for Texture #include "texture.h" // Para Texture
#include "utils.h" // for ParamGame, Param, Zone, BLOCK #include "utils.h" // Para Zone, BLOCK, Color, bg_color
#include "writer.h" // for Writer #include "writer.h" // Para Writer
struct JA_Music_t;
// Constructor // Constructor
Intro::Intro(JA_Music_t *music) Intro::Intro()
: music(music) : texture_(Resource::get()->getTexture("intro.png")),
text_(std::make_shared<Text>(Resource::get()->getTexture("nokia.png"), Resource::get()->getTextFile("nokia.txt")))
{ {
// Copia los punteros
auto renderer = Screen::get()->getRenderer();
// Reserva memoria para los objetos
texture = std::make_shared<Texture>(renderer, Asset::get()->get("intro.png"));
text = std::make_shared<Text>(Asset::get()->get("nokia.png"), Asset::get()->get("nokia.txt"), renderer);
// Inicializa variables // Inicializa variables
section::name = section::NAME_INTRO; section::name = section::Name::INTRO;
section::options = section::OPTIONS_NULL; section::options = section::Options::NONE;
ticks = 0;
ticksSpeed = 15;
scene = 1;
// Inicializa los bitmaps de la intro // Inicializa los bitmaps de la intro
constexpr int totalBitmaps = 6; constexpr int totalBitmaps = 6;
for (int i = 0; i < totalBitmaps; ++i) for (int i = 0; i < totalBitmaps; ++i)
{ {
auto ss = std::make_unique<SmartSprite>(texture); auto ss = std::make_unique<SmartSprite>(texture_);
ss->setWidth(128); ss->setWidth(128);
ss->setHeight(96); ss->setHeight(96);
ss->setFinishedCounter(20); ss->setFinishedCounter(20);
ss->setDestX(param.game.game_area.center_x - 64); ss->setDestX(param.game.game_area.center_x - 64);
ss->setDestY(param.game.game_area.first_quarter_y - 24); ss->setDestY(param.game.game_area.first_quarter_y - 24);
bitmaps.push_back(std::move(ss)); bitmaps_.push_back(std::move(ss));
} }
bitmaps[0]->setPosX(-128); bitmaps_[0]->setPosX(-128);
bitmaps[0]->setPosY(param.game.game_area.first_quarter_y - 24); bitmaps_[0]->setPosY(param.game.game_area.first_quarter_y - 24);
bitmaps[0]->setVelX(0.0f); bitmaps_[0]->setVelX(0.0f);
bitmaps[0]->setVelY(0.0f); bitmaps_[0]->setVelY(0.0f);
bitmaps[0]->setAccelX(0.6f); bitmaps_[0]->setAccelX(0.6f);
bitmaps[0]->setAccelY(0.0f); bitmaps_[0]->setAccelY(0.0f);
bitmaps[0]->setSpriteClip(0, 0, 128, 96); bitmaps_[0]->setSpriteClip(0, 0, 128, 96);
bitmaps[1]->setPosX(param.game.width); bitmaps_[1]->setPosX(param.game.width);
bitmaps[1]->setPosY(param.game.game_area.first_quarter_y - 24); bitmaps_[1]->setPosY(param.game.game_area.first_quarter_y - 24);
bitmaps[1]->setVelX(-1.0f); bitmaps_[1]->setVelX(-1.0f);
bitmaps[1]->setVelY(0.0f); bitmaps_[1]->setVelY(0.0f);
bitmaps[1]->setAccelX(-0.3f); bitmaps_[1]->setAccelX(-0.3f);
bitmaps[1]->setAccelY(0.0f); bitmaps_[1]->setAccelY(0.0f);
bitmaps[1]->setSpriteClip(128, 0, 128, 96); bitmaps_[1]->setSpriteClip(128, 0, 128, 96);
bitmaps[2]->setPosX(param.game.game_area.center_x - 64); bitmaps_[2]->setPosX(param.game.game_area.center_x - 64);
bitmaps[2]->setPosY(-96); bitmaps_[2]->setPosY(-96);
bitmaps[2]->setVelX(0.0f); bitmaps_[2]->setVelX(0.0f);
bitmaps[2]->setVelY(3.0f); bitmaps_[2]->setVelY(3.0f);
bitmaps[2]->setAccelX(0.1f); bitmaps_[2]->setAccelX(0.1f);
bitmaps[2]->setAccelY(0.3f); bitmaps_[2]->setAccelY(0.3f);
bitmaps[2]->setSpriteClip(0, 96, 128, 96); bitmaps_[2]->setSpriteClip(0, 96, 128, 96);
bitmaps[2]->setFinishedCounter(250); bitmaps_[2]->setFinishedCounter(250);
bitmaps[3]->setPosX(param.game.game_area.center_x - 64); bitmaps_[3]->setPosX(param.game.game_area.center_x - 64);
bitmaps[3]->setPosY(param.game.height); bitmaps_[3]->setPosY(param.game.height);
bitmaps[3]->setVelX(0.0f); bitmaps_[3]->setVelX(0.0f);
bitmaps[3]->setVelY(-0.7f); bitmaps_[3]->setVelY(-0.7f);
bitmaps[3]->setAccelX(0.0f); bitmaps_[3]->setAccelX(0.0f);
bitmaps[3]->setAccelY(0.0f); bitmaps_[3]->setAccelY(0.0f);
bitmaps[3]->setSpriteClip(128, 96, 128, 96); bitmaps_[3]->setSpriteClip(128, 96, 128, 96);
bitmaps[4]->setPosX(param.game.game_area.center_x - 64); bitmaps_[4]->setPosX(param.game.game_area.center_x - 64);
bitmaps[4]->setPosY(-96); bitmaps_[4]->setPosY(-96);
bitmaps[4]->setVelX(0.0f); bitmaps_[4]->setVelX(0.0f);
bitmaps[4]->setVelY(3.0f); bitmaps_[4]->setVelY(3.0f);
bitmaps[4]->setAccelX(0.1f); bitmaps_[4]->setAccelX(0.1f);
bitmaps[4]->setAccelY(0.3f); bitmaps_[4]->setAccelY(0.3f);
bitmaps[4]->setSpriteClip(0, 192, 128, 96); bitmaps_[4]->setSpriteClip(0, 192, 128, 96);
bitmaps[5]->setPosX(param.game.width); bitmaps_[5]->setPosX(param.game.width);
bitmaps[5]->setPosY(param.game.game_area.first_quarter_y - 24); bitmaps_[5]->setPosY(param.game.game_area.first_quarter_y - 24);
bitmaps[5]->setVelX(-0.7f); bitmaps_[5]->setVelX(-0.7f);
bitmaps[5]->setVelY(0.0f); bitmaps_[5]->setVelY(0.0f);
bitmaps[5]->setAccelX(0.0f); bitmaps_[5]->setAccelX(0.0f);
bitmaps[5]->setAccelY(0.0f); bitmaps_[5]->setAccelY(0.0f);
bitmaps[5]->setSpriteClip(128, 192, 128, 96); 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 totalTexts = 9;
for (int i = 0; i < totalTexts; ++i) for (int i = 0; i < totalTexts; ++i)
{ {
auto w = std::make_unique<Writer>(text); auto w = std::make_unique<Writer>(text_);
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(-1);
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_[0]->setCaption(lang::getText(27));
texts[0]->setSpeed(8); texts_[0]->setSpeed(8);
// Tot esta tranquil a la UPV // Tot esta tranquil a la UPV
texts[1]->setCaption(lang::getText(28)); texts_[1]->setCaption(lang::getText(28));
texts[1]->setSpeed(8); texts_[1]->setSpeed(8);
// Fins que un desaprensiu... // Fins que un desaprensiu...
texts[2]->setCaption(lang::getText(29)); texts_[2]->setCaption(lang::getText(29));
texts[2]->setSpeed(12); texts_[2]->setSpeed(12);
// HEY! ME ANE A FERME UN CORTAET... // HEY! ME ANE A FERME UN CORTAET...
texts[3]->setCaption(lang::getText(30)); texts_[3]->setCaption(lang::getText(30));
texts[3]->setSpeed(8); texts_[3]->setSpeed(8);
// UAAAAAAAAAAAAA!!! // UAAAAAAAAAAAAA!!!
texts[4]->setCaption(lang::getText(31)); texts_[4]->setCaption(lang::getText(31));
texts[4]->setSpeed(1); texts_[4]->setSpeed(1);
// Espera un moment... // Espera un moment...
texts[5]->setCaption(lang::getText(32)); texts_[5]->setCaption(lang::getText(32));
texts[5]->setSpeed(16); texts_[5]->setSpeed(16);
// Si resulta que no tinc solt! // Si resulta que no tinc solt!
texts[6]->setCaption(lang::getText(33)); texts_[6]->setCaption(lang::getText(33));
texts[6]->setSpeed(2); texts_[6]->setSpeed(2);
// MERDA DE MAQUINA! // MERDA DE MAQUINA!
texts[7]->setCaption(lang::getText(34)); texts_[7]->setCaption(lang::getText(34));
texts[7]->setSpeed(3); texts_[7]->setSpeed(3);
// Blop... blop... blop... // Blop... blop... blop...
texts[8]->setCaption(lang::getText(35)); texts_[8]->setCaption(lang::getText(35));
texts[8]->setSpeed(16); texts_[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 // Recarga todas las texturas
void Intro::reloadTextures() void Intro::reloadTextures()
{ {
texture->reLoad(); texture_->reLoad();
text->reLoadTexture(); text_->reLoadTexture();
} }
// Comprueba los eventos // Comprueba los eventos
@@ -172,16 +161,15 @@ void Intro::checkEvents()
{ {
case SDL_QUIT: case SDL_QUIT:
{ {
section::name = section::NAME_QUIT; section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break; break;
} }
case SDL_WINDOWEVENT: case SDL_WINDOWEVENT:
{ {
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
reloadTextures(); reloadTextures();
}
break; break;
} }
@@ -198,14 +186,11 @@ void Intro::checkInput()
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;
return; return;
} }
// Comprueba el input para el resto de objetos
Screen::get()->checkInput();
// 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
globalInputs::check(); globalInputs::check();
} }
@@ -213,153 +198,158 @@ void Intro::checkInput()
// Actualiza las escenas de la intro // Actualiza las escenas de la intro
void Intro::updateScenes() void Intro::updateScenes()
{ {
switch (scene) switch (scene_)
{ {
case 1: case 1:
// Primera imagen - UPV { // Primera imagen - UPV
if (!bitmaps[0]->hasFinished()) if (!bitmaps_[0]->hasFinished())
{ {
bitmaps[0]->setEnabled(true); bitmaps_[0]->setEnabled(true);
} }
// Primer texto de la primera imagen // Primer texto de la primera imagen
if (bitmaps[0]->hasFinished() && !texts[0]->hasFinished()) if (bitmaps_[0]->hasFinished() && !texts_[0]->hasFinished())
{ {
texts[0]->setEnabled(true); texts_[0]->setEnabled(true);
} }
// Segundo texto de la primera imagen // Segundo texto de la primera imagen
if (texts[0]->hasFinished() && !texts[1]->hasFinished()) if (texts_[0]->hasFinished() && !texts_[1]->hasFinished())
{ {
texts[0]->setEnabled(false); texts_[0]->setEnabled(false);
texts[1]->setEnabled(true); texts_[1]->setEnabled(true);
} }
// Tercer texto de la primera imagen // Tercer texto de la primera imagen
if (texts[1]->hasFinished() && !texts[2]->hasFinished()) if (texts_[1]->hasFinished() && !texts_[2]->hasFinished())
{ {
texts[1]->setEnabled(false); texts_[1]->setEnabled(false);
texts[2]->setEnabled(true); texts_[2]->setEnabled(true);
} }
// Fin de la primera escena // Fin de la primera escena
if (texts[2]->hasFinished()) if (texts_[2]->hasFinished())
{ {
bitmaps[0]->setEnabled(false); bitmaps_[0]->setEnabled(false);
texts[2]->setEnabled(false); texts_[2]->setEnabled(false);
scene++; scene_++;
} }
break; break;
}
case 2: case 2:
// Segunda imagen - Máquina { // Segunda imagen - Máquina
if (!bitmaps[1]->hasFinished()) if (!bitmaps_[1]->hasFinished())
{ {
bitmaps[1]->setEnabled(true); bitmaps_[1]->setEnabled(true);
} }
// Primer texto de la segunda imagen // Primer texto de la segunda imagen
if (bitmaps[1]->hasFinished() && !texts[3]->hasFinished()) if (bitmaps_[1]->hasFinished() && !texts_[3]->hasFinished())
{ {
texts[3]->setEnabled(true); texts_[3]->setEnabled(true);
} }
// Fin de la segunda escena // Fin de la segunda escena
if (texts[3]->hasFinished()) if (texts_[3]->hasFinished())
{ {
bitmaps[1]->setEnabled(false); bitmaps_[1]->setEnabled(false);
texts[3]->setEnabled(false); texts_[3]->setEnabled(false);
scene++; scene_++;
} }
break; break;
}
case 3: case 3:
// Tercera imagen junto con primer texto - GRITO { // Tercera imagen junto con primer texto - GRITO
if (!bitmaps[2]->hasFinished() && !texts[4]->hasFinished()) if (!bitmaps_[2]->hasFinished() && !texts_[4]->hasFinished())
{ {
bitmaps[2]->setEnabled(true); bitmaps_[2]->setEnabled(true);
texts[4]->setEnabled(true); texts_[4]->setEnabled(true);
} }
// Fin de la tercera escena // Fin de la tercera escena
if (bitmaps[2]->hasFinished() && texts[4]->hasFinished()) if (bitmaps_[2]->hasFinished() && texts_[4]->hasFinished())
{ {
bitmaps[2]->setEnabled(false); bitmaps_[2]->setEnabled(false);
texts[4]->setEnabled(false); texts_[4]->setEnabled(false);
scene++; scene_++;
} }
break; break;
}
case 4: case 4:
// Cuarta imagen junto con primer texto - Reflexión { // Cuarta imagen junto con primer texto - Reflexión
if (!bitmaps[3]->hasFinished() && !texts[5]->hasFinished()) if (!bitmaps_[3]->hasFinished() && !texts_[5]->hasFinished())
{ {
bitmaps[3]->setEnabled(true); bitmaps_[3]->setEnabled(true);
texts[5]->setEnabled(true); texts_[5]->setEnabled(true);
} }
// Segundo texto de la cuarta imagen // Segundo texto de la cuarta imagen
if (texts[5]->hasFinished() && !texts[6]->hasFinished()) if (texts_[5]->hasFinished() && !texts_[6]->hasFinished())
{ {
texts[5]->setEnabled(false); texts_[5]->setEnabled(false);
texts[6]->setEnabled(true); texts_[6]->setEnabled(true);
} }
// Fin de la cuarta escena // Fin de la cuarta escena
if (bitmaps[3]->hasFinished() && texts[6]->hasFinished()) if (bitmaps_[3]->hasFinished() && texts_[6]->hasFinished())
{ {
bitmaps[3]->setEnabled(false); bitmaps_[3]->setEnabled(false);
texts[6]->setEnabled(false); texts_[6]->setEnabled(false);
scene++; scene_++;
} }
break; break;
}
case 5: case 5:
// Quinta imagen - Patada { // Quinta imagen - Patada
if (!bitmaps[4]->hasFinished()) if (!bitmaps_[4]->hasFinished())
{ {
bitmaps[4]->setEnabled(true); bitmaps_[4]->setEnabled(true);
} }
// Primer texto de la quinta imagen // Primer texto de la quinta imagen
if (bitmaps[4]->hasFinished() && !texts[7]->hasFinished()) if (bitmaps_[4]->hasFinished() && !texts_[7]->hasFinished())
{ {
texts[7]->setEnabled(true); texts_[7]->setEnabled(true);
} }
// Fin de la quinta escena // Fin de la quinta escena
if (bitmaps[4]->hasFinished() && texts[7]->hasFinished()) if (bitmaps_[4]->hasFinished() && texts_[7]->hasFinished())
{ {
bitmaps[4]->setEnabled(false); bitmaps_[4]->setEnabled(false);
texts[7]->setEnabled(false); texts_[7]->setEnabled(false);
scene++; scene_++;
} }
break; break;
}
case 6: case 6:
// Sexta imagen junto con texto - Globos de café { // Sexta imagen junto con texto - Globos de café
if (!bitmaps[5]->hasFinished() && !texts[8]->hasFinished()) if (!bitmaps_[5]->hasFinished() && !texts_[8]->hasFinished())
{ {
bitmaps[5]->setEnabled(true); bitmaps_[5]->setEnabled(true);
texts[8]->setEnabled(true); texts_[8]->setEnabled(true);
} }
// Acaba el último texto // Acaba el último texto
if (bitmaps[5]->hasFinished() && texts[8]->hasFinished()) if (bitmaps_[5]->hasFinished() && texts_[8]->hasFinished())
{ {
bitmaps[5]->setEnabled(false); bitmaps_[5]->setEnabled(false);
texts[8]->setEnabled(false); texts_[8]->setEnabled(false);
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;
} }
break; break;
}
default: default:
break; break;
@@ -369,21 +359,23 @@ void Intro::updateScenes()
// Actualiza las variables del objeto // Actualiza las variables del objeto
void Intro::update() void Intro::update()
{ {
if (SDL_GetTicks() - ticks > ticksSpeed) constexpr int TICKS_SPEED = 15;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
{ {
// Actualiza el contador de ticks // Actualiza el contador de ticks
ticks = SDL_GetTicks(); ticks_ = SDL_GetTicks();
// Actualiza el objeto screen // Actualiza el objeto screen
Screen::get()->update(); Screen::get()->update();
// Actualiza los objetos // Actualiza los objetos
for (auto &bitmap : bitmaps) for (auto &bitmap : bitmaps_)
{ {
bitmap->update(); bitmap->update();
} }
for (auto &text : texts) for (auto &text : texts_)
{ {
text->update(); text->update();
} }
@@ -403,12 +395,12 @@ void Intro::render()
Screen::get()->clean(bg_color); Screen::get()->clean(bg_color);
// Dibuja los objetos // Dibuja los objetos
for (auto &bitmap : bitmaps) for (const auto &bitmap : bitmaps_)
{ {
bitmap->render(); bitmap->render();
} }
for (auto &text : texts) for (const auto &text : texts_)
{ {
text->render(); text->render();
} }
@@ -420,9 +412,9 @@ void Intro::render()
// Bucle principal // Bucle principal
void Intro::run() void Intro::run()
{ {
JA_PlayMusic(music, 0); JA_PlayMusic(Resource::get()->getMusic("intro.ogg"), 0);
while (section::name == section::NAME_INTRO) while (section::name == section::Name::INTRO)
{ {
checkInput(); checkInput();
update(); update();

View File

@@ -1,14 +1,12 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event #include <SDL2/SDL_stdinc.h> // Para Uint32
#include <SDL2/SDL_stdinc.h> // for Uint32, Uint8 #include <memory> // Para unique_ptr, shared_ptr
#include <vector> // for vector #include <vector> // Para vector
#include <memory> #include "smart_sprite.h" // Para SmartSprite
#include "smart_sprite.h" #include "writer.h" // Para Writer
#include "texture.h" class Text; // lines 8-8
#include "text.h" class Texture; // lines 9-9
#include "writer.h"
struct JA_Music_t;
/* /*
Esta clase gestiona un estado del programa. Se encarga de mostrar la secuencia Esta clase gestiona un estado del programa. Se encarga de mostrar la secuencia
@@ -20,17 +18,15 @@ class Intro
{ {
private: private:
// Objetos // Objetos
std::shared_ptr<Texture> texture; // Textura con los graficos std::shared_ptr<Texture> texture_; // Textura con los graficos
std::shared_ptr<Text> text; // Textos de la intro 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
// Variables // Variables
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
Uint8 ticksSpeed; // Velocidad a la que se repiten los bucles del programa int scene_ = 1; // Indica que escena está activa
JA_Music_t *music; // Musica para la intro
int scene; // Indica que escena está activa
// Actualiza las variables del objeto // Actualiza las variables del objeto
void update(); void update();
@@ -52,7 +48,7 @@ private:
public: public:
// Constructor // Constructor
Intro(JA_Music_t *music); Intro();
// Destructor // Destructor
~Intro() = default; ~Intro() = default;

View File

@@ -1,65 +1,65 @@
#include "item.h" #include "item.h"
#include <stdlib.h> // for rand #include <stdlib.h> // para rand
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // para SpriteAnimated
#include "param.h" // for param #include "param.h" // para param
class Texture; class Texture;
// Constructor // Constructor
Item::Item(int kind, float x, float y, SDL_Rect *playArea, std::shared_ptr<Texture> texture, std::vector<std::string> *animation) Item::Item(ItemType type, float x, float y, SDL_Rect &play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
: kind(kind), playArea(playArea) : sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
type_(type),
play_area_(play_area)
{ {
sprite = std::make_unique<AnimatedSprite>(texture, "", animation); switch (type)
enabled = true;
timeToLive = 600;
accelX = 0.0f;
floorCollision = false;
if (kind == ITEM_COFFEE_MACHINE)
{ {
width = 28; case ItemType::COFFEE_MACHINE:
height = 37; {
posX = (((int)x + (playArea->w / 2)) % (playArea->w - width - 5)) + 2; width_ = 28;
posY = -height; height_ = 37;
velX = 0.0f; pos_x_ = ((static_cast<int>(x) + (play_area.w / 2)) % (play_area.w - width_ - 5)) + 2;
velY = -0.1f; pos_y_ = -height_;
accelY = 0.1f; vel_x_ = 0.0f;
collider.r = 10; vel_y_ = -0.1f;
accel_y_ = 0.1f;
collider_.r = 10;
break;
} }
else default:
{ {
width = 20; width_ = 20;
height = 20; height_ = 20;
posX = x; pos_x_ = x;
posY = y; pos_y_ = y;
velX = -1.0f + ((rand() % 5) * 0.5f); vel_x_ = -1.0f + ((rand() % 5) * 0.5f);
velY = -4.0f; vel_y_ = -4.0f;
accelY = 0.2f; accel_y_ = 0.2f;
collider.r = width / 2; collider_.r = width_ / 2;
break;
}
} }
sprite->setPosX(posX); sprite_->setPosX(pos_x_);
sprite->setPosY(posY); sprite_->setPosY(pos_y_);
shiftColliders(); shiftColliders();
} }
// Centra el objeto en la posición X // Centra el objeto en la posición X
void Item::allignTo(int x) void Item::alignTo(int x)
{ {
posX = float(x - (width / 2)); pos_x_ = static_cast<float>(x - (width_ / 2));
if (posX < param.game.play_area.rect.x) if (pos_x_ < param.game.play_area.rect.x)
{ {
posX = param.game.play_area.rect.x + 1; pos_x_ = param.game.play_area.rect.x + 1;
} }
else if ((posX + width) > playArea->w) else if (pos_x_ + width_ > play_area_.w)
{ {
posX = float(playArea->w - width - 1); pos_x_ = static_cast<float>(play_area_.w - width_ - 1);
} }
// Posición X,Y del sprite // Posición X,Y del sprite
sprite->setPosX(int(posX)); sprite_->setPosX(pos_x_);
sprite->setPosY(int(posY)); sprite_->setPosY(pos_y_);
// Alinea el circulo de colisión con el objeto // Alinea el circulo de colisión con el objeto
shiftColliders(); shiftColliders();
@@ -68,15 +68,15 @@ void Item::allignTo(int x)
// Pinta el objeto en la pantalla // Pinta el objeto en la pantalla
void Item::render() void Item::render()
{ {
if (enabled) if (enabled_)
{ {
if (timeToLive > 200) if (time_to_live_ > 200)
{ {
sprite->render(); sprite_->render();
} }
else if (timeToLive % 20 > 10) else if (time_to_live_ % 20 > 10)
{ {
sprite->render(); sprite_->render();
} }
} }
} }
@@ -84,68 +84,68 @@ void Item::render()
// Actualiza la posición y estados del objeto // Actualiza la posición y estados del objeto
void Item::move() void Item::move()
{ {
floorCollision = false; floor_collision_ = false;
// Calcula la nueva posición // Calcula la nueva posición
posX += velX; pos_x_ += vel_x_;
posY += velY; pos_y_ += vel_y_;
// Aplica las aceleraciones a la velocidad // Aplica las aceleraciones a la velocidad
velX += accelX; vel_x_ += accel_x_;
velY += accelY; vel_y_ += accel_y_;
// Si queda fuera de pantalla, corregimos su posición y cambiamos su sentido // Si queda fuera de pantalla, corregimos su posición y cambiamos su sentido
if ((posX < param.game.play_area.rect.x) || (posX + width > playArea->w)) if ((pos_x_ < param.game.play_area.rect.x) || (pos_x_ + width_ > play_area_.w))
{ {
// Corregir posición // Corregir posición
posX -= velX; pos_x_ -= vel_x_;
// Invertir sentido // Invertir sentido
velX = -velX; vel_x_ = -vel_x_;
} }
// Si se sale por arriba rebota (excepto la maquina de café) // Si se sale por arriba rebota (excepto la maquina de café)
if ((posY < param.game.play_area.rect.y) && !(kind == ITEM_COFFEE_MACHINE)) if ((pos_y_ < param.game.play_area.rect.y) && !(type_ == ItemType::COFFEE_MACHINE))
{ {
// Corrige // Corrige
posY = param.game.play_area.rect.y; pos_y_ = param.game.play_area.rect.y;
// Invierte el sentido // Invierte el sentido
velY = -velY; vel_y_ = -vel_y_;
} }
// Si el objeto se sale por la parte inferior // Si el objeto se sale por la parte inferior
if (posY + height > playArea->h) if (pos_y_ + height_ > play_area_.h)
{ {
// Detiene el objeto // Detiene el objeto
velY = 0; vel_y_ = 0;
velX = 0; vel_x_ = 0;
accelX = 0; accel_x_ = 0;
accelY = 0; accel_y_ = 0;
posY = playArea->h - height; pos_y_ = play_area_.h - height_;
if (kind == ITEM_COFFEE_MACHINE) if (type_ == ItemType::COFFEE_MACHINE)
{ {
floorCollision = true; floor_collision_ = true;
} }
} }
// Actualiza la posición del sprite // Actualiza la posición del sprite
sprite->setPosX(int(posX)); sprite_->setPosX(int(pos_x_));
sprite->setPosY(int(posY)); sprite_->setPosY(int(pos_y_));
shiftColliders(); shiftColliders();
} }
// Pone a cero todos los valores del objeto // Pone a cero todos los valores del objeto
void Item::disable() void Item::disable()
{ {
enabled = false; enabled_ = false;
} }
// Actualiza el objeto a su posicion, animación y controla los contadores // Actualiza el objeto a su posicion, animación y controla los contadores
void Item::update() void Item::update()
{ {
move(); move();
sprite->animate(); sprite_->update();
updateTimeToLive(); updateTimeToLive();
checkTimeToLive(); checkTimeToLive();
} }
@@ -153,70 +153,70 @@ void Item::update()
// Actualiza el contador // Actualiza el contador
void Item::updateTimeToLive() void Item::updateTimeToLive()
{ {
if (timeToLive > 0) if (time_to_live_ > 0)
{ {
timeToLive--; time_to_live_--;
} }
} }
// Comprueba si el objeto sigue vivo // Comprueba si el objeto sigue vivo
void Item::checkTimeToLive() void Item::checkTimeToLive()
{ {
if (timeToLive == 0) if (time_to_live_ == 0)
disable(); disable();
} }
// Obtiene del valor de la variable // Obtiene del valor de la variable
float Item::getPosX() float Item::getPosX()
{ {
return posX; return pos_x_;
} }
// Obtiene del valor de la variable // Obtiene del valor de la variable
float Item::getPosY() float Item::getPosY()
{ {
return posY; return pos_y_;
} }
// Obtiene del valor de la variable // Obtiene del valor de la variable
int Item::getWidth() int Item::getWidth()
{ {
return width; return width_;
} }
// Obtiene del valor de la variable // Obtiene del valor de la variable
int Item::getHeight() int Item::getHeight()
{ {
return height; return height_;
} }
// Obtiene del valor de la variable // Obtiene del valor de la variable
int Item::getClass() ItemType Item::getType()
{ {
return kind; return type_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool Item::isEnabled() bool Item::isEnabled()
{ {
return enabled; return enabled_;
} }
// Obtiene el circulo de colisión // Obtiene el circulo de colisión
Circle &Item::getCollider() Circle &Item::getCollider()
{ {
return collider; return collider_;
} }
// Alinea el circulo de colisión con la posición del objeto // Alinea el circulo de colisión con la posición del objeto
void Item::shiftColliders() void Item::shiftColliders()
{ {
collider.x = int(posX + (width / 2)); collider_.x = int(pos_x_ + (width_ / 2));
collider.y = int(posY + (height / 2)); collider_.y = int(pos_y_ + (height_ / 2));
} }
// Informa si el objeto ha colisionado con el suelo // Informa si el objeto ha colisionado con el suelo
bool Item::isOnFloor() bool Item::isOnFloor()
{ {
return floorCollision; return floor_collision_;
} }

View File

@@ -1,44 +1,48 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint16 #include <SDL2/SDL_stdinc.h> // para Uint16
#include <string> // for string #include <memory> // para shared_ptr, unique_ptr
#include <vector> // for vector #include <string> // para string
#include <memory> #include <vector> // para vector
#include "utils.h" // for Circle #include "animated_sprite.h" // para SpriteAnimated
#include "animated_sprite.h" #include "utils.h" // para Circle
#include "texture.h" class Texture;
// Tipos de objetos // Tipos de objetos
#define ITEM_POINTS_1_DISK 1 enum class ItemType : int
#define ITEM_POINTS_2_GAVINA 2 {
#define ITEM_POINTS_3_PACMAR 3 DISK = 1,
#define ITEM_CLOCK 4 GAVINA = 2,
#define ITEM_COFFEE 5 PACMAR = 3,
#define ITEM_COFFEE_MACHINE 6 CLOCK = 4,
#define ITEM_NULL 7 COFFEE = 5,
COFFEE_MACHINE = 6,
NONE = 7,
};
// Clase Item // Clase Item
class Item class Item
{ {
private: private:
// Objetos y punteros // Objetos y punteros
std::unique_ptr<AnimatedSprite> sprite; // Sprite con los graficos del objeto std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los graficos del objeto
// Variables // Variables
float posX; // Posición X del objeto float pos_x_; // Posición X del objeto
float posY; // Posición Y del objeto float pos_y_; // Posición Y del objeto
int width; // Ancho del objeto int width_; // Ancho del objeto
int height; // Alto del objeto int height_; // Alto del objeto
float velX; // Velocidad en el eje X float vel_x_; // Velocidad en el eje X
float velY; // Velocidad en el eje Y float vel_y_; // Velocidad en el eje Y
float accelX; // Aceleración en el eje X float accel_x_ = 0.0f; // Aceleración en el eje X
float accelY; // Aceleración en el eje Y float accel_y_; // Aceleración en el eje Y
bool floorCollision; // Indica si el objeto colisiona con el suelo bool floor_collision_ = false; // Indica si el objeto colisiona con el suelo
int kind; // Especifica el tipo de objeto que es ItemType type_; // Especifica el tipo de objeto que es
bool enabled; // Especifica si el objeto está habilitado bool enabled_ = true; // Especifica si el objeto está habilitado
Circle collider; // Circulo de colisión del objeto Circle collider_; // Circulo de colisión del objeto
SDL_Rect *playArea; // Rectangulo con la zona de juego SDL_Rect play_area_; // Rectangulo con la zona de juego
Uint16 time_to_live_ = 600; // Temporizador con el tiempo que el objeto está presente
// Alinea el circulo de colisión con la posición del objeto // Alinea el circulo de colisión con la posición del objeto
void shiftColliders(); void shiftColliders();
@@ -46,17 +50,21 @@ private:
// Actualiza la posición y estados del objeto // Actualiza la posición y estados del objeto
void move(); void move();
public: // Actualiza el contador
Uint16 timeToLive; // Temporizador con el tiempo que el objeto está presente void updateTimeToLive();
// Comprueba si el objeto sigue vivo
void checkTimeToLive();
public:
// Constructor // Constructor
Item(int kind, float x, float y, SDL_Rect *playArea, std::shared_ptr<Texture> texture, std::vector<std::string> *animation); Item(ItemType type, float x, float y, SDL_Rect &play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation);
// Destructor // Destructor
~Item() = default; ~Item() = default;
// Centra el objeto en la posición X // Centra el objeto en la posición X
void allignTo(int x); void alignTo(int x);
// Pinta el objeto en la pantalla // Pinta el objeto en la pantalla
void render(); void render();
@@ -67,12 +75,6 @@ public:
// Actualiza al objeto a su posicion, animación y controla los contadores // Actualiza al objeto a su posicion, animación y controla los contadores
void update(); void update();
// Actualiza el contador
void updateTimeToLive();
// Comprueba si el objeto sigue vivo
void checkTimeToLive();
// Obtiene del valor de la variable // Obtiene del valor de la variable
float getPosX(); float getPosX();
@@ -86,7 +88,7 @@ public:
int getHeight(); int getHeight();
// Obtiene del valor de la variable // Obtiene del valor de la variable
int getClass(); ItemType getType();
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool isEnabled(); bool isEnabled();

View File

@@ -1,74 +1,91 @@
#ifndef JA_USESDLMIXER #ifndef JA_USESDLMIXER
#include "jail_audio.h" #include "jail_audio.h"
#include <stdint.h> // for uint8_t #include <stdint.h> // para uint8_t
#include <stdio.h> // for NULL, fseek, fclose, fopen, fread, ftell, FILE #include <stdio.h> // para NULL, fseek, fclose, fopen, fread, ftell, FILE
#include <stdlib.h> // for free, malloc #include <stdlib.h> // para free, malloc
#include "stb_vorbis.c" // for stb_vorbis_decode_memory #include "stb_vorbis.c" // para stb_vorbis_decode_memory
#define JA_MAX_SIMULTANEOUS_CHANNELS 5 #define JA_MAX_SIMULTANEOUS_CHANNELS 5
struct JA_Sound_t { struct JA_Sound_t
Uint32 length {0}; {
Uint8* buffer {NULL}; Uint32 length{0};
Uint8 *buffer{NULL};
}; };
struct JA_Channel_t { struct JA_Channel_t
JA_Sound_t *sound; {
int pos {0}; JA_Sound_t *sound;
int times {0}; int pos{0};
JA_Channel_state state { JA_CHANNEL_FREE }; int times{0};
JA_Channel_state state{JA_CHANNEL_FREE};
}; };
struct JA_Music_t { struct JA_Music_t
int samples {0}; {
int pos {0}; int samples{0};
int times {0}; int pos{0};
short* output {NULL}; int times{0};
JA_Music_state state {JA_MUSIC_INVALID}; short *output{NULL};
JA_Music_state state{JA_MUSIC_INVALID};
}; };
JA_Music_t *current_music{NULL}; JA_Music_t *current_music{NULL};
JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS]; JA_Channel_t channels[JA_MAX_SIMULTANEOUS_CHANNELS];
int JA_freq {48000}; int JA_freq{48000};
SDL_AudioFormat JA_format {AUDIO_S16}; SDL_AudioFormat JA_format{AUDIO_S16};
Uint8 JA_channels {2}; Uint8 JA_channels{2};
int JA_musicVolume = 128; int JA_musicVolume = 128;
int JA_soundVolume = 64; int JA_soundVolume = 64;
bool JA_musicEnabled = true; bool JA_musicEnabled = true;
bool JA_soundEnabled = true; bool JA_soundEnabled = true;
SDL_AudioDeviceID sdlAudioDevice = 0; SDL_AudioDeviceID sdlAudioDevice = 0;
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); {
SDL_MixAudioFormat(stream, (Uint8*)(current_music->output+current_music->pos), AUDIO_S16, size, JA_musicVolume); const int size = SDL_min(len, current_music->samples * 2 - current_music->pos);
current_music->pos += size/2; SDL_MixAudioFormat(stream, (Uint8 *)(current_music->output + current_music->pos), AUDIO_S16, size, JA_musicVolume);
if (size < len) { current_music->pos += size / 2;
if (current_music->times != 0) { if (size < len)
SDL_MixAudioFormat(stream+size, (Uint8*)current_music->output, AUDIO_S16, len-size, JA_musicVolume); {
current_music->pos = (len-size)/2; if (current_music->times != 0)
if (current_music->times > 0) current_music->times--; {
} else { SDL_MixAudioFormat(stream + size, (Uint8 *)current_music->output, AUDIO_S16, len - size, JA_musicVolume);
current_music->pos = (len - size) / 2;
if (current_music->times > 0)
current_music->times--;
}
else
{
current_music->pos = 0; current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED; current_music->state = JA_MUSIC_STOPPED;
} }
} }
} }
// Mixar els channels mi amol // Mixar els channels mi amol
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
if (channels[i].state == JA_CHANNEL_PLAYING) { {
if (channels[i].state == JA_CHANNEL_PLAYING)
{
const int size = SDL_min(len, channels[i].sound->length - channels[i].pos); const int size = SDL_min(len, channels[i].sound->length - channels[i].pos);
SDL_MixAudioFormat(stream, channels[i].sound->buffer + channels[i].pos, AUDIO_S16, size, JA_soundVolume); SDL_MixAudioFormat(stream, channels[i].sound->buffer + channels[i].pos, AUDIO_S16, size, JA_soundVolume);
channels[i].pos += size; channels[i].pos += size;
if (size < len) { if (size < len)
if (channels[i].times != 0) { {
SDL_MixAudioFormat(stream + size, channels[i].sound->buffer, AUDIO_S16, len-size, JA_soundVolume); if (channels[i].times != 0)
channels[i].pos = len-size; {
if (channels[i].times > 0) channels[i].times--; SDL_MixAudioFormat(stream + size, channels[i].sound->buffer, AUDIO_S16, len - size, JA_soundVolume);
} else { channels[i].pos = len - size;
if (channels[i].times > 0)
channels[i].times--;
}
else
{
JA_StopChannel(i); JA_StopChannel(i);
} }
} }
@@ -76,23 +93,28 @@ void audioCallback(void * userdata, uint8_t * stream, int len) {
} }
} }
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) { void JA_Init(const int freq, const SDL_AudioFormat format, const int channels)
{
JA_freq = freq; JA_freq = freq;
JA_format = format; JA_format = format;
JA_channels = channels; JA_channels = channels;
SDL_AudioSpec audioSpec{JA_freq, JA_format, JA_channels, 0, 1024, 0, 0, audioCallback, NULL}; SDL_AudioSpec audioSpec{JA_freq, JA_format, JA_channels, 0, 1024, 0, 0, audioCallback, NULL};
if (sdlAudioDevice != 0) SDL_CloseAudioDevice(sdlAudioDevice); if (sdlAudioDevice != 0)
SDL_CloseAudioDevice(sdlAudioDevice);
sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0); sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
SDL_PauseAudioDevice(sdlAudioDevice, 0); SDL_PauseAudioDevice(sdlAudioDevice, 0);
} }
void JA_Quit() { void JA_Quit()
{
SDL_PauseAudioDevice(sdlAudioDevice, 1); SDL_PauseAudioDevice(sdlAudioDevice, 1);
if (sdlAudioDevice != 0) SDL_CloseAudioDevice(sdlAudioDevice); if (sdlAudioDevice != 0)
SDL_CloseAudioDevice(sdlAudioDevice);
sdlAudioDevice = 0; sdlAudioDevice = 0;
} }
JA_Music_t *JA_LoadMusic(const char* filename) { JA_Music_t *JA_LoadMusic(const char *filename)
{
int chan, samplerate; int chan, samplerate;
// [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.
@@ -100,8 +122,9 @@ JA_Music_t *JA_LoadMusic(const char* filename) {
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
long fsize = ftell(f); long fsize = ftell(f);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
Uint8 *buffer = (Uint8*)malloc(fsize + 1); Uint8 *buffer = (Uint8 *)malloc(fsize + 1);
if (fread(buffer, fsize, 1, f)!=1) return NULL; if (fread(buffer, fsize, 1, f) != 1)
return NULL;
fclose(f); fclose(f);
JA_Music_t *music = new JA_Music_t(); JA_Music_t *music = new JA_Music_t();
@@ -109,17 +132,18 @@ JA_Music_t *JA_LoadMusic(const char* filename) {
music->samples = stb_vorbis_decode_memory(buffer, fsize, &chan, &samplerate, &music->output); 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 // [RZC 28/08/22] Abans el descomprimiem mentre el teniem obert
// music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output); // music->samples = stb_vorbis_decode_filename(filename, &chan, &samplerate, &music->output);
SDL_AudioCVT cvt; SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq); SDL_BuildAudioCVT(&cvt, AUDIO_S16, chan, samplerate, JA_format, JA_channels, JA_freq);
if (cvt.needed) { if (cvt.needed)
{
cvt.len = music->samples * chan * 2; cvt.len = music->samples * chan * 2;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult); cvt.buf = (Uint8 *)SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, music->output, cvt.len); SDL_memcpy(cvt.buf, music->output, cvt.len);
SDL_ConvertAudio(&cvt); SDL_ConvertAudio(&cvt);
free(music->output); free(music->output);
music->output = (short*)cvt.buf; music->output = (short *)cvt.buf;
} }
music->pos = 0; music->pos = 0;
music->state = JA_MUSIC_STOPPED; music->state = JA_MUSIC_STOPPED;
@@ -129,9 +153,11 @@ JA_Music_t *JA_LoadMusic(const char* filename) {
void JA_PlayMusic(JA_Music_t *music, const int loop) void JA_PlayMusic(JA_Music_t *music, const int loop)
{ {
if (!JA_musicEnabled) return; if (!JA_musicEnabled || !music)
return;
if (current_music != NULL) { if (current_music != NULL)
{
current_music->pos = 0; current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED; current_music->state = JA_MUSIC_STOPPED;
} }
@@ -143,67 +169,78 @@ void JA_PlayMusic(JA_Music_t *music, const int loop)
void JA_PauseMusic() void JA_PauseMusic()
{ {
if (!JA_musicEnabled) return; if (!JA_musicEnabled)
return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return; if (current_music == NULL || current_music->state == JA_MUSIC_INVALID)
return;
current_music->state = JA_MUSIC_PAUSED; current_music->state = JA_MUSIC_PAUSED;
} }
void JA_ResumeMusic() void JA_ResumeMusic()
{ {
if (!JA_musicEnabled) return; if (!JA_musicEnabled)
return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return; if (current_music == NULL || current_music->state == JA_MUSIC_INVALID)
return;
current_music->state = JA_MUSIC_PLAYING; current_music->state = JA_MUSIC_PLAYING;
} }
void JA_StopMusic() void JA_StopMusic()
{ {
if (!JA_musicEnabled) return; if (!JA_musicEnabled)
return;
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID) return; if (current_music == NULL || current_music->state == JA_MUSIC_INVALID)
return;
current_music->pos = 0; current_music->pos = 0;
current_music->state = JA_MUSIC_STOPPED; current_music->state = JA_MUSIC_STOPPED;
} }
JA_Music_state JA_GetMusicState() { JA_Music_state JA_GetMusicState()
if (!JA_musicEnabled) return JA_MUSIC_DISABLED; {
if (!JA_musicEnabled)
return JA_MUSIC_DISABLED;
if (current_music == NULL) return JA_MUSIC_INVALID; if (current_music == NULL)
return JA_MUSIC_INVALID;
return current_music->state; return current_music->state;
} }
void JA_DeleteMusic(JA_Music_t *music) { void JA_DeleteMusic(JA_Music_t *music)
if (current_music == music) current_music = NULL; {
if (current_music == music)
current_music = NULL;
free(music->output); free(music->output);
delete music; delete music;
} }
int JA_SetMusicVolume(int volume) int JA_SetMusicVolume(int volume)
{ {
JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0 : volume; JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0
: volume;
return JA_musicVolume; return JA_musicVolume;
} }
void JA_EnableMusic(const bool value) void JA_EnableMusic(const bool value)
{ {
if (!value && current_music != NULL && current_music->state==JA_MUSIC_PLAYING) JA_StopMusic(); if (!value && current_music != NULL && current_music->state == JA_MUSIC_PLAYING)
JA_StopMusic();
JA_musicEnabled = value; JA_musicEnabled = value;
} }
JA_Sound_t *JA_NewSound(Uint8 *buffer, Uint32 length)
{
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length) {
JA_Sound_t *sound = new JA_Sound_t(); JA_Sound_t *sound = new JA_Sound_t();
sound->buffer = buffer; sound->buffer = buffer;
sound->length = length; sound->length = length;
return sound; 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();
SDL_AudioSpec wavSpec; SDL_AudioSpec wavSpec;
SDL_LoadWAV(filename, &wavSpec, &sound->buffer, &sound->length); SDL_LoadWAV(filename, &wavSpec, &sound->buffer, &sound->length);
@@ -211,7 +248,7 @@ JA_Sound_t *JA_LoadSound(const char* filename) {
SDL_AudioCVT cvt; SDL_AudioCVT cvt;
SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq); SDL_BuildAudioCVT(&cvt, wavSpec.format, wavSpec.channels, wavSpec.freq, JA_format, JA_channels, JA_freq);
cvt.len = sound->length; cvt.len = sound->length;
cvt.buf = (Uint8 *) SDL_malloc(cvt.len * cvt.len_mult); cvt.buf = (Uint8 *)SDL_malloc(cvt.len * cvt.len_mult);
SDL_memcpy(cvt.buf, sound->buffer, sound->length); SDL_memcpy(cvt.buf, sound->buffer, sound->length);
SDL_ConvertAudio(&cvt); SDL_ConvertAudio(&cvt);
SDL_FreeWAV(sound->buffer); SDL_FreeWAV(sound->buffer);
@@ -223,11 +260,16 @@ 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) return 0; if (!JA_soundEnabled || !sound)
return 0;
int channel = 0; int channel = 0;
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; } while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE)
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS) channel = 0; {
channel++;
}
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS)
channel = 0;
channels[channel].sound = sound; channels[channel].sound = sound;
channels[channel].times = loop; channels[channel].times = loop;
@@ -238,8 +280,10 @@ int JA_PlaySound(JA_Sound_t *sound, const int loop)
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++)
if (channels[i].sound == sound) JA_StopChannel(i); {
if (channels[i].sound == sound)
JA_StopChannel(i);
} }
SDL_free(sound->buffer); SDL_free(sound->buffer);
delete sound; delete sound;
@@ -247,41 +291,60 @@ void JA_DeleteSound(JA_Sound_t *sound)
void JA_PauseChannel(const int channel) void JA_PauseChannel(const int channel)
{ {
if (!JA_soundEnabled) return; if (!JA_soundEnabled)
return;
if (channel == -1) { if (channel == -1)
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { {
if (channels[i].state == JA_CHANNEL_PLAYING) channels[i].state = JA_CHANNEL_PAUSED; for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
{
if (channels[i].state == JA_CHANNEL_PLAYING)
channels[i].state = JA_CHANNEL_PAUSED;
} }
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) { }
if (channels[channel].state == JA_CHANNEL_PLAYING) channels[channel].state = JA_CHANNEL_PAUSED; else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
{
if (channels[channel].state == JA_CHANNEL_PLAYING)
channels[channel].state = JA_CHANNEL_PAUSED;
} }
} }
void JA_ResumeChannel(const int channel) void JA_ResumeChannel(const int channel)
{ {
if (!JA_soundEnabled) return; if (!JA_soundEnabled)
return;
if (channel == -1) { if (channel == -1)
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { {
if (channels[i].state == JA_CHANNEL_PAUSED) channels[i].state = JA_CHANNEL_PLAYING; for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
{
if (channels[i].state == JA_CHANNEL_PAUSED)
channels[i].state = JA_CHANNEL_PLAYING;
} }
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) { }
if (channels[channel].state == JA_CHANNEL_PAUSED) channels[channel].state = JA_CHANNEL_PLAYING; else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
{
if (channels[channel].state == JA_CHANNEL_PAUSED)
channels[channel].state = JA_CHANNEL_PLAYING;
} }
} }
void JA_StopChannel(const int channel) void JA_StopChannel(const int channel)
{ {
if (!JA_soundEnabled) return; if (!JA_soundEnabled)
return;
if (channel == -1) { if (channel == -1)
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) { {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
{
channels[i].state = JA_CHANNEL_FREE; channels[i].state = JA_CHANNEL_FREE;
channels[i].pos = 0; channels[i].pos = 0;
channels[i].sound = NULL; channels[i].sound = NULL;
} }
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) { }
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
{
channels[channel].state = JA_CHANNEL_FREE; channels[channel].state = JA_CHANNEL_FREE;
channels[channel].pos = 0; channels[channel].pos = 0;
channels[channel].sound = NULL; channels[channel].sound = NULL;
@@ -290,15 +353,18 @@ void JA_StopChannel(const int channel)
JA_Channel_state JA_GetChannelState(const int channel) JA_Channel_state JA_GetChannelState(const int channel)
{ {
if (!JA_soundEnabled) return JA_SOUND_DISABLED; if (!JA_soundEnabled)
return JA_SOUND_DISABLED;
if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS) return JA_CHANNEL_INVALID; if (channel < 0 || channel >= JA_MAX_SIMULTANEOUS_CHANNELS)
return JA_CHANNEL_INVALID;
return channels[channel].state; return channels[channel].state;
} }
int JA_SetSoundVolume(int volume) int JA_SetSoundVolume(int volume)
{ {
JA_soundVolume = volume > 128 ? 128 : volume < 0 ? 0 : volume; JA_soundVolume = volume > 128 ? 128 : volume < 0 ? 0
: volume;
return JA_soundVolume; return JA_soundVolume;
} }
@@ -306,15 +372,17 @@ void JA_EnableSound(const bool value)
{ {
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
{ {
if (channels[i].state == JA_CHANNEL_PLAYING) JA_StopChannel(i); if (channels[i].state == JA_CHANNEL_PLAYING)
JA_StopChannel(i);
} }
JA_soundEnabled = value; JA_soundEnabled = value;
} }
int JA_SetVolume(int volume) int JA_SetVolume(int volume)
{ {
JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0 : volume; JA_musicVolume = volume > 128 ? 128 : volume < 0 ? 0
JA_soundVolume = JA_musicVolume/2; : volume;
JA_soundVolume = JA_musicVolume / 2;
return JA_musicVolume; return JA_musicVolume;
} }

View File

@@ -1,17 +1,31 @@
#pragma once #pragma once
#include <SDL2/SDL_audio.h> // for SDL_AudioFormat #include <SDL2/SDL_audio.h> // para SDL_AudioFormat
#include <SDL2/SDL_stdinc.h> // for Uint32, Uint8 #include <SDL2/SDL_stdinc.h> // para Uint32, Uint8
struct JA_Music_t; // lines 5-5 struct JA_Music_t; // lines 5-5
struct JA_Sound_t; // lines 6-6 struct JA_Sound_t; // lines 6-6
enum JA_Channel_state { JA_CHANNEL_INVALID, JA_CHANNEL_FREE, JA_CHANNEL_PLAYING, JA_CHANNEL_PAUSED, JA_SOUND_DISABLED }; enum JA_Channel_state
enum JA_Music_state { JA_MUSIC_INVALID, JA_MUSIC_PLAYING, JA_MUSIC_PAUSED, JA_MUSIC_STOPPED, JA_MUSIC_DISABLED }; {
JA_CHANNEL_INVALID,
JA_CHANNEL_FREE,
JA_CHANNEL_PLAYING,
JA_CHANNEL_PAUSED,
JA_SOUND_DISABLED
};
enum JA_Music_state
{
JA_MUSIC_INVALID,
JA_MUSIC_PLAYING,
JA_MUSIC_PAUSED,
JA_MUSIC_STOPPED,
JA_MUSIC_DISABLED
};
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels); 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);
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();
@@ -21,8 +35,8 @@ void JA_DeleteMusic(JA_Music_t *music);
int JA_SetMusicVolume(int volume); int JA_SetMusicVolume(int volume);
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(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);
void JA_PauseChannel(const int channel); void JA_PauseChannel(const int channel);
void JA_ResumeChannel(const int channel); void JA_ResumeChannel(const int channel);

View File

@@ -1,166 +0,0 @@
#ifdef JA_USESDLMIXER
#include "jail_audio.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
#include <stdio.h>
struct JA_Sound_t {}; // Dummy structs
struct JA_Music_t {};
int JA_freq {48000};
SDL_AudioFormat JA_format {AUDIO_S16};
Uint8 JA_channels {2};
int JA_musicVolume = 128;
int JA_soundVolume = 64;
bool JA_musicEnabled = true;
bool JA_soundEnabled = true;
void JA_Init(const int freq, const SDL_AudioFormat format, const int channels) {
JA_freq = freq;
JA_format = format;
JA_channels = channels;
Mix_OpenAudio(JA_freq, JA_format, JA_channels, 1024);
}
void JA_Quit() {
Mix_CloseAudio();
}
JA_Music_t *JA_LoadMusic(const char* filename) {
return (JA_Music_t*)Mix_LoadMUS(filename);
}
void JA_PlayMusic(JA_Music_t *music, const int loop)
{
if (!JA_musicEnabled) return;
Mix_PlayMusic((Mix_Music*)music, loop);
Mix_VolumeMusic(JA_musicVolume);
}
void JA_PauseMusic()
{
if (!JA_musicEnabled) return;
Mix_PauseMusic();
}
void JA_ResumeMusic()
{
if (!JA_musicEnabled) return;
Mix_ResumeMusic();
}
void JA_StopMusic()
{
if (!JA_musicEnabled) return;
Mix_HaltMusic();
}
JA_Music_state JA_GetMusicState()
{
if (!JA_musicEnabled) return JA_MUSIC_DISABLED;
if (Mix_PausedMusic()) {
return JA_MUSIC_PAUSED;
} else if (Mix_PlayingMusic()) {
return JA_MUSIC_PLAYING;
} else {
return JA_MUSIC_STOPPED;
}
}
void JA_DeleteMusic(JA_Music_t *music)
{
Mix_FreeMusic((Mix_Music*)music);
}
int JA_SetMusicVolume(int volume)
{
JA_musicVolume = volume;
Mix_VolumeMusic(JA_musicVolume);
return JA_musicVolume;
}
void JA_EnableMusic(const bool value)
{
if (Mix_PlayingMusic()) Mix_HaltMusic();
JA_musicEnabled = value;
}
JA_Sound_t *JA_NewSound(Uint8* buffer, Uint32 length)
{
return NULL;
}
JA_Sound_t *JA_LoadSound(const char* filename) {
JA_Sound_t *sound = (JA_Sound_t*)Mix_LoadWAV(filename);
return sound;
}
int JA_PlaySound(JA_Sound_t *sound, const int loop) {
if (!JA_soundEnabled) return -1;
const int channel = Mix_PlayChannel(-1, (Mix_Chunk*)sound, loop);
Mix_Volume(-1, JA_soundVolume);
return channel;
}
void JA_DeleteSound(JA_Sound_t *sound)
{
Mix_FreeChunk((Mix_Chunk*)sound);
}
void JA_PauseChannel(const int channel)
{
if (!JA_soundEnabled) return;
Mix_Pause(channel);
}
void JA_ResumeChannel(const int channel)
{
if (!JA_soundEnabled) return;
Mix_Resume(channel);
}
void JA_StopChannel(const int channel)
{
if (!JA_soundEnabled) return;
Mix_HaltChannel(channel);
}
JA_Channel_state JA_GetChannelState(const int channel)
{
if (!JA_soundEnabled) return JA_SOUND_DISABLED;
if (Mix_Paused(channel)) {
return JA_CHANNEL_PAUSED;
} else if (Mix_Playing(channel)) {
return JA_CHANNEL_PLAYING;
} else {
return JA_CHANNEL_FREE;
}
}
int JA_SetSoundVolume(int volume)
{
JA_musicVolume = volume;
Mix_Volume(-1, JA_musicVolume);
return JA_musicVolume;
}
void JA_EnableSound(const bool value)
{
Mix_HaltChannel(-1);
JA_soundEnabled = value;
}
int JA_SetVolume(int volume)
{
JA_SetSoundVolume(volume);
return JA_SetMusicVolume(volume);
}
#endif

View File

@@ -1,10 +1,10 @@
#ifndef NO_SHADERS #ifndef NO_SHADERS
#include "jail_shader.h" #include "jail_shader.h"
#include <SDL2/SDL_rect.h> // for SDL_Point #include <SDL2/SDL_rect.h> // para SDL_Point
#include <stdlib.h> // for NULL, free, malloc, exit #include <stdlib.h> // para NULL, free, malloc, exit
#include <string.h> // for strncmp #include <string.h> // para strncmp
#include <iostream> // for basic_ostream, char_traits, operator<< #include <iostream> // para basic_ostream, char_traits, operator<<
#ifdef __APPLE__ #ifdef __APPLE__
#include "CoreFoundation/CoreFoundation.h" #include "CoreFoundation/CoreFoundation.h"
@@ -14,7 +14,7 @@
#include <OpenGL/gl3.h> #include <OpenGL/gl3.h>
#else #else
#include <OpenGL/gl.h> #include <OpenGL/gl.h>
#endif //!ESSENTIAL_GL_PRACTICES_SUPPORT_GL3 #endif //! ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#else #else
#include <SDL2/SDL_opengl.h> #include <SDL2/SDL_opengl.h>
#endif #endif
@@ -24,12 +24,12 @@ namespace shader
SDL_Window *win = nullptr; SDL_Window *win = nullptr;
SDL_Renderer *renderer = nullptr; SDL_Renderer *renderer = nullptr;
GLuint programId = 0; GLuint programId = 0;
SDL_Texture* backBuffer = nullptr; SDL_Texture *backBuffer = nullptr;
SDL_Point win_size = {320*4, 256*4}; SDL_Point win_size = {320 * 4, 256 * 4};
SDL_Point tex_size = {320, 256}; SDL_Point tex_size = {320, 256};
bool usingOpenGL; bool usingOpenGL;
#ifndef __APPLE__ #ifndef __APPLE__
// I'm avoiding the use of GLEW or some extensions handler, but that // I'm avoiding the use of GLEW or some extensions handler, but that
// doesn't mean you should... // doesn't mean you should...
@@ -47,7 +47,8 @@ namespace shader
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
PFNGLUSEPROGRAMPROC glUseProgram; PFNGLUSEPROGRAMPROC glUseProgram;
bool initGLExtensions() { bool initGLExtensions()
{
glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader"); glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader");
glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource"); glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource");
glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader"); glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader");
@@ -63,55 +64,59 @@ namespace shader
glUseProgram = (PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram"); glUseProgram = (PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram");
return glCreateShader && glShaderSource && glCompileShader && glGetShaderiv && return glCreateShader && glShaderSource && glCompileShader && glGetShaderiv &&
glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram && glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram &&
glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog && glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog &&
glUseProgram; glUseProgram;
} }
#endif #endif
GLuint compileShader(const char* source, GLuint shaderType) { GLuint compileShader(const char *source, GLuint shaderType)
{
// Create ID for shader // Create ID for shader
GLuint result = glCreateShader(shaderType); GLuint result = glCreateShader(shaderType);
// Add define depending on shader type // Add define depending on shader type
const char *sources[2] = { shaderType==GL_VERTEX_SHADER?"#define VERTEX\n":"#define FRAGMENT\n", source }; const char *sources[2] = {shaderType == GL_VERTEX_SHADER ? "#define VERTEX\n" : "#define FRAGMENT\n", source};
// Define shader text // Define shader text
glShaderSource(result, 2, sources, NULL); glShaderSource(result, 2, sources, NULL);
// Compile shader // Compile shader
glCompileShader(result); glCompileShader(result);
//Check vertex shader for errors // Check vertex shader for errors
GLint shaderCompiled = GL_FALSE; GLint shaderCompiled = GL_FALSE;
glGetShaderiv( result, GL_COMPILE_STATUS, &shaderCompiled ); glGetShaderiv(result, GL_COMPILE_STATUS, &shaderCompiled);
if( shaderCompiled != GL_TRUE ) { if (shaderCompiled != GL_TRUE)
{
std::cout << "Error en la compilación: " << result << "!" << std::endl; std::cout << "Error en la compilación: " << result << "!" << std::endl;
GLint logLength; GLint logLength;
glGetShaderiv(result, GL_INFO_LOG_LENGTH, &logLength); glGetShaderiv(result, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0) if (logLength > 0)
{ {
GLchar *log = (GLchar*)malloc(logLength); GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(result, logLength, &logLength, log); glGetShaderInfoLog(result, logLength, &logLength, log);
std::cout << "Shader compile log:" << log << std::endl; std::cout << "Shader compile log:" << log << std::endl;
free(log); free(log);
} }
glDeleteShader(result); glDeleteShader(result);
result = 0; result = 0;
// } else { // } else {
// std::cout << "Shader compilado correctamente. Id = " << result << std::endl; // std::cout << "Shader compilado correctamente. Id = " << result << std::endl;
} }
return result; return result;
} }
GLuint compileProgram(const char* vertexShaderSource, const char* fragmentShaderSource) { GLuint compileProgram(const char *vertexShaderSource, const char *fragmentShaderSource)
{
GLuint programId = 0; GLuint programId = 0;
GLuint vtxShaderId, fragShaderId; GLuint vtxShaderId, fragShaderId;
programId = glCreateProgram(); programId = glCreateProgram();
vtxShaderId = compileShader(vertexShaderSource, GL_VERTEX_SHADER); vtxShaderId = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
fragShaderId = compileShader(fragmentShaderSource?fragmentShaderSource:vertexShaderSource, GL_FRAGMENT_SHADER); fragShaderId = compileShader(fragmentShaderSource ? fragmentShaderSource : vertexShaderSource, GL_FRAGMENT_SHADER);
if(vtxShaderId && fragShaderId) { if (vtxShaderId && fragShaderId)
{
// Associate shader with program // Associate shader with program
glAttachShader(programId, vtxShaderId); glAttachShader(programId, vtxShaderId);
glAttachShader(programId, fragShaderId); glAttachShader(programId, fragShaderId);
@@ -121,24 +126,28 @@ namespace shader
// Check the status of the compile/link // Check the status of the compile/link
GLint logLen; GLint logLen;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen); glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen);
if(logLen > 0) { if (logLen > 0)
char* log = (char*) malloc(logLen * sizeof(char)); {
char *log = (char *)malloc(logLen * sizeof(char));
// Show any errors as appropriate // Show any errors as appropriate
glGetProgramInfoLog(programId, logLen, &logLen, log); glGetProgramInfoLog(programId, logLen, &logLen, log);
std::cout << "Prog Info Log: " << std::endl << log << std::endl; std::cout << "Prog Info Log: " << std::endl
<< log << std::endl;
free(log); free(log);
} }
} }
if(vtxShaderId) { if (vtxShaderId)
{
glDeleteShader(vtxShaderId); glDeleteShader(vtxShaderId);
} }
if(fragShaderId) { if (fragShaderId)
{
glDeleteShader(fragShaderId); glDeleteShader(fragShaderId);
} }
return programId; return programId;
} }
const bool init(SDL_Window* win, SDL_Texture* backBuffer, const char* vertexShader, const char* fragmentShader) const bool init(SDL_Window *win, SDL_Texture *backBuffer, const char *vertexShader, const char *fragmentShader)
{ {
shader::win = win; shader::win = win;
shader::renderer = SDL_GetRenderer(win); shader::renderer = SDL_GetRenderer(win);
@@ -155,19 +164,23 @@ namespace shader
SDL_RendererInfo rendererInfo; SDL_RendererInfo rendererInfo;
SDL_GetRendererInfo(renderer, &rendererInfo); SDL_GetRendererInfo(renderer, &rendererInfo);
if(!strncmp(rendererInfo.name, "opengl", 6)) { if (!strncmp(rendererInfo.name, "opengl", 6))
//std::cout << "Es OpenGL!" << std::endl; {
#ifndef __APPLE__ // std::cout << "Es OpenGL!" << std::endl;
if (!initGLExtensions()) { #ifndef __APPLE__
if (!initGLExtensions())
{
std::cout << "WARNING: No s'han pogut inicialitzar les extensions d'OpenGL!" << std::endl; std::cout << "WARNING: No s'han pogut inicialitzar les extensions d'OpenGL!" << std::endl;
usingOpenGL = false; usingOpenGL = false;
return false; return false;
} }
#endif #endif
// Compilar el shader y dejarlo listo para usar. // Compilar el shader y dejarlo listo para usar.
programId = compileProgram(vertexShader, fragmentShader); programId = compileProgram(vertexShader, fragmentShader);
//std::cout << "programId = " << programId << std::endl; // std::cout << "programId = " << programId << std::endl;
} else { }
else
{
std::cout << "WARNING: El driver del renderer no es OpenGL." << std::endl; std::cout << "WARNING: El driver del renderer no es OpenGL." << std::endl;
usingOpenGL = false; usingOpenGL = false;
return false; return false;
@@ -180,16 +193,18 @@ namespace shader
{ {
GLint oldProgramId; GLint oldProgramId;
// Guarrada para obtener el textureid (en driverdata->texture) // Guarrada para obtener el textureid (en driverdata->texture)
//Detach the texture // Detach the texture
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_SetRenderTarget(renderer, NULL); SDL_SetRenderTarget(renderer, NULL);
SDL_RenderClear(renderer); SDL_RenderClear(renderer);
if (usingOpenGL) { if (usingOpenGL)
{
SDL_GL_BindTexture(backBuffer, NULL, NULL); SDL_GL_BindTexture(backBuffer, NULL, NULL);
if(programId != 0) { if (programId != 0)
glGetIntegerv(GL_CURRENT_PROGRAM,&oldProgramId); {
glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgramId);
glUseProgram(programId); glUseProgram(programId);
} }
@@ -210,21 +225,24 @@ namespace shader
glViewport(0, 0, win_size.x, win_size.y); glViewport(0, 0, win_size.x, win_size.y);
glBegin(GL_TRIANGLE_STRIP); glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(minu, minv); glTexCoord2f(minu, minv);
glVertex2f(minx, miny); glVertex2f(minx, miny);
glTexCoord2f(maxu, minv); glTexCoord2f(maxu, minv);
glVertex2f(maxx, miny); glVertex2f(maxx, miny);
glTexCoord2f(minu, maxv); glTexCoord2f(minu, maxv);
glVertex2f(minx, maxy); glVertex2f(minx, maxy);
glTexCoord2f(maxu, maxv); glTexCoord2f(maxu, maxv);
glVertex2f(maxx, maxy); glVertex2f(maxx, maxy);
glEnd(); glEnd();
SDL_GL_SwapWindow(win); SDL_GL_SwapWindow(win);
if(programId != 0) { if (programId != 0)
{
glUseProgram(oldProgramId); glUseProgram(oldProgramId);
} }
} else { }
else
{
SDL_RenderCopy(renderer, backBuffer, NULL, NULL); SDL_RenderCopy(renderer, backBuffer, NULL, NULL);
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer);
} }

View File

@@ -2,8 +2,8 @@
#pragma once #pragma once
#include <SDL2/SDL_render.h> // for SDL_Texture #include <SDL2/SDL_render.h> // para SDL_Texture
#include <SDL2/SDL_video.h> // for SDL_Window #include <SDL2/SDL_video.h> // para SDL_Window
// TIPS: // TIPS:
// ======================================================================= // =======================================================================
@@ -40,8 +40,8 @@
namespace shader namespace shader
{ {
const bool init(SDL_Window* win, SDL_Texture* backBuffer, const bool init(SDL_Window *win, SDL_Texture *backBuffer,
const char* vertexShader, const char* fragmentShader=nullptr); const char *vertexShader, const char *fragmentShader = nullptr);
void render(); void render();
} }

View File

@@ -1,19 +1,19 @@
#include "lang.h" #include "lang.h"
#include <fstream> // for basic_ifstream, basic_istream, ifstream #include <fstream> // para basic_ifstream, basic_istream, ifstream
#include <vector> // for vector #include <vector> // para vector
namespace lang namespace lang
{ {
std::vector<std::string> texts; // Vector con los textos std::vector<std::string> texts; // Vector con los textos
// Inicializa los textos del juego en el idioma seleccionado // Inicializa los textos del juego en el idioma seleccionado
bool loadFromFile(std::string filePath) bool loadFromFile(std::string file_path)
{ {
texts.clear(); texts.clear();
bool success = false; bool success = false;
std::ifstream rfile(filePath); std::ifstream rfile(file_path);
if (rfile.is_open() && rfile.good()) if (rfile.is_open() && rfile.good())
{ {
success = true; success = true;

View File

@@ -1,10 +1,10 @@
#pragma once #pragma once
#include <string> // for string #include <string> // para string
namespace lang namespace lang
{ {
enum lang_e enum class Code : int
{ {
es_ES = 0, es_ES = 0,
ba_BA = 1, ba_BA = 1,
@@ -12,7 +12,7 @@ namespace lang
}; };
// Inicializa los textos del juego en el idioma seleccionado // Inicializa los textos del juego en el idioma seleccionado
bool loadFromFile(std::string filePath); bool loadFromFile(std::string file_path);
// Obtiene la cadena de texto del indice // Obtiene la cadena de texto del indice
std::string getText(int index); std::string getText(int index);

View File

@@ -1,73 +1,71 @@
#include "logo.h" #include "logo.h"
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED #include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <string> // for basic_string #include <utility> // Para move
#include "asset.h" // for Asset #include "global_inputs.h" // Para check
#include "global_inputs.h" // for globalInputs::check #include "input.h" // Para Input
#include "input.h" // for Input #include "jail_audio.h" // Para JA_StopMusic
#include "jail_audio.h" // for JA_StopMusic #include "param.h" // Para Param, ParamGame, param
#include "param.h" // for param #include "resource.h" // Para Resource
#include "screen.h" // for Screen #include "screen.h" // Para Screen
#include "section.h" // for name, name_e, options, options_e #include "section.h" // Para Name, name, Options, options
#include "sprite.h" // for Sprite #include "sprite.h" // Para Sprite
#include "texture.h" // for Texture #include "texture.h" // Para Texture
#include "utils.h" // Para Color, Zone
// Constructor // Constructor
Logo::Logo() Logo::Logo()
: since_texture_(Resource::get()->getTexture("logo_since_1998.png")),
since_sprite_(std::make_unique<Sprite>(since_texture_)),
jail_texture_(Resource::get()->getTexture("logo_jailgames.png")),
ticks_(0)
{ {
// Copia la dirección de los objetos
SDL_Renderer *renderer = Screen::get()->getRenderer();
// Reserva memoria para los punteros
jailTexture = std::make_shared<Texture>(renderer, Asset::get()->get("logo_jailgames.png"));
sinceTexture = std::make_shared<Texture>(renderer, Asset::get()->get("logo_since_1998.png"));
sinceSprite = std::make_unique<Sprite>((param.game.width - sinceTexture->getWidth()) / 2, 83 + jailTexture->getHeight() + 5, sinceTexture->getWidth(), sinceTexture->getHeight(), sinceTexture);
// Inicializa variables // Inicializa variables
counter = 0; counter_ = 0;
section::name = section::NAME_LOGO; section::name = section::Name::LOGO;
ticks = 0; dest_.x = param.game.game_area.center_x - jail_texture_->getWidth() / 2;
ticksSpeed = 15; dest_.y = param.game.game_area.center_y - jail_texture_->getHeight() / 2;
showSinceSprite_cm = 70; since_sprite_->setPosition({(param.game.width - since_texture_->getWidth()) / 2, 83 + jail_texture_->getHeight() + 5, since_texture_->getWidth(), since_texture_->getHeight()});
initFade_cm = 300; since_sprite_->setY(dest_.y + jail_texture_->getHeight() + 5);
endLogo_cm = 400; since_sprite_->setSpriteClip(0, 0, since_texture_->getWidth(), since_texture_->getHeight());
postLogoDuration = 20; since_texture_->setColor(0x00, 0x00, 0x00); // Esto en linux no hace nada ??
speed = 8;
dest.x = param.game.game_area.center_x - jailTexture->getWidth() / 2;
dest.y = param.game.game_area.center_y - jailTexture->getHeight() / 2;
sinceSprite->setPosY(dest.y + jailTexture->getHeight() + 5);
sinceSprite->setSpriteClip(0, 0, sinceTexture->getWidth(), sinceTexture->getHeight());
sinceSprite->setEnabled(false);
sinceTexture->setColor(0x00, 0x00, 0x00); // Esto en linux no hace nada ??
// Crea los sprites de cada linea // Crea los sprites de cada linea
for (int i = 0; i < jailTexture->getHeight(); ++i) for (int i = 0; i < jail_texture_->getHeight(); ++i)
{ {
auto temp = std::make_unique<Sprite>(0, i, jailTexture->getWidth(), 1, jailTexture); auto temp = std::make_unique<Sprite>(jail_texture_, 0, i, jail_texture_->getWidth(), 1);
temp->setSpriteClip(0, i, jailTexture->getWidth(), 1); temp->setSpriteClip(0, i, jail_texture_->getWidth(), 1);
const int posX = (i % 2 == 0) ? param.game.width + (i * 3) : -jailTexture->getWidth() - (i * 3); const int posX = (i % 2 == 0) ? param.game.width + (i * 3) : -jail_texture_->getWidth() - (i * 3);
temp->setPosX(posX); temp->setX(posX);
temp->setPosY(dest.y + i); temp->setY(dest_.y + i);
jailSprite.push_back(std::move(temp)); jail_sprite_.push_back(std::move(temp));
} }
// Inicializa el vector de colores // Inicializa el vector de colores
color.push_back({0x00, 0x00, 0x00}); // Black color_.push_back(Color(0x00, 0x00, 0x00)); // Black
color.push_back({0x00, 0x00, 0xd8}); // Blue color_.push_back(Color(0x00, 0x00, 0xd8)); // Blue
color.push_back({0xd8, 0x00, 0x00}); // Red color_.push_back(Color(0xd8, 0x00, 0x00)); // Red
color.push_back({0xd8, 0x00, 0xd8}); // Magenta color_.push_back(Color(0xd8, 0x00, 0xd8)); // Magenta
color.push_back({0x00, 0xd8, 0x00}); // Green color_.push_back(Color(0x00, 0xd8, 0x00)); // Green
color.push_back({0x00, 0xd8, 0xd8}); // Cyan color_.push_back(Color(0x00, 0xd8, 0xd8)); // Cyan
color.push_back({0xd8, 0xd8, 0x00}); // Yellow color_.push_back(Color(0xd8, 0xd8, 0x00)); // Yellow
color.push_back({0xFF, 0xFF, 0xFF}); // Bright white color_.push_back(Color(0xFF, 0xFF, 0xFF)); // Bright white
}
// Destructor
Logo::~Logo()
{
jail_texture_->setColor(255, 255, 255);
since_texture_->setColor(255, 255, 255);
} }
// Recarga todas las texturas // Recarga todas las texturas
void Logo::reloadTextures() void Logo::reloadTextures()
{ {
jailTexture->reLoad(); jail_texture_->reLoad();
sinceTexture->reLoad(); since_texture_->reLoad();
} }
// Comprueba el manejador de eventos // Comprueba el manejador de eventos
@@ -80,7 +78,8 @@ void Logo::checkEvents()
// Evento de salida de la aplicación // Evento de salida de la aplicación
if (event.type == SDL_QUIT) if (event.type == SDL_QUIT)
{ {
section::name = section::NAME_QUIT; section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break; break;
} }
@@ -102,14 +101,11 @@ void Logo::checkInput()
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;
return; return;
} }
// Comprueba el input para el resto de objetos
Screen::get()->checkInput();
// 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
globalInputs::check(); globalInputs::check();
} }
@@ -117,26 +113,26 @@ void Logo::checkInput()
// Gestiona el logo de JAILGAME // Gestiona el logo de JAILGAME
void Logo::updateJAILGAMES() void Logo::updateJAILGAMES()
{ {
if (counter > 30) if (counter_ > 30)
{ {
for (int i = 0; i < (int)jailSprite.size(); ++i) for (int i = 0; i < (int)jail_sprite_.size(); ++i)
{ {
if (jailSprite[i]->getPosX() != dest.x) if (jail_sprite_[i]->getX() != dest_.x)
{ {
if (i % 2 == 0) if (i % 2 == 0)
{ {
jailSprite[i]->incPosX(-speed); jail_sprite_[i]->incX(-SPEED);
if (jailSprite[i]->getPosX() < dest.x) if (jail_sprite_[i]->getX() < dest_.x)
{ {
jailSprite[i]->setPosX(dest.x); jail_sprite_[i]->setX(dest_.x);
} }
} }
else else
{ {
jailSprite[i]->incPosX(speed); jail_sprite_[i]->incX(SPEED);
if (jailSprite[i]->getPosX() > dest.x) if (jail_sprite_[i]->getX() > dest_.x)
{ {
jailSprite[i]->setPosX(dest.x); jail_sprite_[i]->setX(dest_.x);
} }
} }
} }
@@ -152,19 +148,19 @@ void Logo::updateTextureColors()
// Manejo de 'sinceTexture' // Manejo de 'sinceTexture'
for (int i = 0; i <= 7; ++i) for (int i = 0; i <= 7; ++i)
{ {
if (counter == showSinceSprite_cm + inc * i) if (counter_ == SHOW_SINCE_SPRITE_COUNTER_MARK + inc * i)
{ {
sinceTexture->setColor(color[i].r, color[i].g, color[i].b); since_texture_->setColor(color_[i].r, color_[i].g, color_[i].b);
} }
} }
// Manejo de 'jailTexture' y 'sinceTexture' en el fade // Manejo de 'jailTexture' y 'sinceTexture' en el fade
for (int i = 0; i <= 6; ++i) for (int i = 0; i <= 6; ++i)
{ {
if (counter == initFade_cm + inc * i) if (counter_ == INIT_FADE_COUNTER_MARK + inc * i)
{ {
jailTexture->setColor(color[6 - i].r, color[6 - i].g, color[6 - i].b); jail_texture_->setColor(color_[6 - i].r, color_[6 - i].g, color_[6 - i].b);
sinceTexture->setColor(color[6 - i].r, color[6 - i].g, color[6 - i].b); since_texture_->setColor(color_[6 - i].r, color_[6 - i].g, color_[6 - i].b);
} }
} }
} }
@@ -172,11 +168,12 @@ void Logo::updateTextureColors()
// Actualiza las variables // Actualiza las variables
void Logo::update() void Logo::update()
{ {
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego constexpr int TICKS_SPEED = 15;
if (SDL_GetTicks() - ticks > ticksSpeed)
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
{ {
// Actualiza el contador de ticks // Actualiza el contador de ticks
ticks = SDL_GetTicks(); ticks_ = SDL_GetTicks();
// Actualiza el objeto screen // Actualiza el objeto screen
Screen::get()->update(); Screen::get()->update();
@@ -191,18 +188,12 @@ void Logo::update()
updateTextureColors(); updateTextureColors();
// Gestiona el contador y sus eventos // Gestiona el contador y sus eventos
counter++; counter_++;
// Comprueba si ha terminado el logo // Comprueba si ha terminado el logo
if (counter == endLogo_cm + postLogoDuration) if (counter_ == END_LOGO_COUNTER_MARK + POST_LOGO_DURATION)
{ {
section::name = section::NAME_INTRO; section::name = section::Name::INTRO;
}
// Comprueba si se ha de mostrar el sprite
else if (counter == showSinceSprite_cm)
{
sinceSprite->setEnabled(true);
} }
} }
} }
@@ -217,11 +208,15 @@ void Logo::render()
Screen::get()->clean(); Screen::get()->clean();
// Dibuja los sprites // Dibuja los sprites
for (auto &sprite : jailSprite) for (auto &sprite : jail_sprite_)
{ {
sprite->render(); sprite->render();
} }
sinceSprite->render();
if (counter_ >= SHOW_SINCE_SPRITE_COUNTER_MARK)
{
since_sprite_->render();
}
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
Screen::get()->blit(); Screen::get()->blit();
@@ -233,7 +228,7 @@ void Logo::run()
// Detiene la música // Detiene la música
JA_StopMusic(); JA_StopMusic();
while (section::name == section::NAME_LOGO) while (section::name == section::Name::LOGO)
{ {
checkInput(); checkInput();
update(); update();

View File

@@ -1,13 +1,12 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event #include <SDL2/SDL_rect.h> // Para SDL_Point
#include <SDL2/SDL_rect.h> // for SDL_Point #include <SDL2/SDL_stdinc.h> // Para Uint32
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <memory> // Para shared_ptr, unique_ptr
#include <vector> // for vector #include <vector> // Para vector
#include <memory> class Sprite;
#include "utils.h" // for Color class Texture; // lines 9-9
#include "sprite.h" struct Color;
#include "texture.h"
/* /*
Esta clase gestiona un estado del programa. Se encarga de dibujar por pantalla el Esta clase gestiona un estado del programa. Se encarga de dibujar por pantalla el
@@ -21,23 +20,24 @@
class Logo class Logo
{ {
private: private:
// Constantes
static constexpr int SHOW_SINCE_SPRITE_COUNTER_MARK = 70; // Tiempo del contador en el que empieza a verse el sprite de "SINCE 1998"
static constexpr int INIT_FADE_COUNTER_MARK = 300; // Tiempo del contador cuando inicia el fade a negro
static constexpr int END_LOGO_COUNTER_MARK = 400; // Tiempo del contador para terminar el logo
static constexpr int POST_LOGO_DURATION = 20; // Tiempo que dura el logo con el fade al maximo
static constexpr int SPEED = 8; // Velocidad de desplazamiento de cada linea
// Objetos y punteros // Objetos y punteros
std::shared_ptr<Texture> sinceTexture; // Textura con los graficos "Since 1998" std::shared_ptr<Texture> since_texture_; // Textura con los graficos "Since 1998"
std::unique_ptr<Sprite> sinceSprite; // Sprite para manejar la sinceTexture std::unique_ptr<Sprite> since_sprite_; // Sprite para manejar la sinceTexture
std::shared_ptr<Texture> jailTexture; // Textura con los graficos "JAILGAMES" std::shared_ptr<Texture> jail_texture_; // Textura con los graficos "JAILGAMES"
std::vector<std::unique_ptr<Sprite>> jailSprite; // Vector con los sprites de cada linea que forman el bitmap JAILGAMES std::vector<std::unique_ptr<Sprite>> jail_sprite_; // Vector con los sprites de cada linea que forman el bitmap JAILGAMES
// Variables // Variables
std::vector<Color> color; // Vector con los colores para el fade std::vector<Color> color_; // Vector con los colores para el fade
int counter; // Contador int counter_; // Contador
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa SDL_Point dest_; // Posición X donde dibujar el logo
int showSinceSprite_cm; // Tiempo del contador en el que empieza a verse el sprite de "SINCE 1998"
int initFade_cm; // Tiempo del contador cuando inicia el fade a negro
int endLogo_cm; // Tiempo del contador para terminar el logo
int postLogoDuration; // Tiempo que dura el logo con el fade al maximo
int speed; // Velocidad de desplazamiento de cada linea
SDL_Point dest; // Posición X donde dibujar el logo
// Actualiza las variables // Actualiza las variables
void update(); void update();
@@ -65,7 +65,7 @@ public:
Logo(); Logo();
// Destructor // Destructor
~Logo() = default; ~Logo();
// Bucle principal // Bucle principal
void run(); void run();

View File

@@ -7,25 +7,14 @@ Actualizando a la versión "Arcade Edition" en 08/05/2024
*/ */
#include <iostream> // for basic_ostream, char_traits, operator<<, cout #include <memory> // Para make_unique, unique_ptr
#include <string> // for basic_string, operator<<, string #include "director.h" // Para Director
#include "director.h" // for Director
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
std::cout << "Game start" << std::endl; // Crea el objeto Director
auto director = std::make_unique<Director>(argc, const_cast<const char **>(argv));
// Crea el objeto Director // Bucle principal
Director *director = new Director(argc, argv); return director->run();
// Bucle principal
const auto exit = director->run();
// Destruye el objeto Director
delete director;
const auto endType = exit == 0 ? "keyboard" : "controller";
std::cout << "\nGame end with " << endType << std::endl;
return exit;
} }

View File

@@ -1,48 +1,40 @@
#include "manage_hiscore_table.h" #include "manage_hiscore_table.h"
#include <SDL2/SDL_error.h> // for SDL_GetError #include <SDL2/SDL_error.h> // Para SDL_GetError
#include <SDL2/SDL_rwops.h> // for SDL_RWread, SDL_RWwrite, SDL_RWFromFile #include <SDL2/SDL_rwops.h> // Para SDL_RWread, SDL_RWwrite, SDL_RWFromFile
#include <stdlib.h> // for free, malloc #include <algorithm> // Para sort
#include <algorithm> // for sort #include <iostream> // Para basic_ostream, operator<<, cout, endl
#include <iostream> // for basic_ostream, char_traits, operator<< #include "utils.h" // Para HiScoreEntry, getFileName
#include "utils.h" // for HiScoreEntry
// Constructor
ManageHiScoreTable::ManageHiScoreTable(std::vector<HiScoreEntry> *table)
: table(table) {}
// Resetea la tabla a los valores por defecto // Resetea la tabla a los valores por defecto
void ManageHiScoreTable::clear() void ManageHiScoreTable::clear()
{ {
// Limpia la tabla // Limpia la tabla
table->clear(); table_.clear();
// Añade 10 entradas predefinidas // Añade 10 entradas predefinidas
table->push_back({"Bry", 1000000}); table_.push_back(HiScoreEntry("Bry", 1000000));
table->push_back({"Usufondo", 500000}); table_.push_back(HiScoreEntry("Usufondo", 500000));
table->push_back({"G.Lucas", 100000}); table_.push_back(HiScoreEntry("G.Lucas", 100000));
table->push_back({"P.Delgat", 50000}); table_.push_back(HiScoreEntry("P.Delgat", 50000));
table->push_back({"P.Arrabalera", 10000}); table_.push_back(HiScoreEntry("P.Arrabalera", 10000));
table->push_back({"Pelechano", 5000}); table_.push_back(HiScoreEntry("Pelechano", 5000));
table->push_back({"Sahuquillo", 1000}); table_.push_back(HiScoreEntry("Sahuquillo", 1000));
table->push_back({"Bacteriol", 500}); table_.push_back(HiScoreEntry("Bacteriol", 500));
table->push_back({"Pepe", 200}); table_.push_back(HiScoreEntry("Pepe", 200));
table->push_back({"Rosita", 100}); table_.push_back(HiScoreEntry("Rosita", 100));
} }
// Añade un elemento a la tabla // Añade un elemento a la tabla
void ManageHiScoreTable::add(HiScoreEntry entry) void ManageHiScoreTable::add(HiScoreEntry entry)
{ {
// Añade la entrada a la tabla // Añade la entrada a la tabla
table->push_back(entry); table_.push_back(entry);
// Ordena la tabla // Ordena la tabla
sort(); sort();
// Deja solo las 10 primeras entradas // Deja solo las 10 primeras entradas
if ((int)table->size() > 10) table_.resize(10);
{
table->resize(10);
}
} }
// Ordena la tabla // Ordena la tabla
@@ -50,31 +42,28 @@ void ManageHiScoreTable::sort()
{ {
struct struct
{ {
bool operator()(HiScoreEntry a, HiScoreEntry b) const { return a.score > b.score; } bool operator()(const HiScoreEntry &a, const HiScoreEntry &b) const { return a.score > b.score; }
} customLess; } scoreDescendingComparator;
std::sort(table->begin(), table->end(), customLess); std::sort(table_.begin(), table_.end(), scoreDescendingComparator);
} }
// Carga la tabla con los datos de un fichero // Carga la tabla con los datos de un fichero
bool ManageHiScoreTable::loadFromFile(std::string filePath) bool ManageHiScoreTable::loadFromFile(const std::string &file_path)
{ {
clear(); clear();
auto success = true;
bool success = true; auto file = SDL_RWFromFile(file_path.c_str(), "r+b");
const std::string filename = filePath.substr(filePath.find_last_of("\\/") + 1);
SDL_RWops *file = SDL_RWFromFile(filePath.c_str(), "r+b");
if (file) if (file)
{ {
#ifdef DEBUG std::cout << "Reading file: " << getFileName(file_path) << std::endl;
std::cout << "Reading file: " << filename.c_str() << std::endl;
#endif for (auto &entry : table_)
for (int i = 0; i < (int)table->size(); ++i)
{ {
int nameSize = 0; int nameSize = 0;
if (SDL_RWread(file, &table->at(i).score, sizeof(int), 1) == 0) if (SDL_RWread(file, &entry.score, sizeof(int), 1) == 0)
{ {
success = false; success = false;
break; break;
@@ -86,19 +75,15 @@ bool ManageHiScoreTable::loadFromFile(std::string filePath)
break; break;
} }
char *name = (char *)malloc(nameSize + 1); std::vector<char> nameBuffer(nameSize + 1);
if (SDL_RWread(file, name, sizeof(char) * nameSize, 1) == 0) if (SDL_RWread(file, nameBuffer.data(), sizeof(char) * nameSize, 1) == 0)
{ {
success = false; success = false;
free(name);
break; break;
} }
else
{ nameBuffer[nameSize] = '\0';
name[nameSize] = 0; entry.name = std::string(nameBuffer.data());
table->at(i).name = name;
free(name);
}
} }
SDL_RWclose(file); SDL_RWclose(file);
@@ -113,34 +98,28 @@ bool ManageHiScoreTable::loadFromFile(std::string filePath)
} }
// Guarda la tabla en un fichero // Guarda la tabla en un fichero
bool ManageHiScoreTable::saveToFile(std::string filePath) bool ManageHiScoreTable::saveToFile(const std::string &file_path)
{ {
bool success = true; auto success = true;
const std::string fileName = filePath.substr(filePath.find_last_of("\\/") + 1); auto file = SDL_RWFromFile(file_path.c_str(), "w+b");
SDL_RWops *file = SDL_RWFromFile(filePath.c_str(), "w+b");
if (file) if (file)
{ {
// Guarda los datos // Guarda los datos
for (int i = 0; i < (int)table->size(); ++i) for (int i = 0; i < (int)table_.size(); ++i)
{ {
SDL_RWwrite(file, &table->at(i).score, sizeof(int), 1); SDL_RWwrite(file, &table_.at(i).score, sizeof(int), 1);
const int nameSize = (int)table->at(i).name.size(); const int nameSize = (int)table_.at(i).name.size();
SDL_RWwrite(file, &nameSize, sizeof(int), 1); SDL_RWwrite(file, &nameSize, sizeof(int), 1);
SDL_RWwrite(file, table->at(i).name.c_str(), nameSize, 1); SDL_RWwrite(file, table_.at(i).name.c_str(), nameSize, 1);
} }
#ifdef DEBUG std::cout << "Writing file: " << getFileName(file_path).c_str() << std::endl;
std::cout << "Writing file: " << fileName.c_str() << std::endl;
#endif
// Cierra el fichero
SDL_RWclose(file); SDL_RWclose(file);
} }
else else
{ {
#ifdef DEBUG std::cout << "Error: Unable to save " << getFileName(file_path).c_str() << " file! " << SDL_GetError() << std::endl;
std::cout << "Error: Unable to save " << fileName.c_str() << " file! " << SDL_GetError() << std::endl;
#endif
} }
return success; return success;
} }

View File

@@ -1,8 +1,7 @@
#pragma once #pragma once
#include <string> // for string #include <string> // para string
#include <vector> // for vector #include <vector> // para vector
struct HiScoreEntry;
/* /*
Esta clase sirve para añadir elementos hiScoreEntry_r a un vector (tabla), de manera Esta clase sirve para añadir elementos hiScoreEntry_r a un vector (tabla), de manera
@@ -12,19 +11,31 @@ struct HiScoreEntry;
leer y escribir la tabla a un fichero leer y escribir la tabla a un fichero
*/ */
// Estructura para las entradas de la tabla de recirds
struct HiScoreEntry
{
std::string name; // Nombre
int score; // Puntuación
// Constructor
explicit HiScoreEntry(const std::string &n = "", int s = 0)
: name(n), score(s) {}
};
// Clase ManageHiScoreTable // Clase ManageHiScoreTable
class ManageHiScoreTable class ManageHiScoreTable
{ {
private: private:
// Variables // Variables
std::vector<HiScoreEntry> *table; // Tabla con los records std::vector<HiScoreEntry> &table_; // Tabla con los records
// Ordena la tabla // Ordena la tabla
void sort(); void sort();
public: public:
// Constructor // Constructor
ManageHiScoreTable(std::vector<HiScoreEntry> *table); explicit ManageHiScoreTable(std::vector<HiScoreEntry> &table)
: table_(table) {}
// Destructor // Destructor
~ManageHiScoreTable() = default; ~ManageHiScoreTable() = default;
@@ -36,8 +47,8 @@ public:
void add(HiScoreEntry entry); void add(HiScoreEntry entry);
// Carga la tabla con los datos de un fichero // Carga la tabla con los datos de un fichero
bool loadFromFile(std::string filePath); bool loadFromFile(const std::string &file_path);
// Guarda la tabla en un fichero // Guarda la tabla en un fichero
bool saveToFile(std::string filePath); bool saveToFile(const std::string &file_path);
}; };

View File

@@ -1,34 +1,34 @@
#include "moving_sprite.h" #include "moving_sprite.h"
#include "texture.h" // for Texture #include <algorithm> // Para max
#include "texture.h" // Para Texture
// Constructor // Constructor
MovingSprite::MovingSprite(float x, float y, int w, int h, float vx, float vy, float ax, float ay, std::shared_ptr<Texture> texture) MovingSprite::MovingSprite(std::shared_ptr<Texture> texture, SDL_Rect pos, Rotate rotate, float zoom_w, float zoom_h, SDL_RendererFlip flip)
: Sprite((int)x, (int)y, w, h, texture), x_(x), y_(y), vx_(vx), vy_(vy), ax_(ax), ay_(ay) : Sprite(texture, pos),
{ x_(pos.x),
// Establece el zoom W,H del sprite y_(pos.y),
zoomW_ = 1; rotate_(rotate),
zoomH_ = 1; zoom_w_(zoom_w),
zoom_h_(zoom_h),
flip_(flip) {}
// Establece el angulo con el que se dibujará MovingSprite::MovingSprite(std::shared_ptr<Texture> texture, SDL_Rect pos)
angle_ = (double)0; : Sprite(texture, pos),
x_(pos.x),
y_(pos.y),
rotate_(Rotate()),
zoom_w_(1.0f),
zoom_h_(1.0f),
flip_(SDL_FLIP_NONE) {}
// Establece los valores de rotacion MovingSprite::MovingSprite(std::shared_ptr<Texture> texture)
rotateEnabled_ = false; : Sprite(texture),
rotateSpeed_ = 0; x_(0.0f),
rotateAmount_ = (double)0; y_(0.0f),
rotate_(Rotate()),
// Contador interno zoom_w_(1.0f),
counter_ = 0; zoom_h_(1.0f),
flip_(SDL_FLIP_NONE) { Sprite::clear(); }
// Establece el rectangulo de donde coger la imagen
spriteClip_ = {0, 0, w_, h_};
// Establece el centro de rotación
center_ = nullptr;
// Establece el tipo de volteado
currentFlip_ = SDL_FLIP_NONE;
};
// Reinicia todas las variables // Reinicia todas las variables
void MovingSprite::clear() void MovingSprite::clear()
@@ -42,17 +42,14 @@ void MovingSprite::clear()
ax_ = 0.0f; // Aceleración en el eje X. Variación de la velocidad ax_ = 0.0f; // Aceleración en el eje X. Variación de la velocidad
ay_ = 0.0f; // Aceleración en el eje Y. Variación de la velocidad ay_ = 0.0f; // Aceleración en el eje Y. Variación de la velocidad
zoomW_ = 1.0f; // Zoom aplicado a la anchura rotate_ = Rotate(); // Inicializa la estructura
zoomH_ = 1.0f; // Zoom aplicado a la altura
angle_ = 0.0; // Angulo para dibujarlo zoom_w_ = 1.0f; // Zoom aplicado a la anchura
rotateEnabled_ = false; // Indica si ha de rotar zoom_h_ = 1.0f; // Zoom aplicado a la altura
center_ = nullptr; // Centro de rotación
rotateSpeed_ = 0; // Velocidad de giro
rotateAmount_ = 0.0; // Cantidad de grados a girar en cada iteración
counter_ = 0; // Contador interno
currentFlip_ = SDL_FLIP_NONE; // Establece como se ha de voltear el sprite flip_ = SDL_FLIP_NONE; // Establece como se ha de voltear el sprite
Sprite::clear();
} }
// Mueve el sprite // Mueve el sprite
@@ -63,17 +60,118 @@ void MovingSprite::move()
vx_ += ax_; vx_ += ax_;
vy_ += ay_; vy_ += ay_;
pos_.x = static_cast<int>(x_);
pos_.y = static_cast<int>(y_);
}
// Actualiza las variables internas del objeto
void MovingSprite::update()
{
move();
rotate();
} }
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void MovingSprite::render() void MovingSprite::render()
{ {
if (enabled_) texture_->render(pos_.x, pos_.y, &sprite_clip_, zoom_w_, zoom_h_, rotate_.angle, rotate_.center, flip_);
}
// Establece el valor de la variable
void MovingSprite::setZoomW(float value)
{
zoom_w_ = value;
}
// Establece el valor de la variable
void MovingSprite::setZoomH(float value)
{
zoom_h_ = value;
}
// Establece el valor de la variable
void MovingSprite::setAngle(double value)
{
rotate_.angle = value;
}
// Incrementa el valor del ángulo
void MovingSprite::updateAngle()
{
rotate_.angle += rotate_.amount;
}
// Obtiene el valor de la variable
bool MovingSprite::isRotating() const
{
return rotate_.enabled;
}
// Establece la rotacion
void MovingSprite::rotate()
{
if (rotate_.enabled)
{ {
texture_->render((int)x_, (int)y_, &spriteClip_, zoomW_, zoomH_, angle_, center_, currentFlip_); ++rotate_.counter;
if (rotate_.counter % rotate_.speed == 0)
{
updateAngle();
rotate_.counter = 0;
}
} }
} }
// Establece el valor de la variable
void MovingSprite::enableRotate()
{
rotate_.enabled = true;
rotate_.counter = 0;
}
// Establece el valor de la variable
void MovingSprite::disableRotate()
{
rotate_.enabled = false;
rotate_.counter = 0;
}
// Establece el valor de la variable
void MovingSprite::setRotateSpeed(int value)
{
rotate_.speed = std::max(1, value);
}
// Establece el valor de la variable
void MovingSprite::setRotateAmount(double value)
{
rotate_.amount = value;
}
// Cambia el sentido de la rotación
void MovingSprite::switchRotate()
{
rotate_.amount *= -1;
}
// Establece el valor de la variable
void MovingSprite::setFlip(SDL_RendererFlip flip)
{
flip_ = flip;
}
// Gira el sprite horizontalmente
void MovingSprite::flip()
{
flip_ = (flip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL;
}
// Obtiene el valor de la variable
SDL_RendererFlip MovingSprite::getFlip()
{
return flip_;
}
// Obtiene el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getPosX() const float MovingSprite::getPosX() const
{ {
@@ -110,31 +208,13 @@ float MovingSprite::getAccelY() const
return ay_; return ay_;
} }
// Obtiene el valor de la variable
float MovingSprite::getZoomW() const
{
return zoomW_;
}
// Obtiene el valor de la variable
float MovingSprite::getZoomH() const
{
return zoomH_;
}
// Obtiene el valor de la variable
double MovingSprite::getAngle() const
{
return angle_;
}
// Establece la posición y_ el tamaño del objeto // Establece la posición y_ el tamaño del objeto
void MovingSprite::setRect(SDL_Rect rect) void MovingSprite::setPos(SDL_Rect rect)
{ {
x_ = (float)rect.x; x_ = static_cast<float>(rect.x);
y_ = (float)rect.y; y_ = static_cast<float>(rect.y);
w_ = rect.w;
h_ = rect.h; pos_ = rect;
} }
// Establece el valor de las variables // Establece el valor de las variables
@@ -142,18 +222,23 @@ void MovingSprite::setPos(float x, float y)
{ {
x_ = x; x_ = x;
y_ = y; y_ = y;
pos_.x = static_cast<int>(x_);
pos_.y = static_cast<int>(y_);
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setPosX(float value) void MovingSprite::setPosX(float value)
{ {
x_ = value; x_ = value;
pos_.x = static_cast<int>(x_);
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setPosY(float value) void MovingSprite::setPosY(float value)
{ {
y_ = value; y_ = value;
pos_.y = static_cast<int>(y_);
} }
// Establece el valor de la variable // Establece el valor de la variable
@@ -179,123 +264,3 @@ void MovingSprite::setAccelY(float value)
{ {
ay_ = value; ay_ = value;
} }
// Establece el valor de la variable
void MovingSprite::setZoomW(float value)
{
zoomW_ = value;
}
// Establece el valor de la variable
void MovingSprite::setZoomH(float value)
{
zoomH_ = value;
}
// Establece el valor de la variable
void MovingSprite::setAngle(double value)
{
angle_ = value;
}
// Incrementa el valor de la variable
void MovingSprite::incAngle(double value)
{
angle_ += value;
}
// Decrementa el valor de la variable
void MovingSprite::decAngle(double value)
{
angle_ -= value;
}
// Obtiene el valor de la variable
bool MovingSprite::getRotate() const
{
return rotateEnabled_;
}
// Obtiene el valor de la variable
Uint16 MovingSprite::getRotateSpeed() const
{
return rotateSpeed_;
}
// Establece la rotacion
void MovingSprite::rotate()
{
if (rotateEnabled_)
{
if (counter_ % rotateSpeed_ == 0)
{
incAngle(rotateAmount_);
}
}
}
// Establece el valor de la variable
void MovingSprite::setRotate(bool value)
{
rotateEnabled_ = value;
}
// Establece el valor de la variable
void MovingSprite::setRotateSpeed(int value)
{
rotateSpeed_ = (value < 1) ? 1 : value;
}
// Establece el valor de la variable
void MovingSprite::setRotateAmount(double value)
{
rotateAmount_ = value;
}
// Establece el valor de la variable
void MovingSprite::disableRotate()
{
rotateEnabled_ = false;
angle_ = (double)0;
}
// Actualiza las variables internas del objeto
void MovingSprite::update()
{
if (enabled_)
{
move();
rotate();
++counter_ %= 60000;
}
}
// Cambia el sentido de la rotación
void MovingSprite::switchRotate()
{
rotateAmount_ *= -1;
}
// Establece el valor de la variable
void MovingSprite::setFlip(SDL_RendererFlip flip)
{
currentFlip_ = flip;
}
// Gira el sprite horizontalmente
void MovingSprite::flip()
{
currentFlip_ = (currentFlip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL;
}
// Obtiene el valor de la variable
SDL_RendererFlip MovingSprite::getFlip()
{
return currentFlip_;
}
// Devuelve el rectangulo donde está el sprite
SDL_Rect MovingSprite::getRect()
{
return (SDL_Rect){(int)x_, (int)y_, w_, h_};
}

View File

@@ -1,39 +1,44 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point #include <SDL2/SDL_rect.h> // Para SDL_Rect, SDL_Point
#include <SDL2/SDL_render.h> // for SDL_RendererFlip #include <SDL2/SDL_render.h> // Para SDL_RendererFlip
#include <SDL2/SDL_stdinc.h> // for Uint16 #include <memory> // Para shared_ptr
#include <memory> #include "sprite.h" // Para Sprite
#include "sprite.h" // for Sprite class Texture; // lines 8-8
#include "texture.h"
// Clase MovingSprite. Añade posicion y velocidad en punto flotante // Clase MovingSprite. Añade movimiento y efectos de rotación, zoom y flip al sprite
class MovingSprite : public Sprite class MovingSprite : public Sprite
{ {
public:
struct Rotate
{
bool enabled; // Indica si ha de rotar
int counter; // Contador
int speed; // Velocidad de giro
double angle; // Angulo para dibujarlo
float amount; // Cantidad de grados a girar en cada iteración
SDL_Point *center; // Centro de rotación
Rotate() : enabled(false), counter(0), speed(0), angle(0.0), amount(0.0f), center(nullptr) {}
};
protected: protected:
float x_; // Posición en el eje X float x_; // Posición en el eje X
float y_; // Posición en el eje Y float y_; // Posición en el eje Y
float vx_; // Velocidad en el eje X. Cantidad de pixeles a desplazarse float vx_ = 0.0f; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
float vy_; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse float vy_ = 0.0f; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
float ax_; // Aceleración en el eje X. Variación de la velocidad float ax_ = 0.0f; // Aceleración en el eje X. Variación de la velocidad
float ay_; // Aceleración en el eje Y. Variación de la velocidad float ay_ = 0.0f; // Aceleración en el eje Y. Variación de la velocidad
float zoomW_; // Zoom aplicado a la anchura Rotate rotate_; // Variables usada para controlar la rotación del sprite
float zoomH_; // Zoom aplicado a la altura float zoom_w_; // Zoom aplicado a la anchura
float zoom_h_; // Zoom aplicado a la altura
SDL_RendererFlip flip_; // Indica como se voltea el sprite
double angle_; // Angulo para dibujarlo // Incrementa el valor del ángulo
bool rotateEnabled_; // Indica si ha de rotar void updateAngle();
int rotateSpeed_; // Velocidad de giro
double rotateAmount_; // Cantidad de grados a girar en cada iteración
int counter_; // Contador interno
SDL_Point *center_; // Centro de rotación
SDL_RendererFlip currentFlip_; // Indica como se voltea el sprite
public:
// Constructor
MovingSprite(float x = 0, float y = 0, int w = 0, int h = 0, float velx = 0, float vely = 0, float accelx = 0, float accely = 0, std::shared_ptr<Texture> texture = nullptr);
// Mueve el sprite // Mueve el sprite
void move(); void move();
@@ -41,71 +46,56 @@ public:
// Rota el sprite // Rota el sprite
void rotate(); void rotate();
// Actualiza las variables internas del objeto public:
void update(); // Constructor
MovingSprite(std::shared_ptr<Texture> texture, SDL_Rect pos, MovingSprite::Rotate rotate, float zoom_w, float zoom_h, SDL_RendererFlip flip);
MovingSprite(std::shared_ptr<Texture> texture, SDL_Rect pos);
explicit MovingSprite(std::shared_ptr<Texture> texture);
// Reinicia todas las variables // Destructor
void clear(); virtual ~MovingSprite() = default;
// Actualiza las variables internas del objeto
virtual void update();
// Reinicia todas las variables a cero
void clear() override;
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void render(); void render() override;
// Obten el valor de la variable // Obtiene la variable
float getPosX() const; float getPosX() const;
float getPosY() const; float getPosY() const;
// Obten el valor de la variable
float getVelX() const; float getVelX() const;
float getVelY() const; float getVelY() const;
// Obten el valor de la variable
float getAccelX() const; float getAccelX() const;
float getAccelY() const; float getAccelY() const;
// Obten el valor de la variable // Establece la variable
float getZoomW() const;
float getZoomH() const;
// Obten el valor de la variable
double getAngle() const;
bool getRotate() const;
Uint16 getRotateSpeed() const;
// Establece la posición y el tamaño del objeto
void setRect(SDL_Rect rect);
// Establece el valor de las variables
void setPos(float x, float y);
// Establece el valor de la variable
void setPosX(float value);
void setPosY(float value);
// Establece el valor de la variable
void setVelX(float value); void setVelX(float value);
void setVelY(float value); void setVelY(float value);
// Establece el valor de la variable
void setAccelX(float value); void setAccelX(float value);
void setAccelY(float value); void setAccelY(float value);
// Obten el valor de la variable
bool isRotating() const;
// Establece el valor de la variable // Establece el valor de la variable
void setZoomW(float value); void setZoomW(float value);
void setZoomH(float value); void setZoomH(float value);
// Establece el valor de la variable // Establece el valor de la variable
void setAngle(double vaue); void setAngle(double vaue);
void incAngle(double value);
void decAngle(double value); // Activa o desactiva el efecto derotación
void enableRotate();
void disableRotate();
// Establece el valor de la variable // Establece el valor de la variable
void setRotate(bool value);
void setRotateSpeed(int value); void setRotateSpeed(int value);
void setRotateAmount(double value); void setRotateAmount(double value);
// Quita el efecto de rotación y deja el sprite en su angulo inicial.
void disableRotate();
// Cambia el sentido de la rotación // Cambia el sentido de la rotación
void switchRotate(); void switchRotate();
@@ -118,6 +108,15 @@ public:
// Obtiene el valor de la variable // Obtiene el valor de la variable
SDL_RendererFlip getFlip(); SDL_RendererFlip getFlip();
// Devuelve el rectangulo donde está el sprite // Establece la posición y_ el tamaño del objeto
SDL_Rect getRect(); void setPos(SDL_Rect rect);
// Establece el valor de las variables
void setPos(float x, float y);
// Establece el valor de la variable
void setPosX(float value);
// Establece el valor de la variable
void setPosY(float value);
}; };

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