clang-format

This commit is contained in:
2026-04-03 10:58:04 +02:00
parent 550a005ca6
commit c25d4dc7e5
50 changed files with 9735 additions and 11503 deletions

View File

@@ -1,12 +1,13 @@
#include "animatedsprite.h"
#include <fstream> // for basic_ostream, operator<<, basic_istream, basic...
#include <iostream> // for cout
#include <sstream> // for basic_stringstream
#include "texture.h" // for Texture
// Carga la animación desde un fichero
animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, bool verbose)
{
animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, bool verbose) {
// Inicializa variables
animatedSprite_t as;
as.texture = texture;
@@ -20,56 +21,45 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
std::string line;
// El fichero se puede abrir
if (file.good())
{
if (file.good()) {
// Procesa el fichero linea a linea
if (verbose)
{
if (verbose) {
std::cout << "Animation loaded: " << filename << std::endl;
}
while (std::getline(file, line))
{
while (std::getline(file, line)) {
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
if (line == "[animation]") {
animation_t buffer;
buffer.counter = 0;
buffer.currentFrame = 0;
buffer.completed = false;
do
{
do {
std::getline(file, line);
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "name")
{
if (pos != (int)line.npos) {
if (line.substr(0, pos) == "name") {
buffer.name = line.substr(pos + 1, line.length());
}
else if (line.substr(0, pos) == "speed")
{
else if (line.substr(0, pos) == "speed") {
buffer.speed = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "loop")
{
else if (line.substr(0, pos) == "loop") {
buffer.loop = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frames")
{
else if (line.substr(0, pos) == "frames") {
// Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length()));
std::string tmp;
SDL_Rect rect = {0, 0, frameWidth, frameHeight};
while (getline(ss, tmp, ','))
{
while (getline(ss, tmp, ',')) {
// Comprueba que el tile no sea mayor que el maximo indice permitido
const int numTile = std::stoi(tmp) > maxTiles ? 0 : std::stoi(tmp);
rect.x = (numTile % framesPerRow) * frameWidth;
@@ -78,8 +68,7 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
}
}
else
{
else {
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
}
}
@@ -90,42 +79,34 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
}
// En caso contrario se parsea el fichero para buscar las variables y los valores
else
{
else {
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "framesPerRow")
{
if (pos != (int)line.npos) {
if (line.substr(0, pos) == "framesPerRow") {
framesPerRow = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frameWidth")
{
else if (line.substr(0, pos) == "frameWidth") {
frameWidth = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frameHeight")
{
else if (line.substr(0, pos) == "frameHeight") {
frameHeight = std::stoi(line.substr(pos + 1, line.length()));
}
else
{
else {
std::cout << "Warning: file " << filename.c_str() << "\n, unknown parameter \"" << line.substr(0, pos).c_str() << "\"" << std::endl;
}
// Normaliza valores
if (framesPerRow == 0 && frameWidth > 0)
{
if (framesPerRow == 0 && frameWidth > 0) {
framesPerRow = texture->getWidth() / frameWidth;
}
if (maxTiles == 0 && frameWidth > 0 && frameHeight > 0)
{
if (maxTiles == 0 && frameWidth > 0 && frameHeight > 0) {
const int w = texture->getWidth() / frameWidth;
const int h = texture->getHeight() / frameHeight;
maxTiles = w * h;
@@ -138,10 +119,8 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
file.close();
}
// El fichero no se puede abrir
else
{
if (verbose)
{
else {
if (verbose) {
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl;
}
}
@@ -150,26 +129,22 @@ animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, b
}
// Constructor
AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, std::string file, std::vector<std::string> *buffer)
{
AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, std::string file, std::vector<std::string> *buffer) {
// Copia los punteros
setTexture(texture);
setRenderer(renderer);
// Carga las animaciones
if (file != "")
{
if (file != "") {
animatedSprite_t as = loadAnimationFromFile(texture, file);
// Copia los datos de las animaciones
for (auto animation : as.animations)
{
for (auto animation : as.animations) {
this->animation.push_back(animation);
}
}
else if (buffer)
{
else if (buffer) {
loadFromVector(buffer);
}
@@ -178,8 +153,7 @@ AnimatedSprite::AnimatedSprite(Texture *texture, SDL_Renderer *renderer, std::st
}
// Constructor
AnimatedSprite::AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animation)
{
AnimatedSprite::AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animation) {
// Copia los punteros
setTexture(animation->texture);
setRenderer(renderer);
@@ -188,32 +162,26 @@ AnimatedSprite::AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animati
currentAnimation = 0;
// Copia los datos de las animaciones
for (auto a : animation->animations)
{
for (auto a : animation->animations) {
this->animation.push_back(a);
}
}
// Destructor
AnimatedSprite::~AnimatedSprite()
{
for (auto &a : animation)
{
AnimatedSprite::~AnimatedSprite() {
for (auto &a : animation) {
a.frames.clear();
}
animation.clear();
}
// Obtiene el indice de la animación a partir del nombre
int AnimatedSprite::getIndex(std::string name)
{
int AnimatedSprite::getIndex(std::string name) {
int index = -1;
for (auto a : animation)
{
for (auto a : animation) {
index++;
if (a.name == name)
{
if (a.name == name) {
return index;
}
}
@@ -224,10 +192,8 @@ int AnimatedSprite::getIndex(std::string name)
}
// Calcula el frame correspondiente a la animación
void AnimatedSprite::animate()
{
if (!enabled || animation[currentAnimation].speed == 0)
{
void AnimatedSprite::animate() {
if (!enabled || animation[currentAnimation].speed == 0) {
return;
}
@@ -236,22 +202,17 @@ void AnimatedSprite::animate()
// Si alcanza el final de la animación, reinicia el contador de la animación
// en función de la variable loop y coloca el nuevo frame
if (animation[currentAnimation].currentFrame >= (int)animation[currentAnimation].frames.size())
{
if (animation[currentAnimation].loop == -1)
{ // Si no hay loop, deja el último frame
if (animation[currentAnimation].currentFrame >= (int)animation[currentAnimation].frames.size()) {
if (animation[currentAnimation].loop == -1) { // Si no hay loop, deja el último frame
animation[currentAnimation].currentFrame = animation[currentAnimation].frames.size();
animation[currentAnimation].completed = true;
}
else
{ // Si hay loop, vuelve al frame indicado
} else { // Si hay loop, vuelve al frame indicado
animation[currentAnimation].counter = 0;
animation[currentAnimation].currentFrame = animation[currentAnimation].loop;
}
}
// En caso contrario
else
{
else {
// Escoge el frame correspondiente de la animación
setSpriteClip(animation[currentAnimation].frames[animation[currentAnimation].currentFrame]);
@@ -261,17 +222,14 @@ void AnimatedSprite::animate()
}
// Obtiene el numero de frames de la animación actual
int AnimatedSprite::getNumFrames()
{
int AnimatedSprite::getNumFrames() {
return (int)animation[currentAnimation].frames.size();
}
// Establece el frame actual de la animación
void AnimatedSprite::setCurrentFrame(int num)
{
void AnimatedSprite::setCurrentFrame(int num) {
// Descarta valores fuera de rango
if (num >= (int)animation[currentAnimation].frames.size())
{
if (num >= (int)animation[currentAnimation].frames.size()) {
num = 0;
}
@@ -284,68 +242,57 @@ void AnimatedSprite::setCurrentFrame(int num)
}
// Establece el valor del contador
void AnimatedSprite::setAnimationCounter(std::string name, int num)
{
void AnimatedSprite::setAnimationCounter(std::string name, int num) {
animation[getIndex(name)].counter = num;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(std::string name, int speed)
{
void AnimatedSprite::setAnimationSpeed(std::string name, int speed) {
animation[getIndex(name)].counter = speed;
}
// Establece la velocidad de una animación
void AnimatedSprite::setAnimationSpeed(int index, int speed)
{
void AnimatedSprite::setAnimationSpeed(int index, int speed) {
animation[index].counter = speed;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(std::string name, int loop)
{
void AnimatedSprite::setAnimationLoop(std::string name, int loop) {
animation[getIndex(name)].loop = loop;
}
// Establece si la animación se reproduce en bucle
void AnimatedSprite::setAnimationLoop(int index, int loop)
{
void AnimatedSprite::setAnimationLoop(int index, int loop) {
animation[index].loop = loop;
}
// Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(std::string name, bool value)
{
void AnimatedSprite::setAnimationCompleted(std::string name, bool value) {
animation[getIndex(name)].completed = value;
}
// OLD - Establece el valor de la variable
void AnimatedSprite::setAnimationCompleted(int index, bool value)
{
void AnimatedSprite::setAnimationCompleted(int index, bool value) {
animation[index].completed = value;
}
// Comprueba si ha terminado la animación
bool AnimatedSprite::animationIsCompleted()
{
bool AnimatedSprite::animationIsCompleted() {
return animation[currentAnimation].completed;
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(std::string name, Uint8 index)
{
SDL_Rect AnimatedSprite::getAnimationClip(std::string name, Uint8 index) {
return animation[getIndex(name)].frames[index];
}
// Devuelve el rectangulo de una animación y frame concreto
SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF)
{
SDL_Rect AnimatedSprite::getAnimationClip(int indexA, Uint8 indexF) {
return animation[indexA].frames[indexF];
}
// Carga la animación desde un vector
bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
{
bool AnimatedSprite::loadFromVector(std::vector<std::string> *source) {
// Inicializa variables
int framesPerRow = 0;
int frameWidth = 0;
@@ -358,21 +305,18 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
// Recorre todo el vector
int index = 0;
while (index < (int)source->size())
{
while (index < (int)source->size()) {
// Lee desde el vector
line = source->at(index);
// Si la linea contiene el texto [animation] se realiza el proceso de carga de una animación
if (line == "[animation]")
{
if (line == "[animation]") {
animation_t buffer;
buffer.counter = 0;
buffer.currentFrame = 0;
buffer.completed = false;
do
{
do {
// Aumenta el indice para leer la siguiente linea
index++;
line = source->at(index);
@@ -381,31 +325,25 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "name")
{
if (pos != (int)line.npos) {
if (line.substr(0, pos) == "name") {
buffer.name = line.substr(pos + 1, line.length());
}
else if (line.substr(0, pos) == "speed")
{
else if (line.substr(0, pos) == "speed") {
buffer.speed = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "loop")
{
else if (line.substr(0, pos) == "loop") {
buffer.loop = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frames")
{
else if (line.substr(0, pos) == "frames") {
// Se introducen los valores separados por comas en un vector
std::stringstream ss(line.substr(pos + 1, line.length()));
std::string tmp;
SDL_Rect rect = {0, 0, frameWidth, frameHeight};
while (getline(ss, tmp, ','))
{
while (getline(ss, tmp, ',')) {
// Comprueba que el tile no sea mayor que el maximo indice permitido
const int numTile = std::stoi(tmp) > maxTiles ? 0 : std::stoi(tmp);
rect.x = (numTile % framesPerRow) * frameWidth;
@@ -414,8 +352,7 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
}
}
else
{
else {
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
success = false;
}
@@ -427,43 +364,35 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
}
// En caso contrario se parsea el fichero para buscar las variables y los valores
else
{
else {
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (pos != (int)line.npos)
{
if (line.substr(0, pos) == "framesPerRow")
{
if (pos != (int)line.npos) {
if (line.substr(0, pos) == "framesPerRow") {
framesPerRow = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frameWidth")
{
else if (line.substr(0, pos) == "frameWidth") {
frameWidth = std::stoi(line.substr(pos + 1, line.length()));
}
else if (line.substr(0, pos) == "frameHeight")
{
else if (line.substr(0, pos) == "frameHeight") {
frameHeight = std::stoi(line.substr(pos + 1, line.length()));
}
else
{
else {
std::cout << "Warning: unknown parameter " << line.substr(0, pos).c_str() << std::endl;
success = false;
}
// Normaliza valores
if (framesPerRow == 0 && frameWidth > 0)
{
if (framesPerRow == 0 && frameWidth > 0) {
framesPerRow = texture->getWidth() / frameWidth;
}
if (maxTiles == 0 && frameWidth > 0 && frameHeight > 0)
{
if (maxTiles == 0 && frameWidth > 0 && frameHeight > 0) {
const int w = texture->getWidth() / frameWidth;
const int h = texture->getHeight() / frameHeight;
maxTiles = w * h;
@@ -482,11 +411,9 @@ bool AnimatedSprite::loadFromVector(std::vector<std::string> *source)
}
// Establece la animacion actual
void AnimatedSprite::setCurrentAnimation(std::string name)
{
void AnimatedSprite::setCurrentAnimation(std::string name) {
const int newAnimation = getIndex(name);
if (currentAnimation != newAnimation)
{
if (currentAnimation != newAnimation) {
currentAnimation = newAnimation;
animation[currentAnimation].currentFrame = 0;
animation[currentAnimation].counter = 0;
@@ -495,11 +422,9 @@ void AnimatedSprite::setCurrentAnimation(std::string name)
}
// Establece la animacion actual
void AnimatedSprite::setCurrentAnimation(int index)
{
void AnimatedSprite::setCurrentAnimation(int index) {
const int newAnimation = index;
if (currentAnimation != newAnimation)
{
if (currentAnimation != newAnimation) {
currentAnimation = newAnimation;
animation[currentAnimation].currentFrame = 0;
animation[currentAnimation].counter = 0;
@@ -508,30 +433,25 @@ void AnimatedSprite::setCurrentAnimation(int index)
}
// Actualiza las variables del objeto
void AnimatedSprite::update()
{
void AnimatedSprite::update() {
animate();
MovingSprite::update();
}
// Establece el rectangulo para un frame de una animación
void AnimatedSprite::setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h)
{
void AnimatedSprite::setAnimationFrames(Uint8 index_animation, Uint8 index_frame, int x, int y, int w, int h) {
animation[index_animation].frames.push_back({x, y, w, h});
}
// OLD - Establece el contador para todas las animaciones
void AnimatedSprite::setAnimationCounter(int value)
{
for (auto &a : animation)
{
void AnimatedSprite::setAnimationCounter(int value) {
for (auto &a : animation) {
a.counter = value;
}
}
// Reinicia la animación
void AnimatedSprite::resetAnimation()
{
void AnimatedSprite::resetAnimation() {
animation[currentAnimation].currentFrame = 0;
animation[currentAnimation].counter = 0;
animation[currentAnimation].completed = false;

View File

@@ -1,13 +1,14 @@
#pragma once
#include <SDL3/SDL.h>
#include <string> // for string, basic_string
#include <vector> // for vector
#include "movingsprite.h" // for MovingSprite
class Texture;
struct animation_t
{
struct animation_t {
std::string name; // Nombre de la animacion
std::vector<SDL_Rect> frames; // Cada uno de los frames que componen la animación
int speed; // Velocidad de la animación
@@ -17,8 +18,7 @@ struct animation_t
int counter; // Contador para las animaciones
};
struct animatedSprite_t
{
struct animatedSprite_t {
std::vector<animation_t> animations; // Vector con las diferentes animaciones
Texture *texture; // Textura con los graficos para el sprite
};
@@ -26,14 +26,13 @@ struct animatedSprite_t
// Carga la animación desde un fichero
animatedSprite_t loadAnimationFromFile(Texture *texture, std::string filePath, bool verbose = false);
class AnimatedSprite : public MovingSprite
{
private:
class AnimatedSprite : public MovingSprite {
private:
// Variables
std::vector<animation_t> animation; // Vector con las diferentes animaciones
int currentAnimation; // Animacion activa
public:
public:
// Constructor
AnimatedSprite(Texture *texture = nullptr, SDL_Renderer *renderer = nullptr, std::string file = "", std::vector<std::string> *buffer = nullptr);
AnimatedSprite(SDL_Renderer *renderer, animatedSprite_t *animation);

View File

@@ -1,19 +1,19 @@
#include "asset.h"
#include <SDL3/SDL.h>
#include <stddef.h> // for size_t
#include <iostream> // for basic_ostream, operator<<, cout, endl
// Constructor
Asset::Asset(std::string executablePath)
{
Asset::Asset(std::string executablePath) {
this->executablePath = executablePath.substr(0, executablePath.find_last_of("\\/"));
longestName = 0;
verbose = true;
}
// Añade un elemento a la lista
void Asset::add(std::string file, enum assetType type, bool required, bool absolute)
{
void Asset::add(std::string file, enum assetType type, bool required, bool absolute) {
item_t temp;
temp.file = absolute ? file : executablePath + file;
temp.type = type;
@@ -25,33 +25,27 @@ void Asset::add(std::string file, enum assetType type, bool required, bool absol
}
// Devuelve el fichero de un elemento de la lista a partir de una cadena
std::string Asset::get(std::string text)
{
for (auto f : fileList)
{
std::string Asset::get(std::string text) {
for (auto f : fileList) {
const size_t lastIndex = f.file.find_last_of("/") + 1;
const std::string file = f.file.substr(lastIndex, std::string::npos);
if (file == text)
{
if (file == text) {
return f.file;
}
}
if (verbose)
{
if (verbose) {
std::cout << "Warning: file " << text.c_str() << " not found" << std::endl;
}
return "";
}
// Comprueba que existen todos los elementos
bool Asset::check()
{
bool Asset::check() {
bool success = true;
if (verbose)
{
if (verbose) {
std::cout << "\n** Checking files" << std::endl;
std::cout << "Executable path is: " << executablePath << std::endl;
@@ -59,31 +53,24 @@ bool Asset::check()
}
// Comprueba la lista de ficheros clasificandolos por tipo
for (int type = 0; type < t_maxAssetType; ++type)
{
for (int type = 0; type < t_maxAssetType; ++type) {
// Comprueba si hay ficheros de ese tipo
bool any = false;
for (auto f : fileList)
{
if ((f.required) && (f.type == type))
{
for (auto f : fileList) {
if ((f.required) && (f.type == type)) {
any = true;
}
}
// Si hay ficheros de ese tipo, comprueba si existen
if (any)
{
if (verbose)
{
if (any) {
if (verbose) {
std::cout << "\n>> " << getTypeName(type).c_str() << " FILES" << std::endl;
}
for (auto f : fileList)
{
if ((f.required) && (f.type == type))
{
for (auto f : fileList) {
if ((f.required) && (f.type == type)) {
success &= checkFile(f.file);
}
}
@@ -91,15 +78,11 @@ bool Asset::check()
}
// Resultado
if (verbose)
{
if (success)
{
if (verbose) {
if (success) {
std::cout << "\n** All files OK.\n"
<< std::endl;
}
else
{
} else {
std::cout << "\n** A file is missing. Exiting.\n"
<< std::endl;
}
@@ -109,8 +92,7 @@ bool Asset::check()
}
// Comprueba que existe un fichero
bool Asset::checkFile(std::string path)
{
bool Asset::checkFile(std::string path) {
bool success = false;
std::string result = "ERROR";
@@ -118,15 +100,13 @@ bool Asset::checkFile(std::string path)
const std::string filename = path.substr(path.find_last_of("\\/") + 1);
SDL_IOStream *file = SDL_IOFromFile(path.c_str(), "rb");
if (file != nullptr)
{
if (file != nullptr) {
result = "OK";
success = true;
SDL_CloseIO(file);
}
if (verbose)
{
if (verbose) {
std::cout.setf(std::ios::left, std::ios::adjustfield);
std::cout << "Checking file: ";
std::cout.width(longestName + 2);
@@ -139,10 +119,8 @@ bool Asset::checkFile(std::string path)
}
// Devuelve el nombre del tipo de recurso
std::string Asset::getTypeName(int type)
{
switch (type)
{
std::string Asset::getTypeName(int type) {
switch (type) {
case t_bitmap:
return "BITMAP";
break;
@@ -186,7 +164,6 @@ std::string Asset::getTypeName(int type)
}
// Establece si ha de mostrar texto por pantalla
void Asset::setVerbose(bool value)
{
void Asset::setVerbose(bool value) {
verbose = value;
}

View File

@@ -3,8 +3,7 @@
#include <string> // for string, basic_string
#include <vector> // for vector
enum assetType
{
enum assetType {
t_bitmap,
t_music,
t_sound,
@@ -18,16 +17,14 @@ enum assetType
};
// Clase Asset
class Asset
{
private:
class Asset {
private:
// Estructura para definir un item
struct item_t
{
struct item_t {
std::string file; // Ruta del fichero desde la raiz del directorio
enum assetType type; // Indica el tipo de recurso
bool required; // Indica si es un fichero que debe de existir
//bool absolute; // Indica si la ruta que se ha proporcionado es una ruta absoluta
// bool absolute; // Indica si la ruta que se ha proporcionado es una ruta absoluta
};
// Variables
@@ -42,7 +39,7 @@ private:
// Devuelve el nombre del tipo de recurso
std::string getTypeName(int type);
public:
public:
// Constructor
Asset(std::string path);

View File

@@ -1,5 +1,7 @@
#include "balloon.h"
#include <math.h> // for abs
#include "animatedsprite.h" // for AnimatedSprite
#include "const.h" // for PLAY_AREA_LEFT, PLAY_AREA_RIGHT, PLAY_AR...
#include "movingsprite.h" // for MovingSprite
@@ -7,15 +9,13 @@
#include "texture.h" // for Texture
// Constructor
Balloon::Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer, Texture *texture, std::vector<std::string> *animation, SDL_Renderer *renderer)
{
Balloon::Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer, Texture *texture, std::vector<std::string> *animation, SDL_Renderer *renderer) {
sprite = new AnimatedSprite(texture, renderer, "", animation);
disable();
enabled = true;
switch (kind)
{
switch (kind) {
case BALLOON_1:
// Alto y ancho del objeto
width = BALLOON_WIDTH_1;
@@ -215,12 +215,9 @@ Balloon::Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 c
// Añade rotación al sprite
sprite->setRotate(false);
sprite->setRotateSpeed(0);
if (velX > 0.0f)
{
if (velX > 0.0f) {
sprite->setRotateAmount(2.0);
}
else
{
} else {
sprite->setRotateAmount(-2.0);
}
@@ -283,14 +280,12 @@ Balloon::Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 c
}
// Destructor
Balloon::~Balloon()
{
Balloon::~Balloon() {
delete sprite;
}
// Centra el globo en la posición X
void Balloon::allignTo(int x)
{
void Balloon::allignTo(int x) {
posX = float(x - (width / 2));
if (posX < PLAY_AREA_LEFT)
@@ -307,14 +302,10 @@ void Balloon::allignTo(int x)
}
// Pinta el globo en la pantalla
void Balloon::render()
{
if ((visible) && (enabled))
{
if (bouncing.enabled)
{
if (kind != POWER_BALL)
{
void Balloon::render() {
if ((visible) && (enabled)) {
if (bouncing.enabled) {
if (kind != POWER_BALL) {
// Aplica desplazamiento para el zoom
sprite->setPosX(getPosX() + bouncing.despX);
sprite->setPosY(getPosY() + bouncing.despY);
@@ -322,27 +313,21 @@ void Balloon::render()
sprite->setPosX(getPosX() - bouncing.despX);
sprite->setPosY(getPosY() - bouncing.despY);
}
}
else if (isBeingCreated())
{
} else if (isBeingCreated()) {
// Aplica alpha blending
sprite->getTexture()->setAlpha(255 - (int)((float)creationCounter * (255.0f / (float)creationCounterIni)));
sprite->render();
if (kind == POWER_BALL)
{
if (kind == POWER_BALL) {
Sprite *sp = new Sprite(sprite->getRect(), sprite->getTexture(), sprite->getRenderer());
sp->setSpriteClip(407, 0, 37, 37);
sp->render();
delete sp;
}
sprite->getTexture()->setAlpha(255);
}
else
{
} else {
sprite->render();
if (kind == POWER_BALL and !popping)
{
if (kind == POWER_BALL and !popping) {
Sprite *sp = new Sprite(sprite->getRect(), sprite->getTexture(), sprite->getRenderer());
sp->setSpriteClip(407, 0, 37, 37);
sp->render();
@@ -353,17 +338,14 @@ void Balloon::render()
}
// Actualiza la posición y estados del globo
void Balloon::move()
{
void Balloon::move() {
// Comprueba si se puede mover
if (!isStopped())
{
if (!isStopped()) {
// Lo mueve a izquierda o derecha
posX += (velX * speed);
// Si queda fuera de pantalla, corregimos su posición y cambiamos su sentido
if ((posX < PLAY_AREA_LEFT) || (posX + width > PLAY_AREA_RIGHT))
{
if ((posX < PLAY_AREA_LEFT) || (posX + width > PLAY_AREA_RIGHT)) {
// Corrige posición
posX -= (velX * speed);
@@ -374,8 +356,7 @@ void Balloon::move()
sprite->switchRotate();
// Activa el efecto de rebote
if (kind != POWER_BALL)
{
if (kind != POWER_BALL) {
bounceStart();
}
}
@@ -384,8 +365,7 @@ void Balloon::move()
posY += (velY * speed);
// Si se sale por arriba
if (posY < PLAY_AREA_TOP)
{
if (posY < PLAY_AREA_TOP) {
// Corrige
posY = PLAY_AREA_TOP;
@@ -393,15 +373,13 @@ void Balloon::move()
velY = -velY;
// Activa el efecto de rebote
if (kind != POWER_BALL)
{
if (kind != POWER_BALL) {
bounceStart();
}
}
// Si el globo se sale por la parte inferior
if (posY + height > PLAY_AREA_BOTTOM)
{
if (posY + height > PLAY_AREA_BOTTOM) {
// Corrige
posY = PLAY_AREA_BOTTOM - height;
@@ -409,8 +387,7 @@ void Balloon::move()
velY = -defaultVelY;
// Activa el efecto de rebote
if (kind != POWER_BALL)
{
if (kind != POWER_BALL) {
bounceStart();
}
}
@@ -428,8 +405,7 @@ void Balloon::move()
travelY += speed;
// Si la distancia acumulada en Y es igual a la velocidad, se aplica la gravedad
if (travelY >= 1.0f)
{
if (travelY >= 1.0f) {
// Quita el excedente
travelY -= 1.0f;
@@ -448,8 +424,7 @@ void Balloon::move()
}
// Deshabilita el globo y pone a cero todos los valores
void Balloon::disable()
{
void Balloon::disable() {
beingCreated = false;
blinking = false;
collider.r = 0;
@@ -484,8 +459,7 @@ void Balloon::disable()
}
// Explosiona el globo
void Balloon::pop()
{
void Balloon::pop() {
setPopping(true);
sprite->disableRotate();
setStop(true);
@@ -495,10 +469,8 @@ void Balloon::pop()
}
// Actualiza al globo a su posicion, animación y controla los contadores
void Balloon::update()
{
if (enabled)
{
void Balloon::update() {
if (enabled) {
sprite->MovingSprite::update();
move();
updateAnimation();
@@ -510,38 +482,31 @@ void Balloon::update()
}
// Actualiza los estados del globo
void Balloon::updateState()
{
void Balloon::updateState() {
// Si está explotando
if (isPopping())
{
if (isPopping()) {
setInvulnerable(true);
setStop(true);
if (sprite->animationIsCompleted())
{
if (sprite->animationIsCompleted()) {
disable();
}
}
// Si se está creando
if (isBeingCreated())
{
if (isBeingCreated()) {
// Actualiza el valor de las variables
setStop(true);
setInvulnerable(true);
// Todavia tiene tiempo en el contador
if (creationCounter > 0)
{
if (creationCounter > 0) {
// Desplaza lentamente el globo hacia abajo y hacia un lado
if (creationCounter % 10 == 0)
{
if (creationCounter % 10 == 0) {
posY++;
posX += velX;
// Comprueba no se salga por los laterales
if ((posX < PLAY_AREA_LEFT) || (posX > (PLAY_AREA_RIGHT - width)))
{
if ((posX < PLAY_AREA_LEFT) || (posX > (PLAY_AREA_RIGHT - width))) {
// Corrige y cambia el sentido de la velocidad
posX -= velX;
velX = -velX;
@@ -558,38 +523,31 @@ void Balloon::updateState()
creationCounter--;
}
// El contador ha llegado a cero
else
{
else {
setBeingCreated(false);
setStop(false);
setVisible(true);
setInvulnerable(false);
if (kind == POWER_BALL)
{
if (kind == POWER_BALL) {
sprite->setRotate(true);
}
}
}
// Solo comprueba el estado detenido cuando no se está creando
else if (isStopped())
{
else if (isStopped()) {
// Si es una powerball deja de rodar
if (kind == POWER_BALL)
{
if (kind == POWER_BALL) {
sprite->setRotate(false);
}
// Reduce el contador
if (stoppedCounter > 0)
{
if (stoppedCounter > 0) {
stoppedCounter--;
}
// Quitarles el estado "detenido" si no estan explosionando
else if (!isPopping())
{
else if (!isPopping()) {
// Si es una powerball vuelve a rodar
if (kind == POWER_BALL)
{
if (kind == POWER_BALL) {
sprite->setRotate(true);
}
@@ -599,33 +557,24 @@ void Balloon::updateState()
}
// Establece la animación correspondiente al estado
void Balloon::updateAnimation()
{
void Balloon::updateAnimation() {
std::string creatingAnimation = "blue";
std::string normalAnimation = "orange";
if (kind == POWER_BALL)
{
if (kind == POWER_BALL) {
creatingAnimation = "powerball";
normalAnimation = "powerball";
}
else if (getClass() == HEXAGON_CLASS)
{
} else if (getClass() == HEXAGON_CLASS) {
creatingAnimation = "red";
normalAnimation = "green";
}
// Establece el frame de animación
if (isPopping())
{
if (isPopping()) {
sprite->setCurrentAnimation("pop");
}
else if (isBeingCreated())
{
} else if (isBeingCreated()) {
sprite->setCurrentAnimation(creatingAnimation);
}
else
{
} else {
sprite->setCurrentAnimation(normalAnimation);
}
@@ -633,75 +582,62 @@ void Balloon::updateAnimation()
}
// Comprueba si el globo está habilitado
bool Balloon::isEnabled()
{
bool Balloon::isEnabled() {
return enabled;
}
// Obtiene del valor de la variable
float Balloon::getPosX()
{
float Balloon::getPosX() {
return posX;
}
// Obtiene del valor de la variable
float Balloon::getPosY()
{
float Balloon::getPosY() {
return posY;
}
// Obtiene del valor de la variable
float Balloon::getVelY()
{
float Balloon::getVelY() {
return velY;
}
// Obtiene del valor de la variable
int Balloon::getWidth()
{
int Balloon::getWidth() {
return width;
}
// Obtiene del valor de la variable
int Balloon::getHeight()
{
int Balloon::getHeight() {
return height;
}
// Establece el valor de la variable
void Balloon::setVelY(float velY)
{
void Balloon::setVelY(float velY) {
this->velY = velY;
}
// Establece el valor de la variable
void Balloon::setSpeed(float speed)
{
void Balloon::setSpeed(float speed) {
this->speed = speed;
}
// Obtiene del valor de la variable
int Balloon::getKind()
{
int Balloon::getKind() {
return kind;
}
// Obtiene del valor de la variable
Uint8 Balloon::getSize()
{
Uint8 Balloon::getSize() {
return size;
}
// Obtiene la clase a la que pertenece el globo
Uint8 Balloon::getClass()
{
if ((kind >= BALLOON_1) && (kind <= BALLOON_4))
{
Uint8 Balloon::getClass() {
if ((kind >= BALLOON_1) && (kind <= BALLOON_4)) {
return BALLOON_CLASS;
}
else if ((kind >= HEXAGON_1) && (kind <= HEXAGON_4))
{
else if ((kind >= HEXAGON_1) && (kind <= HEXAGON_4)) {
return HEXAGON_CLASS;
}
@@ -709,129 +645,106 @@ Uint8 Balloon::getClass()
}
// Establece el valor de la variable
void Balloon::setStop(bool state)
{
void Balloon::setStop(bool state) {
stopped = state;
}
// Obtiene del valor de la variable
bool Balloon::isStopped()
{
bool Balloon::isStopped() {
return stopped;
}
// Establece el valor de la variable
void Balloon::setBlink(bool value)
{
void Balloon::setBlink(bool value) {
blinking = value;
}
// Obtiene del valor de la variable
bool Balloon::isBlinking()
{
bool Balloon::isBlinking() {
return blinking;
}
// Establece el valor de la variable
void Balloon::setVisible(bool value)
{
void Balloon::setVisible(bool value) {
visible = value;
}
// Obtiene del valor de la variable
bool Balloon::isVisible()
{
bool Balloon::isVisible() {
return visible;
}
// Establece el valor de la variable
void Balloon::setInvulnerable(bool value)
{
void Balloon::setInvulnerable(bool value) {
invulnerable = value;
}
// Obtiene del valor de la variable
bool Balloon::isInvulnerable()
{
bool Balloon::isInvulnerable() {
return invulnerable;
}
// Establece el valor de la variable
void Balloon::setBeingCreated(bool value)
{
void Balloon::setBeingCreated(bool value) {
beingCreated = value;
}
// Obtiene del valor de la variable
bool Balloon::isBeingCreated()
{
bool Balloon::isBeingCreated() {
return beingCreated;
}
// Establece el valor de la variable
void Balloon::setPopping(bool value)
{
void Balloon::setPopping(bool value) {
popping = value;
}
// Obtiene del valor de la variable
bool Balloon::isPopping()
{
bool Balloon::isPopping() {
return popping;
}
// Establece el valor de la variable
void Balloon::setStoppedTimer(Uint16 time)
{
void Balloon::setStoppedTimer(Uint16 time) {
stoppedCounter = time;
}
// Obtiene del valor de la variable
Uint16 Balloon::getStoppedTimer()
{
Uint16 Balloon::getStoppedTimer() {
return stoppedCounter;
}
// Obtiene del valor de la variable
Uint16 Balloon::getScore()
{
Uint16 Balloon::getScore() {
return score;
}
// Obtiene el circulo de colisión
circle_t &Balloon::getCollider()
{
circle_t &Balloon::getCollider() {
return collider;
}
// Alinea el circulo de colisión con la posición del objeto globo
void Balloon::updateColliders()
{
void Balloon::updateColliders() {
collider.x = Uint16(posX + collider.r);
collider.y = posY + collider.r;
}
// Obtiene le valor de la variable
Uint8 Balloon::getMenace()
{
if (isEnabled())
{
Uint8 Balloon::getMenace() {
if (isEnabled()) {
return menace;
}
else
{
} else {
return 0;
}
}
// Obtiene le valor de la variable
Uint8 Balloon::getPower()
{
Uint8 Balloon::getPower() {
return power;
}
void Balloon::bounceStart()
{
void Balloon::bounceStart() {
bouncing.enabled = true;
bouncing.zoomW = 1;
bouncing.zoomH = 1;
@@ -841,8 +754,7 @@ void Balloon::bounceStart()
bouncing.despY = 0;
}
void Balloon::bounceStop()
{
void Balloon::bounceStop() {
bouncing.enabled = false;
bouncing.counter = 0;
bouncing.zoomW = 1.0f;
@@ -853,10 +765,8 @@ void Balloon::bounceStop()
bouncing.despY = 0.0f;
}
void Balloon::updateBounce()
{
if (bouncing.enabled)
{
void Balloon::updateBounce() {
if (bouncing.enabled) {
bouncing.zoomW = bouncing.w[bouncing.counter / bouncing.speed];
bouncing.zoomH = bouncing.h[bouncing.counter / bouncing.speed];
sprite->setZoomW(bouncing.zoomW);
@@ -864,8 +774,7 @@ void Balloon::updateBounce()
bouncing.despX = (sprite->getSpriteClip().w - (sprite->getSpriteClip().w * bouncing.zoomW));
bouncing.despY = (sprite->getSpriteClip().h - (sprite->getSpriteClip().h * bouncing.zoomH));
bouncing.counter++;
if ((bouncing.counter / bouncing.speed) > (MAX_BOUNCE - 1))
{
if ((bouncing.counter / bouncing.speed) > (MAX_BOUNCE - 1)) {
bounceStop();
}
}

View File

@@ -1,8 +1,10 @@
#pragma once
#include <SDL3/SDL.h>
#include <string> // for string
#include <vector> // for vector
#include "utils.h" // for circle_t
class AnimatedSprite;
class Texture;
@@ -67,12 +69,10 @@ constexpr int POWERBALL_SCREENPOWER_MINIMUM = 10;
constexpr int POWERBALL_COUNTER = 8;
// Clase Balloon
class Balloon
{
private:
class Balloon {
private:
// Estructura para las variables para el efecto de los rebotes
struct bouncing
{
struct bouncing {
bool enabled; // Si el efecto está activo
Uint8 counter; // Countador para el efecto
Uint8 speed; // Velocidad a la que transcurre el efecto
@@ -139,7 +139,7 @@ private:
// Establece el valor de la variable
void setBeingCreated(bool value);
public:
public:
// Constructor
Balloon(float x, float y, Uint8 kind, float velx, float speed, Uint16 creationtimer, Texture *texture, std::vector<std::string> *animation, SDL_Renderer *renderer);

View File

@@ -1,11 +1,11 @@
#include "bullet.h"
#include "const.h" // for NO_KIND, PLAY_AREA_LEFT, PLAY_AREA_RIGHT, PLAY_A...
#include "sprite.h" // for Sprite
class Texture;
// Constructor
Bullet::Bullet(int x, int y, int kind, bool poweredUp, int owner, Texture *texture, SDL_Renderer *renderer)
{
Bullet::Bullet(int x, int y, int kind, bool poweredUp, int owner, Texture *texture, SDL_Renderer *renderer) {
sprite = new Sprite({x, y, 10, 10}, texture, renderer);
// Posición inicial del objeto
@@ -26,19 +26,15 @@ Bullet::Bullet(int x, int y, int kind, bool poweredUp, int owner, Texture *textu
this->owner = owner;
// Valores especificos según el tipo
switch (kind)
{
switch (kind) {
case BULLET_UP:
// Establece la velocidad inicial
velX = 0;
// Rectangulo con los gráficos del objeto
if (!poweredUp)
{
if (!poweredUp) {
sprite->setSpriteClip(0 * width, 0, sprite->getWidth(), sprite->getHeight());
}
else
{
} else {
sprite->setSpriteClip((0 + 3) * width, 0, sprite->getWidth(), sprite->getHeight());
}
break;
@@ -48,12 +44,9 @@ Bullet::Bullet(int x, int y, int kind, bool poweredUp, int owner, Texture *textu
velX = -2;
// Rectangulo con los gráficos del objeto
if (!poweredUp)
{
if (!poweredUp) {
sprite->setSpriteClip(1 * width, 0, sprite->getWidth(), sprite->getHeight());
}
else
{
} else {
sprite->setSpriteClip((1 + 3) * width, 0, sprite->getWidth(), sprite->getHeight());
}
break;
@@ -63,12 +56,9 @@ Bullet::Bullet(int x, int y, int kind, bool poweredUp, int owner, Texture *textu
velX = 2;
// Rectangulo con los gráficos del objeto
if (!poweredUp)
{
if (!poweredUp) {
sprite->setSpriteClip(2 * width, 0, sprite->getWidth(), sprite->getHeight());
}
else
{
} else {
sprite->setSpriteClip((2 + 3) * width, 0, sprite->getWidth(), sprite->getHeight());
}
break;
@@ -85,20 +75,17 @@ Bullet::Bullet(int x, int y, int kind, bool poweredUp, int owner, Texture *textu
}
// Destructor
Bullet::~Bullet()
{
Bullet::~Bullet() {
delete sprite;
}
// Pinta el objeto en pantalla
void Bullet::render()
{
void Bullet::render() {
sprite->render();
}
// Actualiza la posición y estado del objeto en horizontal
Uint8 Bullet::move()
{
Uint8 Bullet::move() {
// Variable con el valor de retorno
Uint8 msg = BULLET_MOVE_OK;
@@ -106,8 +93,7 @@ Uint8 Bullet::move()
posX += velX;
// Si el objeto se sale del area de juego por los laterales
if ((posX < PLAY_AREA_LEFT - width) || (posX > PLAY_AREA_RIGHT))
{
if ((posX < PLAY_AREA_LEFT - width) || (posX > PLAY_AREA_RIGHT)) {
// Se deshabilita
kind = NO_KIND;
@@ -119,8 +105,7 @@ Uint8 Bullet::move()
posY += int(velY);
// Si el objeto se sale del area de juego por la parte superior
if (posY < PLAY_AREA_TOP - height)
{
if (posY < PLAY_AREA_TOP - height) {
// Se deshabilita
kind = NO_KIND;
@@ -139,75 +124,61 @@ Uint8 Bullet::move()
}
// Comprueba si el objeto está habilitado
bool Bullet::isEnabled()
{
if (kind == NO_KIND)
{
bool Bullet::isEnabled() {
if (kind == NO_KIND) {
return false;
}
else
{
} else {
return true;
}
}
// Deshabilita el objeto
void Bullet::disable()
{
void Bullet::disable() {
kind = NO_KIND;
}
// Obtiene el valor de la variable
int Bullet::getPosX()
{
int Bullet::getPosX() {
return posX;
}
// Obtiene el valor de la variable
int Bullet::getPosY()
{
int Bullet::getPosY() {
return posY;
}
// Establece el valor de la variable
void Bullet::setPosX(int x)
{
void Bullet::setPosX(int x) {
posX = x;
}
// Establece el valor de la variable
void Bullet::setPosY(int y)
{
void Bullet::setPosY(int y) {
posY = y;
}
// Obtiene el valor de la variable
int Bullet::getVelY()
{
int Bullet::getVelY() {
return velY;
}
// Obtiene el valor de la variable
int Bullet::getKind()
{
int Bullet::getKind() {
return kind;
}
// Obtiene el valor de la variable
int Bullet::getOwner()
{
int Bullet::getOwner() {
return owner;
}
// Obtiene el circulo de colisión
circle_t &Bullet::getCollider()
{
circle_t &Bullet::getCollider() {
return collider;
}
// Alinea el circulo de colisión con el objeto
void Bullet::shiftColliders()
{
void Bullet::shiftColliders() {
collider.x = posX + collider.r;
collider.y = posY + collider.r;
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <SDL3/SDL.h>
#include "utils.h" // for circle_t
class Sprite;
class Texture;
@@ -15,9 +16,8 @@ constexpr int BULLET_MOVE_OK = 0;
constexpr int BULLET_MOVE_OUT = 1;
// Clase Bullet
class Bullet
{
private:
class Bullet {
private:
// Objetos y punteros
Sprite *sprite; // Sprite con los graficos y métodos de pintado
@@ -35,7 +35,7 @@ private:
// Alinea el circulo de colisión con el objeto
void shiftColliders();
public:
public:
// Constructor
Bullet(int x, int y, int kind, bool poweredUp, int owner, Texture *texture, SDL_Renderer *renderer);

View File

@@ -1,8 +1,9 @@
#pragma once
#include <SDL3/SDL.h>
#include "utils.h"
#include "lang.h"
#include "utils.h"
// Tamaño de bloque
constexpr int BLOCK = 8;

View File

@@ -1,16 +1,19 @@
#include "director.h"
#include <SDL3/SDL.h>
#include <errno.h> // for errno, EEXIST, EACCES, ENAMETOO...
#include <stdio.h> // for printf, perror
#include <string.h> // for strcmp
#include <sys/stat.h> // for mkdir, stat, S_IRWXU
#include <unistd.h> // for getuid
#include <cstdlib> // for exit, EXIT_FAILURE, srand
#include <fstream> // for basic_ostream, operator<<, basi...
#include <iostream> // for cout
#include <memory>
#include <string> // for basic_string, operator+, char_t...
#include <vector> // for vector
#include <memory>
#include "asset.h" // for Asset, assetType
#include "const.h" // for SECTION_PROG_LOGO, GAMECANVAS_H...
#include "game.h" // for Game
@@ -29,8 +32,7 @@
#endif
// Constructor
Director::Director(int argc, const char *argv[])
{
Director::Director(int argc, const char *argv[]) {
std::cout << "Game start" << std::endl;
// Inicializa variables
section = new section_t();
@@ -55,8 +57,7 @@ Director::Director(int argc, const char *argv[])
asset->setVerbose(options->console);
// Si falta algún fichero no inicia el programa
if (!setFileList())
{
if (!setFileList()) {
exit(EXIT_FAILURE);
}
@@ -82,8 +83,7 @@ Director::Director(int argc, const char *argv[])
screen = new Screen(window, renderer, asset, options);
}
Director::~Director()
{
Director::~Director() {
saveConfigFile();
delete asset;
@@ -102,8 +102,7 @@ Director::~Director()
}
// Inicializa el objeto input
void Director::initInput()
{
void Director::initInput() {
// Establece si ha de mostrar mensajes
input->setVerbose(options->console);
@@ -150,68 +149,52 @@ void Director::initInput()
}
// Inicializa JailAudio
void Director::initJailAudio()
{
void Director::initJailAudio() {
JA_Init(48000, SDL_AUDIO_S16, 2);
}
// Arranca SDL y crea la ventana
bool Director::initSDL()
{
bool Director::initSDL() {
// Indicador de éxito
bool success = true;
// Inicializa SDL
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD))
{
if (options->console)
{
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMEPAD)) {
if (options->console) {
std::cout << "SDL could not initialize!\nSDL Error: " << SDL_GetError() << std::endl;
}
success = false;
}
else
{
} else {
// Inicia el generador de numeros aleatorios
std::srand(static_cast<unsigned int>(SDL_GetTicks()));
// Crea la ventana
int incW = 0;
int incH = 0;
if (options->borderEnabled)
{
if (options->borderEnabled) {
incW = options->borderWidth * 2;
incH = options->borderHeight * 2;
}
window = SDL_CreateWindow(WINDOW_CAPTION, (options->gameWidth + incW) * options->windowSize, (options->gameHeight + incH) * options->windowSize, 0);
if (window == nullptr)
{
if (options->console)
{
if (window == nullptr) {
if (options->console) {
std::cout << "Window could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
success = false;
}
else
{
} else {
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
// Crea un renderizador para la ventana
renderer = SDL_CreateRenderer(window, NULL);
if (renderer == nullptr)
{
if (options->console)
{
if (renderer == nullptr) {
if (options->console) {
std::cout << "Renderer could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
success = false;
}
else
{
} else {
// Activa vsync si es necesario
if (options->vSync)
{
if (options->vSync) {
SDL_SetRenderVSync(renderer, 1);
}
@@ -227,16 +210,14 @@ bool Director::initSDL()
}
}
if (options->console)
{
if (options->console) {
std::cout << std::endl;
}
return success;
}
// Crea el indice de ficheros
bool Director::setFileList()
{
bool Director::setFileList() {
#ifdef MACOS_BUNDLE
const std::string prefix = "/../Resources";
#else
@@ -366,8 +347,7 @@ bool Director::setFileList()
}
// Inicializa las opciones del programa
void Director::initOptions()
{
void Director::initOptions() {
// Crea el puntero a la estructura de opciones
options = new options_t;
@@ -406,24 +386,20 @@ void Director::initOptions()
}
// Comprueba los parametros del programa
void Director::checkProgramArguments(int argc, const char *argv[])
{
void Director::checkProgramArguments(int argc, const char *argv[]) {
// Establece la ruta del programa
executablePath = argv[0];
// Comprueba el resto de parametros
for (int i = 1; i < argc; ++i)
{
if (strcmp(argv[i], "--console") == 0)
{
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "--console") == 0) {
options->console = true;
}
}
}
// Crea la carpeta del sistema donde guardar datos
void Director::createSystemFolder(const std::string &folder)
{
void Director::createSystemFolder(const std::string &folder) {
#ifdef _WIN32
systemFolder = std::string(getenv("APPDATA")) + "/" + folder;
#elif __APPLE__
@@ -439,8 +415,7 @@ void Director::createSystemFolder(const std::string &folder)
// Intenta crear ".config", per si no existeix
std::string config_base_folder = std::string(homedir) + "/.config";
int ret = mkdir(config_base_folder.c_str(), S_IRWXU);
if (ret == -1 && errno != EEXIST)
{
if (ret == -1 && errno != EEXIST) {
printf("ERROR CREATING CONFIG BASE FOLDER.");
exit(EXIT_FAILURE);
}
@@ -448,8 +423,7 @@ void Director::createSystemFolder(const std::string &folder)
#endif
struct stat st = {0};
if (stat(systemFolder.c_str(), &st) == -1)
{
if (stat(systemFolder.c_str(), &st) == -1) {
errno = 0;
#ifdef _WIN32
int ret = mkdir(systemFolder.c_str());
@@ -457,10 +431,8 @@ void Director::createSystemFolder(const std::string &folder)
int ret = mkdir(systemFolder.c_str(), S_IRWXU);
#endif
if (ret == -1)
{
switch (errno)
{
if (ret == -1) {
switch (errno) {
case EACCES:
printf("the parent directory does not allow write");
exit(EXIT_FAILURE);
@@ -482,8 +454,7 @@ void Director::createSystemFolder(const std::string &folder)
}
// Carga el fichero de configuración
bool Director::loadConfigFile()
{
bool Director::loadConfigFile() {
// Indicador de éxito en la carga
bool success = true;
@@ -493,25 +464,19 @@ bool Director::loadConfigFile()
std::ifstream file(asset->get(filePath));
// Si el fichero se puede abrir
if (file.good())
{
if (file.good()) {
// Procesa el fichero linea a linea
if (options->console)
{
if (options->console) {
std::cout << "Reading file " << filePath << std::endl;
}
while (std::getline(file, line))
{
while (std::getline(file, line)) {
// Comprueba que la linea no sea un comentario
if (line.substr(0, 1) != "#")
{
if (line.substr(0, 1) != "#") {
// Encuentra la posición del caracter '='
int pos = line.find("=");
// Procesa las dos subcadenas
if (!setOptions(options, line.substr(0, pos), line.substr(pos + 1, line.length())))
{
if (options->console)
{
if (!setOptions(options, line.substr(0, pos), line.substr(pos + 1, line.length()))) {
if (options->console) {
std::cout << "Warning: file " << filePath << std::endl;
std::cout << "Unknown parameter " << line.substr(0, pos).c_str() << std::endl;
}
@@ -521,32 +486,27 @@ bool Director::loadConfigFile()
}
// Cierra el fichero
if (options->console)
{
if (options->console) {
std::cout << "Closing file " << filePath << std::endl;
}
file.close();
}
// El fichero no existe
else
{ // Crea el fichero con los valores por defecto
else { // Crea el fichero con los valores por defecto
saveConfigFile();
}
// Normaliza los valores
if (options->videoMode != 0 && options->videoMode != SDL_WINDOW_FULLSCREEN)
{
if (options->videoMode != 0 && options->videoMode != SDL_WINDOW_FULLSCREEN) {
options->videoMode = 0;
}
if (options->windowSize < 1 || options->windowSize > 4)
{
if (options->windowSize < 1 || options->windowSize > 4) {
options->windowSize = 3;
}
if (options->language < 0 || options->language > MAX_LANGUAGES)
{
if (options->language < 0 || options->language > MAX_LANGUAGES) {
options->language = en_UK;
}
@@ -554,48 +514,37 @@ bool Director::loadConfigFile()
}
// Guarda el fichero de configuración
bool Director::saveConfigFile()
{
bool Director::saveConfigFile() {
bool success = true;
// Crea y abre el fichero de texto
std::ofstream file(asset->get("config.txt"));
if (file.good())
{
if (options->console)
{
if (file.good()) {
if (options->console) {
std::cout << asset->get("config.txt") << " open for writing" << std::endl;
}
}
else
{
if (options->console)
{
} else {
if (options->console) {
std::cout << asset->get("config.txt") << " can't be opened" << std::endl;
}
}
// Opciones g´raficas
file << "## VISUAL OPTIONS\n";
if (options->videoMode == 0)
{
if (options->videoMode == 0) {
file << "videoMode=0\n";
}
else if (options->videoMode == SDL_WINDOW_FULLSCREEN)
{
else if (options->videoMode == SDL_WINDOW_FULLSCREEN) {
file << "videoMode=SDL_WINDOW_FULLSCREEN\n";
}
file << "windowSize=" + std::to_string(options->windowSize) + "\n";
if (options->filter == FILTER_NEAREST)
{
if (options->filter == FILTER_NEAREST) {
file << "filter=FILTER_NEAREST\n";
}
else
{
} else {
file << "filter=FILTER_LINEAL\n";
}
@@ -619,38 +568,31 @@ bool Director::saveConfigFile()
return success;
}
void Director::runLogo()
{
void Director::runLogo() {
auto logo = std::make_unique<Logo>(renderer, screen, asset, input, section);
logo->run();
}
void Director::runIntro()
{
void Director::runIntro() {
auto intro = std::make_unique<Intro>(renderer, screen, asset, input, lang, section);
intro->run();
}
void Director::runTitle()
{
void Director::runTitle() {
auto title = std::make_unique<Title>(renderer, screen, input, asset, options, lang, section);
title->run();
}
void Director::runGame()
{
void Director::runGame() {
const int numPlayers = section->subsection == SUBSECTION_GAME_PLAY_1P ? 1 : 2;
auto game = std::make_unique<Game>(numPlayers, 0, renderer, screen, asset, lang, input, false, options, section);
game->run();
}
int Director::run()
{
int Director::run() {
// Bucle principal
while (section->name != SECTION_PROG_QUIT)
{
switch (section->name)
{
while (section->name != SECTION_PROG_QUIT) {
switch (section->name) {
case SECTION_PROG_LOGO:
runLogo();
break;
@@ -673,103 +615,80 @@ int Director::run()
}
// Asigna variables a partir de dos cadenas
bool Director::setOptions(options_t *options, std::string var, std::string value)
{
bool Director::setOptions(options_t *options, std::string var, std::string value) {
// Indicador de éxito en la asignación
bool success = true;
// Opciones de video
if (var == "videoMode")
{
if (value == "SDL_WINDOW_FULLSCREEN" || value == "SDL_WINDOW_FULLSCREEN_DESKTOP")
{
if (var == "videoMode") {
if (value == "SDL_WINDOW_FULLSCREEN" || value == "SDL_WINDOW_FULLSCREEN_DESKTOP") {
options->videoMode = SDL_WINDOW_FULLSCREEN;
}
else
{
} else {
options->videoMode = 0;
}
}
else if (var == "windowSize")
{
else if (var == "windowSize") {
options->windowSize = std::stoi(value);
if ((options->windowSize < 1) || (options->windowSize > 4))
{
if ((options->windowSize < 1) || (options->windowSize > 4)) {
options->windowSize = 3;
}
}
else if (var == "filter")
{
if (value == "FILTER_LINEAL")
{
else if (var == "filter") {
if (value == "FILTER_LINEAL") {
options->filter = FILTER_LINEAL;
}
else
{
} else {
options->filter = FILTER_NEAREST;
}
}
else if (var == "vSync")
{
else if (var == "vSync") {
options->vSync = stringToBool(value);
}
else if (var == "integerScale")
{
else if (var == "integerScale") {
options->integerScale = stringToBool(value);
}
else if (var == "keepAspect")
{
else if (var == "keepAspect") {
options->keepAspect = stringToBool(value);
}
else if (var == "borderEnabled")
{
else if (var == "borderEnabled") {
options->borderEnabled = stringToBool(value);
}
else if (var == "borderWidth")
{
else if (var == "borderWidth") {
options->borderWidth = std::stoi(value);
}
else if (var == "borderHeight")
{
else if (var == "borderHeight") {
options->borderHeight = std::stoi(value);
}
// Opciones varias
else if (var == "language")
{
else if (var == "language") {
options->language = std::stoi(value);
}
else if (var == "difficulty")
{
else if (var == "difficulty") {
options->difficulty = std::stoi(value);
}
else if (var == "input0")
{
else if (var == "input0") {
options->input[0].deviceType = std::stoi(value);
}
else if (var == "input1")
{
else if (var == "input1") {
options->input[1].deviceType = std::stoi(value);
}
// Lineas vacias o que empiezan por comentario
else if (var == "" || var.substr(0, 1) == "#")
{
else if (var == "" || var.substr(0, 1) == "#") {
}
else
{
else {
success = false;
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <SDL3/SDL.h>
#include <string> // for string, basic_string
class Asset;
class Game;
@@ -14,11 +15,10 @@ struct options_t;
struct section_t;
// Textos
constexpr const char* WINDOW_CAPTION = "© 2020 Coffee Crisis — JailDesigner";
constexpr const char *WINDOW_CAPTION = "© 2020 Coffee Crisis — JailDesigner";
class Director
{
private:
class Director {
private:
// Objetos y punteros
SDL_Window *window; // La ventana donde dibujamos
SDL_Renderer *renderer; // El renderizador de la ventana
@@ -75,7 +75,7 @@ private:
// Ejecuta la seccion de juego donde se juega
void runGame();
public:
public:
// Constructor
Director(int argc, const char *argv[]);

View File

@@ -1,35 +1,33 @@
#include "fade.h"
#include <SDL3/SDL.h>
#include <stdlib.h> // for rand
#include <iostream> // for char_traits, basic_ostream, operator<<
#include "const.h" // for GAMECANVAS_HEIGHT, GAMECANVAS_WIDTH
// Constructor
Fade::Fade(SDL_Renderer *renderer)
{
Fade::Fade(SDL_Renderer *renderer) {
mRenderer = renderer;
mBackbuffer = SDL_CreateTexture(mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT);
if (mBackbuffer != nullptr)
{
if (mBackbuffer != nullptr) {
SDL_SetTextureScaleMode(mBackbuffer, SDL_SCALEMODE_NEAREST);
}
if (mBackbuffer == nullptr)
{
if (mBackbuffer == nullptr) {
std::cout << "Error: textTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
// Destructor
Fade::~Fade()
{
Fade::~Fade() {
SDL_DestroyTexture(mBackbuffer);
mBackbuffer = nullptr;
}
// Inicializa las variables
void Fade::init(Uint8 r, Uint8 g, Uint8 b)
{
void Fade::init(Uint8 r, Uint8 g, Uint8 b) {
mFadeType = FADE_CENTER;
mEnabled = false;
mFinished = false;
@@ -40,18 +38,13 @@ void Fade::init(Uint8 r, Uint8 g, Uint8 b)
}
// Pinta una transición en pantalla
void Fade::render()
{
if (mEnabled && !mFinished)
{
switch (mFadeType)
{
case FADE_FULLSCREEN:
{
void Fade::render() {
if (mEnabled && !mFinished) {
switch (mFadeType) {
case FADE_FULLSCREEN: {
SDL_FRect fRect1 = {0, 0, (float)GAMECANVAS_WIDTH, (float)GAMECANVAS_HEIGHT};
for (int i = 0; i < 256; i += 4)
{
for (int i = 0; i < 256; i += 4) {
// Dibujamos sobre el renderizador
SDL_SetRenderTarget(mRenderer, nullptr);
@@ -76,15 +69,13 @@ void Fade::render()
break;
}
case FADE_CENTER:
{
case FADE_CENTER: {
SDL_FRect fR1 = {0, 0, (float)GAMECANVAS_WIDTH, 0};
SDL_FRect fR2 = {0, 0, (float)GAMECANVAS_WIDTH, 0};
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, 64);
for (int i = 0; i < mCounter; i++)
{
for (int i = 0; i < mCounter; i++) {
fR1.h = fR2.h = (float)(i * 4);
fR2.y = (float)(GAMECANVAS_HEIGHT - (i * 4));
@@ -97,12 +88,10 @@ void Fade::render()
break;
}
case FADE_RANDOM_SQUARE:
{
case FADE_RANDOM_SQUARE: {
SDL_FRect fRs = {0, 0, 32, 32};
for (Uint16 i = 0; i < 50; i++)
{
for (Uint16 i = 0; i < 50; i++) {
// Crea un color al azar
mR = 255 * (rand() % 2);
mG = 255 * (rand() % 2);
@@ -134,42 +123,36 @@ void Fade::render()
}
}
if (mFinished)
{
if (mFinished) {
SDL_SetRenderDrawColor(mRenderer, mR, mG, mB, 255);
SDL_RenderClear(mRenderer);
}
}
// Actualiza las variables internas
void Fade::update()
{
void Fade::update() {
if (mEnabled)
mCounter++;
}
// Activa el fade
void Fade::activateFade()
{
void Fade::activateFade() {
mEnabled = true;
mFinished = false;
mCounter = 0;
}
// Comprueba si está activo
bool Fade::isEnabled()
{
bool Fade::isEnabled() {
return mEnabled;
}
// Comprueba si ha terminado la transicion
bool Fade::hasEnded()
{
bool Fade::hasEnded() {
return mFinished;
}
// Establece el tipo de fade
void Fade::setFadeType(Uint8 fadeType)
{
void Fade::setFadeType(Uint8 fadeType) {
mFadeType = fadeType;
}

View File

@@ -8,9 +8,8 @@ constexpr int FADE_CENTER = 1;
constexpr int FADE_RANDOM_SQUARE = 2;
// Clase Fade
class Fade
{
private:
class Fade {
private:
SDL_Renderer *mRenderer; // El renderizador de la ventana
SDL_Texture *mBackbuffer; // Textura para usar como backbuffer
Uint8 mFadeType; // Tipo de fade a realizar
@@ -21,7 +20,7 @@ private:
SDL_Rect mRect1; // Rectangulo usado para crear los efectos de transición
SDL_Rect mRect2; // Rectangulo usado para crear los efectos de transición
public:
public:
// Constructor
Fade(SDL_Renderer *renderer);

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,10 @@
#pragma once
#include <SDL3/SDL.h>
#include <string> // for string, basic_string
#include <vector> // for vector
#include "utils.h" // for demoKeys_t, color_t
class Asset;
class Balloon;
@@ -50,11 +52,9 @@ constexpr int ITEM_COFFEE_MACHINE_ODDS = 4;
constexpr int TIME_STOPPED_COUNTER = 300;
// Clase Game
class Game
{
private:
struct enemyInits_t
{
class Game {
private:
struct enemyInits_t {
int x; // Posición en el eje X donde crear al enemigo
int y; // Posición en el eje Y donde crear al enemigo
float velX; // Velocidad inicial en el eje X
@@ -68,8 +68,7 @@ private:
enemyInits_t init[MAX_NUMBER_OF_ENEMIES_IN_A_FORMATION]; // Vector con todas las inicializaciones de los enemigos de la formación
};
struct enemyPool_t
{
struct enemyPool_t {
enemyFormation_t *set[10]; // Conjunto de formaciones enemigas
};
@@ -83,15 +82,13 @@ private:
Uint8 number; // Numero de fase
};
struct effect_t
{
struct effect_t {
bool flash; // Indica si se ha de pintar la pantalla de blanco
bool shake; // Indica si se ha de agitar la pantalla
Uint8 shakeCounter; // Contador para medir el tiempo que dura el efecto
};
struct helper_t
{
struct helper_t {
bool needCoffee; // Indica si se necesitan cafes
bool needCoffeeMachine; // Indica si se necesita PowerUp
bool needPowerBall; // Indica si se necesita una PowerBall
@@ -104,8 +101,7 @@ private:
int itemCoffeeMachineOdds; // Probabilidad de aparición del objeto
};
struct demo_t
{
struct demo_t {
bool enabled; // Indica si está activo el modo demo
bool recording; // Indica si está activado el modo para grabar la demo
Uint16 counter; // Contador para el modo demo
@@ -514,7 +510,7 @@ private:
// Establece la máxima puntuación desde fichero o desde las puntuaciones online
void setHiScore();
public:
public:
// Constructor
Game(int numPlayers, int currentStage, SDL_Renderer *renderer, Screen *screen, Asset *asset, Lang *lang, Input *input, bool demo, options_t *options, section_t *section);

View File

@@ -1,10 +1,11 @@
#include "input.h"
#include <SDL3/SDL.h>
#include <iostream> // for basic_ostream, operator<<, cout, basi...
// Constructor
Input::Input(std::string file)
{
Input::Input(std::string file) {
// Fichero gamecontrollerdb.txt
dbPath = file;
@@ -24,80 +25,57 @@ Input::Input(std::string file)
}
// Actualiza el estado del objeto
void Input::update()
{
if (disabledUntil == d_keyPressed && !checkAnyInput())
{
void Input::update() {
if (disabledUntil == d_keyPressed && !checkAnyInput()) {
enable();
}
}
// Asigna inputs a teclas
void Input::bindKey(Uint8 input, SDL_Scancode code)
{
void Input::bindKey(Uint8 input, SDL_Scancode code) {
keyBindings[input].scancode = code;
}
// Asigna inputs a botones del mando
void Input::bindGameControllerButton(Uint8 input, SDL_GamepadButton button)
{
void Input::bindGameControllerButton(Uint8 input, SDL_GamepadButton button) {
gameControllerBindings[input].button = button;
}
// Comprueba si un input esta activo
bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
{
if (!enabled)
{
bool Input::checkInput(Uint8 input, bool repeat, int device, int index) {
if (!enabled) {
return false;
}
bool successKeyboard = false;
bool successGameController = false;
if (device == INPUT_USE_ANY)
{
if (device == INPUT_USE_ANY) {
index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
{
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY) {
const bool *keyStates = SDL_GetKeyboardState(nullptr);
if (repeat)
{
if (keyStates[keyBindings[input].scancode])
{
if (repeat) {
if (keyStates[keyBindings[input].scancode]) {
successKeyboard = true;
}
else
{
} else {
successKeyboard = false;
}
}
else
{
if (!keyBindings[input].active)
{
if (keyStates[keyBindings[input].scancode])
{
} else {
if (!keyBindings[input].active) {
if (keyStates[keyBindings[input].scancode]) {
keyBindings[input].active = true;
successKeyboard = true;
}
else
{
} else {
successKeyboard = false;
}
}
else
{
if (!keyStates[keyBindings[input].scancode])
{
} else {
if (!keyStates[keyBindings[input].scancode]) {
keyBindings[input].active = false;
successKeyboard = false;
}
else
{
} else {
successKeyboard = false;
}
}
@@ -105,42 +83,26 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
}
if (gameControllerFound())
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY))
{
if (repeat)
{
if (SDL_GetGamepadButton(connectedControllers[index], gameControllerBindings[input].button))
{
if ((device == INPUT_USE_GAMECONTROLLER) || (device == INPUT_USE_ANY)) {
if (repeat) {
if (SDL_GetGamepadButton(connectedControllers[index], gameControllerBindings[input].button)) {
successGameController = true;
}
else
{
} else {
successGameController = false;
}
}
else
{
if (!gameControllerBindings[input].active)
{
if (SDL_GetGamepadButton(connectedControllers[index], gameControllerBindings[input].button))
{
} else {
if (!gameControllerBindings[input].active) {
if (SDL_GetGamepadButton(connectedControllers[index], gameControllerBindings[input].button)) {
gameControllerBindings[input].active = true;
successGameController = true;
}
else
{
} else {
successGameController = false;
}
}
else
{
if (!SDL_GetGamepadButton(connectedControllers[index], gameControllerBindings[input].button))
{
} else {
if (!SDL_GetGamepadButton(connectedControllers[index], gameControllerBindings[input].button)) {
gameControllerBindings[input].active = false;
successGameController = false;
}
else
{
} else {
successGameController = false;
}
}
@@ -151,34 +113,25 @@ bool Input::checkInput(Uint8 input, bool repeat, int device, int index)
}
// Comprueba si hay almenos un input activo
bool Input::checkAnyInput(int device, int index)
{
if (device == INPUT_USE_ANY)
{
bool Input::checkAnyInput(int device, int index) {
if (device == INPUT_USE_ANY) {
index = 0;
}
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY)
{
if (device == INPUT_USE_KEYBOARD || device == INPUT_USE_ANY) {
const bool *mKeystates = SDL_GetKeyboardState(nullptr);
for (int i = 0; i < (int)keyBindings.size(); ++i)
{
if (mKeystates[keyBindings[i].scancode])
{
for (int i = 0; i < (int)keyBindings.size(); ++i) {
if (mKeystates[keyBindings[i].scancode]) {
return true;
}
}
}
if (gameControllerFound())
{
if (device == INPUT_USE_GAMECONTROLLER || device == INPUT_USE_ANY)
{
for (int i = 0; i < (int)gameControllerBindings.size(); ++i)
{
if (SDL_GetGamepadButton(connectedControllers[index], gameControllerBindings[i].button))
{
if (gameControllerFound()) {
if (device == INPUT_USE_GAMECONTROLLER || device == INPUT_USE_ANY) {
for (int i = 0; i < (int)gameControllerBindings.size(); ++i) {
if (SDL_GetGamepadButton(connectedControllers[index], gameControllerBindings[i].button)) {
return true;
}
}
@@ -189,19 +142,15 @@ bool Input::checkAnyInput(int device, int index)
}
// Busca si hay un mando conectado
bool Input::discoverGameController()
{
bool Input::discoverGameController() {
bool found = false;
if (SDL_WasInit(SDL_INIT_GAMEPAD) != SDL_INIT_GAMEPAD)
{
if (SDL_WasInit(SDL_INIT_GAMEPAD) != SDL_INIT_GAMEPAD) {
SDL_InitSubSystem(SDL_INIT_GAMEPAD);
}
if (SDL_AddGamepadMappingsFromFile(dbPath.c_str()) < 0)
{
if (verbose)
{
if (SDL_AddGamepadMappingsFromFile(dbPath.c_str()) < 0) {
if (verbose) {
std::cout << "Error, could not load " << dbPath.c_str() << " file: " << SDL_GetError() << std::endl;
}
}
@@ -210,53 +159,42 @@ bool Input::discoverGameController()
SDL_JoystickID *joysticks = SDL_GetJoysticks(&nJoysticks);
numGamepads = 0;
if (joysticks)
{
if (joysticks) {
// Cuenta el numero de mandos
for (int i = 0; i < nJoysticks; ++i)
{
if (SDL_IsGamepad(joysticks[i]))
{
for (int i = 0; i < nJoysticks; ++i) {
if (SDL_IsGamepad(joysticks[i])) {
numGamepads++;
}
}
if (verbose)
{
if (verbose) {
std::cout << "\nChecking for game controllers...\n";
std::cout << nJoysticks << " joysticks found, " << numGamepads << " are gamepads\n";
}
if (numGamepads > 0)
{
if (numGamepads > 0) {
found = true;
int padIndex = 0;
for (int i = 0; i < nJoysticks; i++)
{
for (int i = 0; i < nJoysticks; i++) {
if (!SDL_IsGamepad(joysticks[i])) continue;
// Abre el mando y lo añade a la lista
SDL_Gamepad *pad = SDL_OpenGamepad(joysticks[i]);
if (pad != nullptr)
{
if (pad != nullptr) {
connectedControllers.push_back(pad);
const std::string separator(" #");
const char *padName = SDL_GetGamepadName(pad);
std::string name = padName ? padName : "Unknown";
name.resize(25);
name = name + separator + std::to_string(padIndex);
if (verbose)
{
if (verbose) {
std::cout << name << std::endl;
}
controllerNames.push_back(name);
padIndex++;
}
else
{
if (verbose)
{
} else {
if (verbose) {
std::cout << "SDL_GetError() = " << SDL_GetError() << std::endl;
}
}
@@ -272,53 +210,41 @@ bool Input::discoverGameController()
}
// Comprueba si hay algun mando conectado
bool Input::gameControllerFound()
{
if (numGamepads > 0)
{
bool Input::gameControllerFound() {
if (numGamepads > 0) {
return true;
}
else
{
} else {
return false;
}
}
// Obten el nombre de un mando de juego
std::string Input::getControllerName(int index)
{
if (numGamepads > 0)
{
std::string Input::getControllerName(int index) {
if (numGamepads > 0) {
return controllerNames[index];
}
else
{
} else {
return "";
}
}
// Obten el numero de mandos conectados
int Input::getNumControllers()
{
int Input::getNumControllers() {
return numGamepads;
}
// Establece si ha de mostrar mensajes
void Input::setVerbose(bool value)
{
void Input::setVerbose(bool value) {
verbose = value;
}
// Deshabilita las entradas durante un periodo de tiempo
void Input::disableUntil(i_disable_e value)
{
void Input::disableUntil(i_disable_e value) {
disabledUntil = value;
enabled = false;
}
// Hablita las entradas
void Input::enable()
{
void Input::enable() {
enabled = true;
disabledUntil = d_notDisabled;
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <SDL3/SDL.h>
#include <string> // for string, basic_string
#include <vector> // for vector
@@ -13,8 +14,7 @@ constexpr int INPUT_USE_KEYBOARD = 0;
constexpr int INPUT_USE_GAMECONTROLLER = 1;
constexpr int INPUT_USE_ANY = 2;
enum inputs_e
{
enum inputs_e {
// Inputs obligatorios
input_null,
input_up,
@@ -38,24 +38,20 @@ enum inputs_e
input_number_of_inputs
};
enum i_disable_e
{
enum i_disable_e {
d_notDisabled,
d_forever,
d_keyPressed
};
class Input
{
private:
struct keyBindings_t
{
class Input {
private:
struct keyBindings_t {
Uint8 scancode; // Scancode asociado
bool active; // Indica si está activo
};
struct GameControllerBindings_t
{
struct GameControllerBindings_t {
SDL_GamepadButton button; // GameControllerButton asociado
bool active; // Indica si está activo
};
@@ -73,7 +69,7 @@ private:
i_disable_e disabledUntil; // Tiempo que esta deshabilitado
bool enabled; // Indica si está habilitado
public:
public:
// Constructor
Input(std::string file);

View File

@@ -1,8 +1,11 @@
#include "instructions.h"
#include <SDL3/SDL.h>
#include <algorithm> // for max
#include <iostream> // for char_traits, basic_ostream, operator<<
#include <string> // for basic_string
#include "asset.h" // for Asset
#include "const.h" // for shdwTxtColor, GAMECANVAS_CENTER_X, GAME...
#include "input.h" // for Input, REPEAT_FALSE, inputs_e
@@ -17,8 +20,7 @@
const Uint8 SELF = 0;
// Constructor
Instructions::Instructions(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, Lang *lang, section_t *section)
{
Instructions::Instructions(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, Lang *lang, section_t *section) {
// Copia los punteros
this->renderer = renderer;
this->screen = screen;
@@ -53,12 +55,9 @@ Instructions::Instructions(SDL_Renderer *renderer, Screen *screen, Asset *asset,
// Crea un backbuffer para el renderizador
backbuffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT);
if (backbuffer != nullptr)
{
if (backbuffer != nullptr) {
SDL_SetTextureScaleMode(backbuffer, Texture::currentScaleMode);
}
else
{
} else {
std::cout << "Error: textTexture could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
@@ -72,10 +71,8 @@ Instructions::Instructions(SDL_Renderer *renderer, Screen *screen, Asset *asset,
}
// Destructor
Instructions::~Instructions()
{
for (auto texture : itemTextures)
{
Instructions::~Instructions() {
for (auto texture : itemTextures) {
texture->unload();
delete texture;
}
@@ -89,33 +86,26 @@ Instructions::~Instructions()
}
// Actualiza las variables
void Instructions::update()
{
void Instructions::update() {
// Comprueba las entradas
checkInput();
// Actualiza las variables
if (SDL_GetTicks() - ticks > ticksSpeed)
{
if (SDL_GetTicks() - ticks > ticksSpeed) {
// Actualiza el contador de ticks
ticks = SDL_GetTicks();
if (mode == m_auto)
{ // Modo automático
if (mode == m_auto) { // Modo automático
counter++;
if (counter == counterEnd)
{
if (counter == counterEnd) {
section->name = SECTION_PROG_TITLE;
section->subsection = SUBSECTION_TITLE_1;
}
}
else
{ // Modo manual
} else { // Modo manual
++counter %= 60000;
if (manualQuit)
{
if (manualQuit) {
section->name = SECTION_PROG_TITLE;
section->subsection = SUBSECTION_TITLE_3;
}
@@ -124,8 +114,7 @@ void Instructions::update()
}
// Pinta en pantalla
void Instructions::render()
{
void Instructions::render() {
// Pinta en pantalla
SDL_Rect window = {0, 0, GAMECANVAS_WIDTH, GAMECANVAS_HEIGHT};
SDL_Rect srcRect = {0, 0, 16, 16};
@@ -157,8 +146,7 @@ void Instructions::render()
text->writeShadowed(84, 140, lang->getText(20), shdwTxtColor);
text->writeShadowed(84, 156, lang->getText(21), shdwTxtColor);
if ((mode == m_manual) && (counter % 50 > 14))
{
if ((mode == m_manual) && (counter % 50 > 14)) {
text->writeDX(TXT_CENTER | TXT_COLOR | TXT_SHADOW, GAMECANVAS_CENTER_X, GAMECANVAS_HEIGHT - 12, lang->getText(22), 1, orangeColor, 1, shdwTxtColor);
}
@@ -207,12 +195,9 @@ void Instructions::render()
screen->clean(bgColor);
// Establece la ventana del backbuffer
if (mode == m_auto)
{
if (mode == m_auto) {
window.y = std::max(8, GAMECANVAS_HEIGHT - counter + 100);
}
else
{
} else {
window.y = 0;
}
@@ -225,14 +210,11 @@ void Instructions::render()
}
// Comprueba los eventos
void Instructions::checkEvents()
{
void Instructions::checkEvents() {
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(eventHandler) != 0)
{
while (SDL_PollEvent(eventHandler) != 0) {
// Evento de salida de la aplicación
if (eventHandler->type == SDL_EVENT_QUIT)
{
if (eventHandler->type == SDL_EVENT_QUIT) {
section->name = SECTION_PROG_QUIT;
break;
}
@@ -240,40 +222,30 @@ void Instructions::checkEvents()
}
// Comprueba las entradas
void Instructions::checkInput()
{
if (input->checkInput(input_exit, REPEAT_FALSE))
{
void Instructions::checkInput() {
if (input->checkInput(input_exit, REPEAT_FALSE)) {
section->name = SECTION_PROG_QUIT;
}
else if (input->checkInput(input_window_fullscreen, REPEAT_FALSE))
{
else if (input->checkInput(input_window_fullscreen, REPEAT_FALSE)) {
screen->switchVideoMode();
}
else if (input->checkInput(input_window_dec_size, REPEAT_FALSE))
{
else if (input->checkInput(input_window_dec_size, REPEAT_FALSE)) {
screen->decWindowSize();
}
else if (input->checkInput(input_window_inc_size, REPEAT_FALSE))
{
else if (input->checkInput(input_window_inc_size, REPEAT_FALSE)) {
screen->incWindowSize();
}
else if (input->checkInput(input_pause, REPEAT_FALSE) || input->checkInput(input_accept, REPEAT_FALSE) || input->checkInput(input_fire_left, REPEAT_FALSE) || input->checkInput(input_fire_center, REPEAT_FALSE) || input->checkInput(input_fire_right, REPEAT_FALSE))
{
if (mode == m_auto)
{
else if (input->checkInput(input_pause, REPEAT_FALSE) || input->checkInput(input_accept, REPEAT_FALSE) || input->checkInput(input_fire_left, REPEAT_FALSE) || input->checkInput(input_fire_center, REPEAT_FALSE) || input->checkInput(input_fire_right, REPEAT_FALSE)) {
if (mode == m_auto) {
JA_StopMusic();
section->name = SECTION_PROG_TITLE;
section->subsection = SUBSECTION_TITLE_1;
}
else
{
if (counter > 30)
{
} else {
if (counter > 30) {
manualQuit = true;
}
}
@@ -281,12 +253,10 @@ void Instructions::checkInput()
}
// Bucle para la pantalla de instrucciones
void Instructions::run(mode_e mode)
{
void Instructions::run(mode_e mode) {
this->mode = mode;
while (section->name == SELF)
{
while (section->name == SELF) {
update();
checkEvents();
render();

View File

@@ -1,6 +1,7 @@
#pragma once
#include <SDL3/SDL.h>
#include <vector> // for vector
class Asset;
class Input;
@@ -11,16 +12,14 @@ class Text;
class Texture;
struct section_t;
enum mode_e
{
enum mode_e {
m_manual,
m_auto
};
// Clase Instructions
class Instructions
{
private:
class Instructions {
private:
// Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana
Screen *screen; // Objeto encargado de dibujar en pantalla
@@ -54,7 +53,7 @@ private:
// Comprueba las entradas
void checkInput();
public:
public:
// Constructor
Instructions(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, Lang *lang, section_t *section);

View File

@@ -1,6 +1,9 @@
#include "intro.h"
#include <SDL3/SDL.h>
#include <string> // for basic_string
#include "asset.h" // for Asset
#include "const.h" // for GAMECANVAS_CENTER_X, GAMECANVAS_FIRST_QU...
#include "input.h" // for Input, REPEAT_FALSE, inputs_e
@@ -14,8 +17,7 @@
#include "writer.h" // for Writer
// Constructor
Intro::Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, Lang *lang, section_t *section)
{
Intro::Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, Lang *lang, section_t *section) {
// Copia los punteros
this->renderer = renderer;
this->screen = screen;
@@ -41,8 +43,7 @@ Intro::Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input,
// Inicializa los bitmaps de la intro
const int totalBitmaps = 6;
for (int i = 0; i < totalBitmaps; ++i)
{
for (int i = 0; i < totalBitmaps; ++i) {
SmartSprite *ss = new SmartSprite(texture, renderer);
ss->setWidth(128);
ss->setHeight(96);
@@ -103,8 +104,7 @@ Intro::Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input,
// Inicializa los textos de la intro
const int totalTexts = 9;
for (int i = 0; i < totalTexts; ++i)
{
for (int i = 0; i < totalTexts; ++i) {
Writer *w = new Writer(text);
w->setPosX(BLOCK * 0);
w->setPosY(GAMECANVAS_HEIGHT - (BLOCK * 6));
@@ -150,27 +150,23 @@ Intro::Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input,
texts[8]->setCaption(lang->getText(35));
texts[8]->setSpeed(16);
for (auto text : texts)
{
for (auto text : texts) {
text->center(GAMECANVAS_CENTER_X);
}
}
// Destructor
Intro::~Intro()
{
Intro::~Intro() {
delete eventHandler;
texture->unload();
delete texture;
for (auto bitmap : bitmaps)
{
for (auto bitmap : bitmaps) {
delete bitmap;
}
for (auto text : texts)
{
for (auto text : texts) {
delete text;
}
@@ -178,8 +174,7 @@ Intro::~Intro()
}
// Carga los recursos
bool Intro::loadMedia()
{
bool Intro::loadMedia() {
// Musicas
music = JA_LoadMusic(asset->get("intro.ogg").c_str());
@@ -187,14 +182,11 @@ bool Intro::loadMedia()
}
// Comprueba los eventos
void Intro::checkEvents()
{
void Intro::checkEvents() {
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(eventHandler) != 0)
{
while (SDL_PollEvent(eventHandler) != 0) {
// Evento de salida de la aplicación
if (eventHandler->type == SDL_EVENT_QUIT)
{
if (eventHandler->type == SDL_EVENT_QUIT) {
section->name = SECTION_PROG_QUIT;
break;
}
@@ -202,30 +194,24 @@ void Intro::checkEvents()
}
// Comprueba las entradas
void Intro::checkInput()
{
if (input->checkInput(input_exit, REPEAT_FALSE))
{
void Intro::checkInput() {
if (input->checkInput(input_exit, REPEAT_FALSE)) {
section->name = SECTION_PROG_QUIT;
}
else if (input->checkInput(input_window_fullscreen, REPEAT_FALSE))
{
else if (input->checkInput(input_window_fullscreen, REPEAT_FALSE)) {
screen->switchVideoMode();
}
else if (input->checkInput(input_window_dec_size, REPEAT_FALSE))
{
else if (input->checkInput(input_window_dec_size, REPEAT_FALSE)) {
screen->decWindowSize();
}
else if (input->checkInput(input_window_inc_size, REPEAT_FALSE))
{
else if (input->checkInput(input_window_inc_size, REPEAT_FALSE)) {
screen->incWindowSize();
}
else if (input->checkInput(input_pause, REPEAT_FALSE) || input->checkInput(input_accept, REPEAT_FALSE) || input->checkInput(input_fire_left, REPEAT_FALSE) || input->checkInput(input_fire_center, REPEAT_FALSE) || input->checkInput(input_fire_right, REPEAT_FALSE))
{
else if (input->checkInput(input_pause, REPEAT_FALSE) || input->checkInput(input_accept, REPEAT_FALSE) || input->checkInput(input_fire_left, REPEAT_FALSE) || input->checkInput(input_fire_center, REPEAT_FALSE) || input->checkInput(input_fire_right, REPEAT_FALSE)) {
JA_StopMusic();
section->name = SECTION_PROG_TITLE;
section->subsection = SUBSECTION_TITLE_1;
@@ -233,40 +219,33 @@ void Intro::checkInput()
}
// Actualiza las escenas de la intro
void Intro::updateScenes()
{
switch (scene)
{
void Intro::updateScenes() {
switch (scene) {
case 1:
// Primera imagen - UPV
if (!bitmaps[0]->hasFinished())
{
if (!bitmaps[0]->hasFinished()) {
bitmaps[0]->setEnabled(true);
}
// Primer texto de la primera imagen
if (bitmaps[0]->hasFinished() && !texts[0]->hasFinished())
{
if (bitmaps[0]->hasFinished() && !texts[0]->hasFinished()) {
texts[0]->setEnabled(true);
}
// 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[1]->setEnabled(true);
}
// 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[2]->setEnabled(true);
}
// Fin de la primera escena
if (texts[2]->hasFinished())
{
if (texts[2]->hasFinished()) {
bitmaps[0]->setEnabled(false);
texts[2]->setEnabled(false);
scene++;
@@ -276,20 +255,17 @@ void Intro::updateScenes()
case 2:
// Segunda imagen - Máquina
if (!bitmaps[1]->hasFinished())
{
if (!bitmaps[1]->hasFinished()) {
bitmaps[1]->setEnabled(true);
}
// Primer texto de la segunda imagen
if (bitmaps[1]->hasFinished() && !texts[3]->hasFinished())
{
if (bitmaps[1]->hasFinished() && !texts[3]->hasFinished()) {
texts[3]->setEnabled(true);
}
// Fin de la segunda escena
if (texts[3]->hasFinished())
{
if (texts[3]->hasFinished()) {
bitmaps[1]->setEnabled(false);
texts[3]->setEnabled(false);
scene++;
@@ -299,15 +275,13 @@ void Intro::updateScenes()
case 3:
// 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);
texts[4]->setEnabled(true);
}
// Fin de la tercera escena
if (bitmaps[2]->hasFinished() && texts[4]->hasFinished())
{
if (bitmaps[2]->hasFinished() && texts[4]->hasFinished()) {
bitmaps[2]->setEnabled(false);
texts[4]->setEnabled(false);
scene++;
@@ -317,22 +291,19 @@ void Intro::updateScenes()
case 4:
// 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);
texts[5]->setEnabled(true);
}
// 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[6]->setEnabled(true);
}
// Fin de la cuarta escena
if (bitmaps[3]->hasFinished() && texts[6]->hasFinished())
{
if (bitmaps[3]->hasFinished() && texts[6]->hasFinished()) {
bitmaps[3]->setEnabled(false);
texts[6]->setEnabled(false);
scene++;
@@ -342,20 +313,17 @@ void Intro::updateScenes()
case 5:
// Quinta imagen - Patada
if (!bitmaps[4]->hasFinished())
{
if (!bitmaps[4]->hasFinished()) {
bitmaps[4]->setEnabled(true);
}
// Primer texto de la quinta imagen
if (bitmaps[4]->hasFinished() && !texts[7]->hasFinished())
{
if (bitmaps[4]->hasFinished() && !texts[7]->hasFinished()) {
texts[7]->setEnabled(true);
}
// Fin de la quinta escena
if (bitmaps[4]->hasFinished() && texts[7]->hasFinished())
{
if (bitmaps[4]->hasFinished() && texts[7]->hasFinished()) {
bitmaps[4]->setEnabled(false);
texts[7]->setEnabled(false);
scene++;
@@ -365,15 +333,13 @@ void Intro::updateScenes()
case 6:
// 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);
texts[8]->setEnabled(true);
}
// Acaba el último texto
if (bitmaps[5]->hasFinished() && texts[8]->hasFinished())
{
if (bitmaps[5]->hasFinished() && texts[8]->hasFinished()) {
bitmaps[5]->setEnabled(false);
texts[8]->setEnabled(false);
JA_StopMusic();
@@ -389,24 +355,20 @@ void Intro::updateScenes()
}
// Actualiza las variables del objeto
void Intro::update()
{
void Intro::update() {
JA_Update();
checkInput();
if (SDL_GetTicks() - ticks > ticksSpeed)
{
if (SDL_GetTicks() - ticks > ticksSpeed) {
// Actualiza el contador de ticks
ticks = SDL_GetTicks();
// Actualiza los objetos
for (auto bitmap : bitmaps)
{
for (auto bitmap : bitmaps) {
bitmap->update();
}
for (auto text : texts)
{
for (auto text : texts) {
text->update();
}
@@ -416,8 +378,7 @@ void Intro::update()
}
// Dibuja el objeto en pantalla
void Intro::render()
{
void Intro::render() {
// Prepara para empezar a dibujar en la textura de juego
screen->start();
@@ -425,13 +386,11 @@ void Intro::render()
screen->clean(bgColor);
// Dibuja los objetos
for (auto bitmap : bitmaps)
{
for (auto bitmap : bitmaps) {
bitmap->render();
}
for (auto text : texts)
{
for (auto text : texts) {
text->render();
}
@@ -440,12 +399,10 @@ void Intro::render()
}
// Bucle principal
void Intro::run()
{
void Intro::run() {
JA_PlayMusic(music, 0);
while (section->name == SECTION_PROG_INTRO)
{
while (section->name == SECTION_PROG_INTRO) {
update();
checkEvents();
render();

View File

@@ -1,6 +1,7 @@
#pragma once
#include <SDL3/SDL.h>
#include <vector> // for vector
class Asset;
class Input;
@@ -14,9 +15,8 @@ struct JA_Music_t;
struct section_t;
// Clase Intro
class Intro
{
private:
class Intro {
private:
// Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana
Screen *screen; // Objeto encargado de dibujar en pantalla
@@ -54,7 +54,7 @@ private:
// Actualiza las escenas de la intro
void updateScenes();
public:
public:
// Constructor
Intro(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, Lang *lang, section_t *section);

View File

@@ -1,12 +1,13 @@
#include "item.h"
#include <stdlib.h> // for rand
#include "animatedsprite.h" // for AnimatedSprite
#include "const.h" // for PLAY_AREA_LEFT, PLAY_AREA_RIGHT, PLAY_AR...
class Texture;
// Constructor
Item::Item(Uint8 kind, float x, float y, Texture *texture, std::vector<std::string> *animation, SDL_Renderer *renderer)
{
Item::Item(Uint8 kind, float x, float y, Texture *texture, std::vector<std::string> *animation, SDL_Renderer *renderer) {
sprite = new AnimatedSprite(texture, renderer, "", animation);
this->kind = kind;
@@ -15,8 +16,7 @@ Item::Item(Uint8 kind, float x, float y, Texture *texture, std::vector<std::stri
accelX = 0.0f;
floorCollision = false;
if (kind == ITEM_COFFEE_MACHINE)
{
if (kind == ITEM_COFFEE_MACHINE) {
width = 23;
height = 29;
posX = (((int)x + (PLAY_AREA_WIDTH / 2)) % (PLAY_AREA_WIDTH - width - 5)) + 2;
@@ -25,9 +25,7 @@ Item::Item(Uint8 kind, float x, float y, Texture *texture, std::vector<std::stri
velY = -0.1f;
accelY = 0.1f;
collider.r = 10;
}
else
{
} else {
width = 16;
height = 16;
posX = x;
@@ -44,22 +42,17 @@ Item::Item(Uint8 kind, float x, float y, Texture *texture, std::vector<std::stri
}
// Destructor
Item::~Item()
{
Item::~Item() {
delete sprite;
}
// Centra el objeto en la posición X
void Item::allignTo(int x)
{
void Item::allignTo(int x) {
posX = float(x - (width / 2));
if (posX < PLAY_AREA_LEFT)
{
if (posX < PLAY_AREA_LEFT) {
posX = PLAY_AREA_LEFT + 1;
}
else if ((posX + width) > PLAY_AREA_RIGHT)
{
} else if ((posX + width) > PLAY_AREA_RIGHT) {
posX = float(PLAY_AREA_RIGHT - width - 1);
}
@@ -72,24 +65,18 @@ void Item::allignTo(int x)
}
// Pinta el objeto en la pantalla
void Item::render()
{
if (enabled)
{
if (timeToLive > 200)
{
void Item::render() {
if (enabled) {
if (timeToLive > 200) {
sprite->render();
}
else if (timeToLive % 20 > 10)
{
} else if (timeToLive % 20 > 10) {
sprite->render();
}
}
}
// Actualiza la posición y estados del objeto
void Item::move()
{
void Item::move() {
floorCollision = false;
// Calcula la nueva posición
@@ -101,8 +88,7 @@ void Item::move()
velY += accelY;
// Si queda fuera de pantalla, corregimos su posición y cambiamos su sentido
if ((posX < PLAY_AREA_LEFT) || (posX + width > PLAY_AREA_RIGHT))
{
if ((posX < PLAY_AREA_LEFT) || (posX + width > PLAY_AREA_RIGHT)) {
// Corregir posición
posX -= velX;
@@ -111,8 +97,7 @@ void Item::move()
}
// Si se sale por arriba rebota (excepto la maquina de café)
if ((posY < PLAY_AREA_TOP) && !(kind == ITEM_COFFEE_MACHINE))
{
if ((posY < PLAY_AREA_TOP) && !(kind == ITEM_COFFEE_MACHINE)) {
// Corrige
posY -= velY;
@@ -121,8 +106,7 @@ void Item::move()
}
// Si el objeto se sale por la parte inferior
if (posY + height > PLAY_AREA_BOTTOM)
{
if (posY + height > PLAY_AREA_BOTTOM) {
// Corrige
posY -= velY;
@@ -132,8 +116,7 @@ void Item::move()
accelX = 0;
accelY = 0;
posY = PLAY_AREA_BOTTOM - height;
if (kind == ITEM_COFFEE_MACHINE)
{
if (kind == ITEM_COFFEE_MACHINE) {
floorCollision = true;
}
}
@@ -145,14 +128,12 @@ void Item::move()
}
// Pone a cero todos los valores del objeto
void Item::disable()
{
void Item::disable() {
enabled = false;
}
// Actualiza el objeto a su posicion, animación y controla los contadores
void Item::update()
{
void Item::update() {
move();
sprite->animate();
updateTimeToLive();
@@ -160,72 +141,60 @@ void Item::update()
}
// Actualiza el contador
void Item::updateTimeToLive()
{
if (timeToLive > 0)
{
void Item::updateTimeToLive() {
if (timeToLive > 0) {
timeToLive--;
}
}
// Comprueba si el objeto sigue vivo
void Item::checkTimeToLive()
{
void Item::checkTimeToLive() {
if (timeToLive == 0)
disable();
}
// Obtiene del valor de la variable
float Item::getPosX()
{
float Item::getPosX() {
return posX;
}
// Obtiene del valor de la variable
float Item::getPosY()
{
float Item::getPosY() {
return posY;
}
// Obtiene del valor de la variable
int Item::getWidth()
{
int Item::getWidth() {
return width;
}
// Obtiene del valor de la variable
int Item::getHeight()
{
int Item::getHeight() {
return height;
}
// Obtiene del valor de la variable
int Item::getClass()
{
int Item::getClass() {
return kind;
}
// Obtiene el valor de la variable
bool Item::isEnabled()
{
bool Item::isEnabled() {
return enabled;
}
// Obtiene el circulo de colisión
circle_t &Item::getCollider()
{
circle_t &Item::getCollider() {
return collider;
}
// 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.y = int(posY + (height / 2));
}
// Informa si el objeto ha colisionado con el suelo
bool Item::isOnFloor()
{
bool Item::isOnFloor() {
return floorCollision;
}

View File

@@ -1,8 +1,10 @@
#pragma once
#include <SDL3/SDL.h>
#include <string> // for string
#include <vector> // for vector
#include "utils.h" // for circle_t
class AnimatedSprite;
class Texture;
@@ -16,9 +18,8 @@ constexpr int ITEM_COFFEE = 5;
constexpr int ITEM_COFFEE_MACHINE = 6;
// Clase Item
class Item
{
private:
class Item {
private:
// Objetos y punteros
AnimatedSprite *sprite; // Sprite con los graficos del objeto
@@ -42,7 +43,7 @@ private:
// Actualiza la posición y estados del objeto
void move();
public:
public:
Uint16 timeToLive; // Temporizador con el tiempo que el objeto está presente
// Constructor

View File

@@ -1,25 +1,23 @@
#include "lang.h"
#include <fstream> // for basic_ifstream, basic_istream, ifstream
#include "asset.h" // for Asset
// Constructor
Lang::Lang(Asset *mAsset)
{
Lang::Lang(Asset *mAsset) {
this->mAsset = mAsset;
}
// Destructor
Lang::~Lang()
{
Lang::~Lang() {
}
// Inicializa los textos del juego en el idioma seleccionado
bool Lang::setLang(Uint8 lang)
{
bool Lang::setLang(Uint8 lang) {
std::string file;
switch (lang)
{
switch (lang) {
case es_ES:
file = mAsset->get("es_ES.txt");
break;
@@ -43,20 +41,17 @@ bool Lang::setLang(Uint8 lang)
bool success = false;
std::ifstream rfile(file);
if (rfile.is_open() && rfile.good())
{
if (rfile.is_open() && rfile.good()) {
success = true;
std::string line;
// lee el resto de datos del fichero
int index = 0;
while (std::getline(rfile, line))
{
while (std::getline(rfile, line)) {
// Almacena solo las lineas que no empiezan por # o no esten vacias
const bool test1 = line.substr(0,1) != "#";
const bool test1 = line.substr(0, 1) != "#";
const bool test2 = !line.empty();
if (test1 && test2)
{
if (test1 && test2) {
mTextStrings[index] = line;
index++;
}
@@ -67,7 +62,6 @@ bool Lang::setLang(Uint8 lang)
}
// Obtiene la cadena de texto del indice
std::string Lang::getText(int index)
{
std::string Lang::getText(int index) {
return mTextStrings[index];
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <SDL3/SDL.h>
#include <string> // for string, basic_string
class Asset;
@@ -14,13 +15,12 @@ constexpr int MAX_LANGUAGES = 3;
constexpr int MAX_TEXT_STRINGS = 100;
// Clase Lang
class Lang
{
private:
class Lang {
private:
Asset *mAsset; // Objeto que gestiona todos los ficheros de recursos
std::string mTextStrings[MAX_TEXT_STRINGS]; // Vector con los textos
public:
public:
// Constructor
Lang(Asset *mAsset);

View File

@@ -1,7 +1,10 @@
#include "logo.h"
#include <SDL3/SDL.h>
#include <algorithm> // for min
#include <string> // for basic_string
#include "asset.h" // for Asset
#include "const.h" // for bgColor, SECTION_PROG_LOGO, SECTION_PROG...
#include "input.h" // for Input, REPEAT_FALSE, inputs_e
@@ -16,8 +19,7 @@ constexpr int INIT_FADE = 100;
constexpr int END_LOGO = 200;
// Constructor
Logo::Logo(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, section_t *section)
{
Logo::Logo(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, section_t *section) {
// Copia la dirección de los objetos
this->renderer = renderer;
this->screen = screen;
@@ -39,8 +41,7 @@ Logo::Logo(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, s
}
// Destructor
Logo::~Logo()
{
Logo::~Logo() {
texture->unload();
delete texture;
@@ -49,24 +50,19 @@ Logo::~Logo()
}
// Comprueba si ha terminado el logo
void Logo::checkLogoEnd()
{
if (counter >= END_LOGO + 20)
{
void Logo::checkLogoEnd() {
if (counter >= END_LOGO + 20) {
section->name = SECTION_PROG_INTRO;
section->subsection = 0;
}
}
// Comprueba los eventos
void Logo::checkEvents()
{
void Logo::checkEvents() {
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(eventHandler) != 0)
{
while (SDL_PollEvent(eventHandler) != 0) {
// Evento de salida de la aplicación
if (eventHandler->type == SDL_EVENT_QUIT)
{
if (eventHandler->type == SDL_EVENT_QUIT) {
section->name = SECTION_PROG_QUIT;
break;
}
@@ -74,41 +70,33 @@ void Logo::checkEvents()
}
// Comprueba las entradas
void Logo::checkInput()
{
if (input->checkInput(input_exit, REPEAT_FALSE))
{
void Logo::checkInput() {
if (input->checkInput(input_exit, REPEAT_FALSE)) {
section->name = SECTION_PROG_QUIT;
}
else if (input->checkInput(input_window_fullscreen, REPEAT_FALSE))
{
else if (input->checkInput(input_window_fullscreen, REPEAT_FALSE)) {
screen->switchVideoMode();
}
else if (input->checkInput(input_window_dec_size, REPEAT_FALSE))
{
else if (input->checkInput(input_window_dec_size, REPEAT_FALSE)) {
screen->decWindowSize();
}
else if (input->checkInput(input_window_inc_size, REPEAT_FALSE))
{
else if (input->checkInput(input_window_inc_size, REPEAT_FALSE)) {
screen->incWindowSize();
}
else if (input->checkInput(input_pause, REPEAT_FALSE) || input->checkInput(input_accept, REPEAT_FALSE) || input->checkInput(input_fire_left, REPEAT_FALSE) || input->checkInput(input_fire_center, REPEAT_FALSE) || input->checkInput(input_fire_right, REPEAT_FALSE))
{
else if (input->checkInput(input_pause, REPEAT_FALSE) || input->checkInput(input_accept, REPEAT_FALSE) || input->checkInput(input_fire_left, REPEAT_FALSE) || input->checkInput(input_fire_center, REPEAT_FALSE) || input->checkInput(input_fire_right, REPEAT_FALSE)) {
section->name = SECTION_PROG_TITLE;
section->subsection = SUBSECTION_TITLE_1;
}
}
// Dibuja el fade
void Logo::renderFade()
{
void Logo::renderFade() {
// Dibuja el fade
if (counter >= INIT_FADE)
{
if (counter >= INIT_FADE) {
const float step = (float)(counter - INIT_FADE) / (float)(END_LOGO - INIT_FADE);
const int alpha = std::min((int)(255 * step), 255);
SDL_SetRenderDrawColor(renderer, bgColor.r, bgColor.g, bgColor.b, alpha);
@@ -117,13 +105,11 @@ void Logo::renderFade()
}
// Actualiza las variables del objeto
void Logo::update()
{
void Logo::update() {
JA_Update();
checkInput();
if (SDL_GetTicks() - ticks > ticksSpeed)
{
if (SDL_GetTicks() - ticks > ticksSpeed) {
// Actualiza el contador de ticks
ticks = SDL_GetTicks();
@@ -136,8 +122,7 @@ void Logo::update()
}
// Dibuja el objeto en pantalla
void Logo::render()
{
void Logo::render() {
// Prepara para empezar a dibujar en la textura de juego
screen->start();
@@ -155,12 +140,10 @@ void Logo::render()
}
// Bucle para el logo del juego
void Logo::run()
{
void Logo::run() {
JA_StopMusic();
while (section->name == SECTION_PROG_LOGO)
{
while (section->name == SECTION_PROG_LOGO) {
update();
checkEvents();
render();

View File

@@ -9,9 +9,8 @@ class Texture;
struct section_t;
// Clase Logo
class Logo
{
private:
class Logo {
private:
// Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana
Screen *screen; // Objeto encargado de dibujar en pantalla
@@ -45,7 +44,7 @@ private:
// Dibuja el fade
void renderFade();
public:
public:
// Constructor
Logo(SDL_Renderer *renderer, Screen *screen, Asset *asset, Input *input, section_t *section);

View File

@@ -40,11 +40,11 @@ Reescribiendo el código el 27/09/2022
*/
#include <memory>
#include "stb_vorbis.c"
#include "director.h"
int main(int argc, char *argv[])
{
#include "director.h"
#include "stb_vorbis.c"
int main(int argc, char *argv[]) {
// Crea el objeto Director
auto director = std::make_unique<Director>(argc, const_cast<const char **>(argv));

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,10 @@
#pragma once
#include <SDL3/SDL.h>
#include <string> // for string, basic_string
#include <vector> // for vector
#include "utils.h" // for color_t
class Asset;
class Input;
@@ -22,18 +24,15 @@ constexpr int SOUND_CANCEL = 2;
constexpr int MENU_NO_OPTION = -1;
// Clase Menu
class Menu
{
private:
struct rectangle_t
{
class Menu {
private:
struct rectangle_t {
SDL_Rect rect; // Rectangulo
color_t color; // Color
int a; // Transparencia
};
struct item_t
{
struct item_t {
std::string label; // Texto
SDL_Rect rect; // Rectangulo que delimita el elemento
int hPaddingDown; // Espaciado bajo el elemento
@@ -45,8 +44,7 @@ private:
bool line; // Indica si el elemento lleva una linea a continuación
};
struct selector_t
{
struct selector_t {
float originY; // Coordenada de origen
float targetY; // Coordenada de destino
float despY; // Cantidad de pixeles que se desplaza el selector en cada salto: (target - origin) / numJumps
@@ -142,7 +140,7 @@ private:
// Calcula los colores del selector para el degradado
void setSelectorItemColors();
public:
public:
// Constructor
Menu(SDL_Renderer *renderer, Asset *asset, Input *input, std::string file = "");

View File

@@ -1,9 +1,9 @@
#include "movingsprite.h"
#include "texture.h" // for Texture
// Constructor
MovingSprite::MovingSprite(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, Texture *texture, SDL_Renderer *renderer)
{
MovingSprite::MovingSprite(float x, float y, int w, int h, float velx, float vely, float accelx, float accely, Texture *texture, SDL_Renderer *renderer) {
// Copia los punteros
this->texture = texture;
this->renderer = renderer;
@@ -52,8 +52,7 @@ MovingSprite::MovingSprite(float x, float y, int w, int h, float velx, float vel
};
// Reinicia todas las variables
void MovingSprite::clear()
{
void MovingSprite::clear() {
x = 0.0f; // Posición en el eje X
y = 0.0f; // Posición en el eje Y
@@ -77,10 +76,8 @@ void MovingSprite::clear()
}
// Mueve el sprite
void MovingSprite::move()
{
if (enabled)
{
void MovingSprite::move() {
if (enabled) {
xPrev = x;
yPrev = y;
@@ -93,71 +90,59 @@ void MovingSprite::move()
}
// Muestra el sprite por pantalla
void MovingSprite::render()
{
if (enabled)
{
void MovingSprite::render() {
if (enabled) {
texture->render(renderer, (int)x, (int)y, &spriteClip, zoomW, zoomH, angle, center, currentFlip);
}
}
// Obtiene el valor de la variable
float MovingSprite::getPosX()
{
float MovingSprite::getPosX() {
return x;
}
// Obtiene el valor de la variable
float MovingSprite::getPosY()
{
float MovingSprite::getPosY() {
return y;
}
// Obtiene el valor de la variable
float MovingSprite::getVelX()
{
float MovingSprite::getVelX() {
return vx;
}
// Obtiene el valor de la variable
float MovingSprite::getVelY()
{
float MovingSprite::getVelY() {
return vy;
}
// Obtiene el valor de la variable
float MovingSprite::getAccelX()
{
float MovingSprite::getAccelX() {
return ax;
}
// Obtiene el valor de la variable
float MovingSprite::getAccelY()
{
float MovingSprite::getAccelY() {
return ay;
}
// Obtiene el valor de la variable
float MovingSprite::getZoomW()
{
float MovingSprite::getZoomW() {
return zoomW;
}
// Obtiene el valor de la variable
float MovingSprite::getZoomH()
{
float MovingSprite::getZoomH() {
return zoomH;
}
// Obtiene el valor de la variable
double MovingSprite::getAngle()
{
double MovingSprite::getAngle() {
return angle;
}
// Establece la posición y el tamaño del objeto
void MovingSprite::setRect(SDL_Rect rect)
{
void MovingSprite::setRect(SDL_Rect rect) {
x = (float)rect.x;
y = (float)rect.y;
w = rect.w;
@@ -165,198 +150,163 @@ void MovingSprite::setRect(SDL_Rect rect)
}
// Establece el valor de la variable
void MovingSprite::setPosX(float value)
{
void MovingSprite::setPosX(float value) {
x = value;
}
// Establece el valor de la variable
void MovingSprite::setPosY(float value)
{
void MovingSprite::setPosY(float value) {
y = value;
}
// Establece el valor de la variable
void MovingSprite::setVelX(float value)
{
void MovingSprite::setVelX(float value) {
vx = value;
}
// Establece el valor de la variable
void MovingSprite::setVelY(float value)
{
void MovingSprite::setVelY(float value) {
vy = value;
}
// Establece el valor de la variable
void MovingSprite::setAccelX(float value)
{
void MovingSprite::setAccelX(float value) {
ax = value;
}
// Establece el valor de la variable
void MovingSprite::setAccelY(float value)
{
void MovingSprite::setAccelY(float value) {
ay = value;
}
// Establece el valor de la variable
void MovingSprite::setZoomW(float value)
{
void MovingSprite::setZoomW(float value) {
zoomW = value;
}
// Establece el valor de la variable
void MovingSprite::setZoomH(float value)
{
void MovingSprite::setZoomH(float value) {
zoomH = value;
}
// Establece el valor de la variable
void MovingSprite::setAngle(double value)
{
void MovingSprite::setAngle(double value) {
angle = value;
}
// Incrementa el valor de la variable
void MovingSprite::incAngle(double value)
{
void MovingSprite::incAngle(double value) {
angle += value;
}
// Decrementa el valor de la variable
void MovingSprite::decAngle(double value)
{
void MovingSprite::decAngle(double value) {
angle -= value;
}
// Obtiene el valor de la variable
bool MovingSprite::getRotate()
{
bool MovingSprite::getRotate() {
return rotateEnabled;
}
// Obtiene el valor de la variable
Uint16 MovingSprite::getRotateSpeed()
{
Uint16 MovingSprite::getRotateSpeed() {
return rotateSpeed;
}
// Establece la rotacion
void MovingSprite::rotate()
{
void MovingSprite::rotate() {
if (enabled)
if (rotateEnabled)
{
if (counter % rotateSpeed == 0)
{
if (rotateEnabled) {
if (counter % rotateSpeed == 0) {
incAngle(rotateAmount);
}
}
}
// Establece el valor de la variable
void MovingSprite::setRotate(bool value)
{
void MovingSprite::setRotate(bool value) {
rotateEnabled = value;
}
// Establece el valor de la variable
void MovingSprite::setRotateSpeed(int value)
{
if (value < 1)
{
void MovingSprite::setRotateSpeed(int value) {
if (value < 1) {
rotateSpeed = 1;
}
else
{
} else {
rotateSpeed = value;
}
}
// Establece el valor de la variable
void MovingSprite::setRotateAmount(double value)
{
void MovingSprite::setRotateAmount(double value) {
rotateAmount = value;
}
// Establece el valor de la variable
void MovingSprite::disableRotate()
{
void MovingSprite::disableRotate() {
rotateEnabled = false;
angle = (double)0;
}
// Actualiza las variables internas del objeto
void MovingSprite::update()
{
void MovingSprite::update() {
move();
rotate();
if (enabled)
{
if (enabled) {
++counter %= 60000;
}
}
// Cambia el sentido de la rotación
void MovingSprite::switchRotate()
{
void MovingSprite::switchRotate() {
rotateAmount *= -1;
}
// Establece el valor de la variable
void MovingSprite::setFlip(SDL_FlipMode flip)
{
void MovingSprite::setFlip(SDL_FlipMode flip) {
currentFlip = flip;
}
// Gira el sprite horizontalmente
void MovingSprite::flip()
{
void MovingSprite::flip() {
currentFlip = (currentFlip == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL;
}
// Obtiene el valor de la variable
SDL_FlipMode MovingSprite::getFlip()
{
SDL_FlipMode MovingSprite::getFlip() {
return currentFlip;
}
// Devuelve el rectangulo donde está el sprite
SDL_Rect MovingSprite::getRect()
{
SDL_Rect MovingSprite::getRect() {
const SDL_Rect rect = {(int)x, (int)y, w, h};
return rect;
}
// Deshace el último movimiento
void MovingSprite::undoMove()
{
void MovingSprite::undoMove() {
x = xPrev;
y = yPrev;
}
// Deshace el último movimiento en el eje X
void MovingSprite::undoMoveX()
{
void MovingSprite::undoMoveX() {
x = xPrev;
}
// Deshace el último movimiento en el eje Y
void MovingSprite::undoMoveY()
{
void MovingSprite::undoMoveY() {
y = yPrev;
}
// Pone a cero las velocidades de desplacamiento
void MovingSprite::clearVel()
{
void MovingSprite::clearVel() {
vx = vy = 0.0f;
}
// Devuelve el incremento en el eje X en pixels
int MovingSprite::getIncX()
{
int MovingSprite::getIncX() {
return (int)x - (int)xPrev;
}

View File

@@ -1,13 +1,13 @@
#pragma once
#include <SDL3/SDL.h>
#include "sprite.h" // for Sprite
class Texture;
// Clase MovingSprite. Añade posicion y velocidad en punto flotante
class MovingSprite : public Sprite
{
protected:
class MovingSprite : public Sprite {
protected:
float x; // Posición en el eje X
float y; // Posición en el eje Y
@@ -31,7 +31,7 @@ protected:
SDL_Point *center; // Centro de rotación
SDL_FlipMode currentFlip; // Indica como se voltea el sprite
public:
public:
// Constructor
MovingSprite(float x = 0, float y = 0, int w = 0, int h = 0, float velx = 0, float vely = 0, float accelx = 0, float accely = 0, Texture *texture = nullptr, SDL_Renderer *renderer = nullptr);

View File

@@ -1,13 +1,14 @@
#include "player.h"
#include <stdlib.h> // for rand
#include "animatedsprite.h" // for AnimatedSprite
#include "const.h" // for PLAY_AREA_LEFT, PLAY_AREA_RIGHT
#include "input.h" // for inputs_e
#include "texture.h" // for Texture
// Constructor
Player::Player(float x, int y, SDL_Renderer *renderer, std::vector<Texture *> texture, std::vector<std::vector<std::string> *> animations)
{
Player::Player(float x, int y, SDL_Renderer *renderer, std::vector<Texture *> texture, std::vector<std::vector<std::string> *> animations) {
// Copia los punteros
this->renderer = renderer;
@@ -27,8 +28,7 @@ Player::Player(float x, int y, SDL_Renderer *renderer, std::vector<Texture *> te
}
// Destructor
Player::~Player()
{
Player::~Player() {
delete headSprite;
delete bodySprite;
delete legsSprite;
@@ -37,8 +37,7 @@ Player::~Player()
}
// Iniciador
void Player::init()
{
void Player::init() {
// Inicializa variables de estado
alive = true;
deathCounter = DEATH_COUNTER;
@@ -95,10 +94,8 @@ void Player::init()
}
// Actua en consecuencia de la entrada recibida
void Player::setInput(Uint8 input)
{
switch (input)
{
void Player::setInput(Uint8 input) {
switch (input) {
case input_left:
velX = -baseSpeed;
setWalkingStatus(PLAYER_STATUS_WALKING_LEFT);
@@ -129,16 +126,13 @@ void Player::setInput(Uint8 input)
}
// Mueve el jugador a la posición y animación que le corresponde
void Player::move()
{
if (isAlive())
{
void Player::move() {
if (isAlive()) {
// Mueve el jugador a derecha o izquierda
posX += velX;
// Si el jugador abandona el area de juego por los laterales
if ((posX < PLAY_AREA_LEFT - 5) || (posX + width > PLAY_AREA_RIGHT + 5))
{ // Restaura su posición
if ((posX < PLAY_AREA_LEFT - 5) || (posX + width > PLAY_AREA_RIGHT + 5)) { // Restaura su posición
posX -= velX;
}
@@ -154,14 +148,11 @@ void Player::move()
fireSprite->setPosX(getPosX() - 2);
fireSprite->setPosY(posY - 8);
}
else
{
} else {
deathSprite->update();
// Si el cadaver abandona el area de juego por los laterales
if ((deathSprite->getPosX() < PLAY_AREA_LEFT) || (deathSprite->getPosX() + width > PLAY_AREA_RIGHT))
{ // Restaura su posición
if ((deathSprite->getPosX() < PLAY_AREA_LEFT) || (deathSprite->getPosX() + width > PLAY_AREA_RIGHT)) { // Restaura su posición
const float vx = deathSprite->getVelX();
deathSprite->setPosX(deathSprite->getPosX() - vx);
@@ -172,69 +163,53 @@ void Player::move()
}
// Pinta el jugador en pantalla
void Player::render()
{
if (isAlive())
{
if (invulnerable)
{
if ((invulnerableCounter % 10) > 4)
{
if (powerUp)
{
void Player::render() {
if (isAlive()) {
if (invulnerable) {
if ((invulnerableCounter % 10) > 4) {
if (powerUp) {
fireSprite->render();
}
legsSprite->render();
bodySprite->render();
headSprite->render();
}
}
else
{
if (powerUp)
{
} else {
if (powerUp) {
fireSprite->render();
}
legsSprite->render();
bodySprite->render();
headSprite->render();
}
}
else
{
} else {
deathSprite->render();
}
}
// Establece el estado del jugador cuando camina
void Player::setWalkingStatus(Uint8 status)
{
void Player::setWalkingStatus(Uint8 status) {
// Si cambiamos de estado, reiniciamos la animación
if (statusWalking != status)
{
if (statusWalking != status) {
statusWalking = status;
// legsSprite->setCurrentFrame(0);
}
}
// Establece el estado del jugador cuando dispara
void Player::setFiringStatus(Uint8 status)
{
void Player::setFiringStatus(Uint8 status) {
// Si cambiamos de estado, reiniciamos la animación
if (statusFiring != status)
{
if (statusFiring != status) {
statusFiring = status;
}
}
// 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
std::string aBodyCoffees = "";
std::string aHeadCoffees = "";
if (coffees > 0)
{
if (coffees > 0) {
aBodyCoffees = coffees == 1 ? "_1C" : "_2C";
aHeadCoffees = "_1C";
}
@@ -249,15 +224,12 @@ void Player::setAnimation()
// Establece la animación a partir de las cadenas
legsSprite->setCurrentAnimation(aWalking);
legsSprite->setFlip(flipWalk);
if (statusFiring == PLAYER_STATUS_FIRING_NO)
{ // No esta disparando
if (statusFiring == PLAYER_STATUS_FIRING_NO) { // No esta disparando
bodySprite->setCurrentAnimation(aWalking + aBodyCoffees + aPowerUp);
bodySprite->setFlip(flipWalk);
headSprite->setCurrentAnimation(aWalking + aHeadCoffees + aPowerUp);
headSprite->setFlip(flipWalk);
}
else
{ // Está disparando
} else { // Está disparando
bodySprite->setCurrentAnimation(aFiring + aBodyCoffees + aPowerUp);
bodySprite->setFlip(flipFire);
headSprite->setCurrentAnimation(aFiring + aHeadCoffees + aPowerUp);
@@ -274,69 +246,54 @@ void Player::setAnimation()
}
// Obtiene el valor de la variable
int Player::getPosX()
{
int Player::getPosX() {
return int(posX);
}
// Obtiene el valor de la variable
int Player::getPosY()
{
int Player::getPosY() {
return posY;
}
// Obtiene el valor de la variable
int Player::getWidth()
{
int Player::getWidth() {
return width;
}
// Obtiene el valor de la variable
int Player::getHeight()
{
int Player::getHeight() {
return height;
}
// Indica si el jugador puede disparar
bool Player::canFire()
{
bool Player::canFire() {
// Si el contador a llegado a cero, podemos disparar. En caso contrario decrementamos el contador
if (cooldown > 0)
{
if (cooldown > 0) {
return false;
}
else
{
} else {
return true;
}
}
// Establece el valor de la variable
void Player::setFireCooldown(int time)
{
void Player::setFireCooldown(int time) {
cooldown = time;
}
// Actualiza el valor de la variable
void Player::updateCooldown()
{
if (cooldown > 0)
{
void Player::updateCooldown() {
if (cooldown > 0) {
cooldown--;
if (powerUp)
{
if (powerUp) {
cooldown--;
}
}
else
{
} else {
setFiringStatus(PLAYER_STATUS_FIRING_NO);
}
}
// Actualiza al jugador a su posicion, animación y controla los contadores
void Player::update()
{
void Player::update() {
move();
setAnimation();
shiftColliders();
@@ -348,121 +305,95 @@ void Player::update()
}
// Obtiene la puntuación del jugador
Uint32 Player::getScore()
{
Uint32 Player::getScore() {
return score;
}
// Asigna un valor a la puntuación del jugador
void Player::setScore(Uint32 score)
{
void Player::setScore(Uint32 score) {
this->score = score;
}
// Incrementa la puntuación del jugador
void Player::addScore(Uint32 score)
{
void Player::addScore(Uint32 score) {
this->score += score;
}
// Obtiene el valor de la variable
bool Player::isAlive()
{
bool Player::isAlive() {
return alive;
}
// Establece el valor de la variable
void Player::setAlive(bool value)
{
void Player::setAlive(bool value) {
alive = value;
if (!value)
{
if (!value) {
deathSprite->setPosX(headSprite->getRect().x);
deathSprite->setPosY(headSprite->getRect().y);
deathSprite->setAccelY(0.2f);
deathSprite->setVelY(-6.6f);
deathSprite->setVelX(3.3f);
if (rand() % 2 == 0)
{
if (rand() % 2 == 0) {
deathSprite->setVelX(-3.3f);
}
}
}
// Obtiene el valor de la variable
float Player::getScoreMultiplier()
{
float Player::getScoreMultiplier() {
return scoreMultiplier;
}
// Establece el valor de la variable
void Player::setScoreMultiplier(float value)
{
void Player::setScoreMultiplier(float value) {
scoreMultiplier = value;
}
// Aumenta el valor de la variable hasta un máximo
void Player::incScoreMultiplier()
{
if (scoreMultiplier < 5.0f)
{
void Player::incScoreMultiplier() {
if (scoreMultiplier < 5.0f) {
scoreMultiplier += 0.1f;
}
else
{
} else {
scoreMultiplier = 5.0f;
}
}
// Decrementa el valor de la variable hasta un mínimo
void Player::decScoreMultiplier()
{
if (scoreMultiplier > 1.0f)
{
void Player::decScoreMultiplier() {
if (scoreMultiplier > 1.0f) {
scoreMultiplier -= 0.1f;
}
else
{
} else {
scoreMultiplier = 1.0f;
}
}
// Obtiene el valor de la variable
bool Player::isInvulnerable()
{
bool Player::isInvulnerable() {
return invulnerable;
}
// Establece el valor de la variable
void Player::setInvulnerable(bool value)
{
void Player::setInvulnerable(bool value) {
invulnerable = value;
}
// Obtiene el valor de la variable
Uint16 Player::getInvulnerableCounter()
{
Uint16 Player::getInvulnerableCounter() {
return invulnerableCounter;
}
// Establece el valor de la variable
void Player::setInvulnerableCounter(Uint16 value)
{
void Player::setInvulnerableCounter(Uint16 value) {
invulnerableCounter = value;
}
// Actualiza el valor de la variable
void Player::updateInvulnerableCounter()
{
if (invulnerable)
{
if (invulnerableCounter > 0)
{
void Player::updateInvulnerableCounter() {
if (invulnerable) {
if (invulnerableCounter > 0) {
invulnerableCounter--;
}
else
{
} else {
invulnerable = false;
invulnerableCounter = PLAYER_INVULNERABLE_COUNTER;
}
@@ -470,81 +401,64 @@ void Player::updateInvulnerableCounter()
}
// Actualiza el valor de la variable
void Player::updateDeathCounter()
{
if (!alive)
{
if (deathCounter > 0)
{
void Player::updateDeathCounter() {
if (!alive) {
if (deathCounter > 0) {
deathCounter--;
}
}
}
// Obtiene el valor de la variable
bool Player::isPowerUp()
{
bool Player::isPowerUp() {
return powerUp;
}
// Establece el valor de la variable
void Player::setPowerUp(bool value)
{
void Player::setPowerUp(bool value) {
powerUp = value;
}
// Obtiene el valor de la variable
Uint16 Player::getPowerUpCounter()
{
Uint16 Player::getPowerUpCounter() {
return powerUpCounter;
}
// Establece el valor de la variable
void Player::setPowerUpCounter(Uint16 value)
{
void Player::setPowerUpCounter(Uint16 value) {
powerUpCounter = value;
}
// Actualiza el valor de la variable
void Player::updatePowerUpCounter()
{
if ((powerUpCounter > 0) && (powerUp))
{
void Player::updatePowerUpCounter() {
if ((powerUpCounter > 0) && (powerUp)) {
powerUpCounter--;
}
else
{
} else {
powerUp = false;
powerUpCounter = PLAYER_POWERUP_COUNTER;
}
}
// Obtiene el valor de la variable
bool Player::hasExtraHit()
{
bool Player::hasExtraHit() {
return extraHit;
}
// Concede un toque extra al jugador
void Player::giveExtraHit()
{
void Player::giveExtraHit() {
extraHit = true;
coffees++;
if (coffees > 2)
{
if (coffees > 2) {
coffees = 2;
}
}
// Quita el toque extra al jugador
void Player::removeExtraHit()
{
if (coffees > 0)
{
void Player::removeExtraHit() {
if (coffees > 0) {
coffees--;
}
if (coffees == 0)
{
if (coffees == 0) {
extraHit = false;
}
invulnerable = true;
@@ -552,68 +466,53 @@ void Player::removeExtraHit()
}
// Habilita la entrada de ordenes
void Player::enableInput()
{
void Player::enableInput() {
input = true;
}
// Deshabilita la entrada de ordenes
void Player::disableInput()
{
void Player::disableInput() {
input = false;
}
// Devuelve el numero de cafes actuales
Uint8 Player::getCoffees()
{
Uint8 Player::getCoffees() {
return coffees;
}
// Obtiene el circulo de colisión
circle_t &Player::getCollider()
{
circle_t &Player::getCollider() {
return collider;
}
// 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.y = int(posY + (height / 2));
}
// Obtiene el puntero a la textura con los gráficos de la animación de morir
Texture *Player::getDeadTexture()
{
Texture *Player::getDeadTexture() {
return deathSprite->getTexture();
;
}
// Obtiene el valor de la variable
Uint16 Player::getDeathCounter()
{
Uint16 Player::getDeathCounter() {
return deathCounter;
}
// Actualiza el valor de la variable
void Player::updatePowerUpHeadOffset()
{
if (!powerUp)
{
void Player::updatePowerUpHeadOffset() {
if (!powerUp) {
// powerUpHeadOffset = 0;
}
else
{
} else {
// powerUpHeadOffset = 96;
if (powerUpCounter < 300)
{
if (powerUpCounter % 10 > 4)
{
if (powerUpCounter < 300) {
if (powerUpCounter % 10 > 4) {
// powerUpHeadOffset = 96;
fireSprite->setEnabled(false);
}
else
{
} else {
// powerUpHeadOffset = 0;
fireSprite->setEnabled(true);
}
@@ -622,8 +521,7 @@ void Player::updatePowerUpHeadOffset()
}
// Pone las texturas del jugador
void Player::setPlayerTextures(std::vector<Texture *> texture)
{
void Player::setPlayerTextures(std::vector<Texture *> texture) {
headSprite->setTexture(texture[0]);
bodySprite->setTexture(texture[1]);
legsSprite->setTexture(texture[2]);

View File

@@ -1,8 +1,10 @@
#pragma once
#include <SDL3/SDL.h>
#include <string> // for string
#include <vector> // for vector
#include "utils.h" // for circle_t
class AnimatedSprite;
class Texture;
@@ -25,9 +27,8 @@ constexpr int PLAYER_INVULNERABLE_COUNTER = 200;
constexpr int PLAYER_POWERUP_COUNTER = 1500;
// Clase Player
class Player
{
private:
class Player {
private:
// Objetos y punteros
SDL_Renderer *renderer; // El renderizador de la ventana
AnimatedSprite *headSprite; // Sprite para dibujar la cabeza
@@ -78,7 +79,7 @@ private:
// Actualiza el valor de la variable
void updatePowerUpHeadOffset();
public:
public:
// Constructor
Player(float x, int y, SDL_Renderer *renderer, std::vector<Texture *> texture, std::vector<std::vector<std::string> *> animations);

View File

@@ -1,13 +1,14 @@
#include "screen.h"
#include <SDL3/SDL.h>
#include <algorithm> // for max, min
#include <iostream> // for basic_ostream, operator<<, cout, endl
#include <string> // for basic_string, char_traits, string
class Asset;
// Constructor
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options)
{
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options) {
// Inicializa variables
this->window = window;
this->renderer = renderer;
@@ -29,14 +30,11 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options
// Crea la textura donde se dibujan los graficos del juego
gameCanvas = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, gameCanvasWidth, gameCanvasHeight);
if (gameCanvas != nullptr)
{
if (gameCanvas != nullptr) {
SDL_SetTextureScaleMode(gameCanvas, options->filter == FILTER_NEAREST ? SDL_SCALEMODE_NEAREST : SDL_SCALEMODE_LINEAR);
}
if (gameCanvas == nullptr)
{
if (options->console)
{
if (gameCanvas == nullptr) {
if (options->console) {
std::cout << "TitleSurface could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
@@ -49,27 +47,23 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options
}
// Destructor
Screen::~Screen()
{
Screen::~Screen() {
SDL_DestroyTexture(gameCanvas);
}
// Limpia la pantalla
void Screen::clean(color_t color)
{
void Screen::clean(color_t color) {
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 0xFF);
SDL_RenderClear(renderer);
}
// Prepara para empezar a dibujar en la textura de juego
void Screen::start()
{
void Screen::start() {
SDL_SetRenderTarget(renderer, gameCanvas);
}
// Vuelca el contenido del renderizador en pantalla
void Screen::blit()
{
void Screen::blit() {
// Vuelve a dejar el renderizador en modo normal
SDL_SetRenderTarget(renderer, nullptr);
@@ -86,29 +80,25 @@ void Screen::blit()
}
// Establece el modo de video
void Screen::setVideoMode(int videoMode)
{
void Screen::setVideoMode(int videoMode) {
// Aplica el modo de video
SDL_SetWindowFullscreen(window, videoMode != 0);
// Si está activo el modo ventana quita el borde
if (videoMode == 0)
{
if (videoMode == 0) {
// Muestra el puntero
SDL_ShowCursor();
// Esconde la ventana
//SDL_HideWindow(window);
// SDL_HideWindow(window);
if (options->borderEnabled)
{
if (options->borderEnabled) {
windowWidth = gameCanvasWidth + borderWidth;
windowHeight = gameCanvasHeight + borderHeight;
dest = {0 + (borderWidth / 2), 0 + (borderHeight / 2), gameCanvasWidth, gameCanvasHeight};
}
else
{
else {
windowWidth = gameCanvasWidth;
windowHeight = gameCanvasHeight;
dest = {0, 0, gameCanvasWidth, gameCanvasHeight};
@@ -119,12 +109,11 @@ void Screen::setVideoMode(int videoMode)
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
// Muestra la ventana
//SDL_ShowWindow(window);
// SDL_ShowWindow(window);
}
// Si está activo el modo de pantalla completa añade el borde
else if (videoMode == SDL_WINDOW_FULLSCREEN)
{
else if (videoMode == SDL_WINDOW_FULLSCREEN) {
// Oculta el puntero
SDL_HideCursor();
@@ -132,12 +121,10 @@ void Screen::setVideoMode(int videoMode)
SDL_GetWindowSize(window, &windowWidth, &windowHeight);
// Aplica el escalado al rectangulo donde se pinta la textura del juego
if (options->integerScale)
{
if (options->integerScale) {
// Calcula el tamaño de la escala máxima
int scale = 0;
while (((gameCanvasWidth * (scale + 1)) <= windowWidth) && ((gameCanvasHeight * (scale + 1)) <= windowHeight))
{
while (((gameCanvasWidth * (scale + 1)) <= windowWidth) && ((gameCanvasHeight * (scale + 1)) <= windowHeight)) {
scale++;
}
@@ -145,27 +132,20 @@ void Screen::setVideoMode(int videoMode)
dest.h = gameCanvasHeight * scale;
dest.x = (windowWidth - dest.w) / 2;
dest.y = (windowHeight - dest.h) / 2;
}
else if (options->keepAspect)
{
} else if (options->keepAspect) {
float ratio = (float)gameCanvasWidth / (float)gameCanvasHeight;
if ((windowWidth - gameCanvasWidth) >= (windowHeight - gameCanvasHeight))
{
if ((windowWidth - gameCanvasWidth) >= (windowHeight - gameCanvasHeight)) {
dest.h = windowHeight;
dest.w = (int)((windowHeight * ratio) + 0.5f);
dest.x = (windowWidth - dest.w) / 2;
dest.y = (windowHeight - dest.h) / 2;
}
else
{
} else {
dest.w = windowWidth;
dest.h = (int)((windowWidth / ratio) + 0.5f);
dest.x = (windowWidth - dest.w) / 2;
dest.y = (windowHeight - dest.h) / 2;
}
}
else
{
} else {
dest.w = windowWidth;
dest.h = windowHeight;
dest.x = dest.y = 0;
@@ -182,83 +162,70 @@ void Screen::setVideoMode(int videoMode)
}
// Camibia entre pantalla completa y ventana
void Screen::switchVideoMode()
{
void Screen::switchVideoMode() {
options->videoMode = (options->videoMode == 0) ? SDL_WINDOW_FULLSCREEN : 0;
setVideoMode(options->videoMode);
}
// Cambia el tamaño de la ventana
void Screen::setWindowSize(int size)
{
void Screen::setWindowSize(int size) {
options->windowSize = size;
setVideoMode(0);
}
// Reduce el tamaño de la ventana
void Screen::decWindowSize()
{
void Screen::decWindowSize() {
--options->windowSize;
options->windowSize = std::max(options->windowSize, 1);
setVideoMode(0);
}
// Aumenta el tamaño de la ventana
void Screen::incWindowSize()
{
void Screen::incWindowSize() {
++options->windowSize;
options->windowSize = std::min(options->windowSize, 4);
setVideoMode(0);
}
// Cambia el color del borde
void Screen::setBorderColor(color_t color)
{
void Screen::setBorderColor(color_t color) {
borderColor = color;
}
// Cambia el tipo de mezcla
void Screen::setBlendMode(SDL_BlendMode blendMode)
{
void Screen::setBlendMode(SDL_BlendMode blendMode) {
SDL_SetRenderDrawBlendMode(renderer, blendMode);
}
// Establece el tamaño del borde
void Screen::setBorderWidth(int s)
{
void Screen::setBorderWidth(int s) {
options->borderWidth = s;
}
// Establece el tamaño del borde
void Screen::setBorderHeight(int s)
{
void Screen::setBorderHeight(int s) {
options->borderHeight = s;
}
// Establece si se ha de ver el borde en el modo ventana
void Screen::setBorderEnabled(bool value)
{
void Screen::setBorderEnabled(bool value) {
options->borderEnabled = value;
}
// Cambia entre borde visible y no visible
void Screen::switchBorder()
{
void Screen::switchBorder() {
options->borderEnabled = !options->borderEnabled;
setVideoMode(0);
}
// Activa el fade
void Screen::setFade()
{
void Screen::setFade() {
fade = true;
}
// Comprueba si ha terminado el fade
bool Screen::fadeEnded()
{
if (fade || fadeCounter > 0)
{
bool Screen::fadeEnded() {
if (fade || fadeCounter > 0) {
return false;
}
@@ -266,16 +233,13 @@ bool Screen::fadeEnded()
}
// Activa el spectrum fade
void Screen::setspectrumFade()
{
void Screen::setspectrumFade() {
spectrumFade = true;
}
// Comprueba si ha terminado el spectrum fade
bool Screen::spectrumFadeEnded()
{
if (spectrumFade || spectrumFadeCounter > 0)
{
bool Screen::spectrumFadeEnded() {
if (spectrumFade || spectrumFadeCounter > 0) {
return false;
}
@@ -283,33 +247,27 @@ bool Screen::spectrumFadeEnded()
}
// Inicializa las variables para el fade
void Screen::iniFade()
{
void Screen::iniFade() {
fade = false;
fadeCounter = 0;
fadeLenght = 200;
}
// Actualiza el fade
void Screen::updateFade()
{
if (!fade)
{
void Screen::updateFade() {
if (!fade) {
return;
}
fadeCounter++;
if (fadeCounter > fadeLenght)
{
if (fadeCounter > fadeLenght) {
iniFade();
}
}
// Dibuja el fade
void Screen::renderFade()
{
if (!fade)
{
void Screen::renderFade() {
if (!fade) {
return;
}
@@ -322,8 +280,7 @@ void Screen::renderFade()
}
// Inicializa las variables para el fade spectrum
void Screen::iniSpectrumFade()
{
void Screen::iniSpectrumFade() {
spectrumFade = false;
spectrumFadeCounter = 0;
spectrumFadeLenght = 50;
@@ -332,33 +289,27 @@ void Screen::iniSpectrumFade()
// Inicializa el vector de colores
const std::vector<std::string> vColors = {"black", "blue", "red", "magenta", "green", "cyan", "yellow", "bright_white"};
for (auto v : vColors)
{
for (auto v : vColors) {
spectrumColor.push_back(stringToColor(options->palette, v));
}
}
// Actualiza el spectrum fade
void Screen::updateSpectrumFade()
{
if (!spectrumFade)
{
void Screen::updateSpectrumFade() {
if (!spectrumFade) {
return;
}
spectrumFadeCounter++;
if (spectrumFadeCounter > spectrumFadeLenght)
{
if (spectrumFadeCounter > spectrumFadeLenght) {
iniSpectrumFade();
SDL_SetTextureColorMod(gameCanvas, 255, 255, 255);
}
}
// Dibuja el spectrum fade
void Screen::renderSpectrumFade()
{
if (!spectrumFade)
{
void Screen::renderSpectrumFade() {
if (!spectrumFade) {
return;
}
@@ -370,15 +321,13 @@ void Screen::renderSpectrumFade()
}
// Actualiza los efectos
void Screen::updateFX()
{
void Screen::updateFX() {
updateFade();
updateSpectrumFade();
}
// Dibuja los efectos
void Screen::renderFX()
{
void Screen::renderFX() {
renderFade();
renderSpectrumFade();
}

View File

@@ -1,7 +1,9 @@
#pragma once
#include <SDL3/SDL.h>
#include <vector> // for vector
#include "utils.h" // for color_t
class Asset;
@@ -9,9 +11,8 @@ class Asset;
constexpr int FILTER_NEAREST = 0;
constexpr int FILTER_LINEAL = 1;
class Screen
{
private:
class Screen {
private:
// Objetos y punteros
SDL_Window *window; // Ventana de la aplicación
SDL_Renderer *renderer; // El renderizador de la ventana
@@ -59,7 +60,7 @@ private:
// Dibuja el spectrum fade
void renderSpectrumFade();
public:
public:
// Constructor
Screen(SDL_Window *window, SDL_Renderer *renderer, Asset *asset, options_t *options);

View File

@@ -1,10 +1,10 @@
#include "smartsprite.h"
#include "movingsprite.h" // for MovingSprite
class Texture;
// Constructor
SmartSprite::SmartSprite(Texture *texture, SDL_Renderer *renderer)
{
SmartSprite::SmartSprite(Texture *texture, SDL_Renderer *renderer) {
// Copia punteros
setTexture(texture);
setRenderer(renderer);
@@ -14,8 +14,7 @@ SmartSprite::SmartSprite(Texture *texture, SDL_Renderer *renderer)
}
// Inicializa el objeto
void SmartSprite::init()
{
void SmartSprite::init() {
enabled = false;
enabledCounter = 0;
onDestination = false;
@@ -26,10 +25,8 @@ void SmartSprite::init()
}
// Actualiza la posición y comprueba si ha llegado a su destino
void SmartSprite::update()
{
if (enabled)
{
void SmartSprite::update() {
if (enabled) {
// Actualiza las variables internas del objeto
MovingSprite::update();
@@ -42,72 +39,59 @@ void SmartSprite::update()
}
// Pinta el objeto en pantalla
void SmartSprite::render()
{
if (enabled)
{
void SmartSprite::render() {
if (enabled) {
// Muestra el sprite por pantalla
MovingSprite::render();
}
}
// Obtiene el valor de la variable
bool SmartSprite::isEnabled()
{
bool SmartSprite::isEnabled() {
return enabled;
}
// Establece el valor de la variable
void SmartSprite::setEnabled(bool enabled)
{
void SmartSprite::setEnabled(bool enabled) {
this->enabled = enabled;
}
// Obtiene el valor de la variable
int SmartSprite::getEnabledCounter()
{
int SmartSprite::getEnabledCounter() {
return enabledCounter;
}
// Establece el valor de la variable
void SmartSprite::setEnabledCounter(int value)
{
void SmartSprite::setEnabledCounter(int value) {
enabledCounter = value;
}
// Establece el valor de la variable
void SmartSprite::setDestX(int x)
{
void SmartSprite::setDestX(int x) {
destX = x;
}
// Establece el valor de la variable
void SmartSprite::setDestY(int y)
{
void SmartSprite::setDestY(int y) {
destY = y;
}
// Obtiene el valor de la variable
int SmartSprite::getDestX()
{
int SmartSprite::getDestX() {
return destX;
}
// Obtiene el valor de la variable
int SmartSprite::getDestY()
{
int SmartSprite::getDestY() {
return destY;
}
// Comprueba el movimiento
void SmartSprite::checkMove()
{
void SmartSprite::checkMove() {
// Comprueba si se desplaza en el eje X hacia la derecha
if (getAccelX() > 0 || getVelX() > 0)
{
if (getAccelX() > 0 || getVelX() > 0) {
// Comprueba si ha llegado al destino
if (getPosX() > destX)
{
if (getPosX() > destX) {
// Lo coloca en posición
setPosX(destX);
@@ -117,11 +101,9 @@ void SmartSprite::checkMove()
}
}
// Comprueba si se desplaza en el eje X hacia la izquierda
else if (getAccelX() < 0 || getVelX() < 0)
{
else if (getAccelX() < 0 || getVelX() < 0) {
// Comprueba si ha llegado al destino
if (getPosX() < destX)
{
if (getPosX() < destX) {
// Lo coloca en posición
setPosX(destX);
@@ -132,11 +114,9 @@ void SmartSprite::checkMove()
}
// Comprueba si se desplaza en el eje Y hacia abajo
if (getAccelY() > 0 || getVelY() > 0)
{
if (getAccelY() > 0 || getVelY() > 0) {
// Comprueba si ha llegado al destino
if (getPosY() > destY)
{
if (getPosY() > destY) {
// Lo coloca en posición
setPosY(destY);
@@ -146,11 +126,9 @@ void SmartSprite::checkMove()
}
}
// Comprueba si se desplaza en el eje Y hacia arriba
else if (getAccelY() < 0 || getVelY() < 0)
{
else if (getAccelY() < 0 || getVelY() < 0) {
// Comprueba si ha llegado al destino
if (getPosY() < destY)
{
if (getPosY() < destY) {
// Lo coloca en posición
setPosY(destY);
@@ -162,32 +140,25 @@ void SmartSprite::checkMove()
}
// Comprueba si ha terminado
void SmartSprite::checkFinished()
{
void SmartSprite::checkFinished() {
// Comprueba si ha llegado a su destino
onDestination = (getPosX() == destX && getPosY() == destY) ? true : false;
if (onDestination)
{ // Si esta en el destino comprueba su contador
if (enabledCounter == 0)
{ // Si ha llegado a cero, deshabilita el objeto y lo marca como finalizado
if (onDestination) { // Si esta en el destino comprueba su contador
if (enabledCounter == 0) { // Si ha llegado a cero, deshabilita el objeto y lo marca como finalizado
finished = true;
}
else
{ // Si no ha llegado a cero, decrementa el contador
} else { // Si no ha llegado a cero, decrementa el contador
enabledCounter--;
}
}
}
// Obtiene el valor de la variable
bool SmartSprite::isOnDestination()
{
bool SmartSprite::isOnDestination() {
return onDestination;
}
// Obtiene el valor de la variable
bool SmartSprite::hasFinished()
{
bool SmartSprite::hasFinished() {
return finished;
}

View File

@@ -1,13 +1,13 @@
#pragma once
#include <SDL3/SDL.h>
#include "animatedsprite.h" // for AnimatedSprite
class Texture;
// Clase SmartSprite
class SmartSprite : public AnimatedSprite
{
private:
class SmartSprite : public AnimatedSprite {
private:
// Variables
bool enabled; // Indica si esta habilitado
bool onDestination; // Indica si está en el destino
@@ -22,7 +22,7 @@ private:
// Comprueba si ha terminado
void checkFinished();
public:
public:
// Constructor
SmartSprite(Texture *texture, SDL_Renderer *renderer);

View File

@@ -1,9 +1,9 @@
#include "sprite.h"
#include "texture.h" // for Texture
// Constructor
Sprite::Sprite(int x, int y, int w, int h, Texture *texture, SDL_Renderer *renderer)
{
Sprite::Sprite(int x, int y, int w, int h, Texture *texture, SDL_Renderer *renderer) {
// Establece la posición X,Y del sprite
this->x = x;
this->y = y;
@@ -25,8 +25,7 @@ Sprite::Sprite(int x, int y, int w, int h, Texture *texture, SDL_Renderer *rende
enabled = true;
}
Sprite::Sprite(SDL_Rect rect, Texture *texture, SDL_Renderer *renderer)
{
Sprite::Sprite(SDL_Rect rect, Texture *texture, SDL_Renderer *renderer) {
// Establece la posición X,Y del sprite
x = rect.x;
y = rect.y;
@@ -49,140 +48,117 @@ Sprite::Sprite(SDL_Rect rect, Texture *texture, SDL_Renderer *renderer)
}
// Destructor
Sprite::~Sprite()
{
Sprite::~Sprite() {
texture = nullptr;
renderer = nullptr;
}
// Muestra el sprite por pantalla
void Sprite::render()
{
if (enabled)
{
void Sprite::render() {
if (enabled) {
texture->render(renderer, x, y, &spriteClip);
}
}
// Obten el valor de la variable
int Sprite::getPosX()
{
int Sprite::getPosX() {
return x;
}
// Obten el valor de la variable
int Sprite::getPosY()
{
int Sprite::getPosY() {
return y;
}
// Obten el valor de la variable
int Sprite::getWidth()
{
int Sprite::getWidth() {
return w;
}
// Obten el valor de la variable
int Sprite::getHeight()
{
int Sprite::getHeight() {
return h;
}
// Establece la posición del objeto
void Sprite::setPos(SDL_Rect rect)
{
void Sprite::setPos(SDL_Rect rect) {
this->x = rect.x;
this->y = rect.y;
}
// Establece el valor de la variable
void Sprite::setPosX(int x)
{
void Sprite::setPosX(int x) {
this->x = x;
}
// Establece el valor de la variable
void Sprite::setPosY(int y)
{
void Sprite::setPosY(int y) {
this->y = y;
}
// Establece el valor de la variable
void Sprite::setWidth(int w)
{
void Sprite::setWidth(int w) {
this->w = w;
}
// Establece el valor de la variable
void Sprite::setHeight(int h)
{
void Sprite::setHeight(int h) {
this->h = h;
}
// Obten el valor de la variable
SDL_Rect Sprite::getSpriteClip()
{
SDL_Rect Sprite::getSpriteClip() {
return spriteClip;
}
// Establece el valor de la variable
void Sprite::setSpriteClip(SDL_Rect rect)
{
void Sprite::setSpriteClip(SDL_Rect rect) {
spriteClip = rect;
}
// Establece el valor de la variable
void Sprite::setSpriteClip(int x, int y, int w, int h)
{
void Sprite::setSpriteClip(int x, int y, int w, int h) {
spriteClip = {x, y, w, h};
}
// Obten el valor de la variable
Texture *Sprite::getTexture()
{
Texture *Sprite::getTexture() {
return texture;
}
// Establece el valor de la variable
void Sprite::setTexture(Texture *texture)
{
void Sprite::setTexture(Texture *texture) {
this->texture = texture;
}
// Obten el valor de la variable
SDL_Renderer *Sprite::getRenderer()
{
SDL_Renderer *Sprite::getRenderer() {
return renderer;
}
// Establece el valor de la variable
void Sprite::setRenderer(SDL_Renderer *renderer)
{
void Sprite::setRenderer(SDL_Renderer *renderer) {
this->renderer = renderer;
}
// Establece el valor de la variable
void Sprite::setEnabled(bool value)
{
void Sprite::setEnabled(bool value) {
enabled = value;
}
// Comprueba si el objeto está habilitado
bool Sprite::isEnabled()
{
bool Sprite::isEnabled() {
return enabled;
}
// Devuelve el rectangulo donde está el sprite
SDL_Rect Sprite::getRect()
{
SDL_Rect Sprite::getRect() {
SDL_Rect rect = {x, y, w, h};
return rect;
}
// Establece los valores de posición y tamaño del sprite
void Sprite::setRect(SDL_Rect rect)
{
void Sprite::setRect(SDL_Rect rect) {
x = rect.x;
y = rect.y;
w = rect.w;

View File

@@ -4,9 +4,8 @@
class Texture;
// Clase sprite
class Sprite
{
protected:
class Sprite {
protected:
int x; // Posición en el eje X donde dibujar el sprite
int y; // Posición en el eje Y donde dibujar el sprite
int w; // Ancho del sprite
@@ -18,7 +17,7 @@ protected:
bool enabled; // Indica si el sprite esta habilitado
public:
public:
// Constructor
Sprite(int x = 0, int y = 0, int w = 0, int h = 0, Texture *texture = nullptr, SDL_Renderer *renderer = nullptr);
Sprite(SDL_Rect rect, Texture *texture, SDL_Renderer *renderer);

View File

@@ -1,19 +1,19 @@
#include "text.h"
#include <fstream> // for char_traits, basic_ostream, basic_ifstream, ope...
#include <iostream> // for cout
#include "sprite.h" // for Sprite
#include "texture.h" // for Texture
#include "utils.h" // for color_t
// Llena una estructuta textFile_t desde un fichero
textFile_t LoadTextFile(std::string file, bool verbose)
{
textFile_t LoadTextFile(std::string file, bool verbose) {
textFile_t tf;
// Inicializa a cero el vector con las coordenadas
for (int i = 0; i < 128; ++i)
{
for (int i = 0; i < 128; ++i) {
tf.offset[i].x = 0;
tf.offset[i].y = 0;
tf.offset[i].w = 0;
@@ -23,8 +23,7 @@ textFile_t LoadTextFile(std::string file, bool verbose)
const std::string filename = file.substr(file.find_last_of("\\/") + 1).c_str();
std::ifstream rfile(file);
if (rfile.is_open() && rfile.good())
{
if (rfile.is_open() && rfile.good()) {
std::string buffer;
// Lee los dos primeros valores del fichero
@@ -39,11 +38,9 @@ textFile_t LoadTextFile(std::string file, bool verbose)
// lee el resto de datos del fichero
int index = 32;
int line_read = 0;
while (std::getline(rfile, buffer))
{
while (std::getline(rfile, buffer)) {
// Almacena solo las lineas impares
if (line_read % 2 == 1)
{
if (line_read % 2 == 1) {
tf.offset[index++].w = std::stoi(buffer);
}
@@ -53,25 +50,21 @@ textFile_t LoadTextFile(std::string file, bool verbose)
};
// Cierra el fichero
if (verbose)
{
if (verbose) {
std::cout << "Text loaded: " << filename.c_str() << std::endl;
}
rfile.close();
}
// El fichero no se puede abrir
else
{
if (verbose)
{
else {
if (verbose) {
std::cout << "Warning: Unable to open " << filename.c_str() << " file" << std::endl;
}
}
// Establece las coordenadas para cada caracter ascii de la cadena y su ancho
for (int i = 32; i < 128; ++i)
{
for (int i = 32; i < 128; ++i) {
tf.offset[i].x = ((i - 32) % 15) * tf.boxWidth;
tf.offset[i].y = ((i - 32) / 15) * tf.boxHeight;
}
@@ -80,16 +73,14 @@ textFile_t LoadTextFile(std::string file, bool verbose)
}
// Constructor
Text::Text(std::string bitmapFile, std::string textFile, SDL_Renderer *renderer)
{
Text::Text(std::string bitmapFile, std::string textFile, SDL_Renderer *renderer) {
// Carga los offsets desde el fichero
textFile_t tf = LoadTextFile(textFile);
// Inicializa variables desde la estructura
boxHeight = tf.boxHeight;
boxWidth = tf.boxWidth;
for (int i = 0; i < 128; ++i)
{
for (int i = 0; i < 128; ++i) {
offset[i].x = tf.offset[i].x;
offset[i].y = tf.offset[i].y;
offset[i].w = tf.offset[i].w;
@@ -104,16 +95,14 @@ Text::Text(std::string bitmapFile, std::string textFile, SDL_Renderer *renderer)
}
// Constructor
Text::Text(std::string textFile, Texture *texture, SDL_Renderer *renderer)
{
Text::Text(std::string textFile, Texture *texture, SDL_Renderer *renderer) {
// Carga los offsets desde el fichero
textFile_t tf = LoadTextFile(textFile);
// Inicializa variables desde la estructura
boxHeight = tf.boxHeight;
boxWidth = tf.boxWidth;
for (int i = 0; i < 128; ++i)
{
for (int i = 0; i < 128; ++i) {
offset[i].x = tf.offset[i].x;
offset[i].y = tf.offset[i].y;
offset[i].w = tf.offset[i].w;
@@ -128,13 +117,11 @@ Text::Text(std::string textFile, Texture *texture, SDL_Renderer *renderer)
}
// Constructor
Text::Text(textFile_t *textFile, Texture *texture, SDL_Renderer *renderer)
{
Text::Text(textFile_t *textFile, Texture *texture, SDL_Renderer *renderer) {
// Inicializa variables desde la estructura
boxHeight = textFile->boxHeight;
boxWidth = textFile->boxWidth;
for (int i = 0; i < 128; ++i)
{
for (int i = 0; i < 128; ++i) {
offset[i].x = textFile->offset[i].x;
offset[i].y = textFile->offset[i].y;
offset[i].w = textFile->offset[i].w;
@@ -149,30 +136,25 @@ Text::Text(textFile_t *textFile, Texture *texture, SDL_Renderer *renderer)
}
// Destructor
Text::~Text()
{
Text::~Text() {
delete sprite;
if (texture != nullptr)
{
if (texture != nullptr) {
delete texture;
}
}
// 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, std::string text, int kerning, int lenght) {
int shift = 0;
if (lenght == -1)
{
if (lenght == -1) {
lenght = text.length();
}
sprite->setPosY(y);
const int width = sprite->getWidth();
const int height = sprite->getHeight();
for (int i = 0; i < lenght; ++i)
{
for (int i = 0; i < lenght; ++i) {
const int index = text[i];
sprite->setSpriteClip(offset[index].x, offset[index].y, width, height);
sprite->setPosX(x + shift);
@@ -182,16 +164,14 @@ void Text::write(int x, int y, std::string text, int kerning, int lenght)
}
// Escribe el texto con colores
void Text::writeColored(int x, int y, std::string text, color_t color, int kerning, int lenght)
{
void Text::writeColored(int x, int y, std::string text, color_t color, int kerning, int lenght) {
sprite->getTexture()->setColor(color.r, color.g, color.b);
write(x, y, text, kerning, lenght);
sprite->getTexture()->setColor(255, 255, 255);
}
// Escribe el texto con sombra
void Text::writeShadowed(int x, int y, std::string text, color_t color, Uint8 shadowDistance, int kerning, int lenght)
{
void Text::writeShadowed(int x, int y, std::string text, color_t color, Uint8 shadowDistance, int kerning, int lenght) {
sprite->getTexture()->setColor(color.r, color.g, color.b);
write(x + shadowDistance, y + shadowDistance, text, kerning, lenght);
sprite->getTexture()->setColor(255, 255, 255);
@@ -199,57 +179,45 @@ void Text::writeShadowed(int x, int y, std::string text, color_t color, Uint8 sh
}
// 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, std::string text, int kerning, int lenght) {
x -= (Text::lenght(text, kerning) / 2);
write(x, y, text, kerning, lenght);
}
// Escribe texto con extras
void Text::writeDX(Uint8 flags, int x, int y, std::string text, int kerning, color_t textColor, Uint8 shadowDistance, color_t shadowColor, int lenght)
{
void Text::writeDX(Uint8 flags, int x, int y, std::string text, int kerning, color_t textColor, Uint8 shadowDistance, color_t shadowColor, int lenght) {
const bool centered = ((flags & TXT_CENTER) == TXT_CENTER);
const bool shadowed = ((flags & TXT_SHADOW) == TXT_SHADOW);
const bool colored = ((flags & TXT_COLOR) == TXT_COLOR);
const bool stroked = ((flags & TXT_STROKE) == TXT_STROKE);
if (centered)
{
if (centered) {
x -= (Text::lenght(text, kerning) / 2);
}
if (shadowed)
{
if (shadowed) {
writeColored(x + shadowDistance, y + shadowDistance, text, shadowColor, kerning, lenght);
}
if (stroked)
{
for (int dist = 1; dist <= shadowDistance; ++dist)
{
for (int dy = -dist; dy <= dist; ++dy)
{
for (int dx = -dist; dx <= dist; ++dx)
{
if (stroked) {
for (int dist = 1; dist <= shadowDistance; ++dist) {
for (int dy = -dist; dy <= dist; ++dy) {
for (int dx = -dist; dx <= dist; ++dx) {
writeColored(x + dx, y + dy, text, shadowColor, kerning, lenght);
}
}
}
}
if (colored)
{
if (colored) {
writeColored(x, y, text, textColor, kerning, lenght);
}
else
{
} else {
write(x, y, text, kerning, lenght);
}
}
// Obtiene la longitud en pixels de una cadena
int Text::lenght(std::string text, int kerning)
{
int Text::lenght(std::string text, int kerning) {
int shift = 0;
for (int i = 0; i < (int)text.length(); ++i)
@@ -260,19 +228,16 @@ int Text::lenght(std::string text, int kerning)
}
// Devuelve el valor de la variable
int Text::getCharacterSize()
{
int Text::getCharacterSize() {
return boxWidth;
}
// Recarga la textura
void Text::reLoadTexture()
{
void Text::reLoadTexture() {
sprite->getTexture()->reLoad();
}
// Establece si se usa un tamaño fijo de letra
void Text::setFixedWidth(bool value)
{
void Text::setFixedWidth(bool value) {
fixedWidth = value;
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <SDL3/SDL.h>
#include <string> // for string
class Sprite;
class Texture;
@@ -12,15 +13,13 @@ constexpr int TXT_SHADOW = 2;
constexpr int TXT_CENTER = 4;
constexpr int TXT_STROKE = 8;
struct offset_t
{
struct offset_t {
int x;
int y;
int w;
};
struct textFile_t
{
struct textFile_t {
int boxWidth; // Anchura de la caja de cada caracter en el png
int boxHeight; // Altura de la caja de cada caracter en el png
offset_t offset[128]; // Vector con las posiciones y ancho de cada letra
@@ -30,9 +29,8 @@ struct textFile_t
textFile_t LoadTextFile(std::string file, bool verbose = false);
// Clase texto. Pinta texto en pantalla a partir de un bitmap
class Text
{
private:
class Text {
private:
// Objetos y punteros
Sprite *sprite; // Objeto con los graficos para el texto
Texture *texture; // Textura con los bitmaps del texto
@@ -43,7 +41,7 @@ private:
bool fixedWidth; // Indica si el texto se ha de escribir con longitud fija en todas las letras
offset_t offset[128]; // Vector con las posiciones y ancho de cada letra
public:
public:
// Constructor
Text(std::string bitmapFile, std::string textFile, SDL_Renderer *renderer);
Text(std::string textFile, Texture *texture, SDL_Renderer *renderer);

View File

@@ -1,21 +1,21 @@
#include "texture.h"
#include <SDL3/SDL.h>
#include <stdlib.h> // for exit
#include <iostream> // for basic_ostream, operator<<, cout, endl
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h" // for stbi_failure_reason, stbi_image_free
SDL_ScaleMode Texture::currentScaleMode = SDL_SCALEMODE_NEAREST;
void Texture::setGlobalScaleMode(SDL_ScaleMode mode)
{
void Texture::setGlobalScaleMode(SDL_ScaleMode mode) {
currentScaleMode = mode;
}
// Constructor
Texture::Texture(SDL_Renderer *renderer, std::string path, bool verbose)
{
Texture::Texture(SDL_Renderer *renderer, std::string path, bool verbose) {
// Copia punteros
this->renderer = renderer;
this->path = path;
@@ -26,48 +26,38 @@ Texture::Texture(SDL_Renderer *renderer, std::string path, bool verbose)
height = 0;
// Carga el fichero en la textura
if (path != "")
{
if (path != "") {
loadFromFile(path, renderer, verbose);
}
}
// Destructor
Texture::~Texture()
{
Texture::~Texture() {
// Libera memoria
unload();
}
// Carga una imagen desde un fichero
bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer, bool verbose)
{
bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer, bool verbose) {
const std::string filename = path.substr(path.find_last_of("\\/") + 1);
int req_format = STBI_rgb_alpha;
int width, height, orig_format;
unsigned char *data = stbi_load(path.c_str(), &width, &height, &orig_format, req_format);
if (data == nullptr)
{
if (data == nullptr) {
SDL_Log("Loading image failed: %s", stbi_failure_reason());
exit(1);
}
else
{
if (verbose)
{
} else {
if (verbose) {
std::cout << "Image loaded: " << filename.c_str() << std::endl;
}
}
int pitch;
SDL_PixelFormat pixel_format;
if (req_format == STBI_rgb)
{
if (req_format == STBI_rgb) {
pitch = 3 * width; // 3 bytes por pixel * pixels per linea
pixel_format = SDL_PIXELFORMAT_RGB24;
}
else
{ // STBI_rgb_alpha (RGBA)
} else { // STBI_rgb_alpha (RGBA)
pitch = 4 * width;
pixel_format = SDL_PIXELFORMAT_RGBA32;
}
@@ -80,26 +70,18 @@ bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer, bool verbos
// Carga la imagen desde una ruta específica
SDL_Surface *loadedSurface = SDL_CreateSurfaceFrom(width, height, pixel_format, (void *)data, pitch);
if (loadedSurface == nullptr)
{
if (verbose)
{
if (loadedSurface == nullptr) {
if (verbose) {
std::cout << "Unable to load image " << path.c_str() << std::endl;
}
}
else
{
} else {
// Crea la textura desde los pixels de la surface
newTexture = SDL_CreateTextureFromSurface(renderer, loadedSurface);
if (newTexture == nullptr)
{
if (verbose)
{
if (newTexture == nullptr) {
if (verbose) {
std::cout << "Unable to create texture from " << path.c_str() << "! SDL Error: " << SDL_GetError() << std::endl;
}
}
else
{
} else {
// Obtiene las dimensiones de la imagen
this->width = loadedSurface->w;
this->height = loadedSurface->h;
@@ -119,16 +101,12 @@ bool Texture::loadFromFile(std::string path, SDL_Renderer *renderer, bool verbos
}
// Crea una textura en blanco
bool Texture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess access)
{
bool Texture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_TextureAccess access) {
// Crea una textura sin inicializar
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, access, width, height);
if (texture == nullptr)
{
if (texture == nullptr) {
std::cout << "Unable to create blank texture! SDL Error: " << SDL_GetError() << std::endl;
}
else
{
} else {
this->width = width;
this->height = height;
SDL_SetTextureScaleMode(texture, currentScaleMode);
@@ -138,11 +116,9 @@ bool Texture::createBlank(SDL_Renderer *renderer, int width, int height, SDL_Tex
}
// Libera la memoria de la textura
void Texture::unload()
{
void Texture::unload() {
// Libera la textura si existe
if (texture != nullptr)
{
if (texture != nullptr) {
SDL_DestroyTexture(texture);
texture = nullptr;
width = 0;
@@ -151,32 +127,27 @@ void Texture::unload()
}
// Establece el color para la modulacion
void Texture::setColor(Uint8 red, Uint8 green, Uint8 blue)
{
void Texture::setColor(Uint8 red, Uint8 green, Uint8 blue) {
SDL_SetTextureColorMod(texture, red, green, blue);
}
// Establece el blending
void Texture::setBlendMode(SDL_BlendMode blending)
{
void Texture::setBlendMode(SDL_BlendMode blending) {
SDL_SetTextureBlendMode(texture, blending);
}
// Establece el alpha para la modulación
void Texture::setAlpha(Uint8 alpha)
{
void Texture::setAlpha(Uint8 alpha) {
SDL_SetTextureAlphaMod(texture, alpha);
}
// Renderiza la textura en un punto específico
void Texture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, float zoomW, float zoomH, double angle, SDL_Point *center, SDL_FlipMode flip)
{
void Texture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, float zoomW, float zoomH, double angle, SDL_Point *center, SDL_FlipMode flip) {
// Establece el destino de renderizado en la pantalla
SDL_FRect renderQuad = {(float)x, (float)y, (float)width, (float)height};
// Obtiene las dimesiones del clip de renderizado
if (clip != nullptr)
{
if (clip != nullptr) {
renderQuad.w = (float)clip->w;
renderQuad.h = (float)clip->h;
}
@@ -187,8 +158,7 @@ void Texture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, float
// Convierte el clip a SDL_FRect
SDL_FRect srcRect;
SDL_FRect *srcRectPtr = nullptr;
if (clip != nullptr)
{
if (clip != nullptr) {
srcRect = {(float)clip->x, (float)clip->y, (float)clip->w, (float)clip->h};
srcRectPtr = &srcRect;
}
@@ -196,8 +166,7 @@ void Texture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, float
// Convierte el centro a SDL_FPoint
SDL_FPoint fCenter;
SDL_FPoint *fCenterPtr = nullptr;
if (center != nullptr)
{
if (center != nullptr) {
fCenter = {(float)center->x, (float)center->y};
fCenterPtr = &fCenter;
}
@@ -207,31 +176,26 @@ void Texture::render(SDL_Renderer *renderer, int x, int y, SDL_Rect *clip, float
}
// Establece la textura como objetivo de renderizado
void Texture::setAsRenderTarget(SDL_Renderer *renderer)
{
void Texture::setAsRenderTarget(SDL_Renderer *renderer) {
SDL_SetRenderTarget(renderer, texture);
}
// Obtiene el ancho de la imagen
int Texture::getWidth()
{
int Texture::getWidth() {
return width;
}
// Obtiene el alto de la imagen
int Texture::getHeight()
{
int Texture::getHeight() {
return height;
}
// Recarga la textura
bool Texture::reLoad()
{
bool Texture::reLoad() {
return loadFromFile(path, renderer);
}
// Obtiene la textura
SDL_Texture *Texture::getSDLTexture()
{
SDL_Texture *Texture::getSDLTexture() {
return texture;
}

View File

@@ -1,11 +1,11 @@
#pragma once
#include <SDL3/SDL.h>
#include <string> // for basic_string, string
class Texture
{
private:
class Texture {
private:
// Objetos y punteros
SDL_Texture *texture; // La textura
SDL_Renderer *renderer; // Renderizador donde dibujar la textura
@@ -15,7 +15,7 @@ private:
int height; // Alto de la imagen
std::string path; // Ruta de la imagen de la textura
public:
public:
static SDL_ScaleMode currentScaleMode; // Modo de escalado global para nuevas texturas
// Establece el modo de escalado global para nuevas texturas

View File

@@ -1,8 +1,11 @@
#include "title.h"
#include <SDL3/SDL.h>
#include <stdlib.h> // for rand
#include <iostream> // for basic_ostream, operator<<, basic_ostrea...
#include <string> // for basic_string, operator+, char_traits
#include "animatedsprite.h" // for AnimatedSprite
#include "asset.h" // for Asset
#include "const.h" // for GAMECANVAS_CENTER_X, SECTION_PROG_QUIT
@@ -19,8 +22,7 @@
#include "texture.h" // for Texture
// Constructor
Title::Title(SDL_Renderer *renderer, Screen *screen, Input *input, Asset *asset, options_t *options, Lang *lang, section_t *section)
{
Title::Title(SDL_Renderer *renderer, Screen *screen, Input *input, Asset *asset, options_t *options, Lang *lang, section_t *section) {
// Copia las direcciones de los punteros
this->renderer = renderer;
this->screen = screen;
@@ -68,8 +70,7 @@ Title::Title(SDL_Renderer *renderer, Screen *screen, Input *input, Asset *asset,
}
// Destructor
Title::~Title()
{
Title::~Title() {
delete eventHandler;
delete fade;
@@ -105,8 +106,7 @@ Title::~Title()
}
// Inicializa los valores
void Title::init()
{
void Title::init() {
// Inicializa variables
section->subsection = SUBSECTION_TITLE_1;
counter = TITLE_COUNTER;
@@ -144,14 +144,11 @@ void Title::init()
deviceIndex.push_back(0); // El primer mando encontrado. Si no ha encontrado ninguno es el teclado
// Si ha encontrado un mando se lo asigna al segundo jugador
if (input->gameControllerFound())
{
if (input->gameControllerFound()) {
options->input[1].id = availableInputDevices[deviceIndex[1]].id;
options->input[1].name = availableInputDevices[deviceIndex[1]].name;
options->input[1].deviceType = availableInputDevices[deviceIndex[1]].deviceType;
}
else
{ // Si no ha encontrado un mando, deshabilita la opción de jugar a 2 jugadores
} else { // Si no ha encontrado un mando, deshabilita la opción de jugar a 2 jugadores
menu.title->setSelectable(1, false);
menu.title->setGreyed(1, true);
}
@@ -216,8 +213,7 @@ void Title::init()
backgroundWindow.h = GAMECANVAS_HEIGHT;
// Inicializa los valores del vector con los valores del seno
for (int i = 0; i < 360; ++i)
{
for (int i = 0; i < 360; ++i) {
sin[i] = SDL_sinf((float)i * 3.14f / 180.0f);
}
@@ -226,8 +222,7 @@ void Title::init()
}
// Actualiza las variables del objeto
void Title::update()
{
void Title::update() {
// Actualiza el audio
JA_Update();
@@ -235,23 +230,19 @@ void Title::update()
checkInput();
// Calcula la lógica de los objetos
if (SDL_GetTicks() - ticks > ticksSpeed)
{
if (SDL_GetTicks() - ticks > ticksSpeed) {
// Actualiza el contador de ticks
ticks = SDL_GetTicks();
switch (section->subsection)
{
switch (section->subsection) {
// Sección 1 - Titulo desplazandose
case SUBSECTION_TITLE_1:
{
case SUBSECTION_TITLE_1: {
// Actualiza los objetos
coffeeBitmap->update();
crisisBitmap->update();
// Si los objetos han llegado a su destino, cambiamos de Sección
if (coffeeBitmap->hasFinished() && crisisBitmap->hasFinished())
{
if (coffeeBitmap->hasFinished() && crisisBitmap->hasFinished()) {
section->subsection = SUBSECTION_TITLE_2;
// Pantallazo blanco
@@ -262,12 +253,10 @@ void Title::update()
// Reproduce el efecto sonoro
JA_PlaySound(crashSound);
}
}
break;
} break;
// Sección 2 - Titulo vibrando
case SUBSECTION_TITLE_2:
{
case SUBSECTION_TITLE_2: {
// Agita la pantalla
static const int v[] = {-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 0};
static const int a = coffeeBitmap->getPosX();
@@ -281,20 +270,15 @@ void Title::update()
step++;
if (step == 33)
{
if (step == 33) {
section->subsection = SUBSECTION_TITLE_3;
}
}
break;
} break;
// Sección 3 - La pantalla de titulo con el menú y la música
case SUBSECTION_TITLE_3:
{
if (counter > 0)
{ // Reproduce la música
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{
case SUBSECTION_TITLE_3: {
if (counter > 0) { // Reproduce la música
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED)) {
JA_PlayMusic(titleMusic);
}
@@ -304,10 +288,8 @@ void Title::update()
// Actualiza la lógica del titulo
fade->update();
if (fade->hasEnded())
{
switch (postFade)
{
if (fade->hasEnded()) {
switch (postFade) {
case 0: // 1 PLAYER
section->name = SECTION_PROG_GAME;
section->subsection = SUBSECTION_GAME_PLAY_1P;
@@ -328,15 +310,12 @@ void Title::update()
case 3: // TIME OUT
counter = TITLE_COUNTER;
menu.active->reset();
if (demo)
{
if (demo) {
runDemoGame();
if (section->name != SECTION_PROG_QUIT)
{
if (section->name != SECTION_PROG_QUIT) {
runInstructions(m_auto);
}
}
else
} else
section->name = SECTION_PROG_LOGO;
break;
@@ -349,16 +328,13 @@ void Title::update()
updateBG();
// Comprueba las entradas para el menu
if (menuVisible == true)
{
if (menuVisible == true) {
menu.active->update();
}
// Comprueba si se ha seleccionado algún item del menú de titulo
if (menu.active->getName() == "TITLE")
{
switch (menu.active->getItemSelected())
{
if (menu.active->getName() == "TITLE") {
switch (menu.active->getItemSelected()) {
case 0: // 1 PLAYER -> Cambia al manu de selección de jugador
menu.active = menu.playerSelect;
break;
@@ -384,10 +360,8 @@ void Title::update()
}
// Comprueba si se ha seleccionado algún item del menú de selección de jugador
if (menu.active->getName() == "PLAYER_SELECT")
{
switch (menu.active->getItemSelected())
{
if (menu.active->getName() == "PLAYER_SELECT") {
switch (menu.active->getItemSelected()) {
case 0:
// Este item no se puede seleccionar y actua de titulo
break;
@@ -415,10 +389,8 @@ void Title::update()
}
// Comprueba si se ha seleccionado algún item de opciones
if (menu.active->getName() == "OPTIONS")
{
switch (menu.active->getItemSelected())
{
if (menu.active->getName() == "OPTIONS") {
switch (menu.active->getItemSelected()) {
case 0: // Difficulty
if (options->difficulty == DIFFICULTY_EASY)
options->difficulty = DIFFICULTY_NORMAL;
@@ -448,13 +420,10 @@ void Title::update()
case 6: // Display mode
switchFullScreenModeVar();
if (options->videoMode != 0)
{
if (options->videoMode != 0) {
menu.options->setSelectable(8, false);
menu.options->setGreyed(8, true);
}
else
{
} else {
menu.options->setSelectable(8, true);
menu.options->setGreyed(8, false);
}
@@ -508,33 +477,25 @@ void Title::update()
}
}
if (menu.active->getName() == "TITLE")
{
if (menu.active->getName() == "TITLE") {
counter--;
}
}
else if (counter == 0)
{
if (demo)
{
} else if (counter == 0) {
if (demo) {
runDemoGame();
if (section->name != SECTION_PROG_QUIT)
{
if (section->name != SECTION_PROG_QUIT) {
runInstructions(m_auto);
}
init();
demo = false;
counter = TITLE_COUNTER;
}
else
{
} else {
section->name = SECTION_PROG_LOGO;
}
}
// Sección Instrucciones
if (section->subsection == SUBSECTION_TITLE_INSTRUCTIONS)
{
if (section->subsection == SUBSECTION_TITLE_INSTRUCTIONS) {
runInstructions(m_auto);
counter = TITLE_COUNTER;
demo = true;
@@ -550,13 +511,10 @@ void Title::update()
}
// Dibuja el objeto en pantalla
void Title::render()
{
switch (section->subsection)
{
void Title::render() {
switch (section->subsection) {
// Sección 1 - Titulo desplazandose
case SUBSECTION_TITLE_1:
{
case SUBSECTION_TITLE_1: {
// Prepara para empezar a dibujar en la textura de juego
screen->start();
@@ -564,7 +522,10 @@ void Title::render()
screen->clean(bgColor);
// Dibuja el tileado de fondo
{ SDL_FRect fSrc = {(float)backgroundWindow.x, (float)backgroundWindow.y, (float)backgroundWindow.w, (float)backgroundWindow.h}; SDL_RenderTexture(renderer, background, &fSrc, nullptr); };
{
SDL_FRect fSrc = {(float)backgroundWindow.x, (float)backgroundWindow.y, (float)backgroundWindow.w, (float)backgroundWindow.h};
SDL_RenderTexture(renderer, background, &fSrc, nullptr);
};
// Dibuja el degradado
gradient->render();
@@ -575,20 +536,17 @@ void Title::render()
// Vuelca el contenido del renderizador en pantalla
screen->blit();
}
break;
} break;
// Sección 2 - Titulo vibrando
case SUBSECTION_TITLE_2:
{ // Reproduce el efecto sonoro
case SUBSECTION_TITLE_2: { // Reproduce el efecto sonoro
JA_PlaySound(crashSound);
// Agita la pantalla
const int v[] = {-1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 0};
const int a = coffeeBitmap->getPosX();
const int b = crisisBitmap->getPosX();
for (int n = 0; n < 11 * 3; ++n)
{
for (int n = 0; n < 11 * 3; ++n) {
// Prepara para empezar a dibujar en la textura de juego
screen->start();
@@ -596,7 +554,10 @@ void Title::render()
screen->clean(bgColor);
// Dibuja el tileado de fondo
{ SDL_FRect fSrc = {(float)backgroundWindow.x, (float)backgroundWindow.y, (float)backgroundWindow.w, (float)backgroundWindow.h}; SDL_RenderTexture(renderer, background, &fSrc, nullptr); };
{
SDL_FRect fSrc = {(float)backgroundWindow.x, (float)backgroundWindow.y, (float)backgroundWindow.w, (float)backgroundWindow.h};
SDL_RenderTexture(renderer, background, &fSrc, nullptr);
};
// Dibuja el degradado
gradient->render();
@@ -622,22 +583,23 @@ void Title::render()
break;
// Sección 3 - La pantalla de titulo con el menú y la música
case SUBSECTION_TITLE_3:
{ // Prepara para empezar a dibujar en la textura de juego
case SUBSECTION_TITLE_3: { // Prepara para empezar a dibujar en la textura de juego
screen->start();
// Limpia la pantalla
screen->clean(bgColor);
// Dibuja el tileado de fondo
{ SDL_FRect fSrc = {(float)backgroundWindow.x, (float)backgroundWindow.y, (float)backgroundWindow.w, (float)backgroundWindow.h}; SDL_RenderTexture(renderer, background, &fSrc, nullptr); };
{
SDL_FRect fSrc = {(float)backgroundWindow.x, (float)backgroundWindow.y, (float)backgroundWindow.w, (float)backgroundWindow.h};
SDL_RenderTexture(renderer, background, &fSrc, nullptr);
};
// Dibuja el degradado
gradient->render();
// Dibuja los objetos
if (menu.active->getName() != "OPTIONS")
{
if (menu.active->getName() != "OPTIONS") {
// Bitmaps con el logo/titulo del juego
coffeeBitmap->render();
crisisBitmap->render();
@@ -646,8 +608,7 @@ void Title::render()
text2->writeDX(TXT_CENTER | TXT_SHADOW, GAMECANVAS_CENTER_X, GAMECANVAS_HEIGHT - (BLOCK * 2), TEXT_COPYRIGHT, 1, noColor, 1, shdwTxtColor);
}
if (menuVisible == true)
{
if (menuVisible == true) {
menu.active->render();
}
@@ -655,8 +616,7 @@ void Title::render()
dustBitmapL->render();
// PRESS ANY KEY!
if ((counter % 50 > 14) && (menuVisible == false))
{
if ((counter % 50 > 14) && (menuVisible == false)) {
text1->writeDX(TXT_CENTER | TXT_SHADOW, GAMECANVAS_CENTER_X, PLAY_AREA_THIRD_QUARTER_Y + BLOCK, lang->getText(23), 1, noColor, 1, shdwTxtColor);
}
@@ -665,8 +625,7 @@ void Title::render()
// Vuelca el contenido del renderizador en pantalla
screen->blit();
}
break;
} break;
default:
break;
@@ -674,27 +633,21 @@ void Title::render()
}
// Comprueba los eventos
void Title::checkEvents()
{
void Title::checkEvents() {
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(eventHandler) != 0)
{
while (SDL_PollEvent(eventHandler) != 0) {
// Evento de salida de la aplicación
if (eventHandler->type == SDL_EVENT_QUIT)
{
if (eventHandler->type == SDL_EVENT_QUIT) {
section->name = SECTION_PROG_QUIT;
break;
}
else if (eventHandler->type == SDL_EVENT_RENDER_DEVICE_RESET || eventHandler->type == SDL_EVENT_RENDER_TARGETS_RESET)
{
else if (eventHandler->type == SDL_EVENT_RENDER_DEVICE_RESET || eventHandler->type == SDL_EVENT_RENDER_TARGETS_RESET) {
reLoadTextures();
}
if (section->subsection == SUBSECTION_TITLE_3)
{ // Si se pulsa alguna tecla durante la tercera sección del titulo
if ((eventHandler->type == SDL_EVENT_KEY_UP) || (eventHandler->type == SDL_EVENT_JOYSTICK_BUTTON_UP))
{
if (section->subsection == SUBSECTION_TITLE_3) { // Si se pulsa alguna tecla durante la tercera sección del titulo
if ((eventHandler->type == SDL_EVENT_KEY_UP) || (eventHandler->type == SDL_EVENT_JOYSTICK_BUTTON_UP)) {
// Muestra el menu
menuVisible = true;
@@ -706,39 +659,30 @@ void Title::checkEvents()
}
// Comprueba las entradas
void Title::checkInput()
{
if (input->checkInput(input_exit, REPEAT_FALSE))
{
void Title::checkInput() {
if (input->checkInput(input_exit, REPEAT_FALSE)) {
section->name = SECTION_PROG_QUIT;
}
else if (input->checkInput(input_window_fullscreen, REPEAT_FALSE))
{
else if (input->checkInput(input_window_fullscreen, REPEAT_FALSE)) {
screen->switchVideoMode();
}
else if (input->checkInput(input_window_dec_size, REPEAT_FALSE))
{
else if (input->checkInput(input_window_dec_size, REPEAT_FALSE)) {
screen->decWindowSize();
}
else if (input->checkInput(input_window_inc_size, REPEAT_FALSE))
{
else if (input->checkInput(input_window_inc_size, REPEAT_FALSE)) {
screen->incWindowSize();
}
}
// Actualiza el tileado de fondo
void Title::updateBG()
{
if (backgroundMode == 0)
{ // El tileado de fondo se desplaza en diagonal
void Title::updateBG() {
if (backgroundMode == 0) { // El tileado de fondo se desplaza en diagonal
++backgroundWindow.x %= 64;
++backgroundWindow.y %= 64;
}
else
{ // El tileado de fondo se desplaza en circulo
} else { // El tileado de fondo se desplaza en circulo
++backgroundCounter %= 360;
backgroundWindow.x = 128 + (int(sin[(backgroundCounter + 270) % 360] * 128));
backgroundWindow.y = 96 + (int(sin[(360 - backgroundCounter) % 360] * 96));
@@ -746,10 +690,8 @@ void Title::updateBG()
}
// Cambia el valor de la variable de modo de pantalla completa
void Title::switchFullScreenModeVar()
{
switch (options->videoMode)
{
void Title::switchFullScreenModeVar() {
switch (options->videoMode) {
case 0:
options->videoMode = SDL_WINDOW_FULLSCREEN;
break;
@@ -764,12 +706,10 @@ void Title::switchFullScreenModeVar()
}
// Actualiza los elementos de los menus
void Title::updateMenuLabels()
{
void Title::updateMenuLabels() {
int i = 0;
// DIFFICULTY
switch (options->difficulty)
{
switch (options->difficulty) {
case DIFFICULTY_EASY:
menu.options->setItemCaption(i, lang->getText(59) + ": " + lang->getText(66)); // EASY
break;
@@ -793,8 +733,7 @@ void Title::updateMenuLabels()
i++;
// PLAYER 1 CONTROLS - OPTIONS
switch (options->input[0].deviceType)
{
switch (options->input[0].deviceType) {
case INPUT_USE_KEYBOARD:
menu.options->setItemCaption(i, lang->getText(69)); // KEYBOARD
menu.options->setGreyed(i, false);
@@ -804,8 +743,7 @@ void Title::updateMenuLabels()
menu.options->setItemCaption(i, lang->getText(70)); // GAME CONTROLLER
if (!input->gameControllerFound())
menu.options->setGreyed(i, true);
else
{
else {
menu.options->setGreyed(i, false);
menu.options->setItemCaption(i, options->input[0].name);
}
@@ -822,8 +760,7 @@ void Title::updateMenuLabels()
i++;
// PLAYER 2 CONTROLS - OPTIONS
switch (options->input[1].deviceType)
{
switch (options->input[1].deviceType) {
case INPUT_USE_KEYBOARD:
menu.options->setItemCaption(i, lang->getText(69)); // KEYBOARD
menu.options->setGreyed(i, false);
@@ -833,8 +770,7 @@ void Title::updateMenuLabels()
menu.options->setItemCaption(i, lang->getText(70)); // GAME CONTROLLER
if (!input->gameControllerFound())
menu.options->setGreyed(i, true);
else
{
else {
menu.options->setGreyed(i, false);
menu.options->setItemCaption(i, options->input[1].name);
}
@@ -847,8 +783,7 @@ void Title::updateMenuLabels()
i++;
// LANGUAGE
switch (options->language)
{
switch (options->language) {
case es_ES:
menu.options->setItemCaption(i, lang->getText(8) + ": " + lang->getText(24)); // SPANISH
break;
@@ -872,8 +807,7 @@ void Title::updateMenuLabels()
i++;
// DISPLAY MODE - OPTIONS
switch (options->videoMode)
{
switch (options->videoMode) {
case 0:
menu.options->setItemCaption(i, lang->getText(4)); // WINDOW
break;
@@ -957,8 +891,7 @@ void Title::updateMenuLabels()
}
// Aplica las opciones de menu seleccionadas
void Title::applyOptions()
{
void Title::applyOptions() {
screen->setVideoMode(options->videoMode);
lang->setLang(options->language);
@@ -968,10 +901,8 @@ void Title::applyOptions()
}
// Bucle para el titulo del juego
void Title::run()
{
while (section->name == SECTION_PROG_TITLE)
{
void Title::run() {
while (section->name == SECTION_PROG_TITLE) {
update();
checkEvents();
render();
@@ -979,28 +910,24 @@ void Title::run()
}
// Ejecuta la parte donde se muestran las instrucciones
void Title::runInstructions(mode_e mode)
{
void Title::runInstructions(mode_e mode) {
instructions = new Instructions(renderer, screen, asset, input, lang, section);
instructions->run(mode);
delete instructions;
}
// Ejecuta el juego en modo demo
void Title::runDemoGame()
{
void Title::runDemoGame() {
demoGame = new Game(1, 0, renderer, screen, asset, lang, input, true, options, section);
demoGame->run();
delete demoGame;
}
// Modifica las opciones para los controles de los jugadores
bool Title::updatePlayerInputs(int numPlayer)
{
bool Title::updatePlayerInputs(int numPlayer) {
const int numDevices = availableInputDevices.size();
if (!input->gameControllerFound())
{ // Si no hay mandos se deja todo de manera prefijada
if (!input->gameControllerFound()) { // Si no hay mandos se deja todo de manera prefijada
deviceIndex[0] = 0;
deviceIndex[1] = 0;
@@ -1013,36 +940,27 @@ bool Title::updatePlayerInputs(int numPlayer)
options->input[1].deviceType = INPUT_USE_GAMECONTROLLER;
return true;
}
else
{ // Si hay mas de un dispositivo, se recorre el vector
if (options->console)
{
} else { // Si hay mas de un dispositivo, se recorre el vector
if (options->console) {
std::cout << "numplayer:" << numPlayer << std::endl;
std::cout << "deviceindex:" << deviceIndex[numPlayer] << std::endl;
}
// Incrementa el indice
if (deviceIndex[numPlayer] < numDevices - 1)
{
if (deviceIndex[numPlayer] < numDevices - 1) {
deviceIndex[numPlayer]++;
}
else
{
} else {
deviceIndex[numPlayer] = 0;
}
if (options->console)
{
if (options->console) {
std::cout << "deviceindex:" << deviceIndex[numPlayer] << std::endl;
}
// Si coincide con el del otro jugador, se lo intercambian
if (deviceIndex[0] == deviceIndex[1])
{
if (deviceIndex[0] == deviceIndex[1]) {
const int theOtherPlayer = (numPlayer + 1) % 2;
deviceIndex[theOtherPlayer]--;
if (deviceIndex[theOtherPlayer] < 0)
{
if (deviceIndex[theOtherPlayer] < 0) {
deviceIndex[theOtherPlayer] = numDevices - 1;
}
}
@@ -1056,18 +974,14 @@ bool Title::updatePlayerInputs(int numPlayer)
}
// Crea el mosaico de fondo del titulo
void Title::createTiledBackground()
{
void Title::createTiledBackground() {
// Crea la textura para el mosaico de fondo
background = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, GAMECANVAS_WIDTH * 2, GAMECANVAS_HEIGHT * 2);
if (background != nullptr)
{
if (background != nullptr) {
SDL_SetTextureScaleMode(background, Texture::currentScaleMode);
}
if (background == nullptr)
{
if (options->console)
{
if (background == nullptr) {
if (options->console) {
std::cout << "TitleSurface could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
}
}
@@ -1083,10 +997,8 @@ void Title::createTiledBackground()
// Rellena la textura con el tile
tile->setSpriteClip(0, 0, 64, 64);
for (int i = 0; i < 8; ++i)
{
for (int j = 0; j < 6; ++j)
{
for (int i = 0; i < 8; ++i) {
for (int j = 0; j < 6; ++j) {
tile->setPosX(i * 64);
tile->setPosY(j * 64);
tile->render();
@@ -1103,10 +1015,8 @@ void Title::createTiledBackground()
}
// Comprueba cuantos mandos hay conectados para gestionar el menu de opciones
void Title::checkInputDevices()
{
if (options->console)
{
void Title::checkInputDevices() {
if (options->console) {
std::cout << "Filling devices for options menu..." << std::endl;
}
input->discoverGameController();
@@ -1116,14 +1026,12 @@ void Title::checkInputDevices()
// Añade todos los mandos
if (numControllers > 0)
for (int i = 0; i < numControllers; ++i)
{
for (int i = 0; i < numControllers; ++i) {
temp.id = i;
temp.name = input->getControllerName(i);
temp.deviceType = INPUT_USE_GAMECONTROLLER;
availableInputDevices.push_back(temp);
if (options->console)
{
if (options->console) {
std::cout << "Device " << (int)availableInputDevices.size() << " - " << temp.name.c_str() << std::endl;
}
}
@@ -1133,16 +1041,14 @@ void Title::checkInputDevices()
temp.name = "KEYBOARD";
temp.deviceType = INPUT_USE_KEYBOARD;
availableInputDevices.push_back(temp);
if (options->console)
{
if (options->console) {
std::cout << "Device " << (int)availableInputDevices.size() << " - " << temp.name.c_str() << std::endl;
std::cout << std::endl;
}
}
// Recarga las texturas
void Title::reLoadTextures()
{
void Title::reLoadTextures() {
dustTexture->reLoad();
coffeeTexture->reLoad();
crisisTexture->reLoad();

View File

@@ -1,7 +1,9 @@
#pragma once
#include <SDL3/SDL.h>
#include <vector> // for vector
#include "instructions.h" // for mode_e
#include "utils.h" // for input_t, options_t, section_t
class AnimatedSprite;
@@ -28,11 +30,9 @@ constexpr int TITLE_COUNTER = 800;
// Cantidad de eventos de la pantalla de título
constexpr int TITLE_TOTAL_EVENTS = 2;
class Title
{
private:
struct menu_t
{
class Title {
private:
struct menu_t {
Menu *title; // Menu de la pantalla de título
Menu *options; // Menú de la pantalla de opciones
Menu *playerSelect; // Menu para elegir jugador
@@ -135,7 +135,7 @@ private:
// Recarga las texturas
void reLoadTextures();
public:
public:
// Constructor
Title(SDL_Renderer *renderer, Screen *screen, Input *input, Asset *asset, options_t *options, Lang *lang, section_t *section);

View File

@@ -1,25 +1,24 @@
#include "utils.h"
#include <stdlib.h> // for abs, free, malloc
#include <cmath> // for round, abs
// Calcula el cuadrado de la distancia entre dos puntos
double distanceSquared(int x1, int y1, int x2, int y2)
{
double distanceSquared(int x1, int y1, int x2, int y2) {
const int deltaX = x2 - x1;
const int deltaY = y2 - y1;
return deltaX * deltaX + deltaY * deltaY;
}
// Detector de colisiones entre dos circulos
bool checkCollision(circle_t &a, circle_t &b)
{
bool checkCollision(circle_t &a, circle_t &b) {
// Calcula el radio total al cuadrado
int totalRadiusSquared = a.r + b.r;
totalRadiusSquared = totalRadiusSquared * totalRadiusSquared;
// Si la distancia entre el centro de los circulos es inferior a la suma de sus radios
if (distanceSquared(a.x, a.y, b.x, b.y) < (totalRadiusSquared))
{
if (distanceSquared(a.x, a.y, b.x, b.y) < (totalRadiusSquared)) {
// Los circulos han colisionado
return true;
}
@@ -29,42 +28,30 @@ bool checkCollision(circle_t &a, circle_t &b)
}
// Detector de colisiones entre un circulo y un rectangulo
bool checkCollision(circle_t &a, SDL_Rect &b)
{
bool checkCollision(circle_t &a, SDL_Rect &b) {
// Closest point on collision box
int cX, cY;
// Find closest x offset
if (a.x < b.x)
{
if (a.x < b.x) {
cX = b.x;
}
else if (a.x > b.x + b.w)
{
} else if (a.x > b.x + b.w) {
cX = b.x + b.w;
}
else
{
} else {
cX = a.x;
}
// Find closest y offset
if (a.y < b.y)
{
if (a.y < b.y) {
cY = b.y;
}
else if (a.y > b.y + b.h)
{
} else if (a.y > b.y + b.h) {
cY = b.y + b.h;
}
else
{
} else {
cY = a.y;
}
// If the closest point is inside the circle_t
if (distanceSquared(a.x, a.y, cX, cY) < a.r * a.r)
{
if (distanceSquared(a.x, a.y, cX, cY) < a.r * a.r) {
// This box and the circle_t have collided
return true;
}
@@ -74,8 +61,7 @@ bool checkCollision(circle_t &a, SDL_Rect &b)
}
// Detector de colisiones entre dos rectangulos
bool checkCollision(SDL_Rect &a, SDL_Rect &b)
{
bool checkCollision(SDL_Rect &a, SDL_Rect &b) {
// Calcula las caras del rectangulo a
const int leftA = a.x;
const int rightA = a.x + a.w;
@@ -89,23 +75,19 @@ bool checkCollision(SDL_Rect &a, SDL_Rect &b)
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;
}
if (topA >= bottomB)
{
if (topA >= bottomB) {
return false;
}
if (rightA <= leftB)
{
if (rightA <= leftB) {
return false;
}
if (leftA >= rightB)
{
if (leftA >= rightB) {
return false;
}
@@ -114,29 +96,24 @@ bool checkCollision(SDL_Rect &a, SDL_Rect &b)
}
// Detector de colisiones entre un punto y un rectangulo
bool checkCollision(SDL_Point &p, SDL_Rect &r)
{
bool checkCollision(SDL_Point &p, SDL_Rect &r) {
// Comprueba si el punto está a la izquierda del rectangulo
if (p.x < r.x)
{
if (p.x < r.x) {
return false;
}
// Comprueba si el punto está a la derecha del rectangulo
if (p.x > r.x + r.w)
{
if (p.x > r.x + r.w) {
return false;
}
// Comprueba si el punto está por encima del rectangulo
if (p.y < r.y)
{
if (p.y < r.y) {
return false;
}
// Comprueba si el punto está por debajo del rectangulo
if (p.y > r.y + r.h)
{
if (p.y > r.y + r.h) {
return false;
}
@@ -145,29 +122,24 @@ bool checkCollision(SDL_Point &p, SDL_Rect &r)
}
// Detector de colisiones entre una linea horizontal y un rectangulo
bool checkCollision(h_line_t &l, SDL_Rect &r)
{
bool checkCollision(h_line_t &l, SDL_Rect &r) {
// Comprueba si la linea esta por encima del rectangulo
if (l.y < r.y)
{
if (l.y < r.y) {
return false;
}
// Comprueba si la linea esta por debajo del rectangulo
if (l.y >= r.y + r.h)
{
if (l.y >= r.y + r.h) {
return false;
}
// Comprueba si el inicio de la linea esta a la derecha del rectangulo
if (l.x1 >= r.x + r.w)
{
if (l.x1 >= r.x + r.w) {
return false;
}
// Comprueba si el final de la linea esta a la izquierda del rectangulo
if (l.x2 < r.x)
{
if (l.x2 < r.x) {
return false;
}
@@ -176,29 +148,24 @@ bool checkCollision(h_line_t &l, SDL_Rect &r)
}
// Detector de colisiones entre una linea vertical y un rectangulo
bool checkCollision(v_line_t &l, SDL_Rect &r)
{
bool checkCollision(v_line_t &l, SDL_Rect &r) {
// Comprueba si la linea esta por la izquierda del rectangulo
if (l.x < r.x)
{
if (l.x < r.x) {
return false;
}
// Comprueba si la linea esta por la derecha del rectangulo
if (l.x >= r.x + r.w)
{
if (l.x >= r.x + r.w) {
return false;
}
// Comprueba si el inicio de la linea esta debajo del rectangulo
if (l.y1 >= r.y + r.h)
{
if (l.y1 >= r.y + r.h) {
return false;
}
// Comprueba si el final de la linea esta encima del rectangulo
if (l.y2 < r.y)
{
if (l.y2 < r.y) {
return false;
}
@@ -207,29 +174,24 @@ bool checkCollision(v_line_t &l, SDL_Rect &r)
}
// Detector de colisiones entre una linea horizontal y un punto
bool checkCollision(h_line_t &l, SDL_Point &p)
{
bool checkCollision(h_line_t &l, SDL_Point &p) {
// Comprueba si el punto esta sobre la linea
if (p.y > l.y)
{
if (p.y > l.y) {
return false;
}
// Comprueba si el punto esta bajo la linea
if (p.y < l.y)
{
if (p.y < l.y) {
return false;
}
// Comprueba si el punto esta a la izquierda de la linea
if (p.x < l.x1)
{
if (p.x < l.x1) {
return false;
}
// Comprueba si el punto esta a la derecha de la linea
if (p.x > l.x2)
{
if (p.x > l.x2) {
return false;
}
@@ -238,8 +200,7 @@ bool checkCollision(h_line_t &l, SDL_Point &p)
}
// Detector de colisiones entre dos lineas
SDL_Point checkCollision(line_t &l1, line_t &l2)
{
SDL_Point checkCollision(line_t &l1, line_t &l2) {
const float x1 = l1.x1;
const float y1 = l1.y1;
const float x2 = l1.x2;
@@ -255,8 +216,7 @@ SDL_Point checkCollision(line_t &l1, line_t &l2)
float uB = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
// if uA and uB are between 0-1, lines are colliding
if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1)
{
if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {
// Calcula la intersección
const float x = x1 + (uA * (x2 - x1));
const float y = y1 + (uA * (y2 - y1));
@@ -267,8 +227,7 @@ SDL_Point checkCollision(line_t &l1, line_t &l2)
}
// Detector de colisiones entre dos lineas
SDL_Point checkCollision(d_line_t &l1, v_line_t &l2)
{
SDL_Point checkCollision(d_line_t &l1, v_line_t &l2) {
const float x1 = l1.x1;
const float y1 = l1.y1;
const float x2 = l1.x2;
@@ -284,8 +243,7 @@ SDL_Point checkCollision(d_line_t &l1, v_line_t &l2)
float uB = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1));
// if uA and uB are between 0-1, lines are colliding
if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1)
{
if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {
// Calcula la intersección
const float x = x1 + (uA * (x2 - x1));
const float y = y1 + (uA * (y2 - y1));
@@ -318,12 +276,10 @@ SDL_Point checkCollision(d_line_t &l1, v_line_t &l2)
}*/
// Normaliza una linea diagonal
void normalizeLine(d_line_t &l)
{
void normalizeLine(d_line_t &l) {
// Las lineas diagonales van de izquierda a derecha
// x2 mayor que x1
if (l.x2 < l.x1)
{
if (l.x2 < l.x1) {
const int x = l.x1;
const int y = l.y1;
l.x1 = l.x2;
@@ -334,35 +290,29 @@ void normalizeLine(d_line_t &l)
}
// Detector de colisiones entre un punto y una linea diagonal
bool checkCollision(SDL_Point &p, d_line_t &l)
{
bool checkCollision(SDL_Point &p, d_line_t &l) {
// Comprueba si el punto está en alineado con la linea
if (abs(p.x - l.x1) != abs(p.y - l.y1))
{
if (abs(p.x - l.x1) != abs(p.y - l.y1)) {
return false;
}
// Comprueba si está a la derecha de la linea
if (p.x > l.x1 && p.x > l.x2)
{
if (p.x > l.x1 && p.x > l.x2) {
return false;
}
// Comprueba si está a la izquierda de la linea
if (p.x < l.x1 && p.x < l.x2)
{
if (p.x < l.x1 && p.x < l.x2) {
return false;
}
// Comprueba si está por encima de la linea
if (p.y > l.y1 && p.y > l.y2)
{
if (p.y > l.y1 && p.y > l.y2) {
return false;
}
// Comprueba si está por debajo de la linea
if (p.y < l.y1 && p.y < l.y2)
{
if (p.y < l.y1 && p.y < l.y2) {
return false;
}
@@ -380,170 +330,135 @@ bool checkCollision(SDL_Point &p, d_line_t &l)
}
// Devuelve un color_t a partir de un string
color_t stringToColor(palette_e pal, std::string str)
{
if (pal == p_zxspectrum)
{
if (str == "black")
{
color_t stringToColor(palette_e pal, std::string str) {
if (pal == p_zxspectrum) {
if (str == "black") {
return {0x00, 0x00, 0x00};
}
else if (str == "bright_black")
{
else if (str == "bright_black") {
return {0x00, 0x00, 0x00};
}
else if (str == "blue")
{
else if (str == "blue") {
return {0x00, 0x00, 0xd8};
}
else if (str == "bright_blue")
{
else if (str == "bright_blue") {
return {0x00, 0x00, 0xFF};
}
else if (str == "red")
{
else if (str == "red") {
return {0xd8, 0x00, 0x00};
}
else if (str == "bright_red")
{
else if (str == "bright_red") {
return {0xFF, 0x00, 0x00};
}
else if (str == "magenta")
{
else if (str == "magenta") {
return {0xd8, 0x00, 0xd8};
}
else if (str == "bright_magenta")
{
else if (str == "bright_magenta") {
return {0xFF, 0x00, 0xFF};
}
else if (str == "green")
{
else if (str == "green") {
return {0x00, 0xd8, 0x00};
}
else if (str == "bright_green")
{
else if (str == "bright_green") {
return {0x00, 0xFF, 0x00};
}
else if (str == "cyan")
{
else if (str == "cyan") {
return {0x00, 0xd8, 0xd8};
}
else if (str == "bright_cyan")
{
else if (str == "bright_cyan") {
return {0x00, 0xFF, 0xFF};
}
else if (str == "yellow")
{
else if (str == "yellow") {
return {0xd8, 0xd8, 0x00};
}
else if (str == "bright_yellow")
{
else if (str == "bright_yellow") {
return {0xFF, 0xFF, 0x00};
}
else if (str == "white")
{
else if (str == "white") {
return {0xd8, 0xd8, 0xd8};
}
else if (str == "bright_white")
{
else if (str == "bright_white") {
return {0xFF, 0xFF, 0xFF};
}
}
else if (pal == p_zxarne)
{ // zxarne
if (str == "black")
{
else if (pal == p_zxarne) { // zxarne
if (str == "black") {
return {0x00, 0x00, 0x00};
}
else if (str == "bright_black")
{
else if (str == "bright_black") {
return {0x3C, 0x35, 0x1F};
}
else if (str == "blue")
{
else if (str == "blue") {
return {0x31, 0x33, 0x90};
}
else if (str == "bright_blue")
{
else if (str == "bright_blue") {
return {0x15, 0x59, 0xDB};
}
else if (str == "red")
{
else if (str == "red") {
return {0xA7, 0x32, 0x11};
}
else if (str == "bright_red")
{
else if (str == "bright_red") {
return {0xD8, 0x55, 0x25};
}
else if (str == "magenta")
{
else if (str == "magenta") {
return {0xA1, 0x55, 0x89};
}
else if (str == "bright_magenta")
{
else if (str == "bright_magenta") {
return {0xCD, 0x7A, 0x50};
}
else if (str == "green")
{
else if (str == "green") {
return {0x62, 0x9A, 0x31};
}
else if (str == "bright_green")
{
else if (str == "bright_green") {
return {0x9C, 0xD3, 0x3C};
}
else if (str == "cyan")
{
else if (str == "cyan") {
return {0x28, 0xA4, 0xCB};
}
else if (str == "bright_cyan")
{
else if (str == "bright_cyan") {
return {0x65, 0xDC, 0xD6};
}
else if (str == "yellow")
{
else if (str == "yellow") {
return {0xE8, 0xBC, 0x50};
}
else if (str == "bright_yellow")
{
else if (str == "bright_yellow") {
return {0xF1, 0xE7, 0x82};
}
else if (str == "white")
{
else if (str == "white") {
return {0xBF, 0xBF, 0xBD};
}
else if (str == "bright_white")
{
else if (str == "bright_white") {
return {0xF2, 0xF1, 0xED};
}
}
@@ -552,38 +467,28 @@ color_t stringToColor(palette_e pal, std::string str)
}
// Convierte una cadena en un valor booleano
bool stringToBool(std::string str)
{
if (str == "true")
{
bool stringToBool(std::string str) {
if (str == "true") {
return true;
}
else
{
} else {
return false;
}
}
// Convierte un valor booleano en una cadena
std::string boolToString(bool value)
{
if (value)
{
std::string boolToString(bool value) {
if (value) {
return "true";
}
else
{
} else {
return "false";
}
}
// Convierte una cadena a minusculas
std::string toLower(std::string str)
{
std::string toLower(std::string str) {
const char *original = str.c_str();
char *lower = (char *)malloc(str.size() + 1);
for (int i = 0; i < (int)str.size(); ++i)
{
for (int i = 0; i < (int)str.size(); ++i) {
char c = original[i];
lower[i] = (c >= 65 && c <= 90) ? c + 32 : c;
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <SDL3/SDL.h>
#include <string> // for string, basic_string
#include <vector> // for vector
@@ -10,65 +11,62 @@ constexpr int DIFFICULTY_NORMAL = 1;
constexpr int DIFFICULTY_HARD = 2;
// Estructura para definir un circulo
struct circle_t
{
struct circle_t {
int x;
int y;
int r;
};
// Estructura para definir una linea horizontal
struct h_line_t
{
struct h_line_t {
int x1, x2, y;
};
// Estructura para definir una linea vertical
struct v_line_t
{
struct v_line_t {
int x, y1, y2;
};
// Estructura para definir una linea diagonal
struct d_line_t
{
struct d_line_t {
int x1, y1, x2, y2;
};
// Estructura para definir una linea
struct line_t
{
struct line_t {
int x1, y1, x2, y2;
};
// Estructura para definir un color
struct color_t
{
struct color_t {
Uint8 r;
Uint8 g;
Uint8 b;
color_t() : r(0), g(0), b(0) {} // Constructor por defecto
color_t(Uint8 red, Uint8 green, Uint8 blue) : r(red), g(green), b(blue) {}
color_t()
: r(0),
g(0),
b(0) {} // Constructor por defecto
color_t(Uint8 red, Uint8 green, Uint8 blue)
: r(red),
g(green),
b(blue) {}
};
// Tipos de paleta
enum palette_e
{
enum palette_e {
p_zxspectrum,
p_zxarne
};
// Estructura para saber la seccion y subseccion del programa
struct section_t
{
struct section_t {
Uint8 name;
Uint8 subsection;
};
// Estructura para mapear el teclado usado en la demo
struct demoKeys_t
{
struct demoKeys_t {
Uint8 left;
Uint8 right;
Uint8 noInput;
@@ -78,23 +76,20 @@ struct demoKeys_t
};
// Estructura para albergar métodos de control
struct input_t
{
struct input_t {
int id; // Identificador en el vector de mandos
std::string name; // Nombre del dispositivo
Uint8 deviceType; // Tipo de dispositivo (teclado o mando)
};
// Estructura con opciones de la pantalla
struct op_screen_t
{
struct op_screen_t {
int windowWidth; // Ancho de la ventana
int windowHeight; // Alto de la ventana
};
// Estructura con todas las opciones de configuración del programa
struct options_t
{
struct options_t {
Uint8 difficulty; // Dificultad del juego
Uint8 playerSelected; // Jugador seleccionado para el modo 1P
std::vector<input_t> input; // Modo de control (teclado o mando)

View File

@@ -1,9 +1,9 @@
#include "writer.h"
#include "text.h" // for Text
// Constructor
Writer::Writer(Text *text)
{
Writer::Writer(Text *text) {
// Copia los punteros
this->text = text;
@@ -23,37 +23,27 @@ Writer::Writer(Text *text)
}
// Actualiza el objeto
void Writer::update()
{
if (enabled)
{
if (!completed)
{ // No completado
if (writingCounter > 0)
{
void Writer::update() {
if (enabled) {
if (!completed) { // No completado
if (writingCounter > 0) {
writingCounter--;
}
else if (writingCounter == 0)
{
else if (writingCounter == 0) {
index++;
writingCounter = speed;
}
if (index == lenght)
{
if (index == lenght) {
completed = true;
}
}
if (completed)
{ // Completado
if (enabledCounter > 0)
{
if (completed) { // Completado
if (enabledCounter > 0) {
enabledCounter--;
}
else if (enabledCounter == 0)
{
} else if (enabledCounter == 0) {
finished = true;
}
}
@@ -61,78 +51,65 @@ void Writer::update()
}
// Dibuja el objeto en pantalla
void Writer::render()
{
if (enabled)
{
void Writer::render() {
if (enabled) {
text->write(posX, posY, caption, kerning, index);
}
}
// Establece el valor de la variable
void Writer::setPosX(int value)
{
void Writer::setPosX(int value) {
posX = value;
}
// Establece el valor de la variable
void Writer::setPosY(int value)
{
void Writer::setPosY(int value) {
posY = value;
}
// Establece el valor de la variable
void Writer::setKerning(int value)
{
void Writer::setKerning(int value) {
kerning = value;
}
// Establece el valor de la variable
void Writer::setCaption(std::string text)
{
void Writer::setCaption(std::string text) {
caption = text;
lenght = text.length();
}
// Establece el valor de la variable
void Writer::setSpeed(int value)
{
void Writer::setSpeed(int value) {
speed = value;
writingCounter = value;
}
// Establece el valor de la variable
void Writer::setEnabled(bool value)
{
void Writer::setEnabled(bool value) {
enabled = value;
}
// Obtiene el valor de la variable
bool Writer::IsEnabled()
{
bool Writer::IsEnabled() {
return enabled;
}
// Establece el valor de la variable
void Writer::setEnabledCounter(int time)
{
void Writer::setEnabledCounter(int time) {
enabledCounter = time;
}
// Obtiene el valor de la variable
int Writer::getEnabledCounter()
{
int Writer::getEnabledCounter() {
return enabledCounter;
}
// Centra la cadena de texto a un punto X
void Writer::center(int x)
{
void Writer::center(int x) {
setPosX(x - (text->lenght(caption, kerning) / 2));
}
// Obtiene el valor de la variable
bool Writer::hasFinished()
{
bool Writer::hasFinished() {
return finished;
}

View File

@@ -4,9 +4,8 @@
class Text;
// Clase Writer. Pinta texto en pantalla letra a letra a partir de una cadena y un bitmap
class Writer
{
private:
class Writer {
private:
// Objetos y punteros
Text *text; // Objeto encargado de escribir el texto
@@ -24,7 +23,7 @@ private:
int enabledCounter; // Temporizador para deshabilitar el objeto
bool finished; // Indica si ya ha terminado
public:
public:
// Constructor
Writer(Text *text);