32 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
e99c2c5265 fix: faltava el nom de la classe en shutdownSystem() 2024-10-15 18:58:10 +02:00
942924c65c Afegit codi per apagar el sistema al eixir del joc 2024-10-15 18:24:19 +02:00
089da99b5b Afegida la funció getNewPosition a la classe Screen per a respectar la posició de la finestra al canviarla de tamany 2024-10-15 18:12:16 +02:00
3fdd60c9e2 Treballant en els game_texts 2024-10-15 14:02:37 +02:00
3b9885ab03 Commit de Boromir 2024-10-14 22:33:45 +02:00
39a8c992e1 Ja duplica la ultima lletra al posar el nom 2024-10-14 17:12:07 +02:00
94 changed files with 3268 additions and 3375 deletions

View File

@@ -1,11 +1,12 @@
## GAME
game.item_size 20
game.width 320
game.height 240
game.play_area.rect.x 0
game.play_area.rect.y 0
game.play_area.rect.w 320
game.play_area.rect.h 200
game.item_size 20 # Tamaño de los items del juego
game.width 320 # Ancho de la resolucion nativa del juego
game.height 240 # Alto de la resolucion nativa del juego
game.play_area.rect.x 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.y 0 # Rectangulo con la posición de la zona de juego
game.play_area.rect.w 320 # Rectangulo con la posición de la zona de juego
game.play_area.rect.h 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.num_squares_width 160

View File

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

View File

Before

Width:  |  Height:  |  Size: 84 B

After

Width:  |  Height:  |  Size: 84 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 935 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 337 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 376 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 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
## 94 - NOTIFICACIONES
Torna a polsar per eixir ...
Torna a polsar per eixir
## 95 - DEFINE BUTTONS
Disparar cap a l'esquerra
@@ -344,4 +344,7 @@ Eixir
Per favor
## 115 - MARCADOR
espere
espere
## 116 - NOTIFICACIONES
Torna a polsar per apagar el sistema

View File

@@ -344,4 +344,7 @@ Exit
Please
## 115 - MARCADOR
wait
wait
## 116 - NOTIFICACIONES
Press again to shutdown system

View File

@@ -344,4 +344,7 @@ Salir
Por favor
## 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 <sstream> // for basic_stringstream
#include "texture.h" // for Texture
#include "utils.h"
// Carga la animación desde un fichero
AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string file_path)
// Carga las animaciones en un vector(Animations) desde un fichero
Animations loadAnimationsFromFile(const std::string &file_path)
{
// Inicializa variables
AnimatedFile af;
af.texture = texture;
auto frames_per_row = 0;
auto frame_width = 0;
auto frame_height = 0;
auto max_tiles = 0;
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
std::vector<std::string> buffer;
std::ifstream file(file_path);
if (!file)
{
std::cerr << "Error: Fichero no encontrado " << file_path << std::endl;
throw std::runtime_error("Fichero no encontrado: " + file_path);
}
std::string line;
printWithDots("Animation : ", file_path.substr(file_path.find_last_of("\\/") + 1), "[ LOADED ]");
// El fichero se puede abrir
if (file.good())
while (std::getline(file, line))
{
// Procesa el fichero linea a linea
#ifdef VERBOSE
std::cout << "Animation loaded: " << file_name << std::endl;
#endif
while (std::getline(file, line))
{
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
Animation buffer;
buffer.counter = 0;
buffer.current_frame = 0;
buffer.completed = false;
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")
{
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
buffer.push_back(line);
}
return af;
return buffer;
}
// 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),
current_animation_(0)
{
// Carga las animaciones
if (!file.empty())
if (!file_path.empty())
{
AnimatedFile as = loadAnimationFromFile(texture, file);
// Copia los datos de las animaciones
std::copy(as.animations.begin(), as.animations.end(), std::back_inserter(animations_));
animations_ = loadFromFile(file_path);
}
}
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
AnimatedSprite::AnimatedSprite(const AnimatedFile *animation)
: MovingSprite(animation->texture),
current_animation_(0)
{
// Copia los datos de las animaciones
std::copy(animation->animations.begin(), animation->animations.end(), std::back_inserter(animations_));
}
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture)
: MovingSprite(texture),
current_animation_(0) {}
// Destructor
AnimatedSprite::~AnimatedSprite()
@@ -207,9 +75,7 @@ int AnimatedSprite::getIndex(const std::string &name)
return index;
}
}
#ifdef VERBOSE
std::cout << "** Warning: could not find \"" << name.c_str() << "\" animation" << std::endl;
#endif
return -1;
}
@@ -333,152 +199,6 @@ SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF)
return animations_[indexA].frames[indexF];
}
// Carga la animación desde un vector
bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
{
// Inicializa variables
auto frames_per_row = 0;
auto frame_width = 0;
auto frame_height = 0;
auto max_tiles = 0;
// Indicador de éxito en el proceso
auto success = true;
std::string line;
// Recorre todo el vector
auto index = 0;
while (index < (int)source->size())
{
// Lee desde el vector
line = source->at(index);
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
Animation buffer;
buffer.counter = 0;
buffer.current_frame = 0;
buffer.completed = false;
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
void AnimatedSprite::setCurrentAnimation(const std::string &name)
{
@@ -533,4 +253,279 @@ void AnimatedSprite::resetAnimation()
animations_[current_animation_].current_frame = 0;
animations_[current_animation_].counter = 0;
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
int current_frame; // Frame actual
int counter; // Contador para las animaciones
Animation() : name(std::string()), speed(5), loop(0), completed(false), current_frame(0), counter(0) {}
};
struct AnimatedFile
{
std::vector<Animation> animations; // Vector con las diferentes animaciones
std::shared_ptr<Texture> texture; // Textura con los graficos para el sprite
};
using Animations = std::vector<std::string>;
// Carga la animación desde un fichero
AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string filePath);
// Carga las animaciones en un vector(Animations) desde un fichero
Animations loadAnimationsFromFile(const std::string &file_path);
class AnimatedSprite : public MovingSprite
{
@@ -35,16 +33,26 @@ protected:
std::vector<Animation> animations_; // Vector con las diferentes animaciones
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:
// Constructor
explicit AnimatedSprite(std::shared_ptr<Texture> texture = nullptr, const std::string &file = std::string(), std::vector<std::string> *buffer = nullptr);
explicit AnimatedSprite(const AnimatedFile *animation);
AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path);
AnimatedSprite(std::shared_ptr<Texture> texture, const Animations &animations);
explicit AnimatedSprite(std::shared_ptr<Texture> texture);
// Destructor
virtual ~AnimatedSprite();
// Calcula el frame correspondiente a la animación actual
void animate();
// Actualiza las variables del objeto
void update() override;
// Obtiene el número de frames de la animación actual
int getNumFrames();
@@ -77,16 +85,10 @@ public:
// Obtiene el indice de la animación a partir del nombre
int getIndex(const std::string &name);
// Carga la animación desde un vector
bool loadFromVector(std::vector<std::string> *source);
// Establece la animacion actual
void setCurrentAnimation(const std::string &name = "default");
void setCurrentAnimation(int index = 0);
// Actualiza las variables del objeto
void update() override;
// 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);

View File

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

View File

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

View File

@@ -1,9 +1,9 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <memory> // for unique_ptr, shared_ptr
#include "utils.h" // for Color
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <memory> // for unique_ptr, shared_ptr
#include "utils.h" // for Color
class MovingSprite;
class Sprite;
class Texture;
@@ -107,7 +107,7 @@ private:
public:
// Constructor
explicit Background(SDL_Renderer *renderer);
Background();
// Destructor
~Background();

View File

@@ -1,14 +1,14 @@
#include "balloon.h"
#include <cmath> // for abs
#include "animated_sprite.h" // for AnimatedSprite
#include "animated_sprite.h" // for SpriteAnimated
#include "moving_sprite.h" // for MovingSprite
#include "param.h" // for param
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
// 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)
: sprite_(std::make_unique<AnimatedSprite>(texture, "", 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)),
pos_x_(x),
pos_y_(y),
vel_x_(vel_x),
@@ -121,10 +121,10 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 1;
// Inicializa los valores de velocidad y gravedad
vel_y_ = abs(vel_x) * 2;
max_vel_y_ = abs(vel_x) * 2;
vel_y_ = fabs(vel_x_ * 2.0f);
max_vel_y_ = vel_y_;
gravity_ = 0.00f;
default_vel_y_ = abs(vel_x) * 2;
default_vel_y_ = vel_y_;
// Puntos que da el globo al ser destruido
score_ = BALLOON_SCORE_1;
@@ -142,10 +142,10 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 3;
// Inicializa los valores de velocidad y gravedad
vel_y_ = abs(vel_x) * 2;
max_vel_y_ = abs(vel_x) * 2;
vel_y_ = fabs(vel_x_ * 2.0f);
max_vel_y_ = vel_y_;
gravity_ = 0.00f;
default_vel_y_ = abs(vel_x) * 2;
default_vel_y_ = vel_y_;
// Puntos que da el globo al ser destruido
score_ = BALLOON_SCORE_2;
@@ -163,10 +163,10 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 7;
// Inicializa los valores de velocidad y gravedad
vel_y_ = abs(vel_x) * 2;
max_vel_y_ = abs(vel_x) * 2;
vel_y_ = fabs(vel_x_ * 2.0f);
max_vel_y_ = vel_y_;
gravity_ = 0.00f;
default_vel_y_ = abs(vel_x) * 2;
default_vel_y_ = vel_y_;
// Puntos que da el globo al ser destruido
score_ = BALLOON_SCORE_3;
@@ -184,10 +184,10 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 15;
// Inicializa los valores de velocidad y gravedad
vel_y_ = abs(vel_x) * 2;
max_vel_y_ = abs(vel_x) * 2;
vel_y_ = fabs(vel_x_ * 2.0f);
max_vel_y_ = vel_y_;
gravity_ = 0.00f;
default_vel_y_ = abs(vel_x) * 2;
default_vel_y_ = vel_y_;
// Puntos que da el globo al ser destruido
score_ = BALLOON_SCORE_4;
@@ -217,7 +217,7 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
menace_ = 0;
// Añade rotación al sprite_
sprite_->setRotate(false);
sprite_->disableRotate();
sprite_->setRotateSpeed(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_.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_
sprite_->setWidth(width_);
sprite_->setHeight(height_);
// Posición X,Y del sprite_
sprite_->setPosX((int)pos_x_);
sprite_->setPosY((int)pos_y_);
// Configura el sprite
sprite_->setPos({static_cast<int>(pos_x_), static_cast<int>(pos_y_), width_, height_});
// Tamaño del circulo de colisión
collider_.r = width_ / 2;
@@ -306,7 +301,7 @@ void Balloon::render()
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->render();
}
@@ -396,10 +391,6 @@ void Balloon::move()
// Aplica la gravedad al objeto sin pasarse de una velocidad máxima
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_
@@ -454,13 +445,13 @@ void Balloon::update()
{
if (enabled_)
{
sprite_->MovingSprite::update();
sprite_->update();
move();
updateAnimation();
updateColliders();
updateState();
updateBounce();
counter_++;
++counter_;
}
}
@@ -510,7 +501,7 @@ void Balloon::updateState()
setInvulnerable(false);
if (kind_ == POWER_BALL)
{
sprite_->setRotate(true);
sprite_->enableRotate();
}
}
}
@@ -520,7 +511,7 @@ void Balloon::updateState()
// Si es una powerball deja de rodar
if (kind_ == POWER_BALL)
{
sprite_->setRotate(false);
sprite_->disableRotate();
}
// Reduce el contador
@@ -536,7 +527,7 @@ void Balloon::updateState()
// Si es una powerball vuelve a rodar
if (kind_ == POWER_BALL)
{
sprite_->setRotate(true);
sprite_->enableRotate();
}
}
}
@@ -569,7 +560,7 @@ void Balloon::updateAnimation()
sprite_->setCurrentAnimation(normal_animation);
}
sprite_->animate();
sprite_->update();
}
// Comprueba si el globo está habilitado
@@ -609,15 +600,15 @@ int Balloon::getHeight() const
}
// 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
void Balloon::setSpeed(float speed_)
void Balloon::setSpeed(float speed)
{
this->speed_ = speed_;
speed_ = speed;
}
// Obtiene del valor de la variable

View File

@@ -4,7 +4,7 @@
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string
#include <vector> // for vector
#include "animated_sprite.h" // for AnimatedSprite
#include "animated_sprite.h" // for SpriteAnimated
#include "utils.h" // for Circle
class Texture;
@@ -141,7 +141,7 @@ private:
public:
// 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
~Balloon() = default;

View File

@@ -37,15 +37,11 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[i].number_of_balloons = 0;
for (int j = 0; j < MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION; j++)
{
balloon_formation_[i].init[j].x = 0;
balloon_formation_[i].init[j].y = 0;
balloon_formation_[i].init[j].vel_x = 0;
balloon_formation_[i].init[j].kind = 0;
balloon_formation_[i].init[j].creation_counter = 0;
balloon_formation_[i].init[j] = BalloonFormationParams();
}
}
const int creation_time = 300;
constexpr int CREATION_TIME = 300;
int inc_x = 0;
int inc_time = 0;
int j = 0;
@@ -61,7 +57,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y4;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE * (((i % 2) * 2) - 1);
balloon_formation_[j].init[i].kind = BALLOON_4;
balloon_formation_[j].init[i].creation_counter = creation_time + (inc_time * i);
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
@@ -75,7 +71,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y4;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE * (((i % 2) * 2) - 1);
balloon_formation_[j].init[i].kind = BALLOON_4;
balloon_formation_[j].init[i].creation_counter = creation_time + (inc_time * i);
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
@@ -89,7 +85,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y2;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_2;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
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
@@ -103,7 +99,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y2;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_2;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #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].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #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].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #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].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #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].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
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
@@ -173,7 +169,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_1;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
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
@@ -187,7 +183,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y1;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_1;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #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].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_4;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #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].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_4;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
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
@@ -229,7 +225,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y2;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_2;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
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
@@ -243,7 +239,7 @@ void BalloonFormations::initBalloonFormations()
balloon_formation_[j].init[i].y = y2;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_2;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #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].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #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].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #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].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #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].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_3;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #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].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].kind = BALLOON_1;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #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].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].kind = BALLOON_1;
balloon_formation_[j].init[i].creation_counter = creation_time - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = CREATION_TIME - (inc_time * i);
}
// #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].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
@@ -365,13 +361,13 @@ void BalloonFormations::initBalloonFormations()
{
balloon_formation_[j].init[i].x = x2_0 + (i * inc_x);
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) - (inc_time * i);
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * i);
}
else
{
balloon_formation_[j].init[i].x = x2_100 - ((i - half) * inc_x);
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) - (inc_time * (i - half));
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * (i - half));
}
balloon_formation_[j].init[i].y = y2;
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].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
{
balloon_formation_[j].init[i].x = x3_100 - ((i - half) * inc_x);
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) - (inc_time * (i - half));
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * (i - half));
}
balloon_formation_[j].init[i].y = y3;
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].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
{
balloon_formation_[j].init[i].x = x3_100 - ((i - half) * inc_x);
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) - (inc_time * (i - half));
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * (i - half));
}
balloon_formation_[j].init[i].y = y3;
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].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
{
balloon_formation_[j].init[i].x = x1_50;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_NEGATIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) + (inc_time * (i - half));
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) + (inc_time * (i - half));
}
balloon_formation_[j].init[i].y = y1;
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].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
{
balloon_formation_[j].init[i].x = x1_50 - 20;
balloon_formation_[j].init[i].vel_x = BALLOON_VELX_POSITIVE;
balloon_formation_[j].init[i].creation_counter = (creation_time) - (inc_time * (i - half));
balloon_formation_[j].init[i].creation_counter = (CREATION_TIME) - (inc_time * (i - half));
}
balloon_formation_[j].init[i].y = y1;
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
struct BalloonFormationParams
{
int x; // Posición en el eje X donde crear al enemigo
int y; // Posición en el eje Y donde crear al enemigo
float vel_x; // Velocidad inicial en el eje X
int kind; // Tipo de enemigo
int creation_counter; // Temporizador para la creación del enemigo
int x = 0; // Posición en el eje X donde crear al enemigo
int y = 0; // Posición en el eje Y donde crear al enemigo
float vel_x = 0.0f; // Velocidad inicial en el eje X
int kind = 0; // Tipo de 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

View File

@@ -12,7 +12,7 @@ constexpr int BULLET_VELX_RIGHT = 2;
// Constructor
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_y_(y),
width_(BULLET_WIDTH),
@@ -57,8 +57,8 @@ BulletMoveStatus Bullet::move()
return BulletMoveStatus::OUT;
}
sprite_->setPosX(pos_x_);
sprite_->setPosY(pos_y_);
sprite_->setX(pos_x_);
sprite_->setY(pos_y_);
shiftColliders();
return BulletMoveStatus::OK;

View File

@@ -1,12 +1,12 @@
#include "define_buttons.h"
#include <utility> // for move
#include "input.h" // for Input, InputType
#include "lang.h" // for getText
#include "options.h" // for options
#include "param.h" // for param
#include "section.h" // for Name, Options, name, options
#include "text.h" // for Text
#include "utils.h" // for OptionsController, Options, Param, ParamGame
#include <utility> // for move
#include "input.h" // for Input, InputType
#include "lang.h" // for getText
#include "options.h" // for options
#include "param.h" // for param
#include "section.h" // for Name, Options, name, options
#include "text.h" // for Text
#include "utils.h" // for OptionsController, Options, Param, ParamGame
// Constructor
DefineButtons::DefineButtons(std::unique_ptr<Text> text_)
@@ -106,7 +106,7 @@ void DefineButtons::checkInput()
case SDL_QUIT:
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_NORMAL;
section::options = section::Options::QUIT_WITH_KEYBOARD;
break;
}
@@ -157,7 +157,7 @@ void DefineButtons::incIndexButton()
// Guarda los cambios en las opciones
saveBindingsToOptions();
//input_->allActive(index_controller_);
// input_->allActive(index_controller_);
// Reinicia variables
index_button_ = 0;

View File

@@ -8,6 +8,7 @@
#include <SDL2/SDL_scancode.h> // for SDL_SCANCODE_0, SDL_SCANCODE_DOWN
#include <SDL2/SDL_stdinc.h> // for SDL_bool, Uint32
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <cstdlib> // for system
#include <errno.h> // for errno, EEXIST, EACCES, ENAMETOO...
#include <stdio.h> // for printf, perror
#include <string.h> // for strcmp
@@ -29,9 +30,11 @@
#include "lang.h" // for Code, loadFromFile
#include "logo.h" // for Logo
#include "manage_hiscore_table.h" // for ManageHiScoreTable
#include "notifier.h" // for Notifier
#include "on_screen_help.h" // for OnScreenHelp
#include "options.h" // for options, loadOptionsFile, saveO...
#include "param.h" // for param, loadParamsFromFile
#include "resource.h" //for Resource
#include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options
#include "title.h" // for Title
@@ -53,6 +56,14 @@ Director::Director(int argc, const char *argv[])
section::name = section::Name::LOGO;
#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
checkProgramArguments(argc, argv);
@@ -63,11 +74,8 @@ Director::Director(int argc, const char *argv[])
// Crea el objeto que controla los ficheros de recursos
Asset::init(executable_path_);
// Si falta algún fichero no inicia el programa
if (!setFileList())
{
exit(EXIT_FAILURE);
}
// Crea el indice de ficheros
setFileList();
// Carga el fichero de configuración
loadOptionsFile(Asset::get()->get("config.txt"));
@@ -96,19 +104,18 @@ Director::Director(int argc, const char *argv[])
// Crea los objetos
lang::loadFromFile(getLangFile((lang::Code)options.game.language));
Input::init(Asset::get()->get("gamecontrollerdb.txt"));
initInput();
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();
// Carga los sonidos del juego
loadSounds();
// Carga las musicas del juego
loadMusics();
globalInputs::init();
}
@@ -117,25 +124,23 @@ Director::~Director()
saveOptionsFile(Asset::get()->get("config.txt"));
Asset::destroy();
Resource::destroy();
Input::destroy();
Screen::destroy();
Notifier::destroy();
OnScreenHelp::destroy();
sounds_.clear();
musics_.clear();
SDL_DestroyRenderer(renderer_);
SDL_DestroyWindow(window_);
SDL_Quit();
std::cout << "\nBye!" << std::endl;
}
/// Inicializa el objeto input
void Director::initInput()
// Asigna los botones y teclas al objeto Input
void Director::bindInputs()
{
// Busca si hay mandos conectados
Input::get()->discoverGameControllers();
// Teclado - Movimiento del jugador
Input::get()->bindKey(InputType::UP, SDL_SCANCODE_UP);
Input::get()->bindKey(InputType::DOWN, SDL_SCANCODE_DOWN);
@@ -243,9 +248,7 @@ bool Director::initSDL()
// Inicializa SDL
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
#ifdef VERBOSE
std::cout << "SDL could not initialize!\nSDL Error: " << SDL_GetError() << std::endl;
#endif
success = false;
}
else
@@ -253,7 +256,6 @@ bool Director::initSDL()
// Inicia el generador de numeros aleatorios
std::srand(static_cast<unsigned int>(SDL_GetTicks()));
#ifdef VERBOSE
// Muestra información de la pantalla
/*std::cout << "\nDisplay modes list:" << std::endl;
for (int i = 0; i < SDL_GetNumDisplayModes(0); ++i)
@@ -267,30 +269,23 @@ bool Director::initSDL()
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 << "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
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";
#endif
}
#ifndef NO_SHADERS
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"))
{
#ifdef VERBOSE
std::cout << "Warning: opengl not enabled!\n";
#endif // VERBOSE
}
#endif // NO_SHADERS
// 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);
if (!window_)
{
#ifdef VERBOSE
std::cout << "Window could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
#endif
success = false;
}
else
@@ -309,9 +304,7 @@ bool Director::initSDL()
if (!renderer_)
{
#ifdef VERBOSE
std::cout << "Renderer could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
#endif
success = false;
}
else
@@ -329,14 +322,12 @@ bool Director::initSDL()
}
}
#ifdef VERBOSE
std::cout << std::endl;
#endif
return success;
}
// Crea el indice de ficheros
bool Director::setFileList()
void Director::setFileList()
{
#ifdef MACOS_BUNDLE
const std::string prefix = "/../Resources";
@@ -380,94 +371,127 @@ bool Director::setFileList()
Asset::get()->add(prefix + "/data/shaders/crtpi.glsl", AssetType::DATA);
// Texturas
Asset::get()->add(prefix + "/data/gfx/controllers/controllers.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/balloon2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon2.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon3.png", AssetType::BITMAP);
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.ani", AssetType::ANIMATION);
{ // Controllers
Asset::get()->add(prefix + "/data/gfx/controllers/controllers.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/explosion2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion2.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion3.png", AssetType::BITMAP);
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.ani", AssetType::ANIMATION);
{ // Balloons
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/balloon2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon2.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/balloon3.png", AssetType::BITMAP);
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.ani", AssetType::ANIMATION);
}
Asset::get()->add(prefix + "/data/gfx/balloon/powerball.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/powerball.ani", AssetType::ANIMATION);
{ // Explosions
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/explosion2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion2.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/balloon/explosion3.png", AssetType::BITMAP);
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.ani", AssetType::ANIMATION);
}
Asset::get()->add(prefix + "/data/gfx/bullet/bullet.png", AssetType::BITMAP);
{ // Power Ball
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/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_clouds2.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_sky_colors.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_text.png", AssetType::BITMAP);
{ // Bala
Asset::get()->add(prefix + "/data/gfx/bullet/bullet.png", AssetType::BITMAP);
}
Asset::get()->add(prefix + "/data/gfx/intro/intro.png", AssetType::BITMAP);
{ // Juego
Asset::get()->add(prefix + "/data/gfx/game/game_buildings.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_clouds1.png", AssetType::BITMAP);
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_power_meter.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game/game_sky_colors.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_since_1998.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_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_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/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_points2_gavina.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_points2_gavina.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_points3_pacmar.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_points3_pacmar.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_clock.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_clock.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.ani", AssetType::ANIMATION);
{ // Intro
Asset::get()->add(prefix + "/data/gfx/intro/intro.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_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_dust.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_dust.ani", AssetType::ANIMATION);
{ // Logo
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_since_1998.png", 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_pal2.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_pal3.gif", AssetType::PALETTE);
{ // Items
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_points2_gavina.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_points2_gavina.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_points3_pacmar.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_points3_pacmar.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_clock.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_clock.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.ani", AssetType::ANIMATION);
}
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_pal2.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_pal3.gif", AssetType::PALETTE);
{ // Titulo
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_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_dust.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/title/title_dust.ani", AssetType::ANIMATION);
}
Asset::get()->add(prefix + "/data/gfx/player/player.ani", AssetType::ANIMATION);
{ // Jugador 1
Asset::get()->add(prefix + "/data/gfx/player/player1.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/player/player1_one_coffee_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_two_coffee_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_all_white_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player1_power.png", AssetType::BITMAP);
}
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);
{ // Jugador 2
Asset::get()->add(prefix + "/data/gfx/player/player2.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/player/player2_one_coffee_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_two_coffee_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_all_white_palette.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/gfx/player/player2_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_power.ani", AssetType::ANIMATION);
}
// 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/nokia.png", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/nokia_big2.png", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/nokia.png", AssetType::BITMAP);
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/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/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.gif", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/smb2_pal1.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/font/smb2.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/smb2_palette1.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/font/smb2.txt", AssetType::FONT);
// Textos
@@ -475,7 +499,9 @@ bool Director::setFileList()
Asset::get()->add(prefix + "/data/lang/en_UK.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
@@ -563,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
void Director::runLogo()
{
@@ -605,14 +599,14 @@ void Director::runLogo()
// Ejecuta la sección con la secuencia de introducción
void Director::runIntro()
{
auto intro = std::make_unique<Intro>(getMusic(musics_, "intro.ogg"));
auto intro = std::make_unique<Intro>();
intro->run();
}
// Ejecuta la sección con el título del juego
void Director::runTitle()
{
auto title = std::make_unique<Title>(getMusic(musics_, "title.ogg"));
auto title = std::make_unique<Title>();
title->run();
}
@@ -621,21 +615,21 @@ void Director::runGame()
{
const auto player_id = section::options == section::Options::GAME_PLAY_1P ? 1 : 2;
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();
}
// Ejecuta la sección donde se muestran las instrucciones
void Director::runInstructions()
{
auto instructions = std::make_unique<Instructions>(getMusic(musics_, "title.ogg"));
auto instructions = std::make_unique<Instructions>();
instructions->run();
}
// Ejecuta la sección donde se muestra la tabla de puntuaciones
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();
}
@@ -644,7 +638,7 @@ void Director::runDemoGame()
{
const auto player_id = (rand() % 2) + 1;
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();
}
@@ -692,8 +686,22 @@ int Director::run()
}
}
const int return_code = section::options == section::Options::QUIT_NORMAL ? 0 : 1;
return return_code;
#ifdef ARCADE
// Comprueba si ha de apagar el sistema
if (section::options == section::Options::QUIT_WITH_CONTROLLER)
shutdownSystem();
#endif
const auto return_code = (section::options == section::Options::QUIT_WITH_KEYBOARD) ? "with keyboard" : (section::options == section::Options::QUIT_WITH_CONTROLLER) ? "with controller"
: "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
@@ -718,4 +726,22 @@ std::string Director::getLangFile(lang::Code code)
}
return Asset::get()->get("en_UK.txt");
}
// Apaga el sistema
void Director::shutdownSystem()
{
#ifdef _WIN32
// Apaga el sistema en Windows
system("shutdown /s /t 0");
#elif __APPLE__
// Apaga el sistema en macOS
system("sudo shutdown -h now");
#elif __linux__
// Apaga el sistema en Linux
system("shutdown -h now");
#else
// Sistema operativo no compatible
#error "Sistema operativo no soportado"
#endif
}

View File

@@ -1,12 +1,15 @@
#pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_video.h> // for SDL_Window
#include <string> // for string
#include <vector> // for vector
namespace lang { enum class Code : int; }
struct MusicFile;
struct SoundFile;
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_video.h> // for SDL_Window
#include <string> // for string
#include <vector> // for vector
namespace lang
{
enum class Code : int;
}
struct ResourceMusic;
struct ResourceSound;
// Textos
constexpr char WINDOW_CAPTION[] = "Coffee Crisis Arcade Edition";
@@ -15,15 +18,14 @@ class Director
{
private:
// Objetos y punteros
SDL_Window *window_; // La ventana donde dibujamos
SDL_Renderer *renderer_; // El renderizador de la ventana
SDL_Window *window_; // La ventana donde dibujamos
SDL_Renderer *renderer_; // El renderizador de la ventana
std::streambuf *orig_buf; // Puntero al buffer de flujo original para restaurar std::cout
// Variables
std::string executable_path_; // Path del ejecutable
std::string system_folder_; // Carpeta del sistema donde guardar datos
std::string executable_path_; // Path del ejecutable
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::vector<SoundFile> sounds_; // Vector con los sonidos
std::vector<MusicFile> musics_; // Vector con las musicas
// Inicializa jail_audio
void initJailAudio();
@@ -31,20 +33,14 @@ private:
// Arranca SDL y crea la ventana
bool initSDL();
// Inicializa el objeto input
void initInput();
// Asigna los botones y teclas al objeto Input
void bindInputs();
// Carga los parametros para configurar el juego
void loadParams(const std::string &file_path);
// Crea el indice de ficheros
bool setFileList();
// Carga los sonidos del juego
void loadSounds();
// Carga las musicas del juego
void loadMusics();
void setFileList();
// Comprueba los parametros del programa
void checkProgramArguments(int argc, const char *argv[]);
@@ -76,6 +72,9 @@ private:
// Obtiene una fichero a partir de un lang::Code
std::string getLangFile(lang::Code code);
// Apaga el sistema
void shutdownSystem();
public:
// Constructor
Director(int argc, const char *argv[]);

View File

@@ -15,7 +15,7 @@ void EnterName::init()
// Inicia la lista de caracteres permitidos
character_list_ = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()";
pos_ = 0;
position_ = 0;
num_characters_ = (int)character_list_.size();
// Pone la lista de indices para que refleje el nombre
@@ -26,26 +26,27 @@ void EnterName::init()
}
// Incrementa la posición
void EnterName::incPos()
void EnterName::incPosition()
{
pos_++;
pos_ = std::min(pos_, NAME_LENGHT - 1);
position_++;
position_ = std::min(position_, NAME_LENGHT - 1);
checkIfPositionHasBeenUsed();
}
// Decrementa la posición
void EnterName::decPos()
void EnterName::decPosition()
{
pos_--;
pos_ = std::max(pos_, 0);
position_--;
position_ = std::max(position_, 0);
}
// Incrementa el índice
void EnterName::incIndex()
{
++character_index_[pos_];
if (character_index_[pos_] >= num_characters_)
++character_index_[position_];
if (character_index_[position_] >= num_characters_)
{
character_index_[pos_] = 0;
character_index_[position_] = 0;
}
updateName();
}
@@ -53,15 +54,15 @@ void EnterName::incIndex()
// Decrementa el índice
void EnterName::decIndex()
{
--character_index_[pos_];
if (character_index_[pos_] < 0)
--character_index_[position_];
if (character_index_[position_] < 0)
{
character_index_[pos_] = num_characters_ - 1;
character_index_[position_] = num_characters_ - 1;
}
updateName();
}
// Actualiza la variable
// Actualiza el nombre a partir de la lista de índices
void EnterName::updateName()
{
name_.clear();
@@ -74,16 +75,18 @@ void EnterName::updateName()
// Actualiza la variable
void EnterName::updateCharacterIndex()
{
// Rellena de espacios
// Rellena de espacios y marca como no usados
for (int i = 0; i < NAME_LENGHT; ++i)
{
character_index_[i] = 0;
position_has_been_used_[i] = false;
}
// Coloca los índices en funcion de los caracteres que forman el nombre
for (int i = 0; i < (int)name_.size(); ++i)
{
character_index_[i] = findIndex(name_.at(i));
position_has_been_used_[i] = true;
}
}
@@ -107,7 +110,21 @@ std::string EnterName::getName() const
}
// Obtiene la posición que se está editando
int EnterName::getPos() const
int EnterName::getPosition() const
{
return pos_;
return position_;
}
// Comprueba la posición y copia el caracter si es necesario
void EnterName::checkIfPositionHasBeenUsed()
{
auto used = position_has_been_used_[position_];
if (!used && position_ > 0)
{
character_index_[position_] = character_index_[position_ - 1];
}
position_has_been_used_[position_] = true;
updateName();
}

View File

@@ -16,13 +16,14 @@ constexpr int NAME_LENGHT = 8;
class EnterName
{
private:
std::string character_list_; // Lista de todos los caracteres permitidos
std::string name_; // Nombre introducido
int pos_; // Posición a editar del nombre
int num_characters_; // Cantidad de caracteres de la lista de caracteres
int character_index_[NAME_LENGHT]; // Indice de la lista para cada uno de los caracteres que forman el nombre
std::string character_list_; // Lista de todos los caracteres permitidos
std::string name_; // Nombre introducido
int position_; // Posición a editar del nombre
int num_characters_; // Cantidad de caracteres de la lista de caracteres
int character_index_[NAME_LENGHT]; // Indice de la lista para cada uno de los caracteres que forman el nombre
bool position_has_been_used_[NAME_LENGHT]; // Indica si en esa posición se ha puesto ya alguna letra. Se utiliza para replicar la letra anterior la primera vez
// Actualiza la variable
// Actualiza el nombre a partir de la lista de índices
void updateName();
// Actualiza la variable
@@ -31,6 +32,9 @@ private:
// Encuentra el indice de un caracter en "characterList"
int findIndex(char character);
// Comprueba la posición y copia el caracter si es necesario
void checkIfPositionHasBeenUsed();
public:
// Constructor
EnterName();
@@ -42,10 +46,10 @@ public:
void init();
// Incrementa la posición
void incPos();
void incPosition();
// Decrementa la posición
void decPos();
void decPosition();
// Incrementa el índice
void incIndex();
@@ -57,5 +61,5 @@ public:
std::string getName() const;
// Obtiene la posición que se está editando
int getPos() const;
int getPosition() const;
};

View File

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

View File

@@ -1,16 +1,20 @@
#pragma once
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string
#include <vector> // for vector
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string
#include <vector> // for vector
class AnimatedSprite;
class Texture;
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
@@ -41,7 +45,7 @@ public:
void render();
// 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
void add(int x, int y, int size);

View File

@@ -4,11 +4,12 @@
#include <stdlib.h> // for rand
#include <algorithm> // for min, max
#include "param.h" // for param
#include "screen.h"
#include "utils.h" // for Param, ParamGame, ParamFade
// Constructor
Fade::Fade(SDL_Renderer *renderer)
: renderer_(renderer)
Fade::Fade()
: renderer_(Screen::get()->getRenderer())
{
// Crea la textura donde dibujar el fade
backbuffer_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -24,6 +24,7 @@ class Texture;
enum class BulletType; // lines 26-26
struct JA_Music_t; // lines 27-27
struct JA_Sound_t; // lines 28-28
enum class ItemType;
// Modo demo
constexpr bool GAME_MODE_DEMO_OFF = false;
@@ -31,26 +32,6 @@ constexpr bool GAME_MODE_DEMO_ON = true;
// Cantidad de elementos a escribir en los ficheros de datos
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
@@ -82,6 +63,7 @@ constexpr int TIME_STOPPED_COUNTER = 300;
class Game
{
private:
// Estructuras
struct Helper
{
bool need_coffee; // Indica si se necesitan cafes
@@ -96,14 +78,25 @@ private:
int item_coffee_machine_odds; // Probabilidad de aparición del objeto
};
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
DemoKeys data_file[2][TOTAL_DEMO_DATA]; // Vector con diferentes sets de datos con los movimientos para la demo
};
// Constantes
// Contadores
static constexpr int STAGE_COUNTER_ = 200;
static constexpr int HELP_COUNTER_ = 1000;
static constexpr int GAME_COMPLETED_START_FADE_ = 500;
static constexpr int GAME_COMPLETED_END_ = 700;
static constexpr int GAME_OVER_COUNTER_ = 350;
static constexpr int TIME_STOPPED_COUNTER_ = 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
SDL_Renderer *renderer_; // El renderizador de la ventana
@@ -118,26 +111,24 @@ private:
SDL_Texture *canvas_; // Textura para dibujar la zona de juego
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
std::vector<std::shared_ptr<Balloon>> balloons_; // Vector con los globos
std::vector<std::unique_ptr<Bullet>> bullets_; // Vector con las balas
std::vector<std::unique_ptr<Item>> items_; // Vector con los items
std::vector<SmartSprite *> smart_sprites_; // Vector con los smartsprites
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
std::vector<std::shared_ptr<Balloon>> balloons_; // Vector con los globos
std::vector<std::unique_ptr<Bullet>> bullets_; // Vector con las balas
std::vector<std::unique_ptr<Item>> items_; // Vector con los items
std::vector<std::unique_ptr<SmartSprite>> smart_sprites_; // Vector con los smartsprites
std::shared_ptr<Texture> bullet_texture_; // Textura para las balas
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>> 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::shared_ptr<Texture> game_text_texture_; // Textura para los sprites con textos
std::vector<std::shared_ptr<Texture>> game_text_textures_; // Vector con las texturas para los sprites con textos
std::vector<std::vector<std::string> *> 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> *> 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>> 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>> 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::unique_ptr<Text> text_; // Fuente para los textos del juego
std::unique_ptr<Text> text_big_; // Fuente de texto grande
@@ -146,62 +137,39 @@ private:
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
std::shared_ptr<SmartSprite> p1000_sprite_; // Sprite con el texto 1.000
std::shared_ptr<SmartSprite> p2500_sprite_; // Sprite con el texto 2.500
std::shared_ptr<SmartSprite> p5000_sprite_; // Sprite con el texto 5.000
JA_Sound_t *balloon_sound_; // Sonido para la explosión del globo
JA_Sound_t *bullet_sound_; // Sonido para los disparos
JA_Sound_t *player_collision_sound_; // Sonido para la colisión del jugador con un enemigo
JA_Sound_t *hi_score_sound_; // Sonido para cuando se alcanza la máxima puntuación
JA_Sound_t *item_drop_sound_; // Sonido para cuando se genera un item
JA_Sound_t *item_pick_up_sound_; // Sonido para cuando se recoge un item
JA_Sound_t *coffee_out_sound_; // Sonido para cuando el jugador pierde el café al recibir un impacto
JA_Sound_t *stage_change_sound_; // Sonido para cuando se cambia de fase
JA_Sound_t *bubble1_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble2_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble3_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble4_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *clock_sound_; // Sonido para cuando se detiene el tiempo con el item reloj
JA_Sound_t *power_ball_sound_; // Sonido para cuando se explota una Power Ball
JA_Sound_t *coffee_machine_sound_; // Sonido para cuando la máquina de café toca el suelo
JA_Music_t *music_; // Musica de fondo
// Variables
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
HiScoreEntry hi_score_; // Máxima puntuación y nombre de quien la ostenta
int current_stage_; // Indica la fase actual
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 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 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
bool time_stopped_; // Indica si el tiempo está detenido
int time_stopped_counter_; // Temporizador para llevar la cuenta del tiempo detenido
int counter_; // Contador para el juego
int balloons_popped_; // Lleva la cuenta de los globos explotados
int last_ballon_deploy_; // Guarda cual ha sido la última formación desplegada para no repetir;
int balloon_deploy_counter_; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero
float balloon_speed_; // Velocidad a la que se mueven los enemigos
float default_balloon_speed_; // Velocidad base de los enemigos, sin incrementar
Helper helper_; // Variable para gestionar las ayudas
bool power_ball_enabled_; // Indica si hay una powerball ya activa
int power_ball_counter_; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
bool coffee_machine_enabled_; // Indica si hay una máquina de café en el terreno de juego
bool game_completed_; // Indica si se ha completado la partida, llegando al final de la ultima pantalla
int game_completed_counter_; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos
GameDifficulty difficulty_; // Dificultad del juego
float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
Color difficulty_color_; // Color asociado a la dificultad
int last_stage_reached_; // Contiene el número de la última pantalla que se ha alcanzado
Demo demo_; // Variable con todas las variables relacionadas con el modo demo
int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
bool paused_; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade)
int current_power_; // Poder actual almacenado para completar la fase
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
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
int current_stage_; // Indica la fase actual
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 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 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
bool time_stopped_; // Indica si el tiempo está detenido
int time_stopped_counter_; // Temporizador para llevar la cuenta del tiempo detenido
int counter_; // Contador para el juego
int balloons_popped_; // Lleva la cuenta de los globos explotados
int last_ballon_deploy_; // Guarda cual ha sido la última formación desplegada para no repetir;
int balloon_deploy_counter_; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero
float balloon_speed_; // Velocidad a la que se mueven los enemigos
float default_balloon_speed_; // Velocidad base de los enemigos, sin incrementar
Helper helper_; // Variable para gestionar las ayudas
bool power_ball_enabled_; // Indica si hay una powerball ya activa
int power_ball_counter_; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
bool coffee_machine_enabled_; // Indica si hay una máquina de café en el terreno de juego
bool game_completed_; // Indica si se ha completado la partida, llegando al final de la ultima pantalla
int game_completed_counter_; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos
GameDifficulty difficulty_; // Dificultad del juego
float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
Color difficulty_color_; // Color asociado a la dificultad
int last_stage_reached_; // Contiene el número de la última pantalla que se ha alcanzado
Demo demo_; // Variable con todas las variables relacionadas con el modo demo
int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
bool paused_; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade)
int current_power_; // Poder actual almacenado para completar la fase
#ifdef DEBUG
bool auto_pop_balloons_; // Si es true, incrementa automaticamente los globos explotados
#endif
@@ -224,12 +192,6 @@ private:
// Libera los recursos previamente cargados
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
void deployBalloonFormation();
@@ -315,28 +277,28 @@ private:
void renderItems();
// Devuelve un item en función del azar
int dropItem();
ItemType dropItem();
// Crea un objeto item
void createItem(int kind, float x, float y);
void createItem(ItemType type, float x, float y);
// Vacia el vector de items
void freeItems();
// Crea un objeto SmartSprite
void createItemScoreSprite(int x, int y, std::shared_ptr<SmartSprite> sprite);
// Crea un objeto SpriteSmart
void createItemScoreSprite(int x, int y, std::shared_ptr<Texture> texture);
// 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);
// Actualiza los SmartSprites
void updateSmartSprites();
// Actualiza los SpriteSmarts
void updateSpriteSmarts();
// Pinta los SmartSprites activos
void renderSmartSprites();
// Pinta los SpriteSmarts activos
void renderSpriteSmarts();
// Acciones a realizar cuando el jugador muere
void killPlayer(std::shared_ptr<Player> &player);
@@ -371,9 +333,6 @@ private:
// Actualiza el fondo
void updateBackground();
// Gestiona la entrada durante el juego
void checkInput();
// Pinta diferentes mensajes en la pantalla
void renderMessages();
@@ -407,9 +366,6 @@ private:
// Comprueba si todos los jugadores han terminado de jugar
bool allPlayersAreNotPlaying();
// Carga las animaciones
void loadAnimations(std::string file_path, std::vector<std::string> *buffer);
// Elimina todos los objetos contenidos en vectores
void deleteAllVectorObjects();
@@ -443,9 +399,40 @@ private:
// Obtiene un controlador a partir del "id" del jugador
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:
// Constructor
Game(int playerID, int current_stage, bool demo, JA_Music_t *music);
Game(int playerID, int current_stage, bool demo);
// Destructor
~Game();

View File

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

View File

@@ -1,8 +1,8 @@
#pragma once
#include <memory> // for unique_ptr, shared_ptr
class AnimatedSprite;
class SmartSprite;
#include "animated_sprite.h"
#include "smart_sprite.h"
class Sprite;
class Texture;
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"
JA_Sound_t *crash_sound_; // Sonido con el impacto del título
// Variables
int x_; // Posición donde dibujar el logo
int y_; // Posición donde dibujar el logo
@@ -63,7 +61,7 @@ public:
GameLogo(int x, int y);
// Destructor
~GameLogo();
~GameLogo() = default;
// Pinta la clase en pantalla
void render();

View File

@@ -3,6 +3,7 @@
#include "input.h" // for Input, inputs_e, INPUT_DO_NOT_ALLOW_REPEAT
#include "jail_audio.h" // for JA_EnableMusic, JA_EnableSound
#include "lang.h" // for getText
#include "notifier.h" // for Notifier
#include "options.h" // for options
#include "on_screen_help.h"
#include "screen.h" // for Screen
@@ -28,14 +29,21 @@ namespace globalInputs
// Termina
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::options = code;
}
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()
{
section::name = section::Name::INIT;
Screen::get()->showNotification("Reset");
Notifier::get()->showText("Reset");
}
// Activa o desactiva el audio
@@ -52,7 +60,7 @@ namespace globalInputs
options.audio.sound.enabled = options.audio.music.enabled = !options.audio.music.enabled;
JA_EnableMusic(options.audio.music.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
@@ -61,7 +69,7 @@ namespace globalInputs
// Comprueba si se sale con el teclado
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;
}
@@ -99,7 +107,7 @@ namespace globalInputs
// Comprueba si se sale con el mando
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;
}

View File

@@ -15,37 +15,29 @@
#include "lang.h" // for getText
#include "options.h" // for options
#include "param.h" // for param
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options
#include "text.h" // for Text, TEXT_CENTER, TEXT_SHADOW, TEXT...
#include "utils.h" // for Param, ParamGame, Color, HiScoreEntry
// Constructor
HiScoreTable::HiScoreTable(JA_Music_t *music)
: music_(music)
HiScoreTable::HiScoreTable()
: 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
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
// Inicializa el resto de variables
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
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
background_->setPos(param.game.game_area.rect);
background_->setCloudsSpeed(-0.1f);
background_->setGradientNumber(1);
@@ -70,7 +62,7 @@ HiScoreTable::~HiScoreTable()
void HiScoreTable::update()
{
// Actualiza las variables
if (SDL_GetTicks() - ticks_ > ticks_speed_)
if (SDL_GetTicks() - ticks_ > TICKS_SPEED_)
{
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks();
@@ -78,7 +70,7 @@ void HiScoreTable::update()
// Mantiene la música sonando
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
@@ -99,7 +91,7 @@ void HiScoreTable::update()
background_->setAlpha(96);
}
if (counter_ == counter_end_)
if (counter_ == COUNTER_END_)
{
fade_->activate();
}
@@ -188,6 +180,7 @@ void HiScoreTable::checkEvents()
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}

View File

@@ -9,7 +9,6 @@ class Background; // lines 8-8
class Fade; // lines 9-9
class Text; // lines 10-10
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
@@ -25,10 +24,13 @@ struct JA_Music_t; // lines 12-12
class HiScoreTable
{
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
SDL_Renderer *renderer_; // El renderizador de la ventana
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<Background> background_; // Objeto para dibujar el fondo del juego
@@ -36,9 +38,7 @@ private:
// Variables
Uint16 counter_; // Contador
Uint16 counter_end_; // Valor final para el contador
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
FadeMode fade_mode_; // Modo de fade a utilizar
@@ -68,7 +68,7 @@ private:
public:
// Constructor
explicit HiScoreTable(JA_Music_t *music);
HiScoreTable();
// Destructor
~HiScoreTable();

View File

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

View File

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

View File

@@ -1,16 +1,16 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Texture, SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for unique_ptr, shared_ptr
#include <vector> // for vector
#include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Texture, SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for unique_ptr, shared_ptr
#include <vector> // for vector
class Fade;
class Sprite;
class Text;
class Texture;
class Tiledbg;
struct JA_Music_t; // lines 14-14
class TiledBG;
struct JA_Music_t; // lines 14-14
/*
Esta clase gestiona un estado del programa. Se encarga de poner en pantalla
@@ -33,11 +33,10 @@ private:
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::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
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 *backbuffer_; // Textura para usar como backbuffer
@@ -79,7 +78,7 @@ private:
public:
// Constructor
explicit Instructions(JA_Music_t *music);
Instructions();
// Destructor
~Instructions();

View File

@@ -1,33 +1,30 @@
#include "intro.h"
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED
#include <utility> // for move
#include "asset.h" // for Asset
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_StopMusic, JA_PlayMusic
#include "lang.h" // for getText
#include "param.h" // for param
#include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options
#include "smart_sprite.h" // for SmartSprite
#include "text.h" // for Text
#include "texture.h" // for Texture
#include "utils.h" // for Param, ParamGame, Zone, BLOCK, Color
#include "writer.h" // for Writer
struct JA_Music_t; // lines 19-19
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED
#include <utility> // for move
#include "asset.h" // for Asset
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_StopMusic, JA_PlayMusic
#include "lang.h" // for getText
#include "param.h" // for param
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options
#include "smart_sprite.h" // for SpriteSmart
#include "text.h" // for Text
#include "texture.h" // for Texture
#include "utils.h" // for Param, ParamGame, Zone, BLOCK, Color
#include "writer.h" // for Writer
struct JA_Music_t; // lines 19-19
// Constructor
Intro::Intro(JA_Music_t *music)
: music_(music)
Intro::Intro()
{
// Copia los punteros
auto renderer = Screen::get()->getRenderer();
// Reserva memoria para los objetos
texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("intro.png"));
text_ = std::make_shared<Text>(Asset::get()->get("nokia.png"), Asset::get()->get("nokia.txt"), renderer);
texture_ = Resource::get()->getTexture("intro.png");
text_ = std::make_shared<Text>(Resource::get()->getTexture("nokia.png"), Resource::get()->getTextFile("nokia.txt"));
// Inicializa variables
section::name = section::Name::INTRO;
@@ -173,6 +170,7 @@ void Intro::checkEvents()
case SDL_QUIT:
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
@@ -425,7 +423,7 @@ void Intro::render()
// Bucle principal
void Intro::run()
{
JA_PlayMusic(music_, 0);
JA_PlayMusic(Resource::get()->getMusic("intro.ogg"), 0);
while (section::name == section::Name::INTRO)
{

View File

@@ -1,13 +1,13 @@
#pragma once
#include <SDL2/SDL_stdinc.h> // for Uint32, Uint8
#include <memory> // for unique_ptr, shared_ptr
#include <vector> // for vector
#include "smart_sprite.h" // for SmartSprite
#include "writer.h" // for Writer
#include <SDL2/SDL_stdinc.h> // for Uint32, Uint8
#include <memory> // for unique_ptr, shared_ptr
#include <vector> // for vector
#include "smart_sprite.h" // for SpriteSmart
#include "writer.h" // for Writer
class Text;
class Texture;
struct JA_Music_t; // lines 11-11
struct JA_Music_t; // lines 11-11
/*
Esta clase gestiona un estado del programa. Se encarga de mostrar la secuencia
@@ -28,7 +28,6 @@ private:
// Variables
Uint32 ticks_; // Contador de ticks para ajustar la velocidad 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
// Actualiza las variables del objeto
@@ -51,7 +50,7 @@ private:
public:
// Constructor
explicit Intro(JA_Music_t *music);
Intro();
// Destructor
~Intro() = default;

View File

@@ -1,20 +1,20 @@
#include "item.h"
#include <stdlib.h> // for rand
#include "animated_sprite.h" // for AnimatedSprite
#include "animated_sprite.h" // for SpriteAnimated
#include "param.h" // for param
class Texture;
// Constructor
Item::Item(int kind, float x, float y, SDL_Rect *play_area, std::shared_ptr<Texture> texture, std::vector<std::string> *animation)
: sprite_(std::make_unique<AnimatedSprite>(texture, "", animation)),
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)),
accel_x_(0.0f),
floor_collision_(false),
kind_(kind),
type_(type),
enabled_(true),
play_area_(play_area),
time_to_live_(600)
{
if (kind == ITEM_COFFEE_MACHINE)
if (type == ItemType::COFFEE_MACHINE)
{
width_ = 28;
height_ = 37;
@@ -104,7 +104,7 @@ void Item::move()
}
// Si se sale por arriba rebota (excepto la maquina de café)
if ((pos_y_ < param.game.play_area.rect.y) && !(kind_ == ITEM_COFFEE_MACHINE))
if ((pos_y_ < param.game.play_area.rect.y) && !(type_ == ItemType::COFFEE_MACHINE))
{
// Corrige
pos_y_ = param.game.play_area.rect.y;
@@ -122,7 +122,7 @@ void Item::move()
accel_x_ = 0;
accel_y_ = 0;
pos_y_ = play_area_->h - height_;
if (kind_ == ITEM_COFFEE_MACHINE)
if (type_ == ItemType::COFFEE_MACHINE)
{
floor_collision_ = true;
}
@@ -144,7 +144,7 @@ void Item::disable()
void Item::update()
{
move();
sprite_->animate();
sprite_->update();
updateTimeToLive();
checkTimeToLive();
}
@@ -190,9 +190,9 @@ int Item::getHeight()
}
// Obtiene del valor de la variable
int Item::getClass()
ItemType Item::getType()
{
return kind_;
return type_;
}
// Obtiene el valor de la variable

View File

@@ -1,22 +1,25 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint16
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string
#include <vector> // for vector
#include "animated_sprite.h" // for AnimatedSprite
#include "utils.h" // for Circle
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint16
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string
#include <vector> // for vector
#include "animated_sprite.h" // for SpriteAnimated
#include "utils.h" // for Circle
class Texture;
// Tipos de objetos
constexpr int ITEM_POINTS_1_DISK = 1;
constexpr int ITEM_POINTS_2_GAVINA = 2;
constexpr int ITEM_POINTS_3_PACMAR = 3;
constexpr int ITEM_CLOCK = 4;
constexpr int ITEM_COFFEE = 5;
constexpr int ITEM_COFFEE_MACHINE = 6;
constexpr int ITEM_NULL = 7;
enum class ItemType : int
{
DISK = 1,
GAVINA = 2,
PACMAR = 3,
CLOCK = 4,
COFFEE = 5,
COFFEE_MACHINE = 6,
NONE = 7,
};
// Clase Item
class Item
@@ -35,7 +38,7 @@ private:
float accel_x_; // Aceleración en el eje X
float accel_y_; // Aceleración en el eje Y
bool floor_collision_; // Indica si el objeto colisiona con el suelo
int kind_; // Especifica el tipo de objeto que es
ItemType type_; // Especifica el tipo de objeto que es
bool enabled_; // Especifica si el objeto está habilitado
Circle collider_; // Circulo de colisión del objeto
SDL_Rect *play_area_; // Rectangulo con la zona de juego
@@ -55,7 +58,7 @@ private:
public:
// Constructor
Item(int kind, 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
~Item() = default;
@@ -85,7 +88,7 @@ public:
int getHeight();
// Obtiene del valor de la variable
int getClass();
ItemType getType();
// Obtiene el valor de la variable
bool isEnabled();

View File

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

View File

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

View File

@@ -1,29 +1,26 @@
#include "logo.h"
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED
#include <utility> // for move
#include "asset.h" // for Asset
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_StopMusic
#include "param.h" // for param
#include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED
#include <utility> // for move
#include "asset.h" // for Asset
#include "global_inputs.h" // for check
#include "input.h" // for Input
#include "jail_audio.h" // for JA_StopMusic
#include "param.h" // for param
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "section.h" // for Name, name, Options, options
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
// Constructor
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
counter_ = 0;
@@ -31,18 +28,19 @@ Logo::Logo()
ticks_ = 0;
dest_.x = param.game.game_area.center_x - jail_texture_->getWidth() / 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_texture_->setColor(0x00, 0x00, 0x00); // Esto en linux no hace nada ??
// Crea los sprites de cada linea
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);
const int posX = (i % 2 == 0) ? param.game.width + (i * 3) : -jail_texture_->getWidth() - (i * 3);
temp->setPosX(posX);
temp->setPosY(dest_.y + i);
temp->setX(posX);
temp->setY(dest_.y + i);
jail_sprite_.push_back(std::move(temp));
}
@@ -75,6 +73,7 @@ void Logo::checkEvents()
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
@@ -115,22 +114,22 @@ void Logo::updateJAILGAMES()
{
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)
{
jail_sprite_[i]->incPosX(-SPEED);
if (jail_sprite_[i]->getIntPosX() < dest_.x)
jail_sprite_[i]->incX(-SPEED);
if (jail_sprite_[i]->getX() < dest_.x)
{
jail_sprite_[i]->setPosX(dest_.x);
jail_sprite_[i]->setX(dest_.x);
}
}
else
{
jail_sprite_[i]->incPosX(SPEED);
if (jail_sprite_[i]->getIntPosX() > dest_.x)
jail_sprite_[i]->incX(SPEED);
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[])
{
std::cout << "Game start" << std::endl;
// Crea el objeto Director
auto director = std::make_unique<Director>(argc, const_cast<const char **>(argv));
// Bucle principal
const auto exit = director->run();
const auto endType = exit == 0 ? "keyboard" : "controller";
std::cout << "\nGame end with " << endType << std::endl;
return exit;
return director->run();
}

View File

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

View File

@@ -2,34 +2,44 @@
#include "texture.h" // for Texture
// Constructor
MovingSprite::MovingSprite(float x, float y, int w, int h, float vx, float vy, float ax, float ay, std::shared_ptr<Texture> texture)
: Sprite((int)x, (int)y, w, h, texture),
x_(x),
y_(y),
vx_(vx),
vy_(vy),
ax_(ax),
ay_(ay),
zoom_w_(1),
zoom_h_(1),
counter_(0),
flip_(SDL_FLIP_NONE)
{
// Establece los valores de rotacion
rotate_.enabled = false;
rotate_.speed = 0;
rotate_.angle = 0.0f;
rotate_.amount = 0.0f;
rotate_.center = nullptr;
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture, SDL_Rect pos, Rotate rotate, float zoom_w, float zoom_h, SDL_RendererFlip flip)
: 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_(zoom_w),
zoom_h_(zoom_h),
flip_(flip) {}
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)
: Sprite(texture)
{
clear();
};
: Sprite(texture),
x_(0.0f),
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
void MovingSprite::clear()
@@ -43,21 +53,14 @@ void MovingSprite::clear()
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
rotate_ = Rotate(); // Inicializa la estructura
zoom_w_ = 1.0f; // Zoom aplicado a la anchura
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
setPos((SDL_Rect){0, 0, 0, 0});
setSpriteClip((SDL_Rect){0, 0, 0, 0});
Sprite::clear();
}
// Mueve el sprite
@@ -68,12 +71,140 @@ void MovingSprite::move()
vx_ += ax_;
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
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
@@ -112,29 +243,11 @@ float MovingSprite::getAccelY() const
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
void MovingSprite::setPos(SDL_Rect rect)
{
x_ = (float)rect.x;
y_ = (float)rect.y;
x_ = static_cast<float>(rect.x);
y_ = static_cast<float>(rect.y);
pos_ = rect;
}
@@ -145,22 +258,22 @@ void MovingSprite::setPos(float x, float y)
x_ = x;
y_ = y;
pos_.x = (int)x;
pos_.y = (int)y;
pos_.x = static_cast<int>(x_);
pos_.y = static_cast<int>(y_);
}
// Establece el valor de la variable
void MovingSprite::setPosX(float value)
{
x_ = value;
pos_.x = (int)x_;
pos_.x = static_cast<int>(x_);
}
// Establece el valor de la variable
void MovingSprite::setPosY(float value)
{
y_ = value;
pos_.y = (int)y_;
pos_.y = static_cast<int>(y_);
}
// Establece el valor de la variable
@@ -185,121 +298,4 @@ void MovingSprite::setAccelX(float value)
void MovingSprite::setAccelY(float 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

@@ -1,25 +1,29 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point
#include <SDL2/SDL_render.h> // for SDL_RendererFlip
#include <SDL2/SDL_stdinc.h> // for Uint16
#include <memory> // for shared_ptr
#include "sprite.h" // for Sprite
#include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point
#include <SDL2/SDL_render.h> // for SDL_RendererFlip
#include <SDL2/SDL_stdinc.h> // for Uint16
#include <memory> // for shared_ptr
#include "sprite.h" // for Sprite
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
{
protected:
public:
struct Rotate
{
bool enabled; // Indica si ha de rotar
int counter; // Contador
int speed; // Velocidad de giro
float angle; // Angulo para dibujarlo
float amount; // Cantidad de grados a girar en cada iteración
double angle; // Angulo para dibujarlo
float amount; // Cantidad de grados a girar en cada iteración
SDL_Point *center; // Centro de rotación
Rotate() : enabled(false), counter(0), speed(0), angle(0.0), amount(0.0f), center(nullptr) {}
};
protected:
float x_; // Posición en el eje X
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 ay_; // Aceleración en el eje Y. Variación de la velocidad
float zoom_w_; // Zoom aplicado a la anchura
float zoom_h_; // Zoom aplicado a la altura
int counter_; // Contador interno
Rotate rotate_; // Variables usada para controlar la rotación del sprite
float zoom_w_; // Zoom aplicado a la anchura
float zoom_h_; // Zoom aplicado a la altura
SDL_RendererFlip flip_; // Indica como se voltea el sprite
public:
// Constructor
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;
// Incrementa el valor del ángulo
void updateAngle();
// Mueve el sprite
void move();
@@ -50,54 +47,46 @@ public:
// Rota el sprite
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
virtual void update();
// Reinicia todas las variables
void clear();
// Reinicia todas las variables a cero
void clear() override;
// Muestra el sprite por pantalla
void render() override;
// Obten el valor de la variable
// Obtiene la variable
float getPosX() const;
float getPosY() const;
// Obten el valor de la variable
float getVelX() const;
float getVelY() const;
// Obten el valor de la variable
float getAccelX() 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
float getZoomW() const;
float getZoomH() const;
// Obten el valor de la variable
float getAngle() const;
bool getRotate() const;
Uint16 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);
bool isRotating() const;
double getAngle() const;
int getRotateSpeed() const;
// Establece el valor de la variable
void setZoomW(float value);
@@ -105,17 +94,15 @@ public:
// Establece el valor de la variable
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
void setRotate(bool value);
void setRotateSpeed(int 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
void switchRotate();
@@ -128,5 +115,15 @@ public:
// Obtiene el valor de la variable
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

@@ -1,15 +1,16 @@
#include "on_screen_help.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <memory> // for make_unique, make_shared, unique_ptr
#include "asset.h" // for Asset
#include "lang.h" // for getText
#include "param.h" // for param
#include "screen.h" // for Screen
#include "sprite.h" // for Sprite
#include "text.h" // for Text
#include "texture.h" // for Texture
#include "utils.h" // for easeInOutSine, Param, ParamGame
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <memory> // for make_unique, make_shared, unique_ptr
#include "asset.h" // for Asset
#include "lang.h" // for getText
#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
#include "utils.h" // for easeInOutSine, Param, ParamGame
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
OnScreenHelp *OnScreenHelp::onScreenHelp = nullptr;
@@ -95,13 +96,13 @@ void OnScreenHelp::fillTexture()
SDL_SetRenderTarget(Screen::get()->getRenderer(), texture);
// 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
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
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
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
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;
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)
{
sprite->setSpriteClip(buttonClip);
sprite->setPos(buttonPos);
sprite->setPosition(buttonPos);
sprite->render();
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;
// Variables para manejar el fichero
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
std::ifstream file(file_path);
// Si el fichero se puede abrir
if (file.good())
{
// Procesa el fichero linea a linea
#ifdef VERBOSE
std::cout << "Reading file: " << file_name << std::endl;
#endif
std::string line;
while (std::getline(file, line))
{
@@ -109,10 +105,8 @@ bool loadOptionsFile(std::string file_path)
// Procesa las dos subcadenas
if (!setOptions(line.substr(0, pos), line.substr(pos + 1, line.length())))
{
#ifdef VERBOSE
std::cout << "Warning: file " << file_name << std::endl;
std::cout << "Unknown parameter " << line.substr(0, pos).c_str() << std::endl;
#endif
success = false;
}
}
@@ -152,22 +146,16 @@ bool loadOptionsFile(std::string file_path)
// Guarda el fichero de configuración
bool saveOptionsFile(std::string file_path)
{
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
std::ofstream file(file_path);
if (!file.good())
{
#ifdef VERBOSE
std::cout << file_name << " can't be opened" << std::endl;
#endif
return false;
}
#ifdef VERBOSE
std::cout << "Writing file: " << file_name << std::endl;
#endif
// Opciones de video
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;
}
// 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)
{
// Inicializa los parámetros con valores por defecto
@@ -177,16 +74,12 @@ void loadParamsFromFile(const std::string &file_path)
std::ifstream file(file_path);
if (!file.is_open())
{
#ifdef VERBOSE
std::cerr << "Error: No se pudo abrir el archivo " << file_path << std::endl;
#endif
throw std::runtime_error("No se pudo abrir el archivo: " + file_path);
}
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
std::cout << "Reading file: " << file_name << std::endl;
#endif
std::string line, param1, param2;
while (std::getline(file, line))
@@ -255,6 +148,11 @@ bool setParams(const std::string &var, const std::string &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
else if (var == "fade.num_squares_width")
{

View File

@@ -3,7 +3,7 @@
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <stdlib.h> // for rand
#include <algorithm> // for max, min
#include "animated_sprite.h" // for AnimatedSprite
#include "animated_sprite.h" // for SpriteAnimated
#include "input.h" // for inputs_e
#include "param.h" // for param
#include "texture.h" // for Texture
@@ -11,9 +11,9 @@
#include "options.h"
// 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_sprite_(std::make_unique<AnimatedSprite>(texture[0], "", animations[0])),
power_sprite_(std::make_unique<AnimatedSprite>(texture[1], "", animations[1])),
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])),
power_sprite_(std::make_unique<AnimatedSprite>(texture[1], animations[1])),
enter_name_(std::make_unique<EnterName>()),
play_area_(play_area),
id_(id),
@@ -55,7 +55,9 @@ void Player::init()
coffees_ = 0;
input_ = true;
continue_ticks_ = 0;
continue_counter_ = 20;
continue_counter_ = 10;
enter_name_ticks_ = 0;
enter_name_counter_ = param.game.enter_name_seconds;
width_ = 30;
height_ = 30;
collider_.r = 9;
@@ -68,6 +70,7 @@ void Player::init()
cooldown_ = 10;
// Establece la posición del sprite
player_sprite_->clear();
player_sprite_->setPosX(pos_x_);
player_sprite_->setPosY(pos_y_);
@@ -149,11 +152,11 @@ void Player::setInputEnteringName(InputType input)
switch (input)
{
case InputType::LEFT:
enter_name_->decPos();
enter_name_->decPosition();
break;
case InputType::RIGHT:
enter_name_->incPos();
enter_name_->incPosition();
break;
case InputType::UP:
@@ -277,10 +280,10 @@ void Player::setAnimation()
}
// Actualiza las animaciones de los sprites
player_sprite_->animate();
player_sprite_->update();
// powerSprite->setFlip(flip_walk);
power_sprite_->animate();
power_sprite_->update();
}
// Obtiene el valor de la variable
@@ -344,9 +347,10 @@ void Player::update()
setAnimation();
shiftColliders();
updateCooldown();
updatePowerUpCounter();
updatePowerUp();
updateInvulnerable();
updateContinueCounter();
updateEnterNameCounter();
updateScoreboard();
}
@@ -574,7 +578,7 @@ void Player::updateInvulnerable()
{
if (invulnerable_counter_ > 0)
{
invulnerable_counter_--;
--invulnerable_counter_;
invulnerable_counter_ % 8 > 3 ? player_sprite_->getTexture()->setPalette(coffees_) : player_sprite_->getTexture()->setPalette(3);
}
else
@@ -611,15 +615,12 @@ void Player::setPowerUpCounter(int value)
}
// 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_--;
}
else
{
power_up_ = false;
--power_up_counter_;
power_up_ = power_up_counter_ > 0;
}
}
@@ -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
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
void Player::setName(const std::string &name)
{
@@ -763,7 +790,7 @@ int Player::getRecordNamePos() const
{
if (enter_name_)
{
return enter_name_->getPos();
return enter_name_->getPosition();
}
return 0;

View File

@@ -1,16 +1,17 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for unique_ptr, shared_ptr
#include <string> // for string
#include <vector> // for vector
#include "animated_sprite.h" // for AnimatedSprite
#include "enter_name.h" // for EnterName
#include "utils.h" // for Circle
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for unique_ptr, shared_ptr
#include <string> // for string
#include <vector> // for vector
#include "animated_sprite.h" // for SpriteAnimated
#include "smart_sprite.h" // for SpriteAnimated
#include "enter_name.h" // for EnterName
#include "utils.h" // for Circle
class Texture;
enum class InputType : int;
enum class ScoreboardMode; // lines 12-12
enum class ScoreboardMode; // lines 12-12
// Estados del jugador
enum class PlayerStatus
@@ -48,7 +49,7 @@ private:
SDL_Rect *play_area_; // Rectangulo con la zona de juego
// 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
int pos_y_; // Posicion en el eje Y
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
int scoreboard_panel_; // Panel del marcador asociado al 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
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
void shiftColliders();
@@ -90,6 +93,12 @@ private:
// Actualiza el contador de continue
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
bool isRenderable() const;
@@ -104,7 +113,7 @@ private:
public:
// 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
~Player() = default;
@@ -236,7 +245,7 @@ public:
void setPowerUpCounter(int value);
// Actualiza el valor de la variable
void updatePowerUpCounter();
void updatePowerUp();
// Obtiene el valor de la variable
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

@@ -5,8 +5,10 @@
#include <math.h> // for roundf
#include <iomanip>
#include <sstream>
#include "asset.h" // for Asset
#include "lang.h" // for getText
#include "asset.h" // for Asset
#include "lang.h" // for getText
#include "resource.h" // for Resource
#include "screen.h"
#include "sprite.h" // for Sprite
#include "text.h" // for Text
#include "texture.h" // for Texture
@@ -15,9 +17,9 @@
Scoreboard *Scoreboard::scoreboard_ = nullptr;
// [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
@@ -33,13 +35,13 @@ Scoreboard *Scoreboard::get()
}
// Constructor
Scoreboard::Scoreboard(SDL_Renderer *renderer)
: renderer_(renderer),
game_power_meter_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_power_meter.png"))),
Scoreboard::Scoreboard()
: renderer_(Screen::get()->getRenderer()),
game_power_meter_texture_(Resource::get()->getTexture("game_power_meter.png")),
power_meter_sprite_(std::make_unique<Sprite>(game_power_meter_texture_)),
text_scoreboard_(std::make_unique<Text>(Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), renderer)),
text_scoreboard_(std::make_unique<Text>(Resource::get()->getTexture("8bithud.png"), Resource::get()->getTextFile("8bithud.txt"))),
stage_(1),
hi_score_(0),
power_(0),
@@ -66,7 +68,7 @@ Scoreboard::Scoreboard(SDL_Renderer *renderer)
// Recalcula las anclas de los elementos
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
background_ = nullptr;
@@ -106,7 +108,7 @@ std::string Scoreboard::updateScoreText(int num)
// Actualiza el contador
void Scoreboard::updateCounter()
{
if (SDL_GetTicks() - ticks_ > SCOREBOARD_TICK_SPEED)
if (SDL_GetTicks() - ticks_ > SCOREBOARD_TICK_SPEED_)
{
ticks_ = SDL_GetTicks();
counter_++;
@@ -418,8 +420,8 @@ void Scoreboard::recalculateAnchors()
// Recoloca los sprites
if (power_meter_sprite_)
{
power_meter_sprite_->setPosX(slot4_2_.x - 20);
power_meter_sprite_->setPosY(slot4_2_.y);
power_meter_sprite_->setX(slot4_2_.x - 20);
power_meter_sprite_->setY(slot4_2_.y);
}
}

View File

@@ -1,12 +1,12 @@
#pragma once
#include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for unique_ptr, shared_ptr
#include <string> // for string
#include <vector> // for vector
#include "utils.h" // for Color
#include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for unique_ptr, shared_ptr
#include <string> // for string
#include <vector> // for vector
#include "utils.h" // for Color
class Sprite;
class Text;
class Texture;
@@ -16,7 +16,6 @@ constexpr int SCOREBOARD_LEFT_PANEL = 0;
constexpr int SCOREBOARD_CENTER_PANEL = 1;
constexpr int SCOREBOARD_RIGHT_PANEL = 2;
constexpr int SCOREBOARD_MAX_PANELS = 3;
constexpr int SCOREBOARD_TICK_SPEED = 100;
// Enums
enum class ScoreboardMode : int
@@ -42,6 +41,9 @@ struct Panel
class Scoreboard
{
private:
// Constantes
static constexpr int SCOREBOARD_TICK_SPEED_ = 100;
// [SINGLETON] Objeto scoreboard privado para Don Melitón
static Scoreboard *scoreboard_;
@@ -103,14 +105,14 @@ private:
// [SINGLETON] Ahora el constructor y el destructor son privados
// Constructor
explicit Scoreboard(SDL_Renderer *renderer);
Scoreboard();
// Destructor
~Scoreboard();
public:
// [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
static void destroy();

View File

@@ -12,7 +12,7 @@
#include "dbgtxt.h" // for dbg_print
#include "global_inputs.h" // for servicePressedCounter
#include "input.h" // for Input, inputs_e, INPUT_DO_NOT_ALLOW_REPEAT
#include "notify.h" // for Notify
#include "notifier.h" // for Notify
#include "on_screen_help.h" // for OnScreenHelp
#include "options.h" // for options
#include "param.h" // for param
@@ -47,7 +47,6 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer)
: window_(window),
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)),
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();
// Muestra las notificaciones
notify_->render();
Notifier::get()->render();
#ifdef NO_SHADERS
// Vuelve a dejar el renderizador en modo normal
@@ -200,8 +199,9 @@ void Screen::setVideoMode(ScreenVideoMode videoMode)
SDL_ShowCursor(SDL_ENABLE);
#endif
// Modifica el tamaño de la ventana
SDL_Point pos = getNewPosition();
SDL_SetWindowSize(window_, param.game.width * options.video.window.size, param.game.height * options.video.window.size);
SDL_SetWindowPosition(window_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_SetWindowPosition(window_, pos.x, pos.y);
break;
}
@@ -280,7 +280,7 @@ void Screen::setBlendMode(SDL_BlendMode blendMode)
void Screen::update()
{
updateShakeEffect();
notify_->update();
Notifier::get()->update();
updateFPS();
OnScreenHelp::get()->update();
}
@@ -294,7 +294,7 @@ void Screen::checkInput()
{
switchVideoMode();
const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen";
showNotification(mode + " mode");
Notifier::get()->showText(mode + " mode");
return;
}
@@ -303,7 +303,7 @@ void Screen::checkInput()
{
decWindowSize();
const std::string size = std::to_string(options.video.window.size);
showNotification("Window size x" + size);
Notifier::get()->showText("Window size x" + size);
return;
}
@@ -312,7 +312,7 @@ void Screen::checkInput()
{
incWindowSize();
const std::string size = std::to_string(options.video.window.size);
showNotification("Window size x" + size);
Notifier::get()->showText("Window size x" + size);
return;
}
#endif
@@ -442,7 +442,7 @@ void Screen::switchShaders()
options.video.shaders = !options.video.shaders;
setVideoMode(options.video.mode);
const std::string value = options.video.shaders ? "on" : "off";
showNotification("Shaders " + value);
Notifier::get()->showText("Shaders " + value);
}
// Atenua la pantalla
@@ -451,12 +451,6 @@ void Screen::attenuate(bool 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
SDL_Renderer *Screen::getRenderer()
{
@@ -490,8 +484,38 @@ void Screen::displayInfo()
}
}
// Indica si hay alguna notificación activa en pantalla
bool Screen::notificationsAreActive() const
// Calcula la nueva posición de la ventana a partir de la antigua al cambiarla de tamaño
SDL_Point Screen::getNewPosition()
{
return notify_->active();
// Obtiene la posición actual de la ventana
SDL_Point current_position;
SDL_GetWindowPosition(window_, &current_position.x, &current_position.y);
// Obtiene las dimensiones actuales de la ventana
int current_width, current_height;
SDL_GetWindowSize(window_, &current_width, &current_height);
// Obtiene las dimesiones que tendrá la ventana
const int new_width = param.game.width * options.video.window.size;
const int new_height = param.game.height * options.video.window.size;
// Obtiene el centro de la ventana actual
SDL_Point center;
center.x = current_position.x + current_width / 2;
center.y = current_position.y + current_height / 2;
// Calcula la nueva posición a partir del centro y las nuevas diemsiones
SDL_Point new_pos;
new_pos.x = center.x - new_width / 2;
new_pos.y = center.y - new_height / 2;
// Obtiene las dimensiones del escritorio
SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode(0, &DM);
// Evita que la ventana quede fuera del escritorio
new_pos.x = std::clamp(new_pos.x, 30, DM.w - new_width);
new_pos.y = std::clamp(new_pos.y, 30, DM.h - new_height);
return new_pos;
}

View File

@@ -8,7 +8,6 @@
#include <string> // for basic_string, string
#include "utils.h" // for Color
#include <memory>
class Notify;
enum class ScreenFilter : int
{
@@ -29,11 +28,10 @@ private:
static Screen *screen_;
// Objetos y punteros
SDL_Window *window_; // Ventana de la aplicación
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 *shader_canvas_; // Textura para pasarle al shader desde gameCanvas
SDL_Window *window_; // Ventana de la aplicación
SDL_Renderer *renderer_; // El renderizador de la ventana
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
// Variables
SDL_Rect src_rect_; // Coordenadas de donde va a pillar la textura del juego para dibujarla
@@ -85,6 +83,9 @@ private:
// Muestra información por pantalla
void displayInfo();
// Calcula la nueva posición de la ventana a partir de la antigua al cambiarla de tamaño
SDL_Point getNewPosition();
// [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos screen desde fuera
// Constructor
@@ -151,12 +152,6 @@ public:
// Atenua la pantalla
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
SDL_Renderer *getRenderer();
};

View File

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

View File

@@ -1,5 +1,4 @@
#include "smart_sprite.h"
#include "moving_sprite.h" // for MovingSprite
class Texture;
// Constructor
@@ -14,8 +13,7 @@ void SmartSprite::init()
{
finished_counter_ = 0;
on_destination_ = false;
dest_x_ = 0;
dest_y_ = 0;
dest_x_ = dest_y_ = 0;
finished_ = false;
enabled_ = false;
}
@@ -127,7 +125,7 @@ void SmartSprite::checkMove()
void SmartSprite::checkFinished()
{
// Comprueba si ha llegado a su destino
on_destination_ = (getPosX() == dest_x_ && getPosY() == dest_y_) ? true : false;
on_destination_ = (getPosX() == dest_x_ && getPosY() == dest_y_);
if (on_destination_)
{

View File

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

View File

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

View File

@@ -1,30 +1,29 @@
#include "text.h"
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <fstream> // for basic_ostream, basic_ifstream, basic_istream
#include <iostream> // for cout
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include "utils.h" // for Color
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <fstream> // for basic_ostream, basic_ifstream, basic_istream
#include <iostream> // for cout
#include "resource.h" // for Resource
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include "utils.h" // for Color
// 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
for (int i = 0; i < 128; ++i)
{
tf.offset[i].x = 0;
tf.offset[i].y = 0;
tf.offset[i].w = 0;
tf.box_width = 0;
tf.box_height = 0;
tf->offset[i].x = 0;
tf->offset[i].y = 0;
tf->offset[i].w = 0;
tf->box_width = 0;
tf->box_height = 0;
}
// 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();
#endif
std::ifstream file(file_path);
if (file.is_open() && file.good())
@@ -34,11 +33,11 @@ TextFile LoadTextFile(std::string file_path)
// Lee los dos primeros valores del fichero
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);
tf.box_height = std::stoi(buffer);
tf->box_height = std::stoi(buffer);
// lee el resto de datos del fichero
auto index = 32;
@@ -48,7 +47,7 @@ TextFile LoadTextFile(std::string file_path)
// Almacena solo las lineas impares
if (line_read % 2 == 1)
{
tf.offset[index++].w = std::stoi(buffer);
tf->offset[index++].w = std::stoi(buffer);
}
// Limpia el buffer
@@ -56,80 +55,53 @@ TextFile LoadTextFile(std::string file_path)
line_read++;
};
// Cierra el fichero
#ifdef VERBOSE
std::cout << "Text loaded: " << file_name << std::endl;
#endif
// Cierra el fichero
printWithDots("Text File : ", file_name, "[ LOADED ]");
file.close();
}
// El fichero no se puede abrir
else
{
#ifdef VERBOSE
std::cout << "Warning: Unable to open " << file_name << " file" << std::endl;
#endif
std::cerr << "Error: Fichero no encontrado " << file_path << std::endl;
throw std::runtime_error("Fichero no encontrado: " + file_path);
}
// Establece las coordenadas para cada caracter ascii de la cadena y su ancho
for (int i = 32; i < 128; ++i)
{
tf.offset[i].x = ((i - 32) % 15) * tf.box_width;
tf.offset[i].y = ((i - 32) / 15) * tf.box_height;
tf->offset[i].x = ((i - 32) % 15) * tf->box_width;
tf->offset[i].y = ((i - 32) / 15) * tf->box_height;
}
return tf;
}
// 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
auto tf = LoadTextFile(text_file);
auto tf = loadTextFile(text_file);
// Inicializa variables desde la estructura
box_height_ = tf.box_height;
box_width_ = tf.box_width;
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;
offset_[i].x = tf->offset[i].x;
offset_[i].y = tf->offset[i].y;
offset_[i].w = tf->offset[i].w;
}
// Crea los objetos
texture_ = std::make_shared<Texture>(renderer, bitmap_file);
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
fixed_width_ = false;
}
// Constructor
Text::Text(const std::string &text_file, std::shared_ptr<Texture> texture)
{
// 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)
Text::Text(std::shared_ptr<Texture> texture, std::shared_ptr<TextFile> text_file)
{
// Inicializa variables desde la estructura
box_height_ = text_file->box_height;
@@ -142,7 +114,7 @@ Text::Text(TextFile *text_file, std::shared_ptr<Texture> texture)
}
// 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
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();
}
sprite_->setPosY(y);
sprite_->setY(y);
const auto width = sprite_->getWidth();
const auto height = sprite_->getHeight();
for (int i = 0; i < lenght; ++i)
{
const auto index = static_cast<int>(text[i]);
sprite_->setSpriteClip(offset_[index].x, offset_[index].y, width, height);
sprite_->setPosX(x + shift);
sprite_->setX(x + shift);
sprite_->render();
shift += fixed_width_ ? box_width_ : (offset_[int(text[i])].w + kerning);
}
@@ -267,16 +239,4 @@ void Text::reLoadTexture()
void Text::setFixedWidth(bool 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
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
class Text
@@ -34,7 +34,6 @@ class Text
private:
// Objetos y punteros
std::unique_ptr<Sprite> sprite_; // Objeto con los graficos para el texto
std::shared_ptr<Texture> texture_; // Textura con los bitmaps del texto
// Variables
int box_width_; // Anchura de la caja de cada caracter en el png
@@ -44,9 +43,8 @@ private:
public:
// Constructor
Text(const std::string &bitmap_file, const std::string &text_file, SDL_Renderer *renderer);
Text(const std::string &text_file, std::shared_ptr<Texture> texture);
Text(TextFile *text_file, std::shared_ptr<Texture> texture);
Text(std::shared_ptr<Texture> texture, const std::string &text_file);
Text(std::shared_ptr<Texture> texture, std::shared_ptr<TextFile> text_file);
// Destructor
~Text() = default;
@@ -77,10 +75,4 @@ public:
// Establece si se usa un tamaño fijo de letra
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 "utils.h"
#include <SDL2/SDL_error.h> // for SDL_GetError
#include <SDL2/SDL_surface.h> // for SDL_CreateRGBSurfaceWithFormatFrom
#include <fcntl.h> // for SEEK_END, SEEK_SET
#include <stdio.h> // for fseek, fclose, fopen, fread, ftell, NULL
#include <stdlib.h> // for malloc, free, exit
#include <iostream> // for basic_ostream, operator<<, cout, endl
#include "gif.c" // for LoadGif, LoadPalette
#include <fstream>
#include <sstream>
#include "gif.c" // for LoadGif, LoadPalette
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h" // for stbi_failure_reason, stbi_image_free
// Constructor
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
if (!path_.empty())
{
@@ -37,9 +38,14 @@ Texture::Texture(SDL_Renderer *renderer, const std::string &path)
// .gif
else if (extension == "gif")
{
// Crea la surface desde un fichero
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);
SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);
flipSurface();
@@ -50,28 +56,26 @@ Texture::Texture(SDL_Renderer *renderer, const std::string &path)
// Destructor
Texture::~Texture()
{
unload();
unloadTexture();
unloadSurface();
palettes_.clear();
}
// 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 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)
{
#ifdef VERBOSE
std::cout << "Loading image failed: " << stbi_failure_reason() << std::endl;
#endif
exit(1);
std::cerr << "Error: Fichero no encontrado " << file_path << std::endl;
throw std::runtime_error("Fichero no encontrado: " + file_path);
}
else
{
#ifdef VERBOSE
const std::string file_name = path.substr(path.find_last_of("\\/") + 1);
std::cout << "Image loaded: " << file_name << std::endl;
#endif
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
printWithDots("Image : ", file_name, "[ LOADED ]");
}
int depth, pitch;
@@ -90,7 +94,7 @@ bool Texture::loadFromFile(const std::string &path)
}
// Limpia
unload();
unloadTexture();
// La textura final
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);
if (loadedSurface == nullptr)
{
#ifdef VERBOSE
std::cout << "Unable to load image " << path << std::endl;
#endif
std::cout << "Unable to load image " << file_path << std::endl;
}
else
{
@@ -109,9 +111,7 @@ bool Texture::loadFromFile(const std::string &path)
newTexture = SDL_CreateTextureFromSurface(renderer_, loadedSurface);
if (newTexture == nullptr)
{
#ifdef VERBOSE
std::cout << "Unable to create texture from " << path << "! SDL Error: " << SDL_GetError() << std::endl;
#endif
std::cout << "Unable to create texture from " << file_path << "! SDL Error: " << SDL_GetError() << std::endl;
}
else
{
@@ -137,9 +137,7 @@ bool Texture::createBlank(int width, int height, SDL_PixelFormatEnum format, SDL
texture_ = SDL_CreateTexture(renderer_, format, access, width, height);
if (!texture_)
{
#ifdef VERBOSE
std::cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << std::endl;
#endif
}
else
{
@@ -151,7 +149,7 @@ bool Texture::createBlank(int width, int height, SDL_PixelFormatEnum format, SDL
}
// Libera la memoria de la textura
void Texture::unload()
void Texture::unloadTexture()
{
// Libera la textura
if (texture_)
@@ -161,13 +159,6 @@ void Texture::unload()
width_ = 0;
height_ = 0;
}
// Libera la surface
if (surface_)
{
deleteSurface(surface_);
surface_ = nullptr;
}
}
// Establece el color para la modulacion
@@ -238,61 +229,56 @@ SDL_Texture *Texture::getSDLTexture()
return texture_;
}
// Crea una nueva surface
/*Surface Texture::newSurface(int w, int h)
// Desencadenar la superficie actual
void Texture::unloadSurface()
{
Surface surf = static_cast<Surface>(malloc(sizeof(surface_s)));
surf->w = w;
surf->h = h;
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);
surface_.reset(); // Resetea el shared_ptr
width_ = 0;
height_ = 0;
}
// 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");
if (!f)
// Desencadenar la superficie actual
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);
long size = ftell(f);
fseek(f, 0, SEEK_SET);
Uint8 *buffer = static_cast<Uint8 *>(malloc(size));
fread(buffer, size, 1, f);
fclose(f);
// Obtener el tamaño del archivo
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
// 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;
Uint8 *pixels = LoadGif(buffer, &w, &h);
if (pixels == nullptr)
Uint8 *rawPixels = LoadGif(buffer.data(), &w, &h);
if (!rawPixels)
{
return nullptr;
}
Surface surface = static_cast<Surface>(malloc(sizeof(surface_s)));
surface->w = w;
surface->h = h;
surface->data = pixels;
free(buffer);
// Crear un std::shared_ptr con std::make_shared para pixels
auto pixels = std::shared_ptr<Uint8[]>(rawPixels, std::default_delete<Uint8[]>());
auto surface = std::make_shared<Surface>(w, h, pixels);
// Actualizar la anchura y altura
width_ = w;
height_ = h;
@@ -315,7 +301,7 @@ void Texture::flipSurface()
SDL_LockTexture(texture_, nullptr, reinterpret_cast<void **>(&pixels), &pitch);
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_);
}
@@ -327,14 +313,20 @@ void Texture::setPaletteColor(int palette, int index, Uint32 color)
}
// 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;
FILE *f = fopen(file_name.c_str(), "rb");
FILE *f = fopen(file_path.c_str(), "rb");
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);
@@ -361,9 +353,9 @@ std::vector<Uint32> Texture::loadPal(const std::string &file_name)
}
// 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);
}
@@ -372,7 +364,7 @@ void Texture::setPalette(int palette)
{
if (palette < (int)palettes_.size())
{
paletteIndex_ = palette;
current_palette_ = palette;
flipSurface();
}
}

View File

@@ -1,51 +1,54 @@
#pragma once
#include <SDL2/SDL_blendmode.h> // for SDL_BlendMode
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888, SDL_PixelF...
#include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_FLIP_NONE, SDL_TEX...
#include <SDL2/SDL_stdinc.h> // for Uint8, Uint32, Uint16
#include <string> // for string, basic_string
#include <vector> // for vector
#include <SDL2/SDL_blendmode.h> // for SDL_BlendMode
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888, SDL_PixelF...
#include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_FLIP_NONE, SDL_TEX...
#include <SDL2/SDL_stdinc.h> // for Uint8, Uint32, Uint16
#include <string> // for string, basic_string
#include <vector> // for vector
#include <memory>
// Definiciones de tipos
struct surface_s
struct Surface
{
Uint8 *data;
std::shared_ptr<Uint8[]> data;
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
{
private:
// Objetos y punteros
SDL_Texture *texture_; // La textura
SDL_Renderer *renderer_; // Renderizador donde dibujar la textura
Surface surface_; // Surface para usar imagenes en formato gif con paleta
SDL_Texture *texture_; // La textura
SDL_Renderer *renderer_; // Renderizador donde dibujar la textura
std::shared_ptr<Surface> surface_; // Surface para usar imagenes en formato gif con paleta
// Variables
int width_; // Ancho de la imagen
int height_; // Alto de la imagen
std::string path_; // Ruta de la imagen de la textura
std::vector<std::vector<Uint32>> palettes_; // Vector con las diferentes paletas
int paletteIndex_; // Indice de la paleta en uso
// Crea una nueva surface
//Surface newSurface(int w, int h);
// Elimina una surface
void deleteSurface(Surface surface);
int current_palette_; // Indice de la paleta en uso
// 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
void flipSurface();
void flipSurface();
// 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:
// Constructor
@@ -60,9 +63,6 @@ public:
// Crea una textura en blanco
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
void setColor(Uint8 red, Uint8 green, Uint8 blue);
@@ -91,7 +91,7 @@ public:
SDL_Texture *getSDLTexture();
// 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
void setPaletteColor(int palette, int index, Uint32 color);

View File

@@ -1,116 +1,102 @@
#include "tiled_bg.h"
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_stdinc.h> // for SDL_sinf
#include <stdlib.h> // for rand
#include <memory> // for unique_ptr, make_shared, make_unique
#include "screen.h" // for Screen
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <stdlib.h> // for rand
#include <memory> // for unique_ptr, make_shared, make_unique
#include <cmath> // for sinf
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
// Constructor
Tiledbg::Tiledbg(std::string texture_path, SDL_Rect pos, int mode)
: texture_path_(texture_path), pos_(pos), mode_(mode)
TiledBG::TiledBG(SDL_Rect pos, TiledBGMode 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
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
fillTexture();
// Coloca la ventana que recorre el mosaico de fondo de manera que coincida
// con el mosaico que hay pintado en el titulo al iniciar
window_.x = 128;
window_.y = 96;
window_.w = pos_.w;
window_.h = pos_.h;
window_ = {128, 96, pos_.w, pos_.h};
// Inicializa los valores del vector con los valores del seno
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
void Tiledbg::fillTexture()
void TiledBG::fillTexture()
{
// 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>((SDL_Rect){0, 0, tile_width_, tile_height_}, bg_tile_texture);
auto tile = std::make_unique<Sprite>(Resource::get()->getTexture("title_bg_tile.png"), (SDL_Rect){0, 0, TILE_WIDTH_, TILE_HEIGHT_});
// Prepara para dibujar sobre la textura
auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, canvas_);
// Rellena la textura con el tile
const auto i_max = pos_.w * 2 / tile_width_;
const auto j_max = pos_.h * 2 / tile_height_;
tile->setSpriteClip(0, 0, tile_width_, tile_height_);
const auto i_max = pos_.w * 2 / TILE_WIDTH_;
const auto j_max = pos_.h * 2 / TILE_HEIGHT_;
tile->setSpriteClip(0, 0, TILE_WIDTH_, TILE_HEIGHT_);
for (int i = 0; i < i_max; ++i)
{
for (int j = 0; j < j_max; ++j)
{
tile->setPosX(i * tile_width_);
tile->setPosY(j * tile_height_);
tile->setX(i * TILE_WIDTH_);
tile->setY(j * TILE_HEIGHT_);
tile->render();
}
}
// Vuelve a colocar el renderizador como estaba
SDL_SetRenderTarget(renderer_, temp);
// Libera la memoria utilizada por los objetos
bg_tile_texture->unload();
}
// Pinta la clase en pantalla
void Tiledbg::render()
void TiledBG::render()
{
SDL_RenderCopy(renderer_, canvas_, &window_, &pos_);
}
// 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
++window_.x %= tile_width_;
++window_.y %= tile_height_;
++window_.x %= TILE_WIDTH_;
++window_.y %= TILE_HEIGHT_;
break;
}
else if (mode_ == TILED_MODE_CIRCLE)
case TiledBGMode::CIRCLE:
{ // El tileado de fondo se desplaza en circulo
++counter_ %= 360;
window_.x = 128 + (int(sin_[(counter_ + 270) % 360] * 128));
window_.y = 96 + (int(sin_[(360 - counter_) % 360] * 96));
break;
}
default:
break;
}
}
// Recarga las texturas
void Tiledbg::reLoad()
void TiledBG::reLoad()
{
fillTexture();
}

View File

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

View File

@@ -1,84 +1,72 @@
#include "title.h"
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_KEYDOWN
#include <SDL2/SDL_keycode.h> // for SDLK_1, SDLK_2, SDLK_3
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <string> // for char_traits, operator+, to_string, bas...
#include <utility> // for move
#include <vector> // for vector
#include "asset.h" // for Asset
#include "global_inputs.h" // for check
#include "input.h" // for Input, InputType, INPUT_DO_NOT_ALLOW_R...
#include "jail_audio.h" // for JA_GetMusicState, JA_Music_state, JA_P...
#include "lang.h" // for getText
#include "options.h" // for options
#include "param.h" // for param
#include "screen.h" // for Screen
#include "section.h" // for Options, options, Name, name
#include "texture.h" // for Texture
#include "utils.h" // for Param, OptionsController, Color, Param...
struct JA_Music_t; // lines 17-17
#include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_KEYDOWN
#include <SDL2/SDL_keycode.h> // for SDLK_1, SDLK_2, SDLK_3
#include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <string> // for char_traits, operator+, to_string, bas...
#include <utility> // for move
#include <vector> // for vector
#include "asset.h" // for Asset
#include "global_inputs.h" // for check
#include "input.h" // for Input, InputType, INPUT_DO_NOT_ALLOW_R...
#include "jail_audio.h" // for JA_GetMusicState, JA_Music_state, JA_P...
#include "lang.h" // for getText
#include "notifier.h" // for Notifier
#include "options.h" // for options
#include "param.h" // for param
#include "resource.h" // for Resource
#include "screen.h" // for Screen
#include "section.h" // for Options, options, Name, name
#include "texture.h" // for Texture
#include "utils.h" // for Param, OptionsController, Color, Param...
struct JA_Music_t; // lines 17-17
// Constructor
Title::Title(JA_Music_t *music)
: music_(music)
Title::Title()
: 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
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);
// Configura objetos
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_->setType(FadeType::RANDOM_SQUARE);
fade_->setPost(param.fade.post_duration);
demo_ = true;
num_controllers_ = input_->getNumControllers();
Resource::get()->getTexture("smb2.gif")->setPalette(1);
// 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
void Title::update()
{
// Calcula la lógica de los objetos
if (SDL_GetTicks() - ticks_ > ticks_speed_)
if (SDL_GetTicks() - ticks_ > TICKS_SPEED_)
{
// Actualiza el contador de ticks_
ticks_ = SDL_GetTicks();
// Actualiza el objeto screen
screen_->update();
Screen::get()->update();
// Comprueba el fade_ y si se ha acabado
fade_->update();
@@ -115,7 +103,7 @@ void Title::update()
// Reproduce la música
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
@@ -137,10 +125,10 @@ void Title::update()
void Title::render()
{
// Prepara para empezar a dibujar en la textura de juego
screen_->start();
Screen::get()->start();
// Limpia la pantalla
screen_->clean(bg_color);
Screen::get()->clean(bg_color);
// Dibuja el mosacico de fondo
tiled_bg_->render();
@@ -161,7 +149,7 @@ void Title::render()
// Mini logo
const int pos1 = (param.game.height / 5 * 4) + BLOCK;
const int pos2 = pos1 + mini_logo_sprite_->getHeight() + 3;
mini_logo_sprite_->setPosY(pos1);
mini_logo_sprite_->setY(pos1);
mini_logo_sprite_->render();
// Texto con el copyright
@@ -175,7 +163,7 @@ void Title::render()
fade_->render();
// Vuelca el contenido del renderizador en pantalla
screen_->blit();
Screen::get()->blit();
}
// Comprueba los eventos
@@ -192,6 +180,7 @@ void Title::checkEvents()
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
@@ -240,7 +229,7 @@ void Title::checkInput()
if (!define_buttons_->isEnabled())
{
// 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)
{
@@ -250,27 +239,27 @@ void Title::checkInput()
}
// 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
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();
return;
}
// 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);
return;
}
// 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
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)
{
@@ -284,7 +273,7 @@ void Title::checkInput()
}
// Comprueba el input para el resto de objetos
screen_->checkInput();
Screen::get()->checkInput();
define_buttons_->checkInput();
// 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
void Title::swapControllers()
{
const auto num_controllers = input_->getNumControllers();
const auto num_controllers = Input::get()->getNumControllers();
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();
}

View File

@@ -1,18 +1,21 @@
#pragma once
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for unique_ptr, shared_ptr
#include "define_buttons.h" // for DefineButtons
#include "fade.h" // for Fade
#include "game_logo.h" // for GameLogo
#include "sprite.h" // for Sprite
#include "text.h" // for Text
#include "tiled_bg.h" // for Tiledbg
class Input; // lines 17-17
class Screen; // lines 18-18
class Texture; // lines 20-20
namespace section { enum class Name; }
struct JA_Music_t; // lines 21-21
#include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for unique_ptr, shared_ptr
#include "define_buttons.h" // for DefineButtons
#include "fade.h" // for Fade
#include "game_logo.h" // for GameLogo
#include "sprite.h" // for Sprite
#include "text.h" // for Text
#include "tiled_bg.h" // for TiledBG
class Input; // lines 17-17
class Screen; // lines 18-18
class Texture; // lines 20-20
namespace section
{
enum class Name;
}
struct JA_Music_t; // lines 21-21
// Textos
constexpr const char TEXT_COPYRIGHT[] = "@2020,2024 JailDesigner";
@@ -39,32 +42,27 @@ constexpr bool ALLOW_TITLE_ANIMATION_SKIP = true;
class Title
{
private:
// Objetos y punteros
Screen *screen_; // Objeto encargado de dibujar en pantalla
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
// Constantes
static constexpr Uint32 TICKS_SPEED_ = 15; // Velocidad a la que se repiten los bucles del programa
// Objetos y punteros
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<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
int counter_; // Temporizador para la pantalla de titulo
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
int counter_; // Temporizador para la pantalla de titulo
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
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
int post_fade_; // Opción a realizar cuando termina el fundido
int num_controllers_; // Número de mandos conectados
// Inicializa los valores de las variables
void init();
int post_fade_; // Opción a realizar cuando termina el fundido
int num_controllers_; // Número de mandos conectados
// Actualiza las variables del objeto
void update();
@@ -89,10 +87,10 @@ private:
public:
// Constructor
explicit Title(JA_Music_t *music);
Title();
// Destructor
~Title() = default;
~Title();
// Bucle para el titulo del juego
void run();

View File

@@ -1,4 +1,6 @@
#include "utils.h"
#include <iostream>
#include <string>
#include <algorithm> // for min, clamp, find_if_not, transform
#include <cctype> // for tolower, isspace
#include <cmath> // for cos, pow, M_PI
@@ -104,38 +106,6 @@ std::string toLower(const std::string &str)
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
void DrawCircle(SDL_Renderer *renderer, int32_t centerX, int32_t centerY, int32_t radius)
{
@@ -213,4 +183,92 @@ double easeOutQuint(double t)
double easeInOutSine(double t)
{
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_Sound_t; // lines 13-13
// Constantes
constexpr int BLOCK = 8;
constexpr int TOTAL_DEMO_DATA = 2000;
// Dificultad del juego
enum class GameDifficulty
{
@@ -25,9 +29,6 @@ enum class GameDifficulty
HARD = 2,
};
// Tamaño de bloque
constexpr int BLOCK = 8;
// Estructura para definir un circulo
struct Circle
{
@@ -58,7 +59,6 @@ struct HiScoreEntry
int score; // Puntuación
};
// Estructura para mapear el teclado usado en la demo
struct DemoKeys
{
Uint8 left;
@@ -67,6 +67,21 @@ struct DemoKeys
Uint8 fire;
Uint8 fire_left;
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
@@ -152,11 +167,12 @@ struct Zone
// param.game
struct ParamGame
{
int width; // Ancho de la resolucion nativa del juego
int height; // Alto de la resolucion nativa del juego
int item_size; // Tamaño de los items del juego
Zone play_area; // Rectangulo con la posición de la zona de juego
Zone game_area; // Rectangulo con las dimensiones del juego
int width; // Ancho de la resolucion nativa del juego
int height; // Alto de la resolucion nativa del juego
int item_size; // Tamaño de los items del juego
Zone play_area; // Rectangulo con la posición de la zona de juego
Zone game_area; // Rectangulo con las dimensiones del juego
int enter_name_seconds; // Duración en segundos para introducir el nombre al finalizar la partida
};
// param.fade
@@ -214,20 +230,6 @@ struct Param
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
double distanceSquared(int x1, int y1, int x2, int y2);
@@ -255,15 +257,6 @@ std::string boolToOnOff(bool value);
// Convierte una cadena a minusculas
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
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
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
extern const Color bg_color;
extern const Color no_color;