Compare commits

9 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
46 changed files with 673 additions and 690 deletions

View File

Before

Width:  |  Height:  |  Size: 84 B

After

Width:  |  Height:  |  Size: 84 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 929 B

View File

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 173 B

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 772 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

View File

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 944 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 84 B

View File

@@ -6,35 +6,36 @@
#include "moving_sprite.h" // for MovingSprite
#include "param.h" // for param
#include "resource.h" // for Resource
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include "screen.h"
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
// Constructor
Background::Background(SDL_Renderer *renderer)
: renderer_(renderer),
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"))
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};
@@ -87,11 +88,11 @@ Background::Background(SDL_Renderer *renderer)
}
// 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_);
@@ -120,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();

View File

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

View File

@@ -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;
@@ -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;
@@ -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_
@@ -460,7 +451,7 @@ void Balloon::update()
updateColliders();
updateState();
updateBounce();
counter_++;
++counter_;
}
}
@@ -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

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

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

@@ -134,6 +134,8 @@ Director::~Director()
SDL_DestroyWindow(window_);
SDL_Quit();
std::cout << "\nBye!" << std::endl;
}
// Asigna los botones y teclas al objeto Input
@@ -369,85 +371,113 @@ void 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);
{ // Bala
Asset::get()->add(prefix + "/data/gfx/bullet/bullet.png", AssetType::BITMAP);
}
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_1000_points.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_2500_points.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/game_text/game_text_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);
{ // 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/intro/intro.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/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);
{ // Intro
Asset::get()->add(prefix + "/data/gfx/intro/intro.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);
{ // 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/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);
{ // 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/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);
{ // 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/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);
{ // 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.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);
}
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);
{ // 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::BITMAP);
@@ -461,7 +491,7 @@ void Director::setFileList()
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::BITMAP);
Asset::get()->add(prefix + "/data/font/smb2_pal1.gif", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/font/smb2_palette1.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/font/smb2.txt", AssetType::FONT);
// Textos
@@ -658,19 +688,20 @@ int Director::run()
#ifdef ARCADE
// Comprueba si ha de apagar el sistema
if (section::options == section::Options::QUIT_SHUTDOWN)
if (section::options == section::Options::QUIT_WITH_CONTROLLER)
shutdownSystem();
#endif
const auto return_code = (section::options == section::Options::QUIT_NORMAL) ? "keyboard" : "controller";
std::cout << "\nGame end with " << return_code << std::endl;
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 (return_code == std::string("keyboard")) ? 0 : 1;
return (section::options == section::Options::QUIT_WITH_CONTROLLER) ? 1 : 0;
}
// Obtiene una fichero a partir de un lang::Code

View File

@@ -38,6 +38,7 @@
#include "texture.h" // for Texture
struct JA_Music_t; // lines 35-35
struct JA_Sound_t; // lines 36-36
#include "dbgtxt.h"
// Constructor
Game::Game(int player_id, int current_stage, bool demo)
@@ -55,11 +56,11 @@ Game::Game(int player_id, int current_stage, bool demo)
difficulty_ = options.game.difficulty;
// Crea los objetos
Scoreboard::init(renderer_);
Scoreboard::init();
scoreboard_ = Scoreboard::get();
fade_ = std::make_unique<Fade>();
background_ = std::make_unique<Background>(renderer_);
background_ = std::make_unique<Background>();
explosions_ = std::make_unique<Explosions>();
balloon_formations_ = std::make_unique<BalloonFormations>();
@@ -69,10 +70,10 @@ Game::Game(int player_id, int current_stage, bool demo)
// Inicializa los vectores con los datos para la demo
if (demo_.enabled)
{ // Aleatoriza la asignación del fichero
const auto index1 = rand() % 2;
const auto index2 = (index1 + 1) % 2;
loadDemoFile(asset_->get("demo1.bin"), &this->demo_.data_file[index1]);
loadDemoFile(asset_->get("demo2.bin"), &this->demo_.data_file[index2]);
const auto demo1 = rand() % 2;
const auto demo2 = (demo1 == 0) ? 1 : 0;
demo_.data.emplace_back(Resource::get()->getDemoData(demo1));
demo_.data.emplace_back(Resource::get()->getDemoData(demo2));
}
background_->setPos(param.game.play_area.rect);
@@ -92,10 +93,13 @@ Game::Game(int player_id, int current_stage, bool demo)
Game::~Game()
{
// Guarda las puntuaciones en un fichero
auto manager = std::make_unique<ManageHiScoreTable>(&options.game.hi_score_table);
manager->saveToFile(asset_->get("score.bin"));
if (!demo_.enabled)
{
auto manager = std::make_unique<ManageHiScoreTable>(&options.game.hi_score_table);
manager->saveToFile(asset_->get("score.bin"));
}
#ifdef RECORDING
saveDemoFile(asset->get("demo1.bin"));
saveDemoFile(Asset::get()->get("demo1.bin"), demo_.data.at(0));
#endif
// Elimina todos los objetos contenidos en vectores
@@ -112,9 +116,6 @@ Game::~Game()
// Inicializa las variables necesarias para la sección 'Game'
void Game::init(int player_id)
{
ticks_ = 0;
ticks_speed_ = 15;
// Elimina qualquier jugador que hubiese antes de crear los nuevos
players_.clear();
@@ -189,6 +190,7 @@ void Game::init(int player_id)
scoreboard_->setMode(SCOREBOARD_CENTER_PANEL, ScoreboardMode::STAGE_INFO);
// Resto de variables
ticks_ = 0;
hi_score_.score = options.game.hi_score_table[0].score;
hi_score_.name = options.game.hi_score_table[0].name;
paused_ = false;
@@ -200,8 +202,8 @@ void Game::init(int player_id)
menace_current_ = 0;
menace_threshold_ = 0;
hi_score_achieved_ = false;
stage_bitmap_counter_ = STAGE_COUNTER;
game_over_counter_ = GAME_OVER_COUNTER;
stage_bitmap_counter_ = STAGE_COUNTER_;
game_over_counter_ = GAME_OVER_COUNTER_;
time_stopped_ = false;
time_stopped_counter_ = 0;
counter_ = 0;
@@ -211,13 +213,13 @@ void Game::init(int player_id)
helper_.need_coffee = false;
helper_.need_coffee_machine = false;
helper_.need_power_ball = false;
helper_.counter = HELP_COUNTER;
helper_.item_disk_odds = ITEM_POINTS_1_DISK_ODDS;
helper_.item_gavina_odds = ITEM_POINTS_2_GAVINA_ODDS;
helper_.item_pacmar_odds = ITEM_POINTS_3_PACMAR_ODDS;
helper_.item_clock_odds = ITEM_CLOCK_ODDS;
helper_.item_coffee_odds = ITEM_COFFEE_ODDS;
helper_.item_coffee_machine_odds = ITEM_COFFEE_MACHINE_ODDS;
helper_.counter = HELP_COUNTER_;
helper_.item_disk_odds = ITEM_POINTS_1_DISK_ODDS_;
helper_.item_gavina_odds = ITEM_POINTS_2_GAVINA_ODDS_;
helper_.item_pacmar_odds = ITEM_POINTS_3_PACMAR_ODDS_;
helper_.item_clock_odds = ITEM_CLOCK_ODDS_;
helper_.item_coffee_odds = ITEM_COFFEE_ODDS_;
helper_.item_coffee_machine_odds = ITEM_COFFEE_MACHINE_ODDS_;
power_ball_enabled_ = false;
power_ball_counter_ = 0;
coffee_machine_enabled_ = false;
@@ -279,7 +281,7 @@ void Game::init(int player_id)
// Modo grabar demo
#ifdef RECORDING
demo.recording = true;
demo_.recording = true;
#else
demo_.recording = false;
#endif
@@ -347,13 +349,7 @@ void Game::loadMedia()
{
std::vector<std::shared_ptr<Texture>> player_texture;
player_texture.emplace_back(Resource::get()->getTexture("player1.gif"));
player_texture.back()->addPalette(asset_->get("player1_pal1.gif"));
player_texture.back()->addPalette(asset_->get("player1_pal2.gif"));
player_texture.back()->addPalette(asset_->get("player1_pal3.gif"));
player_texture.emplace_back(Resource::get()->getTexture("player_power.gif"));
player_texture.back()->addPalette(asset_->get("player_power_pal.gif"));
player_texture.emplace_back(Resource::get()->getTexture("player1_power.png"));
player_textures_.push_back(player_texture);
}
@@ -361,14 +357,7 @@ void Game::loadMedia()
{
std::vector<std::shared_ptr<Texture>> player_texture;
player_texture.emplace_back(Resource::get()->getTexture("player2.gif"));
player_texture.back()->addPalette(asset_->get("player2_pal1.gif"));
player_texture.back()->addPalette(asset_->get("player2_pal2.gif"));
player_texture.back()->addPalette(asset_->get("player2_pal3.gif"));
player_texture.emplace_back(Resource::get()->getTexture("player_power.gif"));
player_texture.back()->addPalette(asset_->get("player_power_pal.gif"));
player_texture.back()->setPalette(1);
player_texture.emplace_back(Resource::get()->getTexture("player2_power.png"));
player_textures_.push_back(player_texture);
}
@@ -431,99 +420,6 @@ void Game::unloadMedia()
item_animations_.clear();
}
// Carga el fichero de datos para la demo
bool Game::loadDemoFile(const std::string &file_path, DemoKeys (*data_file)[TOTAL_DEMO_DATA])
{
// Indicador de éxito en la carga
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(), "r+b");
if (!file)
{ // El fichero no existe
std::cout << "Warning: Unable to open " << file_name.c_str() << " file" << std::endl;
// Creamos el fichero para escritura
file = SDL_RWFromFile(file_path.c_str(), "w+b");
// Si ha creado el fichero
if (file)
{
std::cout << "New file (" << file_name.c_str() << ") created!" << std::endl;
// Inicializas los datos y los guarda en el fichero
for (int i = 0; i < TOTAL_DEMO_DATA; ++i)
{
DemoKeys dk;
dk.left = 0;
dk.right = 0;
dk.no_input = 0;
dk.fire = 0;
dk.fire_left = 0;
dk.fire_right = 0;
(*data_file)[i] = dk;
SDL_RWwrite(file, &dk, sizeof(DemoKeys), 1);
}
// Cerramos el fichero
SDL_RWclose(file);
}
else
{ // Si no puede crear el fichero
std::cout << "Error: Unable to create file " << file_name.c_str() << std::endl;
success = false;
}
}
// El fichero existe
else
{
// Mensaje de proceder a la carga de los datos
std::cout << "Reading file: " << file_name.c_str() << std::endl;
// Lee todos los datos del fichero y los deja en el destino
for (int i = 0; i < TOTAL_DEMO_DATA; ++i)
{
DemoKeys tmp;
SDL_RWread(file, &tmp, sizeof(DemoKeys), 1);
(*data_file)[i] = tmp;
}
// Cierra el fichero
SDL_RWclose(file);
}
return success;
}
#ifdef RECORDING
// Guarda el fichero de datos para la demo
bool Game::saveDemoFile(const std::string &file_path)
{
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 (int i = 0; i < TOTAL_DEMO_DATA; ++i)
{
SDL_RWwrite(file, &demo.dataFile[0][i], sizeof(DemoKeys), 1);
}
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;
}
return success;
}
#endif // RECORDING
// Crea una formación de enemigos
void Game::deployBalloonFormation()
{
@@ -543,7 +439,7 @@ void Game::deployBalloonFormation()
else
{
// Decrementa el contador de despliegues enemigos de la PowerBall
power_ball_counter_ > 0 ? power_ball_counter_-- : power_ball_counter_ = 0;
power_ball_counter_ = (power_ball_counter_ > 0) ? (power_ball_counter_ - 1) : 0;
// Elige una formación enemiga la azar
auto set = rand() % 10;
@@ -679,7 +575,7 @@ void Game::updateStage()
}
// Incrementa el contador del bitmap que aparece mostrando el cambio de fase
if (stage_bitmap_counter_ < STAGE_COUNTER)
if (stage_bitmap_counter_ < STAGE_COUNTER_)
{
stage_bitmap_counter_++;
}
@@ -751,9 +647,8 @@ void Game::renderBalloons()
std::shared_ptr<Balloon> Game::createBalloon(float x, int y, int kind, float velx, float speed, int creation_timer)
{
const auto index = (kind - 1) % 4;
auto b = std::make_shared<Balloon>(x, y, kind, velx, speed, creation_timer, balloon_textures_[index], balloon_animations_[index]);
balloons_.push_back(b);
return b;
balloons_.emplace_back(std::make_shared<Balloon>(x, y, kind, velx, speed, creation_timer, balloon_textures_[index], balloon_animations_[index]));
return balloons_.back();
}
// Crea una PowerBall
@@ -852,11 +747,11 @@ void Game::popBalloon(std::shared_ptr<Balloon> balloon)
{ // En cualquier otro caso, crea dos globos de un tipo inferior
auto balloon_left = createBalloon(0, balloon->getPosY(), balloon->getKind() - 1, BALLOON_VELX_NEGATIVE, balloon_speed_, 0);
balloon_left->allignTo(balloon->getPosX() + (balloon->getWidth() / 2));
balloon_left->setVelY(balloon_left->getClass() == BALLOON_CLASS ? -2.50f : BALLOON_VELX_NEGATIVE);
balloon_left->setVelY(balloon_left->getClass() == BALLOON_CLASS ? -2.50f : BALLOON_VELX_NEGATIVE * 2.0f);
auto balloon_right = createBalloon(0, balloon->getPosY(), balloon->getKind() - 1, BALLOON_VELX_POSITIVE, balloon_speed_, 0);
balloon_right->allignTo(balloon->getPosX() + (balloon->getWidth() / 2));
balloon_right->setVelY(balloon_right->getClass() == BALLOON_CLASS ? -2.50f : BALLOON_VELX_NEGATIVE);
balloon_right->setVelY(balloon_right->getClass() == BALLOON_CLASS ? -2.50f : BALLOON_VELX_NEGATIVE * 2.0f);
// Elimina el globo
explosions_->add(balloon->getPosX(), balloon->getPosY(), size);
@@ -1241,7 +1136,7 @@ ItemType Game::dropItem()
case 4:
if (lucky_number < helper_.item_coffee_odds)
{
helper_.item_coffee_odds = ITEM_COFFEE_ODDS;
helper_.item_coffee_odds = ITEM_COFFEE_ODDS_;
return ItemType::COFFEE;
}
else
@@ -1256,7 +1151,7 @@ ItemType Game::dropItem()
case 5:
if (lucky_number < helper_.item_coffee_machine_odds)
{
helper_.item_coffee_machine_odds = ITEM_COFFEE_MACHINE_ODDS;
helper_.item_coffee_machine_odds = ITEM_COFFEE_MACHINE_ODDS_;
if (!coffee_machine_enabled_ && helper_.need_coffee_machine)
{
return ItemType::COFFEE_MACHINE;
@@ -1455,7 +1350,7 @@ void Game::updateTimeStoppedCounter()
if (time_stopped_counter_ > 0)
{
time_stopped_counter_--;
stopAllBalloons(TIME_STOPPED_COUNTER);
stopAllBalloons(TIME_STOPPED_COUNTER_);
}
else
{
@@ -1477,7 +1372,7 @@ void Game::updateBalloonDeployCounter()
void Game::update()
{
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks_ > ticks_speed_)
if (SDL_GetTicks() - ticks_ > TICKS_SPEED_)
{
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks();
@@ -1513,9 +1408,9 @@ void Game::update()
checkInput();
// Incrementa el contador de la demo
if (demo.counter < TOTAL_DEMO_DATA)
if (demo_.counter < TOTAL_DEMO_DATA)
{
demo.counter++;
demo_.counter++;
}
// Si se ha llenado el vector con datos, sale del programa
@@ -1703,7 +1598,7 @@ void Game::updateMenace()
void Game::renderMessages()
{
// GetReady
if (counter_ < STAGE_COUNTER && !demo_.enabled)
if (counter_ < STAGE_COUNTER_ && !demo_.enabled)
{
text_nokia2_big_->write((int)get_ready_bitmap_path_[counter_], param.game.play_area.center_y - 8, lang::getText(75), -2);
}
@@ -1733,7 +1628,7 @@ void Game::renderMessages()
}
// STAGE NUMBER
if (stage_bitmap_counter_ < STAGE_COUNTER)
if (stage_bitmap_counter_ < STAGE_COUNTER_)
{
const auto stage_number = balloon_formations_->getStage(current_stage_).number;
std::string text;
@@ -1763,9 +1658,9 @@ void Game::renderMessages()
// Habilita el efecto del item de detener el tiempo
void Game::enableTimeStopItem()
{
stopAllBalloons(TIME_STOPPED_COUNTER);
stopAllBalloons(TIME_STOPPED_COUNTER_);
setTimeStopped(true);
incTimeStoppedCounter(TIME_STOPPED_COUNTER);
incTimeStoppedCounter(TIME_STOPPED_COUNTER_);
if (JA_GetMusicState() == JA_MUSIC_PLAYING && !demo_.enabled)
{
JA_PauseMusic();
@@ -1836,8 +1731,8 @@ void Game::initPaths()
}
// Letrero de STAGE #
constexpr auto first_part = STAGE_COUNTER / 4; // 50
constexpr auto second_part = first_part * 3; // 150
constexpr auto first_part = STAGE_COUNTER_ / 4; // 50
constexpr auto second_part = first_part * 3; // 150
const auto center_point = param.game.play_area.center_y - (BLOCK * 2);
const auto distance = (param.game.play_area.rect.h) - (param.game.play_area.center_y - 16);
@@ -1851,7 +1746,7 @@ void Game::initPaths()
stage_bitmap_path_[i] = (int)center_point;
}
for (int i = second_part; i < STAGE_COUNTER; ++i)
for (int i = second_part; i < STAGE_COUNTER_; ++i)
{
stage_bitmap_path_[i] = (sin[(int)(((i - 149) * 1.8f) + 90)] * (center_point + 17) - 17);
}
@@ -1878,7 +1773,7 @@ void Game::initPaths()
get_ready_bitmap_path_[i] = (int)finish1;
}
for (int i = second_part; i < STAGE_COUNTER; ++i)
for (int i = second_part; i < STAGE_COUNTER_; ++i)
{
get_ready_bitmap_path_[i] = sin[(int)((i - second_part) * 1.8f)];
get_ready_bitmap_path_[i] *= distance2;
@@ -1894,7 +1789,7 @@ void Game::updateGameCompleted()
game_completed_counter_++;
}
if (game_completed_counter_ == GAME_COMPLETED_END)
if (game_completed_counter_ == GAME_COMPLETED_END_)
{
section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1;
@@ -1970,6 +1865,7 @@ void Game::checkEvents()
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
@@ -2041,20 +1937,6 @@ void Game::checkEvents()
break;
}
// Ralentiza mucho la lógica
case SDLK_4:
{
ticks_speed_ *= 10;
break;
}
// Acelera mucho la lógica
case SDLK_5:
{
ticks_speed_ /= 10;
break;
}
default:
break;
}
@@ -2254,7 +2136,7 @@ void Game::handleDemoMode()
// Incluye movimientos (izquierda, derecha, sin movimiento) y disparos automáticos.
void Game::handleDemoPlayerInput(const std::shared_ptr<Player> &player, int index)
{
const auto &demoData = demo_.data_file[index][demo_.counter];
const auto &demoData = demo_.data[index][demo_.counter];
if (demoData.left == 1)
player->setInput(InputType::LEFT);
@@ -2314,21 +2196,21 @@ void Game::handleNormalPlayerInput(const std::shared_ptr<Player> &player)
{
player->setInput(InputType::LEFT);
#ifdef RECORDING
demo.keys.left = 1;
demo_.keys.left = 1;
#endif
}
else if (input_->checkInput(InputType::RIGHT, INPUT_ALLOW_REPEAT, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index))
{
player->setInput(InputType::RIGHT);
#ifdef RECORDING
demo.keys.right = 1;
demo_.keys.right = 1;
#endif
}
else
{
player->setInput(InputType::NONE);
#ifdef RECORDING
demo.keys.no_input = 1;
demo_.keys.no_input = 1;
#endif
}
@@ -2342,21 +2224,21 @@ void Game::handleFireInputs(const std::shared_ptr<Player> &player, bool autofire
{
handleFireInput(player, BulletType::UP);
#ifdef RECORDING
demo.keys.fire = 1;
demo_.keys.fire = 1;
#endif
}
else if (input_->checkInput(InputType::FIRE_LEFT, autofire, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index))
{
handleFireInput(player, BulletType::LEFT);
#ifdef RECORDING
demo.keys.fire_left = 1;
demo_.keys.fire_left = 1;
#endif
}
else if (input_->checkInput(InputType::FIRE_RIGHT, autofire, options.controller[controllerIndex].device_type, options.controller[controllerIndex].index))
{
handleFireInput(player, BulletType::RIGHT);
#ifdef RECORDING
demo.keys.fire_right = 1;
demo_.keys.fire_right = 1;
#endif
}
}

View File

@@ -32,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
@@ -83,6 +63,7 @@ constexpr int TIME_STOPPED_COUNTER = 300;
class Game
{
private:
// Estructuras
struct Helper
{
bool need_coffee; // Indica si se necesitan cafes
@@ -97,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
@@ -146,39 +138,38 @@ private:
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
// 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
@@ -201,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();

View File

@@ -39,7 +39,7 @@ namespace globalInputs
else
{
#ifdef ARCADE
const int index = code == section::Options::QUIT_NORMAL ? 94 : 116;
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);
@@ -69,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;
}
@@ -107,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

@@ -23,29 +23,21 @@
// Constructor
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>();
background_ = std::make_unique<Background>(renderer_);
text_ = std::make_unique<Text>(Resource::get()->getTexture("smb2.gif"), Resource::get()->getTextFile("smb2.txt"));
// 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();
@@ -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

@@ -24,6 +24,10 @@ enum class FadeMode : Uint8; // lines 11-11
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
@@ -34,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

View File

@@ -416,10 +416,9 @@ bool Input::discoverGameControllers()
}
}
{
std::cout << "\nChecking for game controllers...\n";
std::cout << num_joysticks_ << " joysticks found, " << num_gamepads_ << " are gamepads\n";
}
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)
{
@@ -434,7 +433,7 @@ bool Input::discoverGameControllers()
connected_controllers_.push_back(pad);
const std::string name = SDL_GameControllerNameForIndex(i);
{
std::cout << name << std::endl;
std::cout << "#" << i << ": " << name << std::endl;
}
controller_names_.push_back(name);
}
@@ -449,6 +448,8 @@ bool Input::discoverGameControllers()
SDL_GameControllerEventState(SDL_ENABLE);
}
std::cout << "\n** FINISHED LOOKING FOR GAME CONTROLLERS" << std::endl;
return found;
}

View File

@@ -31,7 +31,7 @@ Instructions::Instructions()
// Crea objetos
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}, TILED_MODE_STATIC);
tiled_bg_ = std::make_unique<TiledBG>((SDL_Rect){0, 0, param.game.width, param.game.height}, TiledBGMode::STATIC);
fade_ = std::make_unique<Fade>();
// Crea un backbuffer para el renderizador
@@ -297,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

@@ -170,6 +170,7 @@ void Intro::checkEvents()
case SDL_QUIT:
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}

View File

@@ -73,6 +73,7 @@ void Logo::checkEvents()
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}

View File

@@ -347,7 +347,7 @@ void Player::update()
setAnimation();
shiftColliders();
updateCooldown();
updatePowerUpCounter();
updatePowerUp();
updateInvulnerable();
updateContinueCounter();
updateEnterNameCounter();
@@ -578,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
@@ -615,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;
}
}

View File

@@ -43,13 +43,13 @@ class Player
{
private:
// Objetos y punteros
std::unique_ptr<AnimatedSprite> player_sprite_; // Sprite para dibujar el jugador
std::unique_ptr<AnimatedSprite> power_sprite_; // Sprite para dibujar el aura del jugador con el poder a tope
std::unique_ptr<EnterName> enter_name_; // Clase utilizada para introducir el nombre
SDL_Rect *play_area_; // Rectangulo con la zona de juego
std::unique_ptr<AnimatedSprite> player_sprite_; // Sprite para dibujar el jugador
std::unique_ptr<AnimatedSprite> power_sprite_; // Sprite para dibujar el aura del jugador con el poder a tope
std::unique_ptr<EnterName> enter_name_; // Clase utilizada para introducir el nombre
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
@@ -245,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;

View File

@@ -33,6 +33,8 @@ Resource::Resource()
loadTextures();
loadTextFiles();
loadAnimations();
loadDemoData();
addPalettes();
std::cout << "\n** RESOURCES LOADED" << std::endl;
}
@@ -116,6 +118,12 @@ Animations &Resource::getAnimation(const std::string &name)
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()
{
@@ -219,4 +227,30 @@ void Resource::loadAnimations()
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"));
}

View File

@@ -7,6 +7,7 @@
#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
@@ -75,6 +76,7 @@ private:
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();
@@ -91,6 +93,12 @@ private:
// 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
@@ -123,4 +131,7 @@ public:
// 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

@@ -8,17 +8,18 @@
#include "asset.h" // for Asset
#include "lang.h" // for getText
#include "resource.h" // for Resource
#include "sprite.h" // for Sprite
#include "text.h" // for Text
#include "texture.h" // for Texture
#include "screen.h"
#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
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
@@ -34,8 +35,8 @@ Scoreboard *Scoreboard::get()
}
// Constructor
Scoreboard::Scoreboard(SDL_Renderer *renderer)
: renderer_(renderer),
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_)),
@@ -107,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_++;

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

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

@@ -77,33 +77,8 @@ std::shared_ptr<TextFile> loadTextFile(const std::string &file_path)
return tf;
}
// Constructor
Text::Text(const std::string &bitmap_file, const std::string &text_file, SDL_Renderer *renderer)
{
// 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
texture_ = std::make_shared<Texture>(renderer, bitmap_file);
sprite_ = std::make_unique<Sprite>(texture_, (SDL_Rect){0, 0, box_width_, box_height_});
// Inicializa variables
fixed_width_ = false;
}
// Constructor
Text::Text(std::shared_ptr<Texture> texture, const std::string &text_file)
: texture_(texture)
{
// Carga los offsets desde el fichero
auto tf = loadTextFile(text_file);
@@ -127,7 +102,6 @@ Text::Text(std::shared_ptr<Texture> texture, const std::string &text_file)
// Constructor
Text::Text(std::shared_ptr<Texture> texture, std::shared_ptr<TextFile> text_file)
: texture_(texture)
{
// Inicializa variables desde la estructura
box_height_ = text_file->box_height;
@@ -265,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

@@ -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,7 +43,6 @@ private:
public:
// Constructor
Text(const std::string &bitmap_file, const std::string &text_file, SDL_Renderer *renderer);
Text(std::shared_ptr<Texture> texture, const std::string &text_file);
Text(std::shared_ptr<Texture> texture, std::shared_ptr<TextFile> text_file);
@@ -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

@@ -7,22 +7,22 @@
#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())
{
@@ -38,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();
@@ -51,7 +56,9 @@ Texture::Texture(SDL_Renderer *renderer, const std::string &path)
// Destructor
Texture::~Texture()
{
unload();
unloadTexture();
unloadSurface();
palettes_.clear();
}
// Carga una imagen desde un fichero
@@ -87,7 +94,7 @@ bool Texture::loadFromFile(const std::string &file_path)
}
// Limpia
unload();
unloadTexture();
// La textura final
SDL_Texture *newTexture = nullptr;
@@ -142,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_)
@@ -152,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
@@ -229,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;
@@ -306,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_);
}
@@ -318,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);
@@ -352,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);
}
@@ -363,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

@@ -9,11 +9,11 @@
#include "texture.h" // for Texture
// Constructor
TiledBG::TiledBG(SDL_Rect pos, int mode)
TiledBG::TiledBG(SDL_Rect pos, TiledBGMode mode)
: renderer_(Screen::get()->getRenderer()),
pos_(pos),
counter_(0),
mode_(mode == TILED_MODE_RANDOM ? rand() % 2 : mode)
mode_(mode == TiledBGMode::RANDOM ? static_cast<TiledBGMode>(rand() % 2) : mode)
{
// Crea la textura para el mosaico de fondo
canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, pos_.w * 2, pos_.h * 2);
@@ -28,7 +28,7 @@ TiledBG::TiledBG(SDL_Rect pos, int mode)
// Inicializa los valores del vector con los valores del seno
for (int i = 0; i < 360; ++i)
{
sin_[i] = std::sinf(i * 3.14159f / 180.0f); // Convierte grados a radianes y calcula el seno
sin_[i] = std::sin(i * 3.14159 / 180.0); // Convierte grados a radianes y calcula el seno
}
}
@@ -75,16 +75,23 @@ void TiledBG::render()
// Actualiza la lógica de la clase
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_;
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;
}
}

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.
@@ -30,17 +33,17 @@ private:
SDL_Texture *canvas_; // Textura donde dibujar el fondo formado por tiles
// Variables
SDL_Rect pos_; // Posición y tamaño del mosaico
int counter_; // Contador
int mode_; // Tipo de movimiento del mosaico
float sin_[360]; // Vector con los valores del seno precalculados
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(SDL_Rect pos, int mode);
TiledBG(SDL_Rect pos, TiledBGMode mode);
// Destructor
~TiledBG();

View File

@@ -24,51 +24,43 @@ struct JA_Music_t; // lines 17-17
// Constructor
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())
{
// Reserva memoria y crea los objetos
fade_ = std::make_unique<Fade>();
text1_ = std::make_unique<Text>(Resource::get()->getTexture("smb2.gif"), Resource::get()->getTextFile("smb2.txt"));
text1_->addPalette(Asset::get()->get("smb2_pal1.gif"));
text1_->setPalette(1);
text2_ = std::make_unique<Text>(Resource::get()->getTexture("8bithud.png"), Resource::get()->getTextFile("8bithud.txt"));
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());
tiled_bg_ = std::make_unique<TiledBG>((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::get()->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();
@@ -188,6 +180,7 @@ void Title::checkEvents()
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}

View File

@@ -42,29 +42,28 @@ constexpr bool ALLOW_TITLE_ANIMATION_SKIP = true;
class Title
{
private:
// Objetos y punteros
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
// 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
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();
// Actualiza las variables del objeto
void update();
@@ -91,7 +90,7 @@ public:
Title();
// Destructor
~Title() = default;
~Title();
// Bucle para el titulo del juego
void run();

View File

@@ -197,9 +197,78 @@ void printWithDots(const std::string &text1, const std::string &text2, const std
std::cout.setf(std::ios::left, std::ios::adjustfield);
std::cout << text1;
std::cout.width(70 - text1.length() - text3.length());
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
@@ -215,7 +230,6 @@ struct Param
ParamNotification notification; // Opciones para las notificaciones
};
// Calcula el cuadrado de la distancia entre dos puntos
double distanceSquared(int x1, int y1, int x2, int y2);
@@ -267,6 +281,14 @@ 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;