Compare commits

62 Commits

Author SHA1 Message Date
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
117b80bdfc idem 2024-10-10 20:59:39 +02:00
d6c3c89872 Estandaritzant noms segons convencions 2024-10-10 20:27:31 +02:00
9e5f41644e Açò ja no hi ha Cristo que ho pete 2024-10-10 13:48:53 +02:00
fc8fdc5fe5 Llevats uns punterets que sobraven en director.cpp 2024-10-10 09:23:16 +02:00
6fe294c59d Pos ja compila pero no es veu una puta merda ... 2024-10-10 08:06:36 +02:00
3fa5b227ae commit de anar a dormir 2024-10-09 23:01:44 +02:00
f2fa216b0d Commit pa que Mon arregle el codi mentre em dutxe 2024-10-09 21:48:01 +02:00
3c1dcad3ab Commit de anar al llit amb el portatil 2024-10-08 23:15:55 +02:00
bd3aa0bb06 Arreglos varios al codi 2024-10-08 22:38:58 +02:00
3e3d764b25 Commitet pa gastar el Cppcheck 2024-10-08 20:32:24 +02:00
c00f4326ae Commit de "guardar partida" 2024-10-08 18:07:54 +02:00
9ce0f16d33 Arreglats els constructors de Text 2024-10-08 18:07:44 +02:00
06a4f439c1 Posant make_uniques, s'ha quedat tot enmerdat per culpa d'un struct 2024-10-08 13:53:24 +02:00
9d41d14d68 Actualitzats els scripts de valgrind 2024-10-07 20:11:08 +02:00
0d0e49316f Afegit scripts a linux-utils 2024-10-07 18:44:18 +02:00
bf945ef14b Corregits 8.000.000 de segmentation faults en intro.cpp 2024-10-07 18:37:08 +02:00
0330fe6b74 Make uniques en intro.cpp 2024-10-07 17:28:34 +02:00
6305a67c84 Actualitzat .gitignore 2024-10-07 17:28:22 +02:00
5f18189269 Actualizado Makefile 2024-10-07 12:32:53 +02:00
7ebefd7b54 Les enum class passen a estar totes amb la inicial en majuscula 2024-10-07 12:30:46 +02:00
cffa4c3c92 Commitet pa valgrind, he aprofitat i posat mes make_unique i enum class 2024-10-07 10:49:29 +02:00
4f0ea9dcf2 Make_unique en title.cpp 2024-10-07 08:22:51 +02:00
b1f936a791 Pasaeta de include-what-you-use abans que es desmadre tot 2024-10-06 22:43:28 +02:00
1c0554d4df Actualitzat script check-includes.sh 2024-10-06 22:43:00 +02:00
8ba77d7d5d Demanada ajuda a la IA pa que m'arregle un poc la meua merda: Para optimizar este código y evitar duplicar la lógica para cada jugador, podemos extraer el código común en una función reutilizable. Así, reducimos la repetición y mejoramos la legibilidad. 2024-10-06 21:07:26 +02:00
6515ec6c7b Els panels dels marcadors ja passen a game over sense pasar per waiting un frame gracies a una parafernalia que he montat 2024-10-06 21:02:49 +02:00
b979c0f2b8 Mes textos 2024-10-06 21:02:12 +02:00
a95e5077e3 Els panels del marcador ara canvien de mode a petició i no a cada frame 2024-10-06 20:19:43 +02:00
6ea6f85e3e Nous textos 2024-10-06 20:14:37 +02:00
fe6e63e39f fix: la classe Screen ja ha recuperat un poc del lustro que tenia
shake effect ja no està fet "the torerous menner"
shake effect ja va amb shaders
2024-10-06 18:57:47 +02:00
afe092c742 Muntat a c++14 per a make_unique
Mes autos, const i constexpr perl codi
Ara la classe Screen es un poc pitjor
2024-10-06 14:58:00 +02:00
25a2753b13 Canviats defines per constexpr i enum class
Canviats punters a unique_ptr
Afegit const a alguns metodes de classse
fix: el segon jugador no podia unirse a la partida
new: Quan els dos jugadors han decidit no continuar, ja no poden continuar i el marcador així ho reflectix
fix: al posar el nom per segona vegada en la mateixa partida, no es reseteja la posició del selector
fix: el fade venetian no netejava la textura i de vegades eixien gràfics corruptes
fix: ara grava a disco cada vegada que es posa nom al morir
2024-10-05 23:53:42 +02:00
ee721ff573 debug 2024-10-03 19:35:58 +02:00
c07fd62037 Corregit bug en el text a l'hora d'intercanviar els mandos. Apareixia el nom del mando que te guardat a la configuració pero no estava connectat 2024-10-03 19:26:32 +02:00
fb74733f2c Correcció de textos 2024-10-03 18:16:20 +02:00
468bd0950c Modificat controllers.png 2024-10-03 18:13:48 +02:00
938e4ad011 La targeta d'ajuda ja ix amb els mandos i s'ha de deixar apretat el botó 2024-10-03 17:37:33 +02:00
71bd3bed52 Eliminades variables sobrants en director.cpp 2024-10-03 17:02:40 +02:00
5ebc58dd01 La tarjeta d'ajuda ja entra i ix amb animacions suavitzades 2024-10-02 18:03:20 +02:00
9b3e549876 Añadidas funciones de suavizado a utils.cpp 2024-10-02 18:00:21 +02:00
abc8a0b632 La tarjeta d'ajuda ix pero no s'amaga 2024-10-02 13:56:43 +02:00
111 changed files with 7886 additions and 8626 deletions

2
.gitignore vendored
View File

@@ -14,3 +14,5 @@ thumbs.db
*config.bin *config.bin
*score.bin *score.bin
coffee_crisis* coffee_crisis*
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++11 -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++11 -Wall 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++11 -Wall -Os -ffunction-sections -fdata-sections CXXFLAGS:= -std=c++20 -Wall -Os -ffunction-sections -fdata-sections
CXXFLAGS_DEBUG:= -std=c++11 -Wall 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,19 +1,19 @@
## GAME ## GAME
game.itemSize 20 game.item_size 20
game.width 320 game.width 320
game.height 240 game.height 240
game.playArea.rect.x 0 game.play_area.rect.x 0
game.playArea.rect.y 0 game.play_area.rect.y 0
game.playArea.rect.w 320 game.play_area.rect.w 320
game.playArea.rect.h 200 game.play_area.rect.h 200
## FADE ## FADE
fade.numSquaresWidth 160 fade.num_squares_width 160
fade.numSquaresHeight 120 fade.num_squares_height 120
fade.randomSquaresDelay 1 fade.random_squares_delay 1
fade.randomSquaresMult 500 fade.random_squares_mult 500
fade.postDuration 80 fade.post_duration 80
fade.venetianSize 16 fade.venetian_size 16
## SCOREBOARD ## SCOREBOARD
scoreboard.x 0 scoreboard.x 0
@@ -22,23 +22,31 @@ scoreboard.w 320
scoreboard.h 40 scoreboard.h 40
## TITLE ## TITLE
title.pressStartPosition 170 title.press_start_position 170
title.titleDuration 800 title.title_duration 800
title.arcadeEditionPosition 123 title.arcade_edition_position 123
title.titleCCPosition 80 title.title_c_c_position 80
## BACKGROUND ## BACKGROUND
background.attenuateColor.r 255 background.attenuate_color.r 255
background.attenuateColor.g 255 background.attenuate_color.g 255
background.attenuateColor.b 255 background.attenuate_color.b 255
background.attenuateAlpha 0 background.attenuate_alpha 0
## BALLOONS ## BALLOONS
balloon1.vel 2.75f balloon_1.vel 2.75f
balloon1.grav 0.09f balloon_1.grav 0.09f
balloon2.vel 3.70f balloon_2.vel 3.70f
balloon2.grav 0.10f balloon_2.grav 0.10f
balloon3.vel 4.70f balloon_3.vel 4.70f
balloon3.grav 0.10f balloon_3.grav 0.10f
balloon4.vel 5.45f balloon_4.vel 5.45f
balloon4.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,19 +1,19 @@
## GAME ## GAME
game.itemSize 20 game.item_size 20
game.width 320 game.width 320
game.height 256 game.height 256
game.playArea.rect.x 0 game.play_area.rect.x 0
game.playArea.rect.y 0 game.play_area.rect.y 0
game.playArea.rect.w 320 game.play_area.rect.w 320
game.playArea.rect.h 216 game.play_area.rect.h 216
## FADE ## FADE
fade.numSquaresWidth 160 fade.num_squares_width 160
fade.numSquaresHeight 128 fade.num_squares_height 128
fade.randomSquaresDelay 1 fade.random_squares_delay 1
fade.randomSquaresMult 500 fade.random_squares_mult 500
fade.postDuration 80 fade.post_duration 80
fade.venetianSize 16 fade.venetian_size 16
## SCOREBOARD ## SCOREBOARD
scoreboard.x 0 scoreboard.x 0
@@ -22,23 +22,31 @@ scoreboard.w 320
scoreboard.h 40 scoreboard.h 40
## TITLE ## TITLE
title.pressStartPosition 180 title.press_start_position 180
title.titleDuration 800 title.title_duration 800
title.arcadeEditionPosition 123 title.arcade_edition_position 123
title.titleCCPosition 80 title.title_c_c_position 80
## BACKGROUND ## BACKGROUND
background.attenuateColor.r 255 background.attenuate_color.r 255
background.attenuateColor.g 255 background.attenuate_color.g 255
background.attenuateColor.b 255 background.attenuate_color.b 255
background.attenuateAlpha 0 background.attenuate_alpha 0
## BALLOONS ## BALLOONS
balloon1.vel 2.75f balloon_1.vel 2.75f
balloon1.grav 0.09f balloon_1.grav 0.09f
balloon2.vel 3.70f balloon_2.vel 3.70f
balloon2.grav 0.10f balloon_2.grav 0.10f
balloon3.vel 4.70f balloon_3.vel 4.70f
balloon3.grav 0.10f balloon_3.grav 0.10f
balloon4.vel 5.45f balloon_4.vel 5.45f
balloon4.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,5 +1,5 @@
frameWidth=10 frame_width=10
frameHeight=10 frame_height=10
[animation] [animation]
name=orange name=orange

View File

@@ -1,5 +1,5 @@
frameWidth=16 frame_width=16
frameHeight=16 frame_height=16
[animation] [animation]
name=orange name=orange

View File

@@ -1,5 +1,5 @@
frameWidth=26 frame_width=26
frameHeight=26 frame_height=26
[animation] [animation]
name=orange name=orange

View File

@@ -1,5 +1,5 @@
frameWidth=48 frame_width=48
frameHeight=48 frame_height=48
[animation] [animation]
name=orange name=orange

View File

@@ -1,5 +1,5 @@
frameWidth=10 frame_width=10
frameHeight=10 frame_height=10
[animation] [animation]
name=default name=default

View File

@@ -1,5 +1,5 @@
frameWidth=16 frame_width=16
frameHeight=16 frame_height=16
[animation] [animation]
name=default name=default

View File

@@ -1,5 +1,5 @@
frameWidth=26 frame_width=26
frameHeight=26 frame_height=26
[animation] [animation]
name=default name=default

View File

@@ -1,5 +1,5 @@
frameWidth=46 frame_width=46
frameHeight=46 frame_height=46
[animation] [animation]
name=default name=default

View File

@@ -1,5 +1,5 @@
frameWidth=46 frame_width=46
frameHeight=46 frame_height=46
[animation] [animation]
name=powerball name=powerball

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 799 B

View File

@@ -1,5 +1,5 @@
frameWidth=20 frame_width=20
frameHeight=20 frame_height=20
[animation] [animation]
name=default name=default

View File

@@ -1,5 +1,5 @@
frameWidth=20 frame_width=20
frameHeight=20 frame_height=20
[animation] [animation]
name=default name=default

View File

@@ -1,5 +1,5 @@
frameWidth=28 frame_width=28
frameHeight=37 frame_height=37
[animation] [animation]
name=default name=default

View File

@@ -1,5 +1,5 @@
frameWidth=20 frame_width=20
frameHeight=20 frame_height=20
[animation] [animation]
name=default name=default

View File

@@ -1,5 +1,5 @@
frameWidth=20 frame_width=20
frameHeight=20 frame_height=20
[animation] [animation]
name=default name=default

View File

@@ -1,5 +1,5 @@
frameWidth=20 frame_width=20
frameHeight=20 frame_height=20
[animation] [animation]
name=default name=default

View File

@@ -1,5 +1,5 @@
frameWidth=30 frame_width=30
frameHeight=30 frame_height=30
[animation] [animation]
name=walk name=walk

View File

@@ -1,5 +1,5 @@
frameWidth=39 frame_width=39
frameHeight=44 frame_height=44
[animation] [animation]
name=default name=default

View File

@@ -1,5 +1,5 @@
frameWidth=16 frame_width=16
frameHeight=16 frame_height=16
[animation] [animation]
name=default name=default

View File

@@ -320,22 +320,28 @@ Continuar?
Posa el nom Posa el nom
## 107 - AJUDA ## 107 - AJUDA
Canvia mandos Intercanviar mandos
## 108 - AJUDA ## 108 - AJUDA
Configuracio Configuracio
## 109 - AJUDA ## 109 - AJUDA
Des-activa el so Alternar el audio
## 110 - AJUDA ## 110 - AJUDA
Filtros Filtres
## 111 - AJUDA ## 111 - AJUDA
Reset Reiniciar
## 112 - AJUDA ## 112 - AJUDA
Pausa Pausar
## 113 - AJUDA ## 113 - AJUDA
Eixir Eixir
## 114 - MARCADOR
Per favor
## 115 - MARCADOR
espere

View File

@@ -323,10 +323,10 @@ Enter name
Swap Controllers Swap Controllers
## 108 - AJUDA ## 108 - AJUDA
Config Configuration
## 109 - AJUDA ## 109 - AJUDA
Un-mute audio Toggle audio
## 110 - AJUDA ## 110 - AJUDA
Shaders Shaders
@@ -339,3 +339,9 @@ Pause
## 113 - AJUDA ## 113 - AJUDA
Exit Exit
## 114 - MARCADOR
Please
## 115 - MARCADOR
wait

View File

@@ -320,22 +320,28 @@ Continuar?
Pon tu nombre Pon tu nombre
## 107 - AJUDA ## 107 - AJUDA
Intercambia mandos Intercambiar mandos
## 108 - AJUDA ## 108 - AJUDA
Configuracion Configuracion
## 109 - AJUDA ## 109 - AJUDA
Des-activa el sonido Alternar el audio
## 110 - AJUDA ## 110 - AJUDA
Filtros Filtros
## 111 - AJUDA ## 111 - AJUDA
Reset Reiniciar
## 112 - AJUDA ## 112 - AJUDA
Pausa Pausar
## 113 - AJUDA ## 113 - AJUDA
Salir Salir
## 114 - MARCADOR
Por favor
## 115 - MARCADOR
espere

View File

@@ -4,5 +4,7 @@ SOURCEPATH=../source/
for i in "$SOURCEPATH"/*.cpp for i in "$SOURCEPATH"/*.cpp
do do
include-what-you-use -D DEBUG -D VERBOSE -std=c++11 -Wall "$i" include-what-you-use -D DEBUG -D VERBOSE -std=c++20 -Wall "$i"
read -p "Presiona cualquier tecla para continuar..."
clear
done done

View File

@@ -0,0 +1,3 @@
#!/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

@@ -0,0 +1,12 @@
{
ignore_unversioned_libs
Memcheck:Leak
...
obj:*/lib*/lib*.so
}
{
ignore_versioned_libs
Memcheck:Leak
...
obj:*/lib*/lib*.so.*
}

View File

@@ -1,41 +1,48 @@
#include "animated_sprite.h" #include "animated_sprite.h"
#include <algorithm> // for copy
#include <fstream> // for basic_ostream, operator<<, basic_istream, basic... #include <fstream> // for basic_ostream, operator<<, basic_istream, basic...
#include <iostream> // for cout #include <iostream> // for cout
#include <iterator> // for back_insert_iterator, back_inserter
#include <sstream> // for basic_stringstream #include <sstream> // for basic_stringstream
#include "texture.h" // for Texture #include "texture.h" // for Texture
// Carga la animación desde un fichero // Carga la animación desde un fichero
animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, bool verbose) AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string file_path)
{ {
// Inicializa variables // Inicializa variables
animatedSprite_t as; AnimatedFile af;
as.texture = texture; af.texture = texture;
int framesPerRow = 0; auto frames_per_row = 0;
int frameWidth = 0; auto frame_width = 0;
int frameHeight = 0; auto frame_height = 0;
int maxTiles = 0; auto max_tiles = 0;
const std::string filename = filePath.substr(filePath.find_last_of("\\/") + 1); #ifdef VERBOSE
std::ifstream file(filePath); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
std::ifstream file(file_path);
std::string line; std::string line;
// El fichero se puede abrir // El fichero se puede abrir
if (file.good()) if (file.good())
{ {
// Procesa el fichero linea a linea // Procesa el fichero linea a linea
if (verbose) #ifdef VERBOSE
{ std::cout << "Animation loaded: " << file_name << std::endl;
std::cout << "Animation loaded: " << filename << std::endl; #endif
}
while (std::getline(file, line)) while (std::getline(file, line))
{ {
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación // Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]") if (line == "[animation]")
{ {
animation_t buffer; Animation buffer;
buffer.counter = 0; buffer.counter = 0;
buffer.currentFrame = 0; buffer.current_frame = 0;
buffer.completed = false; buffer.completed = false;
buffer.name.clear();
buffer.speed = 5;
buffer.loop = 0;
buffer.frames.clear();
do do
{ {
@@ -45,7 +52,7 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
int pos = line.find("="); int pos = line.find("=");
// Procesa las dos subcadenas // Procesa las dos subcadenas
if (pos != (int)line.npos) if (pos != static_cast<int>(line.npos))
{ {
if (line.substr(0, pos) == "name") if (line.substr(0, pos) == "name")
{ {
@@ -67,26 +74,28 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
// Se introducen los valores separados por comas en un vector // Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length())); std::stringstream ss(line.substr(pos + 1, line.length()));
std::string tmp; std::string tmp;
SDL_Rect rect = {0, 0, frameWidth, frameHeight}; SDL_Rect rect = {0, 0, frame_width, frame_height};
while (getline(ss, tmp, ',')) while (getline(ss, tmp, ','))
{ {
// Comprueba que el tile no sea mayor que el maximo indice permitido // Comprueba que el tile no sea mayor que el maximo indice permitido
const int numTile = std::stoi(tmp) > maxTiles ? 0 : std::stoi(tmp); const auto num_tile = std::stoi(tmp) > max_tiles ? 0 : std::stoi(tmp);
rect.x = (numTile % framesPerRow) * frameWidth; rect.x = (num_tile % frames_per_row) * frame_width;
rect.y = (numTile / framesPerRow) * frameHeight; rect.y = (num_tile / frames_per_row) * frame_height;
buffer.frames.push_back(rect); buffer.frames.push_back(rect);
} }
} }
else else
{ {
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl; #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]"); } while (line != "[/animation]");
// Añade la animación al vector de animaciones // Añade la animación al vector de animaciones
as.animations.push_back(buffer); af.animations.push_back(buffer);
} }
// En caso contrario se parsea el fichero para buscar las variables y los valores // En caso contrario se parsea el fichero para buscar las variables y los valores
@@ -98,37 +107,39 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
// Procesa las dos subcadenas // Procesa las dos subcadenas
if (pos != (int)line.npos) if (pos != (int)line.npos)
{ {
if (line.substr(0, pos) == "framesPerRow") if (line.substr(0, pos) == "frames_per_row")
{ {
framesPerRow = std::stoi(line.substr(pos + 1, line.length())); frames_per_row = std::stoi(line.substr(pos + 1, line.length()));
} }
else if (line.substr(0, pos) == "frameWidth") else if (line.substr(0, pos) == "frame_width")
{ {
frameWidth = std::stoi(line.substr(pos + 1, line.length())); frame_width = std::stoi(line.substr(pos + 1, line.length()));
} }
else if (line.substr(0, pos) == "frameHeight") else if (line.substr(0, pos) == "frame_height")
{ {
frameHeight = std::stoi(line.substr(pos + 1, line.length())); frame_height = std::stoi(line.substr(pos + 1, line.length()));
} }
else else
{ {
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl; #ifdef VERBOSE
std::cout << "Warning: file " << file_name.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
#endif
} }
// Normaliza valores // Normaliza valores
if (framesPerRow == 0 && frameWidth > 0) if (frames_per_row == 0 && frame_width > 0)
{ {
framesPerRow = texture->getWidth() / frameWidth; frames_per_row = texture->getWidth() / frame_width;
} }
if (maxTiles == 0 && frameWidth > 0 && frameHeight > 0) if (max_tiles == 0 && frame_width > 0 && frame_height > 0)
{ {
const int w = texture->getWidth() / frameWidth; const auto w = texture->getWidth() / frame_width;
const int h = texture->getHeight() / frameHeight; const auto h = texture->getHeight() / frame_height;
maxTiles = w * h; max_tiles = w * h;
} }
} }
} }
@@ -140,74 +151,55 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
// El fichero no se puede abrir // El fichero no se puede abrir
else else
{ {
if (verbose) #ifdef VERBOSE
{ std::cout << "Warning: Unable to open " << file_name.c_str() << " file" << std::endl;
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl; #endif
}
} }
return as; return af;
} }
// Constructor // Constructor
AnimatedSprite::AnimatedSprite(Texture *texture, std::string file, std::vector<std::string> *buffer) AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file, std::vector<std::string> *buffer)
: MovingSprite(texture),
current_animation_(0)
{ {
// Copia los punteros
setTexture(texture);
// Carga las animaciones // Carga las animaciones
if (file != "") if (!file.empty())
{ {
animatedSprite_t as = loadAnimationFromFile(texture, file); AnimatedFile as = loadAnimationFromFile(texture, file);
// Copia los datos de las animaciones // Copia los datos de las animaciones
for (auto animation : as.animations) std::copy(as.animations.begin(), as.animations.end(), std::back_inserter(animations_));
{
this->animation.push_back(animation);
}
} }
else if (buffer) else if (buffer)
{ {
loadFromVector(buffer); loadFromVector(buffer);
} }
// Inicializa variables
currentAnimation = 0;
} }
// Constructor // Constructor
AnimatedSprite::AnimatedSprite(animatedSprite_t *animation) AnimatedSprite::AnimatedSprite(const AnimatedFile *animation)
: MovingSprite(animation->texture),
current_animation_(0)
{ {
// Copia los punteros
setTexture(animation->texture);
// Inicializa variables
currentAnimation = 0;
// Copia los datos de las animaciones // Copia los datos de las animaciones
for (auto a : animation->animations) std::copy(animation->animations.begin(), animation->animations.end(), std::back_inserter(animations_));
{
this->animation.push_back(a);
}
} }
// Destructor // Destructor
AnimatedSprite::~AnimatedSprite() AnimatedSprite::~AnimatedSprite()
{ {
for (auto &a : animation) animations_.clear();
{
a.frames.clear();
}
animation.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)
{ {
int index = -1; auto index = -1;
for (auto a : animation) for (const auto &a : animations_)
{ {
index++; index++;
if (a.name == name) if (a.name == name)
@@ -215,147 +207,147 @@ 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 || animation[currentAnimation].speed == 0) if (animations_[current_animation_].speed == 0)
{ {
return; return;
} }
// Calcula el frame actual a partir del contador // Calcula el frame actual a partir del contador
animation[currentAnimation].currentFrame = animation[currentAnimation].counter / animation[currentAnimation].speed; animations_[current_animation_].current_frame = animations_[current_animation_].counter / animations_[current_animation_].speed;
// Si alcanza el final de la animación, reinicia el contador de la animación // Si alcanza el final de la animación, reinicia el contador de la animación
// en función de la variable loop y coloca el nuevo frame // en función de la variable loop y coloca el nuevo frame
if (animation[currentAnimation].currentFrame >= (int)animation[currentAnimation].frames.size()) if (animations_[current_animation_].current_frame >= (int)animations_[current_animation_].frames.size())
{ {
if (animation[currentAnimation].loop == -1) if (animations_[current_animation_].loop == -1)
{ // Si no hay loop, deja el último frame { // Si no hay loop, deja el último frame
animation[currentAnimation].currentFrame = animation[currentAnimation].frames.size(); animations_[current_animation_].current_frame = animations_[current_animation_].frames.size();
animation[currentAnimation].completed = true; animations_[current_animation_].completed = true;
} }
else else
{ // Si hay loop, vuelve al frame indicado { // Si hay loop, vuelve al frame indicado
animation[currentAnimation].counter = 0; animations_[current_animation_].counter = 0;
animation[currentAnimation].currentFrame = animation[currentAnimation].loop; animations_[current_animation_].current_frame = animations_[current_animation_].loop;
} }
} }
// En caso contrario // En caso contrario
else else
{ {
// Escoge el frame correspondiente de la animación // Escoge el frame correspondiente de la animación
setSpriteClip(animation[currentAnimation].frames[animation[currentAnimation].currentFrame]); setSpriteClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]);
// Incrementa el contador de la animacion // Incrementa el contador de la animacion
animation[currentAnimation].counter++; animations_[current_animation_].counter++;
} }
} }
// Obtiene el número de frames de la animación actual // Obtiene el número de frames de la animación actual
int AnimatedSprite::getNumFrames() int AnimatedSprite::getNumFrames()
{ {
return (int)animation[currentAnimation].frames.size(); return (int)animations_[current_animation_].frames.size();
} }
// Establece el frame actual de la animación // Establece el frame actual de la animación
void AnimatedSprite::setCurrentFrame(int num) void AnimatedSprite::setCurrentFrame(int num)
{ {
// Descarta valores fuera de rango // Descarta valores fuera de rango
if (num >= (int)animation[currentAnimation].frames.size()) if (num >= (int)animations_[current_animation_].frames.size())
{ {
num = 0; num = 0;
} }
// Cambia el valor de la variable // Cambia el valor de la variable
animation[currentAnimation].currentFrame = num; animations_[current_animation_].current_frame = num;
animation[currentAnimation].counter = 0; animations_[current_animation_].counter = 0;
// Escoge el frame correspondiente de la animación // Escoge el frame correspondiente de la animación
setSpriteClip(animation[currentAnimation].frames[animation[currentAnimation].currentFrame]); setSpriteClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]);
} }
// Establece el valor del contador // Establece el valor del contador
void AnimatedSprite::setAnimationCounter(std::string name, int num) void AnimatedSprite::setAnimationCounter(const std::string &name, int num)
{ {
animation[getIndex(name)].counter = num; animations_[getIndex(name)].counter = num;
} }
// Establece la velocidad de una animación // Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(std::string name, int speed) void AnimatedSprite::setAnimationSpeed(const std::string &name, int speed)
{ {
animation[getIndex(name)].counter = speed; animations_[getIndex(name)].counter = speed;
} }
// Establece la velocidad de una animación // Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(int index, int speed) void AnimatedSprite::setAnimationSpeed(int index, int speed)
{ {
animation[index].counter = speed; animations_[index].counter = speed;
} }
// Establece si la animación se reproduce en bucle // Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(std::string name, int loop) void AnimatedSprite::setAnimationLoop(const std::string &name, int loop)
{ {
animation[getIndex(name)].loop = loop; animations_[getIndex(name)].loop = loop;
} }
// Establece si la animación se reproduce en bucle // Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(int index, int loop) void AnimatedSprite::setAnimationLoop(int index, int loop)
{ {
animation[index].loop = loop; animations_[index].loop = loop;
} }
// Establece el valor de la variable // Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(std::string name, bool value) void AnimatedSprite::setAnimationCompleted(const std::string &name, bool value)
{ {
animation[getIndex(name)].completed = value; animations_[getIndex(name)].completed = value;
} }
// OLD - Establece el valor de la variable // OLD - Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(int index, bool value) void AnimatedSprite::setAnimationCompleted(int index, bool value)
{ {
animation[index].completed = 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 animation[currentAnimation].completed; return animations_[current_animation_].completed;
} }
// Devuelve el rectangulo de una animación y frame concreto // Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(std::string name, Uint8 index) SDL_Rect AnimatedSprite::getAnimationClip(const std::string &name, Uint8 index)
{ {
return animation[getIndex(name)].frames[index]; return animations_[getIndex(name)].frames[index];
} }
// Devuelve el rectangulo de una animación y frame concreto // Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF) SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF)
{ {
return animation[indexA].frames[indexF]; return animations_[indexA].frames[indexF];
} }
// Carga la animación desde un vector // Carga la animación desde un vector
bool AnimatedSprite::loadFromVector(std::vector<std::string> *source) bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
{ {
// Inicializa variables // Inicializa variables
int framesPerRow = 0; auto frames_per_row = 0;
int frameWidth = 0; auto frame_width = 0;
int frameHeight = 0; auto frame_height = 0;
int maxTiles = 0; auto max_tiles = 0;
// Indicador de éxito en el proceso // Indicador de éxito en el proceso
bool success = true; auto success = true;
std::string line; std::string line;
// Recorre todo el vector // Recorre todo el vector
int index = 0; auto index = 0;
while (index < (int)source->size()) while (index < (int)source->size())
{ {
// Lee desde el vector // Lee desde el vector
@@ -364,10 +356,14 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación // Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]") if (line == "[animation]")
{ {
animation_t buffer; Animation buffer;
buffer.counter = 0; buffer.counter = 0;
buffer.currentFrame = 0; buffer.current_frame = 0;
buffer.completed = false; buffer.completed = false;
buffer.name.clear();
buffer.speed = 5;
buffer.loop = 0;
buffer.frames.clear();
do do
{ {
@@ -379,7 +375,7 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
int pos = line.find("="); int pos = line.find("=");
// Procesa las dos subcadenas // Procesa las dos subcadenas
if (pos != (int)line.npos) if (pos != static_cast<int>(line.npos))
{ {
if (line.substr(0, pos) == "name") if (line.substr(0, pos) == "name")
{ {
@@ -401,27 +397,29 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
// Se introducen los valores separados por comas en un vector // Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length())); std::stringstream ss(line.substr(pos + 1, line.length()));
std::string tmp; std::string tmp;
SDL_Rect rect = {0, 0, frameWidth, frameHeight}; SDL_Rect rect = {0, 0, frame_width, frame_height};
while (getline(ss, tmp, ',')) while (getline(ss, tmp, ','))
{ {
// Comprueba que el tile no sea mayor que el maximo indice permitido // Comprueba que el tile no sea mayor que el maximo indice permitido
const int numTile = std::stoi(tmp) > maxTiles ? 0 : std::stoi(tmp); const int num_tile = std::stoi(tmp) > max_tiles ? 0 : std::stoi(tmp);
rect.x = (numTile % framesPerRow) * frameWidth; rect.x = (num_tile % frames_per_row) * frame_width;
rect.y = (numTile / framesPerRow) * frameHeight; rect.y = (num_tile / frames_per_row) * frame_height;
buffer.frames.push_back(rect); buffer.frames.push_back(rect);
} }
} }
else else
{ {
#ifdef VERBOSE
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl; std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
#endif
success = false; success = false;
} }
} }
} while (line != "[/animation]"); } while (line != "[/animation]");
// Añade la animación al vector de animaciones // Añade la animación al vector de animaciones
animation.push_back(buffer); animations_.push_back(buffer);
} }
// En caso contrario se parsea el fichero para buscar las variables y los valores // En caso contrario se parsea el fichero para buscar las variables y los valores
@@ -433,38 +431,40 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
// Procesa las dos subcadenas // Procesa las dos subcadenas
if (pos != (int)line.npos) if (pos != (int)line.npos)
{ {
if (line.substr(0, pos) == "framesPerRow") if (line.substr(0, pos) == "frames_per_row")
{ {
framesPerRow = std::stoi(line.substr(pos + 1, line.length())); frames_per_row = std::stoi(line.substr(pos + 1, line.length()));
} }
else if (line.substr(0, pos) == "frameWidth") else if (line.substr(0, pos) == "frame_width")
{ {
frameWidth = std::stoi(line.substr(pos + 1, line.length())); frame_width = std::stoi(line.substr(pos + 1, line.length()));
} }
else if (line.substr(0, pos) == "frameHeight") else if (line.substr(0, pos) == "frame_height")
{ {
frameHeight = std::stoi(line.substr(pos + 1, line.length())); frame_height = std::stoi(line.substr(pos + 1, line.length()));
} }
else else
{ {
#ifdef VERBOSE
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl; std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
#endif
success = false; success = false;
} }
// Normaliza valores // Normaliza valores
if (framesPerRow == 0 && frameWidth > 0) if (frames_per_row == 0 && frame_width > 0)
{ {
framesPerRow = texture->getWidth() / frameWidth; frames_per_row = texture_->getWidth() / frame_width;
} }
if (maxTiles == 0 && frameWidth > 0 && frameHeight > 0) if (max_tiles == 0 && frame_width > 0 && frame_height > 0)
{ {
const int w = texture->getWidth() / frameWidth; const int w = texture_->getWidth() / frame_width;
const int h = texture->getHeight() / frameHeight; const int h = texture_->getHeight() / frame_height;
maxTiles = w * h; max_tiles = w * h;
} }
} }
} }
@@ -474,34 +474,34 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
} }
// Pone un valor por defecto // Pone un valor por defecto
setRect({0, 0, frameWidth, frameHeight}); setPos((SDL_Rect){0, 0, frame_width, frame_height});
return success; return success;
} }
// Establece la animacion actual // Establece la animacion actual
void AnimatedSprite::setCurrentAnimation(std::string name) void AnimatedSprite::setCurrentAnimation(const std::string &name)
{ {
const int newAnimation = getIndex(name); const auto new_animation = getIndex(name);
if (currentAnimation != newAnimation) if (current_animation_ != new_animation)
{ {
currentAnimation = newAnimation; current_animation_ = new_animation;
animation[currentAnimation].currentFrame = 0; animations_[current_animation_].current_frame = 0;
animation[currentAnimation].counter = 0; animations_[current_animation_].counter = 0;
animation[currentAnimation].completed = false; animations_[current_animation_].completed = false;
} }
} }
// Establece la animacion actual // Establece la animacion actual
void AnimatedSprite::setCurrentAnimation(int index) void AnimatedSprite::setCurrentAnimation(int index)
{ {
const int newAnimation = index; const auto new_animation = index;
if (currentAnimation != newAnimation) if (current_animation_ != new_animation)
{ {
currentAnimation = newAnimation; current_animation_ = new_animation;
animation[currentAnimation].currentFrame = 0; animations_[current_animation_].current_frame = 0;
animation[currentAnimation].counter = 0; animations_[current_animation_].counter = 0;
animation[currentAnimation].completed = false; animations_[current_animation_].completed = false;
} }
} }
@@ -515,13 +515,13 @@ void AnimatedSprite::update()
// Establece el rectangulo para un frame de una animación // 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) void AnimatedSprite::setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h)
{ {
animation[index_animation].frames.push_back({x, y, w, h}); animations_[index_animation].frames.push_back({x, y, w, h});
} }
// OLD - Establece el contador para todas las animaciones // OLD - Establece el contador para todas las animaciones
void AnimatedSprite::setAnimationCounter(int value) void AnimatedSprite::setAnimationCounter(int value)
{ {
for (auto &a : animation) for (auto &a : animations_)
{ {
a.counter = value; a.counter = value;
} }
@@ -530,7 +530,7 @@ void AnimatedSprite::setAnimationCounter(int value)
// Reinicia la animación // Reinicia la animación
void AnimatedSprite::resetAnimation() void AnimatedSprite::resetAnimation()
{ {
animation[currentAnimation].currentFrame = 0; animations_[current_animation_].current_frame = 0;
animation[currentAnimation].counter = 0; animations_[current_animation_].counter = 0;
animation[currentAnimation].completed = false; animations_[current_animation_].completed = false;
} }

View File

@@ -2,45 +2,46 @@
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint8 #include <SDL2/SDL_stdinc.h> // for Uint8
#include <string> // for string, basic_string #include <memory> // for shared_ptr
#include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "moving_sprite.h" // for MovingSprite #include "moving_sprite.h" // for MovingSprite
class Texture; class Texture;
struct animation_t struct Animation
{ {
std::string name; // Nombre de la animacion std::string name; // Nombre de la animacion
std::vector<SDL_Rect> frames; // Cada uno de los frames que componen la animación std::vector<SDL_Rect> frames; // Cada uno de los frames que componen la animación
int speed; // Velocidad de la animación int speed; // Velocidad de la animación
int loop; // Indica a que frame vuelve la animación al terminar. -1 para que no vuelva int loop; // Indica a que frame vuelve la animación al terminar. -1 para que no vuelva
bool completed; // Indica si ha finalizado la animación bool completed; // Indica si ha finalizado la animación
int currentFrame; // Frame actual int current_frame; // Frame actual
int counter; // Contador para las animaciones int counter; // Contador para las animaciones
}; };
struct animatedSprite_t struct AnimatedFile
{ {
std::vector<animation_t> animations; // Vector con las diferentes animaciones std::vector<Animation> animations; // Vector con las diferentes animaciones
Texture *texture; // Textura con los graficos para el sprite std::shared_ptr<Texture> texture; // Textura con los graficos para el sprite
}; };
// Carga la animación desde un fichero // Carga la animación desde un fichero
animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, bool verbose = false); AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string filePath);
class AnimatedSprite : public MovingSprite class AnimatedSprite : public MovingSprite
{ {
private: protected:
// Variables // Variables
std::vector<animation_t> animation; // Vector con las diferentes animaciones std::vector<Animation> animations_; // Vector con las diferentes animaciones
int currentAnimation; // Animacion activa int current_animation_; // Animacion activa
public: public:
// Constructor // Constructor
AnimatedSprite(Texture *texture = nullptr, std::string file = "", std::vector<std::string> *buffer = nullptr); explicit AnimatedSprite(std::shared_ptr<Texture> texture = nullptr, const std::string &file = std::string(), std::vector<std::string> *buffer = nullptr);
AnimatedSprite(animatedSprite_t *animation); explicit AnimatedSprite(const AnimatedFile *animation);
// Destructor // Destructor
~AnimatedSprite(); virtual ~AnimatedSprite();
// Calcula el frame correspondiente a la animación actual // Calcula el frame correspondiente a la animación actual
void animate(); void animate();
@@ -52,39 +53,39 @@ public:
void setCurrentFrame(int num); void setCurrentFrame(int num);
// Establece el valor del contador // Establece el valor del contador
void setAnimationCounter(std::string name, int num); void setAnimationCounter(const std::string &name, int num);
// Establece la velocidad de una animación // Establece la velocidad de una animación
void setAnimationSpeed(std::string name, int speed); void setAnimationSpeed(const std::string &name, int speed);
void setAnimationSpeed(int index, int speed); void setAnimationSpeed(int index, int speed);
// Establece el frame al que vuelve la animación al finalizar // Establece el frame al que vuelve la animación al finalizar
void setAnimationLoop(std::string name, int loop); void setAnimationLoop(const std::string &name, int loop);
void setAnimationLoop(int index, int loop); void setAnimationLoop(int index, int loop);
// Establece el valor de la variable // Establece el valor de la variable
void setAnimationCompleted(std::string name, bool value); void setAnimationCompleted(const std::string &name, bool value);
void setAnimationCompleted(int index, 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 // Devuelve el rectangulo de una animación y frame concreto
SDL_Rect getAnimationClip(std::string name = "default", Uint8 index = 0); SDL_Rect getAnimationClip(const std::string &name = "default", Uint8 index = 0);
SDL_Rect getAnimationClip(int indexA = 0, Uint8 indexF = 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 // Carga la animación desde un vector
bool loadFromVector(std::vector<std::string> *source); 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 // Actualiza las variables del objeto
void update(); void update() override;
// OLD - Establece el rectangulo para un frame de una animación // 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); void setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h);

View File

@@ -5,64 +5,53 @@
#include <iostream> // for basic_ostream, operator<<, cout, endl #include <iostream> // for basic_ostream, operator<<, cout, endl
// [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 executablePath) void Asset::init(const std::string &executable_path)
{ {
Asset::asset = new Asset(executablePath); 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 // Constructor
Asset::Asset(std::string executablePath) Asset::Asset(const std::string &executable_path)
: executable_path_(executable_path.substr(0, executable_path.find_last_of("\\/")))
{ {
this->executablePath = executablePath.substr(0, executablePath.find_last_of("\\/")); longest_name_ = 0;
longestName = 0;
#ifdef VERBOSE
verbose = true;
#else
verbose = false;
#endif
}
// Destructor
Asset::~Asset()
{
} }
// Añade un elemento a la lista // Añade un elemento a la lista
void Asset::add(std::string file, enum assetType type, bool required, bool absolute) void Asset::add(const std::string &file, AssetType type, bool required, bool absolute)
{ {
item_t temp; AssetItem ai;
temp.file = absolute ? file : executablePath + file; ai.file = absolute ? file : executable_path_ + file;
temp.type = type; ai.type = type;
temp.required = required; ai.required = required;
fileList.push_back(temp); file_list_.push_back(ai);
const std::string filename = file.substr(file.find_last_of("\\/") + 1); const std::string file_name = file.substr(file.find_last_of("\\/") + 1);
longestName = SDL_max(longestName, filename.size()); longest_name_ = SDL_max(longest_name_, file_name.size());
} }
// Devuelve el fichero de un elemento de la lista a partir de una cadena // Devuelve el fichero de un elemento de la lista a partir de una cadena
std::string Asset::get(std::string text) std::string Asset::get(const std::string &text) const
{ {
for (auto f : fileList) for (const auto &f : file_list_)
{ {
const size_t lastIndex = f.file.find_last_of("/") + 1; const size_t last_index = f.file.find_last_of("/") + 1;
const std::string file = f.file.substr(lastIndex, std::string::npos); const std::string file = f.file.substr(last_index, std::string::npos);
if (file == text) if (file == text)
{ {
@@ -70,35 +59,33 @@ std::string Asset::get(std::string text)
} }
} }
if (verbose) #ifdef VERBOSE
{
std::cout << "Warning: file " << text.c_str() << " not found" << std::endl; std::cout << "Warning: file " << text.c_str() << " not found" << std::endl;
} #endif
return ""; return "";
} }
// Comprueba que existen todos los elementos // Comprueba que existen todos los elementos
bool Asset::check() bool Asset::check() const
{ {
bool success = true; bool success = true;
if (verbose) #ifdef VERBOSE
{
std::cout << "\n** Checking files" << std::endl; std::cout << "\n** Checking files" << std::endl;
std::cout << "Executable path is: " << executablePath << std::endl; std::cout << "Executable path is: " << executable_path_ << std::endl;
std::cout << "Sample filepath: " << fileList.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 < t_maxAssetType; ++type) for (int type = 0; type < static_cast<int>(AssetType::MAX_ASSET_TYPE); ++type)
{ {
// Comprueba si hay ficheros de ese tipo // Comprueba si hay ficheros de ese tipo
bool any = false; bool any = false;
for (auto f : fileList) for (const auto &f : file_list_)
{ {
if ((f.required) && (f.type == type)) if (f.required && f.type == static_cast<AssetType>(type))
{ {
any = true; any = true;
} }
@@ -107,14 +94,13 @@ bool Asset::check()
// Si hay ficheros de ese tipo, comprueba si existen // Si hay ficheros de ese tipo, comprueba si existen
if (any) if (any)
{ {
if (verbose) #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 : fileList) for (const auto &f : file_list_)
{ {
if ((f.required) && (f.type == type)) if (f.required && f.type == static_cast<AssetType>(type))
{ {
success &= checkFile(f.file); success &= checkFile(f.file);
} }
@@ -123,91 +109,78 @@ bool Asset::check()
} }
// Resultado // Resultado
if (verbose) #ifdef VERBOSE
{ std::cout << (success ? "\n** All files OK.\n" : "\n** A file is missing. Exiting.\n") << std::endl;
if (success) #endif
{
std::cout << "\n** All files OK.\n"
<< std::endl;
}
else
{
std::cout << "\n** A file is missing. Exiting.\n"
<< std::endl;
}
}
return success; return success;
} }
// Comprueba que existe un fichero // Comprueba que existe un fichero
bool Asset::checkFile(std::string path) bool Asset::checkFile(const std::string &path) const
{ {
bool success = false; auto success = false;
std::string result = "ERROR";
// Comprueba si existe el fichero // Comprueba si existe el fichero
const std::string filename = path.substr(path.find_last_of("\\/") + 1); auto file = SDL_RWFromFile(path.c_str(), "rb");
SDL_RWops *file = SDL_RWFromFile(path.c_str(), "rb");
if (file != nullptr) if (file)
{ {
result = "OK";
success = true; success = true;
SDL_RWclose(file); SDL_RWclose(file);
} }
if (verbose) #ifdef VERBOSE
{ const std::string file_name = path.substr(path.find_last_of("\\/") + 1);
std::cout.setf(std::ios::left, std::ios::adjustfield); std::cout.setf(std::ios::left, std::ios::adjustfield);
std::cout << "Checking file: "; std::cout << "Checking file: ";
std::cout.width(longestName + 2); std::cout.width(longest_name_ + 2);
std::cout.fill('.'); std::cout.fill('.');
std::cout << filename + " "; std::cout << file_name;
std::cout << " [" + result + "]" << std::endl; std::cout << (success ? " [OK]" : " [ERROR]") << 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) std::string Asset::getTypeName(AssetType type) const
{ {
switch (type) switch (type)
{ {
case t_bitmap: case AssetType::BITMAP:
return "BITMAP"; return "BITMAP";
break; break;
case t_music: case AssetType::MUSIC:
return "MUSIC"; return "MUSIC";
break; break;
case t_sound: case AssetType::SOUND:
return "SOUND"; return "SOUND";
break; break;
case t_font: case AssetType::FONT:
return "FONT"; return "FONT";
break; break;
case t_lang: case AssetType::LANG:
return "LANG"; return "LANG";
break; break;
case t_data: case AssetType::DATA:
return "DATA"; return "DATA";
break; break;
case t_animation: case AssetType::ANIMATION:
return "ANIMATION"; return "ANIMATION";
break; break;
case t_palette: case AssetType::PALETTE:
return "PALETTE"; return "PALETTE";
break; break;
case t_item: case AssetType::ITEM:
return "ITEM"; return "ITEM";
break; break;
@@ -217,18 +190,12 @@ std::string Asset::getTypeName(int type)
} }
} }
// Establece si ha de mostrar texto por pantalla
void Asset::setVerbose(bool value)
{
verbose = value;
}
// Devuelve la lista de recursos de un tipo // Devuelve la lista de recursos de un tipo
std::vector<std::string> Asset::getListByType(assetType type) std::vector<std::string> Asset::getListByType(AssetType type) const
{ {
std::vector<std::string> list; std::vector<std::string> list;
for (auto f : fileList) for (auto f : file_list_)
{ {
if (f.type == type) if (f.type == type)
{ {

View File

@@ -3,18 +3,18 @@
#include <string> // for string, basic_string #include <string> // for string, basic_string
#include <vector> // for vector #include <vector> // for vector
enum assetType enum class AssetType : int
{ {
t_bitmap, BITMAP,
t_music, MUSIC,
t_sound, SOUND,
t_font, FONT,
t_lang, LANG,
t_data, DATA,
t_animation, ANIMATION,
t_palette, PALETTE,
t_item, ITEM,
t_maxAssetType MAX_ASSET_TYPE,
}; };
// Clase Asset // Clase Asset
@@ -22,38 +22,37 @@ 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 item_t struct AssetItem
{ {
std::string file; // Ruta del fichero desde la raiz del directorio std::string file; // Ruta del fichero desde la raiz del directorio
enum assetType type; // Indica el tipo de recurso enum 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 // bool absolute; // Indica si la ruta que se ha proporcionado es una ruta absoluta
}; };
// Variables // Variables
int longestName; // Contiene la longitud del nombre de fichero mas largo int longest_name_; // Contiene la longitud del nombre de fichero mas largo
std::vector<item_t> fileList; // Listado con todas las rutas a los ficheros std::vector<AssetItem> file_list_; // Listado con todas las rutas a los ficheros
std::string executablePath; // Ruta al ejecutable std::string executable_path_; // Ruta al ejecutable
bool verbose; // Indica si ha de mostrar información por pantalla
// Comprueba que existe un fichero // Comprueba que existe un fichero
bool checkFile(std::string executablePath); 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); std::string getTypeName(AssetType type) const;
// Constructor // Constructor
Asset(std::string path); explicit Asset(const std::string &executable_path);
// Destructor // Destructor
~Asset(); ~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();
@@ -62,17 +61,14 @@ 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, enum 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 un elemento de la lista a partir de una cadena
std::string get(std::string text); std::string get(const std::string &text) const;
// Comprueba que existen todos los elementos // Comprueba que existen todos los elementos
bool check(); bool check() const;
// Establece si ha de mostrar texto por pantalla
void setVerbose(bool value);
// Devuelve la lista de recursos de un tipo // Devuelve la lista de recursos de un tipo
std::vector<std::string> getListByType(assetType type); std::vector<std::string> getListByType(AssetType type) const;
}; };

View File

@@ -1,8 +1,7 @@
#include "background.h" #include "background.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <algorithm> // for max, min #include <algorithm> // for clamp, max
#include <string> // for basic_string
#include "asset.h" // for Asset #include "asset.h" // for Asset
#include "moving_sprite.h" // for MovingSprite #include "moving_sprite.h" // for MovingSprite
#include "param.h" // for param #include "param.h" // for param
@@ -11,177 +10,161 @@
// Constructor // Constructor
Background::Background(SDL_Renderer *renderer) Background::Background(SDL_Renderer *renderer)
: renderer_(renderer),
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")))
{ {
// Copia los punteros
this->renderer = renderer;
asset = Asset::get();
// Carga las texturas
buildingsTexture = new Texture(renderer, asset->get("game_buildings.png"));
topCloudsTexture = new Texture(renderer, asset->get("game_clouds1.png"));
bottomCloudsTexture = new Texture(renderer, asset->get("game_clouds2.png"));
grassTexture = new Texture(renderer, asset->get("game_grass.png"));
gradientsTexture = new Texture(renderer, asset->get("game_sky_colors.png"));
// Inicializa variables // Inicializa variables
gradientNumber = 0; gradient_number_ = 0;
alpha = 0; alpha_ = 0;
cloudsSpeed = 0; clouds_speed_ = 0;
transition = 0; transition_ = 0;
counter = 0; counter_ = 0;
rect = {0, 0, gradientsTexture->getWidth() / 2, gradientsTexture->getHeight() / 2}; rect_ = {0, 0, gradients_texture_->getWidth() / 2, gradients_texture_->getHeight() / 2};
srcRect = {0, 0, 320, 240}; src_rect_ = {0, 0, 320, 240};
dstRect = {0, 0, 320, 240}; dst_rect_ = {0, 0, 320, 240};
base = rect.h; base_ = rect_.h;
color = {param.background.attenuateColor.r, param.background.attenuateColor.g, param.background.attenuateColor.b}; color_ = {param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b};
alphaColorText = alphaColorTextTemp = param.background.attenuateAlpha; alpha_color_text_ = alpha_color_text_temp_ = param.background.attenuate_alpha;
gradientRect[0] = {0, 0, rect.w, rect.h}; gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
gradientRect[1] = {rect.w, 0, rect.w, rect.h}; gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h};
gradientRect[2] = {0, rect.h, rect.w, rect.h}; gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h};
gradientRect[3] = {rect.w, rect.h, rect.w, rect.h}; gradient_rect_[3] = {rect_.w, rect_.h, rect_.w, rect_.h};
const int topCloudsTextureHeight = topCloudsTexture->getHeight() / 4; const int top_clouds_texture_height = top_clouds_texture_->getHeight() / 4;
const int bottomCloudsTextureHeight = bottomCloudsTexture->getHeight() / 4; const int bottom_clouds_texture_height = bottom_clouds_texture_->getHeight() / 4;
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
{ {
topCloudsRect[i] = {0, i * topCloudsTextureHeight, topCloudsTexture->getWidth(), topCloudsTextureHeight}; top_clouds_rect_[i] = {0, i * top_clouds_texture_height, top_clouds_texture_->getWidth(), top_clouds_texture_height};
bottomCloudsRect[i] = {0, i * bottomCloudsTextureHeight, bottomCloudsTexture->getWidth(), bottomCloudsTextureHeight}; 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 topClouds_y = base - 165; const int top_clouds_y = base_ - 165;
const int bottomClouds_y = base - 101; const int bottom_clouds_y = base_ - 101;
const float topCloudsSpeed = 0.1f; constexpr float top_clouds_speed = 0.1f;
const float bottomCloudsSpeed = 0.05f; constexpr float bottom_clouds_speed = 0.05f;
topCloudsSprite_A = new MovingSprite(0, topClouds_y, rect.w, topCloudsTexture->getHeight(), -topCloudsSpeed, 0.0f, 0.0f, 0.0f, topCloudsTexture); 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_);
topCloudsSprite_B = new MovingSprite(rect.w, topClouds_y, rect.w, topCloudsTexture->getHeight(), -topCloudsSpeed, 0.0f, 0.0f, 0.0f, topCloudsTexture); 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_);
bottomCloudsSprite_A = new MovingSprite(0, bottomClouds_y, rect.w, bottomCloudsTexture->getHeight(), -bottomCloudsSpeed, 0.0f, 0.0f, 0.0f, bottomCloudsTexture); 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_);
bottomCloudsSprite_B = new MovingSprite(rect.w, bottomClouds_y, rect.w, bottomCloudsTexture->getHeight(), -bottomCloudsSpeed, 0.0f, 0.0f, 0.0f, bottomCloudsTexture); 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_);
buildingsSprite = new Sprite(0, 0, buildingsTexture->getWidth(), buildingsTexture->getHeight(), buildingsTexture); buildings_sprite_ = std::make_unique<Sprite>(0, 0, buildings_texture_->getWidth(), buildings_texture_->getHeight(), buildings_texture_);
gradientSprite = new Sprite(0, 0, rect.w, rect.h, gradientsTexture); gradient_sprite_ = std::make_unique<Sprite>(0, 0, rect_.w, rect_.h, gradients_texture_);
grassSprite = new Sprite(0, 0, grassTexture->getWidth(), grassTexture->getHeight() / 2, grassTexture); grass_sprite_ = std::make_unique<Sprite>(0, 0, grass_texture_->getWidth(), grass_texture_->getHeight() / 2, grass_texture_);
// Inicializa objetos // Inicializa objetos
topCloudsSprite_A->setSpriteClip(0, 0, topCloudsTexture->getWidth(), topCloudsTexture->getHeight()); top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
topCloudsSprite_B->setSpriteClip(0, 0, topCloudsTexture->getWidth(), topCloudsTexture->getHeight()); top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
bottomCloudsSprite_A->setSpriteClip(0, 0, bottomCloudsTexture->getWidth(), bottomCloudsTexture->getHeight()); bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
bottomCloudsSprite_B->setSpriteClip(0, 0, bottomCloudsTexture->getWidth(), bottomCloudsTexture->getHeight()); bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
buildingsSprite->setPosY(base - buildingsSprite->getHeight()); buildings_sprite_->setPosY(base_ - buildings_sprite_->getHeight());
grassSprite->setPosY(base - grassSprite->getHeight()); grass_sprite_->setPosY(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
colorTexture = 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(colorTexture, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND);
setColor(color); setColor(color_);
SDL_SetTextureAlphaMod(colorTexture, alphaColorText); SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_);
} }
// Destructor // Destructor
Background::~Background() Background::~Background()
{ {
delete buildingsTexture; SDL_DestroyTexture(canvas_);
delete topCloudsTexture; SDL_DestroyTexture(color_texture_);
delete bottomCloudsTexture;
delete grassTexture;
delete gradientsTexture;
delete topCloudsSprite_A;
delete topCloudsSprite_B;
delete bottomCloudsSprite_A;
delete bottomCloudsSprite_B;
delete buildingsSprite;
delete gradientSprite;
delete grassSprite;
SDL_DestroyTexture(canvas);
SDL_DestroyTexture(colorTexture);
} }
// Actualiza la lógica del objeto // Actualiza la lógica del objeto
void Background::update() void Background::update()
{ {
// Actualiza el valor de alpha // Actualiza el valor de alpha_
updateAlphaColorText(); updateAlphaColorText();
// Actualiza las nubes // Actualiza las nubes
updateClouds(); updateClouds();
// Calcula el frame de la hierba // Calcula el frame de la hierba
grassSprite->setSpriteClip(0, (10 * (counter / 20 % 2)), 320, 10); grass_sprite_->setSpriteClip(0, (10 * (counter_ / 20 % 2)), 320, 10);
// Calcula el valor de alpha // Calcula el valor de alpha_
alpha = std::max((255 - (int)(255 * transition)), 0); alpha_ = std::max((255 - (int)(255 * transition_)), 0);
// 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
gradientsTexture->setAlpha(255); gradients_texture_->setAlpha(255);
gradientSprite->setSpriteClip(gradientRect[(gradientNumber + 1) % 4]); gradient_sprite_->setSpriteClip(gradient_rect_[(gradient_number_ + 1) % 4]);
gradientSprite->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
gradientsTexture->setAlpha(alpha); gradients_texture_->setAlpha(alpha_);
gradientSprite->setSpriteClip(gradientRect[gradientNumber]); gradient_sprite_->setSpriteClip(gradient_rect_[gradient_number_]);
gradientSprite->render(); gradient_sprite_->render();
} }
// 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
topCloudsTexture->setAlpha(255); top_clouds_texture_->setAlpha(255);
topCloudsSprite_A->setSpriteClip(topCloudsRect[(gradientNumber + 1) % 4]); top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]);
topCloudsSprite_A->render(); top_clouds_sprite_b_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]);
topCloudsSprite_B->setSpriteClip(topCloudsRect[(gradientNumber + 1) % 4]); top_clouds_sprite_a_->render();
topCloudsSprite_B->render(); top_clouds_sprite_b_->render();
// Dibuja el segundo conjunto de nubes // Dibuja el segundo conjunto de nubes, las de delante
topCloudsTexture->setAlpha(alpha); top_clouds_texture_->setAlpha(alpha_);
topCloudsSprite_A->setSpriteClip(topCloudsRect[gradientNumber]); top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[gradient_number_]);
topCloudsSprite_A->render(); top_clouds_sprite_b_->setSpriteClip(top_clouds_rect_[gradient_number_]);
topCloudsSprite_B->setSpriteClip(topCloudsRect[gradientNumber]); top_clouds_sprite_a_->render();
topCloudsSprite_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
bottomCloudsTexture->setAlpha(255); bottom_clouds_texture_->setAlpha(255);
bottomCloudsSprite_A->setSpriteClip(bottomCloudsRect[(gradientNumber + 1) % 4]); bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]);
bottomCloudsSprite_A->render(); bottom_clouds_sprite_b_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]);
bottomCloudsSprite_B->setSpriteClip(bottomCloudsRect[(gradientNumber + 1) % 4]); bottom_clouds_sprite_a_->render();
bottomCloudsSprite_B->render(); bottom_clouds_sprite_b_->render();
// Dibuja el segundo conjunto de nubes // Dibuja el segundo conjunto de nubes, las de delante
bottomCloudsTexture->setAlpha(alpha); bottom_clouds_texture_->setAlpha(alpha_);
bottomCloudsSprite_A->setSpriteClip(bottomCloudsRect[gradientNumber]); bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[gradient_number_]);
bottomCloudsSprite_A->render(); bottom_clouds_sprite_b_->setSpriteClip(bottom_clouds_rect_[gradient_number_]);
bottomCloudsSprite_B->setSpriteClip(bottomCloudsRect[gradientNumber]); bottom_clouds_sprite_a_->render();
bottomCloudsSprite_B->render(); bottom_clouds_sprite_b_->render();
} }
// Compone todos los elementos del fondo en la textura // Compone todos los elementos del fondo en la textura
void Background::fillCanvas() void Background::fillCanvas()
{ {
// Cambia el destino del renderizador // Cambia el destino del renderizador
SDL_Texture *temp = SDL_GetRenderTarget(renderer); auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer, canvas); SDL_SetRenderTarget(renderer_, canvas_);
// Dibuja el gradiente de fondo // Dibuja el gradiente de fondo
renderGradient(); renderGradient();
@@ -193,119 +176,114 @@ void Background::fillCanvas()
renderBottomClouds(); renderBottomClouds();
// Dibuja los edificios // Dibuja los edificios
buildingsSprite->render(); buildings_sprite_->render();
// Dibuja la hierba // Dibuja la hierba
grassSprite->render(); grass_sprite_->render();
// Deja el renderizador apuntando donde estaba // Deja el renderizador apuntando donde estaba
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
} }
// Dibuja el objeto // Dibuja el objeto
void Background::render() void Background::render()
{ {
// Fondo // Fondo
SDL_RenderCopy(renderer, canvas, &srcRect, &dstRect); SDL_RenderCopy(renderer_, canvas_, &src_rect_, &dst_rect_);
// Atenuación // Atenuación
SDL_RenderCopy(renderer, colorTexture, &srcRect, &dstRect); SDL_RenderCopy(renderer_, color_texture_, &src_rect_, &dst_rect_);
} }
// Vuelve a cargar las texturas // Vuelve a cargar las texturas
void Background::reloadTextures() void Background::reloadTextures()
{ {
buildingsTexture->reLoad(); buildings_texture_->reLoad();
topCloudsTexture->reLoad(); top_clouds_texture_->reLoad();
bottomCloudsTexture->reLoad(); bottom_clouds_texture_->reLoad();
grassTexture->reLoad(); grass_texture_->reLoad();
gradientsTexture->reLoad(); gradients_texture_->reLoad();
} }
// Ajusta el valor de la variable // Ajusta el valor de la variable
void Background::setCloudsSpeed(float value) void Background::setCloudsSpeed(float value)
{ {
cloudsSpeed = value; clouds_speed_ = value;
} }
// Ajusta el valor de la variable // Ajusta el valor de la variable
void Background::setGradientNumber(int value) void Background::setGradientNumber(int value)
{ {
gradientNumber = value % 4; gradient_number_ = value % 4;
} }
// 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
void Background::setPos(SDL_Rect pos) void Background::setPos(SDL_Rect pos)
{ {
this->dstRect = pos; dst_rect_ = pos;
// Si cambian las medidas del destino, hay que cambiar las del origen para evitar deformar la imagen // Si cambian las medidas del destino, hay que cambiar las del origen para evitar deformar la imagen
this->srcRect.x = 0; src_rect_.x = 0;
this->srcRect.y = rect.h - pos.h; src_rect_.y = rect_.h - pos.h;
this->srcRect.w = pos.w; src_rect_.w = pos.w;
this->srcRect.h = pos.h; src_rect_.h = pos.h;
} }
// Ajusta el valor de la variable // Ajusta el valor de la variable
void Background::setSrcRect(SDL_Rect value) void Background::setSrcRect(SDL_Rect value)
{ {
srcRect = value; src_rect_ = value;
} }
// Ajusta el valor de la variable // Ajusta el valor de la variable
void Background::setDstRect(SDL_Rect value) void Background::setDstRect(SDL_Rect value)
{ {
dstRect = value; dst_rect_ = value;
} }
// Establece el color de atenuación // Establece el color_ de atenuación
void Background::setColor(color_t color) void Background::setColor(Color color)
{ {
this->color = color; color_ = color;
// Colorea la textura // Colorea la textura
SDL_Texture *temp = SDL_GetRenderTarget(renderer); auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer, colorTexture); SDL_SetRenderTarget(renderer_, color_texture_);
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 255); SDL_SetRenderDrawColor(renderer_, color_.r, color_.g, color_.b, 255);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
} }
// Establece la transparencia de la atenuación // Establece la transparencia de la atenuación
void Background::setAlpha(int alpha) void Background::setAlpha(int alpha)
{ {
// Evita que se asignen valores fuera de rango // Evita que se asignen valores fuera de rango
alpha = std::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
alphaColorTextTemp = alphaColorText; alpha_color_text_temp_ = alpha_color_text_;
alpha_color_text_ = alpha_;
// Establece el nuevo valor
alphaColorText = alpha;
} }
// Actualiza el valor de alpha // Actualiza el valor de alpha_
void Background::updateAlphaColorText() void Background::updateAlphaColorText()
{ {
if (alphaColorText == alphaColorTextTemp) if (alpha_color_text_ == alpha_color_text_temp_)
{ {
return; return;
} }
else else
{ {
alphaColorText > alphaColorTextTemp ? alphaColorTextTemp++ : alphaColorTextTemp--; alpha_color_text_ > alpha_color_text_temp_ ? ++alpha_color_text_temp_ : --alpha_color_text_temp_;
SDL_SetTextureAlphaMod(colorTexture, alphaColorTextTemp); SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_temp_);
} }
} }
@@ -313,35 +291,35 @@ void Background::updateAlphaColorText()
void Background::updateClouds() void Background::updateClouds()
{ {
// Aplica la velocidad calculada a las nubes // Aplica la velocidad calculada a las nubes
topCloudsSprite_A->setVelX(cloudsSpeed); top_clouds_sprite_a_->setVelX(clouds_speed_);
topCloudsSprite_B->setVelX(cloudsSpeed); top_clouds_sprite_b_->setVelX(clouds_speed_);
bottomCloudsSprite_A->setVelX(cloudsSpeed / 2); bottom_clouds_sprite_a_->setVelX(clouds_speed_ / 2);
bottomCloudsSprite_B->setVelX(cloudsSpeed / 2); bottom_clouds_sprite_b_->setVelX(clouds_speed_ / 2);
// Mueve las nubes // Mueve las nubes
topCloudsSprite_A->move(); top_clouds_sprite_a_->move();
topCloudsSprite_B->move(); top_clouds_sprite_b_->move();
bottomCloudsSprite_A->move(); bottom_clouds_sprite_a_->move();
bottomCloudsSprite_B->move(); bottom_clouds_sprite_b_->move();
// Calcula el offset de las nubes // Calcula el offset de las nubes
if (topCloudsSprite_A->getPosX() < -topCloudsSprite_A->getWidth()) if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth())
{ {
topCloudsSprite_A->setPosX(topCloudsSprite_A->getWidth()); top_clouds_sprite_a_->setPosX(top_clouds_sprite_a_->getWidth());
} }
if (topCloudsSprite_B->getPosX() < -topCloudsSprite_B->getWidth()) if (top_clouds_sprite_b_->getPosX() < -top_clouds_sprite_b_->getWidth())
{ {
topCloudsSprite_B->setPosX(topCloudsSprite_B->getWidth()); top_clouds_sprite_b_->setPosX(top_clouds_sprite_b_->getWidth());
} }
if (bottomCloudsSprite_A->getPosX() < -bottomCloudsSprite_A->getWidth()) if (bottom_clouds_sprite_a_->getPosX() < -bottom_clouds_sprite_a_->getWidth())
{ {
bottomCloudsSprite_A->setPosX(bottomCloudsSprite_A->getWidth()); bottom_clouds_sprite_a_->setPosX(bottom_clouds_sprite_a_->getWidth());
} }
if (bottomCloudsSprite_B->getPosX() < -bottomCloudsSprite_B->getWidth()) if (bottom_clouds_sprite_b_->getPosX() < -bottom_clouds_sprite_b_->getWidth())
{ {
bottomCloudsSprite_B->setPosX(bottomCloudsSprite_B->getWidth()); bottom_clouds_sprite_b_->setPosX(bottom_clouds_sprite_b_->getWidth());
} }
} }

View File

@@ -2,8 +2,8 @@
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include "utils.h" // for color_t #include <memory> // for unique_ptr, shared_ptr
class Asset; #include "utils.h" // for Color
class MovingSprite; class MovingSprite;
class Sprite; class Sprite;
class Texture; class Texture;
@@ -38,7 +38,7 @@ class Texture;
- setDstRecr(SDL_Rect value) - 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. Rectangulo de destino donde se mostrará el rectángulo antrior. Automaticamente modifica srcRect para coincidor en tamaño con el destino.
- setColor(color_t color) - setColor(Color color)
Establece el color de la textura de superposición Establece el color de la textura de superposición
- setAlpha(int alpha) - setAlpha(int alpha)
@@ -50,43 +50,42 @@ class Background
{ {
private: private:
// Objetos y punteros // Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
Asset *asset; // Objeto que gestiona todos los ficheros de recursos
Texture *buildingsTexture; // Textura con los edificios de fondo std::shared_ptr<Texture> buildings_texture_; // Textura con los edificios de fondo
Texture *topCloudsTexture; // Textura con las nubes de fondo std::shared_ptr<Texture> top_clouds_texture_; // Textura con las nubes de fondo
Texture *bottomCloudsTexture; // Textura con las nubes de fondo std::shared_ptr<Texture> bottom_clouds_texture_; // Textura con las nubes de fondo
Texture *grassTexture; // Textura con la hierba del suelo std::shared_ptr<Texture> grass_texture_; // Textura con la hierba del suelo
Texture *gradientsTexture; // Textura con los diferentes colores de fondo del juego std::shared_ptr<Texture> gradients_texture_; // Textura con los diferentes colores de fondo del juego
MovingSprite *topCloudsSprite_A; // Sprite para las nubes superiores std::unique_ptr<MovingSprite> top_clouds_sprite_a_; // Sprite para las nubes superiores
MovingSprite *topCloudsSprite_B; // Sprite para las nubes superiores std::unique_ptr<MovingSprite> top_clouds_sprite_b_; // Sprite para las nubes superiores
MovingSprite *bottomCloudsSprite_A; // Sprite para las nubes inferiores std::unique_ptr<MovingSprite> bottom_clouds_sprite_a_; // Sprite para las nubes inferiores
MovingSprite *bottomCloudsSprite_B; // Sprite para las nubes inferiores std::unique_ptr<MovingSprite> bottom_clouds_sprite_b_; // Sprite para las nubes inferiores
Sprite *buildingsSprite; // Sprite con los edificios de fondo std::unique_ptr<Sprite> buildings_sprite_; // Sprite con los edificios de fondo
Sprite *gradientSprite; // Sprite con los graficos del degradado de color de fondo std::unique_ptr<Sprite> gradient_sprite_; // Sprite con los graficos del degradado de color de fondo
Sprite *grassSprite; // Sprite para la hierba std::unique_ptr<Sprite> grass_sprite_; // Sprite para la hierba
SDL_Texture *canvas; // Textura para componer el fondo SDL_Texture *canvas_; // Textura para componer el fondo
SDL_Texture *colorTexture; // Textura para atenuar el fondo SDL_Texture *color_texture_; // Textura para atenuar el fondo
// Variables // Variables
SDL_Rect gradientRect[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 topCloudsRect[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 bottomCloudsRect[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 gradientNumber; // Indica el número de degradado de fondo que se va a dibujar int gradient_number_; // Indica el número de degradado de fondo que se va a dibujar
int alpha; // Transparencia entre los dos degradados int alpha_; // Transparencia entre los dos degradados
float cloudsSpeed; // Velocidad a la que se desplazan las nubes float clouds_speed_; // Velocidad a la que se desplazan las nubes
float transition; // Nivel de transición del fondo 0..1 float transition_; // Nivel de transición del fondo 0..1
int counter; // Contador interno int counter_; // Contador interno
SDL_Rect rect; // Tamaño del objeto fondo SDL_Rect rect_; // Tamaño del objeto fondo
SDL_Rect srcRect; // 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 dstRect; // Posición donde dibujar la parte del objeto fondo que se dibujará en pantalla SDL_Rect dst_rect_; // Posición donde dibujar la parte del objeto fondo que se dibujará en pantalla
int base; // Linea de fondo coincidente con el area inferior de la zona de juego int base_; // Linea de fondo coincidente con el area inferior de la zona de juego
color_t color; // Color para atenuar el fondo Color color_; // Color para atenuar el fondo
int alphaColorText; // Alpha para atenuar el fondo int alpha_color_text_; // Alpha para atenuar el fondo
int alphaColorTextTemp; // Valor temporal para hacer la transición de alpha int alpha_color_text_temp_; // Valor temporal para hacer la transición de alpha
// Dibuja el gradiente de fondo // Dibuja el gradiente de fondo
void renderGradient(); void renderGradient();
@@ -108,7 +107,7 @@ private:
public: public:
// Constructor // Constructor
Background(SDL_Renderer *renderer); explicit Background(SDL_Renderer *renderer);
// Destructor // Destructor
~Background(); ~Background();
@@ -141,7 +140,7 @@ public:
void setDstRect(SDL_Rect value); void setDstRect(SDL_Rect value);
// Establece el color de atenuación // Establece el color de atenuación
void setColor(color_t color); void setColor(Color color);
// Establece la transparencia de la atenuación // Establece la transparencia de la atenuación
void setAlpha(int alpha); void setAlpha(int alpha);

File diff suppressed because it is too large Load Diff

View File

@@ -1,77 +1,78 @@
#pragma once #pragma once
#include <SDL2/SDL_stdinc.h> // for Uint8, Uint16, Uint32 #include <SDL2/SDL_stdinc.h> // for Uint8, Uint16, Uint32
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "utils.h" // for circle_t #include "animated_sprite.h" // for AnimatedSprite
class AnimatedSprite; #include "utils.h" // for Circle
class Texture; class Texture;
// 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
#define MAX_BOUNCE 10 constexpr int MAX_BOUNCE = 10;
// Tipos de globo // Tipos de globo
#define BALLOON_1 1 constexpr int BALLOON_1 = 1;
#define BALLOON_2 2 constexpr int BALLOON_2 = 2;
#define BALLOON_3 3 constexpr int BALLOON_3 = 3;
#define BALLOON_4 4 constexpr int BALLOON_4 = 4;
#define HEXAGON_1 5 constexpr int HEXAGON_1 = 5;
#define HEXAGON_2 6 constexpr int HEXAGON_2 = 6;
#define HEXAGON_3 7 constexpr int HEXAGON_3 = 7;
#define HEXAGON_4 8 constexpr int HEXAGON_4 = 8;
#define POWER_BALL 9 constexpr int POWER_BALL = 9;
// Puntos de globo // Puntos de globo
#define BALLOON_SCORE_1 50 constexpr int BALLOON_SCORE_1 = 50;
#define BALLOON_SCORE_2 100 constexpr int BALLOON_SCORE_2 = 100;
#define BALLOON_SCORE_3 200 constexpr int BALLOON_SCORE_3 = 200;
#define BALLOON_SCORE_4 400 constexpr int BALLOON_SCORE_4 = 400;
// Tamaños de globo // Tamaños de globo
#define BALLOON_SIZE_1 1 constexpr int BALLOON_SIZE_1 = 1;
#define BALLOON_SIZE_2 2 constexpr int BALLOON_SIZE_2 = 2;
#define BALLOON_SIZE_3 3 constexpr int BALLOON_SIZE_3 = 3;
#define BALLOON_SIZE_4 4 constexpr int BALLOON_SIZE_4 = 4;
// Clases de globo // Clases de globo
#define BALLOON_CLASS 0 constexpr int BALLOON_CLASS = 0;
#define HEXAGON_CLASS 1 constexpr int HEXAGON_CLASS = 1;
// Velocidad del globo // Velocidad del globo
#define BALLOON_VELX_POSITIVE 0.7f constexpr float BALLOON_VELX_POSITIVE = 0.7f;
#define BALLOON_VELX_NEGATIVE -0.7f constexpr float BALLOON_VELX_NEGATIVE = -0.7f;
// Indice para las animaciones de los globos // Indice para las animaciones de los globos
#define BALLOON_MOVING_ANIMATION 0 constexpr int BALLOON_MOVING_ANIMATION = 0;
#define BALLOON_POP_ANIMATION 1 constexpr int BALLOON_POP_ANIMATION = 1;
#define BALLOON_BORN_ANIMATION 2 constexpr int BALLOON_BORN_ANIMATION = 2;
// Cantidad posible de globos // Cantidad posible de globos
#define MAX_BALLOONS 100 constexpr int MAX_BALLOONS = 100;
// Velocidades a las que se mueven los globos // Velocidades a las que se mueven los globos
#define BALLOON_SPEED_1 0.60f constexpr float BALLOON_SPEED_1 = 0.60f;
#define BALLOON_SPEED_2 0.70f constexpr float BALLOON_SPEED_2 = 0.70f;
#define BALLOON_SPEED_3 0.80f constexpr float BALLOON_SPEED_3 = 0.80f;
#define BALLOON_SPEED_4 0.90f constexpr float BALLOON_SPEED_4 = 0.90f;
#define BALLOON_SPEED_5 1.00f constexpr float BALLOON_SPEED_5 = 1.00f;
// Tamaño de los globos // Tamaño de los globos
#define BALLOON_WIDTH_1 10 constexpr int BALLOON_WIDTH_1 = 10;
#define BALLOON_WIDTH_2 16 constexpr int BALLOON_WIDTH_2 = 16;
#define BALLOON_WIDTH_3 26 constexpr int BALLOON_WIDTH_3 = 26;
#define BALLOON_WIDTH_4 46 constexpr int BALLOON_WIDTH_4 = 46;
// PowerBall // PowerBall
#define POWERBALL_SCREENPOWER_MINIMUM 10 constexpr int POWERBALL_SCREENPOWER_MINIMUM = 10;
#define POWERBALL_COUNTER 8 constexpr int POWERBALL_COUNTER = 8;
// Clase Balloon // Clase Balloon
class Balloon class Balloon
{ {
private: private:
// Estructura para las variables para el efecto de los rebotes // Estructura para las variables para el efecto de los rebotes
struct bouncing struct Bouncing
{ {
bool enabled; // Si el efecto está activo bool enabled; // Si el efecto está activo
Uint8 counter; // Countador para el efecto Uint8 counter; // Countador para el efecto
@@ -85,37 +86,37 @@ private:
}; };
// Objetos y punteros // Objetos y punteros
AnimatedSprite *sprite; // Sprite del objeto globo std::unique_ptr<AnimatedSprite> sprite_; // Sprite del objeto globo
// Variables // Variables
float posX; // Posición en el eje X float pos_x_; // Posición en el eje X
float posY; // Posición en el eje Y float pos_y_; // Posición en el eje Y
Uint8 width; // Ancho Uint8 width_; // Ancho
Uint8 height; // Alto Uint8 height_; // Alto
float velX; // Velocidad en el eje X. Cantidad de pixeles a desplazarse float vel_x_; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
float velY; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse float vel_y_; // 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 defaultVelY; // Velocidad inicial que tienen al rebotar contra el suelo float default_vel_y_; // Velocidad inicial que tienen al rebotar contra el suelo
float maxVelY; // Máxima velocidad que puede alcanzar el objeto en el eje Y float max_vel_y_; // Máxima velocidad que puede alcanzar el objeto en el eje Y
bool beingCreated; // 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 blinking_; // Indica si el globo está intermitente
bool enabled; // 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 visible; // Indica si el globo es visible bool visible_; // Indica si el globo es visible
circle_t collider; // Circulo de colisión del objeto Circle collider_; // Circulo de colisión del objeto
Uint16 creationCounter; // Temporizador para controlar el estado "creandose" Uint16 creation_counter_; // Temporizador para controlar el estado "creandose"
Uint16 creationCounterIni; // 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
Uint16 stoppedCounter; // Contador para controlar el estado "parado" Uint16 stopped_counter_; // Contador para controlar el estado "parado"
Uint8 kind; // Tipo de 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; // Contador interno Uint32 counter_; // Contador interno
float travelY; // 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 size; // Tamaño del globo Uint8 size_; // Tamaño del globo
Uint8 power; // Cantidad de poder que alberga el globo Uint8 power_; // Cantidad de poder que alberga el globo
bouncing bouncing; // Contiene las variables para el efecto de rebote 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 updateColliders();
@@ -140,10 +141,10 @@ private:
public: public:
// Constructor // Constructor
Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer, Texture *texture, std::vector<std::string> *animation); 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);
// Destructor // Destructor
~Balloon(); ~Balloon() = default;
// Centra el globo en la posición X // Centra el globo en la posición X
void allignTo(int x); void allignTo(int x);
@@ -164,86 +165,86 @@ public:
void update(); void update();
// Comprueba si el globo está habilitado // Comprueba si el globo está habilitado
bool isEnabled(); bool isEnabled() const;
// Obtiene del valor de la variable // Obtiene del valor de la variable
float getPosX(); float getPosX() const;
// Obtiene del valor de la variable // Obtiene del valor de la variable
float getPosY(); float getPosY() const;
// Obtiene del valor de la variable // Obtiene del valor de la variable
float getVelY(); float getVelY() const;
// Obtiene del valor de la variable // Obtiene del valor de la variable
int getWidth(); int getWidth() const;
// Obtiene del valor de la variable // Obtiene del valor de la variable
int getHeight(); int getHeight() const;
// Establece el valor de la variable // Establece el valor de la variable
void setVelY(float velY); void setVelY(float vel_y);
// Establece el valor de la variable // Establece el valor de la variable
void setSpeed(float speed); void setSpeed(float speed);
// Obtiene del valor de la variable // Obtiene del valor de la variable
int getKind(); int getKind() const;
// Obtiene del valor de la variable // Obtiene del valor de la variable
Uint8 getSize(); Uint8 getSize() const;
// Obtiene la clase a la que pertenece el globo // Obtiene la clase a la que pertenece el globo
Uint8 getClass(); Uint8 getClass() const;
// Establece el valor de la variable // Establece el valor de la variable
void setStop(bool value); void setStop(bool value);
// Obtiene del valor de la variable // Obtiene del valor de la variable
bool isStopped(); bool isStopped() const;
// Establece el valor de la variable // Establece el valor de la variable
void setBlink(bool value); void setBlink(bool value);
// Obtiene del valor de la variable // Obtiene del valor de la variable
bool isBlinking(); bool isBlinking() const;
// Establece el valor de la variable // Establece el valor de la variable
void setVisible(bool value); void setVisible(bool value);
// Obtiene del valor de la variable // Obtiene del valor de la variable
bool isVisible(); bool isVisible() const;
// Establece el valor de la variable // Establece el valor de la variable
void setInvulnerable(bool value); void setInvulnerable(bool value);
// Obtiene del valor de la variable // Obtiene del valor de la variable
bool isInvulnerable(); bool isInvulnerable() const;
// Obtiene del valor de la variable // Obtiene del valor de la variable
bool isBeingCreated(); bool isBeingCreated() const;
// Establece el valor de la variable // Establece el valor de la variable
void setStoppedTimer(Uint16 time); void setStoppedTimer(Uint16 time);
// Obtiene del valor de la variable // Obtiene del valor de la variable
Uint16 getStoppedTimer(); Uint16 getStoppedTimer() const;
// Obtiene del valor de la variable // Obtiene del valor de la variable
Uint16 getScore(); Uint16 getScore() const;
// Obtiene el circulo de colisión // Obtiene el circulo de colisión
circle_t &getCollider(); Circle &getCollider();
// Obtiene le valor de la variable // Obtiene le valor de la variable
Uint8 getMenace(); Uint8 getMenace() const;
// Obtiene le valor de la variable // Obtiene le valor de la variable
Uint8 getPower(); Uint8 getPower() const;
// Indica si el globo se puede explotar // Indica si el globo se puede explotar
bool canBePopped(); bool canBePopped() const;
// Indica si el globo se puede destruir // Indica si el globo se puede destruir
bool canBeDestroyed(); bool canBeDestroyed() const;
}; };

View File

@@ -0,0 +1,718 @@
#include "balloon_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
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_WIDTH_4;
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_WIDTH_3;
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_WIDTH_2;
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_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_BALLOON_FORMATIONS; i++)
{
balloon_formation_[i].number_of_balloons = 0;
for (int j = 0; j < MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION; j++)
{
balloon_formation_[i].init[j].x = 0;
balloon_formation_[i].init[j].y = 0;
balloon_formation_[i].init[j].vel_x = 0;
balloon_formation_[i].init[j].kind = 0;
balloon_formation_[i].init[j].creation_counter = 0;
}
}
const 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].kind = BALLOON_4;
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_WIDTH_4 / 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].kind = BALLOON_4;
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_WIDTH_2 + 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].kind = BALLOON_2;
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_WIDTH_2 + 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].kind = BALLOON_2;
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_WIDTH_3 * 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].kind = BALLOON_3;
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_WIDTH_3 * 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].kind = BALLOON_3;
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_WIDTH_3 + 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].kind = BALLOON_3;
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_WIDTH_3 + 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].kind = BALLOON_3;
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_WIDTH_1 + 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].kind = BALLOON_1;
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_WIDTH_1 + 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].kind = BALLOON_1;
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_WIDTH_4 + 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].kind = BALLOON_4;
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_WIDTH_4 + 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].kind = BALLOON_4;
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_WIDTH_2 + 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].kind = BALLOON_2;
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_WIDTH_2 + 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].kind = BALLOON_2;
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_WIDTH_3 * 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].kind = BALLOON_3;
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_WIDTH_3 * 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].kind = BALLOON_3;
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_WIDTH_3 + 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].kind = BALLOON_3;
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_WIDTH_3 + 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].kind = BALLOON_3;
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_WIDTH_1 + 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].kind = BALLOON_1;
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_WIDTH_1 + 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].kind = BALLOON_1;
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_WIDTH_4 + 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].kind = BALLOON_4;
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_WIDTH_2 + 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].kind = BALLOON_2;
}
// #22 - Diez enemigos BALLOON3. Hacia la derecha/izquierda. Separados. Simetricos
j = 22;
balloon_formation_[j].number_of_balloons = 10;
inc_x = BALLOON_WIDTH_3 * 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].kind = BALLOON_3;
}
// #23 - Diez enemigos BALLOON3. Hacia la derecha. Juntos. Simetricos
j = 23;
balloon_formation_[j].number_of_balloons = 10;
inc_x = BALLOON_WIDTH_3 + 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].kind = BALLOON_3;
}
// #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].kind = BALLOON_1;
}
// #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].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++)
{
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].kind = balloon_formation_[k].init[i].kind + 4;
}
}
// 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].kind = BALLOON_1;
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].kind = BALLOON_2;
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].kind = BALLOON_3;
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].kind = BALLOON_4;
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,63 @@
#pragma once
constexpr int NUMBER_OF_BALLOON_FORMATIONS = 100;
constexpr int MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION = 50;
// Estructuras
struct BalloonFormationParams
{
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 vel_x; // Velocidad inicial en el eje X
int kind; // Tipo de enemigo
int creation_counter; // Temporizador para la creación del enemigo
};
struct BalloonFormationUnit // Contiene la información de una formación enemiga
{
int number_of_balloons; // Cantidad de enemigos que forman la formación
BalloonFormationParams init[MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION]; // Vector con todas las inicializaciones de los enemigos de la formación
};
struct BalloonFormationPool
{
BalloonFormationUnit *set[10]; // 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_[10]; // Variable con los datos de cada pantalla
BalloonFormationUnit balloon_formation_[NUMBER_OF_BALLOON_FORMATIONS]; // Vector con todas las formaciones enemigas
BalloonFormationPool balloon_formation_pool_[10]; // 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,9 +1,9 @@
#include "bullet.h" #include "bullet.h"
#include <memory> // for unique_ptr, make_unique, shared_ptr
#include "param.h" // for param #include "param.h" // for param
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include <memory> // for std::unique_ptr class Texture;
// Constantes evaluables en tiempo de compilación
constexpr int BULLET_WIDTH = 12; constexpr int BULLET_WIDTH = 12;
constexpr int BULLET_HEIGHT = 12; constexpr int BULLET_HEIGHT = 12;
constexpr int BULLET_VELY = -3; constexpr int BULLET_VELY = -3;
@@ -11,47 +11,54 @@ constexpr int BULLET_VELX_LEFT = -2;
constexpr int BULLET_VELX_RIGHT = 2; constexpr int BULLET_VELX_RIGHT = 2;
// Constructor // Constructor
Bullet::Bullet(int x, int y, BulletType kind, bool poweredUp, int owner, SDL_Rect *playArea, Texture *texture) Bullet::Bullet(int x, int y, BulletType kind, bool powered_up, int owner, SDL_Rect *play_area, std::shared_ptr<Texture> texture)
: posX(x), posY(y), width(BULLET_WIDTH), height(BULLET_HEIGHT), velX(0), velY(BULLET_VELY), : sprite_(std::make_unique<Sprite>(SDL_Rect{x, y, BULLET_WIDTH, BULLET_HEIGHT}, texture)),
kind(kind), owner(owner), playArea(playArea), pos_x_(x),
sprite(std::unique_ptr<Sprite>(new Sprite(SDL_Rect{x, y, BULLET_WIDTH, BULLET_HEIGHT}, texture))) // Crear manualmente el std::unique_ptr pos_y_(y),
width_(BULLET_WIDTH),
height_(BULLET_HEIGHT),
vel_x_(0),
vel_y_(BULLET_VELY),
kind_(kind),
owner_(owner),
play_area_(play_area)
{ {
velX = (kind == BulletType::LEFT) ? BULLET_VELX_LEFT : (kind == BulletType::RIGHT) ? BULLET_VELX_RIGHT vel_x_ = (kind_ == BulletType::LEFT) ? BULLET_VELX_LEFT : (kind_ == BulletType::RIGHT) ? BULLET_VELX_RIGHT
: 0; : 0;
auto spriteOffset = poweredUp ? 3 : 0; auto sprite_offset = powered_up ? 3 : 0;
auto kindIndex = static_cast<int>(kind); auto kind_index = static_cast<int>(kind);
sprite->setSpriteClip((kindIndex + spriteOffset) * width, 0, sprite->getWidth(), sprite->getHeight()); sprite_->setSpriteClip((kind_index + sprite_offset) * width_, 0, sprite_->getWidth(), sprite_->getHeight());
collider.r = width / 2; collider_.r = width_ / 2;
shiftColliders(); shiftColliders();
} }
// Implementación de render (llama al render del sprite) // Implementación de render (llama al render del sprite_)
void Bullet::render() void Bullet::render()
{ {
sprite->render(); sprite_->render();
} }
// Implementación del movimiento usando BulletMoveStatus // Implementación del movimiento usando BulletMoveStatus
BulletMoveStatus Bullet::move() BulletMoveStatus Bullet::move()
{ {
posX += velX; pos_x_ += vel_x_;
if (posX < param.game.playArea.rect.x - width || posX > playArea->w) if (pos_x_ < param.game.play_area.rect.x - width_ || pos_x_ > play_area_->w)
{ {
disable(); disable();
return BulletMoveStatus::OUT; return BulletMoveStatus::OUT;
} }
posY += velY; pos_y_ += vel_y_;
if (posY < param.game.playArea.rect.y - height) if (pos_y_ < param.game.play_area.rect.y - height_)
{ {
disable(); disable();
return BulletMoveStatus::OUT; return BulletMoveStatus::OUT;
} }
sprite->setPosX(posX); sprite_->setPosX(pos_x_);
sprite->setPosY(posY); sprite_->setPosY(pos_y_);
shiftColliders(); shiftColliders();
return BulletMoveStatus::OK; return BulletMoveStatus::OK;
@@ -59,56 +66,56 @@ BulletMoveStatus Bullet::move()
bool Bullet::isEnabled() const bool Bullet::isEnabled() const
{ {
return kind != BulletType::NULL_TYPE; return kind_ != BulletType::NONE;
} }
void Bullet::disable() void Bullet::disable()
{ {
kind = BulletType::NULL_TYPE; kind_ = BulletType::NONE;
} }
int Bullet::getPosX() const int Bullet::getPosX() const
{ {
return posX; return pos_x_;
} }
int Bullet::getPosY() const int Bullet::getPosY() const
{ {
return posY; return pos_y_;
} }
void Bullet::setPosX(int x) void Bullet::setPosX(int x)
{ {
posX = x; pos_x_ = x;
} }
void Bullet::setPosY(int y) void Bullet::setPosY(int y)
{ {
posY = y; pos_y_ = y;
} }
int Bullet::getVelY() const int Bullet::getVelY() const
{ {
return velY; return vel_y_;
} }
BulletType Bullet::getKind() const BulletType Bullet::getKind() const
{ {
return kind; return kind_;
} }
int Bullet::getOwner() const int Bullet::getOwner() const
{ {
return owner; return owner_;
} }
circle_t &Bullet::getCollider() Circle &Bullet::getCollider()
{ {
return collider; return collider_;
} }
void Bullet::shiftColliders() void Bullet::shiftColliders()
{ {
collider.x = posX + collider.r; collider_.x = pos_x_ + collider_.r;
collider.y = posY + collider.r; collider_.y = pos_y_ + collider_.r;
} }

View File

@@ -2,10 +2,10 @@
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint8 #include <SDL2/SDL_stdinc.h> // for Uint8
#include <memory> // for unique_ptr #include <memory> // for shared_ptr, unique_ptr
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "utils.h" // for circle_t #include "utils.h" // for Circle
class Texture; // lines 9-9 class Texture;
// Enumeración para los diferentes tipos de balas // Enumeración para los diferentes tipos de balas
enum class BulletType enum class BulletType
@@ -13,7 +13,7 @@ enum class BulletType
UP, UP,
LEFT, LEFT,
RIGHT, RIGHT,
NULL_TYPE NONE
}; };
// Enumeración para los resultados del movimiento de la bala // Enumeración para los resultados del movimiento de la bala
@@ -27,36 +27,53 @@ enum class BulletMoveStatus : Uint8
class Bullet class Bullet
{ {
private: private:
int posX; // Posición en el eje X std::unique_ptr<Sprite> sprite_; // Sprite con los gráficos y métodos de pintado
int posY; // Posición en el eje Y
Uint8 width; // Ancho del objeto int pos_x_; // Posición en el eje X
Uint8 height; // Alto del objeto int pos_y_; // Posición en el eje Y
int velX; // Velocidad en el eje X Uint8 width_; // Ancho del objeto
int velY; // Velocidad en el eje Y Uint8 height_; // Alto del objeto
BulletType kind; // Tipo de objeto
int owner; // Identificador del dueño del objeto int vel_x_; // Velocidad en el eje X
circle_t collider; // Círculo de colisión del objeto int vel_y_; // Velocidad en el eje Y
SDL_Rect *playArea; // Rectángulo con la zona de juego
std::unique_ptr<Sprite> sprite; // Sprite con los gráficos y métodos de pintado 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
void shiftColliders(); // Alinea el círculo de colisión con el objeto void shiftColliders(); // Alinea el círculo de colisión con el objeto
public: public:
Bullet(int x, int y, BulletType kind, bool poweredUp, int owner, SDL_Rect *playArea, Texture *texture); // Constructor
Bullet(int x, int y, BulletType kind, bool powered_up, int owner, SDL_Rect *play_area, std::shared_ptr<Texture> texture);
// Destructor
~Bullet() = default; ~Bullet() = default;
void render(); // Pinta el objeto en pantalla // Pinta el objeto en pantalla
BulletMoveStatus move(); // Actualiza la posición y estado del objeto void render();
bool isEnabled() const; // Comprueba si el objeto está habilitado // Actualiza la posición y estado del objeto
void disable(); // Deshabilita el objeto BulletMoveStatus move();
// Comprueba si el objeto está habilitado
bool isEnabled() const;
// Deshabilita el objeto
void disable();
// Obtiene la posición
int getPosX() const; int getPosX() const;
int getPosY() const; int getPosY() const;
// Establece la posición
void setPosX(int x); void setPosX(int x);
void setPosY(int y); void setPosY(int y);
// Obtiene parámetros
int getVelY() const; int getVelY() const;
BulletType getKind() const; BulletType getKind() const;
int getOwner() const; int getOwner() const;
circle_t &getCollider(); Circle &getCollider();
}; };

View File

@@ -1,128 +1,123 @@
#include "define_buttons.h" #include "define_buttons.h"
#include <utility> // for move
#include "input.h" // for Input, InputType
#include "lang.h" // for getText #include "lang.h" // for getText
#include "options.h" // for options #include "options.h" // for options
#include "param.h" // for param #include "param.h" // for param
#include "section.h" // for name, name_e, options, options_e #include "section.h" // for Name, Options, name, options
#include "text.h" // for Text #include "text.h" // for Text
#include "utils.h" // for op_controller_t, options_t, param_t, paramGame_t #include "utils.h" // for OptionsController, Options, Param, ParamGame
// Constructor // Constructor
DefineButtons::DefineButtons(Text *text) DefineButtons::DefineButtons(std::unique_ptr<Text> text_)
: text_(std::move(text_))
{ {
// Copia punteros a los objetos // Copia punteros a los objetos
input = Input::get(); input_ = Input::get();
this->text = text;
// Inicializa variables // Inicializa variables
enabled = false; enabled_ = false;
x = param.game.width / 2; x_ = param.game.width / 2;
y = param.title.pressStartPosition; y_ = param.title.press_start_position;
indexController = 0; index_controller_ = 0;
indexButton = 0; index_button_ = 0;
buttons.clear(); buttons_.clear();
db_button_t button; DefineButtonsButton button;
button.label = lang::getText(95); button.label = lang::getText(95);
button.input = input_fire_left; button.input = InputType::FIRE_LEFT;
button.button = SDL_CONTROLLER_BUTTON_X; button.button = SDL_CONTROLLER_BUTTON_X;
buttons.push_back(button); buttons_.push_back(button);
button.label = lang::getText(96); button.label = lang::getText(96);
button.input = input_fire_center; button.input = InputType::FIRE_CENTER;
button.button = SDL_CONTROLLER_BUTTON_Y; button.button = SDL_CONTROLLER_BUTTON_Y;
buttons.push_back(button); buttons_.push_back(button);
button.label = lang::getText(97); button.label = lang::getText(97);
button.input = input_fire_right; button.input = InputType::FIRE_RIGHT;
button.button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER; button.button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
buttons.push_back(button); buttons_.push_back(button);
button.label = lang::getText(98); button.label = lang::getText(98);
button.input = input_start; button.input = InputType::START;
button.button = SDL_CONTROLLER_BUTTON_START; button.button = SDL_CONTROLLER_BUTTON_START;
buttons.push_back(button); buttons_.push_back(button);
button.label = lang::getText(99); button.label = lang::getText(99);
button.input = input_exit; button.input = InputType::EXIT;
button.button = SDL_CONTROLLER_BUTTON_BACK; button.button = SDL_CONTROLLER_BUTTON_BACK;
buttons.push_back(button); buttons_.push_back(button);
for (int i = 0; i < input->getNumControllers(); ++i) for (int i = 0; i < input_->getNumControllers(); ++i)
{
controllerNames.push_back(input->getControllerName(i));
}
}
// Destructor
DefineButtons::~DefineButtons()
{
}
// Actualiza las variables del objeto
void DefineButtons::update()
{
if (enabled)
{ {
controller_names_.push_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].playerId)); text_->writeCentered(x_, y_ - 10, lang::getText(100) + std::to_string(options.controller[index_controller_].player_id));
text->writeCentered(x, y, controllerNames[indexController]); text_->writeCentered(x_, y_, controller_names_[index_controller_]);
text->writeCentered(x, y + 10, buttons[indexButton].label); text_->writeCentered(x_, y_ + 10, buttons_[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(SDL_ControllerButtonEvent *event)
{ {
int i = input->getJoyIndex(event->which); int i = input_->getJoyIndex(event->which);
// Solo pillamos botones del mando que toca // Solo pillamos botones del mando que toca
if (i != indexController) if (i != index_controller_)
{ {
return; return;
} }
buttons[indexButton].button = (SDL_GameControllerButton)event->button; buttons_[index_button_].button = (SDL_GameControllerButton)event->button;
incIndexButton(); incIndexButton();
} }
// Asigna los botones definidos al input // Asigna los botones definidos al input_
void DefineButtons::bindButtons() void DefineButtons::bindButtons()
{ {
for (int i = 0; i < (int)buttons.size(); ++i) for (int i = 0; i < (int)buttons_.size(); ++i)
{ {
input->bindGameControllerButton(indexController, buttons[i].input, buttons[i].button); input_->bindGameControllerButton(index_controller_, buttons_[i].input, buttons_[i].button);
} }
} }
// Comprueba las entradas // Comprueba las entradas
void DefineButtons::checkInput() void DefineButtons::checkInput()
{ {
if (enabled) 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_NORMAL;
break; break;
} }
if (event.type == SDL_CONTROLLERBUTTONDOWN) case SDL_CONTROLLERBUTTONDOWN:
{ {
doControllerButtonDown(&event.cbutton); doControllerButtonDown(&event.cbutton);
break;
}
default:
break;
} }
} }
} }
@@ -131,11 +126,11 @@ 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;
return true; return true;
} }
@@ -145,29 +140,29 @@ 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_ == (int)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); //input_->allActive(index_controller_);
// Reinicia variables // Reinicia variables
indexButton = 0; index_button_ = 0;
indexController = 0; index_controller_ = 0;
enabled = false; enabled_ = false;
} }
} }
@@ -175,17 +170,17 @@ 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); options.controller[index_controller_].name = input_->getControllerName(index_controller_);
for (int j = 0; j < (int)options.controller[indexController].inputs.size(); ++j) for (int j = 0; j < (int)options.controller[index_controller_].inputs.size(); ++j)
{ {
options.controller[indexController].buttons[j] = input->getControllerBinding(indexController, options.controller[indexController].inputs[j]); options.controller[index_controller_].buttons[j] = input_->getControllerBinding(index_controller_, options.controller[index_controller_].inputs[j]);
} }
} }
// Intercambia los jugadores asignados a los dos primeros mandos // Intercambia los jugadores asignados a los dos primeros mandos
void DefineButtons::swapControllers() void DefineButtons::swapControllers()
{ {
const int temp = options.controller[0].playerId; const int temp = options.controller[0].player_id;
options.controller[0].playerId = options.controller[1].playerId; options.controller[0].player_id = options.controller[1].player_id;
options.controller[1].playerId = temp; options.controller[1].player_id = temp;
} }

View File

@@ -2,15 +2,17 @@
#include <SDL2/SDL_events.h> // for SDL_ControllerButtonEvent #include <SDL2/SDL_events.h> // for SDL_ControllerButtonEvent
#include <SDL2/SDL_gamecontroller.h> // for SDL_GameControllerButton #include <SDL2/SDL_gamecontroller.h> // for SDL_GameControllerButton
#include <string> // for string, basic_string #include <memory> // for shared_ptr, unique_ptr
#include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "input.h" // for inputs_e class Input;
class Text; class Text;
enum class InputType : int;
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
}; };
@@ -19,17 +21,17 @@ class DefineButtons
{ {
private: private:
// Objetos // Objetos
Input *input; // Objeto pata gestionar la entrada Input *input_; // Objeto pata gestionar la entrada
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_; // 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 int index_controller_; // Indice del controlador a reasignar
int indexButton; // Indice para saber qué bot´çon se está definiendo int index_button_; // Indice para saber qué bot´çon 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();
@@ -45,13 +47,10 @@ private:
public: public:
// Constructor // Constructor
DefineButtons(Text *text); explicit DefineButtons(std::unique_ptr<Text> text);
// Destructor // Destructor
~DefineButtons(); ~DefineButtons() = default;
// Actualiza las variables del objeto
void update();
// Dibuja el objeto en pantalla // Dibuja el objeto en pantalla
void render(); void render();

View File

@@ -5,49 +5,52 @@
#include <SDL2/SDL_error.h> // for SDL_GetError #include <SDL2/SDL_error.h> // for SDL_GetError
#include <SDL2/SDL_gamecontroller.h> // for SDL_CONTROLLER_BUTTON_B, SDL_CO... #include <SDL2/SDL_gamecontroller.h> // for SDL_CONTROLLER_BUTTON_B, SDL_CO...
#include <SDL2/SDL_hints.h> // for SDL_SetHint, SDL_HINT_RENDER_DR... #include <SDL2/SDL_hints.h> // for SDL_SetHint, SDL_HINT_RENDER_DR...
#include <SDL2/SDL_scancode.h> // for SDL_SCANCODE_DOWN, SDL_SCANCODE_E #include <SDL2/SDL_scancode.h> // for SDL_SCANCODE_0, SDL_SCANCODE_DOWN
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <SDL2/SDL_stdinc.h> // for SDL_bool, Uint32
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <errno.h> // for errno, EACCES, EEXIST, ENAMETOO... #include <errno.h> // for errno, EEXIST, EACCES, ENAMETOO...
#include <stdio.h> // for printf, perror, size_t #include <stdio.h> // for printf, perror
#include <string.h> // for strcmp #include <string.h> // for strcmp
#include <sys/stat.h> // for stat, mkdir, S_IRWXU #include <sys/stat.h> // for mkdir, stat, S_IRWXU
#include <unistd.h> // for getuid #include <unistd.h> // for getuid
#include <cstdlib> // for exit, EXIT_FAILURE, rand, srand #include <cstdlib> // for exit, EXIT_FAILURE, rand, srand
#include <iostream> // for basic_ostream, operator<<, cout #include <iostream> // for basic_ostream, operator<<, cout
#include <string> // for basic_string, operator+, allocator #include <memory> // for make_unique, unique_ptr
#include "asset.h" // for Asset, assetType #include <string> // for operator+, allocator, char_traits
#include "asset.h" // for Asset, AssetType
#include "dbgtxt.h" // for dbg_init #include "dbgtxt.h" // for dbg_init
#include "game.h" // for Game, GAME_MODE_DEMO_OFF, GAME_... #include "game.h" // for Game, GAME_MODE_DEMO_OFF, GAME_...
#include "global_inputs.h" // for init
#include "hiscore_table.h" // for HiScoreTable #include "hiscore_table.h" // for HiScoreTable
#include "input.h" // for inputs_e, Input #include "input.h" // for Input, InputType
#include "instructions.h" // for Instructions #include "instructions.h" // for Instructions
#include "intro.h" // for Intro #include "intro.h" // for Intro
#include "jail_audio.h" // for JA_DeleteMusic, JA_DeleteSound #include "jail_audio.h" // for JA_LoadMusic, JA_LoadSound, JA_...
#include "lang.h" // for Code, loadFromFile
#include "logo.h" // for Logo #include "logo.h" // for Logo
#include "manage_hiscore_table.h" // for ManageHiScoreTable #include "manage_hiscore_table.h" // for ManageHiScoreTable
#include "on_screen_help.h" // for OnScreenHelp #include "on_screen_help.h" // for OnScreenHelp
#include "options.h" // for options, loadOptionsFile, saveO... #include "options.h" // for options, loadOptionsFile, saveO...
#include "param.h" // for param, loadParamsFromFile #include "param.h" // for param, loadParamsFromFile
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "section.h" // for name_e, name, options, options_e #include "section.h" // for Name, name, Options, options
#include "title.h" // for Title #include "title.h" // for Title
#include "utils.h" // for music_file_t, sound_file_t, opt... #include "utils.h" // for MusicFile, SoundFile, Options
#ifndef _WIN32 #ifndef _WIN32
#include <pwd.h> // for getpwuid, passwd #include <pwd.h> // for getpwuid, passwd
#endif #endif
// Constructor // Constructor
Director::Director(int argc, char *argv[]) Director::Director(int argc, const char *argv[])
{ {
#ifdef RECORDING #ifdef RECORDING
section::name = section::NAME_GAME; section::name = section::Name::GAME;
section::options = section::OPTIONS_GAME_PLAY_1P; section::options = section::Options::GAME_PLAY_1P;
#elif DEBUG #elif DEBUG
section::name = section::NAME_LOGO; section::name = section::Name::LOGO;
#else #else
section::name = section::NAME_LOGO; section::name = section::Name::LOGO;
#endif #endif
// Comprueba los parametros del programa // Comprueba los parametros del programa
@@ -58,8 +61,7 @@ Director::Director(int argc, char *argv[])
createSystemFolder("jailgames/coffee_crisis_arcade_edition"); createSystemFolder("jailgames/coffee_crisis_arcade_edition");
// Crea el objeto que controla los ficheros de recursos // Crea el objeto que controla los ficheros de recursos
Asset::init(executablePath); Asset::init(executable_path_);
asset = Asset::get();
// Si falta algún fichero no inicia el programa // Si falta algún fichero no inicia el programa
if (!setFileList()) if (!setFileList())
@@ -68,20 +70,19 @@ Director::Director(int argc, char *argv[])
} }
// Carga el fichero de configuración // Carga el fichero de configuración
loadOptionsFile(asset->get("config.txt")); loadOptionsFile(Asset::get()->get("config.txt"));
// Carga los parametros para configurar el juego // Carga los parametros para configurar el juego
#ifdef ANBERNIC #ifdef ANBERNIC
const std::string paramFilePath = asset->get("param_320x240.txt"); const std::string paramFilePath = asset->get("param_320x240.txt");
#else #else
const std::string paramFilePath = paramFileArgument == "--320x240" ? asset->get("param_320x240.txt") : asset->get("param_320x256.txt"); const std::string paramFilePath = param_file_argument_ == "--320x240" ? Asset::get()->get("param_320x240.txt") : Asset::get()->get("param_320x256.txt");
#endif #endif
loadParams(paramFilePath); loadParams(paramFilePath);
// Carga el fichero de puntuaciones // Carga el fichero de puntuaciones
ManageHiScoreTable *manager = new ManageHiScoreTable(&options.game.hiScoreTable); auto manager = std::make_unique<ManageHiScoreTable>(&options.game.hi_score_table);
manager->loadFromFile(asset->get("score.bin")); manager->loadFromFile(Asset::get()->get("score.bin"));
delete manager;
// Inicializa SDL // Inicializa SDL
initSDL(); initSDL();
@@ -90,17 +91,15 @@ Director::Director(int argc, char *argv[])
initJailAudio(); initJailAudio();
// Inicializa el texto de debug // Inicializa el texto de debug
dbg_init(renderer); dbg_init(renderer_);
// Crea los objetos // Crea los objetos
lang::loadFromFile(getLangFile((lang::lang_e)options.game.language)); lang::loadFromFile(getLangFile((lang::Code)options.game.language));
Input::init(asset->get("gamecontrollerdb.txt")); Input::init(Asset::get()->get("gamecontrollerdb.txt"));
input = Input::get();
initInput(); initInput();
Screen::init(window, renderer); Screen::init(window_, renderer_);
screen = Screen::get();
OnScreenHelp::init(); OnScreenHelp::init();
@@ -109,119 +108,118 @@ Director::Director(int argc, char *argv[])
// Carga las musicas del juego // Carga las musicas del juego
loadMusics(); loadMusics();
globalInputs::init();
} }
Director::~Director() Director::~Director()
{ {
saveOptionsFile(asset->get("config.txt")); saveOptionsFile(Asset::get()->get("config.txt"));
Asset::destroy(); Asset::destroy();
Input::destroy(); Input::destroy();
Screen::destroy(); Screen::destroy();
OnScreenHelp::destroy(); OnScreenHelp::destroy();
deleteSounds(); sounds_.clear();
deleteMusics(); musics_.clear();
SDL_DestroyRenderer(renderer); SDL_DestroyRenderer(renderer_);
SDL_DestroyWindow(window); SDL_DestroyWindow(window_);
SDL_Quit(); SDL_Quit();
} }
// Inicializa el objeto input /// Inicializa el objeto input
void Director::initInput() void Director::initInput()
{ {
// Establece si ha de mostrar mensajes
#ifdef VERBOSE
input->setVerbose(true);
#else
input->setVerbose(false);
#endif
// Busca si hay mandos conectados // Busca si hay mandos conectados
input->discoverGameControllers(); Input::get()->discoverGameControllers();
// Teclado - Movimiento del jugador // Teclado - Movimiento del jugador
input->bindKey(input_up, SDL_SCANCODE_UP); Input::get()->bindKey(InputType::UP, SDL_SCANCODE_UP);
input->bindKey(input_down, SDL_SCANCODE_DOWN); Input::get()->bindKey(InputType::DOWN, SDL_SCANCODE_DOWN);
input->bindKey(input_left, SDL_SCANCODE_LEFT); Input::get()->bindKey(InputType::LEFT, SDL_SCANCODE_LEFT);
input->bindKey(input_right, SDL_SCANCODE_RIGHT); Input::get()->bindKey(InputType::RIGHT, SDL_SCANCODE_RIGHT);
input->bindKey(input_fire_left, SDL_SCANCODE_Q); Input::get()->bindKey(InputType::FIRE_LEFT, SDL_SCANCODE_Q);
input->bindKey(input_fire_center, SDL_SCANCODE_W); Input::get()->bindKey(InputType::FIRE_CENTER, SDL_SCANCODE_W);
input->bindKey(input_fire_right, SDL_SCANCODE_E); Input::get()->bindKey(InputType::FIRE_RIGHT, SDL_SCANCODE_E);
input->bindKey(input_start, SDL_SCANCODE_RETURN); Input::get()->bindKey(InputType::START, SDL_SCANCODE_RETURN);
// Teclado - Control del programa // Teclado - Control del programa
input->bindKey(input_service, SDL_SCANCODE_0); Input::get()->bindKey(InputType::SERVICE, SDL_SCANCODE_0);
input->bindKey(input_exit, SDL_SCANCODE_ESCAPE); Input::get()->bindKey(InputType::EXIT, SDL_SCANCODE_ESCAPE);
input->bindKey(input_pause, SDL_SCANCODE_P); Input::get()->bindKey(InputType::PAUSE, SDL_SCANCODE_P);
input->bindKey(input_window_dec_size, SDL_SCANCODE_F1); Input::get()->bindKey(InputType::WINDOW_DEC_SIZE, SDL_SCANCODE_F1);
input->bindKey(input_window_inc_size, SDL_SCANCODE_F2); Input::get()->bindKey(InputType::WINDOW_INC_SIZE, SDL_SCANCODE_F2);
input->bindKey(input_window_fullscreen, SDL_SCANCODE_F3); Input::get()->bindKey(InputType::WINDOW_FULLSCREEN, SDL_SCANCODE_F3);
input->bindKey(input_video_shaders, SDL_SCANCODE_F4); Input::get()->bindKey(InputType::VIDEO_SHADERS, SDL_SCANCODE_F4);
input->bindKey(input_mute, SDL_SCANCODE_F5); Input::get()->bindKey(InputType::MUTE, SDL_SCANCODE_F5);
input->bindKey(input_showinfo, SDL_SCANCODE_F6); Input::get()->bindKey(InputType::SHOWINFO, SDL_SCANCODE_F6);
input->bindKey(input_reset, SDL_SCANCODE_F10); Input::get()->bindKey(InputType::RESET, SDL_SCANCODE_F10);
// Asigna botones a inputs // Asigna botones a inputs
const int numGamePads = input->getNumControllers(); const int num_gamepads = Input::get()->getNumControllers();
for (int i = 0; i < numGamePads; ++i) for (int i = 0; i < num_gamepads; ++i)
{ {
// Mando - Movimiento del jugador // Mando - Movimiento del jugador
input->bindGameControllerButton(i, input_up, SDL_CONTROLLER_BUTTON_DPAD_UP); Input::get()->bindGameControllerButton(i, InputType::UP, SDL_CONTROLLER_BUTTON_DPAD_UP);
input->bindGameControllerButton(i, input_down, SDL_CONTROLLER_BUTTON_DPAD_DOWN); Input::get()->bindGameControllerButton(i, InputType::DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
input->bindGameControllerButton(i, input_left, SDL_CONTROLLER_BUTTON_DPAD_LEFT); Input::get()->bindGameControllerButton(i, InputType::LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
input->bindGameControllerButton(i, input_right, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); Input::get()->bindGameControllerButton(i, InputType::RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
input->bindGameControllerButton(i, input_fire_left, SDL_CONTROLLER_BUTTON_X); Input::get()->bindGameControllerButton(i, InputType::FIRE_LEFT, SDL_CONTROLLER_BUTTON_X);
input->bindGameControllerButton(i, input_fire_center, SDL_CONTROLLER_BUTTON_Y); Input::get()->bindGameControllerButton(i, InputType::FIRE_CENTER, SDL_CONTROLLER_BUTTON_Y);
input->bindGameControllerButton(i, input_fire_right, SDL_CONTROLLER_BUTTON_B); Input::get()->bindGameControllerButton(i, InputType::FIRE_RIGHT, SDL_CONTROLLER_BUTTON_B);
input->bindGameControllerButton(i, input_start, SDL_CONTROLLER_BUTTON_START); Input::get()->bindGameControllerButton(i, InputType::START, SDL_CONTROLLER_BUTTON_START);
// Mando - Control del programa // Mando - Control del programa
input->bindGameControllerButton(i, input_service, SDL_CONTROLLER_BUTTON_BACK); Input::get()->bindGameControllerButton(i, InputType::SERVICE, SDL_CONTROLLER_BUTTON_BACK);
input->bindGameControllerButton(i, input_exit, input_start); Input::get()->bindGameControllerButton(i, InputType::EXIT, InputType::START);
input->bindGameControllerButton(i, input_pause, input_fire_right); Input::get()->bindGameControllerButton(i, InputType::PAUSE, InputType::FIRE_RIGHT);
input->bindGameControllerButton(i, input_video_shaders, input_fire_left); Input::get()->bindGameControllerButton(i, InputType::VIDEO_SHADERS, InputType::FIRE_LEFT);
input->bindGameControllerButton(i, input_mute, input_left); Input::get()->bindGameControllerButton(i, InputType::MUTE, InputType::LEFT);
input->bindGameControllerButton(i, input_showinfo, input_right); Input::get()->bindGameControllerButton(i, InputType::SHOWINFO, InputType::RIGHT);
input->bindGameControllerButton(i, input_reset, input_fire_center); Input::get()->bindGameControllerButton(i, InputType::RESET, InputType::FIRE_CENTER);
input->bindGameControllerButton(i, input_config, input_down); Input::get()->bindGameControllerButton(i, InputType::CONFIG, InputType::DOWN);
input->bindGameControllerButton(i, input_swap_controllers, input_up); Input::get()->bindGameControllerButton(i, InputType::SWAP_CONTROLLERS, InputType::UP);
} }
// Mapea las asignaciones a los botones desde el archivo de configuración, si se da el caso // Mapea las asignaciones a los botones desde el archivo de configuración, si se da el caso
for (int i = 0; i < numGamePads; ++i) for (int i = 0; i < num_gamepads; ++i)
for (int index = 0; index < (int)options.controller.size(); ++index) for (int index = 0; index < (int)options.controller.size(); ++index)
if (input->getControllerName(i) == options.controller[index].name) if (Input::get()->getControllerName(i) == options.controller[index].name)
{
options.controller[index].plugged = true;
for (int j = 0; j < (int)options.controller[index].inputs.size(); ++j) for (int j = 0; j < (int)options.controller[index].inputs.size(); ++j)
{ {
input->bindGameControllerButton(i, options.controller[index].inputs[j], options.controller[index].buttons[j]); Input::get()->bindGameControllerButton(i, options.controller[index].inputs[j], options.controller[index].buttons[j]);
}
} }
// Asigna botones a inputs desde otros inputs // Asigna botones a inputs desde otros inputs
for (int i = 0; i < numGamePads; ++i) for (int i = 0; i < num_gamepads; ++i)
{ {
input->bindGameControllerButton(i, input_exit, input_start); Input::get()->bindGameControllerButton(i, InputType::EXIT, InputType::START);
input->bindGameControllerButton(i, input_reset, input_fire_center); Input::get()->bindGameControllerButton(i, InputType::RESET, InputType::FIRE_CENTER);
input->bindGameControllerButton(i, input_pause, input_fire_right); Input::get()->bindGameControllerButton(i, InputType::PAUSE, InputType::FIRE_RIGHT);
input->bindGameControllerButton(i, input_video_shaders, input_fire_left); Input::get()->bindGameControllerButton(i, InputType::VIDEO_SHADERS, InputType::FIRE_LEFT);
input->bindGameControllerButton(i, input_mute, input_left); Input::get()->bindGameControllerButton(i, InputType::MUTE, InputType::LEFT);
input->bindGameControllerButton(i, input_showinfo, input_right); Input::get()->bindGameControllerButton(i, InputType::SHOWINFO, InputType::RIGHT);
input->bindGameControllerButton(i, input_config, input_down); Input::get()->bindGameControllerButton(i, InputType::CONFIG, InputType::DOWN);
input->bindGameControllerButton(i, input_swap_controllers, input_up); Input::get()->bindGameControllerButton(i, InputType::SWAP_CONTROLLERS, InputType::UP);
} }
// Guarda las asignaciones de botones en las opciones // Guarda las asignaciones de botones en las opciones
for (int i = 0; i < numGamePads; ++i) for (int i = 0; i < num_gamepads; ++i)
{ {
options.controller[i].name = input->getControllerName(i); options.controller[i].name = Input::get()->getControllerName(i);
for (int j = 0; j < (int)options.controller[i].inputs.size(); ++j) for (int j = 0; j < (int)options.controller[i].inputs.size(); ++j)
{ {
options.controller[i].buttons[j] = input->getControllerBinding(i, options.controller[i].inputs[j]); options.controller[i].buttons[j] = Input::get()->getControllerBinding(i, options.controller[i].inputs[j]);
} }
} }
} }
@@ -240,7 +238,7 @@ void Director::initJailAudio()
bool Director::initSDL() bool Director::initSDL()
{ {
// Indicador de éxito // Indicador de éxito
bool success = true; auto success = true;
// Inicializa SDL // Inicializa SDL
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
@@ -272,7 +270,7 @@ bool Director::initSDL()
#endif #endif
// Establece el filtro de la textura // Establece el filtro de la textura
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, std::to_string(options.video.filter).c_str())) if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, std::to_string(static_cast<int>(options.video.filter)).c_str()))
{ {
#ifdef VERBOSE #ifdef VERBOSE
std::cout << "Warning: texture filtering not enabled!\n"; std::cout << "Warning: texture filtering not enabled!\n";
@@ -287,8 +285,8 @@ bool Director::initSDL()
} }
#endif // NO_SHADERS #endif // NO_SHADERS
// Crea la ventana // Crea la ventana
window = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, param.game.width * options.video.window.size, param.game.height * options.video.window.size, SDL_WINDOW_HIDDEN); window_ = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, param.game.width * options.video.window.size, param.game.height * options.video.window.size, SDL_WINDOW_HIDDEN);
if (window == nullptr) if (!window_)
{ {
#ifdef VERBOSE #ifdef VERBOSE
std::cout << "Window could not be created!\nSDL Error: " << SDL_GetError() << std::endl; std::cout << "Window could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
@@ -299,17 +297,17 @@ bool Director::initSDL()
{ {
// Crea un renderizador para la ventana. El vsync se activa en funcion de las opciones // Crea un renderizador para la ventana. El vsync se activa en funcion de las opciones
Uint32 flags = 0; Uint32 flags = 0;
if (options.video.vSync) if (options.video.v_sync)
{ {
flags = flags | SDL_RENDERER_PRESENTVSYNC; flags = SDL_RENDERER_PRESENTVSYNC;
} }
#ifndef NO_SHADERS #ifndef NO_SHADERS
// La aceleración se activa según el define // La aceleración se activa según el define
flags = flags | SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE; flags = flags | SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
#endif #endif
renderer = SDL_CreateRenderer(window, -1, flags); renderer_ = SDL_CreateRenderer(window_, -1, flags);
if (renderer == nullptr) if (!renderer_)
{ {
#ifdef VERBOSE #ifdef VERBOSE
std::cout << "Renderer could not be created!\nSDL Error: " << SDL_GetError() << std::endl; std::cout << "Renderer could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
@@ -319,13 +317,14 @@ bool Director::initSDL()
else else
{ {
// Inicializa el color de renderizado // Inicializa el color de renderizado
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
// Establece el tamaño del buffer de renderizado // Establece el tamaño del buffer de renderizado
SDL_RenderSetLogicalSize(renderer, param.game.width, param.game.height); SDL_RenderSetLogicalSize(renderer_, param.game.width, param.game.height);
SDL_RenderSetIntegerScale(renderer_, static_cast<SDL_bool>(options.video.integer_scale));
// Establece el modo de mezcla // Establece el modo de mezcla
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
} }
} }
} }
@@ -342,197 +341,202 @@ bool Director::setFileList()
#ifdef MACOS_BUNDLE #ifdef MACOS_BUNDLE
const std::string prefix = "/../Resources"; const std::string prefix = "/../Resources";
#else #else
const std::string prefix = ""; const std::string prefix;
#endif #endif
// Ficheros de configuración // Ficheros de configuración
asset->add(systemFolder + "/config.txt", t_data, false, true); Asset::get()->add(system_folder_ + "/config.txt", AssetType::DATA, false, true);
asset->add(systemFolder + "/score.bin", t_data, false, true); Asset::get()->add(system_folder_ + "/score.bin", AssetType::DATA, false, true);
asset->add(prefix + "/data/config/param_320x240.txt", t_data); Asset::get()->add(prefix + "/data/config/param_320x240.txt", AssetType::DATA);
asset->add(prefix + "/data/config/param_320x256.txt", t_data); Asset::get()->add(prefix + "/data/config/param_320x256.txt", AssetType::DATA);
asset->add(prefix + "/data/config/demo1.bin", t_data); Asset::get()->add(prefix + "/data/config/demo1.bin", AssetType::DATA);
asset->add(prefix + "/data/config/demo2.bin", t_data); Asset::get()->add(prefix + "/data/config/demo2.bin", AssetType::DATA);
asset->add(prefix + "/data/config/gamecontrollerdb.txt", t_data); Asset::get()->add(prefix + "/data/config/gamecontrollerdb.txt", AssetType::DATA);
// Musicas // Musicas
asset->add(prefix + "/data/music/intro.ogg", t_music); Asset::get()->add(prefix + "/data/music/intro.ogg", AssetType::MUSIC);
asset->add(prefix + "/data/music/playing.ogg", t_music); Asset::get()->add(prefix + "/data/music/playing.ogg", AssetType::MUSIC);
asset->add(prefix + "/data/music/title.ogg", t_music); Asset::get()->add(prefix + "/data/music/title.ogg", AssetType::MUSIC);
// Sonidos // Sonidos
asset->add(prefix + "/data/sound/balloon.wav", t_sound); Asset::get()->add(prefix + "/data/sound/balloon.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/bubble1.wav", t_sound); Asset::get()->add(prefix + "/data/sound/bubble1.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/bubble2.wav", t_sound); Asset::get()->add(prefix + "/data/sound/bubble2.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/bubble3.wav", t_sound); Asset::get()->add(prefix + "/data/sound/bubble3.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/bubble4.wav", t_sound); Asset::get()->add(prefix + "/data/sound/bubble4.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/bullet.wav", t_sound); Asset::get()->add(prefix + "/data/sound/bullet.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/coffeeout.wav", t_sound); Asset::get()->add(prefix + "/data/sound/coffeeout.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/hiscore.wav", t_sound); Asset::get()->add(prefix + "/data/sound/hiscore.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/itemdrop.wav", t_sound); Asset::get()->add(prefix + "/data/sound/itemdrop.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/itempickup.wav", t_sound); Asset::get()->add(prefix + "/data/sound/itempickup.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/player_collision.wav", t_sound); Asset::get()->add(prefix + "/data/sound/player_collision.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/stage_change.wav", t_sound); Asset::get()->add(prefix + "/data/sound/stage_change.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/title.wav", t_sound); Asset::get()->add(prefix + "/data/sound/title.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/clock.wav", t_sound); Asset::get()->add(prefix + "/data/sound/clock.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/powerball.wav", t_sound); Asset::get()->add(prefix + "/data/sound/powerball.wav", AssetType::SOUND);
asset->add(prefix + "/data/sound/notify.wav", t_sound); Asset::get()->add(prefix + "/data/sound/notify.wav", AssetType::SOUND);
// Shaders // Shaders
asset->add(prefix + "/data/shaders/crtpi.glsl", t_data); Asset::get()->add(prefix + "/data/shaders/crtpi.glsl", AssetType::DATA);
// Texturas // Texturas
asset->add(prefix + "/data/gfx/controllers/controllers.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/controllers/controllers.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/balloon/balloon1.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/balloon/balloon1.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/balloon/balloon1.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/balloon/balloon1.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/balloon/balloon2.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/balloon/balloon2.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/balloon/balloon2.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/balloon/balloon2.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/balloon/balloon3.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/balloon/balloon3.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/balloon/balloon3.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/balloon/balloon3.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/balloon/balloon4.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/balloon/balloon4.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/balloon/balloon4.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/balloon/balloon4.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/balloon/explosion1.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/balloon/explosion1.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/balloon/explosion1.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/balloon/explosion1.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/balloon/explosion2.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/balloon/explosion2.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/balloon/explosion2.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/balloon/explosion2.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/balloon/explosion3.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/balloon/explosion3.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/balloon/explosion3.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/balloon/explosion3.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/balloon/explosion4.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/balloon/explosion4.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/balloon/explosion4.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/balloon/explosion4.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/balloon/powerball.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/balloon/powerball.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/balloon/powerball.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/balloon/powerball.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/bullet/bullet.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/bullet/bullet.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/game/game_buildings.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/game/game_buildings.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/game/game_clouds1.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/game/game_clouds1.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/game/game_clouds2.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/game/game_clouds2.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/game/game_grass.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/game/game_grass.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/game/game_power_meter.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/game/game_power_meter.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/game/game_sky_colors.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/game/game_sky_colors.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/game/game_text.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/game/game_text.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/intro/intro.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/intro/intro.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/logo/logo_jailgames.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/logo/logo_jailgames.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/logo/logo_jailgames_mini.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/logo/logo_jailgames_mini.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/logo/logo_since_1998.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/logo/logo_since_1998.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/item/item_points1_disk.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/item/item_points1_disk.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/item/item_points1_disk.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/item/item_points1_disk.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/item/item_points2_gavina.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/item/item_points2_gavina.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/item/item_points2_gavina.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/item/item_points2_gavina.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/item/item_points3_pacmar.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/item/item_points3_pacmar.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/item/item_points3_pacmar.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/item/item_points3_pacmar.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/item/item_clock.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/item/item_clock.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/item/item_clock.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/item/item_clock.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/item/item_coffee.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/item/item_coffee.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/item/item_coffee.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/item/item_coffee.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/item/item_coffee_machine.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/item/item_coffee_machine.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/title/title_bg_tile.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/title/title_bg_tile.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/title/title_coffee.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/title/title_coffee.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/title/title_crisis.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/title/title_crisis.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/title/title_arcade_edition.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/title/title_arcade_edition.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/title/title_dust.png", t_bitmap); Asset::get()->add(prefix + "/data/gfx/title/title_dust.png", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/title/title_dust.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/title/title_dust.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/player/player1.gif", t_bitmap); Asset::get()->add(prefix + "/data/gfx/player/player1.gif", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/player/player1_pal1.gif", t_palette); Asset::get()->add(prefix + "/data/gfx/player/player1_pal1.gif", AssetType::PALETTE);
asset->add(prefix + "/data/gfx/player/player1_pal2.gif", t_palette); Asset::get()->add(prefix + "/data/gfx/player/player1_pal2.gif", AssetType::PALETTE);
asset->add(prefix + "/data/gfx/player/player1_pal3.gif", t_palette); Asset::get()->add(prefix + "/data/gfx/player/player1_pal3.gif", AssetType::PALETTE);
asset->add(prefix + "/data/gfx/player/player2.gif", t_bitmap); Asset::get()->add(prefix + "/data/gfx/player/player2.gif", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/player/player2_pal1.gif", t_palette); Asset::get()->add(prefix + "/data/gfx/player/player2_pal1.gif", AssetType::PALETTE);
asset->add(prefix + "/data/gfx/player/player2_pal2.gif", t_palette); Asset::get()->add(prefix + "/data/gfx/player/player2_pal2.gif", AssetType::PALETTE);
asset->add(prefix + "/data/gfx/player/player2_pal3.gif", t_palette); Asset::get()->add(prefix + "/data/gfx/player/player2_pal3.gif", AssetType::PALETTE);
asset->add(prefix + "/data/gfx/player/player.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/player/player.ani", AssetType::ANIMATION);
asset->add(prefix + "/data/gfx/player/player_power.gif", t_bitmap); Asset::get()->add(prefix + "/data/gfx/player/player_power.gif", AssetType::BITMAP);
asset->add(prefix + "/data/gfx/player/player_power_pal.gif", t_palette); Asset::get()->add(prefix + "/data/gfx/player/player_power_pal.gif", AssetType::PALETTE);
asset->add(prefix + "/data/gfx/player/player_power.ani", t_animation); Asset::get()->add(prefix + "/data/gfx/player/player_power.ani", AssetType::ANIMATION);
// Fuentes de texto // Fuentes de texto
asset->add(prefix + "/data/font/8bithud.png", t_font); Asset::get()->add(prefix + "/data/font/8bithud.png", AssetType::FONT);
asset->add(prefix + "/data/font/8bithud.txt", t_font); Asset::get()->add(prefix + "/data/font/8bithud.txt", AssetType::FONT);
asset->add(prefix + "/data/font/nokia.png", t_font); Asset::get()->add(prefix + "/data/font/nokia.png", AssetType::FONT);
asset->add(prefix + "/data/font/nokia_big2.png", t_font); Asset::get()->add(prefix + "/data/font/nokia_big2.png", AssetType::FONT);
asset->add(prefix + "/data/font/nokia.txt", t_font); Asset::get()->add(prefix + "/data/font/nokia.txt", AssetType::FONT);
asset->add(prefix + "/data/font/nokia2.png", t_font); Asset::get()->add(prefix + "/data/font/nokia2.png", AssetType::FONT);
asset->add(prefix + "/data/font/nokia2.txt", t_font); Asset::get()->add(prefix + "/data/font/nokia2.txt", AssetType::FONT);
asset->add(prefix + "/data/font/nokia_big2.txt", t_font); Asset::get()->add(prefix + "/data/font/nokia_big2.txt", AssetType::FONT);
asset->add(prefix + "/data/font/smb2_big.png", t_font); Asset::get()->add(prefix + "/data/font/smb2_big.png", AssetType::FONT);
asset->add(prefix + "/data/font/smb2_big.txt", t_font); Asset::get()->add(prefix + "/data/font/smb2_big.txt", AssetType::FONT);
asset->add(prefix + "/data/font/smb2.gif", t_font); Asset::get()->add(prefix + "/data/font/smb2.gif", AssetType::FONT);
asset->add(prefix + "/data/font/smb2_pal1.gif", t_palette); Asset::get()->add(prefix + "/data/font/smb2_pal1.gif", AssetType::PALETTE);
asset->add(prefix + "/data/font/smb2.txt", t_font); Asset::get()->add(prefix + "/data/font/smb2.txt", AssetType::FONT);
// Textos // Textos
asset->add(prefix + "/data/lang/es_ES.txt", t_lang); Asset::get()->add(prefix + "/data/lang/es_ES.txt", AssetType::LANG);
asset->add(prefix + "/data/lang/en_UK.txt", t_lang); Asset::get()->add(prefix + "/data/lang/en_UK.txt", AssetType::LANG);
asset->add(prefix + "/data/lang/ba_BA.txt", t_lang); Asset::get()->add(prefix + "/data/lang/ba_BA.txt", AssetType::LANG);
return asset->check(); return Asset::get()->check();
} }
// Carga los parametros para configurar el juego // Carga los parametros para configurar el juego
void Director::loadParams(std::string filepath) void Director::loadParams(const std::string &file_path)
{ {
loadParamsFromFile(filepath); loadParamsFromFile(file_path);
// Modifica las opciones desde el fichero de parametros
options.video.window.width = options.video.window.size * param.game.width;
options.video.window.height = options.video.window.size * param.game.height;
options.video.gameWidth = param.game.width;
options.video.gameHeight = param.game.height;
} }
// Comprueba los parametros del programa // Comprueba los parametros del programa
void Director::checkProgramArguments(int argc, char *argv[]) void Director::checkProgramArguments(int argc, const char *argv[])
{ {
// Establece la ruta del programa // Establece la ruta del programa
executablePath = argv[0]; executable_path_ = argv[0];
// Valores por defecto // Valores por defecto
paramFileArgument = ""; param_file_argument_.clear();
// Comprueba el resto de parametros // Comprueba el resto de parámetros
for (int i = 1; i < argc; ++i) for (int i = 1; i < argc; ++i)
{ {
if (strcmp(argv[i], "--320x240") == 0) if (strcmp(argv[i], "--320x240") == 0)
{ {
paramFileArgument = argv[i]; param_file_argument_ = argv[i];
} }
} }
} }
// Crea la carpeta del sistema donde guardar datos // Crea la carpeta del sistema donde guardar datos
void Director::createSystemFolder(std::string folder) void Director::createSystemFolder(const std::string &folder)
{ {
#ifdef _WIN32 #ifdef _WIN32
systemFolder = std::string(getenv("APPDATA")) + "/" + folder; system_folder_ = std::string(getenv("APPDATA")) + "/" + folder;
#elif __APPLE__ #elif __APPLE__
struct passwd *pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
const char *homedir = pw->pw_dir; const char *homedir = pw->pw_dir;
systemFolder = std::string(homedir) + "/Library/Application Support" + "/" + folder; system_folder_ = std::string(homedir) + "/Library/Application Support" + "/" + folder;
#elif __linux__ #elif __linux__
struct passwd *pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
const char *homedir = pw->pw_dir; const char *homedir = pw->pw_dir;
systemFolder = std::string(homedir) + "/." + folder; system_folder_ = std::string(homedir) + "/.config/" + folder;
{
// Intenta crear ".config", per si no existeix
std::string config_base_folder = std::string(homedir) + "/.config";
int ret = mkdir(config_base_folder.c_str(), S_IRWXU);
if (ret == -1 && errno != EEXIST)
{
printf("ERROR CREATING CONFIG BASE FOLDER.");
exit(EXIT_FAILURE);
}
}
#endif #endif
struct stat st = {0}; struct stat st = {0};
if (stat(systemFolder.c_str(), &st) == -1) if (stat(system_folder_.c_str(), &st) == -1)
{ {
errno = 0; errno = 0;
#ifdef _WIN32 #ifdef _WIN32
int ret = mkdir(systemFolder.c_str()); int ret = mkdir(system_folder_.c_str());
#else #else
int ret = mkdir(systemFolder.c_str(), S_IRWXU); int ret = mkdir(system_folder_.c_str(), S_IRWXU);
#endif #endif
if (ret == -1) if (ret == -1)
@@ -563,17 +567,15 @@ void Director::createSystemFolder(std::string folder)
void Director::loadSounds() void Director::loadSounds()
{ {
// Obtiene la lista con las rutas a los ficheros de sonidos // Obtiene la lista con las rutas a los ficheros de sonidos
std::vector<std::string> list = asset->getListByType(t_sound); auto list = Asset::get()->getListByType(AssetType::SOUND);
sounds.clear(); sounds_.clear();
for (auto l : list) for (const auto &l : list)
{ {
const size_t lastIndex = l.find_last_of("/") + 1; auto last_index = l.find_last_of('/') + 1;
const std::string name = l.substr(lastIndex, std::string::npos); auto name = l.substr(last_index);
sound_file_t temp;
temp.name = name; // Añade el nombre del fichero sounds_.emplace_back(SoundFile{name, JA_LoadSound(l.c_str())});
temp.file = JA_LoadSound(l.c_str()); // Carga el fichero de audio
sounds.push_back(temp);
} }
} }
@@ -581,136 +583,107 @@ void Director::loadSounds()
void Director::loadMusics() void Director::loadMusics()
{ {
// Obtiene la lista con las rutas a los ficheros musicales // Obtiene la lista con las rutas a los ficheros musicales
std::vector<std::string> list = asset->getListByType(t_music); auto list = Asset::get()->getListByType(AssetType::MUSIC);
musics.clear(); musics_.clear();
for (auto l : list) for (const auto &l : list)
{ {
const size_t lastIndex = l.find_last_of("/") + 1; auto last_index = l.find_last_of('/') + 1;
const std::string name = l.substr(lastIndex, std::string::npos); auto name = l.substr(last_index);
music_file_t temp;
temp.name = name; // Añade el nombre del fichero
temp.file = JA_LoadMusic(l.c_str()); // Carga el fichero de audio
musics.push_back(temp);
}
}
// Libera la memoria usada por los sonidos del juego musics_.emplace_back(MusicFile{name, JA_LoadMusic(l.c_str())});
void Director::deleteSounds()
{
for (auto s : sounds)
{
JA_DeleteSound(s.file);
} }
sounds.clear();
}
// Libera la memoria usada por las músicas del juego
void Director::deleteMusics()
{
for (auto m : musics)
{
JA_DeleteMusic(m.file);
}
musics.clear();
} }
// Ejecuta la sección con el logo // Ejecuta la sección con el logo
void Director::runLogo() void Director::runLogo()
{ {
logo = new Logo(); auto logo = std::make_unique<Logo>();
logo->run(); logo->run();
delete logo;
} }
// Ejecuta la sección con la secuencia de introducción // Ejecuta la sección con la secuencia de introducción
void Director::runIntro() void Director::runIntro()
{ {
intro = new Intro(getMusic(musics, "intro.ogg")); auto intro = std::make_unique<Intro>(getMusic(musics_, "intro.ogg"));
intro->run(); intro->run();
delete intro;
} }
// Ejecuta la sección con el titulo del juego // Ejecuta la sección con el título del juego
void Director::runTitle() void Director::runTitle()
{ {
title = new Title(getMusic(musics, "title.ogg")); auto title = std::make_unique<Title>(getMusic(musics_, "title.ogg"));
title->run(); title->run();
delete title;
} }
// Ejecuta la sección donde se juega al juego // Ejecuta la sección donde se juega al juego
void Director::runGame() void Director::runGame()
{ {
const int playerID = section::options == section::OPTIONS_GAME_PLAY_1P ? 1 : 2; const auto player_id = section::options == section::Options::GAME_PLAY_1P ? 1 : 2;
const int currentStage = 0; constexpr auto current_stage = 0;
game = new Game(playerID, currentStage, GAME_MODE_DEMO_OFF, getMusic(musics, "playing.ogg")); auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_OFF, getMusic(musics_, "playing.ogg"));
game->run(); game->run();
delete game;
} }
// Ejecuta la sección donde se muestran las instrucciones // Ejecuta la sección donde se muestran las instrucciones
void Director::runInstructions() void Director::runInstructions()
{ {
instructions = new Instructions(getMusic(musics, "title.ogg")); auto instructions = std::make_unique<Instructions>(getMusic(musics_, "title.ogg"));
instructions->run(); instructions->run();
delete instructions;
} }
// Ejecuta la sección donde se muestra la tabla de puntuaciones // Ejecuta la sección donde se muestra la tabla de puntuaciones
void Director::runHiScoreTable() void Director::runHiScoreTable()
{ {
hiScoreTable = new HiScoreTable(getMusic(musics, "title.ogg")); auto hi_score_table = std::make_unique<HiScoreTable>(getMusic(musics_, "title.ogg"));
hiScoreTable->run(); hi_score_table->run();
delete hiScoreTable;
} }
// Ejecuta el juego en modo demo // Ejecuta el juego en modo demo
void Director::runDemoGame() void Director::runDemoGame()
{ {
const int playerID = (rand() % 2) + 1; const auto player_id = (rand() % 2) + 1;
const int currentStage = 0; constexpr auto current_stage = 0;
demoGame = new Game(playerID, currentStage, GAME_MODE_DEMO_ON, nullptr); auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_ON, nullptr);
demoGame->run(); game->run();
delete demoGame;
} }
int Director::run() int Director::run()
{ {
// Bucle principal // Bucle principal
while (section::name != section::NAME_QUIT) while (section::name != section::Name::QUIT)
{ {
switch (section::name) switch (section::name)
{ {
case section::NAME_INIT: case section::Name::INIT:
section::name = section::NAME_LOGO; section::name = section::Name::LOGO;
break; break;
case section::NAME_LOGO: case section::Name::LOGO:
runLogo(); runLogo();
break; break;
case section::NAME_INTRO: case section::Name::INTRO:
runIntro(); runIntro();
break; break;
case section::NAME_TITLE: case section::Name::TITLE:
runTitle(); runTitle();
break; break;
case section::NAME_GAME: case section::Name::GAME:
runGame(); runGame();
break; break;
case section::NAME_HI_SCORE_TABLE: case section::Name::HI_SCORE_TABLE:
runHiScoreTable(); runHiScoreTable();
break; break;
case section::NAME_GAME_DEMO: case section::Name::GAME_DEMO:
runDemoGame(); runDemoGame();
break; break;
case section::NAME_INSTRUCTIONS: case section::Name::INSTRUCTIONS:
runInstructions(); runInstructions();
break; break;
@@ -719,30 +692,30 @@ int Director::run()
} }
} }
const int returnCode = section::options == section::OPTIONS_QUIT_NORMAL ? 0 : 1; const int return_code = section::options == section::Options::QUIT_NORMAL ? 0 : 1;
return returnCode; return return_code;
} }
// Obtiene una fichero a partir de un lang_e // Obtiene una fichero a partir de un lang::Code
std::string Director::getLangFile(lang::lang_e lang) std::string Director::getLangFile(lang::Code code)
{ {
switch (lang) switch (code)
{ {
case lang::ba_BA: case lang::Code::ba_BA:
return asset->get("ba_BA.txt"); return Asset::get()->get("ba_BA.txt");
break; break;
case lang::es_ES: case lang::Code::es_ES:
return asset->get("es_ES.txt"); return Asset::get()->get("es_ES.txt");
break; break;
case lang::en_UK: case lang::Code::en_UK:
return asset->get("en_UK.txt"); return Asset::get()->get("en_UK.txt");
break; break;
default: default:
break; break;
} }
return asset->get("en_UK.txt"); return Asset::get()->get("en_UK.txt");
} }

View File

@@ -2,46 +2,28 @@
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_video.h> // for SDL_Window #include <SDL2/SDL_video.h> // for SDL_Window
#include <string> // for string, basic_string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "lang.h" // for lang_e namespace lang { enum class Code : int; }
#include "utils.h" // for music_file_t, sound_file_t struct MusicFile;
class Asset; struct SoundFile;
class Game;
class HiScoreTable;
class Input;
class Instructions;
class Intro;
class Logo;
class Screen;
class Title;
// 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
Screen *screen; // Objeto encargado de dibujar en pantalla
Logo *logo; // Objeto para la sección del logo
Intro *intro; // Objeto para la sección de la intro
Title *title; // Objeto para la sección del titulo y el menu de opciones
Game *game; // Objeto para la sección del juego
Instructions *instructions; // Objeto para la sección de las instrucciones
HiScoreTable *hiScoreTable; // Objeto para mostrar las mejores puntuaciones online
Game *demoGame; // Objeto para lanzar la demo del juego
Input *input; // Objeto Input para gestionar las entradas
Asset *asset; // Objeto que gestiona todos los ficheros de recursos
// 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::string param_file_argument_; // Argumento para gestionar el fichero con los parametros del programa
std::vector<sound_file_t> sounds; // Vector con los sonidos std::vector<SoundFile> sounds_; // Vector con los sonidos
std::vector<music_file_t> musics; // Vector con las musicas std::vector<MusicFile> musics_; // Vector con las musicas
// Inicializa jail_audio // Inicializa jail_audio
void initJailAudio(); void initJailAudio();
@@ -53,7 +35,7 @@ private:
void initInput(); void initInput();
// Carga los parametros para configurar el juego // Carga los parametros para configurar el juego
void loadParams(std::string filepath); void loadParams(const std::string &file_path);
// Crea el indice de ficheros // Crea el indice de ficheros
bool setFileList(); bool setFileList();
@@ -64,17 +46,11 @@ private:
// Carga las musicas del juego // Carga las musicas del juego
void loadMusics(); void loadMusics();
// Libera la memoria usada por los sonidos del juego
void deleteSounds();
// Libera la memoria usada por las músicas del juego
void deleteMusics();
// 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();
@@ -97,12 +73,12 @@ 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);
public: public:
// Constructor // Constructor
Director(int argc, char *argv[]); Director(int argc, const char *argv[]);
// Destructor // Destructor
~Director(); ~Director();

View File

@@ -1,725 +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_t, param_t, zone_t, BLOCK
// Constructor
EnemyFormations::EnemyFormations()
{
initEnemyFormations();
initEnemyPools();
initGameStages();
}
// Destructor
EnemyFormations::~EnemyFormations()
{
}
// Inicializa las formaciones enemigas
void EnemyFormations::initEnemyFormations()
{
const int y4 = - BLOCK;
const int x4_0 = param.game.playArea.rect.x;
const int x4_100 = param.game.playArea.rect.w - BALLOON_WIDTH_4;
const int y3 = - BLOCK;
const int x3_0 = param.game.playArea.rect.x;
const int x3_100 = param.game.playArea.rect.w - BALLOON_WIDTH_3;
const int y2 = - BLOCK;
const int x2_0 = param.game.playArea.rect.x;
const int x2_100 = param.game.playArea.rect.w - BALLOON_WIDTH_2;
const int y1 = - BLOCK;
const int x1_0 = param.game.playArea.rect.x;
const int x1_50 = param.game.playArea.centerX - (BALLOON_WIDTH_1 / 2);
const int x1_100 = param.game.playArea.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.playArea.centerX;
incTime = 0;
for (int i = 0; i < enemyFormation[j].numberOfEnemies; i++)
{
enemyFormation[j].init[i].x = param.game.playArea.firstQuarterX - (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)
{
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();
// Devuelve una fase
stage_t getStage(int index);
};

View File

@@ -3,15 +3,20 @@
// Constructor // Constructor
EnterName::EnterName() EnterName::EnterName()
{
init();
}
// Inicializa el objeto
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 = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; character_list_ = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()";
characterList = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()"; pos_ = 0;
pos = 0; num_characters_ = (int)character_list_.size();
numCharacters = (int)characterList.size();
// Pone la lista de indices para que refleje el nombre // Pone la lista de indices para que refleje el nombre
updateCharacterIndex(); updateCharacterIndex();
@@ -20,32 +25,27 @@ EnterName::EnterName()
updateName(); updateName();
} }
// Destructor
EnterName::~EnterName()
{
}
// Incrementa la posición // Incrementa la posición
void EnterName::incPos() void EnterName::incPos()
{ {
pos++; pos_++;
pos = std::min(pos, NAME_LENGHT - 1); pos_ = std::min(pos_, NAME_LENGHT - 1);
} }
// Decrementa la posición // Decrementa la posición
void EnterName::decPos() void EnterName::decPos()
{ {
pos--; pos_--;
pos = std::max(pos, 0); pos_ = std::max(pos_, 0);
} }
// Incrementa el índice // Incrementa el índice
void EnterName::incIndex() void EnterName::incIndex()
{ {
++characterIndex[pos]; ++character_index_[pos_];
if (characterIndex[pos] >= numCharacters) if (character_index_[pos_] >= num_characters_)
{ {
characterIndex[pos] = 0; character_index_[pos_] = 0;
} }
updateName(); updateName();
} }
@@ -53,10 +53,10 @@ void EnterName::incIndex()
// Decrementa el índice // Decrementa el índice
void EnterName::decIndex() void EnterName::decIndex()
{ {
--characterIndex[pos]; --character_index_[pos_];
if (characterIndex[pos] < 0) if (character_index_[pos_] < 0)
{ {
characterIndex[pos] = numCharacters - 1; character_index_[pos_] = num_characters_ - 1;
} }
updateName(); updateName();
} }
@@ -64,10 +64,10 @@ void EnterName::decIndex()
// Actualiza la variable // Actualiza la variable
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]]);
} }
} }
@@ -77,22 +77,22 @@ void EnterName::updateCharacterIndex()
// Rellena de espacios // Rellena de espacios
for (int i = 0; i < NAME_LENGHT; ++i) for (int i = 0; i < NAME_LENGHT; ++i)
{ {
characterIndex[i] = 0; character_index_[i] = 0;
} }
// Coloca los índices en funcion de los caracteres que forman el nombre // Coloca los índices en funcion de los caracteres que forman el nombre
for (int i = 0; i < (int)name.size(); ++i) for (int i = 0; i < (int)name_.size(); ++i)
{ {
characterIndex[i] = findIndex(name.at(i)); character_index_[i] = findIndex(name_.at(i));
} }
} }
// 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)
{ {
for (int i = 0; i < (int)characterList.size(); ++i) for (int i = 0; i < (int)character_list_.size(); ++i)
{ {
if (character == characterList[i]) if (character == character_list_[i])
{ {
return i; return i;
} }
@@ -101,13 +101,13 @@ int EnterName::findIndex(char character)
} }
// Obtiene el nombre // Obtiene el nombre
std::string EnterName::getName() 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() int EnterName::getPos() const
{ {
return pos; return pos_;
} }

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,11 +16,11 @@
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 pos_; // 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
// Actualiza la variable // Actualiza la variable
void updateName(); void updateName();
@@ -36,7 +36,10 @@ public:
EnterName(); EnterName();
// Destructor // Destructor
~EnterName(); ~EnterName() = default;
// Inicializa el objeto
void init();
// Incrementa la posición // Incrementa la posición
void incPos(); void incPos();
@@ -51,8 +54,8 @@ public:
void decIndex(); void decIndex();
// Obtiene el nombre // Obtiene el nombre
std::string getName(); std::string getName() const;
// Obtiene la posición que se está editando // Obtiene la posición que se está editando
int getPos(); int getPos() const;
}; };

View File

@@ -1,30 +1,25 @@
#include "explosions.h" #include "explosions.h"
#include <utility> // for move
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for AnimatedSprite
class Texture; class Texture; // lines 3-3
// Constructor // Constructor
Explosions::Explosions() Explosions::Explosions()
{ {
textures.clear(); textures_.clear();
explosions.clear(); explosions_.clear();
} }
// Destructor // Destructor
Explosions::~Explosions() Explosions::~Explosions()
{ {
for (auto explosion : explosions) explosions_.clear();
{
if (explosion)
{
delete explosion;
}
}
} }
// 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();
} }
@@ -36,42 +31,41 @@ 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 objetp // Añade texturas al objeto
void Explosions::addTexture(int size, Texture *texture, std::vector<std::string> *animation) void Explosions::addTexture(int size, std::shared_ptr<Texture> texture, std::vector<std::string> *animation)
{ {
explosion_texture_t temp; ExplosionTexture temp;
temp.size = size; temp.size = size;
temp.texture = texture; temp.texture = texture;
temp.animation = animation; temp.animation = animation;
textures.push_back(temp); 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 int index = getIndexBySize(size);
AnimatedSprite *sprite = new AnimatedSprite(textures[index].texture, "", textures[index].animation); auto sprite = std::make_unique<AnimatedSprite>(textures_[index].texture, "", textures_[index].animation);
sprite->setPos(x, y); sprite->setPos(x, y);
explosions.push_back(sprite); 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())
{ {
delete explosions[i]; explosions_.erase(explosions_.begin() + i);
explosions.erase(explosions.begin() + i);
} }
} }
} }
@@ -80,9 +74,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,13 +1,14 @@
#pragma once #pragma once
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
class AnimatedSprite; class AnimatedSprite;
class Texture; class Texture;
struct explosion_texture_t struct ExplosionTexture
{ {
Texture *texture; // Textura para la explosión std::shared_ptr<Texture> texture; // Textura para la explosión
std::vector<std::string> *animation; // Animación para la textura std::vector<std::string> *animation; // Animación para la textura
int size; // Tamaño de la explosión int size; // Tamaño de la explosión
}; };
@@ -17,8 +18,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<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();
@@ -39,8 +40,8 @@ public:
// Dibuja el objeto en pantalla // Dibuja el objeto en pantalla
void render(); void render();
// Añade texturas al objetp // Añade texturas al objeto
void addTexture(int size, Texture *texture, std::vector<std::string> *animation); void addTexture(int size, std::shared_ptr<Texture> texture, 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

@@ -4,17 +4,15 @@
#include <stdlib.h> // for rand #include <stdlib.h> // for rand
#include <algorithm> // for min, max #include <algorithm> // for min, max
#include "param.h" // for param #include "param.h" // for param
#include "utils.h" // for param_t, paramGame_t, paramFade_t #include "utils.h" // for Param, ParamGame, ParamFade
// Constructor // Constructor
Fade::Fade(SDL_Renderer *renderer) Fade::Fade(SDL_Renderer *renderer)
: renderer_(renderer)
{ {
// Copia punteros y objetos
this->renderer = renderer;
// 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();
@@ -23,179 +21,177 @@ 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 = FADE_CENTER; type_ = FadeType::CENTER;
mode = FADE_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.numSquaresWidth; post_counter_ = 0;
numSquaresHeight = param.fade.numSquaresHeight; num_squares_width_ = param.fade.num_squares_width;
fadeRandomSquaresDelay = param.fade.randomSquaresDelay; num_squares_height_ = param.fade.num_squares_height;
fadeRandomSquaresMult = param.fade.randomSquaresMult; 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 FADE_FULLSCREEN: case FadeType::FULLSCREEN:
{ {
// Modifica la transparencia de la // Modifica la transparencia
if (mode == FADE_OUT) a_ = mode_ == FadeMode::OUT ? std::min(counter_ * 4, 255) : 255 - std::min(counter_ * 4, 255);
a = std::min(counter * 4, 255);
else
a = 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;
} }
case FADE_CENTER: case FadeType::CENTER:
{ {
// Dibuja sobre el backbuffer // Dibuja sobre el backbuffer_
SDL_Texture *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 FADE_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_
SDL_Texture *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;
} }
case FADE_VENETIAN: case FadeType::VENETIAN:
{ {
// Counter debe ir de 0 a 150 // Counter debe ir de 0 a 150
if (square.back().h < param.fade.venetianSize) if (square_.back().h < param.fade.venetian_size)
{ {
// Dibuja sobre el backbuffer // Dibuja sobre el backbuffer_
SDL_Texture *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 Uint8 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
i == 0 ? square[i].h = h : square[i].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_++;
} }
} }
@@ -203,84 +199,85 @@ 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 FADE_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 FADE_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 FADE_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
int num = numSquaresWidth * numSquaresHeight; auto num = num_squares_width_ * num_squares_height_;
while (num > 1) while (num > 1)
{ {
int 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
SDL_Texture *temp = SDL_GetRenderTarget(renderer); auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer, backbuffer); SDL_SetRenderTarget(renderer_, backbuffer_);
a = mode == FADE_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 == FADE_OUT ? 255 : 0; a_ = mode_ == FadeMode::OUT ? 255 : 0;
break; break;
} }
case FADE_VENETIAN: case FadeType::VENETIAN:
{ {
rect1 = {0, 0, param.game.width, 0}; cleanBackbuffer(0, 0, 0, 0);
square.clear(); rect1_ = {0, 0, param.game.width, 0};
a = 255; square_.clear();
a_ = 255;
// Añade los cuadrados al vector // Añade los cuadrados al vector
const int max = param.game.height / param.fade.venetianSize; 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.venetianSize; rect1_.y = i * param.fade.venetian_size;
square.push_back(rect1); square_.push_back(rect1_);
} }
break; break;
@@ -289,55 +286,55 @@ void Fade::activate()
} }
// Comprueba si está activo // Comprueba si está activo
bool Fade::isEnabled() bool Fade::isEnabled() const
{ {
return enabled; return enabled_;
} }
// Comprueba si ha terminado la transicion // Comprueba si ha terminado la transicion
bool Fade::hasEnded() 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(Uint8 type) void Fade::setType(FadeType type)
{ {
this->type = type; type_ = type;
} }
// Establece el modo de fade // Establece el modo de fade
void Fade::setMode(Uint8 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(int r, int g, int b, int a) void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{ {
// Dibujamos sobre el backbuffer // Dibujamos sobre el backbuffer_
SDL_Texture *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

@@ -6,49 +6,55 @@
#include <vector> // for vector #include <vector> // for vector
// Tipos de fundido // Tipos de fundido
#define FADE_FULLSCREEN 0 enum class FadeType : Uint8
#define FADE_CENTER 1 {
#define FADE_RANDOM_SQUARE 2 FULLSCREEN = 0,
#define FADE_VENETIAN 3 CENTER = 1,
RANDOM_SQUARE = 2,
VENETIAN = 3,
};
// Modos de fundido // Modos de fundido
#define FADE_IN 0 enum class FadeMode : Uint8
#define FADE_OUT 1 {
IN = 0,
OUT = 1,
};
// Clase Fade // Clase Fade
class Fade 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
Uint8 type; // Tipo de fade a realizar FadeType type_; // Tipo de fade a realizar
Uint8 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 FADE_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 FADE_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 FADE_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();
// Limpia el backbuffer // Limpia el backbuffer
void cleanBackbuffer(int r, int g, int b, int a); void cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
public: public:
// Constructor // Constructor
Fade(SDL_Renderer *renderer); explicit Fade(SDL_Renderer *renderer);
// Destructor // Destructor
~Fade(); ~Fade();
@@ -66,16 +72,16 @@ public:
void activate(); void activate();
// Comprueba si ha terminado la transicion // Comprueba si ha terminado la transicion
bool hasEnded(); bool hasEnded() const;
// Comprueba si está activo // Comprueba si está activo
bool isEnabled(); bool isEnabled() const;
// Establece el tipo de fade // Establece el tipo de fade
void setType(Uint8 type); void setType(FadeType type);
// Establece el modo de fade // Establece el modo de fade
void setMode(Uint8 mode); void setMode(FadeMode mode);
// Establece el color del fade // Establece el color del fade
void setColor(Uint8 r, Uint8 g, Uint8 b); void setColor(Uint8 r, Uint8 g, Uint8 b);

File diff suppressed because it is too large Load Diff

View File

@@ -1,55 +1,56 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "section.h" // for options_e #include "balloon.h" // for Balloon
#include "utils.h" // for demoKeys_t, color_t, hiScoreEntry_t #include "player.h" // for Player
class Asset; // lines 11-11 #include "utils.h" // for DemoKeys, Color, HiScoreEntry
class Background; // lines 12-12 class Asset;
class Balloon; // lines 13-13 class Background;
class Bullet; // lines 14-14 class BalloonFormations;
class EnemyFormations; // lines 15-15 class Bullet;
class Explosions; // lines 16-16 class Explosions;
class Fade; // lines 17-17 class Fade;
class Input; // lines 18-18 class Input;
class Item; // lines 19-19 class Item;
class Player; // lines 20-20 class Scoreboard;
class Scoreboard; // lines 21-21 class Screen;
class Screen; // lines 22-22 class SmartSprite;
class SmartSprite; // lines 23-23 class Text;
class Text; // lines 24-24 class Texture;
class Texture; // lines 25-25 enum class BulletType; // lines 26-26
enum class BulletType; struct JA_Music_t; // lines 27-27
struct JA_Music_t; // lines 26-26 struct JA_Sound_t; // lines 28-28
struct JA_Sound_t; // lines 27-27
#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 constexpr int TOTAL_DEMO_DATA = 2000;
// Contadores // Contadores
#define STAGE_COUNTER 200 constexpr int STAGE_COUNTER = 200;
#define HELP_COUNTER 1000 constexpr int HELP_COUNTER = 1000;
#define GAME_COMPLETED_START_FADE 500 constexpr int GAME_COMPLETED_START_FADE = 500;
#define GAME_COMPLETED_END 700 constexpr int GAME_COMPLETED_END = 700;
constexpr int GAME_OVER_COUNTER = 350;
// Porcentaje de aparición de los objetos // Porcentaje de aparición de los objetos
#define ITEM_POINTS_1_DISK_ODDS 10 constexpr int ITEM_POINTS_1_DISK_ODDS = 10;
#define ITEM_POINTS_2_GAVINA_ODDS 6 constexpr int ITEM_POINTS_2_GAVINA_ODDS = 6;
#define ITEM_POINTS_3_PACMAR_ODDS 3 constexpr int ITEM_POINTS_3_PACMAR_ODDS = 3;
#define ITEM_CLOCK_ODDS 5 constexpr int ITEM_CLOCK_ODDS = 5;
#define ITEM_COFFEE_ODDS 5 constexpr int ITEM_COFFEE_ODDS = 5;
#define ITEM_POWER_BALL_ODDS 0 constexpr int ITEM_POWER_BALL_ODDS = 0;
#define ITEM_COFFEE_MACHINE_ODDS 4 constexpr int ITEM_COFFEE_MACHINE_ODDS = 4;
// Valores para las variables asociadas a los objetos // Valores para las variables asociadas a los objetos
#define TIME_STOPPED_COUNTER 300 constexpr int 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
@@ -81,127 +82,128 @@ struct JA_Sound_t; // lines 27-27
class Game class Game
{ {
private: private:
struct helper_t struct Helper
{ {
bool needCoffee; // Indica si se necesitan cafes bool need_coffee; // Indica si se necesitan cafes
bool needCoffeeMachine; // Indica si se necesita PowerUp bool need_coffee_machine; // Indica si se necesita PowerUp
bool needPowerBall; // Indica si se necesita una PowerBall bool need_power_ball; // Indica si se necesita una PowerBall
int counter; // Contador para no dar ayudas consecutivas int counter; // Contador para no dar ayudas consecutivas
int itemPoints1Odds; // Probabilidad de aparición del objeto int item_disk_odds; // Probabilidad de aparición del objeto
int itemPoints2Odds; // Probabilidad de aparición del objeto int item_gavina_odds; // Probabilidad de aparición del objeto
int itemPoints3Odds; // Probabilidad de aparición del objeto int item_pacmar_odds; // Probabilidad de aparición del objeto
int itemClockOdds; // Probabilidad de aparición del objeto int item_clock_odds; // Probabilidad de aparición del objeto
int itemCoffeeOdds; // Probabilidad de aparición del objeto int item_coffee_odds; // Probabilidad de aparición del objeto
int itemCoffeeMachineOdds; // Probabilidad de aparición del objeto int item_coffee_machine_odds; // Probabilidad de aparición del objeto
}; };
struct demo_t struct Demo
{ {
bool enabled; // Indica si está activo el modo demo bool enabled; // Indica si está activo el modo demo
bool recording; // Indica si está activado el modo para grabar la demo bool recording; // Indica si está activado el modo para grabar la demo
int counter; // Contador para el modo demo int counter; // Contador para el modo demo
demoKeys_t keys; // Variable con las pulsaciones de teclas del modo demo DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo
demoKeys_t dataFile[2][TOTAL_DEMO_DATA]; // Vector con diferentes sets de datos con los movimientos para la demo DemoKeys data_file[2][TOTAL_DEMO_DATA]; // Vector con diferentes sets de datos con los movimientos para la demo
}; };
// 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
Background *background; // Objeto para dibujar el fondo del juego
Explosions *explosions; // Objeto para dibujar explosiones
EnemyFormations *enemyFormations; // Objeto para gestionar las oleadas enemigas
SDL_Texture *canvas; // Textura para dibujar la zona de juego
std::vector<Player *> players; // Vector con los jugadores std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
std::vector<Balloon *> balloons; // Vector con los globos std::unique_ptr<Explosions> explosions_; // Objeto para dibujar explosiones
std::vector<Bullet *> bullets; // Vector con las balas std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para gestionar las oleadas enemigas
std::vector<Item *> items; // Vector con los items
std::vector<SmartSprite *> smartSprites; // Vector con los smartsprites
Texture *bulletTexture; // Textura para las balas SDL_Texture *canvas_; // Textura para dibujar la zona de juego
std::vector<Texture *> itemTextures; // Vector con las texturas de los items
std::vector<Texture *> balloonTextures; // Vector con las texturas de los globos
std::vector<Texture *> explosionsTextures; // Vector con las texturas de las explosiones
std::vector<Texture *> player1Textures; // Vector con las texturas del jugador
std::vector<Texture *> player2Textures; // Vector con las texturas del jugador
std::vector<std::vector<Texture *>> playerTextures; // Vector con todas las texturas de los jugadores;
Texture *gameTextTexture; // Textura para los sprites con textos 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::unique_ptr<Bullet>> bullets_; // Vector con las balas
std::vector<std::unique_ptr<Item>> items_; // Vector con los items
std::vector<SmartSprite *> smart_sprites_; // Vector con los smartsprites
std::vector<std::vector<std::string> *> itemAnimations; // Vector con las animaciones de los items std::shared_ptr<Texture> bullet_texture_; // Textura para las balas
std::vector<std::vector<std::string> *> playerAnimations; // Vector con las animaciones del jugador std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
std::vector<std::vector<std::string> *> balloonAnimations; // Vector con las animaciones de los globos std::vector<std::shared_ptr<Texture>> balloon_textures_; // Vector con las texturas de los globos
std::vector<std::vector<std::string> *> explosionsAnimations; // Vector con las animaciones de las explosiones std::vector<std::shared_ptr<Texture>> explosions_textures_; // Vector con las texturas de las explosiones
std::vector<std::shared_ptr<Texture>> player1_textures_; // Vector con las texturas del jugador
std::vector<std::shared_ptr<Texture>> player2_textures_; // Vector con las texturas del jugador
std::vector<std::vector<std::shared_ptr<Texture>>> player_textures_; // Vector con todas las texturas de los jugadores;
Text *text; // Fuente para los textos del juego std::shared_ptr<Texture> game_text_texture_; // Textura para los sprites con textos
Text *textBig; // Fuente de texto grande
Text *textNokia2; // Otra fuente de texto para mensajes
Text *textNokiaBig2; // Y la versión en grande
Fade *fade; // Objeto para renderizar fades std::vector<std::vector<std::string> *> item_animations_; // Vector con las animaciones de los items
SDL_Event *eventHandler; // Manejador de eventos std::vector<std::vector<std::string> *> player_animations_; // Vector con las animaciones del jugador
std::vector<std::vector<std::string> *> balloon_animations_; // Vector con las animaciones de los globos
std::vector<std::vector<std::string> *> explosions_animations_; // Vector con las animaciones de las explosiones
SmartSprite *n1000Sprite; // Sprite con el texto 1.000 std::unique_ptr<Text> text_; // Fuente para los textos del juego
SmartSprite *n2500Sprite; // Sprite con el texto 2.500 std::unique_ptr<Text> text_big_; // Fuente de texto grande
SmartSprite *n5000Sprite; // Sprite con el texto 5.000 std::unique_ptr<Text> text_nokia2_; // Otra fuente de texto para mensajes
std::unique_ptr<Text> text_nokia2_big_; // Y la versión en grande
JA_Sound_t *balloonSound; // Sonido para la explosión del globo std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
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 std::shared_ptr<SmartSprite> p1000_sprite_; // Sprite con el texto 1.000
std::shared_ptr<SmartSprite> p2500_sprite_; // Sprite con el texto 2.500
std::shared_ptr<SmartSprite> p5000_sprite_; // Sprite con el texto 5.000
JA_Sound_t *balloon_sound_; // Sonido para la explosión del globo
JA_Sound_t *bullet_sound_; // Sonido para los disparos
JA_Sound_t *player_collision_sound_; // Sonido para la colisión del jugador con un enemigo
JA_Sound_t *hi_score_sound_; // Sonido para cuando se alcanza la máxima puntuación
JA_Sound_t *item_drop_sound_; // Sonido para cuando se genera un item
JA_Sound_t *item_pick_up_sound_; // Sonido para cuando se recoge un item
JA_Sound_t *coffee_out_sound_; // Sonido para cuando el jugador pierde el café al recibir un impacto
JA_Sound_t *stage_change_sound_; // Sonido para cuando se cambia de fase
JA_Sound_t *bubble1_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble2_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble3_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble4_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *clock_sound_; // Sonido para cuando se detiene el tiempo con el item reloj
JA_Sound_t *power_ball_sound_; // Sonido para cuando se explota una Power Ball
JA_Sound_t *coffee_machine_sound_; // 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 Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
bool hiScoreAchieved; // Indica si se ha superado la puntuación máxima bool hi_score_achieved_; // Indica si se ha superado la puntuación máxima
hiScoreEntry_t hiScore; // Máxima puntuación y nombre de quien la ostenta HiScoreEntry hi_score_; // 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 int stage_bitmap_counter_; // Contador para el tiempo visible del texto de Stage
float stageBitmapPath[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto float stage_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto
float getReadyBitmapPath[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto float get_ready_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto
int gameOverCounter; // Contador para el estado de fin de partida int game_over_counter_; // Contador para el estado de fin de partida
int menaceCurrent; // Nivel de amenaza actual int menace_current_; // Nivel de amenaza actual
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 int menace_threshold_; // 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 timeStopped; // Indica si el tiempo está detenido bool time_stopped_; // Indica si el tiempo está detenido
int timeStoppedCounter; // Temporizador para llevar la cuenta del tiempo detenido int time_stopped_counter_; // Temporizador para llevar la cuenta del tiempo detenido
int counter; // Contador para el juego int counter_; // Contador para el juego
int balloonsPopped; // Lleva la cuenta de los globos explotados int balloons_popped_; // Lleva la cuenta de los globos explotados
int lastEnemyDeploy; // Guarda cual ha sido la última formación desplegada para no repetir; int last_ballon_deploy_; // Guarda cual ha sido la última formación desplegada para no repetir;
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_; // 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 float balloon_speed_; // Velocidad a la que se mueven los enemigos
float defaultEnemySpeed; // Velocidad base de los enemigos, sin incrementar float default_balloon_speed_; // Velocidad base de los enemigos, sin incrementar
helper_t helper; // Variable para gestionar las ayudas Helper helper_; // Variable para gestionar las ayudas
bool powerBallEnabled; // Indica si hay una powerball ya activa bool power_ball_enabled_; // Indica si hay una powerball ya activa
int powerBallCounter; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra int power_ball_counter_; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
bool coffeeMachineEnabled; // Indica si hay una máquina de café en el terreno de juego bool coffee_machine_enabled_; // Indica si hay una máquina de café en el terreno de juego
bool gameCompleted; // Indica si se ha completado la partida, llegando al final de la ultima pantalla bool game_completed_; // Indica si se ha completado la partida, llegando al final de la ultima pantalla
int gameCompletedCounter; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos int game_completed_counter_; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos
int difficulty; // Dificultad del juego GameDifficulty difficulty_; // Dificultad del juego
float difficultyScoreMultiplier; // Multiplicador de puntos en función de la dificultad float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
color_t difficultyColor; // Color asociado a la dificultad Color difficulty_color_; // Color asociado a la dificultad
int lastStageReached; // Contiene el número de la última pantalla que se ha alcanzado int last_stage_reached_; // Contiene el número de la última pantalla que se ha alcanzado
demo_t demo; // Variable con todas las variables relacionadas con el modo demo Demo demo_; // Variable con todas las variables relacionadas con el modo demo
int totalPowerToCompleteGame; // La suma del poder necesario para completar todas las fases int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
bool paused; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade) 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 int current_power_; // 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_; // Si es true, incrementa automaticamente los globos explotados
#endif #endif
// Actualiza el juego // Actualiza el juego
@@ -214,7 +216,7 @@ private:
void checkEvents(); void checkEvents();
// Inicializa las variables necesarias para la sección 'Game' // Inicializa las variables necesarias para la sección 'Game'
void init(int playerID); void init(int player_id);
// Carga los recursos necesarios para la sección 'Game' // Carga los recursos necesarios para la sección 'Game'
void loadMedia(); void loadMedia();
@@ -223,13 +225,13 @@ private:
void unloadMedia(); void unloadMedia();
// Carga el fichero de datos para la demo // Carga el fichero de datos para la demo
bool loadDemoFile(std::string filePath, demoKeys_t (*dataFile)[TOTAL_DEMO_DATA]); bool loadDemoFile(const std::string &file_path, DemoKeys (*data_file)[TOTAL_DEMO_DATA]);
#ifdef RECORDING #ifdef RECORDING
// Guarda el fichero de datos para la demo // Guarda el fichero de datos para la demo
bool saveDemoFile(std::string filePath); bool saveDemoFile(const std::string &file_path);
#endif #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);
@@ -256,7 +258,7 @@ private:
void renderBalloons(); void renderBalloons();
// Crea un globo nuevo en el vector de globos // Crea un globo nuevo en el vector de globos
int createBalloon(float x, int y, int kind, float velx, float speed, int stoppedcounter); std::shared_ptr<Balloon> createBalloon(float x, int y, int kind, float velx, float speed, int stopped_counter);
// Crea una PowerBall // Crea una PowerBall
void createPowerBall(); void createPowerBall();
@@ -264,23 +266,14 @@ 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 updateBalloonSpeed();
// 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(Balloon *balloon); void popBalloon(std::shared_ptr<Balloon> balloon);
// Explosiona un globo. Lo destruye // Explosiona un globo. Lo destruye
void destroyBalloon(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();
@@ -291,17 +284,14 @@ private:
// Pone en marcha todos los globos // Pone en marcha todos los globos
void startAllBalloons(); void startAllBalloons();
// Obtiene el número de globos activos
int countBalloons();
// Vacia el vector de globos // Vacia el vector de globos
void freeBalloons(); void freeBalloons();
// Comprueba la colisión entre el jugador y los globos activos // Comprueba la colisión entre el jugador y los globos activos
bool checkPlayerBalloonCollision(Player *player); bool checkPlayerBalloonCollision(std::shared_ptr<Player> &player);
// Comprueba la colisión entre el jugador y los items // Comprueba la colisión entre el jugador y los items
void checkPlayerItemCollision(Player *player); void checkPlayerItemCollision(std::shared_ptr<Player> &player);
// Comprueba la colisión entre las balas y los globos // Comprueba la colisión entre las balas y los globos
void checkBulletBalloonCollision(); void checkBulletBalloonCollision();
@@ -313,7 +303,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();
@@ -334,7 +324,7 @@ private:
void freeItems(); void freeItems();
// Crea un objeto SmartSprite // Crea un objeto SmartSprite
void createItemScoreSprite(int x, int y, SmartSprite *sprite); void createItemScoreSprite(int x, int y, std::shared_ptr<SmartSprite> sprite);
// Vacia el vector de smartsprites // Vacia el vector de smartsprites
void freeSmartSprites(); void freeSmartSprites();
@@ -349,19 +339,19 @@ private:
void renderSmartSprites(); void renderSmartSprites();
// Acciones a realizar cuando el jugador muere // Acciones a realizar cuando el jugador muere
void killPlayer(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 // Obtiene el valor de la variable
int getMenace(); int getMenace() const;
// Establece el valor de la variable // Establece el valor de la variable
void setTimeStopped(bool value); void setTimeStopped(bool value);
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool isTimeStopped(); bool isTimeStopped() const;
// Establece el valor de la variable // Establece el valor de la variable
void setTimeStoppedCounter(int value); void setTimeStoppedCounter(int value);
@@ -370,7 +360,7 @@ private:
void incTimeStoppedCounter(int value); 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 updateTimeStoppedCounter();
@@ -409,13 +399,16 @@ private:
void updateHelper(); void updateHelper();
// Comprueba si todos los jugadores han terminado de jugar // Comprueba si todos los jugadores han terminado de jugar
bool allPlayersAreWaiting(); bool allPlayersAreWaitingOrGameOver();
// Comprueba si todos los jugadores han terminado de jugar
bool allPlayersAreGameOver();
// 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 // Carga las animaciones
void loadAnimations(std::string filePath, std::vector<std::string> *buffer); void loadAnimations(std::string file_path, std::vector<std::string> *buffer);
// Elimina todos los objetos contenidos en vectores // Elimina todos los objetos contenidos en vectores
void deleteAllVectorObjects(); void deleteAllVectorObjects();
@@ -436,26 +429,23 @@ 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);
// Comprueba si la puntuación entra en la tabla de mejores puntuaciones // Saca del estado de GAME OVER al jugador si el otro está activo
bool IsEligibleForHighScore(int score); 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();
// Obtiene un jugador a partir de su "id" // Obtiene un jugador a partir de su "id"
Player *getPlayer(int id); std::shared_ptr<Player> getPlayer(int id);
// 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);
// Termina
void quit(section::options_e code);
public: public:
// Constructor // Constructor
Game(int playerID, int currentStage, bool demo, JA_Music_t *music); Game(int playerID, int current_stage, bool demo, JA_Music_t *music);
// Destructor // Destructor
~Game(); ~Game();

View File

@@ -1,6 +1,6 @@
#include "game_logo.h" #include "game_logo.h"
#include <SDL2/SDL_render.h> // for SDL_FLIP_HORIZONTAL
#include <algorithm> // for max #include <algorithm> // for max
#include <string> // for basic_string
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for AnimatedSprite
#include "asset.h" // for Asset #include "asset.h" // for Asset
#include "jail_audio.h" // for JA_DeleteSound, JA_LoadSound, JA_PlaySound #include "jail_audio.h" // for JA_DeleteSound, JA_LoadSound, JA_PlaySound
@@ -9,33 +9,28 @@
#include "smart_sprite.h" // for SmartSprite #include "smart_sprite.h" // for SmartSprite
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "texture.h" // for Texture #include "texture.h" // for Texture
#include "utils.h" // for param_t, paramGame_t, paramTitle_t #include "utils.h" // for Param, ParamGame, ParamTitle
// Constructor // Constructor
GameLogo::GameLogo(int x, int y) GameLogo::GameLogo(int x, int y)
: dust_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_dust.png"))),
coffee_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_coffee.png"))),
crisis_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_crisis.png"))),
arcade_edition_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_arcade_edition.png"))),
dust_left_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Asset::get()->get("title_dust.ani"))),
dust_right_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Asset::get()->get("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>((param.game.width - arcade_edition_texture_->getWidth()) / 2, param.title.arcade_edition_position, arcade_edition_texture_->getWidth(), arcade_edition_texture_->getHeight(), arcade_edition_texture_)),
crash_sound_(JA_LoadSound(Asset::get()->get("title.wav").c_str())),
x_(x),
y_(y)
{ {
// Copia los punteros
screen = Screen::get();
renderer = screen->getRenderer();
asset = Asset::get();
this->x = x;
this->y = y;
// Crea los objetos
dustTexture = new Texture(renderer, asset->get("title_dust.png"));
coffeeTexture = new Texture(renderer, asset->get("title_coffee.png"));
crisisTexture = new Texture(renderer, asset->get("title_crisis.png"));
arcadeEditionTexture = new Texture(renderer, asset->get("title_arcade_edition.png"));
coffeeBitmap = new SmartSprite(coffeeTexture);
crisisBitmap = new SmartSprite(crisisTexture);
arcadeEditionBitmap = new Sprite((param.game.width - arcadeEditionTexture->getWidth()) / 2, param.title.arcadeEditionPosition, arcadeEditionTexture->getWidth(), arcadeEditionTexture->getHeight(), arcadeEditionTexture);
dustBitmapL = new AnimatedSprite(dustTexture, asset->get("title_dust.ani"));
dustBitmapR = new AnimatedSprite(dustTexture, asset->get("title_dust.ani"));
// Sonidos
crashSound = JA_LoadSound(asset->get("title.wav").c_str());
// Inicializa las variables // Inicializa las variables
init(); init();
} }
@@ -43,152 +38,140 @@ GameLogo::GameLogo(int x, int y)
// Destructor // Destructor
GameLogo::~GameLogo() GameLogo::~GameLogo()
{ {
delete dustTexture; JA_DeleteSound(crash_sound_);
delete coffeeTexture;
delete crisisTexture;
delete arcadeEditionTexture;
delete coffeeBitmap;
delete crisisBitmap;
delete arcadeEditionBitmap;
delete dustBitmapL;
delete dustBitmapR;
JA_DeleteSound(crashSound);
} }
// Inicializa las variables // Inicializa las variables
void GameLogo::init() void GameLogo::init()
{ {
const int xp = x - coffeeBitmap->getWidth() / 2; const auto xp = x_ - coffee_sprite_->getWidth() / 2;
const int desp = getInitialVerticalDesp(); const auto desp = getInitialVerticalDesp();
// Variables // Variables
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'
coffeeBitmap->init(); coffee_sprite_->init();
coffeeBitmap->setPosX(xp); coffee_sprite_->setPosX(xp);
coffeeBitmap->setPosY(y - coffeeTexture->getHeight() - desp); coffee_sprite_->setPosY(y_ - coffee_texture_->getHeight() - desp);
coffeeBitmap->setWidth(coffeeTexture->getWidth()); coffee_sprite_->setWidth(coffee_texture_->getWidth());
coffeeBitmap->setHeight(coffeeTexture->getHeight()); coffee_sprite_->setHeight(coffee_texture_->getHeight());
coffeeBitmap->setVelX(0.0f); coffee_sprite_->setVelX(0.0f);
coffeeBitmap->setVelY(2.5f); coffee_sprite_->setVelY(2.5f);
coffeeBitmap->setAccelX(0.0f); coffee_sprite_->setAccelX(0.0f);
coffeeBitmap->setAccelY(0.1f); coffee_sprite_->setAccelY(0.1f);
coffeeBitmap->setSpriteClip(0, 0, coffeeTexture->getWidth(), coffeeTexture->getHeight()); coffee_sprite_->setSpriteClip(0, 0, coffee_texture_->getWidth(), coffee_texture_->getHeight());
coffeeBitmap->setEnabled(true); coffee_sprite_->setEnabled(true);
coffeeBitmap->setEnabledCounter(0); coffee_sprite_->setFinishedCounter(0);
coffeeBitmap->setDestX(xp); coffee_sprite_->setDestX(xp);
coffeeBitmap->setDestY(y - coffeeTexture->getHeight()); coffee_sprite_->setDestY(y_ - coffee_texture_->getHeight());
// Inicializa el bitmap de 'Crisis' // Inicializa el bitmap de 'Crisis'
crisisBitmap->init(); crisis_sprite_->init();
crisisBitmap->setPosX(xp + 15); crisis_sprite_->setPosX(xp + 15);
crisisBitmap->setPosY(y + desp); crisis_sprite_->setPosY(y_ + desp);
crisisBitmap->setWidth(crisisTexture->getWidth()); crisis_sprite_->setWidth(crisis_texture_->getWidth());
crisisBitmap->setHeight(crisisTexture->getHeight()); crisis_sprite_->setHeight(crisis_texture_->getHeight());
crisisBitmap->setVelX(0.0f); crisis_sprite_->setVelX(0.0f);
crisisBitmap->setVelY(-2.5f); crisis_sprite_->setVelY(-2.5f);
crisisBitmap->setAccelX(0.0f); crisis_sprite_->setAccelX(0.0f);
crisisBitmap->setAccelY(-0.1f); crisis_sprite_->setAccelY(-0.1f);
crisisBitmap->setSpriteClip(0, 0, crisisTexture->getWidth(), crisisTexture->getHeight()); crisis_sprite_->setSpriteClip(0, 0, crisis_texture_->getWidth(), crisis_texture_->getHeight());
crisisBitmap->setEnabled(true); crisis_sprite_->setEnabled(true);
crisisBitmap->setEnabledCounter(0); crisis_sprite_->setFinishedCounter(0);
crisisBitmap->setDestX(xp + 15); crisis_sprite_->setDestX(xp + 15);
crisisBitmap->setDestY(y); crisis_sprite_->setDestY(y_);
// Inicializa el bitmap de 'DustRight' // Inicializa el bitmap de 'DustRight'
dustBitmapR->resetAnimation(); dust_right_sprite_->resetAnimation();
dustBitmapR->setPosX(coffeeBitmap->getPosX() + coffeeBitmap->getWidth()); dust_right_sprite_->setPosX(coffee_sprite_->getPosX() + coffee_sprite_->getWidth());
dustBitmapR->setPosY(y); dust_right_sprite_->setPosY(y_);
dustBitmapR->setWidth(16); dust_right_sprite_->setWidth(16);
dustBitmapR->setHeight(16); dust_right_sprite_->setHeight(16);
dustBitmapR->setFlip(SDL_FLIP_HORIZONTAL); dust_right_sprite_->setFlip(SDL_FLIP_HORIZONTAL);
// Inicializa el bitmap de 'DustLeft' // Inicializa el bitmap de 'DustLeft'
dustBitmapL->resetAnimation(); dust_left_sprite_->resetAnimation();
dustBitmapL->setPosX(coffeeBitmap->getPosX() - 16); dust_left_sprite_->setPosX(coffee_sprite_->getPosX() - 16);
dustBitmapL->setPosY(y); dust_left_sprite_->setPosY(y_);
dustBitmapL->setWidth(16); dust_left_sprite_->setWidth(16);
dustBitmapL->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
coffeeBitmap->render(); coffee_sprite_->render();
crisisBitmap->render(); crisis_sprite_->render();
if (status == finished) if (status_ == Status::FINISHED)
arcadeEditionBitmap->render(); {
arcade_edition_sprite_->render();
}
// Dibuja el polvillo del logo // Dibuja el polvillo del logo
dustBitmapR->render(); dust_right_sprite_->render();
dustBitmapL->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 == moving) if (status_ == Status::MOVING)
{ {
coffeeBitmap->update(); coffee_sprite_->update();
crisisBitmap->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 (coffeeBitmap->hasFinished() && crisisBitmap->hasFinished()) if (coffee_sprite_->hasFinished() && crisis_sprite_->hasFinished())
{ {
status = shaking; status_ = Status::SHAKING;
// Pantallazo blanco
//screen->flash(flashColor, 10);
// Reproduce el efecto sonoro // Reproduce el efecto sonoro
JA_PlaySound(crashSound); JA_PlaySound(crash_sound_);
} }
} }
else if (status == shaking) else if (status_ == 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 int desp = shake.remaining % 2 == 0 ? shake.desp * (-1) : shake.desp; const auto desp = shake_.remaining % 2 == 0 ? shake_.desp * (-1) : shake_.desp;
coffeeBitmap->setPosX(shake.origin + desp); coffee_sprite_->setPosX(shake_.origin + desp);
crisisBitmap->setPosX(shake.origin + desp + 15); crisis_sprite_->setPosX(shake_.origin + desp + 15);
shake.remaining--; shake_.remaining--;
} }
} }
else else
{ {
coffeeBitmap->setPosX(shake.origin); coffee_sprite_->setPosX(shake_.origin);
crisisBitmap->setPosX(shake.origin + 15); crisis_sprite_->setPosX(shake_.origin + 15);
status = finished; status_ = Status::FINISHED;
} }
dustBitmapR->update(); dust_right_sprite_->update();
dustBitmapL->update(); dust_left_sprite_->update();
} }
else if (status == finished) else if (status_ == Status::FINISHED)
{ {
dustBitmapR->update(); dust_right_sprite_->update();
dustBitmapL->update(); dust_left_sprite_->update();
} }
} }
@@ -196,28 +179,28 @@ void GameLogo::update()
void GameLogo::enable() void GameLogo::enable()
{ {
init(); init();
status = moving; status_ = Status::MOVING;
} }
// Indica si ha terminado la animación // Indica si ha terminado la animación
bool GameLogo::hasFinished() bool GameLogo::hasFinished() const
{ {
return (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()
{ {
int despUp = y; auto desp_up = y_;
int 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,51 +1,25 @@
#pragma once #pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <memory> // for unique_ptr, shared_ptr
class AnimatedSprite; class AnimatedSprite;
class Asset;
class Screen;
class SmartSprite; class SmartSprite;
class Sprite; class Sprite;
class Texture; class Texture;
struct JA_Sound_t; struct JA_Sound_t; // lines 10-10
// Clase GameLogo // Clase GameLogo
class GameLogo class GameLogo
{ {
private: private:
// Objetos y punteros enum class Status
SDL_Renderer *renderer; // El renderizador de la ventana
Screen *screen; // Objeto encargado de dibujar en pantalla
Asset *asset; // Objeto que gestiona todos los ficheros de recursos
Texture *dustTexture; // Textura con los graficos del polvo
Texture *coffeeTexture; // Textura con los graficos de la palabra "COFFEE"
Texture *crisisTexture; // Textura con los graficos de la plabra "CRISIS"
Texture *arcadeEditionTexture; // Textura con los graficos de "Arcade Edition"
AnimatedSprite *dustBitmapL; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
AnimatedSprite *dustBitmapR; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
SmartSprite *coffeeBitmap; // Sprite con la palabra "COFFEE" para la pantalla de titulo
SmartSprite *crisisBitmap; // Sprite con la palabra "CRISIS" para la pantalla de titulo
Sprite *arcadeEditionBitmap; // 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 status_e
{ {
disabled, DISABLED,
moving, MOVING,
shaking, SHAKING,
finished FINISHED,
} status; // Estado en el que se encuentra la clase };
struct shake_t struct Shake
{ {
int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x
int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse
@@ -53,7 +27,30 @@ 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"
JA_Sound_t *crash_sound_; // Sonido con el impacto del título
// 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();
@@ -78,7 +75,7 @@ public:
void enable(); void enable();
// Indica si ha terminado la animación // Indica si ha terminado la animación
bool hasFinished(); bool hasFinished() const;
// Recarga las texturas // Recarga las texturas
void reLoad(); void reLoad();

View File

@@ -6,15 +6,31 @@
#include "options.h" // for options #include "options.h" // for options
#include "on_screen_help.h" #include "on_screen_help.h"
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "section.h" // for options_e, name, name_e, options #include "section.h" // for SectionOptions, name, SectionName, options
#include "utils.h" // for op_audio_t, options_t, op_music_t, boolToOnOff #include "utils.h" // for OptionsAudio, Options, OptionsMusic, boolToOnOff
namespace globalInputs
{
// Variables
std::vector<int> service_pressed_counter;
// Inicializa variables
void init()
{
const auto num_inputs = Input::get()->getNumControllers() + 1;
service_pressed_counter.reserve(num_inputs);
for (int i = 0; i < num_inputs; ++i)
{
service_pressed_counter.push_back(0);
}
}
// Termina // Termina
void quit(section::options_e code) void quit(section::Options code)
{ {
if (Screen::get()->notificationsAreActive()) if (Screen::get()->notificationsAreActive())
{ {
section::name = section::NAME_QUIT; section::name = section::Name::QUIT;
section::options = code; section::options = code;
} }
else else
@@ -26,7 +42,7 @@ void quit(section::options_e code)
// Reinicia // Reinicia
void reset() void reset()
{ {
section::name = section::NAME_INIT; section::name = section::Name::INIT;
Screen::get()->showNotification("Reset"); Screen::get()->showNotification("Reset");
} }
@@ -40,55 +56,82 @@ void switchAudio()
} }
// 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 checkGlobalInputs() void check()
{ {
// Comprueba si se sale con el teclado // Comprueba si se sale con el teclado
if (Input::get()->checkInput(input_exit, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
quit(section::OPTIONS_QUIT_NORMAL); quit(section::Options::QUIT_NORMAL);
return; return;
} }
// Comprueba si se va a resetear el juego // Comprueba si se va a resetear el juego
else if (Input::get()->checkInput(input_reset, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) else if (Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
reset(); reset();
return; return;
} }
else if (Input::get()->checkInput(input_mute, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) else if (Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
switchAudio(); switchAudio();
return; return;
} }
else if (Input::get()->checkInput(input_service, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) else if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{
service_pressed_counter[0]++;
if (service_pressed_counter[0] >= 3000)
{ {
OnScreenHelp::get()->toggleState(); OnScreenHelp::get()->toggleState();
service_pressed_counter[0] = 0;
}
return; return;
} }
else
{
service_pressed_counter[0] = 0;
}
for (int i = 0; i < Input::get()->getNumControllers(); ++i) for (int i = 0; i < Input::get()->getNumControllers(); ++i)
{ {
// Comprueba si se sale con el mando // Comprueba si se sale con el mando
if (Input::get()->checkModInput(input_service, input_exit, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkModInput(InputType::SERVICE, InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
quit(section::OPTIONS_QUIT_SHUTDOWN); quit(section::Options::QUIT_SHUTDOWN);
return; return;
} }
// Comprueba si se va a resetear el juego // Comprueba si se va a resetear el juego
else if (Input::get()->checkModInput(input_service, input_reset, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) else if (Input::get()->checkModInput(InputType::SERVICE, InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
reset(); reset();
return; return;
} }
// Comprueba si se va a activar o desactivar el audio // Comprueba si se va a activar o desactivar el audio
else if (Input::get()->checkModInput(input_service, input_mute, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) else if (Input::get()->checkModInput(InputType::SERVICE, InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
switchAudio(); switchAudio();
return; return;
} }
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{
service_pressed_counter[i + 1]++;
if (service_pressed_counter[i + 1] >= 3000)
{
OnScreenHelp::get()->toggleState();
service_pressed_counter[i + 1] = 0;
}
return;
}
else
{
service_pressed_counter[i + 1] = 0;
}
}
} }
} }

View File

@@ -1,2 +1,11 @@
#include <vector>
namespace globalInputs
{
extern std::vector<int> service_pressed_counter;
// Inicializa variables
void init();
// 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 checkGlobalInputs(); void check();
}

View File

@@ -1,5 +1,6 @@
#include "hiscore_table.h" #include "hiscore_table.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_QUIT
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED #include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED
@@ -7,56 +8,53 @@
#include <vector> // for vector #include <vector> // for vector
#include "asset.h" // for Asset #include "asset.h" // for Asset
#include "background.h" // for Background #include "background.h" // for Background
#include "fade.h" // for Fade, FADE_IN, FADE_OUT, FADE_RANDOM... #include "fade.h" // for Fade, FadeMode, FadeType
#include "global_inputs.h" // for checkGlobalInputs #include "global_inputs.h" // for check
#include "input.h" // for Input #include "input.h" // for Input
#include "jail_audio.h" // for JA_GetMusicState, JA_Music_state #include "jail_audio.h" // for JA_GetMusicState, JA_Music_state
#include "lang.h" // for getText #include "lang.h" // for getText
#include "options.h" // for options #include "options.h" // for options
#include "param.h" // for param #include "param.h" // for param
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "text.h" // for Text, TXT_CENTER, TXT_SHADOW, TXT_COLOR #include "section.h" // for Name, name, Options, options
#include "utils.h" // for param_t, paramGame_t, hiScoreEntry_t #include "text.h" // for Text, TEXT_CENTER, TEXT_SHADOW, TEXT...
#include "utils.h" // for Param, ParamGame, Color, HiScoreEntry
// Constructor // Constructor
HiScoreTable::HiScoreTable(JA_Music_t *music) HiScoreTable::HiScoreTable(JA_Music_t *music)
: music_(music)
{ {
// Copia punteros // Copia punteros
this->music = music; renderer_ = Screen::get()->getRenderer();
asset = Asset::get();
input = Input::get();
screen = Screen::get();
renderer = screen->getRenderer();
// Objetos // Objetos
eventHandler = new SDL_Event(); fade_ = std::make_unique<Fade>(renderer_);
fade = new Fade(renderer); background_ = std::make_unique<Background>(renderer_);
background = new Background(renderer); text_ = std::make_unique<Text>(Asset::get()->get("smb2.gif"), Asset::get()->get("smb2.txt"), renderer_);
text = new Text(asset->get("smb2.gif"), asset->get("smb2.txt"), 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); 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 variables // Inicializa variables
section::name = section::NAME_HI_SCORE_TABLE; section::name = section::Name::HI_SCORE_TABLE;
ticks = 0; ticks_ = 0;
ticksSpeed = 15; ticks_speed_ = 15;
counter = 0; counter_ = 0;
counterEnd = 800; counter_end_ = 800;
viewArea = {0, 0, param.game.width, param.game.height}; view_area_ = {0, 0, param.game.width, param.game.height};
fadeMode = FADE_IN; fade_mode_ = FadeMode::IN;
// Inicializa objetos // Inicializa objetos
background->setPos(param.game.gameArea.rect); background_->setPos(param.game.game_area.rect);
background->setCloudsSpeed(-0.1f); background_->setCloudsSpeed(-0.1f);
background->setGradientNumber(1); background_->setGradientNumber(1);
background->setTransition(0.8f); background_->setTransition(0.8f);
fade->setColor(fadeColor.r, fadeColor.g, fadeColor.b); fade_->setColor(fade_color.r, fade_color.g, fade_color.b);
fade->setType(FADE_RANDOM_SQUARE); fade_->setType(FadeType::RANDOM_SQUARE);
fade->setPost(param.fade.postDuration); fade_->setPost(param.fade.post_duration);
fade->setMode(fadeMode); fade_->setMode(fade_mode_);
fade->activate(); 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();
@@ -65,47 +63,45 @@ HiScoreTable::HiScoreTable(JA_Music_t *music)
// Destructor // Destructor
HiScoreTable::~HiScoreTable() HiScoreTable::~HiScoreTable()
{ {
delete text; SDL_DestroyTexture(backbuffer_);
delete eventHandler;
delete background;
SDL_DestroyTexture(backbuffer);
} }
// Actualiza las variables // Actualiza las variables
void HiScoreTable::update() void HiScoreTable::update()
{ {
// Actualiza las variables // Actualiza las variables
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(music_);
}
// Actualiza el objeto screen // Actualiza el objeto screen
screen->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({0, 0, 0});
background->setAlpha(96); background_->setAlpha(96);
} }
if (counter == counterEnd) if (counter_ == counter_end_)
{ {
fade->activate(); fade_->activate();
} }
} }
} }
@@ -113,70 +109,71 @@ 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
const int maxNames = 10; constexpr auto max_names = 10;
const int spaceBetweenHeader = 32; constexpr auto space_between_header = 32;
const int spaceBetweenLines = text->getCharacterSize() * 2.0f; const auto space_between_lines = text_->getCharacterSize() * 2.0f;
const int size = spaceBetweenHeader + spaceBetweenLines * (maxNames - 1) + text->getCharacterSize(); const auto size = space_between_header + space_between_lines * (max_names - 1) + text_->getCharacterSize();
const int 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
SDL_Texture *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.gameArea.centerX, firstLine, lang::getText(42), 1, orangeColor, 1, shdwTxtColor); 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 int nameLenght = options.game.hiScoreTable[i].name.length(); const auto name_lenght = options.game.hi_score_table[i].name.length();
const std::string score = format(options.game.hiScoreTable[i].score); const auto score = format(options.game.hi_score_table[i].score);
const int scoreLenght = score.size(); const auto score_lenght = score.size();
const int numDots = 25 - nameLenght - scoreLenght; const auto num_dots = 25 - name_lenght - score_lenght;
std::string dots = ""; std::string dots;
for (int j = 0; j < numDots; ++j) for (int j = 0; j < (int)num_dots; ++j)
{ {
dots = dots + "."; dots = dots + ".";
} }
const std::string line = options.game.hiScoreTable[i].name + dots + score; const auto line = options.game.hi_score_table[i].name + dots + score;
text->writeDX(TXT_CENTER | TXT_SHADOW, param.game.gameArea.centerX, (i * spaceBetweenLines) + firstLine + spaceBetweenHeader, line, 1, orangeColor, 1, shdwTxtColor); 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
void HiScoreTable::render() void HiScoreTable::render()
{ {
// Prepara para empezar a dibujar en la textura de juego // Prepara para empezar a dibujar en la textura de juego
screen->start(); Screen::get()->start();
// Limpia la pantalla // Limpia la pantalla
screen->clean(bgColor); 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_);
fade->render(); // Renderiza el fade
fade_->render();
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
screen->blit(); Screen::get()->blit();
} }
// Recarga todas las texturas // Recarga todas las texturas
void HiScoreTable::reloadTextures() void HiScoreTable::reloadTextures()
{ {
text->reLoadTexture(); text_->reLoadTexture();
fillTexture(); fillTexture();
} }
@@ -184,19 +181,20 @@ 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) != 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;
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();
} }
@@ -208,25 +206,25 @@ void HiScoreTable::checkEvents()
void HiScoreTable::checkInput() void HiScoreTable::checkInput()
{ {
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar) // Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
if (input->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 // Comprueba el input para el resto de objetos
screen->checkInput(); 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
checkGlobalInputs(); globalInputs::check();
} }
// 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();
@@ -235,62 +233,21 @@ void HiScoreTable::run()
} }
} }
// Transforma un valor numérico en una cadena de 6 cifras
std::string HiScoreTable::scoreToString(int num)
{
if ((num >= 0) && (num <= 9))
{
return ("000000" + std::to_string(num));
}
if ((num >= 10) && (num <= 99))
{
return ("00000" + std::to_string(num));
}
if ((num >= 100) && (num <= 999))
{
return ("0000" + std::to_string(num));
}
if ((num >= 1000) && (num <= 9999))
{
return ("000" + std::to_string(num));
}
if ((num >= 010000) && (num <= 99999))
{
return ("00" + std::to_string(num));
}
if ((num >= 100000) && (num <= 999999))
{
return ("0" + std::to_string(num));
}
if ((num >= 1000000) && (num <= 9999999))
{
return (std::to_string(num));
}
return (std::to_string(num));
}
// Gestiona el fade // Gestiona el fade
void HiScoreTable::updateFade() void HiScoreTable::updateFade()
{ {
fade->update(); fade_->update();
if (fade->hasEnded() && fadeMode == FADE_IN) if (fade_->hasEnded() && fade_mode_ == FadeMode::IN)
{ {
fade->reset(); fade_->reset();
fadeMode = FADE_OUT; fade_mode_ = FadeMode::OUT;
fade->setMode(fadeMode); fade_->setMode(fade_mode_);
} }
if (fade->hasEnded() && fadeMode == FADE_OUT) if (fade_->hasEnded() && fade_mode_ == FadeMode::OUT)
{ {
section::name = section::NAME_INSTRUCTIONS; section::name = section::Name::INSTRUCTIONS;
} }
} }
@@ -300,9 +257,9 @@ std::string HiScoreTable::format(int number)
const std::string separator = "."; const std::string separator = ".";
const std::string score = std::to_string(number); const std::string score = std::to_string(number);
int index = (int)score.size() - 1; auto index = (int)score.size() - 1;
std::string result = ""; std::string result;
int i = 0; auto i = 0;
while (index >= 0) while (index >= 0)
{ {
result = score.at(index) + result; result = score.at(index) + result;

View File

@@ -1,18 +1,15 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint16, Uint32 #include <SDL2/SDL_stdinc.h> // for Uint16, Uint32, Uint8
#include <memory> // for unique_ptr
#include <string> // for string #include <string> // for string
#include "section.h" // for options_e class Background; // lines 8-8
class Asset; class Fade; // lines 9-9
class Background; class Text; // lines 10-10
class Fade; enum class FadeMode : Uint8; // lines 11-11
class Input; struct JA_Music_t; // lines 12-12
class Screen;
class Text;
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
@@ -29,24 +26,21 @@ class HiScoreTable
{ {
private: private:
// 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 SDL_Texture *backbuffer_; // Textura para usar como backbuffer
SDL_Event *eventHandler; // Manejador de eventos JA_Music_t *music_; // Musica de fondo
SDL_Texture *backbuffer; // Textura para usar como backbuffer
Asset *asset; // Objeto que gestiona todos los ficheros de recursos std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
Input *input; // Objeto pata gestionar la entrada std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
Background *background; // Objeto para dibujar el fondo del juego std::unique_ptr<Text> text_; // Objeto para escribir texto
Fade *fade; // Objeto para renderizar fades
Text *text; // Objeto para escribir texto
JA_Music_t *music; // Musica de fondo
// Variables // Variables
Uint16 counter; // Contador Uint16 counter_; // Contador
Uint16 counterEnd; // Valor final para el contador Uint16 counter_end_; // 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
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
SDL_Rect viewArea; // Parte de la textura que se muestra en pantalla SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla
int fadeMode; // Modo de fade a utilizar FadeMode fade_mode_; // Modo de fade a utilizar
// Actualiza las variables // Actualiza las variables
void update(); void update();
@@ -63,9 +57,6 @@ private:
// Convierte un entero a un string con separadores de miles // Convierte un entero a un string con separadores de miles
std::string format(int number); std::string format(int number);
// Transforma un valor numérico en una cadena de 6 cifras
std::string scoreToString(int num);
// Crea el contenido de la textura con la lista de puntuaciones // Crea el contenido de la textura con la lista de puntuaciones
void fillTexture(); void fillTexture();
@@ -75,12 +66,9 @@ private:
// Gestiona el fade // Gestiona el fade
void updateFade(); void updateFade();
// Termina
void quit(section::options_e code);
public: public:
// Constructor // Constructor
HiScoreTable(JA_Music_t *music); explicit HiScoreTable(JA_Music_t *music);
// Destructor // Destructor
~HiScoreTable(); ~HiScoreTable();

View File

@@ -6,125 +6,106 @@
#include <iostream> // for basic_ostream, operator<<, cout, basi... #include <iostream> // for basic_ostream, operator<<, cout, basi...
// [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 file) void Input::init(const std::string &game_controller_db_path)
{ {
Input::input = new Input(file); 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 file) Input::Input(const std::string &game_controller_db_path)
: game_controller_db_path_(game_controller_db_path),
enabled_(true)
{ {
// Inicializa variables
verbose = false;
enabled = true;
// Fichero gamecontrollerdb.txt
dbPath = file;
// Busca si hay mandos conectados // Busca si hay mandos conectados
discoverGameControllers(); discoverGameControllers();
// Inicializa las vectores // Inicializa las vectores
keyBindings_t kb; KeyBindings kb;
kb.scancode = 0; kb.scancode = 0;
kb.active = false; kb.active = false;
keyBindings.resize(input_number_of_inputs, kb); key_bindings_.resize(static_cast<int>(InputType::NUMBER_OF_INPUTS), kb);
GameControllerBindings_t gcb; ControllerBindings gcb;
gcb.button = SDL_CONTROLLER_BUTTON_INVALID; gcb.button = SDL_CONTROLLER_BUTTON_INVALID;
gcb.active = false; gcb.active = false;
gameControllerBindings.resize(numGamepads); controller_bindings_.resize(num_gamepads_);
for (int i = 0; i < numGamepads; ++i) for (int i = 0; i < num_gamepads_; ++i)
{ {
gameControllerBindings[i].resize(input_number_of_inputs, gcb); controller_bindings_[i].resize(static_cast<int>(InputType::NUMBER_OF_INPUTS), gcb);
} }
// Listado de los inputs usados para jugar, excluyendo botones para la interfaz // Listado de los inputs usados para jugar, excluyendo botones para la interfaz
gameInputs.clear(); game_inputs_.clear();
gameInputs.push_back(input_fire_left); game_inputs_.push_back(InputType::FIRE_LEFT);
gameInputs.push_back(input_fire_center); game_inputs_.push_back(InputType::FIRE_CENTER);
gameInputs.push_back(input_fire_right); game_inputs_.push_back(InputType::FIRE_RIGHT);
gameInputs.push_back(input_up); game_inputs_.push_back(InputType::UP);
gameInputs.push_back(input_down); game_inputs_.push_back(InputType::DOWN);
gameInputs.push_back(input_left); game_inputs_.push_back(InputType::LEFT);
gameInputs.push_back(input_right); game_inputs_.push_back(InputType::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_.clear();
buttonInputs.push_back(input_fire_left); button_inputs_.push_back(InputType::FIRE_LEFT);
buttonInputs.push_back(input_fire_center); button_inputs_.push_back(InputType::FIRE_CENTER);
buttonInputs.push_back(input_fire_right); button_inputs_.push_back(InputType::FIRE_RIGHT);
buttonInputs.push_back(input_start); button_inputs_.push_back(InputType::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_[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_[controller_index][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_[controller_index][static_cast<int>(input_target)].button = controller_bindings_[controller_index][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, int device, int controller_index)
{ {
if (!enabled) if (!enabled_)
{ {
return false; return false;
} }
bool successKeyboard = false; bool success_keyboard = false;
bool successGameController = false; bool success_controller = false;
const int input_index = static_cast<int>(input);
if (device == INPUT_USE_ANY) if (device == INPUT_USE_ANY)
{ {
index = 0; controller_index = 0;
} }
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY) if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
@@ -133,108 +114,109 @@ bool Input::checkInput(inputs_e input, bool repeat, int device, int index)
if (repeat) if (repeat)
{ {
if (keyStates[keyBindings[input].scancode] != 0) if (keyStates[key_bindings_[input_index].scancode] != 0)
{ {
successKeyboard = true; success_keyboard = true;
} }
else else
{ {
successKeyboard = false; success_keyboard = 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; success_keyboard = false;
} }
else else
{ {
successKeyboard = false; success_keyboard = false;
} }
} }
} }
} }
if (gameControllerFound() && index < numGamepads) if (gameControllerFound() && controller_index < num_gamepads_)
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY)) if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_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) if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
{ {
successGameController = true; success_controller = true;
} }
else else
{ {
successGameController = false; success_controller = false;
} }
} }
else else
{ {
if (!gameControllerBindings[index][input].active) if (!controller_bindings_[controller_index][input_index].active)
{ {
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) != 0) if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
{ {
gameControllerBindings[index][input].active = true; controller_bindings_[controller_index][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_[controller_index], controller_bindings_[controller_index][input_index].button) == 0)
{ {
gameControllerBindings[index][input].active = false; controller_bindings_[controller_index][input_index].active = false;
successGameController = false; success_controller = false;
} }
else else
{ {
successGameController = false; success_controller = false;
} }
} }
} }
} }
} }
return (successKeyboard || successGameController); return (success_keyboard || success_controller);
} }
// Comprueba si un input con modificador esta activo // Comprueba si un input con modificador esta activo
bool Input::checkModInput(inputs_e inputMod, inputs_e input, bool repeat, int device, int index) bool Input::checkModInput(InputType input_mod, InputType input, bool repeat, int device, int controller_index)
{ {
if (!enabled || index >= numGamepads || !checkInput(inputMod, INPUT_ALLOW_REPEAT, device, index)) if (!enabled_ || controller_index >= num_gamepads_ || !checkInput(input_mod, INPUT_ALLOW_REPEAT, device, controller_index))
{ {
return false; return false;
} }
bool successKeyboard = false; bool success_keyboard = false;
bool successGameController = false; bool success_controller = false;
const int input_index = static_cast<int>(input);
if (device == INPUT_USE_ANY) if (device == INPUT_USE_ANY)
{ {
index = 0; controller_index = 0;
} }
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY) if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
@@ -243,111 +225,111 @@ bool Input::checkModInput(inputs_e inputMod, inputs_e input, bool repeat, int de
if (repeat) if (repeat)
{ {
if (keyStates[keyBindings[input].scancode] != 0) if (keyStates[key_bindings_[input_index].scancode] != 0)
{ {
successKeyboard = true; success_keyboard = true;
} }
else else
{ {
successKeyboard = false; success_keyboard = 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; success_keyboard = false;
} }
else else
{ {
successKeyboard = false; success_keyboard = false;
} }
} }
} }
} }
if (gameControllerFound() && index < numGamepads) if (gameControllerFound() && controller_index < num_gamepads_)
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY)) if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_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) if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
{ {
successGameController = true; success_controller = true;
} }
else else
{ {
successGameController = false; success_controller = false;
} }
} }
else else
{ {
if (!gameControllerBindings[index][input].active) if (!controller_bindings_[controller_index][input_index].active)
{ {
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) != 0) if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
{ {
gameControllerBindings[index][input].active = true; controller_bindings_[controller_index][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_[controller_index], controller_bindings_[controller_index][input_index].button) == 0)
{ {
gameControllerBindings[index][input].active = false; controller_bindings_[controller_index][input_index].active = false;
successGameController = false; success_controller = false;
} }
else else
{ {
successGameController = false; success_controller = false;
} }
} }
} }
} }
} }
return (successKeyboard || successGameController); return (success_keyboard || success_controller);
} }
// Comprueba si hay almenos un input activo // Comprueba si hay almenos un input activo
bool Input::checkAnyInput(int device, int index) bool Input::checkAnyInput(int device, int controller_index)
{ {
if (device == INPUT_USE_ANY) if (device == INPUT_USE_ANY)
{ {
index = 0; controller_index = 0;
} }
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY) 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;
} }
} }
@@ -357,11 +339,11 @@ bool Input::checkAnyInput(int device, int index)
{ {
if (device == INPUT_USE_GAMECONTROLLER || device == INPUT_USE_ANY) if (device == INPUT_USE_GAMECONTROLLER || device == INPUT_USE_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;
} }
} }
@@ -375,13 +357,13 @@ 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, INPUT_USE_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, INPUT_USE_KEYBOARD))
@@ -390,7 +372,7 @@ int Input::checkAnyButtonPressed(bool repeat)
} }
// 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, INPUT_USE_GAMECONTROLLER, i))
{ {
@@ -412,62 +394,63 @@ 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) #ifdef VERBOSE
{ {
std::cout << "Error, could not load " << dbPath.c_str() << " file: " << SDL_GetError() << std::endl; std::cout << "Error, could not load " << game_controller_db_path_.c_str() << " file: " << SDL_GetError() << std::endl;
} }
#endif
} }
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); SDL_Joystick *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) #ifdef VERBOSE
{ {
std::cout << "\nChecking for game controllers...\n"; std::cout << "\nChecking for game controllers...\n";
std::cout << numJoysticks << " joysticks found, " << numGamepads << " are gamepads\n"; std::cout << num_joysticks_ << " joysticks found, " << num_gamepads_ << " are gamepads\n";
} }
#endif
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); #ifdef VERBOSE
// name.resize(25);
// name = name + separator + std::to_string(i);
if (verbose)
{ {
std::cout << name << std::endl; std::cout << name << std::endl;
} }
controllerNames.push_back(name); #endif
controller_names_.push_back(name);
} }
else else
{ {
if (verbose) #ifdef VERBOSE
{ {
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl; std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
} }
#endif
} }
} }
@@ -480,47 +463,27 @@ bool Input::discoverGameControllers()
// Comprueba si hay algun mando conectado // Comprueba si hay algun mando conectado
bool Input::gameControllerFound() bool Input::gameControllerFound()
{ {
return numGamepads > 0 ? true : false; return num_gamepads_ > 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) std::string Input::getControllerName(int controller_index) const
{ {
return numGamepads > 0 ? controllerNames[index] : ""; return num_gamepads_ > 0 ? controller_names_[controller_index] : "";
} }
// Obten el número de mandos conectados // Obten el número de mandos conectados
int Input::getNumControllers() int Input::getNumControllers() const
{ {
return numGamepads; return num_gamepads_;
}
// 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) 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;
} }
@@ -529,7 +492,7 @@ int Input::getJoyIndex(int id)
} }
// Muestra por consola los controles asignados // Muestra por consola los controles asignados
void Input::printBindings(int device, int index) void Input::printBindings(int device, int controller_index) const
{ {
if (device == INPUT_USE_ANY || device == INPUT_USE_KEYBOARD) if (device == INPUT_USE_ANY || device == INPUT_USE_KEYBOARD)
{ {
@@ -538,35 +501,35 @@ void Input::printBindings(int device, int index)
if (device == INPUT_USE_GAMECONTROLLER) if (device == INPUT_USE_GAMECONTROLLER)
{ {
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"
<< controllerNames[index] << std::endl; << controller_names_[controller_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_[controller_index][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) 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) int Input::getIndexByName(const std::string &name) const
{ {
for (int i = 0; i < numGamepads; ++i) for (int i = 0; i < num_gamepads_; ++i)
{ {
if (controllerNames[i] == name) if (controller_names_[i] == name)
{ {
return i; return i;
} }
@@ -574,30 +537,30 @@ int Input::getIndexByName(std::string name)
return -1; return -1;
} }
// Convierte un inputs_e a std::string // Convierte un InputType a std::string
std::string Input::to_string(inputs_e input) std::string Input::to_string(InputType input) const
{ {
if (input == input_fire_left) if (input == InputType::FIRE_LEFT)
{ {
return "input_fire_left"; return "input_fire_left";
} }
if (input == input_fire_center) if (input == InputType::FIRE_CENTER)
{ {
return "input_fire_center"; return "input_fire_center";
} }
if (input == input_fire_right) if (input == InputType::FIRE_RIGHT)
{ {
return "input_fire_right"; return "input_fire_right";
} }
if (input == input_start) if (input == InputType::START)
{ {
return "input_start"; return "input_start";
} }
if (input == input_service) if (input == InputType::SERVICE)
{ {
return "input_service"; return "input_service";
} }
@@ -605,76 +568,67 @@ std::string Input::to_string(inputs_e input)
return ""; return "";
} }
// Convierte un std::string a inputs_e // Convierte un std::string a InputType
inputs_e Input::to_inputs_e(std::string name) InputType Input::to_inputs_e(const std::string &name) const
{ {
if (name == "input_fire_left") if (name == "input_fire_left")
{ {
return input_fire_left; return InputType::FIRE_LEFT;
} }
if (name == "input_fire_center") if (name == "input_fire_center")
{ {
return input_fire_center; return InputType::FIRE_CENTER;
} }
if (name == "input_fire_right") if (name == "input_fire_right")
{ {
return input_fire_right; return InputType::FIRE_RIGHT;
} }
if (name == "input_start") if (name == "input_start")
{ {
return input_start; return InputType::START;
} }
if (name == "input_service") if (name == "input_service")
{ {
return input_service; return InputType::SERVICE;
} }
return input_null; return InputType::NONE;
}
// 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) bool Input::checkAxisInput(InputType input, int controller_index) const
{ {
bool success = false; bool success = false;
switch (input) switch (input)
{ {
case input_left: case InputType::LEFT:
if (SDL_GameControllerGetAxis(connectedControllers[index], SDL_CONTROLLER_AXIS_LEFTX) < -30000) if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) < -30000)
{ {
success = true; success = true;
} }
break; break;
case input_right: case InputType::RIGHT:
if (SDL_GameControllerGetAxis(connectedControllers[index], SDL_CONTROLLER_AXIS_LEFTX) > 30000) if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) > 30000)
{ {
success = true; success = true;
} }
break; break;
case input_up: case InputType::UP:
if (SDL_GameControllerGetAxis(connectedControllers[index], SDL_CONTROLLER_AXIS_LEFTY) < -30000) if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) < -30000)
{ {
success = true; success = true;
} }
break; break;
case input_down: case InputType::DOWN:
if (SDL_GameControllerGetAxis(connectedControllers[index], SDL_CONTROLLER_AXIS_LEFTY) > 30000) if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) > 30000)
{ {
success = true; success = true;
} }

View File

@@ -16,98 +16,89 @@ device contiene el tipo de dispositivo a comprobar:
INPUT_USE_ANY mirará tanto el teclado como el PRIMER controlador INPUT_USE_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 constexpr int INPUT_USE_KEYBOARD = 0;
#define INPUT_USE_GAMECONTROLLER 1 constexpr int INPUT_USE_GAMECONTROLLER = 1;
#define INPUT_USE_ANY 2 constexpr int INPUT_USE_ANY = 2;
enum i_disable_e
{
d_notDisabled,
d_forever,
d_keyPressed
};
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
}; };
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
}; };
// 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> game_inputs_; // Inputs usados para jugar, normalmente direcciones y botones
std::vector<inputs_e> buttonInputs; // Inputs asignados al jugador y a botones, excluyendo direcciones std::vector<InputType> button_inputs_; // Inputs asignados al jugador y a botones, excluyendo direcciones
int numJoysticks; // Número de joysticks conectados int num_joysticks_; // Número de joysticks conectados
int numGamepads; // Número de mandos conectados int num_gamepads_; // Número de mandos conectados
std::string dbPath; // Ruta al archivo gamecontrollerdb.txt std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt
bool verbose; // Indica si ha de mostrar mensajes bool enabled_; // Indica si está habilitado
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); bool checkAxisInput(InputType input, int controller_index = 0) const;
// Constructor // Constructor
Input(std::string file); 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 file); 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 +106,21 @@ 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, int device = INPUT_USE_ANY, int controller_index = 0);
// Comprueba si un input con modificador esta activo // 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); bool checkModInput(InputType input_mod, InputType input, bool repeat = true, int device = INPUT_USE_ANY, int controller_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(int device = INPUT_USE_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);
@@ -144,38 +132,26 @@ public:
bool gameControllerFound(); bool gameControllerFound();
// Obten el número de mandos conectados // Obten el número de mandos conectados
int getNumControllers(); int getNumControllers() const;
// Obten el nombre de un mando de juego // Obten el nombre de un mando de juego
std::string getControllerName(int index); 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); 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); void printBindings(int device = INPUT_USE_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); 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); 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); 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); 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,66 +1,63 @@
#include "instructions.h" #include "instructions.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_QUIT
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED #include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED
#include <algorithm> // for max #include <algorithm> // for max
#include <string> // for basic_string #include <utility> // for move
#include "asset.h" // for Asset #include "asset.h" // for Asset
#include "fade.h" // for Fade, FADE_FULLSCREEN, FADE_IN #include "fade.h" // for Fade, FadeMode, FadeType
#include "global_inputs.h" // for checkGlobalInputs #include "global_inputs.h" // for check
#include "input.h" // for Input #include "input.h" // for Input
#include "jail_audio.h" // for JA_GetMusicState, JA_Music_state #include "jail_audio.h" // for JA_GetMusicState, JA_Music_state
#include "lang.h" // for getText #include "lang.h" // for getText
#include "param.h" // for param #include "param.h" // for param
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "section.h" // for name, name_e, options, options_e #include "section.h" // for Name, name, Options, options
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "text.h" // for Text, TXT_CENTER, TXT_COLOR, TXT_SHADOW #include "text.h" // for Text, TEXT_CENTER, TEXT_COLOR, TEXT_...
#include "texture.h" // for Texture #include "texture.h" // for Texture
#include "tiled_bg.h" // for Tiledbg, TILED_MODE_STATIC #include "tiled_bg.h" // for Tiledbg, TILED_MODE_STATIC
#include "utils.h" // for param_t, paramGame_t, color_t, shdwT... #include "utils.h" // for Param, ParamGame, Color, shdw_txt_color
struct JA_Music_t; struct JA_Music_t; // lines 22-22
// Constructor // Constructor
Instructions::Instructions(JA_Music_t *music) Instructions::Instructions(JA_Music_t *music)
: music_(music)
{ {
// Copia los punteros // Copia los punteros
this->music = music; renderer_ = Screen::get()->getRenderer();
input = Input::get();
screen = Screen::get();
asset = Asset::get();
renderer = screen->getRenderer();
// Crea objetos // Crea objetos
eventHandler = new SDL_Event(); text_ = std::make_unique<Text>(Asset::get()->get("smb2.gif"), Asset::get()->get("smb2.txt"), renderer_);
text = new Text(asset->get("smb2.gif"), asset->get("smb2.txt"), renderer); tiled_bg_ = std::make_unique<Tiledbg>(Asset::get()->get("title_bg_tile.png"), (SDL_Rect){0, 0, param.game.width, param.game.height}, TILED_MODE_STATIC);
tiledbg = new Tiledbg(asset->get("title_bg_tile.png"), {0, 0, param.game.width, param.game.height}, TILED_MODE_STATIC); fade_ = std::make_unique<Fade>(renderer_);
fade = new 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); 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); 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; ticks_ = 0;
ticksSpeed = 15; ticks_speed_ = 15;
counter = 0; counter_ = 0;
counterEnd = 700; counter_end_ = 700;
view = {0, 0, param.game.width, param.game.height}; view_ = {0, 0, param.game.width, param.game.height};
spritePos = {0, 0}; sprite_pos_ = {0, 0};
itemSpace = 2; item_space_ = 2;
// Inicializa objetos // Inicializa objetos
fade->setColor(fadeColor.r, fadeColor.g, fadeColor.b); fade_->setColor(fade_color.r, fade_color.g, fade_color.b);
fade->setType(FADE_FULLSCREEN); fade_->setType(FadeType::FULLSCREEN);
fade->setPost(param.fade.postDuration); fade_->setPost(param.fade.post_duration);
fade->setMode(FADE_IN); fade_->setMode(FadeMode::IN);
fade->activate(); fade_->activate();
// Rellena la textura de texto // Rellena la textura de texto
fillTexture(); fillTexture();
@@ -72,205 +69,190 @@ Instructions::Instructions(JA_Music_t *music)
// Destructor // Destructor
Instructions::~Instructions() Instructions::~Instructions()
{ {
for (auto texture : itemTextures) item_textures_.clear();
{ sprites_.clear();
texture->unload();
delete texture;
}
itemTextures.clear();
for (auto sprite : sprites) SDL_DestroyTexture(backbuffer_);
{ SDL_DestroyTexture(texture_);
delete sprite;
}
sprites.clear();
delete eventHandler;
delete text;
delete tiledbg;
delete fade;
SDL_DestroyTexture(backbuffer);
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
Texture *item1 = new Texture(renderer, asset->get("item_points1_disk.png")); auto item1 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_points1_disk.png"));
itemTextures.push_back(item1); item_textures_.push_back(item1);
Texture *item2 = new Texture(renderer, asset->get("item_points2_gavina.png")); auto item2 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_points2_gavina.png"));
itemTextures.push_back(item2); item_textures_.push_back(item2);
Texture *item3 = new Texture(renderer, asset->get("item_points3_pacmar.png")); auto item3 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_points3_pacmar.png"));
itemTextures.push_back(item3); item_textures_.push_back(item3);
Texture *item4 = new Texture(renderer, asset->get("item_clock.png")); auto item4 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_clock.png"));
itemTextures.push_back(item4); item_textures_.push_back(item4);
Texture *item5 = new Texture(renderer, asset->get("item_coffee.png")); auto item5 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_coffee.png"));
itemTextures.push_back(item5); item_textures_.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)
{ {
Sprite *sprite = new Sprite(0, 0, param.game.itemSize, param.game.itemSize, itemTextures[i]); auto sprite = std::make_unique<Sprite>(0, 0, param.game.item_size, param.game.item_size, item_textures_[i]);
sprite->setPos((SDL_Point){spritePos.x, spritePos.y + ((param.game.itemSize + itemSpace) * i)}); sprite->setPos((SDL_Point){sprite_pos_.x, sprite_pos_.y + ((param.game.item_size + item_space_) * i)});
sprites.push_back(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.itemSize, param.game.itemSize}; SDL_Rect src_rect = {0, 0, param.game.item_size, param.game.item_size};
// Disquito // Disquito
srcRect.y = param.game.itemSize * (((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.itemSize * (((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.itemSize * (((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.itemSize * (((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.itemSize * (((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.itemSize + 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.itemSize + 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.gameArea.centerX, firstLine, lang::getText(11), 1, orangeColor, 1, shdwTxtColor); 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.gameArea.centerX, anchor1 + spaceBetweenLines * 0, lang::getText(12), 1, noColor, 1, shdwTxtColor); 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.gameArea.centerX, anchor1 + spaceBetweenLines * 1, lang::getText(13), 1, noColor, 1, shdwTxtColor); 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.gameArea.centerX, anchor1 + spaceNewParagraph + spaceBetweenLines * 2, lang::getText(14), 1, noColor, 1, shdwTxtColor); 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.gameArea.centerX, anchor1 + spaceNewParagraph + spaceBetweenLines * 3, lang::getText(15), 1, noColor, 1, shdwTxtColor); 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.gameArea.centerX, anchor2, lang::getText(16), 1, orangeColor, 1, shdwTxtColor); 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.itemSize + text->getCharacterSize()) / 2); // const int anchor4 = anchor3 + ((param.game.item_size + text->getCharacterSize()) / 2);
text->writeShadowed(anchorItem + despX, anchor3 + spaceBetweenItemLines * 0, lang::getText(17), shdwTxtColor); 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), shdwTxtColor); 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), shdwTxtColor); 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), shdwTxtColor); 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), shdwTxtColor); 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.itemSize - 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 // Actualiza las variables
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(music_);
// Actualiza el objeto screen // Actualiza el objeto screen
screen->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;
} }
} }
} }
@@ -282,34 +264,34 @@ void Instructions::render()
fillBackbuffer(); fillBackbuffer();
// Prepara para empezar a dibujar en la textura de juego // Prepara para empezar a dibujar en la textura de juego
screen->start(); Screen::get()->start();
// Limpia la pantalla // Limpia la pantalla
screen->clean(bgColor); 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->blit(); Screen::get()->blit();
} }
// 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();
} }
@@ -317,19 +299,20 @@ 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) != 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;
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();
} }
@@ -341,25 +324,25 @@ void Instructions::checkEvents()
void Instructions::checkInput() void Instructions::checkInput()
{ {
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar) // Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
if (input->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 // Comprueba el input para el resto de objetos
screen->checkInput(); 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
checkGlobalInputs(); globalInputs::check();
} }
// 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,19 +1,16 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event
#include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Texture, SDL_Renderer #include <SDL2/SDL_render.h> // for SDL_Texture, SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for unique_ptr, shared_ptr
#include <vector> // for vector #include <vector> // for vector
class Asset;
class Fade; class Fade;
class Input;
class Screen;
class Sprite; class Sprite;
class Text; class Text;
class Texture; class Texture;
class Tiledbg; class Tiledbg;
struct JA_Music_t; struct JA_Music_t; // lines 14-14
/* /*
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
@@ -33,28 +30,25 @@ class Instructions
{ {
private: private:
// Objetos y punteros // Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
Screen *screen; // Objeto encargado de dibujar en pantalla std::vector<std::unique_ptr<Sprite>> sprites_; // Vector con los sprites de los items
std::vector<Texture *> itemTextures; // Vector con las texturas de los items std::unique_ptr<Text> text_; // Objeto para escribir texto
std::vector<Sprite *> sprites; // Vector con los sprites de los items std::unique_ptr<Tiledbg> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo
SDL_Event *eventHandler; // Manejador de eventos std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
SDL_Texture *backbuffer; // Textura para usar como backbuffer
SDL_Texture *texture; // Textura fija con el texto SDL_Renderer *renderer_; // El renderizador de la ventana
Asset *asset; // Objeto que gestiona todos los ficheros de recursos JA_Music_t *music_; // Musica de fondo
Input *input; // Objeto pata gestionar la entrada SDL_Texture *texture_; // Textura fija con el texto
Text *text; // Objeto para escribir texto SDL_Texture *backbuffer_; // Textura para usar como backbuffer
Tiledbg *tiledbg; // Objeto para dibujar el mosaico animado de fondo
Fade *fade; // Objeto para renderizar fades
JA_Music_t *music; // Musica de fondo
// Variables // Variables
int counter; // Contador int counter_; // Contador
int counterEnd; // Valor final para el contador int counter_end_; // 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
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa Uint32 ticks_speed_; // 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 spritePos; // Posición del primer sprite SDL_Point sprite_pos_; // Posición del primer sprite
int itemSpace; // Espacio entre los items int item_space_; // Espacio entre los items
// Actualiza las variables // Actualiza las variables
void update(); void update();
@@ -85,7 +79,7 @@ private:
public: public:
// Constructor // Constructor
Instructions(JA_Music_t *music); explicit Instructions(JA_Music_t *music);
// Destructor // Destructor
~Instructions(); ~Instructions();

View File

@@ -1,206 +1,192 @@
#include "intro.h" #include "intro.h"
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED #include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED
#include <string> // for basic_string #include <utility> // for move
#include "asset.h" // for Asset #include "asset.h" // for Asset
#include "global_inputs.h" // for checkGlobalInputs #include "global_inputs.h" // for check
#include "input.h" // for Input #include "input.h" // for Input
#include "jail_audio.h" // for JA_StopMusic, JA_PlayMusic #include "jail_audio.h" // for JA_StopMusic, JA_PlayMusic
#include "lang.h" // for getText #include "lang.h" // for getText
#include "param.h" // for param #include "param.h" // for param
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "section.h" // for name, name_e, options, options_e #include "section.h" // for Name, name, Options, options
#include "smart_sprite.h" // for SmartSprite #include "smart_sprite.h" // for SmartSprite
#include "text.h" // for Text #include "text.h" // for Text
#include "texture.h" // for Texture #include "texture.h" // for Texture
#include "utils.h" // for paramGame_t, param_t, zone_t, BLOCK #include "utils.h" // for Param, ParamGame, Zone, BLOCK, Color
#include "writer.h" // for Writer #include "writer.h" // for Writer
struct JA_Music_t; struct JA_Music_t; // lines 19-19
// Constructor // Constructor
Intro::Intro(JA_Music_t *music) Intro::Intro(JA_Music_t *music)
: music_(music)
{ {
// Copia los punteros // Copia los punteros
this->music = music; auto renderer = Screen::get()->getRenderer();
input = Input::get();
asset = Asset::get();
screen = Screen::get();
SDL_Renderer *renderer = screen->getRenderer();
// Reserva memoria para los objetos // Reserva memoria para los objetos
eventHandler = new SDL_Event(); texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("intro.png"));
texture = new Texture(renderer, asset->get("intro.png")); text_ = std::make_shared<Text>(Asset::get()->get("nokia.png"), Asset::get()->get("nokia.txt"), renderer);
text = new Text(asset->get("nokia.png"), asset->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; ticks_ = 0;
ticksSpeed = 15; ticks_speed_ = 15;
scene = 1; scene_ = 1;
// Inicializa los bitmaps de la intro // Inicializa los bitmaps de la intro
const int totalBitmaps = 6; constexpr int totalBitmaps = 6;
for (int i = 0; i < totalBitmaps; ++i) for (int i = 0; i < totalBitmaps; ++i)
{ {
SmartSprite *ss = new SmartSprite(texture); auto ss = std::make_unique<SmartSprite>(texture_);
ss->setWidth(128); ss->setWidth(128);
ss->setHeight(96); ss->setHeight(96);
ss->setEnabledCounter(20); ss->setFinishedCounter(20);
ss->setDestX(param.game.gameArea.centerX - 64); ss->setDestX(param.game.game_area.center_x - 64);
ss->setDestY(param.game.gameArea.firstQuarterY - 24); ss->setDestY(param.game.game_area.first_quarter_y - 24);
bitmaps.push_back(ss); bitmaps_.push_back(std::move(ss));
} }
bitmaps[0]->setPosX(-128); bitmaps_[0]->setPosX(-128);
bitmaps[0]->setPosY(param.game.gameArea.firstQuarterY - 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.gameArea.firstQuarterY - 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.gameArea.centerX - 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]->setEnabledCounter(250); bitmaps_[2]->setFinishedCounter(250);
bitmaps[3]->setPosX(param.game.gameArea.centerX - 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.gameArea.centerX - 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.gameArea.firstQuarterY - 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
const int totalTexts = 9; constexpr int totalTexts = 9;
for (int i = 0; i < totalTexts; ++i) for (int i = 0; i < totalTexts; ++i)
{ {
Writer *w = new 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->setEnabledCounter(180); w->setFinishedCounter(180);
texts.push_back(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.gameArea.centerX); text->center(param.game.game_area.center_x);
}
}
// Destructor
Intro::~Intro()
{
delete eventHandler;
delete texture;
for (auto bitmap : bitmaps)
{
delete bitmap;
}
for (auto text : texts)
{
delete text;
} }
} }
// 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
void Intro::checkEvents() void Intro::checkEvents()
{ {
SDL_Event event;
// Comprueba los eventos que hay en la cola // Comprueba los eventos que hay en la cola
while (SDL_PollEvent(eventHandler) != 0) while (SDL_PollEvent(&event))
{ {
// Evento de salida de la aplicación switch (event.type)
if (eventHandler->type == SDL_QUIT)
{ {
section::name = section::NAME_QUIT; case SDL_QUIT:
{
section::name = section::Name::QUIT;
break; break;
} }
// Comprueba si se ha cambiado el tamaño de la ventana case SDL_WINDOWEVENT:
else if (eventHandler->type == SDL_WINDOWEVENT)
{ {
if (eventHandler->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{ {
reloadTextures(); reloadTextures();
} }
break;
}
default:
break;
} }
} }
} }
@@ -209,171 +195,176 @@ void Intro::checkEvents()
void Intro::checkInput() void Intro::checkInput()
{ {
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar) // Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
if (input->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 // Comprueba el input para el resto de objetos
screen->checkInput(); 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
checkGlobalInputs(); globalInputs::check();
} }
// 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;
@@ -383,21 +374,21 @@ void Intro::updateScenes()
// Actualiza las variables del objeto // Actualiza las variables del objeto
void Intro::update() void Intro::update()
{ {
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->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();
} }
@@ -411,32 +402,32 @@ void Intro::update()
void Intro::render() void Intro::render()
{ {
// Prepara para empezar a dibujar en la textura de juego // Prepara para empezar a dibujar en la textura de juego
screen->start(); Screen::get()->start();
// Limpia la pantalla // Limpia la pantalla
screen->clean(bgColor); 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();
} }
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
screen->blit(); Screen::get()->blit();
} }
// Bucle principal // Bucle principal
void Intro::run() void Intro::run()
{ {
JA_PlayMusic(music, 0); JA_PlayMusic(music_, 0);
while (section::name == section::NAME_INTRO) while (section::name == section::Name::INTRO)
{ {
checkInput(); checkInput();
update(); update();

View File

@@ -1,16 +1,13 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event
#include <SDL2/SDL_stdinc.h> // for Uint32, Uint8 #include <SDL2/SDL_stdinc.h> // for Uint32, Uint8
#include <memory> // for unique_ptr, shared_ptr
#include <vector> // for vector #include <vector> // for vector
class Asset; #include "smart_sprite.h" // for SmartSprite
class Input; #include "writer.h" // for Writer
class Screen;
class SmartSprite;
class Text; class Text;
class Texture; class Texture;
class Writer; struct JA_Music_t; // lines 11-11
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
@@ -21,21 +18,18 @@ struct JA_Music_t;
class Intro class Intro
{ {
private: private:
// Objetos y punteros // Objetos
Screen *screen; // Objeto encargado de dibujar en pantalla std::shared_ptr<Texture> texture_; // Textura con los graficos
Texture *texture; // Textura con los graficos std::shared_ptr<Text> text_; // Textos de la intro
SDL_Event *eventHandler; // Manejador de eventos
Asset *asset; // Objeto que gestiona todos los ficheros de recursos std::vector<std::unique_ptr<SmartSprite>> bitmaps_; // Vector con los sprites inteligentes para los dibujos de la intro
Input *input; // Objeto pata gestionar la entrada std::vector<std::unique_ptr<Writer>> texts_; // Textos de la intro
std::vector<SmartSprite *> bitmaps; // Vector con los sprites inteligentes para los dibujos de la intro
std::vector<Writer *> texts; // Textos de la intro
Text *text; // Textos de la intro
// Variables // Variables
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
Uint8 ticksSpeed; // Velocidad a la que se repiten los bucles del programa Uint8 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
JA_Music_t *music; // Musica para la intro JA_Music_t *music_; // Musica para la intro
int scene; // Indica que escena está activa int scene_; // Indica que escena está activa
// Actualiza las variables del objeto // Actualiza las variables del objeto
void update(); void update();
@@ -57,10 +51,10 @@ private:
public: public:
// Constructor // Constructor
Intro(JA_Music_t *music); explicit Intro(JA_Music_t *music);
// Destructor // Destructor
~Intro(); ~Intro() = default;
// Bucle principal // Bucle principal
void run(); void run();

View File

@@ -5,68 +5,60 @@
class Texture; class Texture;
// Constructor // Constructor
Item::Item(int kind, float x, float y, SDL_Rect *playArea, Texture *texture, std::vector<std::string> *animation) Item::Item(int kind, float x, float y, SDL_Rect *play_area, std::shared_ptr<Texture> texture, std::vector<std::string> *animation)
: sprite_(std::make_unique<AnimatedSprite>(texture, "", animation)),
accel_x_(0.0f),
floor_collision_(false),
kind_(kind),
enabled_(true),
play_area_(play_area),
time_to_live_(600)
{ {
sprite = new AnimatedSprite(texture, "", animation);
this->kind = kind;
this->playArea = playArea;
enabled = true;
timeToLive = 600;
accelX = 0.0f;
floorCollision = false;
if (kind == ITEM_COFFEE_MACHINE) if (kind == ITEM_COFFEE_MACHINE)
{ {
width = 28; width_ = 28;
height = 37; height_ = 37;
posX = (((int)x + (playArea->w / 2)) % (playArea->w - width - 5)) + 2; pos_x_ = (((int)x + (play_area->w / 2)) % (play_area->w - width_ - 5)) + 2;
posY = -height; pos_y_ = -height_;
velX = 0.0f; vel_x_ = 0.0f;
velY = -0.1f; vel_y_ = -0.1f;
accelY = 0.1f; accel_y_ = 0.1f;
collider.r = 10; collider_.r = 10;
} }
else else
{ {
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;
} }
sprite->setPosX(posX); sprite_->setPosX(pos_x_);
sprite->setPosY(posY); sprite_->setPosY(pos_y_);
shiftColliders(); shiftColliders();
} }
// Destructor
Item::~Item()
{
delete sprite;
}
// Centra el objeto en la posición X // Centra el objeto en la posición X
void Item::allignTo(int x) void Item::allignTo(int x)
{ {
posX = float(x - (width / 2)); pos_x_ = float(x - (width_ / 2));
if (posX < param.game.playArea.rect.x) if (pos_x_ < param.game.play_area.rect.x)
{ {
posX = param.game.playArea.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_ = float(play_area_->w - width_ - 1);
} }
// Posición X,Y del sprite // Posición X,Y del sprite
sprite->setPosX(int(posX)); sprite_->setPosX(int(pos_x_));
sprite->setPosY(int(posY)); sprite_->setPosY(int(pos_y_));
// Alinea el circulo de colisión con el objeto // Alinea el circulo de colisión con el objeto
shiftColliders(); shiftColliders();
@@ -75,15 +67,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();
} }
} }
} }
@@ -91,68 +83,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.playArea.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.playArea.rect.y) && !(kind == ITEM_COFFEE_MACHINE)) if ((pos_y_ < param.game.play_area.rect.y) && !(kind_ == ITEM_COFFEE_MACHINE))
{ {
// Corrige // Corrige
posY = param.game.playArea.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 (kind_ == ITEM_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_->animate();
updateTimeToLive(); updateTimeToLive();
checkTimeToLive(); checkTimeToLive();
} }
@@ -160,70 +152,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() int Item::getClass()
{ {
return kind; return kind_;
} }
// 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_t &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

@@ -2,42 +2,44 @@
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint16 #include <SDL2/SDL_stdinc.h> // for Uint16
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "utils.h" // for circle_t #include "animated_sprite.h" // for AnimatedSprite
class AnimatedSprite; #include "utils.h" // for Circle
class Texture; class Texture;
// Tipos de objetos // Tipos de objetos
#define ITEM_POINTS_1_DISK 1 constexpr int ITEM_POINTS_1_DISK = 1;
#define ITEM_POINTS_2_GAVINA 2 constexpr int ITEM_POINTS_2_GAVINA = 2;
#define ITEM_POINTS_3_PACMAR 3 constexpr int ITEM_POINTS_3_PACMAR = 3;
#define ITEM_CLOCK 4 constexpr int ITEM_CLOCK = 4;
#define ITEM_COFFEE 5 constexpr int ITEM_COFFEE = 5;
#define ITEM_COFFEE_MACHINE 6 constexpr int ITEM_COFFEE_MACHINE = 6;
#define ITEM_NULL 7 constexpr int ITEM_NULL = 7;
// Clase Item // Clase Item
class Item class Item
{ {
private: private:
// Objetos y punteros // Objetos y punteros
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_; // 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_; // Indica si el objeto colisiona con el suelo
int kind; // Especifica el tipo de objeto que es int kind_; // Especifica el tipo de objeto que es
bool enabled; // Especifica si el objeto está habilitado bool enabled_; // Especifica si el objeto está habilitado
circle_t 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_; // 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();
@@ -45,14 +47,18 @@ 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, Texture *texture, std::vector<std::string> *animation); Item(int kind, float x, float y, SDL_Rect *play_area, std::shared_ptr<Texture> texture, std::vector<std::string> *animation);
// Destructor // Destructor
~Item(); ~Item() = default;
// Centra el objeto en la posición X // Centra el objeto en la posición X
void allignTo(int x); void allignTo(int x);
@@ -66,12 +72,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();
@@ -91,7 +91,7 @@ public:
bool isEnabled(); bool isEnabled();
// Obtiene el circulo de colisión // Obtiene el circulo de colisión
circle_t &getCollider(); Circle &getCollider();
// Informa si el objeto ha colisionado con el suelo // Informa si el objeto ha colisionado con el suelo
bool isOnFloor(); bool isOnFloor();

View File

@@ -7,13 +7,13 @@ 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

@@ -4,7 +4,7 @@
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,15 +1,16 @@
#include "logo.h" #include "logo.h"
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED #include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED
#include <string> // for basic_string #include <utility> // for move
#include "asset.h" // for Asset #include "asset.h" // for Asset
#include "global_inputs.h" // for checkGlobalInputs #include "global_inputs.h" // for check
#include "input.h" // for Input #include "input.h" // for Input
#include "jail_audio.h" // for JA_StopMusic #include "jail_audio.h" // for JA_StopMusic
#include "param.h" // for param #include "param.h" // for param
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "section.h" // for name, name_e, options, options_e #include "section.h" // for Name, name, Options, options
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "texture.h" // for Texture #include "texture.h" // for Texture
@@ -17,92 +18,70 @@
Logo::Logo() Logo::Logo()
{ {
// Copia la dirección de los objetos // Copia la dirección de los objetos
input = Input::get(); SDL_Renderer *renderer = Screen::get()->getRenderer();
screen = Screen::get();
asset = Asset::get();
SDL_Renderer *renderer = screen->getRenderer();
// Reserva memoria para los punteros // Reserva memoria para los punteros
eventHandler = new SDL_Event(); jail_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("logo_jailgames.png"));
jailTexture = new Texture(renderer, asset->get("logo_jailgames.png")); since_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("logo_since_1998.png"));
sinceTexture = new Texture(renderer, asset->get("logo_since_1998.png")); since_sprite_ = std::make_unique<Sprite>((param.game.width - since_texture_->getWidth()) / 2, 83 + jail_texture_->getHeight() + 5, since_texture_->getWidth(), since_texture_->getHeight(), since_texture_);
sinceSprite = new 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; ticks_ = 0;
ticksSpeed = 15; dest_.x = param.game.game_area.center_x - jail_texture_->getWidth() / 2;
showSinceSprite_cm = 70; dest_.y = param.game.game_area.center_y - jail_texture_->getHeight() / 2;
initFade_cm = 300; since_sprite_->setPosY(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.gameArea.centerX - jailTexture->getWidth() / 2;
dest.y = param.game.gameArea.centerY - 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)
{ {
Sprite *temp = new Sprite(0, i, jailTexture->getWidth(), 1, jailTexture); auto temp = std::make_unique<Sprite>(0, i, jail_texture_->getWidth(), 1, jail_texture_);
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->setPosX(posX);
temp->setPosY(dest.y + i); temp->setPosY(dest_.y + i);
jailSprite.push_back(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({0x00, 0x00, 0x00}); // Black
color.push_back({0x00, 0x00, 0xd8}); // Blue color_.push_back({0x00, 0x00, 0xd8}); // Blue
color.push_back({0xd8, 0x00, 0x00}); // Red color_.push_back({0xd8, 0x00, 0x00}); // Red
color.push_back({0xd8, 0x00, 0xd8}); // Magenta color_.push_back({0xd8, 0x00, 0xd8}); // Magenta
color.push_back({0x00, 0xd8, 0x00}); // Green color_.push_back({0x00, 0xd8, 0x00}); // Green
color.push_back({0x00, 0xd8, 0xd8}); // Cyan color_.push_back({0x00, 0xd8, 0xd8}); // Cyan
color.push_back({0xd8, 0xd8, 0x00}); // Yellow color_.push_back({0xd8, 0xd8, 0x00}); // Yellow
color.push_back({0xFF, 0xFF, 0xFF}); // Bright white color_.push_back({0xFF, 0xFF, 0xFF}); // Bright white
}
// Destructor
Logo::~Logo()
{
for (auto sprite : jailSprite)
{
delete sprite;
}
delete sinceSprite;
delete eventHandler;
} }
// 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
void Logo::checkEvents() void Logo::checkEvents()
{ {
SDL_Event event;
// Comprueba los eventos que hay en la cola // Comprueba los eventos que hay en la cola
while (SDL_PollEvent(eventHandler) != 0) 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;
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();
} }
@@ -114,44 +93,44 @@ void Logo::checkEvents()
void Logo::checkInput() void Logo::checkInput()
{ {
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar) // Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
if (input->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 // Comprueba el input para el resto de objetos
screen->checkInput(); 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
checkGlobalInputs(); globalInputs::check();
} }
// 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]->getIntPosX() != dest_.x)
{ {
if (i % 2 == 0) if (i % 2 == 0)
{ {
jailSprite[i]->incPosX(-speed); jail_sprite_[i]->incPosX(-SPEED);
if (jailSprite[i]->getPosX() < dest.x) if (jail_sprite_[i]->getIntPosX() < dest_.x)
{ {
jailSprite[i]->setPosX(dest.x); jail_sprite_[i]->setPosX(dest_.x);
} }
} }
else else
{ {
jailSprite[i]->incPosX(speed); jail_sprite_[i]->incPosX(SPEED);
if (jailSprite[i]->getPosX() > dest.x) if (jail_sprite_[i]->getIntPosX() > dest_.x)
{ {
jailSprite[i]->setPosX(dest.x); jail_sprite_[i]->setPosX(dest_.x);
} }
} }
} }
@@ -162,88 +141,25 @@ void Logo::updateJAILGAMES()
// Gestiona el color de las texturas // Gestiona el color de las texturas
void Logo::updateTextureColors() void Logo::updateTextureColors()
{ {
const int inc = 4; constexpr int inc = 4;
if (counter <= showSinceSprite_cm + inc * 0) // Manejo de 'sinceTexture'
for (int i = 0; i <= 7; ++i)
{ {
sinceTexture->setColor(color[0].r, color[0].g, color[0].b); if (counter_ == SHOW_SINCE_SPRITE_COUNTER_MARK + inc * i)
{
since_texture_->setColor(color_[i].r, color_[i].g, color_[i].b);
}
} }
else if (counter == showSinceSprite_cm + inc * 1) // Manejo de 'jailTexture' y 'sinceTexture' en el fade
for (int i = 0; i <= 6; ++i)
{ {
sinceTexture->setColor(color[1].r, color[1].g, color[1].b); if (counter_ == INIT_FADE_COUNTER_MARK + inc * i)
{
jail_texture_->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);
} }
else if (counter == showSinceSprite_cm + inc * 2)
{
sinceTexture->setColor(color[2].r, color[2].g, color[2].b);
}
else if (counter == showSinceSprite_cm + inc * 3)
{
sinceTexture->setColor(color[3].r, color[3].g, color[3].b);
}
else if (counter == showSinceSprite_cm + inc * 4)
{
sinceTexture->setColor(color[4].r, color[4].g, color[4].b);
}
else if (counter == showSinceSprite_cm + inc * 5)
{
sinceTexture->setColor(color[5].r, color[5].g, color[5].b);
}
else if (counter == showSinceSprite_cm + inc * 6)
{
sinceTexture->setColor(color[6].r, color[6].g, color[6].b);
}
else if (counter == showSinceSprite_cm + inc * 7)
{
sinceTexture->setColor(color[7].r, color[7].g, color[7].b);
}
else if (counter == initFade_cm + inc * 0)
{
jailTexture->setColor(color[6].r, color[6].g, color[6].b);
sinceTexture->setColor(color[6].r, color[6].g, color[6].b);
}
else if (counter == initFade_cm + inc * 1)
{
jailTexture->setColor(color[5].r, color[5].g, color[5].b);
sinceTexture->setColor(color[5].r, color[5].g, color[5].b);
}
else if (counter == initFade_cm + inc * 2)
{
jailTexture->setColor(color[4].r, color[4].g, color[4].b);
sinceTexture->setColor(color[4].r, color[4].g, color[4].b);
}
else if (counter == initFade_cm + inc * 3)
{
jailTexture->setColor(color[3].r, color[3].g, color[3].b);
sinceTexture->setColor(color[3].r, color[3].g, color[3].b);
}
else if (counter == initFade_cm + inc * 4)
{
jailTexture->setColor(color[2].r, color[2].g, color[2].b);
sinceTexture->setColor(color[2].r, color[2].g, color[2].b);
}
else if (counter == initFade_cm + inc * 5)
{
jailTexture->setColor(color[1].r, color[1].g, color[1].b);
sinceTexture->setColor(color[1].r, color[1].g, color[1].b);
}
else if (counter == initFade_cm + inc * 6)
{
jailTexture->setColor(color[0].r, color[0].g, color[0].b);
sinceTexture->setColor(color[0].r, color[0].g, color[0].b);
} }
} }
@@ -251,13 +167,13 @@ void Logo::updateTextureColors()
void Logo::update() void Logo::update()
{ {
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego // Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
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->update(); Screen::get()->update();
// Comprueba las entradas // Comprueba las entradas
checkInput(); checkInput();
@@ -269,18 +185,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);
} }
} }
} }
@@ -289,20 +199,24 @@ void Logo::update()
void Logo::render() void Logo::render()
{ {
// Prepara para empezar a dibujar en la textura de juego // Prepara para empezar a dibujar en la textura de juego
screen->start(); Screen::get()->start();
// Limpia la pantalla // Limpia la pantalla
screen->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->blit(); Screen::get()->blit();
} }
// Bucle para el logo del juego // Bucle para el logo del juego
@@ -311,7 +225,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,14 +1,11 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event
#include <SDL2/SDL_rect.h> // for SDL_Point #include <SDL2/SDL_rect.h> // for SDL_Point
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for unique_ptr, shared_ptr
#include <vector> // for vector #include <vector> // for vector
#include "utils.h" // for color_t #include "sprite.h" // for Sprite
class Asset; #include "utils.h" // for Color
class Input;
class Screen;
class Sprite;
class Texture; class Texture;
/* /*
@@ -23,27 +20,25 @@ class Texture;
class Logo class Logo
{ {
private: private:
// Constantes
static constexpr Uint32 TICKS_SPEED = 15; // Velocidad a la que se repiten los bucles del programa
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
Screen *screen; // Objeto encargado de dibujar en pantalla std::shared_ptr<Texture> since_texture_; // Textura con los graficos "Since 1998"
Asset *asset; // Objeto con los ficheros de recursos std::unique_ptr<Sprite> since_sprite_; // Sprite para manejar la sinceTexture
Input *input; // Objeto pata gestionar la entrada std::shared_ptr<Texture> jail_texture_; // Textura con los graficos "JAILGAMES"
Texture *jailTexture; // Textura con los graficos "JAILGAMES" std::vector<std::unique_ptr<Sprite>> jail_sprite_; // Vector con los sprites de cada linea que forman el bitmap JAILGAMES
Texture *sinceTexture; // Textura con los graficos "Since 1998"
SDL_Event *eventHandler; // Manejador de eventos
std::vector<Sprite *> jailSprite; // Vector con los sprites de cada linea que forman el bitmap JAILGAMES
Sprite *sinceSprite; // Sprite para manejar la sinceTexture
// Variables // Variables
std::vector<color_t> 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();
@@ -71,7 +66,7 @@ public:
Logo(); Logo();
// Destructor // Destructor
~Logo(); ~Logo() = default;
// Bucle principal // Bucle principal
void run(); void run();

View File

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

View File

@@ -4,51 +4,44 @@
#include <stdlib.h> // for free, malloc #include <stdlib.h> // for free, malloc
#include <algorithm> // for sort #include <algorithm> // for sort
#include <iostream> // for basic_ostream, char_traits, operator<< #include <iostream> // for basic_ostream, char_traits, operator<<
#include "utils.h" // for hiScoreEntry_t #include "utils.h" // for HiScoreEntry
// Constructor // Constructor
ManageHiScoreTable::ManageHiScoreTable(std::vector<hiScoreEntry_t> *table) ManageHiScoreTable::ManageHiScoreTable(std::vector<HiScoreEntry> *table)
{ : table_(table) {}
this->table = table;
}
// Destructor
ManageHiScoreTable::~ManageHiScoreTable()
{
}
// 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({"Bry", 1000000});
table->push_back({"Usufondo", 500000}); table_->push_back({"Usufondo", 500000});
table->push_back({"G.Lucas", 100000}); table_->push_back({"G.Lucas", 100000});
table->push_back({"P.Delgat", 50000}); table_->push_back({"P.Delgat", 50000});
table->push_back({"P.Arrabalera", 10000}); table_->push_back({"P.Arrabalera", 10000});
table->push_back({"Pelechano", 5000}); table_->push_back({"Pelechano", 5000});
table->push_back({"Sahuquillo", 1000}); table_->push_back({"Sahuquillo", 1000});
table->push_back({"Bacteriol", 500}); table_->push_back({"Bacteriol", 500});
table->push_back({"Pepe", 200}); table_->push_back({"Pepe", 200});
table->push_back({"Rosita", 100}); table_->push_back({"Rosita", 100});
} }
// Añade un elemento a la tabla // Añade un elemento a la tabla
void ManageHiScoreTable::add(hiScoreEntry_t 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) if (static_cast<int>(table_->size()) > 10)
{ {
table->resize(10); table_->resize(10);
} }
} }
@@ -57,31 +50,31 @@ void ManageHiScoreTable::sort()
{ {
struct struct
{ {
bool operator()(hiScoreEntry_t a, hiScoreEntry_t b) const { return a.score > b.score; } bool operator()(const HiScoreEntry &a, const HiScoreEntry &b) const { return a.score > b.score; }
} customLess; } custom_less;
std::sort(table->begin(), table->end(), customLess); std::sort(table_->begin(), table_->end(), custom_less);
} }
// 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();
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(), "r+b");
SDL_RWops *file = SDL_RWFromFile(filePath.c_str(), "r+b");
if (file) if (file)
{ {
#ifdef DEBUG #ifdef VERBOSE
std::cout << "Reading file: " << filename.c_str() << std::endl; const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
std::cout << "Reading file: " << file_name.c_str() << std::endl;
#endif #endif
for (int i = 0; i < (int)table->size(); ++i) 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, &table_->at(i).score, sizeof(int), 1) == 0)
{ {
success = false; success = false;
break; break;
@@ -93,7 +86,7 @@ bool ManageHiScoreTable::loadFromFile(std::string filePath)
break; break;
} }
char *name = (char *)malloc(nameSize + 1); char *name = static_cast<char *>(malloc(nameSize + 1));
if (SDL_RWread(file, name, sizeof(char) * nameSize, 1) == 0) if (SDL_RWread(file, name, sizeof(char) * nameSize, 1) == 0)
{ {
success = false; success = false;
@@ -103,7 +96,7 @@ bool ManageHiScoreTable::loadFromFile(std::string filePath)
else else
{ {
name[nameSize] = 0; name[nameSize] = 0;
table->at(i).name = name; table_->at(i).name = name;
free(name); free(name);
} }
} }
@@ -120,33 +113,35 @@ 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; #ifdef VERBOSE
const std::string fileName = filePath.substr(filePath.find_last_of("\\/") + 1); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
SDL_RWops *file = SDL_RWFromFile(filePath.c_str(), "w+b"); #endif
auto success = true;
auto file = SDL_RWFromFile(file_path.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 #ifdef VERBOSE
std::cout << "Writing file: " << fileName.c_str() << std::endl; std::cout << "Writing file: " << file_name.c_str() << std::endl;
#endif #endif
// Cierra el fichero // Cierra el fichero
SDL_RWclose(file); SDL_RWclose(file);
} }
else else
{ {
#ifdef DEBUG #ifdef VERBOSE
std::cout << "Error: Unable to save " << fileName.c_str() << " file! " << SDL_GetError() << std::endl; std::cout << "Error: Unable to save " << file_name.c_str() << " file! " << SDL_GetError() << std::endl;
#endif #endif
} }
return success; return success;

View File

@@ -2,7 +2,7 @@
#include <string> // for string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
struct hiScoreEntry_t; 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
@@ -17,27 +17,27 @@ class ManageHiScoreTable
{ {
private: private:
// Variables // Variables
std::vector<hiScoreEntry_t> *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_t> *table); explicit ManageHiScoreTable(std::vector<HiScoreEntry> *table);
// Destructor // Destructor
~ManageHiScoreTable(); ~ManageHiScoreTable() = default;
// Resetea la tabla a los valores por defecto // Resetea la tabla a los valores por defecto
void clear(); void clear();
// Añade un elemento a la tabla // Añade un elemento a la tabla
void add(hiScoreEntry_t 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

@@ -2,261 +2,241 @@
#include "texture.h" // for Texture #include "texture.h" // for Texture
// Constructor // Constructor
MovingSprite::MovingSprite(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, Texture *texture) MovingSprite::MovingSprite(float x, float y, int w, int h, float vx, float vy, float ax, float ay, std::shared_ptr<Texture> texture)
: Sprite((int)x, (int)y, w, h, texture),
x_(x),
y_(y),
vx_(vx),
vy_(vy),
ax_(ax),
ay_(ay),
zoom_w_(1),
zoom_h_(1),
counter_(0),
flip_(SDL_FLIP_NONE)
{ {
// Copia los punteros
this->texture = texture;
// Establece el alto y el ancho del sprite
this->w = w;
this->h = h;
// Establece la posición X,Y del sprite
this->x = x;
this->y = y;
xPrev = x;
yPrev = y;
// Establece la velocidad X,Y del sprite
vx = velx;
vy = vely;
// Establece la aceleración X,Y del sprite
ax = accelx;
ay = accely;
// Establece el zoom W,H del sprite
zoomW = 1;
zoomH = 1;
// Establece el angulo con el que se dibujará
angle = (double)0;
// Establece los valores de rotacion // Establece los valores de rotacion
rotateEnabled = false; rotate_.enabled = false;
rotateSpeed = 0; rotate_.speed = 0;
rotateAmount = (double)0; rotate_.angle = 0.0f;
rotate_.amount = 0.0f;
rotate_.center = nullptr;
// Contador interno sprite_clip_ = (SDL_Rect){0, 0, w, h};
counter = 0; };
// Establece el rectangulo de donde coger la imagen MovingSprite::MovingSprite(std::shared_ptr<Texture> texture)
spriteClip = {0, 0, w, h}; : Sprite(texture)
{
// Establece el centro de rotación clear();
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()
{ {
x = 0.0f; // Posición en el eje X x_ = 0.0f; // Posición en el eje X
y = 0.0f; // Posición en el eje Y y_ = 0.0f; // Posición en el eje Y
vx = 0.0f; // Velocidad en el eje X. Cantidad de pixeles a desplazarse vx_ = 0.0f; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
vy = 0.0f; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse vy_ = 0.0f; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
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 zoom_w_ = 1.0f; // Zoom aplicado a la anchura
zoomH = 1.0f; // Zoom aplicado a la altura zoom_h_ = 1.0f; // Zoom aplicado a la altura
angle = 0.0; // Angulo para dibujarlo rotate_.enabled = false; // Indica si ha de rotar
rotateEnabled = false; // Indica si ha de rotar rotate_.speed = 0; // Velocidad de giro
center = nullptr; // Centro de rotación rotate_.angle = 0.0f; // Angulo para dibujarlo
rotateSpeed = 0; // Velocidad de giro rotate_.amount = 0.0f; // Cantidad de grados a girar en cada iteración
rotateAmount = 0.0; // Cantidad de grados a girar en cada iteración rotate_.center = nullptr; // Centro de rotación
counter = 0; // Contador interno
currentFlip = SDL_FLIP_NONE; // Establece como se ha de voltear el sprite counter_ = 0; // Contador interno
flip_ = SDL_FLIP_NONE; // Establece como se ha de voltear el sprite
setPos((SDL_Rect){0, 0, 0, 0});
setSpriteClip((SDL_Rect){0, 0, 0, 0});
} }
// Mueve el sprite // Mueve el sprite
void MovingSprite::move() void MovingSprite::move()
{ {
if (enabled) x_ += vx_;
{ y_ += vy_;
xPrev = x;
yPrev = y;
x += vx; vx_ += ax_;
y += vy; vy_ += ay_;
vx += ax;
vy += ay;
}
} }
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void MovingSprite::render() void MovingSprite::render()
{ {
if (enabled) texture_->render((int)x_, (int)y_, &sprite_clip_, zoom_w_, zoom_h_, (double)rotate_.angle, rotate_.center, flip_);
{
texture->render((int)x, (int)y, &spriteClip, zoomW, zoomH, angle, center, currentFlip);
}
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getPosX() float MovingSprite::getPosX() const
{ {
return x; return x_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getPosY() float MovingSprite::getPosY() const
{ {
return y; return y_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getVelX() float MovingSprite::getVelX() const
{ {
return vx; return vx_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getVelY() float MovingSprite::getVelY() const
{ {
return vy; return vy_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getAccelX() float MovingSprite::getAccelX() const
{ {
return ax; return ax_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getAccelY() float MovingSprite::getAccelY() const
{ {
return ay; return ay_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getZoomW() float MovingSprite::getZoomW() const
{ {
return zoomW; return zoom_w_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getZoomH() float MovingSprite::getZoomH() const
{ {
return zoomH; return zoom_h_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
double MovingSprite::getAngle() float MovingSprite::getAngle() const
{ {
return angle; return rotate_.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_ = (float)rect.x;
y = (float)rect.y; y_ = (float)rect.y;
w = rect.w;
h = rect.h; pos_ = rect;
} }
// Establece el valor de las variables // Establece el valor de las variables
void MovingSprite::setPos(float x, float y) void MovingSprite::setPos(float x, float y)
{ {
this->x = x; x_ = x;
this->y = y; y_ = y;
pos_.x = (int)x;
pos_.y = (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 = (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 = (int)y_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setVelX(float value) void MovingSprite::setVelX(float value)
{ {
vx = value; vx_ = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setVelY(float value) void MovingSprite::setVelY(float value)
{ {
vy = value; vy_ = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setAccelX(float value) void MovingSprite::setAccelX(float value)
{ {
ax = value; ax_ = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setAccelY(float value) void MovingSprite::setAccelY(float value)
{ {
ay = value; ay_ = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setZoomW(float value) void MovingSprite::setZoomW(float value)
{ {
zoomW = value; zoom_w_ = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setZoomH(float value) void MovingSprite::setZoomH(float value)
{ {
zoomH = value; zoom_h_ = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setAngle(double value) void MovingSprite::setAngle(double value)
{ {
angle = value; rotate_.angle = value;
} }
// Incrementa el valor de la variable // Incrementa el valor de la variable
void MovingSprite::incAngle(double value) void MovingSprite::incAngle(double value)
{ {
angle += value; rotate_.angle += value;
} }
// Decrementa el valor de la variable // Decrementa el valor de la variable
void MovingSprite::decAngle(double value) void MovingSprite::decAngle(double value)
{ {
angle -= value; rotate_.angle -= value;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool MovingSprite::getRotate() bool MovingSprite::getRotate() const
{ {
return rotateEnabled; return rotate_.enabled;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
Uint16 MovingSprite::getRotateSpeed() Uint16 MovingSprite::getRotateSpeed() const
{ {
return rotateSpeed; return rotate_.speed;
} }
// Establece la rotacion // Establece la rotacion
void MovingSprite::rotate() void MovingSprite::rotate()
{ {
if (enabled) if (rotate_.enabled)
if (rotateEnabled)
{ {
if (counter % rotateSpeed == 0) if (counter_ % rotate_.speed == 0)
{ {
incAngle(rotateAmount); incAngle(rotate_.amount);
} }
} }
} }
@@ -264,33 +244,26 @@ void MovingSprite::rotate()
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setRotate(bool value) void MovingSprite::setRotate(bool value)
{ {
rotateEnabled = value; rotate_.enabled = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setRotateSpeed(int value) void MovingSprite::setRotateSpeed(int value)
{ {
if (value < 1) rotate_.speed = (value < 1) ? 1 : value;
{
rotateSpeed = 1;
}
else
{
rotateSpeed = value;
}
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setRotateAmount(double value) void MovingSprite::setRotateAmount(double value)
{ {
rotateAmount = value; rotate_.amount = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::disableRotate() void MovingSprite::disableRotate()
{ {
rotateEnabled = false; rotate_.enabled = false;
angle = (double)0; rotate_.angle = 0.0f;
} }
// Actualiza las variables internas del objeto // Actualiza las variables internas del objeto
@@ -298,71 +271,35 @@ void MovingSprite::update()
{ {
move(); move();
rotate(); rotate();
++counter_ %= 60000;
if (enabled)
{
++counter %= 60000;
}
} }
// Cambia el sentido de la rotación // Cambia el sentido de la rotación
void MovingSprite::switchRotate() void MovingSprite::switchRotate()
{ {
rotateAmount *= -1; rotate_.amount *= -1;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setFlip(SDL_RendererFlip flip) void MovingSprite::setFlip(SDL_RendererFlip flip)
{ {
currentFlip = flip; flip_ = flip;
} }
// Gira el sprite horizontalmente // Gira el sprite horizontalmente
void MovingSprite::flip() void MovingSprite::flip()
{ {
currentFlip = (currentFlip == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL; flip_ = (flip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
SDL_RendererFlip MovingSprite::getFlip() SDL_RendererFlip MovingSprite::getFlip()
{ {
return currentFlip; return flip_;
} }
// Devuelve el rectangulo donde está el sprite // Devuelve el rectangulo donde está el sprite
SDL_Rect MovingSprite::getRect() SDL_Rect MovingSprite::getPos() const
{ {
const SDL_Rect rect = {(int)x, (int)y, w, h}; return (SDL_Rect){(int)x_, (int)y_, pos_.w, pos_.h};
return rect;
}
// Deshace el último movimiento
void MovingSprite::undoMove()
{
x = xPrev;
y = yPrev;
}
// Deshace el último movimiento en el eje X
void MovingSprite::undoMoveX()
{
x = xPrev;
}
// Deshace el último movimiento en el eje Y
void MovingSprite::undoMoveY()
{
y = yPrev;
}
// Pone a cero las velocidades de desplacamiento
void MovingSprite::clearVel()
{
vx = vy = 0.0f;
}
// Devuelve el incremento en el eje X en pixels
int MovingSprite::getIncX()
{
return (int)x - (int)xPrev;
} }

View File

@@ -3,6 +3,7 @@
#include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point #include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point
#include <SDL2/SDL_render.h> // for SDL_RendererFlip #include <SDL2/SDL_render.h> // for SDL_RendererFlip
#include <SDL2/SDL_stdinc.h> // for Uint16 #include <SDL2/SDL_stdinc.h> // for Uint16
#include <memory> // for shared_ptr
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
class Texture; class Texture;
@@ -10,32 +11,38 @@ class Texture;
class MovingSprite : public Sprite class MovingSprite : public Sprite
{ {
protected: protected:
float x; // Posición en el eje X struct Rotate
float y; // Posición en el eje Y {
bool enabled; // Indica si ha de rotar
float xPrev; // Posición anterior en el eje X int speed; // Velocidad de giro
float yPrev; // Posición anterior en el eje Y float angle; // Angulo para dibujarlo
float amount; // Cantidad de grados a girar en cada iteración
float vx; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
float vy; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
float ax; // 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 zoomW; // Zoom aplicado a la anchura
float zoomH; // Zoom aplicado a la altura
double angle; // Angulo para dibujarlo
bool rotateEnabled; // Indica si ha de rotar
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_Point *center; // Centro de rotación
SDL_RendererFlip currentFlip; // Indica como se voltea el sprite };
float x_; // Posición en el eje X
float y_; // Posición en el eje Y
float vx_; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
float vy_; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
float ax_; // 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 zoom_w_; // Zoom aplicado a la anchura
float zoom_h_; // Zoom aplicado a la altura
int counter_; // Contador interno
Rotate rotate_; // Variables usada para controlar la rotación del sprite
SDL_RendererFlip flip_; // Indica como se voltea el sprite
public: public:
// Constructor // 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, Texture *texture = nullptr); explicit 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);
explicit MovingSprite(std::shared_ptr<Texture> texture = nullptr);
// Destructor
virtual ~MovingSprite() = default;
// Mueve el sprite // Mueve el sprite
void move(); void move();
@@ -44,93 +51,66 @@ public:
void rotate(); void rotate();
// Actualiza las variables internas del objeto // Actualiza las variables internas del objeto
void update(); virtual void update();
// Reinicia todas las variables // Reinicia todas las variables
void clear(); void clear();
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void render(); void render() override;
// Obten el valor de la variable // Obten el valor de la variable
float getPosX(); float getPosX() const;
float getPosY() const;
// Obten el valor de la variable // Obten el valor de la variable
float getPosY(); float getVelX() const;
float getVelY() const;
// Obten el valor de la variable // Obten el valor de la variable
float getVelX(); float getAccelX() const;
float getAccelY() const;
// Obten el valor de la variable // Obten el valor de la variable
float getVelY(); float getZoomW() const;
float getZoomH() const;
// Obten el valor de la variable // Obten el valor de la variable
float getAccelX(); float getAngle() const;
bool getRotate() const;
Uint16 getRotateSpeed() const;
// Obten el valor de la variable // Establece la posición del objeto
float getAccelY(); void setPos(SDL_Rect rect) override;
// Obten el valor de la variable
float getZoomW();
// Obten el valor de la variable
float getZoomH();
// Obten el valor de la variable
double getAngle();
// Obtiene el valor de la variable
bool getRotate();
// Obtiene el valor de la variable
Uint16 getRotateSpeed();
// 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); void setPos(float x, float y);
// Devuelve el rectangulo donde está el sprite
SDL_Rect getPos() const override;
// Establece el valor de la variable // Establece el valor de la variable
void setPosX(float value); void setPosX(float value);
// Establece el valor de la variable
void setPosY(float value); void setPosY(float value);
// Establece el valor de la variable // Establece el valor de la variable
void setVelX(float value); void setVelX(float value);
// Establece el valor de la variable
void setVelY(float value); void setVelY(float value);
// Establece el valor de la variable // Establece el valor de la variable
void setAccelX(float value); void setAccelX(float value);
// Establece el valor de la variable
void setAccelY(float value); void setAccelY(float value);
// Establece el valor de la variable // Establece el valor de la variable
void setZoomW(float value); void setZoomW(float value);
// Establece el valor de la variable
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);
// Incrementa el valor de la variable
void incAngle(double value); void incAngle(double value);
// Decrementa el valor de la variable
void decAngle(double value); void decAngle(double value);
// Establece el valor de la variable // Establece el valor de la variable
void setRotate(bool value); void setRotate(bool value);
// Establece el valor de la variable
void setRotateSpeed(int value); void setRotateSpeed(int value);
// Establece el valor de la variable
void setRotateAmount(double value); void setRotateAmount(double value);
// Quita el efecto de rotación y deja el sprite en su angulo inicial. // Quita el efecto de rotación y deja el sprite en su angulo inicial.
@@ -148,21 +128,5 @@ 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
SDL_Rect getRect();
// Deshace el último movimiento
void undoMove();
// Deshace el último movimiento en el eje X
void undoMoveX();
// Deshace el último movimiento en el eje Y
void undoMoveY();
// Pone a cero las velocidades de desplacamiento
void clearVel();
// Devuelve el incremento en el eje X en pixels
int getIncX();
}; };

View File

@@ -1,56 +1,36 @@
#include "notify.h" #include "notify.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <string> // for basic_string, char_traits, string #include <string> // for string
#include "jail_audio.h" // for JA_DeleteSound, JA_LoadSound, JA_Pla... #include "jail_audio.h" // for JA_DeleteSound, JA_LoadSound, JA_Pla...
#include "options.h" // for options #include "param.h" // for param
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "text.h" // for Text #include "text.h" // for Text
#include "texture.h" // for Texture #include "texture.h" // for Texture
// Constructor // Constructor
Notify::Notify(SDL_Renderer *renderer, std::string iconFile, std::string bitmapFile, std::string textFile, std::string soundFile) Notify::Notify(SDL_Renderer *renderer, std::string iconFile, std::string bitmapFile, std::string textFile, const std::string &soundFile)
: renderer(renderer),
text(std::make_unique<Text>(bitmapFile, textFile, renderer)),
bgColor(param.notification.color),
waitTime(150),
stack(false),
sound(JA_LoadSound(soundFile.c_str()))
{ {
// Inicializa variables // Inicializa variables
this->renderer = renderer; hasIcons = !iconFile.empty();
bgColor = options.notification.color;
waitTime = 150;
stack = false;
hasIcons = iconFile == "" ? false : true;
iconTexture = nullptr;
textTexture = nullptr;
text = nullptr;
// Crea objetos // Crea objetos
if (hasIcons) iconTexture = hasIcons ? std::make_unique<Texture>(renderer, iconFile) : nullptr;
{
iconTexture = new Texture(renderer, iconFile);
}
textTexture = new Texture(renderer, bitmapFile);
text = new Text(textFile, textTexture, renderer);
sound = JA_LoadSound(soundFile.c_str());
} }
// Destructor // Destructor
Notify::~Notify() Notify::~Notify()
{ {
// Libera la memoria de los objetos // Libera la memoria de los objetos
if (textTexture)
delete textTexture;
if (iconTexture)
delete iconTexture;
if (text)
delete text;
JA_DeleteSound(sound); JA_DeleteSound(sound);
for (auto notification : notifications) notifications.clear();
{
delete notification.sprite;
delete notification.texture;
}
} }
// Dibuja las notificaciones por pantalla // Dibuja las notificaciones por pantalla
@@ -70,7 +50,7 @@ void Notify::update()
// Si la notificación anterior está "saliendo", no hagas nada // Si la notificación anterior está "saliendo", no hagas nada
if (i > 0) if (i > 0)
{ {
if (notifications[i - 1].state == ns_rising) if (notifications[i - 1].status == NotificationStatus::RISING)
{ {
break; break;
} }
@@ -81,9 +61,9 @@ void Notify::update()
// Hace sonar la notificación en el primer frame // Hace sonar la notificación en el primer frame
if (notifications[i].counter == 1) if (notifications[i].counter == 1)
{ {
if (options.notification.sound) if (param.notification.sound)
{ {
if (notifications[i].state == ns_rising) if (notifications[i].status == NotificationStatus::RISING)
{ // Reproduce el sonido de la notificación { // Reproduce el sonido de la notificación
JA_PlaySound(sound); JA_PlaySound(sound);
} }
@@ -91,12 +71,12 @@ void Notify::update()
} }
// Comprueba los estados // Comprueba los estados
if (notifications[i].state == ns_rising) if (notifications[i].status == NotificationStatus::RISING)
{ {
const float step = ((float)notifications[i].counter / notifications[i].travelDist); const float step = ((float)notifications[i].counter / notifications[i].travelDist);
const int alpha = 255 * step; const int alpha = 255 * step;
if (options.notification.posV == pos_top) if (param.notification.pos_v == NotifyPosition::TOP)
{ {
notifications[i].rect.y++; notifications[i].rect.y++;
} }
@@ -108,27 +88,27 @@ void Notify::update()
if (notifications[i].rect.y == notifications[i].y) if (notifications[i].rect.y == notifications[i].y)
{ {
notifications[i].state = ns_stay; notifications[i].status = NotificationStatus::STAY;
notifications[i].texture->setAlpha(255); notifications[i].texture->setAlpha(255);
notifications[i].counter = 0; notifications[i].counter = 0;
} }
} }
else if (notifications[i].state == ns_stay) else if (notifications[i].status == NotificationStatus::STAY)
{ {
if (notifications[i].counter == waitTime) if (notifications[i].counter == waitTime)
{ {
notifications[i].state = ns_vanishing; notifications[i].status = NotificationStatus::VANISHING;
notifications[i].counter = 0; notifications[i].counter = 0;
} }
} }
else if (notifications[i].state == ns_vanishing) else if (notifications[i].status == NotificationStatus::VANISHING)
{ {
const float step = (notifications[i].counter / (float)notifications[i].travelDist); const float step = (notifications[i].counter / (float)notifications[i].travelDist);
const int alpha = 255 * (1 - step); const int alpha = 255 * (1 - step);
if (options.notification.posV == pos_top) if (param.notification.pos_v == NotifyPosition::TOP)
{ {
notifications[i].rect.y--; notifications[i].rect.y--;
} }
@@ -140,11 +120,11 @@ void Notify::update()
if (notifications[i].rect.y == notifications[i].y - notifications[i].travelDist) if (notifications[i].rect.y == notifications[i].y - notifications[i].travelDist)
{ {
notifications[i].state = ns_finished; notifications[i].status = NotificationStatus::FINISHED;
} }
} }
notifications[i].sprite->setRect(notifications[i].rect); notifications[i].sprite->setPos(notifications[i].rect);
} }
clearFinishedNotifications(); clearFinishedNotifications();
@@ -155,10 +135,8 @@ void Notify::clearFinishedNotifications()
{ {
for (int i = (int)notifications.size() - 1; i >= 0; --i) for (int i = (int)notifications.size() - 1; i >= 0; --i)
{ {
if (notifications[i].state == ns_finished) if (notifications[i].status == NotificationStatus::FINISHED)
{ {
delete notifications[i].sprite;
delete notifications[i].texture;
notifications.erase(notifications.begin() + i); notifications.erase(notifications.begin() + i);
} }
} }
@@ -168,22 +146,19 @@ void Notify::clearFinishedNotifications()
void Notify::showText(std::string text1, std::string text2, int icon) void Notify::showText(std::string text1, std::string text2, int icon)
{ {
// Cuenta el número de textos a mostrar // Cuenta el número de textos a mostrar
int numTexts = 0; const int numTexts = !text1.empty() + !text2.empty();
if (text1 != "")
numTexts++;
if (text2 != "")
numTexts++;
// Si no hay texto, acaba // Si no hay texto, acaba
if (numTexts == 0) if (numTexts == 0)
{ {
return; return;
} }
// Si solo hay un texto, lo coloca en la primera variable // Si solo hay un texto, lo coloca en la primera variable
else if (numTexts == 1) if (numTexts == 1)
{ {
text1 = text1 + text2; text1 += text2;
text2 = ""; text2.clear();
} }
// Si las notificaciones no se apilan, elimina las anteriores // Si las notificaciones no se apilan, elimina las anteriores
@@ -193,46 +168,37 @@ void Notify::showText(std::string text1, std::string text2, int icon)
} }
// Inicializa variables // Inicializa variables
const int iconSize = 16; constexpr auto iconSize = 16;
const int paddingOut = 1; constexpr auto paddingOut = 1;
const int paddingIn = text->getCharacterSize() / 2; const auto paddingIn = text->getCharacterSize() / 2;
const int iconSpace = icon >= 0 ? iconSize + paddingIn : 0; const auto iconSpace = icon >= 0 ? iconSize + paddingIn : 0;
const std::string txt = text1.length() > text2.length() ? text1 : text2; const std::string txt = text1.length() > text2.length() ? text1 : text2;
const int width = text->lenght(txt) + (paddingIn * 2) + iconSpace; const auto width = text->lenght(txt) + (paddingIn * 2) + iconSpace;
const int height = (text->getCharacterSize() * numTexts) + (paddingIn * 2); const auto height = (text->getCharacterSize() * numTexts) + (paddingIn * 2);
const notification_shape_t shape = notification_shape_squared; const auto shape = NotificationShape::SQUARED;
// Posición horizontal // Posición horizontal
int despH = 0; auto despH = 0;
if (options.notification.posH == pos_left) if (param.notification.pos_h == NotifyPosition::LEFT)
{ {
despH = paddingOut; despH = paddingOut;
} }
else if (options.notification.posH == pos_middle) else if (param.notification.pos_h == NotifyPosition::MIDDLE)
{ {
despH = ((options.video.gameWidth / 2) - (width / 2)); despH = ((param.game.width / 2) - (width / 2));
} }
else else
{ {
despH = options.video.gameWidth - width - paddingOut; despH = param.game.width - width - paddingOut;
} }
// Posición vertical // Posición vertical
int despV = 0; const int despV = (param.notification.pos_v == NotifyPosition::TOP) ? paddingOut : (param.game.height - height - paddingOut);
if (options.notification.posV == pos_top)
{
despV = paddingOut;
}
else
{
despV = options.video.gameHeight - height - paddingOut;
}
const int travelDist = height + paddingOut;
// Offset // Offset
int offset = 0; const auto travelDist = height + paddingOut;
if (options.notification.posV == pos_top) auto offset = 0;
if (param.notification.pos_v == NotifyPosition::TOP)
{ {
offset = (int)notifications.size() > 0 ? notifications.back().y + travelDist : despV; offset = (int)notifications.size() > 0 ? notifications.back().y + travelDist : despV;
} }
@@ -242,27 +208,21 @@ void Notify::showText(std::string text1, std::string text2, int icon)
} }
// Crea la notificacion // Crea la notificacion
notification_t n; Notification n;
// Inicializa variables // Inicializa variables
n.y = offset; n.y = offset;
n.travelDist = travelDist; n.travelDist = travelDist;
n.counter = 0; n.counter = 0;
n.state = ns_rising; n.status = NotificationStatus::RISING;
n.text1 = text1; n.text1 = text1;
n.text2 = text2; n.text2 = text2;
n.shape = shape; n.shape = shape;
if (options.notification.posV == pos_top) auto yPos = offset + (param.notification.pos_v == NotifyPosition::TOP ? -travelDist : travelDist);
{ n.rect = {despH, yPos, width, height};
n.rect = {despH, offset - travelDist, width, height};
}
else
{
n.rect = {despH, offset + travelDist, width, height};
}
// Crea la textura // Crea la textura
n.texture = new Texture(renderer); n.texture = std::make_shared<Texture>(renderer);
n.texture->createBlank(width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET); n.texture->createBlank(width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET);
n.texture->setBlendMode(SDL_BLENDMODE_BLEND); n.texture->setBlendMode(SDL_BLENDMODE_BLEND);
@@ -272,7 +232,7 @@ void Notify::showText(std::string text1, std::string text2, int icon)
// Dibuja el fondo de la notificación // Dibuja el fondo de la notificación
SDL_SetRenderDrawColor(renderer, bgColor.r, bgColor.g, bgColor.b, 255); SDL_SetRenderDrawColor(renderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_Rect rect; SDL_Rect rect;
if (shape == notification_shape_rounded) if (shape == NotificationShape::ROUNDED)
{ {
rect = {4, 0, width - (4 * 2), height}; rect = {4, 0, width - (4 * 2), height};
SDL_RenderFillRect(renderer, &rect); SDL_RenderFillRect(renderer, &rect);
@@ -287,7 +247,7 @@ void Notify::showText(std::string text1, std::string text2, int icon)
SDL_RenderFillRect(renderer, &rect); SDL_RenderFillRect(renderer, &rect);
} }
else if (shape == notification_shape_squared) else if (shape == NotificationShape::SQUARED)
{ {
SDL_RenderClear(renderer); SDL_RenderClear(renderer);
} }
@@ -295,15 +255,14 @@ void Notify::showText(std::string text1, std::string text2, int icon)
// Dibuja el icono de la notificación // Dibuja el icono de la notificación
if (hasIcons && icon >= 0 && numTexts == 2) if (hasIcons && icon >= 0 && numTexts == 2)
{ {
Sprite *sp = new Sprite({0, 0, iconSize, iconSize}, iconTexture); auto sp = std::make_unique<Sprite>((SDL_Rect){0, 0, iconSize, iconSize}, iconTexture);
sp->setPos({paddingIn, paddingIn, iconSize, iconSize}); sp->setPos({paddingIn, paddingIn, iconSize, iconSize});
sp->setSpriteClip({iconSize * (icon % 10), iconSize * (icon / 10), iconSize, iconSize}); sp->setSpriteClip({iconSize * (icon % 10), iconSize * (icon / 10), iconSize, iconSize});
sp->render(); sp->render();
delete sp;
} }
// Escribe el texto de la notificación // Escribe el texto de la notificación
color_t color = {255, 255, 255}; Color color = {255, 255, 255};
if (numTexts == 2) if (numTexts == 2)
{ // Dos lineas de texto { // Dos lineas de texto
text->writeColored(paddingIn + iconSpace, paddingIn, text1, color); text->writeColored(paddingIn + iconSpace, paddingIn, text1, color);
@@ -318,7 +277,7 @@ void Notify::showText(std::string text1, std::string text2, int icon)
SDL_SetRenderTarget(renderer, nullptr); SDL_SetRenderTarget(renderer, nullptr);
// Crea el sprite de la notificación // Crea el sprite de la notificación
n.sprite = new Sprite(n.rect, n.texture); n.sprite = std::make_shared<Sprite>(n.rect, n.texture);
// Deja la notificación invisible // Deja la notificación invisible
n.texture->setAlpha(0); n.texture->setAlpha(0);
@@ -343,7 +302,7 @@ void Notify::clearNotifications()
{ {
for (int i = 0; i < (int)notifications.size(); ++i) for (int i = 0; i < (int)notifications.size(); ++i)
{ {
notifications[i].state = ns_finished; notifications[i].status = NotificationStatus::FINISHED;
} }
clearFinishedNotifications(); clearFinishedNotifications();

View File

@@ -2,74 +2,72 @@
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_render.h> // for SDL_Renderer
#include <string> // for basic_string, string #include <memory> // for shared_ptr, unique_ptr
#include <string> // for string, basic_string
#include <vector> // for vector #include <vector> // for vector
#include "utils.h" // for color_t #include "utils.h" // for Color
class Sprite; class Sprite;
class Text; class Text;
class Texture; class Texture;
struct JA_Sound_t; struct JA_Sound_t; // lines 12-12
#ifndef NOTIFY_H
#define NOTIFY_H
class Notify class Notify
{ {
private: private:
enum notification_state_e enum class NotificationStatus
{ {
ns_rising, RISING,
ns_stay, STAY,
ns_vanishing, VANISHING,
ns_finished FINISHED,
}; };
enum notification_position_e enum class NotificationPosition
{ {
upperLeft, UPPER_LEFT,
upperCenter, UPPER_CENTER,
upperRight, UPPER_RIGHT,
middleLeft, MIDDLE_LEFT,
middleRight, MIDDLE_RIGHT,
bottomLeft, BOTTOM_LEFT,
bottomCenter, BOTTOM_CENTER,
bottomRight BOTTOM_RIGHT,
}; };
enum notification_shape_t enum class NotificationShape
{ {
notification_shape_rounded, ROUNDED,
notification_shape_squared, SQUARED,
}; };
struct notification_t struct Notification
{ {
std::shared_ptr<Texture> texture;
std::shared_ptr<Sprite> sprite;
std::string text1; std::string text1;
std::string text2; std::string text2;
int counter; int counter;
notification_state_e state; NotificationStatus status;
notification_position_e position; NotificationPosition position;
Texture *texture; NotificationShape shape;
Sprite *sprite;
SDL_Rect rect; SDL_Rect rect;
int y; int y;
int travelDist; int travelDist;
notification_shape_t shape;
}; };
// Objetos y punteros // Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana SDL_Renderer *renderer; // El renderizador de la ventana
Texture *textTexture; // Textura para la fuente de las notificaciones
Texture *iconTexture; // Textura para los iconos de las notificaciones std::shared_ptr<Texture> iconTexture; // Textura para los iconos de las notificaciones
Text *text; // Objeto para dibujar texto std::unique_ptr<Text> text; // Objeto para dibujar texto
// Variables // Variables
color_t bgColor; // Color de fondo de las notificaciones Color bgColor; // Color de fondo de las notificaciones
int waitTime; // Tiempo que se ve la notificación int waitTime; // Tiempo que se ve la notificación
std::vector<notification_t> notifications; // La lista de notificaciones activas std::vector<Notification> notifications; // La lista de notificaciones activas
JA_Sound_t *sound; // Sonido a reproducir cuando suena la notificación
bool stack; // Indica si las notificaciones se apilan bool stack; // Indica si las notificaciones se apilan
bool hasIcons; // Indica si el notificador tiene textura para iconos bool hasIcons; // Indica si el notificador tiene textura para iconos
JA_Sound_t *sound; // Sonido a reproducir cuando suena la notificación
// Elimina las notificaciones finalizadas // Elimina las notificaciones finalizadas
void clearFinishedNotifications(); void clearFinishedNotifications();
@@ -79,7 +77,7 @@ private:
public: public:
// Constructor // Constructor
Notify(SDL_Renderer *renderer, std::string iconFile, std::string bitmapFile, std::string textFile, std::string soundFile); Notify(SDL_Renderer *renderer, std::string iconFile, std::string bitmapFile, std::string textFile, const std::string &soundFile);
// Destructor // Destructor
~Notify(); ~Notify();
@@ -91,10 +89,8 @@ public:
void update(); void update();
// Muestra una notificación de texto por pantalla; // Muestra una notificación de texto por pantalla;
void showText(std::string text1 = "", std::string text2 = "", int icon = -1); void showText(std::string text1 = std::string(), std::string text2 = std::string(), int icon = -1);
// Indica si hay notificaciones activas // Indica si hay notificaciones activas
bool active(); bool active();
}; };
#endif

View File

@@ -1,11 +1,15 @@
#include "on_screen_help.h" #include "on_screen_help.h"
#include "screen.h" #include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include "asset.h" #include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include "input.h" #include <memory> // for make_unique, make_shared, unique_ptr
#include "text.h" #include "asset.h" // for Asset
#include "sprite.h" #include "lang.h" // for getText
#include "texture.h" #include "param.h" // for param
#include "lang.h" #include "screen.h" // for Screen
#include "sprite.h" // for Sprite
#include "text.h" // for Text
#include "texture.h" // for Texture
#include "utils.h" // for easeInOutSine, Param, ParamGame
// [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
OnScreenHelp *OnScreenHelp::onScreenHelp = nullptr; OnScreenHelp *OnScreenHelp::onScreenHelp = nullptr;
@@ -15,13 +19,13 @@ constexpr int ICONSIZE = 16;
constexpr SDL_Point PADDING = {8, 8}; constexpr SDL_Point PADDING = {8, 8};
constexpr SDL_Point DESP = {ICONSIZE + 4, 5}; constexpr SDL_Point DESP = {ICONSIZE + 4, 5};
constexpr SDL_Rect CONTROLLER_UP = {16, 16, ICONSIZE, ICONSIZE}; constexpr SDL_Rect CONTROLLER_UP = {16, 0, ICONSIZE, ICONSIZE};
constexpr SDL_Rect CONTROLLER_DOWN = {48, 16, ICONSIZE, ICONSIZE}; constexpr SDL_Rect CONTROLLER_DOWN = {48, 0, ICONSIZE, ICONSIZE};
constexpr SDL_Rect CONTROLLER_LEFT = {64, 16, ICONSIZE, ICONSIZE}; constexpr SDL_Rect CONTROLLER_LEFT = {64, 0, ICONSIZE, ICONSIZE};
constexpr SDL_Rect LEFT_BUTTON = {48, 144, ICONSIZE, ICONSIZE}; constexpr SDL_Rect LEFT_BUTTON = {112, 0, ICONSIZE, ICONSIZE};
constexpr SDL_Rect TOP_BUTTON = {0, 144, ICONSIZE, ICONSIZE}; constexpr SDL_Rect TOP_BUTTON = {80, 0, ICONSIZE, ICONSIZE};
constexpr SDL_Rect RIGHT_BUTTON = {16, 144, ICONSIZE, ICONSIZE}; constexpr SDL_Rect RIGHT_BUTTON = {96, 0, ICONSIZE, ICONSIZE};
constexpr SDL_Rect START_BUTTON = {128, 320, ICONSIZE, ICONSIZE}; constexpr SDL_Rect START_BUTTON = {0, 0, ICONSIZE, ICONSIZE};
constexpr SDL_Rect CONTROLLER_UP_POS = {PADDING.x, PADDING.y + 18 * 0, ICONSIZE, ICONSIZE}; constexpr SDL_Rect CONTROLLER_UP_POS = {PADDING.x, PADDING.y + 18 * 0, ICONSIZE, ICONSIZE};
constexpr SDL_Rect CONTROLLER_DOWN_POS = {PADDING.x, PADDING.y + 18 * 1, ICONSIZE, ICONSIZE}; constexpr SDL_Rect CONTROLLER_DOWN_POS = {PADDING.x, PADDING.y + 18 * 1, ICONSIZE, ICONSIZE};
@@ -50,7 +54,7 @@ OnScreenHelp *OnScreenHelp::get()
} }
// Constructor // Constructor
OnScreenHelp::OnScreenHelp() : state(OnScreenHelpStatus::showing) OnScreenHelp::OnScreenHelp() : state(OnScreenHelpStatus::hidden), index(0)
{ {
setSize(); setSize();
@@ -58,6 +62,7 @@ OnScreenHelp::OnScreenHelp() : state(OnScreenHelpStatus::showing)
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
fillTexture(); fillTexture();
precalculatePath(hiddenPos, showingPos, 60);
} }
// Destructor // Destructor
@@ -69,6 +74,8 @@ OnScreenHelp::~OnScreenHelp()
// Actualiza la lógica interna // Actualiza la lógica interna
void OnScreenHelp::update() void OnScreenHelp::update()
{ {
// Actualiza la posición
updatePosition();
} }
// Muestra el objeto en pantalla // Muestra el objeto en pantalla
@@ -84,17 +91,17 @@ void OnScreenHelp::render()
void OnScreenHelp::fillTexture() void OnScreenHelp::fillTexture()
{ {
// Cambia el renderizador a la textura // Cambia el renderizador a la textura
SDL_Texture *temp = SDL_GetRenderTarget(Screen::get()->getRenderer()); auto temp = SDL_GetRenderTarget(Screen::get()->getRenderer());
SDL_SetRenderTarget(Screen::get()->getRenderer(), texture); SDL_SetRenderTarget(Screen::get()->getRenderer(), texture);
// Crea el objeto para el texto // Crea el objeto para el texto
Text *text = new Text(Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), Screen::get()->getRenderer()); auto text = std::make_unique<Text>(Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), Screen::get()->getRenderer());
// Crea la textura con los gráficos // Crea la textura con los gráficos
Texture *controllersTexture = new Texture(Screen::get()->getRenderer(), Asset::get()->get("controllers.png")); auto controllersTexture = std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("controllers.png"));
// Crea el sprite para dibujar los gráficos // Crea el sprite para dibujar los gráficos
Sprite *sprite = new Sprite({0, 0, 16, 16}, controllersTexture); auto sprite = std::make_unique<Sprite>((SDL_Rect){0, 0, 16, 16}, controllersTexture);
// Borra la textura // Borra la textura
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 0); SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 0);
@@ -115,78 +122,134 @@ void OnScreenHelp::fillTexture()
rect = {0, 4, dest.w, dest.h - (4 * 2)}; rect = {0, 4, dest.w, dest.h - (4 * 2)};
SDL_RenderFillRect(Screen::get()->getRenderer(), &rect); SDL_RenderFillRect(Screen::get()->getRenderer(), &rect);
// Dibuja los iconos y el texto rect = {0, 0, dest.w / 2, dest.h};
sprite->setSpriteClip(CONTROLLER_UP); SDL_RenderFillRect(Screen::get()->getRenderer(), &rect);
sprite->setPos(CONTROLLER_UP_POS);
sprite->render();
text->write(CONTROLLER_UP_POS.x + DESP.x, CONTROLLER_UP_POS.y + DESP.y, lang::getText(107));
sprite->setSpriteClip(CONTROLLER_DOWN); // Renderiza los botones y el texto
sprite->setPos(CONTROLLER_DOWN_POS); renderButton(sprite.get(), text.get(), CONTROLLER_UP, CONTROLLER_UP_POS, 107);
sprite->render(); renderButton(sprite.get(), text.get(), CONTROLLER_DOWN, CONTROLLER_DOWN_POS, 108);
text->write(CONTROLLER_DOWN_POS.x + DESP.x, CONTROLLER_DOWN_POS.y + DESP.y, lang::getText(108)); renderButton(sprite.get(), text.get(), CONTROLLER_LEFT, CONTROLLER_LEFT_POS, 109);
renderButton(sprite.get(), text.get(), LEFT_BUTTON, LEFT_BUTTON_POS, 110);
sprite->setSpriteClip(CONTROLLER_LEFT); renderButton(sprite.get(), text.get(), TOP_BUTTON, TOP_BUTTON_POS, 111);
sprite->setPos(CONTROLLER_LEFT_POS); renderButton(sprite.get(), text.get(), RIGHT_BUTTON, RIGHT_BUTTON_POS, 112);
sprite->render(); renderButton(sprite.get(), text.get(), START_BUTTON, START_BUTTON_POS, 113);
text->write(CONTROLLER_LEFT_POS.x + DESP.x, CONTROLLER_LEFT_POS.y + DESP.y, lang::getText(109));
sprite->setSpriteClip(LEFT_BUTTON);
sprite->setPos(LEFT_BUTTON_POS);
sprite->render();
text->write(LEFT_BUTTON_POS.x + DESP.x, LEFT_BUTTON_POS.y + DESP.y, lang::getText(110));
sprite->setSpriteClip(TOP_BUTTON);
sprite->setPos(TOP_BUTTON_POS);
sprite->render();
text->write(TOP_BUTTON_POS.x + DESP.x, TOP_BUTTON_POS.y + DESP.y, lang::getText(111));
sprite->setSpriteClip(RIGHT_BUTTON);
sprite->setPos(RIGHT_BUTTON_POS);
sprite->render();
text->write(RIGHT_BUTTON_POS.x + DESP.x, RIGHT_BUTTON_POS.y + DESP.y, lang::getText(112));
sprite->setSpriteClip(START_BUTTON);
sprite->setPos(START_BUTTON_POS);
sprite->render();
text->write(START_BUTTON_POS.x + DESP.x, START_BUTTON_POS.y + DESP.y, lang::getText(113));
// text->write(0, 0, "hola");
// Restaura el destino de renderizado // Restaura el destino de renderizado
SDL_SetRenderTarget(Screen::get()->getRenderer(), temp); SDL_SetRenderTarget(Screen::get()->getRenderer(), temp);
// Elimina los objetos
delete text;
delete controllersTexture;
delete sprite;
} }
// Define el ancho y alto de la textura // Define el ancho y alto de la textura
void OnScreenHelp::setSize() void OnScreenHelp::setSize()
{ {
const int textSize = getLargestStringSize(); const auto textSize = getLargestStringSize();
dest = (SDL_Rect){8, 8, PADDING.x + DESP.x + textSize + PADDING.x, PADDING.y + (7 * 18) + PADDING.y}; const auto width = PADDING.x + DESP.x + textSize + PADDING.x;
const auto height = PADDING.y + (7 * 18) + PADDING.y;
const auto x = 0;
const auto y = (param.game.height - height) / 2;
dest = (SDL_Rect){x, y, width, height};
hiddenPos = -width;
showingPos = 0;
} }
// Activa o desactiva el objeto // Activa o desactiva el objeto
void OnScreenHelp::toggleState() void OnScreenHelp::toggleState()
{ {
state = state == OnScreenHelpStatus::showing ? OnScreenHelpStatus::hidden : OnScreenHelpStatus::showing; if (state == OnScreenHelpStatus::showing || state == OnScreenHelpStatus::entering)
{
state = OnScreenHelpStatus::exitting;
}
else if (state == OnScreenHelpStatus::hidden || state == OnScreenHelpStatus::exitting)
{
state = OnScreenHelpStatus::entering;
}
} }
// Calcula la longitud en pixels del texto más largo // Calcula la longitud en pixels del texto más largo
int OnScreenHelp::getLargestStringSize() const auto OnScreenHelp::getLargestStringSize() -> int const
{ {
Text *text = new Text(Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), Screen::get()->getRenderer()); auto text = std::make_unique<Text>(Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), Screen::get()->getRenderer());
int size = 0; auto size = 0;
for (int i = 107; i <= 113; ++i) for (int i = 107; i <= 113; ++i)
{ {
const int textSize = text->lenght(lang::getText(i)); const auto textSize = text->lenght(lang::getText(i));
size = textSize > size ? textSize : size; size = textSize > size ? textSize : size;
} }
delete text;
return size; return size;
} }
// Renderizara el boton y el texto
void OnScreenHelp::renderButton(Sprite *sprite, Text *text, const SDL_Rect &buttonClip, const SDL_Rect &buttonPos, int textId)
{
sprite->setSpriteClip(buttonClip);
sprite->setPos(buttonPos);
sprite->render();
text->write(buttonPos.x + DESP.x, buttonPos.y + DESP.y, lang::getText(textId));
}
// Actualiza la posición
void OnScreenHelp::updatePosition()
{
switch (state)
{
case OnScreenHelpStatus::hidden:
{
index = 0;
break;
}
case OnScreenHelpStatus::showing:
{
index = path.size() - 1;
break;
}
case OnScreenHelpStatus::exitting:
{
if (index > 0)
{
index--;
}
else
{
state = OnScreenHelpStatus::hidden;
}
break;
}
case OnScreenHelpStatus::entering:
{
if (index < (int)path.size() - 1)
{
index++;
}
else
{
state = OnScreenHelpStatus::showing;
}
break;
}
default:
break;
}
dest.x = path[index];
}
// Rellena los puntos por donde pasa la animación
void OnScreenHelp::precalculatePath(double start, double end, int steps)
{
path.reserve(steps);
for (int i = 0; i <= steps; ++i)
{
double t = static_cast<double>(i) / steps;
double value = start + (end - start) * easeInOutSine(t);
path.push_back(static_cast<int>(value));
}
}

View File

@@ -1,11 +1,10 @@
#pragma once #pragma once
#include <SDL2/SDL.h> #include <SDL2/SDL_rect.h> // for SDL_Rect
class Screen; #include <SDL2/SDL_render.h> // for SDL_Texture
class Asset; #include <vector> // for vector
class Input;
class Texture;
class Sprite; class Sprite;
class Text;
enum class OnScreenHelpStatus enum class OnScreenHelpStatus
{ {
@@ -22,14 +21,13 @@ private:
// [SINGLETON] Objeto screen privado para Don Melitón // [SINGLETON] Objeto screen privado para Don Melitón
static OnScreenHelp *onScreenHelp; static OnScreenHelp *onScreenHelp;
Screen *screen; // Objeto encargado de dibujar en pantalla
Asset *asset; // Objeto con los ficheros de recursos
Input *input; // Objeto pata gestionar la entrada
SDL_Texture *texture; // Textura donde dibujar SDL_Texture *texture; // Textura donde dibujar
SDL_Rect dest; // Posición donde dibujar la textura; SDL_Rect dest; // Posición donde dibujar la textura;
int hiddenPos, showingPos; // Las dos posiciones donde colocar la textura
OnScreenHelpStatus state; // Estado del objeto OnScreenHelpStatus state; // Estado del objeto
std::vector<int> path; // Puntos por donde pasa la animación de la tarjeta
int index; // Indice para recorrer la animación
// [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos screen desde fuera // [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos screen desde fuera
@@ -46,7 +44,16 @@ private:
void setSize(); void setSize();
// Calcula la longitud en pixels del texto más largo // Calcula la longitud en pixels del texto más largo
int getLargestStringSize() const; auto getLargestStringSize() -> int const;
// Renderizara el boton y el texto
void renderButton(Sprite *sprite, Text *text, const SDL_Rect &buttonClip, const SDL_Rect &buttonPos, int textId);
// Actualiza la posición
void updatePosition();
// Rellena los puntos por donde pasa la animación
void precalculatePath(double start, double end, int steps);
public: public:
// [SINGLETON] Crearemos el objeto screen con esta función estática // [SINGLETON] Crearemos el objeto screen con esta función estática

View File

@@ -1,44 +1,36 @@
#include "options.h" #include "options.h"
#include <SDL2/SDL_gamecontroller.h> // for SDL_GameControllerButton, SDL_C... #include <SDL2/SDL_gamecontroller.h> // for SDL_GameControllerButton, SDL_C...
#include <SDL2/SDL_video.h> // for SDL_WINDOW_FULLSCREEN, SDL_WIND...
#include <algorithm> // for max, min #include <algorithm> // for max, min
#include <fstream> // for char_traits, basic_ostream, ope... #include <fstream> // for basic_ostream, operator<<, basi...
#include <iostream> // for cout #include <iostream> // for cout
#include <vector> // for vector #include <vector> // for vector
#include "input.h" // for inputs_e, INPUT_USE_ANY, INPUT_... #include "input.h" // for inputs_e, INPUT_USE_ANY, INPUT_...
#include "lang.h" // for lang_e #include "lang.h" // for lang_e
#include "screen.h" // for SCREEN_FILTER_NEAREST, SCREEN_V... #include "screen.h" // for ScreenVideoMode, ScreenFilter
#include "utils.h" // for op_controller_t, options_t, op_... #include "utils.h" // for OptionsController, Options, op_...
// Variables // Variables
options_t options; Options options;
// Declaraciones // Declaraciones
bool setOptions(std::string var, std::string value); bool setOptions(const std::string &var, const std::string &value);
// Inicializa las opciones del programa // Inicializa las opciones del programa
void initOptions() void initOptions()
{ {
// Opciones de video // Opciones de video
#ifdef ANBERNIC #ifdef ANBERNIC
options.video.mode = 0; options.video.mode = ScreenVideoMode::WINDOW;
options.video.window.size = 3; options.video.window.size = 3;
#else #else
options.video.mode = 0; options.video.mode = ScreenVideoMode::WINDOW;
options.video.window.size = 2; options.video.window.size = 2;
#endif #endif
options.video.filter = SCREEN_FILTER_NEAREST; options.video.filter = ScreenFilter::NEAREST;
options.video.vSync = true; options.video.v_sync = true;
options.video.integerScale = true; options.video.integer_scale = true;
options.video.keepAspect = true;
options.video.shaders = true; options.video.shaders = true;
// Opciones de las notificaciones
options.notification.posV = pos_top;
options.notification.posH = pos_left;
options.notification.sound = false;
options.notification.color = {48, 48, 48};
// Opciones de audio // Opciones de audio
options.audio.music.enabled = true; options.audio.music.enabled = true;
options.audio.music.volume = 128; options.audio.music.volume = 128;
@@ -46,29 +38,30 @@ void initOptions()
options.audio.sound.volume = 64; options.audio.sound.volume = 64;
// Opciones de juego // Opciones de juego
options.game.difficulty = DIFFICULTY_NORMAL; options.game.difficulty = GameDifficulty::NORMAL;
options.game.language = lang::ba_BA; options.game.language = lang::Code::ba_BA;
options.game.autofire = true; options.game.autofire = true;
// Opciones de control // Opciones de control
options.controller.clear(); options.controller.clear();
op_controller_t c; OptionsController c;
const int numPlayers = 2; constexpr int num_players = 2;
for (int index = 0; index < numPlayers; ++index) for (int index = 0; index < num_players; ++index)
{ {
c.index = index; c.index = index;
c.playerId = index + 1; c.player_id = index + 1;
c.deviceType = INPUT_USE_GAMECONTROLLER; c.device_type = INPUT_USE_GAMECONTROLLER;
c.name = "NO NAME"; c.name = "NO NAME";
c.plugged = false;
// Inputs que se guardan en las opciones y, por tanto, a disco // Inputs que se guardan en las opciones y, por tanto, a disco
c.inputs.clear(); c.inputs.clear();
c.inputs.push_back(input_fire_left); c.inputs.push_back(InputType::FIRE_LEFT);
c.inputs.push_back(input_fire_center); c.inputs.push_back(InputType::FIRE_CENTER);
c.inputs.push_back(input_fire_right); c.inputs.push_back(InputType::FIRE_RIGHT);
c.inputs.push_back(input_start); c.inputs.push_back(InputType::START);
c.inputs.push_back(input_service); c.inputs.push_back(InputType::SERVICE);
// Botones asociados a los inputs anteriores // Botones asociados a los inputs anteriores
c.buttons.clear(); c.buttons.clear();
@@ -80,11 +73,11 @@ void initOptions()
options.controller.push_back(c); options.controller.push_back(c);
} }
options.controller[0].deviceType = INPUT_USE_ANY; // El primer jugador puede usar tanto el teclado como el primer mando options.controller[0].device_type = INPUT_USE_ANY; // El primer jugador puede usar tanto el teclado como el primer mando
} }
// Carga el fichero de configuración // Carga el fichero de configuración
bool loadOptionsFile(std::string filePath) bool loadOptionsFile(std::string file_path)
{ {
// Inicializa las opciones del programa // Inicializa las opciones del programa
initOptions(); initOptions();
@@ -93,15 +86,17 @@ bool loadOptionsFile(std::string filePath)
bool success = true; bool success = true;
// Variables para manejar el fichero // Variables para manejar el fichero
const std::string fileName = filePath.substr(filePath.find_last_of("\\/") + 1); #ifdef VERBOSE
std::ifstream file(filePath); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
std::ifstream file(file_path);
// Si el fichero se puede abrir // Si el fichero se puede abrir
if (file.good()) if (file.good())
{ {
// Procesa el fichero linea a linea // Procesa el fichero linea a linea
#ifdef VERBOSE #ifdef VERBOSE
std::cout << "Reading file: " << fileName << std::endl; std::cout << "Reading file: " << file_name << std::endl;
#endif #endif
std::string line; std::string line;
while (std::getline(file, line)) while (std::getline(file, line))
@@ -115,7 +110,7 @@ bool loadOptionsFile(std::string filePath)
if (!setOptions(line.substr(0, pos), line.substr(pos + 1, line.length()))) if (!setOptions(line.substr(0, pos), line.substr(pos + 1, line.length())))
{ {
#ifdef VERBOSE #ifdef VERBOSE
std::cout << "Warning: file " << fileName << std::endl; std::cout << "Warning: file " << file_name << std::endl;
std::cout << "Unknown parameter " << line.substr(0, pos).c_str() << std::endl; std::cout << "Unknown parameter " << line.substr(0, pos).c_str() << std::endl;
#endif #endif
success = false; success = false;
@@ -130,16 +125,15 @@ bool loadOptionsFile(std::string filePath)
// El fichero no existe // El fichero no existe
else else
{ // Crea el fichero con los valores por defecto { // Crea el fichero con los valores por defecto
saveOptionsFile(filePath); saveOptionsFile(file_path);
} }
// Normaliza los valores // Normaliza los valores
const bool a = options.video.mode == 0; const bool a = options.video.mode == ScreenVideoMode::WINDOW;
const bool b = options.video.mode == SDL_WINDOW_FULLSCREEN; const bool b = options.video.mode == ScreenVideoMode::FULLSCREEN;
const bool c = options.video.mode == SDL_WINDOW_FULLSCREEN_DESKTOP; if (!(a || b))
if (!(a || b || c))
{ {
options.video.mode = SCREEN_VIDEO_MODE_WINDOW; options.video.mode = ScreenVideoMode::WINDOW;
} }
if (options.video.window.size < 1 || options.video.window.size > 4) if (options.video.window.size < 1 || options.video.window.size > 4)
@@ -147,89 +141,56 @@ bool loadOptionsFile(std::string filePath)
options.video.window.size = 3; options.video.window.size = 3;
} }
if (options.game.language < 0 || options.game.language > 2) if (options.game.language != lang::Code::en_UK && options.game.language != lang::Code::ba_BA && options.game.language != lang::Code::es_ES)
{ {
options.game.language = lang::en_UK; options.game.language = lang::Code::en_UK;
} }
return success; return success;
} }
// Guarda el fichero de configuración // Guarda el fichero de configuración
bool saveOptionsFile(std::string filePath) bool saveOptionsFile(std::string file_path)
{ {
const std::string fileName = filePath.substr(filePath.find_last_of("\\/") + 1); #ifdef VERBOSE
std::ofstream file(filePath); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
std::ofstream file(file_path);
if (!file.good()) if (!file.good())
{ {
#ifdef VERBOSE #ifdef VERBOSE
std::cout << fileName << " can't be opened" << std::endl; std::cout << file_name << " can't be opened" << std::endl;
#endif #endif
return false; return false;
} }
#ifdef VERBOSE #ifdef VERBOSE
std::cout << "Writing file: " << fileName << std::endl; std::cout << "Writing file: " << file_name << std::endl;
#endif #endif
// Opciones de video // Opciones de video
const auto value_video_mode_winow = std::to_string(static_cast<int>(ScreenVideoMode::WINDOW));
const auto value_video_mode_fullscreen = std::to_string(static_cast<int>(ScreenVideoMode::FULLSCREEN));
const auto value_filter_nearest = std::to_string(static_cast<int>(ScreenFilter::NEAREST));
const auto value_filter_lineal = std::to_string(static_cast<int>(ScreenFilter::LINEAL));
file << "## VIDEO\n"; file << "## VIDEO\n";
file << "## video.mode [0: window, 1: full screen]\n"; file << "## video.mode [" << value_video_mode_winow << ": window, " << value_video_mode_fullscreen << ": fullscreen]\n";
file << "## video.filter [0: nearest, 1: lineal]\n"; file << "## video.filter [" << value_filter_nearest << ": nearest, " << value_filter_lineal << ": lineal]\n";
file << "\n"; file << "\n";
if (options.video.mode == SCREEN_VIDEO_MODE_WINDOW) const auto valueVideoMode = std::to_string(static_cast<int>(options.video.mode));
{ file << "video.mode=" << valueVideoMode << "\n";
file << "video.mode=0\n";
}
else if (options.video.mode == SCREEN_VIDEO_MODE_FULLSCREEN)
{
file << "video.mode=1\n";
}
file << "video.window.size=" + std::to_string(options.video.window.size) + "\n"; file << "video.window.size=" + std::to_string(options.video.window.size) + "\n";
options.video.filter == SCREEN_FILTER_NEAREST ? file << "video.filter=0\n" : file << "video.filter=1\n"; const auto valueFilter = std::to_string(static_cast<int>(options.video.filter));
file << "video.filter=" << valueFilter << "\n";
file << "video.v_sync=" + boolToString(options.video.v_sync) + "\n";
file << "video.integer_scale=" + boolToString(options.video.integer_scale) + "\n";
file << "video.shaders=" + boolToString(options.video.shaders) + "\n"; file << "video.shaders=" + boolToString(options.video.shaders) + "\n";
file << "video.vSync=" + boolToString(options.video.vSync) + "\n";
file << "video.integerScale=" + boolToString(options.video.integerScale) + "\n";
file << "video.keepAspect=" + boolToString(options.video.keepAspect) + "\n";
// Opciones de notificaciones
file << "\n\n## NOTIFICATION\n";
file << "## notification.posV [pos_top | pos_bottom]\n";
file << "## notification.posH [pos_left | pos_middle | pos_right]\n";
file << "\n";
if (options.notification.posV == pos_top)
{
file << "notification.posV=pos_top\n";
}
else
{
file << "notification.posV=pos_bottom\n";
}
if (options.notification.posH == pos_left)
{
file << "notification.posH=pos_left\n";
}
else if (options.notification.posH == pos_middle)
{
file << "notification.posH=pos_middle\n";
}
else
{
file << "notification.posH=pos_right\n";
}
file << "notification.sound=" + boolToString(options.notification.sound) + "\n";
// Opciones de audio // Opciones de audio
file << "\n\n## AUDIO\n"; file << "\n\n## AUDIO\n";
@@ -242,32 +203,35 @@ bool saveOptionsFile(std::string filePath)
file << "audio.sound.volume=" + std::to_string(options.audio.sound.volume) + "\n"; file << "audio.sound.volume=" + std::to_string(options.audio.sound.volume) + "\n";
// Opciones del juego // Opciones del juego
const auto value_difficulty_easy = std::to_string(static_cast<int>(GameDifficulty::EASY));
const auto value_difficulty_normal = std::to_string(static_cast<int>(GameDifficulty::NORMAL));
const auto value_difficulty_hard = std::to_string(static_cast<int>(GameDifficulty::HARD));
file << "\n\n## GAME\n"; file << "\n\n## GAME\n";
file << "## game.language [0: spanish, 1: valencian, 2: english]\n"; file << "## game.language [0: spanish, 1: valencian, 2: english]\n";
file << "## game.difficulty [0: easy, 1: normal, 2: hard]\n"; file << "## game.difficulty [" << value_difficulty_easy << ": easy, " << value_difficulty_normal << ": normal, " << value_difficulty_hard << ": hard]\n";
file << "\n"; file << "\n";
file << "game.language=" + std::to_string(options.game.language) + "\n"; file << "game.language=" + std::to_string(static_cast<int>(options.game.language)) + "\n";
file << "game.difficulty=" + std::to_string(options.game.difficulty) + "\n"; file << "game.difficulty=" + std::to_string(static_cast<int>(options.game.difficulty)) + "\n";
file << "game.autofire=" + boolToString(options.game.autofire) + "\n"; file << "game.autofire=" + boolToString(options.game.autofire) + "\n";
// Opciones de mandos // Opciones de mandos
file << "\n\n## CONTROLLERS\n"; file << "\n\n## CONTROLLERS\n";
file << "\n"; file << "\n";
const int numPlayers = 2; const int num_players = 2;
for (int index = 0; index < numPlayers; ++index) for (int index = 0; index < num_players; ++index)
{ {
const std::string joyIndex = std::to_string(index + 1); const std::string joyIndex = std::to_string(index + 1);
file << "controller" + joyIndex + ".name=" + options.controller[index].name + "\n"; file << "controller" + joyIndex + ".name=" + options.controller[index].name + "\n";
file << "controller" + joyIndex + ".player=" + std::to_string(options.controller[index].playerId) + "\n"; file << "controller" + joyIndex + ".player=" + std::to_string(options.controller[index].player_id) + "\n";
file << "controller" + joyIndex + ".button.fire_left=" + std::to_string((int)options.controller[index].buttons[0]) + "\n"; file << "controller" + joyIndex + ".button.fire_left=" + std::to_string((int)options.controller[index].buttons[0]) + "\n";
file << "controller" + joyIndex + ".button.fire_center=" + std::to_string((int)options.controller[index].buttons[1]) + "\n"; file << "controller" + joyIndex + ".button.fire_center=" + std::to_string((int)options.controller[index].buttons[1]) + "\n";
file << "controller" + joyIndex + ".button.fire_right=" + std::to_string((int)options.controller[index].buttons[2]) + "\n"; file << "controller" + joyIndex + ".button.fire_right=" + std::to_string((int)options.controller[index].buttons[2]) + "\n";
file << "controller" + joyIndex + ".button.start=" + std::to_string((int)options.controller[index].buttons[3]) + "\n"; file << "controller" + joyIndex + ".button.start=" + std::to_string((int)options.controller[index].buttons[3]) + "\n";
file << "controller" + joyIndex + ".button.service=" + std::to_string((int)options.controller[index].buttons[4]) + "\n"; file << "controller" + joyIndex + ".button.service=" + std::to_string((int)options.controller[index].buttons[4]) + "\n";
if (index < numPlayers - 1) if (index < num_players - 1)
{ {
file << "\n"; file << "\n";
} }
@@ -280,15 +244,15 @@ bool saveOptionsFile(std::string filePath)
} }
// Asigna variables a partir de dos cadenas // Asigna variables a partir de dos cadenas
bool setOptions(std::string var, std::string value) bool setOptions(const std::string &var, const std::string &value)
{ {
// Indicador de éxito en la asignación // Indicador de éxito en la asignación
bool success = true; auto success = true;
// Opciones de video // Opciones de video
if (var == "video.mode") if (var == "video.mode")
{ {
options.video.mode = value == std::to_string(SCREEN_VIDEO_MODE_WINDOW) ? SCREEN_VIDEO_MODE_WINDOW : SCREEN_VIDEO_MODE_FULLSCREEN; options.video.mode = static_cast<ScreenVideoMode>(std::stoi(value));
} }
else if (var == "video.window.size") else if (var == "video.window.size")
@@ -302,7 +266,7 @@ bool setOptions(std::string var, std::string value)
else if (var == "video.filter") else if (var == "video.filter")
{ {
options.video.filter = value == std::to_string(SCREEN_FILTER_NEAREST) ? SCREEN_FILTER_NEAREST : SCREEN_FILTER_LINEAL; options.video.filter = static_cast<ScreenFilter>(std::stoi(value));
} }
else if (var == "video.shaders") else if (var == "video.shaders")
@@ -310,46 +274,14 @@ bool setOptions(std::string var, std::string value)
options.video.shaders = stringToBool(value); options.video.shaders = stringToBool(value);
} }
else if (var == "video.vSync") else if (var == "video.integer_scale")
{ {
options.video.vSync = stringToBool(value); options.video.integer_scale = stringToBool(value);
} }
else if (var == "video.integerScale") else if (var == "video.v_sync")
{ {
options.video.integerScale = stringToBool(value); options.video.v_sync = stringToBool(value);
}
else if (var == "video.keepAspect")
{
options.video.keepAspect = stringToBool(value);
}
// Opciones de notificaciones
else if (var == "notification.posH")
{
if (value == "pos_left")
{
options.notification.posH = pos_left;
}
else if (value == "pos_middle")
{
options.notification.posH = pos_middle;
}
else
{
options.notification.posH = pos_right;
}
}
else if (var == "notification.posV")
{
options.notification.posV = value == "pos_top" ? pos_top : pos_bottom;
}
else if (var == "notification.sound")
{
options.notification.sound = stringToBool(value);
} }
// Opciones de audio // Opciones de audio
@@ -376,12 +308,12 @@ bool setOptions(std::string var, std::string value)
// Opciones de juego // Opciones de juego
else if (var == "game.language") else if (var == "game.language")
{ {
options.game.language = std::stoi(value); options.game.language = static_cast<lang::Code>(std::stoi(value));
} }
else if (var == "game.difficulty") else if (var == "game.difficulty")
{ {
options.game.difficulty = std::stoi(value); options.game.difficulty = static_cast<GameDifficulty>(std::stoi(value));
} }
else if (var == "game.autofire") else if (var == "game.autofire")
@@ -397,7 +329,7 @@ bool setOptions(std::string var, std::string value)
else if (var == "controller1.player") else if (var == "controller1.player")
{ {
options.controller[0].playerId = std::max(1, std::min(2, std::stoi(value))); options.controller[0].player_id = std::max(1, std::min(2, std::stoi(value)));
} }
else if (var == "controller1.button.fire_left") else if (var == "controller1.button.fire_left")
@@ -432,7 +364,7 @@ bool setOptions(std::string var, std::string value)
else if (var == "controller2.player") else if (var == "controller2.player")
{ {
options.controller[1].playerId = std::max(1, std::min(2, std::stoi(value))); options.controller[1].player_id = std::max(1, std::min(2, std::stoi(value)));
} }
else if (var == "controller2.button.fire_left") else if (var == "controller2.button.fire_left")
@@ -461,7 +393,7 @@ bool setOptions(std::string var, std::string value)
} }
// Lineas vacias o que empiezan por comentario // Lineas vacias o que empiezan por comentario
else if (var == "" || var.substr(0, 1) == "#") else if (var.empty() || var.starts_with("#"))
{ {
} }

View File

@@ -1,13 +1,13 @@
#pragma once #pragma once
#include <string> // for string #include <string> // for string
struct options_t; struct Options;
// Variables // Variables
extern options_t options; extern Options options;
// Carga el fichero de configuración // Carga el fichero de configuración
bool loadOptionsFile(std::string filePath); bool loadOptionsFile(std::string file_path);
// Guarda el fichero de configuración // Guarda el fichero de configuración
bool saveOptionsFile(std::string filePath); bool saveOptionsFile(std::string file_path);

View File

@@ -1,12 +1,15 @@
#include "param.h" #include "param.h"
#include <fstream> // for char_traits, basic_ostream, basic_ifstream, basi... #include <fstream> // for char_traits, basic_ostream, basic_ifstream, basi...
#include <iostream> // for cout #include <iostream> // for cout
#include "utils.h" // for param_t, paramGame_t, zone_t, paramBalloon_t #include <sstream>
#include <string>
#include <stdexcept>
#include "utils.h" // for Param, ParamGame, Zone, ParamBalloon
param_t param; Param param;
// Asigna variables a partir de dos cadenas // Asigna variables a partir de dos cadenas
bool setParams(std::string var, std::string value); bool setParams(const std::string &var, const std::string &value);
// Calcula variables a partir de otras variables // Calcula variables a partir de otras variables
void precalculateZones(); void precalculateZones();
@@ -17,51 +20,59 @@ void initParam()
// GAME // GAME
param.game.width = 320; param.game.width = 320;
param.game.height = 256; param.game.height = 256;
param.game.itemSize = 20; param.game.item_size = 20;
param.game.gameArea.rect = {0, 0, param.game.width, param.game.height}; param.game.game_area.rect = {0, 0, param.game.width, param.game.height};
param.game.playArea.rect = {0, 0, param.game.width, 216}; param.game.play_area.rect = {0, 0, param.game.width, 216};
precalculateZones(); precalculateZones();
// SCOREBOARD // SCOREBOARD
param.scoreboard = {0, 216, param.game.width, 40}; param.scoreboard = {0, 216, param.game.width, 40};
// FADE // FADE
param.fade.numSquaresWidth = param.game.width / 2; param.fade.num_squares_width = param.game.width / 2;
param.fade.numSquaresHeight = param.game.height / 2; param.fade.num_squares_height = param.game.height / 2;
param.fade.randomSquaresDelay = 1; param.fade.random_squares_delay = 1;
param.fade.randomSquaresMult = 500; param.fade.random_squares_mult = 500;
param.fade.postDuration = 80; param.fade.post_duration = 80;
param.fade.venetianSize = 16; param.fade.venetian_size = 16;
// TITLE // TITLE
param.title.pressStartPosition = 160; param.title.press_start_position = 160;
param.title.titleDuration = 800; param.title.title_duration = 800;
param.title.arcadeEditionPosition = 123; param.title.arcade_edition_position = 123;
param.title.titleCCPosition = 11; param.title.title_c_c_position = 11;
// BACKGROUND // BACKGROUND
param.background.attenuateColor = {255, 255, 255}; param.background.attenuate_color = (Color){255, 255, 255};
param.background.attenuateAlpha = 32; param.background.attenuate_alpha = 32;
// BALLOONS // BALLOONS
param.balloon1.vel = 2.60f; param.balloon_1.vel = 2.60f;
param.balloon1.grav = 0.09f; param.balloon_1.grav = 0.09f;
param.balloon2.vel = 3.50f; param.balloon_2.vel = 3.50f;
param.balloon2.grav = 0.10f; param.balloon_2.grav = 0.10f;
param.balloon3.vel = 4.50f; param.balloon_3.vel = 4.50f;
param.balloon3.grav = 0.10f; param.balloon_3.grav = 0.10f;
param.balloon4.vel = 4.95f; param.balloon_4.vel = 4.95f;
param.balloon4.grav = 0.10f; param.balloon_4.grav = 0.10f;
// NOTIFICATION
param.notification.pos_v = NotifyPosition::TOP;
param.notification.pos_h = NotifyPosition::LEFT;
param.notification.sound = false;
param.notification.color.r = 48;
param.notification.color.g = 48;
param.notification.color.b = 48;
} }
// Establece valores para los parametros a partir de un fichero de texto // Establece valores para los parametros a partir de un fichero de texto
void loadParamsFromFile(std::string filePath) /*void loadParamsFromFile(std::string file_path)
{ {
// Pone valores por defecto a las variables // Pone valores por defecto a las variables
initParam(); initParam();
// Variables para manejar el fichero // Variables para manejar el fichero
std::ifstream file(filePath); std::ifstream file(file_path);
std::string line; std::string line;
std::string param1; std::string param1;
std::string param2; std::string param2;
@@ -70,18 +81,25 @@ void loadParamsFromFile(std::string filePath)
if (file.good()) if (file.good())
{ {
#ifdef VERBOSE #ifdef VERBOSE
const std::string filename = filePath.substr(filePath.find_last_of("\\/") + 1); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
std::cout << "Reading file: " << filename << std::endl; std::cout << "Reading file: " << file_name << std::endl;
#endif #endif
// Procesa cada linea del fichero // Procesa cada linea del fichero
while (std::getline(file, line)) while (std::getline(file, line))
{ {
// Reinicia variables // Reinicia variables
param1 = ""; param1.clear();
param2 = ""; param2.clear();
// Elimina los comentarios // Elimina los comentarios al final de una linea
line = line.substr(0, line.find("#")); {
// line = line.substr(0, line.find("#"));
auto pos = line.find("#");
if (pos != std::string::npos)
{
line.resize(pos);
}
}
// Ignora los espacios en blanco // Ignora los espacios en blanco
int pos = 0; int pos = 0;
@@ -145,17 +163,61 @@ void loadParamsFromFile(std::string filePath)
} }
#ifdef VERBOSE #ifdef VERBOSE
else else
std::cout << "Failed to load file: " << filePath << std::endl; std::cout << "Failed to load file: " << file_path << std::endl;
#endif #endif
precalculateZones();
}*/
void loadParamsFromFile(const std::string &file_path)
{
// Inicializa los parámetros con valores por defecto
initParam();
// Abre el archivo
std::ifstream file(file_path);
if (!file.is_open())
{
#ifdef VERBOSE
std::cerr << "Error: No se pudo abrir el archivo " << file_path << std::endl;
#endif
throw std::runtime_error("No se pudo abrir el archivo: " + file_path);
}
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
std::cout << "Reading file: " << file_name << std::endl;
#endif
std::string line, param1, param2;
while (std::getline(file, line))
{
// Elimina comentarios
auto comment_pos = line.find('#');
if (comment_pos != std::string::npos)
{
line.resize(comment_pos);
}
// Usa un stream para separar palabras
std::istringstream iss(line);
if (iss >> param1 >> param2)
{
setParams(param1, param2);
}
}
// Cierra el archivo
file.close();
// Realiza cálculos adicionales después de cargar los parámetros
precalculateZones(); precalculateZones();
} }
// Asigna variables a partir de dos cadenas // Asigna variables a partir de dos cadenas
bool setParams(std::string var, std::string value) bool setParams(const std::string &var, const std::string &value)
{ {
// Indicador de éxito en la asignación // Indicador de éxito en la asignación
bool success = true; auto success = true;
// GAME // GAME
if (var == "game.width") if (var == "game.width")
@@ -168,60 +230,60 @@ bool setParams(std::string var, std::string value)
param.game.height = std::stoi(value); param.game.height = std::stoi(value);
} }
else if (var == "game.itemSize") else if (var == "game.item_size")
{ {
param.game.itemSize = std::stoi(value); param.game.item_size = std::stoi(value);
} }
else if (var == "game.playArea.rect.x") else if (var == "game.play_area.rect.x")
{ {
param.game.playArea.rect.x = std::stoi(value); param.game.play_area.rect.x = std::stoi(value);
} }
else if (var == "game.playArea.rect.y") else if (var == "game.play_area.rect.y")
{ {
param.game.playArea.rect.y = std::stoi(value); param.game.play_area.rect.y = std::stoi(value);
} }
else if (var == "game.playArea.rect.w") else if (var == "game.play_area.rect.w")
{ {
param.game.playArea.rect.w = std::stoi(value); param.game.play_area.rect.w = std::stoi(value);
} }
else if (var == "game.playArea.rect.h") else if (var == "game.play_area.rect.h")
{ {
param.game.playArea.rect.h = std::stoi(value); param.game.play_area.rect.h = std::stoi(value);
} }
// FADE // FADE
else if (var == "fade.numSquaresWidth") else if (var == "fade.num_squares_width")
{ {
param.fade.numSquaresWidth = std::stoi(value); param.fade.num_squares_width = std::stoi(value);
} }
else if (var == "fade.numSquaresHeight") else if (var == "fade.num_squares_height")
{ {
param.fade.numSquaresHeight = std::stoi(value); param.fade.num_squares_height = std::stoi(value);
} }
else if (var == "fade.randomSquaresDelay") else if (var == "fade.random_squares_delay")
{ {
param.fade.randomSquaresDelay = std::stoi(value); param.fade.random_squares_delay = std::stoi(value);
} }
else if (var == "fade.randomSquaresMult") else if (var == "fade.random_squares_mult")
{ {
param.fade.randomSquaresMult = std::stoi(value); param.fade.random_squares_mult = std::stoi(value);
} }
else if (var == "fade.postDuration") else if (var == "fade.post_duration")
{ {
param.fade.postDuration = std::stoi(value); param.fade.post_duration = std::stoi(value);
} }
else if (var == "fade.venetianSize") else if (var == "fade.venetian_size")
{ {
param.fade.venetianSize = std::stoi(value); param.fade.venetian_size = std::stoi(value);
} }
// SCOREBOARD // SCOREBOARD
@@ -246,86 +308,128 @@ bool setParams(std::string var, std::string value)
} }
// TITLE // TITLE
else if (var == "title.pressStartPosition") else if (var == "title.press_start_position")
{ {
param.title.pressStartPosition = std::stoi(value); param.title.press_start_position = std::stoi(value);
} }
else if (var == "title.titleDuration") else if (var == "title.title_duration")
{ {
param.title.titleDuration = std::stoi(value); param.title.title_duration = std::stoi(value);
} }
else if (var == "title.arcadeEditionPosition") else if (var == "title.arcade_edition_position")
{ {
param.title.arcadeEditionPosition = std::stoi(value); param.title.arcade_edition_position = std::stoi(value);
} }
else if (var == "title.titleCCPosition") else if (var == "title.title_c_c_position")
{ {
param.title.titleCCPosition = std::stoi(value); param.title.title_c_c_position = std::stoi(value);
} }
// BACKGROUND // BACKGROUND
else if (var == "background.attenuateColor.r") else if (var == "background.attenuate_color.r")
{ {
param.background.attenuateColor.r = std::stoi(value); param.background.attenuate_color.r = std::stoi(value);
} }
else if (var == "background.attenuateColor.g") else if (var == "background.attenuate_color.g")
{ {
param.background.attenuateColor.g = std::stoi(value); param.background.attenuate_color.g = std::stoi(value);
} }
else if (var == "background.attenuateColor.b") else if (var == "background.attenuate_color.b")
{ {
param.background.attenuateColor.b = std::stoi(value); param.background.attenuate_color.b = std::stoi(value);
} }
else if (var == "background.attenuateAlpha") else if (var == "background.attenuate_alpha")
{ {
param.background.attenuateAlpha = std::stoi(value); param.background.attenuate_alpha = std::stoi(value);
} }
// BALLOON // BALLOON
else if (var == "balloon1.vel") else if (var == "balloon_1.vel")
{ {
param.balloon1.vel = std::stof(value); param.balloon_1.vel = std::stof(value);
} }
else if (var == "balloon1.grav") else if (var == "balloon_1.grav")
{ {
param.balloon1.grav = std::stof(value); param.balloon_1.grav = std::stof(value);
} }
else if (var == "balloon2.vel") else if (var == "balloon_2.vel")
{ {
param.balloon2.vel = std::stof(value); param.balloon_2.vel = std::stof(value);
} }
else if (var == "balloon2.grav") else if (var == "balloon_2.grav")
{ {
param.balloon2.grav = std::stof(value); param.balloon_2.grav = std::stof(value);
} }
else if (var == "balloon3.vel") else if (var == "balloon_3.vel")
{ {
param.balloon3.vel = std::stof(value); param.balloon_3.vel = std::stof(value);
} }
else if (var == "balloon3.grav") else if (var == "balloon_3.grav")
{ {
param.balloon3.grav = std::stof(value); param.balloon_3.grav = std::stof(value);
} }
else if (var == "balloon4.vel") else if (var == "balloon_4.vel")
{ {
param.balloon4.vel = std::stof(value); param.balloon_4.vel = std::stof(value);
} }
else if (var == "balloon4.grav") else if (var == "balloon_4.grav")
{ {
param.balloon4.grav = std::stof(value); param.balloon_4.grav = std::stof(value);
}
// NOTIFICACIONES
else if (var == "notification.pos_h")
{
if (value == "LEFT")
{
param.notification.pos_h = NotifyPosition::LEFT;
}
else if (value == "MIDDLE")
{
param.notification.pos_h = NotifyPosition::MIDDLE;
}
else
{
param.notification.pos_h = NotifyPosition::RIGHT;
}
}
else if (var == "notification.pos_v")
{
param.notification.pos_v = value == "TOP" ? NotifyPosition::TOP : NotifyPosition::BOTTOM;
}
else if (var == "notification.sound")
{
param.notification.sound = stringToBool(value);
}
else if (var == "notification.color.r")
{
param.notification.color.r = std::stoi(value);
}
else if (var == "notification.color.g")
{
param.notification.color.g = std::stoi(value);
}
else if (var == "notification.color.b")
{
param.notification.color.b = std::stoi(value);
} }
// RESTO // RESTO
@@ -341,19 +445,19 @@ bool setParams(std::string var, std::string value)
void precalculateZones() void precalculateZones()
{ {
// playArea // playArea
param.game.playArea.centerX = param.game.playArea.rect.w / 2; param.game.play_area.center_x = param.game.play_area.rect.w / 2;
param.game.playArea.firstQuarterX = param.game.playArea.rect.w / 4; param.game.play_area.first_quarter_x = param.game.play_area.rect.w / 4;
param.game.playArea.thirdQuarterX = param.game.playArea.rect.w / 4 * 3; param.game.play_area.third_quarter_x = param.game.play_area.rect.w / 4 * 3;
param.game.playArea.centerY = param.game.playArea.rect.h / 2; param.game.play_area.center_y = param.game.play_area.rect.h / 2;
param.game.playArea.firstQuarterY = param.game.playArea.rect.h / 4; param.game.play_area.first_quarter_y = param.game.play_area.rect.h / 4;
param.game.playArea.thirdQuarterY = param.game.playArea.rect.h / 4 * 3; param.game.play_area.third_quarter_y = param.game.play_area.rect.h / 4 * 3;
// gameArea // gameArea
param.game.gameArea.rect = {0, 0, param.game.width, param.game.height}; param.game.game_area.rect = {0, 0, param.game.width, param.game.height};
param.game.gameArea.centerX = param.game.gameArea.rect.w / 2; param.game.game_area.center_x = param.game.game_area.rect.w / 2;
param.game.gameArea.firstQuarterX = param.game.gameArea.rect.w / 4; param.game.game_area.first_quarter_x = param.game.game_area.rect.w / 4;
param.game.gameArea.thirdQuarterX = param.game.gameArea.rect.w / 4 * 3; param.game.game_area.third_quarter_x = param.game.game_area.rect.w / 4 * 3;
param.game.gameArea.centerY = param.game.gameArea.rect.h / 2; param.game.game_area.center_y = param.game.game_area.rect.h / 2;
param.game.gameArea.firstQuarterY = param.game.gameArea.rect.h / 4; param.game.game_area.first_quarter_y = param.game.game_area.rect.h / 4;
param.game.gameArea.thirdQuarterY = param.game.gameArea.rect.h / 4 * 3; param.game.game_area.third_quarter_y = param.game.game_area.rect.h / 4 * 3;
} }

View File

@@ -1,9 +1,9 @@
#pragma once #pragma once
#include <string> // for string #include <string> // for string
struct param_t; struct Param;
extern param_t param; extern Param param;
// Establece valores para los parametros a partir de un fichero de texto // Establece valores para los parametros a partir de un fichero de texto
void loadParamsFromFile(std::string filePath); void loadParamsFromFile(const std::string &file_path);

File diff suppressed because it is too large Load Diff

View File

@@ -2,76 +2,84 @@
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <SDL2/SDL_stdinc.h> // for Uint32
#include <string> // for string, basic_string #include <memory> // for unique_ptr, shared_ptr
#include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "utils.h" // for circle_t #include "animated_sprite.h" // for AnimatedSprite
class AnimatedSprite; #include "enter_name.h" // for EnterName
class EnterName; #include "utils.h" // for Circle
class Texture; class Texture;
enum class InputType : int;
enum class ScoreboardMode; // lines 12-12
// Estados del jugador // Estados del jugador
#define PLAYER_STATUS_WALKING_LEFT 0 enum class PlayerStatus
#define PLAYER_STATUS_WALKING_RIGHT 1 {
#define PLAYER_STATUS_WALKING_STOP 2 WALKING_LEFT,
WALKING_RIGHT,
WALKING_STOP,
#define PLAYER_STATUS_FIRING_UP 0 FIRING_UP,
#define PLAYER_STATUS_FIRING_LEFT 1 FIRING_LEFT,
#define PLAYER_STATUS_FIRING_RIGHT 2 FIRING_RIGHT,
#define PLAYER_STATUS_FIRING_NO 3 FIRING_NO,
#define PLAYER_STATUS_PLAYING 0 PLAYING,
#define PLAYER_STATUS_CONTINUE 1 CONTINUE,
#define PLAYER_STATUS_WAITING 2 WAITING,
#define PLAYER_STATUS_ENTERING_NAME 3 ENTERING_NAME,
#define PLAYER_STATUS_DYING 4 DYING,
#define PLAYER_STATUS_DIED 5 DIED,
GAME_OVER,
};
// Variables del jugador // Variables del jugador
#define PLAYER_INVULNERABLE_COUNTER 200 constexpr int PLAYER_INVULNERABLE_COUNTER = 200;
#define PLAYER_POWERUP_COUNTER 1500 constexpr int PLAYER_POWERUP_COUNTER = 1500;
// Clase Player // Clase Player
class Player class Player
{ {
private: private:
// Objetos y punteros // Objetos y punteros
AnimatedSprite *playerSprite; // Sprite para dibujar el jugador std::unique_ptr<AnimatedSprite> player_sprite_; // Sprite para dibujar el jugador
AnimatedSprite *powerSprite; // Sprite para dibujar el aura del jugador con el poder a tope std::unique_ptr<AnimatedSprite> power_sprite_; // Sprite para dibujar el aura del jugador con el poder a tope
SDL_Rect *playArea; // Rectangulo con la zona de juego std::unique_ptr<EnterName> enter_name_; // Clase utilizada para introducir el nombre
EnterName *enterName; SDL_Rect *play_area_; // Rectangulo con la zona de juego
// Variables // Variables
int id; // Numero de identificación para el jugador int id_; // Numero de identificación para el jugador
float posX; // Posicion en el eje X float pos_x_; // Posicion en el eje X
int posY; // Posicion en el eje Y int pos_y_; // Posicion en el eje Y
float defaultPosX; // Posición inicial para el jugador float default_pos_x_; // Posición inicial para el jugador
int defaultPosY; // Posición inicial para el jugador int default_pos_y_; // Posición inicial para el jugador
int width; // Anchura int width_; // Anchura
int height; // Altura int height_; // Altura
float velX; // Cantidad de pixeles a desplazarse en el eje X float vel_x_; // Cantidad de pixeles a desplazarse en el eje X
int velY; // Cantidad de pixeles a desplazarse en el eje Y int vel_y_; // Cantidad de pixeles a desplazarse en el eje Y
float baseSpeed; // Velocidad base del jugador float base_speed_; // Velocidad base del jugador
int cooldown; // Contador durante el cual no puede disparar int cooldown_; // Contador durante el cual no puede disparar
int score; // Puntos del jugador int score_; // Puntos del jugador
float scoreMultiplier; // Multiplicador de puntos float score_multiplier_; // Multiplicador de puntos
int statusWalking; // Estado del jugador al moverse PlayerStatus status_walking_; // Estado del jugador al moverse
int statusFiring; // Estado del jugador al disparar PlayerStatus status_firing_; // Estado del jugador al disparar
int statusPlaying; // Estado del jugador en el juego PlayerStatus status_playing_; // Estado del jugador en el juego
bool invulnerable; // Indica si el jugador es invulnerable bool invulnerable_; // Indica si el jugador es invulnerable
int invulnerableCounter; // Contador para la invulnerabilidad int invulnerable_counter_; // Contador para la invulnerabilidad
bool extraHit; // Indica si el jugador tiene un toque extra bool extra_hit_; // Indica si el jugador tiene un toque extra
int coffees; // Indica cuantos cafes lleva acumulados int coffees_; // Indica cuantos cafes lleva acumulados
bool powerUp; // Indica si el jugador tiene activo el modo PowerUp bool power_up_; // Indica si el jugador tiene activo el modo PowerUp
int powerUpCounter; // Temporizador para el modo PowerUp int power_up_counter_; // Temporizador para el modo PowerUp
int powerUpDespX; // Desplazamiento del sprite de PowerUp respecto al sprite del jugador int power_up_desp_x_; // Desplazamiento del sprite de PowerUp respecto al sprite del jugador
bool input; // Indica si puede recibir ordenes de entrada bool input_; // Indica si puede recibir ordenes de entrada
circle_t collider; // Circulo de colisión del jugador Circle collider_; // Circulo de colisión del jugador
int continueCounter; // Contador para poder continuar int continue_counter_; // Contador para poder continuar
Uint32 continueTicks; // Variable para poder cambiar el contador de continue en función del tiempo Uint32 continue_ticks_; // Variable para poder cambiar el contador de continue en función del tiempo
int scoreBoardPanel; // Panel del marcador asociado al jugador int scoreboard_panel_; // Panel del marcador asociado al jugador
std::string name; // Nombre del jugador std::string name_; // Nombre del jugador
std::string recordName; // Nombre del jugador para l atabla de mejores puntuaciones std::string record_name_; // Nombre del jugador para l atabla de mejores puntuaciones
int controllerIndex; // Indice del array de mandos que utilizará para moverse int controller_index_; // Indice del array de mandos que utilizará para moverse
bool demo_; // Para que el jugador sepa si está en el modo demostración
// Actualiza el circulo de colisión a la posición del jugador // Actualiza el circulo de colisión a la posición del jugador
void shiftColliders(); void shiftColliders();
@@ -82,12 +90,24 @@ private:
// Actualiza el contador de continue // Actualiza el contador de continue
void updateContinueCounter(); void updateContinueCounter();
// Indica si el jugador se puede dibujar
bool isRenderable() const;
// Actualiza el panel del marcador
void updateScoreboard();
// Comprueba si la puntuación entra en la tabla de mejores puntuaciones
bool IsEligibleForHighScore();
// Cambia el modo del marcador
void setScoreboardMode(ScoreboardMode mode);
public: public:
// Constructor // Constructor
Player(int id, float x, int y, SDL_Rect *playArea, std::vector<Texture *> texture, std::vector<std::vector<std::string> *> animations); Player(int id, float x, int y, bool demo, SDL_Rect *play_area, std::vector<std::shared_ptr<Texture>> texture, std::vector<std::vector<std::string> *> animations);
// Destructor // Destructor
~Player(); ~Player() = default;
// Iniciador // Iniciador
void init(); void init();
@@ -99,43 +119,43 @@ public:
void render(); void render();
// Pone las texturas del jugador // Pone las texturas del jugador
void setPlayerTextures(std::vector<Texture *> texture); void setPlayerTextures(const std::vector<std::shared_ptr<Texture>> &texture);
// Actua en consecuencia de la entrada recibida // Actua en consecuencia de la entrada recibida
void setInput(int input); void setInput(InputType input);
// Procesa inputs para cuando está jugando // Procesa inputs para cuando está jugando
void setInputPlaying(int input); void setInputPlaying(InputType input);
// Procesa inputs para cuando está introduciendo el nombre // Procesa inputs para cuando está introduciendo el nombre
void setInputEnteringName(int input); void setInputEnteringName(InputType input);
// Mueve el jugador a la posición y animación que le corresponde // Mueve el jugador a la posición y animación que le corresponde
void move(); void move();
// Establece el estado del jugador // Establece el estado del jugador
void setWalkingStatus(int status); void setWalkingStatus(PlayerStatus status);
// Establece el estado del jugador // Establece el estado del jugador
void setFiringStatus(int status); void setFiringStatus(PlayerStatus status);
// Establece la animación correspondiente al estado // Establece la animación correspondiente al estado
void setAnimation(); void setAnimation();
// Obtiene el valor de la variable // Obtiene el valor de la variable
int getPosX(); int getPosX() const;
// Obtiene el valor de la variable // Obtiene el valor de la variable
int getPosY(); int getPosY() const;
// Obtiene el valor de la variable // Obtiene el valor de la variable
int getWidth(); int getWidth() const;
// Obtiene el valor de la variable // Obtiene el valor de la variable
int getHeight(); int getHeight() const;
// Indica si el jugador puede disparar // Indica si el jugador puede disparar
bool canFire(); bool canFire() const;
// Establece el valor de la variable // Establece el valor de la variable
void setFireCooldown(int time); void setFireCooldown(int time);
@@ -144,7 +164,7 @@ public:
void updateCooldown(); void updateCooldown();
// Obtiene la puntuación del jugador // Obtiene la puntuación del jugador
int getScore(); int getScore() const;
// Asigna un valor a la puntuación del jugador // Asigna un valor a la puntuación del jugador
void setScore(int score); void setScore(int score);
@@ -153,31 +173,34 @@ public:
void addScore(int score); void addScore(int score);
// Indica si el jugador está jugando // Indica si el jugador está jugando
bool isPlaying(); bool isPlaying() const;
// Indica si el jugador está continuando // Indica si el jugador está continuando
bool isContinue(); bool isContinue() const;
// Indica si el jugador está esperando // Indica si el jugador está esperando
bool isWaiting(); bool isWaiting() const;
// Indica si el jugador está introduciendo su nombre // Indica si el jugador está introduciendo su nombre
bool isEnteringName(); bool isEnteringName() const;
// Indica si el jugador está muriendose // Indica si el jugador está muriendose
bool isDying(); bool isDying() const;
// Indica si el jugador ha terminado de morir // Indica si el jugador ha terminado de morir
bool hasDied(); bool hasDied() const;
// Indica si el jugador ya ha terminado de jugar
bool isGameOver() const;
// Establece el estado del jugador en el juego // Establece el estado del jugador en el juego
void setStatusPlaying(int value); void setStatusPlaying(PlayerStatus value);
// Obtiene el estado del jugador en el juego // Obtiene el estado del jugador en el juego
int getStatusPlaying(); PlayerStatus getStatusPlaying() const;
// Obtiene el valor de la variable // Obtiene el valor de la variable
float getScoreMultiplier(); float getScoreMultiplier() const;
// Establece el valor de la variable // Establece el valor de la variable
void setScoreMultiplier(float value); void setScoreMultiplier(float value);
@@ -189,25 +212,25 @@ public:
void decScoreMultiplier(); void decScoreMultiplier();
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool isInvulnerable(); bool isInvulnerable() const;
// Establece el valor del estado // Establece el valor del estado
void setInvulnerable(bool value); void setInvulnerable(bool value);
// Obtiene el valor de la variable // Obtiene el valor de la variable
int getInvulnerableCounter(); int getInvulnerableCounter() const;
// Establece el valor de la variable // Establece el valor de la variable
void setInvulnerableCounter(int value); void setInvulnerableCounter(int value);
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool isPowerUp(); bool isPowerUp() const;
// Establece el valor de la variable a verdadero // Establece el valor de la variable a verdadero
void setPowerUp(); void setPowerUp();
// Obtiene el valor de la variable // Obtiene el valor de la variable
int getPowerUpCounter(); int getPowerUpCounter() const;
// Establece el valor de la variable // Establece el valor de la variable
void setPowerUpCounter(int value); void setPowerUpCounter(int value);
@@ -216,7 +239,7 @@ public:
void updatePowerUpCounter(); void updatePowerUpCounter();
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool hasExtraHit(); bool hasExtraHit() const;
// Concede un toque extra al jugador // Concede un toque extra al jugador
void giveExtraHit(); void giveExtraHit();
@@ -231,44 +254,44 @@ public:
void disableInput(); void disableInput();
// Devuelve el número de cafes actuales // Devuelve el número de cafes actuales
int getCoffees(); int getCoffees() const;
// Obtiene el circulo de colisión // Obtiene el circulo de colisión
circle_t &getCollider(); Circle &getCollider();
// Obtiene el valor de la variable // Obtiene el valor de la variable
int getContinueCounter(); int getContinueCounter() const;
// Le asigna un panel en el marcador al jugador // Le asigna un panel en el marcador al jugador
void setScoreBoardPanel(int panel); void setScoreBoardPanel(int panel);
// Obtiene el valor de la variable // Obtiene el valor de la variable
int getScoreBoardPanel(); int getScoreBoardPanel() const;
// Decrementa el contador de continuar // Decrementa el contador de continuar
void decContinueCounter(); void decContinueCounter();
// Establece el nombre del jugador // Establece el nombre del jugador
void setName(std::string name); void setName(const std::string &name);
// Establece el nombre del jugador para la tabla de mejores puntuaciones // Establece el nombre del jugador para la tabla de mejores puntuaciones
void setRecordName(std::string recordName); void setRecordName(const std::string &record_name);
// Obtiene el nombre del jugador // Obtiene el nombre del jugador
std::string getName(); std::string getName() const;
// Obtiene el nombre del jugador para la tabla de mejores puntuaciones // Obtiene el nombre del jugador para la tabla de mejores puntuaciones
std::string getRecordName(); std::string getRecordName() const;
// Obtiene la posici´´on que se está editando del nombre del jugador para la tabla de mejores puntuaciones // Obtiene la posici´´on que se está editando del nombre del jugador para la tabla de mejores puntuaciones
int getRecordNamePos(); int getRecordNamePos() const;
// Establece el mando que usará para ser controlado // Establece el mando que usará para ser controlado
void setController(int index); void setController(int index);
// Obtiene el mando que usa para ser controlado // Obtiene el mando que usa para ser controlado
int getController(); int getController() const;
// Obtiene el "id" del jugador // Obtiene el "id" del jugador
int getId(); int getId() const;
}; };

View File

@@ -3,56 +3,73 @@
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <math.h> // for roundf #include <math.h> // for roundf
#include <iomanip>
#include <sstream>
#include "asset.h" // for Asset #include "asset.h" // for Asset
#include "lang.h" // for getText #include "lang.h" // for getText
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "text.h" // for Text #include "text.h" // for Text
#include "texture.h" // for Texture #include "texture.h" // for Texture
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Scoreboard *Scoreboard::scoreboard_ = nullptr;
// [SINGLETON] Crearemos el objeto score_board con esta función estática
void Scoreboard::init(SDL_Renderer *renderer)
{
Scoreboard::scoreboard_ = new Scoreboard(renderer);
}
// [SINGLETON] Destruiremos el objeto score_board con esta función estática
void Scoreboard::destroy()
{
delete Scoreboard::scoreboard_;
}
// [SINGLETON] Con este método obtenemos el objeto score_board y podemos trabajar con él
Scoreboard *Scoreboard::get()
{
return Scoreboard::scoreboard_;
}
// Constructor // Constructor
Scoreboard::Scoreboard(SDL_Renderer *renderer) Scoreboard::Scoreboard(SDL_Renderer *renderer)
: renderer_(renderer),
game_power_meter_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_power_meter.png"))),
power_meter_sprite_(std::make_unique<Sprite>(game_power_meter_texture_)),
text_scoreboard_(std::make_unique<Text>(Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), renderer)),
stage_(1),
hi_score_(0),
power_(0),
hi_score_name_(std::string()),
color_({0, 0, 0}),
rect_({0, 0, 320, 40}),
ticks_(SDL_GetTicks()),
counter_(0)
{ {
// Copia los punteros
this->renderer = renderer;
asset = Asset::get();
// Inicializa punteros
gamePowerMeterTexture = nullptr;
powerMeterSprite = nullptr;
textScoreBoard = nullptr;
// Inicializa variables // Inicializa variables
stage = 1;
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i) for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i)
{ {
name[i] = ""; name_[i].clear();
recordName[i] = ""; record_name_[i].clear();
selectorPos[i] = 0; selector_pos_[i] = 0;
score[i] = 0; score_[i] = 0;
mult[i] = 0; mult_[i] = 0;
continueCounter[i] = 0; continue_counter_[i] = 0;
} }
hiScore = 0;
power = 0; panel_[SCOREBOARD_LEFT_PANEL].mode = ScoreboardMode::SCORE;
hiScoreName = ""; panel_[SCOREBOARD_RIGHT_PANEL].mode = ScoreboardMode::SCORE;
color = {0, 0, 0}; panel_[SCOREBOARD_CENTER_PANEL].mode = ScoreboardMode::STAGE_INFO;
rect = {0, 0, 320, 40};
panel[SCOREBOARD_LEFT_PANEL].mode = SCOREBOARD_MODE_SCORE;
panel[SCOREBOARD_RIGHT_PANEL].mode = SCOREBOARD_MODE_SCORE;
panel[SCOREBOARD_CENTER_PANEL].mode = SCOREBOARD_MODE_STAGE_INFO;
ticks = SDL_GetTicks();
counter = 0;
// Recalcula las anclas de los elementos // Recalcula las anclas de los elementos
recalculateAnchors(); recalculateAnchors();
power_meter_sprite_->setPos({slot4_2_.x - 20, slot4_2_.y, 40, 7});
// Crea objetos
gamePowerMeterTexture = new Texture(renderer, asset->get("game_power_meter.png"));
powerMeterSprite = new Sprite(slot4_2.x - 20, slot4_2.y, 40, 7, gamePowerMeterTexture);
textScoreBoard = new Text(asset->get("8bithud.png"), asset->get("8bithud.txt"), renderer);
// Crea la textura de fondo // Crea la textura de fondo
background = nullptr; background_ = nullptr;
createBackgroundTexture(); createBackgroundTexture();
// Crea las texturas de los paneles // Crea las texturas de los paneles
@@ -64,15 +81,12 @@ Scoreboard::Scoreboard(SDL_Renderer *renderer)
Scoreboard::~Scoreboard() Scoreboard::~Scoreboard()
{ {
gamePowerMeterTexture->unload(); if (background_)
delete gamePowerMeterTexture;
delete powerMeterSprite;
delete textScoreBoard;
if (background)
{ {
SDL_DestroyTexture(background); SDL_DestroyTexture(background_);
} }
for (auto texture : panelTexture)
for (auto texture : panel_texture_)
{ {
if (texture) if (texture)
{ {
@@ -82,53 +96,20 @@ Scoreboard::~Scoreboard()
} }
// Transforma un valor numérico en una cadena de 6 cifras // Transforma un valor numérico en una cadena de 6 cifras
std::string Scoreboard::updateScoreText(Uint32 num) std::string Scoreboard::updateScoreText(int num)
{ {
if ((num >= 0) && (num <= 9)) std::ostringstream oss;
{ oss << std::setw(8) << std::setfill('0') << num;
return ("000000" + std::to_string(num)); return oss.str();
}
if ((num >= 10) && (num <= 99))
{
return ("00000" + std::to_string(num));
}
if ((num >= 100) && (num <= 999))
{
return ("0000" + std::to_string(num));
}
if ((num >= 1000) && (num <= 9999))
{
return ("000" + std::to_string(num));
}
if ((num >= 010000) && (num <= 99999))
{
return ("00" + std::to_string(num));
}
if ((num >= 100000) && (num <= 999999))
{
return ("0" + std::to_string(num));
}
if ((num >= 1000000) && (num <= 9999999))
{
return (std::to_string(num));
}
return (std::to_string(num));
} }
// Actualiza el contador // Actualiza el contador
void Scoreboard::updateCounter() void Scoreboard::updateCounter()
{ {
if (SDL_GetTicks() - ticks > SCOREBOARD_TICK_SPEED) if (SDL_GetTicks() - ticks_ > SCOREBOARD_TICK_SPEED)
{ {
ticks = SDL_GetTicks(); ticks_ = SDL_GetTicks();
counter++; counter_++;
} }
} }
@@ -142,80 +123,80 @@ void Scoreboard::update()
// Pinta el marcador // Pinta el marcador
void Scoreboard::render() void Scoreboard::render()
{ {
SDL_RenderCopy(renderer, background, nullptr, &rect); SDL_RenderCopy(renderer_, background_, nullptr, &rect_);
} }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setName(int panel, std::string name) void Scoreboard::setName(int panel_, const std::string &name_)
{ {
this->name[panel] = name; this->name_[panel_] = name_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setRecordName(int panel, std::string recordName) void Scoreboard::setRecordName(int panel_, const std::string &record_name_)
{ {
this->recordName[panel] = recordName; this->record_name_[panel_] = record_name_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setSelectorPos(int panel, int pos) void Scoreboard::setSelectorPos(int panel_, int pos)
{ {
selectorPos[panel] = pos; selector_pos_[panel_] = pos;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setScore(int panel, int score) void Scoreboard::setScore(int panel_, int score_)
{ {
this->score[panel] = score; this->score_[panel_] = score_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setMult(int panel, float mult) void Scoreboard::setMult(int panel_, float mult_)
{ {
this->mult[panel] = mult; this->mult_[panel_] = mult_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setContinue(int panel, int value) void Scoreboard::setContinue(int panel_, int value)
{ {
continueCounter[panel] = value; continue_counter_[panel_] = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setStage(int stage) void Scoreboard::setStage(int stage_)
{ {
this->stage = stage; this->stage_ = stage_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setHiScore(int hiScore) void Scoreboard::setHiScore(int hi_score_)
{ {
this->hiScore = hiScore; this->hi_score_ = hi_score_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setPower(float power) void Scoreboard::setPower(float power_)
{ {
this->power = power; this->power_ = power_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setHiScoreName(std::string name) void Scoreboard::setHiScoreName(const std::string &name_)
{ {
hiScoreName = name; hi_score_name_ = name_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setColor(color_t color) void Scoreboard::setColor(Color color_)
{ {
this->color = color; this->color_ = color_;
fillBackgroundTexture(); fillBackgroundTexture();
} }
// Establece el valor de la variable // Establece el valor de la variable
void Scoreboard::setPos(SDL_Rect rect) void Scoreboard::setPos(SDL_Rect rect_)
{ {
this->rect = rect; this->rect_ = rect_;
// Recalcula las anclas de los elementos // Recalcula las anclas de los elementos
recalculateAnchors(); recalculateAnchors();
@@ -234,97 +215,127 @@ void Scoreboard::setPos(SDL_Rect rect)
void Scoreboard::fillPanelTextures() void Scoreboard::fillPanelTextures()
{ {
// Guarda a donde apunta actualmente el renderizador // Guarda a donde apunta actualmente el renderizador
SDL_Texture *temp = SDL_GetRenderTarget(renderer); SDL_Texture *temp = SDL_GetRenderTarget(renderer_);
// Genera el contenidoi de cada panel // Genera el contenidoi de cada panel_
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i) for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i)
{ {
// Cambia el destino del renderizador // Cambia el destino del renderizador
SDL_SetRenderTarget(renderer, panelTexture[i]); SDL_SetRenderTarget(renderer_, panel_texture_[i]);
// Dibuja el fondo de la textura // Dibuja el fondo de la textura
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0); SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
switch (panel[i].mode) switch (panel_[i].mode)
{
case ScoreboardMode::SCORE:
{ {
case SCOREBOARD_MODE_SCORE:
// SCORE // SCORE
textScoreBoard->writeCentered(slot4_1.x, slot4_1.y, name[i]); text_scoreboard_->writeCentered(slot4_1_.x, slot4_1_.y, name_[i]);
textScoreBoard->writeCentered(slot4_2.x, slot4_2.y, updateScoreText(score[i])); text_scoreboard_->writeCentered(slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]));
// MULT // MULT
textScoreBoard->writeCentered(slot4_3.x, slot4_3.y, lang::getText(55)); text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y, lang::getText(55));
textScoreBoard->writeCentered(slot4_4.x, slot4_4.y, std::to_string(mult[i]).substr(0, 3)); text_scoreboard_->writeCentered(slot4_4_.x, slot4_4_.y, std::to_string(mult_[i]).substr(0, 3));
break; break;
}
case SCOREBOARD_MODE_DEMO: case ScoreboardMode::DEMO:
textScoreBoard->writeCentered(slot4_1.x, slot4_1.y + 4, lang::getText(101));
if (counter % 10 < 8)
{ {
textScoreBoard->writeCentered(slot4_3.x, slot4_3.y - 2, lang::getText(103)); // DEMO MODE
textScoreBoard->writeCentered(slot4_4.x, slot4_4.y - 2, lang::getText(104)); text_scoreboard_->writeCentered(slot4_1_.x, slot4_1_.y + 4, lang::getText(101));
// PRESS START TO PLAY
if (counter_ % 10 < 8)
{
text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y - 2, lang::getText(103));
text_scoreboard_->writeCentered(slot4_4_.x, slot4_4_.y - 2, lang::getText(104));
} }
break; break;
}
case SCOREBOARD_MODE_GAME_OVER: case ScoreboardMode::WAITING:
textScoreBoard->writeCentered(slot4_1.x, slot4_1.y + 4, lang::getText(102));
if (counter % 10 < 8)
{ {
textScoreBoard->writeCentered(slot4_3.x, slot4_3.y - 2, lang::getText(103)); // GAME OVER
textScoreBoard->writeCentered(slot4_4.x, slot4_4.y - 2, lang::getText(104)); text_scoreboard_->writeCentered(slot4_1_.x, slot4_1_.y + 4, lang::getText(102));
// PRESS START TO PLAY
if (counter_ % 10 < 8)
{
text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y - 2, lang::getText(103));
text_scoreboard_->writeCentered(slot4_4_.x, slot4_4_.y - 2, lang::getText(104));
} }
break; break;
}
case SCOREBOARD_MODE_STAGE_INFO: case ScoreboardMode::GAME_OVER:
{
// GAME OVER
text_scoreboard_->writeCentered(slot4_1_.x, slot4_1_.y + 4, lang::getText(102));
// PLEASE WAIT
if (counter_ % 10 < 8)
{
text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y - 2, lang::getText(114));
text_scoreboard_->writeCentered(slot4_4_.x, slot4_4_.y - 2, lang::getText(115));
}
break;
}
case ScoreboardMode::STAGE_INFO:
{
// STAGE // STAGE
textScoreBoard->writeCentered(slot4_1.x, slot4_1.y, lang::getText(57) + std::to_string(stage)); text_scoreboard_->writeCentered(slot4_1_.x, slot4_1_.y, lang::getText(57) + std::to_string(stage_));
// POWERMETER // POWERMETER
powerMeterSprite->setSpriteClip(0, 0, 40, 7); power_meter_sprite_->setSpriteClip(0, 0, 40, 7);
powerMeterSprite->render(); power_meter_sprite_->render();
powerMeterSprite->setSpriteClip(40, 0, int(power * 40.0f), 7); power_meter_sprite_->setSpriteClip(40, 0, int(power_ * 40.0f), 7);
powerMeterSprite->render(); power_meter_sprite_->render();
// HI-SCORE // HI-SCORE
textScoreBoard->writeCentered(slot4_3.x, slot4_3.y, lang::getText(56)); text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y, lang::getText(56));
textScoreBoard->writeCentered(slot4_4.x, slot4_4.y, hiScoreName + " - " + updateScoreText(hiScore)); text_scoreboard_->writeCentered(slot4_4_.x, slot4_4_.y, hi_score_name_ + " - " + updateScoreText(hi_score_));
break; break;
}
case SCOREBOARD_MODE_CONTINUE: case ScoreboardMode::CONTINUE:
{
// SCORE // SCORE
textScoreBoard->writeCentered(slot4_1.x, slot4_1.y, name[i]); text_scoreboard_->writeCentered(slot4_1_.x, slot4_1_.y, name_[i]);
textScoreBoard->writeCentered(slot4_2.x, slot4_2.y, updateScoreText(score[i])); text_scoreboard_->writeCentered(slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]));
// CONTINUE // CONTINUE
textScoreBoard->writeCentered(slot4_3.x, slot4_3.y, lang::getText(105)); text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y, lang::getText(105));
textScoreBoard->writeCentered(slot4_4.x, slot4_4.y, std::to_string(continueCounter[i])); text_scoreboard_->writeCentered(slot4_4_.x, slot4_4_.y, std::to_string(continue_counter_[i]));
break; break;
}
case SCOREBOARD_MODE_ENTER_NAME: case ScoreboardMode::ENTER_NAME:
{ {
// SCORE // SCORE
textScoreBoard->writeCentered(slot4_1.x, slot4_1.y, name[i]); text_scoreboard_->writeCentered(slot4_1_.x, slot4_1_.y, name_[i]);
textScoreBoard->writeCentered(slot4_2.x, slot4_2.y, updateScoreText(score[i])); text_scoreboard_->writeCentered(slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]));
// ENTER NAME // ENTER NAME
textScoreBoard->writeCentered(slot4_3.x, slot4_3.y, lang::getText(106)); text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y, lang::getText(106));
SDL_Rect rect = {enterNamePos.x, enterNamePos.y, 5, 7}; SDL_Rect rect = {enter_name_pos_.x, enter_name_pos_.y, 5, 7};
SDL_SetRenderDrawColor(renderer, 0xFF, 0xFF, 0xEB, 255); SDL_SetRenderDrawColor(renderer_, 0xFF, 0xFF, 0xEB, 255);
for (int j = 0; j < (int)recordName[i].size(); ++j) for (int j = 0; j < (int)record_name_[i].size(); ++j)
{ {
if (j == selectorPos[i]) if (j == selector_pos_[i])
{ // La letra seleccionada se pinta de forma intermitente { // La letra seleccionada se pinta de forma intermitente
if (counter % 3 > 0) if (counter_ % 3 > 0)
{ {
SDL_RenderDrawLine(renderer, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h); SDL_RenderDrawLine(renderer_, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h);
textScoreBoard->write(rect.x, rect.y, recordName[i].substr(j, 1)); text_scoreboard_->write(rect.x, rect.y, record_name_[i].substr(j, 1));
} }
} }
else else
{ {
SDL_RenderDrawLine(renderer, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h); SDL_RenderDrawLine(renderer_, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h);
textScoreBoard->write(rect.x, rect.y, recordName[i].substr(j, 1)); text_scoreboard_->write(rect.x, rect.y, record_name_[i].substr(j, 1));
} }
rect.x += 7; rect.x += 7;
} }
@@ -337,7 +348,7 @@ void Scoreboard::fillPanelTextures()
} }
// Deja el renderizador apuntando donde estaba // Deja el renderizador apuntando donde estaba
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
} }
// Rellena la textura de fondo // Rellena la textura de fondo
@@ -347,41 +358,41 @@ void Scoreboard::fillBackgroundTexture()
fillPanelTextures(); fillPanelTextures();
// Cambia el destino del renderizador // Cambia el destino del renderizador
SDL_Texture *temp = SDL_GetRenderTarget(renderer); SDL_Texture *temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer, background); SDL_SetRenderTarget(renderer_, background_);
// Dibuja el fondo del marcador // Dibuja el fondo del marcador
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 255); SDL_SetRenderDrawColor(renderer_, color_.r, color_.g, color_.b, 255);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
// Copia las texturas de los paneles // Copia las texturas de los paneles
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i) for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i)
{ {
SDL_RenderCopy(renderer, panelTexture[i], nullptr, &panel[i].pos); SDL_RenderCopy(renderer_, panel_texture_[i], nullptr, &panel_[i].pos);
} }
// Dibuja la linea que separa la zona de juego del marcador // Dibuja la linea que separa la zona de juego del marcador
renderSeparator(); renderSeparator();
// Deja el renderizador apuntando donde estaba // Deja el renderizador apuntando donde estaba
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
} }
// Recalcula las anclas de los elementos // Recalcula las anclas de los elementos
void Scoreboard::recalculateAnchors() void Scoreboard::recalculateAnchors()
{ {
// Recalcula la posición y el tamaño de los paneles // Recalcula la posición y el tamaño de los paneles
const float panelWidth = (float)rect.w / (float)SCOREBOARD_MAX_PANELS; const float panelWidth = (float)rect_.w / (float)SCOREBOARD_MAX_PANELS;
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i) for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i)
{ {
panel[i].pos.x = roundf(panelWidth * i); panel_[i].pos.x = roundf(panelWidth * i);
panel[i].pos.y = 0; panel_[i].pos.y = 0;
panel[i].pos.w = roundf(panelWidth * (i + 1)) - panel[i].pos.x; panel_[i].pos.w = roundf(panelWidth * (i + 1)) - panel_[i].pos.x;
panel[i].pos.h = rect.h; panel_[i].pos.h = rect_.h;
} }
// Constantes para definir las zonas del panel: 4 filas y 1 columna // Constantes para definir las zonas del panel_: 4 filas y 1 columna
const int rowSize = rect.h / 4; const int rowSize = rect_.h / 4;
const int textHeight = 7; const int textHeight = 7;
// Filas // Filas
@@ -394,63 +405,63 @@ void Scoreboard::recalculateAnchors()
const int col = panelWidth / 2; const int col = panelWidth / 2;
// Slots de 4 // Slots de 4
slot4_1 = {col, row1}; slot4_1_ = {col, row1};
slot4_2 = {col, row2}; slot4_2_ = {col, row2};
slot4_3 = {col, row3}; slot4_3_ = {col, row3};
slot4_4 = {col, row4}; slot4_4_ = {col, row4};
// Primer cuadrado para poner el nombre de record // Primer cuadrado para poner el nombre de record
const int enterNameLenght = 8 * 7; const int enterNameLenght = 8 * 7;
enterNamePos.x = (panelWidth - enterNameLenght) / 2; enter_name_pos_.x = (panelWidth - enterNameLenght) / 2;
enterNamePos.y = row4; enter_name_pos_.y = row4;
// Recoloca los sprites // Recoloca los sprites
if (powerMeterSprite) if (power_meter_sprite_)
{ {
powerMeterSprite->setPosX(slot4_2.x - 20); power_meter_sprite_->setPosX(slot4_2_.x - 20);
powerMeterSprite->setPosY(slot4_2.y); power_meter_sprite_->setPosY(slot4_2_.y);
} }
} }
// Establece el modo del marcador // Establece el modo del marcador
void Scoreboard::setMode(int index, scoreboard_modes_e mode) void Scoreboard::setMode(int index, ScoreboardMode mode)
{ {
panel[index].mode = mode; panel_[index].mode = mode;
} }
// Crea la textura de fondo // Crea la textura de fondo
void Scoreboard::createBackgroundTexture() void Scoreboard::createBackgroundTexture()
{ {
// Elimina la textura en caso de existir // Elimina la textura en caso de existir
if (background) if (background_)
{ {
SDL_DestroyTexture(background); SDL_DestroyTexture(background_);
} }
// Recrea la textura de fondo // Recrea la textura de fondo
background = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect.w, rect.h); background_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(background, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(background_, SDL_BLENDMODE_BLEND);
} }
// Crea las texturas de los paneles // Crea las texturas de los paneles
void Scoreboard::createPanelTextures() void Scoreboard::createPanelTextures()
{ {
// Elimina las texturas en caso de existir // Elimina las texturas en caso de existir
for (auto texture : panelTexture) for (auto texture : panel_texture_)
{ {
if (texture != nullptr) if (texture != nullptr)
{ {
SDL_DestroyTexture(texture); SDL_DestroyTexture(texture);
} }
} }
panelTexture.clear(); panel_texture_.clear();
// Crea las texturas para cada panel // Crea las texturas para cada panel_
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i) for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i)
{ {
SDL_Texture *tex = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, panel[i].pos.w, panel[i].pos.h); SDL_Texture *tex = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, panel_[i].pos.w, panel_[i].pos.h);
SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND);
panelTexture.push_back(tex); panel_texture_.push_back(tex);
} }
} }
@@ -458,6 +469,6 @@ void Scoreboard::createPanelTextures()
void Scoreboard::renderSeparator() void Scoreboard::renderSeparator()
{ {
// Dibuja la linea que separa el marcador de la zona de juego // Dibuja la linea que separa el marcador de la zona de juego
SDL_SetRenderDrawColor(renderer, separatorColor.r, separatorColor.g, separatorColor.b, 255); SDL_SetRenderDrawColor(renderer_, separator_color.r, separator_color.g, separator_color.b, 255);
SDL_RenderDrawLine(renderer, 0, 0, rect.w, 0); SDL_RenderDrawLine(renderer_, 0, 0, rect_.w, 0);
} }

View File

@@ -3,38 +3,38 @@
#include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <SDL2/SDL_stdinc.h> // for Uint32
#include <string> // for string, basic_string #include <memory> // for unique_ptr, shared_ptr
#include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "utils.h" // for color_t #include "utils.h" // for Color
class Asset;
class Sprite; class Sprite;
class Text; class Text;
class Texture; class Texture;
// Defines // Defines
#define SCOREBOARD_LEFT_PANEL 0 constexpr int SCOREBOARD_LEFT_PANEL = 0;
#define SCOREBOARD_CENTER_PANEL 1 constexpr int SCOREBOARD_CENTER_PANEL = 1;
#define SCOREBOARD_RIGHT_PANEL 2 constexpr int SCOREBOARD_RIGHT_PANEL = 2;
#define SCOREBOARD_MAX_PANELS 3 constexpr int SCOREBOARD_MAX_PANELS = 3;
constexpr int SCOREBOARD_TICK_SPEED = 100;
#define SCOREBOARD_TICK_SPEED 100
// Enums // Enums
enum scoreboard_modes_e enum class ScoreboardMode : int
{ {
SCOREBOARD_MODE_SCORE, SCORE,
SCOREBOARD_MODE_STAGE_INFO, STAGE_INFO,
SCOREBOARD_MODE_CONTINUE, CONTINUE,
SCOREBOARD_MODE_GAME_OVER, WAITING,
SCOREBOARD_MODE_DEMO, GAME_OVER,
SCOREBOARD_MODE_ENTER_NAME, DEMO,
SCOREBOARD_MODE_NUM_MODES, ENTER_NAME,
NUM_MODES,
}; };
// Structs // Structs
struct panel_t struct Panel
{ {
scoreboard_modes_e mode; // Modo en el que se encuentra el panel ScoreboardMode mode; // Modo en el que se encuentra el panel
SDL_Rect pos; // Posición donde dibujar el panel dentro del marcador SDL_Rect pos; // Posición donde dibujar el panel dentro del marcador
}; };
@@ -42,41 +42,45 @@ struct panel_t
class Scoreboard class Scoreboard
{ {
private: private:
// [SINGLETON] Objeto scoreboard privado para Don Melitón
static Scoreboard *scoreboard_;
// Objetos y punteros // Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
Asset *asset; // Objeto que gestiona todos los ficheros de recursos
Texture *gamePowerMeterTexture; // Textura con el marcador de poder de la fase std::shared_ptr<Texture> game_power_meter_texture_; // Textura con el marcador de poder de la fase
Sprite *powerMeterSprite; // Sprite para el medidor de poder de la fase std::unique_ptr<Sprite> power_meter_sprite_; // Sprite para el medidor de poder de la fase
Text *textScoreBoard; // Fuente para el marcador del juego std::unique_ptr<Text> text_scoreboard_; // Fuente para el marcador del juego
SDL_Texture *background; // Textura para dibujar el marcador
std::vector<SDL_Texture *> panelTexture; // Texturas para dibujar cada panel; SDL_Texture *background_; // Textura para dibujar el marcador
std::vector<SDL_Texture *> panel_texture_; // Texturas para dibujar cada panel
// Variables // Variables
int stage; // Número de fase actual std::string name_[SCOREBOARD_MAX_PANELS]; // Nom de cada jugador
std::string name[SCOREBOARD_MAX_PANELS]; // Nom de cada jugador std::string record_name_[SCOREBOARD_MAX_PANELS]; // Nombre introducido para la tabla de records
std::string recordName[SCOREBOARD_MAX_PANELS]; // Nombre introducido para la tabla de records int selector_pos_[SCOREBOARD_MAX_PANELS]; // Posición del selector de letra para introducir el nombre
int selectorPos[SCOREBOARD_MAX_PANELS]; // Posición del selector de letra para introducir el nombre int score_[SCOREBOARD_MAX_PANELS]; // Puntuación de los jugadores
int score[SCOREBOARD_MAX_PANELS]; // Puntuación de los jugadores float mult_[SCOREBOARD_MAX_PANELS]; // Multiplicador de los jugadores
float mult[SCOREBOARD_MAX_PANELS]; // Multiplicador de los jugadores int continue_counter_[SCOREBOARD_MAX_PANELS]; // Tiempo para continuar de los jugadores
int continueCounter[SCOREBOARD_MAX_PANELS]; // Tiempo para continuar de los jugadores Panel panel_[SCOREBOARD_MAX_PANELS]; // Lista con todos los paneles del marcador
int hiScore; // Máxima puntuación int stage_; // Número de fase actual
float power; // Poder actual de la fase int hi_score_; // Máxima puntuación
std::string hiScoreName; // Nombre del jugador con la máxima puntuación float power_; // Poder actual de la fase
color_t color; // Color del marcador std::string hi_score_name_; // Nombre del jugador con la máxima puntuación
SDL_Rect rect; // Posición y dimensiones del marcador Color color_; // Color del marcador
panel_t panel[SCOREBOARD_MAX_PANELS]; // Lista con todos los paneles del marcador SDL_Rect rect_; // Posición y dimensiones del marcador
Uint32 ticks; // Variable donde almacenar el valor de SDL_GetTiks() Uint32 ticks_; // Variable donde almacenar el valor de SDL_GetTiks()
int counter; // Contador int counter_; // Contador
// Puntos predefinidos para colocar elementos en los paneles // Puntos predefinidos para colocar elementos en los paneles
SDL_Point slot4_1, slot4_2, slot4_3, slot4_4; SDL_Point slot4_1_, slot4_2_, slot4_3_, slot4_4_;
SDL_Point enterNamePos; SDL_Point enter_name_pos_;
// Recalcula las anclas de los elementos // Recalcula las anclas de los elementos
void recalculateAnchors(); void recalculateAnchors();
// Transforma un valor numérico en una cadena de 6 cifras // Transforma un valor numérico en una cadena de 6 cifras
std::string updateScoreText(Uint32 num); std::string updateScoreText(int num);
// Crea la textura de fondo // Crea la textura de fondo
void createBackgroundTexture(); void createBackgroundTexture();
@@ -96,13 +100,24 @@ private:
// Dibuja la linea que separa la zona de juego del marcador // Dibuja la linea que separa la zona de juego del marcador
void renderSeparator(); void renderSeparator();
public: // [SINGLETON] Ahora el constructor y el destructor son privados
// Constructor // Constructor
Scoreboard(SDL_Renderer *renderer); explicit Scoreboard(SDL_Renderer *renderer);
// Destructor // Destructor
~Scoreboard(); ~Scoreboard();
public:
// [SINGLETON] Crearemos el objeto scoreboard con esta función estática
static void init(SDL_Renderer *renderer);
// [SINGLETON] Destruiremos el objeto scoreboard con esta función estática
static void destroy();
// [SINGLETON] Con este método obtenemos el objeto scoreboard y podemos trabajar con él
static Scoreboard *get();
// Actualiza la lógica del marcador // Actualiza la lógica del marcador
void update(); void update();
@@ -110,10 +125,10 @@ public:
void render(); void render();
// Establece el valor de la variable // Establece el valor de la variable
void setName(int panel, std::string name); void setName(int panel, const std::string &name);
// Establece el valor de la variable // Establece el valor de la variable
void setRecordName(int panel, std::string recordName); void setRecordName(int panel, const std::string &record_name);
// Establece el valor de la variable // Establece el valor de la variable
void setSelectorPos(int panel, int pos); void setSelectorPos(int panel, int pos);
@@ -131,20 +146,20 @@ public:
void setStage(int stage); void setStage(int stage);
// Establece el valor de la variable // Establece el valor de la variable
void setHiScore(int hiScore); void setHiScore(int hi_score);
// Establece el valor de la variable // Establece el valor de la variable
void setPower(float power); void setPower(float power);
// Establece el valor de la variable // Establece el valor de la variable
void setHiScoreName(std::string name); void setHiScoreName(const std::string &name);
// Establece el valor de la variable // Establece el valor de la variable
void setColor(color_t color); void setColor(Color color);
// Establece el valor de la variable // Establece el valor de la variable
void setPos(SDL_Rect rect); void setPos(SDL_Rect rect);
// Establece el modo del marcador // Establece el modo del marcador
void setMode(int index, scoreboard_modes_e mode); void setMode(int index, ScoreboardMode mode);
}; };

View File

@@ -7,115 +7,112 @@
#include <fstream> // for basic_ifstream, ifstream #include <fstream> // for basic_ifstream, ifstream
#include <iterator> // for istreambuf_iterator, operator!= #include <iterator> // for istreambuf_iterator, operator!=
#include <string> // for basic_string, operator+, to_string, cha... #include <string> // for basic_string, operator+, to_string, cha...
#include <vector> // for vector
#include "asset.h" // for Asset #include "asset.h" // for Asset
#include "dbgtxt.h" // for dbg_print #include "dbgtxt.h" // for dbg_print
#include "global_inputs.h" // for servicePressedCounter
#include "input.h" // for Input, inputs_e, INPUT_DO_NOT_ALLOW_REPEAT #include "input.h" // for Input, inputs_e, INPUT_DO_NOT_ALLOW_REPEAT
#include "notify.h" // for Notify #include "notify.h" // for Notify
#include "on_screen_help.h" // for OnScreenHelp
#include "options.h" // for options #include "options.h" // for options
#include "on_screen_help.h" #include "param.h" // for param
#ifndef NO_SHADERS #ifndef NO_SHADERS
#include "jail_shader.h" // for init, render #include "jail_shader.h" // for init, render
#endif #endif
// [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
Screen *Screen::screen = nullptr; Screen *Screen::screen_ = nullptr;
// [SINGLETON] Crearemos el objeto screen con esta función estática // [SINGLETON] Crearemos el objeto screen con esta función estática
void Screen::init(SDL_Window *window, SDL_Renderer *renderer) void Screen::init(SDL_Window *window, SDL_Renderer *renderer)
{ {
Screen::screen = new Screen(window, renderer); Screen::screen_ = new Screen(window, renderer);
} }
// [SINGLETON] Destruiremos el objeto screen con esta función estática // [SINGLETON] Destruiremos el objeto screen con esta función estática
void Screen::destroy() void Screen::destroy()
{ {
delete Screen::screen; delete Screen::screen_;
} }
// [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
Screen *Screen::get() Screen *Screen::get()
{ {
return Screen::screen; return Screen::screen_;
} }
// Constructor // Constructor
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer) : window(window), renderer(renderer) Screen::Screen(SDL_Window *window, SDL_Renderer *renderer)
{ : window_(window),
// Copia punteros renderer_(renderer),
input = Input::get();
asset = Asset::get();
// Inicializa variables notify_(std::make_unique<Notify>(renderer_, std::string(), Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), Asset::get()->get("notify.wav"))),
SDL_GetRendererOutputSize(renderer, &windowWidth, &windowHeight); game_canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
gameCanvasWidth = options.video.gameWidth; shader_canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
gameCanvasHeight = options.video.gameHeight;
dest = {0, 0, 0, 0}; src_rect_({0, 0, param.game.width, param.game.height}),
borderColor = {0, 0, 0}; dst_rect_({0, 0, param.game.width, param.game.height}),
flashEffect.enabled = false; border_color_({0x00, 0x00, 0x00}),
flashEffect.counter = 0; attenuate_effect_(false),
flashEffect.lenght = 0; fps_ticks_(0),
flashEffect.color = {0xFF, 0xFF, 0xFF}; fps_counter_(0),
shakeEffect.desp = 1; fps_(0),
shakeEffect.delay = 3;
shakeEffect.counter = 0;
shakeEffect.lenght = 8;
shakeEffect.remaining = 0;
shakeEffect.origin = 0;
attenuateEffect = false;
fpsTicks = 0;
fpsCounter = 0;
fps = 0;
#ifdef DEBUG #ifdef DEBUG
showInfo = false; show_info_(true)
#else #else
showInfo = false; show_info_(false)
#endif #endif
{
// Inicializa variables
flash_effect_.enabled = false;
flash_effect_.counter = 0;
flash_effect_.lenght = 0;
flash_effect_.color = {0xFF, 0xFF, 0xFF};
shake_effect_.enabled = false;
shake_effect_.desp = 2;
shake_effect_.delay = 3;
shake_effect_.counter = 0;
shake_effect_.lenght = 8;
shake_effect_.remaining = 0;
shake_effect_.originalPos = 0;
shake_effect_.originalWidth = param.game.width;
SDL_DisplayMode DM; SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode(0, &DM); SDL_GetCurrentDisplayMode(0, &DM);
infoResolution = std::to_string(DM.w) + " X " + std::to_string(DM.h) + " AT " + std::to_string(DM.refresh_rate) + " HZ"; info_resolution_ = std::to_string(DM.w) + " X " + std::to_string(DM.h) + " AT " + std::to_string(DM.refresh_rate) + " HZ";
// Crea los objetos
notify = new Notify(renderer, "", asset->get("8bithud.png"), asset->get("8bithud.txt"), asset->get("notify.wav"));
// Define el color del borde para el modo de pantalla completa
borderColor = {0x00, 0x00, 0x00};
// Crea la textura donde se dibujan los graficos del juego
gameCanvas = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, gameCanvasWidth, gameCanvasHeight);
// Establece el modo de video // Establece el modo de video
setVideoMode(options.video.mode); setVideoMode(options.video.mode);
// Muestra la ventana // Muestra la ventana
SDL_ShowWindow(window); SDL_ShowWindow(window_);
} }
// Destructor // Destructor
Screen::~Screen() Screen::~Screen()
{ {
delete notify; SDL_DestroyTexture(game_canvas_);
SDL_DestroyTexture(gameCanvas); SDL_DestroyTexture(shader_canvas_);
} }
// Limpia la pantalla // Limpia la pantalla
void Screen::clean(color_t color) void Screen::clean(Color color)
{ {
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 0xFF); SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 0xFF);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
} }
// Prepara para empezar a dibujar en la textura de juego // Prepara para empezar a dibujar en la textura de juego
void Screen::start() void Screen::start()
{ {
SDL_SetRenderTarget(renderer, gameCanvas); SDL_SetRenderTarget(renderer_, game_canvas_);
} }
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
void Screen::blit() void Screen::blit()
{ {
// Actualiza el contador de FPS // Actualiza el contador de FPS
fpsCounter++; fps_counter_++;
// Actualiza y dibuja el efecto de flash en la pantalla // Actualiza y dibuja el efecto de flash en la pantalla
doFlash(); doFlash();
@@ -130,57 +127,70 @@ void Screen::blit()
displayInfo(); displayInfo();
// Muestra las notificaciones // Muestra las notificaciones
notify->render(); notify_->render();
#ifdef NO_SHADERS #ifdef NO_SHADERS
// Vuelve a dejar el renderizador en modo normal // Vuelve a dejar el renderizador en modo normal
SDL_SetRenderTarget(renderer, nullptr); SDL_SetRenderTarget(renderer_, nullptr);
// Borra el contenido previo // Borra el contenido previo
SDL_SetRenderDrawColor(renderer, borderColor.r, borderColor.g, borderColor.b, 0xFF); SDL_SetRenderDrawColor(renderer_, border_color_.r, border_color_.g, border_color_.b, 0xFF);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
// Copia la textura de juego en el renderizador en la posición adecuada // Copia la textura de juego en el renderizador en la posición adecuada
SDL_RenderCopy(renderer, gameCanvas, nullptr, &dest); if (shake_effect_.enabled)
SDL_RenderCopy(renderer_, game_canvas_, nullptr, nullptr);
SDL_RenderCopy(renderer_, game_canvas_, &src_rect_, &dst_rect_);
// Muestra por pantalla el renderizador // Muestra por pantalla el renderizador
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer_);
#else #else
if (options.video.shaders) if (options.video.shaders)
{ {
SDL_SetRenderTarget(renderer_, shader_canvas_);
SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
SDL_RenderClear(renderer_);
if (shake_effect_.enabled)
SDL_RenderCopy(renderer_, game_canvas_, nullptr, nullptr);
SDL_RenderCopy(renderer_, game_canvas_, &src_rect_, &dst_rect_);
SDL_SetRenderTarget(renderer_, nullptr);
shader::render(); shader::render();
} }
else else
{ {
// Vuelve a dejar el renderizador en modo normal // Vuelve a dejar el renderizador en modo normal
SDL_SetRenderTarget(renderer, nullptr); SDL_SetRenderTarget(renderer_, nullptr);
// Borra el contenido previo // Borra el render
SDL_SetRenderDrawColor(renderer, borderColor.r, borderColor.g, borderColor.b, 0xFF); SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
// Copia la textura de juego en el renderizador en la posición adecuada // Copia la textura de juego en el renderizador en la posición adecuada
SDL_RenderCopy(renderer, gameCanvas, nullptr, &dest); if (shake_effect_.enabled)
SDL_RenderCopy(renderer_, game_canvas_, nullptr, nullptr);
SDL_RenderCopy(renderer_, game_canvas_, &src_rect_, &dst_rect_);
// Muestra por pantalla el renderizador // Muestra por pantalla el renderizador
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer_);
} }
#endif #endif
} }
// Establece el modo de video // Establece el modo de video
void Screen::setVideoMode(int videoMode) void Screen::setVideoMode(ScreenVideoMode videoMode)
{ {
#ifdef ARCADE #ifdef ARCADE
videoMode = SCREEN_VIDEO_MODE_WINDOW; options.video.mode = ScreenVideoMode::WINDOW;
// videoMode = SCREEN_VIDEO_MODE_FULLSCREEN; #else
options.video.mode = videoMode;
#endif #endif
// Si está activo el modo ventana quita el borde switch (options.video.mode)
if (videoMode == SCREEN_VIDEO_MODE_WINDOW)
{ {
// Aplica el modo de video case ScreenVideoMode::WINDOW:
SDL_SetWindowFullscreen(window, 0); {
// Cambia a modo de ventana
SDL_SetWindowFullscreen(window_, 0);
#ifdef ARCADE #ifdef ARCADE
// Oculta el puntero // Oculta el puntero
@@ -189,117 +199,45 @@ void Screen::setVideoMode(int videoMode)
// Muestra el puntero // Muestra el puntero
SDL_ShowCursor(SDL_ENABLE); SDL_ShowCursor(SDL_ENABLE);
#endif #endif
windowWidth = gameCanvasWidth;
windowHeight = gameCanvasHeight;
dest = {0, 0, windowWidth, windowHeight};
// Modifica el tamaño de la ventana // Modifica el tamaño de la ventana
SDL_SetWindowSize(window, windowWidth * options.video.window.size, windowHeight * options.video.window.size); SDL_SetWindowSize(window_, param.game.width * options.video.window.size, param.game.height * options.video.window.size);
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); SDL_SetWindowPosition(window_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
break;
} }
// Si está activo el modo de pantalla completa añade el borde // Si está activo el modo de pantalla completa añade el borde
else if (videoMode == SCREEN_VIDEO_MODE_FULLSCREEN) case ScreenVideoMode::FULLSCREEN:
{ {
// Aplica el modo de video // Aplica el modo de video
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); SDL_SetWindowFullscreen(window_, SDL_WINDOW_FULLSCREEN_DESKTOP);
#ifdef ARCADE
/*SDL_DisplayMode DM;
DM.w = 1024;
DM.h = 600;
DM.refresh_rate = 60;
if (!SDL_SetWindowDisplayMode(window, &DM))
{
std::cout << SDL_GetError() << std::endl;
}
else
{
std::cout << "Changed windows display mode" << std::endl;
}*/
#endif
// Oculta el puntero // Oculta el puntero
SDL_ShowCursor(SDL_DISABLE); SDL_ShowCursor(SDL_DISABLE);
// Obten el alto y el ancho de la ventana break;
// SDL_GetWindowSize(window, &windowWidth, &windowHeight);
// Aplica el escalado al rectangulo donde se pinta la textura del juego
if (options.video.integerScale)
{
// Calcula el tamaño de la escala máxima
int scale = 0;
while (((gameCanvasWidth * (scale + 1)) <= windowWidth) && ((gameCanvasHeight * (scale + 1)) <= windowHeight))
{
scale++;
} }
dest.w = gameCanvasWidth * scale; default:
dest.h = gameCanvasHeight * scale; break;
dest.x = (windowWidth - dest.w) / 2;
dest.y = (windowHeight - dest.h) / 2;
}
else if (options.video.keepAspect)
{
float ratio = (float)gameCanvasWidth / (float)gameCanvasHeight;
if ((windowWidth - gameCanvasWidth) >= (windowHeight - gameCanvasHeight))
{
dest.h = windowHeight;
dest.w = (int)((windowHeight * ratio) + 0.5f);
dest.x = (windowWidth - dest.w) / 2;
dest.y = (windowHeight - dest.h) / 2;
}
else
{
dest.w = windowWidth;
dest.h = (int)((windowWidth / ratio) + 0.5f);
dest.x = (windowWidth - dest.w) / 2;
dest.y = (windowHeight - dest.h) / 2;
}
}
else
{
// dest = {0, 0, windowWidth, windowHeight};
dest = {0, 0, gameCanvasWidth, gameCanvasHeight};
}
} }
#ifdef NO_SHADERS
// El renderizador pasa a tener el tamaño de la pantalla en fullscreen o del juego en modo ventana
SDL_RenderSetLogicalSize(renderer, windowWidth, windowHeight);
#else
// Reinicia los shaders // Reinicia los shaders
if (options.video.shaders) if (options.video.shaders)
{ {
std::ifstream f(asset->get("crtpi.glsl").c_str()); #ifndef NO_SHADERS
std::ifstream f(Asset::get()->get("crtpi.glsl").c_str());
std::string source((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()); std::string source((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
shader::init(window, gameCanvas, source.c_str()); shader::init(window_, shader_canvas_, source.c_str());
}
// Modifica el tamaño del renderizador
else
{
// El renderizador pasa a tener el tamaño de la pantalla en fullscreen o del juego en modo ventana
// SDL_RenderSetLogicalSize(renderer, windowWidth, windowHeight);
SDL_RenderSetLogicalSize(renderer, gameCanvasWidth, gameCanvasHeight);
}
#endif #endif
}
// Actualiza las opciones
options.video.mode = videoMode;
options.video.window.width = windowWidth;
options.video.window.height = windowHeight;
// Actualiza variables
shakeEffect.origin = dest.x;
} }
// Camibia entre pantalla completa y ventana // Camibia entre pantalla completa y ventana
void Screen::switchVideoMode() void Screen::switchVideoMode()
{ {
options.video.mode = options.video.mode == SCREEN_VIDEO_MODE_WINDOW ? SCREEN_VIDEO_MODE_FULLSCREEN : SCREEN_VIDEO_MODE_WINDOW; options.video.mode = options.video.mode == ScreenVideoMode::WINDOW ? ScreenVideoMode::FULLSCREEN : ScreenVideoMode::WINDOW;
setVideoMode(options.video.mode); setVideoMode(options.video.mode);
} }
@@ -307,7 +245,7 @@ void Screen::switchVideoMode()
void Screen::setWindowSize(int size) void Screen::setWindowSize(int size)
{ {
options.video.window.size = size; options.video.window.size = size;
setVideoMode(SCREEN_VIDEO_MODE_WINDOW); setVideoMode(ScreenVideoMode::WINDOW);
} }
// Reduce el tamaño de la ventana // Reduce el tamaño de la ventana
@@ -315,7 +253,7 @@ void Screen::decWindowSize()
{ {
--options.video.window.size; --options.video.window.size;
options.video.window.size = std::max(options.video.window.size, 1); options.video.window.size = std::max(options.video.window.size, 1);
setVideoMode(SCREEN_VIDEO_MODE_WINDOW); setVideoMode(ScreenVideoMode::WINDOW);
} }
// Aumenta el tamaño de la ventana // Aumenta el tamaño de la ventana
@@ -323,27 +261,28 @@ void Screen::incWindowSize()
{ {
++options.video.window.size; ++options.video.window.size;
options.video.window.size = std::min(options.video.window.size, 4); options.video.window.size = std::min(options.video.window.size, 4);
setVideoMode(SCREEN_VIDEO_MODE_WINDOW); setVideoMode(ScreenVideoMode::WINDOW);
} }
// Cambia el color del borde // Cambia el color del borde
void Screen::setBorderColor(color_t color) void Screen::setBorderColor(Color color)
{ {
borderColor = color; border_color_ = color;
} }
// Cambia el tipo de mezcla // Cambia el tipo de mezcla
void Screen::setBlendMode(SDL_BlendMode blendMode) void Screen::setBlendMode(SDL_BlendMode blendMode)
{ {
SDL_SetRenderDrawBlendMode(renderer, blendMode); SDL_SetRenderDrawBlendMode(renderer_, blendMode);
} }
// Actualiza la lógica de la clase // Actualiza la lógica de la clase
void Screen::update() void Screen::update()
{ {
updateShake(); updateShakeEffect();
notify->update(); notify_->update();
updateFPS(); updateFPS();
OnScreenHelp::get()->update();
} }
// Comprueba las entradas // Comprueba las entradas
@@ -351,16 +290,16 @@ void Screen::checkInput()
{ {
#ifndef ARCADE #ifndef ARCADE
// Comprueba el teclado para cambiar entre pantalla completa y ventana // Comprueba el teclado para cambiar entre pantalla completa y ventana
if (input->checkInput(input_window_fullscreen, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::WINDOW_FULLSCREEN, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
switchVideoMode(); switchVideoMode();
const std::string mode = options.video.mode == SCREEN_VIDEO_MODE_WINDOW ? "Window" : "Fullscreen"; const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen";
showNotification(mode + " mode"); showNotification(mode + " mode");
return; return;
} }
// Comprueba el teclado para decrementar el tamaño de la ventana // Comprueba el teclado para decrementar el tamaño de la ventana
if (input->checkInput(input_window_dec_size, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::WINDOW_DEC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
decWindowSize(); decWindowSize();
const std::string size = std::to_string(options.video.window.size); const std::string size = std::to_string(options.video.window.size);
@@ -369,7 +308,7 @@ void Screen::checkInput()
} }
// Comprueba el teclado para incrementar el tamaño de la ventana // Comprueba el teclado para incrementar el tamaño de la ventana
if (input->checkInput(input_window_inc_size, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::WINDOW_INC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
incWindowSize(); incWindowSize();
const std::string size = std::to_string(options.video.window.size); const std::string size = std::to_string(options.video.window.size);
@@ -379,7 +318,7 @@ void Screen::checkInput()
#endif #endif
// Comprueba el teclado para activar o desactivar los shaders // Comprueba el teclado para activar o desactivar los shaders
if (input->checkInput(input_video_shaders, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
switchShaders(); switchShaders();
return; return;
@@ -387,26 +326,26 @@ void Screen::checkInput()
#ifdef DEBUG #ifdef DEBUG
// Comprueba el teclado para mostrar la información de debug // Comprueba el teclado para mostrar la información de debug
if (input->checkInput(input_showinfo, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
showInfo = !showInfo; show_info_ = !show_info_;
return; return;
} }
#endif #endif
for (int i = 0; i < input->getNumControllers(); ++i) for (int i = 0; i < Input::get()->getNumControllers(); ++i)
{ {
// Comprueba los mandos para activar o desactivar los shaders // Comprueba los mandos para activar o desactivar los shaders
if (input->checkModInput(input_service, input_video_shaders, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkModInput(InputType::SERVICE, InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
switchShaders(); switchShaders();
return; return;
} }
// Comprueba los mandos para mostrar la información de debug // Comprueba los mandos para mostrar la información de debug
if (input->checkModInput(input_service, input_showinfo, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkModInput(InputType::SERVICE, InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
showInfo = !showInfo; show_info_ = !show_info_;
return; return;
} }
} }
@@ -415,75 +354,85 @@ void Screen::checkInput()
// Agita la pantalla // Agita la pantalla
void Screen::shake() void Screen::shake()
{ {
// Si ya hay un shake effect en marcha no se pilla el origen, solo se renuevan los contadores // Si no hay un shake effect activo, se guarda una copia de los valores actuales antes de modificarlos
if (shakeEffect.remaining == 0) if (!shake_effect_.enabled)
{ {
shakeEffect.origin = dest.x; shake_effect_.enabled = true;
shake_effect_.originalPos = src_rect_.x;
shake_effect_.originalWidth = src_rect_.w;
src_rect_.w -= shake_effect_.desp;
dst_rect_.w = src_rect_.w;
} }
shakeEffect.remaining = shakeEffect.lenght; // Si ya hay un shake effect en marcha no se pilla el origen, solo se renuevan los contadores
shakeEffect.counter = shakeEffect.delay; shake_effect_.remaining = shake_effect_.lenght;
shake_effect_.counter = shake_effect_.delay;
} }
// Actualiza la logica para agitar la pantalla // Actualiza la logica para agitar la pantalla
void Screen::updateShake() void Screen::updateShakeEffect()
{ {
if (shakeEffect.remaining > 0) if (shake_effect_.enabled)
{ {
if (shakeEffect.counter > 0) if (shake_effect_.counter > 0)
{ {
shakeEffect.counter--; shake_effect_.counter--;
} }
else else
{ {
shakeEffect.counter = shakeEffect.delay; shake_effect_.counter = shake_effect_.delay;
const int desp = shakeEffect.remaining % 2 == 0 ? shakeEffect.desp * (-1) : shakeEffect.desp; const auto srcdesp = shake_effect_.remaining % 2 == 0 ? 0 : shake_effect_.desp;
dest.x = shakeEffect.origin + desp; const auto dstdesp = shake_effect_.remaining % 2 == 1 ? 0 : shake_effect_.desp;
shakeEffect.remaining--; src_rect_.x = shake_effect_.originalPos + srcdesp;
} dst_rect_.x = shake_effect_.originalPos + dstdesp;
} shake_effect_.remaining--;
else shake_effect_.enabled = shake_effect_.remaining == -1 ? false : true;
if (!shake_effect_.enabled)
{ {
dest.x = shakeEffect.origin; src_rect_.x = shake_effect_.originalPos;
src_rect_.w = shake_effect_.originalWidth;
dst_rect_ = src_rect_;
}
}
} }
} }
// Pone la pantalla de color // Pone la pantalla de color
void Screen::flash(color_t color, int lenght) void Screen::flash(Color color, int lenght)
{ {
flashEffect.enabled = true; flash_effect_.enabled = true;
flashEffect.counter = 0; flash_effect_.counter = 0;
flashEffect.lenght = lenght; flash_effect_.lenght = lenght;
flashEffect.color = color; flash_effect_.color = color;
} }
// Actualiza y dibuja el efecto de flash en la pantalla // Actualiza y dibuja el efecto de flash en la pantalla
void Screen::doFlash() void Screen::doFlash()
{ {
if (flashEffect.enabled) if (flash_effect_.enabled)
{ {
// Dibuja el color del flash en la textura // Dibuja el color del flash en la textura
SDL_Texture *temp = SDL_GetRenderTarget(renderer); SDL_Texture *temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer, gameCanvas); SDL_SetRenderTarget(renderer_, game_canvas_);
SDL_SetRenderDrawColor(renderer, flashEffect.color.r, flashEffect.color.g, flashEffect.color.b, 0xFF); SDL_SetRenderDrawColor(renderer_, flash_effect_.color.r, flash_effect_.color.g, flash_effect_.color.b, 0xFF);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
// Actualiza la lógica del efecto // Actualiza la lógica del efecto
flashEffect.counter < flashEffect.lenght ? flashEffect.counter++ : flashEffect.enabled = false; flash_effect_.counter < flash_effect_.lenght ? flash_effect_.counter++ : flash_effect_.enabled = false;
} }
} }
// Atenua la pantalla // Atenua la pantalla
void Screen::doAttenuate() void Screen::doAttenuate()
{ {
if (attenuateEffect) if (attenuate_effect_)
{ {
SDL_Texture *temp = SDL_GetRenderTarget(renderer); SDL_Texture *temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer, gameCanvas); SDL_SetRenderTarget(renderer_, game_canvas_);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 64); SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 64);
SDL_RenderFillRect(renderer, nullptr); SDL_RenderFillRect(renderer_, nullptr);
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
} }
} }
@@ -499,48 +448,50 @@ void Screen::switchShaders()
// Atenua la pantalla // Atenua la pantalla
void Screen::attenuate(bool value) void Screen::attenuate(bool value)
{ {
attenuateEffect = value; attenuate_effect_ = value;
} }
// Muestra una notificación de texto por pantalla; // Muestra una notificación de texto por pantalla;
void Screen::showNotification(std::string text1, std::string text2, int icon) void Screen::showNotification(const std::string &text1, const std::string &text2, int icon)
{ {
notify->showText(text1, text2, icon); notify_->showText(text1, text2, icon);
} }
// Obtiene el puntero al renderizador // Obtiene el puntero al renderizador
SDL_Renderer *Screen::getRenderer() SDL_Renderer *Screen::getRenderer()
{ {
return renderer; return renderer_;
} }
// Calcula los frames por segundo // Calcula los frames por segundo
void Screen::updateFPS() void Screen::updateFPS()
{ {
if (SDL_GetTicks() - fpsTicks > 1000) if (SDL_GetTicks() - fps_ticks_ > 1000)
{ {
fpsTicks = SDL_GetTicks(); fps_ticks_ = SDL_GetTicks();
fps = fpsCounter; fps_ = fps_counter_;
fpsCounter = 0; fps_counter_ = 0;
} }
} }
// Muestra información por pantalla // Muestra información por pantalla
void Screen::displayInfo() void Screen::displayInfo()
{ {
if (showInfo) if (show_info_)
{ {
// FPS // FPS
const std::string fpstext = std::to_string(fps) + " FPS"; const std::string fpstext = std::to_string(fps_) + " FPS";
dbg_print(gameCanvasWidth - fpstext.length() * 8, 0, fpstext.c_str(), 255, 255, 0); dbg_print(param.game.width - fpstext.length() * 8, 0, fpstext.c_str(), 255, 255, 0);
// Resolution // Resolution
dbg_print(0, 0, infoResolution.c_str(), 255, 255, 0); dbg_print(0, 0, info_resolution_.c_str(), 255, 255, 0);
dbg_print(0, 8, std::to_string(globalInputs::service_pressed_counter[0]).c_str(), 255, 255, 0);
} }
} }
// Indica si hay alguna notificación activa en pantalla // Indica si hay alguna notificación activa en pantalla
bool Screen::notificationsAreActive() bool Screen::notificationsAreActive() const
{ {
return notify->active(); return notify_->active();
} }

View File

@@ -6,68 +6,72 @@
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <SDL2/SDL_stdinc.h> // for Uint32
#include <SDL2/SDL_video.h> // for SDL_Window #include <SDL2/SDL_video.h> // for SDL_Window
#include <string> // for basic_string, string #include <string> // for basic_string, string
#include "utils.h" // for color_t #include "utils.h" // for Color
class Asset; #include <memory>
class Input;
class Notify; class Notify;
#define SCREEN_FILTER_NEAREST 0 enum class ScreenFilter : int
#define SCREEN_FILTER_LINEAL 1 {
NEAREST = 0,
LINEAL = 1,
};
#define SCREEN_VIDEO_MODE_WINDOW 0 enum class ScreenVideoMode : int
#define SCREEN_VIDEO_MODE_FULLSCREEN 1 {
WINDOW = 0,
FULLSCREEN = 1,
};
class Screen class Screen
{ {
private: private:
// [SINGLETON] Objeto screen privado para Don Melitón // [SINGLETON] Objeto screen privado para Don Melitón
static Screen *screen; static Screen *screen_;
// Objetos y punteros // Objetos y punteros
SDL_Window *window; // Ventana de la aplicación SDL_Window *window_; // Ventana de la aplicación
SDL_Renderer *renderer; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
Asset *asset; // Objeto con el listado de recursos std::unique_ptr<Notify> notify_; // Pinta notificaciones en pantalla
Input *input; // Objeto para leer las entradas de teclado o mando SDL_Texture *game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador
Notify *notify; // Pinta notificaciones en pantalla SDL_Texture *shader_canvas_; // Textura para pasarle al shader desde gameCanvas
SDL_Texture *gameCanvas; // Textura para completar la ventana de juego hasta la pantalla completa
// Variables // Variables
int windowWidth; // Ancho de la pantalla o ventana SDL_Rect src_rect_; // Coordenadas de donde va a pillar la textura del juego para dibujarla
int windowHeight; // Alto de la pantalla o ventana SDL_Rect dst_rect_; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana
int gameCanvasWidth; // Resolución interna del juego. Es el ancho de la textura donde se dibuja el juego Color border_color_; // Color del borde añadido a la textura de juego para rellenar la pantalla
int gameCanvasHeight; // Resolución interna del juego. Es el alto de la textura donde se dibuja el juego bool attenuate_effect_; // Indica si la pantalla ha de estar atenuada
SDL_Rect dest; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana Uint32 fps_ticks_; // Ticks para contar los frames por segundo
color_t borderColor; // Color del borde añadido a la textura de juego para rellenar la pantalla int fps_counter_; // Contador de frames por segundo
bool attenuateEffect; // Indica si la pantalla ha de estar atenuada int fps_; // Frames calculados en el último segundo
Uint32 fpsTicks; // Ticks para contar los frames por segundo bool show_info_; // Indica si ha de mostrar/ocultar la información de la pantalla
int fpsCounter; // Contador de frames por segundo std::string info_resolution_; // Texto con la informacion de la pantalla
int fps; // Frames calculados en el último segundo
bool showInfo; // Indica si ha de mostrar/ocultar la información de la pantalla
std::string infoResolution; // Texto con la informacion de la pantalla
struct effect_t struct FlashEffect
{ {
bool enabled; // Indica si el efecto está activo bool enabled; // Indica si el efecto está activo
int counter; // Contador para el efecto int counter; // Contador para el efecto
int lenght; // Duración del efecto int lenght; // Duración del efecto
color_t color; // Color del efecto Color color; // Color del efecto
}; };
// Variables - Efectos struct ShakeEffect
effect_t flashEffect; // Variable para gestionar el efecto de flash
struct shake_t
{ {
int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x
int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse
int counter; // Contador para el retraso int counter; // Contador para el retraso
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 originalPos; // Posición inicial de la pantalla para dejarla igual tras el desplazamiento
} shakeEffect; int originalWidth; // Anchura inicial de la pantalla para dejarla igual tras el desplazamiento
bool enabled; // Indica si el efecto está activo
};
// Variables - Efectos
FlashEffect flash_effect_; // Variable para gestionar el efecto de flash
ShakeEffect shake_effect_; // Variable para gestionar el efecto de agitar la pantalla
// Actualiza la logica para agitar la pantalla // Actualiza la logica para agitar la pantalla
void updateShake(); void updateShakeEffect();
// Actualiza y dibuja el efecto de flash en la pantalla // Actualiza y dibuja el efecto de flash en la pantalla
void doFlash(); void doFlash();
@@ -81,7 +85,6 @@ private:
// Muestra información por pantalla // Muestra información por pantalla
void displayInfo(); void displayInfo();
// [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos screen desde fuera // [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos screen desde fuera
// Constructor // Constructor
@@ -107,7 +110,7 @@ public:
void checkInput(); void checkInput();
// Limpia la pantalla // Limpia la pantalla
void clean(color_t color = {0x00, 0x00, 0x00}); void clean(Color color = {0x00, 0x00, 0x00});
// Prepara para empezar a dibujar en la textura de juego // Prepara para empezar a dibujar en la textura de juego
void start(); void start();
@@ -116,7 +119,7 @@ public:
void blit(); void blit();
// Establece el modo de video // Establece el modo de video
void setVideoMode(int videoMode); void setVideoMode(ScreenVideoMode video_mode);
// Camibia entre pantalla completa y ventana // Camibia entre pantalla completa y ventana
void switchVideoMode(); void switchVideoMode();
@@ -131,16 +134,16 @@ public:
void incWindowSize(); void incWindowSize();
// Cambia el color del borde // Cambia el color del borde
void setBorderColor(color_t color); void setBorderColor(Color color);
// Cambia el tipo de mezcla // Cambia el tipo de mezcla
void setBlendMode(SDL_BlendMode blendMode); void setBlendMode(SDL_BlendMode blend_mode);
// Agita la pantalla // Agita la pantalla
void shake(); void shake();
// Pone la pantalla de color // Pone la pantalla de color
void flash(color_t color, int lenght); void flash(Color color, int lenght);
// Activa/desactiva los shaders // Activa/desactiva los shaders
void switchShaders(); void switchShaders();
@@ -149,10 +152,10 @@ public:
void attenuate(bool value); void attenuate(bool value);
// Muestra una notificación de texto por pantalla; // Muestra una notificación de texto por pantalla;
void showNotification(std::string text1 = "", std::string text2 = "", int icon = -1); void showNotification(const std::string &text1 = std::string(), const std::string &text2 = std::string(), int icon = -1);
// Indica si hay alguna notificación activa en pantalla // Indica si hay alguna notificación activa en pantalla
bool notificationsAreActive(); bool notificationsAreActive() const;
// Obtiene el puntero al renderizador // Obtiene el puntero al renderizador
SDL_Renderer *getRenderer(); SDL_Renderer *getRenderer();

View File

@@ -2,6 +2,6 @@
namespace section namespace section
{ {
name_e name; Name name;
options_e options; Options options;
} }

View File

@@ -3,31 +3,31 @@
namespace section namespace section
{ {
// Secciones del programa // Secciones del programa
enum name_e enum class Name
{ {
NAME_INIT = 0, INIT = 0,
NAME_LOGO = 1, LOGO = 1,
NAME_INTRO = 2, INTRO = 2,
NAME_TITLE = 3, TITLE = 3,
NAME_GAME = 4, GAME = 4,
NAME_HI_SCORE_TABLE = 5, HI_SCORE_TABLE = 5,
NAME_GAME_DEMO = 6, GAME_DEMO = 6,
NAME_INSTRUCTIONS = 7, INSTRUCTIONS = 7,
NAME_QUIT = 8, QUIT = 8,
}; };
// Opciones para la sección // Opciones para la sección
enum options_e enum class Options
{ {
OPTIONS_GAME_PLAY_1P = 0, GAME_PLAY_1P = 0,
OPTIONS_GAME_PLAY_2P = 1, GAME_PLAY_2P = 1,
OPTIONS_TITLE_1 = 2, TITLE_1 = 2,
OPTIONS_TITLE_2 = 3, TITLE_2 = 3,
OPTIONS_QUIT_NORMAL = 4, QUIT_NORMAL = 4,
OPTIONS_QUIT_SHUTDOWN = 5, QUIT_SHUTDOWN = 5,
OPTIONS_NULL = 6, NONE = 6,
}; };
extern name_e name; extern Name name;
extern options_e options; extern Options options;
} }

View File

@@ -3,99 +3,62 @@
class Texture; class Texture;
// Constructor // Constructor
SmartSprite::SmartSprite(Texture *texture) SmartSprite::SmartSprite(std::shared_ptr<Texture> texture)
: AnimatedSprite(texture)
{ {
// Copia punteros
setTexture(texture);
// Inicializa el objeto
init(); init();
} }
// Inicializa el objeto // Inicializa el objeto
void SmartSprite::init() void SmartSprite::init()
{ {
enabled = false; finished_counter_ = 0;
enabledCounter = 0; on_destination_ = false;
onDestination = false; dest_x_ = 0;
destX = 0; dest_y_ = 0;
destY = 0; finished_ = false;
counter = 0; enabled_ = false;
finished = false;
} }
// Actualiza la posición y comprueba si ha llegado a su destino // Actualiza la posición y comprueba si ha llegado a su destino
void SmartSprite::update() void SmartSprite::update()
{ {
if (enabled) if (enabled_)
{ {
// Actualiza las variables internas del objeto
MovingSprite::update(); MovingSprite::update();
// Comprueba el movimiento
checkMove(); checkMove();
// Comprueba si ha terminado
checkFinished(); checkFinished();
} }
} }
// Pinta el objeto en pantalla
void SmartSprite::render()
{
if (enabled)
{
// Muestra el sprite por pantalla
MovingSprite::render();
}
}
// Obtiene el valor de la variable
bool SmartSprite::isEnabled()
{
return enabled;
}
// Establece el valor de la variable // Establece el valor de la variable
void SmartSprite::setEnabled(bool enabled) void SmartSprite::setFinishedCounter(int value)
{ {
this->enabled = enabled; finished_counter_ = value;
}
// Obtiene el valor de la variable
int SmartSprite::getEnabledCounter()
{
return enabledCounter;
}
// Establece el valor de la variable
void SmartSprite::setEnabledCounter(int value)
{
enabledCounter = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void SmartSprite::setDestX(int x) void SmartSprite::setDestX(int x)
{ {
destX = x; dest_x_ = x;
} }
// Establece el valor de la variable // Establece el valor de la variable
void SmartSprite::setDestY(int y) void SmartSprite::setDestY(int y)
{ {
destY = y; dest_y_ = y;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int SmartSprite::getDestX() int SmartSprite::getDestX() const
{ {
return destX; return dest_x_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int SmartSprite::getDestY() int SmartSprite::getDestY() const
{ {
return destY; return dest_y_;
} }
// Comprueba el movimiento // Comprueba el movimiento
@@ -105,10 +68,10 @@ void SmartSprite::checkMove()
if (getAccelX() > 0 || getVelX() > 0) if (getAccelX() > 0 || getVelX() > 0)
{ {
// Comprueba si ha llegado al destino // Comprueba si ha llegado al destino
if (getPosX() > destX) if (getPosX() > dest_x_)
{ {
// Lo coloca en posición // Lo coloca en posición
setPosX(destX); setPosX(dest_x_);
// Lo detiene // Lo detiene
setVelX(0.0f); setVelX(0.0f);
@@ -119,10 +82,10 @@ void SmartSprite::checkMove()
else if (getAccelX() < 0 || getVelX() < 0) else if (getAccelX() < 0 || getVelX() < 0)
{ {
// Comprueba si ha llegado al destino // Comprueba si ha llegado al destino
if (getPosX() < destX) if (getPosX() < dest_x_)
{ {
// Lo coloca en posición // Lo coloca en posición
setPosX(destX); setPosX(dest_x_);
// Lo detiene // Lo detiene
setVelX(0.0f); setVelX(0.0f);
@@ -134,10 +97,10 @@ void SmartSprite::checkMove()
if (getAccelY() > 0 || getVelY() > 0) if (getAccelY() > 0 || getVelY() > 0)
{ {
// Comprueba si ha llegado al destino // Comprueba si ha llegado al destino
if (getPosY() > destY) if (getPosY() > dest_y_)
{ {
// Lo coloca en posición // Lo coloca en posición
setPosY(destY); setPosY(dest_y_);
// Lo detiene // Lo detiene
setVelY(0.0f); setVelY(0.0f);
@@ -148,10 +111,10 @@ void SmartSprite::checkMove()
else if (getAccelY() < 0 || getVelY() < 0) else if (getAccelY() < 0 || getVelY() < 0)
{ {
// Comprueba si ha llegado al destino // Comprueba si ha llegado al destino
if (getPosY() < destY) if (getPosY() < dest_y_)
{ {
// Lo coloca en posición // Lo coloca en posición
setPosY(destY); setPosY(dest_y_);
// Lo detiene // Lo detiene
setVelY(0.0f); setVelY(0.0f);
@@ -164,29 +127,34 @@ void SmartSprite::checkMove()
void SmartSprite::checkFinished() void SmartSprite::checkFinished()
{ {
// Comprueba si ha llegado a su destino // Comprueba si ha llegado a su destino
onDestination = (getPosX() == destX && getPosY() == destY) ? true : false; on_destination_ = (getPosX() == dest_x_ && getPosY() == dest_y_) ? true : false;
if (onDestination) if (on_destination_)
{ // Si esta en el destino comprueba su contador {
if (enabledCounter == 0) if (finished_counter_ == 0)
{ // Si ha llegado a cero, deshabilita el objeto y lo marca como finalizado {
finished = true; finished_ = true;
} }
else else
{ // Si no ha llegado a cero, decrementa el contador {
enabledCounter--; --finished_counter_;
} }
} }
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool SmartSprite::isOnDestination() bool SmartSprite::isOnDestination() const
{ {
return onDestination; return on_destination_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool SmartSprite::hasFinished() bool SmartSprite::hasFinished() const
{ {
return finished; return finished_;
}
void SmartSprite::setEnabled(bool value)
{
enabled_ = value;
} }

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <memory> // for shared_ptr
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for AnimatedSprite
class Texture; class Texture;
@@ -8,12 +9,12 @@ class SmartSprite : public AnimatedSprite
{ {
private: private:
// Variables // Variables
bool enabled; // Indica si esta habilitado bool on_destination_; // Indica si está en el destino
bool onDestination; // Indica si está en el destino int dest_x_; // Posicion de destino en el eje X
int destX; // Posicion de destino en el eje X int dest_y_; // Posicion de destino en el eje Y
int destY; // Posicion de destino en el eje Y int finished_counter_; // Contador para deshabilitarlo
int enabledCounter; // Contador para deshabilitarlo bool finished_; // Indica si ya ha terminado
bool finished; // Indica si ya ha terminado bool enabled_; // Indica si el objeto está habilitado
// Comprueba el movimiento // Comprueba el movimiento
void checkMove(); void checkMove();
@@ -23,28 +24,19 @@ private:
public: public:
// Constructor // Constructor
SmartSprite(Texture *texture); explicit SmartSprite(std::shared_ptr<Texture> texture);
// Destructor
~SmartSprite() = default;
// Inicializa el objeto // Inicializa el objeto
void init(); void init();
// Actualiza la posición y comprueba si ha llegado a su destino // Actualiza la posición y comprueba si ha llegado a su destino
void update(); void update() override;
// Pinta el objeto en pantalla
void render();
// Obtiene el valor de la variable
bool isEnabled();
// Establece el valor de la variable // Establece el valor de la variable
void setEnabled(bool enabled); void setFinishedCounter(int value);
// Obtiene el valor de la variable
int getEnabledCounter();
// Establece el valor de la variable
void setEnabledCounter(int value);
// Establece el valor de la variable // Establece el valor de la variable
void setDestX(int x); void setDestX(int x);
@@ -53,14 +45,16 @@ public:
void setDestY(int y); void setDestY(int y);
// Obtiene el valor de la variable // Obtiene el valor de la variable
int getDestX(); int getDestX() const;
// Obtiene el valor de la variable // Obtiene el valor de la variable
int getDestY(); int getDestY() const;
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool isOnDestination(); bool isOnDestination() const;
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool hasFinished(); bool hasFinished() const;
void setEnabled(bool value);
}; };

View File

@@ -1,192 +1,137 @@
#include "sprite.h" #include "sprite.h"
#include "texture.h" // for Texture
// Constructor // Constructor
Sprite::Sprite(int x, int y, int w, int h, Texture *texture) Sprite::Sprite(int x, int y, int w, int h, std::shared_ptr<Texture> texture)
{ : texture_(texture),
// Establece la posición X,Y del sprite pos_((SDL_Rect){x, y, w, h}),
this->x = x; sprite_clip_((SDL_Rect){0, 0, pos_.w, pos_.h}) {}
this->y = y;
// Establece el alto y el ancho del sprite Sprite::Sprite(SDL_Rect rect, std::shared_ptr<Texture> texture)
this->w = w; : texture_(texture),
this->h = h; pos_(rect),
sprite_clip_((SDL_Rect){0, 0, pos_.w, pos_.h}) {}
// Establece la textura donde están los gráficos para el sprite Sprite::Sprite(std::shared_ptr<Texture> texture)
this->texture = texture; : texture_(texture) {}
// Establece el rectangulo de donde coger la imagen
spriteClip = {0, 0, w, h};
// Inicializa variables
enabled = true;
}
Sprite::Sprite(SDL_Rect rect, Texture *texture)
{
// Establece la posición X,Y del sprite
x = rect.x;
y = rect.y;
// Establece el alto y el ancho del sprite
w = rect.w;
h = rect.h;
// Establece la textura donde están los gráficos para el sprite
this->texture = texture;
// Establece el rectangulo de donde coger la imagen
spriteClip = {0, 0, w, h};
// Inicializa variables
enabled = true;
}
// Destructor
Sprite::~Sprite()
{
texture = nullptr;
}
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void Sprite::render() void Sprite::render()
{ {
if (enabled) texture_->render(pos_.x, pos_.y, &sprite_clip_);
{
texture->render(x, y, &spriteClip);
}
} }
// Obten el valor de la variable // Obten el valor de la variable
int Sprite::getPosX() int Sprite::getIntPosX() const
{ {
return x; return pos_.x;
} }
// Obten el valor de la variable // Obten el valor de la variable
int Sprite::getPosY() int Sprite::getIntPosY() const
{ {
return y; return pos_.y;
} }
// Obten el valor de la variable // Obten el valor de la variable
int Sprite::getWidth() int Sprite::getWidth() const
{ {
return w; return pos_.w;
} }
// Obten el valor de la variable // Obten el valor de la variable
int Sprite::getHeight() int Sprite::getHeight() const
{ {
return h; return pos_.h;
}
// Establece la posición del objeto
void Sprite::setPos(int x, int y)
{
pos_.x = x;
pos_.y = y;
} }
// Establece la posición del objeto // Establece la posición del objeto
void Sprite::setPos(SDL_Point p) void Sprite::setPos(SDL_Point p)
{ {
this->x = p.x; pos_.x = p.x;
this->y = p.y; pos_.y = p.y;
} }
// Establece la posición del objeto // Establece la posición del objeto
void Sprite::setPos(SDL_Rect r) void Sprite::setPos(SDL_Rect r)
{ {
this->x = r.x; pos_ = r;
this->y = r.y;
this->w = r.w;
this->h = r.h;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setPosX(int x) void Sprite::setPosX(int x)
{ {
this->x = x; pos_.x = x;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setPosY(int y) void Sprite::setPosY(int y)
{ {
this->y = y; pos_.y = y;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setWidth(int w) void Sprite::setWidth(int w)
{ {
this->w = w; pos_.w = w;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setHeight(int h) void Sprite::setHeight(int h)
{ {
this->h = h; pos_.h = h;
} }
// Obten el valor de la variable // Obten el valor de la variable
SDL_Rect Sprite::getSpriteClip() SDL_Rect Sprite::getSpriteClip() const
{ {
return spriteClip; return sprite_clip_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setSpriteClip(SDL_Rect rect) void Sprite::setSpriteClip(SDL_Rect rect)
{ {
spriteClip = rect; sprite_clip_ = rect;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setSpriteClip(int x, int y, int w, int h) void Sprite::setSpriteClip(int x, int y, int w, int h)
{ {
spriteClip = {x, y, w, h}; sprite_clip_ = (SDL_Rect){x, y, w, h};
} }
// Obten el valor de la variable // Obten el valor de la variable
Texture *Sprite::getTexture() std::shared_ptr<Texture> Sprite::getTexture() const
{ {
return texture; return texture_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setTexture(Texture *texture) void Sprite::setTexture(std::shared_ptr<Texture> texture)
{ {
this->texture = texture; texture_ = texture;
}
// Establece el valor de la variable
void Sprite::setEnabled(bool value)
{
enabled = value;
}
// Comprueba si el objeto está habilitado
bool Sprite::isEnabled()
{
return enabled;
} }
// Devuelve el rectangulo donde está el sprite // Devuelve el rectangulo donde está el sprite
SDL_Rect Sprite::getRect() SDL_Rect Sprite::getPos() const
{ {
SDL_Rect rect = {x, y, w, h}; return pos_;
return rect;
}
// Establece los valores de posición y tamaño del sprite
void Sprite::setRect(SDL_Rect rect)
{
x = rect.x;
y = rect.y;
w = rect.w;
h = rect.h;
} }
// Incrementa el valor de la variable // Incrementa el valor de la variable
void Sprite::incPosX(int value) void Sprite::incPosX(int value)
{ {
x += value; pos_.x += value;
} }
// Incrementa el valor de la variable // Incrementa el valor de la variable
void Sprite::incPosY(int value) void Sprite::incPosY(int value)
{ {
y += value; pos_.y += value;
} }

View File

@@ -1,91 +1,64 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point #include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point
class Texture; #include "texture.h"
#include <memory>
// Clase sprite // Clase sprite
class Sprite class Sprite
{ {
protected: protected:
int x; // Posición en el eje X donde dibujar el sprite // Variables
int y; // Posición en el eje Y donde dibujar el sprite std::shared_ptr<Texture> texture_; // Textura donde estan todos los dibujos del sprite
int w; // Ancho del sprite SDL_Rect pos_; // Posición y tamaño donde dibujar el sprite
int h; // Alto del sprite SDL_Rect sprite_clip_; // Rectangulo de origen de la textura que se dibujará en pantalla
Texture *texture; // Textura donde estan todos los dibujos del sprite
SDL_Rect spriteClip; // Rectangulo de origen de la textura que se dibujará en pantalla
bool enabled; // Indica si el sprite esta habilitado
public: public:
// Constructor // Constructor
Sprite(int x = 0, int y = 0, int w = 0, int h = 0, Texture *texture = nullptr); explicit Sprite(int x = 0, int y = 0, int w = 0, int h = 0, std::shared_ptr<Texture> texture = nullptr);
Sprite(SDL_Rect rect, Texture *texture); explicit Sprite(SDL_Rect rect, std::shared_ptr<Texture> texture = nullptr);
explicit Sprite(std::shared_ptr<Texture> texture = nullptr);
// Destructor // Destructor
~Sprite(); virtual ~Sprite() = default;
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void render(); virtual void render();
// Obten el valor de la variable // Obten el valor de la variable
int getPosX(); int getIntPosX() const;
int getIntPosY() const;
int getWidth() const;
int getHeight() const;
// Obten el valor de la variable // Devuelve el rectangulo donde está el sprite
int getPosY(); virtual SDL_Rect getPos() const;
// Obten el valor de la variable
int getWidth();
// Obten el valor de la variable
int getHeight();
// Establece la posición del objeto
void setPos(SDL_Point p);
void setPos(SDL_Rect r);
// Establece el valor de la variable // Establece el valor de la variable
void setPosX(int x); void setPosX(int x);
// Establece el valor de la variable
void setPosY(int y); void setPosY(int y);
void setWidth(int w);
void setHeight(int h);
// Establece la posición del objeto
void setPos(int x, int y);
void setPos(SDL_Point p);
virtual void setPos(SDL_Rect r);
// Incrementa el valor de la variable // Incrementa el valor de la variable
void incPosX(int value); void incPosX(int value);
// Incrementa el valor de la variable
void incPosY(int value); void incPosY(int value);
// Establece el valor de la variable
void setWidth(int w);
// Establece el valor de la variable
void setHeight(int h);
// Obten el valor de la variable // Obten el valor de la variable
SDL_Rect getSpriteClip(); SDL_Rect getSpriteClip() const;
// Establece el valor de la variable // Establece el valor de la variable
void setSpriteClip(SDL_Rect rect); void setSpriteClip(SDL_Rect rect);
// Establece el valor de la variable
void setSpriteClip(int x, int y, int w, int h); void setSpriteClip(int x, int y, int w, int h);
// Obten el valor de la variable // Obten el valor de la variable
Texture *getTexture(); std::shared_ptr<Texture> getTexture() const;
// Establece el valor de la variable // Establece el valor de la variable
void setTexture(Texture *texture); void setTexture(std::shared_ptr<Texture> texture);
// Establece el valor de la variable
void setEnabled(bool value);
// Comprueba si el objeto está habilitado
bool isEnabled();
// Devuelve el rectangulo donde está el sprite
SDL_Rect getRect();
// Establece los valores de posición y tamaño del sprite
void setRect(SDL_Rect rect);
}; };

View File

@@ -1,4 +1,4 @@
/* stb_image - v2.27 - public domain image loader - http://nothings.org/stb /* stb_image - v2.30 - public domain image loader - http://nothings.org/stb
no warranty implied; use at your own risk no warranty implied; use at your own risk
Do this: Do this:
@@ -48,6 +48,9 @@ LICENSE
RECENT REVISION HISTORY: RECENT REVISION HISTORY:
2.30 (2024-05-31) avoid erroneous gcc warning
2.29 (2023-05-xx) optimizations
2.28 (2023-01-29) many error fixes, security errors, just tons of stuff
2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes
2.26 (2020-07-13) many minor fixes 2.26 (2020-07-13) many minor fixes
2.25 (2020-02-02) fix warnings 2.25 (2020-02-02) fix warnings
@@ -108,7 +111,7 @@ RECENT REVISION HISTORY:
Cass Everitt Ryamond Barbiero github:grim210 Cass Everitt Ryamond Barbiero github:grim210
Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw
Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus
Josh Tobin Matthew Gregan github:poppolopoppo Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo
Julian Raschke Gregory Mullen Christian Floisand github:darealshinji Julian Raschke Gregory Mullen Christian Floisand github:darealshinji
Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007
Brad Weinberger Matvey Cherevko github:mosra Brad Weinberger Matvey Cherevko github:mosra
@@ -140,7 +143,7 @@ RECENT REVISION HISTORY:
// // ... x = width, y = height, n = # 8-bit components per pixel ... // // ... x = width, y = height, n = # 8-bit components per pixel ...
// // ... replace '0' with '1'..'4' to force that many components per pixel // // ... replace '0' with '1'..'4' to force that many components per pixel
// // ... but 'n' will always be the number that it would have been if you said 0 // // ... but 'n' will always be the number that it would have been if you said 0
// stbi_image_free(data) // stbi_image_free(data);
// //
// Standard parameters: // Standard parameters:
// int *x -- outputs image width in pixels // int *x -- outputs image width in pixels
@@ -635,7 +638,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#endif #endif
#endif #endif
#ifdef _MSC_VER #if defined(_MSC_VER) || defined(__SYMBIAN32__)
typedef unsigned short stbi__uint16; typedef unsigned short stbi__uint16;
typedef signed short stbi__int16; typedef signed short stbi__int16;
typedef unsigned int stbi__uint32; typedef unsigned int stbi__uint32;
@@ -1063,6 +1066,23 @@ static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
} }
#endif #endif
// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow.
static int stbi__addints_valid(int a, int b)
{
if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow
if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0.
return a <= INT_MAX - b;
}
// returns 1 if the product of two ints fits in a signed short, 0 on overflow.
static int stbi__mul2shorts_valid(int a, int b)
{
if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow
if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid
if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN
return a >= SHRT_MIN / b;
}
// stbi__err - error // stbi__err - error
// stbi__errpf - error returning pointer to float // stbi__errpf - error returning pointer to float
// stbi__errpuc - error returning pointer to unsigned char // stbi__errpuc - error returning pointer to unsigned char
@@ -1985,9 +2005,12 @@ static int stbi__build_huffman(stbi__huffman *h, int *count)
int i,j,k=0; int i,j,k=0;
unsigned int code; unsigned int code;
// build size list for each symbol (from JPEG spec) // build size list for each symbol (from JPEG spec)
for (i=0; i < 16; ++i) for (i=0; i < 16; ++i) {
for (j=0; j < count[i]; ++j) for (j=0; j < count[i]; ++j) {
h->size[k++] = (stbi_uc) (i+1); h->size[k++] = (stbi_uc) (i+1);
if(k >= 257) return stbi__err("bad size list","Corrupt JPEG");
}
}
h->size[k] = 0; h->size[k] = 0;
// compute actual symbols (from jpeg spec) // compute actual symbols (from jpeg spec)
@@ -2112,6 +2135,8 @@ stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h)
// convert the huffman code to the symbol id // convert the huffman code to the symbol id
c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k];
if(c < 0 || c >= 256) // symbol id out of bounds!
return -1;
STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]);
// convert the id to a symbol // convert the id to a symbol
@@ -2130,6 +2155,7 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
unsigned int k; unsigned int k;
int sgn; int sgn;
if (j->code_bits < n) stbi__grow_buffer_unsafe(j); if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing
sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative)
k = stbi_lrot(j->code_buffer, n); k = stbi_lrot(j->code_buffer, n);
@@ -2144,6 +2170,7 @@ stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n)
{ {
unsigned int k; unsigned int k;
if (j->code_bits < n) stbi__grow_buffer_unsafe(j); if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing
k = stbi_lrot(j->code_buffer, n); k = stbi_lrot(j->code_buffer, n);
j->code_buffer = k & ~stbi__bmask[n]; j->code_buffer = k & ~stbi__bmask[n];
k &= stbi__bmask[n]; k &= stbi__bmask[n];
@@ -2155,6 +2182,7 @@ stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j)
{ {
unsigned int k; unsigned int k;
if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); if (j->code_bits < 1) stbi__grow_buffer_unsafe(j);
if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing
k = j->code_buffer; k = j->code_buffer;
j->code_buffer <<= 1; j->code_buffer <<= 1;
--j->code_bits; --j->code_bits;
@@ -2192,8 +2220,10 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman
memset(data,0,64*sizeof(data[0])); memset(data,0,64*sizeof(data[0]));
diff = t ? stbi__extend_receive(j, t) : 0; diff = t ? stbi__extend_receive(j, t) : 0;
if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG");
dc = j->img_comp[b].dc_pred + diff; dc = j->img_comp[b].dc_pred + diff;
j->img_comp[b].dc_pred = dc; j->img_comp[b].dc_pred = dc;
if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
data[0] = (short) (dc * dequant[0]); data[0] = (short) (dc * dequant[0]);
// decode AC components, see JPEG spec // decode AC components, see JPEG spec
@@ -2207,6 +2237,7 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman
if (r) { // fast-AC path if (r) { // fast-AC path
k += (r >> 4) & 15; // run k += (r >> 4) & 15; // run
s = r & 15; // combined length s = r & 15; // combined length
if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");
j->code_buffer <<= s; j->code_buffer <<= s;
j->code_bits -= s; j->code_bits -= s;
// decode into unzigzag'd location // decode into unzigzag'd location
@@ -2246,8 +2277,10 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__
if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
diff = t ? stbi__extend_receive(j, t) : 0; diff = t ? stbi__extend_receive(j, t) : 0;
if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG");
dc = j->img_comp[b].dc_pred + diff; dc = j->img_comp[b].dc_pred + diff;
j->img_comp[b].dc_pred = dc; j->img_comp[b].dc_pred = dc;
if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
data[0] = (short) (dc * (1 << j->succ_low)); data[0] = (short) (dc * (1 << j->succ_low));
} else { } else {
// refinement scan for DC coefficient // refinement scan for DC coefficient
@@ -2282,6 +2315,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
if (r) { // fast-AC path if (r) { // fast-AC path
k += (r >> 4) & 15; // run k += (r >> 4) & 15; // run
s = r & 15; // combined length s = r & 15; // combined length
if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");
j->code_buffer <<= s; j->code_buffer <<= s;
j->code_bits -= s; j->code_bits -= s;
zig = stbi__jpeg_dezigzag[k++]; zig = stbi__jpeg_dezigzag[k++];
@@ -3102,6 +3136,7 @@ static int stbi__process_marker(stbi__jpeg *z, int m)
sizes[i] = stbi__get8(z->s); sizes[i] = stbi__get8(z->s);
n += sizes[i]; n += sizes[i];
} }
if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values!
L -= 17; L -= 17;
if (tc == 0) { if (tc == 0) {
if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0;
@@ -3351,6 +3386,28 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
return 1; return 1;
} }
static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j)
{
// some JPEGs have junk at end, skip over it but if we find what looks
// like a valid marker, resume there
while (!stbi__at_eof(j->s)) {
stbi_uc x = stbi__get8(j->s);
while (x == 0xff) { // might be a marker
if (stbi__at_eof(j->s)) return STBI__MARKER_none;
x = stbi__get8(j->s);
if (x != 0x00 && x != 0xff) {
// not a stuffed zero or lead-in to another marker, looks
// like an actual marker, return it
return x;
}
// stuffed zero has x=0 now which ends the loop, meaning we go
// back to regular scan loop.
// repeated 0xff keeps trying to read the next byte of the marker.
}
}
return STBI__MARKER_none;
}
// decode image to YCbCr format // decode image to YCbCr format
static int stbi__decode_jpeg_image(stbi__jpeg *j) static int stbi__decode_jpeg_image(stbi__jpeg *j)
{ {
@@ -3367,25 +3424,22 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j)
if (!stbi__process_scan_header(j)) return 0; if (!stbi__process_scan_header(j)) return 0;
if (!stbi__parse_entropy_coded_data(j)) return 0; if (!stbi__parse_entropy_coded_data(j)) return 0;
if (j->marker == STBI__MARKER_none ) { if (j->marker == STBI__MARKER_none ) {
// handle 0s at the end of image data from IP Kamera 9060 j->marker = stbi__skip_jpeg_junk_at_end(j);
while (!stbi__at_eof(j->s)) {
int x = stbi__get8(j->s);
if (x == 255) {
j->marker = stbi__get8(j->s);
break;
}
}
// if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0
} }
m = stbi__get_marker(j);
if (STBI__RESTART(m))
m = stbi__get_marker(j);
} else if (stbi__DNL(m)) { } else if (stbi__DNL(m)) {
int Ld = stbi__get16be(j->s); int Ld = stbi__get16be(j->s);
stbi__uint32 NL = stbi__get16be(j->s); stbi__uint32 NL = stbi__get16be(j->s);
if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG");
if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG");
} else {
if (!stbi__process_marker(j, m)) return 0;
}
m = stbi__get_marker(j); m = stbi__get_marker(j);
} else {
if (!stbi__process_marker(j, m)) return 1;
m = stbi__get_marker(j);
}
} }
if (j->progressive) if (j->progressive)
stbi__jpeg_finish(j); stbi__jpeg_finish(j);
@@ -3976,6 +4030,7 @@ static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int re
unsigned char* result; unsigned char* result;
stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
if (!j) return stbi__errpuc("outofmem", "Out of memory"); if (!j) return stbi__errpuc("outofmem", "Out of memory");
memset(j, 0, sizeof(stbi__jpeg));
STBI_NOTUSED(ri); STBI_NOTUSED(ri);
j->s = s; j->s = s;
stbi__setup_jpeg(j); stbi__setup_jpeg(j);
@@ -3989,6 +4044,7 @@ static int stbi__jpeg_test(stbi__context *s)
int r; int r;
stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg));
if (!j) return stbi__err("outofmem", "Out of memory"); if (!j) return stbi__err("outofmem", "Out of memory");
memset(j, 0, sizeof(stbi__jpeg));
j->s = s; j->s = s;
stbi__setup_jpeg(j); stbi__setup_jpeg(j);
r = stbi__decode_jpeg_header(j, STBI__SCAN_type); r = stbi__decode_jpeg_header(j, STBI__SCAN_type);
@@ -4014,6 +4070,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
int result; int result;
stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
if (!j) return stbi__err("outofmem", "Out of memory"); if (!j) return stbi__err("outofmem", "Out of memory");
memset(j, 0, sizeof(stbi__jpeg));
j->s = s; j->s = s;
result = stbi__jpeg_info_raw(j, x, y, comp); result = stbi__jpeg_info_raw(j, x, y, comp);
STBI_FREE(j); STBI_FREE(j);
@@ -4121,6 +4178,7 @@ typedef struct
{ {
stbi_uc *zbuffer, *zbuffer_end; stbi_uc *zbuffer, *zbuffer_end;
int num_bits; int num_bits;
int hit_zeof_once;
stbi__uint32 code_buffer; stbi__uint32 code_buffer;
char *zout; char *zout;
@@ -4187,10 +4245,21 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
int b,s; int b,s;
if (a->num_bits < 16) { if (a->num_bits < 16) {
if (stbi__zeof(a)) { if (stbi__zeof(a)) {
return -1; /* report error for unexpected end of data. */ if (!a->hit_zeof_once) {
// This is the first time we hit eof, insert 16 extra padding btis
// to allow us to keep going; if we actually consume any of them
// though, that is invalid data. This is caught later.
a->hit_zeof_once = 1;
a->num_bits += 16; // add 16 implicit zero bits
} else {
// We already inserted our extra 16 padding bits and are again
// out, this stream is actually prematurely terminated.
return -1;
} }
} else {
stbi__fill_bits(a); stbi__fill_bits(a);
} }
}
b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
if (b) { if (b) {
s = b >> 9; s = b >> 9;
@@ -4254,17 +4323,25 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
int len,dist; int len,dist;
if (z == 256) { if (z == 256) {
a->zout = zout; a->zout = zout;
if (a->hit_zeof_once && a->num_bits < 16) {
// The first time we hit zeof, we inserted 16 extra zero bits into our bit
// buffer so the decoder can just do its speculative decoding. But if we
// actually consumed any of those bits (which is the case when num_bits < 16),
// the stream actually read past the end so it is malformed.
return stbi__err("unexpected end","Corrupt PNG");
}
return 1; return 1;
} }
if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data
z -= 257; z -= 257;
len = stbi__zlength_base[z]; len = stbi__zlength_base[z];
if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]);
z = stbi__zhuffman_decode(a, &a->z_distance); z = stbi__zhuffman_decode(a, &a->z_distance);
if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data
dist = stbi__zdist_base[z]; dist = stbi__zdist_base[z];
if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);
if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");
if (zout + len > a->zout_end) { if (len > a->zout_end - zout) {
if (!stbi__zexpand(a, zout, len)) return 0; if (!stbi__zexpand(a, zout, len)) return 0;
zout = a->zout; zout = a->zout;
} }
@@ -4408,6 +4485,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
if (!stbi__parse_zlib_header(a)) return 0; if (!stbi__parse_zlib_header(a)) return 0;
a->num_bits = 0; a->num_bits = 0;
a->code_buffer = 0; a->code_buffer = 0;
a->hit_zeof_once = 0;
do { do {
final = stbi__zreceive(a,1); final = stbi__zreceive(a,1);
type = stbi__zreceive(a,2); type = stbi__zreceive(a,2);
@@ -4563,9 +4641,8 @@ enum {
STBI__F_up=2, STBI__F_up=2,
STBI__F_avg=3, STBI__F_avg=3,
STBI__F_paeth=4, STBI__F_paeth=4,
// synthetic filters used for first scanline to avoid needing a dummy row of 0s // synthetic filter used for first scanline to avoid needing a dummy row of 0s
STBI__F_avg_first, STBI__F_avg_first
STBI__F_paeth_first
}; };
static stbi_uc first_row_filter[5] = static stbi_uc first_row_filter[5] =
@@ -4574,22 +4651,47 @@ static stbi_uc first_row_filter[5] =
STBI__F_sub, STBI__F_sub,
STBI__F_none, STBI__F_none,
STBI__F_avg_first, STBI__F_avg_first,
STBI__F_paeth_first STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub
}; };
static int stbi__paeth(int a, int b, int c) static int stbi__paeth(int a, int b, int c)
{ {
int p = a + b - c; // This formulation looks very different from the reference in the PNG spec, but is
int pa = abs(p-a); // actually equivalent and has favorable data dependencies and admits straightforward
int pb = abs(p-b); // generation of branch-free code, which helps performance significantly.
int pc = abs(p-c); int thresh = c*3 - (a + b);
if (pa <= pb && pa <= pc) return a; int lo = a < b ? a : b;
if (pb <= pc) return b; int hi = a < b ? b : a;
return c; int t0 = (hi <= thresh) ? lo : c;
int t1 = (thresh <= lo) ? hi : t0;
return t1;
} }
static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 };
// adds an extra all-255 alpha channel
// dest == src is legal
// img_n must be 1 or 3
static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n)
{
int i;
// must process data backwards since we allow dest==src
if (img_n == 1) {
for (i=x-1; i >= 0; --i) {
dest[i*2+1] = 255;
dest[i*2+0] = src[i];
}
} else {
STBI_ASSERT(img_n == 3);
for (i=x-1; i >= 0; --i) {
dest[i*4+3] = 255;
dest[i*4+2] = src[i*3+2];
dest[i*4+1] = src[i*3+1];
dest[i*4+0] = src[i*3+0];
}
}
}
// create the png data from post-deflated data // create the png data from post-deflated data
static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
{ {
@@ -4597,6 +4699,8 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
stbi__context *s = a->s; stbi__context *s = a->s;
stbi__uint32 i,j,stride = x*out_n*bytes; stbi__uint32 i,j,stride = x*out_n*bytes;
stbi__uint32 img_len, img_width_bytes; stbi__uint32 img_len, img_width_bytes;
stbi_uc *filter_buf;
int all_ok = 1;
int k; int k;
int img_n = s->img_n; // copy it into a local for later int img_n = s->img_n; // copy it into a local for later
@@ -4608,8 +4712,11 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
if (!a->out) return stbi__err("outofmem", "Out of memory"); if (!a->out) return stbi__err("outofmem", "Out of memory");
// note: error exits here don't need to clean up a->out individually,
// stbi__do_png always does on error.
if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG");
img_width_bytes = (((img_n * x * depth) + 7) >> 3); img_width_bytes = (((img_n * x * depth) + 7) >> 3);
if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG");
img_len = (img_width_bytes + 1) * y; img_len = (img_width_bytes + 1) * y;
// we used to check for exact match between raw_len and img_len on non-interlaced PNGs, // we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
@@ -4617,188 +4724,136 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
// so just check for raw_len < img_len always. // so just check for raw_len < img_len always.
if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
for (j=0; j < y; ++j) { // Allocate two scan lines worth of filter workspace buffer.
stbi_uc *cur = a->out + stride*j; filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0);
stbi_uc *prior; if (!filter_buf) return stbi__err("outofmem", "Out of memory");
int filter = *raw++;
if (filter > 4)
return stbi__err("invalid filter","Corrupt PNG");
// Filtering for low-bit-depth images
if (depth < 8) { if (depth < 8) {
if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG");
cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
filter_bytes = 1; filter_bytes = 1;
width = img_width_bytes; width = img_width_bytes;
} }
prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above
for (j=0; j < y; ++j) {
// cur/prior filter buffers alternate
stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes;
stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes;
stbi_uc *dest = a->out + stride*j;
int nk = width * filter_bytes;
int filter = *raw++;
// check filter type
if (filter > 4) {
all_ok = stbi__err("invalid filter","Corrupt PNG");
break;
}
// if first row, use special filter that doesn't sample previous row // if first row, use special filter that doesn't sample previous row
if (j == 0) filter = first_row_filter[filter]; if (j == 0) filter = first_row_filter[filter];
// handle first byte explicitly // perform actual filtering
for (k=0; k < filter_bytes; ++k) {
switch (filter) { switch (filter) {
case STBI__F_none : cur[k] = raw[k]; break; case STBI__F_none:
case STBI__F_sub : cur[k] = raw[k]; break; memcpy(cur, raw, nk);
case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; break;
case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; case STBI__F_sub:
case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; memcpy(cur, raw, filter_bytes);
case STBI__F_avg_first : cur[k] = raw[k]; break; for (k = filter_bytes; k < nk; ++k)
case STBI__F_paeth_first: cur[k] = raw[k]; break; cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]);
} break;
} case STBI__F_up:
if (depth == 8) {
if (img_n != out_n)
cur[img_n] = 255; // first pixel
raw += img_n;
cur += out_n;
prior += out_n;
} else if (depth == 16) {
if (img_n != out_n) {
cur[filter_bytes] = 255; // first pixel top byte
cur[filter_bytes+1] = 255; // first pixel bottom byte
}
raw += filter_bytes;
cur += output_bytes;
prior += output_bytes;
} else {
raw += 1;
cur += 1;
prior += 1;
}
// this is a little gross, so that we don't switch per-pixel or per-component
if (depth < 8 || img_n == out_n) {
int nk = (width - 1)*filter_bytes;
#define STBI__CASE(f) \
case f: \
for (k = 0; k < nk; ++k) for (k = 0; k < nk; ++k)
switch (filter) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]);
// "none" filter turns into a memcpy here; make that explicit. break;
case STBI__F_none: memcpy(cur, raw, nk); break; case STBI__F_avg:
STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; for (k = 0; k < filter_bytes; ++k)
STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1));
STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; for (k = filter_bytes; k < nk; ++k)
STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1));
STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; break;
STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; case STBI__F_paeth:
for (k = 0; k < filter_bytes; ++k)
cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0)
for (k = filter_bytes; k < nk; ++k)
cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes]));
break;
case STBI__F_avg_first:
memcpy(cur, raw, filter_bytes);
for (k = filter_bytes; k < nk; ++k)
cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1));
break;
} }
#undef STBI__CASE
raw += nk; raw += nk;
// expand decoded bits in cur to dest, also adding an extra alpha channel if desired
if (depth < 8) {
stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
stbi_uc *in = cur;
stbi_uc *out = dest;
stbi_uc inb = 0;
stbi__uint32 nsmp = x*img_n;
// expand bits to bytes first
if (depth == 4) {
for (i=0; i < nsmp; ++i) {
if ((i & 1) == 0) inb = *in++;
*out++ = scale * (inb >> 4);
inb <<= 4;
}
} else if (depth == 2) {
for (i=0; i < nsmp; ++i) {
if ((i & 3) == 0) inb = *in++;
*out++ = scale * (inb >> 6);
inb <<= 2;
}
} else {
STBI_ASSERT(depth == 1);
for (i=0; i < nsmp; ++i) {
if ((i & 7) == 0) inb = *in++;
*out++ = scale * (inb >> 7);
inb <<= 1;
}
}
// insert alpha=255 values if desired
if (img_n != out_n)
stbi__create_png_alpha_expand8(dest, dest, x, img_n);
} else if (depth == 8) {
if (img_n == out_n)
memcpy(dest, cur, x*img_n);
else
stbi__create_png_alpha_expand8(dest, cur, x, img_n);
} else if (depth == 16) {
// convert the image data from big-endian to platform-native
stbi__uint16 *dest16 = (stbi__uint16*)dest;
stbi__uint32 nsmp = x*img_n;
if (img_n == out_n) {
for (i = 0; i < nsmp; ++i, ++dest16, cur += 2)
*dest16 = (cur[0] << 8) | cur[1];
} else { } else {
STBI_ASSERT(img_n+1 == out_n); STBI_ASSERT(img_n+1 == out_n);
#define STBI__CASE(f) \
case f: \
for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
for (k=0; k < filter_bytes; ++k)
switch (filter) {
STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break;
STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break;
STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break;
STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break;
STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break;
STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break;
}
#undef STBI__CASE
// the loop above sets the high byte of the pixels' alpha, but for
// 16 bit png files we also need the low byte set. we'll do that here.
if (depth == 16) {
cur = a->out + stride*j; // start at the beginning of the row again
for (i=0; i < x; ++i,cur+=output_bytes) {
cur[filter_bytes+1] = 255;
}
}
}
}
// we make a separate pass to expand bits to pixels; for performance,
// this could run two scanlines behind the above code, so it won't
// intefere with filtering but will still be in the cache.
if (depth < 8) {
for (j=0; j < y; ++j) {
stbi_uc *cur = a->out + stride*j;
stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes;
// unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit
// png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop
stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
// note that the final byte might overshoot and write more data than desired.
// we can allocate enough data that this never writes out of memory, but it
// could also overwrite the next scanline. can it overwrite non-empty data
// on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel.
// so we need to explicitly clamp the final ones
if (depth == 4) {
for (k=x*img_n; k >= 2; k-=2, ++in) {
*cur++ = scale * ((*in >> 4) );
*cur++ = scale * ((*in ) & 0x0f);
}
if (k > 0) *cur++ = scale * ((*in >> 4) );
} else if (depth == 2) {
for (k=x*img_n; k >= 4; k-=4, ++in) {
*cur++ = scale * ((*in >> 6) );
*cur++ = scale * ((*in >> 4) & 0x03);
*cur++ = scale * ((*in >> 2) & 0x03);
*cur++ = scale * ((*in ) & 0x03);
}
if (k > 0) *cur++ = scale * ((*in >> 6) );
if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03);
if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03);
} else if (depth == 1) {
for (k=x*img_n; k >= 8; k-=8, ++in) {
*cur++ = scale * ((*in >> 7) );
*cur++ = scale * ((*in >> 6) & 0x01);
*cur++ = scale * ((*in >> 5) & 0x01);
*cur++ = scale * ((*in >> 4) & 0x01);
*cur++ = scale * ((*in >> 3) & 0x01);
*cur++ = scale * ((*in >> 2) & 0x01);
*cur++ = scale * ((*in >> 1) & 0x01);
*cur++ = scale * ((*in ) & 0x01);
}
if (k > 0) *cur++ = scale * ((*in >> 7) );
if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01);
if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01);
if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01);
if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01);
if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01);
if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01);
}
if (img_n != out_n) {
int q;
// insert alpha = 255
cur = a->out + stride*j;
if (img_n == 1) { if (img_n == 1) {
for (q=x-1; q >= 0; --q) { for (i = 0; i < x; ++i, dest16 += 2, cur += 2) {
cur[q*2+1] = 255; dest16[0] = (cur[0] << 8) | cur[1];
cur[q*2+0] = cur[q]; dest16[1] = 0xffff;
} }
} else { } else {
STBI_ASSERT(img_n == 3); STBI_ASSERT(img_n == 3);
for (q=x-1; q >= 0; --q) { for (i = 0; i < x; ++i, dest16 += 4, cur += 6) {
cur[q*4+3] = 255; dest16[0] = (cur[0] << 8) | cur[1];
cur[q*4+2] = cur[q*3+2]; dest16[1] = (cur[2] << 8) | cur[3];
cur[q*4+1] = cur[q*3+1]; dest16[2] = (cur[4] << 8) | cur[5];
cur[q*4+0] = cur[q*3+0]; dest16[3] = 0xffff;
}
} }
} }
} }
} }
} else if (depth == 16) {
// force the image data from big-endian to platform-native.
// this is done in a separate pass due to the decoding relying
// on the data being untouched, but could probably be done
// per-line during decode if care is taken.
stbi_uc *cur = a->out;
stbi__uint16 *cur16 = (stbi__uint16*)cur;
for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { STBI_FREE(filter_buf);
*cur16 = (cur[0] << 8) | cur[1]; if (!all_ok) return 0;
}
}
return 1; return 1;
} }
@@ -4955,7 +5010,7 @@ STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)
static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set;
static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set;
STBIDEF void stbi__unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply)
{ {
stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply;
stbi__unpremultiply_on_load_set = 1; stbi__unpremultiply_on_load_set = 1;
@@ -5064,14 +5119,13 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
if (!pal_img_n) { if (!pal_img_n) {
s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0);
if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode");
if (scan == STBI__SCAN_header) return 1;
} else { } else {
// if paletted, then pal_n is our final components, and // if paletted, then pal_n is our final components, and
// img_n is # components to decompress/filter. // img_n is # components to decompress/filter.
s->img_n = 1; s->img_n = 1;
if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG");
// if SCAN_header, have to scan to see if we have a tRNS
} }
// even with SCAN_header, have to scan to see if we have a tRNS
break; break;
} }
@@ -5103,10 +5157,14 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
has_trans = 1; has_trans = 1;
// non-paletted with tRNS = constant alpha. if header-scanning, we can stop now.
if (scan == STBI__SCAN_header) { ++s->img_n; return 1; }
if (z->depth == 16) { if (z->depth == 16) {
for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is for (k = 0; k < s->img_n && k < 3; ++k) // extra loop test to suppress false GCC warning
tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
} else { } else {
for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger for (k = 0; k < s->img_n && k < 3; ++k)
tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
} }
} }
break; break;
@@ -5115,7 +5173,13 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
case STBI__PNG_TYPE('I','D','A','T'): { case STBI__PNG_TYPE('I','D','A','T'): {
if (first) return stbi__err("first not IHDR", "Corrupt PNG"); if (first) return stbi__err("first not IHDR", "Corrupt PNG");
if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG");
if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } if (scan == STBI__SCAN_header) {
// header scan definitely stops at first IDAT
if (pal_img_n)
s->img_n = pal_img_n;
return 1;
}
if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes");
if ((int)(ioff + c.length) < (int)ioff) return 0; if ((int)(ioff + c.length) < (int)ioff) return 0;
if (ioff + c.length > idata_limit) { if (ioff + c.length > idata_limit) {
stbi__uint32 idata_limit_old = idata_limit; stbi__uint32 idata_limit_old = idata_limit;
@@ -5498,8 +5562,22 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
psize = (info.offset - info.extra_read - info.hsz) >> 2; psize = (info.offset - info.extra_read - info.hsz) >> 2;
} }
if (psize == 0) { if (psize == 0) {
if (info.offset != s->callback_already_read + (s->img_buffer - s->img_buffer_original)) { // accept some number of extra bytes after the header, but if the offset points either to before
// the header ends or implies a large amount of extra data, reject the file as malformed
int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original);
int header_limit = 1024; // max we actually read is below 256 bytes currently.
int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size.
if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) {
return stbi__errpuc("bad header", "Corrupt BMP");
}
// we established that bytes_read_so_far is positive and sensible.
// the first half of this test rejects offsets that are either too small positives, or
// negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn
// ensures the number computed in the second half of the test can't overflow.
if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) {
return stbi__errpuc("bad offset", "Corrupt BMP"); return stbi__errpuc("bad offset", "Corrupt BMP");
} else {
stbi__skip(s, info.offset - bytes_read_so_far);
} }
} }
@@ -7187,12 +7265,12 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
// Run // Run
value = stbi__get8(s); value = stbi__get8(s);
count -= 128; count -= 128;
if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
for (z = 0; z < count; ++z) for (z = 0; z < count; ++z)
scanline[i++ * 4 + k] = value; scanline[i++ * 4 + k] = value;
} else { } else {
// Dump // Dump
if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
for (z = 0; z < count; ++z) for (z = 0; z < count; ++z)
scanline[i++ * 4 + k] = stbi__get8(s); scanline[i++ * 4 + k] = stbi__get8(s);
} }
@@ -7446,10 +7524,17 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req
out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0);
if (!out) return stbi__errpuc("outofmem", "Out of memory"); if (!out) return stbi__errpuc("outofmem", "Out of memory");
stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8)); if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) {
STBI_FREE(out);
return stbi__errpuc("bad PNM", "PNM file truncated");
}
if (req_comp && req_comp != s->img_n) { if (req_comp && req_comp != s->img_n) {
if (ri->bits_per_channel == 16) {
out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y);
} else {
out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
}
if (out == NULL) return out; // stbi__convert_format frees input on failure if (out == NULL) return out; // stbi__convert_format frees input on failure
} }
return out; return out;
@@ -7486,6 +7571,8 @@ static int stbi__pnm_getinteger(stbi__context *s, char *c)
while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) {
value = value*10 + (*c - '0'); value = value*10 + (*c - '0');
*c = (char) stbi__get8(s); *c = (char) stbi__get8(s);
if((value > 214748364) || (value == 214748364 && *c > '7'))
return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int");
} }
return value; return value;
@@ -7516,9 +7603,13 @@ static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp)
stbi__pnm_skip_whitespace(s, &c); stbi__pnm_skip_whitespace(s, &c);
*x = stbi__pnm_getinteger(s, &c); // read width *x = stbi__pnm_getinteger(s, &c); // read width
if(*x == 0)
return stbi__err("invalid width", "PPM image header had zero or overflowing width");
stbi__pnm_skip_whitespace(s, &c); stbi__pnm_skip_whitespace(s, &c);
*y = stbi__pnm_getinteger(s, &c); // read height *y = stbi__pnm_getinteger(s, &c); // read height
if (*y == 0)
return stbi__err("invalid width", "PPM image header had zero or overflowing width");
stbi__pnm_skip_whitespace(s, &c); stbi__pnm_skip_whitespace(s, &c);
maxv = stbi__pnm_getinteger(s, &c); // read max value maxv = stbi__pnm_getinteger(s, &c); // read max value

View File

@@ -1,14 +1,15 @@
#include "text.h" #include "text.h"
#include <fstream> // for char_traits, basic_ostream, basic_ifstream, ope... #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <fstream> // for basic_ostream, basic_ifstream, basic_istream
#include <iostream> // for cout #include <iostream> // for cout
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "texture.h" // for Texture #include "texture.h" // for Texture
#include "utils.h" // for color_t #include "utils.h" // for Color
// Llena una estructuta textFile_t desde un fichero // Llena una estructuta TextFile desde un fichero
textFile_t LoadTextFile(std::string file, bool verbose) TextFile LoadTextFile(std::string file_path)
{ {
textFile_t tf; TextFile tf;
// Inicializa a cero el vector con las coordenadas // Inicializa a cero el vector con las coordenadas
for (int i = 0; i < 128; ++i) for (int i = 0; i < 128; ++i)
@@ -16,29 +17,33 @@ textFile_t LoadTextFile(std::string file, bool verbose)
tf.offset[i].x = 0; tf.offset[i].x = 0;
tf.offset[i].y = 0; tf.offset[i].y = 0;
tf.offset[i].w = 0; tf.offset[i].w = 0;
tf.box_width = 0;
tf.box_height = 0;
} }
// Abre el fichero para leer los valores // Abre el fichero para leer los valores
const std::string filename = file.substr(file.find_last_of("\\/") + 1).c_str(); #ifdef VERBOSE
std::ifstream rfile(file); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1).c_str();
#endif
std::ifstream file(file_path);
if (rfile.is_open() && rfile.good()) if (file.is_open() && file.good())
{ {
std::string buffer; std::string buffer;
// Lee los dos primeros valores del fichero // Lee los dos primeros valores del fichero
std::getline(rfile, buffer); std::getline(file, buffer);
std::getline(rfile, buffer); std::getline(file, buffer);
tf.boxWidth = std::stoi(buffer); tf.box_width = std::stoi(buffer);
std::getline(rfile, buffer); std::getline(file, buffer);
std::getline(rfile, buffer); std::getline(file, buffer);
tf.boxHeight = std::stoi(buffer); tf.box_height = std::stoi(buffer);
// lee el resto de datos del fichero // lee el resto de datos del fichero
int index = 32; auto index = 32;
int line_read = 0; auto line_read = 0;
while (std::getline(rfile, buffer)) while (std::getline(file, buffer))
{ {
// Almacena solo las lineas impares // Almacena solo las lineas impares
if (line_read % 2 == 1) if (line_read % 2 == 1)
@@ -52,165 +57,151 @@ textFile_t LoadTextFile(std::string file, bool verbose)
}; };
// Cierra el fichero // Cierra el fichero
if (verbose) #ifdef VERBOSE
{ std::cout << "Text loaded: " << file_name << std::endl;
std::cout << "Text loaded: " << filename.c_str() << std::endl; #endif
} file.close();
rfile.close();
} }
// El fichero no se puede abrir // El fichero no se puede abrir
else else
{ {
if (verbose) #ifdef VERBOSE
{ std::cout << "Warning: Unable to open " << file_name << " file" << std::endl;
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl; #endif
}
} }
// Establece las coordenadas para cada caracter ascii de la cadena y su ancho // Establece las coordenadas para cada caracter ascii de la cadena y su ancho
for (int i = 32; i < 128; ++i) for (int i = 32; i < 128; ++i)
{ {
tf.offset[i].x = ((i - 32) % 15) * tf.boxWidth; tf.offset[i].x = ((i - 32) % 15) * tf.box_width;
tf.offset[i].y = ((i - 32) / 15) * tf.boxHeight; tf.offset[i].y = ((i - 32) / 15) * tf.box_height;
} }
return tf; return tf;
} }
// Constructor // Constructor
Text::Text(std::string bitmapFile, std::string textFile, SDL_Renderer *renderer) Text::Text(const std::string &bitmap_file, const std::string &text_file, SDL_Renderer *renderer)
{ {
// Carga los offsets desde el fichero // Carga los offsets desde el fichero
textFile_t tf = LoadTextFile(textFile); auto tf = LoadTextFile(text_file);
// Inicializa variables desde la estructura // Inicializa variables desde la estructura
boxHeight = tf.boxHeight; box_height_ = tf.box_height;
boxWidth = tf.boxWidth; box_width_ = tf.box_width;
for (int i = 0; i < 128; ++i) for (int i = 0; i < 128; ++i)
{ {
offset[i].x = tf.offset[i].x; offset_[i].x = tf.offset[i].x;
offset[i].y = tf.offset[i].y; offset_[i].y = tf.offset[i].y;
offset[i].w = tf.offset[i].w; offset_[i].w = tf.offset[i].w;
} }
// Crea los objetos // Crea los objetos
texture = new Texture(renderer, bitmapFile); texture_ = std::make_shared<Texture>(renderer, bitmap_file);
sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture); sprite_ = std::make_unique<Sprite>((SDL_Rect){0, 0, box_width_, box_height_}, texture_);
// Inicializa variables // Inicializa variables
fixedWidth = false; fixed_width_ = false;
} }
// Constructor // Constructor
Text::Text(std::string textFile, Texture *texture, SDL_Renderer *renderer) Text::Text(const std::string &text_file, std::shared_ptr<Texture> texture)
{ {
// Carga los offsets desde el fichero // Carga los offsets desde el fichero
textFile_t tf = LoadTextFile(textFile); auto tf = LoadTextFile(text_file);
// Inicializa variables desde la estructura // Inicializa variables desde la estructura
boxHeight = tf.boxHeight; box_height_ = tf.box_height;
boxWidth = tf.boxWidth; box_width_ = tf.box_width;
for (int i = 0; i < 128; ++i) for (int i = 0; i < 128; ++i)
{ {
offset[i].x = tf.offset[i].x; offset_[i].x = tf.offset[i].x;
offset[i].y = tf.offset[i].y; offset_[i].y = tf.offset[i].y;
offset[i].w = tf.offset[i].w; offset_[i].w = tf.offset[i].w;
} }
// Crea los objetos // Crea los objetos
this->texture = nullptr; sprite_ = std::make_unique<Sprite>((SDL_Rect){0, 0, box_width_, box_height_}, texture);
sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture);
// Inicializa variables // Inicializa variables
fixedWidth = false; fixed_width_ = false;
} }
// Constructor // Constructor
Text::Text(textFile_t *textFile, Texture *texture, SDL_Renderer *renderer) Text::Text(TextFile *text_file, std::shared_ptr<Texture> texture)
{ {
// Inicializa variables desde la estructura // Inicializa variables desde la estructura
boxHeight = textFile->boxHeight; box_height_ = text_file->box_height;
boxWidth = textFile->boxWidth; box_width_ = text_file->box_width;
for (int i = 0; i < 128; ++i) for (int i = 0; i < 128; ++i)
{ {
offset[i].x = textFile->offset[i].x; offset_[i].x = text_file->offset[i].x;
offset[i].y = textFile->offset[i].y; offset_[i].y = text_file->offset[i].y;
offset[i].w = textFile->offset[i].w; offset_[i].w = text_file->offset[i].w;
} }
// Crea los objetos // Crea los objetos
this->texture = nullptr; sprite_ = std::make_unique<Sprite>((SDL_Rect){0, 0, box_width_, box_height_}, texture);
sprite = new Sprite({0, 0, boxWidth, boxHeight}, texture);
// Inicializa variables // Inicializa variables
fixedWidth = false; fixed_width_ = false;
}
// Destructor
Text::~Text()
{
delete sprite;
if (texture != nullptr)
{
delete texture;
}
} }
// Escribe texto en pantalla // Escribe texto en pantalla
void Text::write(int x, int y, std::string text, int kerning, int lenght) void Text::write(int x, int y, const std::string &text, int kerning, int lenght)
{ {
int shift = 0; auto shift = 0;
if (lenght == -1) if (lenght == -1)
{ {
lenght = text.length(); lenght = text.length();
} }
sprite->setPosY(y); sprite_->setPosY(y);
const int width = sprite->getWidth(); const auto width = sprite_->getWidth();
const int height = sprite->getHeight(); const auto height = sprite_->getHeight();
for (int i = 0; i < lenght; ++i) for (int i = 0; i < lenght; ++i)
{ {
const int index = text[i]; const auto index = static_cast<int>(text[i]);
sprite->setSpriteClip(offset[index].x, offset[index].y, width, height); sprite_->setSpriteClip(offset_[index].x, offset_[index].y, width, height);
sprite->setPosX(x + shift); sprite_->setPosX(x + shift);
sprite->render(); sprite_->render();
shift += fixedWidth ? boxWidth : (offset[int(text[i])].w + kerning); shift += fixed_width_ ? box_width_ : (offset_[int(text[i])].w + kerning);
} }
} }
// Escribe el texto con colores // Escribe el texto con colores
void Text::writeColored(int x, int y, std::string text, color_t color, int kerning, int lenght) void Text::writeColored(int x, int y, const std::string &text, Color color, int kerning, int lenght)
{ {
sprite->getTexture()->setColor(color.r, color.g, color.b); sprite_->getTexture()->setColor(color.r, color.g, color.b);
write(x, y, text, kerning, lenght); write(x, y, text, kerning, lenght);
sprite->getTexture()->setColor(255, 255, 255); sprite_->getTexture()->setColor(255, 255, 255);
} }
// Escribe el texto con sombra // Escribe el texto con sombra
void Text::writeShadowed(int x, int y, std::string text, color_t color, Uint8 shadowDistance, int kerning, int lenght) void Text::writeShadowed(int x, int y, const std::string &text, Color color, Uint8 shadow_distance, int kerning, int lenght)
{ {
sprite->getTexture()->setColor(color.r, color.g, color.b); sprite_->getTexture()->setColor(color.r, color.g, color.b);
write(x + shadowDistance, y + shadowDistance, text, kerning, lenght); write(x + shadow_distance, y + shadow_distance, text, kerning, lenght);
sprite->getTexture()->setColor(255, 255, 255); sprite_->getTexture()->setColor(255, 255, 255);
write(x, y, text, kerning, lenght); write(x, y, text, kerning, lenght);
} }
// Escribe el texto centrado en un punto x // Escribe el texto centrado en un punto x
void Text::writeCentered(int x, int y, std::string text, int kerning, int lenght) void Text::writeCentered(int x, int y, const std::string &text, int kerning, int lenght)
{ {
x -= (Text::lenght(text, kerning) / 2); x -= (Text::lenght(text, kerning) / 2);
write(x, y, text, kerning, lenght); write(x, y, text, kerning, lenght);
} }
// Escribe texto con extras // Escribe texto con extras
void Text::writeDX(Uint8 flags, int x, int y, std::string text, int kerning, color_t textColor, Uint8 shadowDistance, color_t shadowColor, int lenght) void Text::writeDX(Uint8 flags, int x, int y, const std::string &text, int kerning, Color textColor, Uint8 shadow_distance, Color shadow_color, int lenght)
{ {
const bool centered = ((flags & TXT_CENTER) == TXT_CENTER); const auto centered = ((flags & TEXT_CENTER) == TEXT_CENTER);
const bool shadowed = ((flags & TXT_SHADOW) == TXT_SHADOW); const auto shadowed = ((flags & TEXT_SHADOW) == TEXT_SHADOW);
const bool colored = ((flags & TXT_COLOR) == TXT_COLOR); const auto colored = ((flags & TEXT_COLOR) == TEXT_COLOR);
const bool stroked = ((flags & TXT_STROKE) == TXT_STROKE); const auto stroked = ((flags & TEXT_STROKE) == TEXT_STROKE);
if (centered) if (centered)
{ {
@@ -219,18 +210,18 @@ void Text::writeDX(Uint8 flags, int x, int y, std::string text, int kerning, col
if (shadowed) if (shadowed)
{ {
writeColored(x + shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght); writeColored(x + shadow_distance, y + shadow_distance, text, shadow_color, kerning, lenght);
} }
if (stroked) if (stroked)
{ {
for (int dist = 1; dist <= shadowDistance; ++dist) for (int dist = 1; dist <= shadow_distance; ++dist)
{ {
for (int dy = -dist; dy <= dist; ++dy) for (int dy = -dist; dy <= dist; ++dy)
{ {
for (int dx = -dist; dx <= dist; ++dx) for (int dx = -dist; dx <= dist; ++dx)
{ {
writeColored(x + dx, y + dy, text, shadowColor, kerning, lenght); writeColored(x + dx, y + dy, text, shadow_color, kerning, lenght);
} }
} }
} }
@@ -247,43 +238,45 @@ void Text::writeDX(Uint8 flags, int x, int y, std::string text, int kerning, col
} }
// Obtiene la longitud en pixels de una cadena // Obtiene la longitud en pixels de una cadena
int Text::lenght(std::string text, int kerning) int Text::lenght(const std::string &text, int kerning) const
{ {
int shift = 0; auto shift = 0;
for (int i = 0; i < (int)text.length(); ++i) for (int i = 0; i < (int)text.length(); ++i)
shift += (offset[int(text[i])].w + kerning); {
shift += (offset_[int(text[i])].w + kerning);
}
// Descuenta el kerning del último caracter // Descuenta el kerning del último caracter
return shift - kerning; return shift - kerning;
} }
// Devuelve el valor de la variable // Devuelve el valor de la variable
int Text::getCharacterSize() int Text::getCharacterSize() const
{ {
return boxWidth; return box_width_;
} }
// Recarga la textura // Recarga la textura
void Text::reLoadTexture() void Text::reLoadTexture()
{ {
sprite->getTexture()->reLoad(); sprite_->getTexture()->reLoad();
} }
// Establece si se usa un tamaño fijo de letra // Establece si se usa un tamaño fijo de letra
void Text::setFixedWidth(bool value) void Text::setFixedWidth(bool value)
{ {
fixedWidth = value; fixed_width_ = value;
} }
// Carga una paleta de colores para el texto // Carga una paleta de colores para el texto
void Text::addPalette(std::string path) void Text::addPalette(const std::string &path)
{ {
texture->addPalette(path); texture_->addPalette(path);
} }
// Establece una paleta de colores para el texto // Establece una paleta de colores para el texto
void Text::setPalette(int index) void Text::setPalette(int index)
{ {
texture->setPalette(index); texture_->setPalette(index);
} }

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