Compare commits

18 Commits

Author SHA1 Message Date
9825c7fb9b Pasaeta de include-what-you-use 2024-10-13 21:58:36 +02:00
d0a6e4c572 Afegits destructors virtuals en les classes Sprite 2024-10-13 21:23:15 +02:00
7c876e1d4d Acabat amb cppcheck
Arreglades les herencies de les classes Sprite
2024-10-13 21:00:33 +02:00
809c10048e Commit pa poder tornar a passar el cppcheck 2024-10-13 19:39:43 +02:00
babf02226c Mes recomanacions de cppcheck 2024-10-13 19:26:27 +02:00
46540ad7c3 Optimitzat el tema de comparacions i asignacions de strings buits. Mes que optimitzat, ara està mes mono 2024-10-13 14:25:05 +02:00
ba7c44ad06 Actualitzat Makefile 2024-10-13 14:24:15 +02:00
46b19ee82f Mes recomanacions de cppcheck aplicades
Abans de tocar unes cosetes de strings buits
2024-10-13 13:49:00 +02:00
b2122ac239 Eliminats fitxers que s'havien colat 2024-10-13 11:04:50 +02:00
c11a868289 Afegides recomanacions de cppcheck
Optimitzada la funció updateBalloonSpeed() i eliminades funcions sobrants o redundants
2024-10-13 11:03:50 +02:00
22d457285d Modificat .gitignore 2024-10-13 11:03:00 +02:00
b060f21696 Arreglades les herencies de Sprite
Abans de llevar mil coses que sobren i replantejar-se estes 4 classes
2024-10-13 10:01:07 +02:00
33ea8d90ca Acabat de renamar, encara que he descobert cosetes i tindré que fer altra pasaeta
Actualitzat stb_image.h a la última versió
2024-10-12 22:25:43 +02:00
cce14dba4d Mes renames. Mes ordre. 2024-10-12 12:03:19 +02:00
101e375fd3 Variables renombrades en input.cpp 2024-10-12 11:01:42 +02:00
4ef759772a game.cpp renombrat 2024-10-12 09:15:20 +02:00
07714aabc3 Abans de renombrar game.cpp 2024-10-12 07:26:41 +02:00
d50cf23721 Abans de renombrar player.cpp 2024-10-11 21:58:59 +02:00
79 changed files with 4517 additions and 4700 deletions

1
.gitignore vendored
View File

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

View File

@@ -25,8 +25,8 @@ INCLUDES:= -I$(DIR_SOURCES)
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
FixPath = $(subst /,\,$1) FixPath = $(subst /,\,$1)
SOURCES := source/*.cpp SOURCES := source/*.cpp
CXXFLAGS:= -std=c++14 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows CXXFLAGS:= -std=c++20 -Wall -Os -ffunction-sections -fdata-sections -Wl,--gc-sections -static-libstdc++ -Wl,-subsystem,windows
CXXFLAGS_DEBUG:= -std=c++14 -Wall -g CXXFLAGS_DEBUG:= -std=c++20 -Wall -g
LDFLAGS := -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32 LDFLAGS := -lmingw32 -lws2_32 -lSDL2main -lSDL2 -lopengl32
RM = del /Q RM = del /Q
MKD:= mkdir MKD:= mkdir
@@ -34,8 +34,8 @@ else
FixPath = $1 FixPath = $1
SOURCES := $(shell find $(DIR_SOURCES) -name '*.cpp') SOURCES := $(shell find $(DIR_SOURCES) -name '*.cpp')
SOURCES := source/*.cpp SOURCES := source/*.cpp
CXXFLAGS:= -std=c++14 -Wall -Os -ffunction-sections -fdata-sections CXXFLAGS:= -std=c++20 -Wall -Os -ffunction-sections -fdata-sections
CXXFLAGS_DEBUG:= -std=c++14 -Wall -g CXXFLAGS_DEBUG:= -std=c++20 -Wall -g
LDFLAGS := -lSDL2 LDFLAGS := -lSDL2
RM = rm -f RM = rm -f
MKD:= mkdir -p MKD:= mkdir -p

View File

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

View File

@@ -1,6 +1,8 @@
#include "animated_sprite.h" #include "animated_sprite.h"
#include <algorithm> // for copy
#include <fstream> // for basic_ostream, operator<<, basic_istream, basic... #include <fstream> // for basic_ostream, operator<<, basic_istream, basic...
#include <iostream> // for cout #include <iostream> // for cout
#include <iterator> // for back_insert_iterator, back_inserter
#include <sstream> // for basic_stringstream #include <sstream> // for basic_stringstream
#include "texture.h" // for Texture #include "texture.h" // for Texture
@@ -15,7 +17,9 @@ AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string
auto frame_height = 0; auto frame_height = 0;
auto max_tiles = 0; auto max_tiles = 0;
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
std::ifstream file(file_path); std::ifstream file(file_path);
std::string line; std::string line;
@@ -35,6 +39,10 @@ AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string
buffer.counter = 0; buffer.counter = 0;
buffer.current_frame = 0; buffer.current_frame = 0;
buffer.completed = false; buffer.completed = false;
buffer.name.clear();
buffer.speed = 5;
buffer.loop = 0;
buffer.frames.clear();
do do
{ {
@@ -44,7 +52,7 @@ AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string
int pos = line.find("="); int pos = line.find("=");
// Procesa las dos subcadenas // Procesa las dos subcadenas
if (pos != (int)line.npos) if (pos != static_cast<int>(line.npos))
{ {
if (line.substr(0, pos) == "name") if (line.substr(0, pos) == "name")
{ {
@@ -152,46 +160,32 @@ AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string
} }
// Constructor // Constructor
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, std::string file, std::vector<std::string> *buffer) AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file, std::vector<std::string> *buffer)
: MovingSprite(texture),
current_animation_(0)
{ {
// Copia los punteros
setTexture(texture);
// Carga las animaciones // Carga las animaciones
if (file != "") if (!file.empty())
{ {
AnimatedFile as = loadAnimationFromFile(texture, file); AnimatedFile as = loadAnimationFromFile(texture, file);
// Copia los datos de las animaciones // Copia los datos de las animaciones
for (auto animation : as.animations) std::copy(as.animations.begin(), as.animations.end(), std::back_inserter(animations_));
{
animations_.push_back(animation);
}
} }
else if (buffer) else if (buffer)
{ {
loadFromVector(buffer); loadFromVector(buffer);
} }
// Inicializa variables
current_animation_ = 0;
} }
// Constructor // Constructor
AnimatedSprite::AnimatedSprite(AnimatedFile *animation) AnimatedSprite::AnimatedSprite(const AnimatedFile *animation)
: MovingSprite(animation->texture),
current_animation_(0)
{ {
// Copia los punteros
setTexture(animation->texture);
// Inicializa variables
current_animation_ = 0;
// Copia los datos de las animaciones // Copia los datos de las animaciones
for (auto a : animation->animations) std::copy(animation->animations.begin(), animation->animations.end(), std::back_inserter(animations_));
{
animations_.push_back(a);
}
} }
// Destructor // Destructor
@@ -201,11 +195,11 @@ AnimatedSprite::~AnimatedSprite()
} }
// Obtiene el indice de la animación a partir del nombre // Obtiene el indice de la animación a partir del nombre
int AnimatedSprite::getIndex(std::string name) int AnimatedSprite::getIndex(const std::string &name)
{ {
auto index = -1; auto index = -1;
for (auto a : animations_) for (const auto &a : animations_)
{ {
index++; index++;
if (a.name == name) if (a.name == name)
@@ -222,7 +216,7 @@ int AnimatedSprite::getIndex(std::string name)
// Calcula el frame correspondiente a la animación // Calcula el frame correspondiente a la animación
void AnimatedSprite::animate() void AnimatedSprite::animate()
{ {
if (!enabled_ || animations_[current_animation_].speed == 0) if (animations_[current_animation_].speed == 0)
{ {
return; return;
} }
@@ -280,13 +274,13 @@ void AnimatedSprite::setCurrentFrame(int num)
} }
// Establece el valor del contador // Establece el valor del contador
void AnimatedSprite::setAnimationCounter(std::string name, int num) void AnimatedSprite::setAnimationCounter(const std::string &name, int num)
{ {
animations_[getIndex(name)].counter = num; animations_[getIndex(name)].counter = num;
} }
// Establece la velocidad de una animación // Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(std::string name, int speed) void AnimatedSprite::setAnimationSpeed(const std::string &name, int speed)
{ {
animations_[getIndex(name)].counter = speed; animations_[getIndex(name)].counter = speed;
} }
@@ -298,7 +292,7 @@ void AnimatedSprite::setAnimationSpeed(int index, int speed)
} }
// Establece si la animación se reproduce en bucle // Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(std::string name, int loop) void AnimatedSprite::setAnimationLoop(const std::string &name, int loop)
{ {
animations_[getIndex(name)].loop = loop; animations_[getIndex(name)].loop = loop;
} }
@@ -310,7 +304,7 @@ void AnimatedSprite::setAnimationLoop(int index, int loop)
} }
// Establece el valor de la variable // Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(std::string name, bool value) void AnimatedSprite::setAnimationCompleted(const std::string &name, bool value)
{ {
animations_[getIndex(name)].completed = value; animations_[getIndex(name)].completed = value;
} }
@@ -328,7 +322,7 @@ bool AnimatedSprite::animationIsCompleted()
} }
// Devuelve el rectangulo de una animación y frame concreto // Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(std::string name, Uint8 index) SDL_Rect AnimatedSprite::getAnimationClip(const std::string &name, Uint8 index)
{ {
return animations_[getIndex(name)].frames[index]; return animations_[getIndex(name)].frames[index];
} }
@@ -366,6 +360,10 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
buffer.counter = 0; buffer.counter = 0;
buffer.current_frame = 0; buffer.current_frame = 0;
buffer.completed = false; buffer.completed = false;
buffer.name.clear();
buffer.speed = 5;
buffer.loop = 0;
buffer.frames.clear();
do do
{ {
@@ -377,7 +375,7 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
int pos = line.find("="); int pos = line.find("=");
// Procesa las dos subcadenas // Procesa las dos subcadenas
if (pos != (int)line.npos) if (pos != static_cast<int>(line.npos))
{ {
if (line.substr(0, pos) == "name") if (line.substr(0, pos) == "name")
{ {
@@ -476,13 +474,13 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
} }
// Pone un valor por defecto // Pone un valor por defecto
setRect({0, 0, frame_width, frame_height}); setPos((SDL_Rect){0, 0, frame_width, frame_height});
return success; return success;
} }
// Establece la animacion actual // Establece la animacion actual
void AnimatedSprite::setCurrentAnimation(std::string name) void AnimatedSprite::setCurrentAnimation(const std::string &name)
{ {
const auto new_animation = getIndex(name); const auto new_animation = getIndex(name);
if (current_animation_ != new_animation) if (current_animation_ != new_animation)
@@ -510,11 +508,8 @@ void AnimatedSprite::setCurrentAnimation(int index)
// Actualiza las variables del objeto // Actualiza las variables del objeto
void AnimatedSprite::update() void AnimatedSprite::update()
{ {
if (enabled_) animate();
{ MovingSprite::update();
animate();
MovingSprite::update();
}
} }
// Establece el rectangulo para un frame de una animación // Establece el rectangulo para un frame de una animación

View File

@@ -2,11 +2,11 @@
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint8 #include <SDL2/SDL_stdinc.h> // for Uint8
#include <string> // for string, basic_string #include <memory> // for shared_ptr
#include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "moving_sprite.h" // for MovingSprite #include "moving_sprite.h" // for MovingSprite
#include "texture.h" class Texture;
#include <memory>
struct Animation struct Animation
{ {
@@ -30,18 +30,18 @@ AnimatedFile loadAnimationFromFile(std::shared_ptr<Texture> texture, std::string
class AnimatedSprite : public MovingSprite class AnimatedSprite : public MovingSprite
{ {
private: protected:
// Variables // Variables
std::vector<Animation> animations_; // Vector con las diferentes animaciones std::vector<Animation> animations_; // Vector con las diferentes animaciones
int current_animation_; // Animacion activa int current_animation_; // Animacion activa
public: public:
// Constructor // Constructor
AnimatedSprite(std::shared_ptr<Texture> texture = nullptr, std::string file = "", std::vector<std::string> *buffer = nullptr); explicit AnimatedSprite(std::shared_ptr<Texture> texture = nullptr, const std::string &file = std::string(), std::vector<std::string> *buffer = nullptr);
AnimatedSprite(AnimatedFile *animation); explicit AnimatedSprite(const AnimatedFile *animation);
// Destructor // Destructor
~AnimatedSprite(); virtual ~AnimatedSprite();
// Calcula el frame correspondiente a la animación actual // Calcula el frame correspondiente a la animación actual
void animate(); void animate();
@@ -53,39 +53,39 @@ public:
void setCurrentFrame(int num); void setCurrentFrame(int num);
// Establece el valor del contador // Establece el valor del contador
void setAnimationCounter(std::string name, int num); void setAnimationCounter(const std::string &name, int num);
// Establece la velocidad de una animación // Establece la velocidad de una animación
void setAnimationSpeed(std::string name, int speed); void setAnimationSpeed(const std::string &name, int speed);
void setAnimationSpeed(int index, int speed); void setAnimationSpeed(int index, int speed);
// Establece el frame al que vuelve la animación al finalizar // Establece el frame al que vuelve la animación al finalizar
void setAnimationLoop(std::string name, int loop); void setAnimationLoop(const std::string &name, int loop);
void setAnimationLoop(int index, int loop); void setAnimationLoop(int index, int loop);
// Establece el valor de la variable // Establece el valor de la variable
void setAnimationCompleted(std::string name, bool value); void setAnimationCompleted(const std::string &name, bool value);
void setAnimationCompleted(int index, bool value); void setAnimationCompleted(int index, bool value);
// Comprueba si ha terminado la animación // Comprueba si ha terminado la animación
bool animationIsCompleted(); bool animationIsCompleted();
// Devuelve el rectangulo de una animación y frame concreto // Devuelve el rectangulo de una animación y frame concreto
SDL_Rect getAnimationClip(std::string name = "default", Uint8 index = 0); SDL_Rect getAnimationClip(const std::string &name = "default", Uint8 index = 0);
SDL_Rect getAnimationClip(int indexA = 0, Uint8 indexF = 0); SDL_Rect getAnimationClip(int indexA = 0, Uint8 indexF = 0);
// Obtiene el indice de la animación a partir del nombre // Obtiene el indice de la animación a partir del nombre
int getIndex(std::string name); int getIndex(const std::string &name);
// Carga la animación desde un vector // Carga la animación desde un vector
bool loadFromVector(std::vector<std::string> *source); bool loadFromVector(std::vector<std::string> *source);
// Establece la animacion actual // Establece la animacion actual
void setCurrentAnimation(std::string name = "default"); void setCurrentAnimation(const std::string &name = "default");
void setCurrentAnimation(int index = 0); void setCurrentAnimation(int index = 0);
// Actualiza las variables del objeto // Actualiza las variables del objeto
void update(); void update() override;
// OLD - Establece el rectangulo para un frame de una animación // OLD - Establece el rectangulo para un frame de una animación
void setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h); void setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h);

View File

@@ -5,35 +5,35 @@
#include <iostream> // for basic_ostream, operator<<, cout, endl #include <iostream> // for basic_ostream, operator<<, cout, endl
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Asset *Asset::asset = nullptr; Asset *Asset::asset_ = nullptr;
// [SINGLETON] Crearemos el objeto asset con esta función estática // [SINGLETON] Crearemos el objeto asset con esta función estática
void Asset::init(std::string executable_path) void Asset::init(const std::string &executable_path)
{ {
Asset::asset = new Asset(executable_path); Asset::asset_ = new Asset(executable_path);
} }
// [SINGLETON] Destruiremos el objeto asset con esta función estática // [SINGLETON] Destruiremos el objeto asset con esta función estática
void Asset::destroy() void Asset::destroy()
{ {
delete Asset::asset; delete Asset::asset_;
} }
// [SINGLETON] Con este método obtenemos el objeto asset y podemos trabajar con él // [SINGLETON] Con este método obtenemos el objeto asset y podemos trabajar con él
Asset *Asset::get() Asset *Asset::get()
{ {
return Asset::asset; return Asset::asset_;
} }
// Constructor // Constructor
Asset::Asset(std::string executable_path) Asset::Asset(const std::string &executable_path)
: executable_path_(executable_path.substr(0, executable_path.find_last_of("\\/")))
{ {
executable_path_ = executable_path.substr(0, executable_path.find_last_of("\\/"));
longest_name_ = 0; longest_name_ = 0;
} }
// Añade un elemento a la lista // Añade un elemento a la lista
void Asset::add(std::string file, AssetType type, bool required, bool absolute) void Asset::add(const std::string &file, AssetType type, bool required, bool absolute)
{ {
AssetItem ai; AssetItem ai;
ai.file = absolute ? file : executable_path_ + file; ai.file = absolute ? file : executable_path_ + file;
@@ -46,9 +46,9 @@ void Asset::add(std::string file, AssetType type, bool required, bool absolute)
} }
// Devuelve el fichero de un elemento de la lista a partir de una cadena // Devuelve el fichero de un elemento de la lista a partir de una cadena
std::string Asset::get(std::string text) const std::string Asset::get(const std::string &text) const
{ {
for (auto f : file_list_) for (const auto &f : file_list_)
{ {
const size_t last_index = f.file.find_last_of("/") + 1; const size_t last_index = f.file.find_last_of("/") + 1;
const std::string file = f.file.substr(last_index, std::string::npos); const std::string file = f.file.substr(last_index, std::string::npos);
@@ -83,7 +83,7 @@ bool Asset::check() const
// Comprueba si hay ficheros de ese tipo // Comprueba si hay ficheros de ese tipo
bool any = false; bool any = false;
for (auto f : file_list_) for (const auto &f : file_list_)
{ {
if (f.required && f.type == static_cast<AssetType>(type)) if (f.required && f.type == static_cast<AssetType>(type))
{ {
@@ -98,7 +98,7 @@ bool Asset::check() const
std::cout << "\n>> " << getTypeName(static_cast<AssetType>(type)).c_str() << " FILES" << std::endl; std::cout << "\n>> " << getTypeName(static_cast<AssetType>(type)).c_str() << " FILES" << std::endl;
#endif #endif
for (auto f : file_list_) for (const auto &f : file_list_)
{ {
if (f.required && f.type == static_cast<AssetType>(type)) if (f.required && f.type == static_cast<AssetType>(type))
{ {
@@ -117,29 +117,27 @@ bool Asset::check() const
} }
// Comprueba que existe un fichero // Comprueba que existe un fichero
bool Asset::checkFile(std::string path) const bool Asset::checkFile(const std::string &path) const
{ {
bool success = false; auto success = false;
std::string result = "ERROR";
// Comprueba si existe el fichero // Comprueba si existe el fichero
const std::string file_name = path.substr(path.find_last_of("\\/") + 1); auto file = SDL_RWFromFile(path.c_str(), "rb");
SDL_RWops *file = SDL_RWFromFile(path.c_str(), "rb");
if (file != nullptr) if (file)
{ {
result = "OK";
success = true; success = true;
SDL_RWclose(file); SDL_RWclose(file);
} }
#ifdef VERBOSE #ifdef VERBOSE
const std::string file_name = path.substr(path.find_last_of("\\/") + 1);
std::cout.setf(std::ios::left, std::ios::adjustfield); std::cout.setf(std::ios::left, std::ios::adjustfield);
std::cout << "Checking file: "; std::cout << "Checking file: ";
std::cout.width(longest_name_ + 2); std::cout.width(longest_name_ + 2);
std::cout.fill('.'); std::cout.fill('.');
std::cout << file_name + " "; std::cout << file_name;
std::cout << " [" + result + "]" << std::endl; std::cout << (success ? " [OK]" : " [ERROR]") << std::endl;
#endif #endif
return success; return success;

View File

@@ -1,7 +1,7 @@
#pragma once #pragma once
#include <string> // for string, basic_string #include <string> // for string, basic_string
#include <vector> // for vector #include <vector> // for vector
enum class AssetType : int enum class AssetType : int
{ {
@@ -22,7 +22,7 @@ class Asset
{ {
private: private:
// [SINGLETON] Objeto asset privado para Don Melitón // [SINGLETON] Objeto asset privado para Don Melitón
static Asset *asset; static Asset *asset_;
// Estructura para definir un item // Estructura para definir un item
struct AssetItem struct AssetItem
@@ -34,25 +34,25 @@ private:
}; };
// Variables // Variables
int longest_name_; // Contiene la longitud del nombre de fichero mas largo int longest_name_; // Contiene la longitud del nombre de fichero mas largo
std::vector<AssetItem> file_list_; // Listado con todas las rutas a los ficheros std::vector<AssetItem> file_list_; // Listado con todas las rutas a los ficheros
std::string executable_path_; // Ruta al ejecutable std::string executable_path_; // Ruta al ejecutable
// Comprueba que existe un fichero // Comprueba que existe un fichero
bool checkFile(std::string executable_path) const; bool checkFile(const std::string &path) const;
// Devuelve el nombre del tipo de recurso // Devuelve el nombre del tipo de recurso
std::string getTypeName(AssetType type) const; std::string getTypeName(AssetType type) const;
// Constructor // Constructor
Asset(std::string path); explicit Asset(const std::string &executable_path);
// Destructor // Destructor
~Asset() = default; ~Asset() = default;
public: public:
// [SINGLETON] Crearemos el objeto screen con esta función estática // [SINGLETON] Crearemos el objeto screen con esta función estática
static void init(std::string path); static void init(const std::string &executable_path);
// [SINGLETON] Destruiremos el objeto screen con esta función estática // [SINGLETON] Destruiremos el objeto screen con esta función estática
static void destroy(); static void destroy();
@@ -61,10 +61,10 @@ public:
static Asset *get(); static Asset *get();
// Añade un elemento a la lista // Añade un elemento a la lista
void add(std::string file, AssetType type, bool required = true, bool absolute = false); void add(const std::string &file, AssetType type, bool required = true, bool absolute = false);
// Devuelve un elemento de la lista a partir de una cadena // Devuelve un elemento de la lista a partir de una cadena
std::string get(std::string text) const; std::string get(const std::string &text) const;
// Comprueba que existen todos los elementos // Comprueba que existen todos los elementos
bool check() const; bool check() const;

View File

@@ -1,22 +1,23 @@
#include "background.h" #include "background.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <algorithm> // for max, min #include <algorithm> // for clamp, max
#include <string> // for basic_string #include "asset.h" // for Asset
#include "asset.h" // for Asset #include "moving_sprite.h" // for MovingSprite
#include "param.h" // for param #include "param.h" // for param
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
// Constructor // Constructor
Background::Background(SDL_Renderer *renderer) Background::Background(SDL_Renderer *renderer)
: renderer_(renderer) : renderer_(renderer),
{ buildings_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_buildings.png"))),
// Carga las texturas top_clouds_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_clouds1.png"))),
buildings_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("game_buildings.png")); bottom_clouds_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_clouds2.png"))),
top_clouds_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("game_clouds1.png")); grass_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_grass.png"))),
bottom_clouds_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("game_clouds2.png")); gradients_texture_(std::make_shared<Texture>(renderer, Asset::get()->get("game_sky_colors.png")))
grass_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("game_grass.png"));
gradients_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("game_sky_colors.png"));
{
// Inicializa variables // Inicializa variables
gradient_number_ = 0; gradient_number_ = 0;
alpha_ = 0; alpha_ = 0;
@@ -104,18 +105,19 @@ void Background::update()
// Incrementa el contador // Incrementa el contador
counter_++; counter_++;
// Compone todos los elementos del fondo en la textura
fillCanvas(); fillCanvas();
} }
// Dibuja el gradiente de fondo // Dibuja el gradiente de fondo
void Background::renderGradient() void Background::renderGradient()
{ {
// Dibuja el gradiente 2 // Dibuja el gradiente de detras
gradients_texture_->setAlpha(255); gradients_texture_->setAlpha(255);
gradient_sprite_->setSpriteClip(gradient_rect_[(gradient_number_ + 1) % 4]); gradient_sprite_->setSpriteClip(gradient_rect_[(gradient_number_ + 1) % 4]);
gradient_sprite_->render(); gradient_sprite_->render();
// Dibuja el gradiente 1 con una opacidad cada vez menor // Dibuja el gradiente de delante con una opacidad cada vez menor
gradients_texture_->setAlpha(alpha_); gradients_texture_->setAlpha(alpha_);
gradient_sprite_->setSpriteClip(gradient_rect_[gradient_number_]); gradient_sprite_->setSpriteClip(gradient_rect_[gradient_number_]);
gradient_sprite_->render(); gradient_sprite_->render();
@@ -124,36 +126,36 @@ void Background::renderGradient()
// Dibuja las nubes de arriba // Dibuja las nubes de arriba
void Background::renderTopClouds() void Background::renderTopClouds()
{ {
// Dibuja el primer conjunto de nubes // Dibuja el primer conjunto de nubes, las de detras
top_clouds_texture_->setAlpha(255); top_clouds_texture_->setAlpha(255);
top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]); top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]);
top_clouds_sprite_a_->render();
top_clouds_sprite_b_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]); top_clouds_sprite_b_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]);
top_clouds_sprite_a_->render();
top_clouds_sprite_b_->render(); top_clouds_sprite_b_->render();
// Dibuja el segundo conjunto de nubes // Dibuja el segundo conjunto de nubes, las de delante
top_clouds_texture_->setAlpha(alpha_); top_clouds_texture_->setAlpha(alpha_);
top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[gradient_number_]); top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[gradient_number_]);
top_clouds_sprite_a_->render();
top_clouds_sprite_b_->setSpriteClip(top_clouds_rect_[gradient_number_]); top_clouds_sprite_b_->setSpriteClip(top_clouds_rect_[gradient_number_]);
top_clouds_sprite_a_->render();
top_clouds_sprite_b_->render(); top_clouds_sprite_b_->render();
} }
// Dibuja las nubes de abajo // Dibuja las nubes de abajo
void Background::renderBottomClouds() void Background::renderBottomClouds()
{ {
// Dibuja el primer conjunto de nubes // Dibuja el primer conjunto de nubes, las de detras
bottom_clouds_texture_->setAlpha(255); bottom_clouds_texture_->setAlpha(255);
bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]); bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]);
bottom_clouds_sprite_a_->render();
bottom_clouds_sprite_b_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]); bottom_clouds_sprite_b_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]);
bottom_clouds_sprite_a_->render();
bottom_clouds_sprite_b_->render(); bottom_clouds_sprite_b_->render();
// Dibuja el segundo conjunto de nubes // Dibuja el segundo conjunto de nubes, las de delante
bottom_clouds_texture_->setAlpha(alpha_); bottom_clouds_texture_->setAlpha(alpha_);
bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[gradient_number_]); bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[gradient_number_]);
bottom_clouds_sprite_a_->render();
bottom_clouds_sprite_b_->setSpriteClip(bottom_clouds_rect_[gradient_number_]); bottom_clouds_sprite_b_->setSpriteClip(bottom_clouds_rect_[gradient_number_]);
bottom_clouds_sprite_a_->render();
bottom_clouds_sprite_b_->render(); bottom_clouds_sprite_b_->render();
} }
@@ -218,9 +220,7 @@ void Background::setGradientNumber(int value)
// Ajusta el valor de la variable // Ajusta el valor de la variable
void Background::setTransition(float value) void Background::setTransition(float value)
{ {
value = std::min(value, 1.0f); transition_ = std::clamp(value, 0.0f, 1.0f);
value = std::max(value, 0.0f);
transition_ = value;
} }
// Establece la posición del objeto // Establece la posición del objeto
@@ -266,13 +266,10 @@ void Background::setColor(Color color)
void Background::setAlpha(int alpha) void Background::setAlpha(int alpha)
{ {
// Evita que se asignen valores fuera de rango // Evita que se asignen valores fuera de rango
alpha_ = std::min(alpha, 255); alpha_ = std::clamp(alpha, 0, 255);
alpha_ = std::max(alpha, 0);
// Guarda el valor actual // Guarda el valor actual y establece el nuevo valor
alpha_color_text_temp_ = alpha_color_text_; alpha_color_text_temp_ = alpha_color_text_;
// Establece el nuevo valor
alpha_color_text_ = alpha_; alpha_color_text_ = alpha_;
} }

View File

@@ -1,12 +1,12 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include "utils.h" // for Color #include <memory> // for unique_ptr, shared_ptr
#include "moving_sprite.h" #include "utils.h" // for Color
#include "sprite.h" class MovingSprite;
#include "texture.h" class Sprite;
#include <memory> class Texture;
/* /*
Esta clase es la encargada de dibujar el fondo que aparece durante la sección Esta clase es la encargada de dibujar el fondo que aparece durante la sección
@@ -107,7 +107,7 @@ private:
public: public:
// Constructor // Constructor
Background(SDL_Renderer *renderer); explicit Background(SDL_Renderer *renderer);
// Destructor // Destructor
~Background(); ~Background();

View File

@@ -1,5 +1,5 @@
#include "balloon.h" #include "balloon.h"
#include <math.h> // for abs #include <cmath> // for abs
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for AnimatedSprite
#include "moving_sprite.h" // for MovingSprite #include "moving_sprite.h" // for MovingSprite
#include "param.h" // for param #include "param.h" // for param
@@ -8,11 +8,24 @@
// Constructor // Constructor
Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr<Texture> texture, std::vector<std::string> *animation) Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16 creation_timer, std::shared_ptr<Texture> texture, std::vector<std::string> *animation)
: kind_(kind), speed_(speed) : sprite_(std::make_unique<AnimatedSprite>(texture, "", animation)),
pos_x_(x),
pos_y_(y),
vel_x_(vel_x),
being_created_(creation_timer > 0),
blinking_(false),
enabled_(true),
invulnerable_(creation_timer > 0),
stopped_(true),
visible_(true),
creation_counter_(creation_timer),
creation_counter_ini_(creation_timer),
stopped_counter_(0),
kind_(kind),
counter_(0),
travel_y_(1.0f),
speed_(speed)
{ {
sprite_ = std::make_unique<AnimatedSprite>(texture, "", animation);
enabled_ = true;
switch (kind_) switch (kind_)
{ {
@@ -24,7 +37,6 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 1; power_ = 1;
// Inicializa los valores de velocidad y gravedad // Inicializa los valores de velocidad y gravedad
vel_x_ = vel_x;
vel_y_ = 0; vel_y_ = 0;
max_vel_y_ = 3.0f; max_vel_y_ = 3.0f;
gravity_ = param.balloon_1.grav; gravity_ = param.balloon_1.grav;
@@ -46,7 +58,6 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 3; power_ = 3;
// Inicializa los valores de velocidad y gravedad // Inicializa los valores de velocidad y gravedad
vel_x_ = vel_x;
vel_y_ = 0; vel_y_ = 0;
max_vel_y_ = 3.0f; max_vel_y_ = 3.0f;
gravity_ = param.balloon_2.grav; gravity_ = param.balloon_2.grav;
@@ -68,7 +79,6 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 7; power_ = 7;
// Inicializa los valores de velocidad y gravedad // Inicializa los valores de velocidad y gravedad
vel_x_ = vel_x;
vel_y_ = 0; vel_y_ = 0;
max_vel_y_ = 3.0f; max_vel_y_ = 3.0f;
gravity_ = param.balloon_3.grav; gravity_ = param.balloon_3.grav;
@@ -90,7 +100,6 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 15; power_ = 15;
// Inicializa los valores de velocidad y gravedad // Inicializa los valores de velocidad y gravedad
vel_x_ = vel_x;
vel_y_ = 0; vel_y_ = 0;
max_vel_y_ = 3.0f; max_vel_y_ = 3.0f;
gravity_ = param.balloon_4.grav; gravity_ = param.balloon_4.grav;
@@ -112,7 +121,6 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 1; power_ = 1;
// Inicializa los valores de velocidad y gravedad // Inicializa los valores de velocidad y gravedad
vel_x_ = vel_x;
vel_y_ = abs(vel_x) * 2; vel_y_ = abs(vel_x) * 2;
max_vel_y_ = abs(vel_x) * 2; max_vel_y_ = abs(vel_x) * 2;
gravity_ = 0.00f; gravity_ = 0.00f;
@@ -134,7 +142,6 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 3; power_ = 3;
// Inicializa los valores de velocidad y gravedad // Inicializa los valores de velocidad y gravedad
vel_x_ = vel_x;
vel_y_ = abs(vel_x) * 2; vel_y_ = abs(vel_x) * 2;
max_vel_y_ = abs(vel_x) * 2; max_vel_y_ = abs(vel_x) * 2;
gravity_ = 0.00f; gravity_ = 0.00f;
@@ -156,7 +163,6 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 7; power_ = 7;
// Inicializa los valores de velocidad y gravedad // Inicializa los valores de velocidad y gravedad
vel_x_ = vel_x;
vel_y_ = abs(vel_x) * 2; vel_y_ = abs(vel_x) * 2;
max_vel_y_ = abs(vel_x) * 2; max_vel_y_ = abs(vel_x) * 2;
gravity_ = 0.00f; gravity_ = 0.00f;
@@ -178,7 +184,6 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 15; power_ = 15;
// Inicializa los valores de velocidad y gravedad // Inicializa los valores de velocidad y gravedad
vel_x_ = vel_x;
vel_y_ = abs(vel_x) * 2; vel_y_ = abs(vel_x) * 2;
max_vel_y_ = abs(vel_x) * 2; max_vel_y_ = abs(vel_x) * 2;
gravity_ = 0.00f; gravity_ = 0.00f;
@@ -200,7 +205,6 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
power_ = 0; power_ = 0;
// Inicializa los valores de velocidad y gravedad // Inicializa los valores de velocidad y gravedad
vel_x_ = vel_x;
vel_y_ = 0; vel_y_ = 0;
max_vel_y_ = 3.0f; max_vel_y_ = 3.0f;
gravity_ = param.balloon_4.grav; gravity_ = param.balloon_4.grav;
@@ -223,10 +227,6 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
break; break;
} }
// Posición inicial
pos_x_ = x;
pos_y_ = y;
// Valores para el efecto de rebote // Valores para el efecto de rebote
bouncing_.enabled = false; bouncing_.enabled = false;
bouncing_.counter = 0; bouncing_.counter = 0;
@@ -251,23 +251,6 @@ Balloon::Balloon(float x, float y, Uint8 kind, float vel_x, float speed, Uint16
// Alinea el circulo de colisión con el objeto // Alinea el circulo de colisión con el objeto
updateColliders(); updateColliders();
// Inicializa variables
stopped_ = true;
stopped_counter_ = 0;
blinking_ = false;
visible_ = true;
invulnerable_ = true;
being_created_ = true;
creation_counter_ = creation_timer;
creation_counter_ini_ = creation_timer;
// Actualiza valores
being_created_ = creation_counter_ == 0 ? false : true;
invulnerable_ = being_created_ == false ? false : true;
counter_ = 0;
travel_y_ = 1.0f;
} }
// Centra el globo en la posición X // Centra el globo en la posición X
@@ -323,7 +306,7 @@ void Balloon::render()
if (kind_ == POWER_BALL && !isBeingCreated()) if (kind_ == POWER_BALL && !isBeingCreated())
{ {
auto sp = std::make_unique<Sprite>(sprite_->getRect(), sprite_->getTexture()); auto sp = std::make_unique<Sprite>(sprite_->getPos(), sprite_->getTexture());
sp->setSpriteClip(BALLOON_WIDTH_4, 0, BALLOON_WIDTH_4, BALLOON_WIDTH_4); sp->setSpriteClip(BALLOON_WIDTH_4, 0, BALLOON_WIDTH_4, BALLOON_WIDTH_4);
sp->render(); sp->render();
} }

View File

@@ -1,12 +1,12 @@
#pragma once #pragma once
#include <SDL2/SDL_stdinc.h> // for Uint8, Uint16, Uint32 #include <SDL2/SDL_stdinc.h> // for Uint8, Uint16, Uint32
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include <memory> #include "animated_sprite.h" // for AnimatedSprite
#include "utils.h" // for Circle #include "utils.h" // for Circle
#include "animated_sprite.h" class Texture;
#include "texture.h"
// Cantidad de elementos del vector con los valores de la deformación del globo al rebotar // Cantidad de elementos del vector con los valores de la deformación del globo al rebotar
constexpr int MAX_BOUNCE = 10; constexpr int MAX_BOUNCE = 10;

View File

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

View File

@@ -0,0 +1,63 @@
#pragma once
constexpr int NUMBER_OF_BALLOON_FORMATIONS = 100;
constexpr int MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION = 50;
// Estructuras
struct BalloonFormationParams
{
int x; // Posición en el eje X donde crear al enemigo
int y; // Posición en el eje Y donde crear al enemigo
float vel_x; // Velocidad inicial en el eje X
int kind; // Tipo de enemigo
int creation_counter; // Temporizador para la creación del enemigo
};
struct BalloonFormationUnit // Contiene la información de una formación enemiga
{
int number_of_balloons; // Cantidad de enemigos que forman la formación
BalloonFormationParams init[MAX_NUMBER_OF_BALLOONS_IN_A_FORMATION]; // Vector con todas las inicializaciones de los enemigos de la formación
};
struct BalloonFormationPool
{
BalloonFormationUnit *set[10]; // Conjunto de formaciones de globos
};
struct Stage // Contiene todas las variables relacionadas con una fase
{
BalloonFormationPool *balloon_pool; // El conjunto de formaciones de globos de la fase
int power_to_complete; // Cantidad de poder que se necesita para completar la fase
int max_menace; // Umbral máximo de amenaza de la fase
int min_menace; // Umbral mínimo de amenaza de la fase
int number; // Número de fase
};
// Clase BalloonFormations, para gestionar las formaciones de globos
class BalloonFormations
{
private:
// Variables
Stage stage_[10]; // Variable con los datos de cada pantalla
BalloonFormationUnit balloon_formation_[NUMBER_OF_BALLOON_FORMATIONS]; // Vector con todas las formaciones enemigas
BalloonFormationPool balloon_formation_pool_[10]; // Variable con los diferentes conjuntos de formaciones enemigas
// Inicializa las formaciones enemigas
void initBalloonFormations();
// Inicializa los conjuntos de formaciones
void initBalloonFormationPools();
// Inicializa las fases del juego
void initGameStages();
public:
// Constructor
BalloonFormations();
// Destructor
~BalloonFormations() = default;
// Devuelve una fase
Stage getStage(int index) const;
};

View File

@@ -1,9 +1,9 @@
#include "bullet.h" #include "bullet.h"
#include "param.h" // for param #include <memory> // for unique_ptr, make_unique, shared_ptr
#include "sprite.h" // for Sprite #include "param.h" // for param
#include <memory> // for std::unique_ptr #include "sprite.h" // for Sprite
class Texture;
// Constantes evaluables en tiempo de compilación
constexpr int BULLET_WIDTH = 12; constexpr int BULLET_WIDTH = 12;
constexpr int BULLET_HEIGHT = 12; constexpr int BULLET_HEIGHT = 12;
constexpr int BULLET_VELY = -3; constexpr int BULLET_VELY = -3;
@@ -11,16 +11,23 @@ constexpr int BULLET_VELX_LEFT = -2;
constexpr int BULLET_VELX_RIGHT = 2; constexpr int BULLET_VELX_RIGHT = 2;
// Constructor // Constructor
Bullet::Bullet(int x, int y, BulletType kind_, bool poweredUp, int owner, SDL_Rect *play_area, std::shared_ptr<Texture> texture) Bullet::Bullet(int x, int y, BulletType kind, bool powered_up, int owner, SDL_Rect *play_area, std::shared_ptr<Texture> texture)
: pos_x_(x), pos_y_(y), width_(BULLET_WIDTH), height_(BULLET_HEIGHT), vel_x_(0), vel_y_(BULLET_VELY), : sprite_(std::make_unique<Sprite>(SDL_Rect{x, y, BULLET_WIDTH, BULLET_HEIGHT}, texture)),
kind_(kind_), owner_(owner), play_area_(play_area) pos_x_(x),
pos_y_(y),
width_(BULLET_WIDTH),
height_(BULLET_HEIGHT),
vel_x_(0),
vel_y_(BULLET_VELY),
kind_(kind),
owner_(owner),
play_area_(play_area)
{ {
vel_x_ = (kind_ == BulletType::LEFT) ? BULLET_VELX_LEFT : (kind_ == BulletType::RIGHT) ? BULLET_VELX_RIGHT vel_x_ = (kind_ == BulletType::LEFT) ? BULLET_VELX_LEFT : (kind_ == BulletType::RIGHT) ? BULLET_VELX_RIGHT
: 0; : 0;
auto sprite_offset = poweredUp ? 3 : 0; auto sprite_offset = powered_up ? 3 : 0;
auto kind_index = static_cast<int>(kind_); auto kind_index = static_cast<int>(kind);
sprite_ = std::make_unique<Sprite>(SDL_Rect{x, y, BULLET_WIDTH, BULLET_HEIGHT}, texture);
sprite_->setSpriteClip((kind_index + sprite_offset) * width_, 0, sprite_->getWidth(), sprite_->getHeight()); sprite_->setSpriteClip((kind_index + sprite_offset) * width_, 0, sprite_->getWidth(), sprite_->getHeight());
collider_.r = width_ / 2; collider_.r = width_ / 2;
@@ -59,12 +66,12 @@ BulletMoveStatus Bullet::move()
bool Bullet::isEnabled() const bool Bullet::isEnabled() const
{ {
return kind_ != BulletType::NULL_TYPE; return kind_ != BulletType::NONE;
} }
void Bullet::disable() void Bullet::disable()
{ {
kind_ = BulletType::NULL_TYPE; kind_ = BulletType::NONE;
} }
int Bullet::getPosX() const int Bullet::getPosX() const

View File

@@ -1,11 +1,11 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint8 #include <SDL2/SDL_stdinc.h> // for Uint8
#include <memory> // for unique_ptr #include <memory> // for shared_ptr, unique_ptr
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "utils.h" // for Circle #include "utils.h" // for Circle
#include "texture.h" // lines 9-9 class Texture;
// Enumeración para los diferentes tipos de balas // Enumeración para los diferentes tipos de balas
enum class BulletType enum class BulletType
@@ -13,7 +13,7 @@ enum class BulletType
UP, UP,
LEFT, LEFT,
RIGHT, RIGHT,
NULL_TYPE NONE
}; };
// Enumeración para los resultados del movimiento de la bala // Enumeración para los resultados del movimiento de la bala
@@ -27,18 +27,21 @@ enum class BulletMoveStatus : Uint8
class Bullet class Bullet
{ {
private: private:
int pos_x_; // Posición en el eje X
int pos_y_; // Posición en el eje Y
Uint8 width_; // Ancho del objeto
Uint8 height_; // Alto del objeto
int vel_x_; // Velocidad en el eje X
int vel_y_; // Velocidad en el eje Y
BulletType kind_; // Tipo de objeto
int owner_; // Identificador del dueño del objeto
Circle collider_; // Círculo de colisión del objeto
SDL_Rect *play_area_; // Rectángulo con la zona de juego
std::unique_ptr<Sprite> sprite_; // Sprite con los gráficos y métodos de pintado std::unique_ptr<Sprite> sprite_; // Sprite con los gráficos y métodos de pintado
int pos_x_; // Posición en el eje X
int pos_y_; // Posición en el eje Y
Uint8 width_; // Ancho del objeto
Uint8 height_; // Alto del objeto
int vel_x_; // Velocidad en el eje X
int vel_y_; // Velocidad en el eje Y
BulletType kind_; // Tipo de objeto
int owner_; // Identificador del dueño del objeto
Circle collider_; // Círculo de colisión del objeto
SDL_Rect *play_area_; // Rectángulo con la zona de juego
void shiftColliders(); // Alinea el círculo de colisión con el objeto void shiftColliders(); // Alinea el círculo de colisión con el objeto
public: public:

View File

@@ -1,10 +1,12 @@
#include "define_buttons.h" #include "define_buttons.h"
#include "lang.h" // for getText #include <utility> // for move
#include "options.h" // for options #include "input.h" // for Input, InputType
#include "param.h" // for param #include "lang.h" // for getText
#include "section.h" // for name, SectionName, options, SectionOptions #include "options.h" // for options
#include "text.h" // for Text #include "param.h" // for param
#include "utils.h" // for OptionsController, Options, Param, ParamGame #include "section.h" // for Name, Options, name, options
#include "text.h" // for Text
#include "utils.h" // for OptionsController, Options, Param, ParamGame
// Constructor // Constructor
DefineButtons::DefineButtons(std::unique_ptr<Text> text_) DefineButtons::DefineButtons(std::unique_ptr<Text> text_)
@@ -24,27 +26,27 @@ DefineButtons::DefineButtons(std::unique_ptr<Text> text_)
DefineButtonsButton button; DefineButtonsButton button;
button.label = lang::getText(95); button.label = lang::getText(95);
button.input = input_fire_left; button.input = InputType::FIRE_LEFT;
button.button = SDL_CONTROLLER_BUTTON_X; button.button = SDL_CONTROLLER_BUTTON_X;
buttons_.push_back(button); buttons_.push_back(button);
button.label = lang::getText(96); button.label = lang::getText(96);
button.input = input_fire_center; button.input = InputType::FIRE_CENTER;
button.button = SDL_CONTROLLER_BUTTON_Y; button.button = SDL_CONTROLLER_BUTTON_Y;
buttons_.push_back(button); buttons_.push_back(button);
button.label = lang::getText(97); button.label = lang::getText(97);
button.input = input_fire_right; button.input = InputType::FIRE_RIGHT;
button.button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER; button.button = SDL_CONTROLLER_BUTTON_RIGHTSHOULDER;
buttons_.push_back(button); buttons_.push_back(button);
button.label = lang::getText(98); button.label = lang::getText(98);
button.input = input_start; button.input = InputType::START;
button.button = SDL_CONTROLLER_BUTTON_START; button.button = SDL_CONTROLLER_BUTTON_START;
buttons_.push_back(button); buttons_.push_back(button);
button.label = lang::getText(99); button.label = lang::getText(99);
button.input = input_exit; button.input = InputType::EXIT;
button.button = SDL_CONTROLLER_BUTTON_BACK; button.button = SDL_CONTROLLER_BUTTON_BACK;
buttons_.push_back(button); buttons_.push_back(button);
@@ -155,7 +157,7 @@ void DefineButtons::incIndexButton()
// Guarda los cambios en las opciones // Guarda los cambios en las opciones
saveBindingsToOptions(); saveBindingsToOptions();
input_->allActive(index_controller_); //input_->allActive(index_controller_);
// Reinicia variables // Reinicia variables
index_button_ = 0; index_button_ = 0;

View File

@@ -1,17 +1,18 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_ControllerButtonEvent #include <SDL2/SDL_events.h> // for SDL_ControllerButtonEvent
#include <SDL2/SDL_gamecontroller.h> // for SDL_GameControllerButton #include <SDL2/SDL_gamecontroller.h> // for SDL_GameControllerButton
#include <string> // for string, basic_string #include <memory> // for shared_ptr, unique_ptr
#include <vector> // for vector #include <string> // for string
#include "input.h" // for inputs_e #include <vector> // for vector
#include "text.h" class Input;
#include <memory> class Text;
enum class InputType : int;
struct DefineButtonsButton struct DefineButtonsButton
{ {
std::string label; // Texto en pantalla para el botón std::string label; // Texto en pantalla para el botón
inputs_e input; // Input asociado InputType input; // Input asociado
SDL_GameControllerButton button; // Botón del mando correspondiente SDL_GameControllerButton button; // Botón del mando correspondiente
}; };
@@ -46,7 +47,7 @@ private:
public: public:
// Constructor // Constructor
DefineButtons(std::unique_ptr<Text> text); explicit DefineButtons(std::unique_ptr<Text> text);
// Destructor // Destructor
~DefineButtons() = default; ~DefineButtons() = default;

View File

@@ -5,43 +5,44 @@
#include <SDL2/SDL_error.h> // for SDL_GetError #include <SDL2/SDL_error.h> // for SDL_GetError
#include <SDL2/SDL_gamecontroller.h> // for SDL_CONTROLLER_BUTTON_B, SDL_CO... #include <SDL2/SDL_gamecontroller.h> // for SDL_CONTROLLER_BUTTON_B, SDL_CO...
#include <SDL2/SDL_hints.h> // for SDL_SetHint, SDL_HINT_RENDER_DR... #include <SDL2/SDL_hints.h> // for SDL_SetHint, SDL_HINT_RENDER_DR...
#include <SDL2/SDL_scancode.h> // for SDL_SCANCODE_DOWN, SDL_SCANCODE_E #include <SDL2/SDL_scancode.h> // for SDL_SCANCODE_0, SDL_SCANCODE_DOWN
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <SDL2/SDL_stdinc.h> // for SDL_bool, Uint32
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <errno.h> // for errno, EACCES, EEXIST, ENAMETOO... #include <errno.h> // for errno, EEXIST, EACCES, ENAMETOO...
#include <stdio.h> // for printf, perror, size_t #include <stdio.h> // for printf, perror
#include <string.h> // for strcmp #include <string.h> // for strcmp
#include <sys/stat.h> // for stat, mkdir, S_IRWXU #include <sys/stat.h> // for mkdir, stat, S_IRWXU
#include <unistd.h> // for getuid #include <unistd.h> // for getuid
#include <cstdlib> // for exit, EXIT_FAILURE, rand, srand #include <cstdlib> // for exit, EXIT_FAILURE, rand, srand
#include <iostream> // for basic_ostream, operator<<, cout #include <iostream> // for basic_ostream, operator<<, cout
#include <string> // for basic_string, operator+, allocator #include <memory> // for make_unique, unique_ptr
#include "asset.h" // for Asset, assetType #include <string> // for operator+, allocator, char_traits
#include "asset.h" // for Asset, AssetType
#include "dbgtxt.h" // for dbg_init #include "dbgtxt.h" // for dbg_init
#include "game.h" // for Game, GAME_MODE_DEMO_OFF, GAME_... #include "game.h" // for Game, GAME_MODE_DEMO_OFF, GAME_...
#include "global_inputs.h" #include "global_inputs.h" // for init
#include "hiscore_table.h" // for HiScoreTable #include "hiscore_table.h" // for HiScoreTable
#include "input.h" // for inputs_e, Input #include "input.h" // for Input, InputType
#include "instructions.h" // for Instructions #include "instructions.h" // for Instructions
#include "intro.h" // for Intro #include "intro.h" // for Intro
#include "jail_audio.h" // for JA_DeleteMusic, JA_DeleteSound #include "jail_audio.h" // for JA_LoadMusic, JA_LoadSound, JA_...
#include "logo.h" // for Logo #include "lang.h" // for Code, loadFromFile
#include "manage_hiscore_table.h" // for ManageHiScoreTable #include "logo.h" // for Logo
#include "on_screen_help.h" // for OnScreenHelp #include "manage_hiscore_table.h" // for ManageHiScoreTable
#include "options.h" // for options, loadOptionsFile, saveO... #include "on_screen_help.h" // for OnScreenHelp
#include "param.h" // for param, loadParamsFromFile #include "options.h" // for options, loadOptionsFile, saveO...
#include "screen.h" // for Screen #include "param.h" // for param, loadParamsFromFile
#include "section.h" // for SectionName, name, options, SectionOptions #include "screen.h" // for Screen
#include "title.h" // for Title #include "section.h" // for Name, name, Options, options
#include "utils.h" // for MusicFile, SoundFile, opt... #include "title.h" // for Title
#include <memory> #include "utils.h" // for MusicFile, SoundFile, Options
#ifndef _WIN32 #ifndef _WIN32
#include <pwd.h> // for getpwuid, passwd #include <pwd.h> // for getpwuid, passwd
#endif #endif
// Constructor // Constructor
Director::Director(int argc, char *argv[]) Director::Director(int argc, const char *argv[])
{ {
#ifdef RECORDING #ifdef RECORDING
section::name = section::Name::GAME; section::name = section::Name::GAME;
@@ -93,7 +94,7 @@ Director::Director(int argc, char *argv[])
dbg_init(renderer_); dbg_init(renderer_);
// Crea los objetos // Crea los objetos
lang::loadFromFile(getLangFile((lang::lang_e)options.game.language)); lang::loadFromFile(getLangFile((lang::Code)options.game.language));
Input::init(Asset::get()->get("gamecontrollerdb.txt")); Input::init(Asset::get()->get("gamecontrollerdb.txt"));
initInput(); initInput();
@@ -132,69 +133,63 @@ Director::~Director()
/// Inicializa el objeto input /// Inicializa el objeto input
void Director::initInput() void Director::initInput()
{ {
// Establece si ha de mostrar mensajes
#ifdef VERBOSE
Input::get()->setVerbose(true);
#else
Input::get()->setVerbose(false);
#endif
// Busca si hay mandos conectados // Busca si hay mandos conectados
Input::get()->discoverGameControllers(); Input::get()->discoverGameControllers();
// Teclado - Movimiento del jugador // Teclado - Movimiento del jugador
Input::get()->bindKey(input_up, SDL_SCANCODE_UP); Input::get()->bindKey(InputType::UP, SDL_SCANCODE_UP);
Input::get()->bindKey(input_down, SDL_SCANCODE_DOWN); Input::get()->bindKey(InputType::DOWN, SDL_SCANCODE_DOWN);
Input::get()->bindKey(input_left, SDL_SCANCODE_LEFT); Input::get()->bindKey(InputType::LEFT, SDL_SCANCODE_LEFT);
Input::get()->bindKey(input_right, SDL_SCANCODE_RIGHT); Input::get()->bindKey(InputType::RIGHT, SDL_SCANCODE_RIGHT);
Input::get()->bindKey(input_fire_left, SDL_SCANCODE_Q); Input::get()->bindKey(InputType::FIRE_LEFT, SDL_SCANCODE_Q);
Input::get()->bindKey(input_fire_center, SDL_SCANCODE_W); Input::get()->bindKey(InputType::FIRE_CENTER, SDL_SCANCODE_W);
Input::get()->bindKey(input_fire_right, SDL_SCANCODE_E); Input::get()->bindKey(InputType::FIRE_RIGHT, SDL_SCANCODE_E);
Input::get()->bindKey(input_start, SDL_SCANCODE_RETURN); Input::get()->bindKey(InputType::START, SDL_SCANCODE_RETURN);
// Teclado - Control del programa // Teclado - Control del programa
Input::get()->bindKey(input_service, SDL_SCANCODE_0); Input::get()->bindKey(InputType::SERVICE, SDL_SCANCODE_0);
Input::get()->bindKey(input_exit, SDL_SCANCODE_ESCAPE); Input::get()->bindKey(InputType::EXIT, SDL_SCANCODE_ESCAPE);
Input::get()->bindKey(input_pause, SDL_SCANCODE_P); Input::get()->bindKey(InputType::PAUSE, SDL_SCANCODE_P);
Input::get()->bindKey(input_window_dec_size, SDL_SCANCODE_F1); Input::get()->bindKey(InputType::WINDOW_DEC_SIZE, SDL_SCANCODE_F1);
Input::get()->bindKey(input_window_inc_size, SDL_SCANCODE_F2); Input::get()->bindKey(InputType::WINDOW_INC_SIZE, SDL_SCANCODE_F2);
Input::get()->bindKey(input_window_fullscreen, SDL_SCANCODE_F3); Input::get()->bindKey(InputType::WINDOW_FULLSCREEN, SDL_SCANCODE_F3);
Input::get()->bindKey(input_video_shaders, SDL_SCANCODE_F4); Input::get()->bindKey(InputType::VIDEO_SHADERS, SDL_SCANCODE_F4);
Input::get()->bindKey(input_mute, SDL_SCANCODE_F5); Input::get()->bindKey(InputType::MUTE, SDL_SCANCODE_F5);
Input::get()->bindKey(input_showinfo, SDL_SCANCODE_F6); Input::get()->bindKey(InputType::SHOWINFO, SDL_SCANCODE_F6);
Input::get()->bindKey(input_reset, SDL_SCANCODE_F10); Input::get()->bindKey(InputType::RESET, SDL_SCANCODE_F10);
// Asigna botones a inputs // Asigna botones a inputs
const int numGamePads = Input::get()->getNumControllers(); const int num_gamepads = Input::get()->getNumControllers();
for (int i = 0; i < numGamePads; ++i) for (int i = 0; i < num_gamepads; ++i)
{ {
// Mando - Movimiento del jugador // Mando - Movimiento del jugador
Input::get()->bindGameControllerButton(i, input_up, SDL_CONTROLLER_BUTTON_DPAD_UP); Input::get()->bindGameControllerButton(i, InputType::UP, SDL_CONTROLLER_BUTTON_DPAD_UP);
Input::get()->bindGameControllerButton(i, input_down, SDL_CONTROLLER_BUTTON_DPAD_DOWN); Input::get()->bindGameControllerButton(i, InputType::DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
Input::get()->bindGameControllerButton(i, input_left, SDL_CONTROLLER_BUTTON_DPAD_LEFT); Input::get()->bindGameControllerButton(i, InputType::LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
Input::get()->bindGameControllerButton(i, input_right, SDL_CONTROLLER_BUTTON_DPAD_RIGHT); Input::get()->bindGameControllerButton(i, InputType::RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
Input::get()->bindGameControllerButton(i, input_fire_left, SDL_CONTROLLER_BUTTON_X); Input::get()->bindGameControllerButton(i, InputType::FIRE_LEFT, SDL_CONTROLLER_BUTTON_X);
Input::get()->bindGameControllerButton(i, input_fire_center, SDL_CONTROLLER_BUTTON_Y); Input::get()->bindGameControllerButton(i, InputType::FIRE_CENTER, SDL_CONTROLLER_BUTTON_Y);
Input::get()->bindGameControllerButton(i, input_fire_right, SDL_CONTROLLER_BUTTON_B); Input::get()->bindGameControllerButton(i, InputType::FIRE_RIGHT, SDL_CONTROLLER_BUTTON_B);
Input::get()->bindGameControllerButton(i, input_start, SDL_CONTROLLER_BUTTON_START); Input::get()->bindGameControllerButton(i, InputType::START, SDL_CONTROLLER_BUTTON_START);
// Mando - Control del programa // Mando - Control del programa
Input::get()->bindGameControllerButton(i, input_service, SDL_CONTROLLER_BUTTON_BACK); Input::get()->bindGameControllerButton(i, InputType::SERVICE, SDL_CONTROLLER_BUTTON_BACK);
Input::get()->bindGameControllerButton(i, input_exit, input_start); Input::get()->bindGameControllerButton(i, InputType::EXIT, InputType::START);
Input::get()->bindGameControllerButton(i, input_pause, input_fire_right); Input::get()->bindGameControllerButton(i, InputType::PAUSE, InputType::FIRE_RIGHT);
Input::get()->bindGameControllerButton(i, input_video_shaders, input_fire_left); Input::get()->bindGameControllerButton(i, InputType::VIDEO_SHADERS, InputType::FIRE_LEFT);
Input::get()->bindGameControllerButton(i, input_mute, input_left); Input::get()->bindGameControllerButton(i, InputType::MUTE, InputType::LEFT);
Input::get()->bindGameControllerButton(i, input_showinfo, input_right); Input::get()->bindGameControllerButton(i, InputType::SHOWINFO, InputType::RIGHT);
Input::get()->bindGameControllerButton(i, input_reset, input_fire_center); Input::get()->bindGameControllerButton(i, InputType::RESET, InputType::FIRE_CENTER);
Input::get()->bindGameControllerButton(i, input_config, input_down); Input::get()->bindGameControllerButton(i, InputType::CONFIG, InputType::DOWN);
Input::get()->bindGameControllerButton(i, input_swap_controllers, input_up); Input::get()->bindGameControllerButton(i, InputType::SWAP_CONTROLLERS, InputType::UP);
} }
// Mapea las asignaciones a los botones desde el archivo de configuración, si se da el caso // Mapea las asignaciones a los botones desde el archivo de configuración, si se da el caso
for (int i = 0; i < numGamePads; ++i) for (int i = 0; i < num_gamepads; ++i)
for (int index = 0; index < (int)options.controller.size(); ++index) for (int index = 0; index < (int)options.controller.size(); ++index)
if (Input::get()->getControllerName(i) == options.controller[index].name) if (Input::get()->getControllerName(i) == options.controller[index].name)
{ {
@@ -206,20 +201,20 @@ void Director::initInput()
} }
// Asigna botones a inputs desde otros inputs // Asigna botones a inputs desde otros inputs
for (int i = 0; i < numGamePads; ++i) for (int i = 0; i < num_gamepads; ++i)
{ {
Input::get()->bindGameControllerButton(i, input_exit, input_start); Input::get()->bindGameControllerButton(i, InputType::EXIT, InputType::START);
Input::get()->bindGameControllerButton(i, input_reset, input_fire_center); Input::get()->bindGameControllerButton(i, InputType::RESET, InputType::FIRE_CENTER);
Input::get()->bindGameControllerButton(i, input_pause, input_fire_right); Input::get()->bindGameControllerButton(i, InputType::PAUSE, InputType::FIRE_RIGHT);
Input::get()->bindGameControllerButton(i, input_video_shaders, input_fire_left); Input::get()->bindGameControllerButton(i, InputType::VIDEO_SHADERS, InputType::FIRE_LEFT);
Input::get()->bindGameControllerButton(i, input_mute, input_left); Input::get()->bindGameControllerButton(i, InputType::MUTE, InputType::LEFT);
Input::get()->bindGameControllerButton(i, input_showinfo, input_right); Input::get()->bindGameControllerButton(i, InputType::SHOWINFO, InputType::RIGHT);
Input::get()->bindGameControllerButton(i, input_config, input_down); Input::get()->bindGameControllerButton(i, InputType::CONFIG, InputType::DOWN);
Input::get()->bindGameControllerButton(i, input_swap_controllers, input_up); Input::get()->bindGameControllerButton(i, InputType::SWAP_CONTROLLERS, InputType::UP);
} }
// Guarda las asignaciones de botones en las opciones // Guarda las asignaciones de botones en las opciones
for (int i = 0; i < numGamePads; ++i) for (int i = 0; i < num_gamepads; ++i)
{ {
options.controller[i].name = Input::get()->getControllerName(i); options.controller[i].name = Input::get()->getControllerName(i);
for (int j = 0; j < (int)options.controller[i].inputs.size(); ++j) for (int j = 0; j < (int)options.controller[i].inputs.size(); ++j)
@@ -304,7 +299,7 @@ bool Director::initSDL()
Uint32 flags = 0; Uint32 flags = 0;
if (options.video.v_sync) if (options.video.v_sync)
{ {
flags = flags | SDL_RENDERER_PRESENTVSYNC; flags = SDL_RENDERER_PRESENTVSYNC;
} }
#ifndef NO_SHADERS #ifndef NO_SHADERS
// La aceleración se activa según el define // La aceleración se activa según el define
@@ -346,7 +341,7 @@ bool Director::setFileList()
#ifdef MACOS_BUNDLE #ifdef MACOS_BUNDLE
const std::string prefix = "/../Resources"; const std::string prefix = "/../Resources";
#else #else
const std::string prefix = ""; const std::string prefix;
#endif #endif
// Ficheros de configuración // Ficheros de configuración
@@ -484,21 +479,21 @@ bool Director::setFileList()
} }
// Carga los parametros para configurar el juego // Carga los parametros para configurar el juego
void Director::loadParams(std::string filepath) void Director::loadParams(const std::string &file_path)
{ {
loadParamsFromFile(filepath); loadParamsFromFile(file_path);
} }
// Comprueba los parametros del programa // Comprueba los parametros del programa
void Director::checkProgramArguments(int argc, char *argv[]) void Director::checkProgramArguments(int argc, const char *argv[])
{ {
// Establece la ruta del programa // Establece la ruta del programa
executable_path_ = argv[0]; executable_path_ = argv[0];
// Valores por defecto // Valores por defecto
param_file_argument_ = ""; param_file_argument_.clear();
// Comprueba el resto de parametros // Comprueba el resto de parámetros
for (int i = 1; i < argc; ++i) for (int i = 1; i < argc; ++i)
{ {
if (strcmp(argv[i], "--320x240") == 0) if (strcmp(argv[i], "--320x240") == 0)
@@ -509,7 +504,7 @@ void Director::checkProgramArguments(int argc, char *argv[])
} }
// Crea la carpeta del sistema donde guardar datos // Crea la carpeta del sistema donde guardar datos
void Director::createSystemFolder(std::string folder) void Director::createSystemFolder(const std::string &folder)
{ {
#ifdef _WIN32 #ifdef _WIN32
system_folder_ = std::string(getenv("APPDATA")) + "/" + folder; system_folder_ = std::string(getenv("APPDATA")) + "/" + folder;
@@ -572,17 +567,15 @@ void Director::createSystemFolder(std::string folder)
void Director::loadSounds() void Director::loadSounds()
{ {
// Obtiene la lista con las rutas a los ficheros de sonidos // Obtiene la lista con las rutas a los ficheros de sonidos
std::vector<std::string> list = Asset::get()->getListByType(AssetType::SOUND); auto list = Asset::get()->getListByType(AssetType::SOUND);
sounds_.clear(); sounds_.clear();
for (auto l : list) for (const auto &l : list)
{ {
const size_t lastIndex = l.find_last_of("/") + 1; auto last_index = l.find_last_of('/') + 1;
const std::string name = l.substr(lastIndex, std::string::npos); auto name = l.substr(last_index);
SoundFile temp;
temp.name = name; // Añade el nombre del fichero sounds_.emplace_back(SoundFile{name, JA_LoadSound(l.c_str())});
temp.file = JA_LoadSound(l.c_str()); // Carga el fichero de audio
sounds_.push_back(temp);
} }
} }
@@ -590,78 +583,69 @@ void Director::loadSounds()
void Director::loadMusics() void Director::loadMusics()
{ {
// Obtiene la lista con las rutas a los ficheros musicales // Obtiene la lista con las rutas a los ficheros musicales
std::vector<std::string> list = Asset::get()->getListByType(AssetType::MUSIC); auto list = Asset::get()->getListByType(AssetType::MUSIC);
musics_.clear(); musics_.clear();
for (auto l : list) for (const auto &l : list)
{ {
const size_t lastIndex = l.find_last_of("/") + 1; auto last_index = l.find_last_of('/') + 1;
const std::string name = l.substr(lastIndex, std::string::npos); auto name = l.substr(last_index);
MusicFile temp;
temp.name = name; // Añade el nombre del fichero musics_.emplace_back(MusicFile{name, JA_LoadMusic(l.c_str())});
temp.file = JA_LoadMusic(l.c_str()); // Carga el fichero de audio
musics_.push_back(temp);
} }
} }
// Ejecuta la sección con el logo // Ejecuta la sección con el logo
void Director::runLogo() void Director::runLogo()
{ {
auto logo = new Logo(); auto logo = std::make_unique<Logo>();
logo->run(); logo->run();
delete logo;
} }
// Ejecuta la sección con la secuencia de introducción // Ejecuta la sección con la secuencia de introducción
void Director::runIntro() void Director::runIntro()
{ {
auto intro = new Intro(getMusic(musics_, "intro.ogg")); auto intro = std::make_unique<Intro>(getMusic(musics_, "intro.ogg"));
intro->run(); intro->run();
delete intro;
} }
// Ejecuta la sección con el titulo del juego // Ejecuta la sección con el título del juego
void Director::runTitle() void Director::runTitle()
{ {
auto title = new Title(getMusic(musics_, "title.ogg")); auto title = std::make_unique<Title>(getMusic(musics_, "title.ogg"));
title->run(); title->run();
delete title;
} }
// Ejecuta la sección donde se juega al juego // Ejecuta la sección donde se juega al juego
void Director::runGame() void Director::runGame()
{ {
const auto playerID = section::options == section::Options::GAME_PLAY_1P ? 1 : 2; const auto player_id = section::options == section::Options::GAME_PLAY_1P ? 1 : 2;
constexpr auto currentStage = 0; constexpr auto current_stage = 0;
auto game = new Game(playerID, currentStage, GAME_MODE_DEMO_OFF, getMusic(musics_, "playing.ogg")); auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_OFF, getMusic(musics_, "playing.ogg"));
game->run(); game->run();
delete game;
} }
// Ejecuta la sección donde se muestran las instrucciones // Ejecuta la sección donde se muestran las instrucciones
void Director::runInstructions() void Director::runInstructions()
{ {
auto instructions = new Instructions(getMusic(musics_, "title.ogg")); auto instructions = std::make_unique<Instructions>(getMusic(musics_, "title.ogg"));
instructions->run(); instructions->run();
delete instructions;
} }
// Ejecuta la sección donde se muestra la tabla de puntuaciones // Ejecuta la sección donde se muestra la tabla de puntuaciones
void Director::runHiScoreTable() void Director::runHiScoreTable()
{ {
auto hiScoreTable = new HiScoreTable(getMusic(musics_, "title.ogg")); auto hi_score_table = std::make_unique<HiScoreTable>(getMusic(musics_, "title.ogg"));
hiScoreTable->run(); hi_score_table->run();
delete hiScoreTable;
} }
// Ejecuta el juego en modo demo // Ejecuta el juego en modo demo
void Director::runDemoGame() void Director::runDemoGame()
{ {
const auto playerID = (rand() % 2) + 1; const auto player_id = (rand() % 2) + 1;
constexpr auto currentStage = 0; constexpr auto current_stage = 0;
auto game = new Game(playerID, currentStage, GAME_MODE_DEMO_ON, nullptr); auto game = std::make_unique<Game>(player_id, current_stage, GAME_MODE_DEMO_ON, nullptr);
game->run(); game->run();
delete game;
} }
int Director::run() int Director::run()
@@ -708,24 +692,24 @@ int Director::run()
} }
} }
const int returnCode = section::options == section::Options::QUIT_NORMAL ? 0 : 1; const int return_code = section::options == section::Options::QUIT_NORMAL ? 0 : 1;
return returnCode; return return_code;
} }
// Obtiene una fichero a partir de un lang_e // Obtiene una fichero a partir de un lang::Code
std::string Director::getLangFile(lang::lang_e lang) std::string Director::getLangFile(lang::Code code)
{ {
switch (lang) switch (code)
{ {
case lang::ba_BA: case lang::Code::ba_BA:
return Asset::get()->get("ba_BA.txt"); return Asset::get()->get("ba_BA.txt");
break; break;
case lang::es_ES: case lang::Code::es_ES:
return Asset::get()->get("es_ES.txt"); return Asset::get()->get("es_ES.txt");
break; break;
case lang::en_UK: case lang::Code::en_UK:
return Asset::get()->get("en_UK.txt"); return Asset::get()->get("en_UK.txt");
break; break;

View File

@@ -1,11 +1,12 @@
#pragma once #pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_video.h> // for SDL_Window #include <SDL2/SDL_video.h> // for SDL_Window
#include <string> // for string, basic_string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "lang.h" // for lang_e namespace lang { enum class Code : int; }
#include "utils.h" // for MusicFile, SoundFile struct MusicFile;
struct SoundFile;
// Textos // Textos
constexpr char WINDOW_CAPTION[] = "Coffee Crisis Arcade Edition"; constexpr char WINDOW_CAPTION[] = "Coffee Crisis Arcade Edition";
@@ -34,7 +35,7 @@ private:
void initInput(); void initInput();
// Carga los parametros para configurar el juego // Carga los parametros para configurar el juego
void loadParams(std::string file_path); void loadParams(const std::string &file_path);
// Crea el indice de ficheros // Crea el indice de ficheros
bool setFileList(); bool setFileList();
@@ -46,10 +47,10 @@ private:
void loadMusics(); void loadMusics();
// Comprueba los parametros del programa // Comprueba los parametros del programa
void checkProgramArguments(int argc, char *argv[]); void checkProgramArguments(int argc, const char *argv[]);
// Crea la carpeta del sistema donde guardar datos // Crea la carpeta del sistema donde guardar datos
void createSystemFolder(std::string folder); void createSystemFolder(const std::string &folder);
// Ejecuta la sección con el logo // Ejecuta la sección con el logo
void runLogo(); void runLogo();
@@ -72,12 +73,12 @@ private:
// Ejecuta el juego en modo demo // Ejecuta el juego en modo demo
void runDemoGame(); void runDemoGame();
// Obtiene una fichero a partir de un lang_e // Obtiene una fichero a partir de un lang::Code
std::string getLangFile(lang::lang_e lang); std::string getLangFile(lang::Code code);
public: public:
// Constructor // Constructor
Director(int argc, char *argv[]); Director(int argc, const char *argv[]);
// Destructor // Destructor
~Director(); ~Director();

View File

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

View File

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

View File

@@ -1,6 +1,7 @@
#include "explosions.h" #include "explosions.h"
#include <utility> // for move
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for AnimatedSprite
class Texture; class Texture; // lines 3-3
// Constructor // Constructor
Explosions::Explosions() Explosions::Explosions()

View File

@@ -1,10 +1,10 @@
#pragma once #pragma once
#include <string> // for string #include <memory> // for shared_ptr, unique_ptr
#include <vector> // for vector #include <string> // for string
#include "animated_sprite.h" #include <vector> // for vector
#include <memory> class AnimatedSprite;
#include "texture.h" class Texture;
struct ExplosionTexture struct ExplosionTexture
{ {

View File

@@ -7,8 +7,8 @@
#include "utils.h" // for Param, ParamGame, ParamFade #include "utils.h" // for Param, ParamGame, ParamFade
// Constructor // Constructor
Fade::Fade(SDL_Renderer *renderer_) Fade::Fade(SDL_Renderer *renderer)
: renderer_(renderer_) : renderer_(renderer)
{ {
// Crea la textura donde dibujar el fade // Crea la textura donde dibujar el fade
backbuffer_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height); backbuffer_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,56 +1,56 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "section.h" // for SectionOptions #include "balloon.h" // for Balloon
#include "player.h" // for Player
#include "utils.h" // for DemoKeys, Color, HiScoreEntry #include "utils.h" // for DemoKeys, Color, HiScoreEntry
#include <memory> class Asset;
#include "asset.h" // lines 11-11 class Background;
#include "background.h" // lines 12-12 class BalloonFormations;
#include "balloon.h" // lines 13-13 class Bullet;
#include "bullet.h" // lines 14-14 class Explosions;
#include "enemy_formations.h" // lines 15-15 class Fade;
#include "explosions.h" // lines 16-16 class Input;
#include "fade.h" // lines 17-17 class Item;
#include "input.h" // lines 18-18 class Scoreboard;
#include "item.h" // lines 19-19 class Screen;
#include "player.h" // lines 20-20 class SmartSprite;
#include "scoreboard.h" // lines 21-21 class Text;
#include "screen.h" // lines 22-22 class Texture;
#include "smart_sprite.h" // lines 23-23 enum class BulletType; // lines 26-26
#include "text.h" // lines 24-24 struct JA_Music_t; // lines 27-27
#include "texture.h" // lines 24-24 struct JA_Sound_t; // lines 28-28
enum class BulletType;
struct JA_Music_t; // lines 26-26
struct JA_Sound_t; // lines 27-27
#define GAME_MODE_DEMO_OFF false // Modo demo
#define GAME_MODE_DEMO_ON true constexpr bool GAME_MODE_DEMO_OFF = false;
constexpr bool GAME_MODE_DEMO_ON = true;
// Cantidad de elementos a escribir en los ficheros de datos // Cantidad de elementos a escribir en los ficheros de datos
#define TOTAL_SCORE_DATA 3 constexpr int TOTAL_SCORE_DATA = 3;
#define TOTAL_DEMO_DATA 2000 constexpr int TOTAL_DEMO_DATA = 2000;
// Contadores // Contadores
#define STAGE_COUNTER 200 constexpr int STAGE_COUNTER = 200;
#define HELP_COUNTER 1000 constexpr int HELP_COUNTER = 1000;
#define GAME_COMPLETED_START_FADE 500 constexpr int GAME_COMPLETED_START_FADE = 500;
#define GAME_COMPLETED_END 700 constexpr int GAME_COMPLETED_END = 700;
constexpr int GAME_OVER_COUNTER = 350;
// Porcentaje de aparición de los objetos // Porcentaje de aparición de los objetos
#define ITEM_POINTS_1_DISK_ODDS 10 constexpr int ITEM_POINTS_1_DISK_ODDS = 10;
#define ITEM_POINTS_2_GAVINA_ODDS 6 constexpr int ITEM_POINTS_2_GAVINA_ODDS = 6;
#define ITEM_POINTS_3_PACMAR_ODDS 3 constexpr int ITEM_POINTS_3_PACMAR_ODDS = 3;
#define ITEM_CLOCK_ODDS 5 constexpr int ITEM_CLOCK_ODDS = 5;
#define ITEM_COFFEE_ODDS 5 constexpr int ITEM_COFFEE_ODDS = 5;
#define ITEM_POWER_BALL_ODDS 0 constexpr int ITEM_POWER_BALL_ODDS = 0;
#define ITEM_COFFEE_MACHINE_ODDS 4 constexpr int ITEM_COFFEE_MACHINE_ODDS = 4;
// Valores para las variables asociadas a los objetos // Valores para las variables asociadas a los objetos
#define TIME_STOPPED_COUNTER 300 constexpr int TIME_STOPPED_COUNTER = 300;
/* /*
Esta clase gestiona un estado del programa. Se encarga de toda la parte en la Esta clase gestiona un estado del programa. Se encarga de toda la parte en la
@@ -82,129 +82,128 @@ struct JA_Sound_t; // lines 27-27
class Game class Game
{ {
private: private:
struct helper_t struct Helper
{ {
bool needCoffee; // Indica si se necesitan cafes bool need_coffee; // Indica si se necesitan cafes
bool needCoffeeMachine; // Indica si se necesita PowerUp bool need_coffee_machine; // Indica si se necesita PowerUp
bool needPowerBall; // Indica si se necesita una PowerBall bool need_power_ball; // Indica si se necesita una PowerBall
int counter; // Contador para no dar ayudas consecutivas int counter; // Contador para no dar ayudas consecutivas
int itemPoints1Odds; // Probabilidad de aparición del objeto int item_disk_odds; // Probabilidad de aparición del objeto
int itemPoints2Odds; // Probabilidad de aparición del objeto int item_gavina_odds; // Probabilidad de aparición del objeto
int itemPoints3Odds; // Probabilidad de aparición del objeto int item_pacmar_odds; // Probabilidad de aparición del objeto
int itemClockOdds; // Probabilidad de aparición del objeto int item_clock_odds; // Probabilidad de aparición del objeto
int itemCoffeeOdds; // Probabilidad de aparición del objeto int item_coffee_odds; // Probabilidad de aparición del objeto
int itemCoffeeMachineOdds; // Probabilidad de aparición del objeto int item_coffee_machine_odds; // Probabilidad de aparición del objeto
}; };
struct demo_t struct Demo
{ {
bool enabled; // Indica si está activo el modo demo bool enabled; // Indica si está activo el modo demo
bool recording; // Indica si está activado el modo para grabar la demo bool recording; // Indica si está activado el modo para grabar la demo
int counter; // Contador para el modo demo int counter; // Contador para el modo demo
DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo DemoKeys keys; // Variable con las pulsaciones de teclas del modo demo
DemoKeys dataFile[2][TOTAL_DEMO_DATA]; // Vector con diferentes sets de datos con los movimientos para la demo DemoKeys data_file[2][TOTAL_DEMO_DATA]; // Vector con diferentes sets de datos con los movimientos para la demo
}; };
// Objetos y punteros // Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
Screen *screen; // Objeto encargado de dibujar en pantalla Screen *screen_; // Objeto encargado de dibujar en pantalla
Asset *asset; // Objeto que gestiona todos los ficheros de recursos Asset *asset_; // Objeto que gestiona todos los ficheros de recursos
Input *input; // Manejador de entrada Input *input_; // Manejador de entrada
Scoreboard *scoreboard; // Objeto para dibujar el marcador Scoreboard *scoreboard_; // Objeto para dibujar el marcador
std::unique_ptr<Background> background; // Objeto para dibujar el fondo del juego std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
std::unique_ptr<Explosions> explosions; // Objeto para dibujar explosiones std::unique_ptr<Explosions> explosions_; // Objeto para dibujar explosiones
std::unique_ptr<EnemyFormations> enemyFormations; // Objeto para gestionar las oleadas enemigas std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para gestionar las oleadas enemigas
SDL_Texture *canvas; // Textura para dibujar la zona de juego SDL_Texture *canvas_; // Textura para dibujar la zona de juego
std::vector<std::shared_ptr<Player>> players; // Vector con los jugadores std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
std::vector<std::shared_ptr<Balloon>> balloons; // Vector con los globos std::vector<std::shared_ptr<Balloon>> balloons_; // Vector con los globos
std::vector<std::unique_ptr<Bullet>> bullets; // Vector con las balas std::vector<std::unique_ptr<Bullet>> bullets_; // Vector con las balas
std::vector<std::unique_ptr<Item>> items; // Vector con los items std::vector<std::unique_ptr<Item>> items_; // Vector con los items
std::vector<SmartSprite *> smartSprites; // Vector con los smartsprites std::vector<SmartSprite *> smart_sprites_; // Vector con los smartsprites
std::shared_ptr<Texture> bulletTexture; // Textura para las balas std::shared_ptr<Texture> bullet_texture_; // Textura para las balas
std::vector<std::shared_ptr<Texture>> itemTextures; // Vector con las texturas de los items std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
std::vector<std::shared_ptr<Texture>> balloonTextures; // Vector con las texturas de los globos std::vector<std::shared_ptr<Texture>> balloon_textures_; // Vector con las texturas de los globos
std::vector<std::shared_ptr<Texture>> explosionsTextures; // Vector con las texturas de las explosiones std::vector<std::shared_ptr<Texture>> explosions_textures_; // Vector con las texturas de las explosiones
std::vector<std::shared_ptr<Texture>> player1Textures; // Vector con las texturas del jugador std::vector<std::shared_ptr<Texture>> player1_textures_; // Vector con las texturas del jugador
std::vector<std::shared_ptr<Texture>> player2Textures; // Vector con las texturas del jugador std::vector<std::shared_ptr<Texture>> player2_textures_; // Vector con las texturas del jugador
std::vector<std::vector<std::shared_ptr<Texture>>> playerTextures; // Vector con todas las texturas de los jugadores; std::vector<std::vector<std::shared_ptr<Texture>>> player_textures_; // Vector con todas las texturas de los jugadores;
std::shared_ptr<Texture> gameTextTexture; // Textura para los sprites con textos std::shared_ptr<Texture> game_text_texture_; // Textura para los sprites con textos
std::vector<std::vector<std::string> *> itemAnimations; // Vector con las animaciones de los items std::vector<std::vector<std::string> *> item_animations_; // Vector con las animaciones de los items
std::vector<std::vector<std::string> *> playerAnimations; // Vector con las animaciones del jugador std::vector<std::vector<std::string> *> player_animations_; // Vector con las animaciones del jugador
std::vector<std::vector<std::string> *> balloonAnimations; // Vector con las animaciones de los globos std::vector<std::vector<std::string> *> balloon_animations_; // Vector con las animaciones de los globos
std::vector<std::vector<std::string> *> explosionsAnimations; // Vector con las animaciones de las explosiones std::vector<std::vector<std::string> *> explosions_animations_; // Vector con las animaciones de las explosiones
std::unique_ptr<Text> text; // Fuente para los textos del juego std::unique_ptr<Text> text_; // Fuente para los textos del juego
std::unique_ptr<Text> textBig; // Fuente de texto grande std::unique_ptr<Text> text_big_; // Fuente de texto grande
std::unique_ptr<Text> textNokia2; // Otra fuente de texto para mensajes std::unique_ptr<Text> text_nokia2_; // Otra fuente de texto para mensajes
std::unique_ptr<Text> textNokiaBig2; // Y la versión en grande std::unique_ptr<Text> text_nokia2_big_; // Y la versión en grande
std::unique_ptr<Fade> fade; // Objeto para renderizar fades std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
std::unique_ptr<SDL_Event> eventHandler; // Manejador de eventos
std::shared_ptr<SmartSprite> n1000Sprite; // Sprite con el texto 1.000 std::shared_ptr<SmartSprite> p1000_sprite_; // Sprite con el texto 1.000
std::shared_ptr<SmartSprite> n2500Sprite; // Sprite con el texto 2.500 std::shared_ptr<SmartSprite> p2500_sprite_; // Sprite con el texto 2.500
std::shared_ptr<SmartSprite> n5000Sprite; // Sprite con el texto 5.000 std::shared_ptr<SmartSprite> p5000_sprite_; // Sprite con el texto 5.000
JA_Sound_t *balloonSound; // Sonido para la explosión del globo JA_Sound_t *balloon_sound_; // Sonido para la explosión del globo
JA_Sound_t *bulletSound; // Sonido para los disparos JA_Sound_t *bullet_sound_; // Sonido para los disparos
JA_Sound_t *playerCollisionSound; // Sonido para la colisión del jugador con un enemigo JA_Sound_t *player_collision_sound_; // Sonido para la colisión del jugador con un enemigo
JA_Sound_t *hiScoreSound; // Sonido para cuando se alcanza la máxima puntuación JA_Sound_t *hi_score_sound_; // Sonido para cuando se alcanza la máxima puntuación
JA_Sound_t *itemDropSound; // Sonido para cuando se genera un item JA_Sound_t *item_drop_sound_; // Sonido para cuando se genera un item
JA_Sound_t *itemPickUpSound; // Sonido para cuando se recoge un item JA_Sound_t *item_pick_up_sound_; // Sonido para cuando se recoge un item
JA_Sound_t *coffeeOutSound; // Sonido para cuando el jugador pierde el café al recibir un impacto JA_Sound_t *coffee_out_sound_; // Sonido para cuando el jugador pierde el café al recibir un impacto
JA_Sound_t *stageChangeSound; // Sonido para cuando se cambia de fase JA_Sound_t *stage_change_sound_; // Sonido para cuando se cambia de fase
JA_Sound_t *bubble1Sound; // Sonido para cuando el jugador muere JA_Sound_t *bubble1_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble2Sound; // Sonido para cuando el jugador muere JA_Sound_t *bubble2_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble3Sound; // Sonido para cuando el jugador muere JA_Sound_t *bubble3_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *bubble4Sound; // Sonido para cuando el jugador muere JA_Sound_t *bubble4_sound_; // Sonido para cuando el jugador muere
JA_Sound_t *clockSound; // Sonido para cuando se detiene el tiempo con el item reloj JA_Sound_t *clock_sound_; // Sonido para cuando se detiene el tiempo con el item reloj
JA_Sound_t *powerBallSound; // Sonido para cuando se explota una Power Ball JA_Sound_t *power_ball_sound_; // Sonido para cuando se explota una Power Ball
JA_Sound_t *coffeeMachineSound; // Sonido para cuando la máquina de café toca el suelo JA_Sound_t *coffee_machine_sound_; // Sonido para cuando la máquina de café toca el suelo
JA_Music_t *music; // Musica de fondo JA_Music_t *music_; // Musica de fondo
// Variables // Variables
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
bool hiScoreAchieved; // Indica si se ha superado la puntuación máxima bool hi_score_achieved_; // Indica si se ha superado la puntuación máxima
HiScoreEntry hiScore; // Máxima puntuación y nombre de quien la ostenta HiScoreEntry hi_score_; // Máxima puntuación y nombre de quien la ostenta
int currentStage; // Indica la fase actual int current_stage_; // Indica la fase actual
int stageBitmapCounter; // Contador para el tiempo visible del texto de Stage int stage_bitmap_counter_; // Contador para el tiempo visible del texto de Stage
float stageBitmapPath[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto float stage_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos Y por donde se desplaza el texto
float getReadyBitmapPath[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto float get_ready_bitmap_path_[STAGE_COUNTER]; // Vector con los puntos X por donde se desplaza el texto
int gameOverCounter; // Contador para el estado de fin de partida int game_over_counter_; // Contador para el estado de fin de partida
int menaceCurrent; // Nivel de amenaza actual int menace_current_; // Nivel de amenaza actual
int menaceThreshold; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos int menace_threshold_; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos
bool timeStopped; // Indica si el tiempo está detenido bool time_stopped_; // Indica si el tiempo está detenido
int timeStoppedCounter; // Temporizador para llevar la cuenta del tiempo detenido int time_stopped_counter_; // Temporizador para llevar la cuenta del tiempo detenido
int counter; // Contador para el juego int counter_; // Contador para el juego
int balloonsPopped; // Lleva la cuenta de los globos explotados int balloons_popped_; // Lleva la cuenta de los globos explotados
int lastEnemyDeploy; // Guarda cual ha sido la última formación desplegada para no repetir; int last_ballon_deploy_; // Guarda cual ha sido la última formación desplegada para no repetir;
int enemyDeployCounter; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero int balloon_deploy_counter_; // Cuando se lanza una formación, se le da un valor y no sale otra hasta que llegue a cero
float enemySpeed; // Velocidad a la que se mueven los enemigos float balloon_speed_; // Velocidad a la que se mueven los enemigos
float defaultEnemySpeed; // Velocidad base de los enemigos, sin incrementar float default_balloon_speed_; // Velocidad base de los enemigos, sin incrementar
helper_t helper; // Variable para gestionar las ayudas Helper helper_; // Variable para gestionar las ayudas
bool powerBallEnabled; // Indica si hay una powerball ya activa bool power_ball_enabled_; // Indica si hay una powerball ya activa
int powerBallCounter; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra int power_ball_counter_; // Contador de formaciones enemigas entre la aparicion de una PowerBall y otra
bool coffeeMachineEnabled; // Indica si hay una máquina de café en el terreno de juego bool coffee_machine_enabled_; // Indica si hay una máquina de café en el terreno de juego
bool gameCompleted; // Indica si se ha completado la partida, llegando al final de la ultima pantalla bool game_completed_; // Indica si se ha completado la partida, llegando al final de la ultima pantalla
int gameCompletedCounter; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos int game_completed_counter_; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos
GameDifficulty difficulty; // Dificultad del juego GameDifficulty difficulty_; // Dificultad del juego
float difficultyScoreMultiplier; // Multiplicador de puntos en función de la dificultad float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
Color difficultyColor; // Color asociado a la dificultad Color difficulty_color_; // Color asociado a la dificultad
int lastStageReached; // Contiene el número de la última pantalla que se ha alcanzado int last_stage_reached_; // Contiene el número de la última pantalla que se ha alcanzado
demo_t demo; // Variable con todas las variables relacionadas con el modo demo Demo demo_; // Variable con todas las variables relacionadas con el modo demo
int totalPowerToCompleteGame; // La suma del poder necesario para completar todas las fases int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
bool paused; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade) bool paused_; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade)
int currentPower; // Poder actual almacenado para completar la fase int current_power_; // Poder actual almacenado para completar la fase
#ifdef DEBUG #ifdef DEBUG
bool autoPopBalloons; // Si es true, incrementa automaticamente los globos explotados bool auto_pop_balloons_; // Si es true, incrementa automaticamente los globos explotados
#endif #endif
// Actualiza el juego // Actualiza el juego
@@ -217,7 +216,7 @@ private:
void checkEvents(); void checkEvents();
// Inicializa las variables necesarias para la sección 'Game' // Inicializa las variables necesarias para la sección 'Game'
void init(int playerID); void init(int player_id);
// Carga los recursos necesarios para la sección 'Game' // Carga los recursos necesarios para la sección 'Game'
void loadMedia(); void loadMedia();
@@ -226,13 +225,13 @@ private:
void unloadMedia(); void unloadMedia();
// Carga el fichero de datos para la demo // Carga el fichero de datos para la demo
bool loadDemoFile(std::string filePath, DemoKeys (*dataFile)[TOTAL_DEMO_DATA]); bool loadDemoFile(const std::string &file_path, DemoKeys (*data_file)[TOTAL_DEMO_DATA]);
#ifdef RECORDING #ifdef RECORDING
// Guarda el fichero de datos para la demo // Guarda el fichero de datos para la demo
bool saveDemoFile(std::string filePath); bool saveDemoFile(const std::string &file_path);
#endif #endif
// Crea una formación de enemigos // Crea una formación de enemigos
void deployEnemyFormation(); void deployBalloonFormation();
// Aumenta el poder de la fase // Aumenta el poder de la fase
void increaseStageCurrentPower(int power); void increaseStageCurrentPower(int power);
@@ -259,7 +258,7 @@ private:
void renderBalloons(); void renderBalloons();
// Crea un globo nuevo en el vector de globos // Crea un globo nuevo en el vector de globos
std::shared_ptr<Balloon> createBalloon(float x, int y, int kind, float velx, float speed, int stoppedcounter); std::shared_ptr<Balloon> createBalloon(float x, int y, int kind, float velx, float speed, int stopped_counter);
// Crea una PowerBall // Crea una PowerBall
void createPowerBall(); void createPowerBall();
@@ -267,12 +266,6 @@ private:
// Establece la velocidad de los globos // Establece la velocidad de los globos
void setBalloonSpeed(float speed); void setBalloonSpeed(float speed);
// Incrementa la velocidad de los globos
void incBalloonSpeed();
// Decrementa la velocidad de los globos
void decBalloonSpeed();
// Actualiza la velocidad de los globos en funcion del poder acumulado de la fase // Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
void updateBalloonSpeed(); void updateBalloonSpeed();
@@ -282,9 +275,6 @@ private:
// Explosiona un globo. Lo destruye // Explosiona un globo. Lo destruye
void destroyBalloon(std::shared_ptr<Balloon> &balloon); void destroyBalloon(std::shared_ptr<Balloon> &balloon);
// Explosiona todos los globos
void popAllBalloons();
// Destruye todos los globos // Destruye todos los globos
void destroyAllBalloons(); void destroyAllBalloons();
@@ -294,9 +284,6 @@ private:
// Pone en marcha todos los globos // Pone en marcha todos los globos
void startAllBalloons(); void startAllBalloons();
// Obtiene el número de globos activos
int countBalloons();
// Vacia el vector de globos // Vacia el vector de globos
void freeBalloons(); void freeBalloons();
@@ -316,7 +303,7 @@ private:
void renderBullets(); void renderBullets();
// Crea un objeto bala // Crea un objeto bala
void createBullet(int x, int y, BulletType kind, bool poweredUp, int owner); void createBullet(int x, int y, BulletType kind, bool powered_up, int owner);
// Vacia el vector de balas // Vacia el vector de balas
void freeBullets(); void freeBullets();
@@ -373,7 +360,7 @@ private:
void incTimeStoppedCounter(int value); void incTimeStoppedCounter(int value);
// Actualiza la variable EnemyDeployCounter // Actualiza la variable EnemyDeployCounter
void updateEnemyDeployCounter(); void updateBalloonDeployCounter();
// Actualiza y comprueba el valor de la variable // Actualiza y comprueba el valor de la variable
void updateTimeStoppedCounter(); void updateTimeStoppedCounter();
@@ -421,7 +408,7 @@ private:
bool allPlayersAreNotPlaying(); bool allPlayersAreNotPlaying();
// Carga las animaciones // Carga las animaciones
void loadAnimations(std::string filePath, std::vector<std::string> *buffer); void loadAnimations(std::string file_path, std::vector<std::string> *buffer);
// Elimina todos los objetos contenidos en vectores // Elimina todos los objetos contenidos en vectores
void deleteAllVectorObjects(); void deleteAllVectorObjects();
@@ -442,10 +429,10 @@ private:
void checkMusicStatus(); void checkMusicStatus();
// Añade una puntuación a la tabla de records // Añade una puntuación a la tabla de records
void addScoreToScoreBoard(std::string name, int score); void addScoreToScoreBoard(const std::string &name, int score);
// Saca del estado de GAME OVER al jugador si el otro está activo // Saca del estado de GAME OVER al jugador si el otro está activo
void checkAndUpdatePlayerStatus(int activePlayerIndex, int inactivePlayerIndex); void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index);
// Comprueba el estado de juego de los jugadores // Comprueba el estado de juego de los jugadores
void checkPlayersStatusPlaying(); void checkPlayersStatusPlaying();
@@ -458,7 +445,7 @@ private:
public: public:
// Constructor // Constructor
Game(int playerID, int currentStage, bool demo, JA_Music_t *music); Game(int playerID, int current_stage, bool demo, JA_Music_t *music);
// Destructor // Destructor
~Game(); ~Game();

View File

@@ -1,6 +1,6 @@
#include "game_logo.h" #include "game_logo.h"
#include <SDL2/SDL_render.h> // for SDL_FLIP_HORIZONTAL
#include <algorithm> // for max #include <algorithm> // for max
#include <string> // for basic_string
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for AnimatedSprite
#include "asset.h" // for Asset #include "asset.h" // for Asset
#include "jail_audio.h" // for JA_DeleteSound, JA_LoadSound, JA_PlaySound #include "jail_audio.h" // for JA_DeleteSound, JA_LoadSound, JA_PlaySound
@@ -13,25 +13,24 @@
// Constructor // Constructor
GameLogo::GameLogo(int x, int y) GameLogo::GameLogo(int x, int y)
: x_(x), y_(y) : dust_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_dust.png"))),
coffee_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_coffee.png"))),
crisis_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_crisis.png"))),
arcade_edition_texture_(std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_arcade_edition.png"))),
dust_left_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Asset::get()->get("title_dust.ani"))),
dust_right_sprite_(std::make_unique<AnimatedSprite>(dust_texture_, Asset::get()->get("title_dust.ani"))),
coffee_sprite_(std::make_unique<SmartSprite>(coffee_texture_)),
crisis_sprite_(std::make_unique<SmartSprite>(crisis_texture_)),
arcade_edition_sprite_(std::make_unique<Sprite>((param.game.width - arcade_edition_texture_->getWidth()) / 2, param.title.arcade_edition_position, arcade_edition_texture_->getWidth(), arcade_edition_texture_->getHeight(), arcade_edition_texture_)),
crash_sound_(JA_LoadSound(Asset::get()->get("title.wav").c_str())),
x_(x),
y_(y)
{ {
// Crea los objetos
dust_texture_ = std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_dust.png"));
coffee_texture_ = std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_coffee.png"));
crisis_texture_ = std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_crisis.png"));
arcade_edition_texture_ = std::make_shared<Texture>(Screen::get()->getRenderer(), Asset::get()->get("title_arcade_edition.png"));
coffee_sprite_ = std::make_unique<SmartSprite>(coffee_texture_);
crisis_sprite_ = std::make_unique<SmartSprite>(crisis_texture_);
arcade_edition_sprite_ = std::make_unique<Sprite>((param.game.width - arcade_edition_texture_->getWidth()) / 2, param.title.arcade_edition_position, arcade_edition_texture_->getWidth(), arcade_edition_texture_->getHeight(), arcade_edition_texture_);
dust_left_sprite_ = std::make_unique<AnimatedSprite>(dust_texture_, Asset::get()->get("title_dust.ani"));
dust_right_sprite_ = std::make_unique<AnimatedSprite>(dust_texture_, Asset::get()->get("title_dust.ani"));
// Sonidos
crash_sound_ = JA_LoadSound(Asset::get()->get("title.wav").c_str());
// Inicializa las variables // Inicializa las variables
init(); init();
} }

View File

@@ -1,25 +1,41 @@
#pragma once #pragma once
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <memory> // for unique_ptr, shared_ptr
#include <memory> class AnimatedSprite;
#include "texture.h" class SmartSprite;
#include "animated_sprite.h" class Sprite;
#include "smart_sprite.h" class Texture;
#include "sprite.h" struct JA_Sound_t; // lines 10-10
struct JA_Sound_t;
// Clase GameLogo // Clase GameLogo
class GameLogo class GameLogo
{ {
private: private:
enum class Status
{
DISABLED,
MOVING,
SHAKING,
FINISHED,
};
struct Shake
{
int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x
int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse
int counter; // Contador para el retraso
int lenght; // Cantidad de desplazamientos a realizar
int remaining; // Cantidad de desplazamientos pendientes a realizar
int origin; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
};
// Objetos y punteros // Objetos y punteros
std::shared_ptr<Texture> dust_texture_; // Textura con los graficos del polvo std::shared_ptr<Texture> dust_texture_; // Textura con los graficos del polvo
std::shared_ptr<Texture> coffee_texture_; // Textura con los graficos de la palabra "COFFEE" std::shared_ptr<Texture> coffee_texture_; // Textura con los graficos de la palabra "COFFEE"
std::shared_ptr<Texture> crisis_texture_; // Textura con los graficos de la plabra "CRISIS" std::shared_ptr<Texture> crisis_texture_; // Textura con los graficos de la plabra "CRISIS"
std::shared_ptr<Texture> arcade_edition_texture_; // Textura con los graficos de "Arcade Edition" std::shared_ptr<Texture> arcade_edition_texture_; // Textura con los graficos de "Arcade Edition"
std::unique_ptr<AnimatedSprite> dust_left_sprite_; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo std::unique_ptr<AnimatedSprite> dust_left_sprite_; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
std::unique_ptr<AnimatedSprite> dust_right_sprite_; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo std::unique_ptr<AnimatedSprite> dust_right_sprite_; // Sprite con la el polvo que aparece al colisionar el texto de la pantalla de titulo
std::unique_ptr<SmartSprite> coffee_sprite_; // Sprite con la palabra "COFFEE" para la pantalla de titulo std::unique_ptr<SmartSprite> coffee_sprite_; // Sprite con la palabra "COFFEE" para la pantalla de titulo
@@ -33,23 +49,8 @@ private:
int x_; // Posición donde dibujar el logo int x_; // Posición donde dibujar el logo
int y_; // Posición donde dibujar el logo int y_; // Posición donde dibujar el logo
enum class Status Status status_; // Estado en el que se encuentra la clase
{ Shake shake_; // Estructura para generar el efecto de agitación
DISABLED,
MOVING,
SHAKING,
FINISHED,
} status_; // Estado en el que se encuentra la clase
struct Shake
{
int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x
int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse
int counter; // Contador para el retraso
int lenght; // Cantidad de desplazamientos a realizar
int remaining; // Cantidad de desplazamientos pendientes a realizar
int origin; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
} shake_; // Estructura para generar el efecto de agitación
// Inicializa las variables // Inicializa las variables
void init(); void init();

View File

@@ -12,16 +12,16 @@
namespace globalInputs namespace globalInputs
{ {
// Variables // Variables
std::vector<int> servicePressedCounter; std::vector<int> service_pressed_counter;
// Inicializa variables // Inicializa variables
void init() void init()
{ {
const auto numInputs = Input::get()->getNumControllers() + 1; const auto num_inputs = Input::get()->getNumControllers() + 1;
servicePressedCounter.reserve(numInputs); service_pressed_counter.reserve(num_inputs);
for (int i = 0; i < numInputs; ++i) for (int i = 0; i < num_inputs; ++i)
{ {
servicePressedCounter.push_back(0); service_pressed_counter.push_back(0);
} }
} }
@@ -59,78 +59,78 @@ namespace globalInputs
void check() void check()
{ {
// Comprueba si se sale con el teclado // Comprueba si se sale con el teclado
if (Input::get()->checkInput(input_exit, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
quit(section::Options::QUIT_NORMAL); quit(section::Options::QUIT_NORMAL);
return; return;
} }
// Comprueba si se va a resetear el juego // Comprueba si se va a resetear el juego
else if (Input::get()->checkInput(input_reset, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) else if (Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
reset(); reset();
return; return;
} }
else if (Input::get()->checkInput(input_mute, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) else if (Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
switchAudio(); switchAudio();
return; return;
} }
else if (Input::get()->checkInput(input_service, INPUT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) else if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
servicePressedCounter[0]++; service_pressed_counter[0]++;
if (servicePressedCounter[0] >= 3000) if (service_pressed_counter[0] >= 3000)
{ {
OnScreenHelp::get()->toggleState(); OnScreenHelp::get()->toggleState();
servicePressedCounter[0] = 0; service_pressed_counter[0] = 0;
} }
return; return;
} }
else else
{ {
servicePressedCounter[0] = 0; service_pressed_counter[0] = 0;
} }
for (int i = 0; i < Input::get()->getNumControllers(); ++i) for (int i = 0; i < Input::get()->getNumControllers(); ++i)
{ {
// Comprueba si se sale con el mando // Comprueba si se sale con el mando
if (Input::get()->checkModInput(input_service, input_exit, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkModInput(InputType::SERVICE, InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
quit(section::Options::QUIT_SHUTDOWN); quit(section::Options::QUIT_SHUTDOWN);
return; return;
} }
// Comprueba si se va a resetear el juego // Comprueba si se va a resetear el juego
else if (Input::get()->checkModInput(input_service, input_reset, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) else if (Input::get()->checkModInput(InputType::SERVICE, InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
reset(); reset();
return; return;
} }
// Comprueba si se va a activar o desactivar el audio // Comprueba si se va a activar o desactivar el audio
else if (Input::get()->checkModInput(input_service, input_mute, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) else if (Input::get()->checkModInput(InputType::SERVICE, InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
switchAudio(); switchAudio();
return; return;
} }
if (Input::get()->checkInput(input_service, INPUT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
servicePressedCounter[i + 1]++; service_pressed_counter[i + 1]++;
if (servicePressedCounter[i + 1] >= 3000) if (service_pressed_counter[i + 1] >= 3000)
{ {
OnScreenHelp::get()->toggleState(); OnScreenHelp::get()->toggleState();
servicePressedCounter[i + 1] = 0; service_pressed_counter[i + 1] = 0;
} }
return; return;
} }
else else
{ {
servicePressedCounter[i + 1] = 0; service_pressed_counter[i + 1] = 0;
} }
} }
} }

View File

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

View File

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

View File

@@ -1,17 +1,15 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint16, Uint32 #include <SDL2/SDL_stdinc.h> // for Uint16, Uint32, Uint8
#include <memory> #include <memory> // for unique_ptr
#include <string> // for string #include <string> // for string
#include "fade.h" class Background; // lines 8-8
#include "section.h" // for SectionOptions class Fade; // lines 9-9
#include "background.h" class Text; // lines 10-10
#include "text.h" enum class FadeMode : Uint8; // lines 11-11
struct JA_Music_t; // lines 12-12
struct JA_Music_t;
/* /*
Esta clase gestiona un estado del programa. Se encarga de mostrar la tabla con las puntuaciones Esta clase gestiona un estado del programa. Se encarga de mostrar la tabla con las puntuaciones
@@ -28,22 +26,21 @@ class HiScoreTable
{ {
private: private:
// Objetos y punteros // Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
SDL_Texture *backbuffer; // Textura para usar como backbuffer SDL_Texture *backbuffer_; // Textura para usar como backbuffer
JA_Music_t *music; // Musica de fondo JA_Music_t *music_; // Musica de fondo
std::unique_ptr<Fade> fade; // Objeto para renderizar fades std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
std::unique_ptr<Background> background; // Objeto para dibujar el fondo del juego std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
std::unique_ptr<SDL_Event> eventHandler; // Manejador de eventos std::unique_ptr<Text> text_; // Objeto para escribir texto
std::unique_ptr<Text> text; // Objeto para escribir texto
// Variables // Variables
Uint16 counter; // Contador Uint16 counter_; // Contador
Uint16 counterEnd; // Valor final para el contador Uint16 counter_end_; // Valor final para el contador
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
Uint32 ticksSpeed; // Velocidad a la que se repiten los bucles del programa Uint32 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
SDL_Rect viewArea; // Parte de la textura que se muestra en pantalla SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla
FadeMode fadeMode; // Modo de fade a utilizar FadeMode fade_mode_; // Modo de fade a utilizar
// Actualiza las variables // Actualiza las variables
void update(); void update();
@@ -71,7 +68,7 @@ private:
public: public:
// Constructor // Constructor
HiScoreTable(JA_Music_t *music); explicit HiScoreTable(JA_Music_t *music);
// Destructor // Destructor
~HiScoreTable(); ~HiScoreTable();

View File

@@ -6,122 +6,106 @@
#include <iostream> // for basic_ostream, operator<<, cout, basi... #include <iostream> // for basic_ostream, operator<<, cout, basi...
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Input *Input::input = nullptr; Input *Input::input_ = nullptr;
// [SINGLETON] Crearemos el objeto input con esta función estática // [SINGLETON] Crearemos el objeto input con esta función estática
void Input::init(std::string dbPath) void Input::init(const std::string &game_controller_db_path)
{ {
Input::input = new Input(dbPath); Input::input_ = new Input(game_controller_db_path);
} }
// [SINGLETON] Destruiremos el objeto input con esta función estática // [SINGLETON] Destruiremos el objeto input con esta función estática
void Input::destroy() void Input::destroy()
{ {
delete Input::input; delete Input::input_;
} }
// [SINGLETON] Con este método obtenemos el objeto input y podemos trabajar con él // [SINGLETON] Con este método obtenemos el objeto input y podemos trabajar con él
Input *Input::get() Input *Input::get()
{ {
return Input::input; return Input::input_;
} }
// Constructor // Constructor
Input::Input(std::string dbPath) Input::Input(const std::string &game_controller_db_path)
: dbPath(dbPath) : game_controller_db_path_(game_controller_db_path),
enabled_(true)
{ {
// Inicializa variables
verbose = false;
enabled = true;
// Busca si hay mandos conectados // Busca si hay mandos conectados
discoverGameControllers(); discoverGameControllers();
// Inicializa las vectores // Inicializa las vectores
keyBindings_t kb; KeyBindings kb;
kb.scancode = 0; kb.scancode = 0;
kb.active = false; kb.active = false;
keyBindings.resize(input_number_of_inputs, kb); key_bindings_.resize(static_cast<int>(InputType::NUMBER_OF_INPUTS), kb);
GameControllerBindings_t gcb; ControllerBindings gcb;
gcb.button = SDL_CONTROLLER_BUTTON_INVALID; gcb.button = SDL_CONTROLLER_BUTTON_INVALID;
gcb.active = false; gcb.active = false;
gameControllerBindings.resize(numGamepads); controller_bindings_.resize(num_gamepads_);
for (int i = 0; i < numGamepads; ++i) for (int i = 0; i < num_gamepads_; ++i)
{ {
gameControllerBindings[i].resize(input_number_of_inputs, gcb); controller_bindings_[i].resize(static_cast<int>(InputType::NUMBER_OF_INPUTS), gcb);
} }
// Listado de los inputs usados para jugar, excluyendo botones para la interfaz // Listado de los inputs usados para jugar, excluyendo botones para la interfaz
gameInputs.clear(); game_inputs_.clear();
gameInputs.push_back(input_fire_left); game_inputs_.push_back(InputType::FIRE_LEFT);
gameInputs.push_back(input_fire_center); game_inputs_.push_back(InputType::FIRE_CENTER);
gameInputs.push_back(input_fire_right); game_inputs_.push_back(InputType::FIRE_RIGHT);
gameInputs.push_back(input_up); game_inputs_.push_back(InputType::UP);
gameInputs.push_back(input_down); game_inputs_.push_back(InputType::DOWN);
gameInputs.push_back(input_left); game_inputs_.push_back(InputType::LEFT);
gameInputs.push_back(input_right); game_inputs_.push_back(InputType::RIGHT);
// Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas // Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
buttonInputs.clear(); button_inputs_.clear();
buttonInputs.push_back(input_fire_left); button_inputs_.push_back(InputType::FIRE_LEFT);
buttonInputs.push_back(input_fire_center); button_inputs_.push_back(InputType::FIRE_CENTER);
buttonInputs.push_back(input_fire_right); button_inputs_.push_back(InputType::FIRE_RIGHT);
buttonInputs.push_back(input_start); button_inputs_.push_back(InputType::START);
}
// Destructor
Input::~Input()
{
}
// Actualiza el estado del objeto
void Input::update()
{
if (disabledUntil == d_keyPressed && !checkAnyInput())
{
enable();
}
} }
// Asigna inputs a teclas // Asigna inputs a teclas
void Input::bindKey(inputs_e input, SDL_Scancode code) void Input::bindKey(InputType input, SDL_Scancode code)
{ {
keyBindings[input].scancode = code; key_bindings_[static_cast<int>(input)].scancode = code;
} }
// Asigna inputs a botones del mando // Asigna inputs a botones del mando
void Input::bindGameControllerButton(int index, inputs_e input, SDL_GameControllerButton button) void Input::bindGameControllerButton(int controller_index, InputType input, SDL_GameControllerButton button)
{ {
if (index < numGamepads) if (controller_index < num_gamepads_)
{ {
gameControllerBindings[index][input].button = button; controller_bindings_[controller_index][static_cast<int>(input)].button = button;
} }
} }
// Asigna inputs a botones del mando // Asigna inputs a botones del mando
void Input::bindGameControllerButton(int index, inputs_e inputTarget, inputs_e inputSource) void Input::bindGameControllerButton(int controller_index, InputType input_target, InputType input_source)
{ {
if (index < numGamepads) if (controller_index < num_gamepads_)
{ {
gameControllerBindings[index][inputTarget].button = gameControllerBindings[index][inputSource].button; controller_bindings_[controller_index][static_cast<int>(input_target)].button = controller_bindings_[controller_index][static_cast<int>(input_source)].button;
} }
} }
// Comprueba si un input esta activo // Comprueba si un input esta activo
bool Input::checkInput(inputs_e input, bool repeat, int device, int index) bool Input::checkInput(InputType input, bool repeat, int device, int controller_index)
{ {
if (!enabled) if (!enabled_)
{ {
return false; return false;
} }
bool successKeyboard = false; bool success_keyboard = false;
bool successGameController = false; bool success_controller = false;
const int input_index = static_cast<int>(input);
if (device == INPUT_USE_ANY) if (device == INPUT_USE_ANY)
{ {
index = 0; controller_index = 0;
} }
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY) if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
@@ -130,108 +114,109 @@ bool Input::checkInput(inputs_e input, bool repeat, int device, int index)
if (repeat) if (repeat)
{ {
if (keyStates[keyBindings[input].scancode] != 0) if (keyStates[key_bindings_[input_index].scancode] != 0)
{ {
successKeyboard = true; success_keyboard = true;
} }
else else
{ {
successKeyboard = false; success_keyboard = false;
} }
} }
else else
{ {
if (!keyBindings[input].active) if (!key_bindings_[input_index].active)
{ {
if (keyStates[keyBindings[input].scancode] != 0) if (keyStates[key_bindings_[input_index].scancode] != 0)
{ {
keyBindings[input].active = true; key_bindings_[input_index].active = true;
successKeyboard = true; success_keyboard = true;
} }
else else
{ {
successKeyboard = false; success_keyboard = false;
} }
} }
else else
{ {
if (keyStates[keyBindings[input].scancode] == 0) if (keyStates[key_bindings_[input_index].scancode] == 0)
{ {
keyBindings[input].active = false; key_bindings_[input_index].active = false;
successKeyboard = false; success_keyboard = false;
} }
else else
{ {
successKeyboard = false; success_keyboard = false;
} }
} }
} }
} }
if (gameControllerFound() && index < numGamepads) if (gameControllerFound() && controller_index < num_gamepads_)
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY)) if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY))
{ {
successGameController = checkAxisInput(input, index); success_controller = checkAxisInput(input, controller_index);
if (!successGameController) if (!success_controller)
{ {
if (repeat) if (repeat)
{ {
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) != 0) if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
{ {
successGameController = true; success_controller = true;
} }
else else
{ {
successGameController = false; success_controller = false;
} }
} }
else else
{ {
if (!gameControllerBindings[index][input].active) if (!controller_bindings_[controller_index][input_index].active)
{ {
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) != 0) if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
{ {
gameControllerBindings[index][input].active = true; controller_bindings_[controller_index][input_index].active = true;
successGameController = true; success_controller = true;
} }
else else
{ {
successGameController = false; success_controller = false;
} }
} }
else else
{ {
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) == 0) if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) == 0)
{ {
gameControllerBindings[index][input].active = false; controller_bindings_[controller_index][input_index].active = false;
successGameController = false; success_controller = false;
} }
else else
{ {
successGameController = false; success_controller = false;
} }
} }
} }
} }
} }
return (successKeyboard || successGameController); return (success_keyboard || success_controller);
} }
// Comprueba si un input con modificador esta activo // Comprueba si un input con modificador esta activo
bool Input::checkModInput(inputs_e inputMod, inputs_e input, bool repeat, int device, int index) bool Input::checkModInput(InputType input_mod, InputType input, bool repeat, int device, int controller_index)
{ {
if (!enabled || index >= numGamepads || !checkInput(inputMod, INPUT_ALLOW_REPEAT, device, index)) if (!enabled_ || controller_index >= num_gamepads_ || !checkInput(input_mod, INPUT_ALLOW_REPEAT, device, controller_index))
{ {
return false; return false;
} }
bool successKeyboard = false; bool success_keyboard = false;
bool successGameController = false; bool success_controller = false;
const int input_index = static_cast<int>(input);
if (device == INPUT_USE_ANY) if (device == INPUT_USE_ANY)
{ {
index = 0; controller_index = 0;
} }
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY) if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
@@ -240,111 +225,111 @@ bool Input::checkModInput(inputs_e inputMod, inputs_e input, bool repeat, int de
if (repeat) if (repeat)
{ {
if (keyStates[keyBindings[input].scancode] != 0) if (keyStates[key_bindings_[input_index].scancode] != 0)
{ {
successKeyboard = true; success_keyboard = true;
} }
else else
{ {
successKeyboard = false; success_keyboard = false;
} }
} }
else else
{ {
if (!keyBindings[input].active) if (!key_bindings_[input_index].active)
{ {
if (keyStates[keyBindings[input].scancode] != 0) if (keyStates[key_bindings_[input_index].scancode] != 0)
{ {
keyBindings[input].active = true; key_bindings_[input_index].active = true;
successKeyboard = true; success_keyboard = true;
} }
else else
{ {
successKeyboard = false; success_keyboard = false;
} }
} }
else else
{ {
if (keyStates[keyBindings[input].scancode] == 0) if (keyStates[key_bindings_[input_index].scancode] == 0)
{ {
keyBindings[input].active = false; key_bindings_[input_index].active = false;
successKeyboard = false; success_keyboard = false;
} }
else else
{ {
successKeyboard = false; success_keyboard = false;
} }
} }
} }
} }
if (gameControllerFound() && index < numGamepads) if (gameControllerFound() && controller_index < num_gamepads_)
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY)) if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY))
{ {
successGameController = checkAxisInput(input, index); success_controller = checkAxisInput(input, controller_index);
if (!successGameController) if (!success_controller)
{ {
if (repeat) if (repeat)
{ {
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) != 0) if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
{ {
successGameController = true; success_controller = true;
} }
else else
{ {
successGameController = false; success_controller = false;
} }
} }
else else
{ {
if (!gameControllerBindings[index][input].active) if (!controller_bindings_[controller_index][input_index].active)
{ {
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) != 0) if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) != 0)
{ {
gameControllerBindings[index][input].active = true; controller_bindings_[controller_index][input_index].active = true;
successGameController = true; success_controller = true;
} }
else else
{ {
successGameController = false; success_controller = false;
} }
} }
else else
{ {
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][input].button) == 0) if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][input_index].button) == 0)
{ {
gameControllerBindings[index][input].active = false; controller_bindings_[controller_index][input_index].active = false;
successGameController = false; success_controller = false;
} }
else else
{ {
successGameController = false; success_controller = false;
} }
} }
} }
} }
} }
return (successKeyboard || successGameController); return (success_keyboard || success_controller);
} }
// Comprueba si hay almenos un input activo // Comprueba si hay almenos un input activo
bool Input::checkAnyInput(int device, int index) bool Input::checkAnyInput(int device, int controller_index)
{ {
if (device == INPUT_USE_ANY) if (device == INPUT_USE_ANY)
{ {
index = 0; controller_index = 0;
} }
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY) if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
{ {
const Uint8 *mKeystates = SDL_GetKeyboardState(nullptr); const Uint8 *mKeystates = SDL_GetKeyboardState(nullptr);
for (int i = 0; i < (int)keyBindings.size(); ++i) for (int i = 0; i < (int)key_bindings_.size(); ++i)
{ {
if (mKeystates[keyBindings[i].scancode] != 0 && !keyBindings[i].active) if (mKeystates[key_bindings_[i].scancode] != 0 && !key_bindings_[i].active)
{ {
keyBindings[i].active = true; key_bindings_[i].active = true;
return true; return true;
} }
} }
@@ -354,11 +339,11 @@ bool Input::checkAnyInput(int device, int index)
{ {
if (device == INPUT_USE_GAMECONTROLLER || device == INPUT_USE_ANY) if (device == INPUT_USE_GAMECONTROLLER || device == INPUT_USE_ANY)
{ {
for (int i = 0; i < (int)gameControllerBindings.size(); ++i) for (int i = 0; i < (int)controller_bindings_.size(); ++i)
{ {
if (SDL_GameControllerGetButton(connectedControllers[index], gameControllerBindings[index][i].button) != 0 && !gameControllerBindings[index][i].active) if (SDL_GameControllerGetButton(connected_controllers_[controller_index], controller_bindings_[controller_index][i].button) != 0 && !controller_bindings_[controller_index][i].active)
{ {
gameControllerBindings[index][i].active = true; controller_bindings_[controller_index][i].active = true;
return true; return true;
} }
} }
@@ -372,13 +357,13 @@ bool Input::checkAnyInput(int device, int index)
int Input::checkAnyButtonPressed(bool repeat) int Input::checkAnyButtonPressed(bool repeat)
{ {
// Si está pulsado el botón de servicio, ningún botón se puede considerar pulsado // Si está pulsado el botón de servicio, ningún botón se puede considerar pulsado
if (checkInput(input_service, INPUT_ALLOW_REPEAT, INPUT_USE_ANY)) if (checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_ANY))
{ {
return 0; return 0;
} }
// Solo comprueba los botones definidos previamente // Solo comprueba los botones definidos previamente
for (auto bi : buttonInputs) for (auto bi : button_inputs_)
{ {
// Comprueba el teclado // Comprueba el teclado
if (checkInput(bi, repeat, INPUT_USE_KEYBOARD)) if (checkInput(bi, repeat, INPUT_USE_KEYBOARD))
@@ -387,7 +372,7 @@ int Input::checkAnyButtonPressed(bool repeat)
} }
// Comprueba los mandos // Comprueba los mandos
for (int i = 0; i < numGamepads; ++i) for (int i = 0; i < num_gamepads_; ++i)
{ {
if (checkInput(bi, repeat, INPUT_USE_GAMECONTROLLER, i)) if (checkInput(bi, repeat, INPUT_USE_GAMECONTROLLER, i))
{ {
@@ -409,60 +394,63 @@ bool Input::discoverGameControllers()
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER); SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
} }
if (SDL_GameControllerAddMappingsFromFile(dbPath.c_str()) < 0) if (SDL_GameControllerAddMappingsFromFile(game_controller_db_path_.c_str()) < 0)
{ {
if (verbose) #ifdef VERBOSE
{ {
std::cout << "Error, could not load " << dbPath.c_str() << " file: " << SDL_GetError() << std::endl; std::cout << "Error, could not load " << game_controller_db_path_.c_str() << " file: " << SDL_GetError() << std::endl;
} }
#endif
} }
numJoysticks = SDL_NumJoysticks(); num_joysticks_ = SDL_NumJoysticks();
numGamepads = 0; num_gamepads_ = 0;
// Cuenta el número de mandos // Cuenta el número de mandos
joysticks.clear(); joysticks_.clear();
for (int i = 0; i < numJoysticks; ++i) for (int i = 0; i < num_joysticks_; ++i)
{ {
SDL_Joystick *joy = SDL_JoystickOpen(i); SDL_Joystick *joy = SDL_JoystickOpen(i);
joysticks.push_back(joy); joysticks_.push_back(joy);
if (SDL_IsGameController(i)) if (SDL_IsGameController(i))
{ {
numGamepads++; num_gamepads_++;
} }
} }
if (verbose) #ifdef VERBOSE
{ {
std::cout << "\nChecking for game controllers...\n"; std::cout << "\nChecking for game controllers...\n";
std::cout << numJoysticks << " joysticks found, " << numGamepads << " are gamepads\n"; std::cout << num_joysticks_ << " joysticks found, " << num_gamepads_ << " are gamepads\n";
} }
#endif
if (numGamepads > 0) if (num_gamepads_ > 0)
{ {
found = true; found = true;
for (int i = 0; i < numGamepads; i++) for (int i = 0; i < num_gamepads_; i++)
{ {
// Abre el mando y lo añade a la lista // Abre el mando y lo añade a la lista
SDL_GameController *pad = SDL_GameControllerOpen(i); auto pad = SDL_GameControllerOpen(i);
if (SDL_GameControllerGetAttached(pad) == 1) if (SDL_GameControllerGetAttached(pad) == 1)
{ {
connectedControllers.push_back(pad); connected_controllers_.push_back(pad);
const std::string separator(" #"); const std::string name = SDL_GameControllerNameForIndex(i);
std::string name = SDL_GameControllerNameForIndex(i); #ifdef VERBOSE
if (verbose)
{ {
std::cout << name << std::endl; std::cout << name << std::endl;
} }
controllerNames.push_back(name); #endif
controller_names_.push_back(name);
} }
else else
{ {
if (verbose) #ifdef VERBOSE
{ {
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl; std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
} }
#endif
} }
} }
@@ -475,47 +463,27 @@ bool Input::discoverGameControllers()
// Comprueba si hay algun mando conectado // Comprueba si hay algun mando conectado
bool Input::gameControllerFound() bool Input::gameControllerFound()
{ {
return numGamepads > 0 ? true : false; return num_gamepads_ > 0 ? true : false;
} }
// Obten el nombre de un mando de juego // Obten el nombre de un mando de juego
std::string Input::getControllerName(int index) const std::string Input::getControllerName(int controller_index) const
{ {
return numGamepads > 0 ? controllerNames[index] : ""; return num_gamepads_ > 0 ? controller_names_[controller_index] : "";
} }
// Obten el número de mandos conectados // Obten el número de mandos conectados
int Input::getNumControllers() const int Input::getNumControllers() const
{ {
return numGamepads; return num_gamepads_;
}
// Establece si ha de mostrar mensajes
void Input::setVerbose(bool value)
{
verbose = value;
}
// Deshabilita las entradas durante un periodo de tiempo
void Input::disableUntil(i_disable_e value)
{
disabledUntil = value;
enabled = false;
}
// Hablita las entradas
void Input::enable()
{
enabled = true;
disabledUntil = d_notDisabled;
} }
// Obtiene el indice del controlador a partir de un event.id // Obtiene el indice del controlador a partir de un event.id
int Input::getJoyIndex(int id) const int Input::getJoyIndex(int id) const
{ {
for (int i = 0; i < numJoysticks; ++i) for (int i = 0; i < num_joysticks_; ++i)
{ {
if (SDL_JoystickInstanceID(joysticks[i]) == id) if (SDL_JoystickInstanceID(joysticks_[i]) == id)
{ {
return i; return i;
} }
@@ -524,7 +492,7 @@ int Input::getJoyIndex(int id) const
} }
// Muestra por consola los controles asignados // Muestra por consola los controles asignados
void Input::printBindings(int device, int index) const void Input::printBindings(int device, int controller_index) const
{ {
if (device == INPUT_USE_ANY || device == INPUT_USE_KEYBOARD) if (device == INPUT_USE_ANY || device == INPUT_USE_KEYBOARD)
{ {
@@ -533,35 +501,35 @@ void Input::printBindings(int device, int index) const
if (device == INPUT_USE_GAMECONTROLLER) if (device == INPUT_USE_GAMECONTROLLER)
{ {
if (index >= numGamepads) if (controller_index >= num_gamepads_)
{ {
return; return;
} }
// Muestra el nombre del mando // Muestra el nombre del mando
std::cout << "\n" std::cout << "\n"
<< controllerNames[index] << std::endl; << controller_names_[controller_index] << std::endl;
// Muestra los botones asignados // Muestra los botones asignados
for (auto bi : buttonInputs) for (auto bi : button_inputs_)
{ {
std::cout << to_string(bi) << " : " << gameControllerBindings[index][bi].button << std::endl; std::cout << to_string(bi) << " : " << controller_bindings_[controller_index][static_cast<int>(bi)].button << std::endl;
} }
} }
} }
// Obtiene el SDL_GameControllerButton asignado a un input // Obtiene el SDL_GameControllerButton asignado a un input
SDL_GameControllerButton Input::getControllerBinding(int index, inputs_e input) const SDL_GameControllerButton Input::getControllerBinding(int controller_index, InputType input) const
{ {
return gameControllerBindings[index][input].button; return controller_bindings_[controller_index][static_cast<int>(input)].button;
} }
// Obtiene el indice a partir del nombre del mando // Obtiene el indice a partir del nombre del mando
int Input::getIndexByName(std::string name) const int Input::getIndexByName(const std::string &name) const
{ {
for (int i = 0; i < numGamepads; ++i) for (int i = 0; i < num_gamepads_; ++i)
{ {
if (controllerNames[i] == name) if (controller_names_[i] == name)
{ {
return i; return i;
} }
@@ -569,30 +537,30 @@ int Input::getIndexByName(std::string name) const
return -1; return -1;
} }
// Convierte un inputs_e a std::string // Convierte un InputType a std::string
std::string Input::to_string(inputs_e input) const std::string Input::to_string(InputType input) const
{ {
if (input == input_fire_left) if (input == InputType::FIRE_LEFT)
{ {
return "input_fire_left"; return "input_fire_left";
} }
if (input == input_fire_center) if (input == InputType::FIRE_CENTER)
{ {
return "input_fire_center"; return "input_fire_center";
} }
if (input == input_fire_right) if (input == InputType::FIRE_RIGHT)
{ {
return "input_fire_right"; return "input_fire_right";
} }
if (input == input_start) if (input == InputType::START)
{ {
return "input_start"; return "input_start";
} }
if (input == input_service) if (input == InputType::SERVICE)
{ {
return "input_service"; return "input_service";
} }
@@ -600,76 +568,67 @@ std::string Input::to_string(inputs_e input) const
return ""; return "";
} }
// Convierte un std::string a inputs_e // Convierte un std::string a InputType
inputs_e Input::to_inputs_e(std::string name) const InputType Input::to_inputs_e(const std::string &name) const
{ {
if (name == "input_fire_left") if (name == "input_fire_left")
{ {
return input_fire_left; return InputType::FIRE_LEFT;
} }
if (name == "input_fire_center") if (name == "input_fire_center")
{ {
return input_fire_center; return InputType::FIRE_CENTER;
} }
if (name == "input_fire_right") if (name == "input_fire_right")
{ {
return input_fire_right; return InputType::FIRE_RIGHT;
} }
if (name == "input_start") if (name == "input_start")
{ {
return input_start; return InputType::START;
} }
if (name == "input_service") if (name == "input_service")
{ {
return input_service; return InputType::SERVICE;
} }
return input_null; return InputType::NONE;
}
// Activa todos los inputs. Sirve para evitar inputs sin repeticiones pero que ya vienen pulsados cuando checkInput no estaba monitorizando
void Input::allActive(int index)
{
for (int i = 0; i < (int)buttonInputs.size(); ++i)
{
gameControllerBindings[index][i].active = true;
}
} }
// Comprueba el eje del mando // Comprueba el eje del mando
bool Input::checkAxisInput(inputs_e input, int index) const bool Input::checkAxisInput(InputType input, int controller_index) const
{ {
bool success = false; bool success = false;
switch (input) switch (input)
{ {
case input_left: case InputType::LEFT:
if (SDL_GameControllerGetAxis(connectedControllers[index], SDL_CONTROLLER_AXIS_LEFTX) < -30000) if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) < -30000)
{ {
success = true; success = true;
} }
break; break;
case input_right: case InputType::RIGHT:
if (SDL_GameControllerGetAxis(connectedControllers[index], SDL_CONTROLLER_AXIS_LEFTX) > 30000) if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) > 30000)
{ {
success = true; success = true;
} }
break; break;
case input_up: case InputType::UP:
if (SDL_GameControllerGetAxis(connectedControllers[index], SDL_CONTROLLER_AXIS_LEFTY) < -30000) if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) < -30000)
{ {
success = true; success = true;
} }
break; break;
case input_down: case InputType::DOWN:
if (SDL_GameControllerGetAxis(connectedControllers[index], SDL_CONTROLLER_AXIS_LEFTY) > 30000) if (SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) > 30000)
{ {
success = true; success = true;
} }

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,14 +1,13 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event #include <SDL2/SDL_stdinc.h> // for Uint32, Uint8
#include <SDL2/SDL_stdinc.h> // for Uint32, Uint8 #include <memory> // for unique_ptr, shared_ptr
#include <vector> // for vector #include <vector> // for vector
#include <memory> #include "smart_sprite.h" // for SmartSprite
#include "smart_sprite.h" #include "writer.h" // for Writer
#include "texture.h" class Text;
#include "text.h" class Texture;
#include "writer.h" struct JA_Music_t; // lines 11-11
struct JA_Music_t;
/* /*
Esta clase gestiona un estado del programa. Se encarga de mostrar la secuencia Esta clase gestiona un estado del programa. Se encarga de mostrar la secuencia
@@ -20,17 +19,17 @@ class Intro
{ {
private: private:
// Objetos // Objetos
std::shared_ptr<Texture> texture; // Textura con los graficos std::shared_ptr<Texture> texture_; // Textura con los graficos
std::shared_ptr<Text> text; // Textos de la intro std::shared_ptr<Text> text_; // Textos de la intro
std::vector<std::unique_ptr<SmartSprite>> bitmaps; // Vector con los sprites inteligentes para los dibujos de la intro std::vector<std::unique_ptr<SmartSprite>> bitmaps_; // Vector con los sprites inteligentes para los dibujos de la intro
std::vector<std::unique_ptr<Writer>> texts; // Textos de la intro std::vector<std::unique_ptr<Writer>> texts_; // Textos de la intro
// Variables // Variables
Uint32 ticks; // Contador de ticks para ajustar la velocidad del programa Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
Uint8 ticksSpeed; // Velocidad a la que se repiten los bucles del programa Uint8 ticks_speed_; // Velocidad a la que se repiten los bucles del programa
JA_Music_t *music; // Musica para la intro JA_Music_t *music_; // Musica para la intro
int scene; // Indica que escena está activa int scene_; // Indica que escena está activa
// Actualiza las variables del objeto // Actualiza las variables del objeto
void update(); void update();
@@ -52,7 +51,7 @@ private:
public: public:
// Constructor // Constructor
Intro(JA_Music_t *music); explicit Intro(JA_Music_t *music);
// Destructor // Destructor
~Intro() = default; ~Intro() = default;

View File

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

View File

@@ -1,44 +1,45 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint16 #include <SDL2/SDL_stdinc.h> // for Uint16
#include <string> // for string #include <memory> // for shared_ptr, unique_ptr
#include <vector> // for vector #include <string> // for string
#include <memory> #include <vector> // for vector
#include "utils.h" // for Circle #include "animated_sprite.h" // for AnimatedSprite
#include "animated_sprite.h" #include "utils.h" // for Circle
#include "texture.h" class Texture;
// Tipos de objetos // Tipos de objetos
#define ITEM_POINTS_1_DISK 1 constexpr int ITEM_POINTS_1_DISK = 1;
#define ITEM_POINTS_2_GAVINA 2 constexpr int ITEM_POINTS_2_GAVINA = 2;
#define ITEM_POINTS_3_PACMAR 3 constexpr int ITEM_POINTS_3_PACMAR = 3;
#define ITEM_CLOCK 4 constexpr int ITEM_CLOCK = 4;
#define ITEM_COFFEE 5 constexpr int ITEM_COFFEE = 5;
#define ITEM_COFFEE_MACHINE 6 constexpr int ITEM_COFFEE_MACHINE = 6;
#define ITEM_NULL 7 constexpr int ITEM_NULL = 7;
// Clase Item // Clase Item
class Item class Item
{ {
private: private:
// Objetos y punteros // Objetos y punteros
std::unique_ptr<AnimatedSprite> sprite; // Sprite con los graficos del objeto std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los graficos del objeto
// Variables // Variables
float posX; // Posición X del objeto float pos_x_; // Posición X del objeto
float posY; // Posición Y del objeto float pos_y_; // Posición Y del objeto
int width; // Ancho del objeto int width_; // Ancho del objeto
int height; // Alto del objeto int height_; // Alto del objeto
float velX; // Velocidad en el eje X float vel_x_; // Velocidad en el eje X
float velY; // Velocidad en el eje Y float vel_y_; // Velocidad en el eje Y
float accelX; // Aceleración en el eje X float accel_x_; // Aceleración en el eje X
float accelY; // Aceleración en el eje Y float accel_y_; // Aceleración en el eje Y
bool floorCollision; // Indica si el objeto colisiona con el suelo bool floor_collision_; // Indica si el objeto colisiona con el suelo
int kind; // Especifica el tipo de objeto que es int kind_; // Especifica el tipo de objeto que es
bool enabled; // Especifica si el objeto está habilitado bool enabled_; // Especifica si el objeto está habilitado
Circle collider; // Circulo de colisión del objeto Circle collider_; // Circulo de colisión del objeto
SDL_Rect *playArea; // Rectangulo con la zona de juego SDL_Rect *play_area_; // Rectangulo con la zona de juego
Uint16 time_to_live_; // Temporizador con el tiempo que el objeto está presente
// Alinea el circulo de colisión con la posición del objeto // Alinea el circulo de colisión con la posición del objeto
void shiftColliders(); void shiftColliders();
@@ -46,11 +47,15 @@ private:
// Actualiza la posición y estados del objeto // Actualiza la posición y estados del objeto
void move(); void move();
public: // Actualiza el contador
Uint16 timeToLive; // Temporizador con el tiempo que el objeto está presente void updateTimeToLive();
// Comprueba si el objeto sigue vivo
void checkTimeToLive();
public:
// Constructor // Constructor
Item(int kind, float x, float y, SDL_Rect *playArea, std::shared_ptr<Texture> texture, std::vector<std::string> *animation); Item(int kind, float x, float y, SDL_Rect *play_area, std::shared_ptr<Texture> texture, std::vector<std::string> *animation);
// Destructor // Destructor
~Item() = default; ~Item() = default;
@@ -67,12 +72,6 @@ public:
// Actualiza al objeto a su posicion, animación y controla los contadores // Actualiza al objeto a su posicion, animación y controla los contadores
void update(); void update();
// Actualiza el contador
void updateTimeToLive();
// Comprueba si el objeto sigue vivo
void checkTimeToLive();
// Obtiene del valor de la variable // Obtiene del valor de la variable
float getPosX(); float getPosX();

View File

@@ -7,13 +7,13 @@ namespace lang
std::vector<std::string> texts; // Vector con los textos std::vector<std::string> texts; // Vector con los textos
// Inicializa los textos del juego en el idioma seleccionado // Inicializa los textos del juego en el idioma seleccionado
bool loadFromFile(std::string filePath) bool loadFromFile(std::string file_path)
{ {
texts.clear(); texts.clear();
bool success = false; bool success = false;
std::ifstream rfile(filePath); std::ifstream rfile(file_path);
if (rfile.is_open() && rfile.good()) if (rfile.is_open() && rfile.good())
{ {
success = true; success = true;

View File

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

View File

@@ -1,17 +1,18 @@
#include "logo.h" #include "logo.h"
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED #include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include <string> // for basic_string #include <SDL2/SDL_video.h> // for SDL_WINDOWEVENT_SIZE_CHANGED
#include "asset.h" // for Asset #include <utility> // for move
#include "global_inputs.h" // for globalInputs::check #include "asset.h" // for Asset
#include "input.h" // for Input #include "global_inputs.h" // for check
#include "jail_audio.h" // for JA_StopMusic #include "input.h" // for Input
#include "param.h" // for param #include "jail_audio.h" // for JA_StopMusic
#include "screen.h" // for Screen #include "param.h" // for param
#include "section.h" // for name, SectionName, options, SectionOptions #include "screen.h" // for Screen
#include "sprite.h" // for Sprite #include "section.h" // for Name, name, Options, options
#include "texture.h" // for Texture #include "sprite.h" // for Sprite
#include "texture.h" // for Texture
// Constructor // Constructor
Logo::Logo() Logo::Logo()
@@ -20,54 +21,47 @@ Logo::Logo()
SDL_Renderer *renderer = Screen::get()->getRenderer(); SDL_Renderer *renderer = Screen::get()->getRenderer();
// Reserva memoria para los punteros // Reserva memoria para los punteros
jailTexture = std::make_shared<Texture>(renderer, Asset::get()->get("logo_jailgames.png")); jail_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("logo_jailgames.png"));
sinceTexture = std::make_shared<Texture>(renderer, Asset::get()->get("logo_since_1998.png")); since_texture_ = std::make_shared<Texture>(renderer, Asset::get()->get("logo_since_1998.png"));
sinceSprite = std::make_unique<Sprite>((param.game.width - sinceTexture->getWidth()) / 2, 83 + jailTexture->getHeight() + 5, sinceTexture->getWidth(), sinceTexture->getHeight(), sinceTexture); since_sprite_ = std::make_unique<Sprite>((param.game.width - since_texture_->getWidth()) / 2, 83 + jail_texture_->getHeight() + 5, since_texture_->getWidth(), since_texture_->getHeight(), since_texture_);
// Inicializa variables // Inicializa variables
counter = 0; counter_ = 0;
section::name = section::Name::LOGO; section::name = section::Name::LOGO;
ticks = 0; ticks_ = 0;
ticksSpeed = 15; dest_.x = param.game.game_area.center_x - jail_texture_->getWidth() / 2;
showSinceSprite_cm = 70; dest_.y = param.game.game_area.center_y - jail_texture_->getHeight() / 2;
initFade_cm = 300; since_sprite_->setPosY(dest_.y + jail_texture_->getHeight() + 5);
endLogo_cm = 400; since_sprite_->setSpriteClip(0, 0, since_texture_->getWidth(), since_texture_->getHeight());
postLogoDuration = 20; since_texture_->setColor(0x00, 0x00, 0x00); // Esto en linux no hace nada ??
speed = 8;
dest.x = param.game.game_area.center_x - jailTexture->getWidth() / 2;
dest.y = param.game.game_area.center_y - jailTexture->getHeight() / 2;
sinceSprite->setPosY(dest.y + jailTexture->getHeight() + 5);
sinceSprite->setSpriteClip(0, 0, sinceTexture->getWidth(), sinceTexture->getHeight());
sinceSprite->setEnabled(false);
sinceTexture->setColor(0x00, 0x00, 0x00); // Esto en linux no hace nada ??
// Crea los sprites de cada linea // Crea los sprites de cada linea
for (int i = 0; i < jailTexture->getHeight(); ++i) for (int i = 0; i < jail_texture_->getHeight(); ++i)
{ {
auto temp = std::make_unique<Sprite>(0, i, jailTexture->getWidth(), 1, jailTexture); auto temp = std::make_unique<Sprite>(0, i, jail_texture_->getWidth(), 1, jail_texture_);
temp->setSpriteClip(0, i, jailTexture->getWidth(), 1); temp->setSpriteClip(0, i, jail_texture_->getWidth(), 1);
const int posX = (i % 2 == 0) ? param.game.width + (i * 3) : -jailTexture->getWidth() - (i * 3); const int posX = (i % 2 == 0) ? param.game.width + (i * 3) : -jail_texture_->getWidth() - (i * 3);
temp->setPosX(posX); temp->setPosX(posX);
temp->setPosY(dest.y + i); temp->setPosY(dest_.y + i);
jailSprite.push_back(std::move(temp)); jail_sprite_.push_back(std::move(temp));
} }
// Inicializa el vector de colores // Inicializa el vector de colores
color.push_back({0x00, 0x00, 0x00}); // Black color_.push_back({0x00, 0x00, 0x00}); // Black
color.push_back({0x00, 0x00, 0xd8}); // Blue color_.push_back({0x00, 0x00, 0xd8}); // Blue
color.push_back({0xd8, 0x00, 0x00}); // Red color_.push_back({0xd8, 0x00, 0x00}); // Red
color.push_back({0xd8, 0x00, 0xd8}); // Magenta color_.push_back({0xd8, 0x00, 0xd8}); // Magenta
color.push_back({0x00, 0xd8, 0x00}); // Green color_.push_back({0x00, 0xd8, 0x00}); // Green
color.push_back({0x00, 0xd8, 0xd8}); // Cyan color_.push_back({0x00, 0xd8, 0xd8}); // Cyan
color.push_back({0xd8, 0xd8, 0x00}); // Yellow color_.push_back({0xd8, 0xd8, 0x00}); // Yellow
color.push_back({0xFF, 0xFF, 0xFF}); // Bright white color_.push_back({0xFF, 0xFF, 0xFF}); // Bright white
} }
// Recarga todas las texturas // Recarga todas las texturas
void Logo::reloadTextures() void Logo::reloadTextures()
{ {
jailTexture->reLoad(); jail_texture_->reLoad();
sinceTexture->reLoad(); since_texture_->reLoad();
} }
// Comprueba el manejador de eventos // Comprueba el manejador de eventos
@@ -117,26 +111,26 @@ void Logo::checkInput()
// Gestiona el logo de JAILGAME // Gestiona el logo de JAILGAME
void Logo::updateJAILGAMES() void Logo::updateJAILGAMES()
{ {
if (counter > 30) if (counter_ > 30)
{ {
for (int i = 0; i < (int)jailSprite.size(); ++i) for (int i = 0; i < (int)jail_sprite_.size(); ++i)
{ {
if (jailSprite[i]->getPosX() != dest.x) if (jail_sprite_[i]->getIntPosX() != dest_.x)
{ {
if (i % 2 == 0) if (i % 2 == 0)
{ {
jailSprite[i]->incPosX(-speed); jail_sprite_[i]->incPosX(-SPEED);
if (jailSprite[i]->getPosX() < dest.x) if (jail_sprite_[i]->getIntPosX() < dest_.x)
{ {
jailSprite[i]->setPosX(dest.x); jail_sprite_[i]->setPosX(dest_.x);
} }
} }
else else
{ {
jailSprite[i]->incPosX(speed); jail_sprite_[i]->incPosX(SPEED);
if (jailSprite[i]->getPosX() > dest.x) if (jail_sprite_[i]->getIntPosX() > dest_.x)
{ {
jailSprite[i]->setPosX(dest.x); jail_sprite_[i]->setPosX(dest_.x);
} }
} }
} }
@@ -152,19 +146,19 @@ void Logo::updateTextureColors()
// Manejo de 'sinceTexture' // Manejo de 'sinceTexture'
for (int i = 0; i <= 7; ++i) for (int i = 0; i <= 7; ++i)
{ {
if (counter == showSinceSprite_cm + inc * i) if (counter_ == SHOW_SINCE_SPRITE_COUNTER_MARK + inc * i)
{ {
sinceTexture->setColor(color[i].r, color[i].g, color[i].b); since_texture_->setColor(color_[i].r, color_[i].g, color_[i].b);
} }
} }
// Manejo de 'jailTexture' y 'sinceTexture' en el fade // Manejo de 'jailTexture' y 'sinceTexture' en el fade
for (int i = 0; i <= 6; ++i) for (int i = 0; i <= 6; ++i)
{ {
if (counter == initFade_cm + inc * i) if (counter_ == INIT_FADE_COUNTER_MARK + inc * i)
{ {
jailTexture->setColor(color[6 - i].r, color[6 - i].g, color[6 - i].b); jail_texture_->setColor(color_[6 - i].r, color_[6 - i].g, color_[6 - i].b);
sinceTexture->setColor(color[6 - i].r, color[6 - i].g, color[6 - i].b); since_texture_->setColor(color_[6 - i].r, color_[6 - i].g, color_[6 - i].b);
} }
} }
} }
@@ -173,10 +167,10 @@ void Logo::updateTextureColors()
void Logo::update() void Logo::update()
{ {
// Comprueba que la diferencia de ticks sea mayor a la velocidad del juego // Comprueba que la diferencia de ticks sea mayor a la velocidad del juego
if (SDL_GetTicks() - ticks > ticksSpeed) if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
{ {
// Actualiza el contador de ticks // Actualiza el contador de ticks
ticks = SDL_GetTicks(); ticks_ = SDL_GetTicks();
// Actualiza el objeto screen // Actualiza el objeto screen
Screen::get()->update(); Screen::get()->update();
@@ -191,19 +185,13 @@ void Logo::update()
updateTextureColors(); updateTextureColors();
// Gestiona el contador y sus eventos // Gestiona el contador y sus eventos
counter++; counter_++;
// Comprueba si ha terminado el logo // Comprueba si ha terminado el logo
if (counter == endLogo_cm + postLogoDuration) if (counter_ == END_LOGO_COUNTER_MARK + POST_LOGO_DURATION)
{ {
section::name = section::Name::INTRO; section::name = section::Name::INTRO;
} }
// Comprueba si se ha de mostrar el sprite
else if (counter == showSinceSprite_cm)
{
sinceSprite->setEnabled(true);
}
} }
} }
@@ -217,11 +205,15 @@ void Logo::render()
Screen::get()->clean(); Screen::get()->clean();
// Dibuja los sprites // Dibuja los sprites
for (auto &sprite : jailSprite) for (auto &sprite : jail_sprite_)
{ {
sprite->render(); sprite->render();
} }
sinceSprite->render();
if (counter_ >= SHOW_SINCE_SPRITE_COUNTER_MARK)
{
since_sprite_->render();
}
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
Screen::get()->blit(); Screen::get()->blit();

View File

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

View File

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

View File

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

View File

@@ -17,14 +17,14 @@ class ManageHiScoreTable
{ {
private: private:
// Variables // Variables
std::vector<HiScoreEntry> *table; // Tabla con los records std::vector<HiScoreEntry> *table_; // Tabla con los records
// Ordena la tabla // Ordena la tabla
void sort(); void sort();
public: public:
// Constructor // Constructor
ManageHiScoreTable(std::vector<HiScoreEntry> *table); explicit ManageHiScoreTable(std::vector<HiScoreEntry> *table);
// Destructor // Destructor
~ManageHiScoreTable() = default; ~ManageHiScoreTable() = default;
@@ -36,8 +36,8 @@ public:
void add(HiScoreEntry entry); void add(HiScoreEntry entry);
// Carga la tabla con los datos de un fichero // Carga la tabla con los datos de un fichero
bool loadFromFile(std::string filePath); bool loadFromFile(const std::string &file_path);
// Guarda la tabla en un fichero // Guarda la tabla en un fichero
bool saveToFile(std::string filePath); bool saveToFile(const std::string &file_path);
}; };

View File

@@ -3,31 +3,32 @@
// Constructor // Constructor
MovingSprite::MovingSprite(float x, float y, int w, int h, float vx, float vy, float ax, float ay, std::shared_ptr<Texture> texture) MovingSprite::MovingSprite(float x, float y, int w, int h, float vx, float vy, float ax, float ay, std::shared_ptr<Texture> texture)
: Sprite((int)x, (int)y, w, h, texture), x_(x), y_(y), vx_(vx), vy_(vy), ax_(ax), ay_(ay) : Sprite((int)x, (int)y, w, h, texture),
x_(x),
y_(y),
vx_(vx),
vy_(vy),
ax_(ax),
ay_(ay),
zoom_w_(1),
zoom_h_(1),
counter_(0),
flip_(SDL_FLIP_NONE)
{ {
// Establece el zoom W,H del sprite
zoomW_ = 1;
zoomH_ = 1;
// Establece el angulo con el que se dibujará
angle_ = (double)0;
// Establece los valores de rotacion // Establece los valores de rotacion
rotateEnabled_ = false; rotate_.enabled = false;
rotateSpeed_ = 0; rotate_.speed = 0;
rotateAmount_ = (double)0; rotate_.angle = 0.0f;
rotate_.amount = 0.0f;
rotate_.center = nullptr;
// Contador interno sprite_clip_ = (SDL_Rect){0, 0, w, h};
counter_ = 0; };
// Establece el rectangulo de donde coger la imagen MovingSprite::MovingSprite(std::shared_ptr<Texture> texture)
spriteClip_ = {0, 0, w_, h_}; : Sprite(texture)
{
// Establece el centro de rotación clear();
center_ = nullptr;
// Establece el tipo de volteado
currentFlip_ = SDL_FLIP_NONE;
}; };
// Reinicia todas las variables // Reinicia todas las variables
@@ -42,17 +43,21 @@ void MovingSprite::clear()
ax_ = 0.0f; // Aceleración en el eje X. Variación de la velocidad ax_ = 0.0f; // Aceleración en el eje X. Variación de la velocidad
ay_ = 0.0f; // Aceleración en el eje Y. Variación de la velocidad ay_ = 0.0f; // Aceleración en el eje Y. Variación de la velocidad
zoomW_ = 1.0f; // Zoom aplicado a la anchura zoom_w_ = 1.0f; // Zoom aplicado a la anchura
zoomH_ = 1.0f; // Zoom aplicado a la altura zoom_h_ = 1.0f; // Zoom aplicado a la altura
angle_ = 0.0; // Angulo para dibujarlo rotate_.enabled = false; // Indica si ha de rotar
rotateEnabled_ = false; // Indica si ha de rotar rotate_.speed = 0; // Velocidad de giro
center_ = nullptr; // Centro de rotación rotate_.angle = 0.0f; // Angulo para dibujarlo
rotateSpeed_ = 0; // Velocidad de giro rotate_.amount = 0.0f; // Cantidad de grados a girar en cada iteración
rotateAmount_ = 0.0; // Cantidad de grados a girar en cada iteración rotate_.center = nullptr; // Centro de rotación
counter_ = 0; // Contador interno
currentFlip_ = SDL_FLIP_NONE; // Establece como se ha de voltear el sprite counter_ = 0; // Contador interno
flip_ = SDL_FLIP_NONE; // Establece como se ha de voltear el sprite
setPos((SDL_Rect){0, 0, 0, 0});
setSpriteClip((SDL_Rect){0, 0, 0, 0});
} }
// Mueve el sprite // Mueve el sprite
@@ -68,10 +73,7 @@ void MovingSprite::move()
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void MovingSprite::render() void MovingSprite::render()
{ {
if (enabled_) texture_->render((int)x_, (int)y_, &sprite_clip_, zoom_w_, zoom_h_, (double)rotate_.angle, rotate_.center, flip_);
{
texture_->render((int)x_, (int)y_, &spriteClip_, zoomW_, zoomH_, angle_, center_, currentFlip_);
}
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
@@ -113,28 +115,28 @@ float MovingSprite::getAccelY() const
// Obtiene el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getZoomW() const float MovingSprite::getZoomW() const
{ {
return zoomW_; return zoom_w_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
float MovingSprite::getZoomH() const float MovingSprite::getZoomH() const
{ {
return zoomH_; return zoom_h_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
double MovingSprite::getAngle() const float MovingSprite::getAngle() const
{ {
return angle_; return rotate_.angle;
} }
// Establece la posición y_ el tamaño del objeto // Establece la posición y_ el tamaño del objeto
void MovingSprite::setRect(SDL_Rect rect) void MovingSprite::setPos(SDL_Rect rect)
{ {
x_ = (float)rect.x; x_ = (float)rect.x;
y_ = (float)rect.y; y_ = (float)rect.y;
w_ = rect.w;
h_ = rect.h; pos_ = rect;
} }
// Establece el valor de las variables // Establece el valor de las variables
@@ -142,18 +144,23 @@ void MovingSprite::setPos(float x, float y)
{ {
x_ = x; x_ = x;
y_ = y; y_ = y;
pos_.x = (int)x;
pos_.y = (int)y;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setPosX(float value) void MovingSprite::setPosX(float value)
{ {
x_ = value; x_ = value;
pos_.x = (int)x_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setPosY(float value) void MovingSprite::setPosY(float value)
{ {
y_ = value; y_ = value;
pos_.y = (int)y_;
} }
// Establece el valor de la variable // Establece el valor de la variable
@@ -183,53 +190,53 @@ void MovingSprite::setAccelY(float value)
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setZoomW(float value) void MovingSprite::setZoomW(float value)
{ {
zoomW_ = value; zoom_w_ = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setZoomH(float value) void MovingSprite::setZoomH(float value)
{ {
zoomH_ = value; zoom_h_ = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setAngle(double value) void MovingSprite::setAngle(double value)
{ {
angle_ = value; rotate_.angle = value;
} }
// Incrementa el valor de la variable // Incrementa el valor de la variable
void MovingSprite::incAngle(double value) void MovingSprite::incAngle(double value)
{ {
angle_ += value; rotate_.angle += value;
} }
// Decrementa el valor de la variable // Decrementa el valor de la variable
void MovingSprite::decAngle(double value) void MovingSprite::decAngle(double value)
{ {
angle_ -= value; rotate_.angle -= value;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool MovingSprite::getRotate() const bool MovingSprite::getRotate() const
{ {
return rotateEnabled_; return rotate_.enabled;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
Uint16 MovingSprite::getRotateSpeed() const Uint16 MovingSprite::getRotateSpeed() const
{ {
return rotateSpeed_; return rotate_.speed;
} }
// Establece la rotacion // Establece la rotacion
void MovingSprite::rotate() void MovingSprite::rotate()
{ {
if (rotateEnabled_) if (rotate_.enabled)
{ {
if (counter_ % rotateSpeed_ == 0) if (counter_ % rotate_.speed == 0)
{ {
incAngle(rotateAmount_); incAngle(rotate_.amount);
} }
} }
} }
@@ -237,65 +244,62 @@ void MovingSprite::rotate()
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setRotate(bool value) void MovingSprite::setRotate(bool value)
{ {
rotateEnabled_ = value; rotate_.enabled = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setRotateSpeed(int value) void MovingSprite::setRotateSpeed(int value)
{ {
rotateSpeed_ = (value < 1) ? 1 : value; rotate_.speed = (value < 1) ? 1 : value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setRotateAmount(double value) void MovingSprite::setRotateAmount(double value)
{ {
rotateAmount_ = value; rotate_.amount = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::disableRotate() void MovingSprite::disableRotate()
{ {
rotateEnabled_ = false; rotate_.enabled = false;
angle_ = (double)0; rotate_.angle = 0.0f;
} }
// Actualiza las variables internas del objeto // Actualiza las variables internas del objeto
void MovingSprite::update() void MovingSprite::update()
{ {
if (enabled_) move();
{ rotate();
move(); ++counter_ %= 60000;
rotate();
++counter_ %= 60000;
}
} }
// Cambia el sentido de la rotación // Cambia el sentido de la rotación
void MovingSprite::switchRotate() void MovingSprite::switchRotate()
{ {
rotateAmount_ *= -1; rotate_.amount *= -1;
} }
// Establece el valor de la variable // Establece el valor de la variable
void MovingSprite::setFlip(SDL_RendererFlip flip) void MovingSprite::setFlip(SDL_RendererFlip flip)
{ {
currentFlip_ = flip; flip_ = flip;
} }
// Gira el sprite horizontalmente // Gira el sprite horizontalmente
void MovingSprite::flip() void MovingSprite::flip()
{ {
currentFlip_ = (currentFlip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL; flip_ = (flip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
SDL_RendererFlip MovingSprite::getFlip() SDL_RendererFlip MovingSprite::getFlip()
{ {
return currentFlip_; return flip_;
} }
// Devuelve el rectangulo donde está el sprite // Devuelve el rectangulo donde está el sprite
SDL_Rect MovingSprite::getRect() SDL_Rect MovingSprite::getPos() const
{ {
return (SDL_Rect){(int)x_, (int)y_, w_, h_}; return (SDL_Rect){(int)x_, (int)y_, pos_.w, pos_.h};
} }

View File

@@ -3,14 +3,23 @@
#include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point #include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point
#include <SDL2/SDL_render.h> // for SDL_RendererFlip #include <SDL2/SDL_render.h> // for SDL_RendererFlip
#include <SDL2/SDL_stdinc.h> // for Uint16 #include <SDL2/SDL_stdinc.h> // for Uint16
#include <memory> #include <memory> // for shared_ptr
#include "sprite.h" // for Sprite #include "sprite.h" // for Sprite
#include "texture.h" class Texture;
// Clase MovingSprite. Añade posicion y velocidad en punto flotante // Clase MovingSprite. Añade posicion y velocidad en punto flotante
class MovingSprite : public Sprite class MovingSprite : public Sprite
{ {
protected: protected:
struct Rotate
{
bool enabled; // Indica si ha de rotar
int speed; // Velocidad de giro
float angle; // Angulo para dibujarlo
float amount; // Cantidad de grados a girar en cada iteración
SDL_Point *center; // Centro de rotación
};
float x_; // Posición en el eje X float x_; // Posición en el eje X
float y_; // Posición en el eje Y float y_; // Posición en el eje Y
@@ -20,20 +29,20 @@ protected:
float ax_; // Aceleración en el eje X. Variación de la velocidad float ax_; // Aceleración en el eje X. Variación de la velocidad
float ay_; // Aceleración en el eje Y. Variación de la velocidad float ay_; // Aceleración en el eje Y. Variación de la velocidad
float zoomW_; // Zoom aplicado a la anchura float zoom_w_; // Zoom aplicado a la anchura
float zoomH_; // Zoom aplicado a la altura float zoom_h_; // Zoom aplicado a la altura
double angle_; // Angulo para dibujarlo int counter_; // Contador interno
bool rotateEnabled_; // Indica si ha de rotar Rotate rotate_; // Variables usada para controlar la rotación del sprite
int rotateSpeed_; // Velocidad de giro SDL_RendererFlip flip_; // Indica como se voltea el sprite
double rotateAmount_; // Cantidad de grados a girar en cada iteración
int counter_; // Contador interno
SDL_Point *center_; // Centro de rotación
SDL_RendererFlip currentFlip_; // Indica como se voltea el sprite
public: public:
// Constructor // Constructor
MovingSprite(float x = 0, float y = 0, int w = 0, int h = 0, float velx = 0, float vely = 0, float accelx = 0, float accely = 0, std::shared_ptr<Texture> texture = nullptr); explicit MovingSprite(float x = 0, float y = 0, int w = 0, int h = 0, float velx = 0, float vely = 0, float accelx = 0, float accely = 0, std::shared_ptr<Texture> texture = nullptr);
explicit MovingSprite(std::shared_ptr<Texture> texture = nullptr);
// Destructor
virtual ~MovingSprite() = default;
// Mueve el sprite // Mueve el sprite
void move(); void move();
@@ -42,13 +51,13 @@ public:
void rotate(); void rotate();
// Actualiza las variables internas del objeto // Actualiza las variables internas del objeto
void update(); virtual void update();
// Reinicia todas las variables // Reinicia todas las variables
void clear(); void clear();
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void render(); void render() override;
// Obten el valor de la variable // Obten el valor de la variable
float getPosX() const; float getPosX() const;
@@ -67,16 +76,17 @@ public:
float getZoomH() const; float getZoomH() const;
// Obten el valor de la variable // Obten el valor de la variable
double getAngle() const; float getAngle() const;
bool getRotate() const; bool getRotate() const;
Uint16 getRotateSpeed() const; Uint16 getRotateSpeed() const;
// Establece la posición y el tamaño del objeto // Establece la posición del objeto
void setRect(SDL_Rect rect); void setPos(SDL_Rect rect) override;
// Establece el valor de las variables
void setPos(float x, float y); void setPos(float x, float y);
// Devuelve el rectangulo donde está el sprite
SDL_Rect getPos() const override;
// Establece el valor de la variable // Establece el valor de la variable
void setPosX(float value); void setPosX(float value);
void setPosY(float value); void setPosY(float value);
@@ -118,6 +128,5 @@ public:
// Obtiene el valor de la variable // Obtiene el valor de la variable
SDL_RendererFlip getFlip(); SDL_RendererFlip getFlip();
// Devuelve el rectangulo donde está el sprite
SDL_Rect getRect();
}; };

View File

@@ -1,31 +1,27 @@
#include "notify.h" #include "notify.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <string> // for basic_string, char_traits, string #include <string> // for string
#include "jail_audio.h" // for JA_DeleteSound, JA_LoadSound, JA_Pla... #include "jail_audio.h" // for JA_DeleteSound, JA_LoadSound, JA_Pla...
#include "options.h" // for options #include "param.h" // for param
#include "param.h" #include "sprite.h" // for Sprite
#include "sprite.h" // for Sprite #include "text.h" // for Text
#include "text.h" // for Text #include "texture.h" // for Texture
#include "texture.h" // for Texture
// Constructor // Constructor
Notify::Notify(SDL_Renderer *renderer, std::string iconFile, std::string bitmapFile, std::string textFile, std::string soundFile) Notify::Notify(SDL_Renderer *renderer, std::string iconFile, std::string bitmapFile, std::string textFile, const std::string &soundFile)
: renderer(renderer) : renderer(renderer),
text(std::make_unique<Text>(bitmapFile, textFile, renderer)),
bgColor(param.notification.color),
waitTime(150),
stack(false),
sound(JA_LoadSound(soundFile.c_str()))
{ {
// Inicializa variables // Inicializa variables
bgColor = param.notification.color; hasIcons = !iconFile.empty();
waitTime = 150;
stack = false;
hasIcons = iconFile == "" ? false : true;
// Crea objetos // Crea objetos
if (hasIcons) iconTexture = hasIcons ? std::make_unique<Texture>(renderer, iconFile) : nullptr;
{
iconTexture = std::make_unique<Texture>(renderer, iconFile);
}
text = std::make_unique<Text>(bitmapFile, textFile, renderer);
sound = JA_LoadSound(soundFile.c_str());
} }
// Destructor // Destructor
@@ -150,18 +146,19 @@ void Notify::clearFinishedNotifications()
void Notify::showText(std::string text1, std::string text2, int icon) void Notify::showText(std::string text1, std::string text2, int icon)
{ {
// Cuenta el número de textos a mostrar // Cuenta el número de textos a mostrar
const int numTexts = (text1 != "") + (text2 != ""); const int numTexts = !text1.empty() + !text2.empty();
// Si no hay texto, acaba // Si no hay texto, acaba
if (numTexts == 0) if (numTexts == 0)
{ {
return; return;
} }
// Si solo hay un texto, lo coloca en la primera variable // Si solo hay un texto, lo coloca en la primera variable
else if (numTexts == 1) if (numTexts == 1)
{ {
text1 = text1 + text2; text1 += text2;
text2 = ""; text2.clear();
} }
// Si las notificaciones no se apilan, elimina las anteriores // Si las notificaciones no se apilan, elimina las anteriores

View File

@@ -1,15 +1,15 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_render.h> // for SDL_Renderer
#include <string> // for basic_string, string #include <memory> // for shared_ptr, unique_ptr
#include <vector> // for vector #include <string> // for string, basic_string
#include <memory> #include <vector> // for vector
#include "utils.h" // for Color #include "utils.h" // for Color
#include "text.h" class Sprite;
#include "texture.h" class Text;
#include "sprite.h" class Texture;
struct JA_Sound_t; struct JA_Sound_t; // lines 12-12
class Notify class Notify
{ {
@@ -65,9 +65,9 @@ private:
Color bgColor; // Color de fondo de las notificaciones Color bgColor; // Color de fondo de las notificaciones
int waitTime; // Tiempo que se ve la notificación int waitTime; // Tiempo que se ve la notificación
std::vector<Notification> notifications; // La lista de notificaciones activas std::vector<Notification> notifications; // La lista de notificaciones activas
JA_Sound_t *sound; // Sonido a reproducir cuando suena la notificación
bool stack; // Indica si las notificaciones se apilan bool stack; // Indica si las notificaciones se apilan
bool hasIcons; // Indica si el notificador tiene textura para iconos bool hasIcons; // Indica si el notificador tiene textura para iconos
JA_Sound_t *sound; // Sonido a reproducir cuando suena la notificación
// Elimina las notificaciones finalizadas // Elimina las notificaciones finalizadas
void clearFinishedNotifications(); void clearFinishedNotifications();
@@ -77,7 +77,7 @@ private:
public: public:
// Constructor // Constructor
Notify(SDL_Renderer *renderer, std::string iconFile, std::string bitmapFile, std::string textFile, std::string soundFile); Notify(SDL_Renderer *renderer, std::string iconFile, std::string bitmapFile, std::string textFile, const std::string &soundFile);
// Destructor // Destructor
~Notify(); ~Notify();
@@ -89,7 +89,7 @@ public:
void update(); void update();
// Muestra una notificación de texto por pantalla; // Muestra una notificación de texto por pantalla;
void showText(std::string text1 = "", std::string text2 = "", int icon = -1); void showText(std::string text1 = std::string(), std::string text2 = std::string(), int icon = -1);
// Indica si hay notificaciones activas // Indica si hay notificaciones activas
bool active(); bool active();

View File

@@ -1,16 +1,15 @@
#include "on_screen_help.h" #include "on_screen_help.h"
#include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND #include <SDL2/SDL_blendmode.h> // for SDL_BLENDMODE_BLEND
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <memory> // for make_unique, unique_ptr #include <memory> // for make_unique, make_shared, unique_ptr
#include <string> // for basic_string #include "asset.h" // for Asset
#include "asset.h" // for Asset #include "lang.h" // for getText
#include "lang.h" // for getText #include "param.h" // for param
#include "param.h" // for param #include "screen.h" // for Screen
#include "screen.h" // for Screen #include "sprite.h" // for Sprite
#include "sprite.h" // for Sprite #include "text.h" // for Text
#include "text.h" // for Text #include "texture.h" // for Texture
#include "texture.h" // for Texture #include "utils.h" // for easeInOutSine, Param, ParamGame
#include "utils.h" // for easeInOutSine, ParamGame, Param
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
OnScreenHelp *OnScreenHelp::onScreenHelp = nullptr; OnScreenHelp *OnScreenHelp::onScreenHelp = nullptr;

View File

@@ -1,11 +1,10 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Texture #include <SDL2/SDL_render.h> // for SDL_Texture
#include <vector> // for vector #include <vector> // for vector
#include <memory> class Sprite;
#include "sprite.h" // lines 10-10 class Text;
#include "text.h"
enum class OnScreenHelpStatus enum class OnScreenHelpStatus
{ {

View File

@@ -13,7 +13,7 @@
Options options; Options options;
// Declaraciones // Declaraciones
bool setOptions(std::string var, std::string value); bool setOptions(const std::string &var, const std::string &value);
// Inicializa las opciones del programa // Inicializa las opciones del programa
void initOptions() void initOptions()
@@ -39,7 +39,7 @@ void initOptions()
// Opciones de juego // Opciones de juego
options.game.difficulty = GameDifficulty::NORMAL; options.game.difficulty = GameDifficulty::NORMAL;
options.game.language = lang::ba_BA; options.game.language = lang::Code::ba_BA;
options.game.autofire = true; options.game.autofire = true;
// Opciones de control // Opciones de control
@@ -57,11 +57,11 @@ void initOptions()
// Inputs que se guardan en las opciones y, por tanto, a disco // Inputs que se guardan en las opciones y, por tanto, a disco
c.inputs.clear(); c.inputs.clear();
c.inputs.push_back(input_fire_left); c.inputs.push_back(InputType::FIRE_LEFT);
c.inputs.push_back(input_fire_center); c.inputs.push_back(InputType::FIRE_CENTER);
c.inputs.push_back(input_fire_right); c.inputs.push_back(InputType::FIRE_RIGHT);
c.inputs.push_back(input_start); c.inputs.push_back(InputType::START);
c.inputs.push_back(input_service); c.inputs.push_back(InputType::SERVICE);
// Botones asociados a los inputs anteriores // Botones asociados a los inputs anteriores
c.buttons.clear(); c.buttons.clear();
@@ -86,7 +86,9 @@ bool loadOptionsFile(std::string file_path)
bool success = true; bool success = true;
// Variables para manejar el fichero // Variables para manejar el fichero
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
std::ifstream file(file_path); std::ifstream file(file_path);
// Si el fichero se puede abrir // Si el fichero se puede abrir
@@ -139,9 +141,9 @@ bool loadOptionsFile(std::string file_path)
options.video.window.size = 3; options.video.window.size = 3;
} }
if (options.game.language < 0 || options.game.language > 2) if (options.game.language != lang::Code::en_UK && options.game.language != lang::Code::ba_BA && options.game.language != lang::Code::es_ES)
{ {
options.game.language = lang::en_UK; options.game.language = lang::Code::en_UK;
} }
return success; return success;
@@ -150,7 +152,9 @@ bool loadOptionsFile(std::string file_path)
// Guarda el fichero de configuración // Guarda el fichero de configuración
bool saveOptionsFile(std::string file_path) bool saveOptionsFile(std::string file_path)
{ {
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
#endif
std::ofstream file(file_path); std::ofstream file(file_path);
if (!file.good()) if (!file.good())
@@ -207,7 +211,7 @@ bool saveOptionsFile(std::string file_path)
file << "## game.difficulty [" << value_difficulty_easy << ": easy, " << value_difficulty_normal << ": normal, " << value_difficulty_hard << ": hard]\n"; file << "## game.difficulty [" << value_difficulty_easy << ": easy, " << value_difficulty_normal << ": normal, " << value_difficulty_hard << ": hard]\n";
file << "\n"; file << "\n";
file << "game.language=" + std::to_string(options.game.language) + "\n"; file << "game.language=" + std::to_string(static_cast<int>(options.game.language)) + "\n";
file << "game.difficulty=" + std::to_string(static_cast<int>(options.game.difficulty)) + "\n"; file << "game.difficulty=" + std::to_string(static_cast<int>(options.game.difficulty)) + "\n";
file << "game.autofire=" + boolToString(options.game.autofire) + "\n"; file << "game.autofire=" + boolToString(options.game.autofire) + "\n";
@@ -240,10 +244,10 @@ bool saveOptionsFile(std::string file_path)
} }
// Asigna variables a partir de dos cadenas // Asigna variables a partir de dos cadenas
bool setOptions(std::string var, std::string value) bool setOptions(const std::string &var, const std::string &value)
{ {
// Indicador de éxito en la asignación // Indicador de éxito en la asignación
bool success = true; auto success = true;
// Opciones de video // Opciones de video
if (var == "video.mode") if (var == "video.mode")
@@ -304,7 +308,7 @@ bool setOptions(std::string var, std::string value)
// Opciones de juego // Opciones de juego
else if (var == "game.language") else if (var == "game.language")
{ {
options.game.language = std::stoi(value); options.game.language = static_cast<lang::Code>(std::stoi(value));
} }
else if (var == "game.difficulty") else if (var == "game.difficulty")
@@ -389,7 +393,7 @@ bool setOptions(std::string var, std::string value)
} }
// Lineas vacias o que empiezan por comentario // Lineas vacias o que empiezan por comentario
else if (var == "" || var.substr(0, 1) == "#") else if (var.empty() || var.starts_with("#"))
{ {
} }

View File

@@ -1,12 +1,15 @@
#include "param.h" #include "param.h"
#include <fstream> // for char_traits, basic_ostream, basic_ifstream, basi... #include <fstream> // for char_traits, basic_ostream, basic_ifstream, basi...
#include <iostream> // for cout #include <iostream> // for cout
#include "utils.h" // for Param, ParamGame, Zone, ParamBalloon #include <sstream>
#include <string>
#include <stdexcept>
#include "utils.h" // for Param, ParamGame, Zone, ParamBalloon
Param param; Param param;
// Asigna variables a partir de dos cadenas // Asigna variables a partir de dos cadenas
bool setParams(std::string var, std::string value); bool setParams(const std::string &var, const std::string &value);
// Calcula variables a partir de otras variables // Calcula variables a partir de otras variables
void precalculateZones(); void precalculateZones();
@@ -40,7 +43,7 @@ void initParam()
param.title.title_c_c_position = 11; param.title.title_c_c_position = 11;
// BACKGROUND // BACKGROUND
param.background.attenuate_color = {255, 255, 255}; param.background.attenuate_color = (Color){255, 255, 255};
param.background.attenuate_alpha = 32; param.background.attenuate_alpha = 32;
// BALLOONS // BALLOONS
@@ -52,16 +55,24 @@ void initParam()
param.balloon_3.grav = 0.10f; param.balloon_3.grav = 0.10f;
param.balloon_4.vel = 4.95f; param.balloon_4.vel = 4.95f;
param.balloon_4.grav = 0.10f; param.balloon_4.grav = 0.10f;
// NOTIFICATION
param.notification.pos_v = NotifyPosition::TOP;
param.notification.pos_h = NotifyPosition::LEFT;
param.notification.sound = false;
param.notification.color.r = 48;
param.notification.color.g = 48;
param.notification.color.b = 48;
} }
// Establece valores para los parametros a partir de un fichero de texto // Establece valores para los parametros a partir de un fichero de texto
void loadParamsFromFile(std::string filePath) /*void loadParamsFromFile(std::string file_path)
{ {
// Pone valores por defecto a las variables // Pone valores por defecto a las variables
initParam(); initParam();
// Variables para manejar el fichero // Variables para manejar el fichero
std::ifstream file(filePath); std::ifstream file(file_path);
std::string line; std::string line;
std::string param1; std::string param1;
std::string param2; std::string param2;
@@ -70,18 +81,25 @@ void loadParamsFromFile(std::string filePath)
if (file.good()) if (file.good())
{ {
#ifdef VERBOSE #ifdef VERBOSE
const std::string filename = filePath.substr(filePath.find_last_of("\\/") + 1); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
std::cout << "Reading file: " << filename << std::endl; std::cout << "Reading file: " << file_name << std::endl;
#endif #endif
// Procesa cada linea del fichero // Procesa cada linea del fichero
while (std::getline(file, line)) while (std::getline(file, line))
{ {
// Reinicia variables // Reinicia variables
param1 = ""; param1.clear();
param2 = ""; param2.clear();
// Elimina los comentarios // Elimina los comentarios al final de una linea
line = line.substr(0, line.find("#")); {
// line = line.substr(0, line.find("#"));
auto pos = line.find("#");
if (pos != std::string::npos)
{
line.resize(pos);
}
}
// Ignora los espacios en blanco // Ignora los espacios en blanco
int pos = 0; int pos = 0;
@@ -145,17 +163,61 @@ void loadParamsFromFile(std::string filePath)
} }
#ifdef VERBOSE #ifdef VERBOSE
else else
std::cout << "Failed to load file: " << filePath << std::endl; std::cout << "Failed to load file: " << file_path << std::endl;
#endif #endif
precalculateZones();
}*/
void loadParamsFromFile(const std::string &file_path)
{
// Inicializa los parámetros con valores por defecto
initParam();
// Abre el archivo
std::ifstream file(file_path);
if (!file.is_open())
{
#ifdef VERBOSE
std::cerr << "Error: No se pudo abrir el archivo " << file_path << std::endl;
#endif
throw std::runtime_error("No se pudo abrir el archivo: " + file_path);
}
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1);
std::cout << "Reading file: " << file_name << std::endl;
#endif
std::string line, param1, param2;
while (std::getline(file, line))
{
// Elimina comentarios
auto comment_pos = line.find('#');
if (comment_pos != std::string::npos)
{
line.resize(comment_pos);
}
// Usa un stream para separar palabras
std::istringstream iss(line);
if (iss >> param1 >> param2)
{
setParams(param1, param2);
}
}
// Cierra el archivo
file.close();
// Realiza cálculos adicionales después de cargar los parámetros
precalculateZones(); precalculateZones();
} }
// Asigna variables a partir de dos cadenas // Asigna variables a partir de dos cadenas
bool setParams(std::string var, std::string value) bool setParams(const std::string &var, const std::string &value)
{ {
// Indicador de éxito en la asignación // Indicador de éxito en la asignación
bool success = true; auto success = true;
// GAME // GAME
if (var == "game.width") if (var == "game.width")

View File

@@ -6,4 +6,4 @@ struct Param;
extern Param param; extern Param param;
// Establece valores para los parametros a partir de un fichero de texto // Establece valores para los parametros a partir de un fichero de texto
void loadParamsFromFile(std::string file_path); void loadParamsFromFile(const std::string &file_path);

View File

@@ -11,32 +11,31 @@
#include "options.h" #include "options.h"
// Constructor // Constructor
Player::Player(int id, float x, int y, bool demo, SDL_Rect *playArea, std::vector<std::shared_ptr<Texture>> texture, std::vector<std::vector<std::string> *> animations) Player::Player(int id, float x, int y, bool demo, SDL_Rect *play_area, std::vector<std::shared_ptr<Texture>> texture, std::vector<std::vector<std::string> *> animations)
: player_sprite_(std::make_unique<AnimatedSprite>(texture[0], "", animations[0])),
power_sprite_(std::make_unique<AnimatedSprite>(texture[1], "", animations[1])),
enter_name_(std::make_unique<EnterName>()),
play_area_(play_area),
id_(id),
pos_x_(x),
pos_y_(y),
default_pos_x_(x),
default_pos_y_(y),
status_playing_(PlayerStatus::WAITING),
scoreboard_panel_(0),
name_(std::string()),
controller_index_(0),
demo_(demo)
{ {
// Reserva memoria para los objetos // Reserva memoria para los objetos
playerSprite = std::make_unique<AnimatedSprite>(texture[0], "", animations[0]); power_sprite_->getTexture()->setAlpha(224);
powerSprite = std::make_unique<AnimatedSprite>(texture[1], "", animations[1]);
powerSprite->getTexture()->setAlpha(224);
enterName = std::make_unique<EnterName>();
// Rectangulo con la zona de juego
this->playArea = playArea;
// Establece la posición inicial del jugador
defaultPosX = posX = x;
defaultPosY = posY = y;
// Establece los offsets para el sprite de PowerUp // Establece los offsets para el sprite de PowerUp
powerUpDespX = (powerSprite->getWidth() - playerSprite->getWidth()) / 2; power_up_desp_x_ = (power_sprite_->getWidth() - player_sprite_->getWidth()) / 2;
powerSprite->setPosY(y - (powerSprite->getHeight() - playerSprite->getHeight())); power_sprite_->setPosY(y - (power_sprite_->getHeight() - player_sprite_->getHeight()));
// Inicializa variables // Inicializa variables
this->id = id; setRecordName(enter_name_->getName());
this->demo = demo;
statusPlaying = PlayerStatus::WAITING;
scoreBoardPanel = 0;
name = "";
setRecordName(enterName->getName());
init(); init();
} }
@@ -44,50 +43,54 @@ Player::Player(int id, float x, int y, bool demo, SDL_Rect *playArea, std::vecto
void Player::init() void Player::init()
{ {
// Inicializa variables de estado // Inicializa variables de estado
posX = defaultPosX; pos_x_ = default_pos_x_;
posY = defaultPosY; pos_y_ = default_pos_y_;
statusWalking = PlayerStatus::WALKING_STOP; status_walking_ = PlayerStatus::WALKING_STOP;
statusFiring = PlayerStatus::FIRING_NO; status_firing_ = PlayerStatus::FIRING_NO;
invulnerable = true; invulnerable_ = true;
invulnerableCounter = PLAYER_INVULNERABLE_COUNTER; invulnerable_counter_ = PLAYER_INVULNERABLE_COUNTER;
powerUp = false; power_up_ = false;
powerUpCounter = PLAYER_POWERUP_COUNTER; power_up_counter_ = PLAYER_POWERUP_COUNTER;
extraHit = false; extra_hit_ = false;
coffees = 0; coffees_ = 0;
input = true; input_ = true;
continueTicks = 0; continue_ticks_ = 0;
continueCounter = 20; continue_counter_ = 20;
width = 30; width_ = 30;
height = 30; height_ = 30;
collider.r = 9; collider_.r = 9;
shiftColliders(); shiftColliders();
velX = 0; vel_x_ = 0;
velY = 0; vel_y_ = 0;
baseSpeed = 1.5; base_speed_ = 1.5;
score = 0; score_ = 0;
scoreMultiplier = 1.0f; score_multiplier_ = 1.0f;
cooldown = 10; cooldown_ = 10;
// Establece la posición del sprite // Establece la posición del sprite
playerSprite->setPosX(posX); player_sprite_->setPosX(pos_x_);
playerSprite->setPosY(posY); player_sprite_->setPosY(pos_y_);
// Selecciona un frame para pintar // Selecciona un frame para pintar
playerSprite->setCurrentAnimation("stand"); player_sprite_->setCurrentAnimation("stand");
} }
// Actua en consecuencia de la entrada recibida // Actua en consecuencia de la entrada recibida
void Player::setInput(int input) void Player::setInput(InputType input)
{ {
switch (statusPlaying) switch (status_playing_)
{ {
case PlayerStatus::PLAYING: case PlayerStatus::PLAYING:
{
setInputPlaying(input); setInputPlaying(input);
break; break;
}
case PlayerStatus::ENTERING_NAME: case PlayerStatus::ENTERING_NAME:
{
setInputEnteringName(input); setInputEnteringName(input);
break; break;
}
default: default:
break; break;
@@ -95,68 +98,80 @@ void Player::setInput(int input)
} }
// Procesa inputs para cuando está jugando // Procesa inputs para cuando está jugando
void Player::setInputPlaying(int input) void Player::setInputPlaying(InputType input)
{ {
switch (input) switch (input)
{ {
case input_left: case InputType::LEFT:
velX = -baseSpeed; {
vel_x_ = -base_speed_;
setWalkingStatus(PlayerStatus::WALKING_LEFT); setWalkingStatus(PlayerStatus::WALKING_LEFT);
break; break;
}
case input_right: case InputType::RIGHT:
velX = baseSpeed; {
vel_x_ = base_speed_;
setWalkingStatus(PlayerStatus::WALKING_RIGHT); setWalkingStatus(PlayerStatus::WALKING_RIGHT);
break; break;
}
case input_fire_center: case InputType::FIRE_CENTER:
{
setFiringStatus(PlayerStatus::FIRING_UP); setFiringStatus(PlayerStatus::FIRING_UP);
break; break;
}
case input_fire_left: case InputType::FIRE_LEFT:
{
setFiringStatus(PlayerStatus::FIRING_LEFT); setFiringStatus(PlayerStatus::FIRING_LEFT);
break; break;
}
case input_fire_right: case InputType::FIRE_RIGHT:
{
setFiringStatus(PlayerStatus::FIRING_RIGHT); setFiringStatus(PlayerStatus::FIRING_RIGHT);
break; break;
}
default: default:
velX = 0; {
vel_x_ = 0;
setWalkingStatus(PlayerStatus::WALKING_STOP); setWalkingStatus(PlayerStatus::WALKING_STOP);
break; break;
} }
}
} }
// Procesa inputs para cuando está introduciendo el nombre // Procesa inputs para cuando está introduciendo el nombre
void Player::setInputEnteringName(int input) void Player::setInputEnteringName(InputType input)
{ {
switch (input) switch (input)
{ {
case input_left: case InputType::LEFT:
enterName->decPos(); enter_name_->decPos();
break; break;
case input_right: case InputType::RIGHT:
enterName->incPos(); enter_name_->incPos();
break; break;
case input_up: case InputType::UP:
enterName->incIndex(); enter_name_->incIndex();
break; break;
case input_down: case InputType::DOWN:
enterName->decIndex(); enter_name_->decIndex();
break; break;
case input_start: case InputType::START:
setRecordName(enterName->getName()); setRecordName(enter_name_->getName());
break; break;
default: default:
break; break;
} }
setRecordName(enterName->getName()); setRecordName(enter_name_->getName());
} }
// Mueve el jugador a la posición y animación que le corresponde // Mueve el jugador a la posición y animación que le corresponde
@@ -165,38 +180,38 @@ void Player::move()
if (isPlaying()) if (isPlaying())
{ {
// Mueve el jugador a derecha o izquierda // Mueve el jugador a derecha o izquierda
posX += velX; pos_x_ += vel_x_;
// Si el jugador abandona el area de juego por los laterales // Si el jugador abandona el area de juego por los laterales
if ((posX < param.game.play_area.rect.x - 5) || (posX + width > playArea->w + 5)) if ((pos_x_ < param.game.play_area.rect.x - 5) || (pos_x_ + width_ > play_area_->w + 5))
{ {
// Restaura su posición // Restaura su posición
posX -= velX; pos_x_ -= vel_x_;
} }
// Actualiza la posición del sprite // Actualiza la posición del sprite
playerSprite->setPosX(getPosX()); player_sprite_->setPosX(getPosX());
playerSprite->setPosY(posY); player_sprite_->setPosY(pos_y_);
powerSprite->setPosX(getPosX() - powerUpDespX); power_sprite_->setPosX(getPosX() - power_up_desp_x_);
} }
else if (isDying()) else if (isDying())
{ {
playerSprite->update(); player_sprite_->update();
// Si el cadaver abandona el area de juego por los laterales // Si el cadaver abandona el area de juego por los laterales
if ((playerSprite->getPosX() < param.game.play_area.rect.x) || (playerSprite->getPosX() + width > playArea->w)) if ((player_sprite_->getPosX() < param.game.play_area.rect.x) || (player_sprite_->getPosX() + width_ > play_area_->w))
{ {
// Restaura su posición // Restaura su posición
const float vx = playerSprite->getVelX(); const float vx = player_sprite_->getVelX();
playerSprite->setPosX(playerSprite->getPosX() - vx); player_sprite_->setPosX(player_sprite_->getPosX() - vx);
// Rebota // Rebota
playerSprite->setVelX(-vx); player_sprite_->setVelX(-vx);
} }
// Si el cadaver abandona el area de juego por abajo // Si el cadaver abandona el area de juego por abajo
if (playerSprite->getPosY() > param.game.play_area.rect.h) if (player_sprite_->getPosY() > param.game.play_area.rect.h)
{ {
setStatusPlaying(PlayerStatus::DIED); setStatusPlaying(PlayerStatus::DIED);
} }
@@ -206,122 +221,114 @@ void Player::move()
// Pinta el jugador en pantalla // Pinta el jugador en pantalla
void Player::render() void Player::render()
{ {
if (powerUp && isPlaying()) if (power_up_ && isPlaying())
{ {
if (powerUpCounter > (PLAYER_POWERUP_COUNTER / 4) || powerUpCounter % 20 > 4) if (power_up_counter_ > (PLAYER_POWERUP_COUNTER / 4) || power_up_counter_ % 20 > 4)
{ {
powerSprite->render(); power_sprite_->render();
} }
} }
if (isRenderable()) if (isRenderable())
playerSprite->render(); player_sprite_->render();
} }
// Establece el estado del jugador cuando camina // Establece el estado del jugador cuando camina
void Player::setWalkingStatus(PlayerStatus status) void Player::setWalkingStatus(PlayerStatus status)
{ {
// Si cambiamos de estado, reiniciamos la animación status_walking_ = status;
if (statusWalking != status)
{
statusWalking = status;
}
} }
// Establece el estado del jugador cuando dispara // Establece el estado del jugador cuando dispara
void Player::setFiringStatus(PlayerStatus status) void Player::setFiringStatus(PlayerStatus status)
{ {
// Si cambiamos de estado, reiniciamos la animación status_firing_ = status;
if (statusFiring != status)
{
statusFiring = status;
}
} }
// Establece la animación correspondiente al estado // Establece la animación correspondiente al estado
void Player::setAnimation() void Player::setAnimation()
{ {
// Crea cadenas de texto para componer el nombre de la animación // Crea cadenas de texto para componer el nombre de la animación
const std::string aWalking = statusWalking == PlayerStatus::WALKING_STOP ? "stand" : "walk"; const std::string a_walking = status_walking_ == PlayerStatus::WALKING_STOP ? "stand" : "walk";
const std::string aFiring = statusFiring == PlayerStatus::FIRING_UP ? "centershoot" : "sideshoot"; const std::string a_firing = status_firing_ == PlayerStatus::FIRING_UP ? "centershoot" : "sideshoot";
const SDL_RendererFlip flipWalk = statusWalking == PlayerStatus::WALKING_RIGHT ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE; const SDL_RendererFlip flip_walk = status_walking_ == PlayerStatus::WALKING_RIGHT ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
const SDL_RendererFlip flipFire = statusFiring == PlayerStatus::FIRING_RIGHT ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE; const SDL_RendererFlip flip_fire = status_firing_ == PlayerStatus::FIRING_RIGHT ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE;
// Establece la animación a partir de las cadenas // Establece la animación a partir de las cadenas
if (isPlaying()) if (isPlaying())
{ {
if (statusFiring == PlayerStatus::FIRING_NO) if (status_firing_ == PlayerStatus::FIRING_NO)
{ // No esta disparando { // No esta disparando
playerSprite->setCurrentAnimation(aWalking); player_sprite_->setCurrentAnimation(a_walking);
playerSprite->setFlip(flipWalk); player_sprite_->setFlip(flip_walk);
} }
else else
{ // Está disparando { // Está disparando
playerSprite->setCurrentAnimation(aWalking + "-" + aFiring); player_sprite_->setCurrentAnimation(a_walking + "-" + a_firing);
// Si dispara de lado, invierte el sprite segun hacia donde dispara // Si dispara de lado, invierte el sprite segun hacia donde dispara
// Si dispara recto, invierte el sprite segun hacia donde camina // Si dispara recto, invierte el sprite segun hacia donde camina
aFiring == "centershoot" ? playerSprite->setFlip(flipWalk) : playerSprite->setFlip(flipFire); a_firing == "centershoot" ? player_sprite_->setFlip(flip_walk) : player_sprite_->setFlip(flip_fire);
} }
} }
else else
{ {
playerSprite->setCurrentAnimation("death"); player_sprite_->setCurrentAnimation("death");
} }
// Actualiza las animaciones de los sprites // Actualiza las animaciones de los sprites
playerSprite->animate(); player_sprite_->animate();
// powerSprite->setFlip(flipWalk); // powerSprite->setFlip(flip_walk);
powerSprite->animate(); power_sprite_->animate();
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getPosX() const int Player::getPosX() const
{ {
return int(posX); return int(pos_x_);
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getPosY() const int Player::getPosY() const
{ {
return posY; return pos_y_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getWidth() const int Player::getWidth() const
{ {
return width; return width_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getHeight() const int Player::getHeight() const
{ {
return height; return height_;
} }
// Indica si el jugador puede disparar // Indica si el jugador puede disparar
bool Player::canFire() const bool Player::canFire() const
{ {
// Si el contador a llegado a cero, podemos disparar. En caso contrario decrementamos el contador // Si el contador a llegado a cero, podemos disparar. En caso contrario decrementamos el contador
return cooldown > 0 ? false : true; return cooldown_ > 0 ? false : true;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Player::setFireCooldown(int time) void Player::setFireCooldown(int time)
{ {
cooldown = time; cooldown_ = time;
} }
// Actualiza el valor de la variable // Actualiza el valor de la variable
void Player::updateCooldown() void Player::updateCooldown()
{ {
if (cooldown > 0) if (cooldown_ > 0)
{ {
cooldown--; cooldown_--;
if (powerUp) if (power_up_)
{ {
cooldown--; cooldown_--;
} }
} }
else else
@@ -346,13 +353,13 @@ void Player::update()
// Obtiene la puntuación del jugador // Obtiene la puntuación del jugador
int Player::getScore() const int Player::getScore() const
{ {
return score; return score_;
} }
// Asigna un valor a la puntuación del jugador // Asigna un valor a la puntuación del jugador
void Player::setScore(int score) void Player::setScore(int score)
{ {
this->score = score; score_ = score;
} }
// Incrementa la puntuación del jugador // Incrementa la puntuación del jugador
@@ -360,56 +367,56 @@ void Player::addScore(int score)
{ {
if (isPlaying()) if (isPlaying())
{ {
this->score += score; score_ += score;
} }
} }
// Indica si el jugador está jugando // Indica si el jugador está jugando
bool Player::isPlaying() const bool Player::isPlaying() const
{ {
return statusPlaying == PlayerStatus::PLAYING; return status_playing_ == PlayerStatus::PLAYING;
} }
// Indica si el jugador está continuando // Indica si el jugador está continuando
bool Player::isContinue() const bool Player::isContinue() const
{ {
return statusPlaying == PlayerStatus::CONTINUE; return status_playing_ == PlayerStatus::CONTINUE;
} }
// Indica si el jugador está esperando // Indica si el jugador está esperando
bool Player::isWaiting() const bool Player::isWaiting() const
{ {
return statusPlaying == PlayerStatus::WAITING; return status_playing_ == PlayerStatus::WAITING;
} }
// Indica si el jugador está introduciendo su nombre // Indica si el jugador está introduciendo su nombre
bool Player::isEnteringName() const bool Player::isEnteringName() const
{ {
return statusPlaying == PlayerStatus::ENTERING_NAME; return status_playing_ == PlayerStatus::ENTERING_NAME;
} }
// Indica si el jugador está muriendose // Indica si el jugador está muriendose
bool Player::isDying() const bool Player::isDying() const
{ {
return statusPlaying == PlayerStatus::DYING; return status_playing_ == PlayerStatus::DYING;
} }
// Indica si el jugador ha terminado de morir // Indica si el jugador ha terminado de morir
bool Player::hasDied() const bool Player::hasDied() const
{ {
return statusPlaying == PlayerStatus::DIED; return status_playing_ == PlayerStatus::DIED;
} }
// Indica si el jugador ya ha terminado de jugar // Indica si el jugador ya ha terminado de jugar
bool Player::isGameOver() const bool Player::isGameOver() const
{ {
return statusPlaying == PlayerStatus::GAME_OVER; return status_playing_ == PlayerStatus::GAME_OVER;
} }
// Actualiza el panel del marcador // Actualiza el panel del marcador
void Player::updateScoreboard() void Player::updateScoreboard()
{ {
switch (statusPlaying) switch (status_playing_)
{ {
case PlayerStatus::CONTINUE: case PlayerStatus::CONTINUE:
@@ -433,7 +440,7 @@ void Player::updateScoreboard()
// Cambia el modo del marcador // Cambia el modo del marcador
void Player::setScoreboardMode(ScoreboardMode mode) void Player::setScoreboardMode(ScoreboardMode mode)
{ {
if (!demo) if (!demo_)
{ {
Scoreboard::get()->setMode(getScoreBoardPanel(), mode); Scoreboard::get()->setMode(getScoreBoardPanel(), mode);
} }
@@ -442,13 +449,13 @@ void Player::setScoreboardMode(ScoreboardMode mode)
// Establece el estado del jugador en el juego // Establece el estado del jugador en el juego
void Player::setStatusPlaying(PlayerStatus value) void Player::setStatusPlaying(PlayerStatus value)
{ {
statusPlaying = value; status_playing_ = value;
switch (statusPlaying) switch (status_playing_)
{ {
case PlayerStatus::PLAYING: case PlayerStatus::PLAYING:
{ {
statusPlaying = PlayerStatus::PLAYING; status_playing_ = PlayerStatus::PLAYING;
init(); init();
setScoreboardMode(ScoreboardMode::SCORE); setScoreboardMode(ScoreboardMode::SCORE);
break; break;
@@ -457,9 +464,9 @@ void Player::setStatusPlaying(PlayerStatus value)
case PlayerStatus::CONTINUE: case PlayerStatus::CONTINUE:
{ {
// Inicializa el contador de continuar // Inicializa el contador de continuar
continueTicks = SDL_GetTicks(); continue_ticks_ = SDL_GetTicks();
continueCounter = 9; continue_counter_ = 9;
enterName->init(); enter_name_->init();
setScoreboardMode(ScoreboardMode::CONTINUE); setScoreboardMode(ScoreboardMode::CONTINUE);
break; break;
} }
@@ -479,16 +486,16 @@ void Player::setStatusPlaying(PlayerStatus value)
case PlayerStatus::DYING: case PlayerStatus::DYING:
{ {
// Activa la animación de morir // Activa la animación de morir
playerSprite->setAccelY(0.2f); player_sprite_->setAccelY(0.2f);
playerSprite->setVelY(-6.6f); player_sprite_->setVelY(-6.6f);
rand() % 2 == 0 ? playerSprite->setVelX(3.3f) : playerSprite->setVelX(-3.3f); rand() % 2 == 0 ? player_sprite_->setVelX(3.3f) : player_sprite_->setVelX(-3.3f);
break; break;
} }
case PlayerStatus::DIED: case PlayerStatus::DIED:
{ {
const auto nextPlayerStatus = IsEligibleForHighScore() ? PlayerStatus::ENTERING_NAME : PlayerStatus::CONTINUE; const auto nextPlayerStatus = IsEligibleForHighScore() ? PlayerStatus::ENTERING_NAME : PlayerStatus::CONTINUE;
demo ? setStatusPlaying(PlayerStatus::WAITING) : setStatusPlaying(nextPlayerStatus); demo_ ? setStatusPlaying(PlayerStatus::WAITING) : setStatusPlaying(nextPlayerStatus);
break; break;
} }
@@ -506,74 +513,74 @@ void Player::setStatusPlaying(PlayerStatus value)
// Obtiene el estado del jugador en el juego // Obtiene el estado del jugador en el juego
PlayerStatus Player::getStatusPlaying() const PlayerStatus Player::getStatusPlaying() const
{ {
return statusPlaying; return status_playing_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
float Player::getScoreMultiplier() const float Player::getScoreMultiplier() const
{ {
return scoreMultiplier; return score_multiplier_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Player::setScoreMultiplier(float value) void Player::setScoreMultiplier(float value)
{ {
scoreMultiplier = value; score_multiplier_ = value;
} }
// Aumenta el valor de la variable hasta un máximo // Aumenta el valor de la variable hasta un máximo
void Player::incScoreMultiplier() void Player::incScoreMultiplier()
{ {
scoreMultiplier += 0.1f; score_multiplier_ += 0.1f;
scoreMultiplier = std::min(scoreMultiplier, 5.0f); score_multiplier_ = std::min(score_multiplier_, 5.0f);
} }
// Decrementa el valor de la variable hasta un mínimo // Decrementa el valor de la variable hasta un mínimo
void Player::decScoreMultiplier() void Player::decScoreMultiplier()
{ {
scoreMultiplier -= 0.1f; score_multiplier_ -= 0.1f;
scoreMultiplier = std::max(scoreMultiplier, 1.0f); score_multiplier_ = std::max(score_multiplier_, 1.0f);
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool Player::isInvulnerable() const bool Player::isInvulnerable() const
{ {
return invulnerable; return invulnerable_;
} }
// Establece el valor del estado // Establece el valor del estado
void Player::setInvulnerable(bool value) void Player::setInvulnerable(bool value)
{ {
invulnerable = value; invulnerable_ = value;
invulnerableCounter = invulnerable ? PLAYER_INVULNERABLE_COUNTER : 0; invulnerable_counter_ = invulnerable_ ? PLAYER_INVULNERABLE_COUNTER : 0;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getInvulnerableCounter() const int Player::getInvulnerableCounter() const
{ {
return invulnerableCounter; return invulnerable_counter_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Player::setInvulnerableCounter(int value) void Player::setInvulnerableCounter(int value)
{ {
invulnerableCounter = value; invulnerable_counter_ = value;
} }
// Monitoriza el estado // Monitoriza el estado
void Player::updateInvulnerable() void Player::updateInvulnerable()
{ {
if (invulnerable) if (invulnerable_)
{ {
if (invulnerableCounter > 0) if (invulnerable_counter_ > 0)
{ {
invulnerableCounter--; invulnerable_counter_--;
invulnerableCounter % 8 > 3 ? playerSprite->getTexture()->setPalette(coffees) : playerSprite->getTexture()->setPalette(3); invulnerable_counter_ % 8 > 3 ? player_sprite_->getTexture()->setPalette(coffees_) : player_sprite_->getTexture()->setPalette(3);
} }
else else
{ {
setInvulnerable(false); setInvulnerable(false);
playerSprite->getTexture()->setPalette(coffees); player_sprite_->getTexture()->setPalette(coffees_);
} }
} }
} }
@@ -581,124 +588,123 @@ void Player::updateInvulnerable()
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool Player::isPowerUp() const bool Player::isPowerUp() const
{ {
return powerUp; return power_up_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Player::setPowerUp() void Player::setPowerUp()
{ {
powerUp = true; power_up_ = true;
powerUpCounter = PLAYER_POWERUP_COUNTER; power_up_counter_ = PLAYER_POWERUP_COUNTER;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getPowerUpCounter() const int Player::getPowerUpCounter() const
{ {
return powerUpCounter; return power_up_counter_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Player::setPowerUpCounter(int value) void Player::setPowerUpCounter(int value)
{ {
powerUpCounter = value; power_up_counter_ = value;
} }
// Actualiza el valor de la variable // Actualiza el valor de la variable
void Player::updatePowerUpCounter() void Player::updatePowerUpCounter()
{ {
if ((powerUpCounter > 0) && (powerUp)) if ((power_up_counter_ > 0) && (power_up_))
{ {
powerUpCounter--; power_up_counter_--;
} }
else else
{ {
powerUp = false; power_up_ = false;
// powerUpCounter = PLAYER_POWERUP_COUNTER;
} }
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool Player::hasExtraHit() const bool Player::hasExtraHit() const
{ {
return extraHit; return extra_hit_;
} }
// Concede un toque extra al jugador // Concede un toque extra al jugador
void Player::giveExtraHit() void Player::giveExtraHit()
{ {
extraHit = true; extra_hit_ = true;
if (coffees < 2) if (coffees_ < 2)
{ {
coffees++; coffees_++;
playerSprite->getTexture()->setPalette(coffees); player_sprite_->getTexture()->setPalette(coffees_);
} }
} }
// Quita el toque extra al jugador // Quita el toque extra al jugador
void Player::removeExtraHit() void Player::removeExtraHit()
{ {
if (coffees > 0) if (coffees_ > 0)
{ {
coffees--; coffees_--;
setInvulnerable(true); setInvulnerable(true);
playerSprite->getTexture()->setPalette(coffees); player_sprite_->getTexture()->setPalette(coffees_);
} }
extraHit = coffees == 0 ? false : true; extra_hit_ = coffees_ == 0 ? false : true;
} }
// Habilita la entrada de ordenes // Habilita la entrada de ordenes
void Player::enableInput() void Player::enableInput()
{ {
input = true; input_ = true;
} }
// Deshabilita la entrada de ordenes // Deshabilita la entrada de ordenes
void Player::disableInput() void Player::disableInput()
{ {
input = false; input_ = false;
} }
// Devuelve el número de cafes actuales // Devuelve el número de cafes actuales
int Player::getCoffees() const int Player::getCoffees() const
{ {
return coffees; return coffees_;
} }
// Obtiene el circulo de colisión // Obtiene el circulo de colisión
Circle &Player::getCollider() Circle &Player::getCollider()
{ {
return collider; return collider_;
} }
// Actualiza el circulo de colisión a la posición del jugador // Actualiza el circulo de colisión a la posición del jugador
void Player::shiftColliders() void Player::shiftColliders()
{ {
collider.x = int(posX + (width / 2)); collider_.x = int(pos_x_ + (width_ / 2));
collider.y = int(posY + (height / 2)); collider_.y = int(pos_y_ + (height_ / 2));
} }
// Pone las texturas del jugador // Pone las texturas del jugador
void Player::setPlayerTextures(std::vector<std::shared_ptr<Texture>> texture) void Player::setPlayerTextures(const std::vector<std::shared_ptr<Texture>> &texture)
{ {
playerSprite->setTexture(texture[0]); player_sprite_->setTexture(texture[0]);
powerSprite->setTexture(texture[1]); power_sprite_->setTexture(texture[1]);
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getContinueCounter() const int Player::getContinueCounter() const
{ {
return continueCounter; return continue_counter_;
} }
// Actualiza el contador de continue // Actualiza el contador de continue
void Player::updateContinueCounter() void Player::updateContinueCounter()
{ {
if (statusPlaying == PlayerStatus::CONTINUE) if (status_playing_ == PlayerStatus::CONTINUE)
{ {
const Uint32 ticksSpeed = 1000; constexpr Uint32 ticks_speed = 1000;
if (SDL_GetTicks() - continueTicks > ticksSpeed) if (SDL_GetTicks() - continue_ticks_ > ticks_speed)
{ {
decContinueCounter(); decContinueCounter();
} }
@@ -708,56 +714,56 @@ void Player::updateContinueCounter()
// Le asigna un panel en el marcador al jugador // Le asigna un panel en el marcador al jugador
void Player::setScoreBoardPanel(int panel) void Player::setScoreBoardPanel(int panel)
{ {
scoreBoardPanel = panel; scoreboard_panel_ = panel;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int Player::getScoreBoardPanel() const int Player::getScoreBoardPanel() const
{ {
return scoreBoardPanel; return scoreboard_panel_;
} }
// Decrementa el contador de continuar // Decrementa el contador de continuar
void Player::decContinueCounter() void Player::decContinueCounter()
{ {
continueTicks = SDL_GetTicks(); continue_ticks_ = SDL_GetTicks();
continueCounter--; --continue_counter_;
if (continueCounter < 0) if (continue_counter_ < 0)
{ {
setStatusPlaying(PlayerStatus::GAME_OVER); setStatusPlaying(PlayerStatus::GAME_OVER);
} }
} }
// Establece el nombre del jugador // Establece el nombre del jugador
void Player::setName(std::string name) void Player::setName(const std::string &name)
{ {
this->name = name; name_ = name;
} }
// Establece el nombre del jugador para la tabla de mejores puntuaciones // Establece el nombre del jugador para la tabla de mejores puntuaciones
void Player::setRecordName(std::string recordName) void Player::setRecordName(const std::string &record_name)
{ {
this->recordName = recordName.substr(0, 8); record_name_ = record_name.substr(0, 8);
} }
// Obtiene el nombre del jugador // Obtiene el nombre del jugador
std::string Player::getName() const std::string Player::getName() const
{ {
return name; return name_;
} }
// Obtiene el nombre del jugador para la tabla de mejores puntuaciones // Obtiene el nombre del jugador para la tabla de mejores puntuaciones
std::string Player::getRecordName() const std::string Player::getRecordName() const
{ {
return recordName; return record_name_;
} }
// Obtiene la posici´´on que se está editando del nombre del jugador para la tabla de mejores puntuaciones // Obtiene la posici´´on que se está editando del nombre del jugador para la tabla de mejores puntuaciones
int Player::getRecordNamePos() const int Player::getRecordNamePos() const
{ {
if (enterName) if (enter_name_)
{ {
return enterName->getPos(); return enter_name_->getPos();
} }
return 0; return 0;
@@ -766,19 +772,19 @@ int Player::getRecordNamePos() const
// Establece el mando que usará para ser controlado // Establece el mando que usará para ser controlado
void Player::setController(int index) void Player::setController(int index)
{ {
controllerIndex = index; controller_index_ = index;
} }
// Obtiene el mando que usa para ser controlado // Obtiene el mando que usa para ser controlado
int Player::getController() const int Player::getController() const
{ {
return controllerIndex; return controller_index_;
} }
// Obtiene el "id" del jugador // Obtiene el "id" del jugador
int Player::getId() const int Player::getId() const
{ {
return id; return id_;
} }
// Indica si el jugador se puede dibujar // Indica si el jugador se puede dibujar
@@ -790,5 +796,5 @@ bool Player::isRenderable() const
// Comprueba si la puntuación entra en la tabla de mejores puntuaciones // Comprueba si la puntuación entra en la tabla de mejores puntuaciones
bool Player::IsEligibleForHighScore() bool Player::IsEligibleForHighScore()
{ {
return score > options.game.hi_score_table.back().score; return score_ > options.game.hi_score_table.back().score;
} }

View File

@@ -1,15 +1,16 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for unique_ptr #include <memory> // for unique_ptr, shared_ptr
#include <string> // for string, basic_string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "animated_sprite.h" // for AnimatedSprite #include "animated_sprite.h" // for AnimatedSprite
#include "enter_name.h" // for EnterName #include "enter_name.h" // for EnterName
#include "utils.h" // for Circle #include "utils.h" // for Circle
#include "texture.h" // lines 12-12 class Texture;
enum class ScoreboardMode; enum class InputType : int;
enum class ScoreboardMode; // lines 12-12
// Estados del jugador // Estados del jugador
enum class PlayerStatus enum class PlayerStatus
@@ -41,44 +42,44 @@ class Player
{ {
private: private:
// Objetos y punteros // Objetos y punteros
std::unique_ptr<AnimatedSprite> playerSprite; // Sprite para dibujar el jugador std::unique_ptr<AnimatedSprite> player_sprite_; // Sprite para dibujar el jugador
std::unique_ptr<AnimatedSprite> powerSprite; // Sprite para dibujar el aura del jugador con el poder a tope std::unique_ptr<AnimatedSprite> power_sprite_; // Sprite para dibujar el aura del jugador con el poder a tope
std::unique_ptr<EnterName> enterName; // Clase utilizada para introducir el nombre std::unique_ptr<EnterName> enter_name_; // Clase utilizada para introducir el nombre
SDL_Rect *playArea; // Rectangulo con la zona de juego SDL_Rect *play_area_; // Rectangulo con la zona de juego
// Variables // Variables
int id; // Numero de identificación para el jugador int id_; // Numero de identificación para el jugador
float posX; // Posicion en el eje X float pos_x_; // Posicion en el eje X
int posY; // Posicion en el eje Y int pos_y_; // Posicion en el eje Y
float defaultPosX; // Posición inicial para el jugador float default_pos_x_; // Posición inicial para el jugador
int defaultPosY; // Posición inicial para el jugador int default_pos_y_; // Posición inicial para el jugador
int width; // Anchura int width_; // Anchura
int height; // Altura int height_; // Altura
float velX; // Cantidad de pixeles a desplazarse en el eje X float vel_x_; // Cantidad de pixeles a desplazarse en el eje X
int velY; // Cantidad de pixeles a desplazarse en el eje Y int vel_y_; // Cantidad de pixeles a desplazarse en el eje Y
float baseSpeed; // Velocidad base del jugador float base_speed_; // Velocidad base del jugador
int cooldown; // Contador durante el cual no puede disparar int cooldown_; // Contador durante el cual no puede disparar
int score; // Puntos del jugador int score_; // Puntos del jugador
float scoreMultiplier; // Multiplicador de puntos float score_multiplier_; // Multiplicador de puntos
PlayerStatus statusWalking; // Estado del jugador al moverse PlayerStatus status_walking_; // Estado del jugador al moverse
PlayerStatus statusFiring; // Estado del jugador al disparar PlayerStatus status_firing_; // Estado del jugador al disparar
PlayerStatus statusPlaying; // Estado del jugador en el juego PlayerStatus status_playing_; // Estado del jugador en el juego
bool invulnerable; // Indica si el jugador es invulnerable bool invulnerable_; // Indica si el jugador es invulnerable
int invulnerableCounter; // Contador para la invulnerabilidad int invulnerable_counter_; // Contador para la invulnerabilidad
bool extraHit; // Indica si el jugador tiene un toque extra bool extra_hit_; // Indica si el jugador tiene un toque extra
int coffees; // Indica cuantos cafes lleva acumulados int coffees_; // Indica cuantos cafes lleva acumulados
bool powerUp; // Indica si el jugador tiene activo el modo PowerUp bool power_up_; // Indica si el jugador tiene activo el modo PowerUp
int powerUpCounter; // Temporizador para el modo PowerUp int power_up_counter_; // Temporizador para el modo PowerUp
int powerUpDespX; // Desplazamiento del sprite de PowerUp respecto al sprite del jugador int power_up_desp_x_; // Desplazamiento del sprite de PowerUp respecto al sprite del jugador
bool input; // Indica si puede recibir ordenes de entrada bool input_; // Indica si puede recibir ordenes de entrada
Circle collider; // Circulo de colisión del jugador Circle collider_; // Circulo de colisión del jugador
int continueCounter; // Contador para poder continuar int continue_counter_; // Contador para poder continuar
Uint32 continueTicks; // Variable para poder cambiar el contador de continue en función del tiempo Uint32 continue_ticks_; // Variable para poder cambiar el contador de continue en función del tiempo
int scoreBoardPanel; // Panel del marcador asociado al jugador int scoreboard_panel_; // Panel del marcador asociado al jugador
std::string name; // Nombre del jugador std::string name_; // Nombre del jugador
std::string recordName; // Nombre del jugador para l atabla de mejores puntuaciones std::string record_name_; // Nombre del jugador para l atabla de mejores puntuaciones
int controllerIndex; // Indice del array de mandos que utilizará para moverse int controller_index_; // Indice del array de mandos que utilizará para moverse
bool demo; // Para que el jugador sepa si está en el modo demostración bool demo_; // Para que el jugador sepa si está en el modo demostración
// Actualiza el circulo de colisión a la posición del jugador // Actualiza el circulo de colisión a la posición del jugador
void shiftColliders(); void shiftColliders();
@@ -103,7 +104,7 @@ private:
public: public:
// Constructor // Constructor
Player(int id, float x, int y, bool demo, SDL_Rect *playArea, std::vector<std::shared_ptr<Texture>> texture, std::vector<std::vector<std::string> *> animations); Player(int id, float x, int y, bool demo, SDL_Rect *play_area, std::vector<std::shared_ptr<Texture>> texture, std::vector<std::vector<std::string> *> animations);
// Destructor // Destructor
~Player() = default; ~Player() = default;
@@ -118,16 +119,16 @@ public:
void render(); void render();
// Pone las texturas del jugador // Pone las texturas del jugador
void setPlayerTextures(std::vector<std::shared_ptr<Texture>> texture); void setPlayerTextures(const std::vector<std::shared_ptr<Texture>> &texture);
// Actua en consecuencia de la entrada recibida // Actua en consecuencia de la entrada recibida
void setInput(int input); void setInput(InputType input);
// Procesa inputs para cuando está jugando // Procesa inputs para cuando está jugando
void setInputPlaying(int input); void setInputPlaying(InputType input);
// Procesa inputs para cuando está introduciendo el nombre // Procesa inputs para cuando está introduciendo el nombre
void setInputEnteringName(int input); void setInputEnteringName(InputType input);
// Mueve el jugador a la posición y animación que le corresponde // Mueve el jugador a la posición y animación que le corresponde
void move(); void move();
@@ -271,10 +272,10 @@ public:
void decContinueCounter(); void decContinueCounter();
// Establece el nombre del jugador // Establece el nombre del jugador
void setName(std::string name); void setName(const std::string &name);
// Establece el nombre del jugador para la tabla de mejores puntuaciones // Establece el nombre del jugador para la tabla de mejores puntuaciones
void setRecordName(std::string recordName); void setRecordName(const std::string &record_name);
// Obtiene el nombre del jugador // Obtiene el nombre del jugador
std::string getName() const; std::string getName() const;

View File

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

View File

@@ -1,15 +1,15 @@
#pragma once #pragma once
#include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect #include <SDL2/SDL_rect.h> // for SDL_Point, SDL_Rect
#include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture #include <SDL2/SDL_render.h> // for SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <SDL2/SDL_stdinc.h> // for Uint32
#include <memory> // for unique_ptr #include <memory> // for unique_ptr, shared_ptr
#include <string> // for string, basic_string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "utils.h" // for Color #include "utils.h" // for Color
#include "sprite.h" // lines 11-11 class Sprite;
#include "text.h" // lines 12-12 class Text;
#include "texture.h" // lines 13-13 class Texture;
// Defines // Defines
constexpr int SCOREBOARD_LEFT_PANEL = 0; constexpr int SCOREBOARD_LEFT_PANEL = 0;
@@ -19,7 +19,7 @@ constexpr int SCOREBOARD_MAX_PANELS = 3;
constexpr int SCOREBOARD_TICK_SPEED = 100; constexpr int SCOREBOARD_TICK_SPEED = 100;
// Enums // Enums
enum class ScoreboardMode enum class ScoreboardMode : int
{ {
SCORE, SCORE,
STAGE_INFO, STAGE_INFO,
@@ -32,7 +32,7 @@ enum class ScoreboardMode
}; };
// Structs // Structs
struct panel_t struct Panel
{ {
ScoreboardMode mode; // Modo en el que se encuentra el panel ScoreboardMode mode; // Modo en el que se encuentra el panel
SDL_Rect pos; // Posición donde dibujar el panel dentro del marcador SDL_Rect pos; // Posición donde dibujar el panel dentro del marcador
@@ -43,38 +43,38 @@ class Scoreboard
{ {
private: private:
// [SINGLETON] Objeto scoreboard privado para Don Melitón // [SINGLETON] Objeto scoreboard privado para Don Melitón
static Scoreboard *scoreboard; static Scoreboard *scoreboard_;
// Objetos y punteros // Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
std::shared_ptr<Texture> gamePowerMeterTexture; // Textura con el marcador de poder de la fase std::shared_ptr<Texture> game_power_meter_texture_; // Textura con el marcador de poder de la fase
std::unique_ptr<Sprite> powerMeterSprite; // Sprite para el medidor de poder de la fase std::unique_ptr<Sprite> power_meter_sprite_; // Sprite para el medidor de poder de la fase
std::unique_ptr<Text> textScoreBoard; // Fuente para el marcador del juego std::unique_ptr<Text> text_scoreboard_; // Fuente para el marcador del juego
SDL_Texture *background; // Textura para dibujar el marcador SDL_Texture *background_; // Textura para dibujar el marcador
std::vector<SDL_Texture *> panelTexture; // Texturas para dibujar cada panel; std::vector<SDL_Texture *> panel_texture_; // Texturas para dibujar cada panel
// Variables // Variables
int stage; // Número de fase actual std::string name_[SCOREBOARD_MAX_PANELS]; // Nom de cada jugador
std::string name[SCOREBOARD_MAX_PANELS]; // Nom de cada jugador std::string record_name_[SCOREBOARD_MAX_PANELS]; // Nombre introducido para la tabla de records
std::string recordName[SCOREBOARD_MAX_PANELS]; // Nombre introducido para la tabla de records int selector_pos_[SCOREBOARD_MAX_PANELS]; // Posición del selector de letra para introducir el nombre
int selectorPos[SCOREBOARD_MAX_PANELS]; // Posición del selector de letra para introducir el nombre int score_[SCOREBOARD_MAX_PANELS]; // Puntuación de los jugadores
int score[SCOREBOARD_MAX_PANELS]; // Puntuación de los jugadores float mult_[SCOREBOARD_MAX_PANELS]; // Multiplicador de los jugadores
float mult[SCOREBOARD_MAX_PANELS]; // Multiplicador de los jugadores int continue_counter_[SCOREBOARD_MAX_PANELS]; // Tiempo para continuar de los jugadores
int continueCounter[SCOREBOARD_MAX_PANELS]; // Tiempo para continuar de los jugadores Panel panel_[SCOREBOARD_MAX_PANELS]; // Lista con todos los paneles del marcador
int hiScore; // Máxima puntuación int stage_; // Número de fase actual
float power; // Poder actual de la fase int hi_score_; // Máxima puntuación
std::string hiScoreName; // Nombre del jugador con la máxima puntuación float power_; // Poder actual de la fase
Color color; // Color del marcador std::string hi_score_name_; // Nombre del jugador con la máxima puntuación
SDL_Rect rect; // Posición y dimensiones del marcador Color color_; // Color del marcador
panel_t panel[SCOREBOARD_MAX_PANELS]; // Lista con todos los paneles del marcador SDL_Rect rect_; // Posición y dimensiones del marcador
Uint32 ticks; // Variable donde almacenar el valor de SDL_GetTiks() Uint32 ticks_; // Variable donde almacenar el valor de SDL_GetTiks()
int counter; // Contador int counter_; // Contador
// Puntos predefinidos para colocar elementos en los paneles // Puntos predefinidos para colocar elementos en los paneles
SDL_Point slot4_1, slot4_2, slot4_3, slot4_4; SDL_Point slot4_1_, slot4_2_, slot4_3_, slot4_4_;
SDL_Point enterNamePos; SDL_Point enter_name_pos_;
// Recalcula las anclas de los elementos // Recalcula las anclas de los elementos
void recalculateAnchors(); void recalculateAnchors();
@@ -103,7 +103,7 @@ private:
// [SINGLETON] Ahora el constructor y el destructor son privados // [SINGLETON] Ahora el constructor y el destructor son privados
// Constructor // Constructor
Scoreboard(SDL_Renderer *renderer); explicit Scoreboard(SDL_Renderer *renderer);
// Destructor // Destructor
~Scoreboard(); ~Scoreboard();
@@ -125,10 +125,10 @@ public:
void render(); void render();
// Establece el valor de la variable // Establece el valor de la variable
void setName(int panel, std::string name); void setName(int panel, const std::string &name);
// Establece el valor de la variable // Establece el valor de la variable
void setRecordName(int panel, std::string recordName); void setRecordName(int panel, const std::string &record_name);
// Establece el valor de la variable // Establece el valor de la variable
void setSelectorPos(int panel, int pos); void setSelectorPos(int panel, int pos);
@@ -146,13 +146,13 @@ public:
void setStage(int stage); void setStage(int stage);
// Establece el valor de la variable // Establece el valor de la variable
void setHiScore(int hiScore); void setHiScore(int hi_score);
// Establece el valor de la variable // Establece el valor de la variable
void setPower(float power); void setPower(float power);
// Establece el valor de la variable // Establece el valor de la variable
void setHiScoreName(std::string name); void setHiScoreName(const std::string &name);
// Establece el valor de la variable // Establece el valor de la variable
void setColor(Color color); void setColor(Color color);

View File

@@ -22,105 +22,97 @@
#endif #endif
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado // [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Screen *Screen::screen = nullptr; Screen *Screen::screen_ = nullptr;
// [SINGLETON] Crearemos el objeto screen con esta función estática // [SINGLETON] Crearemos el objeto screen con esta función estática
void Screen::init(SDL_Window *window, SDL_Renderer *renderer) void Screen::init(SDL_Window *window, SDL_Renderer *renderer)
{ {
Screen::screen = new Screen(window, renderer); Screen::screen_ = new Screen(window, renderer);
} }
// [SINGLETON] Destruiremos el objeto screen con esta función estática // [SINGLETON] Destruiremos el objeto screen con esta función estática
void Screen::destroy() void Screen::destroy()
{ {
delete Screen::screen; delete Screen::screen_;
} }
// [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él // [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él
Screen *Screen::get() Screen *Screen::get()
{ {
return Screen::screen; return Screen::screen_;
} }
// Constructor // Constructor
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer) Screen::Screen(SDL_Window *window, SDL_Renderer *renderer)
: window(window), renderer(renderer) : window_(window),
{ renderer_(renderer),
// Copia punteros
input = Input::get();
asset = Asset::get();
// Inicializa variables notify_(std::make_unique<Notify>(renderer_, std::string(), Asset::get()->get("8bithud.png"), Asset::get()->get("8bithud.txt"), Asset::get()->get("notify.wav"))),
srcrect = {0, 0, param.game.width, param.game.height}; game_canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
dstrect = {0, 0, param.game.width, param.game.height}; shader_canvas_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
borderColor = {0, 0, 0};
flashEffect.enabled = false; src_rect_({0, 0, param.game.width, param.game.height}),
flashEffect.counter = 0; dst_rect_({0, 0, param.game.width, param.game.height}),
flashEffect.lenght = 0; border_color_({0x00, 0x00, 0x00}),
flashEffect.color = {0xFF, 0xFF, 0xFF}; attenuate_effect_(false),
shakeEffect.enabled = false; fps_ticks_(0),
shakeEffect.desp = 2; fps_counter_(0),
shakeEffect.delay = 3; fps_(0),
shakeEffect.counter = 0;
shakeEffect.lenght = 8;
shakeEffect.remaining = 0;
shakeEffect.originalPos = 0;
shakeEffect.originalWidth = param.game.width;
attenuateEffect = false;
fpsTicks = 0;
fpsCounter = 0;
fps = 0;
#ifdef DEBUG #ifdef DEBUG
showInfo = true; show_info_(true)
#else #else
showInfo = false; show_info_(false)
#endif #endif
{
// Inicializa variables
flash_effect_.enabled = false;
flash_effect_.counter = 0;
flash_effect_.lenght = 0;
flash_effect_.color = {0xFF, 0xFF, 0xFF};
shake_effect_.enabled = false;
shake_effect_.desp = 2;
shake_effect_.delay = 3;
shake_effect_.counter = 0;
shake_effect_.lenght = 8;
shake_effect_.remaining = 0;
shake_effect_.originalPos = 0;
shake_effect_.originalWidth = param.game.width;
SDL_DisplayMode DM; SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode(0, &DM); SDL_GetCurrentDisplayMode(0, &DM);
infoResolution = std::to_string(DM.w) + " X " + std::to_string(DM.h) + " AT " + std::to_string(DM.refresh_rate) + " HZ"; info_resolution_ = std::to_string(DM.w) + " X " + std::to_string(DM.h) + " AT " + std::to_string(DM.refresh_rate) + " HZ";
// Crea los objetos
notify = std::make_unique<Notify>(renderer, "", asset->get("8bithud.png"), asset->get("8bithud.txt"), asset->get("notify.wav"));
// Define el color del borde para el modo de pantalla completa
borderColor = {0x00, 0x00, 0x00};
// Crea las textura donde se dibujan los graficos del juego
gameCanvas = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);
shaderCanvas = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);
// Establece el modo de video // Establece el modo de video
setVideoMode(options.video.mode); setVideoMode(options.video.mode);
// Muestra la ventana // Muestra la ventana
SDL_ShowWindow(window); SDL_ShowWindow(window_);
} }
// Destructor // Destructor
Screen::~Screen() Screen::~Screen()
{ {
SDL_DestroyTexture(gameCanvas); SDL_DestroyTexture(game_canvas_);
SDL_DestroyTexture(shaderCanvas); SDL_DestroyTexture(shader_canvas_);
} }
// Limpia la pantalla // Limpia la pantalla
void Screen::clean(Color color) void Screen::clean(Color color)
{ {
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 0xFF); SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 0xFF);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
} }
// Prepara para empezar a dibujar en la textura de juego // Prepara para empezar a dibujar en la textura de juego
void Screen::start() void Screen::start()
{ {
SDL_SetRenderTarget(renderer, gameCanvas); SDL_SetRenderTarget(renderer_, game_canvas_);
} }
// Vuelca el contenido del renderizador en pantalla // Vuelca el contenido del renderizador en pantalla
void Screen::blit() void Screen::blit()
{ {
// Actualiza el contador de FPS // Actualiza el contador de FPS
fpsCounter++; fps_counter_++;
// Actualiza y dibuja el efecto de flash en la pantalla // Actualiza y dibuja el efecto de flash en la pantalla
doFlash(); doFlash();
@@ -135,51 +127,51 @@ void Screen::blit()
displayInfo(); displayInfo();
// Muestra las notificaciones // Muestra las notificaciones
notify->render(); notify_->render();
#ifdef NO_SHADERS #ifdef NO_SHADERS
// Vuelve a dejar el renderizador en modo normal // Vuelve a dejar el renderizador en modo normal
SDL_SetRenderTarget(renderer, nullptr); SDL_SetRenderTarget(renderer_, nullptr);
// Borra el contenido previo // Borra el contenido previo
SDL_SetRenderDrawColor(renderer, borderColor.r, borderColor.g, borderColor.b, 0xFF); SDL_SetRenderDrawColor(renderer_, border_color_.r, border_color_.g, border_color_.b, 0xFF);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
// Copia la textura de juego en el renderizador en la posición adecuada // Copia la textura de juego en el renderizador en la posición adecuada
if (shakeEffect.enabled) if (shake_effect_.enabled)
SDL_RenderCopy(renderer, gameCanvas, nullptr, nullptr); SDL_RenderCopy(renderer_, game_canvas_, nullptr, nullptr);
SDL_RenderCopy(renderer, gameCanvas, &srcrect, &dstrect); SDL_RenderCopy(renderer_, game_canvas_, &src_rect_, &dst_rect_);
// Muestra por pantalla el renderizador // Muestra por pantalla el renderizador
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer_);
#else #else
if (options.video.shaders) if (options.video.shaders)
{ {
SDL_SetRenderTarget(renderer, shaderCanvas); SDL_SetRenderTarget(renderer_, shader_canvas_);
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
if (shakeEffect.enabled) if (shake_effect_.enabled)
SDL_RenderCopy(renderer, gameCanvas, nullptr, nullptr); SDL_RenderCopy(renderer_, game_canvas_, nullptr, nullptr);
SDL_RenderCopy(renderer, gameCanvas, &srcrect, &dstrect); SDL_RenderCopy(renderer_, game_canvas_, &src_rect_, &dst_rect_);
SDL_SetRenderTarget(renderer, nullptr); SDL_SetRenderTarget(renderer_, nullptr);
shader::render(); shader::render();
} }
else else
{ {
// Vuelve a dejar el renderizador en modo normal // Vuelve a dejar el renderizador en modo normal
SDL_SetRenderTarget(renderer, nullptr); SDL_SetRenderTarget(renderer_, nullptr);
// Borra el render // Borra el render
SDL_SetRenderDrawColor(renderer, 0x00, 0x00, 0x00, 0xFF); SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
// Copia la textura de juego en el renderizador en la posición adecuada // Copia la textura de juego en el renderizador en la posición adecuada
if (shakeEffect.enabled) if (shake_effect_.enabled)
SDL_RenderCopy(renderer, gameCanvas, nullptr, nullptr); SDL_RenderCopy(renderer_, game_canvas_, nullptr, nullptr);
SDL_RenderCopy(renderer, gameCanvas, &srcrect, &dstrect); SDL_RenderCopy(renderer_, game_canvas_, &src_rect_, &dst_rect_);
// Muestra por pantalla el renderizador // Muestra por pantalla el renderizador
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer_);
} }
#endif #endif
} }
@@ -187,9 +179,10 @@ void Screen::blit()
// Establece el modo de video // Establece el modo de video
void Screen::setVideoMode(ScreenVideoMode videoMode) void Screen::setVideoMode(ScreenVideoMode videoMode)
{ {
options.video.mode = videoMode;
#ifdef ARCADE #ifdef ARCADE
options.video.mode = ScreenVideoMode::WINDOW; options.video.mode = ScreenVideoMode::WINDOW;
#else
options.video.mode = videoMode;
#endif #endif
switch (options.video.mode) switch (options.video.mode)
@@ -197,7 +190,7 @@ void Screen::setVideoMode(ScreenVideoMode videoMode)
case ScreenVideoMode::WINDOW: case ScreenVideoMode::WINDOW:
{ {
// Cambia a modo de ventana // Cambia a modo de ventana
SDL_SetWindowFullscreen(window, 0); SDL_SetWindowFullscreen(window_, 0);
#ifdef ARCADE #ifdef ARCADE
// Oculta el puntero // Oculta el puntero
@@ -207,8 +200,8 @@ void Screen::setVideoMode(ScreenVideoMode videoMode)
SDL_ShowCursor(SDL_ENABLE); SDL_ShowCursor(SDL_ENABLE);
#endif #endif
// Modifica el tamaño de la ventana // Modifica el tamaño de la ventana
SDL_SetWindowSize(window, param.game.width * options.video.window.size, param.game.height * options.video.window.size); SDL_SetWindowSize(window_, param.game.width * options.video.window.size, param.game.height * options.video.window.size);
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); SDL_SetWindowPosition(window_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
break; break;
} }
@@ -217,7 +210,7 @@ void Screen::setVideoMode(ScreenVideoMode videoMode)
case ScreenVideoMode::FULLSCREEN: case ScreenVideoMode::FULLSCREEN:
{ {
// Aplica el modo de video // Aplica el modo de video
SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); SDL_SetWindowFullscreen(window_, SDL_WINDOW_FULLSCREEN_DESKTOP);
// Oculta el puntero // Oculta el puntero
SDL_ShowCursor(SDL_DISABLE); SDL_ShowCursor(SDL_DISABLE);
@@ -233,10 +226,10 @@ void Screen::setVideoMode(ScreenVideoMode videoMode)
if (options.video.shaders) if (options.video.shaders)
{ {
#ifndef NO_SHADERS #ifndef NO_SHADERS
std::ifstream f(asset->get("crtpi.glsl").c_str()); std::ifstream f(Asset::get()->get("crtpi.glsl").c_str());
std::string source((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>()); std::string source((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
shader::init(window, shaderCanvas, source.c_str()); shader::init(window_, shader_canvas_, source.c_str());
#endif #endif
} }
} }
@@ -274,20 +267,20 @@ void Screen::incWindowSize()
// Cambia el color del borde // Cambia el color del borde
void Screen::setBorderColor(Color color) void Screen::setBorderColor(Color color)
{ {
borderColor = color; border_color_ = color;
} }
// Cambia el tipo de mezcla // Cambia el tipo de mezcla
void Screen::setBlendMode(SDL_BlendMode blendMode) void Screen::setBlendMode(SDL_BlendMode blendMode)
{ {
SDL_SetRenderDrawBlendMode(renderer, blendMode); SDL_SetRenderDrawBlendMode(renderer_, blendMode);
} }
// Actualiza la lógica de la clase // Actualiza la lógica de la clase
void Screen::update() void Screen::update()
{ {
updateShake(); updateShakeEffect();
notify->update(); notify_->update();
updateFPS(); updateFPS();
OnScreenHelp::get()->update(); OnScreenHelp::get()->update();
} }
@@ -297,7 +290,7 @@ void Screen::checkInput()
{ {
#ifndef ARCADE #ifndef ARCADE
// Comprueba el teclado para cambiar entre pantalla completa y ventana // Comprueba el teclado para cambiar entre pantalla completa y ventana
if (input->checkInput(input_window_fullscreen, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::WINDOW_FULLSCREEN, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
switchVideoMode(); switchVideoMode();
const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen"; const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen";
@@ -306,7 +299,7 @@ void Screen::checkInput()
} }
// Comprueba el teclado para decrementar el tamaño de la ventana // Comprueba el teclado para decrementar el tamaño de la ventana
if (input->checkInput(input_window_dec_size, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::WINDOW_DEC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
decWindowSize(); decWindowSize();
const std::string size = std::to_string(options.video.window.size); const std::string size = std::to_string(options.video.window.size);
@@ -315,7 +308,7 @@ void Screen::checkInput()
} }
// Comprueba el teclado para incrementar el tamaño de la ventana // Comprueba el teclado para incrementar el tamaño de la ventana
if (input->checkInput(input_window_inc_size, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::WINDOW_INC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
incWindowSize(); incWindowSize();
const std::string size = std::to_string(options.video.window.size); const std::string size = std::to_string(options.video.window.size);
@@ -325,7 +318,7 @@ void Screen::checkInput()
#endif #endif
// Comprueba el teclado para activar o desactivar los shaders // Comprueba el teclado para activar o desactivar los shaders
if (input->checkInput(input_video_shaders, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
switchShaders(); switchShaders();
return; return;
@@ -333,26 +326,26 @@ void Screen::checkInput()
#ifdef DEBUG #ifdef DEBUG
// Comprueba el teclado para mostrar la información de debug // Comprueba el teclado para mostrar la información de debug
if (input->checkInput(input_showinfo, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (Input::get()->checkInput(InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
showInfo = !showInfo; show_info_ = !show_info_;
return; return;
} }
#endif #endif
for (int i = 0; i < input->getNumControllers(); ++i) for (int i = 0; i < Input::get()->getNumControllers(); ++i)
{ {
// Comprueba los mandos para activar o desactivar los shaders // Comprueba los mandos para activar o desactivar los shaders
if (input->checkModInput(input_service, input_video_shaders, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkModInput(InputType::SERVICE, InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
switchShaders(); switchShaders();
return; return;
} }
// Comprueba los mandos para mostrar la información de debug // Comprueba los mandos para mostrar la información de debug
if (input->checkModInput(input_service, input_showinfo, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (Input::get()->checkModInput(InputType::SERVICE, InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
showInfo = !showInfo; show_info_ = !show_info_;
return; return;
} }
} }
@@ -362,43 +355,43 @@ void Screen::checkInput()
void Screen::shake() void Screen::shake()
{ {
// Si no hay un shake effect activo, se guarda una copia de los valores actuales antes de modificarlos // Si no hay un shake effect activo, se guarda una copia de los valores actuales antes de modificarlos
if (!shakeEffect.enabled) if (!shake_effect_.enabled)
{ {
shakeEffect.enabled = true; shake_effect_.enabled = true;
shakeEffect.originalPos = srcrect.x; shake_effect_.originalPos = src_rect_.x;
shakeEffect.originalWidth = srcrect.w; shake_effect_.originalWidth = src_rect_.w;
srcrect.w -= shakeEffect.desp; src_rect_.w -= shake_effect_.desp;
dstrect.w = srcrect.w; dst_rect_.w = src_rect_.w;
} }
// Si ya hay un shake effect en marcha no se pilla el origen, solo se renuevan los contadores // Si ya hay un shake effect en marcha no se pilla el origen, solo se renuevan los contadores
shakeEffect.remaining = shakeEffect.lenght; shake_effect_.remaining = shake_effect_.lenght;
shakeEffect.counter = shakeEffect.delay; shake_effect_.counter = shake_effect_.delay;
} }
// Actualiza la logica para agitar la pantalla // Actualiza la logica para agitar la pantalla
void Screen::updateShake() void Screen::updateShakeEffect()
{ {
if (shakeEffect.enabled) if (shake_effect_.enabled)
{ {
if (shakeEffect.counter > 0) if (shake_effect_.counter > 0)
{ {
shakeEffect.counter--; shake_effect_.counter--;
} }
else else
{ {
shakeEffect.counter = shakeEffect.delay; shake_effect_.counter = shake_effect_.delay;
const auto srcdesp = shakeEffect.remaining % 2 == 0 ? 0 : shakeEffect.desp; const auto srcdesp = shake_effect_.remaining % 2 == 0 ? 0 : shake_effect_.desp;
const auto dstdesp = shakeEffect.remaining % 2 == 1 ? 0 : shakeEffect.desp; const auto dstdesp = shake_effect_.remaining % 2 == 1 ? 0 : shake_effect_.desp;
srcrect.x = shakeEffect.originalPos + srcdesp; src_rect_.x = shake_effect_.originalPos + srcdesp;
dstrect.x = shakeEffect.originalPos + dstdesp; dst_rect_.x = shake_effect_.originalPos + dstdesp;
shakeEffect.remaining--; shake_effect_.remaining--;
shakeEffect.enabled = shakeEffect.remaining == -1 ? false : true; shake_effect_.enabled = shake_effect_.remaining == -1 ? false : true;
if (!shakeEffect.enabled) if (!shake_effect_.enabled)
{ {
srcrect.x = shakeEffect.originalPos; src_rect_.x = shake_effect_.originalPos;
srcrect.w = shakeEffect.originalWidth; src_rect_.w = shake_effect_.originalWidth;
dstrect = srcrect; dst_rect_ = src_rect_;
} }
} }
} }
@@ -407,39 +400,39 @@ void Screen::updateShake()
// Pone la pantalla de color // Pone la pantalla de color
void Screen::flash(Color color, int lenght) void Screen::flash(Color color, int lenght)
{ {
flashEffect.enabled = true; flash_effect_.enabled = true;
flashEffect.counter = 0; flash_effect_.counter = 0;
flashEffect.lenght = lenght; flash_effect_.lenght = lenght;
flashEffect.color = color; flash_effect_.color = color;
} }
// Actualiza y dibuja el efecto de flash en la pantalla // Actualiza y dibuja el efecto de flash en la pantalla
void Screen::doFlash() void Screen::doFlash()
{ {
if (flashEffect.enabled) if (flash_effect_.enabled)
{ {
// Dibuja el color del flash en la textura // Dibuja el color del flash en la textura
SDL_Texture *temp = SDL_GetRenderTarget(renderer); SDL_Texture *temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer, gameCanvas); SDL_SetRenderTarget(renderer_, game_canvas_);
SDL_SetRenderDrawColor(renderer, flashEffect.color.r, flashEffect.color.g, flashEffect.color.b, 0xFF); SDL_SetRenderDrawColor(renderer_, flash_effect_.color.r, flash_effect_.color.g, flash_effect_.color.b, 0xFF);
SDL_RenderClear(renderer); SDL_RenderClear(renderer_);
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
// Actualiza la lógica del efecto // Actualiza la lógica del efecto
flashEffect.counter < flashEffect.lenght ? flashEffect.counter++ : flashEffect.enabled = false; flash_effect_.counter < flash_effect_.lenght ? flash_effect_.counter++ : flash_effect_.enabled = false;
} }
} }
// Atenua la pantalla // Atenua la pantalla
void Screen::doAttenuate() void Screen::doAttenuate()
{ {
if (attenuateEffect) if (attenuate_effect_)
{ {
SDL_Texture *temp = SDL_GetRenderTarget(renderer); SDL_Texture *temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer, gameCanvas); SDL_SetRenderTarget(renderer_, game_canvas_);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 64); SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 64);
SDL_RenderFillRect(renderer, nullptr); SDL_RenderFillRect(renderer_, nullptr);
SDL_SetRenderTarget(renderer, temp); SDL_SetRenderTarget(renderer_, temp);
} }
} }
@@ -455,50 +448,50 @@ void Screen::switchShaders()
// Atenua la pantalla // Atenua la pantalla
void Screen::attenuate(bool value) void Screen::attenuate(bool value)
{ {
attenuateEffect = value; attenuate_effect_ = value;
} }
// Muestra una notificación de texto por pantalla; // Muestra una notificación de texto por pantalla;
void Screen::showNotification(std::string text1, std::string text2, int icon) void Screen::showNotification(const std::string &text1, const std::string &text2, int icon)
{ {
notify->showText(text1, text2, icon); notify_->showText(text1, text2, icon);
} }
// Obtiene el puntero al renderizador // Obtiene el puntero al renderizador
SDL_Renderer *Screen::getRenderer() SDL_Renderer *Screen::getRenderer()
{ {
return renderer; return renderer_;
} }
// Calcula los frames por segundo // Calcula los frames por segundo
void Screen::updateFPS() void Screen::updateFPS()
{ {
if (SDL_GetTicks() - fpsTicks > 1000) if (SDL_GetTicks() - fps_ticks_ > 1000)
{ {
fpsTicks = SDL_GetTicks(); fps_ticks_ = SDL_GetTicks();
fps = fpsCounter; fps_ = fps_counter_;
fpsCounter = 0; fps_counter_ = 0;
} }
} }
// Muestra información por pantalla // Muestra información por pantalla
void Screen::displayInfo() void Screen::displayInfo()
{ {
if (showInfo) if (show_info_)
{ {
// FPS // FPS
const std::string fpstext = std::to_string(fps) + " FPS"; const std::string fpstext = std::to_string(fps_) + " FPS";
dbg_print(param.game.width - fpstext.length() * 8, 0, fpstext.c_str(), 255, 255, 0); dbg_print(param.game.width - fpstext.length() * 8, 0, fpstext.c_str(), 255, 255, 0);
// Resolution // Resolution
dbg_print(0, 0, infoResolution.c_str(), 255, 255, 0); dbg_print(0, 0, info_resolution_.c_str(), 255, 255, 0);
dbg_print(0, 8, std::to_string(globalInputs::servicePressedCounter[0]).c_str(), 255, 255, 0); dbg_print(0, 8, std::to_string(globalInputs::service_pressed_counter[0]).c_str(), 255, 255, 0);
} }
} }
// Indica si hay alguna notificación activa en pantalla // Indica si hay alguna notificación activa en pantalla
bool Screen::notificationsAreActive() bool Screen::notificationsAreActive() const
{ {
return notify->active(); return notify_->active();
} }

View File

@@ -8,17 +8,15 @@
#include <string> // for basic_string, string #include <string> // for basic_string, string
#include "utils.h" // for Color #include "utils.h" // for Color
#include <memory> #include <memory>
class Asset;
class Input;
class Notify; class Notify;
enum class ScreenFilter enum class ScreenFilter : int
{ {
NEAREST = 0, NEAREST = 0,
LINEAL = 1, LINEAL = 1,
}; };
enum class ScreenVideoMode enum class ScreenVideoMode : int
{ {
WINDOW = 0, WINDOW = 0,
FULLSCREEN = 1, FULLSCREEN = 1,
@@ -28,29 +26,27 @@ class Screen
{ {
private: private:
// [SINGLETON] Objeto screen privado para Don Melitón // [SINGLETON] Objeto screen privado para Don Melitón
static Screen *screen; static Screen *screen_;
// Objetos y punteros // Objetos y punteros
SDL_Window *window; // Ventana de la aplicación SDL_Window *window_; // Ventana de la aplicación
SDL_Renderer *renderer; // El renderizador de la ventana SDL_Renderer *renderer_; // El renderizador de la ventana
Asset *asset; // Objeto con el listado de recursos std::unique_ptr<Notify> notify_; // Pinta notificaciones en pantalla
Input *input; // Objeto para leer las entradas de teclado o mando SDL_Texture *game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador
std::unique_ptr<Notify> notify; // Pinta notificaciones en pantalla SDL_Texture *shader_canvas_; // Textura para pasarle al shader desde gameCanvas
SDL_Texture *gameCanvas; // Textura donde se dibuja todo antes de volcarse al renderizador
SDL_Texture *shaderCanvas; // Textura para pasarle al shader desde gameCanvas
// Variables // Variables
SDL_Rect srcrect; // Coordenadas de donde va a pillar la textura del juego para dibujarla SDL_Rect src_rect_; // Coordenadas de donde va a pillar la textura del juego para dibujarla
SDL_Rect dstrect; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana SDL_Rect dst_rect_; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana
Color borderColor; // Color del borde añadido a la textura de juego para rellenar la pantalla Color border_color_; // Color del borde añadido a la textura de juego para rellenar la pantalla
bool attenuateEffect; // Indica si la pantalla ha de estar atenuada bool attenuate_effect_; // Indica si la pantalla ha de estar atenuada
Uint32 fpsTicks; // Ticks para contar los frames por segundo Uint32 fps_ticks_; // Ticks para contar los frames por segundo
int fpsCounter; // Contador de frames por segundo int fps_counter_; // Contador de frames por segundo
int fps; // Frames calculados en el último segundo int fps_; // Frames calculados en el último segundo
bool showInfo; // Indica si ha de mostrar/ocultar la información de la pantalla bool show_info_; // Indica si ha de mostrar/ocultar la información de la pantalla
std::string infoResolution; // Texto con la informacion de la pantalla std::string info_resolution_; // Texto con la informacion de la pantalla
struct effect_t struct FlashEffect
{ {
bool enabled; // Indica si el efecto está activo bool enabled; // Indica si el efecto está activo
int counter; // Contador para el efecto int counter; // Contador para el efecto
@@ -58,10 +54,7 @@ private:
Color color; // Color del efecto Color color; // Color del efecto
}; };
// Variables - Efectos struct ShakeEffect
effect_t flashEffect; // Variable para gestionar el efecto de flash
struct shake_t
{ {
int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x
int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse
@@ -71,10 +64,14 @@ private:
int originalPos; // Posición inicial de la pantalla para dejarla igual tras el desplazamiento int originalPos; // Posición inicial de la pantalla para dejarla igual tras el desplazamiento
int originalWidth; // Anchura inicial de la pantalla para dejarla igual tras el desplazamiento int originalWidth; // Anchura inicial de la pantalla para dejarla igual tras el desplazamiento
bool enabled; // Indica si el efecto está activo bool enabled; // Indica si el efecto está activo
} shakeEffect; };
// Variables - Efectos
FlashEffect flash_effect_; // Variable para gestionar el efecto de flash
ShakeEffect shake_effect_; // Variable para gestionar el efecto de agitar la pantalla
// Actualiza la logica para agitar la pantalla // Actualiza la logica para agitar la pantalla
void updateShake(); void updateShakeEffect();
// Actualiza y dibuja el efecto de flash en la pantalla // Actualiza y dibuja el efecto de flash en la pantalla
void doFlash(); void doFlash();
@@ -122,7 +119,7 @@ public:
void blit(); void blit();
// Establece el modo de video // Establece el modo de video
void setVideoMode(ScreenVideoMode videoMode); void setVideoMode(ScreenVideoMode video_mode);
// Camibia entre pantalla completa y ventana // Camibia entre pantalla completa y ventana
void switchVideoMode(); void switchVideoMode();
@@ -140,7 +137,7 @@ public:
void setBorderColor(Color color); void setBorderColor(Color color);
// Cambia el tipo de mezcla // Cambia el tipo de mezcla
void setBlendMode(SDL_BlendMode blendMode); void setBlendMode(SDL_BlendMode blend_mode);
// Agita la pantalla // Agita la pantalla
void shake(); void shake();
@@ -155,10 +152,10 @@ public:
void attenuate(bool value); void attenuate(bool value);
// Muestra una notificación de texto por pantalla; // Muestra una notificación de texto por pantalla;
void showNotification(std::string text1 = "", std::string text2 = "", int icon = -1); void showNotification(const std::string &text1 = std::string(), const std::string &text2 = std::string(), int icon = -1);
// Indica si hay alguna notificación activa en pantalla // Indica si hay alguna notificación activa en pantalla
bool notificationsAreActive(); bool notificationsAreActive() const;
// Obtiene el puntero al renderizador // Obtiene el puntero al renderizador
SDL_Renderer *getRenderer(); SDL_Renderer *getRenderer();

View File

@@ -4,20 +4,18 @@ class Texture;
// Constructor // Constructor
SmartSprite::SmartSprite(std::shared_ptr<Texture> texture) SmartSprite::SmartSprite(std::shared_ptr<Texture> texture)
: AnimatedSprite(texture)
{ {
// Copia punteros
setTexture(texture);
init(); init();
} }
// Inicializa el objeto // Inicializa el objeto
void SmartSprite::init() void SmartSprite::init()
{ {
finishedCounter_ = 0; finished_counter_ = 0;
onDestination_ = false; on_destination_ = false;
destX_ = 0; dest_x_ = 0;
destY_ = 0; dest_y_ = 0;
finished_ = false; finished_ = false;
enabled_ = false; enabled_ = false;
} }
@@ -36,31 +34,31 @@ void SmartSprite::update()
// Establece el valor de la variable // Establece el valor de la variable
void SmartSprite::setFinishedCounter(int value) void SmartSprite::setFinishedCounter(int value)
{ {
finishedCounter_ = value; finished_counter_ = value;
} }
// Establece el valor de la variable // Establece el valor de la variable
void SmartSprite::setDestX(int x) void SmartSprite::setDestX(int x)
{ {
destX_ = x; dest_x_ = x;
} }
// Establece el valor de la variable // Establece el valor de la variable
void SmartSprite::setDestY(int y) void SmartSprite::setDestY(int y)
{ {
destY_ = y; dest_y_ = y;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int SmartSprite::getDestX() const int SmartSprite::getDestX() const
{ {
return destX_; return dest_x_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
int SmartSprite::getDestY() const int SmartSprite::getDestY() const
{ {
return destY_; return dest_y_;
} }
// Comprueba el movimiento // Comprueba el movimiento
@@ -70,10 +68,10 @@ void SmartSprite::checkMove()
if (getAccelX() > 0 || getVelX() > 0) if (getAccelX() > 0 || getVelX() > 0)
{ {
// Comprueba si ha llegado al destino // Comprueba si ha llegado al destino
if (getPosX() > destX_) if (getPosX() > dest_x_)
{ {
// Lo coloca en posición // Lo coloca en posición
setPosX(destX_); setPosX(dest_x_);
// Lo detiene // Lo detiene
setVelX(0.0f); setVelX(0.0f);
@@ -84,10 +82,10 @@ void SmartSprite::checkMove()
else if (getAccelX() < 0 || getVelX() < 0) else if (getAccelX() < 0 || getVelX() < 0)
{ {
// Comprueba si ha llegado al destino // Comprueba si ha llegado al destino
if (getPosX() < destX_) if (getPosX() < dest_x_)
{ {
// Lo coloca en posición // Lo coloca en posición
setPosX(destX_); setPosX(dest_x_);
// Lo detiene // Lo detiene
setVelX(0.0f); setVelX(0.0f);
@@ -99,10 +97,10 @@ void SmartSprite::checkMove()
if (getAccelY() > 0 || getVelY() > 0) if (getAccelY() > 0 || getVelY() > 0)
{ {
// Comprueba si ha llegado al destino // Comprueba si ha llegado al destino
if (getPosY() > destY_) if (getPosY() > dest_y_)
{ {
// Lo coloca en posición // Lo coloca en posición
setPosY(destY_); setPosY(dest_y_);
// Lo detiene // Lo detiene
setVelY(0.0f); setVelY(0.0f);
@@ -113,10 +111,10 @@ void SmartSprite::checkMove()
else if (getAccelY() < 0 || getVelY() < 0) else if (getAccelY() < 0 || getVelY() < 0)
{ {
// Comprueba si ha llegado al destino // Comprueba si ha llegado al destino
if (getPosY() < destY_) if (getPosY() < dest_y_)
{ {
// Lo coloca en posición // Lo coloca en posición
setPosY(destY_); setPosY(dest_y_);
// Lo detiene // Lo detiene
setVelY(0.0f); setVelY(0.0f);
@@ -129,17 +127,17 @@ void SmartSprite::checkMove()
void SmartSprite::checkFinished() void SmartSprite::checkFinished()
{ {
// Comprueba si ha llegado a su destino // Comprueba si ha llegado a su destino
onDestination_ = (getPosX() == destX_ && getPosY() == destY_) ? true : false; on_destination_ = (getPosX() == dest_x_ && getPosY() == dest_y_) ? true : false;
if (onDestination_) if (on_destination_)
{ {
if (finishedCounter_ == 0) if (finished_counter_ == 0)
{ {
finished_ = true; finished_ = true;
} }
else else
{ {
--finishedCounter_; --finished_counter_;
} }
} }
} }
@@ -147,11 +145,16 @@ void SmartSprite::checkFinished()
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool SmartSprite::isOnDestination() const bool SmartSprite::isOnDestination() const
{ {
return onDestination_; return on_destination_;
} }
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool SmartSprite::hasFinished() const bool SmartSprite::hasFinished() const
{ {
return finished_; return finished_;
}
void SmartSprite::setEnabled(bool value)
{
enabled_ = value;
} }

View File

@@ -1,19 +1,20 @@
#pragma once #pragma once
#include "animated_sprite.h" // for AnimatedSprite #include <memory> // for shared_ptr
#include "texture.h" #include "animated_sprite.h" // for AnimatedSprite
#include <memory> class Texture;
// Clase SmartSprite // Clase SmartSprite
class SmartSprite : public AnimatedSprite class SmartSprite : public AnimatedSprite
{ {
private: private:
// Variables // Variables
bool onDestination_; // Indica si está en el destino bool on_destination_; // Indica si está en el destino
int destX_; // Posicion de destino en el eje X int dest_x_; // Posicion de destino en el eje X
int destY_; // Posicion de destino en el eje Y int dest_y_; // Posicion de destino en el eje Y
int finishedCounter_; // Contador para deshabilitarlo int finished_counter_; // Contador para deshabilitarlo
bool finished_; // Indica si ya ha terminado bool finished_; // Indica si ya ha terminado
bool enabled_; // Indica si el objeto está habilitado
// Comprueba el movimiento // Comprueba el movimiento
void checkMove(); void checkMove();
@@ -23,7 +24,7 @@ private:
public: public:
// Constructor // Constructor
SmartSprite(std::shared_ptr<Texture> texture); explicit SmartSprite(std::shared_ptr<Texture> texture);
// Destructor // Destructor
~SmartSprite() = default; ~SmartSprite() = default;
@@ -32,7 +33,7 @@ public:
void init(); void init();
// Actualiza la posición y comprueba si ha llegado a su destino // Actualiza la posición y comprueba si ha llegado a su destino
void update(); void update() override;
// Establece el valor de la variable // Establece el valor de la variable
void setFinishedCounter(int value); void setFinishedCounter(int value);
@@ -54,4 +55,6 @@ public:
// Obtiene el valor de la variable // Obtiene el valor de la variable
bool hasFinished() const; bool hasFinished() const;
void setEnabled(bool value);
}; };

View File

@@ -2,121 +2,108 @@
// Constructor // Constructor
Sprite::Sprite(int x, int y, int w, int h, std::shared_ptr<Texture> texture) Sprite::Sprite(int x, int y, int w, int h, std::shared_ptr<Texture> texture)
: x_(x), y_(y), w_(w), h_(h), texture_(texture) : texture_(texture),
{ pos_((SDL_Rect){x, y, w, h}),
// Establece el rectangulo de donde coger la imagen sprite_clip_((SDL_Rect){0, 0, pos_.w, pos_.h}) {}
spriteClip_ = {0, 0, w, h};
// Inicializa variables
enabled_ = true;
}
Sprite::Sprite(SDL_Rect rect, std::shared_ptr<Texture> texture) Sprite::Sprite(SDL_Rect rect, std::shared_ptr<Texture> texture)
: x_(rect.x), y_(rect.y), w_(rect.w), h_(rect.h), texture_(texture) : texture_(texture),
{ pos_(rect),
// Establece el rectangulo de donde coger la imagen sprite_clip_((SDL_Rect){0, 0, pos_.w, pos_.h}) {}
spriteClip_ = {0, 0, w_, h_};
// Inicializa variables Sprite::Sprite(std::shared_ptr<Texture> texture)
enabled_ = true; : texture_(texture) {}
}
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void Sprite::render() void Sprite::render()
{ {
if (enabled_) texture_->render(pos_.x, pos_.y, &sprite_clip_);
{
texture_->render(x_, y_, &spriteClip_);
}
} }
// Obten el valor de la variable // Obten el valor de la variable
int Sprite::getPosX() const int Sprite::getIntPosX() const
{ {
return x_; return pos_.x;
} }
// Obten el valor de la variable // Obten el valor de la variable
int Sprite::getPosY() const int Sprite::getIntPosY() const
{ {
return y_; return pos_.y;
} }
// Obten el valor de la variable // Obten el valor de la variable
int Sprite::getWidth() const int Sprite::getWidth() const
{ {
return w_; return pos_.w;
} }
// Obten el valor de la variable // Obten el valor de la variable
int Sprite::getHeight() const int Sprite::getHeight() const
{ {
return h_; return pos_.h;
} }
// Establece la posición del objeto // Establece la posición del objeto
void Sprite::setPos(int x, int y) void Sprite::setPos(int x, int y)
{ {
x_ = x; pos_.x = x;
y_ = y; pos_.y = y;
} }
// Establece la posición del objeto // Establece la posición del objeto
void Sprite::setPos(SDL_Point p) void Sprite::setPos(SDL_Point p)
{ {
x_ = p.x; pos_.x = p.x;
y_ = p.y; pos_.y = p.y;
} }
// Establece la posición del objeto // Establece la posición del objeto
void Sprite::setPos(SDL_Rect r) void Sprite::setPos(SDL_Rect r)
{ {
x_ = r.x; pos_ = r;
y_ = r.y;
w_ = r.w;
h_ = r.h;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setPosX(int x) void Sprite::setPosX(int x)
{ {
x_ = x; pos_.x = x;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setPosY(int y) void Sprite::setPosY(int y)
{ {
y_ = y; pos_.y = y;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setWidth(int w) void Sprite::setWidth(int w)
{ {
w_ = w; pos_.w = w;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setHeight(int h) void Sprite::setHeight(int h)
{ {
h_ = h; pos_.h = h;
} }
// Obten el valor de la variable // Obten el valor de la variable
SDL_Rect Sprite::getSpriteClip() const SDL_Rect Sprite::getSpriteClip() const
{ {
return spriteClip_; return sprite_clip_;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setSpriteClip(SDL_Rect rect) void Sprite::setSpriteClip(SDL_Rect rect)
{ {
spriteClip_ = rect; sprite_clip_ = rect;
} }
// Establece el valor de la variable // Establece el valor de la variable
void Sprite::setSpriteClip(int x, int y, int w, int h) void Sprite::setSpriteClip(int x, int y, int w, int h)
{ {
spriteClip_ = (SDL_Rect){x, y, w, h}; sprite_clip_ = (SDL_Rect){x, y, w, h};
} }
// Obten el valor de la variable // Obten el valor de la variable
@@ -131,32 +118,20 @@ void Sprite::setTexture(std::shared_ptr<Texture> texture)
texture_ = texture; texture_ = texture;
} }
// Establece el valor de la variable
void Sprite::setEnabled(bool value)
{
enabled_ = value;
}
// Comprueba si el objeto está habilitado
bool Sprite::isEnabled() const
{
return enabled_;
}
// Devuelve el rectangulo donde está el sprite // Devuelve el rectangulo donde está el sprite
SDL_Rect Sprite::getRect() const SDL_Rect Sprite::getPos() const
{ {
return (SDL_Rect){x_, y_, w_, h_}; return pos_;
} }
// Incrementa el valor de la variable // Incrementa el valor de la variable
void Sprite::incPosX(int value) void Sprite::incPosX(int value)
{ {
x_ += value; pos_.x += value;
} }
// Incrementa el valor de la variable // Incrementa el valor de la variable
void Sprite::incPosY(int value) void Sprite::incPosY(int value)
{ {
y_ += value; pos_.y += value;
} }

View File

@@ -8,47 +8,43 @@
class Sprite class Sprite
{ {
protected: protected:
int x_; // Posición en el eje X donde dibujar el sprite // Variables
int y_; // Posición en el eje Y donde dibujar el sprite
int w_; // Ancho del sprite
int h_; // Alto del sprite
std::shared_ptr<Texture> texture_; // Textura donde estan todos los dibujos del sprite std::shared_ptr<Texture> texture_; // Textura donde estan todos los dibujos del sprite
SDL_Rect spriteClip_; // Rectangulo de origen de la textura que se dibujará en pantalla SDL_Rect pos_; // Posición y tamaño donde dibujar el sprite
SDL_Rect sprite_clip_; // Rectangulo de origen de la textura que se dibujará en pantalla
bool enabled_; // Indica si el sprite esta habilitado
public: public:
// Constructor // Constructor
Sprite(int x = 0, int y = 0, int w = 0, int h = 0, std::shared_ptr<Texture> texture = nullptr); explicit Sprite(int x = 0, int y = 0, int w = 0, int h = 0, std::shared_ptr<Texture> texture = nullptr);
Sprite(SDL_Rect rect, std::shared_ptr<Texture> texture = nullptr); explicit Sprite(SDL_Rect rect, std::shared_ptr<Texture> texture = nullptr);
explicit Sprite(std::shared_ptr<Texture> texture = nullptr);
// Destructor // Destructor
~Sprite() = default; virtual ~Sprite() = default;
// Muestra el sprite por pantalla // Muestra el sprite por pantalla
void render(); virtual void render();
// Obten el valor de la variable // Obten el valor de la variable
int getPosX() const; int getIntPosX() const;
int getPosY() const; int getIntPosY() const;
int getWidth() const; int getWidth() const;
int getHeight() const; int getHeight() const;
// Establece la posición del objeto
void setPos(int x, int y);
void setPos(SDL_Point p);
void setPos(SDL_Rect r);
// Devuelve el rectangulo donde está el sprite // Devuelve el rectangulo donde está el sprite
SDL_Rect getRect() const; virtual SDL_Rect getPos() const;
// Establece el valor de la variable // Establece el valor de la variable
void setPosX(int x); void setPosX(int x);
void setPosY(int y); void setPosY(int y);
void setWidth(int w); void setWidth(int w);
void setHeight(int h); void setHeight(int h);
// Establece la posición del objeto
void setPos(int x, int y);
void setPos(SDL_Point p);
virtual void setPos(SDL_Rect r);
// Incrementa el valor de la variable // Incrementa el valor de la variable
void incPosX(int value); void incPosX(int value);
void incPosY(int value); void incPosY(int value);
@@ -65,11 +61,4 @@ public:
// Establece el valor de la variable // Establece el valor de la variable
void setTexture(std::shared_ptr<Texture> texture); void setTexture(std::shared_ptr<Texture> texture);
// Establece el valor de la variable
void setEnabled(bool value);
// Comprueba si el objeto está habilitado
bool isEnabled() const;
}; };

View File

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

View File

@@ -1,9 +1,10 @@
#include "text.h" #include "text.h"
#include <fstream> // for char_traits, basic_ostream, basic_ifstream, ope... #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <iostream> // for cout #include <fstream> // for basic_ostream, basic_ifstream, basic_istream
#include "sprite.h" // for Sprite #include <iostream> // for cout
#include "texture.h" // for Texture #include "sprite.h" // for Sprite
#include "utils.h" // for Color #include "texture.h" // for Texture
#include "utils.h" // for Color
// Llena una estructuta TextFile desde un fichero // Llena una estructuta TextFile desde un fichero
TextFile LoadTextFile(std::string file_path) TextFile LoadTextFile(std::string file_path)
@@ -16,10 +17,14 @@ TextFile LoadTextFile(std::string file_path)
tf.offset[i].x = 0; tf.offset[i].x = 0;
tf.offset[i].y = 0; tf.offset[i].y = 0;
tf.offset[i].w = 0; tf.offset[i].w = 0;
tf.box_width = 0;
tf.box_height = 0;
} }
// Abre el fichero para leer los valores // Abre el fichero para leer los valores
#ifdef VERBOSE
const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1).c_str(); const std::string file_name = file_path.substr(file_path.find_last_of("\\/") + 1).c_str();
#endif
std::ifstream file(file_path); std::ifstream file(file_path);
if (file.is_open() && file.good()) if (file.is_open() && file.good())
@@ -53,7 +58,7 @@ TextFile LoadTextFile(std::string file_path)
// Cierra el fichero // Cierra el fichero
#ifdef VERBOSE #ifdef VERBOSE
std::cout << "Text loaded: " << file_name.c_str() << std::endl; std::cout << "Text loaded: " << file_name << std::endl;
#endif #endif
file.close(); file.close();
} }
@@ -62,7 +67,7 @@ TextFile LoadTextFile(std::string file_path)
else else
{ {
#ifdef VERBOSE #ifdef VERBOSE
std::cout << "Warning: Unable to open " << file_name.c_str() << " file" << std::endl; std::cout << "Warning: Unable to open " << file_name << " file" << std::endl;
#endif #endif
} }
@@ -77,7 +82,7 @@ TextFile LoadTextFile(std::string file_path)
} }
// Constructor // Constructor
Text::Text(std::string bitmap_file, std::string text_file, SDL_Renderer *renderer) Text::Text(const std::string &bitmap_file, const std::string &text_file, SDL_Renderer *renderer)
{ {
// Carga los offsets desde el fichero // Carga los offsets desde el fichero
auto tf = LoadTextFile(text_file); auto tf = LoadTextFile(text_file);
@@ -101,7 +106,7 @@ Text::Text(std::string bitmap_file, std::string text_file, SDL_Renderer *rendere
} }
// Constructor // Constructor
Text::Text(std::string text_file, std::shared_ptr<Texture> texture) Text::Text(const std::string &text_file, std::shared_ptr<Texture> texture)
{ {
// Carga los offsets desde el fichero // Carga los offsets desde el fichero
auto tf = LoadTextFile(text_file); auto tf = LoadTextFile(text_file);
@@ -144,7 +149,7 @@ Text::Text(TextFile *text_file, std::shared_ptr<Texture> texture)
} }
// Escribe texto en pantalla // Escribe texto en pantalla
void Text::write(int x, int y, std::string text, int kerning, int lenght) void Text::write(int x, int y, const std::string &text, int kerning, int lenght)
{ {
auto shift = 0; auto shift = 0;
@@ -167,7 +172,7 @@ void Text::write(int x, int y, std::string text, int kerning, int lenght)
} }
// Escribe el texto con colores // Escribe el texto con colores
void Text::writeColored(int x, int y, std::string text, Color color, int kerning, int lenght) void Text::writeColored(int x, int y, const std::string &text, Color color, int kerning, int lenght)
{ {
sprite_->getTexture()->setColor(color.r, color.g, color.b); sprite_->getTexture()->setColor(color.r, color.g, color.b);
write(x, y, text, kerning, lenght); write(x, y, text, kerning, lenght);
@@ -175,7 +180,7 @@ void Text::writeColored(int x, int y, std::string text, Color color, int kerning
} }
// Escribe el texto con sombra // Escribe el texto con sombra
void Text::writeShadowed(int x, int y, std::string text, Color color, Uint8 shadow_distance, int kerning, int lenght) void Text::writeShadowed(int x, int y, const std::string &text, Color color, Uint8 shadow_distance, int kerning, int lenght)
{ {
sprite_->getTexture()->setColor(color.r, color.g, color.b); sprite_->getTexture()->setColor(color.r, color.g, color.b);
write(x + shadow_distance, y + shadow_distance, text, kerning, lenght); write(x + shadow_distance, y + shadow_distance, text, kerning, lenght);
@@ -184,14 +189,14 @@ void Text::writeShadowed(int x, int y, std::string text, Color color, Uint8 shad
} }
// Escribe el texto centrado en un punto x // Escribe el texto centrado en un punto x
void Text::writeCentered(int x, int y, std::string text, int kerning, int lenght) void Text::writeCentered(int x, int y, const std::string &text, int kerning, int lenght)
{ {
x -= (Text::lenght(text, kerning) / 2); x -= (Text::lenght(text, kerning) / 2);
write(x, y, text, kerning, lenght); write(x, y, text, kerning, lenght);
} }
// Escribe texto con extras // Escribe texto con extras
void Text::writeDX(Uint8 flags, int x, int y, std::string text, int kerning, Color textColor, Uint8 shadow_distance, Color shadow_color, int lenght) void Text::writeDX(Uint8 flags, int x, int y, const std::string &text, int kerning, Color textColor, Uint8 shadow_distance, Color shadow_color, int lenght)
{ {
const auto centered = ((flags & TEXT_CENTER) == TEXT_CENTER); const auto centered = ((flags & TEXT_CENTER) == TEXT_CENTER);
const auto shadowed = ((flags & TEXT_SHADOW) == TEXT_SHADOW); const auto shadowed = ((flags & TEXT_SHADOW) == TEXT_SHADOW);
@@ -233,7 +238,7 @@ void Text::writeDX(Uint8 flags, int x, int y, std::string text, int kerning, Col
} }
// Obtiene la longitud en pixels de una cadena // Obtiene la longitud en pixels de una cadena
int Text::lenght(std::string text, int kerning) const int Text::lenght(const std::string &text, int kerning) const
{ {
auto shift = 0; auto shift = 0;
@@ -265,7 +270,7 @@ void Text::setFixedWidth(bool value)
} }
// Carga una paleta de colores para el texto // Carga una paleta de colores para el texto
void Text::addPalette(std::string path) void Text::addPalette(const std::string &path)
{ {
texture_->addPalette(path); texture_->addPalette(path);
} }

View File

@@ -2,11 +2,11 @@
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint8 #include <SDL2/SDL_stdinc.h> // for Uint8
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string #include <string> // for string
#include <memory> #include "sprite.h" // for Sprite
#include "utils.h" #include "utils.h" // for Color
#include "sprite.h" class Texture;
#include "texture.h"
constexpr int TEXT_COLOR = 1; constexpr int TEXT_COLOR = 1;
constexpr int TEXT_SHADOW = 2; constexpr int TEXT_SHADOW = 2;
@@ -33,41 +33,41 @@ class Text
{ {
private: private:
// Objetos y punteros // Objetos y punteros
std::unique_ptr<Sprite> sprite_; // Objeto con los graficos para el texto std::unique_ptr<Sprite> sprite_; // Objeto con los graficos para el texto
std::shared_ptr<Texture> texture_; // Textura con los bitmaps del texto std::shared_ptr<Texture> texture_; // Textura con los bitmaps del texto
// Variables // Variables
int box_width_; // Anchura de la caja de cada caracter en el png int box_width_; // Anchura de la caja de cada caracter en el png
int box_height_; // Altura de la caja de cada caracter en el png int box_height_; // Altura de la caja de cada caracter en el png
bool fixed_width_; // Indica si el texto se ha de escribir con longitud fija en todas las letras bool fixed_width_; // Indica si el texto se ha de escribir con longitud fija en todas las letras
TextOffset offset_[128]; // Vector con las posiciones y ancho de cada letra TextOffset offset_[128]; // Vector con las posiciones y ancho de cada letra
public: public:
// Constructor // Constructor
Text(std::string bitmap_file, std::string text_file, SDL_Renderer *renderer); Text(const std::string &bitmap_file, const std::string &text_file, SDL_Renderer *renderer);
Text(std::string text_file, std::shared_ptr<Texture> texture); Text(const std::string &text_file, std::shared_ptr<Texture> texture);
Text(TextFile *text_file, std::shared_ptr<Texture> texture); Text(TextFile *text_file, std::shared_ptr<Texture> texture);
// Destructor // Destructor
~Text() = default; ~Text() = default;
// Escribe el texto en pantalla // Escribe el texto en pantalla
void write(int x, int y, std::string text, int kerning = 1, int lenght = -1); void write(int x, int y, const std::string &text, int kerning = 1, int lenght = -1);
// Escribe el texto con colores // Escribe el texto con colores
void writeColored(int x, int y, std::string text, Color color, int kerning = 1, int lenght = -1); void writeColored(int x, int y, const std::string &text, Color color, int kerning = 1, int lenght = -1);
// Escribe el texto con sombra // Escribe el texto con sombra
void writeShadowed(int x, int y, std::string text, Color color, Uint8 shadow_distance = 1, int kerning = 1, int lenght = -1); void writeShadowed(int x, int y, const std::string &text, Color color, Uint8 shadow_distance = 1, int kerning = 1, int lenght = -1);
// Escribe el texto centrado en un punto x // Escribe el texto centrado en un punto x
void writeCentered(int x, int y, std::string text, int kerning = 1, int lenght = -1); void writeCentered(int x, int y, const std::string &text, int kerning = 1, int lenght = -1);
// Escribe texto con extras // Escribe texto con extras
void writeDX(Uint8 flags, int x, int y, std::string text, int kerning = 1, Color textColor = {255, 255, 255}, Uint8 shadow_distance = 1, Color shadow_color = {0, 0, 0}, int lenght = -1); void writeDX(Uint8 flags, int x, int y, const std::string &text, int kerning = 1, Color textColor = Color(), Uint8 shadow_distance = 1, Color shadow_color = Color(), int lenght = -1);
// Obtiene la longitud en pixels de una cadena // Obtiene la longitud en pixels de una cadena
int lenght(std::string text, int kerning = 1) const; int lenght(const std::string &text, int kerning = 1) const;
// Devuelve el valor de la variable // Devuelve el valor de la variable
int getCharacterSize() const; int getCharacterSize() const;
@@ -79,7 +79,7 @@ public:
void setFixedWidth(bool value); void setFixedWidth(bool value);
// Carga una paleta de colores para el texto // Carga una paleta de colores para el texto
void addPalette(std::string path); void addPalette(const std::string &path);
// Establece una paleta de colores para el texto // Establece una paleta de colores para el texto
void setPalette(int index); void setPalette(int index);

View File

@@ -11,7 +11,7 @@
#include "stb_image.h" // for stbi_failure_reason, stbi_image_free #include "stb_image.h" // for stbi_failure_reason, stbi_image_free
// Constructor // Constructor
Texture::Texture(SDL_Renderer *renderer, std::string path) Texture::Texture(SDL_Renderer *renderer, const std::string &path)
: renderer_(renderer), path_(path) : renderer_(renderer), path_(path)
{ {
// Inicializa // Inicializa
@@ -23,7 +23,7 @@ Texture::Texture(SDL_Renderer *renderer, std::string path)
palettes_.clear(); palettes_.clear();
// Carga el fichero en la textura // Carga el fichero en la textura
if (path_ != "") if (!path_.empty())
{ {
// Obtiene la extensión // Obtiene la extensión
const std::string extension = path_.substr(path_.find_last_of(".") + 1); const std::string extension = path_.substr(path_.find_last_of(".") + 1);
@@ -37,8 +37,8 @@ Texture::Texture(SDL_Renderer *renderer, std::string path)
// .gif // .gif
else if (extension == "gif") else if (extension == "gif")
{ {
surface_ = loadSurface(path_.c_str()); surface_ = loadSurface(path_);
addPalette(path_.c_str()); addPalette(path_);
setPaletteColor(0, 0, 0x00000000); setPaletteColor(0, 0, 0x00000000);
createBlank(width_, height_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING); createBlank(width_, height_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING);
SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);
@@ -54,13 +54,12 @@ Texture::~Texture()
} }
// Carga una imagen desde un fichero // Carga una imagen desde un fichero
bool Texture::loadFromFile(std::string path) bool Texture::loadFromFile(const std::string &path)
{ {
const std::string file_name = path.substr(path.find_last_of("\\/") + 1);
int req_format = STBI_rgb_alpha; int req_format = STBI_rgb_alpha;
int width, height, orig_format; int width, height, orig_format;
unsigned char *data = stbi_load(path.c_str(), &width, &height, &orig_format, req_format); unsigned char *data = stbi_load(path.c_str(), &width, &height, &orig_format, req_format);
if (data == nullptr) if (!data)
{ {
#ifdef VERBOSE #ifdef VERBOSE
std::cout << "Loading image failed: " << stbi_failure_reason() << std::endl; std::cout << "Loading image failed: " << stbi_failure_reason() << std::endl;
@@ -70,19 +69,20 @@ bool Texture::loadFromFile(std::string path)
else else
{ {
#ifdef VERBOSE #ifdef VERBOSE
std::cout << "Image loaded: " << file_name.c_str() << std::endl; const std::string file_name = path.substr(path.find_last_of("\\/") + 1);
std::cout << "Image loaded: " << file_name << std::endl;
#endif #endif
} }
int depth, pitch; int depth, pitch;
Uint32 pixel_format; Uint32 pixel_format;
if (req_format == STBI_rgb) /*if (req_format == STBI_rgb)
{ {
depth = 24; depth = 24;
pitch = 3 * width; // 3 bytes por pixel * pixels por linea pitch = 3 * width; // 3 bytes por pixel * pixels por linea
pixel_format = SDL_PIXELFORMAT_RGB24; pixel_format = SDL_PIXELFORMAT_RGB24;
} }
else else*/
{ // STBI_rgb_alpha (RGBA) { // STBI_rgb_alpha (RGBA)
depth = 32; depth = 32;
pitch = 4 * width; pitch = 4 * width;
@@ -96,11 +96,11 @@ bool Texture::loadFromFile(std::string path)
SDL_Texture *newTexture = nullptr; SDL_Texture *newTexture = nullptr;
// Carga la imagen desde una ruta específica // Carga la imagen desde una ruta específica
SDL_Surface *loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom((void *)data, width, height, depth, pitch, pixel_format); auto loadedSurface = SDL_CreateRGBSurfaceWithFormatFrom(static_cast<void *>(data), width, height, depth, pitch, pixel_format);
if (loadedSurface == nullptr) if (loadedSurface == nullptr)
{ {
#ifdef VERBOSE #ifdef VERBOSE
std::cout << "Unable to load image " << path.c_str() << std::endl; std::cout << "Unable to load image " << path << std::endl;
#endif #endif
} }
else else
@@ -110,7 +110,7 @@ bool Texture::loadFromFile(std::string path)
if (newTexture == nullptr) if (newTexture == nullptr)
{ {
#ifdef VERBOSE #ifdef VERBOSE
std::cout << "Unable to create texture from " << path.c_str() << "! SDL Error: " << SDL_GetError() << std::endl; std::cout << "Unable to create texture from " << path << "! SDL Error: " << SDL_GetError() << std::endl;
#endif #endif
} }
else else
@@ -137,9 +137,9 @@ bool Texture::createBlank(int width, int height, SDL_PixelFormatEnum format, SDL
texture_ = SDL_CreateTexture(renderer_, format, access, width, height); texture_ = SDL_CreateTexture(renderer_, format, access, width, height);
if (!texture_) if (!texture_)
{ {
#ifdef VERBOSE #ifdef VERBOSE
std::cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << std::endl; std::cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << std::endl;
#endif #endif
} }
else else
{ {
@@ -239,14 +239,14 @@ SDL_Texture *Texture::getSDLTexture()
} }
// Crea una nueva surface // Crea una nueva surface
Surface Texture::newSurface(int w, int h) /*Surface Texture::newSurface(int w, int h)
{ {
Surface surf = (Surface)malloc(sizeof(surface_s)); Surface surf = static_cast<Surface>(malloc(sizeof(surface_s)));
surf->w = w; surf->w = w;
surf->h = h; surf->h = h;
surf->data = (Uint8 *)malloc(w * h); surf->data = static_cast<Uint8 *>(malloc(w * h));
return surf; return surf;
} }*/
// Elimina una surface // Elimina una surface
void Texture::deleteSurface(Surface surface) void Texture::deleteSurface(Surface surface)
@@ -265,29 +265,29 @@ void Texture::deleteSurface(Surface surface)
} }
// Crea una surface desde un fichero .gif // Crea una surface desde un fichero .gif
Surface Texture::loadSurface(const char *file_name) Surface Texture::loadSurface(const std::string &file_name)
{ {
FILE *f = fopen(file_name, "rb"); FILE *f = fopen(file_name.c_str(), "rb");
if (!f) if (!f)
{ {
return NULL; return nullptr;
} }
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
long size = ftell(f); long size = ftell(f);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
Uint8 *buffer = (Uint8 *)malloc(size); Uint8 *buffer = static_cast<Uint8 *>(malloc(size));
fread(buffer, size, 1, f); fread(buffer, size, 1, f);
fclose(f); fclose(f);
Uint16 w, h; Uint16 w, h;
Uint8 *pixels = LoadGif(buffer, &w, &h); Uint8 *pixels = LoadGif(buffer, &w, &h);
if (pixels == NULL) if (pixels == nullptr)
{ {
return NULL; return nullptr;
} }
Surface surface = (Surface)malloc(sizeof(surface_s)); Surface surface = static_cast<Surface>(malloc(sizeof(surface_s)));
surface->w = w; surface->w = w;
surface->h = h; surface->h = h;
surface->data = pixels; surface->data = pixels;
@@ -312,7 +312,7 @@ void Texture::flipSurface()
// Vuelca los datos // Vuelca los datos
Uint32 *pixels; Uint32 *pixels;
int pitch; int pitch;
SDL_LockTexture(texture_, nullptr, (void **)&pixels, &pitch); SDL_LockTexture(texture_, nullptr, reinterpret_cast<void **>(&pixels), &pitch);
for (int i = 0; i < width_ * height_; ++i) for (int i = 0; i < width_ * height_; ++i)
{ {
pixels[i] = palettes_[paletteIndex_][surface_->data[i]]; pixels[i] = palettes_[paletteIndex_][surface_->data[i]];
@@ -327,11 +327,11 @@ void Texture::setPaletteColor(int palette, int index, Uint32 color)
} }
// Carga una paleta desde un fichero // Carga una paleta desde un fichero
std::vector<Uint32> Texture::loadPal(const char *file_name) std::vector<Uint32> Texture::loadPal(const std::string &file_name)
{ {
std::vector<Uint32> palette; std::vector<Uint32> palette;
FILE *f = fopen(file_name, "rb"); FILE *f = fopen(file_name.c_str(), "rb");
if (!f) if (!f)
{ {
return palette; return palette;
@@ -340,12 +340,12 @@ std::vector<Uint32> Texture::loadPal(const char *file_name)
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
long size = ftell(f); long size = ftell(f);
fseek(f, 0, SEEK_SET); fseek(f, 0, SEEK_SET);
Uint8 *buffer = (Uint8 *)malloc(size); Uint8 *buffer = static_cast<Uint8 *>(malloc(size));
fread(buffer, size, 1, f); fread(buffer, size, 1, f);
fclose(f); fclose(f);
Uint32 *pal = LoadPalette(buffer); const auto *pal = LoadPalette(buffer);
if (pal == nullptr) if (!pal)
{ {
return palette; return palette;
} }
@@ -361,9 +361,9 @@ std::vector<Uint32> Texture::loadPal(const char *file_name)
} }
// Añade una paleta a la lista // Añade una paleta a la lista
void Texture::addPalette(std::string path) void Texture::addPalette(const std::string &path)
{ {
palettes_.push_back(loadPal(path.c_str())); palettes_.push_back(loadPal(path));
setPaletteColor((int)palettes_.size() - 1, 0, 0x00000000); setPaletteColor((int)palettes_.size() - 1, 0, 0x00000000);
} }

View File

@@ -33,29 +33,29 @@ private:
int paletteIndex_; // Indice de la paleta en uso int paletteIndex_; // Indice de la paleta en uso
// Crea una nueva surface // Crea una nueva surface
Surface newSurface(int w, int h); //Surface newSurface(int w, int h);
// Elimina una surface // Elimina una surface
void deleteSurface(Surface surface); void deleteSurface(Surface surface);
// Crea una surface desde un fichero .gif // Crea una surface desde un fichero .gif
Surface loadSurface(const char *file_name); Surface loadSurface(const std::string &file_name);
// Vuelca la surface en la textura // Vuelca la surface en la textura
void flipSurface(); void flipSurface();
// Carga una paleta desde un fichero // Carga una paleta desde un fichero
std::vector<Uint32> loadPal(const char *file_name); std::vector<Uint32> loadPal(const std::string &file_name);
public: public:
// Constructor // Constructor
Texture(SDL_Renderer *renderer, std::string path = ""); explicit Texture(SDL_Renderer *renderer, const std::string &path = std::string());
// Destructor // Destructor
~Texture(); ~Texture();
// Carga una imagen desde un fichero // Carga una imagen desde un fichero
bool loadFromFile(std::string path); bool loadFromFile(const std::string &path);
// Crea una textura en blanco // Crea una textura en blanco
bool createBlank(int width, int height, SDL_PixelFormatEnum format = SDL_PIXELFORMAT_RGBA8888, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING); bool createBlank(int width, int height, SDL_PixelFormatEnum format = SDL_PIXELFORMAT_RGBA8888, SDL_TextureAccess = SDL_TEXTUREACCESS_STREAMING);
@@ -91,7 +91,7 @@ public:
SDL_Texture *getSDLTexture(); SDL_Texture *getSDLTexture();
// Añade una paleta a la lista // Añade una paleta a la lista
void addPalette(std::string path); void addPalette(const std::string &path);
// Establece un color de la paleta // Establece un color de la paleta
void setPaletteColor(int palette, int index, Uint32 color); void setPaletteColor(int palette, int index, Uint32 color);

View File

@@ -1,10 +1,11 @@
#include "tiled_bg.h" #include "tiled_bg.h"
#include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888 #include <SDL2/SDL_pixels.h> // for SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_stdinc.h> // for SDL_sinf #include <SDL2/SDL_stdinc.h> // for SDL_sinf
#include <stdlib.h> // for rand #include <stdlib.h> // for rand
#include "screen.h" // for Screen #include <memory> // for unique_ptr, make_shared, make_unique
#include "sprite.h" // for Sprite #include "screen.h" // for Screen
#include "texture.h" // for Texture #include "sprite.h" // for Sprite
#include "texture.h" // for Texture
// Constructor // Constructor
Tiledbg::Tiledbg(std::string texture_path, SDL_Rect pos, int mode) Tiledbg::Tiledbg(std::string texture_path, SDL_Rect pos, int mode)

View File

@@ -1,20 +1,24 @@
#include "title.h" #include "title.h"
#include <SDL2/SDL_keycode.h> // for SDLK_1, SDLK_2, SDLK_3 #include <SDL2/SDL_events.h> // for SDL_PollEvent, SDL_Event, SDL_KEYDOWN
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_keycode.h> // for SDLK_1, SDLK_2, SDLK_3
#include <SDL2/SDL_timer.h> // for SDL_GetTicks #include <SDL2/SDL_rect.h> // for SDL_Rect
#include <string> // for allocator, basic_string, char_traits #include <SDL2/SDL_render.h> // for SDL_Renderer
#include <vector> // for vector #include <SDL2/SDL_timer.h> // for SDL_GetTicks
#include "asset.h" // for Asset #include <string> // for char_traits, operator+, to_string, bas...
#include "global_inputs.h" // for globalInputs::check #include <utility> // for move
#include "input.h" // for Input, inputs_e, INPUT_DO_NOT_ALLOW_RE... #include <vector> // for vector
#include "jail_audio.h" // for JA_GetMusicState, JA_Music_state, JA_P... #include "asset.h" // for Asset
#include "lang.h" // for getText #include "global_inputs.h" // for check
#include "options.h" // for options #include "input.h" // for Input, InputType, INPUT_DO_NOT_ALLOW_R...
#include "param.h" // for param #include "jail_audio.h" // for JA_GetMusicState, JA_Music_state, JA_P...
#include "screen.h" // for Screen #include "lang.h" // for getText
#include "section.h" // for SectionOptions, options, SectionName, name #include "options.h" // for options
#include "param.h" // for param
struct JA_Music_t; #include "screen.h" // for Screen
#include "section.h" // for Options, options, Name, name
#include "texture.h" // for Texture
#include "utils.h" // for Param, OptionsController, Color, Param...
struct JA_Music_t; // lines 17-17
// Constructor // Constructor
Title::Title(JA_Music_t *music) Title::Title(JA_Music_t *music)
@@ -236,7 +240,7 @@ void Title::checkInput()
if (!define_buttons_->isEnabled()) if (!define_buttons_->isEnabled())
{ {
// Comprueba el teclado para empezar a jugar // Comprueba el teclado para empezar a jugar
if (input_->checkInput(input_start, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD)) if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_KEYBOARD))
{ {
if (section::options == section::Options::TITLE_2 || ALLOW_TITLE_ANIMATION_SKIP) if (section::options == section::Options::TITLE_2 || ALLOW_TITLE_ANIMATION_SKIP)
{ {
@@ -249,24 +253,24 @@ void Title::checkInput()
for (int i = 0; i < input_->getNumControllers(); ++i) for (int i = 0; i < input_->getNumControllers(); ++i)
{ {
// Comprueba si se va a intercambiar la asignación de mandos a jugadores // Comprueba si se va a intercambiar la asignación de mandos a jugadores
if (input_->checkModInput(input_service, input_swap_controllers, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (input_->checkModInput(InputType::SERVICE, InputType::SWAP_CONTROLLERS, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
swapControllers(); swapControllers();
return; return;
} }
// Comprueba si algun mando quiere ser configurado // Comprueba si algun mando quiere ser configurado
if (input_->checkModInput(input_service, input_config, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (input_->checkModInput(InputType::SERVICE, InputType::CONFIG, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
define_buttons_->enable(i); define_buttons_->enable(i);
return; return;
} }
// Comprueba el botón de START de los mandos // Comprueba el botón de START de los mandos
if (input_->checkInput(input_start, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
// Si no está el botón de servicio activo // Si no está el botón de servicio activo
if (!input_->checkInput(input_service, INPUT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i)) if (!input_->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, INPUT_USE_GAMECONTROLLER, i))
{ {
if (section::options == section::Options::TITLE_2 || ALLOW_TITLE_ANIMATION_SKIP) if (section::options == section::Options::TITLE_2 || ALLOW_TITLE_ANIMATION_SKIP)
{ {
@@ -315,9 +319,9 @@ void Title::resetCounter()
// Intercambia la asignación de mandos a los jugadores // Intercambia la asignación de mandos a los jugadores
void Title::swapControllers() void Title::swapControllers()
{ {
const int num_controllers_ = input_->getNumControllers(); const auto num_controllers = input_->getNumControllers();
if (num_controllers_ == 0) if (num_controllers == 0)
{ {
return; return;
} }
@@ -330,7 +334,7 @@ void Title::swapControllers()
int playerControllerIndex[MAX_CONTROLLERS]; int playerControllerIndex[MAX_CONTROLLERS];
for (int i = 0; i < MAX_CONTROLLERS; ++i) for (int i = 0; i < MAX_CONTROLLERS; ++i)
{ {
text[i] = ""; text[i].clear();
playerControllerIndex[i] = -1; playerControllerIndex[i] = -1;
} }

View File

@@ -1,24 +1,18 @@
#pragma once #pragma once
#include <SDL2/SDL_events.h> // for SDL_Event #include <SDL2/SDL_stdinc.h> // for Uint32
#include <SDL2/SDL_stdinc.h> // for Uint32 #include <memory> // for unique_ptr, shared_ptr
#include <memory> #include "define_buttons.h" // for DefineButtons
#include "define_buttons.h" #include "fade.h" // for Fade
#include "fade.h" #include "game_logo.h" // for GameLogo
#include "game_logo.h" #include "sprite.h" // for Sprite
#include "text.h" #include "text.h" // for Text
#include "tiled_bg.h" #include "tiled_bg.h" // for Tiledbg
#include "utils.h" // for Section class Input; // lines 17-17
#include "sprite.h" class Screen; // lines 18-18
#include "texture.h" class Texture; // lines 20-20
#include "section.h" namespace section { enum class Name; }
struct JA_Music_t; // lines 21-21
class Asset;
class Input;
class Screen;
class Sprite;
class Texture;
struct JA_Music_t;
// Textos // Textos
constexpr const char TEXT_COPYRIGHT[] = "@2020,2024 JailDesigner"; constexpr const char TEXT_COPYRIGHT[] = "@2020,2024 JailDesigner";
@@ -95,7 +89,7 @@ private:
public: public:
// Constructor // Constructor
Title(JA_Music_t *music); explicit Title(JA_Music_t *music);
// Destructor // Destructor
~Title() = default; ~Title() = default;

View File

@@ -1,11 +1,10 @@
#include "utils.h" #include "utils.h"
#include <stdlib.h> // for free, malloc #include <algorithm> // for min, clamp, find_if_not, transform
#include <algorithm> // for max, min #include <cctype> // for tolower, isspace
#include <cctype> // for isspace #include <cmath> // for cos, pow, M_PI
#include <iterator> // for distance #include <compare> // for operator<
#include <cmath> struct JA_Music_t; // lines 7-7
struct JA_Music_t; // lines 3-3 struct JA_Sound_t; // lines 8-8
struct JA_Sound_t; // lines 4-4
// Colores // Colores
const Color bg_color = {0x27, 0x27, 0x36}; const Color bg_color = {0x27, 0x27, 0x36};
@@ -29,210 +28,112 @@ double distanceSquared(int x1, int y1, int x2, int y2)
} }
// Detector de colisiones entre dos circulos // Detector de colisiones entre dos circulos
bool checkCollision(Circle &a, Circle &b) bool checkCollision(const Circle &a, const Circle &b)
{ {
// Calcula el radio total al cuadrado // Calcula el radio total al cuadrado
int total_radius_squared = a.r + b.r; int total_radius_squared = (a.r + b.r) * (a.r + b.r);
total_radius_squared = total_radius_squared * total_radius_squared;
// Si la distancia entre el centro de los circulos es inferior a la suma de sus radios // Comprueba si la distancia entre los centros de los círculos es inferior a la suma de sus radios
if (distanceSquared(a.x, a.y, b.x, b.y) < (total_radius_squared)) return distanceSquared(a.x, a.y, b.x, b.y) < total_radius_squared;
{
// Los circulos han colisionado
return true;
}
// En caso contrario
return false;
} }
// Detector de colisiones entre un circulo y un rectangulo // Detector de colisiones entre un circulo y un rectangulo
bool checkCollision(Circle &a, SDL_Rect &b) bool checkCollision(const Circle &a, const SDL_Rect &b)
{ {
// Closest point on collision box // Encuentra el punto más cercano en el rectángulo
int cX, cY; int cX = std::clamp(a.x, b.x, b.x + b.w);
int cY = std::clamp(a.y, b.y, b.y + b.h);
// Find closest x offset // Si el punto más cercano está dentro del círculo
if (a.x < b.x) return distanceSquared(a.x, a.y, cX, cY) < a.r * a.r;
{
cX = b.x;
}
else if (a.x > b.x + b.w)
{
cX = b.x + b.w;
}
else
{
cX = a.x;
}
// Find closest y offset
if (a.y < b.y)
{
cY = b.y;
}
else if (a.y > b.y + b.h)
{
cY = b.y + b.h;
}
else
{
cY = a.y;
}
// If the closest point is inside the Circle
if (distanceSquared(a.x, a.y, cX, cY) < a.r * a.r)
{
// This box and the Circle have collided
return true;
}
// If the shapes have not collided
return false;
} }
// Detector de colisiones entre dos rectangulos // Detector de colisiones entre dos rectangulos
bool checkCollision(SDL_Rect &a, SDL_Rect &b) bool checkCollision(const SDL_Rect &a, const SDL_Rect &b)
{ {
// Calcula las caras del rectangulo a const int leftA = a.x, rightA = a.x + a.w, topA = a.y, bottomA = a.y + a.h;
const int leftA = a.x; const int leftB = b.x, rightB = b.x + b.w, topB = b.y, bottomB = b.y + b.h;
const int rightA = a.x + a.w;
const int topA = a.y;
const int bottomA = a.y + a.h;
// Calcula las caras del rectangulo b
const int leftB = b.x;
const int rightB = b.x + b.w;
const int topB = b.y;
const int bottomB = b.y + b.h;
// Si cualquiera de las caras de a está fuera de b
if (bottomA <= topB) if (bottomA <= topB)
{
return false; return false;
}
if (topA >= bottomB) if (topA >= bottomB)
{
return false; return false;
}
if (rightA <= leftB) if (rightA <= leftB)
{
return false; return false;
}
if (leftA >= rightB) if (leftA >= rightB)
{
return false; return false;
}
// Si ninguna de las caras está fuera de b
return true; return true;
} }
// Detector de colisiones entre un punto y un rectangulo // Detector de colisiones entre un punto y un rectangulo
bool checkCollision(SDL_Point &p, SDL_Rect &r) bool checkCollision(const SDL_Point &p, const SDL_Rect &r)
{ {
// Comprueba si el punto está a la izquierda del rectangulo if (p.x < r.x || p.x > r.x + r.w)
if (p.x < r.x)
{
return false; return false;
} if (p.y < r.y || p.y > r.y + r.h)
// Comprueba si el punto está a la derecha del rectangulo
if (p.x > r.x + r.w)
{
return false; return false;
}
// Comprueba si el punto está por encima del rectangulo
if (p.y < r.y)
{
return false;
}
// Comprueba si el punto está por debajo del rectangulo
if (p.y > r.y + r.h)
{
return false;
}
// Si no está fuera, es que está dentro
return true; return true;
} }
// Convierte una cadena en un valor booleano // Convierte una cadena en un valor booleano
bool stringToBool(std::string str) bool stringToBool(const std::string &str)
{ {
return str == "true" ? true : false; return str == "true";
} }
// Convierte un valor booleano en una cadena // Convierte un valor booleano en una cadena
std::string boolToString(bool value) std::string boolToString(bool value)
{ {
return value == true ? "true" : "false"; return value ? "true" : "false";
} }
// Convierte un valor booleano en una cadena "on" o "off" // Convierte un valor booleano en una cadena "on" o "off"
std::string boolToOnOff(bool value) std::string boolToOnOff(bool value)
{ {
return value == true ? "on" : "off"; return value ? "on" : "off";
} }
// Convierte una cadena a minusculas // Convierte una cadena a minusculas
std::string toLower(std::string str) std::string toLower(const std::string &str)
{ {
const char *original = str.c_str(); std::string result = str;
char *lower = (char *)malloc(str.size() + 1); std::transform(result.begin(), result.end(), result.begin(),
for (int i = 0; i < (int)str.size(); ++i) [](unsigned char c)
{ { return std::tolower(c); });
char c = original[i]; return result;
lower[i] = (c >= 65 && c <= 90) ? c + 32 : c;
}
lower[str.size()] = 0;
std::string nova(lower);
free(lower);
return nova;
} }
// Obtiene el fichero de sonido a partir de un nombre // Obtiene el fichero de sonido a partir de un nombre
JA_Sound_t *getSound(std::vector<SoundFile> sounds, std::string name) JA_Sound_t *getSound(const std::vector<SoundFile> &sounds, const std::string &name)
{ {
for (auto s : sounds) for (const auto &s : sounds)
{ {
if (s.name == name) if (s.name == name)
{ {
return s.file; return s.file;
} }
} }
return nullptr; return nullptr;
} }
// Obtiene el fichero de música a partir de un nombre // Obtiene el fichero de música a partir de un nombre
JA_Music_t *getMusic(std::vector<MusicFile> music, std::string name) JA_Music_t *getMusic(const std::vector<MusicFile> &music, const std::string &name)
{ {
for (auto m : music) for (const auto &m : music)
{ {
if (m.name == name) if (m.name == name)
{ {
return m.file; return m.file;
} }
} }
return nullptr; return nullptr;
} }
// Ordena las entradas de la tabla de records // Ordena las entradas de la tabla de records
HiScoreEntry sortHiScoreTable(HiScoreEntry entry1, HiScoreEntry entry2) HiScoreEntry sortHiScoreTable(const HiScoreEntry &entry1, const HiScoreEntry &entry2)
{ {
if (entry1.score > entry2.score) return (entry1.score > entry2.score) ? entry1 : entry2;
{
return entry1;
}
return entry2;
} }
// Dibuja un circulo // Dibuja un circulo
@@ -275,41 +176,31 @@ void DrawCircle(SDL_Renderer *renderer, int32_t centerX, int32_t centerY, int32_
} }
// Aclara el color // Aclara el color
Color lightenColor(Color color, int amount) Color lightenColor(const Color &color, int amount)
{ {
Color newColor; Color newColor;
newColor.r = std::min(255, (int)color.r + amount); newColor.r = std::min(255, color.r + amount);
newColor.g = std::min(255, (int)color.g + amount); newColor.g = std::min(255, color.g + amount);
newColor.b = std::min(255, (int)color.b + amount); newColor.b = std::min(255, color.b + amount);
return newColor; return newColor;
} }
// Oscurece el color // Oscurece el color
Color DarkenColor(Color color, int amount) Color DarkenColor(const Color &color, int amount)
{ {
Color newColor; Color newColor;
newColor.r = std::max(0, (int)color.r - amount); newColor.r = std::min(255, color.r - +amount);
newColor.g = std::max(0, (int)color.g - amount); newColor.g = std::min(255, color.g - +amount);
newColor.b = std::max(0, (int)color.b - amount); newColor.b = std::min(255, color.b - +amount);
return newColor; return newColor;
} }
// Quita los espacioes en un string // Quita los espacioes en un string
std::string trim(const std::string &str) std::string trim(const std::string &str)
{ {
auto start = str.begin(); auto start = std::find_if_not(str.begin(), str.end(), ::isspace);
while (start != str.end() && std::isspace(*start)) auto end = std::find_if_not(str.rbegin(), str.rend(), ::isspace).base();
{ return (start < end ? std::string(start, end) : std::string());
start++;
}
auto end = str.end();
do
{
end--;
} while (std::distance(start, end) > 0 && std::isspace(*end));
return std::string(start, end + 1);
} }
// Función de suavizado // Función de suavizado

View File

@@ -3,15 +3,19 @@
#include <SDL2/SDL_gamecontroller.h> // for SDL_GameControllerButton #include <SDL2/SDL_gamecontroller.h> // for SDL_GameControllerButton
#include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point #include <SDL2/SDL_rect.h> // for SDL_Rect, SDL_Point
#include <SDL2/SDL_render.h> // for SDL_Renderer #include <SDL2/SDL_render.h> // for SDL_Renderer
#include <SDL2/SDL_stdinc.h> // for Uint8, Uint32 #include <SDL2/SDL_stdinc.h> // for Uint8
#include <stdint.h> // for int32_t #include <stdint.h> // for int32_t
#include <string> // for string, basic_string #include <string> // for string
#include <vector> // for vector #include <vector> // for vector
#include "input.h" // for inputs_e enum class InputType : int;
struct JA_Music_t; enum class ScreenFilter; // lines 14-14
struct JA_Sound_t; enum class ScreenVideoMode; // lines 15-15
enum class ScreenFilter; namespace lang
enum class ScreenVideoMode; {
enum class Code : int;
}
struct JA_Music_t; // lines 12-12
struct JA_Sound_t; // lines 13-13
// Dificultad del juego // Dificultad del juego
enum class GameDifficulty enum class GameDifficulty
@@ -22,7 +26,7 @@ enum class GameDifficulty
}; };
// Tamaño de bloque // Tamaño de bloque
#define BLOCK 8 constexpr int BLOCK = 8;
// Estructura para definir un circulo // Estructura para definir un circulo
struct Circle struct Circle
@@ -34,6 +38,7 @@ struct Circle
struct Color struct Color
{ {
Uint8 r, g, b; Uint8 r, g, b;
constexpr Color(int red = 255, int green = 255, int blue = 255) : r(red), g(green), b(blue) {}
}; };
// Posiciones de las notificaciones // Posiciones de las notificaciones
@@ -46,13 +51,6 @@ enum class NotifyPosition
RIGHT, RIGHT,
}; };
// Estructura para saber la seccion y subseccion del programa
/*struct Section
{
section::Name name;
section::Options options;
};*/
// Estructura para las entradas de la tabla de recirds // Estructura para las entradas de la tabla de recirds
struct HiScoreEntry struct HiScoreEntry
{ {
@@ -113,7 +111,7 @@ struct OptionsAudio
struct OptionsGame struct OptionsGame
{ {
GameDifficulty difficulty; // Dificultad del juego GameDifficulty difficulty; // Dificultad del juego
Uint8 language; // Idioma usado en el juego lang::Code language; // Idioma usado en el juego
bool autofire; // Indica si el jugador ha de pulsar repetidamente para disparar o basta con mantener pulsado bool autofire; // Indica si el jugador ha de pulsar repetidamente para disparar o basta con mantener pulsado
std::vector<HiScoreEntry> hi_score_table; // Tabla con las mejores puntuaciones std::vector<HiScoreEntry> hi_score_table; // Tabla con las mejores puntuaciones
}; };
@@ -126,7 +124,7 @@ struct OptionsController
Uint8 device_type; // Indica si se utilizará teclado o mando o ambos Uint8 device_type; // Indica si se utilizará teclado o mando o ambos
std::string name; // Nombre del dispositivo std::string name; // Nombre del dispositivo
bool plugged; // Indica si el mando se encuentra conectado bool plugged; // Indica si el mando se encuentra conectado
std::vector<inputs_e> inputs; // Listado de inputs std::vector<InputType> inputs; // Listado de inputs
std::vector<SDL_GameControllerButton> buttons; // Listado de botones asignados a cada input std::vector<SDL_GameControllerButton> buttons; // Listado de botones asignados a cada input
}; };
@@ -234,19 +232,19 @@ struct MusicFile
double distanceSquared(int x1, int y1, int x2, int y2); double distanceSquared(int x1, int y1, int x2, int y2);
// Detector de colisiones entre dos circulos // Detector de colisiones entre dos circulos
bool checkCollision(Circle &a, Circle &b); bool checkCollision(const Circle &a, const Circle &b);
// Detector de colisiones entre un circulo y un rectangulo // Detector de colisiones entre un circulo y un rectangulo
bool checkCollision(Circle &a, SDL_Rect &b); bool checkCollision(const Circle &a, const SDL_Rect &b);
// Detector de colisiones entre un dos rectangulos // Detector de colisiones entre un dos rectangulos
bool checkCollision(SDL_Rect &a, SDL_Rect &b); bool checkCollision(const SDL_Rect &a, const SDL_Rect &b);
// Detector de colisiones entre un punto y un rectangulo // Detector de colisiones entre un punto y un rectangulo
bool checkCollision(SDL_Point &p, SDL_Rect &r); bool checkCollision(const SDL_Point &p, const SDL_Rect &r);
// Convierte una cadena en un valor booleano // Convierte una cadena en un valor booleano
bool stringToBool(std::string str); bool stringToBool(const std::string &str);
// Convierte un valor booleano en una cadena // Convierte un valor booleano en una cadena
std::string boolToString(bool value); std::string boolToString(bool value);
@@ -255,25 +253,25 @@ std::string boolToString(bool value);
std::string boolToOnOff(bool value); std::string boolToOnOff(bool value);
// Convierte una cadena a minusculas // Convierte una cadena a minusculas
std::string toLower(std::string str); std::string toLower(const std::string &str);
// Obtiene el fichero de sonido a partir de un nombre // Obtiene el fichero de sonido a partir de un nombre
JA_Sound_t *getSound(std::vector<SoundFile> sounds, std::string name); JA_Sound_t *getSound(const std::vector<SoundFile> &sounds, const std::string &name);
// Obtiene el fichero de música a partir de un nombre // Obtiene el fichero de música a partir de un nombre
JA_Music_t *getMusic(std::vector<MusicFile> music, std::string name); JA_Music_t *getMusic(const std::vector<MusicFile> &music, const std::string &name);
// Ordena las entradas de la tabla de records // Ordena las entradas de la tabla de records
HiScoreEntry sortHiScoreTable(HiScoreEntry entry1, HiScoreEntry entry2); HiScoreEntry sortHiScoreTable(const HiScoreEntry &entry1, const HiScoreEntry &entry2);
// Dibuja un circulo // Dibuja un circulo
void DrawCircle(SDL_Renderer *renderer, int32_t centerX, int32_t centerY, int32_t radius); void DrawCircle(SDL_Renderer *renderer, int32_t centerX, int32_t centerY, int32_t radius);
// Aclara el color // Aclara el color
Color lightenColor(Color color, int amount); Color lightenColor(const Color &color, int amount);
// Oscurece el color // Oscurece el color
Color DarkenColor(Color color, int amount); Color DarkenColor(const Color &color, int amount);
// Quita los espacioes en un string // Quita los espacioes en un string
std::string trim(const std::string &str); std::string trim(const std::string &str);

View File

@@ -1,23 +1,21 @@
#include "writer.h" #include "writer.h"
#include "text.h" // for Text
// Constructor // Constructor
Writer::Writer(std::shared_ptr<Text> text) Writer::Writer(std::shared_ptr<Text> text)
: text_(text) : text_(text),
{ pos_x_(0),
// Inicializa variables pos_y_(0),
pos_x_ = 0; kerning_(0),
pos_y_ = 0; caption_(std::string()),
kerning_ = 0; speed_(0),
caption_ = ""; writing_counter_(0),
speed_ = 0; index_(0),
writing_counter_ = 0; lenght_(0),
index_ = 0; completed_(false),
lenght_ = 0; enabled_(false),
completed_ = false; enabled_counter_(0),
enabled_ = false; finished_(false) {}
enabled_counter_ = 0;
finished_ = false;
}
// Actualiza el objeto // Actualiza el objeto
void Writer::update() void Writer::update()
@@ -45,7 +43,11 @@ void Writer::update()
else else
{ {
// Completado // Completado
enabled_counter_ > 0 ? enabled_counter_-- : finished_ = true; finished_ = enabled_counter_ <= 0;
if (!finished_)
{
enabled_counter_--;
}
} }
} }
} }
@@ -78,7 +80,7 @@ void Writer::setKerning(int value)
} }
// Establece el valor de la variable // Establece el valor de la variable
void Writer::setCaption(std::string text) void Writer::setCaption(const std::string &text)
{ {
caption_ = text; caption_ = text;
lenght_ = text.length(); lenght_ = text.length();

View File

@@ -1,10 +1,10 @@
#pragma once #pragma once
#include <string> // for string, basic_string #include <memory> // for shared_ptr
#include <memory> #include <string> // for string
#include "text.h" class Text;
// Clase Writer. Pinta texto en pantalla letra a letra a partir de una cadena y un bitmap // Clase Writer. Pinta texto en pantalla letra a letra a partir de una cadena y un objeto Text
class Writer class Writer
{ {
private: private:
@@ -27,7 +27,7 @@ private:
public: public:
// Constructor // Constructor
Writer(std::shared_ptr<Text> text); explicit Writer(std::shared_ptr<Text> text);
// Destructor // Destructor
~Writer() = default; ~Writer() = default;
@@ -48,7 +48,7 @@ public:
void setKerning(int value); void setKerning(int value);
// Establece el valor de la variable // Establece el valor de la variable
void setCaption(std::string text); void setCaption(const std::string &text);
// Establece el valor de la variable // Establece el valor de la variable
void setSpeed(int value); void setSpeed(int value);