Compare commits

26 Commits

Author SHA1 Message Date
2cb22ed013 fix: els globos tenien un parell de setters mal asignats per culpa de buscar y reemplazar
fix: els globos verds s'inicialitzaven amb vy = 0 per gastar abs en lloc de fabs
fix: corregit un bug milenari que de sempre havia creat els balloons verds al popar al pare amb la meitat de velocitat en y. Lo que jo no se es com anava res. Supose que ara el joc serà un poc mes xungo. Quan rebotaven en el piso ja se'ls posava la velocitat bona (crec)
2024-10-20 22:58:15 +02:00
a3a583deb7 Precàrrega dels fitxers amb dades per al mode demostració 2024-10-20 21:23:04 +02:00
b263e0c4be Modificada la estructura on es guarden els datos de la demo 2024-10-20 20:43:03 +02:00
3bf61fc758 fix: no guardar el fitxer de puntuacions en el modo demo 2024-10-20 19:40:09 +02:00
2377815c02 Amb les textures en memoria i compartides ja no puc fer el trick de canvi de paleta per a la flama del segon jugador tal i com està plantejat el codi. Arreglat creant una segona textura 2024-10-20 19:38:28 +02:00
7434869894 Corregit un fallo amagat baix un ifdef ARCADE. Ja he posat que estiga definit per defecte pa que no torne a passar 2024-10-20 15:43:10 +02:00
848d61b5c0 He fet un "manolete" i he pasat a c++ i smartpointers la cárrega de surfaces desde gif. Sembla que no ha petat res
Precárrega i asignació de paletes a les textures
Ara si algú toca una paleta, que siga conscient que la textura es compartida durant tot el joc
2024-10-20 15:36:04 +02:00
cbc9b3f071 Eliminats els últimes defines i passats a enum class 2024-10-20 12:07:55 +02:00
8bca5095da Modificats, estructurats i ben formatats alguns missatges de consola
Canvis en els codis d'eixida del programa
2024-10-20 11:37:26 +02:00
a4b4e188cd Precàrrega de tots els recursos al inici del joc
8.000.000 de cherrypickings que he anat fent pel codi
2024-10-20 11:06:10 +02:00
f23dcae5b6 Creada la classe Resource
Afegida la musica i els sons a Resource
2024-10-19 10:07:14 +02:00
b879673bc2 Mes merdes que faltaven del merge 2024-10-18 17:10:06 +02:00
a8701dbebc Merge branch 'main' of https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis_arcade_edition 2024-10-18 16:53:53 +02:00
afe835914e Revisada la carrega de recursos en game.cpp 2024-10-18 14:07:25 +02:00
808f1595e9 Treballant en la càrrega de animacions desde fitxers 2024-10-17 21:02:28 +02:00
8e8346b2ab Li he demanat a la IA que revente Game::checkInput() que aixo si que era un monstruo amb sombreret i pajarita 2024-10-17 20:05:26 +02:00
1da8f33a5e Llevats tots els ifdef VERBOSE i redirigit cout a null_stream 2024-10-17 19:31:44 +02:00
50a376e582 Comença a estar tot mes o menos be el desaguisao de les classes Sprite. Encara algunes animacions sembla que van massa ràpides 2024-10-17 19:26:39 +02:00
59de566c5b commit de acabar la jornada laboral 2024-10-17 13:57:41 +02:00
db884cb422 Commit de vesprà tirada a la brossa 2024-10-16 22:35:19 +02:00
5585f996cb A vore si el helper ja funciona com toca 2024-10-16 13:29:16 +02:00
24556eeaa8 Implementat contador per a posar el nom al acabar la partida 2024-10-16 09:18:22 +02:00
dbffda491f Retocat l'aspecte visual de les notificacions 2024-10-15 22:56:24 +02:00
53f5f3f8b0 Ja comprova la notificació d'eixir per diferenciarla de la resta
En ARCADE la notificació diferencia si vas a eixir o a apagar el sistema
2024-10-15 20:40:45 +02:00
e0faa0890e Afegides noves cadenes de text 2024-10-15 20:12:16 +02:00
de6508c37c Don Melitonitzada la classe Notifier e independitzada de la classe Screen
Ara es poden afegir codis a les notificacions per identificarles
2024-10-15 20:09:09 +02:00
85 changed files with 3046 additions and 3030 deletions

View File

@@ -1,11 +1,12 @@
## GAME ## GAME
game.item_size 20 game.item_size 20 # Tamaño de los items del juego
game.width 320 game.width 320 # Ancho de la resolucion nativa del juego
game.height 240 game.height 240 # Alto de la resolucion nativa del juego
game.play_area.rect.x 0 game.play_area.rect.x 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.y 0 game.play_area.rect.y 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.w 320 game.play_area.rect.w 320 # Rectangulo con la posición de la zona de juego
game.play_area.rect.h 200 game.play_area.rect.h 200 # Rectangulo con la posición de la zona de juego
game.enter_name_seconds 30 # Duración en segundos para introducir el nombre al finalizar la partida
## FADE ## FADE
fade.num_squares_width 160 fade.num_squares_width 160

View File

@@ -1,11 +1,12 @@
## GAME ## GAME
game.item_size 20 game.item_size 20 # Tamaño de los items del juego
game.width 320 game.width 320 # Ancho de la resolucion nativa del juego
game.height 256 game.height 256 # Alto de la resolucion nativa del juego
game.play_area.rect.x 0 game.play_area.rect.x 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.y 0 game.play_area.rect.y 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.w 320 game.play_area.rect.w 320 # Rectangulo con la posición de la zona de juego
game.play_area.rect.h 216 game.play_area.rect.h 216 # Rectangulo con la posición de la zona de juego
game.enter_name_seconds 30 # Duración en segundos para introducir el nombre al finalizar la partida
## FADE ## FADE
fade.num_squares_width 160 fade.num_squares_width 160

View File

Before

Width:  |  Height:  |  Size: 84 B

After

Width:  |  Height:  |  Size: 84 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 944 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 B

View File

@@ -281,7 +281,7 @@ MODE FORA DE LINEA
TAULER DE PUNTS TAULER DE PUNTS
## 94 - NOTIFICACIONES ## 94 - NOTIFICACIONES
Torna a polsar per eixir ... Torna a polsar per eixir
## 95 - DEFINE BUTTONS ## 95 - DEFINE BUTTONS
Disparar cap a l'esquerra Disparar cap a l'esquerra
@@ -345,3 +345,6 @@ Per favor
## 115 - MARCADOR ## 115 - MARCADOR
espere espere
## 116 - NOTIFICACIONES
Torna a polsar per apagar el sistema

View File

@@ -345,3 +345,6 @@ Please
## 115 - MARCADOR ## 115 - MARCADOR
wait wait
## 116 - NOTIFICACIONES
Press again to shutdown system

View File

@@ -345,3 +345,6 @@ Por favor
## 115 - MARCADOR ## 115 - MARCADOR
espere espere
## 94 - NOTIFICACIONES
Pulsa otra vez para apagar el sistema

View File

@@ -5,188 +5,56 @@
#include <iterator> // for back_insert_iterator, back_inserter #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
#include "utils.h"
// Carga la animación desde un fichero // Carga las animaciones en un vector(Animations) desde un fichero
AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string file_path) Animations loadAnimationsFromFile(const std::string &file_path)
{ {
// Inicializa variables std::vector<std::string> buffer;
AnimatedFile af;
af.texture = texture;
auto frames_per_row = 0;
auto frame_width = 0;
auto frame_height = 0;
auto max_tiles = 0;
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
std::ifstream file(file_path); std::ifstream file(file_path);
std::string line; if (!file)
// El fichero se puede abrir
if (file.good())
{ {
// Procesa el fichero linea a linea std::cerr << "Error: Fichero no encontrado " << file_path << std::endl;
#ifdef VERBOSE throw std::runtime_error("Fichero no encontrado: " + file_path);
std::cout << "Animation loaded: " << file_name << std::endl; }
#endif
std::string line;
printWithDots("Animation : ", file_path.substr(file_path.find_last_of("\\/") + 1), "[ LOADED ]");
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 buffer.push_back(line);
if (line == "[animation]")
{
Animation buffer;
buffer.counter = 0;
buffer.current_frame = 0;
buffer.completed = false;
buffer.name.clear();
buffer.speed = 5;
buffer.loop = 0;
buffer.frames.clear();
do
{
std::getline(file, line);
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != static_cast<int>(line.npos))
{
if (line.substr(0, pos) == "name")
{
buffer.name = line.substr(pos + 1, line.length());
} }
else if (line.substr(0, pos) == "speed") return buffer;
{
buffer.speed = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "loop")
{
buffer.loop = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frames")
{
// Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length()));
std::string tmp;
SDL_Rect rect = {0, 0, frame_width, frame_height};
while (getline(ss, tmp, ','))
{
// Comprueba que el tile no sea mayor que el maximo indice permitido
const auto num_tile = std::stoi(tmp) > max_tiles ? 0 : std::stoi(tmp);
rect.x = (num_tile % frames_per_row) * frame_width;
rect.y = (num_tile / frames_per_row) * frame_height;
buffer.frames.push_back(rect);
}
}
else
{
#ifdef VERBOSE
std::cout << "Warning: file " << file_name.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
#endif
}
}
} while (line != "[/animation]");
// Añade la animación al vector de animaciones
af.animations.push_back(buffer);
}
// En caso contrario se parsea el fichero para buscar las variables y los valores
else
{
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "frames_per_row")
{
frames_per_row = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_width")
{
frame_width = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_height")
{
frame_height = std::stoi(line.substr(pos + 1, line.length()));
}
else
{
#ifdef VERBOSE
std::cout << "Warning: file " << file_name.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
#endif
}
// Normaliza valores
if (frames_per_row == 0 && frame_width > 0)
{
frames_per_row = texture->getWidth() / frame_width;
}
if (max_tiles == 0 && frame_width > 0 && frame_height > 0)
{
const auto w = texture->getWidth() / frame_width;
const auto h = texture->getHeight() / frame_height;
max_tiles = w * h;
}
}
}
}
// Cierra el fichero
file.close();
}
// El fichero no se puede abrir
else
{
#ifdef VERBOSE
std::cout << "Warning: Unable to open " << file_name.c_str() << " file" << std::endl;
#endif
}
return af;
} }
// Constructor // Constructor
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file, std::vector<std::string> *buffer) AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path)
: MovingSprite(texture), : MovingSprite(texture),
current_animation_(0) current_animation_(0)
{ {
// Carga las animaciones // Carga las animaciones
if (!file.empty()) if (!file_path.empty())
{ {
AnimatedFile as = loadAnimationFromFile(texture, file); animations_ = loadFromFile(file_path);
// Copia los datos de las animaciones
std::copy(as.animations.begin(), as.animations.end(), std::back_inserter(animations_));
} }
}
else if (buffer) AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const Animations &animations)
: MovingSprite(texture),
current_animation_(0)
{
if (!animations.empty())
{ {
loadFromVector(buffer); loadFromVector(animations);
} }
} }
// Constructor // Constructor
AnimatedSprite::AnimatedSprite(const AnimatedFile *animation) AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture)
: MovingSprite(animation->texture), : MovingSprite(texture),
current_animation_(0) current_animation_(0) {}
{
// Copia los datos de las animaciones
std::copy(animation->animations.begin(), animation->animations.end(), std::back_inserter(animations_));
}
// Destructor // Destructor
AnimatedSprite::~AnimatedSprite() AnimatedSprite::~AnimatedSprite()
@@ -207,9 +75,7 @@ int AnimatedSprite::getIndex(const 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;
} }
@@ -333,152 +199,6 @@ SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF)
return animations_[indexA].frames[indexF]; return animations_[indexA].frames[indexF];
} }
// Carga la animación desde un vector
bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
{
// Inicializa variables
auto frames_per_row = 0;
auto frame_width = 0;
auto frame_height = 0;
auto max_tiles = 0;
// Indicador de éxito en el proceso
auto success = true;
std::string line;
// Recorre todo el vector
auto index = 0;
while (index < (int)source->size())
{
// Lee desde el vector
line = source->at(index);
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
Animation buffer;
buffer.counter = 0;
buffer.current_frame = 0;
buffer.completed = false;
buffer.name.clear();
buffer.speed = 5;
buffer.loop = 0;
buffer.frames.clear();
do
{
// Aumenta el indice para leer la siguiente linea
index++;
line = source->at(index);
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != static_cast<int>(line.npos))
{
if (line.substr(0, pos) == "name")
{
buffer.name = line.substr(pos + 1, line.length());
}
else if (line.substr(0, pos) == "speed")
{
buffer.speed = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "loop")
{
buffer.loop = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frames")
{
// Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length()));
std::string tmp;
SDL_Rect rect = {0, 0, frame_width, frame_height};
while (getline(ss, tmp, ','))
{
// Comprueba que el tile no sea mayor que el maximo indice permitido
const int num_tile = std::stoi(tmp) > max_tiles ? 0 : std::stoi(tmp);
rect.x = (num_tile % frames_per_row) * frame_width;
rect.y = (num_tile / frames_per_row) * frame_height;
buffer.frames.push_back(rect);
}
}
else
{
#ifdef VERBOSE
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
#endif
success = false;
}
}
} while (line != "[/animation]");
// Añade la animación al vector de animaciones
animations_.push_back(buffer);
}
// En caso contrario se parsea el fichero para buscar las variables y los valores
else
{
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "frames_per_row")
{
frames_per_row = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_width")
{
frame_width = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_height")
{
frame_height = std::stoi(line.substr(pos + 1, line.length()));
}
else
{
#ifdef VERBOSE
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
#endif
success = false;
}
// Normaliza valores
if (frames_per_row == 0 && frame_width > 0)
{
frames_per_row = texture_->getWidth() / frame_width;
}
if (max_tiles == 0 && frame_width > 0 && frame_height > 0)
{
const int w = texture_->getWidth() / frame_width;
const int h = texture_->getHeight() / frame_height;
max_tiles = w * h;
}
}
}
// Una vez procesada la linea, aumenta el indice para pasar a la siguiente
index++;
}
// Pone un valor por defecto
setPos((SDL_Rect){0, 0, frame_width, frame_height});
return success;
}
// Establece la animacion actual // Establece la animacion actual
void AnimatedSprite::setCurrentAnimation(const std::string &name) void AnimatedSprite::setCurrentAnimation(const std::string &name)
{ {
@@ -534,3 +254,278 @@ void AnimatedSprite::resetAnimation()
animations_[current_animation_].counter = 0; animations_[current_animation_].counter = 0;
animations_[current_animation_].completed = false; animations_[current_animation_].completed = false;
} }
// Carga la animación desde un fichero
std::vector<Animation> AnimatedSprite::loadFromFile(const std::string &file_path)
{
// Inicializa variables
std::vector<Animation> animations;
auto frames_per_row = 0;
auto frame_width = 0;
auto frame_height = 0;
auto max_tiles = 0;
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
std::ifstream file(file_path);
std::string line;
// El fichero se puede abrir
if (file.good())
{
// Procesa el fichero linea a linea
std::cout << "Animation loaded: " << file_name << std::endl;
while (std::getline(file, line))
{
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
Animation animation = Animation();
do
{
std::getline(file, line);
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != static_cast<int>(line.npos))
{
if (line.substr(0, pos) == "name")
{
animation.name = line.substr(pos + 1, line.length());
}
else if (line.substr(0, pos) == "speed")
{
animation.speed = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "loop")
{
animation.loop = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frames")
{
// Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length()));
std::string tmp;
SDL_Rect rect = {0, 0, frame_width, frame_height};
while (getline(ss, tmp, ','))
{
// Comprueba que el tile no sea mayor que el maximo indice permitido
const auto num_tile = std::stoi(tmp) > max_tiles ? 0 : std::stoi(tmp);
rect.x = (num_tile % frames_per_row) * frame_width;
rect.y = (num_tile / frames_per_row) * frame_height;
animation.frames.push_back(rect);
}
}
else
{
std::cout << "Warning: file " << file_name.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
}
}
} while (line != "[/animation]");
// Añade la animación al vector de animaciones
animations.push_back(animation);
}
// En caso contrario se parsea el fichero para buscar las variables y los valores
else
{
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "frames_per_row")
{
frames_per_row = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_width")
{
frame_width = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_height")
{
frame_height = std::stoi(line.substr(pos + 1, line.length()));
}
else
{
std::cout << "Warning: file " << file_name.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
}
// Normaliza valores
if (frames_per_row == 0 && frame_width > 0)
{
frames_per_row = texture_->getWidth() / frame_width;
}
if (max_tiles == 0 && frame_width > 0 && frame_height > 0)
{
const auto w = texture_->getWidth() / frame_width;
const auto h = texture_->getHeight() / frame_height;
max_tiles = w * h;
}
}
}
}
// Cierra el fichero
file.close();
}
// El fichero no se puede abrir
else
{
std::cout << "Warning: Unable to open " << file_name.c_str() << " file" << std::endl;
}
// Pone un valor por defecto
setWidth(frame_width);
setHeight(frame_height);
return animations;
}
// Carga la animación desde un vector
bool AnimatedSprite::loadFromVector(const Animations &source)
{
// Inicializa variables
auto frames_per_row = 0;
auto frame_width = 0;
auto frame_height = 0;
auto max_tiles = 0;
// Indicador de éxito en el proceso
auto success = true;
std::string line;
// Recorre todo el vector
auto index = 0;
while (index < (int)source.size())
{
// Lee desde el vector
line = source.at(index);
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
Animation animation = Animation();
do
{
// Aumenta el indice para leer la siguiente linea
index++;
line = source.at(index);
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != static_cast<int>(line.npos))
{
if (line.substr(0, pos) == "name")
{
animation.name = line.substr(pos + 1, line.length());
}
else if (line.substr(0, pos) == "speed")
{
animation.speed = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "loop")
{
animation.loop = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frames")
{
// Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length()));
std::string tmp;
SDL_Rect rect = {0, 0, frame_width, frame_height};
while (getline(ss, tmp, ','))
{
// Comprueba que el tile no sea mayor que el maximo indice permitido
const int num_tile = std::stoi(tmp) > max_tiles ? 0 : std::stoi(tmp);
rect.x = (num_tile % frames_per_row) * frame_width;
rect.y = (num_tile / frames_per_row) * frame_height;
animation.frames.push_back(rect);
}
}
else
{
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
success = false;
}
}
} while (line != "[/animation]");
// Añade la animación al vector de animaciones
animations_.push_back(animation);
}
// En caso contrario se parsea el fichero para buscar las variables y los valores
else
{
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "frames_per_row")
{
frames_per_row = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_width")
{
frame_width = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frame_height")
{
frame_height = std::stoi(line.substr(pos + 1, line.length()));
}
else
{
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
success = false;
}
// Normaliza valores
if (frames_per_row == 0 && frame_width > 0)
{
frames_per_row = texture_->getWidth() / frame_width;
}
if (max_tiles == 0 && frame_width > 0 && frame_height > 0)
{
const int w = texture_->getWidth() / frame_width;
const int h = texture_->getHeight() / frame_height;
max_tiles = w * h;
}
}
}
// Una vez procesada la linea, aumenta el indice para pasar a la siguiente
index++;
}
// Pone un valor por defecto
setWidth(frame_width);
setHeight(frame_height);
return success;
}

View File

@@ -17,16 +17,14 @@ struct Animation
bool completed; // Indica si ha finalizado la animación bool completed; // Indica si ha finalizado la animación
int current_frame; // Frame actual int current_frame; // Frame actual
int counter; // Contador para las animaciones int counter; // Contador para las animaciones
Animation() : name(std::string()), speed(5), loop(0), completed(false), current_frame(0), counter(0) {}
}; };
struct AnimatedFile using Animations = std::vector<std::string>;
{
std::vector<Animation> animations; // Vector con las diferentes animaciones
std::shared_ptr<Texture> texture; // Textura con los graficos para el sprite
};
// Carga la animación desde un fichero // Carga las animaciones en un vector(Animations) desde un fichero
AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string filePath); Animations loadAnimationsFromFile(const std::string &file_path);
class AnimatedSprite : public MovingSprite class AnimatedSprite : public MovingSprite
{ {
@@ -35,16 +33,26 @@ protected:
std::vector<Animation> animations_; // Vector con las diferentes animaciones std::vector<Animation> animations_; // Vector con las diferentes animaciones
int current_animation_; // Animacion activa int current_animation_; // Animacion activa
// Calcula el frame correspondiente a la animación actual
void animate();
// Carga la animación desde un fichero
std::vector<Animation> loadFromFile(const std::string &file_path);
// Carga la animación desde un vector
bool loadFromVector(const Animations &source);
public: public:
// Constructor // Constructor
explicit AnimatedSprite(std::shared_ptr<Texture> texture = nullptr, const std::string &file = std::string(), std::vector<std::string> *buffer = nullptr); AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path);
explicit AnimatedSprite(const AnimatedFile *animation); AnimatedSprite(std::shared_ptr<Texture> texture, const Animations &animations);
explicit AnimatedSprite(std::shared_ptr<Texture> texture);
// Destructor // Destructor
virtual ~AnimatedSprite(); virtual ~AnimatedSprite();
// Calcula el frame correspondiente a la animación actual // Actualiza las variables del objeto
void animate(); void update() override;
// Obtiene el número de frames de la animación actual // Obtiene el número de frames de la animación actual
int getNumFrames(); int getNumFrames();
@@ -77,16 +85,10 @@ public:
// Obtiene el indice de la animación a partir del nombre // Obtiene el indice de la animación a partir del nombre
int getIndex(const std::string &name); int getIndex(const std::string &name);
// Carga la animación desde un vector
bool loadFromVector(std::vector<std::string> *source);
// Establece la animacion actual // Establece la animacion actual
void setCurrentAnimation(const std::string &name = "default"); void setCurrentAnimation(const std::string &name = "default");
void setCurrentAnimation(int index = 0); void setCurrentAnimation(int index = 0);
// Actualiza las variables del objeto
void update() 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

@@ -1,4 +1,5 @@
#include "asset.h" #include "asset.h"
#include "utils.h"
#include <SDL2/SDL_rwops.h> // for SDL_RWFromFile, SDL_RWclose, SDL_RWops #include <SDL2/SDL_rwops.h> // for SDL_RWFromFile, SDL_RWclose, SDL_RWops
#include <SDL2/SDL_stdinc.h> // for SDL_max #include <SDL2/SDL_stdinc.h> // for SDL_max
#include <stddef.h> // for size_t #include <stddef.h> // for size_t
@@ -59,9 +60,7 @@ std::string Asset::get(const std::string &text) const
} }
} }
#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 "";
} }
@@ -70,12 +69,10 @@ bool Asset::check() const
{ {
bool success = true; bool success = true;
#ifdef VERBOSE std::cout << "\n** CHECKING FILES" << std::endl;
std::cout << "\n** Checking files" << std::endl;
std::cout << "Executable path is: " << executable_path_ << std::endl; // std::cout << "Executable path is: " << executable_path_ << std::endl;
std::cout << "Sample filepath: " << file_list_.back().file << std::endl; // std::cout << "Sample filepath: " << file_list_.back().file << std::endl;
#endif
// Comprueba la lista de ficheros clasificandolos por tipo // Comprueba la lista de ficheros clasificandolos por tipo
for (int type = 0; type < static_cast<int>(AssetType::MAX_ASSET_TYPE); ++type) for (int type = 0; type < static_cast<int>(AssetType::MAX_ASSET_TYPE); ++type)
@@ -94,9 +91,7 @@ bool Asset::check() const
// Si hay ficheros de ese tipo, comprueba si existen // Si hay ficheros de ese tipo, comprueba si existen
if (any) if (any)
{ {
#ifdef VERBOSE
std::cout << "\n>> " << getTypeName(static_cast<AssetType>(type)).c_str() << " FILES" << std::endl; std::cout << "\n>> " << getTypeName(static_cast<AssetType>(type)).c_str() << " FILES" << std::endl;
#endif
for (const auto &f : file_list_) for (const auto &f : file_list_)
{ {
@@ -105,13 +100,13 @@ bool Asset::check() const
success &= checkFile(f.file); success &= checkFile(f.file);
} }
} }
if (success)
std::cout << " All files are OK." << std::endl;
} }
} }
// Resultado // Resultado
#ifdef VERBOSE std::cout << (success ? "\n** CHECKING FILES COMPLETED.\n" : "\n** CHECKING FILES FAILED.\n") << std::endl;
std::cout << (success ? "\n** All files OK.\n" : "\n** A file is missing. Exiting.\n") << std::endl;
#endif
return success; return success;
} }
@@ -130,15 +125,9 @@ bool Asset::checkFile(const std::string &path) const
SDL_RWclose(file); SDL_RWclose(file);
} }
#ifdef VERBOSE
const std::string file_name = path.substr(path.find_last_of("\\/") + 1); const std::string file_name = path.substr(path.find_last_of("\\/") + 1);
std::cout.setf(std::ios::left, std::ios::adjustfield); if (!success)
std::cout << "Checking file: "; printWithDots("Checking file : ", file_name, (success ? " [ OK ]" : " [ ERROR ]"));
std::cout.width(longest_name_ + 2);
std::cout.fill('.');
std::cout << file_name;
std::cout << (success ? " [OK]" : " [ERROR]") << std::endl;
#endif
return success; return success;
} }

View File

@@ -5,34 +5,37 @@
#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
#include "resource.h" // for Resource
#include "screen.h"
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "texture.h" // for Texture #include "texture.h" // for Texture
// Constructor // Constructor
Background::Background(SDL_Renderer *renderer) Background::Background()
: renderer_(renderer), : renderer_(Screen::get()->getRenderer()),
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"))), buildings_texture_(Resource::get()->getTexture("game_buildings.png")),
bottom_clouds_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_clouds2.png"))), top_clouds_texture_(Resource::get()->getTexture("game_clouds1.png")),
grass_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_grass.png"))), bottom_clouds_texture_(Resource::get()->getTexture("game_clouds2.png")),
gradients_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_sky_colors.png"))) grass_texture_(Resource::get()->getTexture("game_grass.png")),
gradients_texture_(Resource::get()->getTexture("game_sky_colors.png")),
gradient_number_(0),
alpha_(0),
clouds_speed_(0),
transition_(0),
counter_(0),
rect_({0, 0, gradients_texture_->getWidth() / 2, gradients_texture_->getHeight() / 2}),
src_rect_({0, 0, 320, 240}),
dst_rect_({0, 0, 320, 240}),
base_(rect_.h),
color_({param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b}),
alpha_color_text_(param.background.attenuate_alpha),
alpha_color_text_temp_(param.background.attenuate_alpha)
{ {
// Inicializa variables // Inicializa variables
gradient_number_ = 0; {
alpha_ = 0;
clouds_speed_ = 0;
transition_ = 0;
counter_ = 0;
rect_ = {0, 0, gradients_texture_->getWidth() / 2, gradients_texture_->getHeight() / 2};
src_rect_ = {0, 0, 320, 240};
dst_rect_ = {0, 0, 320, 240};
base_ = rect_.h;
color_ = {param.background.attenuate_color.r, param.background.attenuate_color.g, param.background.attenuate_color.b};
alpha_color_text_ = alpha_color_text_temp_ = param.background.attenuate_alpha;
gradient_rect_[0] = {0, 0, rect_.w, rect_.h}; gradient_rect_[0] = {0, 0, rect_.w, rect_.h};
gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h}; gradient_rect_[1] = {rect_.w, 0, rect_.w, rect_.h};
gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h}; gradient_rect_[2] = {0, rect_.h, rect_.w, rect_.h};
@@ -45,36 +48,51 @@ Background::Background(SDL_Renderer *renderer)
top_clouds_rect_[i] = {0, i * top_clouds_texture_height, top_clouds_texture_->getWidth(), top_clouds_texture_height}; top_clouds_rect_[i] = {0, i * top_clouds_texture_height, top_clouds_texture_->getWidth(), top_clouds_texture_height};
bottom_clouds_rect_[i] = {0, i * bottom_clouds_texture_height, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_height}; bottom_clouds_rect_[i] = {0, i * bottom_clouds_texture_height, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_height};
} }
}
// Crea los sprites // Crea los sprites
{
const int top_clouds_y = base_ - 165; const int top_clouds_y = base_ - 165;
const int bottom_clouds_y = base_ - 101; const int bottom_clouds_y = base_ - 101;
constexpr float top_clouds_speed = 0.1f;
constexpr float bottom_clouds_speed = 0.05f;
top_clouds_sprite_a_ = std::make_unique<MovingSprite>(0, top_clouds_y, rect_.w, top_clouds_texture_->getHeight(), -top_clouds_speed, 0.0f, 0.0f, 0.0f, top_clouds_texture_);
top_clouds_sprite_b_ = std::make_unique<MovingSprite>(rect_.w, top_clouds_y, rect_.w, top_clouds_texture_->getHeight(), -top_clouds_speed, 0.0f, 0.0f, 0.0f, top_clouds_texture_);
bottom_clouds_sprite_a_ = std::make_unique<MovingSprite>(0, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight(), -bottom_clouds_speed, 0.0f, 0.0f, 0.0f, bottom_clouds_texture_); top_clouds_sprite_a_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_Rect){0, top_clouds_y, rect_.w, top_clouds_texture_->getHeight()});
bottom_clouds_sprite_b_ = std::make_unique<MovingSprite>(rect_.w, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight(), -bottom_clouds_speed, 0.0f, 0.0f, 0.0f, bottom_clouds_texture_); top_clouds_sprite_b_ = std::make_unique<MovingSprite>(top_clouds_texture_, (SDL_Rect){rect_.w, top_clouds_y, rect_.w, top_clouds_texture_->getHeight()});
buildings_sprite_ = std::make_unique<Sprite>(0, 0, buildings_texture_->getWidth(), buildings_texture_->getHeight(), buildings_texture_); bottom_clouds_sprite_a_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_Rect){0, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight()});
gradient_sprite_ = std::make_unique<Sprite>(0, 0, rect_.w, rect_.h, gradients_texture_); bottom_clouds_sprite_b_ = std::make_unique<MovingSprite>(bottom_clouds_texture_, (SDL_Rect){rect_.w, bottom_clouds_y, rect_.w, bottom_clouds_texture_->getHeight()});
grass_sprite_ = std::make_unique<Sprite>(0, 0, grass_texture_->getWidth(), grass_texture_->getHeight() / 2, grass_texture_);
buildings_sprite_ = std::make_unique<Sprite>(buildings_texture_, 0, 0, buildings_texture_->getWidth(), buildings_texture_->getHeight());
gradient_sprite_ = std::make_unique<Sprite>(gradients_texture_, 0, 0, rect_.w, rect_.h);
grass_sprite_ = std::make_unique<Sprite>(grass_texture_, 0, 0, grass_texture_->getWidth(), grass_texture_->getHeight() / 2);
}
// Inicializa objetos // Inicializa objetos
{
constexpr float top_clouds_speed = 0.1f;
constexpr float bottom_clouds_speed = 0.05f;
top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight()); top_clouds_sprite_a_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
top_clouds_sprite_a_->setVelX(-top_clouds_speed);
top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight()); top_clouds_sprite_b_->setSpriteClip(0, 0, top_clouds_texture_->getWidth(), top_clouds_texture_->getHeight());
top_clouds_sprite_b_->setVelX(-top_clouds_speed);
bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight()); bottom_clouds_sprite_a_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
bottom_clouds_sprite_a_->setVelX(-bottom_clouds_speed);
bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight()); bottom_clouds_sprite_b_->setSpriteClip(0, 0, bottom_clouds_texture_->getWidth(), bottom_clouds_texture_->getHeight());
buildings_sprite_->setPosY(base_ - buildings_sprite_->getHeight()); bottom_clouds_sprite_b_->setVelX(-bottom_clouds_speed);
grass_sprite_->setPosY(base_ - grass_sprite_->getHeight());
buildings_sprite_->setY(base_ - buildings_sprite_->getHeight());
grass_sprite_->setY(base_ - grass_sprite_->getHeight());
}
// Crea la textura para componer el fondo // Crea la textura para componer el fondo
canvas_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h); canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(canvas_, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(canvas_, SDL_BLENDMODE_BLEND);
// Crea la textura para atenuar el fondo // Crea la textura para atenuar el fondo
color_texture_ = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h); color_texture_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(color_texture_, SDL_BLENDMODE_BLEND);
setColor(color_); setColor(color_);
SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_); SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_);
@@ -103,7 +121,7 @@ void Background::update()
alpha_ = std::max((255 - (int)(255 * transition_)), 0); alpha_ = std::max((255 - (int)(255 * transition_)), 0);
// Incrementa el contador // Incrementa el contador
counter_++; ++counter_;
// Compone todos los elementos del fondo en la textura // Compone todos los elementos del fondo en la textura
fillCanvas(); fillCanvas();
@@ -297,10 +315,10 @@ void Background::updateClouds()
bottom_clouds_sprite_b_->setVelX(clouds_speed_ / 2); bottom_clouds_sprite_b_->setVelX(clouds_speed_ / 2);
// Mueve las nubes // Mueve las nubes
top_clouds_sprite_a_->move(); top_clouds_sprite_a_->update();
top_clouds_sprite_b_->move(); top_clouds_sprite_b_->update();
bottom_clouds_sprite_a_->move(); bottom_clouds_sprite_a_->update();
bottom_clouds_sprite_b_->move(); bottom_clouds_sprite_b_->update();
// Calcula el offset de las nubes // Calcula el offset de las nubes
if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth()) if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth())

View File

@@ -107,7 +107,7 @@ private:
public: public:
// Constructor // Constructor
explicit Background(SDL_Renderer *renderer); Background();
// Destructor // Destructor
~Background(); ~Background();

View File

@@ -1,14 +1,14 @@
#include "balloon.h" #include "balloon.h"
#include <cmath> // for abs #include <cmath> // for abs
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for SpriteAnimated
#include "moving_sprite.h" // for MovingSprite #include "moving_sprite.h" // for MovingSprite
#include "param.h" // for param #include "param.h" // for param
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "texture.h" // for Texture #include "texture.h" // for Texture
// Constructor // Constructor
Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr<Texture> texture, std::vector<std::string> *animation) Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
: sprite_(std::make_unique<AnimatedSprite>(texture, "", animation)), : sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
pos_x_(x), pos_x_(x),
pos_y_(y), pos_y_(y),
vel_x_(vel_x), vel_x_(vel_x),
@@ -121,10 +121,10 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 1; power_ = 1;
// Inicializa los valores de velocidad y gravedad // Inicializa los valores de velocidad y gravedad
vel_y_ = abs(vel_x) * 2; vel_y_ = fabs(vel_x_ * 2.0f);
max_vel_y_ = abs(vel_x) * 2; max_vel_y_ = vel_y_;
gravity_ = 0.00f; gravity_ = 0.00f;
default_vel_y_ = abs(vel_x) * 2; default_vel_y_ = vel_y_;
// Puntos que da el globo al ser destruido // Puntos que da el globo al ser destruido
score_ = BALLOON_SCORE_1; score_ = BALLOON_SCORE_1;
@@ -142,10 +142,10 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 3; power_ = 3;
// Inicializa los valores de velocidad y gravedad // Inicializa los valores de velocidad y gravedad
vel_y_ = abs(vel_x) * 2; vel_y_ = fabs(vel_x_ * 2.0f);
max_vel_y_ = abs(vel_x) * 2; max_vel_y_ = vel_y_;
gravity_ = 0.00f; gravity_ = 0.00f;
default_vel_y_ = abs(vel_x) * 2; default_vel_y_ = vel_y_;
// Puntos que da el globo al ser destruido // Puntos que da el globo al ser destruido
score_ = BALLOON_SCORE_2; score_ = BALLOON_SCORE_2;
@@ -163,10 +163,10 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 7; power_ = 7;
// Inicializa los valores de velocidad y gravedad // Inicializa los valores de velocidad y gravedad
vel_y_ = abs(vel_x) * 2; vel_y_ = fabs(vel_x_ * 2.0f);
max_vel_y_ = abs(vel_x) * 2; max_vel_y_ = vel_y_;
gravity_ = 0.00f; gravity_ = 0.00f;
default_vel_y_ = abs(vel_x) * 2; default_vel_y_ = vel_y_;
// Puntos que da el globo al ser destruido // Puntos que da el globo al ser destruido
score_ = BALLOON_SCORE_3; score_ = BALLOON_SCORE_3;
@@ -184,10 +184,10 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 15; power_ = 15;
// Inicializa los valores de velocidad y gravedad // Inicializa los valores de velocidad y gravedad
vel_y_ = abs(vel_x) * 2; vel_y_ = fabs(vel_x_ * 2.0f);
max_vel_y_ = abs(vel_x) * 2; max_vel_y_ = vel_y_;
gravity_ = 0.00f; gravity_ = 0.00f;
default_vel_y_ = abs(vel_x) * 2; default_vel_y_ = vel_y_;
// Puntos que da el globo al ser destruido // Puntos que da el globo al ser destruido
score_ = BALLOON_SCORE_4; score_ = BALLOON_SCORE_4;
@@ -217,7 +217,7 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
menace_ = 0; menace_ = 0;
// Añade rotación al sprite_ // Añade rotación al sprite_
sprite_->setRotate(false); sprite_->disableRotate();
sprite_->setRotateSpeed(0); sprite_->setRotateSpeed(0);
vel_x_ > 0.0f ? sprite_->setRotateAmount(2.0) : sprite_->setRotateAmount(-2.0); vel_x_ > 0.0f ? sprite_->setRotateAmount(2.0) : sprite_->setRotateAmount(-2.0);
@@ -238,13 +238,8 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
bouncing_.w = {1.10f, 1.05f, 1.00f, 0.95f, 0.90f, 0.95f, 1.00f, 1.02f, 1.05f, 1.02f}; bouncing_.w = {1.10f, 1.05f, 1.00f, 0.95f, 0.90f, 0.95f, 1.00f, 1.02f, 1.05f, 1.02f};
bouncing_.h = {0.90f, 0.95f, 1.00f, 1.05f, 1.10f, 1.05f, 1.00f, 0.98f, 0.95f, 0.98f}; bouncing_.h = {0.90f, 0.95f, 1.00f, 1.05f, 1.10f, 1.05f, 1.00f, 0.98f, 0.95f, 0.98f};
// Alto y ancho del sprite_ // Configura el sprite
sprite_->setWidth(width_); sprite_->setPos({static_cast<int>(pos_x_), static_cast<int>(pos_y_), width_, height_});
sprite_->setHeight(height_);
// Posición X,Y del sprite_
sprite_->setPosX((int)pos_x_);
sprite_->setPosY((int)pos_y_);
// Tamaño del circulo de colisión // Tamaño del circulo de colisión
collider_.r = width_ / 2; collider_.r = width_ / 2;
@@ -306,7 +301,7 @@ void Balloon::render()
if (kind_ == POWER_BALL && !isBeingCreated()) if (kind_ == POWER_BALL && !isBeingCreated())
{ {
auto sp = std::make_unique<Sprite>(sprite_->getPos(), sprite_->getTexture()); auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
sp->setSpriteClip(BALLOON_WIDTH_4, 0, BALLOON_WIDTH_4, BALLOON_WIDTH_4); sp->setSpriteClip(BALLOON_WIDTH_4, 0, BALLOON_WIDTH_4, BALLOON_WIDTH_4);
sp->render(); sp->render();
} }
@@ -396,10 +391,6 @@ void Balloon::move()
// Aplica la gravedad al objeto sin pasarse de una velocidad máxima // Aplica la gravedad al objeto sin pasarse de una velocidad máxima
vel_y_ += gravity_; vel_y_ += gravity_;
// Al parecer esta asignación se quedó sin hacer y ahora el juego no funciona
// correctamente si se aplica, así que se deja sin efecto
// vel_y_ = std::min(vel_y_, max_vel_y_);
} }
// Actualiza la posición del sprite_ // Actualiza la posición del sprite_
@@ -454,13 +445,13 @@ void Balloon::update()
{ {
if (enabled_) if (enabled_)
{ {
sprite_->MovingSprite::update(); sprite_->update();
move(); move();
updateAnimation(); updateAnimation();
updateColliders(); updateColliders();
updateState(); updateState();
updateBounce(); updateBounce();
counter_++; ++counter_;
} }
} }
@@ -510,7 +501,7 @@ void Balloon::updateState()
setInvulnerable(false); setInvulnerable(false);
if (kind_ == POWER_BALL) if (kind_ == POWER_BALL)
{ {
sprite_->setRotate(true); sprite_->enableRotate();
} }
} }
} }
@@ -520,7 +511,7 @@ void Balloon::updateState()
// Si es una powerball deja de rodar // Si es una powerball deja de rodar
if (kind_ == POWER_BALL) if (kind_ == POWER_BALL)
{ {
sprite_->setRotate(false); sprite_->disableRotate();
} }
// Reduce el contador // Reduce el contador
@@ -536,7 +527,7 @@ void Balloon::updateState()
// Si es una powerball vuelve a rodar // Si es una powerball vuelve a rodar
if (kind_ == POWER_BALL) if (kind_ == POWER_BALL)
{ {
sprite_->setRotate(true); sprite_->enableRotate();
} }
} }
} }
@@ -569,7 +560,7 @@ void Balloon::updateAnimation()
sprite_->setCurrentAnimation(normal_animation); sprite_->setCurrentAnimation(normal_animation);
} }
sprite_->animate(); sprite_->update();
} }
// Comprueba si el globo está habilitado // Comprueba si el globo está habilitado
@@ -609,15 +600,15 @@ int Balloon::getHeight() const
} }
// Establece el valor de la variable // Establece el valor de la variable
void Balloon::setVelY(float vel_y_) void Balloon::setVelY(float vel_y)
{ {
this->vel_y_ = vel_y_; vel_y_ = vel_y;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Balloon::setSpeed(float speed_) void Balloon::setSpeed(float speed)
{ {
this->speed_ = speed_; speed_ = speed;
} }
// Obtiene del valor de la variable // Obtiene del valor de la variable

View File

@@ -4,7 +4,7 @@
#include <memory> // for shared_ptr, unique_ptr #include <memory> // for shared_ptr, unique_ptr
#include <string> // for string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for SpriteAnimated
#include "utils.h" // for Circle #include "utils.h" // for Circle
class Texture; class Texture;
@@ -141,7 +141,7 @@ private:
public: public:
// Constructor // Constructor
Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr<Texture> texture, std::vector<std::string> *animation); Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation);
// Destructor // Destructor
~Balloon() = default; ~Balloon() = default;

View File

@@ -37,15 +37,11 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[i].number_of_balloons = 0; balloon_formation_[i].number_of_balloons = 0;
for (int j = 0; j < MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION; j++) 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] = BalloonFormationParams();
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; constexpr int CREATION_TIME = 300;
int inc_x = 0; int inc_x = 0;
int inc_time = 0; int inc_time = 0;
int j = 0; int j = 0;
@@ -61,7 +57,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y4; 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].vel_x = BALLOON_VELX_NEGATIVE * (((i % 2) * 2) - 1);
balloon_formation_[j].init[i].kind = BALLOON_4; balloon_formation_[j].init[i].kind = BALLOON_4;
balloon_formation_[j].init[i].creation_counter = creation_time + (inc_time * i); 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 // #01 - Dos enemigos BALLOON4 uno a cada cuarto. Ambos van hacia el centro
@@ -75,7 +71,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y4; 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].vel_x = BALLOON_VELX_NEGATIVE * (((i % 2) * 2) - 1);
balloon_formation_[j].init[i].kind = BALLOON_4; balloon_formation_[j].init[i].kind = BALLOON_4;
balloon_formation_[j].init[i].creation_counter = creation_time + (inc_time * i); 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 // #02 - Cuatro enemigos BALLOON2 uno detras del otro. A la izquierda y hacia el centro
@@ -89,7 +85,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y2; balloon_formation_[j].init[i].y = y2;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_2; balloon_formation_[j].init[i].kind = BALLOON_2;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); 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 // #03 - Cuatro enemigos BALLOON2 uno detras del otro. A la derecha y hacia el centro
@@ -103,7 +99,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y2; balloon_formation_[j].init[i].y = y2;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_2; balloon_formation_[j].init[i].kind = BALLOON_2;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
} }
// #04 - Tres enemigos BALLOON3. 0, 25, 50. Hacia la derecha // #04 - Tres enemigos BALLOON3. 0, 25, 50. Hacia la derecha
@@ -117,7 +113,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y3; balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_3; balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
} }
// #05 - Tres enemigos BALLOON3. 50, 75, 100. Hacia la izquierda // #05 - Tres enemigos BALLOON3. 50, 75, 100. Hacia la izquierda
@@ -131,7 +127,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y3; balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_3; balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
} }
// #06 - Tres enemigos BALLOON3. 0, 0, 0. Hacia la derecha // #06 - Tres enemigos BALLOON3. 0, 0, 0. Hacia la derecha
@@ -145,7 +141,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y3; balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_3; balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
} }
// #07 - Tres enemigos BALLOON3. 100, 100, 100. Hacia la izquierda // #07 - Tres enemigos BALLOON3. 100, 100, 100. Hacia la izquierda
@@ -159,7 +155,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y3; balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_3; balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); 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 // #08 - Seis enemigos BALLOON1. 0, 0, 0, 0, 0, 0. Hacia la derecha
@@ -173,7 +169,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y1; balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_1; balloon_formation_[j].init[i].kind = BALLOON_1;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); 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 // #09 - Seis enemigos BALLOON1. 100, 100, 100, 100, 100, 100. Hacia la izquierda
@@ -187,7 +183,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y1; balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_1; balloon_formation_[j].init[i].kind = BALLOON_1;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
} }
// #10 - Tres enemigos BALLOON4 seguidos desde la izquierda // #10 - Tres enemigos BALLOON4 seguidos desde la izquierda
@@ -201,7 +197,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y4; balloon_formation_[j].init[i].y = y4;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_4; balloon_formation_[j].init[i].kind = BALLOON_4;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
} }
// #11 - Tres enemigos BALLOON4 seguidos desde la derecha // #11 - Tres enemigos BALLOON4 seguidos desde la derecha
@@ -215,7 +211,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y4; balloon_formation_[j].init[i].y = y4;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_4; balloon_formation_[j].init[i].kind = BALLOON_4;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); 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 // #12 - Seis enemigos BALLOON2 uno detras del otro. A la izquierda y hacia el centro
@@ -229,7 +225,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y2; balloon_formation_[j].init[i].y = y2;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_2; balloon_formation_[j].init[i].kind = BALLOON_2;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); 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 // #13 - Seis enemigos BALLOON2 uno detras del otro. A la derecha y hacia el centro
@@ -243,7 +239,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y2; balloon_formation_[j].init[i].y = y2;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_2; balloon_formation_[j].init[i].kind = BALLOON_2;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
} }
// #14 - Cinco enemigos BALLOON3. Hacia la derecha. Separados // #14 - Cinco enemigos BALLOON3. Hacia la derecha. Separados
@@ -257,7 +253,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y3; balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_3; balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
} }
// #15 - Cinco enemigos BALLOON3. Hacia la izquierda. Separados // #15 - Cinco enemigos BALLOON3. Hacia la izquierda. Separados
@@ -271,7 +267,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y3; balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_3; balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
} }
// #16 - Cinco enemigos BALLOON3. Hacia la derecha. Juntos // #16 - Cinco enemigos BALLOON3. Hacia la derecha. Juntos
@@ -285,7 +281,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y3; balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_3; balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
} }
// #17 - Cinco enemigos BALLOON3. Hacia la izquierda. Juntos // #17 - Cinco enemigos BALLOON3. Hacia la izquierda. Juntos
@@ -299,7 +295,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y3; balloon_formation_[j].init[i].y = y3;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_3; balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
} }
// #18 - Doce enemigos BALLOON1. Hacia la derecha. Juntos // #18 - Doce enemigos BALLOON1. Hacia la derecha. Juntos
@@ -313,7 +309,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y1; balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_1; balloon_formation_[j].init[i].kind = BALLOON_1;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
} }
// #19 - Doce enemigos BALLOON1. Hacia la izquierda. Juntos // #19 - Doce enemigos BALLOON1. Hacia la izquierda. Juntos
@@ -327,7 +323,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y1; balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_1; balloon_formation_[j].init[i].kind = BALLOON_1;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
} }
// #20 - Dos enemigos BALLOON4 seguidos desde la izquierda/derecha. Simetricos // #20 - Dos enemigos BALLOON4 seguidos desde la izquierda/derecha. Simetricos
@@ -350,7 +346,7 @@ void BalloonFormations::initBalloonFormations()
} }
balloon_formation_[j].init[i].y = y4; balloon_formation_[j].init[i].y = y4;
balloon_formation_[j].init[i].kind = BALLOON_4; balloon_formation_[j].init[i].kind = BALLOON_4;
balloon_formation_[j].init[i].creation_counter = creation_time + (inc_time * i); balloon_formation_[j].init[i].creation_counter = CREATION_TIME + (inc_time * i);
} }
// #21 - Diez enemigos BALLOON2 uno detras del otro. Izquierda/derecha. Simetricos // #21 - Diez enemigos BALLOON2 uno detras del otro. Izquierda/derecha. Simetricos
@@ -365,13 +361,13 @@ void BalloonFormations::initBalloonFormations()
{ {
balloon_formation_[j].init[i].x = x2_0 + (i * inc_x); 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].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) - (inc_time * i); balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * i);
} }
else else
{ {
balloon_formation_[j].init[i].x = x2_100 - ((i - half) * inc_x); 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].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) - (inc_time * (i - half)); 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].y = y2;
balloon_formation_[j].init[i].kind = BALLOON_2; balloon_formation_[j].init[i].kind = BALLOON_2;
@@ -389,13 +385,13 @@ void BalloonFormations::initBalloonFormations()
{ {
balloon_formation_[j].init[i].x = x3_0 + (i * inc_x); 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].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) - (inc_time * i); balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * i);
} }
else else
{ {
balloon_formation_[j].init[i].x = x3_100 - ((i - half) * inc_x); 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].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) - (inc_time * (i - half)); 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].y = y3;
balloon_formation_[j].init[i].kind = BALLOON_3; balloon_formation_[j].init[i].kind = BALLOON_3;
@@ -413,13 +409,13 @@ void BalloonFormations::initBalloonFormations()
{ {
balloon_formation_[j].init[i].x = x3_0 + (i * inc_x); 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].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) - (inc_time * i); balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * i);
} }
else else
{ {
balloon_formation_[j].init[i].x = x3_100 - ((i - half) * inc_x); 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].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) - (inc_time * (i - half)); 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].y = y3;
balloon_formation_[j].init[i].kind = BALLOON_3; balloon_formation_[j].init[i].kind = BALLOON_3;
@@ -436,13 +432,13 @@ void BalloonFormations::initBalloonFormations()
{ {
balloon_formation_[j].init[i].x = x1_50; balloon_formation_[j].init[i].x = x1_50;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) + (inc_time * i); balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) + (inc_time * i);
} }
else else
{ {
balloon_formation_[j].init[i].x = x1_50; balloon_formation_[j].init[i].x = x1_50;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE; 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].creation_counter = (CREATION_TIME) + (inc_time * (i - half));
} }
balloon_formation_[j].init[i].y = y1; balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].kind = BALLOON_1; balloon_formation_[j].init[i].kind = BALLOON_1;
@@ -459,13 +455,13 @@ void BalloonFormations::initBalloonFormations()
{ {
balloon_formation_[j].init[i].x = x1_50 + 20; balloon_formation_[j].init[i].x = x1_50 + 20;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE; balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) - (inc_time * i); balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * i);
} }
else else
{ {
balloon_formation_[j].init[i].x = x1_50 - 20; balloon_formation_[j].init[i].x = x1_50 - 20;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE; 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].creation_counter = (CREATION_TIME) - (inc_time * (i - half));
} }
balloon_formation_[j].init[i].y = y1; balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].kind = BALLOON_1; balloon_formation_[j].init[i].kind = BALLOON_1;

View File

@@ -6,11 +6,15 @@ constexpr int MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION = 50;
// Estructuras // Estructuras
struct BalloonFormationParams struct BalloonFormationParams
{ {
int x; // Posición en el eje X donde crear al enemigo int x = 0; // Posición en el eje X donde crear al enemigo
int y; // Posición en el eje Y donde crear al enemigo int y = 0; // Posición en el eje Y donde crear al enemigo
float vel_x; // Velocidad inicial en el eje X float vel_x = 0.0f; // Velocidad inicial en el eje X
int kind; // Tipo de enemigo int kind = 0; // Tipo de enemigo
int creation_counter; // Temporizador para la creación del enemigo int creation_counter = 0; // Temporizador para la creación del enemigo
// Constructor que inicializa todos los campos con valores proporcionados o predeterminados
BalloonFormationParams(int x_val = 0, int y_val = 0, float vel_x_val = 0.0f, int kind_val = 0, int creation_counter_val = 0)
: x(x_val), y(y_val), vel_x(vel_x_val), kind(kind_val), creation_counter(creation_counter_val) {}
}; };
struct BalloonFormationUnit // Contiene la información de una formación enemiga struct BalloonFormationUnit // Contiene la información de una formación enemiga

View File

@@ -12,7 +12,7 @@ constexpr int BULLET_VELX_RIGHT = 2;
// Constructor // Constructor
Bullet::Bullet(int x, int y, BulletType kind, bool powered_up, int owner, SDL_Rect *play_area, std::shared_ptr<Texture> texture) Bullet::Bullet(int x, int y, BulletType kind, bool powered_up, int owner, SDL_Rect *play_area, std::shared_ptr<Texture> texture)
: sprite_(std::make_unique<Sprite>(SDL_Rect{x, y, BULLET_WIDTH, BULLET_HEIGHT}, texture)), : sprite_(std::make_unique<Sprite>(texture, SDL_Rect{x, y, BULLET_WIDTH, BULLET_HEIGHT})),
pos_x_(x), pos_x_(x),
pos_y_(y), pos_y_(y),
width_(BULLET_WIDTH), width_(BULLET_WIDTH),
@@ -57,8 +57,8 @@ BulletMoveStatus Bullet::move()
return BulletMoveStatus::OUT; return BulletMoveStatus::OUT;
} }
sprite_->setPosX(pos_x_); sprite_->setX(pos_x_);
sprite_->setPosY(pos_y_); sprite_->setY(pos_y_);
shiftColliders(); shiftColliders();
return BulletMoveStatus::OK; return BulletMoveStatus::OK;

View File

@@ -106,7 +106,7 @@ void DefineButtons::checkInput()
case SDL_QUIT: case SDL_QUIT:
{ {
section::name = section::Name::QUIT; section::name = section::Name::QUIT;
section::options = section::Options::QUIT_NORMAL; section::options = section::Options::QUIT_WITH_KEYBOARD;
break; break;
} }
@@ -157,7 +157,7 @@ void DefineButtons::incIndexButton()
// Guarda los cambios en las opciones // Guarda los cambios en las opciones
saveBindingsToOptions(); saveBindingsToOptions();
//input_->allActive(index_controller_); // input_->allActive(index_controller_);
// Reinicia variables // Reinicia variables
index_button_ = 0; index_button_ = 0;

View File

@@ -30,9 +30,11 @@
#include "lang.h" // for Code, loadFromFile #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 "notifier.h" // for Notifier
#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 "resource.h" //for Resource
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options #include "section.h" // for Name, name, Options, options
#include "title.h" // for Title #include "title.h" // for Title
@@ -54,6 +56,14 @@ Director::Director(int argc, const char *argv[])
section::name = section::Name::LOGO; section::name = section::Name::LOGO;
#endif #endif
#ifndef VERBOSE
// Deshabilita todos los std::cout
std::ostream null_stream(nullptr);
orig_buf = std::cout.rdbuf(null_stream.rdbuf());
#endif
std::cout << "Game start" << std::endl;
// Comprueba los parametros del programa // Comprueba los parametros del programa
checkProgramArguments(argc, argv); checkProgramArguments(argc, argv);
@@ -64,11 +74,8 @@ Director::Director(int argc, const char *argv[])
// Crea el objeto que controla los ficheros de recursos // Crea el objeto que controla los ficheros de recursos
Asset::init(executable_path_); Asset::init(executable_path_);
// Si falta algún fichero no inicia el programa // Crea el indice de ficheros
if (!setFileList()) setFileList();
{
exit(EXIT_FAILURE);
}
// Carga el fichero de configuración // Carga el fichero de configuración
loadOptionsFile(Asset::get()->get("config.txt")); loadOptionsFile(Asset::get()->get("config.txt"));
@@ -97,19 +104,18 @@ Director::Director(int argc, const char *argv[])
// Crea los objetos // Crea los objetos
lang::loadFromFile(getLangFile((lang::Code)options.game.language)); lang::loadFromFile(getLangFile((lang::Code)options.game.language));
Input::init(Asset::get()->get("gamecontrollerdb.txt"));
initInput();
Screen::init(window_, renderer_); Screen::init(window_, renderer_);
Resource::init();
Input::init(Asset::get()->get("gamecontrollerdb.txt"));
bindInputs();
auto notifier_text = std::make_shared<Text>(Resource::get()->getTexture("8bithud.png"), Resource::get()->getTextFile("8bithud.txt"));
Notifier::init(std::string(), notifier_text, Asset::get()->get("notify.wav"));
OnScreenHelp::init(); OnScreenHelp::init();
// Carga los sonidos del juego
loadSounds();
// Carga las musicas del juego
loadMusics();
globalInputs::init(); globalInputs::init();
} }
@@ -118,25 +124,23 @@ Director::~Director()
saveOptionsFile(Asset::get()->get("config.txt")); saveOptionsFile(Asset::get()->get("config.txt"));
Asset::destroy(); Asset::destroy();
Resource::destroy();
Input::destroy(); Input::destroy();
Screen::destroy(); Screen::destroy();
Notifier::destroy();
OnScreenHelp::destroy(); OnScreenHelp::destroy();
sounds_.clear();
musics_.clear();
SDL_DestroyRenderer(renderer_); SDL_DestroyRenderer(renderer_);
SDL_DestroyWindow(window_); SDL_DestroyWindow(window_);
SDL_Quit(); SDL_Quit();
std::cout << "\nBye!" << std::endl;
} }
/// Inicializa el objeto input // Asigna los botones y teclas al objeto Input
void Director::initInput() void Director::bindInputs()
{ {
// Busca si hay mandos conectados
Input::get()->discoverGameControllers();
// Teclado - Movimiento del jugador // Teclado - Movimiento del jugador
Input::get()->bindKey(InputType::UP, SDL_SCANCODE_UP); Input::get()->bindKey(InputType::UP, SDL_SCANCODE_UP);
Input::get()->bindKey(InputType::DOWN, SDL_SCANCODE_DOWN); Input::get()->bindKey(InputType::DOWN, SDL_SCANCODE_DOWN);
@@ -244,9 +248,7 @@ bool Director::initSDL()
// Inicializa SDL // Inicializa SDL
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{ {
#ifdef VERBOSE
std::cout << "SDL could not initialize!\nSDL Error: " << SDL_GetError() << std::endl; std::cout << "SDL could not initialize!\nSDL Error: " << SDL_GetError() << std::endl;
#endif
success = false; success = false;
} }
else else
@@ -254,7 +256,6 @@ bool Director::initSDL()
// Inicia el generador de numeros aleatorios // Inicia el generador de numeros aleatorios
std::srand(static_cast<unsigned int>(SDL_GetTicks())); std::srand(static_cast<unsigned int>(SDL_GetTicks()));
#ifdef VERBOSE
// Muestra información de la pantalla // Muestra información de la pantalla
/*std::cout << "\nDisplay modes list:" << std::endl; /*std::cout << "\nDisplay modes list:" << std::endl;
for (int i = 0; i < SDL_GetNumDisplayModes(0); ++i) for (int i = 0; i < SDL_GetNumDisplayModes(0); ++i)
@@ -268,30 +269,23 @@ bool Director::initSDL()
SDL_GetCurrentDisplayMode(0, &DM); SDL_GetCurrentDisplayMode(0, &DM);
std::cout << "\nCurrent display mode: " + std::to_string(DM.w) + "x" + std::to_string(DM.h) + " @ " + std::to_string(DM.refresh_rate) + "Hz" << std::endl; std::cout << "\nCurrent display mode: " + std::to_string(DM.w) + "x" + std::to_string(DM.h) + " @ " + std::to_string(DM.refresh_rate) + "Hz" << std::endl;
std::cout << "Window resolution : " + std::to_string(param.game.width) + "x" + std::to_string(param.game.height) + " x" + std::to_string(options.video.window.size) << std::endl; std::cout << "Window resolution : " + std::to_string(param.game.width) + "x" + std::to_string(param.game.height) + " x" + std::to_string(options.video.window.size) << std::endl;
#endif
// Establece el filtro de la textura // Establece el filtro de la textura
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, std::to_string(static_cast<int>(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
std::cout << "Warning: texture filtering not enabled!\n"; std::cout << "Warning: texture filtering not enabled!\n";
#endif
} }
#ifndef NO_SHADERS #ifndef NO_SHADERS
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl")) if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"))
{ {
#ifdef VERBOSE
std::cout << "Warning: opengl not enabled!\n"; std::cout << "Warning: opengl not enabled!\n";
#endif // VERBOSE
} }
#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_) if (!window_)
{ {
#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;
#endif
success = false; success = false;
} }
else else
@@ -310,9 +304,7 @@ bool Director::initSDL()
if (!renderer_) if (!renderer_)
{ {
#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;
#endif
success = false; success = false;
} }
else else
@@ -330,14 +322,12 @@ bool Director::initSDL()
} }
} }
#ifdef VERBOSE
std::cout << std::endl; std::cout << std::endl;
#endif
return success; return success;
} }
// Crea el indice de ficheros // Crea el indice de ficheros
bool Director::setFileList() void Director::setFileList()
{ {
#ifdef MACOS_BUNDLE #ifdef MACOS_BUNDLE
const std::string prefix = "/../Resources"; const std::string prefix = "/../Resources";
@@ -381,8 +371,12 @@ bool Director::setFileList()
Asset::get()->add(prefix + "/data/shaders/crtpi.glsl", AssetType::DATA); Asset::get()->add(prefix + "/data/shaders/crtpi.glsl", AssetType::DATA);
// Texturas // Texturas
Asset::get()->add(prefix + "/data/gfx/controllers/controllers.png", AssetType::BITMAP);
{ // Controllers
Asset::get()->add(prefix + "/data/gfx/controllers/controllers.png", AssetType::BITMAP);
}
{ // Balloons
Asset::get()->add(prefix + "/data/gfx/balloon/balloon1.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/balloon/balloon1.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon1.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/balloon/balloon1.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon2.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/balloon/balloon2.png", AssetType::BITMAP);
@@ -391,7 +385,9 @@ bool Director::setFileList()
Asset::get()->add(prefix + "/data/gfx/balloon/balloon3.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/balloon/balloon3.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon4.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/balloon/balloon4.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon4.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/balloon/balloon4.ani", AssetType::ANIMATION);
}
{ // Explosions
Asset::get()->add(prefix + "/data/gfx/balloon/explosion1.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/balloon/explosion1.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion1.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/balloon/explosion1.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion2.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/balloon/explosion2.png", AssetType::BITMAP);
@@ -400,31 +396,45 @@ bool Director::setFileList()
Asset::get()->add(prefix + "/data/gfx/balloon/explosion3.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/balloon/explosion3.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion4.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/balloon/explosion4.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion4.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/balloon/explosion4.ani", AssetType::ANIMATION);
}
{ // Power Ball
Asset::get()->add(prefix + "/data/gfx/balloon/powerball.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/balloon/powerball.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/powerball.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/balloon/powerball.ani", AssetType::ANIMATION);
}
{ // Bala
Asset::get()->add(prefix + "/data/gfx/bullet/bullet.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/bullet/bullet.png", AssetType::BITMAP);
}
{ // Juego
Asset::get()->add(prefix + "/data/gfx/game/game_buildings.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/game/game_buildings.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_clouds1.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/game/game_clouds1.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_clouds2.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/game/game_clouds2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_grass.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/game/game_grass.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_power_meter.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/game/game_power_meter.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_sky_colors.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/game/game_sky_colors.png", AssetType::BITMAP);
}
{ // Game Text
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_1000_points.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/game_text/game_text_1000_points.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_2500_points.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/game_text/game_text_2500_points.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_5000_points.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/game_text/game_text_5000_points.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_powerup.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/game_text/game_text_powerup.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_one_hit.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/game_text/game_text_one_hit.png", AssetType::BITMAP);
}
{ // Intro
Asset::get()->add(prefix + "/data/gfx/intro/intro.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/intro/intro.png", AssetType::BITMAP);
}
{ // Logo
Asset::get()->add(prefix + "/data/gfx/logo/logo_jailgames.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/logo/logo_jailgames.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/logo/logo_jailgames_mini.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/logo/logo_jailgames_mini.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/logo/logo_since_1998.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/logo/logo_since_1998.png", AssetType::BITMAP);
}
{ // Items
Asset::get()->add(prefix + "/data/gfx/item/item_points1_disk.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/item/item_points1_disk.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_points1_disk.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/item/item_points1_disk.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_points2_gavina.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/item/item_points2_gavina.png", AssetType::BITMAP);
@@ -437,43 +447,51 @@ bool Director::setFileList()
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/item/item_coffee.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.ani", AssetType::ANIMATION);
}
{ // Titulo
Asset::get()->add(prefix + "/data/gfx/title/title_bg_tile.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/title/title_bg_tile.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_coffee.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/title/title_coffee.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_crisis.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/title/title_crisis.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_arcade_edition.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/title/title_arcade_edition.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_dust.png", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/title/title_dust.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_dust.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/title/title_dust.ani", AssetType::ANIMATION);
}
{ // Jugador 1
Asset::get()->add(prefix + "/data/gfx/player/player1.gif", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/player/player1.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/player/player1_pal1.gif", AssetType::PALETTE); Asset::get()->add(prefix + "/data/gfx/player/player1_one_coffee_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_pal2.gif", AssetType::PALETTE); Asset::get()->add(prefix + "/data/gfx/player/player1_two_coffee_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_pal3.gif", AssetType::PALETTE); Asset::get()->add(prefix + "/data/gfx/player/player1_all_white_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_power.png", AssetType::BITMAP);
}
{ // Jugador 2
Asset::get()->add(prefix + "/data/gfx/player/player2.gif", AssetType::BITMAP); Asset::get()->add(prefix + "/data/gfx/player/player2.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/player/player2_pal1.gif", AssetType::PALETTE); Asset::get()->add(prefix + "/data/gfx/player/player2_one_coffee_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_pal2.gif", AssetType::PALETTE); Asset::get()->add(prefix + "/data/gfx/player/player2_two_coffee_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_pal3.gif", AssetType::PALETTE); Asset::get()->add(prefix + "/data/gfx/player/player2_all_white_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_power.png", AssetType::BITMAP);
}
{ // Animaciones del jugador
Asset::get()->add(prefix + "/data/gfx/player/player.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/player/player.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/player/player_power.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/player/player_power_pal.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player_power.ani", AssetType::ANIMATION); Asset::get()->add(prefix + "/data/gfx/player/player_power.ani", AssetType::ANIMATION);
}
// Fuentes de texto // Fuentes de texto
Asset::get()->add(prefix + "/data/font/8bithud.png", AssetType::FONT); Asset::get()->add(prefix + "/data/font/8bithud.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/8bithud.txt", AssetType::FONT); Asset::get()->add(prefix + "/data/font/8bithud.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/nokia.png", AssetType::FONT); Asset::get()->add(prefix + "/data/font/nokia.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/nokia_big2.png", AssetType::FONT); Asset::get()->add(prefix + "/data/font/nokia_big2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/nokia.txt", AssetType::FONT); Asset::get()->add(prefix + "/data/font/nokia.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/nokia2.png", AssetType::FONT); Asset::get()->add(prefix + "/data/font/nokia2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/nokia2.txt", AssetType::FONT); Asset::get()->add(prefix + "/data/font/nokia2.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/nokia_big2.txt", AssetType::FONT); Asset::get()->add(prefix + "/data/font/nokia_big2.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/smb2_big.png", AssetType::FONT); Asset::get()->add(prefix + "/data/font/smb2_big.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/smb2_big.txt", AssetType::FONT); Asset::get()->add(prefix + "/data/font/smb2_big.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/smb2.gif", AssetType::FONT); Asset::get()->add(prefix + "/data/font/smb2.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/smb2_pal1.gif", AssetType::PALETTE); Asset::get()->add(prefix + "/data/font/smb2_palette1.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/font/smb2.txt", AssetType::FONT); Asset::get()->add(prefix + "/data/font/smb2.txt", AssetType::FONT);
// Textos // Textos
@@ -481,7 +499,9 @@ bool Director::setFileList()
Asset::get()->add(prefix + "/data/lang/en_UK.txt", AssetType::LANG); Asset::get()->add(prefix + "/data/lang/en_UK.txt", AssetType::LANG);
Asset::get()->add(prefix + "/data/lang/ba_BA.txt", AssetType::LANG); Asset::get()->add(prefix + "/data/lang/ba_BA.txt", AssetType::LANG);
return Asset::get()->check(); // Si falta algun fichero, sale del programa
if (!Asset::get()->check())
throw std::runtime_error("Falta algun fichero");
} }
// Carga los parametros para configurar el juego // Carga los parametros para configurar el juego
@@ -569,38 +589,6 @@ void Director::createSystemFolder(const std::string &folder)
} }
} }
// Carga los sonidos del juego
void Director::loadSounds()
{
// Obtiene la lista con las rutas a los ficheros de sonidos
auto list = Asset::get()->getListByType(AssetType::SOUND);
sounds_.clear();
for (const auto &l : list)
{
auto last_index = l.find_last_of('/') + 1;
auto name = l.substr(last_index);
sounds_.emplace_back(SoundFile{name, JA_LoadSound(l.c_str())});
}
}
// Carga las musicas del juego
void Director::loadMusics()
{
// Obtiene la lista con las rutas a los ficheros musicales
auto list = Asset::get()->getListByType(AssetType::MUSIC);
musics_.clear();
for (const auto &l : list)
{
auto last_index = l.find_last_of('/') + 1;
auto name = l.substr(last_index);
musics_.emplace_back(MusicFile{name, JA_LoadMusic(l.c_str())});
}
}
// Ejecuta la sección con el logo // Ejecuta la sección con el logo
void Director::runLogo() void Director::runLogo()
{ {
@@ -611,14 +599,14 @@ void Director::runLogo()
// 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()
{ {
auto intro = std::make_unique<Intro>(getMusic(musics_, "intro.ogg")); auto intro = std::make_unique<Intro>();
intro->run(); intro->run();
} }
// Ejecuta la sección con el título del juego // Ejecuta la sección con el título del juego
void Director::runTitle() void Director::runTitle()
{ {
auto title = std::make_unique<Title>(getMusic(musics_, "title.ogg")); auto title = std::make_unique<Title>();
title->run(); title->run();
} }
@@ -627,21 +615,21 @@ void Director::runGame()
{ {
const auto player_id = section::options == section::Options::GAME_PLAY_1P ? 1 : 2; const auto player_id = section::options == section::Options::GAME_PLAY_1P ? 1 : 2;
constexpr auto current_stage = 0; constexpr auto current_stage = 0;
auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_OFF, getMusic(musics_, "playing.ogg")); auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_OFF);
game->run(); game->run();
} }
// Ejecuta la sección donde se muestran las instrucciones // Ejecuta la sección donde se muestran las instrucciones
void Director::runInstructions() void Director::runInstructions()
{ {
auto instructions = std::make_unique<Instructions>(getMusic(musics_, "title.ogg")); auto instructions = std::make_unique<Instructions>();
instructions->run(); instructions->run();
} }
// 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()
{ {
auto hi_score_table = std::make_unique<HiScoreTable>(getMusic(musics_, "title.ogg")); auto hi_score_table = std::make_unique<HiScoreTable>();
hi_score_table->run(); hi_score_table->run();
} }
@@ -650,7 +638,7 @@ void Director::runDemoGame()
{ {
const auto player_id = (rand() % 2) + 1; const auto player_id = (rand() % 2) + 1;
constexpr auto current_stage = 0; constexpr auto current_stage = 0;
auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_ON, nullptr); auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_ON);
game->run(); game->run();
} }
@@ -700,12 +688,20 @@ int Director::run()
#ifdef ARCADE #ifdef ARCADE
// Comprueba si ha de apagar el sistema // Comprueba si ha de apagar el sistema
if (section::options == section::Options::QUIT_SHUTDOWN) if (section::options == section::Options::QUIT_WITH_CONTROLLER)
shutdownSystem(); shutdownSystem();
#endif #endif
const int return_code = section::options == section::Options::QUIT_NORMAL ? 0 : 1; const auto return_code = (section::options == section::Options::QUIT_WITH_KEYBOARD) ? "with keyboard" : (section::options == section::Options::QUIT_WITH_CONTROLLER) ? "with controller"
return return_code; : "from event";
std::cout << "\nGame end " << return_code << std::endl;
#ifndef VERBOSE
// Habilita de nuevo los std::cout
std::cout.rdbuf(orig_buf);
#endif
return (section::options == section::Options::QUIT_WITH_CONTROLLER) ? 1 : 0;
} }
// Obtiene una fichero a partir de un lang::Code // Obtiene una fichero a partir de un lang::Code

View File

@@ -4,9 +4,12 @@
#include <SDL2/SDL_video.h> // for SDL_Window #include <SDL2/SDL_video.h> // for SDL_Window
#include <string> // for string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
namespace lang { enum class Code : int; } namespace lang
struct MusicFile; {
struct SoundFile; enum class Code : int;
}
struct ResourceMusic;
struct ResourceSound;
// Textos // Textos
constexpr char WINDOW_CAPTION[] = "Coffee Crisis Arcade Edition"; constexpr char WINDOW_CAPTION[] = "Coffee Crisis Arcade Edition";
@@ -17,13 +20,12 @@ 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
std::streambuf *orig_buf; // Puntero al buffer de flujo original para restaurar std::cout
// Variables // Variables
std::string executable_path_; // Path del ejecutable std::string executable_path_; // Path del ejecutable
std::string system_folder_; // Carpeta del sistema donde guardar datos std::string system_folder_; // Carpeta del sistema donde guardar datos
std::string param_file_argument_; // 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<SoundFile> sounds_; // Vector con los sonidos
std::vector<MusicFile> musics_; // Vector con las musicas
// Inicializa jail_audio // Inicializa jail_audio
void initJailAudio(); void initJailAudio();
@@ -31,20 +33,14 @@ private:
// Arranca SDL y crea la ventana // Arranca SDL y crea la ventana
bool initSDL(); bool initSDL();
// Inicializa el objeto input // Asigna los botones y teclas al objeto Input
void initInput(); void bindInputs();
// Carga los parametros para configurar el juego // Carga los parametros para configurar el juego
void loadParams(const std::string &file_path); void loadParams(const std::string &file_path);
// Crea el indice de ficheros // Crea el indice de ficheros
bool setFileList(); void setFileList();
// Carga los sonidos del juego
void loadSounds();
// Carga las musicas del juego
void loadMusics();
// Comprueba los parametros del programa // Comprueba los parametros del programa
void checkProgramArguments(int argc, const char *argv[]); void checkProgramArguments(int argc, const char *argv[]);

View File

@@ -1,6 +1,6 @@
#include "explosions.h" #include "explosions.h"
#include <utility> // for move #include <utility> // for move
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for SpriteAnimated
class Texture; // lines 3-3 class Texture; // lines 3-3
// Constructor // Constructor
@@ -38,22 +38,17 @@ void Explosions::render()
} }
// Añade texturas al objeto // Añade texturas al objeto
void Explosions::addTexture(int size, std::shared_ptr<Texture> texture, std::vector<std::string> *animation) void Explosions::addTexture(int size, std::shared_ptr<Texture> texture, std::vector<std::string> &animation)
{ {
ExplosionTexture temp; textures_.emplace_back(ExplosionTexture(size, texture, animation));
temp.size = size;
temp.texture = texture;
temp.animation = animation;
textures_.push_back(temp);
} }
// Añade una explosión // Añade una explosión
void Explosions::add(int x, int y, int size) void Explosions::add(int x, int y, int size)
{ {
const int index = getIndexBySize(size); const auto index = getIndexBySize(size);
auto sprite = std::make_unique<AnimatedSprite>(textures_[index].texture, "", textures_[index].animation); explosions_.emplace_back(std::make_unique<AnimatedSprite>(textures_[index].texture, textures_[index].animation));
sprite->setPos(x, y); explosions_.back()->setPos(x, y);
explosions_.push_back(std::move(sprite));
} }
// Vacia el vector de elementos finalizados // Vacia el vector de elementos finalizados

View File

@@ -8,9 +8,13 @@ class Texture;
struct ExplosionTexture struct ExplosionTexture
{ {
std::shared_ptr<Texture> texture; // Textura para la explosión
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
std::shared_ptr<Texture> texture; // Textura para la explosión
std::vector<std::string> animation; // Animación para la textura
// Constructor
ExplosionTexture(int sz, std::shared_ptr<Texture> tex, std::vector<std::string> anim)
: size(sz), texture(tex), animation(anim) {}
}; };
// Clase explosions // Clase explosions
@@ -41,7 +45,7 @@ public:
void render(); void render();
// Añade texturas al objeto // Añade texturas al objeto
void addTexture(int size, std::shared_ptr<Texture> texture, std::vector<std::string> *animation); void addTexture(int size, std::shared_ptr<Texture> texture, 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,11 +4,12 @@
#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 "screen.h"
#include "utils.h" // for Param, ParamGame, ParamFade #include "utils.h" // for Param, ParamGame, ParamFade
// Constructor // Constructor
Fade::Fade(SDL_Renderer *renderer) Fade::Fade()
: renderer_(renderer) : renderer_(Screen::get()->getRenderer())
{ {
// Crea la textura donde dibujar el fade // Crea la textura donde dibujar el fade
backbuffer_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height); backbuffer_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);

View File

@@ -54,7 +54,7 @@ private:
public: public:
// Constructor // Constructor
explicit Fade(SDL_Renderer *renderer); Fade();
// Destructor // Destructor
~Fade(); ~Fade();

File diff suppressed because it is too large Load Diff

View File

@@ -32,26 +32,6 @@ 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
constexpr int TOTAL_SCORE_DATA = 3; constexpr int TOTAL_SCORE_DATA = 3;
constexpr int TOTAL_DEMO_DATA = 2000;
// Contadores
constexpr int STAGE_COUNTER = 200;
constexpr int HELP_COUNTER = 1000;
constexpr int GAME_COMPLETED_START_FADE = 500;
constexpr int GAME_COMPLETED_END = 700;
constexpr int GAME_OVER_COUNTER = 350;
// Porcentaje de aparición de los objetos
constexpr int ITEM_POINTS_1_DISK_ODDS = 10;
constexpr int ITEM_POINTS_2_GAVINA_ODDS = 6;
constexpr int ITEM_POINTS_3_PACMAR_ODDS = 3;
constexpr int ITEM_CLOCK_ODDS = 5;
constexpr int ITEM_COFFEE_ODDS = 5;
constexpr int ITEM_POWER_BALL_ODDS = 0;
constexpr int ITEM_COFFEE_MACHINE_ODDS = 4;
// Valores para las variables asociadas a los objetos
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
@@ -83,6 +63,7 @@ constexpr int TIME_STOPPED_COUNTER = 300;
class Game class Game
{ {
private: private:
// Estructuras
struct Helper struct Helper
{ {
bool need_coffee; // Indica si se necesitan cafes bool need_coffee; // Indica si se necesitan cafes
@@ -97,14 +78,25 @@ private:
int item_coffee_machine_odds; // Probabilidad de aparición del objeto int item_coffee_machine_odds; // Probabilidad de aparición del objeto
}; };
struct Demo // Constantes
{
bool enabled; // Indica si está activo el modo demo // Contadores
bool recording; // Indica si está activado el modo para grabar la demo static constexpr int STAGE_COUNTER_ = 200;
int counter; // Contador para el modo demo static constexpr int HELP_COUNTER_ = 1000;
DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo static constexpr int GAME_COMPLETED_START_FADE_ = 500;
DemoKeys data_file[2][TOTAL_DEMO_DATA]; // Vector con diferentes sets de datos con los movimientos para la demo static constexpr int GAME_COMPLETED_END_ = 700;
}; static constexpr int GAME_OVER_COUNTER_ = 350;
static constexpr int TIME_STOPPED_COUNTER_ = 300;
static constexpr int TICKS_SPEED_ = 15;
// Porcentaje de aparición de los objetos
static constexpr int ITEM_POINTS_1_DISK_ODDS_ = 10;
static constexpr int ITEM_POINTS_2_GAVINA_ODDS_ = 6;
static constexpr int ITEM_POINTS_3_PACMAR_ODDS_ = 3;
static constexpr int ITEM_CLOCK_ODDS_ = 5;
static constexpr int ITEM_COFFEE_ODDS_ = 5;
static constexpr int ITEM_POWER_BALL_ODDS_ = 0;
static constexpr int ITEM_COFFEE_MACHINE_ODDS_ = 4;
// Objetos y punteros // Objetos y punteros
SDL_Renderer *renderer_; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
@@ -129,17 +121,14 @@ private:
std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
std::vector<std::shared_ptr<Texture>> balloon_textures_; // Vector con las texturas de los globos std::vector<std::shared_ptr<Texture>> balloon_textures_; // Vector con las texturas de los globos
std::vector<std::shared_ptr<Texture>> explosions_textures_; // Vector con las texturas de las explosiones std::vector<std::shared_ptr<Texture>> explosions_textures_; // Vector con las texturas de las explosiones
std::vector<std::shared_ptr<Texture>> 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; std::vector<std::vector<std::shared_ptr<Texture>>> player_textures_; // Vector con todas las texturas de los jugadores;
std::vector<std::shared_ptr<Texture>> game_text_textures_; // Vector con las texturas para los sprites con textos std::vector<std::shared_ptr<Texture>> game_text_textures_; // Vector con las texturas para los sprites con textos
//std::vector<std::shared_ptr<SmartSprite>> game_text_sprites_; // Sprite con el textos que aparecen al coger items
std::vector<std::vector<std::string> *> item_animations_; // Vector con las animaciones de los items std::vector<std::vector<std::string>> item_animations_; // Vector con las animaciones de los items
std::vector<std::vector<std::string> *> player_animations_; // Vector con las animaciones del jugador std::vector<std::vector<std::string>> player_animations_; // Vector con las animaciones del jugador
std::vector<std::vector<std::string> *> balloon_animations_; // Vector con las animaciones de los globos std::vector<std::vector<std::string>> balloon_animations_; // Vector con las animaciones de los globos
std::vector<std::vector<std::string> *> explosions_animations_; // Vector con las animaciones de las explosiones std::vector<std::vector<std::string>> explosions_animations_; // Vector con las animaciones de las explosiones
std::unique_ptr<Text> text_; // Fuente para los textos del juego std::unique_ptr<Text> text_; // Fuente para los textos del juego
std::unique_ptr<Text> text_big_; // Fuente de texto grande std::unique_ptr<Text> text_big_; // Fuente de texto grande
@@ -148,33 +137,14 @@ private:
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
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 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
bool hi_score_achieved_; // 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 hi_score_; // Máxima puntuación y nombre de quien la ostenta HiScoreEntry hi_score_; // Máxima puntuación y nombre de quien la ostenta
int current_stage_; // Indica la fase actual int current_stage_; // Indica la fase actual
int stage_bitmap_counter_; // Contador para el tiempo visible del texto de Stage int stage_bitmap_counter_; // Contador para el tiempo visible del texto de Stage
float stage_bitmap_path_[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 get_ready_bitmap_path_[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 game_over_counter_; // Contador para el estado de fin de partida int game_over_counter_; // Contador para el estado de fin de partida
int menace_current_; // Nivel de amenaza actual int menace_current_; // Nivel de amenaza actual
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 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
@@ -222,12 +192,6 @@ private:
// Libera los recursos previamente cargados // Libera los recursos previamente cargados
void unloadMedia(); void unloadMedia();
// Carga el fichero de datos para la demo
bool loadDemoFile(const std::string &file_path, DemoKeys (*data_file)[TOTAL_DEMO_DATA]);
#ifdef RECORDING
// Guarda el fichero de datos para la demo
bool saveDemoFile(const std::string &file_path);
#endif
// Crea una formación de enemigos // Crea una formación de enemigos
void deployBalloonFormation(); void deployBalloonFormation();
@@ -321,20 +285,20 @@ private:
// Vacia el vector de items // Vacia el vector de items
void freeItems(); void freeItems();
// Crea un objeto SmartSprite // Crea un objeto SpriteSmart
void createItemScoreSprite(int x, int y, std::shared_ptr<Texture> texture); void createItemScoreSprite(int x, int y, std::shared_ptr<Texture> texture);
// Vacia el vector de smartsprites // Vacia el vector de smartsprites
void freeSmartSprites(); void freeSpriteSmarts();
// Crea un SmartSprite para arrojar el item café al recibir un impacto // Crea un SpriteSmart para arrojar el item café al recibir un impacto
void throwCoffee(int x, int y); void throwCoffee(int x, int y);
// Actualiza los SmartSprites // Actualiza los SpriteSmarts
void updateSmartSprites(); void updateSpriteSmarts();
// Pinta los SmartSprites activos // Pinta los SpriteSmarts activos
void renderSmartSprites(); void renderSpriteSmarts();
// Acciones a realizar cuando el jugador muere // Acciones a realizar cuando el jugador muere
void killPlayer(std::shared_ptr<Player> &player); void killPlayer(std::shared_ptr<Player> &player);
@@ -369,9 +333,6 @@ private:
// Actualiza el fondo // Actualiza el fondo
void updateBackground(); void updateBackground();
// Gestiona la entrada durante el juego
void checkInput();
// Pinta diferentes mensajes en la pantalla // Pinta diferentes mensajes en la pantalla
void renderMessages(); void renderMessages();
@@ -405,9 +366,6 @@ private:
// Comprueba si todos los jugadores han terminado de jugar // Comprueba si todos los jugadores han terminado de jugar
bool allPlayersAreNotPlaying(); bool allPlayersAreNotPlaying();
// Carga las animaciones
void loadAnimations(std::string 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();
@@ -441,9 +399,40 @@ private:
// Obtiene un controlador a partir del "id" del jugador // Obtiene un controlador a partir del "id" del jugador
int getController(int playerId); int getController(int playerId);
// Gestiona la entrada durante el juego
void checkInput();
// Verifica si alguno de los controladores ha solicitado una pausa y actualiza el estado de pausa del juego.
void checkPauseInput();
// Gestiona las entradas de los jugadores en el modo demo, incluyendo movimientos y disparos automáticos.
void handleDemoMode();
// Procesa las entradas para un jugador específico durante el modo demo.
// Incluye movimientos (izquierda, derecha, sin movimiento) y disparos automáticos.
void handleDemoPlayerInput(const std::shared_ptr<Player> &player, int index);
// Maneja el disparo de un jugador, incluyendo la creación de balas y la gestión del tiempo de espera entre disparos.
void handleFireInput(const std::shared_ptr<Player> &player, BulletType bulletType);
// Gestiona las entradas de todos los jugadores en el modo normal (fuera del modo demo).
void handlePlayersInput();
// Maneja las entradas de movimiento y disparo para un jugador en modo normal.
void handleNormalPlayerInput(const std::shared_ptr<Player> &player);
// Procesa las entradas de disparo del jugador, permitiendo disparos automáticos si está habilitado.
void handleFireInputs(const std::shared_ptr<Player> &player, bool autofire, int controllerIndex);
// Maneja la continuación del jugador cuando no está jugando, permitiendo que continúe si se pulsa el botón de inicio.
void handlePlayerContinue(const std::shared_ptr<Player> &player);
// Procesa las entradas para la introducción del nombre del jugador.
void handleNameInput(const std::shared_ptr<Player> &player);
public: public:
// Constructor // Constructor
Game(int playerID, int current_stage, bool demo, JA_Music_t *music); Game(int playerID, int current_stage, bool demo);
// Destructor // Destructor
~Game(); ~Game();

View File

@@ -1,32 +1,32 @@
#include "game_logo.h" #include "game_logo.h"
#include <SDL2/SDL_render.h> // for SDL_FLIP_HORIZONTAL #include <SDL2/SDL_render.h> // for SDL_FLIP_HORIZONTAL
#include <algorithm> // for max #include <algorithm> // for max
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for SpriteAnimated
#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" // JA_PlaySound
#include "param.h" // for param #include "param.h" // for param
#include "resource.h" // for Resource
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "smart_sprite.h" // for SmartSprite #include "smart_sprite.h" // for SpriteSmart
#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, ParamGame, ParamTitle #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"))), : dust_texture_(Resource::get()->getTexture("title_dust.png")),
coffee_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_coffee.png"))), coffee_texture_(Resource::get()->getTexture("title_coffee.png")),
crisis_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_crisis.png"))), crisis_texture_(Resource::get()->getTexture("title_crisis.png")),
arcade_edition_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_arcade_edition.png"))), arcade_edition_texture_(Resource::get()->getTexture("title_arcade_edition.png")),
dust_left_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Asset::get()->get("title_dust.ani"))), dust_left_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Resource::get()->getAnimation("title_dust.ani"))),
dust_right_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Asset::get()->get("title_dust.ani"))), dust_right_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Resource::get()->getAnimation("title_dust.ani"))),
coffee_sprite_(std::make_unique<SmartSprite>(coffee_texture_)), coffee_sprite_(std::make_unique<SmartSprite>(coffee_texture_)),
crisis_sprite_(std::make_unique<SmartSprite>(crisis_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_)), arcade_edition_sprite_(std::make_unique<Sprite>(arcade_edition_texture_, (param.game.width - arcade_edition_texture_->getWidth()) / 2, param.title.arcade_edition_position, arcade_edition_texture_->getWidth(), arcade_edition_texture_->getHeight())),
crash_sound_(JA_LoadSound(Asset::get()->get("title.wav").c_str())),
x_(x), x_(x),
y_(y) y_(y)
@@ -35,12 +35,6 @@ GameLogo::GameLogo(int x, int y)
init(); init();
} }
// Destructor
GameLogo::~GameLogo()
{
JA_DeleteSound(crash_sound_);
}
// Inicializa las variables // Inicializa las variables
void GameLogo::init() void GameLogo::init()
{ {
@@ -124,7 +118,9 @@ void GameLogo::render()
// Actualiza la lógica de la clase // Actualiza la lógica de la clase
void GameLogo::update() void GameLogo::update()
{ {
if (status_ == Status::MOVING) switch (status_)
{
case Status::MOVING:
{ {
coffee_sprite_->update(); coffee_sprite_->update();
crisis_sprite_->update(); crisis_sprite_->update();
@@ -135,11 +131,13 @@ void GameLogo::update()
status_ = Status::SHAKING; status_ = Status::SHAKING;
// Reproduce el efecto sonoro // Reproduce el efecto sonoro
JA_PlaySound(crash_sound_); JA_PlaySound(Resource::get()->getSound("title.wav"));
}
} }
else if (status_ == Status::SHAKING) break;
}
case Status::SHAKING:
{ {
// Agita el logo // Agita el logo
if (shake_.remaining > 0) if (shake_.remaining > 0)
@@ -166,12 +164,20 @@ void GameLogo::update()
dust_right_sprite_->update(); dust_right_sprite_->update();
dust_left_sprite_->update(); dust_left_sprite_->update();
break;
} }
else if (status_ == Status::FINISHED) case Status::FINISHED:
{ {
dust_right_sprite_->update(); dust_right_sprite_->update();
dust_left_sprite_->update(); dust_left_sprite_->update();
break;
}
default:
break;
} }
} }

View File

@@ -1,8 +1,8 @@
#pragma once #pragma once
#include <memory> // for unique_ptr, shared_ptr #include <memory> // for unique_ptr, shared_ptr
class AnimatedSprite; #include "animated_sprite.h"
class SmartSprite; #include "smart_sprite.h"
class Sprite; class Sprite;
class Texture; class Texture;
struct JA_Sound_t; // lines 10-10 struct JA_Sound_t; // lines 10-10
@@ -43,8 +43,6 @@ private:
std::unique_ptr<Sprite> arcade_edition_sprite_; // Sprite con los graficos de "Arcade Edition" 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 // Variables
int x_; // Posición donde dibujar el logo int x_; // Posición donde dibujar el logo
int y_; // Posición donde dibujar el logo int y_; // Posición donde dibujar el logo
@@ -63,7 +61,7 @@ public:
GameLogo(int x, int y); GameLogo(int x, int y);
// Destructor // Destructor
~GameLogo(); ~GameLogo() = default;
// Pinta la clase en pantalla // Pinta la clase en pantalla
void render(); void render();

View File

@@ -3,6 +3,7 @@
#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 "jail_audio.h" // for JA_EnableMusic, JA_EnableSound #include "jail_audio.h" // for JA_EnableMusic, JA_EnableSound
#include "lang.h" // for getText #include "lang.h" // for getText
#include "notifier.h" // for Notifier
#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
@@ -28,14 +29,21 @@ namespace globalInputs
// Termina // Termina
void quit(section::Options code) void quit(section::Options code)
{ {
if (Screen::get()->notificationsAreActive()) const std::string exit_code = "QUIT";
auto code_found = stringInVector(Notifier::get()->getCodes(), exit_code);
if (code_found)
{ {
section::name = section::Name::QUIT; section::name = section::Name::QUIT;
section::options = code; section::options = code;
} }
else else
{ {
Screen::get()->showNotification(lang::getText(94)); #ifdef ARCADE
const int index = code == section::Options::QUIT_WITH_CONTROLLER ? 116 : 94;
Notifier::get()->showText(lang::getText(index), std::string(), -1, exit_code);
#else
Notifier::get()->showText(lang::getText(94), std::string(), -1, exit_code);
#endif
} }
} }
@@ -43,7 +51,7 @@ namespace globalInputs
void reset() void reset()
{ {
section::name = section::Name::INIT; section::name = section::Name::INIT;
Screen::get()->showNotification("Reset"); Notifier::get()->showText("Reset");
} }
// Activa o desactiva el audio // Activa o desactiva el audio
@@ -52,7 +60,7 @@ namespace globalInputs
options.audio.sound.enabled = options.audio.music.enabled = !options.audio.music.enabled; options.audio.sound.enabled = options.audio.music.enabled = !options.audio.music.enabled;
JA_EnableMusic(options.audio.music.enabled); JA_EnableMusic(options.audio.music.enabled);
JA_EnableSound(options.audio.sound.enabled); JA_EnableSound(options.audio.sound.enabled);
Screen::get()->showNotification("Audio " + boolToOnOff(options.audio.music.enabled)); Notifier::get()->showText("Audio " + boolToOnOff(options.audio.music.enabled));
} }
// Comprueba los inputs que se pueden introducir en cualquier sección del juego // Comprueba los inputs que se pueden introducir en cualquier sección del juego
@@ -61,7 +69,7 @@ namespace globalInputs
// Comprueba si se sale con el teclado // Comprueba si se sale con el teclado
if (Input::get()->checkInput(InputType::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_WITH_KEYBOARD);
return; return;
} }
@@ -99,7 +107,7 @@ namespace globalInputs
// Comprueba si se sale con el mando // Comprueba si se sale con el mando
if (Input::get()->checkModInput(InputType::SERVICE, InputType::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_WITH_CONTROLLER);
return; return;
} }

View File

@@ -15,37 +15,29 @@
#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 "resource.h" // for Resource
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options #include "section.h" // for Name, name, Options, options
#include "text.h" // for Text, TEXT_CENTER, TEXT_SHADOW, TEXT... #include "text.h" // for Text, TEXT_CENTER, TEXT_SHADOW, TEXT...
#include "utils.h" // for Param, ParamGame, Color, HiScoreEntry #include "utils.h" // for Param, ParamGame, Color, HiScoreEntry
// Constructor // Constructor
HiScoreTable::HiScoreTable(JA_Music_t *music) HiScoreTable::HiScoreTable()
: music_(music) : renderer_(Screen::get()->getRenderer()),
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
fade_(std::make_unique<Fade>()),
background_(std::make_unique<Background>()),
text_(std::make_unique<Text>(Resource::get()->getTexture("smb2.gif"), Resource::get()->getTextFile("smb2.txt"))),
counter_(0),
ticks_(0),
view_area_({0, 0, param.game.width, param.game.height}),
fade_mode_(FadeMode::IN)
{ {
// Copia punteros // Inicializa el resto de variables
renderer_ = Screen::get()->getRenderer();
// Objetos
fade_ = std::make_unique<Fade>(renderer_);
background_ = std::make_unique<Background>(renderer_);
text_ = std::make_unique<Text>(Asset::get()->get("smb2.gif"), Asset::get()->get("smb2.txt"), renderer_);
// Crea un backbuffer para el renderizador
backbuffer_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
// Inicializa variables
section::name = section::Name::HI_SCORE_TABLE; section::name = section::Name::HI_SCORE_TABLE;
ticks_ = 0;
ticks_speed_ = 15;
counter_ = 0;
counter_end_ = 800;
view_area_ = {0, 0, param.game.width, param.game.height};
fade_mode_ = FadeMode::IN;
// Inicializa objetos // Inicializa objetos
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
background_->setPos(param.game.game_area.rect); background_->setPos(param.game.game_area.rect);
background_->setCloudsSpeed(-0.1f); background_->setCloudsSpeed(-0.1f);
background_->setGradientNumber(1); background_->setGradientNumber(1);
@@ -70,7 +62,7 @@ HiScoreTable::~HiScoreTable()
void HiScoreTable::update() void HiScoreTable::update()
{ {
// Actualiza las variables // Actualiza las variables
if (SDL_GetTicks() - ticks_ > ticks_speed_) if (SDL_GetTicks() - ticks_ > TICKS_SPEED_)
{ {
// Actualiza el contador de ticks // Actualiza el contador de ticks
ticks_ = SDL_GetTicks(); ticks_ = SDL_GetTicks();
@@ -78,7 +70,7 @@ void HiScoreTable::update()
// Mantiene la música sonando // Mantiene la música sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{ {
JA_PlayMusic(music_); JA_PlayMusic(Resource::get()->getMusic("title.ogg"));
} }
// Actualiza el objeto screen // Actualiza el objeto screen
@@ -99,7 +91,7 @@ void HiScoreTable::update()
background_->setAlpha(96); background_->setAlpha(96);
} }
if (counter_ == counter_end_) if (counter_ == COUNTER_END_)
{ {
fade_->activate(); fade_->activate();
} }
@@ -188,6 +180,7 @@ void HiScoreTable::checkEvents()
if (event.type == SDL_QUIT) if (event.type == SDL_QUIT)
{ {
section::name = section::Name::QUIT; section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break; break;
} }

View File

@@ -9,7 +9,6 @@ class Background; // lines 8-8
class Fade; // lines 9-9 class Fade; // lines 9-9
class Text; // lines 10-10 class Text; // lines 10-10
enum class FadeMode : Uint8; // lines 11-11 enum class FadeMode : Uint8; // lines 11-11
struct JA_Music_t; // lines 12-12
/* /*
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
@@ -25,10 +24,13 @@ struct JA_Music_t; // lines 12-12
class HiScoreTable class HiScoreTable
{ {
private: private:
// Constantes
static constexpr Uint16 COUNTER_END_ = 800; // Valor final para el contador
static constexpr Uint32 TICKS_SPEED_ = 15; // Velocidad a la que se repiten los bucles del programa
// 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 SDL_Texture *backbuffer_; // Textura para usar como backbuffer
JA_Music_t *music_; // Musica de fondo
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
@@ -36,9 +38,7 @@ private:
// Variables // Variables
Uint16 counter_; // Contador Uint16 counter_; // 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 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla
FadeMode fade_mode_; // Modo de fade a utilizar FadeMode fade_mode_; // Modo de fade a utilizar
@@ -68,7 +68,7 @@ private:
public: public:
// Constructor // Constructor
explicit HiScoreTable(JA_Music_t *music); HiScoreTable();
// Destructor // Destructor
~HiScoreTable(); ~HiScoreTable();

View File

@@ -396,11 +396,9 @@ bool Input::discoverGameControllers()
if (SDL_GameControllerAddMappingsFromFile(game_controller_db_path_.c_str()) < 0) if (SDL_GameControllerAddMappingsFromFile(game_controller_db_path_.c_str()) < 0)
{ {
#ifdef VERBOSE
{ {
std::cout << "Error, could not load " << game_controller_db_path_.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
} }
num_joysticks_ = SDL_NumJoysticks(); num_joysticks_ = SDL_NumJoysticks();
@@ -418,12 +416,9 @@ bool Input::discoverGameControllers()
} }
} }
#ifdef VERBOSE std::cout << "\n** LOOKING FOR GAME CONTROLLERS" << std::endl;
{ // std::cout << " " << num_joysticks_ << " joysticks found" << std::endl;
std::cout << "\nChecking for game controllers...\n"; std::cout << "Gamepads found: " << num_gamepads_ << std::endl;
std::cout << num_joysticks_ << " joysticks found, " << num_gamepads_ << " are gamepads\n";
}
#endif
if (num_gamepads_ > 0) if (num_gamepads_ > 0)
{ {
@@ -437,26 +432,24 @@ bool Input::discoverGameControllers()
{ {
connected_controllers_.push_back(pad); connected_controllers_.push_back(pad);
const std::string name = SDL_GameControllerNameForIndex(i); const std::string name = SDL_GameControllerNameForIndex(i);
#ifdef VERBOSE
{ {
std::cout << name << std::endl; std::cout << "#" << i << ": " << name << std::endl;
} }
#endif
controller_names_.push_back(name); controller_names_.push_back(name);
} }
else else
{ {
#ifdef VERBOSE
{ {
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl; std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
} }
#endif
} }
} }
SDL_GameControllerEventState(SDL_ENABLE); SDL_GameControllerEventState(SDL_ENABLE);
} }
std::cout << "\n** FINISHED LOOKING FOR GAME CONTROLLERS" << std::endl;
return found; return found;
} }

View File

@@ -13,26 +13,26 @@
#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 "resource.h" // for Resource
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options #include "section.h" // for Name, name, Options, options
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "text.h" // for Text, TEXT_CENTER, TEXT_COLOR, TEXT_... #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, ParamGame, Color, shdw_txt_color #include "utils.h" // for Param, ParamGame, Color, shdw_txt_color
struct JA_Music_t; // lines 22-22 struct JA_Music_t; // lines 22-22
// Constructor // Constructor
Instructions::Instructions(JA_Music_t *music) Instructions::Instructions()
: music_(music)
{ {
// Copia los punteros // Copia los punteros
renderer_ = Screen::get()->getRenderer(); renderer_ = Screen::get()->getRenderer();
// Crea objetos // Crea objetos
text_ = std::make_unique<Text>(Asset::get()->get("smb2.gif"), Asset::get()->get("smb2.txt"), renderer_); text_ = std::make_unique<Text>(Resource::get()->getTexture("smb2.gif"), Resource::get()->getTextFile("smb2.txt"));
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); tiled_bg_ = std::make_unique<TiledBG>((SDL_Rect){0, 0, param.game.width, param.game.height}, TiledBGMode::STATIC);
fade_ = std::make_unique<Fade>(renderer_); fade_ = std::make_unique<Fade>();
// 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);
@@ -80,26 +80,17 @@ Instructions::~Instructions()
void Instructions::iniSprites() void Instructions::iniSprites()
{ {
// Inicializa las texturas // Inicializa las texturas
auto item1 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_points1_disk.png")); item_textures_.emplace_back(Resource::get()->getTexture("item_points1_disk.png"));
item_textures_.push_back(item1); item_textures_.emplace_back(Resource::get()->getTexture("item_points2_gavina.png"));
item_textures_.emplace_back(Resource::get()->getTexture("item_points3_pacmar.png"));
auto item2 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_points2_gavina.png")); item_textures_.emplace_back(Resource::get()->getTexture("item_clock.png"));
item_textures_.push_back(item2); item_textures_.emplace_back(Resource::get()->getTexture("item_coffee.png"));
auto item3 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_points3_pacmar.png"));
item_textures_.push_back(item3);
auto item4 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_clock.png"));
item_textures_.push_back(item4);
auto item5 = std::make_shared<Texture>(renderer_, Asset::get()->get("item_coffee.png"));
item_textures_.push_back(item5);
// Inicializa los sprites // Inicializa los sprites
for (int i = 0; i < (int)item_textures_.size(); ++i) for (int i = 0; i < (int)item_textures_.size(); ++i)
{ {
auto sprite = std::make_unique<Sprite>(0, 0, param.game.item_size, param.game.item_size, item_textures_[i]); auto sprite = std::make_unique<Sprite>(item_textures_[i], 0, 0, param.game.item_size, param.game.item_size);
sprite->setPos((SDL_Point){sprite_pos_.x, sprite_pos_.y + ((param.game.item_size + item_space_) * i)}); sprite->setPosition((SDL_Point){sprite_pos_.x, sprite_pos_.y + ((param.game.item_size + item_space_) * i)});
sprites_.push_back(std::move(sprite)); sprites_.push_back(std::move(sprite));
} }
} }
@@ -231,7 +222,7 @@ void Instructions::update()
// Mantiene la música sonando // Mantiene la música sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
JA_PlayMusic(music_); JA_PlayMusic(Resource::get()->getMusic("title.ogg"));
// Actualiza el objeto screen // Actualiza el objeto screen
Screen::get()->update(); Screen::get()->update();
@@ -306,6 +297,7 @@ void Instructions::checkEvents()
if (event.type == SDL_QUIT) if (event.type == SDL_QUIT)
{ {
section::name = section::Name::QUIT; section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break; break;
} }

View File

@@ -9,7 +9,7 @@ class Fade;
class Sprite; class Sprite;
class Text; class Text;
class Texture; class Texture;
class Tiledbg; class TiledBG;
struct JA_Music_t; // lines 14-14 struct JA_Music_t; // lines 14-14
/* /*
@@ -33,11 +33,10 @@ private:
std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
std::vector<std::unique_ptr<Sprite>> sprites_; // Vector con los sprites de los items std::vector<std::unique_ptr<Sprite>> sprites_; // Vector con los sprites de los items
std::unique_ptr<Text> text_; // Objeto para escribir texto std::unique_ptr<Text> text_; // Objeto para escribir texto
std::unique_ptr<Tiledbg> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo std::unique_ptr<TiledBG> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
SDL_Renderer *renderer_; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
JA_Music_t *music_; // Musica de fondo
SDL_Texture *texture_; // Textura fija con el texto SDL_Texture *texture_; // Textura fija con el texto
SDL_Texture *backbuffer_; // Textura para usar como backbuffer SDL_Texture *backbuffer_; // Textura para usar como backbuffer
@@ -79,7 +78,7 @@ private:
public: public:
// Constructor // Constructor
explicit Instructions(JA_Music_t *music); Instructions();
// Destructor // Destructor
~Instructions(); ~Instructions();

View File

@@ -9,9 +9,10 @@
#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 "resource.h" // for Resource
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options #include "section.h" // for Name, name, Options, options
#include "smart_sprite.h" // for SmartSprite #include "smart_sprite.h" // for SpriteSmart
#include "text.h" // for Text #include "text.h" // for Text
#include "texture.h" // for Texture #include "texture.h" // for Texture
#include "utils.h" // for Param, ParamGame, Zone, BLOCK, Color #include "utils.h" // for Param, ParamGame, Zone, BLOCK, Color
@@ -19,15 +20,11 @@
struct JA_Music_t; // lines 19-19 struct JA_Music_t; // lines 19-19
// Constructor // Constructor
Intro::Intro(JA_Music_t *music) Intro::Intro()
: music_(music)
{ {
// Copia los punteros
auto renderer = Screen::get()->getRenderer();
// Reserva memoria para los objetos // Reserva memoria para los objetos
texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("intro.png")); texture_ = Resource::get()->getTexture("intro.png");
text_ = std::make_shared<Text>(Asset::get()->get("nokia.png"), Asset::get()->get("nokia.txt"), renderer); text_ = std::make_shared<Text>(Resource::get()->getTexture("nokia.png"), Resource::get()->getTextFile("nokia.txt"));
// Inicializa variables // Inicializa variables
section::name = section::Name::INTRO; section::name = section::Name::INTRO;
@@ -173,6 +170,7 @@ void Intro::checkEvents()
case SDL_QUIT: case SDL_QUIT:
{ {
section::name = section::Name::QUIT; section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break; break;
} }
@@ -425,7 +423,7 @@ void Intro::render()
// Bucle principal // Bucle principal
void Intro::run() void Intro::run()
{ {
JA_PlayMusic(music_, 0); JA_PlayMusic(Resource::get()->getMusic("intro.ogg"), 0);
while (section::name == section::Name::INTRO) while (section::name == section::Name::INTRO)
{ {

View File

@@ -3,7 +3,7 @@
#include <SDL2/SDL_stdinc.h> // for Uint32, Uint8 #include <SDL2/SDL_stdinc.h> // for Uint32, Uint8
#include <memory> // for unique_ptr, shared_ptr #include <memory> // for unique_ptr, shared_ptr
#include <vector> // for vector #include <vector> // for vector
#include "smart_sprite.h" // for SmartSprite #include "smart_sprite.h" // for SpriteSmart
#include "writer.h" // for Writer #include "writer.h" // for Writer
class Text; class Text;
class Texture; class Texture;
@@ -28,7 +28,6 @@ private:
// 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 ticks_speed_; // 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
int scene_; // Indica que escena está activa int scene_; // Indica que escena está activa
// Actualiza las variables del objeto // Actualiza las variables del objeto
@@ -51,7 +50,7 @@ private:
public: public:
// Constructor // Constructor
explicit Intro(JA_Music_t *music); Intro();
// Destructor // Destructor
~Intro() = default; ~Intro() = default;

View File

@@ -1,12 +1,12 @@
#include "item.h" #include "item.h"
#include <stdlib.h> // for rand #include <stdlib.h> // for rand
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for SpriteAnimated
#include "param.h" // for param #include "param.h" // for param
class Texture; class Texture;
// Constructor // Constructor
Item::Item(ItemType type, float x, float y, SDL_Rect *play_area, std::shared_ptr<Texture> texture, std::vector<std::string> *animation) Item::Item(ItemType type, float x, float y, SDL_Rect *play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
: sprite_(std::make_unique<AnimatedSprite>(texture, "", animation)), : sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
accel_x_(0.0f), accel_x_(0.0f),
floor_collision_(false), floor_collision_(false),
type_(type), type_(type),
@@ -144,7 +144,7 @@ void Item::disable()
void Item::update() void Item::update()
{ {
move(); move();
sprite_->animate(); sprite_->update();
updateTimeToLive(); updateTimeToLive();
checkTimeToLive(); checkTimeToLive();
} }

View File

@@ -5,7 +5,7 @@
#include <memory> // for shared_ptr, unique_ptr #include <memory> // for shared_ptr, unique_ptr
#include <string> // for string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for SpriteAnimated
#include "utils.h" // for Circle #include "utils.h" // for Circle
class Texture; class Texture;
@@ -58,7 +58,7 @@ private:
public: public:
// Constructor // Constructor
Item(ItemType type, float x, float y, SDL_Rect *play_area, std::shared_ptr<Texture> texture, std::vector<std::string> *animation); Item(ItemType type, float x, float y, SDL_Rect *play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation);
// Destructor // Destructor
~Item() = default; ~Item() = default;

View File

@@ -129,7 +129,7 @@ JA_Music_t *JA_LoadMusic(const char* filename) {
void JA_PlayMusic(JA_Music_t *music, const int loop) void JA_PlayMusic(JA_Music_t *music, const int loop)
{ {
if (!JA_musicEnabled) return; if (!JA_musicEnabled || !music) return;
if (current_music != NULL) { if (current_music != NULL) {
current_music->pos = 0; current_music->pos = 0;
@@ -223,7 +223,7 @@ JA_Sound_t *JA_LoadSound(const char* filename) {
int JA_PlaySound(JA_Sound_t *sound, const int loop) int JA_PlaySound(JA_Sound_t *sound, const int loop)
{ {
if (!JA_soundEnabled) return 0; if (!JA_soundEnabled || !sound) return 0;
int channel = 0; int channel = 0;
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; } while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) { channel++; }

View File

@@ -9,6 +9,7 @@
#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 "resource.h" // for Resource
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options #include "section.h" // for Name, name, Options, options
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
@@ -16,14 +17,10 @@
// Constructor // Constructor
Logo::Logo() Logo::Logo()
: since_texture_(Resource::get()->getTexture("logo_since_1998.png")),
since_sprite_(std::make_unique<Sprite>(since_texture_)),
jail_texture_(Resource::get()->getTexture("logo_jailgames.png"))
{ {
// Copia la dirección de los objetos
SDL_Renderer *renderer = Screen::get()->getRenderer();
// Reserva memoria para los punteros
jail_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("logo_jailgames.png"));
since_texture_ = std::make_shared<Texture>(renderer, Asset::get()->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_);
// Inicializa variables // Inicializa variables
counter_ = 0; counter_ = 0;
@@ -31,18 +28,19 @@ Logo::Logo()
ticks_ = 0; ticks_ = 0;
dest_.x = param.game.game_area.center_x - jail_texture_->getWidth() / 2; dest_.x = param.game.game_area.center_x - jail_texture_->getWidth() / 2;
dest_.y = param.game.game_area.center_y - jail_texture_->getHeight() / 2; dest_.y = param.game.game_area.center_y - jail_texture_->getHeight() / 2;
since_sprite_->setPosY(dest_.y + jail_texture_->getHeight() + 5); since_sprite_->setPosition({(param.game.width - since_texture_->getWidth()) / 2, 83 + jail_texture_->getHeight() + 5, since_texture_->getWidth(), since_texture_->getHeight()});
since_sprite_->setY(dest_.y + jail_texture_->getHeight() + 5);
since_sprite_->setSpriteClip(0, 0, since_texture_->getWidth(), since_texture_->getHeight()); since_sprite_->setSpriteClip(0, 0, since_texture_->getWidth(), since_texture_->getHeight());
since_texture_->setColor(0x00, 0x00, 0x00); // Esto en linux no hace nada ?? since_texture_->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 < jail_texture_->getHeight(); ++i) for (int i = 0; i < jail_texture_->getHeight(); ++i)
{ {
auto temp = std::make_unique<Sprite>(0, i, jail_texture_->getWidth(), 1, jail_texture_); auto temp = std::make_unique<Sprite>(jail_texture_, 0, i, jail_texture_->getWidth(), 1);
temp->setSpriteClip(0, i, jail_texture_->getWidth(), 1); temp->setSpriteClip(0, i, jail_texture_->getWidth(), 1);
const int posX = (i % 2 == 0) ? param.game.width + (i * 3) : -jail_texture_->getWidth() - (i * 3); const int posX = (i % 2 == 0) ? param.game.width + (i * 3) : -jail_texture_->getWidth() - (i * 3);
temp->setPosX(posX); temp->setX(posX);
temp->setPosY(dest_.y + i); temp->setY(dest_.y + i);
jail_sprite_.push_back(std::move(temp)); jail_sprite_.push_back(std::move(temp));
} }
@@ -75,6 +73,7 @@ void Logo::checkEvents()
if (event.type == SDL_QUIT) if (event.type == SDL_QUIT)
{ {
section::name = section::Name::QUIT; section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break; break;
} }
@@ -115,22 +114,22 @@ void Logo::updateJAILGAMES()
{ {
for (int i = 0; i < (int)jail_sprite_.size(); ++i) for (int i = 0; i < (int)jail_sprite_.size(); ++i)
{ {
if (jail_sprite_[i]->getIntPosX() != dest_.x) if (jail_sprite_[i]->getX() != dest_.x)
{ {
if (i % 2 == 0) if (i % 2 == 0)
{ {
jail_sprite_[i]->incPosX(-SPEED); jail_sprite_[i]->incX(-SPEED);
if (jail_sprite_[i]->getIntPosX() < dest_.x) if (jail_sprite_[i]->getX() < dest_.x)
{ {
jail_sprite_[i]->setPosX(dest_.x); jail_sprite_[i]->setX(dest_.x);
} }
} }
else else
{ {
jail_sprite_[i]->incPosX(SPEED); jail_sprite_[i]->incX(SPEED);
if (jail_sprite_[i]->getIntPosX() > dest_.x) if (jail_sprite_[i]->getX() > dest_.x)
{ {
jail_sprite_[i]->setPosX(dest_.x); jail_sprite_[i]->setX(dest_.x);
} }
} }
} }

View File

@@ -13,16 +13,9 @@ Actualizando a la versión "Arcade Edition" en 08/05/2024
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
std::cout << "Game start" << std::endl;
// Crea el objeto Director // Crea el objeto Director
auto director = std::make_unique<Director>(argc, const_cast<const char **>(argv)); auto director = std::make_unique<Director>(argc, const_cast<const char **>(argv));
// Bucle principal // Bucle principal
const auto exit = director->run(); return director->run();
const auto endType = exit == 0 ? "keyboard" : "controller";
std::cout << "\nGame end with " << endType << std::endl;
return exit;
} }

View File

@@ -66,10 +66,8 @@ bool ManageHiScoreTable::loadFromFile(const std::string &file_path)
if (file) if (file)
{ {
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
std::cout << "Reading file: " << file_name.c_str() << std::endl; std::cout << "Reading file: " << file_name.c_str() << std::endl;
#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;
@@ -115,9 +113,7 @@ bool ManageHiScoreTable::loadFromFile(const std::string &file_path)
// Guarda la tabla en un fichero // Guarda la tabla en un fichero
bool ManageHiScoreTable::saveToFile(const std::string &file_path) bool ManageHiScoreTable::saveToFile(const std::string &file_path)
{ {
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
auto success = true; auto success = true;
auto file = SDL_RWFromFile(file_path.c_str(), "w+b"); auto file = SDL_RWFromFile(file_path.c_str(), "w+b");
@@ -132,17 +128,13 @@ bool ManageHiScoreTable::saveToFile(const std::string &file_path)
SDL_RWwrite(file, table_->at(i).name.c_str(), nameSize, 1); SDL_RWwrite(file, table_->at(i).name.c_str(), nameSize, 1);
} }
#ifdef VERBOSE
std::cout << "Writing file: " << file_name.c_str() << std::endl; std::cout << "Writing file: " << file_name.c_str() << std::endl;
#endif
// Cierra el fichero // Cierra el fichero
SDL_RWclose(file); SDL_RWclose(file);
} }
else else
{ {
#ifdef VERBOSE
std::cout << "Error: Unable to save " << file_name.c_str() << " file! " << SDL_GetError() << std::endl; std::cout << "Error: Unable to save " << file_name.c_str() << " file! " << SDL_GetError() << std::endl;
#endif
} }
return success; return success;
} }

View File

@@ -2,34 +2,44 @@
#include "texture.h" // for Texture #include "texture.h" // for Texture
// Constructor // Constructor
MovingSprite::MovingSprite(float x, float y, int w, int h, float vx, float vy, float ax, float ay, std::shared_ptr<Texture> texture) MovingSprite::MovingSprite(std::shared_ptr<Texture> texture, SDL_Rect pos, Rotate rotate, float zoom_w, float zoom_h, SDL_RendererFlip flip)
: Sprite((int)x, (int)y, w, h, texture), : Sprite(texture, pos),
x_(x), x_(pos.x),
y_(y), y_(pos.y),
vx_(vx), vx_(0.0f),
vy_(vy), vy_(0.0f),
ax_(ax), ax_(0.0f),
ay_(ay), ay_(0.0f),
zoom_w_(1), rotate_(rotate),
zoom_h_(1), zoom_w_(zoom_w),
counter_(0), zoom_h_(zoom_h),
flip_(SDL_FLIP_NONE) flip_(flip) {}
{
// Establece los valores de rotacion
rotate_.enabled = false;
rotate_.speed = 0;
rotate_.angle = 0.0f;
rotate_.amount = 0.0f;
rotate_.center = nullptr;
sprite_clip_ = (SDL_Rect){0, 0, w, h}; MovingSprite::MovingSprite(std::shared_ptr<Texture> texture, SDL_Rect pos)
}; : Sprite(texture, pos),
x_(pos.x),
y_(pos.y),
vx_(0.0f),
vy_(0.0f),
ax_(0.0f),
ay_(0.0f),
rotate_(Rotate()),
zoom_w_(1.0f),
zoom_h_(1.0f),
flip_(SDL_FLIP_NONE) {}
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture) MovingSprite::MovingSprite(std::shared_ptr<Texture> texture)
: Sprite(texture) : Sprite(texture),
{ x_(0.0f),
clear(); y_(0.0f),
}; vx_(0.0f),
vy_(0.0f),
ax_(0.0f),
ay_(0.0f),
rotate_(Rotate()),
zoom_w_(1.0f),
zoom_h_(1.0f),
flip_(SDL_FLIP_NONE) { Sprite::clear(); }
// Reinicia todas las variables // Reinicia todas las variables
void MovingSprite::clear() void MovingSprite::clear()
@@ -43,21 +53,14 @@ void MovingSprite::clear()
ax_ = 0.0f; // Aceleración en el eje X. Variación de la velocidad ax_ = 0.0f; // Aceleración en el eje X. Variación de la velocidad
ay_ = 0.0f; // Aceleración en el eje Y. Variación de la velocidad ay_ = 0.0f; // Aceleración en el eje Y. Variación de la velocidad
rotate_ = Rotate(); // Inicializa la estructura
zoom_w_ = 1.0f; // Zoom aplicado a la anchura zoom_w_ = 1.0f; // Zoom aplicado a la anchura
zoom_h_ = 1.0f; // Zoom aplicado a la altura zoom_h_ = 1.0f; // Zoom aplicado a la altura
rotate_.enabled = false; // Indica si ha de rotar
rotate_.speed = 0; // Velocidad de giro
rotate_.angle = 0.0f; // Angulo para dibujarlo
rotate_.amount = 0.0f; // Cantidad de grados a girar en cada iteración
rotate_.center = nullptr; // Centro de rotación
counter_ = 0; // Contador interno
flip_ = SDL_FLIP_NONE; // Establece como se ha de voltear el sprite flip_ = SDL_FLIP_NONE; // Establece como se ha de voltear el sprite
setPos((SDL_Rect){0, 0, 0, 0}); Sprite::clear();
setSpriteClip((SDL_Rect){0, 0, 0, 0});
} }
// Mueve el sprite // Mueve el sprite
@@ -68,12 +71,140 @@ void MovingSprite::move()
vx_ += ax_; vx_ += ax_;
vy_ += ay_; vy_ += ay_;
pos_.x = static_cast<int>(x_);
pos_.y = static_cast<int>(y_);
}
// Actualiza las variables internas del objeto
void MovingSprite::update()
{
move();
rotate();
} }
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void MovingSprite::render() void MovingSprite::render()
{ {
texture_->render((int)x_, (int)y_, &sprite_clip_, zoom_w_, zoom_h_, (double)rotate_.angle, rotate_.center, flip_); texture_->render(pos_.x, pos_.y, &sprite_clip_, zoom_w_, zoom_h_, rotate_.angle, rotate_.center, flip_);
}
// Obtiene el valor de la variable
float MovingSprite::getZoomW() const
{
return zoom_w_;
}
// Obtiene el valor de la variable
float MovingSprite::getZoomH() const
{
return zoom_h_;
}
// Obtiene el valor de la variable
double MovingSprite::getAngle() const
{
return rotate_.angle;
}
// Establece el valor de la variable
void MovingSprite::setZoomW(float value)
{
zoom_w_ = value;
}
// Establece el valor de la variable
void MovingSprite::setZoomH(float value)
{
zoom_h_ = value;
}
// Establece el valor de la variable
void MovingSprite::setAngle(double value)
{
rotate_.angle = value;
}
// Incrementa el valor del ángulo
void MovingSprite::updateAngle()
{
rotate_.angle += rotate_.amount;
}
// Obtiene el valor de la variable
bool MovingSprite::isRotating() const
{
return rotate_.enabled;
}
// Obtiene el valor de la variable
int MovingSprite::getRotateSpeed() const
{
return rotate_.speed;
}
// Establece la rotacion
void MovingSprite::rotate()
{
if (rotate_.enabled)
{
++rotate_.counter;
if (rotate_.counter % rotate_.speed == 0)
{
updateAngle();
rotate_.counter = 0;
}
}
}
// Establece el valor de la variable
void MovingSprite::enableRotate()
{
rotate_.enabled = true;
rotate_.counter = 0;
}
// Establece el valor de la variable
void MovingSprite::disableRotate()
{
rotate_.enabled = false;
rotate_.counter = 0;
}
// Establece el valor de la variable
void MovingSprite::setRotateSpeed(int value)
{
rotate_.speed = std::max(1, value);
}
// Establece el valor de la variable
void MovingSprite::setRotateAmount(double value)
{
rotate_.amount = value;
}
// Cambia el sentido de la rotación
void MovingSprite::switchRotate()
{
rotate_.amount *= -1;
}
// Establece el valor de la variable
void MovingSprite::setFlip(SDL_RendererFlip flip)
{
flip_ = flip;
}
// Gira el sprite horizontalmente
void MovingSprite::flip()
{
flip_ = (flip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL;
}
// Obtiene el valor de la variable
SDL_RendererFlip MovingSprite::getFlip()
{
return flip_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
@@ -112,29 +243,11 @@ float MovingSprite::getAccelY() const
return ay_; return ay_;
} }
// Obtiene el valor de la variable
float MovingSprite::getZoomW() const
{
return zoom_w_;
}
// Obtiene el valor de la variable
float MovingSprite::getZoomH() const
{
return zoom_h_;
}
// Obtiene el valor de la variable
float MovingSprite::getAngle() const
{
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::setPos(SDL_Rect rect) void MovingSprite::setPos(SDL_Rect rect)
{ {
x_ = (float)rect.x; x_ = static_cast<float>(rect.x);
y_ = (float)rect.y; y_ = static_cast<float>(rect.y);
pos_ = rect; pos_ = rect;
} }
@@ -145,22 +258,22 @@ void MovingSprite::setPos(float x, float y)
x_ = x; x_ = x;
y_ = y; y_ = y;
pos_.x = (int)x; pos_.x = static_cast<int>(x_);
pos_.y = (int)y; pos_.y = static_cast<int>(y_);
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setPosX(float value) void MovingSprite::setPosX(float value)
{ {
x_ = value; x_ = value;
pos_.x = (int)x_; pos_.x = static_cast<int>(x_);
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setPosY(float value) void MovingSprite::setPosY(float value)
{ {
y_ = value; y_ = value;
pos_.y = (int)y_; pos_.y = static_cast<int>(y_);
} }
// Establece el valor de la variable // Establece el valor de la variable
@@ -186,120 +299,3 @@ void MovingSprite::setAccelY(float value)
{ {
ay_ = value; ay_ = value;
} }
// Establece el valor de la variable
void MovingSprite::setZoomW(float value)
{
zoom_w_ = value;
}
// Establece el valor de la variable
void MovingSprite::setZoomH(float value)
{
zoom_h_ = value;
}
// Establece el valor de la variable
void MovingSprite::setAngle(double value)
{
rotate_.angle = value;
}
// Incrementa el valor de la variable
void MovingSprite::incAngle(double value)
{
rotate_.angle += value;
}
// Decrementa el valor de la variable
void MovingSprite::decAngle(double value)
{
rotate_.angle -= value;
}
// Obtiene el valor de la variable
bool MovingSprite::getRotate() const
{
return rotate_.enabled;
}
// Obtiene el valor de la variable
Uint16 MovingSprite::getRotateSpeed() const
{
return rotate_.speed;
}
// Establece la rotacion
void MovingSprite::rotate()
{
if (rotate_.enabled)
{
if (counter_ % rotate_.speed == 0)
{
incAngle(rotate_.amount);
}
}
}
// Establece el valor de la variable
void MovingSprite::setRotate(bool value)
{
rotate_.enabled = value;
}
// Establece el valor de la variable
void MovingSprite::setRotateSpeed(int value)
{
rotate_.speed = (value < 1) ? 1 : value;
}
// Establece el valor de la variable
void MovingSprite::setRotateAmount(double value)
{
rotate_.amount = value;
}
// Establece el valor de la variable
void MovingSprite::disableRotate()
{
rotate_.enabled = false;
rotate_.angle = 0.0f;
}
// Actualiza las variables internas del objeto
void MovingSprite::update()
{
move();
rotate();
++counter_ %= 60000;
}
// Cambia el sentido de la rotación
void MovingSprite::switchRotate()
{
rotate_.amount *= -1;
}
// Establece el valor de la variable
void MovingSprite::setFlip(SDL_RendererFlip flip)
{
flip_ = flip;
}
// Gira el sprite horizontalmente
void MovingSprite::flip()
{
flip_ = (flip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL;
}
// Obtiene el valor de la variable
SDL_RendererFlip MovingSprite::getFlip()
{
return flip_;
}
// Devuelve el rectangulo donde está el sprite
SDL_Rect MovingSprite::getPos() const
{
return (SDL_Rect){(int)x_, (int)y_, pos_.w, pos_.h};
}

View File

@@ -7,19 +7,23 @@
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
class Texture; class Texture;
// Clase MovingSprite. Añade posicion y velocidad en punto flotante // Clase MovingSprite. Añade movimiento y efectos de rotación, zoom y flip al sprite
class MovingSprite : public Sprite class MovingSprite : public Sprite
{ {
protected: public:
struct Rotate struct Rotate
{ {
bool enabled; // Indica si ha de rotar bool enabled; // Indica si ha de rotar
int counter; // Contador
int speed; // Velocidad de giro int speed; // Velocidad de giro
float angle; // Angulo para dibujarlo double angle; // Angulo para dibujarlo
float amount; // Cantidad de grados a girar en cada iteración float amount; // Cantidad de grados a girar en cada iteración
SDL_Point *center; // Centro de rotación SDL_Point *center; // Centro de rotación
Rotate() : enabled(false), counter(0), speed(0), angle(0.0), amount(0.0f), center(nullptr) {}
}; };
protected:
float x_; // Posición en el eje X float x_; // Posición en el eje X
float y_; // Posición en el eje Y float y_; // Posición en el eje Y
@@ -29,20 +33,13 @@ protected:
float ax_; // Aceleración en el eje X. Variación de la velocidad 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 ay_; // Aceleración en el eje Y. Variación de la velocidad
Rotate rotate_; // Variables usada para controlar la rotación del sprite
float zoom_w_; // Zoom aplicado a la anchura float zoom_w_; // Zoom aplicado a la anchura
float zoom_h_; // Zoom aplicado a la altura 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 SDL_RendererFlip flip_; // Indica como se voltea el sprite
public: // Incrementa el valor del ángulo
// Constructor void updateAngle();
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();
@@ -50,54 +47,46 @@ public:
// Rota el sprite // Rota el sprite
void rotate(); void rotate();
public:
// Constructor
MovingSprite(std::shared_ptr<Texture> texture, SDL_Rect pos, MovingSprite::Rotate rotate, float zoom_w, float zoom_h, SDL_RendererFlip flip);
MovingSprite(std::shared_ptr<Texture> texture, SDL_Rect pos);
explicit MovingSprite(std::shared_ptr<Texture> texture);
// Destructor
~MovingSprite() = default;
// Actualiza las variables internas del objeto // Actualiza las variables internas del objeto
virtual void update(); virtual void update();
// Reinicia todas las variables // Reinicia todas las variables a cero
void clear(); void clear() override;
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void render() override; void render() override;
// Obten el valor de la variable // Obtiene la variable
float getPosX() const; float getPosX() const;
float getPosY() const; float getPosY() const;
// Obten el valor de la variable
float getVelX() const; float getVelX() const;
float getVelY() const; float getVelY() const;
// Obten el valor de la variable
float getAccelX() const; float getAccelX() const;
float getAccelY() const; float getAccelY() const;
// Establece la variable
void setVelX(float value);
void setVelY(float value);
void setAccelX(float value);
void setAccelY(float value);
// Obten el valor de la variable // Obten el valor de la variable
float getZoomW() const; float getZoomW() const;
float getZoomH() const; float getZoomH() const;
// Obten el valor de la variable // Obten el valor de la variable
float getAngle() const; bool isRotating() const;
bool getRotate() const; double getAngle() const;
Uint16 getRotateSpeed() const; int getRotateSpeed() const;
// Establece la posición del objeto
void setPos(SDL_Rect rect) override;
void setPos(float x, float y);
// Devuelve el rectangulo donde está el sprite
SDL_Rect getPos() const override;
// Establece el valor de la variable
void setPosX(float value);
void setPosY(float value);
// Establece el valor de la variable
void setVelX(float value);
void setVelY(float value);
// Establece el valor de la variable
void setAccelX(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);
@@ -105,17 +94,15 @@ public:
// Establece el valor de la variable // Establece el valor de la variable
void setAngle(double vaue); void setAngle(double vaue);
void incAngle(double value);
void decAngle(double value); // Activa o desactiva el efecto derotación
void enableRotate();
void disableRotate();
// Establece el valor de la variable // Establece el valor de la variable
void setRotate(bool value);
void setRotateSpeed(int value); void setRotateSpeed(int value);
void setRotateAmount(double value); void setRotateAmount(double value);
// Quita el efecto de rotación y deja el sprite en su angulo inicial.
void disableRotate();
// Cambia el sentido de la rotación // Cambia el sentido de la rotación
void switchRotate(); void switchRotate();
@@ -128,5 +115,15 @@ public:
// Obtiene el valor de la variable // Obtiene el valor de la variable
SDL_RendererFlip getFlip(); SDL_RendererFlip getFlip();
// Establece la posición y_ el tamaño del objeto
void setPos(SDL_Rect rect);
// Establece el valor de las variables
void setPos(float x, float y);
// Establece el valor de la variable
void setPosX(float value);
// Establece el valor de la variable
void setPosY(float value);
}; };

344
source/notifier.cpp Normal file
View File

@@ -0,0 +1,344 @@
#include "notifier.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <string> // for string
#include "jail_audio.h" // for JA_DeleteSound, JA_LoadSound, JA_Pla...
#include "param.h" // for param
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "sprite.h" // for Sprite
#include "text.h" // for Text
#include "texture.h" // for Texture
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Notifier *Notifier::notifier_ = nullptr;
// [SINGLETON] Crearemos el objeto screen con esta función estática
void Notifier::init(std::string icon_file, std::shared_ptr<Text> text, const std::string &sound_file)
{
Notifier::notifier_ = new Notifier(icon_file, text, sound_file);
}
// [SINGLETON] Destruiremos el objeto screen con esta función estática
void Notifier::destroy()
{
delete Notifier::notifier_;
}
// [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él
Notifier *Notifier::get()
{
return Notifier::notifier_;
}
// Constructor
Notifier::Notifier(std::string icon_file, std::shared_ptr<Text> text, const std::string &sound_file)
: renderer_(Screen::get()->getRenderer()),
text_(text),
bg_color_(param.notification.color),
wait_time_(150),
stack_(false),
sound_(JA_LoadSound(sound_file.c_str()))
{
// Inicializa variables
has_icons_ = !icon_file.empty();
// Crea objetos
icon_texture_ = has_icons_ ? std::make_unique<Texture>(renderer_, icon_file) : nullptr;
}
// Destructor
Notifier::~Notifier()
{
// Libera la memoria de los objetos
JA_DeleteSound(sound_);
notifications_.clear();
}
// Dibuja las notificaciones por pantalla
void Notifier::render()
{
for (int i = (int)notifications_.size() - 1; i >= 0; --i)
{
notifications_[i].sprite->render();
}
}
// Actualiza el estado de las notificaiones
void Notifier::update()
{
for (int i = 0; i < (int)notifications_.size(); ++i)
{
// Si la notificación anterior está "saliendo", no hagas nada
if (i > 0)
{
if (notifications_[i - 1].status == NotificationStatus::RISING)
{
break;
}
}
notifications_[i].counter++;
// Hace sonar la notificación en el primer frame
if (notifications_[i].counter == 1)
{
if (param.notification.sound)
{
if (notifications_[i].status == NotificationStatus::RISING)
{ // Reproduce el sonido de la notificación
JA_PlaySound(sound_);
}
}
}
// Comprueba los estados
if (notifications_[i].status == NotificationStatus::RISING)
{
const float step = ((float)notifications_[i].counter / notifications_[i].travel_dist);
const int alpha = 255 * step;
if (param.notification.pos_v == NotifyPosition::TOP)
{
notifications_[i].rect.y++;
}
else
{
notifications_[i].rect.y--;
}
notifications_[i].texture->setAlpha(alpha);
if (notifications_[i].rect.y == notifications_[i].y)
{
notifications_[i].status = NotificationStatus::STAY;
notifications_[i].texture->setAlpha(255);
notifications_[i].counter = 0;
}
}
else if (notifications_[i].status == NotificationStatus::STAY)
{
if (notifications_[i].counter == wait_time_)
{
notifications_[i].status = NotificationStatus::VANISHING;
notifications_[i].counter = 0;
}
}
else if (notifications_[i].status == NotificationStatus::VANISHING)
{
const float step = (notifications_[i].counter / (float)notifications_[i].travel_dist);
const int alpha = 255 * (1 - step);
if (param.notification.pos_v == NotifyPosition::TOP)
{
notifications_[i].rect.y--;
}
else
{
notifications_[i].rect.y++;
}
notifications_[i].texture->setAlpha(alpha);
if (notifications_[i].rect.y == notifications_[i].y - notifications_[i].travel_dist)
{
notifications_[i].status = NotificationStatus::FINISHED;
}
}
notifications_[i].sprite->setPosition(notifications_[i].rect);
}
clearFinishedNotifications();
}
// Elimina las notificaciones finalizadas
void Notifier::clearFinishedNotifications()
{
for (int i = (int)notifications_.size() - 1; i >= 0; --i)
{
if (notifications_[i].status == NotificationStatus::FINISHED)
{
notifications_.erase(notifications_.begin() + i);
}
}
}
void Notifier::showText(std::string text1, std::string text2, int icon, std::string code)
{
// Cuenta el número de textos a mostrar
const int num_texts = !text1.empty() + !text2.empty();
// Si no hay texto, acaba
if (num_texts == 0)
{
return;
}
// Si solo hay un texto, lo coloca en la primera variable
if (num_texts == 1)
{
text1 += text2;
text2.clear();
}
// Si las notificaciones no se apilan, elimina las anteriores
if (!stack_)
{
clearNotifications();
}
// Inicializa variables
constexpr auto icon_size = 16;
constexpr auto padding_out = 1;
const auto padding_in_h = text_->getCharacterSize();
const auto padding_in_v = text_->getCharacterSize() / 2;
const auto icon_space = icon >= 0 ? icon_size + padding_in_h : 0;
const std::string txt = text1.length() > text2.length() ? text1 : text2;
const auto width = text_->lenght(txt) + (padding_in_h * 2) + icon_space;
const auto height = (text_->getCharacterSize() * num_texts) + (padding_in_v * 2);
const auto shape = NotificationShape::SQUARED;
// Posición horizontal
auto desp_h = 0;
if (param.notification.pos_h == NotifyPosition::LEFT)
{
desp_h = padding_out;
}
else if (param.notification.pos_h == NotifyPosition::MIDDLE)
{
desp_h = ((param.game.width / 2) - (width / 2));
}
else
{
desp_h = param.game.width - width - padding_out;
}
// Posición vertical
const int desp_v = (param.notification.pos_v == NotifyPosition::TOP) ? padding_out : (param.game.height - height - padding_out);
// Offset
const auto travel_dist = height + padding_out;
auto offset = 0;
if (param.notification.pos_v == NotifyPosition::TOP)
{
offset = (int)notifications_.size() > 0 ? notifications_.back().y + travel_dist : desp_v;
}
else
{
offset = (int)notifications_.size() > 0 ? notifications_.back().y - travel_dist : desp_v;
}
// Crea la notificacion
Notification n;
// Inicializa variables
n.code = code;
n.y = offset;
n.travel_dist = travel_dist;
n.counter = 0;
n.status = NotificationStatus::RISING;
n.text1 = text1;
n.text2 = text2;
n.shape = shape;
auto y_pos = offset + (param.notification.pos_v == NotifyPosition::TOP ? -travel_dist : travel_dist);
n.rect = {desp_h, y_pos, width, height};
// Crea la textura
n.texture = std::make_shared<Texture>(renderer_);
n.texture->createBlank(width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET);
n.texture->setBlendMode(SDL_BLENDMODE_BLEND);
// Prepara para dibujar en la textura
n.texture->setAsRenderTarget(renderer_);
// Dibuja el fondo de la notificación
SDL_SetRenderDrawColor(renderer_, bg_color_.r, bg_color_.g, bg_color_.b, 255);
SDL_Rect rect;
if (shape == NotificationShape::ROUNDED)
{
rect = {4, 0, width - (4 * 2), height};
SDL_RenderFillRect(renderer_, &rect);
rect = {4 / 2, 1, width - 4, height - 2};
SDL_RenderFillRect(renderer_, &rect);
rect = {1, 4 / 2, width - 2, height - 4};
SDL_RenderFillRect(renderer_, &rect);
rect = {0, 4, width, height - (4 * 2)};
SDL_RenderFillRect(renderer_, &rect);
}
else if (shape == NotificationShape::SQUARED)
{
SDL_RenderClear(renderer_);
}
// Dibuja el icono de la notificación
if (has_icons_ && icon >= 0 && num_texts == 2)
{
auto sp = std::make_unique<Sprite>(icon_texture_, (SDL_Rect){0, 0, icon_size, icon_size});
sp->setPosition({padding_in_h, padding_in_v, icon_size, icon_size});
sp->setSpriteClip({icon_size * (icon % 10), icon_size * (icon / 10), icon_size, icon_size});
sp->render();
}
// Escribe el texto de la notificación
Color color = {255, 255, 255};
if (num_texts == 2)
{ // Dos lineas de texto
text_->writeColored(padding_in_h + icon_space, padding_in_v, text1, color);
text_->writeColored(padding_in_h + icon_space, padding_in_v + text_->getCharacterSize() + 1, text2, color);
}
else
{ // Una linea de texto
text_->writeColored(padding_in_h + icon_space, padding_in_v, text1, color);
}
// Deja de dibujar en la textura
SDL_SetRenderTarget(renderer_, nullptr);
// Crea el sprite de la notificación
n.sprite = std::make_shared<Sprite>(n.texture, n.rect);
// Deja la notificación invisible
n.texture->setAlpha(0);
// Añade la notificación a la lista
notifications_.push_back(n);
}
// Indica si hay notificaciones activas
bool Notifier::isActive()
{
if ((int)notifications_.size() > 0)
{
return true;
}
return false;
}
// Finaliza y elimnina todas las notificaciones activas
void Notifier::clearNotifications()
{
for (int i = 0; i < (int)notifications_.size(); ++i)
{
notifications_[i].status = NotificationStatus::FINISHED;
}
clearFinishedNotifications();
}
// Obtiene los códigos de las notificaciones
std::vector<std::string> Notifier::getCodes()
{
std::vector<std::string> codes;
for (int i = 0; i < (int)notifications_.size(); ++i)
{
codes.push_back(notifications_[i].code);
}
return codes;
}

121
source/notifier.h Normal file
View File

@@ -0,0 +1,121 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string, basic_string
#include <vector> // for vector
#include "utils.h" // for Color
class Sprite;
class Text;
class Texture;
struct JA_Sound_t; // lines 12-12
class Notifier
{
private:
// [SINGLETON] Objeto notifier privado para Don Melitón
static Notifier *notifier_;
enum class NotificationStatus
{
RISING,
STAY,
VANISHING,
FINISHED,
};
enum class NotificationPosition
{
UPPER_LEFT,
UPPER_CENTER,
UPPER_RIGHT,
MIDDLE_LEFT,
MIDDLE_RIGHT,
BOTTOM_LEFT,
BOTTOM_CENTER,
BOTTOM_RIGHT,
};
enum class NotificationShape
{
ROUNDED,
SQUARED,
};
struct Notification
{
std::shared_ptr<Texture> texture;
std::shared_ptr<Sprite> sprite;
std::string text1;
std::string text2;
int counter;
NotificationStatus status;
NotificationPosition position;
NotificationShape shape;
SDL_Rect rect;
int y;
int travel_dist;
std::string code; // Permite asignar un código a la notificación
};
// Objetos y punteros
SDL_Renderer *renderer_; // El renderizador de la ventana
std::shared_ptr<Texture> icon_texture_; // Textura para los iconos de las notificaciones
std::shared_ptr<Text> text_; // Objeto para dibujar texto
// Variables
Color bg_color_; // Color de fondo de las notificaciones
int wait_time_; // Tiempo que se ve la notificación
std::vector<Notification> notifications_; // La lista de notificaciones activas
bool stack_; // Indica si las notificaciones se apilan
bool has_icons_; // Indica si el notificador tiene textura para iconos
JA_Sound_t *sound_; // Sonido a reproducir cuando suena la notificación
// Elimina las notificaciones finalizadas
void clearFinishedNotifications();
// Finaliza y elimnina todas las notificaciones activas
void clearNotifications();
// [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos notifier desde fuera
// Constructor
Notifier(std::string icon_file, std::shared_ptr<Text> text, const std::string &sound_file);
// Destructor
~Notifier();
public:
// [SINGLETON] Crearemos el objeto notifier con esta función estática
static void init(std::string icon_file, std::shared_ptr<Text> text, const std::string &sound_file);
// [SINGLETON] Destruiremos el objeto notifier con esta función estática
static void destroy();
// [SINGLETON] Con este método obtenemos el objeto notifier y podemos trabajar con él
static Notifier *get();
// Dibuja las notificaciones por pantalla
void render();
// Actualiza el estado de las notificaiones
void update();
/**
* @brief Muestra una notificación de texto por pantalla.
*
* @param text1 Primer texto opcional para mostrar (valor predeterminado: cadena vacía).
* @param text2 Segundo texto opcional para mostrar (valor predeterminado: cadena vacía).
* @param icon Icono opcional para mostrar (valor predeterminado: -1).
* @param code Permite asignar un código a la notificación (valor predeterminado: cadena vacía).
*/
void showText(std::string text1 = std::string(), std::string text2 = std::string(), int icon = -1, std::string code = std::string());
// Indica si hay notificaciones activas
bool isActive();
// Obtiene los códigos de las notificaciones
std::vector<std::string> getCodes();
};

View File

@@ -1,309 +0,0 @@
#include "notify.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <string> // for string
#include "jail_audio.h" // for JA_DeleteSound, JA_LoadSound, JA_Pla...
#include "param.h" // for param
#include "sprite.h" // for Sprite
#include "text.h" // for Text
#include "texture.h" // for Texture
// Constructor
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
hasIcons = !iconFile.empty();
// Crea objetos
iconTexture = hasIcons ? std::make_unique<Texture>(renderer, iconFile) : nullptr;
}
// Destructor
Notify::~Notify()
{
// Libera la memoria de los objetos
JA_DeleteSound(sound);
notifications.clear();
}
// Dibuja las notificaciones por pantalla
void Notify::render()
{
for (int i = (int)notifications.size() - 1; i >= 0; --i)
{
notifications[i].sprite->render();
}
}
// Actualiza el estado de las notificaiones
void Notify::update()
{
for (int i = 0; i < (int)notifications.size(); ++i)
{
// Si la notificación anterior está "saliendo", no hagas nada
if (i > 0)
{
if (notifications[i - 1].status == NotificationStatus::RISING)
{
break;
}
}
notifications[i].counter++;
// Hace sonar la notificación en el primer frame
if (notifications[i].counter == 1)
{
if (param.notification.sound)
{
if (notifications[i].status == NotificationStatus::RISING)
{ // Reproduce el sonido de la notificación
JA_PlaySound(sound);
}
}
}
// Comprueba los estados
if (notifications[i].status == NotificationStatus::RISING)
{
const float step = ((float)notifications[i].counter / notifications[i].travelDist);
const int alpha = 255 * step;
if (param.notification.pos_v == NotifyPosition::TOP)
{
notifications[i].rect.y++;
}
else
{
notifications[i].rect.y--;
}
notifications[i].texture->setAlpha(alpha);
if (notifications[i].rect.y == notifications[i].y)
{
notifications[i].status = NotificationStatus::STAY;
notifications[i].texture->setAlpha(255);
notifications[i].counter = 0;
}
}
else if (notifications[i].status == NotificationStatus::STAY)
{
if (notifications[i].counter == waitTime)
{
notifications[i].status = NotificationStatus::VANISHING;
notifications[i].counter = 0;
}
}
else if (notifications[i].status == NotificationStatus::VANISHING)
{
const float step = (notifications[i].counter / (float)notifications[i].travelDist);
const int alpha = 255 * (1 - step);
if (param.notification.pos_v == NotifyPosition::TOP)
{
notifications[i].rect.y--;
}
else
{
notifications[i].rect.y++;
}
notifications[i].texture->setAlpha(alpha);
if (notifications[i].rect.y == notifications[i].y - notifications[i].travelDist)
{
notifications[i].status = NotificationStatus::FINISHED;
}
}
notifications[i].sprite->setPos(notifications[i].rect);
}
clearFinishedNotifications();
}
// Elimina las notificaciones finalizadas
void Notify::clearFinishedNotifications()
{
for (int i = (int)notifications.size() - 1; i >= 0; --i)
{
if (notifications[i].status == NotificationStatus::FINISHED)
{
notifications.erase(notifications.begin() + i);
}
}
}
// Muestra una notificación de texto por pantalla;
void Notify::showText(std::string text1, std::string text2, int icon)
{
// Cuenta el número de textos a mostrar
const int numTexts = !text1.empty() + !text2.empty();
// Si no hay texto, acaba
if (numTexts == 0)
{
return;
}
// Si solo hay un texto, lo coloca en la primera variable
if (numTexts == 1)
{
text1 += text2;
text2.clear();
}
// Si las notificaciones no se apilan, elimina las anteriores
if (!stack)
{
clearNotifications();
}
// Inicializa variables
constexpr auto iconSize = 16;
constexpr auto paddingOut = 1;
const auto paddingIn = text->getCharacterSize() / 2;
const auto iconSpace = icon >= 0 ? iconSize + paddingIn : 0;
const std::string txt = text1.length() > text2.length() ? text1 : text2;
const auto width = text->lenght(txt) + (paddingIn * 2) + iconSpace;
const auto height = (text->getCharacterSize() * numTexts) + (paddingIn * 2);
const auto shape = NotificationShape::SQUARED;
// Posición horizontal
auto despH = 0;
if (param.notification.pos_h == NotifyPosition::LEFT)
{
despH = paddingOut;
}
else if (param.notification.pos_h == NotifyPosition::MIDDLE)
{
despH = ((param.game.width / 2) - (width / 2));
}
else
{
despH = param.game.width - width - paddingOut;
}
// Posición vertical
const int despV = (param.notification.pos_v == NotifyPosition::TOP) ? paddingOut : (param.game.height - height - paddingOut);
// Offset
const auto travelDist = height + paddingOut;
auto offset = 0;
if (param.notification.pos_v == NotifyPosition::TOP)
{
offset = (int)notifications.size() > 0 ? notifications.back().y + travelDist : despV;
}
else
{
offset = (int)notifications.size() > 0 ? notifications.back().y - travelDist : despV;
}
// Crea la notificacion
Notification n;
// Inicializa variables
n.y = offset;
n.travelDist = travelDist;
n.counter = 0;
n.status = NotificationStatus::RISING;
n.text1 = text1;
n.text2 = text2;
n.shape = shape;
auto yPos = offset + (param.notification.pos_v == NotifyPosition::TOP ? -travelDist : travelDist);
n.rect = {despH, yPos, width, height};
// Crea la textura
n.texture = std::make_shared<Texture>(renderer);
n.texture->createBlank(width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET);
n.texture->setBlendMode(SDL_BLENDMODE_BLEND);
// Prepara para dibujar en la textura
n.texture->setAsRenderTarget(renderer);
// Dibuja el fondo de la notificación
SDL_SetRenderDrawColor(renderer, bgColor.r, bgColor.g, bgColor.b, 255);
SDL_Rect rect;
if (shape == NotificationShape::ROUNDED)
{
rect = {4, 0, width - (4 * 2), height};
SDL_RenderFillRect(renderer, &rect);
rect = {4 / 2, 1, width - 4, height - 2};
SDL_RenderFillRect(renderer, &rect);
rect = {1, 4 / 2, width - 2, height - 4};
SDL_RenderFillRect(renderer, &rect);
rect = {0, 4, width, height - (4 * 2)};
SDL_RenderFillRect(renderer, &rect);
}
else if (shape == NotificationShape::SQUARED)
{
SDL_RenderClear(renderer);
}
// Dibuja el icono de la notificación
if (hasIcons && icon >= 0 && numTexts == 2)
{
auto sp = std::make_unique<Sprite>((SDL_Rect){0, 0, iconSize, iconSize}, iconTexture);
sp->setPos({paddingIn, paddingIn, iconSize, iconSize});
sp->setSpriteClip({iconSize * (icon % 10), iconSize * (icon / 10), iconSize, iconSize});
sp->render();
}
// Escribe el texto de la notificación
Color color = {255, 255, 255};
if (numTexts == 2)
{ // Dos lineas de texto
text->writeColored(paddingIn + iconSpace, paddingIn, text1, color);
text->writeColored(paddingIn + iconSpace, paddingIn + text->getCharacterSize() + 1, text2, color);
}
else
{ // Una linea de texto
text->writeColored(paddingIn + iconSpace, paddingIn, text1, color);
}
// Deja de dibujar en la textura
SDL_SetRenderTarget(renderer, nullptr);
// Crea el sprite de la notificación
n.sprite = std::make_shared<Sprite>(n.rect, n.texture);
// Deja la notificación invisible
n.texture->setAlpha(0);
// Añade la notificación a la lista
notifications.push_back(n);
}
// Indica si hay notificaciones activas
bool Notify::active()
{
if ((int)notifications.size() > 0)
{
return true;
}
return false;
}
// Finaliza y elimnina todas las notificaciones activas
void Notify::clearNotifications()
{
for (int i = 0; i < (int)notifications.size(); ++i)
{
notifications[i].status = NotificationStatus::FINISHED;
}
clearFinishedNotifications();
}

View File

@@ -1,96 +0,0 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string, basic_string
#include <vector> // for vector
#include "utils.h" // for Color
class Sprite;
class Text;
class Texture;
struct JA_Sound_t; // lines 12-12
class Notify
{
private:
enum class NotificationStatus
{
RISING,
STAY,
VANISHING,
FINISHED,
};
enum class NotificationPosition
{
UPPER_LEFT,
UPPER_CENTER,
UPPER_RIGHT,
MIDDLE_LEFT,
MIDDLE_RIGHT,
BOTTOM_LEFT,
BOTTOM_CENTER,
BOTTOM_RIGHT,
};
enum class NotificationShape
{
ROUNDED,
SQUARED,
};
struct Notification
{
std::shared_ptr<Texture> texture;
std::shared_ptr<Sprite> sprite;
std::string text1;
std::string text2;
int counter;
NotificationStatus status;
NotificationPosition position;
NotificationShape shape;
SDL_Rect rect;
int y;
int travelDist;
};
// Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana
std::shared_ptr<Texture> iconTexture; // Textura para los iconos de las notificaciones
std::unique_ptr<Text> text; // Objeto para dibujar texto
// Variables
Color bgColor; // Color de fondo de las notificaciones
int waitTime; // Tiempo que se ve la notificación
std::vector<Notification> notifications; // La lista de notificaciones activas
bool stack; // Indica si las notificaciones se apilan
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
void clearFinishedNotifications();
// Finaliza y elimnina todas las notificaciones activas
void clearNotifications();
public:
// Constructor
Notify(SDL_Renderer *renderer, std::string iconFile, std::string bitmapFile, std::string textFile, const std::string &soundFile);
// Destructor
~Notify();
// Dibuja las notificaciones por pantalla
void render();
// Actualiza el estado de las notificaiones
void update();
// Muestra una notificación de texto por pantalla;
void showText(std::string text1 = std::string(), std::string text2 = std::string(), int icon = -1);
// Indica si hay notificaciones activas
bool active();
};

View File

@@ -5,6 +5,7 @@
#include "asset.h" // for Asset #include "asset.h" // for Asset
#include "lang.h" // for getText #include "lang.h" // for getText
#include "param.h" // for param #include "param.h" // for param
#include "resource.h" // for Resource
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "text.h" // for Text #include "text.h" // for Text
@@ -95,13 +96,13 @@ void OnScreenHelp::fillTexture()
SDL_SetRenderTarget(Screen::get()->getRenderer(), texture); SDL_SetRenderTarget(Screen::get()->getRenderer(), texture);
// Crea el objeto para el texto // Crea el objeto para el texto
auto text = std::make_unique<Text>(Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), Screen::get()->getRenderer()); auto text = std::make_unique<Text>(Resource::get()->getTexture("8bithud.png"), Resource::get()->getTextFile("8bithud.txt"));
// Crea la textura con los gráficos // Crea la textura con los gráficos
auto controllersTexture = std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("controllers.png")); auto controllersTexture = Resource::get()->getTexture("controllers.png");
// Crea el sprite para dibujar los gráficos // Crea el sprite para dibujar los gráficos
auto sprite = std::make_unique<Sprite>((SDL_Rect){0, 0, 16, 16}, controllersTexture); auto sprite = std::make_unique<Sprite>(controllersTexture, (SDL_Rect){0, 0, 16, 16});
// Borra la textura // Borra la textura
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 0); SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 0);
@@ -170,7 +171,7 @@ void OnScreenHelp::toggleState()
// Calcula la longitud en pixels del texto más largo // Calcula la longitud en pixels del texto más largo
auto OnScreenHelp::getLargestStringSize() -> int const auto OnScreenHelp::getLargestStringSize() -> int const
{ {
auto text = std::make_unique<Text>(Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), Screen::get()->getRenderer()); auto text = std::make_unique<Text>(Resource::get()->getTexture("8bithud.png"), Resource::get()->getTextFile("8bithud.txt"));
auto size = 0; auto size = 0;
for (int i = 107; i <= 113; ++i) for (int i = 107; i <= 113; ++i)
@@ -186,7 +187,7 @@ auto OnScreenHelp::getLargestStringSize() -> int const
void OnScreenHelp::renderButton(Sprite *sprite, Text *text, const SDL_Rect &buttonClip, const SDL_Rect &buttonPos, int textId) void OnScreenHelp::renderButton(Sprite *sprite, Text *text, const SDL_Rect &buttonClip, const SDL_Rect &buttonPos, int textId)
{ {
sprite->setSpriteClip(buttonClip); sprite->setSpriteClip(buttonClip);
sprite->setPos(buttonPos); sprite->setPosition(buttonPos);
sprite->render(); sprite->render();
text->write(buttonPos.x + DESP.x, buttonPos.y + DESP.y, lang::getText(textId)); text->write(buttonPos.x + DESP.x, buttonPos.y + DESP.y, lang::getText(textId));
} }

View File

@@ -86,18 +86,14 @@ bool loadOptionsFile(std::string file_path)
bool success = true; bool success = true;
// Variables para manejar el fichero // Variables para manejar el fichero
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
std::ifstream file(file_path); 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
std::cout << "Reading file: " << file_name << std::endl; std::cout << "Reading file: " << file_name << std::endl;
#endif
std::string line; std::string line;
while (std::getline(file, line)) while (std::getline(file, line))
{ {
@@ -109,10 +105,8 @@ bool loadOptionsFile(std::string file_path)
// Procesa las dos subcadenas // Procesa las dos subcadenas
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
std::cout << "Warning: file " << file_name << 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
success = false; success = false;
} }
} }
@@ -152,22 +146,16 @@ bool loadOptionsFile(std::string file_path)
// Guarda el fichero de configuración // Guarda el fichero de configuración
bool saveOptionsFile(std::string file_path) bool saveOptionsFile(std::string file_path)
{ {
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
std::ofstream file(file_path); std::ofstream file(file_path);
if (!file.good()) if (!file.good())
{ {
#ifdef VERBOSE
std::cout << file_name << " can't be opened" << std::endl; std::cout << file_name << " can't be opened" << std::endl;
#endif
return false; return false;
} }
#ifdef VERBOSE
std::cout << "Writing file: " << file_name << std::endl; std::cout << "Writing file: " << file_name << std::endl;
#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_winow = std::to_string(static_cast<int>(ScreenVideoMode::WINDOW));

View File

@@ -65,109 +65,6 @@ void initParam()
param.notification.color.b = 48; param.notification.color.b = 48;
} }
// Establece valores para los parametros a partir de un fichero de texto
/*void loadParamsFromFile(std::string file_path)
{
// Pone valores por defecto a las variables
initParam();
// Variables para manejar el fichero
std::ifstream file(file_path);
std::string line;
std::string param1;
std::string param2;
// Si el fichero se puede abrir
if (file.good())
{
#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
// Procesa cada linea del fichero
while (std::getline(file, line))
{
// Reinicia variables
param1.clear();
param2.clear();
// Elimina los comentarios al final de una linea
{
// line = line.substr(0, line.find("#"));
auto pos = line.find("#");
if (pos != std::string::npos)
{
line.resize(pos);
}
}
// Ignora los espacios en blanco
int pos = 0;
while (pos < (int)line.size() && (int)line[pos] <= 32)
{
pos++;
}
// Si no ha llegado al final de la linea, es que hay algo escrito (no es una linea vacía)
if (pos < (int)line.size())
{
// Elimina el espacio en blanco
line = line.substr(pos, std::string::npos);
// Se queda con todo lo que no sean espacios en blanco
pos = 1;
while (pos <= (int)line.size() && (int)line[pos] > 32)
{
pos++;
}
// Si llega al final de la linea, falta la segunda palabra
if (pos < (int)line.size())
{
// Se queda con la primera palabra
param1 = line.substr(0, pos);
// Y recorta la linea
line = line.substr(pos, std::string::npos);
// Ignora los espacios en blanco
pos = 0;
while (pos <= (int)line.size() && (int)line[pos] <= 32)
{
pos++;
}
// Si llega al final de la linea, falta la segunda palabra
if (pos < (int)line.size())
{
// Elimina el espacio en blanco
line = line.substr(pos, std::string::npos);
// Ignora los espacios en blanco
pos = 1;
while (pos <= (int)line.size() && (int)line[pos] > 32)
{
pos++;
}
// Se queda con la segunda palabra
param2 = line.substr(0, pos);
}
}
}
setParams(param1, param2);
}
// Cierra el fichero
file.close();
}
#ifdef VERBOSE
else
std::cout << "Failed to load file: " << file_path << std::endl;
#endif
precalculateZones();
}*/
void loadParamsFromFile(const std::string &file_path) void loadParamsFromFile(const std::string &file_path)
{ {
// Inicializa los parámetros con valores por defecto // Inicializa los parámetros con valores por defecto
@@ -177,16 +74,12 @@ void loadParamsFromFile(const std::string &file_path)
std::ifstream file(file_path); std::ifstream file(file_path);
if (!file.is_open()) if (!file.is_open())
{ {
#ifdef VERBOSE
std::cerr << "Error: No se pudo abrir el archivo " << file_path << std::endl; 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); 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); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
std::cout << "Reading file: " << file_name << std::endl; std::cout << "Reading file: " << file_name << std::endl;
#endif
std::string line, param1, param2; std::string line, param1, param2;
while (std::getline(file, line)) while (std::getline(file, line))
@@ -255,6 +148,11 @@ bool setParams(const std::string &var, const std::string &value)
param.game.play_area.rect.h = std::stoi(value); param.game.play_area.rect.h = std::stoi(value);
} }
else if (var == "game.enter_name_seconds")
{
param.game.enter_name_seconds = std::stoi(value);
}
// FADE // FADE
else if (var == "fade.num_squares_width") else if (var == "fade.num_squares_width")
{ {

View File

@@ -3,7 +3,7 @@
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <stdlib.h> // for rand #include <stdlib.h> // for rand
#include <algorithm> // for max, min #include <algorithm> // for max, min
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for SpriteAnimated
#include "input.h" // for inputs_e #include "input.h" // for inputs_e
#include "param.h" // for param #include "param.h" // for param
#include "texture.h" // for Texture #include "texture.h" // for Texture
@@ -11,9 +11,9 @@
#include "options.h" #include "options.h"
// Constructor // Constructor
Player::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) Player::Player(int id, float x, int y, bool demo, SDL_Rect *play_area, std::vector<std::shared_ptr<Texture>> texture, const std::vector<std::vector<std::string>> &animations)
: player_sprite_(std::make_unique<AnimatedSprite>(texture[0], "", animations[0])), : player_sprite_(std::make_unique<AnimatedSprite>(texture[0], animations[0])),
power_sprite_(std::make_unique<AnimatedSprite>(texture[1], "", animations[1])), power_sprite_(std::make_unique<AnimatedSprite>(texture[1], animations[1])),
enter_name_(std::make_unique<EnterName>()), enter_name_(std::make_unique<EnterName>()),
play_area_(play_area), play_area_(play_area),
id_(id), id_(id),
@@ -55,7 +55,9 @@ void Player::init()
coffees_ = 0; coffees_ = 0;
input_ = true; input_ = true;
continue_ticks_ = 0; continue_ticks_ = 0;
continue_counter_ = 20; continue_counter_ = 10;
enter_name_ticks_ = 0;
enter_name_counter_ = param.game.enter_name_seconds;
width_ = 30; width_ = 30;
height_ = 30; height_ = 30;
collider_.r = 9; collider_.r = 9;
@@ -68,6 +70,7 @@ void Player::init()
cooldown_ = 10; cooldown_ = 10;
// Establece la posición del sprite // Establece la posición del sprite
player_sprite_->clear();
player_sprite_->setPosX(pos_x_); player_sprite_->setPosX(pos_x_);
player_sprite_->setPosY(pos_y_); player_sprite_->setPosY(pos_y_);
@@ -277,10 +280,10 @@ void Player::setAnimation()
} }
// Actualiza las animaciones de los sprites // Actualiza las animaciones de los sprites
player_sprite_->animate(); player_sprite_->update();
// powerSprite->setFlip(flip_walk); // powerSprite->setFlip(flip_walk);
power_sprite_->animate(); power_sprite_->update();
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
@@ -344,9 +347,10 @@ void Player::update()
setAnimation(); setAnimation();
shiftColliders(); shiftColliders();
updateCooldown(); updateCooldown();
updatePowerUpCounter(); updatePowerUp();
updateInvulnerable(); updateInvulnerable();
updateContinueCounter(); updateContinueCounter();
updateEnterNameCounter();
updateScoreboard(); updateScoreboard();
} }
@@ -574,7 +578,7 @@ void Player::updateInvulnerable()
{ {
if (invulnerable_counter_ > 0) if (invulnerable_counter_ > 0)
{ {
invulnerable_counter_--; --invulnerable_counter_;
invulnerable_counter_ % 8 > 3 ? player_sprite_->getTexture()->setPalette(coffees_) : player_sprite_->getTexture()->setPalette(3); invulnerable_counter_ % 8 > 3 ? player_sprite_->getTexture()->setPalette(coffees_) : player_sprite_->getTexture()->setPalette(3);
} }
else else
@@ -611,15 +615,12 @@ void Player::setPowerUpCounter(int value)
} }
// Actualiza el valor de la variable // Actualiza el valor de la variable
void Player::updatePowerUpCounter() void Player::updatePowerUp()
{ {
if ((power_up_counter_ > 0) && (power_up_)) if (power_up_)
{ {
power_up_counter_--; --power_up_counter_;
} power_up_ = power_up_counter_ > 0;
else
{
power_up_ = false;
} }
} }
@@ -711,6 +712,20 @@ void Player::updateContinueCounter()
} }
} }
// Actualiza el contador de entrar nombre
void Player::updateEnterNameCounter()
{
if (status_playing_ == PlayerStatus::ENTERING_NAME)
{
constexpr Uint32 ticks_speed = 1000;
if (SDL_GetTicks() - enter_name_ticks_ > ticks_speed)
{
decEnterNameCounter();
}
}
}
// Le asigna un panel en el marcador al jugador // Le asigna un panel en el marcador al jugador
void Player::setScoreBoardPanel(int panel) void Player::setScoreBoardPanel(int panel)
{ {
@@ -734,6 +749,18 @@ void Player::decContinueCounter()
} }
} }
// Decrementa el contador de entrar nombre
void Player::decEnterNameCounter()
{
enter_name_ticks_ = SDL_GetTicks();
--enter_name_counter_;
if (enter_name_counter_ < 0)
{
enter_name_counter_ = param.game.enter_name_seconds;
setStatusPlaying(PlayerStatus::CONTINUE);
}
}
// Establece el nombre del jugador // Establece el nombre del jugador
void Player::setName(const std::string &name) void Player::setName(const std::string &name)
{ {

View File

@@ -5,7 +5,8 @@
#include <memory> // for unique_ptr, shared_ptr #include <memory> // for unique_ptr, shared_ptr
#include <string> // for string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for SpriteAnimated
#include "smart_sprite.h" // for SpriteAnimated
#include "enter_name.h" // for EnterName #include "enter_name.h" // for EnterName
#include "utils.h" // for Circle #include "utils.h" // for Circle
class Texture; class Texture;
@@ -48,7 +49,7 @@ private:
SDL_Rect *play_area_; // Rectangulo con la zona de juego 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. Player1 = 1, Player2 = 2
float pos_x_; // Posicion en el eje X float pos_x_; // Posicion en el eje X
int pos_y_; // Posicion en el eje Y int pos_y_; // Posicion en el eje Y
float default_pos_x_; // Posición inicial para el jugador float default_pos_x_; // Posición inicial para el jugador
@@ -77,9 +78,11 @@ private:
Uint32 continue_ticks_; // 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 scoreboard_panel_; // 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 record_name_; // Nombre del jugador para l atabla de mejores puntuaciones std::string record_name_; // Nombre del jugador para la tabla de mejores puntuaciones
int controller_index_; // 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 bool demo_; // Para que el jugador sepa si está en el modo demostración
int enter_name_counter_; // Contador para poner nombre
Uint32 enter_name_ticks_; // Variable para poder cambiar el contador de poner nombre en función del tiempo
// 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();
@@ -90,6 +93,12 @@ private:
// Actualiza el contador de continue // Actualiza el contador de continue
void updateContinueCounter(); void updateContinueCounter();
// Actualiza el contador de entrar nombre
void updateEnterNameCounter();
// Decrementa el contador de entrar nombre
void decEnterNameCounter();
// Indica si el jugador se puede dibujar // Indica si el jugador se puede dibujar
bool isRenderable() const; bool isRenderable() const;
@@ -104,7 +113,7 @@ private:
public: public:
// Constructor // Constructor
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); Player(int id, float x, int y, bool demo, SDL_Rect *play_area, std::vector<std::shared_ptr<Texture>> texture, const std::vector<std::vector<std::string>> &animations);
// Destructor // Destructor
~Player() = default; ~Player() = default;
@@ -236,7 +245,7 @@ public:
void setPowerUpCounter(int value); void setPowerUpCounter(int value);
// Actualiza el valor de la variable // Actualiza el valor de la variable
void updatePowerUpCounter(); void updatePowerUp();
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool hasExtraHit() const; bool hasExtraHit() const;

256
source/resource.cpp Normal file
View File

@@ -0,0 +1,256 @@
#include <iostream>
#include "resource.h"
#include "asset.h"
#include "screen.h"
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Resource *Resource::resource_ = nullptr;
// [SINGLETON] Crearemos el objeto screen con esta función estática
void Resource::init()
{
Resource::resource_ = new Resource();
}
// [SINGLETON] Destruiremos el objeto screen con esta función estática
void Resource::destroy()
{
delete Resource::resource_;
}
// [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él
Resource *Resource::get()
{
return Resource::resource_;
}
// Constructor
Resource::Resource()
{
std::cout << "** LOADING RESOURCES" << std::endl;
loadSounds();
loadMusics();
loadTextures();
loadTextFiles();
loadAnimations();
loadDemoData();
addPalettes();
std::cout << "\n** RESOURCES LOADED" << std::endl;
}
// Destructor
Resource::~Resource()
{
sounds_.clear();
musics_.clear();
textures_.clear();
text_files_.clear();
animations_.clear();
}
// Obtiene el sonido a partir de un nombre
JA_Sound_t *Resource::getSound(const std::string &name)
{
for (const auto &s : sounds_)
{
if (s.name == name)
{
return s.sound;
}
}
std::cerr << "Error: Sonido no encontrado " << name << std::endl;
throw std::runtime_error("Sonido no encontrado: " + name);
}
// Obtiene la música a partir de un nombre
JA_Music_t *Resource::getMusic(const std::string &name)
{
for (const auto &m : musics_)
{
if (m.name == name)
{
return m.music;
}
}
std::cerr << "Error: Música no encontrada " << name << std::endl;
throw std::runtime_error("Música no encontrada: " + name);
}
// Obtiene la textura a partir de un nombre
std::shared_ptr<Texture> Resource::getTexture(const std::string &name)
{
for (const auto &t : textures_)
{
if (t.name == name)
{
return t.texture;
}
}
std::cerr << "Error: Imagen no encontrada " << name << std::endl;
throw std::runtime_error("Imagen no encontrada: " + name);
}
// Obtiene el fichero de texto a partir de un nombre
std::shared_ptr<TextFile> Resource::getTextFile(const std::string &name)
{
for (const auto &t : text_files_)
{
if (t.name == name)
{
return t.text_file;
}
}
std::cerr << "Error: TextFile no encontrado " << name << std::endl;
throw std::runtime_error("TextFile no encontrado: " + name);
}
// Obtiene la animación a partir de un nombre
Animations &Resource::getAnimation(const std::string &name)
{
for (auto &a : animations_)
{
if (a.name == name)
{
return a.animation;
}
}
std::cerr << "Error: Animación no encontrada " << name << std::endl;
throw std::runtime_error("Animación no encontrada: " + name);
}
// Obtiene el fichero con los datos para el modo demostración a partir de un çindice
DemoData &Resource::getDemoData(int index)
{
return demos_.at(index);
}
// Carga los sonidos
void Resource::loadSounds()
{
std::cout << "\n>> SOUND FILES" << std::endl;
// Obtiene la lista con las rutas a los ficheros de sonidos
auto list = Asset::get()->getListByType(AssetType::SOUND);
sounds_.clear();
for (const auto &l : list)
{
// Encuentra el último índice de '/'
auto last_index = l.find_last_of('/') + 1;
// Obtiene la subcadena desde el último '/'
auto name = l.substr(last_index);
sounds_.emplace_back(ResourceSound(name, JA_LoadSound(l.c_str())));
printWithDots("Sound : ", name, "[ LOADED ]");
}
}
// Carga las musicas
void Resource::loadMusics()
{
std::cout << "\n>> MUSIC FILES" << std::endl;
// Obtiene la lista con las rutas a los ficheros musicales
auto list = Asset::get()->getListByType(AssetType::MUSIC);
musics_.clear();
for (const auto &l : list)
{
// Encuentra el último índice de '/'
auto last_index = l.find_last_of('/') + 1;
// Obtiene la subcadena desde el último '/'
auto name = l.substr(last_index);
musics_.emplace_back(ResourceMusic(name, JA_LoadMusic(l.c_str())));
printWithDots("Music : ", name, "[ LOADED ]");
}
}
// Carga las texturas
void Resource::loadTextures()
{
std::cout << "\n>> TEXTURES" << std::endl;
// Obtiene la lista con las rutas a los ficheros png
auto list = Asset::get()->getListByType(AssetType::BITMAP);
textures_.clear();
for (const auto &l : list)
{
// Encuentra el último índice de '/'
auto last_index = l.find_last_of('/') + 1;
// Obtiene la subcadena desde el último '/'
auto name = l.substr(last_index);
textures_.emplace_back(ResourceTexture(name, std::make_shared<Texture>(Screen::get()->getRenderer(), l)));
}
}
// Carga los ficheros de texto
void Resource::loadTextFiles()
{
std::cout << "\n>> TEXT FILES" << std::endl;
// Obtiene la lista con las rutas a los ficheros png
auto list = Asset::get()->getListByType(AssetType::FONT);
text_files_.clear();
for (const auto &l : list)
{
// Encuentra el último índice de '/'
auto last_index = l.find_last_of('/') + 1;
// Obtiene la subcadena desde el último '/'
auto name = l.substr(last_index);
text_files_.emplace_back(ResourceTextFile(name, loadTextFile(l)));
}
}
// Carga las animaciones
void Resource::loadAnimations()
{
std::cout << "\n>> ANIMATIONS" << std::endl;
// Obtiene la lista con las rutas a los ficheros ani
auto list = Asset::get()->getListByType(AssetType::ANIMATION);
animations_.clear();
for (const auto &l : list)
{
// Encuentra el último índice de '/'
auto last_index = l.find_last_of('/') + 1;
// Obtiene la subcadena desde el último '/'
auto name = l.substr(last_index);
animations_.emplace_back(ResourceAnimation(name, loadAnimationsFromFile(l)));
}
}
// Carga los datos para el modo demostración
void Resource::loadDemoData()
{
std::cout << "\n>> DEMO_FILES" << std::endl;
demos_.emplace_back(loadDemoDataFromFile(Asset::get()->get("demo1.bin")));
demos_.emplace_back(loadDemoDataFromFile(Asset::get()->get("demo2.bin")));
}
// Añade paletas a las texturas
void Resource::addPalettes()
{
// Jugador 1
std::cout << "\n>> PALETTES" << std::endl;
getTexture("player1.gif")->addPaletteFromFile(Asset::get()->get("player1_one_coffee_palette.pal"));
getTexture("player1.gif")->addPaletteFromFile(Asset::get()->get("player1_two_coffee_palette.pal"));
getTexture("player1.gif")->addPaletteFromFile(Asset::get()->get("player1_all_white_palette.pal"));
// Jugador 2
getTexture("player2.gif")->addPaletteFromFile(Asset::get()->get("player2_one_coffee_palette.pal"));
getTexture("player2.gif")->addPaletteFromFile(Asset::get()->get("player2_two_coffee_palette.pal"));
getTexture("player2.gif")->addPaletteFromFile(Asset::get()->get("player2_all_white_palette.pal"));
// Fuentes
getTexture("smb2.gif")->addPaletteFromFile(Asset::get()->get("smb2_palette1.pal"));
}

137
source/resource.h Normal file
View File

@@ -0,0 +1,137 @@
#pragma once
#include <SDL2/SDL.h>
#include <vector>
#include <memory>
#include <string>
#include "jail_audio.h"
#include "texture.h"
#include "text.h"
#include "utils.h"
#include "animated_sprite.h"
// Estructura para almacenar ficheros de sonido y su nombre
struct ResourceSound
{
std::string name; // Nombre del sonido
JA_Sound_t *sound; // Objeto con el sonido
// Constructor
ResourceSound(const std::string &name, JA_Sound_t *sound)
: name(name), sound(sound) {}
};
// Estructura para almacenar ficheros musicales y su nombre
struct ResourceMusic
{
std::string name; // Nombre de la musica
JA_Music_t *music; // Objeto con la música
// Constructor
ResourceMusic(const std::string &name, JA_Music_t *music)
: name(name), music(music) {}
};
// Estructura para almacenar objetos Texture y su nombre
struct ResourceTexture
{
std::string name; // Nombre de la textura
std::shared_ptr<Texture> texture; // Objeto con la textura
// Constructor
ResourceTexture(const std::string &name, std::shared_ptr<Texture> texture)
: name(name), texture(texture) {}
};
// Estructura para almacenar ficheros TextFile y su nombre
struct ResourceTextFile
{
std::string name; // Nombre del fichero
std::shared_ptr<TextFile> text_file; // Objeto con los descriptores de la fuente de texto
// Constructor
ResourceTextFile(const std::string &name, std::shared_ptr<TextFile> text_file)
: name(name), text_file(text_file) {}
};
// Estructura para almacenar ficheros animaciones y su nombre
struct ResourceAnimation
{
std::string name; // Nombre del fichero
Animations animation; // Objeto con las animaciones
// Constructor
ResourceAnimation(const std::string &name, Animations animation)
: name(name), animation(animation) {}
};
class Resource
{
private:
// [SINGLETON] Objeto resource privado para Don Melitón
static Resource *resource_;
std::vector<ResourceSound> sounds_; // Vector con los sonidos
std::vector<ResourceMusic> musics_; // Vector con las musicas
std::vector<ResourceTexture> textures_; // Vector con las musicas
std::vector<ResourceTextFile> text_files_; // Vector con los ficheros de texto
std::vector<ResourceAnimation> animations_; // Vector con las animaciones
std::vector<DemoData> demos_; // Vector con los ficheros de datos para el modo demostración
// Carga los sonidos
void loadSounds();
// Carga las musicas
void loadMusics();
// Carga las texturas
void loadTextures();
// Carga los ficheros de texto
void loadTextFiles();
// Carga las animaciones
void loadAnimations();
// Carga los datos para el modo demostración
void loadDemoData();
// Añade paletas a las texturas
void addPalettes();
// [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos resource desde fuera
// Constructor
Resource();
// Destructor
~Resource();
public:
// [SINGLETON] Crearemos el objeto resource con esta función estática
static void init();
// [SINGLETON] Destruiremos el objeto resource con esta función estática
static void destroy();
// [SINGLETON] Con este método obtenemos el objeto resource y podemos trabajar con él
static Resource *get();
// Obtiene el sonido a partir de un nombre
JA_Sound_t *getSound(const std::string &name);
// Obtiene la música a partir de un nombre
JA_Music_t *getMusic(const std::string &name);
// Obtiene la textura a partir de un nombre
std::shared_ptr<Texture> getTexture(const std::string &name);
// Obtiene el fichero de texto a partir de un nombre
std::shared_ptr<TextFile> getTextFile(const std::string &name);
// Obtiene la animación a partir de un nombre
Animations &getAnimation(const std::string &name);
// Obtiene el fichero con los datos para el modo demostración a partir de un çindice
DemoData &getDemoData(int index);
};

View File

@@ -7,6 +7,8 @@
#include <sstream> #include <sstream>
#include "asset.h" // for Asset #include "asset.h" // for Asset
#include "lang.h" // for getText #include "lang.h" // for getText
#include "resource.h" // for Resource
#include "screen.h"
#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
@@ -15,9 +17,9 @@
Scoreboard *Scoreboard::scoreboard_ = nullptr; Scoreboard *Scoreboard::scoreboard_ = nullptr;
// [SINGLETON] Crearemos el objeto score_board con esta función estática // [SINGLETON] Crearemos el objeto score_board con esta función estática
void Scoreboard::init(SDL_Renderer *renderer) void Scoreboard::init()
{ {
Scoreboard::scoreboard_ = new Scoreboard(renderer); Scoreboard::scoreboard_ = new Scoreboard();
} }
// [SINGLETON] Destruiremos el objeto score_board con esta función estática // [SINGLETON] Destruiremos el objeto score_board con esta función estática
@@ -33,12 +35,12 @@ Scoreboard *Scoreboard::get()
} }
// Constructor // Constructor
Scoreboard::Scoreboard(SDL_Renderer *renderer) Scoreboard::Scoreboard()
: renderer_(renderer), : renderer_(Screen::get()->getRenderer()),
game_power_meter_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_power_meter.png"))), game_power_meter_texture_(Resource::get()->getTexture("game_power_meter.png")),
power_meter_sprite_(std::make_unique<Sprite>(game_power_meter_texture_)), 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)), text_scoreboard_(std::make_unique<Text>(Resource::get()->getTexture("8bithud.png"), Resource::get()->getTextFile("8bithud.txt"))),
stage_(1), stage_(1),
hi_score_(0), hi_score_(0),
@@ -66,7 +68,7 @@ Scoreboard::Scoreboard(SDL_Renderer *renderer)
// 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}); power_meter_sprite_->setPosition({slot4_2_.x - 20, slot4_2_.y, 40, 7});
// Crea la textura de fondo // Crea la textura de fondo
background_ = nullptr; background_ = nullptr;
@@ -106,7 +108,7 @@ std::string Scoreboard::updateScoreText(int 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_++;
@@ -418,8 +420,8 @@ void Scoreboard::recalculateAnchors()
// Recoloca los sprites // Recoloca los sprites
if (power_meter_sprite_) if (power_meter_sprite_)
{ {
power_meter_sprite_->setPosX(slot4_2_.x - 20); power_meter_sprite_->setX(slot4_2_.x - 20);
power_meter_sprite_->setPosY(slot4_2_.y); power_meter_sprite_->setY(slot4_2_.y);
} }
} }

View File

@@ -16,7 +16,6 @@ constexpr int SCOREBOARD_LEFT_PANEL = 0;
constexpr int SCOREBOARD_CENTER_PANEL = 1; constexpr int SCOREBOARD_CENTER_PANEL = 1;
constexpr int SCOREBOARD_RIGHT_PANEL = 2; constexpr int SCOREBOARD_RIGHT_PANEL = 2;
constexpr int SCOREBOARD_MAX_PANELS = 3; constexpr int SCOREBOARD_MAX_PANELS = 3;
constexpr int SCOREBOARD_TICK_SPEED = 100;
// Enums // Enums
enum class ScoreboardMode : int enum class ScoreboardMode : int
@@ -42,6 +41,9 @@ struct Panel
class Scoreboard class Scoreboard
{ {
private: private:
// Constantes
static constexpr int SCOREBOARD_TICK_SPEED_ = 100;
// [SINGLETON] Objeto scoreboard privado para Don Melitón // [SINGLETON] Objeto scoreboard privado para Don Melitón
static Scoreboard *scoreboard_; static Scoreboard *scoreboard_;
@@ -103,14 +105,14 @@ private:
// [SINGLETON] Ahora el constructor y el destructor son privados // [SINGLETON] Ahora el constructor y el destructor son privados
// Constructor // Constructor
explicit Scoreboard(SDL_Renderer *renderer); Scoreboard();
// Destructor // Destructor
~Scoreboard(); ~Scoreboard();
public: public:
// [SINGLETON] Crearemos el objeto scoreboard con esta función estática // [SINGLETON] Crearemos el objeto scoreboard con esta función estática
static void init(SDL_Renderer *renderer); static void init();
// [SINGLETON] Destruiremos el objeto scoreboard con esta función estática // [SINGLETON] Destruiremos el objeto scoreboard con esta función estática
static void destroy(); static void destroy();

View File

@@ -12,7 +12,7 @@
#include "dbgtxt.h" // for dbg_print #include "dbgtxt.h" // for dbg_print
#include "global_inputs.h" // for servicePressedCounter #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 "notifier.h" // for Notify
#include "on_screen_help.h" // for OnScreenHelp #include "on_screen_help.h" // for OnScreenHelp
#include "options.h" // for options #include "options.h" // for options
#include "param.h" // for param #include "param.h" // for param
@@ -47,7 +47,6 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer)
: window_(window), : window_(window),
renderer_(renderer), renderer_(renderer),
notify_(std::make_unique<Notify>(renderer_, std::string(), Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), Asset::get()->get("notify.wav"))),
game_canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), game_canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
shader_canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)), shader_canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
@@ -127,7 +126,7 @@ void Screen::blit()
displayInfo(); displayInfo();
// Muestra las notificaciones // Muestra las notificaciones
notify_->render(); Notifier::get()->render();
#ifdef NO_SHADERS #ifdef NO_SHADERS
// Vuelve a dejar el renderizador en modo normal // Vuelve a dejar el renderizador en modo normal
@@ -281,7 +280,7 @@ void Screen::setBlendMode(SDL_BlendMode blendMode)
void Screen::update() void Screen::update()
{ {
updateShakeEffect(); updateShakeEffect();
notify_->update(); Notifier::get()->update();
updateFPS(); updateFPS();
OnScreenHelp::get()->update(); OnScreenHelp::get()->update();
} }
@@ -295,7 +294,7 @@ void Screen::checkInput()
{ {
switchVideoMode(); switchVideoMode();
const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen"; const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen";
showNotification(mode + " mode"); Notifier::get()->showText(mode + " mode");
return; return;
} }
@@ -304,7 +303,7 @@ void Screen::checkInput()
{ {
decWindowSize(); decWindowSize();
const std::string size = std::to_string(options.video.window.size); const std::string size = std::to_string(options.video.window.size);
showNotification("Window size x" + size); Notifier::get()->showText("Window size x" + size);
return; return;
} }
@@ -313,7 +312,7 @@ void Screen::checkInput()
{ {
incWindowSize(); incWindowSize();
const std::string size = std::to_string(options.video.window.size); const std::string size = std::to_string(options.video.window.size);
showNotification("Window size x" + size); Notifier::get()->showText("Window size x" + size);
return; return;
} }
#endif #endif
@@ -443,7 +442,7 @@ void Screen::switchShaders()
options.video.shaders = !options.video.shaders; options.video.shaders = !options.video.shaders;
setVideoMode(options.video.mode); setVideoMode(options.video.mode);
const std::string value = options.video.shaders ? "on" : "off"; const std::string value = options.video.shaders ? "on" : "off";
showNotification("Shaders " + value); Notifier::get()->showText("Shaders " + value);
} }
// Atenua la pantalla // Atenua la pantalla
@@ -452,12 +451,6 @@ void Screen::attenuate(bool value)
attenuate_effect_ = value; attenuate_effect_ = value;
} }
// Muestra una notificación de texto por pantalla;
void Screen::showNotification(const std::string &text1, const std::string &text2, int icon)
{
notify_->showText(text1, text2, icon);
}
// Obtiene el puntero al renderizador // Obtiene el puntero al renderizador
SDL_Renderer *Screen::getRenderer() SDL_Renderer *Screen::getRenderer()
{ {
@@ -491,12 +484,6 @@ void Screen::displayInfo()
} }
} }
// Indica si hay alguna notificación activa en pantalla
bool Screen::notificationsAreActive() const
{
return notify_->active();
}
// Calcula la nueva posición de la ventana a partir de la antigua al cambiarla de tamaño // Calcula la nueva posición de la ventana a partir de la antigua al cambiarla de tamaño
SDL_Point Screen::getNewPosition() SDL_Point Screen::getNewPosition()
{ {

View File

@@ -8,7 +8,6 @@
#include <string> // for basic_string, string #include <string> // for basic_string, string
#include "utils.h" // for Color #include "utils.h" // for Color
#include <memory> #include <memory>
class Notify;
enum class ScreenFilter : int enum class ScreenFilter : int
{ {
@@ -31,7 +30,6 @@ private:
// 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
std::unique_ptr<Notify> notify_; // Pinta notificaciones en pantalla
SDL_Texture *game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador SDL_Texture *game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador
SDL_Texture *shader_canvas_; // Textura para pasarle al shader desde gameCanvas SDL_Texture *shader_canvas_; // Textura para pasarle al shader desde gameCanvas
@@ -154,12 +152,6 @@ public:
// Atenua la pantalla // Atenua la pantalla
void attenuate(bool value); void attenuate(bool value);
// Muestra una notificación de texto por pantalla;
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
bool notificationsAreActive() const;
// Obtiene el puntero al renderizador // Obtiene el puntero al renderizador
SDL_Renderer *getRenderer(); SDL_Renderer *getRenderer();
}; };

View File

@@ -23,9 +23,10 @@ namespace section
GAME_PLAY_2P = 1, GAME_PLAY_2P = 1,
TITLE_1 = 2, TITLE_1 = 2,
TITLE_2 = 3, TITLE_2 = 3,
QUIT_NORMAL = 4, QUIT_WITH_KEYBOARD = 4,
QUIT_SHUTDOWN = 5, QUIT_WITH_CONTROLLER = 5,
NONE = 6, QUIT_FROM_EVENT = 6,
NONE = 7,
}; };
extern Name name; extern Name name;

View File

@@ -1,5 +1,4 @@
#include "smart_sprite.h" #include "smart_sprite.h"
#include "moving_sprite.h" // for MovingSprite
class Texture; class Texture;
// Constructor // Constructor
@@ -14,8 +13,7 @@ void SmartSprite::init()
{ {
finished_counter_ = 0; finished_counter_ = 0;
on_destination_ = false; on_destination_ = false;
dest_x_ = 0; dest_x_ = dest_y_ = 0;
dest_y_ = 0;
finished_ = false; finished_ = false;
enabled_ = false; enabled_ = false;
} }

View File

@@ -1,10 +1,10 @@
#pragma once #pragma once
#include <memory> // for shared_ptr #include <memory> // for shared_ptr
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for SpriteAnimated
class Texture; class Texture;
// Clase SmartSprite // Clase SpriteSmart
class SmartSprite : public AnimatedSprite class SmartSprite : public AnimatedSprite
{ {
private: private:
@@ -16,12 +16,12 @@ private:
bool finished_; // Indica si ya ha terminado bool finished_; // Indica si ya ha terminado
bool enabled_; // Indica si el objeto está habilitado bool enabled_; // Indica si el objeto está habilitado
// Comprueba el movimiento
void checkMove();
// Comprueba si ha terminado // Comprueba si ha terminado
void checkFinished(); void checkFinished();
// Comprueba el movimiento
void checkMove();
public: public:
// Constructor // Constructor
explicit SmartSprite(std::shared_ptr<Texture> texture); explicit SmartSprite(std::shared_ptr<Texture> texture);

View File

@@ -1,12 +1,12 @@
#include "sprite.h" #include "sprite.h"
// Constructor // Constructor
Sprite::Sprite(int x, int y, int w, int h, std::shared_ptr<Texture> texture) Sprite::Sprite(std::shared_ptr<Texture> texture, int x, int y, int w, int h)
: texture_(texture), : texture_(texture),
pos_((SDL_Rect){x, y, w, h}), pos_((SDL_Rect){x, y, w, h}),
sprite_clip_((SDL_Rect){0, 0, pos_.w, pos_.h}) {} sprite_clip_((SDL_Rect){0, 0, pos_.w, pos_.h}) {}
Sprite::Sprite(SDL_Rect rect, std::shared_ptr<Texture> texture) Sprite::Sprite(std::shared_ptr<Texture> texture, SDL_Rect rect)
: texture_(texture), : texture_(texture),
pos_(rect), pos_(rect),
sprite_clip_((SDL_Rect){0, 0, pos_.w, pos_.h}) {} sprite_clip_((SDL_Rect){0, 0, pos_.w, pos_.h}) {}
@@ -23,13 +23,13 @@ void Sprite::render()
} }
// Obten el valor de la variable // Obten el valor de la variable
int Sprite::getIntPosX() const int Sprite::getX() const
{ {
return pos_.x; return pos_.x;
} }
// Obten el valor de la variable // Obten el valor de la variable
int Sprite::getIntPosY() const int Sprite::getY() const
{ {
return pos_.y; return pos_.y;
} }
@@ -47,33 +47,33 @@ int Sprite::getHeight() const
} }
// Establece la posición del objeto // Establece la posición del objeto
void Sprite::setPos(int x, int y) void Sprite::setPosition(int x, int y)
{ {
pos_.x = x; pos_.x = x;
pos_.y = y; pos_.y = y;
} }
// Establece la posición del objeto // Establece la posición del objeto
void Sprite::setPos(SDL_Point p) void Sprite::setPosition(SDL_Point p)
{ {
pos_.x = p.x; pos_.x = p.x;
pos_.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::setPosition(SDL_Rect r)
{ {
pos_ = r; pos_ = r;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setPosX(int x) void Sprite::setX(int x)
{ {
pos_.x = x; pos_.x = x;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setPosY(int y) void Sprite::setY(int y)
{ {
pos_.y = y; pos_.y = y;
} }
@@ -121,19 +121,26 @@ void Sprite::setTexture(std::shared_ptr<Texture> texture)
} }
// Devuelve el rectangulo donde está el sprite // Devuelve el rectangulo donde está el sprite
SDL_Rect Sprite::getPos() const SDL_Rect Sprite::getPosition() const
{ {
return pos_; return pos_;
} }
// Incrementa el valor de la variable // Incrementa el valor de la variable
void Sprite::incPosX(int value) void Sprite::incX(int value)
{ {
pos_.x += value; pos_.x += value;
} }
// Incrementa el valor de la variable // Incrementa el valor de la variable
void Sprite::incPosY(int value) void Sprite::incY(int value)
{ {
pos_.y += value; pos_.y += value;
} }
// Reinicia las variables a cero
void Sprite::clear()
{
pos_ = {0, 0, 0, 0};
sprite_clip_ = {0, 0, 0, 0};
}

View File

@@ -15,39 +15,42 @@ protected:
public: public:
// Constructor // Constructor
explicit Sprite(int x = 0, int y = 0, int w = 0, int h = 0, std::shared_ptr<Texture> texture = nullptr); Sprite(std::shared_ptr<Texture>, int x, int y, int w, int h);
explicit Sprite(SDL_Rect rect, std::shared_ptr<Texture> texture = nullptr); Sprite(std::shared_ptr<Texture>, SDL_Rect rect);
explicit Sprite(std::shared_ptr<Texture> texture = nullptr); explicit Sprite(std::shared_ptr<Texture>);
// Destructor // Destructor
virtual ~Sprite() = default; ~Sprite() = default;
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
virtual void render(); virtual void render();
// Reinicia las variables a cero
virtual void clear();
// Obten el valor de la variable // Obten el valor de la variable
int getIntPosX() const; int getX() const;
int getIntPosY() const; int getY() const;
int getWidth() const; int getWidth() const;
int getHeight() const; int getHeight() const;
// Devuelve el rectangulo donde está el sprite // Devuelve el rectangulo donde está el sprite
virtual SDL_Rect getPos() const; SDL_Rect getPosition() const;
// Establece el valor de la variable // Establece el valor de la variable
void setPosX(int x); void setX(int x);
void setPosY(int y); void setY(int y);
void setWidth(int w); void setWidth(int w);
void setHeight(int h); void setHeight(int h);
// Establece la posición del objeto // Establece la posición del objeto
void setPos(int x, int y); void setPosition(int x, int y);
void setPos(SDL_Point p); void setPosition(SDL_Point p);
virtual void setPos(SDL_Rect r); void setPosition(SDL_Rect r);
// Incrementa el valor de la variable // Incrementa el valor de la variable
void incPosX(int value); void incX(int value);
void incPosY(int value); void incY(int value);
// Obten el valor de la variable // Obten el valor de la variable
SDL_Rect getSpriteClip() const; SDL_Rect getSpriteClip() const;

View File

@@ -2,29 +2,28 @@
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <fstream> // for basic_ostream, basic_ifstream, basic_istream #include <fstream> // for basic_ostream, basic_ifstream, basic_istream
#include <iostream> // for cout #include <iostream> // for cout
#include "resource.h" // for Resource
#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 #include "utils.h" // for Color
// Llena una estructuta TextFile desde un fichero // Llena una estructuta TextFile desde un fichero
TextFile LoadTextFile(std::string file_path) std::shared_ptr<TextFile> loadTextFile(const std::string &file_path)
{ {
TextFile tf; auto tf = std::make_shared<TextFile>();
// 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)
{ {
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_width = 0;
tf.box_height = 0; tf->box_height = 0;
} }
// Abre el fichero para leer los valores // Abre el fichero para leer los valores
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1).c_str(); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1).c_str();
#endif
std::ifstream file(file_path); std::ifstream file(file_path);
if (file.is_open() && file.good()) if (file.is_open() && file.good())
@@ -34,11 +33,11 @@ TextFile LoadTextFile(std::string file_path)
// Lee los dos primeros valores del fichero // Lee los dos primeros valores del fichero
std::getline(file, buffer); std::getline(file, buffer);
std::getline(file, buffer); std::getline(file, buffer);
tf.box_width = std::stoi(buffer); tf->box_width = std::stoi(buffer);
std::getline(file, buffer); std::getline(file, buffer);
std::getline(file, buffer); std::getline(file, buffer);
tf.box_height = std::stoi(buffer); tf->box_height = std::stoi(buffer);
// lee el resto de datos del fichero // lee el resto de datos del fichero
auto index = 32; auto index = 32;
@@ -48,7 +47,7 @@ TextFile LoadTextFile(std::string file_path)
// Almacena solo las lineas impares // Almacena solo las lineas impares
if (line_read % 2 == 1) if (line_read % 2 == 1)
{ {
tf.offset[index++].w = std::stoi(buffer); tf->offset[index++].w = std::stoi(buffer);
} }
// Limpia el buffer // Limpia el buffer
@@ -56,80 +55,53 @@ TextFile LoadTextFile(std::string file_path)
line_read++; line_read++;
}; };
// Cierra el fichero // Cierra el fichero
#ifdef VERBOSE printWithDots("Text File : ", file_name, "[ LOADED ]");
std::cout << "Text loaded: " << file_name << std::endl;
#endif
file.close(); file.close();
} }
// El fichero no se puede abrir // El fichero no se puede abrir
else else
{ {
#ifdef VERBOSE std::cerr << "Error: Fichero no encontrado " << file_path << std::endl;
std::cout << "Warning: Unable to open " << file_name << " file" << std::endl; throw std::runtime_error("Fichero no encontrado: " + file_path);
#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.box_width; tf->offset[i].x = ((i - 32) % 15) * tf->box_width;
tf.offset[i].y = ((i - 32) / 15) * tf.box_height; tf->offset[i].y = ((i - 32) / 15) * tf->box_height;
} }
return tf; return tf;
} }
// Constructor // Constructor
Text::Text(const std::string &bitmap_file, const std::string &text_file, SDL_Renderer *renderer) Text::Text(std::shared_ptr<Texture> texture, const std::string &text_file)
{ {
// Carga los offsets desde el fichero // Carga los offsets desde el fichero
auto tf = LoadTextFile(text_file); auto tf = loadTextFile(text_file);
// Inicializa variables desde la estructura // Inicializa variables desde la estructura
box_height_ = tf.box_height; box_height_ = tf->box_height;
box_width_ = tf.box_width; 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_ = std::make_shared<Texture>(renderer, bitmap_file); sprite_ = std::make_unique<Sprite>(texture, (SDL_Rect){0, 0, box_width_, box_height_});
sprite_ = std::make_unique<Sprite>((SDL_Rect){0, 0, box_width_, box_height_}, texture_);
// Inicializa variables // Inicializa variables
fixed_width_ = false; fixed_width_ = false;
} }
// Constructor // Constructor
Text::Text(const std::string &text_file, std::shared_ptr<Texture> texture) Text::Text(std::shared_ptr<Texture> texture, std::shared_ptr<TextFile> text_file)
{
// Carga los offsets desde el fichero
auto tf = LoadTextFile(text_file);
// Inicializa variables desde la estructura
box_height_ = tf.box_height;
box_width_ = tf.box_width;
for (int i = 0; i < 128; ++i)
{
offset_[i].x = tf.offset[i].x;
offset_[i].y = tf.offset[i].y;
offset_[i].w = tf.offset[i].w;
}
// Crea los objetos
sprite_ = std::make_unique<Sprite>((SDL_Rect){0, 0, box_width_, box_height_}, texture);
// Inicializa variables
fixed_width_ = false;
}
// Constructor
Text::Text(TextFile *text_file, std::shared_ptr<Texture> texture)
{ {
// Inicializa variables desde la estructura // Inicializa variables desde la estructura
box_height_ = text_file->box_height; box_height_ = text_file->box_height;
@@ -142,7 +114,7 @@ Text::Text(TextFile *text_file, std::shared_ptr<Texture> texture)
} }
// Crea los objetos // Crea los objetos
sprite_ = std::make_unique<Sprite>((SDL_Rect){0, 0, box_width_, box_height_}, texture); sprite_ = std::make_unique<Sprite>(texture, (SDL_Rect){0, 0, box_width_, box_height_});
// Inicializa variables // Inicializa variables
fixed_width_ = false; fixed_width_ = false;
@@ -158,14 +130,14 @@ void Text::write(int x, int y, const std::string &text, int kerning, int lenght)
lenght = text.length(); lenght = text.length();
} }
sprite_->setPosY(y); sprite_->setY(y);
const auto width = sprite_->getWidth(); const auto width = sprite_->getWidth();
const auto height = sprite_->getHeight(); const auto height = sprite_->getHeight();
for (int i = 0; i < lenght; ++i) for (int i = 0; i < lenght; ++i)
{ {
const auto index = static_cast<int>(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_->setX(x + shift);
sprite_->render(); sprite_->render();
shift += fixed_width_ ? box_width_ : (offset_[int(text[i])].w + kerning); shift += fixed_width_ ? box_width_ : (offset_[int(text[i])].w + kerning);
} }
@@ -268,15 +240,3 @@ void Text::setFixedWidth(bool value)
{ {
fixed_width_ = value; fixed_width_ = value;
} }
// Carga una paleta de colores para el texto
void Text::addPalette(const std::string &path)
{
texture_->addPalette(path);
}
// Establece una paleta de colores para el texto
void Text::setPalette(int index)
{
texture_->setPalette(index);
}

View File

@@ -26,7 +26,7 @@ struct TextFile
}; };
// Llena una estructuta TextFile desde un fichero // Llena una estructuta TextFile desde un fichero
TextFile LoadTextFile(std::string file); std::shared_ptr<TextFile> loadTextFile(const std::string &file_path);
// Clase texto. Pinta texto en pantalla a partir de un bitmap // Clase texto. Pinta texto en pantalla a partir de un bitmap
class Text class Text
@@ -34,7 +34,6 @@ class Text
private: private:
// Objetos y punteros // Objetos y punteros
std::unique_ptr<Sprite> sprite_; // Objeto con los graficos para el texto std::unique_ptr<Sprite> sprite_; // Objeto con los graficos para el texto
std::shared_ptr<Texture> texture_; // Textura con los bitmaps del texto
// Variables // Variables
int box_width_; // Anchura de la caja de cada caracter en el png int box_width_; // Anchura de la caja de cada caracter en el png
@@ -44,9 +43,8 @@ private:
public: public:
// Constructor // Constructor
Text(const std::string &bitmap_file, const std::string &text_file, SDL_Renderer *renderer); Text(std::shared_ptr<Texture> texture, const std::string &text_file);
Text(const std::string &text_file, std::shared_ptr<Texture> texture); Text(std::shared_ptr<Texture> texture, std::shared_ptr<TextFile> text_file);
Text(TextFile *text_file, std::shared_ptr<Texture> texture);
// Destructor // Destructor
~Text() = default; ~Text() = default;
@@ -77,10 +75,4 @@ public:
// Establece si se usa un tamaño fijo de letra // Establece si se usa un tamaño fijo de letra
void setFixedWidth(bool value); void setFixedWidth(bool value);
// Carga una paleta de colores para el texto
void addPalette(const std::string &path);
// Establece una paleta de colores para el texto
void setPalette(int index);
}; };

View File

@@ -1,27 +1,28 @@
#include "texture.h" #include "texture.h"
#include "utils.h"
#include <SDL2/SDL_error.h> // for SDL_GetError #include <SDL2/SDL_error.h> // for SDL_GetError
#include <SDL2/SDL_surface.h> // for SDL_CreateRGBSurfaceWithFormatFrom #include <SDL2/SDL_surface.h> // for SDL_CreateRGBSurfaceWithFormatFrom
#include <fcntl.h> // for SEEK_END, SEEK_SET #include <fcntl.h> // for SEEK_END, SEEK_SET
#include <stdio.h> // for fseek, fclose, fopen, fread, ftell, NULL #include <stdio.h> // for fseek, fclose, fopen, fread, ftell, NULL
#include <stdlib.h> // for malloc, free, exit #include <stdlib.h> // for malloc, free, exit
#include <iostream> // for basic_ostream, operator<<, cout, endl #include <iostream> // for basic_ostream, operator<<, cout, endl
#include <fstream>
#include <sstream>
#include "gif.c" // for LoadGif, LoadPalette #include "gif.c" // for LoadGif, LoadPalette
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h" // for stbi_failure_reason, stbi_image_free #include "stb_image.h" // for stbi_failure_reason, stbi_image_free
// Constructor // Constructor
Texture::Texture(SDL_Renderer *renderer, const std::string &path) Texture::Texture(SDL_Renderer *renderer, const std::string &path)
: renderer_(renderer), path_(path) : texture_(nullptr),
renderer_(renderer),
surface_(nullptr),
width_(0),
height_(0),
path_(path),
current_palette_(0)
{ {
// Inicializa
surface_ = nullptr;
texture_ = nullptr;
width_ = 0;
height_ = 0;
paletteIndex_ = 0;
palettes_.clear();
// Carga el fichero en la textura // Carga el fichero en la textura
if (!path_.empty()) if (!path_.empty())
{ {
@@ -37,9 +38,14 @@ Texture::Texture(SDL_Renderer *renderer, const std::string &path)
// .gif // .gif
else if (extension == "gif") else if (extension == "gif")
{ {
// Crea la surface desde un fichero
surface_ = loadSurface(path_); surface_ = loadSurface(path_);
addPalette(path_);
setPaletteColor(0, 0, 0x00000000); // Añade la propia paleta del fichero a la lista
addPaletteFromFile(path_);
//setPaletteColor(0, 0, 0x00000000);
// Crea la textura, establece el BlendMode y copia la surface a la textura
createBlank(width_, height_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING); createBlank(width_, height_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING);
SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);
flipSurface(); flipSurface();
@@ -50,28 +56,26 @@ Texture::Texture(SDL_Renderer *renderer, const std::string &path)
// Destructor // Destructor
Texture::~Texture() Texture::~Texture()
{ {
unload(); unloadTexture();
unloadSurface();
palettes_.clear();
} }
// Carga una imagen desde un fichero // Carga una imagen desde un fichero
bool Texture::loadFromFile(const std::string &path) bool Texture::loadFromFile(const std::string &file_path)
{ {
int req_format = STBI_rgb_alpha; int req_format = STBI_rgb_alpha;
int width, height, orig_format; int width, height, orig_format;
unsigned char *data = stbi_load(path.c_str(), &width, &height, &orig_format, req_format); unsigned char *data = stbi_load(file_path.c_str(), &width, &height, &orig_format, req_format);
if (!data) if (!data)
{ {
#ifdef VERBOSE std::cerr << "Error: Fichero no encontrado " << file_path << std::endl;
std::cout << "Loading image failed: " << stbi_failure_reason() << std::endl; throw std::runtime_error("Fichero no encontrado: " + file_path);
#endif
exit(1);
} }
else else
{ {
#ifdef VERBOSE const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
const std::string file_name = path.substr(path.find_last_of("\\/") + 1); printWithDots("Image : ", file_name, "[ LOADED ]");
std::cout << "Image loaded: " << file_name << std::endl;
#endif
} }
int depth, pitch; int depth, pitch;
@@ -90,7 +94,7 @@ bool Texture::loadFromFile(const std::string &path)
} }
// Limpia // Limpia
unload(); unloadTexture();
// La textura final // La textura final
SDL_Texture *newTexture = nullptr; SDL_Texture *newTexture = nullptr;
@@ -99,9 +103,7 @@ bool Texture::loadFromFile(const std::string &path)
auto loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom(static_cast<void *>(data), width, height, depth, pitch, pixel_format); auto loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom(static_cast<void *>(data), width, height, depth, pitch, pixel_format);
if (loadedSurface == nullptr) if (loadedSurface == nullptr)
{ {
#ifdef VERBOSE std::cout << "Unable to load image " << file_path << std::endl;
std::cout << "Unable to load image " << path << std::endl;
#endif
} }
else else
{ {
@@ -109,9 +111,7 @@ bool Texture::loadFromFile(const std::string &path)
newTexture = SDL_CreateTextureFromSurface(renderer_, loadedSurface); newTexture = SDL_CreateTextureFromSurface(renderer_, loadedSurface);
if (newTexture == nullptr) if (newTexture == nullptr)
{ {
#ifdef VERBOSE std::cout << "Unable to create texture from " << file_path << "! SDL Error: " << SDL_GetError() << std::endl;
std::cout << "Unable to create texture from " << path << "! SDL Error: " << SDL_GetError() << std::endl;
#endif
} }
else else
{ {
@@ -137,9 +137,7 @@ bool Texture::createBlank(int width, int height, SDL_PixelFormatEnum format, SDL
texture_ = SDL_CreateTexture(renderer_, format, access, width, height); texture_ = SDL_CreateTexture(renderer_, format, access, width, height);
if (!texture_) if (!texture_)
{ {
#ifdef VERBOSE
std::cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << std::endl; std::cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << std::endl;
#endif
} }
else else
{ {
@@ -151,7 +149,7 @@ bool Texture::createBlank(int width, int height, SDL_PixelFormatEnum format, SDL
} }
// Libera la memoria de la textura // Libera la memoria de la textura
void Texture::unload() void Texture::unloadTexture()
{ {
// Libera la textura // Libera la textura
if (texture_) if (texture_)
@@ -161,13 +159,6 @@ void Texture::unload()
width_ = 0; width_ = 0;
height_ = 0; height_ = 0;
} }
// Libera la surface
if (surface_)
{
deleteSurface(surface_);
surface_ = nullptr;
}
} }
// Establece el color para la modulacion // Establece el color para la modulacion
@@ -238,61 +229,56 @@ SDL_Texture *Texture::getSDLTexture()
return texture_; return texture_;
} }
// Crea una nueva surface // Desencadenar la superficie actual
/*Surface Texture::newSurface(int w, int h) void Texture::unloadSurface()
{ {
Surface surf = static_cast<Surface>(malloc(sizeof(surface_s))); surface_.reset(); // Resetea el shared_ptr
surf->w = w; width_ = 0;
surf->h = h; height_ = 0;
surf->data = static_cast<Uint8 *>(malloc(w * h));
return surf;
}*/
// Elimina una surface
void Texture::deleteSurface(Surface surface)
{
if (surface == nullptr)
{
return;
}
if (surface->data != nullptr)
{
free(surface->data);
}
free(surface);
} }
// Crea una surface desde un fichero .gif // Crea una surface desde un fichero .gif
Surface Texture::loadSurface(const std::string &file_name) std::shared_ptr<Surface> Texture::loadSurface(const std::string &file_path)
{ {
FILE *f = fopen(file_name.c_str(), "rb"); // Desencadenar la superficie actual
if (!f) unloadSurface();
// Abrir el archivo usando std::ifstream para manejo automático del recurso
std::ifstream file(file_path, std::ios::binary | std::ios::ate);
if (!file)
{ {
return nullptr; std::cerr << "Error: Fichero no encontrado " << file_path << std::endl;
throw std::runtime_error("Fichero no encontrado: " + file_path);
} }
fseek(f, 0, SEEK_END); // Obtener el tamaño del archivo
long size = ftell(f); std::streamsize size = file.tellg();
fseek(f, 0, SEEK_SET); file.seekg(0, std::ios::beg);
Uint8 *buffer = static_cast<Uint8 *>(malloc(size));
fread(buffer, size, 1, f);
fclose(f);
// Leer el contenido del archivo en un buffer
std::vector<Uint8> buffer(size);
if (!file.read(reinterpret_cast<char *>(buffer.data()), size))
{
std::cerr << "Error al leer el fichero " << file_path << std::endl;
throw std::runtime_error("Error al leer el fichero: " + file_path);
}
// Cerrar el archivo (automáticamente manejado por std::ifstream)
file.close();
// Llamar a la función LoadGif
Uint16 w, h; Uint16 w, h;
Uint8 *pixels = LoadGif(buffer, &w, &h); Uint8 *rawPixels = LoadGif(buffer.data(), &w, &h);
if (pixels == nullptr) if (!rawPixels)
{ {
return nullptr; return nullptr;
} }
Surface surface = static_cast<Surface>(malloc(sizeof(surface_s))); // Crear un std::shared_ptr con std::make_shared para pixels
surface->w = w; auto pixels = std::shared_ptr<Uint8[]>(rawPixels, std::default_delete<Uint8[]>());
surface->h = h; auto surface = std::make_shared<Surface>(w, h, pixels);
surface->data = pixels;
free(buffer);
// Actualizar la anchura y altura
width_ = w; width_ = w;
height_ = h; height_ = h;
@@ -315,7 +301,7 @@ void Texture::flipSurface()
SDL_LockTexture(texture_, nullptr, reinterpret_cast<void **>(&pixels), &pitch); SDL_LockTexture(texture_, nullptr, reinterpret_cast<void **>(&pixels), &pitch);
for (int i = 0; i < width_ * height_; ++i) for (int i = 0; i < width_ * height_; ++i)
{ {
pixels[i] = palettes_[paletteIndex_][surface_->data[i]]; pixels[i] = palettes_[current_palette_][surface_->data[i]];
} }
SDL_UnlockTexture(texture_); SDL_UnlockTexture(texture_);
} }
@@ -327,14 +313,20 @@ void Texture::setPaletteColor(int palette, int index, Uint32 color)
} }
// Carga una paleta desde un fichero // Carga una paleta desde un fichero
std::vector<Uint32> Texture::loadPal(const std::string &file_name) std::vector<Uint32> Texture::loadPaletteFromFile(const std::string &file_path)
{ {
std::vector<Uint32> palette; std::vector<Uint32> palette;
FILE *f = fopen(file_name.c_str(), "rb"); FILE *f = fopen(file_path.c_str(), "rb");
if (!f) if (!f)
{ {
return palette; std::cerr << "Error: Fichero no encontrado " << file_path << std::endl;
throw std::runtime_error("Fichero no encontrado: " + file_path);
}
else
{
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
printWithDots("Image : ", file_name, "[ LOADED ]");
} }
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
@@ -361,9 +353,9 @@ std::vector<Uint32> Texture::loadPal(const std::string &file_name)
} }
// Añade una paleta a la lista // Añade una paleta a la lista
void Texture::addPalette(const std::string &path) void Texture::addPaletteFromFile(const std::string &path)
{ {
palettes_.push_back(loadPal(path)); palettes_.emplace_back(loadPaletteFromFile(path));
setPaletteColor((int)palettes_.size() - 1, 0, 0x00000000); setPaletteColor((int)palettes_.size() - 1, 0, 0x00000000);
} }
@@ -372,7 +364,7 @@ void Texture::setPalette(int palette)
{ {
if (palette < (int)palettes_.size()) if (palette < (int)palettes_.size())
{ {
paletteIndex_ = palette; current_palette_ = palette;
flipSurface(); flipSurface();
} }
} }

View File

@@ -7,15 +7,18 @@
#include <SDL2/SDL_stdinc.h> // for Uint8, Uint32, Uint16 #include <SDL2/SDL_stdinc.h> // for Uint8, Uint32, Uint16
#include <string> // for string, basic_string #include <string> // for string, basic_string
#include <vector> // for vector #include <vector> // for vector
#include <memory>
// Definiciones de tipos // Definiciones de tipos
struct surface_s struct Surface
{ {
Uint8 *data; std::shared_ptr<Uint8[]> data;
Uint16 w, h; Uint16 w, h;
};
typedef struct surface_s *Surface; // Constructor
Surface(Uint16 width, Uint16 height, std::shared_ptr<Uint8[]> pixels)
: data(pixels), w(width), h(height) {}
};
class Texture class Texture
{ {
@@ -23,29 +26,29 @@ private:
// Objetos y punteros // Objetos y punteros
SDL_Texture *texture_; // La textura SDL_Texture *texture_; // La textura
SDL_Renderer *renderer_; // Renderizador donde dibujar la textura SDL_Renderer *renderer_; // Renderizador donde dibujar la textura
Surface surface_; // Surface para usar imagenes en formato gif con paleta std::shared_ptr<Surface> surface_; // Surface para usar imagenes en formato gif con paleta
// Variables // Variables
int width_; // Ancho de la imagen int width_; // Ancho de la imagen
int height_; // Alto de la imagen int height_; // Alto de la imagen
std::string path_; // Ruta de la imagen de la textura std::string path_; // Ruta de la imagen de la textura
std::vector<std::vector<Uint32>> palettes_; // Vector con las diferentes paletas std::vector<std::vector<Uint32>> palettes_; // Vector con las diferentes paletas
int paletteIndex_; // Indice de la paleta en uso int current_palette_; // Indice de la paleta en uso
// Crea una nueva surface
//Surface newSurface(int w, int h);
// Elimina una surface
void deleteSurface(Surface surface);
// Crea una surface desde un fichero .gif // Crea una surface desde un fichero .gif
Surface loadSurface(const std::string &file_name); std::shared_ptr<Surface> loadSurface(const std::string &file_name);
// Vuelca la surface en la textura // Vuelca la surface en la textura
void flipSurface(); void flipSurface();
// Carga una paleta desde un fichero // Carga una paleta desde un fichero
std::vector<Uint32> loadPal(const std::string &file_name); std::vector<Uint32> loadPaletteFromFile(const std::string &file_name);
// Libera la memoria de la textura
void unloadTexture();
// Desencadenar la superficie actual
void unloadSurface();
public: public:
// Constructor // Constructor
@@ -60,9 +63,6 @@ public:
// Crea una textura en blanco // Crea una textura en blanco
bool createBlank(int width, int height, SDL_PixelFormatEnum format = SDL_PIXELFORMAT_RGBA8888, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING); bool createBlank(int width, int height, SDL_PixelFormatEnum format = SDL_PIXELFORMAT_RGBA8888, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING);
// Libera la memoria de la textura
void unload();
// Establece el color para la modulacion // Establece el color para la modulacion
void setColor(Uint8 red, Uint8 green, Uint8 blue); void setColor(Uint8 red, Uint8 green, Uint8 blue);
@@ -91,7 +91,7 @@ public:
SDL_Texture *getSDLTexture(); SDL_Texture *getSDLTexture();
// Añade una paleta a la lista // Añade una paleta a la lista
void addPalette(const std::string &path); void addPaletteFromFile(const std::string &path);
// Establece un color de la paleta // Establece un color de la paleta
void setPaletteColor(int palette, int index, Uint32 color); void setPaletteColor(int palette, int index, Uint32 color);

View File

@@ -1,116 +1,102 @@
#include "tiled_bg.h" #include "tiled_bg.h"
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_stdinc.h> // for SDL_sinf
#include <stdlib.h> // for rand #include <stdlib.h> // for rand
#include <memory> // for unique_ptr, make_shared, make_unique #include <memory> // for unique_ptr, make_shared, make_unique
#include <cmath> // for sinf
#include "resource.h" // for Resource
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "texture.h" // for Texture #include "texture.h" // for Texture
// Constructor // Constructor
Tiledbg::Tiledbg(std::string texture_path, SDL_Rect pos, int mode) TiledBG::TiledBG(SDL_Rect pos, TiledBGMode mode)
: texture_path_(texture_path), pos_(pos), mode_(mode) : renderer_(Screen::get()->getRenderer()),
pos_(pos),
counter_(0),
mode_(mode == TiledBGMode::RANDOM ? static_cast<TiledBGMode>(rand() % 2) : mode)
{ {
// Copia los punteros
renderer_ = Screen::get()->getRenderer();
// Crea la textura para el mosaico de fondo // Crea la textura para el mosaico de fondo
canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, pos_.w * 2, pos_.h * 2); canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, pos_.w * 2, pos_.h * 2);
// Inicializa las variables
init();
}
// Destructor
Tiledbg::~Tiledbg()
{
SDL_DestroyTexture(canvas_);
}
// Inicializa las variables
void Tiledbg::init()
{
counter_ = 0;
if (mode_ == TILED_MODE_RANDOM)
{
mode_ = rand() % 2;
}
tile_width_ = 64;
tile_height_ = 64;
// Rellena la textura con el contenido // Rellena la textura con el contenido
fillTexture(); fillTexture();
// Coloca la ventana que recorre el mosaico de fondo de manera que coincida // Coloca la ventana que recorre el mosaico de fondo de manera que coincida
// con el mosaico que hay pintado en el titulo al iniciar // con el mosaico que hay pintado en el titulo al iniciar
window_.x = 128; window_ = {128, 96, pos_.w, pos_.h};
window_.y = 96;
window_.w = pos_.w;
window_.h = pos_.h;
// Inicializa los valores del vector con los valores del seno // Inicializa los valores del vector con los valores del seno
for (int i = 0; i < 360; ++i) for (int i = 0; i < 360; ++i)
{ {
sin_[i] = SDL_sinf((float)i * 3.14f / 180.0f); sin_[i] = std::sin(i * 3.14159 / 180.0); // Convierte grados a radianes y calcula el seno
} }
} }
// Destructor
TiledBG::~TiledBG()
{
SDL_DestroyTexture(canvas_);
}
// Rellena la textura con el contenido // Rellena la textura con el contenido
void Tiledbg::fillTexture() void TiledBG::fillTexture()
{ {
// Crea los objetos para pintar en la textura de fondo // Crea los objetos para pintar en la textura de fondo
auto bg_tile_texture = std::make_shared<Texture>(renderer_, texture_path_); auto tile = std::make_unique<Sprite>(Resource::get()->getTexture("title_bg_tile.png"), (SDL_Rect){0, 0, TILE_WIDTH_, TILE_HEIGHT_});
auto tile = std::make_unique<Sprite>((SDL_Rect){0, 0, tile_width_, tile_height_}, bg_tile_texture);
// Prepara para dibujar sobre la textura // Prepara para dibujar sobre la textura
auto temp = SDL_GetRenderTarget(renderer_); auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, canvas_); SDL_SetRenderTarget(renderer_, canvas_);
// Rellena la textura con el tile // Rellena la textura con el tile
const auto i_max = pos_.w * 2 / tile_width_; const auto i_max = pos_.w * 2 / TILE_WIDTH_;
const auto j_max = pos_.h * 2 / tile_height_; const auto j_max = pos_.h * 2 / TILE_HEIGHT_;
tile->setSpriteClip(0, 0, tile_width_, tile_height_); tile->setSpriteClip(0, 0, TILE_WIDTH_, TILE_HEIGHT_);
for (int i = 0; i < i_max; ++i) for (int i = 0; i < i_max; ++i)
{ {
for (int j = 0; j < j_max; ++j) for (int j = 0; j < j_max; ++j)
{ {
tile->setPosX(i * tile_width_); tile->setX(i * TILE_WIDTH_);
tile->setPosY(j * tile_height_); tile->setY(j * TILE_HEIGHT_);
tile->render(); tile->render();
} }
} }
// Vuelve a colocar el renderizador como estaba // Vuelve a colocar el renderizador como estaba
SDL_SetRenderTarget(renderer_, temp); SDL_SetRenderTarget(renderer_, temp);
// Libera la memoria utilizada por los objetos
bg_tile_texture->unload();
} }
// Pinta la clase en pantalla // Pinta la clase en pantalla
void Tiledbg::render() void TiledBG::render()
{ {
SDL_RenderCopy(renderer_, canvas_, &window_, &pos_); SDL_RenderCopy(renderer_, canvas_, &window_, &pos_);
} }
// Actualiza la lógica de la clase // Actualiza la lógica de la clase
void Tiledbg::update() void TiledBG::update()
{ {
if (mode_ == TILED_MODE_DIAGONAL) switch (mode_)
{
case TiledBGMode::DIAGONAL:
{ // El tileado de fondo se desplaza en diagonal { // El tileado de fondo se desplaza en diagonal
++window_.x %= tile_width_; ++window_.x %= TILE_WIDTH_;
++window_.y %= tile_height_; ++window_.y %= TILE_HEIGHT_;
break;
} }
else if (mode_ == TILED_MODE_CIRCLE) case TiledBGMode::CIRCLE:
{ // El tileado de fondo se desplaza en circulo { // El tileado de fondo se desplaza en circulo
++counter_ %= 360; ++counter_ %= 360;
window_.x = 128 + (int(sin_[(counter_ + 270) % 360] * 128)); window_.x = 128 + (int(sin_[(counter_ + 270) % 360] * 128));
window_.y = 96 + (int(sin_[(360 - counter_) % 360] * 96)); window_.y = 96 + (int(sin_[(360 - counter_) % 360] * 96));
break;
}
default:
break;
} }
} }
// Recarga las texturas // Recarga las texturas
void Tiledbg::reLoad() void TiledBG::reLoad()
{ {
fillTexture(); fillTexture();
} }

View File

@@ -5,10 +5,13 @@
#include <string> // for string, basic_string #include <string> // for string, basic_string
// Modos de funcionamiento para el tileado de fondo // Modos de funcionamiento para el tileado de fondo
#define TILED_MODE_CIRCLE 0 enum class TiledBGMode : int
#define TILED_MODE_DIAGONAL 1 {
#define TILED_MODE_RANDOM 2 CIRCLE = 0,
#define TILED_MODE_STATIC 3 DIAGONAL = 1,
RANDOM = 2,
STATIC = 3,
};
/* /*
Esta clase dibuja un tileado de fondo. Para ello se sirve de una textura "canvas", que rellena con los tiles. Esta clase dibuja un tileado de fondo. Para ello se sirve de una textura "canvas", que rellena con los tiles.
@@ -16,36 +19,34 @@
textura en pantalla textura en pantalla
*/ */
// Clase Tiledbg // Clase TiledBG
class Tiledbg class TiledBG
{ {
private: private:
// Constantes
static constexpr int TILE_WIDTH_ = 64; // Ancho del tile
static constexpr int TILE_HEIGHT_ = 64; // Alto del tile
// Objetos y punteros // Objetos y punteros
SDL_Renderer *renderer_; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
SDL_Rect window_; // Ventana visible para la textura de fondo del titulo SDL_Rect window_; // Ventana visible para la textura de fondo del titulo
SDL_Texture *canvas_; // Textura donde dibujar el fondo formado por tiles SDL_Texture *canvas_; // Textura donde dibujar el fondo formado por tiles
// Variables // Variables
std::string texture_path_; // Fichero para usar en la textura SDL_Rect pos_; // Posición y tamaño del mosaico
SDL_Rect pos_; // Posición y tamaña del mosaico
int counter_; // Contador int counter_; // Contador
int mode_; // Tipo de movimiento del mosaico TiledBGMode mode_; // Tipo de movimiento del mosaico
float sin_[360]; // Vector con los valores del seno precalculados double sin_[360]; // Vector con los valores del seno precalculados
int tile_width_; // Ancho del tile
int tile_height_; // Alto del tile
// Inicializa las variables
void init();
// Rellena la textura con el contenido // Rellena la textura con el contenido
void fillTexture(); void fillTexture();
public: public:
// Constructor // Constructor
Tiledbg(std::string texture_path, SDL_Rect pos, int mode); TiledBG(SDL_Rect pos, TiledBGMode mode);
// Destructor // Destructor
~Tiledbg(); ~TiledBG();
// Pinta la clase en pantalla // Pinta la clase en pantalla
void render(); void render();

View File

@@ -12,8 +12,10 @@
#include "input.h" // for Input, InputType, INPUT_DO_NOT_ALLOW_R... #include "input.h" // for Input, InputType, INPUT_DO_NOT_ALLOW_R...
#include "jail_audio.h" // for JA_GetMusicState, JA_Music_state, JA_P... #include "jail_audio.h" // for JA_GetMusicState, JA_Music_state, JA_P...
#include "lang.h" // for getText #include "lang.h" // for getText
#include "notifier.h" // for Notifier
#include "options.h" // for options #include "options.h" // for options
#include "param.h" // for param #include "param.h" // for param
#include "resource.h" // for Resource
#include "screen.h" // for Screen #include "screen.h" // for Screen
#include "section.h" // for Options, options, Name, name #include "section.h" // for Options, options, Name, name
#include "texture.h" // for Texture #include "texture.h" // for Texture
@@ -21,64 +23,50 @@
struct JA_Music_t; // lines 17-17 struct JA_Music_t; // lines 17-17
// Constructor // Constructor
Title::Title(JA_Music_t *music) Title::Title()
: music_(music) : text1_(std::make_unique<Text>(Resource::get()->getTexture("smb2.gif"), Resource::get()->getTextFile("smb2.txt"))),
text2_(std::make_unique<Text>(Resource::get()->getTexture("8bithud.png"), Resource::get()->getTextFile("8bithud.txt"))),
fade_(std::make_unique<Fade>()),
tiled_bg_(std::make_unique<TiledBG>((SDL_Rect){0, 0, param.game.width, param.game.height}, TiledBGMode::RANDOM)),
game_logo_(std::make_unique<GameLogo>(param.game.game_area.center_x, param.title.title_c_c_position)),
mini_logo_texture_(Resource::get()->getTexture("logo_jailgames_mini.png")),
mini_logo_sprite_(std::make_unique<Sprite>(mini_logo_texture_, param.game.game_area.center_x - mini_logo_texture_->getWidth() / 2, 0, mini_logo_texture_->getWidth(), mini_logo_texture_->getHeight())),
define_buttons_(std::make_unique<DefineButtons>(std::move(text2_))),
counter_(0),
ticks_(0),
demo_(true),
next_section_(section::Name::GAME),
post_fade_(0),
num_controllers_(Input::get()->getNumControllers())
{ {
// Copia las direcciones de los punteros y objetos // Configura objetos
input_ = Input::get();
screen_ = Screen::get();
SDL_Renderer *renderer = screen_->getRenderer();
// Reserva memoria y crea los objetos
fade_ = std::make_unique<Fade>(renderer);
text1_ = std::make_unique<Text>(Asset::get()->get("smb2.gif"), Asset::get()->get("smb2.txt"), renderer);
text1_->addPalette(Asset::get()->get("smb2_pal1.gif"));
text1_->setPalette(1);
text2_ = std::make_unique<Text>(Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), renderer);
mini_logo_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("logo_jailgames_mini.png"));
mini_logo_sprite_ = std::make_unique<Sprite>(param.game.game_area.center_x - mini_logo_texture_->getWidth() / 2, 0, mini_logo_texture_->getWidth(), mini_logo_texture_->getHeight(), mini_logo_texture_);
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_RANDOM);
game_logo_ = std::make_unique<GameLogo>(param.game.game_area.center_x, param.title.title_c_c_position);
game_logo_->enable(); game_logo_->enable();
define_buttons_ = std::make_unique<DefineButtons>(std::move(text2_));
// Inicializa los valores
init();
}
// Inicializa los valores de las variables
void Title::init()
{
// Inicializa variables
section::options = section::Options::TITLE_1;
counter_ = 0;
next_section_ = section::Name::GAME;
post_fade_ = 0;
ticks_ = 0;
ticks_speed_ = 15;
fade_->setColor(fade_color.r, fade_color.g, fade_color.b); fade_->setColor(fade_color.r, fade_color.g, fade_color.b);
fade_->setType(FadeType::RANDOM_SQUARE); fade_->setType(FadeType::RANDOM_SQUARE);
fade_->setPost(param.fade.post_duration); fade_->setPost(param.fade.post_duration);
demo_ = true; Resource::get()->getTexture("smb2.gif")->setPalette(1);
num_controllers_ = input_->getNumControllers();
// Asigna valores a otras variables
section::options = section::Options::TITLE_1;
}
// Destructor
Title::~Title()
{
Resource::get()->getTexture("smb2.gif")->setPalette(0);
} }
// Actualiza las variables del objeto // Actualiza las variables del objeto
void Title::update() void Title::update()
{ {
// Calcula la lógica de los objetos // Calcula la lógica de los objetos
if (SDL_GetTicks() - ticks_ > ticks_speed_) 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 el fade_ y si se ha acabado // Comprueba el fade_ y si se ha acabado
fade_->update(); fade_->update();
@@ -115,7 +103,7 @@ void Title::update()
// Reproduce la música // Reproduce la música
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{ {
JA_PlayMusic(music_); JA_PlayMusic(Resource::get()->getMusic("title.ogg"));
} }
// Actualiza el logo con el título del juego // Actualiza el logo con el título del juego
@@ -137,10 +125,10 @@ void Title::update()
void Title::render() void Title::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(bg_color); Screen::get()->clean(bg_color);
// Dibuja el mosacico de fondo // Dibuja el mosacico de fondo
tiled_bg_->render(); tiled_bg_->render();
@@ -161,7 +149,7 @@ void Title::render()
// Mini logo // Mini logo
const int pos1 = (param.game.height / 5 * 4) + BLOCK; const int pos1 = (param.game.height / 5 * 4) + BLOCK;
const int pos2 = pos1 + mini_logo_sprite_->getHeight() + 3; const int pos2 = pos1 + mini_logo_sprite_->getHeight() + 3;
mini_logo_sprite_->setPosY(pos1); mini_logo_sprite_->setY(pos1);
mini_logo_sprite_->render(); mini_logo_sprite_->render();
// Texto con el copyright // Texto con el copyright
@@ -175,7 +163,7 @@ void Title::render()
fade_->render(); fade_->render();
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
screen_->blit(); Screen::get()->blit();
} }
// Comprueba los eventos // Comprueba los eventos
@@ -192,6 +180,7 @@ void Title::checkEvents()
if (event.type == SDL_QUIT) if (event.type == SDL_QUIT)
{ {
section::name = section::Name::QUIT; section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break; break;
} }
@@ -240,7 +229,7 @@ void Title::checkInput()
if (!define_buttons_->isEnabled()) if (!define_buttons_->isEnabled())
{ {
// Comprueba el teclado para empezar a jugar // Comprueba el teclado para empezar a jugar
if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
if (section::options == section::Options::TITLE_2 || ALLOW_TITLE_ANIMATION_SKIP) if (section::options == section::Options::TITLE_2 || ALLOW_TITLE_ANIMATION_SKIP)
{ {
@@ -250,27 +239,27 @@ void Title::checkInput()
} }
// Comprueba los mandos // Comprueba los mandos
for (int i = 0; i < input_->getNumControllers(); ++i) for (int i = 0; i < Input::get()->getNumControllers(); ++i)
{ {
// Comprueba si se va a intercambiar la asignación de mandos a jugadores // Comprueba si se va a intercambiar la asignación de mandos a jugadores
if (input_->checkModInput(InputType::SERVICE, InputType::SWAP_CONTROLLERS, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkModInput(InputType::SERVICE, InputType::SWAP_CONTROLLERS, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
swapControllers(); swapControllers();
return; return;
} }
// Comprueba si algun mando quiere ser configurado // Comprueba si algun mando quiere ser configurado
if (input_->checkModInput(InputType::SERVICE, InputType::CONFIG, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkModInput(InputType::SERVICE, InputType::CONFIG, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
define_buttons_->enable(i); define_buttons_->enable(i);
return; return;
} }
// Comprueba el botón de START de los mandos // Comprueba el botón de START de los mandos
if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
// Si no está el botón de servicio activo // Si no está el botón de servicio activo
if (!input_->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (!Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
if (section::options == section::Options::TITLE_2 || ALLOW_TITLE_ANIMATION_SKIP) if (section::options == section::Options::TITLE_2 || ALLOW_TITLE_ANIMATION_SKIP)
{ {
@@ -284,7 +273,7 @@ void Title::checkInput()
} }
// Comprueba el input para el resto de objetos // Comprueba el input para el resto de objetos
screen_->checkInput(); Screen::get()->checkInput();
define_buttons_->checkInput(); define_buttons_->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
@@ -319,7 +308,7 @@ void Title::resetCounter()
// Intercambia la asignación de mandos a los jugadores // Intercambia la asignación de mandos a los jugadores
void Title::swapControllers() void Title::swapControllers()
{ {
const auto num_controllers = input_->getNumControllers(); const auto num_controllers = Input::get()->getNumControllers();
if (num_controllers == 0) if (num_controllers == 0)
{ {
@@ -354,7 +343,7 @@ void Title::swapControllers()
} }
} }
screen_->showNotification(text[0], text[1]); Notifier::get()->showText(text[0], text[1]);
resetCounter(); resetCounter();
} }

View File

@@ -7,11 +7,14 @@
#include "game_logo.h" // for GameLogo #include "game_logo.h" // for GameLogo
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "text.h" // for Text #include "text.h" // for Text
#include "tiled_bg.h" // for Tiledbg #include "tiled_bg.h" // for TiledBG
class Input; // lines 17-17 class Input; // lines 17-17
class Screen; // lines 18-18 class Screen; // lines 18-18
class Texture; // lines 20-20 class Texture; // lines 20-20
namespace section { enum class Name; } namespace section
{
enum class Name;
}
struct JA_Music_t; // lines 21-21 struct JA_Music_t; // lines 21-21
// Textos // Textos
@@ -39,33 +42,28 @@ constexpr bool ALLOW_TITLE_ANIMATION_SKIP = true;
class Title class Title
{ {
private: private:
// Objetos y punteros // Constantes
Screen *screen_; // Objeto encargado de dibujar en pantalla static constexpr Uint32 TICKS_SPEED_ = 15; // Velocidad a la que se repiten los bucles del programa
Input *input_; // Objeto para leer las entradas de teclado o mando
std::unique_ptr<Tiledbg> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo
std::unique_ptr<GameLogo> game_logo_; // Objeto para dibujar el logo con el título del juego
std::unique_ptr<DefineButtons> define_buttons_; // Objeto para definir los botones del joystic
std::shared_ptr<Texture> mini_logo_texture_; // Textura con el logo de JailGames mini
std::unique_ptr<Sprite> mini_logo_sprite_; // Sprite con el logo de JailGames mini
// Objetos y punteros
std::unique_ptr<Text> text1_; // Objeto de texto para poder escribir textos en pantalla std::unique_ptr<Text> text1_; // Objeto de texto para poder escribir textos en pantalla
std::unique_ptr<Text> text2_; // Objeto de texto para poder escribir textos en pantalla std::unique_ptr<Text> text2_; // Objeto de texto para poder escribir textos en pantalla
std::unique_ptr<Fade> fade_; // Objeto para realizar fundidos en pantalla std::unique_ptr<Fade> fade_; // Objeto para realizar fundidos en pantalla
std::unique_ptr<TiledBG> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo
std::unique_ptr<GameLogo> game_logo_; // Objeto para dibujar el logo con el título del juego
std::shared_ptr<Texture> mini_logo_texture_; // Textura con el logo de JailGames mini
std::unique_ptr<Sprite> mini_logo_sprite_; // Sprite con el logo de JailGames mini
std::unique_ptr<DefineButtons> define_buttons_; // Objeto para definir los botones del joystic
JA_Music_t *music_; // Musica para el titulo
// Variable // Variable
int counter_; // Temporizador para la pantalla de titulo int counter_; // Temporizador para la pantalla de titulo
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
bool demo_; // Indica si el modo demo estará activo bool demo_; // Indica si el modo demo estará activo
section::Name next_section_; // Indica cual es la siguiente sección a cargar cuando termine el contador del titulo section::Name next_section_; // Indica cual es la siguiente sección a cargar cuando termine el contador del titulo
int post_fade_; // Opción a realizar cuando termina el fundido int post_fade_; // Opción a realizar cuando termina el fundido
int num_controllers_; // Número de mandos conectados int num_controllers_; // Número de mandos conectados
// Inicializa los valores de las variables
void init();
// Actualiza las variables del objeto // Actualiza las variables del objeto
void update(); void update();
@@ -89,10 +87,10 @@ private:
public: public:
// Constructor // Constructor
explicit Title(JA_Music_t *music); Title();
// Destructor // Destructor
~Title() = default; ~Title();
// Bucle para el titulo del juego // Bucle para el titulo del juego
void run(); void run();

View File

@@ -1,4 +1,6 @@
#include "utils.h" #include "utils.h"
#include <iostream>
#include <string>
#include <algorithm> // for min, clamp, find_if_not, transform #include <algorithm> // for min, clamp, find_if_not, transform
#include <cctype> // for tolower, isspace #include <cctype> // for tolower, isspace
#include <cmath> // for cos, pow, M_PI #include <cmath> // for cos, pow, M_PI
@@ -104,38 +106,6 @@ std::string toLower(const std::string &str)
return result; return result;
} }
// Obtiene el fichero de sonido a partir de un nombre
JA_Sound_t *getSound(const std::vector<SoundFile> &sounds, const std::string &name)
{
for (const auto &s : sounds)
{
if (s.name == name)
{
return s.file;
}
}
return nullptr;
}
// Obtiene el fichero de música a partir de un nombre
JA_Music_t *getMusic(const std::vector<MusicFile> &music, const std::string &name)
{
for (const auto &m : music)
{
if (m.name == name)
{
return m.file;
}
}
return nullptr;
}
// Ordena las entradas de la tabla de records
HiScoreEntry sortHiScoreTable(const HiScoreEntry &entry1, const HiScoreEntry &entry2)
{
return (entry1.score > entry2.score) ? entry1 : entry2;
}
// Dibuja un circulo // Dibuja un circulo
void DrawCircle(SDL_Renderer *renderer, int32_t centerX, int32_t centerY, int32_t radius) void DrawCircle(SDL_Renderer *renderer, int32_t centerX, int32_t centerY, int32_t radius)
{ {
@@ -214,3 +184,91 @@ double easeInOutSine(double t)
{ {
return -0.5 * (std::cos(M_PI * t) - 1); return -0.5 * (std::cos(M_PI * t) - 1);
} }
// Comprueba si una vector contiene una cadena
bool stringInVector(const std::vector<std::string> &vec, const std::string &str)
{
return std::find(vec.begin(), vec.end(), str) != vec.end();
}
// Imprime por pantalla una linea de texto de tamaño fijo rellena con puntos
void printWithDots(const std::string &text1, const std::string &text2, const std::string &text3)
{
std::cout.setf(std::ios::left, std::ios::adjustfield);
std::cout << text1;
std::cout.width(50 - text1.length() - text3.length());
std::cout.fill('.');
std::cout << text2;
std::cout << text3 << std::endl;
}
// Carga el fichero de datos para la demo
DemoData loadDemoDataFromFile(const std::string &file_path)
{
DemoData dd;
// Indicador de éxito en la carga
auto file = SDL_RWFromFile(file_path.c_str(), "r+b");
if (!file)
{
std::cerr << "Error: Fichero no encontrado " << file_path << std::endl;
throw std::runtime_error("Fichero no encontrado: " + file_path);
}
else
{
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
printWithDots("DemoData : ", file_name, "[ LOADED ]");
// Lee todos los datos del fichero y los deja en el destino
for (int i = 0; i < TOTAL_DEMO_DATA; ++i)
{
DemoKeys dk = DemoKeys();
SDL_RWread(file, &dk, sizeof(DemoKeys), 1);
dd.push_back(dk);
}
// Cierra el fichero
SDL_RWclose(file);
}
return dd;
}
#ifdef RECORDING
// Guarda el fichero de datos para la demo
bool saveDemoFile(const std::string &file_path, const DemoData &dd)
{
auto success = true;
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
auto file = SDL_RWFromFile(file_path.c_str(), "w+b");
if (file)
{
// Guarda los datos
for (const auto &data : dd)
{
if (SDL_RWwrite(file, &data, sizeof(DemoKeys), 1) != 1)
{
std::cerr << "Error al escribir el fichero " << file_name << std::endl;
success = false;
break;
}
}
if (success)
{
std::cout << "Writing file " << file_name.c_str() << std::endl;
}
// Cierra el fichero
SDL_RWclose(file);
}
else
{
std::cout << "Error: Unable to save " << file_name.c_str() << " file! " << SDL_GetError() << std::endl;
success = false;
}
return success;
}
#endif // RECORDING

View File

@@ -17,6 +17,10 @@ namespace lang
struct JA_Music_t; // lines 12-12 struct JA_Music_t; // lines 12-12
struct JA_Sound_t; // lines 13-13 struct JA_Sound_t; // lines 13-13
// Constantes
constexpr int BLOCK = 8;
constexpr int TOTAL_DEMO_DATA = 2000;
// Dificultad del juego // Dificultad del juego
enum class GameDifficulty enum class GameDifficulty
{ {
@@ -25,9 +29,6 @@ enum class GameDifficulty
HARD = 2, HARD = 2,
}; };
// Tamaño de bloque
constexpr int BLOCK = 8;
// Estructura para definir un circulo // Estructura para definir un circulo
struct Circle struct Circle
{ {
@@ -58,7 +59,6 @@ struct HiScoreEntry
int score; // Puntuación int score; // Puntuación
}; };
// Estructura para mapear el teclado usado en la demo
struct DemoKeys struct DemoKeys
{ {
Uint8 left; Uint8 left;
@@ -67,6 +67,21 @@ struct DemoKeys
Uint8 fire; Uint8 fire;
Uint8 fire_left; Uint8 fire_left;
Uint8 fire_right; Uint8 fire_right;
// Constructor que inicializa todos los campos
DemoKeys(Uint8 l = 0, Uint8 r = 0, Uint8 ni = 0, Uint8 f = 0, Uint8 fl = 0, Uint8 fr = 0)
: left(l), right(r), no_input(ni), fire(f), fire_left(fl), fire_right(fr) {}
};
using DemoData = std::vector<DemoKeys>;
struct Demo
{
bool enabled; // Indica si está activo el modo demo
bool recording; // Indica si está activado el modo para grabar la demo
int counter; // Contador para el modo demo
DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo
std::vector<DemoData> data; // Vector con diferentes sets de datos con los movimientos para la demo
}; };
// Estructura para las opciones de la ventana // Estructura para las opciones de la ventana
@@ -157,6 +172,7 @@ struct ParamGame
int item_size; // Tamaño de los items del juego int item_size; // Tamaño de los items del juego
Zone play_area; // Rectangulo con la posición de la zona de juego Zone play_area; // Rectangulo con la posición de la zona de juego
Zone game_area; // Rectangulo con las dimensiones del juego Zone game_area; // Rectangulo con las dimensiones del juego
int enter_name_seconds; // Duración en segundos para introducir el nombre al finalizar la partida
}; };
// param.fade // param.fade
@@ -214,20 +230,6 @@ struct Param
ParamNotification notification; // Opciones para las notificaciones ParamNotification notification; // Opciones para las notificaciones
}; };
// Estructura para almacenar ficheros de sonido y su nombre
struct SoundFile
{
std::string name; // Nombre del sonido
JA_Sound_t *file; // Fichero con el sonido
};
// Estructura para almacenar ficheros musicales y su nombre
struct MusicFile
{
std::string name; // Nombre de la musica
JA_Music_t *file; // Fichero con la música
};
// Calcula el cuadrado de la distancia entre dos puntos // Calcula el cuadrado de la distancia entre dos puntos
double distanceSquared(int x1, int y1, int x2, int y2); double distanceSquared(int x1, int y1, int x2, int y2);
@@ -255,15 +257,6 @@ std::string boolToOnOff(bool value);
// Convierte una cadena a minusculas // Convierte una cadena a minusculas
std::string toLower(const std::string &str); std::string toLower(const std::string &str);
// Obtiene el fichero de sonido a partir de un nombre
JA_Sound_t *getSound(const std::vector<SoundFile> &sounds, const std::string &name);
// Obtiene el fichero de música a partir de un nombre
JA_Music_t *getMusic(const std::vector<MusicFile> &music, const std::string &name);
// Ordena las entradas de la tabla de records
HiScoreEntry sortHiScoreTable(const HiScoreEntry &entry1, const HiScoreEntry &entry2);
// Dibuja un circulo // Dibuja un circulo
void DrawCircle(SDL_Renderer *renderer, int32_t centerX, int32_t centerY, int32_t radius); void DrawCircle(SDL_Renderer *renderer, int32_t centerX, int32_t centerY, int32_t radius);
@@ -282,6 +275,20 @@ double easeOutQuint(double t);
// Función de suavizado // Función de suavizado
double easeInOutSine(double t); double easeInOutSine(double t);
// Comprueba si una vector contiene una cadena
bool stringInVector(const std::vector<std::string> &vec, const std::string &str);
// Imprime por pantalla una linea de texto de tamaño fijo rellena con puntos
void printWithDots(const std::string &text1, const std::string &text2, const std::string &text3);
// Carga el fichero de datos para la demo
DemoData loadDemoDataFromFile(const std::string &file_path);
#ifdef RECORDING
// Guarda el fichero de datos para la demo
bool saveDemoFile(const std::string &file_path, const DemoData &dd);
#endif
// Colores // Colores
extern const Color bg_color; extern const Color bg_color;
extern const Color no_color; extern const Color no_color;