pasaeta loca de clang-format (despres m'arrepentiré pero bueno)
This commit is contained in:
1 parent
734c220fb0
commit
dabba41179
112 files changed
+22361
-26474
No files matched your search
@@ -0,0 +1,11 @@
|
|||||||
|
BasedOnStyle: Google
|
||||||
|
IndentWidth: 4
|
||||||
|
ColumnLimit: 0 # Sin límite de longitud de línea
|
||||||
|
BreakBeforeBraces: Attach # Llaves en la misma línea
|
||||||
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AlignOperands: false
|
||||||
|
AlignAfterOpenBracket: DontAlign
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
Checks: >
|
||||||
|
readability-identifier-naming,
|
||||||
|
readability-*,
|
||||||
|
modernize-*,
|
||||||
|
clang-analyzer-*
|
||||||
|
|
||||||
|
WarningsAsErrors: '*'
|
||||||
|
|
||||||
|
HeaderFilterRegex: '.*'
|
||||||
|
FormatStyle: file
|
||||||
|
|
||||||
|
CheckOptions:
|
||||||
|
# Variables locales en snake_case
|
||||||
|
- { key: readability-identifier-naming.VariableCase, value: lower_case }
|
||||||
|
|
||||||
|
# Miembros privados en snake_case con sufijo _
|
||||||
|
- { key: readability-identifier-naming.PrivateMemberCase, value: lower_case }
|
||||||
|
- { key: readability-identifier-naming.PrivateMemberSuffix, value: _ }
|
||||||
|
|
||||||
|
# Namespaces en CamelCase
|
||||||
|
- { key: readability-identifier-naming.NamespaceCase, value: CamelCase }
|
||||||
|
|
||||||
|
# Constantes y constexpr en UPPER_CASE
|
||||||
|
- { key: readability-identifier-naming.GlobalConstantCase, value: UPPER_CASE }
|
||||||
|
- { key: readability-identifier-naming.ConstexprVariableCase, value: UPPER_CASE }
|
||||||
|
- { key: readability-identifier-naming.LocalConstantCase, value: UPPER_CASE }
|
||||||
|
|
||||||
|
# Clases, structs y enums en CamelCase
|
||||||
|
- { key: readability-identifier-naming.ClassCase, value: CamelCase }
|
||||||
|
- { key: readability-identifier-naming.StructCase, value: CamelCase }
|
||||||
|
- { key: readability-identifier-naming.EnumCase, value: CamelCase }
|
||||||
|
|
||||||
|
# Valores de enums en UPPER_CASE
|
||||||
|
- { key: readability-identifier-naming.EnumConstantCase, value: UPPER_CASE }
|
||||||
|
|
||||||
|
# Métodos en camelBack
|
||||||
|
- { key: readability-identifier-naming.MethodCase, value: camelBack }
|
||||||
|
|
||||||
|
# Funciones en camelBack
|
||||||
|
- { key: readability-identifier-naming.FunctionCase, value: camelBack }
|
||||||
+181
-221
@@ -1,280 +1,240 @@
|
|||||||
#include "animated_sprite.h"
|
#include "animated_sprite.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_LogWarn, SDL_LogCategory, SDL_LogError
|
#include <SDL3/SDL.h> // Para SDL_LogWarn, SDL_LogCategory, SDL_LogError
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
#include <algorithm> // Para min
|
|
||||||
#include <fstream> // Para basic_istream, basic_ifstream, basic_ios, ifst...
|
|
||||||
#include <sstream> // Para basic_stringstream
|
|
||||||
#include <stdexcept> // Para runtime_error
|
|
||||||
#include <utility> // Para pair
|
|
||||||
|
|
||||||
#include "texture.h" // Para Texture
|
#include <algorithm> // Para min
|
||||||
#include "utils.h" // Para printWithDots
|
#include <fstream> // Para basic_istream, basic_ifstream, basic_ios, ifst...
|
||||||
|
#include <sstream> // Para basic_stringstream
|
||||||
|
#include <stdexcept> // Para runtime_error
|
||||||
|
#include <utility> // Para pair
|
||||||
|
|
||||||
|
#include "texture.h" // Para Texture
|
||||||
|
#include "utils.h" // Para printWithDots
|
||||||
|
|
||||||
// Carga las animaciones en un vector(Animations) desde un fichero
|
// Carga las animaciones en un vector(Animations) desde un fichero
|
||||||
AnimationsFileBuffer loadAnimationsFromFile(const std::string &file_path)
|
AnimationsFileBuffer loadAnimationsFromFile(const std::string &file_path) {
|
||||||
{
|
std::ifstream file(file_path);
|
||||||
std::ifstream file(file_path);
|
if (!file) {
|
||||||
if (!file)
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Fichero no encontrado %s", file_path.c_str());
|
||||||
{
|
throw std::runtime_error("Fichero no encontrado: " + file_path);
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Fichero no encontrado %s", file_path.c_str());
|
}
|
||||||
throw std::runtime_error("Fichero no encontrado: " + file_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
printWithDots("Animation : ", file_path.substr(file_path.find_last_of("\\/") + 1), "[ LOADED ]");
|
printWithDots("Animation : ", file_path.substr(file_path.find_last_of("\\/") + 1), "[ LOADED ]");
|
||||||
|
|
||||||
std::vector<std::string> buffer;
|
std::vector<std::string> buffer;
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(file, line))
|
while (std::getline(file, line)) {
|
||||||
{
|
if (!line.empty())
|
||||||
if (!line.empty())
|
buffer.push_back(line);
|
||||||
buffer.push_back(line);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path)
|
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path)
|
||||||
: MovingSprite(texture)
|
: MovingSprite(texture) {
|
||||||
{
|
// Carga las animaciones
|
||||||
// Carga las animaciones
|
if (!file_path.empty()) {
|
||||||
if (!file_path.empty())
|
AnimationsFileBuffer v = loadAnimationsFromFile(file_path);
|
||||||
{
|
loadFromAnimationsFileBuffer(v);
|
||||||
AnimationsFileBuffer v = loadAnimationsFromFile(file_path);
|
}
|
||||||
loadFromAnimationsFileBuffer(v);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer &animations)
|
AnimatedSprite::AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer &animations)
|
||||||
: MovingSprite(texture)
|
: MovingSprite(texture) {
|
||||||
{
|
if (!animations.empty()) {
|
||||||
if (!animations.empty())
|
loadFromAnimationsFileBuffer(animations);
|
||||||
{
|
}
|
||||||
loadFromAnimationsFileBuffer(animations);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el índice de la animación a partir del nombre
|
// Obtiene el índice de la animación a partir del nombre
|
||||||
int AnimatedSprite::getIndex(const std::string &name)
|
int AnimatedSprite::getIndex(const std::string &name) {
|
||||||
{
|
auto it = animation_indices_.find(name);
|
||||||
auto it = animation_indices_.find(name);
|
if (it != animation_indices_.end()) {
|
||||||
if (it != animation_indices_.end())
|
// Si se encuentra la animación en el mapa, devuelve su índice
|
||||||
{
|
return it->second;
|
||||||
// Si se encuentra la animación en el mapa, devuelve su índice
|
}
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si no se encuentra, muestra una advertencia y devuelve -1
|
// Si no se encuentra, muestra una advertencia y devuelve -1
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "** Warning: could not find \"%s\" animation", name.c_str());
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "** Warning: could not find \"%s\" animation", name.c_str());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calcula el frame correspondiente a la animación
|
// Calcula el frame correspondiente a la animación
|
||||||
void AnimatedSprite::animate()
|
void AnimatedSprite::animate() {
|
||||||
{
|
if (animations_[current_animation_].speed == 0) {
|
||||||
if (animations_[current_animation_].speed == 0)
|
return;
|
||||||
{
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calcula el frame actual a partir del contador
|
// Calcula el frame actual a partir del contador
|
||||||
animations_[current_animation_].current_frame = animations_[current_animation_].counter / animations_[current_animation_].speed;
|
animations_[current_animation_].current_frame = animations_[current_animation_].counter / animations_[current_animation_].speed;
|
||||||
|
|
||||||
// Si alcanza el final de la animación, reinicia el contador de la animación
|
// 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
|
// en función de la variable loop y coloca el nuevo frame
|
||||||
if (animations_[current_animation_].current_frame >= animations_[current_animation_].frames.size())
|
if (animations_[current_animation_].current_frame >= animations_[current_animation_].frames.size()) {
|
||||||
{
|
if (animations_[current_animation_].loop == -1) { // Si no hay loop, deja el último frame
|
||||||
if (animations_[current_animation_].loop == -1)
|
animations_[current_animation_].current_frame = animations_[current_animation_].frames.size();
|
||||||
{ // Si no hay loop, deja el último frame
|
animations_[current_animation_].completed = true;
|
||||||
animations_[current_animation_].current_frame = animations_[current_animation_].frames.size();
|
} else { // Si hay loop, vuelve al frame indicado
|
||||||
animations_[current_animation_].completed = true;
|
animations_[current_animation_].counter = 0;
|
||||||
}
|
animations_[current_animation_].current_frame = animations_[current_animation_].loop;
|
||||||
else
|
}
|
||||||
{ // Si hay loop, vuelve al frame indicado
|
}
|
||||||
animations_[current_animation_].counter = 0;
|
// En caso contrario
|
||||||
animations_[current_animation_].current_frame = animations_[current_animation_].loop;
|
else {
|
||||||
}
|
// Escoge el frame correspondiente de la animación
|
||||||
}
|
setSpriteClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]);
|
||||||
// En caso contrario
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Escoge el frame correspondiente de la animación
|
|
||||||
setSpriteClip(animations_[current_animation_].frames[animations_[current_animation_].current_frame]);
|
|
||||||
|
|
||||||
// Incrementa el contador de la animacion
|
// Incrementa el contador de la animacion
|
||||||
animations_[current_animation_].counter++;
|
animations_[current_animation_].counter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba si ha terminado la animación
|
// Comprueba si ha terminado la animación
|
||||||
bool AnimatedSprite::animationIsCompleted()
|
bool AnimatedSprite::animationIsCompleted() {
|
||||||
{
|
return animations_[current_animation_].completed;
|
||||||
return animations_[current_animation_].completed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece la animacion actual
|
// Establece la animacion actual
|
||||||
void AnimatedSprite::setCurrentAnimation(const std::string &name, bool reset)
|
void AnimatedSprite::setCurrentAnimation(const std::string &name, bool reset) {
|
||||||
{
|
const auto NEW_ANIMATION = getIndex(name);
|
||||||
const auto NEW_ANIMATION = getIndex(name);
|
if (current_animation_ != NEW_ANIMATION) {
|
||||||
if (current_animation_ != NEW_ANIMATION)
|
const auto OLD_ANIMATION = current_animation_;
|
||||||
{
|
current_animation_ = NEW_ANIMATION;
|
||||||
const auto OLD_ANIMATION = current_animation_;
|
if (reset) {
|
||||||
current_animation_ = NEW_ANIMATION;
|
animations_[current_animation_].current_frame = 0;
|
||||||
if (reset)
|
animations_[current_animation_].counter = 0;
|
||||||
{
|
animations_[current_animation_].completed = false;
|
||||||
animations_[current_animation_].current_frame = 0;
|
} else {
|
||||||
animations_[current_animation_].counter = 0;
|
animations_[current_animation_].current_frame = std::min(animations_[OLD_ANIMATION].current_frame, animations_[current_animation_].frames.size());
|
||||||
animations_[current_animation_].completed = false;
|
animations_[current_animation_].counter = animations_[OLD_ANIMATION].counter;
|
||||||
}
|
animations_[current_animation_].completed = animations_[OLD_ANIMATION].completed;
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
animations_[current_animation_].current_frame = std::min(animations_[OLD_ANIMATION].current_frame, animations_[current_animation_].frames.size());
|
|
||||||
animations_[current_animation_].counter = animations_[OLD_ANIMATION].counter;
|
|
||||||
animations_[current_animation_].completed = animations_[OLD_ANIMATION].completed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece la animacion actual
|
// Establece la animacion actual
|
||||||
void AnimatedSprite::setCurrentAnimation(int index, bool reset)
|
void AnimatedSprite::setCurrentAnimation(int index, bool reset) {
|
||||||
{
|
const auto NEW_ANIMATION = index;
|
||||||
const auto NEW_ANIMATION = index;
|
if (current_animation_ != NEW_ANIMATION) {
|
||||||
if (current_animation_ != NEW_ANIMATION)
|
const auto OLD_ANIMATION = current_animation_;
|
||||||
{
|
current_animation_ = NEW_ANIMATION;
|
||||||
const auto OLD_ANIMATION = current_animation_;
|
if (reset) {
|
||||||
current_animation_ = NEW_ANIMATION;
|
animations_[current_animation_].current_frame = 0;
|
||||||
if (reset)
|
animations_[current_animation_].counter = 0;
|
||||||
{
|
animations_[current_animation_].completed = false;
|
||||||
animations_[current_animation_].current_frame = 0;
|
} else {
|
||||||
animations_[current_animation_].counter = 0;
|
animations_[current_animation_].current_frame = std::min(animations_[OLD_ANIMATION].current_frame, animations_[current_animation_].frames.size());
|
||||||
animations_[current_animation_].completed = false;
|
animations_[current_animation_].counter = animations_[OLD_ANIMATION].counter;
|
||||||
}
|
animations_[current_animation_].completed = animations_[OLD_ANIMATION].completed;
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
animations_[current_animation_].current_frame = std::min(animations_[OLD_ANIMATION].current_frame, animations_[current_animation_].frames.size());
|
|
||||||
animations_[current_animation_].counter = animations_[OLD_ANIMATION].counter;
|
|
||||||
animations_[current_animation_].completed = animations_[OLD_ANIMATION].completed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza las variables del objeto
|
// Actualiza las variables del objeto
|
||||||
void AnimatedSprite::update()
|
void AnimatedSprite::update() {
|
||||||
{
|
animate();
|
||||||
animate();
|
MovingSprite::update();
|
||||||
MovingSprite::update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reinicia la animación
|
// Reinicia la animación
|
||||||
void AnimatedSprite::resetAnimation()
|
void AnimatedSprite::resetAnimation() {
|
||||||
{
|
animations_[current_animation_].current_frame = 0;
|
||||||
animations_[current_animation_].current_frame = 0;
|
animations_[current_animation_].counter = 0;
|
||||||
animations_[current_animation_].counter = 0;
|
animations_[current_animation_].completed = false;
|
||||||
animations_[current_animation_].completed = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carga la animación desde un vector de cadenas
|
// Carga la animación desde un vector de cadenas
|
||||||
void AnimatedSprite::loadFromAnimationsFileBuffer(const AnimationsFileBuffer &source)
|
void AnimatedSprite::loadFromAnimationsFileBuffer(const AnimationsFileBuffer &source) {
|
||||||
{
|
float frame_width = 1;
|
||||||
float frame_width = 1;
|
float frame_height = 1;
|
||||||
float frame_height = 1;
|
int frames_per_row = 1;
|
||||||
int frames_per_row = 1;
|
int max_tiles = 1;
|
||||||
int max_tiles = 1;
|
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
while (index < source.size())
|
while (index < source.size()) {
|
||||||
{
|
std::string line = source.at(index);
|
||||||
std::string line = source.at(index);
|
|
||||||
|
|
||||||
// Parsea el fichero para buscar variables y valores
|
// Parsea el fichero para buscar variables y valores
|
||||||
if (line != "[animation]")
|
if (line != "[animation]") {
|
||||||
{
|
// Encuentra la posición del carácter '='
|
||||||
// Encuentra la posición del carácter '='
|
size_t pos = line.find("=");
|
||||||
size_t pos = line.find("=");
|
|
||||||
|
|
||||||
// Procesa las dos subcadenas
|
// Procesa las dos subcadenas
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos) {
|
||||||
{
|
std::string key = line.substr(0, pos);
|
||||||
std::string key = line.substr(0, pos);
|
int value = std::stoi(line.substr(pos + 1));
|
||||||
int value = std::stoi(line.substr(pos + 1));
|
if (key == "frame_width")
|
||||||
if (key == "frame_width")
|
frame_width = value;
|
||||||
frame_width = value;
|
else if (key == "frame_height")
|
||||||
else if (key == "frame_height")
|
frame_height = value;
|
||||||
frame_height = value;
|
else
|
||||||
else
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: unknown parameter %s", key.c_str());
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: unknown parameter %s", key.c_str());
|
|
||||||
|
|
||||||
frames_per_row = texture_->getWidth() / frame_width;
|
frames_per_row = texture_->getWidth() / frame_width;
|
||||||
const int w = texture_->getWidth() / frame_width;
|
const int w = texture_->getWidth() / frame_width;
|
||||||
const int h = texture_->getHeight() / frame_height;
|
const int h = texture_->getHeight() / frame_height;
|
||||||
max_tiles = w * h;
|
max_tiles = w * h;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si la línea contiene el texto [animation] se realiza el proceso de carga de una animación
|
// Si la línea contiene el texto [animation] se realiza el proceso de carga de una animación
|
||||||
if (line == "[animation]")
|
if (line == "[animation]") {
|
||||||
{
|
Animation animation;
|
||||||
Animation animation;
|
do {
|
||||||
do
|
index++;
|
||||||
{
|
line = source.at(index);
|
||||||
index++;
|
size_t pos = line.find("=");
|
||||||
line = source.at(index);
|
|
||||||
size_t pos = line.find("=");
|
|
||||||
|
|
||||||
if (pos != std::string::npos)
|
if (pos != std::string::npos) {
|
||||||
{
|
std::string key = line.substr(0, pos);
|
||||||
std::string key = line.substr(0, pos);
|
std::string value = line.substr(pos + 1);
|
||||||
std::string value = line.substr(pos + 1);
|
|
||||||
|
|
||||||
if (key == "name")
|
if (key == "name")
|
||||||
animation.name = value;
|
animation.name = value;
|
||||||
else if (key == "speed")
|
else if (key == "speed")
|
||||||
animation.speed = std::stoi(value);
|
animation.speed = std::stoi(value);
|
||||||
else if (key == "loop")
|
else if (key == "loop")
|
||||||
animation.loop = std::stoi(value);
|
animation.loop = std::stoi(value);
|
||||||
else if (key == "frames")
|
else if (key == "frames") {
|
||||||
{
|
// Se introducen los valores separados por comas en un vector
|
||||||
// Se introducen los valores separados por comas en un vector
|
std::stringstream ss(value);
|
||||||
std::stringstream ss(value);
|
std::string tmp;
|
||||||
std::string tmp;
|
SDL_FRect rect = {0, 0, frame_width, frame_height};
|
||||||
SDL_FRect rect = {0, 0, frame_width, frame_height};
|
while (getline(ss, tmp, ',')) {
|
||||||
while (getline(ss, tmp, ','))
|
// Comprueba que el tile no sea mayor que el máximo índice permitido
|
||||||
{
|
const int num_tile = std::stoi(tmp);
|
||||||
// Comprueba que el tile no sea mayor que el máximo índice permitido
|
if (num_tile <= max_tiles) {
|
||||||
const int num_tile = std::stoi(tmp);
|
rect.x = (num_tile % frames_per_row) * frame_width;
|
||||||
if (num_tile <= max_tiles)
|
rect.y = (num_tile / frames_per_row) * frame_height;
|
||||||
{
|
animation.frames.emplace_back(rect);
|
||||||
rect.x = (num_tile % frames_per_row) * frame_width;
|
}
|
||||||
rect.y = (num_tile / frames_per_row) * frame_height;
|
}
|
||||||
animation.frames.emplace_back(rect);
|
} else
|
||||||
}
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: unknown parameter %s", key.c_str());
|
||||||
}
|
}
|
||||||
}
|
} while (line != "[/animation]");
|
||||||
else
|
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: unknown parameter %s", key.c_str());
|
|
||||||
}
|
|
||||||
} while (line != "[/animation]");
|
|
||||||
|
|
||||||
// Añade la animación al vector de animaciones
|
// Añade la animación al vector de animaciones
|
||||||
animations_.emplace_back(animation);
|
animations_.emplace_back(animation);
|
||||||
|
|
||||||
// Rellena el mapa con el nombre y el nuevo índice
|
// Rellena el mapa con el nombre y el nuevo índice
|
||||||
animation_indices_[animation.name] = animations_.size() - 1;
|
animation_indices_[animation.name] = animations_.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Una vez procesada la línea, aumenta el índice para pasar a la siguiente
|
// Una vez procesada la línea, aumenta el índice para pasar a la siguiente
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pone un valor por defecto
|
// Pone un valor por defecto
|
||||||
setWidth(frame_width);
|
setWidth(frame_width);
|
||||||
setHeight(frame_height);
|
setHeight(frame_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece la velocidad de la animación
|
// Establece la velocidad de la animación
|
||||||
void AnimatedSprite::setAnimationSpeed(size_t value)
|
void AnimatedSprite::setAnimationSpeed(size_t value) {
|
||||||
{
|
animations_[current_animation_].speed = value;
|
||||||
animations_[current_animation_].speed = value;
|
|
||||||
}
|
}
|
||||||
+31
-32
@@ -1,27 +1,27 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FRect
|
#include <SDL3/SDL.h> // Para SDL_FRect
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
#include <memory> // Para shared_ptr
|
|
||||||
#include <string> // Para basic_string, string, hash
|
|
||||||
#include <unordered_map> // Para unordered_map
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "moving_sprite.h" // Para MovingSprite
|
#include <memory> // Para shared_ptr
|
||||||
|
#include <string> // Para basic_string, string, hash
|
||||||
|
#include <unordered_map> // Para unordered_map
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
|
#include "moving_sprite.h" // Para MovingSprite
|
||||||
|
|
||||||
// Declaración adelantada
|
// Declaración adelantada
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Estructura de Animación
|
// Estructura de Animación
|
||||||
struct Animation
|
struct Animation {
|
||||||
{
|
std::string name; // Nombre de la animación
|
||||||
std::string name; // Nombre de la animación
|
std::vector<SDL_FRect> frames; // Frames que componen la animación
|
||||||
std::vector<SDL_FRect> frames; // Frames que componen la animación
|
int speed; // Velocidad de reproducción
|
||||||
int speed; // Velocidad de reproducción
|
int loop; // Frame de vuelta al terminar (-1 para no repetir)
|
||||||
int loop; // Frame de vuelta al terminar (-1 para no repetir)
|
bool completed; // Indica si la animación ha finalizado
|
||||||
bool completed; // Indica si la animación ha finalizado
|
size_t current_frame; // Frame actual en reproducción
|
||||||
size_t current_frame; // Frame actual en reproducción
|
int counter; // Contador para la animación
|
||||||
int counter; // Contador para la animación
|
|
||||||
|
|
||||||
Animation() : name(std::string()), speed(5), loop(0), completed(false), current_frame(0), counter(0) {}
|
Animation() : name(std::string()), speed(5), loop(0), completed(false), current_frame(0), counter(0) {}
|
||||||
};
|
};
|
||||||
@@ -33,9 +33,8 @@ using AnimationsFileBuffer = std::vector<std::string>;
|
|||||||
AnimationsFileBuffer loadAnimationsFromFile(const std::string &file_path);
|
AnimationsFileBuffer loadAnimationsFromFile(const std::string &file_path);
|
||||||
|
|
||||||
// Clase AnimatedSprite: Sprite animado que hereda de MovingSprite
|
// Clase AnimatedSprite: Sprite animado que hereda de MovingSprite
|
||||||
class AnimatedSprite : public MovingSprite
|
class AnimatedSprite : public MovingSprite {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor ---
|
||||||
AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path);
|
AnimatedSprite(std::shared_ptr<Texture> texture, const std::string &file_path);
|
||||||
AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer &animations);
|
AnimatedSprite(std::shared_ptr<Texture> texture, const AnimationsFileBuffer &animations);
|
||||||
@@ -43,28 +42,28 @@ public:
|
|||||||
virtual ~AnimatedSprite() override = default;
|
virtual ~AnimatedSprite() override = default;
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
void update() override; // Actualiza la animación
|
void update() override; // Actualiza la animación
|
||||||
|
|
||||||
// --- Control de animaciones ---
|
// --- Control de animaciones ---
|
||||||
void setCurrentAnimation(const std::string &name = "default", bool reset = true); // Establece la animación por nombre
|
void setCurrentAnimation(const std::string &name = "default", bool reset = true); // Establece la animación por nombre
|
||||||
void setCurrentAnimation(int index = 0, bool reset = true); // Establece la animación por índice
|
void setCurrentAnimation(int index = 0, bool reset = true); // Establece la animación por índice
|
||||||
void resetAnimation(); // Reinicia la animación actual
|
void resetAnimation(); // Reinicia la animación actual
|
||||||
void setAnimationSpeed(size_t value); // Establece la velocidad de la animación
|
void setAnimationSpeed(size_t value); // Establece la velocidad de la animación
|
||||||
size_t getAnimationSpeed() const { return animations_[current_animation_].speed; } // Obtiene la velocidad de la animación actual
|
size_t getAnimationSpeed() const { return animations_[current_animation_].speed; } // Obtiene la velocidad de la animación actual
|
||||||
|
|
||||||
// --- Consultas ---
|
// --- Consultas ---
|
||||||
bool animationIsCompleted(); // Comprueba si la animación ha terminado
|
bool animationIsCompleted(); // Comprueba si la animación ha terminado
|
||||||
int getIndex(const std::string &name); // Obtiene el índice de una animación por nombre
|
int getIndex(const std::string &name); // Obtiene el índice de una animación por nombre
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// --- Datos de animación ---
|
// --- Datos de animación ---
|
||||||
std::vector<Animation> animations_; // Vector de animaciones disponibles
|
std::vector<Animation> animations_; // Vector de animaciones disponibles
|
||||||
int current_animation_ = 0; // Índice de la animación activa
|
int current_animation_ = 0; // Índice de la animación activa
|
||||||
|
|
||||||
// --- Mapa para búsqueda rápida de animaciones por nombre ---
|
// --- Mapa para búsqueda rápida de animaciones por nombre ---
|
||||||
std::unordered_map<std::string, int> animation_indices_;
|
std::unordered_map<std::string, int> animation_indices_;
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void animate(); // Calcula el frame actual de la animación
|
void animate(); // Calcula el frame actual de la animación
|
||||||
void loadFromAnimationsFileBuffer(const AnimationsFileBuffer &source); // Carga animaciones desde un buffer
|
void loadFromAnimationsFileBuffer(const AnimationsFileBuffer &source); // Carga animaciones desde un buffer
|
||||||
};
|
};
|
||||||
+46
-69
@@ -1,11 +1,12 @@
|
|||||||
#include "asset.h"
|
#include "asset.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_LogError
|
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_LogError
|
||||||
|
|
||||||
#include <algorithm> // Para find_if, max
|
#include <algorithm> // Para find_if, max
|
||||||
#include <fstream> // Para basic_ifstream, ifstream
|
#include <fstream> // Para basic_ifstream, ifstream
|
||||||
#include <string> // Para allocator, string, char_traits, operator+
|
#include <string> // Para allocator, string, char_traits, operator+
|
||||||
|
|
||||||
#include "utils.h" // Para getFileName
|
#include "utils.h" // Para getFileName
|
||||||
|
|
||||||
// Singleton
|
// Singleton
|
||||||
Asset *Asset::instance_ = nullptr;
|
Asset *Asset::instance_ = nullptr;
|
||||||
@@ -20,62 +21,48 @@ void Asset::destroy() { delete Asset::instance_; }
|
|||||||
Asset *Asset::get() { return Asset::instance_; }
|
Asset *Asset::get() { return Asset::instance_; }
|
||||||
|
|
||||||
// Añade un elemento a la lista
|
// Añade un elemento a la lista
|
||||||
void Asset::add(const std::string &file, AssetType type, bool required, bool absolute)
|
void Asset::add(const std::string &file, AssetType type, bool required, bool absolute) {
|
||||||
{
|
|
||||||
file_list_.emplace_back(absolute ? file : executable_path_ + file, type, required);
|
file_list_.emplace_back(absolute ? file : executable_path_ + file, type, required);
|
||||||
longest_name_ = std::max(longest_name_, static_cast<int>(file_list_.back().file.size()));
|
longest_name_ = std::max(longest_name_, static_cast<int>(file_list_.back().file.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Devuelve la ruta completa a un fichero a partir de una cadena
|
// Devuelve la ruta completa a un fichero a partir de una cadena
|
||||||
std::string Asset::get(const std::string &text) const
|
std::string Asset::get(const std::string &text) const {
|
||||||
{
|
auto it = std::find_if(file_list_.begin(), file_list_.end(), [&text](const auto &f) {
|
||||||
auto it = std::find_if(file_list_.begin(), file_list_.end(),
|
return getFileName(f.file) == text;
|
||||||
[&text](const auto &f)
|
});
|
||||||
{
|
|
||||||
return getFileName(f.file) == text;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (it != file_list_.end())
|
if (it != file_list_.end()) {
|
||||||
{
|
|
||||||
return it->file;
|
return it->file;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: file %s not found", text.c_str());
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Warning: file %s not found", text.c_str());
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba que existen todos los elementos
|
// Comprueba que existen todos los elementos
|
||||||
bool Asset::check() const
|
bool Asset::check() const {
|
||||||
{
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n** CHECKING FILES");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n** CHECKING FILES");
|
||||||
|
|
||||||
// Comprueba la lista de ficheros clasificándolos por tipo
|
// Comprueba la lista de ficheros clasificándolos por tipo
|
||||||
for (int type = 0; type < static_cast<int>(AssetType::COUNT); ++type)
|
for (int type = 0; type < static_cast<int>(AssetType::COUNT); ++type) {
|
||||||
{
|
|
||||||
// Comprueba si hay ficheros de ese tipo
|
// Comprueba si hay ficheros de ese tipo
|
||||||
bool any = false;
|
bool any = false;
|
||||||
|
|
||||||
for (const auto &f : file_list_)
|
for (const auto &f : file_list_) {
|
||||||
{
|
if (f.required && f.type == static_cast<AssetType>(type)) {
|
||||||
if (f.required && f.type == static_cast<AssetType>(type))
|
|
||||||
{
|
|
||||||
any = true;
|
any = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si hay ficheros de ese tipo, comprueba si existen
|
// Si hay ficheros de ese tipo, comprueba si existen
|
||||||
if (any)
|
if (any) {
|
||||||
{
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> %s FILES", getTypeName(static_cast<AssetType>(type)).c_str());
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> %s FILES", getTypeName(static_cast<AssetType>(type)).c_str());
|
||||||
|
|
||||||
for (const auto &f : file_list_)
|
for (const auto &f : file_list_) {
|
||||||
{
|
if (f.required && f.type == static_cast<AssetType>(type)) {
|
||||||
if (f.required && f.type == static_cast<AssetType>(type))
|
|
||||||
{
|
|
||||||
success &= checkFile(f.file);
|
success &= checkFile(f.file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,12 +72,9 @@ bool Asset::check() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Resultado
|
// Resultado
|
||||||
if (success)
|
if (success) {
|
||||||
{
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n** CHECKING FILES COMPLETED.\n");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n** CHECKING FILES COMPLETED.\n");
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "\n** CHECKING FILES FAILED.\n");
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "\n** CHECKING FILES FAILED.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,14 +82,12 @@ bool Asset::check() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba que existe un fichero
|
// Comprueba que existe un fichero
|
||||||
bool Asset::checkFile(const std::string &path) const
|
bool Asset::checkFile(const std::string &path) const {
|
||||||
{
|
|
||||||
std::ifstream file(path);
|
std::ifstream file(path);
|
||||||
bool success = file.good();
|
bool success = file.good();
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
if (!success)
|
if (!success) {
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Checking file: %s [ ERROR ]", getFileName(path).c_str());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Checking file: %s [ ERROR ]", getFileName(path).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,42 +95,37 @@ bool Asset::checkFile(const std::string &path) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Devuelve el nombre del tipo de recurso
|
// Devuelve el nombre del tipo de recurso
|
||||||
std::string Asset::getTypeName(AssetType type) const
|
std::string Asset::getTypeName(AssetType type) const {
|
||||||
{
|
switch (type) {
|
||||||
switch (type)
|
case AssetType::BITMAP:
|
||||||
{
|
return "BITMAP";
|
||||||
case AssetType::BITMAP:
|
case AssetType::MUSIC:
|
||||||
return "BITMAP";
|
return "MUSIC";
|
||||||
case AssetType::MUSIC:
|
case AssetType::SOUND:
|
||||||
return "MUSIC";
|
return "SOUND";
|
||||||
case AssetType::SOUND:
|
case AssetType::FONT:
|
||||||
return "SOUND";
|
return "FONT";
|
||||||
case AssetType::FONT:
|
case AssetType::LANG:
|
||||||
return "FONT";
|
return "LANG";
|
||||||
case AssetType::LANG:
|
case AssetType::DATA:
|
||||||
return "LANG";
|
return "DATA";
|
||||||
case AssetType::DATA:
|
case AssetType::DEMODATA:
|
||||||
return "DATA";
|
return "DEMODATA";
|
||||||
case AssetType::DEMODATA:
|
case AssetType::ANIMATION:
|
||||||
return "DEMODATA";
|
return "ANIMATION";
|
||||||
case AssetType::ANIMATION:
|
case AssetType::PALETTE:
|
||||||
return "ANIMATION";
|
return "PALETTE";
|
||||||
case AssetType::PALETTE:
|
default:
|
||||||
return "PALETTE";
|
return "ERROR";
|
||||||
default:
|
|
||||||
return "ERROR";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Devuelve la lista de recursos de un tipo
|
// Devuelve la lista de recursos de un tipo
|
||||||
std::vector<std::string> Asset::getListByType(AssetType type) const
|
std::vector<std::string> Asset::getListByType(AssetType type) const {
|
||||||
{
|
|
||||||
std::vector<std::string> list;
|
std::vector<std::string> list;
|
||||||
|
|
||||||
for (auto f : file_list_)
|
for (auto f : file_list_) {
|
||||||
{
|
if (f.type == type) {
|
||||||
if (f.type == type)
|
|
||||||
{
|
|
||||||
list.push_back(f.file);
|
list.push_back(f.file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+48
-51
@@ -1,66 +1,63 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string> // Para string, basic_string
|
#include <string> // Para string, basic_string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
// Tipos de recursos gestionados por Asset
|
// Tipos de recursos gestionados por Asset
|
||||||
enum class AssetType : int
|
enum class AssetType : int {
|
||||||
{
|
BITMAP,
|
||||||
BITMAP,
|
MUSIC,
|
||||||
MUSIC,
|
SOUND,
|
||||||
SOUND,
|
FONT,
|
||||||
FONT,
|
LANG,
|
||||||
LANG,
|
DATA,
|
||||||
DATA,
|
DEMODATA,
|
||||||
DEMODATA,
|
ANIMATION,
|
||||||
ANIMATION,
|
PALETTE,
|
||||||
PALETTE,
|
COUNT,
|
||||||
COUNT,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clase Asset: gestor de recursos (singleton)
|
// Clase Asset: gestor de recursos (singleton)
|
||||||
class Asset
|
class Asset {
|
||||||
{
|
public:
|
||||||
public:
|
// --- Métodos de singleton ---
|
||||||
// --- Métodos de singleton ---
|
static void init(const std::string &executable_path); // Inicializa el objeto Asset
|
||||||
static void init(const std::string &executable_path); // Inicializa el objeto Asset
|
static void destroy(); // Libera el objeto Asset
|
||||||
static void destroy(); // Libera el objeto Asset
|
static Asset *get(); // Obtiene el puntero al objeto Asset
|
||||||
static Asset *get(); // Obtiene el puntero al objeto Asset
|
|
||||||
|
|
||||||
// --- Métodos para la gestión de recursos ---
|
// --- Métodos para la gestión de recursos ---
|
||||||
void add(const std::string &file, AssetType type, bool required = true, bool absolute = false); // Añade un recurso a la lista
|
void add(const std::string &file, AssetType type, bool required = true, bool absolute = false); // Añade un recurso a la lista
|
||||||
std::string get(const std::string &text) const; // Obtiene la ruta completa de un recurso a partir de su nombre
|
std::string get(const std::string &text) const; // Obtiene la ruta completa de un recurso a partir de su nombre
|
||||||
bool check() const; // Verifica la existencia de todos los recursos requeridos
|
bool check() const; // Verifica la existencia de todos los recursos requeridos
|
||||||
std::vector<std::string> getListByType(AssetType type) const; // Devuelve una lista de archivos de un tipo concreto
|
std::vector<std::string> getListByType(AssetType type) const; // Devuelve una lista de archivos de un tipo concreto
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Estructura interna para almacenar información de cada recurso ---
|
// --- Estructura interna para almacenar información de cada recurso ---
|
||||||
struct AssetItem
|
struct AssetItem {
|
||||||
{
|
std::string file; // Ruta del fichero desde la raíz del directorio
|
||||||
std::string file; // Ruta del fichero desde la raíz del directorio
|
AssetType type; // Tipo de recurso
|
||||||
AssetType type; // Tipo de recurso
|
bool required; // Indica si el fichero es obligatorio
|
||||||
bool required; // Indica si el fichero es obligatorio
|
|
||||||
|
|
||||||
AssetItem(const std::string &filePath, AssetType assetType, bool isRequired)
|
AssetItem(const std::string &filePath, AssetType assetType, bool isRequired)
|
||||||
: file(filePath), type(assetType), required(isRequired) {}
|
: file(filePath), type(assetType), required(isRequired) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Variables internas ---
|
// --- Variables internas ---
|
||||||
int longest_name_ = 0; // Longitud del nombre más largo
|
int longest_name_ = 0; // Longitud del nombre más largo
|
||||||
std::vector<AssetItem> file_list_; // Lista con todas las rutas de recursos
|
std::vector<AssetItem> file_list_; // Lista con todas las rutas de recursos
|
||||||
std::string executable_path_; // Ruta del ejecutable
|
std::string executable_path_; // Ruta del ejecutable
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
bool checkFile(const std::string &path) const; // Verifica si un archivo existe
|
bool checkFile(const std::string &path) const; // Verifica si un archivo existe
|
||||||
std::string getTypeName(AssetType type) const; // Devuelve el nombre textual del tipo de recurso
|
std::string getTypeName(AssetType type) const; // Devuelve el nombre textual del tipo de recurso
|
||||||
|
|
||||||
// --- Patrón Singleton ---
|
// --- Patrón Singleton ---
|
||||||
explicit Asset(const std::string &executable_path)
|
explicit Asset(const std::string &executable_path)
|
||||||
: executable_path_(executable_path) {}
|
: executable_path_(executable_path) {}
|
||||||
~Asset() = default;
|
~Asset() = default;
|
||||||
Asset(const Asset &) = delete;
|
Asset(const Asset &) = delete;
|
||||||
Asset &operator=(const Asset &) = delete;
|
Asset &operator=(const Asset &) = delete;
|
||||||
|
|
||||||
// --- Singleton ---
|
// --- Singleton ---
|
||||||
static Asset *instance_;
|
static Asset *instance_;
|
||||||
};
|
};
|
||||||
+26
-47
@@ -1,11 +1,12 @@
|
|||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_G...
|
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_G...
|
||||||
|
|
||||||
#include <algorithm> // Para clamp
|
#include <algorithm> // Para clamp
|
||||||
|
|
||||||
#include "external/jail_audio.h" // Para JA_FadeOutMusic, JA_Init, JA_PauseM...
|
#include "external/jail_audio.h" // Para JA_FadeOutMusic, JA_Init, JA_PauseM...
|
||||||
#include "options.h" // Para AudioOptions, audio, MusicOptions
|
#include "options.h" // Para AudioOptions, audio, MusicOptions
|
||||||
#include "resource.h" // Para Resource
|
#include "resource.h" // Para Resource
|
||||||
|
|
||||||
// Singleton
|
// Singleton
|
||||||
Audio *Audio::instance_ = nullptr;
|
Audio *Audio::instance_ = nullptr;
|
||||||
@@ -26,70 +27,56 @@ Audio::Audio() { initSDLAudio(); }
|
|||||||
Audio::~Audio() { JA_Quit(); }
|
Audio::~Audio() { JA_Quit(); }
|
||||||
|
|
||||||
// Reproduce la música
|
// Reproduce la música
|
||||||
void Audio::playMusic(const std::string &name, const int loop)
|
void Audio::playMusic(const std::string &name, const int loop) {
|
||||||
{
|
|
||||||
music_.name = name;
|
music_.name = name;
|
||||||
music_.loop = loop;
|
music_.loop = loop;
|
||||||
|
|
||||||
if (music_enabled_ && music_.state != MusicState::PLAYING)
|
if (music_enabled_ && music_.state != MusicState::PLAYING) {
|
||||||
{
|
|
||||||
JA_PlayMusic(Resource::get()->getMusic(name), loop);
|
JA_PlayMusic(Resource::get()->getMusic(name), loop);
|
||||||
music_.state = MusicState::PLAYING;
|
music_.state = MusicState::PLAYING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pausa la música
|
// Pausa la música
|
||||||
void Audio::pauseMusic()
|
void Audio::pauseMusic() {
|
||||||
{
|
if (music_enabled_ && music_.state == MusicState::PLAYING) {
|
||||||
if (music_enabled_ && music_.state == MusicState::PLAYING)
|
|
||||||
{
|
|
||||||
JA_PauseMusic();
|
JA_PauseMusic();
|
||||||
music_.state = MusicState::PAUSED;
|
music_.state = MusicState::PAUSED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detiene la música
|
// Detiene la música
|
||||||
void Audio::stopMusic()
|
void Audio::stopMusic() {
|
||||||
{
|
if (music_enabled_) {
|
||||||
if (music_enabled_)
|
|
||||||
{
|
|
||||||
JA_StopMusic();
|
JA_StopMusic();
|
||||||
music_.state = MusicState::STOPPED;
|
music_.state = MusicState::STOPPED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reproduce un sonido
|
// Reproduce un sonido
|
||||||
void Audio::playSound(const std::string &name, Group group)
|
void Audio::playSound(const std::string &name, Group group) {
|
||||||
{
|
if (sound_enabled_) {
|
||||||
if (sound_enabled_)
|
|
||||||
{
|
|
||||||
JA_PlaySound(Resource::get()->getSound(name), 0, static_cast<int>(group));
|
JA_PlaySound(Resource::get()->getSound(name), 0, static_cast<int>(group));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detiene todos los sonidos
|
// Detiene todos los sonidos
|
||||||
void Audio::stopAllSounds()
|
void Audio::stopAllSounds() {
|
||||||
{
|
if (sound_enabled_) {
|
||||||
if (sound_enabled_)
|
|
||||||
{
|
|
||||||
JA_StopChannel(-1);
|
JA_StopChannel(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Realiza un fundido de salida de la música
|
// Realiza un fundido de salida de la música
|
||||||
void Audio::fadeOutMusic(int milliseconds)
|
void Audio::fadeOutMusic(int milliseconds) {
|
||||||
{
|
if (music_enabled_) {
|
||||||
if (music_enabled_)
|
|
||||||
{
|
|
||||||
JA_FadeOutMusic(milliseconds);
|
JA_FadeOutMusic(milliseconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el volumen de los sonidos
|
// Establece el volumen de los sonidos
|
||||||
void Audio::setSoundVolume(int sound_volume, Group group)
|
void Audio::setSoundVolume(int sound_volume, Group group) {
|
||||||
{
|
if (sound_enabled_) {
|
||||||
if (sound_enabled_)
|
|
||||||
{
|
|
||||||
sound_volume = std::clamp(sound_volume, 0, 100);
|
sound_volume = std::clamp(sound_volume, 0, 100);
|
||||||
const float CONVERTED_VOLUME = (sound_volume / 100.0f) * (Options::audio.volume / 100.0f);
|
const float CONVERTED_VOLUME = (sound_volume / 100.0f) * (Options::audio.volume / 100.0f);
|
||||||
JA_SetSoundVolume(CONVERTED_VOLUME, static_cast<int>(group));
|
JA_SetSoundVolume(CONVERTED_VOLUME, static_cast<int>(group));
|
||||||
@@ -97,10 +84,8 @@ void Audio::setSoundVolume(int sound_volume, Group group)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Establece el volumen de la música
|
// Establece el volumen de la música
|
||||||
void Audio::setMusicVolume(int music_volume)
|
void Audio::setMusicVolume(int music_volume) {
|
||||||
{
|
if (music_enabled_) {
|
||||||
if (music_enabled_)
|
|
||||||
{
|
|
||||||
music_volume = std::clamp(music_volume, 0, 100);
|
music_volume = std::clamp(music_volume, 0, 100);
|
||||||
const float CONVERTED_VOLUME = (music_volume / 100.0f) * (Options::audio.volume / 100.0f);
|
const float CONVERTED_VOLUME = (music_volume / 100.0f) * (Options::audio.volume / 100.0f);
|
||||||
JA_SetMusicVolume(CONVERTED_VOLUME);
|
JA_SetMusicVolume(CONVERTED_VOLUME);
|
||||||
@@ -108,14 +93,12 @@ void Audio::setMusicVolume(int music_volume)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Aplica la configuración
|
// Aplica la configuración
|
||||||
void Audio::applySettings()
|
void Audio::applySettings() {
|
||||||
{
|
|
||||||
enable(Options::audio.enabled);
|
enable(Options::audio.enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establecer estado general
|
// Establecer estado general
|
||||||
void Audio::enable(bool value)
|
void Audio::enable(bool value) {
|
||||||
{
|
|
||||||
enabled_ = value;
|
enabled_ = value;
|
||||||
|
|
||||||
setSoundVolume(enabled_ ? Options::audio.sound.volume : 0);
|
setSoundVolume(enabled_ ? Options::audio.sound.volume : 0);
|
||||||
@@ -123,14 +106,10 @@ void Audio::enable(bool value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa SDL Audio
|
// Inicializa SDL Audio
|
||||||
void Audio::initSDLAudio()
|
void Audio::initSDLAudio() {
|
||||||
{
|
if (!SDL_Init(SDL_INIT_AUDIO)) {
|
||||||
if (!SDL_Init(SDL_INIT_AUDIO))
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_AUDIO could not initialize! SDL Error: %s", SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_AUDIO could not initialize! SDL Error: %s", SDL_GetError());
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "\n** SDL_AUDIO: INITIALIZING\n");
|
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "\n** SDL_AUDIO: INITIALIZING\n");
|
||||||
|
|
||||||
JA_Init(48000, SDL_AUDIO_S16LE, 2);
|
JA_Init(48000, SDL_AUDIO_S16LE, 2);
|
||||||
|
|||||||
+38
-42
@@ -3,65 +3,61 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// Clase Audio: gestor de audio (singleton)
|
// Clase Audio: gestor de audio (singleton)
|
||||||
class Audio
|
class Audio {
|
||||||
{
|
public:
|
||||||
public:
|
enum class Group : int {
|
||||||
enum class Group : int
|
|
||||||
{
|
|
||||||
ALL = -1,
|
ALL = -1,
|
||||||
GAME = 0,
|
GAME = 0,
|
||||||
INTERFACE = 1
|
INTERFACE = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Métodos de singleton ---
|
// --- Métodos de singleton ---
|
||||||
static void init(); // Inicializa el objeto Audio
|
static void init(); // Inicializa el objeto Audio
|
||||||
static void destroy(); // Libera el objeto Audio
|
static void destroy(); // Libera el objeto Audio
|
||||||
static Audio *get(); // Obtiene el puntero al objeto Audio
|
static Audio *get(); // Obtiene el puntero al objeto Audio
|
||||||
|
|
||||||
// --- Control de Música ---
|
// --- Control de Música ---
|
||||||
void playMusic(const std::string &name, int loop = -1); // Reproducir música en bucle
|
void playMusic(const std::string &name, int loop = -1); // Reproducir música en bucle
|
||||||
void pauseMusic(); // Pausar reproducción de música
|
void pauseMusic(); // Pausar reproducción de música
|
||||||
void stopMusic(); // Detener completamente la música
|
void stopMusic(); // Detener completamente la música
|
||||||
void fadeOutMusic(int milliseconds); // Fundido de salida de la música
|
void fadeOutMusic(int milliseconds); // Fundido de salida de la música
|
||||||
|
|
||||||
// --- Control de Sonidos ---
|
// --- Control de Sonidos ---
|
||||||
void playSound(const std::string &name, Group group = Group::GAME); // Reproducir sonido puntual
|
void playSound(const std::string &name, Group group = Group::GAME); // Reproducir sonido puntual
|
||||||
void stopAllSounds(); // Detener todos los sonidos
|
void stopAllSounds(); // Detener todos los sonidos
|
||||||
|
|
||||||
// --- Configuración General ---
|
// --- Configuración General ---
|
||||||
void enable(bool value); // Establecer estado general
|
void enable(bool value); // Establecer estado general
|
||||||
void toggleEnabled() { enabled_ = !enabled_; } // Alternar estado general
|
void toggleEnabled() { enabled_ = !enabled_; } // Alternar estado general
|
||||||
void applySettings(); // Aplica la configuración
|
void applySettings(); // Aplica la configuración
|
||||||
|
|
||||||
// --- Configuración de Sonidos ---
|
// --- Configuración de Sonidos ---
|
||||||
void enableSound() { sound_enabled_ = true; } // Habilitar sonidos
|
void enableSound() { sound_enabled_ = true; } // Habilitar sonidos
|
||||||
void disableSound() { sound_enabled_ = false; } // Deshabilitar sonidos
|
void disableSound() { sound_enabled_ = false; } // Deshabilitar sonidos
|
||||||
void enableSound(bool value) { sound_enabled_ = value; } // Establecer estado de sonidos
|
void enableSound(bool value) { sound_enabled_ = value; } // Establecer estado de sonidos
|
||||||
void toggleSound() { sound_enabled_ = !sound_enabled_; } // Alternar estado de sonidos
|
void toggleSound() { sound_enabled_ = !sound_enabled_; } // Alternar estado de sonidos
|
||||||
|
|
||||||
// --- Configuración de Música ---
|
// --- Configuración de Música ---
|
||||||
void enableMusic() { music_enabled_ = true; } // Habilitar música
|
void enableMusic() { music_enabled_ = true; } // Habilitar música
|
||||||
void disableMusic() { music_enabled_ = false; } // Deshabilitar música
|
void disableMusic() { music_enabled_ = false; } // Deshabilitar música
|
||||||
void enableMusic(bool value) { music_enabled_ = value; } // Establecer estado de música
|
void enableMusic(bool value) { music_enabled_ = value; } // Establecer estado de música
|
||||||
void toggleMusic() { music_enabled_ = !music_enabled_; } // Alternar estado de música
|
void toggleMusic() { music_enabled_ = !music_enabled_; } // Alternar estado de música
|
||||||
|
|
||||||
// --- Control de Volumen ---
|
// --- Control de Volumen ---
|
||||||
void setSoundVolume(int volume, Group group = Group::ALL); // Ajustar volumen de efectos
|
void setSoundVolume(int volume, Group group = Group::ALL); // Ajustar volumen de efectos
|
||||||
void setMusicVolume(int volume); // Ajustar volumen de música
|
void setMusicVolume(int volume); // Ajustar volumen de música
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class MusicState
|
enum class MusicState {
|
||||||
{
|
|
||||||
PLAYING,
|
PLAYING,
|
||||||
PAUSED,
|
PAUSED,
|
||||||
STOPPED,
|
STOPPED,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Music
|
struct Music {
|
||||||
{
|
MusicState state; // Estado actual de la música (reproduciendo, detenido, en pausa)
|
||||||
MusicState state; // Estado actual de la música (reproduciendo, detenido, en pausa)
|
std::string name; // Última pista de música reproducida
|
||||||
std::string name; // Última pista de música reproducida
|
bool loop; // Indica si la última pista de música se debe reproducir en bucle
|
||||||
bool loop; // Indica si la última pista de música se debe reproducir en bucle
|
|
||||||
|
|
||||||
// Constructor para inicializar la música con valores predeterminados
|
// Constructor para inicializar la música con valores predeterminados
|
||||||
Music() : state(MusicState::STOPPED), name(""), loop(false) {}
|
Music() : state(MusicState::STOPPED), name(""), loop(false) {}
|
||||||
@@ -74,18 +70,18 @@ private:
|
|||||||
Music music_;
|
Music music_;
|
||||||
|
|
||||||
// --- Variables de Estado ---
|
// --- Variables de Estado ---
|
||||||
bool enabled_ = true; // Estado general del audio
|
bool enabled_ = true; // Estado general del audio
|
||||||
bool sound_enabled_ = true; // Estado de los efectos de sonido
|
bool sound_enabled_ = true; // Estado de los efectos de sonido
|
||||||
bool music_enabled_ = true; // Estado de la música
|
bool music_enabled_ = true; // Estado de la música
|
||||||
|
|
||||||
// --- Inicializa SDL Audio ---
|
// --- Inicializa SDL Audio ---
|
||||||
void initSDLAudio();
|
void initSDLAudio();
|
||||||
|
|
||||||
// --- Patrón Singleton ---
|
// --- Patrón Singleton ---
|
||||||
Audio(); // Constructor privado
|
Audio(); // Constructor privado
|
||||||
~Audio(); // Destructor privado
|
~Audio(); // Destructor privado
|
||||||
Audio(const Audio &) = delete; // Evitar copia
|
Audio(const Audio &) = delete; // Evitar copia
|
||||||
Audio &operator=(const Audio &) = delete; // Evitar asignación
|
Audio &operator=(const Audio &) = delete; // Evitar asignación
|
||||||
|
|
||||||
// --- Singleton ---
|
// --- Singleton ---
|
||||||
static Audio *instance_;
|
static Audio *instance_;
|
||||||
|
|||||||
+37
-66
@@ -1,17 +1,18 @@
|
|||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
#include "background.h"
|
#include "background.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_SetRenderTarget, SDL_FRect, SDL_Creat...
|
#include <SDL3/SDL.h> // Para SDL_SetRenderTarget, SDL_FRect, SDL_Creat...
|
||||||
|
|
||||||
#include <algorithm> // Para clamp, max
|
#include <algorithm> // Para clamp, max
|
||||||
#include <cmath> // Para cos, sin, M_PI
|
#include <cmath> // Para cos, sin, M_PI
|
||||||
#include <string> // Para basic_string
|
#include <string> // Para basic_string
|
||||||
|
|
||||||
#include "moving_sprite.h" // Para MovingSprite
|
#include "moving_sprite.h" // Para MovingSprite
|
||||||
#include "param.h" // Para Param, ParamBackground, param
|
#include "param.h" // Para Param, ParamBackground, param
|
||||||
#include "resource.h" // Para Resource
|
#include "resource.h" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "screen.h" // Para Screen
|
||||||
#include "sprite.h" // Para Sprite
|
#include "sprite.h" // Para Sprite
|
||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Background::Background()
|
Background::Background()
|
||||||
@@ -47,8 +48,7 @@ Background::Background()
|
|||||||
|
|
||||||
const float TOP_CLOUDS_TEXTURE_HEIGHT = top_clouds_texture_->getHeight() / 4;
|
const float TOP_CLOUDS_TEXTURE_HEIGHT = top_clouds_texture_->getHeight() / 4;
|
||||||
const float BOTTOM_CLOUDS_TEXTURE_HEIGHT = bottom_clouds_texture_->getHeight() / 4;
|
const float BOTTOM_CLOUDS_TEXTURE_HEIGHT = bottom_clouds_texture_->getHeight() / 4;
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i) {
|
||||||
{
|
|
||||||
top_clouds_rect_[i] = {0, i * TOP_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(top_clouds_texture_->getWidth()), TOP_CLOUDS_TEXTURE_HEIGHT};
|
top_clouds_rect_[i] = {0, i * TOP_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(top_clouds_texture_->getWidth()), TOP_CLOUDS_TEXTURE_HEIGHT};
|
||||||
bottom_clouds_rect_[i] = {0, i * BOTTOM_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(bottom_clouds_texture_->getWidth()), BOTTOM_CLOUDS_TEXTURE_HEIGHT};
|
bottom_clouds_rect_[i] = {0, i * BOTTOM_CLOUDS_TEXTURE_HEIGHT, static_cast<float>(bottom_clouds_texture_->getWidth()), BOTTOM_CLOUDS_TEXTURE_HEIGHT};
|
||||||
}
|
}
|
||||||
@@ -107,15 +107,13 @@ Background::Background()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
Background::~Background()
|
Background::~Background() {
|
||||||
{
|
|
||||||
SDL_DestroyTexture(canvas_);
|
SDL_DestroyTexture(canvas_);
|
||||||
SDL_DestroyTexture(color_texture_);
|
SDL_DestroyTexture(color_texture_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza la lógica del objeto
|
// Actualiza la lógica del objeto
|
||||||
void Background::update()
|
void Background::update() {
|
||||||
{
|
|
||||||
// Actualiza el valor de alpha_
|
// Actualiza el valor de alpha_
|
||||||
updateAlphaColorTexture();
|
updateAlphaColorTexture();
|
||||||
|
|
||||||
@@ -140,8 +138,7 @@ void Background::update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja el gradiente de fondo
|
// Dibuja el gradiente de fondo
|
||||||
void Background::renderGradient()
|
void Background::renderGradient() {
|
||||||
{
|
|
||||||
// Dibuja el gradiente de detras
|
// Dibuja el gradiente de detras
|
||||||
gradients_texture_->setAlpha(255);
|
gradients_texture_->setAlpha(255);
|
||||||
gradient_sprite_->setSpriteClip(gradient_rect_[(gradient_number_ + 1) % 4]);
|
gradient_sprite_->setSpriteClip(gradient_rect_[(gradient_number_ + 1) % 4]);
|
||||||
@@ -154,8 +151,7 @@ void Background::renderGradient()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja las nubes de arriba
|
// Dibuja las nubes de arriba
|
||||||
void Background::renderTopClouds()
|
void Background::renderTopClouds() {
|
||||||
{
|
|
||||||
// Dibuja el primer conjunto de nubes, las de detras
|
// Dibuja el primer conjunto de nubes, las de detras
|
||||||
top_clouds_texture_->setAlpha(255);
|
top_clouds_texture_->setAlpha(255);
|
||||||
top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]);
|
top_clouds_sprite_a_->setSpriteClip(top_clouds_rect_[(gradient_number_ + 1) % 4]);
|
||||||
@@ -172,8 +168,7 @@ void Background::renderTopClouds()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja las nubes de abajo
|
// Dibuja las nubes de abajo
|
||||||
void Background::renderBottomClouds()
|
void Background::renderBottomClouds() {
|
||||||
{
|
|
||||||
// Dibuja el primer conjunto de nubes, las de detras
|
// Dibuja el primer conjunto de nubes, las de detras
|
||||||
bottom_clouds_texture_->setAlpha(255);
|
bottom_clouds_texture_->setAlpha(255);
|
||||||
bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]);
|
bottom_clouds_sprite_a_->setSpriteClip(bottom_clouds_rect_[(gradient_number_ + 1) % 4]);
|
||||||
@@ -190,8 +185,7 @@ void Background::renderBottomClouds()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compone todos los elementos del fondo en la textura
|
// Compone todos los elementos del fondo en la textura
|
||||||
void Background::fillCanvas()
|
void Background::fillCanvas() {
|
||||||
{
|
|
||||||
// Cambia el destino del renderizador
|
// Cambia el destino del renderizador
|
||||||
auto temp = SDL_GetRenderTarget(renderer_);
|
auto temp = SDL_GetRenderTarget(renderer_);
|
||||||
SDL_SetRenderTarget(renderer_, canvas_);
|
SDL_SetRenderTarget(renderer_, canvas_);
|
||||||
@@ -220,8 +214,7 @@ void Background::fillCanvas()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja el objeto
|
// Dibuja el objeto
|
||||||
void Background::render()
|
void Background::render() {
|
||||||
{
|
|
||||||
// Fondo
|
// Fondo
|
||||||
SDL_RenderTexture(renderer_, canvas_, &src_rect_, &dst_rect_);
|
SDL_RenderTexture(renderer_, canvas_, &src_rect_, &dst_rect_);
|
||||||
|
|
||||||
@@ -230,26 +223,22 @@ void Background::render()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ajusta el valor de la variable
|
// Ajusta el valor de la variable
|
||||||
void Background::setCloudsSpeed(float value)
|
void Background::setCloudsSpeed(float value) {
|
||||||
{
|
|
||||||
clouds_speed_ = value;
|
clouds_speed_ = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ajusta el valor de la variable
|
// Ajusta el valor de la variable
|
||||||
void Background::setGradientNumber(int value)
|
void Background::setGradientNumber(int value) {
|
||||||
{
|
|
||||||
gradient_number_ = value % 4;
|
gradient_number_ = value % 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ajusta el valor de la variable
|
// Ajusta el valor de la variable
|
||||||
void Background::setTransition(float value)
|
void Background::setTransition(float value) {
|
||||||
{
|
|
||||||
transition_ = std::clamp(value, 0.0f, 1.0f);
|
transition_ = std::clamp(value, 0.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece la posición del objeto
|
// Establece la posición del objeto
|
||||||
void Background::setPos(SDL_FRect pos)
|
void Background::setPos(SDL_FRect pos) {
|
||||||
{
|
|
||||||
dst_rect_ = pos;
|
dst_rect_ = pos;
|
||||||
|
|
||||||
// Si cambian las medidas del destino, hay que cambiar las del origen para evitar deformar la imagen
|
// Si cambian las medidas del destino, hay que cambiar las del origen para evitar deformar la imagen
|
||||||
@@ -260,8 +249,7 @@ void Background::setPos(SDL_FRect pos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Establece el color_ de atenuación
|
// Establece el color_ de atenuación
|
||||||
void Background::setColor(Color color)
|
void Background::setColor(Color color) {
|
||||||
{
|
|
||||||
attenuate_color_ = color;
|
attenuate_color_ = color;
|
||||||
|
|
||||||
// Colorea la textura
|
// Colorea la textura
|
||||||
@@ -275,8 +263,7 @@ void Background::setColor(Color color)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Establece la transparencia de la atenuación
|
// Establece la transparencia de la atenuación
|
||||||
void Background::setAlpha(int alpha)
|
void Background::setAlpha(int alpha) {
|
||||||
{
|
|
||||||
// Evita que se asignen valores fuera de rango
|
// Evita que se asignen valores fuera de rango
|
||||||
alpha_ = std::clamp(alpha, 0, 255);
|
alpha_ = std::clamp(alpha, 0, 255);
|
||||||
|
|
||||||
@@ -286,22 +273,17 @@ void Background::setAlpha(int alpha)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el valor de alpha_
|
// Actualiza el valor de alpha_
|
||||||
void Background::updateAlphaColorTexture()
|
void Background::updateAlphaColorTexture() {
|
||||||
{
|
if (alpha_color_text_ == alpha_color_text_temp_) {
|
||||||
if (alpha_color_text_ == alpha_color_text_temp_)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
alpha_color_text_ > alpha_color_text_temp_ ? ++alpha_color_text_temp_ : --alpha_color_text_temp_;
|
alpha_color_text_ > alpha_color_text_temp_ ? ++alpha_color_text_temp_ : --alpha_color_text_temp_;
|
||||||
SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_temp_);
|
SDL_SetTextureAlphaMod(color_texture_, alpha_color_text_temp_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza las nubes
|
// Actualiza las nubes
|
||||||
void Background::updateClouds()
|
void Background::updateClouds() {
|
||||||
{
|
|
||||||
// Aplica la velocidad calculada a las nubes
|
// Aplica la velocidad calculada a las nubes
|
||||||
top_clouds_sprite_a_->setVelX(clouds_speed_);
|
top_clouds_sprite_a_->setVelX(clouds_speed_);
|
||||||
top_clouds_sprite_b_->setVelX(clouds_speed_);
|
top_clouds_sprite_b_->setVelX(clouds_speed_);
|
||||||
@@ -315,37 +297,31 @@ void Background::updateClouds()
|
|||||||
bottom_clouds_sprite_b_->update();
|
bottom_clouds_sprite_b_->update();
|
||||||
|
|
||||||
// Calcula el offset de las nubes
|
// Calcula el offset de las nubes
|
||||||
if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth())
|
if (top_clouds_sprite_a_->getPosX() < -top_clouds_sprite_a_->getWidth()) {
|
||||||
{
|
|
||||||
top_clouds_sprite_a_->setPosX(top_clouds_sprite_a_->getWidth());
|
top_clouds_sprite_a_->setPosX(top_clouds_sprite_a_->getWidth());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (top_clouds_sprite_b_->getPosX() < -top_clouds_sprite_b_->getWidth())
|
if (top_clouds_sprite_b_->getPosX() < -top_clouds_sprite_b_->getWidth()) {
|
||||||
{
|
|
||||||
top_clouds_sprite_b_->setPosX(top_clouds_sprite_b_->getWidth());
|
top_clouds_sprite_b_->setPosX(top_clouds_sprite_b_->getWidth());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bottom_clouds_sprite_a_->getPosX() < -bottom_clouds_sprite_a_->getWidth())
|
if (bottom_clouds_sprite_a_->getPosX() < -bottom_clouds_sprite_a_->getWidth()) {
|
||||||
{
|
|
||||||
bottom_clouds_sprite_a_->setPosX(bottom_clouds_sprite_a_->getWidth());
|
bottom_clouds_sprite_a_->setPosX(bottom_clouds_sprite_a_->getWidth());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bottom_clouds_sprite_b_->getPosX() < -bottom_clouds_sprite_b_->getWidth())
|
if (bottom_clouds_sprite_b_->getPosX() < -bottom_clouds_sprite_b_->getWidth()) {
|
||||||
{
|
|
||||||
bottom_clouds_sprite_b_->setPosX(bottom_clouds_sprite_b_->getWidth());
|
bottom_clouds_sprite_b_->setPosX(bottom_clouds_sprite_b_->getWidth());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Precalcula el vector con el recorrido del sol
|
// Precalcula el vector con el recorrido del sol
|
||||||
void Background::createSunPath()
|
void Background::createSunPath() {
|
||||||
{
|
|
||||||
constexpr float CENTER_X = 170;
|
constexpr float CENTER_X = 170;
|
||||||
const float center_y = base_ - 80;
|
const float center_y = base_ - 80;
|
||||||
constexpr float RADIUS = 120;
|
constexpr float RADIUS = 120;
|
||||||
|
|
||||||
// Generar puntos de la curva desde 90 a 180 grados
|
// Generar puntos de la curva desde 90 a 180 grados
|
||||||
for (double theta = M_PI / 2; theta <= M_PI; theta += 0.01)
|
for (double theta = M_PI / 2; theta <= M_PI; theta += 0.01) {
|
||||||
{
|
|
||||||
float x = CENTER_X + (RADIUS * cos(theta));
|
float x = CENTER_X + (RADIUS * cos(theta));
|
||||||
float y = center_y - (RADIUS * sin(theta));
|
float y = center_y - (RADIUS * sin(theta));
|
||||||
sun_path_.push_back({x, y});
|
sun_path_.push_back({x, y});
|
||||||
@@ -354,22 +330,19 @@ void Background::createSunPath()
|
|||||||
// Agregar puntos en línea recta después de la curva
|
// Agregar puntos en línea recta después de la curva
|
||||||
constexpr int EXTRA_PIXELS = 40;
|
constexpr int EXTRA_PIXELS = 40;
|
||||||
SDL_FPoint last_point = sun_path_.back();
|
SDL_FPoint last_point = sun_path_.back();
|
||||||
for (int i = 1; i <= EXTRA_PIXELS; ++i)
|
for (int i = 1; i <= EXTRA_PIXELS; ++i) {
|
||||||
{
|
|
||||||
sun_path_.push_back({last_point.x, last_point.y + i});
|
sun_path_.push_back({last_point.x, last_point.y + i});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Precalcula el vector con el recorrido de la luna
|
// Precalcula el vector con el recorrido de la luna
|
||||||
void Background::createMoonPath()
|
void Background::createMoonPath() {
|
||||||
{
|
|
||||||
constexpr float CENTER_X = 100;
|
constexpr float CENTER_X = 100;
|
||||||
const float center_y = base_ - 50;
|
const float center_y = base_ - 50;
|
||||||
constexpr float RADIUS = 140;
|
constexpr float RADIUS = 140;
|
||||||
|
|
||||||
// Generar puntos de la curva desde 0 a 90 grados
|
// Generar puntos de la curva desde 0 a 90 grados
|
||||||
for (double theta = 0; theta <= M_PI / 2; theta += 0.01)
|
for (double theta = 0; theta <= M_PI / 2; theta += 0.01) {
|
||||||
{
|
|
||||||
float x = CENTER_X + (RADIUS * cos(theta));
|
float x = CENTER_X + (RADIUS * cos(theta));
|
||||||
float y = center_y - (RADIUS * sin(theta));
|
float y = center_y - (RADIUS * sin(theta));
|
||||||
moon_path_.push_back({x, y});
|
moon_path_.push_back({x, y});
|
||||||
@@ -377,15 +350,13 @@ void Background::createMoonPath()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Establece la posición del sol
|
// Establece la posición del sol
|
||||||
void Background::setSunProgression(float progress)
|
void Background::setSunProgression(float progress) {
|
||||||
{
|
|
||||||
progress = std::clamp(progress, 0.0f, 1.0f);
|
progress = std::clamp(progress, 0.0f, 1.0f);
|
||||||
sun_index_ = static_cast<size_t>(progress * (sun_path_.size() - 1));
|
sun_index_ = static_cast<size_t>(progress * (sun_path_.size() - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece la posición de la luna
|
// Establece la posición de la luna
|
||||||
void Background::setMoonProgression(float progress)
|
void Background::setMoonProgression(float progress) {
|
||||||
{
|
|
||||||
progress = std::clamp(progress, 0.0f, 1.0f);
|
progress = std::clamp(progress, 0.0f, 1.0f);
|
||||||
moon_index_ = static_cast<size_t>(progress * (moon_path_.size() - 1));
|
moon_index_ = static_cast<size_t>(progress * (moon_path_.size() - 1));
|
||||||
}
|
}
|
||||||
+79
-79
@@ -1,11 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FRect, SDL_FPoint, SDL_Texture, SDL_Renderer
|
#include <SDL3/SDL.h> // Para SDL_FRect, SDL_FPoint, SDL_Texture, SDL_Renderer
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
#include <memory> // Para unique_ptr, shared_ptr
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "utils.h" // Para Color
|
#include <memory> // Para unique_ptr, shared_ptr
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
|
#include "utils.h" // Para Color
|
||||||
|
|
||||||
class MovingSprite;
|
class MovingSprite;
|
||||||
class Sprite;
|
class Sprite;
|
||||||
@@ -25,89 +26,88 @@ class Texture;
|
|||||||
- setAlpha(int alpha) -> Ajusta la transparencia de la capa de atenuación
|
- setAlpha(int alpha) -> Ajusta la transparencia de la capa de atenuación
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Background
|
class Background {
|
||||||
{
|
public:
|
||||||
public:
|
// Constructor y Destructor
|
||||||
// Constructor y Destructor
|
Background();
|
||||||
Background();
|
~Background();
|
||||||
~Background();
|
|
||||||
|
|
||||||
// Actualización y renderizado
|
// Actualización y renderizado
|
||||||
void update(); // Actualiza la lógica del objeto
|
void update(); // Actualiza la lógica del objeto
|
||||||
void render(); // Dibuja el objeto
|
void render(); // Dibuja el objeto
|
||||||
|
|
||||||
// Configuración de posición
|
// Configuración de posición
|
||||||
void setPos(SDL_FRect pos); // Establece la posición del objeto
|
void setPos(SDL_FRect pos); // Establece la posición del objeto
|
||||||
|
|
||||||
// Configuración de animaciones y efectos
|
// Configuración de animaciones y efectos
|
||||||
void setCloudsSpeed(float value); // Ajusta la velocidad de desplazamiento de las nubes
|
void setCloudsSpeed(float value); // Ajusta la velocidad de desplazamiento de las nubes
|
||||||
void setGradientNumber(int value); // Establece el degradado de fondo a usar
|
void setGradientNumber(int value); // Establece el degradado de fondo a usar
|
||||||
void setTransition(float value); // Ajusta la transición entre texturas de fondo
|
void setTransition(float value); // Ajusta la transición entre texturas de fondo
|
||||||
|
|
||||||
// Configuración de efectos visuales
|
// Configuración de efectos visuales
|
||||||
void setColor(Color color); // Establece el color de atenuación
|
void setColor(Color color); // Establece el color de atenuación
|
||||||
void setAlpha(int alpha); // Ajusta la transparencia del fondo
|
void setAlpha(int alpha); // Ajusta la transparencia del fondo
|
||||||
|
|
||||||
// Configuración del sol y la luna
|
// Configuración del sol y la luna
|
||||||
void setSunProgression(float progress); // Establece la posición del sol
|
void setSunProgression(float progress); // Establece la posición del sol
|
||||||
void setMoonProgression(float progress); // Establece la posición de la luna
|
void setMoonProgression(float progress); // Establece la posición de la luna
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Objetos y punteros
|
// Objetos y punteros
|
||||||
SDL_Renderer *renderer_; // Renderizador de la ventana
|
SDL_Renderer *renderer_; // Renderizador de la ventana
|
||||||
|
|
||||||
// Texturas
|
// Texturas
|
||||||
std::shared_ptr<Texture> buildings_texture_;
|
std::shared_ptr<Texture> buildings_texture_;
|
||||||
std::shared_ptr<Texture> top_clouds_texture_;
|
std::shared_ptr<Texture> top_clouds_texture_;
|
||||||
std::shared_ptr<Texture> bottom_clouds_texture_;
|
std::shared_ptr<Texture> bottom_clouds_texture_;
|
||||||
std::shared_ptr<Texture> grass_texture_;
|
std::shared_ptr<Texture> grass_texture_;
|
||||||
std::shared_ptr<Texture> gradients_texture_;
|
std::shared_ptr<Texture> gradients_texture_;
|
||||||
std::shared_ptr<Texture> sun_texture_;
|
std::shared_ptr<Texture> sun_texture_;
|
||||||
std::shared_ptr<Texture> moon_texture_;
|
std::shared_ptr<Texture> moon_texture_;
|
||||||
|
|
||||||
// Sprites
|
// Sprites
|
||||||
std::unique_ptr<MovingSprite> top_clouds_sprite_a_;
|
std::unique_ptr<MovingSprite> top_clouds_sprite_a_;
|
||||||
std::unique_ptr<MovingSprite> top_clouds_sprite_b_;
|
std::unique_ptr<MovingSprite> top_clouds_sprite_b_;
|
||||||
std::unique_ptr<MovingSprite> bottom_clouds_sprite_a_;
|
std::unique_ptr<MovingSprite> bottom_clouds_sprite_a_;
|
||||||
std::unique_ptr<MovingSprite> bottom_clouds_sprite_b_;
|
std::unique_ptr<MovingSprite> bottom_clouds_sprite_b_;
|
||||||
std::unique_ptr<Sprite> buildings_sprite_;
|
std::unique_ptr<Sprite> buildings_sprite_;
|
||||||
std::unique_ptr<Sprite> gradient_sprite_;
|
std::unique_ptr<Sprite> gradient_sprite_;
|
||||||
std::unique_ptr<Sprite> grass_sprite_;
|
std::unique_ptr<Sprite> grass_sprite_;
|
||||||
std::unique_ptr<Sprite> sun_sprite_;
|
std::unique_ptr<Sprite> sun_sprite_;
|
||||||
std::unique_ptr<Sprite> moon_sprite_;
|
std::unique_ptr<Sprite> moon_sprite_;
|
||||||
|
|
||||||
// Buffers de renderizado
|
// Buffers de renderizado
|
||||||
SDL_Texture *canvas_; // Textura para componer el fondo
|
SDL_Texture *canvas_; // Textura para componer el fondo
|
||||||
SDL_Texture *color_texture_; // Textura para atenuar el fondo
|
SDL_Texture *color_texture_; // Textura para atenuar el fondo
|
||||||
|
|
||||||
// Variables de control
|
// Variables de control
|
||||||
SDL_FRect gradient_rect_[4];
|
SDL_FRect gradient_rect_[4];
|
||||||
SDL_FRect top_clouds_rect_[4];
|
SDL_FRect top_clouds_rect_[4];
|
||||||
SDL_FRect bottom_clouds_rect_[4];
|
SDL_FRect bottom_clouds_rect_[4];
|
||||||
int gradient_number_ = 0;
|
int gradient_number_ = 0;
|
||||||
int alpha_ = 0;
|
int alpha_ = 0;
|
||||||
float clouds_speed_ = 0;
|
float clouds_speed_ = 0;
|
||||||
float transition_ = 0;
|
float transition_ = 0;
|
||||||
int counter_ = 0;
|
int counter_ = 0;
|
||||||
SDL_FRect rect_;
|
SDL_FRect rect_;
|
||||||
SDL_FRect src_rect_;
|
SDL_FRect src_rect_;
|
||||||
SDL_FRect dst_rect_;
|
SDL_FRect dst_rect_;
|
||||||
int base_;
|
int base_;
|
||||||
Color attenuate_color_;
|
Color attenuate_color_;
|
||||||
int alpha_color_text_;
|
int alpha_color_text_;
|
||||||
int alpha_color_text_temp_;
|
int alpha_color_text_temp_;
|
||||||
std::vector<SDL_FPoint> sun_path_;
|
std::vector<SDL_FPoint> sun_path_;
|
||||||
std::vector<SDL_FPoint> moon_path_;
|
std::vector<SDL_FPoint> moon_path_;
|
||||||
size_t sun_index_ = 0;
|
size_t sun_index_ = 0;
|
||||||
size_t moon_index_ = 0;
|
size_t moon_index_ = 0;
|
||||||
|
|
||||||
// Métodos internos
|
// Métodos internos
|
||||||
void renderGradient(); // Dibuja el gradiente de fondo
|
void renderGradient(); // Dibuja el gradiente de fondo
|
||||||
void renderTopClouds(); // Dibuja las nubes superiores
|
void renderTopClouds(); // Dibuja las nubes superiores
|
||||||
void renderBottomClouds(); // Dibuja las nubes inferiores
|
void renderBottomClouds(); // Dibuja las nubes inferiores
|
||||||
void fillCanvas(); // Compone todos los elementos en la textura
|
void fillCanvas(); // Compone todos los elementos en la textura
|
||||||
void updateAlphaColorTexture(); // Actualiza el alpha de la textura de atenuación
|
void updateAlphaColorTexture(); // Actualiza el alpha de la textura de atenuación
|
||||||
void updateClouds(); // Actualiza el movimiento de las nubes
|
void updateClouds(); // Actualiza el movimiento de las nubes
|
||||||
void createSunPath(); // Precalcula el recorrido del sol
|
void createSunPath(); // Precalcula el recorrido del sol
|
||||||
void createMoonPath(); // Precalcula el recorrido de la luna
|
void createMoonPath(); // Precalcula el recorrido de la luna
|
||||||
};
|
};
|
||||||
+290
-344
@@ -1,440 +1,386 @@
|
|||||||
#include "balloon.h"
|
#include "balloon.h"
|
||||||
|
|
||||||
#include <algorithm> // Para clamp
|
#include <algorithm> // Para clamp
|
||||||
#include <array> // Para array
|
#include <array> // Para array
|
||||||
#include <cmath> // Para fabs
|
#include <cmath> // Para fabs
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
#include "audio.h" // Para Audio
|
#include "audio.h" // Para Audio
|
||||||
#include "param.h" // Para Param, ParamBalloon, param
|
#include "param.h" // Para Param, ParamBalloon, param
|
||||||
#include "sprite.h" // Para Sprite
|
#include "sprite.h" // Para Sprite
|
||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel_x, float speed, Uint16 creation_timer, SDL_FRect play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
|
Balloon::Balloon(float x, float y, BalloonType type, BalloonSize size, float vel_x, float speed, Uint16 creation_timer, SDL_FRect play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
|
||||||
: sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
|
: sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
|
||||||
x_(x),
|
x_(x),
|
||||||
y_(y),
|
y_(y),
|
||||||
vx_(vel_x),
|
vx_(vel_x),
|
||||||
being_created_(creation_timer > 0),
|
being_created_(creation_timer > 0),
|
||||||
invulnerable_(creation_timer > 0),
|
invulnerable_(creation_timer > 0),
|
||||||
stopped_(creation_timer > 0),
|
stopped_(creation_timer > 0),
|
||||||
creation_counter_(creation_timer),
|
creation_counter_(creation_timer),
|
||||||
creation_counter_ini_(creation_timer),
|
creation_counter_ini_(creation_timer),
|
||||||
type_(type),
|
type_(type),
|
||||||
size_(size),
|
size_(size),
|
||||||
speed_(speed),
|
speed_(speed),
|
||||||
play_area_(play_area)
|
play_area_(play_area) {
|
||||||
{
|
switch (type_) {
|
||||||
switch (type_)
|
case BalloonType::BALLOON: {
|
||||||
{
|
vy_ = 0;
|
||||||
case BalloonType::BALLOON:
|
max_vy_ = 3.0f;
|
||||||
{
|
|
||||||
vy_ = 0;
|
|
||||||
max_vy_ = 3.0f;
|
|
||||||
|
|
||||||
const int index = static_cast<int>(size_);
|
const int index = static_cast<int>(size_);
|
||||||
gravity_ = param.balloon.settings.at(index).grav;
|
gravity_ = param.balloon.settings.at(index).grav;
|
||||||
default_vy_ = param.balloon.settings.at(index).vel;
|
default_vy_ = param.balloon.settings.at(index).vel;
|
||||||
h_ = w_ = BALLOON_SIZE[index];
|
h_ = w_ = BALLOON_SIZE[index];
|
||||||
power_ = BALLOON_POWER[index];
|
power_ = BALLOON_POWER[index];
|
||||||
menace_ = BALLOON_MENACE[index];
|
menace_ = BALLOON_MENACE[index];
|
||||||
score_ = BALLOON_SCORE[index];
|
score_ = BALLOON_SCORE[index];
|
||||||
bouncing_sound_ = BALLOON_BOUNCING_SOUND[index];
|
bouncing_sound_ = BALLOON_BOUNCING_SOUND[index];
|
||||||
popping_sound_ = BALLOON_POPPING_SOUND[index];
|
popping_sound_ = BALLOON_POPPING_SOUND[index];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case BalloonType::FLOATER:
|
case BalloonType::FLOATER: {
|
||||||
{
|
default_vy_ = max_vy_ = vy_ = fabs(vx_ * 2.0f);
|
||||||
default_vy_ = max_vy_ = vy_ = fabs(vx_ * 2.0f);
|
gravity_ = 0.00f;
|
||||||
gravity_ = 0.00f;
|
|
||||||
|
|
||||||
const int index = static_cast<int>(size_);
|
const int index = static_cast<int>(size_);
|
||||||
h_ = w_ = BALLOON_SIZE[index];
|
h_ = w_ = BALLOON_SIZE[index];
|
||||||
power_ = BALLOON_POWER[index];
|
power_ = BALLOON_POWER[index];
|
||||||
menace_ = BALLOON_MENACE[index];
|
menace_ = BALLOON_MENACE[index];
|
||||||
score_ = BALLOON_SCORE[index];
|
score_ = BALLOON_SCORE[index];
|
||||||
bouncing_sound_ = BALLOON_BOUNCING_SOUND[index];
|
bouncing_sound_ = BALLOON_BOUNCING_SOUND[index];
|
||||||
popping_sound_ = BALLOON_POPPING_SOUND[index];
|
popping_sound_ = BALLOON_POPPING_SOUND[index];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case BalloonType::POWERBALL:
|
case BalloonType::POWERBALL: {
|
||||||
{
|
constexpr int index = 3;
|
||||||
constexpr int index = 3;
|
h_ = w_ = BALLOON_SIZE[4];
|
||||||
h_ = w_ = BALLOON_SIZE[4];
|
bouncing_sound_ = BALLOON_BOUNCING_SOUND[3];
|
||||||
bouncing_sound_ = BALLOON_BOUNCING_SOUND[3];
|
popping_sound_ = "power_ball_explosion.wav";
|
||||||
popping_sound_ = "power_ball_explosion.wav";
|
power_ = score_ = menace_ = 0;
|
||||||
power_ = score_ = menace_ = 0;
|
|
||||||
|
|
||||||
vy_ = 0;
|
vy_ = 0;
|
||||||
max_vy_ = 3.0f;
|
max_vy_ = 3.0f;
|
||||||
gravity_ = param.balloon.settings.at(index).grav;
|
gravity_ = param.balloon.settings.at(index).grav;
|
||||||
default_vy_ = param.balloon.settings.at(index).vel;
|
default_vy_ = param.balloon.settings.at(index).vel;
|
||||||
|
|
||||||
sprite_->setRotate(creation_timer <= 0);
|
sprite_->setRotate(creation_timer <= 0);
|
||||||
sprite_->setRotateAmount(vx_ > 0.0f ? 2.0 : -2.0);
|
sprite_->setRotateAmount(vx_ > 0.0f ? 2.0 : -2.0);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configura el sprite
|
// Configura el sprite
|
||||||
sprite_->setWidth(w_);
|
sprite_->setWidth(w_);
|
||||||
sprite_->setHeight(h_);
|
sprite_->setHeight(h_);
|
||||||
shiftSprite();
|
shiftSprite();
|
||||||
|
|
||||||
// Alinea el circulo de colisión con el objeto
|
// Alinea el circulo de colisión con el objeto
|
||||||
collider_.r = w_ / 2;
|
collider_.r = w_ / 2;
|
||||||
shiftColliders();
|
shiftColliders();
|
||||||
|
|
||||||
// Establece la animación a usar
|
// Establece la animación a usar
|
||||||
setAnimation();
|
setAnimation();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Centra el globo en la posición X
|
// Centra el globo en la posición X
|
||||||
void Balloon::alignTo(int x)
|
void Balloon::alignTo(int x) {
|
||||||
{
|
x_ = static_cast<float>(x - (w_ / 2));
|
||||||
x_ = static_cast<float>(x - (w_ / 2));
|
const int min_x = play_area_.x;
|
||||||
const int min_x = play_area_.x;
|
const int max_x = play_area_.w - w_;
|
||||||
const int max_x = play_area_.w - w_;
|
x_ = std::clamp(x_, static_cast<float>(min_x), static_cast<float>(max_x));
|
||||||
x_ = std::clamp(x_, static_cast<float>(min_x), static_cast<float>(max_x));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pinta el globo en la pantalla
|
// Pinta el globo en la pantalla
|
||||||
void Balloon::render()
|
void Balloon::render() {
|
||||||
{
|
if (type_ == BalloonType::POWERBALL) {
|
||||||
if (type_ == BalloonType::POWERBALL)
|
// Renderiza el fondo azul
|
||||||
{
|
{
|
||||||
// Renderiza el fondo azul
|
auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
|
||||||
{
|
sp->setSpriteClip(0, 0, BALLOON_SIZE[4], BALLOON_SIZE[4]);
|
||||||
auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
|
sp->render();
|
||||||
sp->setSpriteClip(0, 0, BALLOON_SIZE[4], BALLOON_SIZE[4]);
|
}
|
||||||
sp->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Renderiza la estrella
|
// Renderiza la estrella
|
||||||
if (!invulnerable_)
|
if (!invulnerable_) {
|
||||||
{
|
SDL_FPoint p = {24.0f, 24.0f};
|
||||||
SDL_FPoint p = {24.0f, 24.0f};
|
sprite_->setRotatingCenter(p);
|
||||||
sprite_->setRotatingCenter(p);
|
sprite_->render();
|
||||||
sprite_->render();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Añade la máscara del borde y los reflejos
|
// Añade la máscara del borde y los reflejos
|
||||||
{
|
{
|
||||||
auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
|
auto sp = std::make_unique<Sprite>(sprite_->getTexture(), sprite_->getPosition());
|
||||||
sp->setSpriteClip(BALLOON_SIZE[4] * 2, 0, BALLOON_SIZE[4], BALLOON_SIZE[4]);
|
sp->setSpriteClip(BALLOON_SIZE[4] * 2, 0, BALLOON_SIZE[4], BALLOON_SIZE[4]);
|
||||||
sp->render();
|
sp->render();
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
// Renderizado para el resto de globos
|
||||||
{
|
if (isBeingCreated()) {
|
||||||
// Renderizado para el resto de globos
|
// Renderizado con transparencia
|
||||||
if (isBeingCreated())
|
sprite_->getTexture()->setAlpha(255 - (int)((float)creation_counter_ * (255.0f / (float)creation_counter_ini_)));
|
||||||
{
|
sprite_->render();
|
||||||
// Renderizado con transparencia
|
sprite_->getTexture()->setAlpha(255);
|
||||||
sprite_->getTexture()->setAlpha(255 - (int)((float)creation_counter_ * (255.0f / (float)creation_counter_ini_)));
|
} else {
|
||||||
sprite_->render();
|
// Renderizado normal
|
||||||
sprite_->getTexture()->setAlpha(255);
|
sprite_->render();
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
// Renderizado normal
|
|
||||||
sprite_->render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza la posición y estados del globo
|
// Actualiza la posición y estados del globo
|
||||||
void Balloon::move()
|
void Balloon::move() {
|
||||||
{
|
// Comprueba si se puede mover
|
||||||
// Comprueba si se puede mover
|
if (!isStopped()) {
|
||||||
if (!isStopped())
|
// Mueve el globo en horizontal
|
||||||
{
|
x_ += vx_ * speed_;
|
||||||
// Mueve el globo en horizontal
|
|
||||||
x_ += vx_ * speed_;
|
|
||||||
|
|
||||||
// Colisión en las partes laterales de la zona de juego
|
// Colisión en las partes laterales de la zona de juego
|
||||||
const int clip = 2;
|
const int clip = 2;
|
||||||
const float min_x = play_area_.x - clip;
|
const float min_x = play_area_.x - clip;
|
||||||
const float max_x = play_area_.x + play_area_.w - w_ + clip;
|
const float max_x = play_area_.x + play_area_.w - w_ + clip;
|
||||||
if (x_ < min_x || x_ > max_x)
|
if (x_ < min_x || x_ > max_x) {
|
||||||
{
|
if (bouncing_sound_enabled_)
|
||||||
if (bouncing_sound_enabled_)
|
playSound(bouncing_sound_);
|
||||||
playSound(bouncing_sound_);
|
x_ = std::clamp(x_, min_x, max_x);
|
||||||
x_ = std::clamp(x_, min_x, max_x);
|
vx_ = -vx_;
|
||||||
vx_ = -vx_;
|
// Activa el efecto de rebote o invierte la rotación
|
||||||
// Activa el efecto de rebote o invierte la rotación
|
if (type_ == BalloonType::POWERBALL) {
|
||||||
if (type_ == BalloonType::POWERBALL)
|
sprite_->switchRotate();
|
||||||
{
|
} else {
|
||||||
sprite_->switchRotate();
|
enableBounce();
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
enableBounce();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mueve el globo en vertical
|
// Mueve el globo en vertical
|
||||||
y_ += vy_ * speed_;
|
y_ += vy_ * speed_;
|
||||||
|
|
||||||
// Colisión en la parte superior solo si el globo va de subida
|
// Colisión en la parte superior solo si el globo va de subida
|
||||||
if (vy_ < 0)
|
if (vy_ < 0) {
|
||||||
{
|
const int min_y = play_area_.y;
|
||||||
const int min_y = play_area_.y;
|
if (y_ < min_y) {
|
||||||
if (y_ < min_y)
|
if (bouncing_sound_enabled_)
|
||||||
{
|
playSound(bouncing_sound_);
|
||||||
if (bouncing_sound_enabled_)
|
y_ = min_y;
|
||||||
playSound(bouncing_sound_);
|
vy_ = -vy_;
|
||||||
y_ = min_y;
|
enableBounce();
|
||||||
vy_ = -vy_;
|
}
|
||||||
enableBounce();
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Colisión en la parte inferior de la zona de juego
|
// Colisión en la parte inferior de la zona de juego
|
||||||
const int max_y = play_area_.y + play_area_.h - h_;
|
const int max_y = play_area_.y + play_area_.h - h_;
|
||||||
if (y_ > max_y)
|
if (y_ > max_y) {
|
||||||
{
|
if (bouncing_sound_enabled_)
|
||||||
if (bouncing_sound_enabled_)
|
playSound(bouncing_sound_);
|
||||||
playSound(bouncing_sound_);
|
y_ = max_y;
|
||||||
y_ = max_y;
|
vy_ = -default_vy_;
|
||||||
vy_ = -default_vy_;
|
if (type_ != BalloonType::POWERBALL) {
|
||||||
if (type_ != BalloonType::POWERBALL)
|
enableBounce();
|
||||||
{
|
} else {
|
||||||
enableBounce();
|
setInvulnerable(false);
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
setInvulnerable(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
Para aplicar la gravedad, el diseño original la aplicaba en cada iteración del bucle
|
Para aplicar la gravedad, el diseño original la aplicaba en cada iteración del bucle
|
||||||
Al añadir el modificador de velocidad se reduce la distancia que recorre el objeto y por
|
Al añadir el modificador de velocidad se reduce la distancia que recorre el objeto y por
|
||||||
tanto recibe mas gravedad. Para solucionarlo se va a aplicar la gravedad cuando se haya
|
tanto recibe mas gravedad. Para solucionarlo se va a aplicar la gravedad cuando se haya
|
||||||
recorrido una distancia igual a la velocidad en Y, que era el cálculo inicial
|
recorrido una distancia igual a la velocidad en Y, que era el cálculo inicial
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Incrementa la variable que calcula la distancia acumulada en Y
|
// Incrementa la variable que calcula la distancia acumulada en Y
|
||||||
travel_y_ += speed_;
|
travel_y_ += speed_;
|
||||||
|
|
||||||
// Si la distancia acumulada en Y es igual a la velocidad, se aplica la gravedad
|
// Si la distancia acumulada en Y es igual a la velocidad, se aplica la gravedad
|
||||||
if (travel_y_ >= 1.0f)
|
if (travel_y_ >= 1.0f) {
|
||||||
{
|
// Quita el excedente
|
||||||
// Quita el excedente
|
travel_y_ -= 1.0f;
|
||||||
travel_y_ -= 1.0f;
|
|
||||||
|
|
||||||
// Aplica la gravedad al objeto sin pasarse de una velocidad máxima
|
// Aplica la gravedad al objeto sin pasarse de una velocidad máxima
|
||||||
vy_ += gravity_;
|
vy_ += gravity_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza al globo a su posicion, animación y controla los contadores
|
// Actualiza al globo a su posicion, animación y controla los contadores
|
||||||
void Balloon::update()
|
void Balloon::update() {
|
||||||
{
|
move();
|
||||||
move();
|
updateState();
|
||||||
updateState();
|
updateBounce();
|
||||||
updateBounce();
|
shiftSprite();
|
||||||
shiftSprite();
|
shiftColliders();
|
||||||
shiftColliders();
|
sprite_->update();
|
||||||
sprite_->update();
|
++counter_;
|
||||||
++counter_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza los estados del globo
|
// Actualiza los estados del globo
|
||||||
void Balloon::updateState()
|
void Balloon::updateState() {
|
||||||
{
|
// Si se está creando
|
||||||
// Si se está creando
|
if (isBeingCreated()) {
|
||||||
if (isBeingCreated())
|
// Actualiza el valor de las variables
|
||||||
{
|
stop();
|
||||||
// Actualiza el valor de las variables
|
setInvulnerable(true);
|
||||||
stop();
|
|
||||||
setInvulnerable(true);
|
|
||||||
|
|
||||||
if (creation_counter_ > 0)
|
if (creation_counter_ > 0) {
|
||||||
{
|
// Desplaza lentamente el globo hacia abajo y hacia un lado
|
||||||
// Desplaza lentamente el globo hacia abajo y hacia un lado
|
if (creation_counter_ % 10 == 0) {
|
||||||
if (creation_counter_ % 10 == 0)
|
y_++;
|
||||||
{
|
x_ += vx_;
|
||||||
y_++;
|
|
||||||
x_ += vx_;
|
|
||||||
|
|
||||||
// Comprueba no se salga por los laterales
|
// Comprueba no se salga por los laterales
|
||||||
const int min_x = play_area_.x;
|
const int min_x = play_area_.x;
|
||||||
const int max_x = play_area_.w - w_;
|
const int max_x = play_area_.w - w_;
|
||||||
|
|
||||||
if (x_ < min_x || x_ > max_x)
|
if (x_ < min_x || x_ > max_x) {
|
||||||
{
|
// Corrige y cambia el sentido de la velocidad
|
||||||
// Corrige y cambia el sentido de la velocidad
|
x_ -= vx_;
|
||||||
x_ -= vx_;
|
vx_ = -vx_;
|
||||||
vx_ = -vx_;
|
}
|
||||||
}
|
}
|
||||||
}
|
--creation_counter_;
|
||||||
--creation_counter_;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
else
|
else {
|
||||||
{
|
// El contador ha llegado a cero
|
||||||
// El contador ha llegado a cero
|
being_created_ = false;
|
||||||
being_created_ = false;
|
start();
|
||||||
start();
|
setInvulnerable(false);
|
||||||
setInvulnerable(false);
|
setAnimation();
|
||||||
setAnimation();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece la animación correspondiente al estado
|
// Establece la animación correspondiente al estado
|
||||||
void Balloon::setAnimation()
|
void Balloon::setAnimation() {
|
||||||
{
|
std::string creating_animation;
|
||||||
std::string creating_animation;
|
std::string normal_animation;
|
||||||
std::string normal_animation;
|
|
||||||
|
|
||||||
switch (type_)
|
switch (type_) {
|
||||||
{
|
case BalloonType::POWERBALL:
|
||||||
case BalloonType::POWERBALL:
|
creating_animation = "powerball";
|
||||||
creating_animation = "powerball";
|
normal_animation = "powerball";
|
||||||
normal_animation = "powerball";
|
break;
|
||||||
break;
|
case BalloonType::FLOATER:
|
||||||
case BalloonType::FLOATER:
|
creating_animation = param.balloon.color.at(2);
|
||||||
creating_animation = param.balloon.color.at(2);
|
normal_animation = param.balloon.color.at(3);
|
||||||
normal_animation = param.balloon.color.at(3);
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
creating_animation = param.balloon.color.at(0);
|
||||||
creating_animation = param.balloon.color.at(0);
|
normal_animation = param.balloon.color.at(1);
|
||||||
normal_animation = param.balloon.color.at(1);
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Establece el frame de animación
|
// Establece el frame de animación
|
||||||
if (use_reversed_colors_)
|
if (use_reversed_colors_)
|
||||||
sprite_->setCurrentAnimation(creating_animation);
|
sprite_->setCurrentAnimation(creating_animation);
|
||||||
else
|
else
|
||||||
sprite_->setCurrentAnimation(isBeingCreated() ? creating_animation : normal_animation);
|
sprite_->setCurrentAnimation(isBeingCreated() ? creating_animation : normal_animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detiene el globo
|
// Detiene el globo
|
||||||
void Balloon::stop()
|
void Balloon::stop() {
|
||||||
{
|
stopped_ = true;
|
||||||
stopped_ = true;
|
if (isPowerBall()) {
|
||||||
if (isPowerBall())
|
sprite_->setRotate(!stopped_);
|
||||||
{
|
}
|
||||||
sprite_->setRotate(!stopped_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pone el globo en movimiento
|
// Pone el globo en movimiento
|
||||||
void Balloon::start()
|
void Balloon::start() {
|
||||||
{
|
stopped_ = false;
|
||||||
stopped_ = false;
|
if (isPowerBall()) {
|
||||||
if (isPowerBall())
|
sprite_->setRotate(!stopped_);
|
||||||
{
|
}
|
||||||
sprite_->setRotate(!stopped_);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alinea el circulo de colisión con la posición del objeto globo
|
// Alinea el circulo de colisión con la posición del objeto globo
|
||||||
void Balloon::shiftColliders()
|
void Balloon::shiftColliders() {
|
||||||
{
|
collider_.x = static_cast<int>(x_) + collider_.r;
|
||||||
collider_.x = static_cast<int>(x_) + collider_.r;
|
collider_.y = static_cast<int>(y_) + collider_.r;
|
||||||
collider_.y = static_cast<int>(y_) + collider_.r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alinea el sprite con la posición del objeto globo
|
// Alinea el sprite con la posición del objeto globo
|
||||||
void Balloon::shiftSprite()
|
void Balloon::shiftSprite() {
|
||||||
{
|
sprite_->setPosX(x_);
|
||||||
sprite_->setPosX(x_);
|
sprite_->setPosY(y_);
|
||||||
sprite_->setPosY(y_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el nivel de zoom del sprite
|
// Establece el nivel de zoom del sprite
|
||||||
void Balloon::zoomSprite()
|
void Balloon::zoomSprite() {
|
||||||
{
|
sprite_->setZoomW(bouncing_.zoomW);
|
||||||
sprite_->setZoomW(bouncing_.zoomW);
|
sprite_->setZoomH(bouncing_.zoomH);
|
||||||
sprite_->setZoomH(bouncing_.zoomH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activa el efecto
|
// Activa el efecto
|
||||||
void Balloon::enableBounce()
|
void Balloon::enableBounce() {
|
||||||
{
|
bouncing_.enabled = true;
|
||||||
bouncing_.enabled = true;
|
bouncing_.reset();
|
||||||
bouncing_.reset();
|
zoomSprite();
|
||||||
zoomSprite();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detiene el efecto
|
// Detiene el efecto
|
||||||
void Balloon::disableBounce()
|
void Balloon::disableBounce() {
|
||||||
{
|
bouncing_.enabled = false;
|
||||||
bouncing_.enabled = false;
|
bouncing_.reset();
|
||||||
bouncing_.reset();
|
zoomSprite();
|
||||||
zoomSprite();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aplica el efecto
|
// Aplica el efecto
|
||||||
void Balloon::updateBounce()
|
void Balloon::updateBounce() {
|
||||||
{
|
if (bouncing_.enabled) {
|
||||||
if (bouncing_.enabled)
|
const int index = bouncing_.counter / bouncing_.speed;
|
||||||
{
|
bouncing_.zoomW = bouncing_.w[index];
|
||||||
const int index = bouncing_.counter / bouncing_.speed;
|
bouncing_.zoomH = bouncing_.h[index];
|
||||||
bouncing_.zoomW = bouncing_.w[index];
|
|
||||||
bouncing_.zoomH = bouncing_.h[index];
|
|
||||||
|
|
||||||
zoomSprite();
|
zoomSprite();
|
||||||
|
|
||||||
if (++bouncing_.counter / bouncing_.speed >= MAX_BOUNCE)
|
if (++bouncing_.counter / bouncing_.speed >= MAX_BOUNCE) {
|
||||||
{
|
disableBounce();
|
||||||
disableBounce();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pone el color alternativo en el globo
|
// Pone el color alternativo en el globo
|
||||||
void Balloon::useReverseColor()
|
void Balloon::useReverseColor() {
|
||||||
{
|
if (!isBeingCreated()) {
|
||||||
if (!isBeingCreated())
|
use_reversed_colors_ = true;
|
||||||
{
|
setAnimation();
|
||||||
use_reversed_colors_ = true;
|
}
|
||||||
setAnimation();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pone el color normal en el globo
|
// Pone el color normal en el globo
|
||||||
void Balloon::useNormalColor()
|
void Balloon::useNormalColor() {
|
||||||
{
|
use_reversed_colors_ = false;
|
||||||
use_reversed_colors_ = false;
|
setAnimation();
|
||||||
setAnimation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reproduce sonido
|
// Reproduce sonido
|
||||||
void Balloon::playSound(const std::string &name)
|
void Balloon::playSound(const std::string &name) {
|
||||||
{
|
if (!sound_enabled_)
|
||||||
if (!sound_enabled_)
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
static auto audio = Audio::get();
|
static auto audio = Audio::get();
|
||||||
audio->playSound(name);
|
audio->playSound(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explota el globo
|
// Explota el globo
|
||||||
void Balloon::pop(bool should_sound)
|
void Balloon::pop(bool should_sound) {
|
||||||
{
|
if (should_sound) {
|
||||||
if (should_sound)
|
if (poping_sound_enabled_)
|
||||||
{
|
playSound(popping_sound_);
|
||||||
if (poping_sound_enabled_)
|
}
|
||||||
playSound(popping_sound_);
|
|
||||||
}
|
|
||||||
|
|
||||||
enabled_ = false;
|
enabled_ = false;
|
||||||
}
|
}
|
||||||
+133
-137
@@ -1,17 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para Uint8, Uint16, SDL_FRect, Uint32
|
#include <SDL3/SDL.h> // Para Uint8, Uint16, SDL_FRect, Uint32
|
||||||
#include <memory> // Para shared_ptr, unique_ptr
|
|
||||||
#include <string> // Para basic_string, string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include <memory> // Para shared_ptr, unique_ptr
|
||||||
#include "utils.h" // Para Circle
|
#include <string> // Para basic_string, string
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
|
#include "utils.h" // Para Circle
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// --- Constantes relacionadas con globos ---
|
// --- Constantes relacionadas con globos ---
|
||||||
constexpr int MAX_BOUNCE = 10; // Cantidad de elementos del vector de deformación
|
constexpr int MAX_BOUNCE = 10; // Cantidad de elementos del vector de deformación
|
||||||
|
|
||||||
constexpr int BALLOON_SCORE[] = {50, 100, 200, 400};
|
constexpr int BALLOON_SCORE[] = {50, 100, 200, 400};
|
||||||
constexpr int BALLOON_POWER[] = {1, 3, 7, 15};
|
constexpr int BALLOON_POWER[] = {1, 3, 7, 15};
|
||||||
@@ -20,19 +21,17 @@ constexpr int BALLOON_SIZE[] = {10, 16, 26, 48, 49};
|
|||||||
const std::string BALLOON_BOUNCING_SOUND[] = {"bubble1.wav", "bubble2.wav", "bubble3.wav", "bubble4.wav"};
|
const std::string BALLOON_BOUNCING_SOUND[] = {"bubble1.wav", "bubble2.wav", "bubble3.wav", "bubble4.wav"};
|
||||||
const std::string BALLOON_POPPING_SOUND[] = {"balloon1.wav", "balloon2.wav", "balloon3.wav", "balloon4.wav"};
|
const std::string BALLOON_POPPING_SOUND[] = {"balloon1.wav", "balloon2.wav", "balloon3.wav", "balloon4.wav"};
|
||||||
|
|
||||||
enum class BalloonSize : Uint8
|
enum class BalloonSize : Uint8 {
|
||||||
{
|
SIZE1 = 0,
|
||||||
SIZE1 = 0,
|
SIZE2 = 1,
|
||||||
SIZE2 = 1,
|
SIZE3 = 2,
|
||||||
SIZE3 = 2,
|
SIZE4 = 3,
|
||||||
SIZE4 = 3,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class BalloonType : Uint8
|
enum class BalloonType : Uint8 {
|
||||||
{
|
BALLOON = 0,
|
||||||
BALLOON = 0,
|
FLOATER = 1,
|
||||||
FLOATER = 1,
|
POWERBALL = 2,
|
||||||
POWERBALL = 2,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr float BALLOON_VELX_POSITIVE = 0.7f;
|
constexpr float BALLOON_VELX_POSITIVE = 0.7f;
|
||||||
@@ -48,133 +47,130 @@ constexpr int POWERBALL_SCREENPOWER_MINIMUM = 10;
|
|||||||
constexpr int POWERBALL_COUNTER = 8;
|
constexpr int POWERBALL_COUNTER = 8;
|
||||||
|
|
||||||
// --- Clase Balloon ---
|
// --- Clase Balloon ---
|
||||||
class Balloon
|
class Balloon {
|
||||||
{
|
public:
|
||||||
public:
|
// --- Constructores y destructor ---
|
||||||
// --- Constructores y destructor ---
|
Balloon(
|
||||||
Balloon(
|
float x,
|
||||||
float x,
|
float y,
|
||||||
float y,
|
BalloonType type,
|
||||||
BalloonType type,
|
BalloonSize size,
|
||||||
BalloonSize size,
|
float vel_x,
|
||||||
float vel_x,
|
float speed,
|
||||||
float speed,
|
Uint16 creation_timer,
|
||||||
Uint16 creation_timer,
|
SDL_FRect play_area,
|
||||||
SDL_FRect play_area,
|
std::shared_ptr<Texture> texture,
|
||||||
std::shared_ptr<Texture> texture,
|
const std::vector<std::string> &animation);
|
||||||
const std::vector<std::string> &animation);
|
~Balloon() = default;
|
||||||
~Balloon() = default;
|
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
void alignTo(int x); // Centra el globo en la posición X
|
void alignTo(int x); // Centra el globo en la posición X
|
||||||
void render(); // Pinta el globo en la pantalla
|
void render(); // Pinta el globo en la pantalla
|
||||||
void move(); // Actualiza la posición y estados del globo
|
void move(); // Actualiza la posición y estados del globo
|
||||||
void update(); // Actualiza el globo (posición, animación, contadores)
|
void update(); // Actualiza el globo (posición, animación, contadores)
|
||||||
void stop(); // Detiene el globo
|
void stop(); // Detiene el globo
|
||||||
void start(); // Pone el globo en movimiento
|
void start(); // Pone el globo en movimiento
|
||||||
void pop(bool should_sound = false); // Explota el globo
|
void pop(bool should_sound = false); // Explota el globo
|
||||||
|
|
||||||
// --- Métodos de color ---
|
// --- Métodos de color ---
|
||||||
void useReverseColor(); // Pone el color alternativo en el globo
|
void useReverseColor(); // Pone el color alternativo en el globo
|
||||||
void useNormalColor(); // Pone el color normal en el globo
|
void useNormalColor(); // Pone el color normal en el globo
|
||||||
|
|
||||||
// --- Getters ---
|
// --- Getters ---
|
||||||
float getPosX() const { return x_; }
|
float getPosX() const { return x_; }
|
||||||
float getPosY() const { return y_; }
|
float getPosY() const { return y_; }
|
||||||
int getWidth() const { return w_; }
|
int getWidth() const { return w_; }
|
||||||
int getHeight() const { return h_; }
|
int getHeight() const { return h_; }
|
||||||
BalloonSize getSize() const { return size_; }
|
BalloonSize getSize() const { return size_; }
|
||||||
BalloonType getType() const { return type_; }
|
BalloonType getType() const { return type_; }
|
||||||
Uint16 getScore() const { return score_; }
|
Uint16 getScore() const { return score_; }
|
||||||
Circle &getCollider() { return collider_; }
|
Circle &getCollider() { return collider_; }
|
||||||
Uint8 getMenace() const { return isEnabled() ? menace_ : 0; }
|
Uint8 getMenace() const { return isEnabled() ? menace_ : 0; }
|
||||||
Uint8 getPower() const { return power_; }
|
Uint8 getPower() const { return power_; }
|
||||||
bool isStopped() const { return stopped_; }
|
bool isStopped() const { return stopped_; }
|
||||||
bool isPowerBall() const { return type_ == BalloonType::POWERBALL; }
|
bool isPowerBall() const { return type_ == BalloonType::POWERBALL; }
|
||||||
bool isInvulnerable() const { return invulnerable_; }
|
bool isInvulnerable() const { return invulnerable_; }
|
||||||
bool isBeingCreated() const { return being_created_; }
|
bool isBeingCreated() const { return being_created_; }
|
||||||
bool isEnabled() const { return enabled_; }
|
bool isEnabled() const { return enabled_; }
|
||||||
bool isUsingReversedColor() { return use_reversed_colors_; }
|
bool isUsingReversedColor() { return use_reversed_colors_; }
|
||||||
bool canBePopped() const { return !isBeingCreated(); }
|
bool canBePopped() const { return !isBeingCreated(); }
|
||||||
|
|
||||||
// --- Setters ---
|
// --- Setters ---
|
||||||
void setVelY(float vel_y) { vy_ = vel_y; }
|
void setVelY(float vel_y) { vy_ = vel_y; }
|
||||||
void setSpeed(float speed) { speed_ = speed; }
|
void setSpeed(float speed) { speed_ = speed; }
|
||||||
void setInvulnerable(bool value) { invulnerable_ = value; }
|
void setInvulnerable(bool value) { invulnerable_ = value; }
|
||||||
void setBouncingSound(bool value) { bouncing_sound_enabled_ = value; }
|
void setBouncingSound(bool value) { bouncing_sound_enabled_ = value; }
|
||||||
void setPoppingSound(bool value) { poping_sound_enabled_ = value; }
|
void setPoppingSound(bool value) { poping_sound_enabled_ = value; }
|
||||||
void setSound(bool value) { sound_enabled_ = value; }
|
void setSound(bool value) { sound_enabled_ = value; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Estructura para el efecto de rebote ---
|
// --- Estructura para el efecto de rebote ---
|
||||||
struct Bouncing
|
struct Bouncing {
|
||||||
{
|
bool enabled = false; // Si el efecto está activo
|
||||||
bool enabled = false; // Si el efecto está activo
|
Uint8 counter = 0; // Contador para el efecto
|
||||||
Uint8 counter = 0; // Contador para el efecto
|
Uint8 speed = 2; // Velocidad del efecto
|
||||||
Uint8 speed = 2; // Velocidad del efecto
|
float zoomW = 1.0f; // Zoom en anchura
|
||||||
float zoomW = 1.0f; // Zoom en anchura
|
float zoomH = 1.0f; // Zoom en altura
|
||||||
float zoomH = 1.0f; // Zoom en altura
|
float despX = 0.0f; // Desplazamiento X antes de pintar
|
||||||
float despX = 0.0f; // Desplazamiento X antes de pintar
|
float despY = 0.0f; // Desplazamiento Y antes de pintar
|
||||||
float despY = 0.0f; // Desplazamiento Y antes de pintar
|
|
||||||
|
|
||||||
float w[MAX_BOUNCE] = {1.10f, 1.05f, 1.00f, 0.95f, 0.90f, 0.95f, 1.00f, 1.02f, 1.05f, 1.02f}; // Zoom ancho
|
float w[MAX_BOUNCE] = {1.10f, 1.05f, 1.00f, 0.95f, 0.90f, 0.95f, 1.00f, 1.02f, 1.05f, 1.02f}; // Zoom ancho
|
||||||
float h[MAX_BOUNCE] = {0.90f, 0.95f, 1.00f, 1.05f, 1.10f, 1.05f, 1.00f, 0.98f, 0.95f, 0.98f}; // Zoom alto
|
float h[MAX_BOUNCE] = {0.90f, 0.95f, 1.00f, 1.05f, 1.10f, 1.05f, 1.00f, 0.98f, 0.95f, 0.98f}; // Zoom alto
|
||||||
|
|
||||||
Bouncing() = default;
|
Bouncing() = default;
|
||||||
void reset()
|
void reset() {
|
||||||
{
|
counter = 0;
|
||||||
counter = 0;
|
zoomW = 1.0f;
|
||||||
zoomW = 1.0f;
|
zoomH = 1.0f;
|
||||||
zoomH = 1.0f;
|
despX = 0.0f;
|
||||||
despX = 0.0f;
|
despY = 0.0f;
|
||||||
despY = 0.0f;
|
}
|
||||||
}
|
} bouncing_;
|
||||||
} bouncing_;
|
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
std::unique_ptr<AnimatedSprite> sprite_; // Sprite del objeto globo
|
std::unique_ptr<AnimatedSprite> sprite_; // Sprite del objeto globo
|
||||||
|
|
||||||
// --- Variables de estado y físicas ---
|
// --- Variables de estado y físicas ---
|
||||||
float x_; // Posición X
|
float x_; // Posición X
|
||||||
float y_; // Posición Y
|
float y_; // Posición Y
|
||||||
float w_; // Ancho
|
float w_; // Ancho
|
||||||
float h_; // Alto
|
float h_; // Alto
|
||||||
float vx_; // Velocidad X
|
float vx_; // Velocidad X
|
||||||
float vy_; // Velocidad Y
|
float vy_; // Velocidad Y
|
||||||
float gravity_; // Aceleración en Y
|
float gravity_; // Aceleración en Y
|
||||||
float default_vy_; // Velocidad inicial al rebotar
|
float default_vy_; // Velocidad inicial al rebotar
|
||||||
float max_vy_; // Máxima velocidad en Y
|
float max_vy_; // Máxima velocidad en Y
|
||||||
bool being_created_; // Si el globo se está creando
|
bool being_created_; // Si el globo se está creando
|
||||||
bool enabled_ = true; // Si el globo está activo
|
bool enabled_ = true; // Si el globo está activo
|
||||||
bool invulnerable_; // Si el globo es invulnerable
|
bool invulnerable_; // Si el globo es invulnerable
|
||||||
bool stopped_; // Si el globo está parado
|
bool stopped_; // Si el globo está parado
|
||||||
bool use_reversed_colors_ = false; // Si se usa el color alternativo
|
bool use_reversed_colors_ = false; // Si se usa el color alternativo
|
||||||
Circle collider_; // Círculo de colisión
|
Circle collider_; // Círculo de colisión
|
||||||
Uint16 creation_counter_; // Temporizador de creación
|
Uint16 creation_counter_; // Temporizador de creación
|
||||||
Uint16 creation_counter_ini_; // Valor inicial del temporizador de creación
|
Uint16 creation_counter_ini_; // Valor inicial del temporizador de creación
|
||||||
Uint16 score_; // Puntos al destruir el globo
|
Uint16 score_; // Puntos al destruir el globo
|
||||||
BalloonType type_; // Tipo de globo
|
BalloonType type_; // Tipo de globo
|
||||||
BalloonSize size_; // Tamaño de globo
|
BalloonSize size_; // Tamaño de globo
|
||||||
Uint8 menace_; // Amenaza que genera el globo
|
Uint8 menace_; // Amenaza que genera el globo
|
||||||
Uint32 counter_ = 0; // Contador interno
|
Uint32 counter_ = 0; // Contador interno
|
||||||
float travel_y_ = 1.0f; // Distancia a recorrer en Y antes de aplicar gravedad
|
float travel_y_ = 1.0f; // Distancia a recorrer en Y antes de aplicar gravedad
|
||||||
float speed_; // Velocidad del globo
|
float speed_; // Velocidad del globo
|
||||||
Uint8 power_; // Poder que alberga el globo
|
Uint8 power_; // Poder que alberga el globo
|
||||||
SDL_FRect play_area_; // Zona de movimiento del globo
|
SDL_FRect play_area_; // Zona de movimiento del globo
|
||||||
std::string bouncing_sound_; // Archivo de sonido al rebotar
|
std::string bouncing_sound_; // Archivo de sonido al rebotar
|
||||||
std::string popping_sound_; // Archivo de sonido al explotar
|
std::string popping_sound_; // Archivo de sonido al explotar
|
||||||
bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar
|
bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar
|
||||||
bool poping_sound_enabled_ = true; // Si debe sonar el globo al explotar
|
bool poping_sound_enabled_ = true; // Si debe sonar el globo al explotar
|
||||||
bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido
|
bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void shiftColliders(); // Alinea el círculo de colisión
|
void shiftColliders(); // Alinea el círculo de colisión
|
||||||
void shiftSprite(); // Alinea el sprite
|
void shiftSprite(); // Alinea el sprite
|
||||||
void zoomSprite(); // Establece el nivel de zoom del sprite
|
void zoomSprite(); // Establece el nivel de zoom del sprite
|
||||||
void enableBounce(); // Activa el efecto de rebote
|
void enableBounce(); // Activa el efecto de rebote
|
||||||
void disableBounce(); // Detiene el efecto de rebote
|
void disableBounce(); // Detiene el efecto de rebote
|
||||||
void updateBounce(); // Aplica el efecto de rebote
|
void updateBounce(); // Aplica el efecto de rebote
|
||||||
void updateState(); // Actualiza los estados del globo
|
void updateState(); // Actualiza los estados del globo
|
||||||
void setAnimation(); // Establece la animación correspondiente
|
void setAnimation(); // Establece la animación correspondiente
|
||||||
void playSound(const std::string &name); // Reproduce sonido
|
void playSound(const std::string &name); // Reproduce sonido
|
||||||
};
|
};
|
||||||
+324
-404
@@ -1,457 +1,377 @@
|
|||||||
#include "balloon_formations.h"
|
#include "balloon_formations.h"
|
||||||
|
|
||||||
#include "balloon.h" // Para BALLOON_VELX_NEGATIVE, BALLOON_VELX_POSITIVE
|
#include "balloon.h" // Para BALLOON_VELX_NEGATIVE, BALLOON_VELX_POSITIVE
|
||||||
#include "param.h" // Para param
|
#include "param.h" // Para param
|
||||||
#include "utils.h" // Para ParamGame, Param, Zone, BLOCK
|
#include "utils.h" // Para ParamGame, Param, Zone, BLOCK
|
||||||
|
|
||||||
void BalloonFormations::initBalloonFormations()
|
void BalloonFormations::initBalloonFormations() {
|
||||||
{
|
constexpr int y4 = -BLOCK;
|
||||||
constexpr int y4 = -BLOCK;
|
const int x4_0 = param.game.play_area.rect.x;
|
||||||
const int x4_0 = param.game.play_area.rect.x;
|
const int x4_100 = param.game.play_area.rect.w - BALLOON_SIZE[3];
|
||||||
const int x4_100 = param.game.play_area.rect.w - BALLOON_SIZE[3];
|
|
||||||
|
|
||||||
constexpr int y3 = -BLOCK;
|
constexpr int y3 = -BLOCK;
|
||||||
const int x3_0 = param.game.play_area.rect.x;
|
const int x3_0 = param.game.play_area.rect.x;
|
||||||
const int x3_100 = param.game.play_area.rect.w - BALLOON_SIZE[2];
|
const int x3_100 = param.game.play_area.rect.w - BALLOON_SIZE[2];
|
||||||
|
|
||||||
constexpr int y2 = -BLOCK;
|
constexpr int y2 = -BLOCK;
|
||||||
const int x2_0 = param.game.play_area.rect.x;
|
const int x2_0 = param.game.play_area.rect.x;
|
||||||
const int x2_100 = param.game.play_area.rect.w - BALLOON_SIZE[1];
|
const int x2_100 = param.game.play_area.rect.w - BALLOON_SIZE[1];
|
||||||
|
|
||||||
constexpr int y1 = -BLOCK;
|
constexpr int y1 = -BLOCK;
|
||||||
const int x1_0 = param.game.play_area.rect.x;
|
const int x1_0 = param.game.play_area.rect.x;
|
||||||
const int x1_50 = param.game.play_area.center_x - (BALLOON_SIZE[0] / 2);
|
const int x1_50 = param.game.play_area.center_x - (BALLOON_SIZE[0] / 2);
|
||||||
const int x1_100 = param.game.play_area.rect.w - BALLOON_SIZE[0];
|
const int x1_100 = param.game.play_area.rect.w - BALLOON_SIZE[0];
|
||||||
|
|
||||||
balloon_formation_.reserve(NUMBER_OF_BALLOON_FORMATIONS);
|
balloon_formation_.reserve(NUMBER_OF_BALLOON_FORMATIONS);
|
||||||
|
|
||||||
constexpr int CREATION_TIME = 300;
|
constexpr int CREATION_TIME = 300;
|
||||||
|
|
||||||
// #00 - Dos enemigos BALLOON4 uno a cada extremo
|
// #00 - Dos enemigos BALLOON4 uno a cada extremo
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params = {
|
std::vector<BalloonFormationParams> init_params = {
|
||||||
BalloonFormationParams(x4_0, y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME),
|
BalloonFormationParams(x4_0, y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME),
|
||||||
BalloonFormationParams(x4_100, y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME)};
|
BalloonFormationParams(x4_100, y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME)};
|
||||||
balloon_formation_.emplace_back(2, init_params);
|
balloon_formation_.emplace_back(2, init_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #01 - Dos enemigos BALLOON4 uno a cada cuarto. Ambos van hacia el centro
|
// #01 - Dos enemigos BALLOON4 uno a cada cuarto. Ambos van hacia el centro
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params = {
|
std::vector<BalloonFormationParams> init_params = {
|
||||||
BalloonFormationParams(param.game.play_area.first_quarter_x - (BALLOON_SIZE[3] / 2), y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME),
|
BalloonFormationParams(param.game.play_area.first_quarter_x - (BALLOON_SIZE[3] / 2), y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME),
|
||||||
BalloonFormationParams(param.game.play_area.third_quarter_x - (BALLOON_SIZE[3] / 2), y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME)};
|
BalloonFormationParams(param.game.play_area.third_quarter_x - (BALLOON_SIZE[3] / 2), y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME)};
|
||||||
balloon_formation_.emplace_back(2, init_params);
|
balloon_formation_.emplace_back(2, init_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #02 - Cuatro enemigos BALLOON2 uno detrás del otro. A la izquierda y hacia el centro
|
// #02 - Cuatro enemigos BALLOON2 uno detrás del otro. A la izquierda y hacia el centro
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i) {
|
||||||
{
|
init_params.emplace_back(x2_0 + (i * (BALLOON_SIZE[1] + 1)), y2, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x2_0 + (i * (BALLOON_SIZE[1] + 1)), y2, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(4, init_params);
|
||||||
balloon_formation_.emplace_back(4, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #03 - Cuatro enemigos BALLOON2 uno detrás del otro. A la derecha y hacia el centro
|
// #03 - Cuatro enemigos BALLOON2 uno detrás del otro. A la derecha y hacia el centro
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i) {
|
||||||
{
|
init_params.emplace_back(x2_100 - (i * (BALLOON_SIZE[1] + 1)), y2, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x2_100 - (i * (BALLOON_SIZE[1] + 1)), y2, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(4, init_params);
|
||||||
balloon_formation_.emplace_back(4, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #04 - Tres enemigos BALLOON3. 0, 25, 50. Hacia la derecha
|
// #04 - Tres enemigos BALLOON3. 0, 25, 50. Hacia la derecha
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i) {
|
||||||
{
|
init_params.emplace_back(x3_0 + (i * (BALLOON_SIZE[2] * 2)), y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x3_0 + (i * (BALLOON_SIZE[2] * 2)), y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(3, init_params);
|
||||||
balloon_formation_.emplace_back(3, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #05 - Tres enemigos BALLOON3. 50, 75, 100. Hacia la izquierda
|
// #05 - Tres enemigos BALLOON3. 50, 75, 100. Hacia la izquierda
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i) {
|
||||||
{
|
init_params.emplace_back(x3_100 - (i * (BALLOON_SIZE[2] * 2)), y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x3_100 - (i * (BALLOON_SIZE[2] * 2)), y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(3, init_params);
|
||||||
balloon_formation_.emplace_back(3, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #06 - Tres enemigos BALLOON3. 0, 0, 0. Hacia la derecha
|
// #06 - Tres enemigos BALLOON3. 0, 0, 0. Hacia la derecha
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i) {
|
||||||
{
|
init_params.emplace_back(x3_0 + (i * (BALLOON_SIZE[2] + 1)), y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x3_0 + (i * (BALLOON_SIZE[2] + 1)), y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(3, init_params);
|
||||||
balloon_formation_.emplace_back(3, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #07 - Tres enemigos BALLOON3. 100, 100, 100. Hacia la izquierda
|
// #07 - Tres enemigos BALLOON3. 100, 100, 100. Hacia la izquierda
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i) {
|
||||||
{
|
init_params.emplace_back(x3_100 - (i * (BALLOON_SIZE[2] + 1)), y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x3_100 - (i * (BALLOON_SIZE[2] + 1)), y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(3, init_params);
|
||||||
balloon_formation_.emplace_back(3, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #08 - Seis enemigos BALLOON1. 0, 0, 0, 0, 0, 0. Hacia la derecha
|
// #08 - Seis enemigos BALLOON1. 0, 0, 0, 0, 0, 0. Hacia la derecha
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i) {
|
||||||
{
|
init_params.emplace_back(x1_0 + (i * (BALLOON_SIZE[0] + 1)), y1, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x1_0 + (i * (BALLOON_SIZE[0] + 1)), y1, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(6, init_params);
|
||||||
balloon_formation_.emplace_back(6, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #09 - Seis enemigos BALLOON1. 100, 100, 100, 100, 100, 100. Hacia la izquierda
|
// #09 - Seis enemigos BALLOON1. 100, 100, 100, 100, 100, 100. Hacia la izquierda
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i) {
|
||||||
{
|
init_params.emplace_back(x1_100 - (i * (BALLOON_SIZE[0] + 1)), y1, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x1_100 - (i * (BALLOON_SIZE[0] + 1)), y1, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(6, init_params);
|
||||||
balloon_formation_.emplace_back(6, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #10 - Tres enemigos BALLOON4 seguidos desde la izquierda. Hacia la derecha
|
// #10 - Tres enemigos BALLOON4 seguidos desde la izquierda. Hacia la derecha
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i) {
|
||||||
{
|
init_params.emplace_back(x4_0 + (i * (BALLOON_SIZE[3] + 1)), y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME - (15 * i));
|
||||||
init_params.emplace_back(x4_0 + (i * (BALLOON_SIZE[3] + 1)), y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME - (15 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(3, init_params);
|
||||||
balloon_formation_.emplace_back(3, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #11 - Tres enemigos BALLOON4 seguidos desde la derecha. Hacia la izquierda
|
// #11 - Tres enemigos BALLOON4 seguidos desde la derecha. Hacia la izquierda
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i) {
|
||||||
{
|
init_params.emplace_back(x4_100 - (i * (BALLOON_SIZE[3] + 1)), y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME - (15 * i));
|
||||||
init_params.emplace_back(x4_100 - (i * (BALLOON_SIZE[3] + 1)), y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME - (15 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(3, init_params);
|
||||||
balloon_formation_.emplace_back(3, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #12 - Seis enemigos BALLOON2 uno detrás del otro. A la izquierda y hacia el centro
|
// #12 - Seis enemigos BALLOON2 uno detrás del otro. A la izquierda y hacia el centro
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i) {
|
||||||
{
|
init_params.emplace_back(x2_0 + (i * (BALLOON_SIZE[1] + 1)), y2, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x2_0 + (i * (BALLOON_SIZE[1] + 1)), y2, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(6, init_params);
|
||||||
balloon_formation_.emplace_back(6, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #13 - Seis enemigos BALLOON2 uno detrás del otro. A la derecha y hacia el centro
|
// #13 - Seis enemigos BALLOON2 uno detrás del otro. A la derecha y hacia el centro
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i) {
|
||||||
{
|
init_params.emplace_back(x2_100 - (i * (BALLOON_SIZE[1] + 1)), y2, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x2_100 - (i * (BALLOON_SIZE[1] + 1)), y2, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(6, init_params);
|
||||||
balloon_formation_.emplace_back(6, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #14 - Cinco enemigos BALLOON3. Hacia la derecha. Separados
|
// #14 - Cinco enemigos BALLOON3. Hacia la derecha. Separados
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i) {
|
||||||
{
|
init_params.emplace_back(x3_0 + (i * (BALLOON_SIZE[2] * 2)), y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x3_0 + (i * (BALLOON_SIZE[2] * 2)), y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(5, init_params);
|
||||||
balloon_formation_.emplace_back(5, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #15 - Cinco enemigos BALLOON3. Hacia la izquierda. Separados
|
// #15 - Cinco enemigos BALLOON3. Hacia la izquierda. Separados
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i) {
|
||||||
{
|
init_params.emplace_back(x3_100 - (i * (BALLOON_SIZE[2] * 2)), y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x3_100 - (i * (BALLOON_SIZE[2] * 2)), y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(5, init_params);
|
||||||
balloon_formation_.emplace_back(5, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #16 - Cinco enemigos BALLOON3. Hacia la derecha. Juntos
|
// #16 - Cinco enemigos BALLOON3. Hacia la derecha. Juntos
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i) {
|
||||||
{
|
init_params.emplace_back(x3_0 + (i * (BALLOON_SIZE[2] + 1)), y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x3_0 + (i * (BALLOON_SIZE[2] + 1)), y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(5, init_params);
|
||||||
balloon_formation_.emplace_back(5, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #17 - Cinco enemigos BALLOON3. Hacia la izquierda. Juntos
|
// #17 - Cinco enemigos BALLOON3. Hacia la izquierda. Juntos
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 5; ++i)
|
for (int i = 0; i < 5; ++i) {
|
||||||
{
|
init_params.emplace_back(x3_100 - (i * (BALLOON_SIZE[2] + 1)), y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x3_100 - (i * (BALLOON_SIZE[2] + 1)), y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(5, init_params);
|
||||||
balloon_formation_.emplace_back(5, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #18 - Doce enemigos BALLOON1. Hacia la derecha. Juntos
|
// #18 - Doce enemigos BALLOON1. Hacia la derecha. Juntos
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 12; ++i)
|
for (int i = 0; i < 12; ++i) {
|
||||||
{
|
init_params.emplace_back(x1_0 + (i * (BALLOON_SIZE[0] + 1)), y1, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x1_0 + (i * (BALLOON_SIZE[0] + 1)), y1, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(12, init_params);
|
||||||
balloon_formation_.emplace_back(12, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #19 - Doce enemigos BALLOON1. Hacia la izquierda. Juntos
|
// #19 - Doce enemigos BALLOON1. Hacia la izquierda. Juntos
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
for (int i = 0; i < 12; ++i)
|
for (int i = 0; i < 12; ++i) {
|
||||||
{
|
init_params.emplace_back(x1_100 - (i * (BALLOON_SIZE[0] + 1)), y1, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (10 * i));
|
||||||
init_params.emplace_back(x1_100 - (i * (BALLOON_SIZE[0] + 1)), y1, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (10 * i));
|
}
|
||||||
}
|
balloon_formation_.emplace_back(12, init_params);
|
||||||
balloon_formation_.emplace_back(12, init_params);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// #20 - Dos enemigos BALLOON4 seguidos desde la izquierda/derecha. Simétricos
|
// #20 - Dos enemigos BALLOON4 seguidos desde la izquierda/derecha. Simétricos
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
const int half = 4 / 2;
|
const int half = 4 / 2;
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i) {
|
||||||
{
|
if (i < half) {
|
||||||
if (i < half)
|
init_params.emplace_back(x4_0 + (i * (BALLOON_SIZE[3] + 1)), y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME + (0 * i));
|
||||||
{
|
} else {
|
||||||
init_params.emplace_back(x4_0 + (i * (BALLOON_SIZE[3] + 1)), y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME + (0 * i));
|
init_params.emplace_back(x4_100 - ((i - half) * (BALLOON_SIZE[3] + 1)), y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME + (0 * i));
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
balloon_formation_.emplace_back(4, init_params);
|
||||||
init_params.emplace_back(x4_100 - ((i - half) * (BALLOON_SIZE[3] + 1)), y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME + (0 * i));
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
balloon_formation_.emplace_back(4, init_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// #20 - Dos enemigos BALLOON4 seguidos desde la izquierda/derecha. Simétricos
|
// #20 - Dos enemigos BALLOON4 seguidos desde la izquierda/derecha. Simétricos
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
const int half = 4 / 2;
|
const int half = 4 / 2;
|
||||||
for (int i = 0; i < 4; ++i)
|
for (int i = 0; i < 4; ++i) {
|
||||||
{
|
if (i < half) {
|
||||||
if (i < half)
|
init_params.emplace_back(x4_0 + (i * (BALLOON_SIZE[3] + 1)), y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME + (0 * i));
|
||||||
{
|
} else {
|
||||||
init_params.emplace_back(x4_0 + (i * (BALLOON_SIZE[3] + 1)), y4, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME + (0 * i));
|
init_params.emplace_back(x4_100 - ((i - half) * (BALLOON_SIZE[3] + 1)), y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME + (0 * i));
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
balloon_formation_.emplace_back(4, init_params);
|
||||||
init_params.emplace_back(x4_100 - ((i - half) * (BALLOON_SIZE[3] + 1)), y4, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE4, CREATION_TIME + (0 * i));
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
balloon_formation_.emplace_back(4, init_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// #21 - Diez enemigos BALLOON2 uno detrás del otro. Izquierda/derecha. Simétricos
|
// #21 - Diez enemigos BALLOON2 uno detrás del otro. Izquierda/derecha. Simétricos
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
const int half = 10 / 2;
|
const int half = 10 / 2;
|
||||||
for (int i = 0; i < 10; ++i)
|
for (int i = 0; i < 10; ++i) {
|
||||||
{
|
if (i < half) {
|
||||||
if (i < half)
|
init_params.emplace_back(x2_0 + (i * (BALLOON_SIZE[1] + 1)), y2, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (3 * i));
|
||||||
{
|
} else {
|
||||||
init_params.emplace_back(x2_0 + (i * (BALLOON_SIZE[1] + 1)), y2, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (3 * i));
|
init_params.emplace_back(x2_100 - ((i - half) * (BALLOON_SIZE[1] + 1)), y2, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (3 * (i - half)));
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
balloon_formation_.emplace_back(10, init_params);
|
||||||
init_params.emplace_back(x2_100 - ((i - half) * (BALLOON_SIZE[1] + 1)), y2, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE2, CREATION_TIME - (3 * (i - half)));
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
balloon_formation_.emplace_back(10, init_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// #22 - Diez enemigos BALLOON3. Hacia la derecha/izquierda. Separados. Simétricos
|
// #22 - Diez enemigos BALLOON3. Hacia la derecha/izquierda. Separados. Simétricos
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
const int half = 10 / 2;
|
const int half = 10 / 2;
|
||||||
for (int i = 0; i < 10; ++i)
|
for (int i = 0; i < 10; ++i) {
|
||||||
{
|
if (i < half) {
|
||||||
if (i < half)
|
init_params.emplace_back(x3_0 + (i * (BALLOON_SIZE[2] * 2)), y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
||||||
{
|
} else {
|
||||||
init_params.emplace_back(x3_0 + (i * (BALLOON_SIZE[2] * 2)), y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
init_params.emplace_back(x3_100 - ((i - half) * (BALLOON_SIZE[2] * 2)), y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * (i - half)));
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
balloon_formation_.emplace_back(10, init_params);
|
||||||
init_params.emplace_back(x3_100 - ((i - half) * (BALLOON_SIZE[2] * 2)), y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * (i - half)));
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
balloon_formation_.emplace_back(10, init_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// #23 - Diez enemigos BALLOON3. Hacia la derecha. Juntos. Simétricos
|
// #23 - Diez enemigos BALLOON3. Hacia la derecha. Juntos. Simétricos
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
const int half = 10 / 2;
|
const int half = 10 / 2;
|
||||||
for (int i = 0; i < 10; ++i)
|
for (int i = 0; i < 10; ++i) {
|
||||||
{
|
if (i < half) {
|
||||||
if (i < half)
|
init_params.emplace_back(x3_0 + (i * (BALLOON_SIZE[2] + 1)), y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
||||||
{
|
} else {
|
||||||
init_params.emplace_back(x3_0 + (i * (BALLOON_SIZE[2] + 1)), y3, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * i));
|
init_params.emplace_back(x3_100 - ((i - half) * (BALLOON_SIZE[2] + 1)), y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * (i - half)));
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
balloon_formation_.emplace_back(10, init_params);
|
||||||
init_params.emplace_back(x3_100 - ((i - half) * (BALLOON_SIZE[2] + 1)), y3, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE3, CREATION_TIME - (10 * (i - half)));
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
balloon_formation_.emplace_back(10, init_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// #24 - Treinta enemigos BALLOON1. Del centro hacia los extremos. Juntos. Simétricos
|
// #24 - Treinta enemigos BALLOON1. Del centro hacia los extremos. Juntos. Simétricos
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
const int half = 30 / 2;
|
const int half = 30 / 2;
|
||||||
for (int i = 0; i < 30; ++i)
|
for (int i = 0; i < 30; ++i) {
|
||||||
{
|
if (i < half) {
|
||||||
if (i < half)
|
init_params.emplace_back(x1_50, y1, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME + (5 * i));
|
||||||
{
|
} else {
|
||||||
init_params.emplace_back(x1_50, y1, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME + (5 * i));
|
init_params.emplace_back(x1_50, y1, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME + (5 * (i - half)));
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
balloon_formation_.emplace_back(30, init_params);
|
||||||
init_params.emplace_back(x1_50, y1, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME + (5 * (i - half)));
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
balloon_formation_.emplace_back(30, init_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// #25 - Treinta enemigos BALLOON1. Del centro hacia adentro. Juntos. Simétricos
|
// #25 - Treinta enemigos BALLOON1. Del centro hacia adentro. Juntos. Simétricos
|
||||||
{
|
{
|
||||||
std::vector<BalloonFormationParams> init_params;
|
std::vector<BalloonFormationParams> init_params;
|
||||||
const int half = 30 / 2;
|
const int half = 30 / 2;
|
||||||
for (int i = 0; i < 30; ++i)
|
for (int i = 0; i < 30; ++i) {
|
||||||
{
|
if (i < half) {
|
||||||
if (i < half)
|
init_params.emplace_back(x1_50 + 20, y1, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (5 * i));
|
||||||
{
|
} else {
|
||||||
init_params.emplace_back(x1_50 + 20, y1, BALLOON_VELX_NEGATIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (5 * i));
|
init_params.emplace_back(x1_50 - 20, y1, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (5 * (i - half)));
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
balloon_formation_.emplace_back(30, init_params);
|
||||||
init_params.emplace_back(x1_50 - 20, y1, BALLOON_VELX_POSITIVE, BalloonType::BALLOON, BalloonSize::SIZE1, CREATION_TIME - (5 * (i - half)));
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
balloon_formation_.emplace_back(30, init_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reservar espacio para el vector
|
// Reservar espacio para el vector
|
||||||
balloon_formation_.resize(100);
|
balloon_formation_.resize(100);
|
||||||
|
|
||||||
// Crea las mismas formaciones pero con hexágonos a partir de la posición 50 del vector
|
// Crea las mismas formaciones pero con hexágonos a partir de la posición 50 del vector
|
||||||
for (int k = 0; k < 50; k++)
|
for (int k = 0; k < 50; k++) {
|
||||||
{
|
std::vector<BalloonFormationParams> init_params;
|
||||||
std::vector<BalloonFormationParams> init_params;
|
for (int i = 0; i < balloon_formation_.at(k).number_of_balloons; i++) {
|
||||||
for (int i = 0; i < balloon_formation_.at(k).number_of_balloons; i++)
|
init_params.emplace_back(
|
||||||
{
|
balloon_formation_.at(k).init.at(i).x,
|
||||||
init_params.emplace_back(
|
balloon_formation_.at(k).init.at(i).y,
|
||||||
balloon_formation_.at(k).init.at(i).x,
|
balloon_formation_.at(k).init.at(i).vel_x,
|
||||||
balloon_formation_.at(k).init.at(i).y,
|
BalloonType::FLOATER,
|
||||||
balloon_formation_.at(k).init.at(i).vel_x,
|
balloon_formation_.at(k).init.at(i).size,
|
||||||
BalloonType::FLOATER,
|
balloon_formation_.at(k).init.at(i).creation_counter);
|
||||||
balloon_formation_.at(k).init.at(i).size,
|
}
|
||||||
balloon_formation_.at(k).init.at(i).creation_counter);
|
balloon_formation_.at(k + 50) = BalloonFormationUnit(balloon_formation_.at(k).number_of_balloons, init_params);
|
||||||
}
|
}
|
||||||
balloon_formation_.at(k + 50) = BalloonFormationUnit(balloon_formation_.at(k).number_of_balloons, init_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TEST
|
// TEST
|
||||||
std::vector<BalloonFormationParams> test_params = {
|
std::vector<BalloonFormationParams> test_params = {
|
||||||
{10, y1, 0, BalloonType::FLOATER, BalloonSize::SIZE1, 200},
|
{10, y1, 0, BalloonType::FLOATER, BalloonSize::SIZE1, 200},
|
||||||
{50, y1, 0, BalloonType::FLOATER, BalloonSize::SIZE2, 200},
|
{50, y1, 0, BalloonType::FLOATER, BalloonSize::SIZE2, 200},
|
||||||
{90, y1, 0, BalloonType::FLOATER, BalloonSize::SIZE3, 200},
|
{90, y1, 0, BalloonType::FLOATER, BalloonSize::SIZE3, 200},
|
||||||
{140, y1, 0, BalloonType::FLOATER, BalloonSize::SIZE4, 200}};
|
{140, y1, 0, BalloonType::FLOATER, BalloonSize::SIZE4, 200}};
|
||||||
|
|
||||||
balloon_formation_.at(99) = BalloonFormationUnit(4, test_params);
|
balloon_formation_.at(99) = BalloonFormationUnit(4, test_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa los conjuntos de formaciones
|
// Inicializa los conjuntos de formaciones
|
||||||
void BalloonFormations::initBalloonFormationPools()
|
void BalloonFormations::initBalloonFormationPools() {
|
||||||
{
|
// Reserva espacio para cada pool de formaciones
|
||||||
// Reserva espacio para cada pool de formaciones
|
balloon_formation_pool_.resize(NUMBER_OF_SETS_PER_POOL);
|
||||||
balloon_formation_pool_.resize(NUMBER_OF_SETS_PER_POOL);
|
|
||||||
|
|
||||||
// Set #0
|
// Set #0
|
||||||
balloon_formation_pool_.at(0) = {
|
balloon_formation_pool_.at(0) = {
|
||||||
&balloon_formation_.at(0), &balloon_formation_.at(1), &balloon_formation_.at(2),
|
&balloon_formation_.at(0), &balloon_formation_.at(1), &balloon_formation_.at(2), &balloon_formation_.at(3), &balloon_formation_.at(4), &balloon_formation_.at(5), &balloon_formation_.at(6), &balloon_formation_.at(7), &balloon_formation_.at(8), &balloon_formation_.at(9)};
|
||||||
&balloon_formation_.at(3), &balloon_formation_.at(4), &balloon_formation_.at(5),
|
|
||||||
&balloon_formation_.at(6), &balloon_formation_.at(7), &balloon_formation_.at(8),
|
|
||||||
&balloon_formation_.at(9)};
|
|
||||||
|
|
||||||
// Set #1
|
// Set #1
|
||||||
balloon_formation_pool_.at(1) = {
|
balloon_formation_pool_.at(1) = {
|
||||||
&balloon_formation_.at(10), &balloon_formation_.at(11), &balloon_formation_.at(12),
|
&balloon_formation_.at(10), &balloon_formation_.at(11), &balloon_formation_.at(12), &balloon_formation_.at(13), &balloon_formation_.at(14), &balloon_formation_.at(15), &balloon_formation_.at(16), &balloon_formation_.at(17), &balloon_formation_.at(18), &balloon_formation_.at(19)};
|
||||||
&balloon_formation_.at(13), &balloon_formation_.at(14), &balloon_formation_.at(15),
|
|
||||||
&balloon_formation_.at(16), &balloon_formation_.at(17), &balloon_formation_.at(18),
|
|
||||||
&balloon_formation_.at(19)};
|
|
||||||
|
|
||||||
// Set #2
|
// Set #2
|
||||||
balloon_formation_pool_.at(2) = {
|
balloon_formation_pool_.at(2) = {
|
||||||
&balloon_formation_.at(0), &balloon_formation_.at(1), &balloon_formation_.at(2),
|
&balloon_formation_.at(0), &balloon_formation_.at(1), &balloon_formation_.at(2), &balloon_formation_.at(3), &balloon_formation_.at(4), &balloon_formation_.at(55), &balloon_formation_.at(56), &balloon_formation_.at(57), &balloon_formation_.at(58), &balloon_formation_.at(59)};
|
||||||
&balloon_formation_.at(3), &balloon_formation_.at(4), &balloon_formation_.at(55),
|
|
||||||
&balloon_formation_.at(56), &balloon_formation_.at(57), &balloon_formation_.at(58),
|
|
||||||
&balloon_formation_.at(59)};
|
|
||||||
|
|
||||||
// Set #3
|
// Set #3
|
||||||
balloon_formation_pool_.at(3) = {
|
balloon_formation_pool_.at(3) = {
|
||||||
&balloon_formation_.at(50), &balloon_formation_.at(51), &balloon_formation_.at(52),
|
&balloon_formation_.at(50), &balloon_formation_.at(51), &balloon_formation_.at(52), &balloon_formation_.at(53), &balloon_formation_.at(54), &balloon_formation_.at(5), &balloon_formation_.at(6), &balloon_formation_.at(7), &balloon_formation_.at(8), &balloon_formation_.at(9)};
|
||||||
&balloon_formation_.at(53), &balloon_formation_.at(54), &balloon_formation_.at(5),
|
|
||||||
&balloon_formation_.at(6), &balloon_formation_.at(7), &balloon_formation_.at(8),
|
|
||||||
&balloon_formation_.at(9)};
|
|
||||||
|
|
||||||
// Set #4
|
// Set #4
|
||||||
balloon_formation_pool_.at(4) = {
|
balloon_formation_pool_.at(4) = {
|
||||||
&balloon_formation_.at(60), &balloon_formation_.at(61), &balloon_formation_.at(62),
|
&balloon_formation_.at(60), &balloon_formation_.at(61), &balloon_formation_.at(62), &balloon_formation_.at(63), &balloon_formation_.at(64), &balloon_formation_.at(65), &balloon_formation_.at(66), &balloon_formation_.at(67), &balloon_formation_.at(68), &balloon_formation_.at(69)};
|
||||||
&balloon_formation_.at(63), &balloon_formation_.at(64), &balloon_formation_.at(65),
|
|
||||||
&balloon_formation_.at(66), &balloon_formation_.at(67), &balloon_formation_.at(68),
|
|
||||||
&balloon_formation_.at(69)};
|
|
||||||
|
|
||||||
// Set #5
|
// Set #5
|
||||||
balloon_formation_pool_.at(5) = {
|
balloon_formation_pool_.at(5) = {
|
||||||
&balloon_formation_.at(10), &balloon_formation_.at(61), &balloon_formation_.at(12),
|
&balloon_formation_.at(10), &balloon_formation_.at(61), &balloon_formation_.at(12), &balloon_formation_.at(63), &balloon_formation_.at(14), &balloon_formation_.at(65), &balloon_formation_.at(16), &balloon_formation_.at(67), &balloon_formation_.at(18), &balloon_formation_.at(69)};
|
||||||
&balloon_formation_.at(63), &balloon_formation_.at(14), &balloon_formation_.at(65),
|
|
||||||
&balloon_formation_.at(16), &balloon_formation_.at(67), &balloon_formation_.at(18),
|
|
||||||
&balloon_formation_.at(69)};
|
|
||||||
|
|
||||||
// Set #6
|
// Set #6
|
||||||
balloon_formation_pool_.at(6) = {
|
balloon_formation_pool_.at(6) = {
|
||||||
&balloon_formation_.at(60), &balloon_formation_.at(11), &balloon_formation_.at(62),
|
&balloon_formation_.at(60), &balloon_formation_.at(11), &balloon_formation_.at(62), &balloon_formation_.at(13), &balloon_formation_.at(64), &balloon_formation_.at(15), &balloon_formation_.at(66), &balloon_formation_.at(17), &balloon_formation_.at(68), &balloon_formation_.at(19)};
|
||||||
&balloon_formation_.at(13), &balloon_formation_.at(64), &balloon_formation_.at(15),
|
|
||||||
&balloon_formation_.at(66), &balloon_formation_.at(17), &balloon_formation_.at(68),
|
|
||||||
&balloon_formation_.at(19)};
|
|
||||||
|
|
||||||
// Set #7
|
// Set #7
|
||||||
balloon_formation_pool_.at(7) = {
|
balloon_formation_pool_.at(7) = {
|
||||||
&balloon_formation_.at(20), &balloon_formation_.at(21), &balloon_formation_.at(22),
|
&balloon_formation_.at(20), &balloon_formation_.at(21), &balloon_formation_.at(22), &balloon_formation_.at(23), &balloon_formation_.at(24), &balloon_formation_.at(65), &balloon_formation_.at(66), &balloon_formation_.at(67), &balloon_formation_.at(68), &balloon_formation_.at(69)};
|
||||||
&balloon_formation_.at(23), &balloon_formation_.at(24), &balloon_formation_.at(65),
|
|
||||||
&balloon_formation_.at(66), &balloon_formation_.at(67), &balloon_formation_.at(68),
|
|
||||||
&balloon_formation_.at(69)};
|
|
||||||
|
|
||||||
// Set #8
|
// Set #8
|
||||||
balloon_formation_pool_.at(8) = {
|
balloon_formation_pool_.at(8) = {
|
||||||
&balloon_formation_.at(70), &balloon_formation_.at(71), &balloon_formation_.at(72),
|
&balloon_formation_.at(70), &balloon_formation_.at(71), &balloon_formation_.at(72), &balloon_formation_.at(73), &balloon_formation_.at(74), &balloon_formation_.at(15), &balloon_formation_.at(16), &balloon_formation_.at(17), &balloon_formation_.at(18), &balloon_formation_.at(19)};
|
||||||
&balloon_formation_.at(73), &balloon_formation_.at(74), &balloon_formation_.at(15),
|
|
||||||
&balloon_formation_.at(16), &balloon_formation_.at(17), &balloon_formation_.at(18),
|
|
||||||
&balloon_formation_.at(19)};
|
|
||||||
|
|
||||||
// Set #9
|
// Set #9
|
||||||
balloon_formation_pool_.at(9) = {
|
balloon_formation_pool_.at(9) = {
|
||||||
&balloon_formation_.at(20), &balloon_formation_.at(21), &balloon_formation_.at(22),
|
&balloon_formation_.at(20), &balloon_formation_.at(21), &balloon_formation_.at(22), &balloon_formation_.at(23), &balloon_formation_.at(24), &balloon_formation_.at(70), &balloon_formation_.at(71), &balloon_formation_.at(72), &balloon_formation_.at(73), &balloon_formation_.at(74)};
|
||||||
&balloon_formation_.at(23), &balloon_formation_.at(24), &balloon_formation_.at(70),
|
|
||||||
&balloon_formation_.at(71), &balloon_formation_.at(72), &balloon_formation_.at(73),
|
|
||||||
&balloon_formation_.at(74)};
|
|
||||||
}
|
}
|
||||||
+17
-21
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "balloon.h" // Para BALLOON_VELX_NEGATIVE, BALLOON_VELX_POSITIVE
|
#include "balloon.h" // Para BALLOON_VELX_NEGATIVE, BALLOON_VELX_POSITIVE
|
||||||
|
|
||||||
// --- Constantes de configuración ---
|
// --- Constantes de configuración ---
|
||||||
constexpr int NUMBER_OF_BALLOON_FORMATIONS = 100;
|
constexpr int NUMBER_OF_BALLOON_FORMATIONS = 100;
|
||||||
@@ -11,14 +11,13 @@ constexpr int NUMBER_OF_SETS_PER_POOL = 10;
|
|||||||
constexpr int NUMBER_OF_STAGES = 10;
|
constexpr int NUMBER_OF_STAGES = 10;
|
||||||
|
|
||||||
// --- Estructuras de datos ---
|
// --- Estructuras de datos ---
|
||||||
struct BalloonFormationParams
|
struct BalloonFormationParams {
|
||||||
{
|
int x = 0; // Posición en el eje X donde crear el globo
|
||||||
int x = 0; // Posición en el eje X donde crear el globo
|
int y = 0; // Posición en el eje Y donde crear el globo
|
||||||
int y = 0; // Posición en el eje Y donde crear el globo
|
float vel_x = 0.0f; // Velocidad inicial en el eje X
|
||||||
float vel_x = 0.0f; // Velocidad inicial en el eje X
|
BalloonType type = BalloonType::BALLOON; // Tipo de globo
|
||||||
BalloonType type = BalloonType::BALLOON; // Tipo de globo
|
BalloonSize size = BalloonSize::SIZE1; // Tamaño de globo
|
||||||
BalloonSize size = BalloonSize::SIZE1; // Tamaño de globo
|
int creation_counter = 0; // Temporizador para la creación del globo
|
||||||
int creation_counter = 0; // Temporizador para la creación del globo
|
|
||||||
|
|
||||||
// Constructor por defecto
|
// Constructor por defecto
|
||||||
BalloonFormationParams() = default;
|
BalloonFormationParams() = default;
|
||||||
@@ -28,10 +27,9 @@ struct BalloonFormationParams
|
|||||||
: x(x_val), y(y_val), vel_x(vel_x_val), type(type_val), size(size_val), creation_counter(creation_counter_val) {}
|
: x(x_val), y(y_val), vel_x(vel_x_val), type(type_val), size(size_val), creation_counter(creation_counter_val) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BalloonFormationUnit
|
struct BalloonFormationUnit {
|
||||||
{
|
int number_of_balloons; // Cantidad de globos que forman la formación
|
||||||
int number_of_balloons; // Cantidad de globos que forman la formación
|
std::vector<BalloonFormationParams> init; // Vector con todas las inicializaciones de los globos de la formación
|
||||||
std::vector<BalloonFormationParams> init; // Vector con todas las inicializaciones de los globos de la formación
|
|
||||||
|
|
||||||
// Constructor con parámetros
|
// Constructor con parámetros
|
||||||
BalloonFormationUnit(int num_balloons, const std::vector<BalloonFormationParams> &init_params)
|
BalloonFormationUnit(int num_balloons, const std::vector<BalloonFormationParams> &init_params)
|
||||||
@@ -44,12 +42,10 @@ struct BalloonFormationUnit
|
|||||||
using BalloonFormationPool = std::vector<const BalloonFormationUnit *>;
|
using BalloonFormationPool = std::vector<const BalloonFormationUnit *>;
|
||||||
|
|
||||||
// --- Clase BalloonFormations ---
|
// --- Clase BalloonFormations ---
|
||||||
class BalloonFormations
|
class BalloonFormations {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
BalloonFormations()
|
BalloonFormations() {
|
||||||
{
|
|
||||||
initBalloonFormations();
|
initBalloonFormations();
|
||||||
initBalloonFormationPools();
|
initBalloonFormationPools();
|
||||||
}
|
}
|
||||||
@@ -60,10 +56,10 @@ public:
|
|||||||
const BalloonFormationUnit &getSet(int pool, int set) { return *balloon_formation_pool_.at(pool).at(set); }
|
const BalloonFormationUnit &getSet(int pool, int set) { return *balloon_formation_pool_.at(pool).at(set); }
|
||||||
const BalloonFormationUnit &getSet(int set) const { return balloon_formation_.at(set); }
|
const BalloonFormationUnit &getSet(int set) const { return balloon_formation_.at(set); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Datos ---
|
// --- Datos ---
|
||||||
std::vector<BalloonFormationUnit> balloon_formation_; // Vector con todas las formaciones enemigas
|
std::vector<BalloonFormationUnit> balloon_formation_; // Vector con todas las formaciones enemigas
|
||||||
std::vector<BalloonFormationPool> balloon_formation_pool_; // Conjuntos de formaciones enemigas
|
std::vector<BalloonFormationPool> balloon_formation_pool_; // Conjuntos de formaciones enemigas
|
||||||
|
|
||||||
// --- Métodos internos de inicialización ---
|
// --- Métodos internos de inicialización ---
|
||||||
void initBalloonFormations();
|
void initBalloonFormations();
|
||||||
|
|||||||
+87
-148
@@ -1,17 +1,18 @@
|
|||||||
#include "balloon_manager.h"
|
#include "balloon_manager.h"
|
||||||
|
|
||||||
#include <stdlib.h> // Para rand
|
#include <stdlib.h> // Para rand
|
||||||
#include <algorithm> // Para remove_if
|
|
||||||
#include <numeric> // Para accumulate
|
|
||||||
|
|
||||||
#include "balloon.h" // Para Balloon, BALLOON_SCORE, BALLOON_VELX...
|
#include <algorithm> // Para remove_if
|
||||||
#include "balloon_formations.h" // Para BalloonFormationParams, BalloonForma...
|
#include <numeric> // Para accumulate
|
||||||
#include "explosions.h" // Para Explosions
|
|
||||||
#include "param.h" // Para Param, ParamGame, param
|
#include "balloon.h" // Para Balloon, BALLOON_SCORE, BALLOON_VELX...
|
||||||
#include "resource.h" // Para Resource
|
#include "balloon_formations.h" // Para BalloonFormationParams, BalloonForma...
|
||||||
#include "screen.h" // Para Screen
|
#include "explosions.h" // Para Explosions
|
||||||
#include "stage.h" // Para addPower
|
#include "param.h" // Para Param, ParamGame, param
|
||||||
#include "utils.h" // Para Zone, Color, flash_color
|
#include "resource.h" // Para Resource
|
||||||
|
#include "screen.h" // Para Screen
|
||||||
|
#include "stage.h" // Para addPower
|
||||||
|
#include "utils.h" // Para Zone, Color, flash_color
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
BalloonManager::BalloonManager()
|
BalloonManager::BalloonManager()
|
||||||
@@ -19,8 +20,7 @@ BalloonManager::BalloonManager()
|
|||||||
balloon_formations_(std::make_unique<BalloonFormations>()) { init(); }
|
balloon_formations_(std::make_unique<BalloonFormations>()) { init(); }
|
||||||
|
|
||||||
// Inicializa
|
// Inicializa
|
||||||
void BalloonManager::init()
|
void BalloonManager::init() {
|
||||||
{
|
|
||||||
// Texturas - Globos
|
// Texturas - Globos
|
||||||
balloon_textures_.emplace_back(Resource::get()->getTexture("balloon1.png"));
|
balloon_textures_.emplace_back(Resource::get()->getTexture("balloon1.png"));
|
||||||
balloon_textures_.emplace_back(Resource::get()->getTexture("balloon2.png"));
|
balloon_textures_.emplace_back(Resource::get()->getTexture("balloon2.png"));
|
||||||
@@ -55,10 +55,8 @@ void BalloonManager::init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza
|
// Actualiza
|
||||||
void BalloonManager::update()
|
void BalloonManager::update() {
|
||||||
{
|
for (auto balloon : balloons_) {
|
||||||
for (auto balloon : balloons_)
|
|
||||||
{
|
|
||||||
balloon->update();
|
balloon->update();
|
||||||
}
|
}
|
||||||
updateBalloonDeployCounter();
|
updateBalloonDeployCounter();
|
||||||
@@ -66,32 +64,25 @@ void BalloonManager::update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Renderiza los objetos
|
// Renderiza los objetos
|
||||||
void BalloonManager::render()
|
void BalloonManager::render() {
|
||||||
{
|
for (auto &balloon : balloons_) {
|
||||||
for (auto &balloon : balloons_)
|
|
||||||
{
|
|
||||||
balloon->render();
|
balloon->render();
|
||||||
}
|
}
|
||||||
explosions_->render();
|
explosions_->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea una formación de enemigos
|
// Crea una formación de enemigos
|
||||||
void BalloonManager::deployBalloonFormation(int stage)
|
void BalloonManager::deployBalloonFormation(int stage) {
|
||||||
{
|
|
||||||
// Solo despliega una formación enemiga si ha pasado cierto tiempo desde la última
|
// Solo despliega una formación enemiga si ha pasado cierto tiempo desde la última
|
||||||
if (balloon_deploy_counter_ == 0)
|
if (balloon_deploy_counter_ == 0) {
|
||||||
{
|
|
||||||
// En este punto se decide entre crear una powerball o una formación enemiga
|
// En este punto se decide entre crear una powerball o una formación enemiga
|
||||||
if ((rand() % 100 < 15) && (canPowerBallBeCreated()))
|
if ((rand() % 100 < 15) && (canPowerBallBeCreated())) {
|
||||||
{
|
|
||||||
// Crea una powerball
|
// Crea una powerball
|
||||||
createPowerBall();
|
createPowerBall();
|
||||||
|
|
||||||
// Da un poco de margen para que se creen mas enemigos
|
// Da un poco de margen para que se creen mas enemigos
|
||||||
balloon_deploy_counter_ = 10;
|
balloon_deploy_counter_ = 10;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Decrementa el contador de despliegues enemigos de la PowerBall
|
// Decrementa el contador de despliegues enemigos de la PowerBall
|
||||||
power_ball_counter_ = (power_ball_counter_ > 0) ? (power_ball_counter_ - 1) : 0;
|
power_ball_counter_ = (power_ball_counter_ > 0) ? (power_ball_counter_ - 1) : 0;
|
||||||
|
|
||||||
@@ -99,8 +90,7 @@ void BalloonManager::deployBalloonFormation(int stage)
|
|||||||
auto formation = rand() % 10;
|
auto formation = rand() % 10;
|
||||||
|
|
||||||
// Evita repetir la ultima formación enemiga desplegada
|
// Evita repetir la ultima formación enemiga desplegada
|
||||||
if (formation == last_balloon_deploy_)
|
if (formation == last_balloon_deploy_) {
|
||||||
{
|
|
||||||
++formation %= 10;
|
++formation %= 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,8 +98,7 @@ void BalloonManager::deployBalloonFormation(int stage)
|
|||||||
|
|
||||||
const auto set = balloon_formations_->getSet(stage, formation);
|
const auto set = balloon_formations_->getSet(stage, formation);
|
||||||
const auto num_enemies = set.number_of_balloons;
|
const auto num_enemies = set.number_of_balloons;
|
||||||
for (int i = 0; i < num_enemies; ++i)
|
for (int i = 0; i < num_enemies; ++i) {
|
||||||
{
|
|
||||||
auto p = set.init[i];
|
auto p = set.init[i];
|
||||||
createBalloon(
|
createBalloon(
|
||||||
p.x,
|
p.x,
|
||||||
@@ -127,42 +116,34 @@ void BalloonManager::deployBalloonFormation(int stage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Crea una formación de enemigos específica
|
// Crea una formación de enemigos específica
|
||||||
void BalloonManager::deploySet(int set_number)
|
void BalloonManager::deploySet(int set_number) {
|
||||||
{
|
|
||||||
const auto set = balloon_formations_->getSet(set_number);
|
const auto set = balloon_formations_->getSet(set_number);
|
||||||
const auto num_enemies = set.number_of_balloons;
|
const auto num_enemies = set.number_of_balloons;
|
||||||
for (int i = 0; i < num_enemies; ++i)
|
for (int i = 0; i < num_enemies; ++i) {
|
||||||
{
|
|
||||||
auto p = set.init[i];
|
auto p = set.init[i];
|
||||||
createBalloon(p.x, p.y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter);
|
createBalloon(p.x, p.y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea una formación de enemigos específica
|
// Crea una formación de enemigos específica
|
||||||
void BalloonManager::deploySet(int set_number, int y)
|
void BalloonManager::deploySet(int set_number, int y) {
|
||||||
{
|
|
||||||
const auto set = balloon_formations_->getSet(set_number);
|
const auto set = balloon_formations_->getSet(set_number);
|
||||||
const auto num_enemies = set.number_of_balloons;
|
const auto num_enemies = set.number_of_balloons;
|
||||||
for (int i = 0; i < num_enemies; ++i)
|
for (int i = 0; i < num_enemies; ++i) {
|
||||||
{
|
|
||||||
auto p = set.init[i];
|
auto p = set.init[i];
|
||||||
createBalloon(p.x, y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter);
|
createBalloon(p.x, y, p.type, p.size, p.vel_x, balloon_speed_, p.creation_counter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vacia del vector de globos los globos que ya no sirven
|
// Vacia del vector de globos los globos que ya no sirven
|
||||||
void BalloonManager::freeBalloons()
|
void BalloonManager::freeBalloons() {
|
||||||
{
|
auto it = std::remove_if(balloons_.begin(), balloons_.end(), [](const auto &balloon) { return !balloon->isEnabled(); });
|
||||||
auto it = std::remove_if(balloons_.begin(), balloons_.end(), [](const auto &balloon)
|
|
||||||
{ return !balloon->isEnabled(); });
|
|
||||||
balloons_.erase(it, balloons_.end());
|
balloons_.erase(it, balloons_.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza la variable enemyDeployCounter
|
// Actualiza la variable enemyDeployCounter
|
||||||
void BalloonManager::updateBalloonDeployCounter()
|
void BalloonManager::updateBalloonDeployCounter() {
|
||||||
{
|
if (balloon_deploy_counter_ > 0) {
|
||||||
if (balloon_deploy_counter_ > 0)
|
|
||||||
{
|
|
||||||
--balloon_deploy_counter_;
|
--balloon_deploy_counter_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,17 +152,13 @@ void BalloonManager::updateBalloonDeployCounter()
|
|||||||
bool BalloonManager::canPowerBallBeCreated() { return (!power_ball_enabled_) && (calculateScreenPower() > POWERBALL_SCREENPOWER_MINIMUM) && (power_ball_counter_ == 0); }
|
bool BalloonManager::canPowerBallBeCreated() { return (!power_ball_enabled_) && (calculateScreenPower() > POWERBALL_SCREENPOWER_MINIMUM) && (power_ball_counter_ == 0); }
|
||||||
|
|
||||||
// Calcula el poder actual de los globos en pantalla
|
// Calcula el poder actual de los globos en pantalla
|
||||||
int BalloonManager::calculateScreenPower()
|
int BalloonManager::calculateScreenPower() {
|
||||||
{
|
return std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon) { return sum + (balloon->isEnabled() ? balloon->getPower() : 0); });
|
||||||
return std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon)
|
|
||||||
{ return sum + (balloon->isEnabled() ? balloon->getPower() : 0); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea un globo nuevo en el vector de globos
|
// Crea un globo nuevo en el vector de globos
|
||||||
std::shared_ptr<Balloon> BalloonManager::createBalloon(float x, int y, BalloonType type, BalloonSize size, float velx, float speed, int creation_timer)
|
std::shared_ptr<Balloon> BalloonManager::createBalloon(float x, int y, BalloonType type, BalloonSize size, float velx, float speed, int creation_timer) {
|
||||||
{
|
if (can_deploy_balloons_) {
|
||||||
if (can_deploy_balloons_)
|
|
||||||
{
|
|
||||||
const int INDEX = static_cast<int>(size);
|
const int INDEX = static_cast<int>(size);
|
||||||
balloons_.emplace_back(std::make_shared<Balloon>(x, y, type, size, velx, speed, creation_timer, play_area_, balloon_textures_.at(INDEX), balloon_animations_.at(INDEX)));
|
balloons_.emplace_back(std::make_shared<Balloon>(x, y, type, size, velx, speed, creation_timer, play_area_, balloon_textures_.at(INDEX), balloon_animations_.at(INDEX)));
|
||||||
balloons_.back()->setSound(sound_enabled_);
|
balloons_.back()->setSound(sound_enabled_);
|
||||||
@@ -194,10 +171,8 @@ std::shared_ptr<Balloon> BalloonManager::createBalloon(float x, int y, BalloonTy
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Crea un globo a partir de otro globo
|
// Crea un globo a partir de otro globo
|
||||||
void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction)
|
void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction) {
|
||||||
{
|
if (can_deploy_balloons_) {
|
||||||
if (can_deploy_balloons_)
|
|
||||||
{
|
|
||||||
// Calcula parametros
|
// Calcula parametros
|
||||||
const float VX = direction == "LEFT" ? BALLOON_VELX_NEGATIVE : BALLOON_VELX_POSITIVE;
|
const float VX = direction == "LEFT" ? BALLOON_VELX_NEGATIVE : BALLOON_VELX_POSITIVE;
|
||||||
const auto SIZE = static_cast<BalloonSize>(static_cast<int>(balloon->getSize()) - 1);
|
const auto SIZE = static_cast<BalloonSize>(static_cast<int>(balloon->getSize()) - 1);
|
||||||
@@ -214,22 +189,18 @@ void BalloonManager::createChildBalloon(const std::shared_ptr<Balloon> &balloon,
|
|||||||
b->setVelY(b->getType() == BalloonType::BALLOON ? -2.50f : BALLOON_VELX_NEGATIVE * 2.0f);
|
b->setVelY(b->getType() == BalloonType::BALLOON ? -2.50f : BALLOON_VELX_NEGATIVE * 2.0f);
|
||||||
|
|
||||||
// Herencia de estados
|
// Herencia de estados
|
||||||
if (balloon->isStopped())
|
if (balloon->isStopped()) {
|
||||||
{
|
|
||||||
b->stop();
|
b->stop();
|
||||||
}
|
}
|
||||||
if (balloon->isUsingReversedColor())
|
if (balloon->isUsingReversedColor()) {
|
||||||
{
|
|
||||||
b->useReverseColor();
|
b->useReverseColor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea una PowerBall
|
// Crea una PowerBall
|
||||||
void BalloonManager::createPowerBall()
|
void BalloonManager::createPowerBall() {
|
||||||
{
|
if (can_deploy_balloons_) {
|
||||||
if (can_deploy_balloons_)
|
|
||||||
{
|
|
||||||
constexpr int VALUES = 6;
|
constexpr int VALUES = 6;
|
||||||
constexpr float POS_Y = -BALLOON_SIZE[4];
|
constexpr float POS_Y = -BALLOON_SIZE[4];
|
||||||
constexpr int CREATION_TIME = 0;
|
constexpr int CREATION_TIME = 0;
|
||||||
@@ -251,33 +222,26 @@ void BalloonManager::createPowerBall()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Establece la velocidad de los globos
|
// Establece la velocidad de los globos
|
||||||
void BalloonManager::setBalloonSpeed(float speed)
|
void BalloonManager::setBalloonSpeed(float speed) {
|
||||||
{
|
|
||||||
balloon_speed_ = speed;
|
balloon_speed_ = speed;
|
||||||
for (auto &balloon : balloons_)
|
for (auto &balloon : balloons_) {
|
||||||
{
|
|
||||||
balloon->setSpeed(speed);
|
balloon->setSpeed(speed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
|
// Explosiona un globo. Lo destruye y crea otros dos si es el caso
|
||||||
int BalloonManager::popBalloon(std::shared_ptr<Balloon> balloon)
|
int BalloonManager::popBalloon(std::shared_ptr<Balloon> balloon) {
|
||||||
{
|
|
||||||
Stage::addPower(1);
|
Stage::addPower(1);
|
||||||
int score = 0;
|
int score = 0;
|
||||||
|
|
||||||
if (balloon->getType() == BalloonType::POWERBALL)
|
if (balloon->getType() == BalloonType::POWERBALL) {
|
||||||
{
|
|
||||||
balloon->pop(true);
|
balloon->pop(true);
|
||||||
score = destroyAllBalloons();
|
score = destroyAllBalloons();
|
||||||
power_ball_enabled_ = false;
|
power_ball_enabled_ = false;
|
||||||
balloon_deploy_counter_ = 20;
|
balloon_deploy_counter_ = 20;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
score = balloon->getScore();
|
score = balloon->getScore();
|
||||||
if (balloon->getSize() != BalloonSize::SIZE1)
|
if (balloon->getSize() != BalloonSize::SIZE1) {
|
||||||
{
|
|
||||||
createChildBalloon(balloon, "LEFT");
|
createChildBalloon(balloon, "LEFT");
|
||||||
createChildBalloon(balloon, "RIGHT");
|
createChildBalloon(balloon, "RIGHT");
|
||||||
}
|
}
|
||||||
@@ -291,28 +255,26 @@ int BalloonManager::popBalloon(std::shared_ptr<Balloon> balloon)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Explosiona un globo. Lo destruye = no crea otros globos
|
// Explosiona un globo. Lo destruye = no crea otros globos
|
||||||
int BalloonManager::destroyBalloon(std::shared_ptr<Balloon> &balloon)
|
int BalloonManager::destroyBalloon(std::shared_ptr<Balloon> &balloon) {
|
||||||
{
|
|
||||||
int score = 0;
|
int score = 0;
|
||||||
|
|
||||||
// Calcula la puntuación y el poder que generaria el globo en caso de romperlo a él y a sus hijos
|
// Calcula la puntuación y el poder que generaria el globo en caso de romperlo a él y a sus hijos
|
||||||
switch (balloon->getSize())
|
switch (balloon->getSize()) {
|
||||||
{
|
case BalloonSize::SIZE4:
|
||||||
case BalloonSize::SIZE4:
|
score = BALLOON_SCORE[3] + (2 * BALLOON_SCORE[2]) + (4 * BALLOON_SCORE[1]) + (8 * BALLOON_SCORE[0]);
|
||||||
score = BALLOON_SCORE[3] + (2 * BALLOON_SCORE[2]) + (4 * BALLOON_SCORE[1]) + (8 * BALLOON_SCORE[0]);
|
break;
|
||||||
break;
|
case BalloonSize::SIZE3:
|
||||||
case BalloonSize::SIZE3:
|
score = BALLOON_SCORE[2] + (2 * BALLOON_SCORE[1]) + (4 * BALLOON_SCORE[0]);
|
||||||
score = BALLOON_SCORE[2] + (2 * BALLOON_SCORE[1]) + (4 * BALLOON_SCORE[0]);
|
break;
|
||||||
break;
|
case BalloonSize::SIZE2:
|
||||||
case BalloonSize::SIZE2:
|
score = BALLOON_SCORE[1] + (2 * BALLOON_SCORE[0]);
|
||||||
score = BALLOON_SCORE[1] + (2 * BALLOON_SCORE[0]);
|
break;
|
||||||
break;
|
case BalloonSize::SIZE1:
|
||||||
case BalloonSize::SIZE1:
|
score = BALLOON_SCORE[0];
|
||||||
score = BALLOON_SCORE[0];
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
score = 0;
|
||||||
score = 0;
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aumenta el poder de la fase
|
// Aumenta el poder de la fase
|
||||||
@@ -326,11 +288,9 @@ int BalloonManager::destroyBalloon(std::shared_ptr<Balloon> &balloon)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Destruye todos los globos
|
// Destruye todos los globos
|
||||||
int BalloonManager::destroyAllBalloons()
|
int BalloonManager::destroyAllBalloons() {
|
||||||
{
|
|
||||||
int score = 0;
|
int score = 0;
|
||||||
for (auto &balloon : balloons_)
|
for (auto &balloon : balloons_) {
|
||||||
{
|
|
||||||
score += destroyBalloon(balloon);
|
score += destroyBalloon(balloon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,59 +302,46 @@ int BalloonManager::destroyAllBalloons()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Detiene todos los globos
|
// Detiene todos los globos
|
||||||
void BalloonManager::stopAllBalloons()
|
void BalloonManager::stopAllBalloons() {
|
||||||
{
|
for (auto &balloon : balloons_) {
|
||||||
for (auto &balloon : balloons_)
|
|
||||||
{
|
|
||||||
balloon->stop();
|
balloon->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pone en marcha todos los globos
|
// Pone en marcha todos los globos
|
||||||
void BalloonManager::startAllBalloons()
|
void BalloonManager::startAllBalloons() {
|
||||||
{
|
for (auto &balloon : balloons_) {
|
||||||
for (auto &balloon : balloons_)
|
if (!balloon->isBeingCreated()) {
|
||||||
{
|
|
||||||
if (!balloon->isBeingCreated())
|
|
||||||
{
|
|
||||||
balloon->start();
|
balloon->start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cambia el color de todos los globos
|
// Cambia el color de todos los globos
|
||||||
void BalloonManager::reverseColorsToAllBalloons()
|
void BalloonManager::reverseColorsToAllBalloons() {
|
||||||
{
|
for (auto &balloon : balloons_) {
|
||||||
for (auto &balloon : balloons_)
|
if (balloon->isStopped()) {
|
||||||
{
|
|
||||||
if (balloon->isStopped())
|
|
||||||
{
|
|
||||||
balloon->useReverseColor();
|
balloon->useReverseColor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cambia el color de todos los globos
|
// Cambia el color de todos los globos
|
||||||
void BalloonManager::normalColorsToAllBalloons()
|
void BalloonManager::normalColorsToAllBalloons() {
|
||||||
{
|
for (auto &balloon : balloons_) {
|
||||||
for (auto &balloon : balloons_)
|
|
||||||
{
|
|
||||||
balloon->useNormalColor();
|
balloon->useNormalColor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea dos globos gordos
|
// Crea dos globos gordos
|
||||||
void BalloonManager::createTwoBigBalloons()
|
void BalloonManager::createTwoBigBalloons() {
|
||||||
{
|
|
||||||
deploySet(1);
|
deploySet(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea una disposición de globos aleatoria
|
// Crea una disposición de globos aleatoria
|
||||||
void BalloonManager::createRandomBalloons()
|
void BalloonManager::createRandomBalloons() {
|
||||||
{
|
|
||||||
const int num_balloons = 2 + rand() % 4;
|
const int num_balloons = 2 + rand() % 4;
|
||||||
for (int i = 0; i < num_balloons; ++i)
|
for (int i = 0; i < num_balloons; ++i) {
|
||||||
{
|
|
||||||
const float x = param.game.game_area.rect.x + (rand() % static_cast<int>(param.game.game_area.rect.w)) - BALLOON_SIZE[3];
|
const float x = param.game.game_area.rect.x + (rand() % static_cast<int>(param.game.game_area.rect.w)) - BALLOON_SIZE[3];
|
||||||
const int y = param.game.game_area.rect.y + (rand() % 50);
|
const int y = param.game.game_area.rect.y + (rand() % 50);
|
||||||
const BalloonSize size = static_cast<BalloonSize>(rand() % 4);
|
const BalloonSize size = static_cast<BalloonSize>(rand() % 4);
|
||||||
@@ -405,37 +352,29 @@ void BalloonManager::createRandomBalloons()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el nivel de ameza actual generado por los globos
|
// Obtiene el nivel de ameza actual generado por los globos
|
||||||
int BalloonManager::getMenace()
|
int BalloonManager::getMenace() {
|
||||||
{
|
return std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon) { return sum + (balloon->isEnabled() ? balloon->getMenace() : 0); });
|
||||||
return std::accumulate(balloons_.begin(), balloons_.end(), 0, [](int sum, const auto &balloon)
|
|
||||||
{ return sum + (balloon->isEnabled() ? balloon->getMenace() : 0); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el sonido de los globos
|
// Establece el sonido de los globos
|
||||||
void BalloonManager::setSounds(bool value)
|
void BalloonManager::setSounds(bool value) {
|
||||||
{
|
|
||||||
sound_enabled_ = value;
|
sound_enabled_ = value;
|
||||||
for (auto &balloon : balloons_)
|
for (auto &balloon : balloons_) {
|
||||||
{
|
|
||||||
balloon->setSound(value);
|
balloon->setSound(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activa o desactiva los sonidos de rebote los globos
|
// Activa o desactiva los sonidos de rebote los globos
|
||||||
void BalloonManager::setBouncingSounds(bool value)
|
void BalloonManager::setBouncingSounds(bool value) {
|
||||||
{
|
|
||||||
bouncing_sound_enabled_ = value;
|
bouncing_sound_enabled_ = value;
|
||||||
for (auto &balloon : balloons_)
|
for (auto &balloon : balloons_) {
|
||||||
{
|
|
||||||
balloon->setBouncingSound(value);
|
balloon->setBouncingSound(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Activa o desactiva los sonidos de los globos al explotar
|
// Activa o desactiva los sonidos de los globos al explotar
|
||||||
void BalloonManager::setPoppingSounds(bool value)
|
void BalloonManager::setPoppingSounds(bool value) {
|
||||||
{
|
|
||||||
poping_sound_enabled_ = value;
|
poping_sound_enabled_ = value;
|
||||||
for (auto &balloon : balloons_)
|
for (auto &balloon : balloons_) {
|
||||||
{
|
|
||||||
balloon->setPoppingSound(value);
|
balloon->setPoppingSound(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+54
-54
@@ -1,92 +1,92 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FRect
|
#include <SDL3/SDL.h> // Para SDL_FRect
|
||||||
#include <memory> // Para shared_ptr, unique_ptr
|
|
||||||
#include <string> // Para string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "balloon.h" // Para BALLOON_SPEED, Balloon
|
#include <memory> // Para shared_ptr, unique_ptr
|
||||||
#include "balloon_formations.h" // Para BalloonFormations
|
#include <string> // Para string
|
||||||
#include "explosions.h" // Para Explosions
|
#include <vector> // Para vector
|
||||||
#include "param.h" // Para Param, ParamGame, param
|
|
||||||
#include "utils.h" // Para Zone
|
#include "balloon.h" // Para BALLOON_SPEED, Balloon
|
||||||
|
#include "balloon_formations.h" // Para BalloonFormations
|
||||||
|
#include "explosions.h" // Para Explosions
|
||||||
|
#include "param.h" // Para Param, ParamGame, param
|
||||||
|
#include "utils.h" // Para Zone
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
using Balloons = std::vector<std::shared_ptr<Balloon>>;
|
using Balloons = std::vector<std::shared_ptr<Balloon>>;
|
||||||
|
|
||||||
// Clase BalloonManager
|
// Clase BalloonManager
|
||||||
class BalloonManager
|
class BalloonManager {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// Constructor y Destructor
|
// Constructor y Destructor
|
||||||
BalloonManager();
|
BalloonManager();
|
||||||
~BalloonManager() = default;
|
~BalloonManager() = default;
|
||||||
|
|
||||||
// Actualización y Renderizado
|
// Actualización y Renderizado
|
||||||
void update(); // Actualiza el estado de los globos
|
void update(); // Actualiza el estado de los globos
|
||||||
void render(); // Renderiza los globos en pantalla
|
void render(); // Renderiza los globos en pantalla
|
||||||
|
|
||||||
// Gestión de globos
|
// Gestión de globos
|
||||||
void freeBalloons(); // Libera globos que ya no sirven
|
void freeBalloons(); // Libera globos que ya no sirven
|
||||||
|
|
||||||
// Creación de formaciones enemigas
|
// Creación de formaciones enemigas
|
||||||
void deployBalloonFormation(int stage); // Crea una formación de enemigos aleatoria
|
void deployBalloonFormation(int stage); // Crea una formación de enemigos aleatoria
|
||||||
void deploySet(int set); // Crea una formación específica
|
void deploySet(int set); // Crea una formación específica
|
||||||
void deploySet(int set, int y); // Crea una formación específica con coordenadas
|
void deploySet(int set, int y); // Crea una formación específica con coordenadas
|
||||||
|
|
||||||
// Creación de globos
|
// Creación de globos
|
||||||
std::shared_ptr<Balloon> createBalloon(float x, int y, BalloonType type, BalloonSize size, float velx, float speed, int creation_timer); // Crea un nuevo globo
|
std::shared_ptr<Balloon> createBalloon(float x, int y, BalloonType type, BalloonSize size, float velx, float speed, int creation_timer); // Crea un nuevo globo
|
||||||
void createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction); // Crea un globo a partir de otro
|
void createChildBalloon(const std::shared_ptr<Balloon> &balloon, const std::string &direction); // Crea un globo a partir de otro
|
||||||
void createPowerBall(); // Crea una PowerBall
|
void createPowerBall(); // Crea una PowerBall
|
||||||
void createTwoBigBalloons(); // Crea dos globos grandes
|
void createTwoBigBalloons(); // Crea dos globos grandes
|
||||||
void createRandomBalloons(); // Crea una disposición aleatoria de globos
|
void createRandomBalloons(); // Crea una disposición aleatoria de globos
|
||||||
|
|
||||||
// Control de velocidad y despliegue
|
// Control de velocidad y despliegue
|
||||||
void setBalloonSpeed(float speed); // Ajusta la velocidad de los globos
|
void setBalloonSpeed(float speed); // Ajusta la velocidad de los globos
|
||||||
void setDefaultBalloonSpeed(float speed) { default_balloon_speed_ = speed; }; // Establece la velocidad base
|
void setDefaultBalloonSpeed(float speed) { default_balloon_speed_ = speed; }; // Establece la velocidad base
|
||||||
void resetBalloonSpeed() { setBalloonSpeed(default_balloon_speed_); }; // Restablece la velocidad de los globos
|
void resetBalloonSpeed() { setBalloonSpeed(default_balloon_speed_); }; // Restablece la velocidad de los globos
|
||||||
void updateBalloonDeployCounter(); // Actualiza el contador de despliegue
|
void updateBalloonDeployCounter(); // Actualiza el contador de despliegue
|
||||||
bool canPowerBallBeCreated(); // Indica si se puede crear una PowerBall
|
bool canPowerBallBeCreated(); // Indica si se puede crear una PowerBall
|
||||||
int calculateScreenPower(); // Calcula el poder de los globos en pantalla
|
int calculateScreenPower(); // Calcula el poder de los globos en pantalla
|
||||||
|
|
||||||
// Manipulación de globos existentes
|
// Manipulación de globos existentes
|
||||||
int popBalloon(std::shared_ptr<Balloon> balloon); // Explosiona un globo, creando otros si aplica
|
int popBalloon(std::shared_ptr<Balloon> balloon); // Explosiona un globo, creando otros si aplica
|
||||||
int destroyBalloon(std::shared_ptr<Balloon> &balloon); // Explosiona un globo sin crear otros
|
int destroyBalloon(std::shared_ptr<Balloon> &balloon); // Explosiona un globo sin crear otros
|
||||||
int destroyAllBalloons(); // Destruye todos los globos
|
int destroyAllBalloons(); // Destruye todos los globos
|
||||||
void stopAllBalloons(); // Detiene el movimiento de los globos
|
void stopAllBalloons(); // Detiene el movimiento de los globos
|
||||||
void startAllBalloons(); // Reactiva el movimiento de los globos
|
void startAllBalloons(); // Reactiva el movimiento de los globos
|
||||||
|
|
||||||
// Cambios de apariencia
|
// Cambios de apariencia
|
||||||
void reverseColorsToAllBalloons(); // Invierte los colores de los globos
|
void reverseColorsToAllBalloons(); // Invierte los colores de los globos
|
||||||
void normalColorsToAllBalloons(); // Restaura los colores originales
|
void normalColorsToAllBalloons(); // Restaura los colores originales
|
||||||
|
|
||||||
// Configuración de sonido
|
// Configuración de sonido
|
||||||
void setSounds(bool value); // Activa o desactiva los sonidos de los globos
|
void setSounds(bool value); // Activa o desactiva los sonidos de los globos
|
||||||
void setBouncingSounds(bool value); // Activa o desactiva los sonidos de rebote los globos
|
void setBouncingSounds(bool value); // Activa o desactiva los sonidos de rebote los globos
|
||||||
void setPoppingSounds(bool value); // Activa o desactiva los sonidos de los globos al explotar
|
void setPoppingSounds(bool value); // Activa o desactiva los sonidos de los globos al explotar
|
||||||
|
|
||||||
// Configuración de juego
|
// Configuración de juego
|
||||||
void setPlayArea(SDL_FRect play_area) { play_area_ = play_area; }; // Define el área de juego
|
void setPlayArea(SDL_FRect play_area) { play_area_ = play_area; }; // Define el área de juego
|
||||||
void setCreationTimeEnabled(bool value) { creation_time_enabled_ = value; }; // Activa o desactiva el tiempo de creación de globos
|
void setCreationTimeEnabled(bool value) { creation_time_enabled_ = value; }; // Activa o desactiva el tiempo de creación de globos
|
||||||
void enableBalloonDeployment(bool value) { can_deploy_balloons_ = value; }; // Activa o desactiva la generación de globos
|
void enableBalloonDeployment(bool value) { can_deploy_balloons_ = value; }; // Activa o desactiva la generación de globos
|
||||||
|
|
||||||
// Obtención de información
|
// Obtención de información
|
||||||
int getMenace(); // Obtiene el nivel de amenaza generado por los globos
|
int getMenace(); // Obtiene el nivel de amenaza generado por los globos
|
||||||
float getBalloonSpeed() const { return balloon_speed_; }
|
float getBalloonSpeed() const { return balloon_speed_; }
|
||||||
Balloons &getBalloons() { return balloons_; }
|
Balloons &getBalloons() { return balloons_; }
|
||||||
int getNumBalloons() const { return balloons_.size(); }
|
int getNumBalloons() const { return balloons_.size(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Balloons balloons_; // Vector con los globos activos
|
Balloons balloons_; // Vector con los globos activos
|
||||||
std::unique_ptr<Explosions> explosions_; // Objeto para gestionar explosiones
|
std::unique_ptr<Explosions> explosions_; // Objeto para gestionar explosiones
|
||||||
std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para manejar formaciones enemigas
|
std::unique_ptr<BalloonFormations> balloon_formations_; // Objeto para manejar formaciones enemigas
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Texture>> balloon_textures_; // Texturas de los globos
|
std::vector<std::shared_ptr<Texture>> balloon_textures_; // Texturas de los globos
|
||||||
std::vector<std::shared_ptr<Texture>> explosions_textures_; // Texturas de explosiones
|
std::vector<std::shared_ptr<Texture>> explosions_textures_; // Texturas de explosiones
|
||||||
|
|
||||||
std::vector<std::vector<std::string>> balloon_animations_; // Animaciones de los globos
|
std::vector<std::vector<std::string>> balloon_animations_; // Animaciones de los globos
|
||||||
std::vector<std::vector<std::string>> explosions_animations_; // Animaciones de las explosiones
|
std::vector<std::vector<std::string>> explosions_animations_; // Animaciones de las explosiones
|
||||||
|
|
||||||
// Variables de control de globos
|
// Variables de control de globos
|
||||||
float balloon_speed_ = BALLOON_SPEED[0];
|
float balloon_speed_ = BALLOON_SPEED[0];
|
||||||
@@ -98,9 +98,9 @@ private:
|
|||||||
SDL_FRect play_area_ = param.game.play_area.rect;
|
SDL_FRect play_area_ = param.game.play_area.rect;
|
||||||
bool creation_time_enabled_ = true;
|
bool creation_time_enabled_ = true;
|
||||||
bool can_deploy_balloons_ = true;
|
bool can_deploy_balloons_ = true;
|
||||||
bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar
|
bool bouncing_sound_enabled_ = false; // Si debe sonar el globo al rebotar
|
||||||
bool poping_sound_enabled_ = true; // Si debe sonar el globo al explotar
|
bool poping_sound_enabled_ = true; // Si debe sonar el globo al explotar
|
||||||
bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido
|
bool sound_enabled_ = true; // Indica si los globos deben hacer algun sonido
|
||||||
|
|
||||||
// Metodos privados
|
// Metodos privados
|
||||||
void init();
|
void init();
|
||||||
|
|||||||
+31
-44
@@ -1,10 +1,10 @@
|
|||||||
#include "bullet.h"
|
#include "bullet.h"
|
||||||
|
|
||||||
#include <memory> // Para allocator, unique_ptr, make_unique
|
#include <memory> // Para allocator, unique_ptr, make_unique
|
||||||
#include <string> // Para char_traits, basic_string, operator+, string
|
#include <string> // Para char_traits, basic_string, operator+, string
|
||||||
|
|
||||||
#include "param.h" // Para Param, ParamGame, param
|
#include "param.h" // Para Param, ParamGame, param
|
||||||
#include "resource.h" // Para Resource
|
#include "resource.h" // Para Resource
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Bullet::Bullet(float x, float y, BulletType bullet_type, bool powered, int owner)
|
Bullet::Bullet(float x, float y, BulletType bullet_type, bool powered, int owner)
|
||||||
@@ -12,29 +12,27 @@ Bullet::Bullet(float x, float y, BulletType bullet_type, bool powered, int owner
|
|||||||
pos_x_(x),
|
pos_x_(x),
|
||||||
pos_y_(y),
|
pos_y_(y),
|
||||||
bullet_type_(bullet_type),
|
bullet_type_(bullet_type),
|
||||||
owner_(owner)
|
owner_(owner) {
|
||||||
{
|
vel_x_ = (bullet_type_ == BulletType::LEFT) ? VEL_X_LEFT_
|
||||||
vel_x_ = (bullet_type_ == BulletType::LEFT) ? VEL_X_LEFT_
|
: (bullet_type_ == BulletType::RIGHT) ? VEL_X_RIGHT_
|
||||||
: (bullet_type_ == BulletType::RIGHT) ? VEL_X_RIGHT_
|
: 0;
|
||||||
: 0;
|
|
||||||
|
|
||||||
std::string powered_type = powered ? "powered_" : "normal_";
|
std::string powered_type = powered ? "powered_" : "normal_";
|
||||||
switch (bullet_type)
|
switch (bullet_type) {
|
||||||
{
|
case BulletType::UP:
|
||||||
case BulletType::UP:
|
sprite_->setCurrentAnimation(powered_type + "up");
|
||||||
sprite_->setCurrentAnimation(powered_type + "up");
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case BulletType::LEFT:
|
case BulletType::LEFT:
|
||||||
sprite_->setCurrentAnimation(powered_type + "left");
|
sprite_->setCurrentAnimation(powered_type + "left");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BulletType::RIGHT:
|
case BulletType::RIGHT:
|
||||||
sprite_->setCurrentAnimation(powered_type + "right");
|
sprite_->setCurrentAnimation(powered_type + "right");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
collider_.r = WIDTH / 2;
|
collider_.r = WIDTH / 2;
|
||||||
@@ -42,32 +40,27 @@ Bullet::Bullet(float x, float y, BulletType bullet_type, bool powered, int owner
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implementación de render (llama al render del sprite_)
|
// Implementación de render (llama al render del sprite_)
|
||||||
void Bullet::render()
|
void Bullet::render() {
|
||||||
{
|
|
||||||
if (bullet_type_ != BulletType::NONE)
|
if (bullet_type_ != BulletType::NONE)
|
||||||
sprite_->render();
|
sprite_->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el estado del objeto
|
// Actualiza el estado del objeto
|
||||||
BulletMoveStatus Bullet::update()
|
BulletMoveStatus Bullet::update() {
|
||||||
{
|
|
||||||
sprite_->update();
|
sprite_->update();
|
||||||
return move();
|
return move();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementación del movimiento usando BulletMoveStatus
|
// Implementación del movimiento usando BulletMoveStatus
|
||||||
BulletMoveStatus Bullet::move()
|
BulletMoveStatus Bullet::move() {
|
||||||
{
|
|
||||||
pos_x_ += vel_x_;
|
pos_x_ += vel_x_;
|
||||||
if (pos_x_ < param.game.play_area.rect.x - WIDTH || pos_x_ > param.game.play_area.rect.w)
|
if (pos_x_ < param.game.play_area.rect.x - WIDTH || pos_x_ > param.game.play_area.rect.w) {
|
||||||
{
|
|
||||||
disable();
|
disable();
|
||||||
return BulletMoveStatus::OUT;
|
return BulletMoveStatus::OUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos_y_ += VEL_Y_;
|
pos_y_ += VEL_Y_;
|
||||||
if (pos_y_ < param.game.play_area.rect.y - HEIGHT)
|
if (pos_y_ < param.game.play_area.rect.y - HEIGHT) {
|
||||||
{
|
|
||||||
disable();
|
disable();
|
||||||
return BulletMoveStatus::OUT;
|
return BulletMoveStatus::OUT;
|
||||||
}
|
}
|
||||||
@@ -78,34 +71,28 @@ BulletMoveStatus Bullet::move()
|
|||||||
return BulletMoveStatus::OK;
|
return BulletMoveStatus::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Bullet::isEnabled() const
|
bool Bullet::isEnabled() const {
|
||||||
{
|
|
||||||
return bullet_type_ != BulletType::NONE;
|
return bullet_type_ != BulletType::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bullet::disable()
|
void Bullet::disable() {
|
||||||
{
|
|
||||||
bullet_type_ = BulletType::NONE;
|
bullet_type_ = BulletType::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Bullet::getOwner() const
|
int Bullet::getOwner() const {
|
||||||
{
|
|
||||||
return owner_;
|
return owner_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Circle &Bullet::getCollider()
|
Circle &Bullet::getCollider() {
|
||||||
{
|
|
||||||
return collider_;
|
return collider_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bullet::shiftColliders()
|
void Bullet::shiftColliders() {
|
||||||
{
|
|
||||||
collider_.x = pos_x_ + collider_.r;
|
collider_.x = pos_x_ + collider_.r;
|
||||||
collider_.y = pos_y_ + collider_.r;
|
collider_.y = pos_y_ + collider_.r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bullet::shiftSprite()
|
void Bullet::shiftSprite() {
|
||||||
{
|
|
||||||
sprite_->setX(pos_x_);
|
sprite_->setX(pos_x_);
|
||||||
sprite_->setY(pos_y_);
|
sprite_->setY(pos_y_);
|
||||||
}
|
}
|
||||||
+47
-49
@@ -1,70 +1,68 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para Uint8
|
#include <SDL3/SDL.h> // Para Uint8
|
||||||
#include <memory> // Para unique_ptr
|
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include <memory> // Para unique_ptr
|
||||||
#include "utils.h" // Para Circle
|
|
||||||
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
|
#include "utils.h" // Para Circle
|
||||||
|
|
||||||
// Tipos de balas
|
// Tipos de balas
|
||||||
enum class BulletType : Uint8
|
enum class BulletType : Uint8 {
|
||||||
{
|
UP,
|
||||||
UP,
|
LEFT,
|
||||||
LEFT,
|
RIGHT,
|
||||||
RIGHT,
|
NONE
|
||||||
NONE
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Resultado del movimiento de la bala
|
// Resultado del movimiento de la bala
|
||||||
enum class BulletMoveStatus : Uint8
|
enum class BulletMoveStatus : Uint8 {
|
||||||
{
|
OK = 0,
|
||||||
OK = 0,
|
OUT = 1
|
||||||
OUT = 1
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clase Bullet
|
// Clase Bullet
|
||||||
class Bullet
|
class Bullet {
|
||||||
{
|
public:
|
||||||
public:
|
// Constantes
|
||||||
// Constantes
|
static constexpr float WIDTH = 12.0f;
|
||||||
static constexpr float WIDTH = 12.0f;
|
static constexpr float HEIGHT = 12.0f;
|
||||||
static constexpr float HEIGHT = 12.0f;
|
|
||||||
|
|
||||||
// Constructor y Destructor
|
// Constructor y Destructor
|
||||||
Bullet(float x, float y, BulletType bullet_type, bool powered, int owner);
|
Bullet(float x, float y, BulletType bullet_type, bool powered, int owner);
|
||||||
~Bullet() = default;
|
~Bullet() = default;
|
||||||
|
|
||||||
// Métodos principales
|
// Métodos principales
|
||||||
void render(); // Dibuja la bala en pantalla
|
void render(); // Dibuja la bala en pantalla
|
||||||
BulletMoveStatus update(); // Actualiza el estado del objeto
|
BulletMoveStatus update(); // Actualiza el estado del objeto
|
||||||
|
|
||||||
// Estado de la bala
|
// Estado de la bala
|
||||||
bool isEnabled() const; // Comprueba si está activa
|
bool isEnabled() const; // Comprueba si está activa
|
||||||
void disable(); // Desactiva la bala
|
void disable(); // Desactiva la bala
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
int getOwner() const; // Devuelve el identificador del dueño
|
int getOwner() const; // Devuelve el identificador del dueño
|
||||||
Circle &getCollider(); // Devuelve el círculo de colisión
|
Circle &getCollider(); // Devuelve el círculo de colisión
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Constantes
|
// Constantes
|
||||||
static constexpr float VEL_Y_ = -3.0f;
|
static constexpr float VEL_Y_ = -3.0f;
|
||||||
static constexpr float VEL_X_LEFT_ = -2.0f;
|
static constexpr float VEL_X_LEFT_ = -2.0f;
|
||||||
static constexpr float VEL_X_RIGHT_ = 2.0f;
|
static constexpr float VEL_X_RIGHT_ = 2.0f;
|
||||||
|
|
||||||
// Propiedades
|
// Propiedades
|
||||||
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos
|
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos
|
||||||
|
|
||||||
float pos_x_; // Posición en el eje X
|
float pos_x_; // Posición en el eje X
|
||||||
float pos_y_; // Posición en el eje Y
|
float pos_y_; // Posición en el eje Y
|
||||||
float vel_x_; // Velocidad en el eje X
|
float vel_x_; // Velocidad en el eje X
|
||||||
|
|
||||||
BulletType bullet_type_; // Tipo de bala
|
BulletType bullet_type_; // Tipo de bala
|
||||||
int owner_; // Identificador del dueño
|
int owner_; // Identificador del dueño
|
||||||
Circle collider_; // Círculo de colisión
|
Circle collider_; // Círculo de colisión
|
||||||
|
|
||||||
// Métodos internos
|
// Métodos internos
|
||||||
void shiftColliders(); // Ajusta el círculo de colisión
|
void shiftColliders(); // Ajusta el círculo de colisión
|
||||||
void shiftSprite(); // Ajusta el sprite
|
void shiftSprite(); // Ajusta el sprite
|
||||||
BulletMoveStatus move(); // Mueve la bala y devuelve su estado
|
BulletMoveStatus move(); // Mueve la bala y devuelve su estado
|
||||||
};
|
};
|
||||||
+39
-65
@@ -1,34 +1,30 @@
|
|||||||
#include "define_buttons.h"
|
#include "define_buttons.h"
|
||||||
|
|
||||||
#include "input.h" // Para Input, InputAction
|
#include "input.h" // Para Input, InputAction
|
||||||
#include "lang.h" // Para getText
|
#include "lang.h" // Para getText
|
||||||
#include "options.h" // Para OptionsController, Options, options
|
#include "options.h" // Para OptionsController, Options, options
|
||||||
#include "param.h" // Para Param, param, ParamGame, ParamTitle
|
#include "param.h" // Para Param, param, ParamGame, ParamTitle
|
||||||
#include "resource.h" // Para Resource
|
#include "resource.h" // Para Resource
|
||||||
#include "text.h" // Para Text
|
#include "text.h" // Para Text
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
DefineButtons::DefineButtons()
|
DefineButtons::DefineButtons()
|
||||||
: input_(Input::get()),
|
: input_(Input::get()),
|
||||||
text_(Resource::get()->getText("8bithud"))
|
text_(Resource::get()->getText("8bithud")) {
|
||||||
{
|
|
||||||
// Inicializa variables
|
// Inicializa variables
|
||||||
x_ = param.game.width / 2;
|
x_ = param.game.width / 2;
|
||||||
y_ = param.title.press_start_position;
|
y_ = param.title.press_start_position;
|
||||||
|
|
||||||
clearButtons();
|
clearButtons();
|
||||||
|
|
||||||
for (int i = 0; i < input_->getNumControllers(); ++i)
|
for (int i = 0; i < input_->getNumControllers(); ++i) {
|
||||||
{
|
|
||||||
controller_names_.emplace_back(input_->getControllerName(i));
|
controller_names_.emplace_back(input_->getControllerName(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja el objeto en pantalla
|
// Dibuja el objeto en pantalla
|
||||||
void DefineButtons::render()
|
void DefineButtons::render() {
|
||||||
{
|
if (enabled_) {
|
||||||
if (enabled_)
|
|
||||||
{
|
|
||||||
text_->writeCentered(x_, y_ - 10, Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(Options::controllers.at(index_controller_).player_id));
|
text_->writeCentered(x_, y_ - 10, Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(Options::controllers.at(index_controller_).player_id));
|
||||||
text_->writeCentered(x_, y_, controller_names_.at(index_controller_));
|
text_->writeCentered(x_, y_, controller_names_.at(index_controller_));
|
||||||
text_->writeCentered(x_, y_ + 10, buttons_.at(index_button_).label);
|
text_->writeCentered(x_, y_ + 10, buttons_.at(index_button_).label);
|
||||||
@@ -36,27 +32,22 @@ void DefineButtons::render()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba el botón que se ha pulsado
|
// Comprueba el botón que se ha pulsado
|
||||||
void DefineButtons::doControllerButtonDown(const SDL_GamepadButtonEvent &event)
|
void DefineButtons::doControllerButtonDown(const SDL_GamepadButtonEvent &event) {
|
||||||
{
|
|
||||||
// Solo pilla botones del mando que toca
|
// Solo pilla botones del mando que toca
|
||||||
if (input_->getJoyIndex(event.which) != static_cast<int>(index_controller_))
|
if (input_->getJoyIndex(event.which) != static_cast<int>(index_controller_)) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto button = static_cast<SDL_GamepadButton>(event.button);
|
const auto button = static_cast<SDL_GamepadButton>(event.button);
|
||||||
if (checkButtonNotInUse(button))
|
if (checkButtonNotInUse(button)) {
|
||||||
{
|
|
||||||
buttons_.at(index_button_).button = button;
|
buttons_.at(index_button_).button = button;
|
||||||
incIndexButton();
|
incIndexButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Asigna los botones definidos al input_
|
// Asigna los botones definidos al input_
|
||||||
void DefineButtons::bindButtons()
|
void DefineButtons::bindButtons() {
|
||||||
{
|
for (const auto &button : buttons_) {
|
||||||
for (const auto &button : buttons_)
|
|
||||||
{
|
|
||||||
input_->bindGameControllerButton(index_controller_, button.input, button.button);
|
input_->bindGameControllerButton(index_controller_, button.input, button.button);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,29 +57,24 @@ void DefineButtons::bindButtons()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba los eventos
|
// Comprueba los eventos
|
||||||
void DefineButtons::checkEvents(const SDL_Event &event)
|
void DefineButtons::checkEvents(const SDL_Event &event) {
|
||||||
{
|
if (enabled_) {
|
||||||
if (enabled_)
|
switch (event.type) {
|
||||||
{
|
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||||
switch (event.type)
|
doControllerButtonDown(event.gbutton);
|
||||||
{
|
break;
|
||||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||||
doControllerButtonDown(event.gbutton);
|
checkEnd();
|
||||||
break;
|
break;
|
||||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
default:
|
||||||
checkEnd();
|
break;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Habilita el objeto
|
// Habilita el objeto
|
||||||
bool DefineButtons::enable(int index)
|
bool DefineButtons::enable(int index) {
|
||||||
{
|
if (index < input_->getNumControllers()) {
|
||||||
if (index < input_->getNumControllers())
|
|
||||||
{
|
|
||||||
enabled_ = true;
|
enabled_ = true;
|
||||||
finished_ = false;
|
finished_ = false;
|
||||||
index_controller_ = index;
|
index_controller_ = index;
|
||||||
@@ -104,37 +90,28 @@ bool DefineButtons::enable(int index)
|
|||||||
bool DefineButtons::isEnabled() const { return enabled_; }
|
bool DefineButtons::isEnabled() const { return enabled_; }
|
||||||
|
|
||||||
// Incrementa el indice de los botones
|
// Incrementa el indice de los botones
|
||||||
void DefineButtons::incIndexButton()
|
void DefineButtons::incIndexButton() {
|
||||||
{
|
if (index_button_ < buttons_.size() - 1) {
|
||||||
if (index_button_ < buttons_.size() - 1)
|
|
||||||
{
|
|
||||||
++index_button_;
|
++index_button_;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
finished_ = true;
|
finished_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Guarda los cambios en las opciones
|
// Guarda los cambios en las opciones
|
||||||
void DefineButtons::saveBindingsToOptions()
|
void DefineButtons::saveBindingsToOptions() {
|
||||||
{
|
|
||||||
// Modifica las opciones para colocar los valores asignados
|
// Modifica las opciones para colocar los valores asignados
|
||||||
auto &controller = Options::controllers.at(index_controller_);
|
auto &controller = Options::controllers.at(index_controller_);
|
||||||
controller.name = input_->getControllerName(index_controller_);
|
controller.name = input_->getControllerName(index_controller_);
|
||||||
for (size_t j = 0; j < controller.inputs.size(); ++j)
|
for (size_t j = 0; j < controller.inputs.size(); ++j) {
|
||||||
{
|
|
||||||
controller.buttons.at(j) = input_->getControllerBinding(index_controller_, controller.inputs.at(j));
|
controller.buttons.at(j) = input_->getControllerBinding(index_controller_, controller.inputs.at(j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba que un botón no esté ya asignado
|
// Comprueba que un botón no esté ya asignado
|
||||||
bool DefineButtons::checkButtonNotInUse(SDL_GamepadButton button)
|
bool DefineButtons::checkButtonNotInUse(SDL_GamepadButton button) {
|
||||||
{
|
for (const auto &b : buttons_) {
|
||||||
for (const auto &b : buttons_)
|
if (b.button == button) {
|
||||||
{
|
|
||||||
if (b.button == button)
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,8 +119,7 @@ bool DefineButtons::checkButtonNotInUse(SDL_GamepadButton button)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Limpia la asignación de botones
|
// Limpia la asignación de botones
|
||||||
void DefineButtons::clearButtons()
|
void DefineButtons::clearButtons() {
|
||||||
{
|
|
||||||
buttons_.clear();
|
buttons_.clear();
|
||||||
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_LEFT"), InputAction::FIRE_LEFT, SDL_GAMEPAD_BUTTON_INVALID);
|
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_LEFT"), InputAction::FIRE_LEFT, SDL_GAMEPAD_BUTTON_INVALID);
|
||||||
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_UP"), InputAction::FIRE_CENTER, SDL_GAMEPAD_BUTTON_INVALID);
|
buttons_.emplace_back(Lang::getText("[DEFINE_BUTTONS] FIRE_UP"), InputAction::FIRE_CENTER, SDL_GAMEPAD_BUTTON_INVALID);
|
||||||
@@ -153,11 +129,9 @@ void DefineButtons::clearButtons()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba si ha finalizado
|
// Comprueba si ha finalizado
|
||||||
void DefineButtons::checkEnd()
|
void DefineButtons::checkEnd() {
|
||||||
{
|
|
||||||
// Comprueba si ha finalizado
|
// Comprueba si ha finalizado
|
||||||
if (finished_)
|
if (finished_) {
|
||||||
{
|
|
||||||
// Asigna los botones definidos al input_
|
// Asigna los botones definidos al input_
|
||||||
bindButtons();
|
bindButtons();
|
||||||
|
|
||||||
|
|||||||
+32
-33
@@ -1,10 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_GamepadButton, SDL_Event, SDL_GamepadButtonEvent
|
#include <SDL3/SDL.h> // Para SDL_GamepadButton, SDL_Event, SDL_GamepadButtonEvent
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
#include <memory> // Para shared_ptr
|
|
||||||
#include <string> // Para basic_string, string
|
#include <memory> // Para shared_ptr
|
||||||
#include <vector> // Para vector
|
#include <string> // Para basic_string, string
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
// Declaraciones adelantadas
|
// Declaraciones adelantadas
|
||||||
class Input;
|
class Input;
|
||||||
@@ -12,48 +13,46 @@ class Text;
|
|||||||
enum class InputAction : int;
|
enum class InputAction : int;
|
||||||
|
|
||||||
// Estructura para definir botones
|
// Estructura para definir botones
|
||||||
struct DefineButtonsButton
|
struct DefineButtonsButton {
|
||||||
{
|
std::string label; // Texto en pantalla
|
||||||
std::string label; // Texto en pantalla
|
InputAction input; // Acción asociada
|
||||||
InputAction input; // Acción asociada
|
SDL_GamepadButton button; // Botón del mando
|
||||||
SDL_GamepadButton button; // Botón del mando
|
|
||||||
|
|
||||||
DefineButtonsButton(const std::string &lbl, InputAction inp, SDL_GamepadButton btn)
|
DefineButtonsButton(const std::string &lbl, InputAction inp, SDL_GamepadButton btn)
|
||||||
: label(lbl), input(inp), button(btn) {}
|
: label(lbl), input(inp), button(btn) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clase DefineButtons
|
// Clase DefineButtons
|
||||||
class DefineButtons
|
class DefineButtons {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
DefineButtons();
|
DefineButtons();
|
||||||
~DefineButtons() = default;
|
~DefineButtons() = default;
|
||||||
|
|
||||||
void render(); // Dibuja el objeto en pantalla
|
void render(); // Dibuja el objeto en pantalla
|
||||||
void checkEvents(const SDL_Event &event); // Procesa los eventos
|
void checkEvents(const SDL_Event &event); // Procesa los eventos
|
||||||
bool enable(int index_controller); // Habilita la redefinición de botones
|
bool enable(int index_controller); // Habilita la redefinición de botones
|
||||||
bool isEnabled() const; // Comprueba si está habilitado
|
bool isEnabled() const; // Comprueba si está habilitado
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Objetos
|
// Objetos
|
||||||
Input *input_ = nullptr; // Gestión de entrada
|
Input *input_ = nullptr; // Gestión de entrada
|
||||||
std::shared_ptr<Text> text_; // Renderizado de texto
|
std::shared_ptr<Text> text_; // Renderizado de texto
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
bool enabled_ = false; // Indica si está activo
|
bool enabled_ = false; // Indica si está activo
|
||||||
int x_ = 0, y_ = 0; // Coordenadas de texto
|
int x_ = 0, y_ = 0; // Coordenadas de texto
|
||||||
std::vector<DefineButtonsButton> buttons_; // Definiciones de botones
|
std::vector<DefineButtonsButton> buttons_; // Definiciones de botones
|
||||||
size_t index_controller_ = 0; // Índice del controlador asignado
|
size_t index_controller_ = 0; // Índice del controlador asignado
|
||||||
size_t index_button_ = 0; // Índice del botón en proceso
|
size_t index_button_ = 0; // Índice del botón en proceso
|
||||||
std::vector<std::string> controller_names_; // Nombres de los mandos
|
std::vector<std::string> controller_names_; // Nombres de los mandos
|
||||||
bool finished_ = false;
|
bool finished_ = false;
|
||||||
|
|
||||||
// Métodos internos
|
// Métodos internos
|
||||||
void incIndexButton(); // Incrementa el índice de botones
|
void incIndexButton(); // Incrementa el índice de botones
|
||||||
void doControllerButtonDown(const SDL_GamepadButtonEvent &event); // Procesa pulsaciones
|
void doControllerButtonDown(const SDL_GamepadButtonEvent &event); // Procesa pulsaciones
|
||||||
void bindButtons(); // Asigna botones al sistema de entrada
|
void bindButtons(); // Asigna botones al sistema de entrada
|
||||||
void saveBindingsToOptions(); // Guarda configuraciones
|
void saveBindingsToOptions(); // Guarda configuraciones
|
||||||
bool checkButtonNotInUse(SDL_GamepadButton button); // Verifica uso de botones
|
bool checkButtonNotInUse(SDL_GamepadButton button); // Verifica uso de botones
|
||||||
void clearButtons(); // Limpia asignaciones actuales
|
void clearButtons(); // Limpia asignaciones actuales
|
||||||
void checkEnd(); // Comprueba si ha finalizado
|
void checkEnd(); // Comprueba si ha finalizado
|
||||||
};
|
};
|
||||||
+500
-546
File diff suppressed because it is too large.
Load diff
+39
-41
@@ -1,55 +1,53 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string> // Para manejar cadenas de texto
|
#include <string> // Para manejar cadenas de texto
|
||||||
|
|
||||||
namespace Lang
|
namespace Lang {
|
||||||
{
|
enum class Code : int;
|
||||||
enum class Code : int;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Director
|
class Director {
|
||||||
{
|
public:
|
||||||
public:
|
// --- Constructor y destructor ---
|
||||||
// --- Constructor y destructor ---
|
Director(int argc, const char *argv[]);
|
||||||
Director(int argc, const char *argv[]);
|
~Director();
|
||||||
~Director();
|
|
||||||
|
|
||||||
// --- Bucle principal ---
|
// --- Bucle principal ---
|
||||||
int run();
|
int run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Variables internas ---
|
// --- Variables internas ---
|
||||||
std::string executable_path_; // Ruta del ejecutable
|
std::string executable_path_; // Ruta del ejecutable
|
||||||
std::string system_folder_; // Carpeta del sistema para almacenar datos
|
std::string system_folder_; // Carpeta del sistema para almacenar datos
|
||||||
|
|
||||||
// --- Inicialización y cierre del sistema ---
|
// --- Inicialización y cierre del sistema ---
|
||||||
void init(); // Inicializa la aplicación
|
void init(); // Inicializa la aplicación
|
||||||
void close(); // Cierra y libera recursos
|
void close(); // Cierra y libera recursos
|
||||||
|
|
||||||
// --- Configuración inicial ---
|
// --- Configuración inicial ---
|
||||||
void loadParams(); // Carga los parámetros del programa
|
void loadParams(); // Carga los parámetros del programa
|
||||||
void loadScoreFile(); // Carga el fichero de puntuaciones
|
void loadScoreFile(); // Carga el fichero de puntuaciones
|
||||||
void createSystemFolder(const std::string &folder); // Crea la carpeta del sistema
|
void createSystemFolder(const std::string &folder); // Crea la carpeta del sistema
|
||||||
|
|
||||||
// --- Gestión de entrada y archivos ---
|
// --- Gestión de entrada y archivos ---
|
||||||
void bindInputs(); // Asigna botones y teclas al sistema de entrada
|
void bindInputs(); // Asigna botones y teclas al sistema de entrada
|
||||||
void setFileList(); // Crea el índice de archivos disponibles
|
void setFileList(); // Crea el índice de archivos disponibles
|
||||||
void checkProgramArguments(int argc, const char *argv[]); // Verifica los parámetros del programa
|
void checkProgramArguments(int argc, const char *argv[]); // Verifica los parámetros del programa
|
||||||
|
|
||||||
// --- Secciones del programa ---
|
// --- Secciones del programa ---
|
||||||
void runLogo(); // Ejecuta la pantalla con el logo
|
void runLogo(); // Ejecuta la pantalla con el logo
|
||||||
void runIntro(); // Ejecuta la introducción del juego
|
void runIntro(); // Ejecuta la introducción del juego
|
||||||
void runTitle(); // Ejecuta la pantalla de título
|
void runTitle(); // Ejecuta la pantalla de título
|
||||||
void runGame(); // Inicia el juego
|
void runGame(); // Inicia el juego
|
||||||
void runInstructions(); // Muestra las instrucciones
|
void runInstructions(); // Muestra las instrucciones
|
||||||
void runCredits(); // Muestra los créditos del juego
|
void runCredits(); // Muestra los créditos del juego
|
||||||
void runHiScoreTable(); // Muestra la tabla de puntuaciones
|
void runHiScoreTable(); // Muestra la tabla de puntuaciones
|
||||||
void runDemoGame(); // Ejecuta el modo demo
|
void runDemoGame(); // Ejecuta el modo demo
|
||||||
void reset(); // Reinicia objetos y vuelve a la sección inicial
|
void reset(); // Reinicia objetos y vuelve a la sección inicial
|
||||||
|
|
||||||
// --- Gestión de archivos de idioma ---
|
// --- Gestión de archivos de idioma ---
|
||||||
std::string getLangFile(Lang::Code code); // Obtiene un fichero de idioma según el código
|
std::string getLangFile(Lang::Code code); // Obtiene un fichero de idioma según el código
|
||||||
|
|
||||||
// --- Apagado del sistema ---
|
// --- Apagado del sistema ---
|
||||||
void shutdownSystem(bool should_shutdown); // Apaga el sistema
|
void shutdownSystem(bool should_shutdown); // Apaga el sistema
|
||||||
};
|
};
|
||||||
+39
-73
@@ -1,10 +1,11 @@
|
|||||||
#include "enter_name.h"
|
#include "enter_name.h"
|
||||||
|
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
#include <stdlib.h> // Para rand
|
#include <stdlib.h> // Para rand
|
||||||
#include <string_view> // Para basic_string_view, string_view
|
|
||||||
|
|
||||||
#include "utils.h" // Para trim
|
#include <string_view> // Para basic_string_view, string_view
|
||||||
|
|
||||||
|
#include "utils.h" // Para trim
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
EnterName::EnterName()
|
EnterName::EnterName()
|
||||||
@@ -12,18 +13,15 @@ EnterName::EnterName()
|
|||||||
character_index_{0} {}
|
character_index_{0} {}
|
||||||
|
|
||||||
// Inicializa el objeto
|
// Inicializa el objeto
|
||||||
void EnterName::init(const std::string &name)
|
void EnterName::init(const std::string &name) {
|
||||||
{
|
|
||||||
// No se pasa ningún nombre
|
// No se pasa ningún nombre
|
||||||
if (name.empty())
|
if (name.empty()) {
|
||||||
{
|
|
||||||
name_ = "A";
|
name_ = "A";
|
||||||
position_ = 0;
|
position_ = 0;
|
||||||
position_overflow_ = false;
|
position_overflow_ = false;
|
||||||
}
|
}
|
||||||
// Se pasa un nombre
|
// Se pasa un nombre
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
name_ = name;
|
name_ = name;
|
||||||
position_ = name_.length();
|
position_ = name_.length();
|
||||||
position_overflow_ = position_ >= NAME_SIZE ? true : false;
|
position_overflow_ = position_ >= NAME_SIZE ? true : false;
|
||||||
@@ -34,28 +32,22 @@ void EnterName::init(const std::string &name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Incrementa la posición
|
// Incrementa la posición
|
||||||
void EnterName::incPosition()
|
void EnterName::incPosition() {
|
||||||
{
|
if (position_overflow_) {
|
||||||
if (position_overflow_)
|
|
||||||
{
|
|
||||||
// Si ya estamos en overflow, no incrementamos más.
|
// Si ya estamos en overflow, no incrementamos más.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
++position_;
|
++position_;
|
||||||
|
|
||||||
if (position_ >= NAME_SIZE)
|
if (position_ >= NAME_SIZE) {
|
||||||
{
|
position_ = NAME_SIZE; // Mantenemos en el índice máximo válido.
|
||||||
position_ = NAME_SIZE; // Mantenemos en el índice máximo válido.
|
position_overflow_ = true; // Activamos el flag de overflow.
|
||||||
position_overflow_ = true; // Activamos el flag de overflow.
|
} else if (position_ > 0) // No es necesario verificar position_ < MAX_NAME_LENGHT
|
||||||
}
|
|
||||||
else if (position_ > 0) // No es necesario verificar position_ < MAX_NAME_LENGHT
|
|
||||||
{
|
{
|
||||||
// Copiamos el índice del carácter anterior si es posible.
|
// Copiamos el índice del carácter anterior si es posible.
|
||||||
character_index_[position_] = character_index_[position_ - 1];
|
character_index_[position_] = character_index_[position_ - 1];
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Si position_ es 0, inicializamos el carácter actual.
|
// Si position_ es 0, inicializamos el carácter actual.
|
||||||
character_index_[position_] = 0;
|
character_index_[position_] = 0;
|
||||||
}
|
}
|
||||||
@@ -64,36 +56,27 @@ void EnterName::incPosition()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decrementa la posición
|
// Decrementa la posición
|
||||||
void EnterName::decPosition()
|
void EnterName::decPosition() {
|
||||||
{
|
if (position_overflow_) {
|
||||||
if (position_overflow_)
|
|
||||||
{
|
|
||||||
// Si estaba en overflow, lo desactivamos y mantenemos position_ en el máximo.
|
// Si estaba en overflow, lo desactivamos y mantenemos position_ en el máximo.
|
||||||
position_overflow_ = false;
|
position_overflow_ = false;
|
||||||
position_ = NAME_SIZE - 1;
|
position_ = NAME_SIZE - 1;
|
||||||
}
|
} else {
|
||||||
else
|
if (position_ > 0) {
|
||||||
{
|
|
||||||
if (position_ > 0)
|
|
||||||
{
|
|
||||||
--position_;
|
--position_;
|
||||||
|
|
||||||
// Limpiamos el carácter siguiente si el índice es válido.
|
// Limpiamos el carácter siguiente si el índice es válido.
|
||||||
if (position_ + 1 < NAME_SIZE)
|
if (position_ + 1 < NAME_SIZE) {
|
||||||
{
|
|
||||||
character_index_[position_ + 1] = 0;
|
character_index_[position_ + 1] = 0;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Si position_ es 0, aseguramos que no vaya a ser negativo y limpiamos el carácter actual.
|
// Si position_ es 0, aseguramos que no vaya a ser negativo y limpiamos el carácter actual.
|
||||||
position_ = 0;
|
position_ = 0;
|
||||||
// character_index_[position_] = 0;
|
// character_index_[position_] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si position_ es menor que NAME_LENGHT, aseguramos que el overflow esté desactivado.
|
// Si position_ es menor que NAME_LENGHT, aseguramos que el overflow esté desactivado.
|
||||||
if (position_ < NAME_SIZE)
|
if (position_ < NAME_SIZE) {
|
||||||
{
|
|
||||||
position_overflow_ = false;
|
position_overflow_ = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,71 +85,57 @@ void EnterName::decPosition()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Incrementa el índice
|
// Incrementa el índice
|
||||||
void EnterName::incIndex()
|
void EnterName::incIndex() {
|
||||||
{
|
if (position_overflow_) {
|
||||||
if (position_overflow_)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
++character_index_[position_];
|
++character_index_[position_];
|
||||||
if (character_index_[position_] >= static_cast<int>(character_list_.size()))
|
if (character_index_[position_] >= static_cast<int>(character_list_.size())) {
|
||||||
{
|
|
||||||
character_index_[position_] = 0;
|
character_index_[position_] = 0;
|
||||||
}
|
}
|
||||||
updateNameFromCharacterIndex();
|
updateNameFromCharacterIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrementa el índice
|
// Decrementa el índice
|
||||||
void EnterName::decIndex()
|
void EnterName::decIndex() {
|
||||||
{
|
if (position_overflow_) {
|
||||||
if (position_overflow_)
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
--character_index_[position_];
|
--character_index_[position_];
|
||||||
if (character_index_[position_] < 0)
|
if (character_index_[position_] < 0) {
|
||||||
{
|
|
||||||
character_index_[position_] = character_list_.size() - 1;
|
character_index_[position_] = character_list_.size() - 1;
|
||||||
}
|
}
|
||||||
updateNameFromCharacterIndex();
|
updateNameFromCharacterIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el nombre a partir de la lista de índices
|
// Actualiza el nombre a partir de la lista de índices
|
||||||
void EnterName::updateNameFromCharacterIndex()
|
void EnterName::updateNameFromCharacterIndex() {
|
||||||
{
|
|
||||||
name_.clear();
|
name_.clear();
|
||||||
for (size_t i = 0; i < NAME_SIZE; ++i)
|
for (size_t i = 0; i < NAME_SIZE; ++i) {
|
||||||
{
|
|
||||||
name_.push_back(character_list_[character_index_[i]]);
|
name_.push_back(character_list_[character_index_[i]]);
|
||||||
}
|
}
|
||||||
name_ = trim(name_);
|
name_ = trim(name_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza la variable
|
// Actualiza la variable
|
||||||
void EnterName::initCharacterIndex(const std::string &name)
|
void EnterName::initCharacterIndex(const std::string &name) {
|
||||||
{
|
|
||||||
// Rellena de espacios
|
// Rellena de espacios
|
||||||
for (size_t i = 0; i < NAME_SIZE; ++i)
|
for (size_t i = 0; i < NAME_SIZE; ++i) {
|
||||||
{
|
|
||||||
character_index_[i] = 0;
|
character_index_[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Coloca los índices en función de los caracteres que forman el nombre
|
// Coloca los índices en función de los caracteres que forman el nombre
|
||||||
for (size_t i = 0; i < name.substr(0, NAME_SIZE).size(); ++i)
|
for (size_t i = 0; i < name.substr(0, NAME_SIZE).size(); ++i) {
|
||||||
{
|
|
||||||
character_index_[i] = findIndex(name.at(i));
|
character_index_[i] = findIndex(name.at(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encuentra el indice de un caracter en "character_list_"
|
// Encuentra el indice de un caracter en "character_list_"
|
||||||
int EnterName::findIndex(char character) const
|
int EnterName::findIndex(char character) const {
|
||||||
{
|
for (size_t i = 0; i < character_list_.size(); ++i) {
|
||||||
for (size_t i = 0; i < character_list_.size(); ++i)
|
if (character == character_list_.at(i)) {
|
||||||
{
|
|
||||||
if (character == character_list_.at(i))
|
|
||||||
{
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,18 +143,15 @@ int EnterName::findIndex(char character) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Devuelve un nombre al azar
|
// Devuelve un nombre al azar
|
||||||
std::string EnterName::getRandomName()
|
std::string EnterName::getRandomName() {
|
||||||
{
|
|
||||||
static constexpr std::array<std::string_view, 8> NAMES = {
|
static constexpr std::array<std::string_view, 8> NAMES = {
|
||||||
"BAL1", "TABE", "DOC", "MON", "SAM1", "JORDI", "JDES", "PEPE"};
|
"BAL1", "TABE", "DOC", "MON", "SAM1", "JORDI", "JDES", "PEPE"};
|
||||||
return std::string(NAMES[rand() % NAMES.size()]);
|
return std::string(NAMES[rand() % NAMES.size()]);
|
||||||
}
|
}
|
||||||
// Obtiene el nombre final introducido
|
// Obtiene el nombre final introducido
|
||||||
std::string EnterName::getFinalName()
|
std::string EnterName::getFinalName() {
|
||||||
{
|
|
||||||
auto name = trim(name_.substr(0, position_));
|
auto name = trim(name_.substr(0, position_));
|
||||||
if (name.empty())
|
if (name.empty()) {
|
||||||
{
|
|
||||||
name = getRandomName();
|
name = getRandomName();
|
||||||
}
|
}
|
||||||
name_ = name;
|
name_ = name;
|
||||||
|
|||||||
+26
-26
@@ -1,43 +1,43 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
#include <array> // Para array
|
|
||||||
#include <string> // Para string, basic_string
|
|
||||||
|
|
||||||
#include "utils.h" // Para trim
|
#include <array> // Para array
|
||||||
|
#include <string> // Para string, basic_string
|
||||||
|
|
||||||
|
#include "utils.h" // Para trim
|
||||||
|
|
||||||
// Tamaño máximo del nombre
|
// Tamaño máximo del nombre
|
||||||
constexpr size_t NAME_SIZE = 5;
|
constexpr size_t NAME_SIZE = 5;
|
||||||
|
|
||||||
// Clase EnterName
|
// Clase EnterName
|
||||||
class EnterName
|
class EnterName {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
EnterName();
|
EnterName();
|
||||||
~EnterName() = default;
|
~EnterName() = default;
|
||||||
|
|
||||||
void init(const std::string &name = ""); // Inicializa con un nombre opcional
|
void init(const std::string &name = ""); // Inicializa con un nombre opcional
|
||||||
|
|
||||||
void incPosition(); // Incrementa la posición del carácter actual
|
void incPosition(); // Incrementa la posición del carácter actual
|
||||||
void decPosition(); // Decrementa la posición del carácter actual
|
void decPosition(); // Decrementa la posición del carácter actual
|
||||||
void incIndex(); // Incrementa el índice del carácter en la lista
|
void incIndex(); // Incrementa el índice del carácter en la lista
|
||||||
void decIndex(); // Decrementa el índice del carácter en la lista
|
void decIndex(); // Decrementa el índice del carácter en la lista
|
||||||
|
|
||||||
std::string getFinalName(); // Obtiene el nombre final introducido
|
std::string getFinalName(); // Obtiene el nombre final introducido
|
||||||
std::string getCurrentName() const { return trim(name_); } // Obtiene el nombre actual en proceso
|
std::string getCurrentName() const { return trim(name_); } // Obtiene el nombre actual en proceso
|
||||||
|
|
||||||
int getPosition() const { return position_; } // Posición actual del carácter editado
|
int getPosition() const { return position_; } // Posición actual del carácter editado
|
||||||
bool getPositionOverflow() const { return position_overflow_; } // Indica si la posición excede el límite
|
bool getPositionOverflow() const { return position_overflow_; } // Indica si la posición excede el límite
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string character_list_; // Lista de caracteres permitidos
|
std::string character_list_; // Lista de caracteres permitidos
|
||||||
std::string name_; // Nombre en proceso
|
std::string name_; // Nombre en proceso
|
||||||
size_t position_ = 0; // Índice del carácter que se edita
|
size_t position_ = 0; // Índice del carácter que se edita
|
||||||
bool position_overflow_ = false; // Flag para exceder límite
|
bool position_overflow_ = false; // Flag para exceder límite
|
||||||
std::array<int, NAME_SIZE> character_index_; // Índices a "character_list_"
|
std::array<int, NAME_SIZE> character_index_; // Índices a "character_list_"
|
||||||
|
|
||||||
void updateNameFromCharacterIndex(); // Actualiza "name_" según "character_index_"
|
void updateNameFromCharacterIndex(); // Actualiza "name_" según "character_index_"
|
||||||
void initCharacterIndex(const std::string &name); // Inicializa índices desde el nombre
|
void initCharacterIndex(const std::string &name); // Inicializa índices desde el nombre
|
||||||
int findIndex(char character) const; // Busca el índice de un carácter en "character_list_"
|
int findIndex(char character) const; // Busca el índice de un carácter en "character_list_"
|
||||||
static std::string getRandomName(); // Devuelve un nombre al azar
|
static std::string getRandomName(); // Devuelve un nombre al azar
|
||||||
};
|
};
|
||||||
+15
-28
@@ -1,14 +1,12 @@
|
|||||||
#include "explosions.h"
|
#include "explosions.h"
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
|
|
||||||
class Texture; // lines 4-4
|
class Texture; // lines 4-4
|
||||||
|
|
||||||
// Actualiza la lógica de la clase
|
// Actualiza la lógica de la clase
|
||||||
void Explosions::update()
|
void Explosions::update() {
|
||||||
{
|
for (auto &explosion : explosions_) {
|
||||||
for (auto &explosion : explosions_)
|
|
||||||
{
|
|
||||||
explosion->update();
|
explosion->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,37 +15,29 @@ void Explosions::update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja el objeto en pantalla
|
// Dibuja el objeto en pantalla
|
||||||
void Explosions::render()
|
void Explosions::render() {
|
||||||
{
|
for (auto &explosion : explosions_) {
|
||||||
for (auto &explosion : explosions_)
|
|
||||||
{
|
|
||||||
explosion->render();
|
explosion->render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Añade texturas al objeto
|
// Añade texturas al objeto
|
||||||
void Explosions::addTexture(int size, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
|
void Explosions::addTexture(int size, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation) {
|
||||||
{
|
|
||||||
textures_.emplace_back(ExplosionTexture(size, texture, animation));
|
textures_.emplace_back(ExplosionTexture(size, texture, animation));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Añade una explosión
|
// Añade una explosión
|
||||||
void Explosions::add(int x, int y, int size)
|
void Explosions::add(int x, int y, int size) {
|
||||||
{
|
|
||||||
const auto INDEX = getIndexBySize(size);
|
const auto INDEX = getIndexBySize(size);
|
||||||
explosions_.emplace_back(std::make_unique<AnimatedSprite>(textures_[INDEX].texture, textures_[INDEX].animation));
|
explosions_.emplace_back(std::make_unique<AnimatedSprite>(textures_[INDEX].texture, textures_[INDEX].animation));
|
||||||
explosions_.back()->setPos(x, y);
|
explosions_.back()->setPos(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vacia el vector de elementos finalizados
|
// Vacia el vector de elementos finalizados
|
||||||
void Explosions::freeExplosions()
|
void Explosions::freeExplosions() {
|
||||||
{
|
if (explosions_.empty() == false) {
|
||||||
if (explosions_.empty() == false)
|
for (int i = explosions_.size() - 1; i >= 0; --i) {
|
||||||
{
|
if (explosions_[i]->animationIsCompleted()) {
|
||||||
for (int i = explosions_.size() - 1; i >= 0; --i)
|
|
||||||
{
|
|
||||||
if (explosions_[i]->animationIsCompleted())
|
|
||||||
{
|
|
||||||
explosions_.erase(explosions_.begin() + i);
|
explosions_.erase(explosions_.begin() + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,12 +45,9 @@ void Explosions::freeExplosions()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Busca una textura a partir del tamaño
|
// Busca una textura a partir del tamaño
|
||||||
int Explosions::getIndexBySize(int size)
|
int Explosions::getIndexBySize(int size) {
|
||||||
{
|
for (int i = 0; i < (int)textures_.size(); ++i) {
|
||||||
for (int i = 0; i < (int)textures_.size(); ++i)
|
if (size == textures_[i].size) {
|
||||||
{
|
|
||||||
if (size == textures_[i].size)
|
|
||||||
{
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-13
@@ -1,28 +1,26 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory> // Para unique_ptr, shared_ptr
|
#include <memory> // Para unique_ptr, shared_ptr
|
||||||
#include <string> // Para string
|
#include <string> // Para string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Estructura para almacenar la información de una textura de explosión
|
// Estructura para almacenar la información de una textura de explosión
|
||||||
struct ExplosionTexture
|
struct ExplosionTexture {
|
||||||
{
|
int size; // Tamaño de la explosión
|
||||||
int size; // Tamaño de la explosión
|
std::shared_ptr<Texture> texture; // Textura para la explosión
|
||||||
std::shared_ptr<Texture> texture; // Textura para la explosión
|
std::vector<std::string> animation; // Animación para la textura
|
||||||
std::vector<std::string> animation; // Animación para la textura
|
|
||||||
|
|
||||||
ExplosionTexture(int sz, std::shared_ptr<Texture> tex, const std::vector<std::string> &anim)
|
ExplosionTexture(int sz, std::shared_ptr<Texture> tex, const std::vector<std::string> &anim)
|
||||||
: size(sz), texture(tex), animation(anim) {}
|
: size(sz), texture(tex), animation(anim) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clase Explosions
|
// Clase Explosions
|
||||||
class Explosions
|
class Explosions {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// Constructor y destructor
|
// Constructor y destructor
|
||||||
Explosions() = default;
|
Explosions() = default;
|
||||||
~Explosions() = default;
|
~Explosions() = default;
|
||||||
@@ -39,7 +37,7 @@ public:
|
|||||||
// Añade una explosión
|
// Añade una explosión
|
||||||
void add(int x, int y, int size);
|
void add(int x, int y, int size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Vector con las texturas a utilizar
|
// Vector con las texturas a utilizar
|
||||||
std::vector<ExplosionTexture> textures_;
|
std::vector<ExplosionTexture> textures_;
|
||||||
|
|
||||||
|
|||||||
Vendored
+199
-243
@@ -1,249 +1,214 @@
|
|||||||
#include "gif.h"
|
#include "gif.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_LogError, SDL_LogCategory, SDL_LogInfo
|
#include <SDL3/SDL.h> // Para SDL_LogError, SDL_LogCategory, SDL_LogInfo
|
||||||
|
|
||||||
#include <cstring> // Para memcpy, size_t
|
#include <cstring> // Para memcpy, size_t
|
||||||
#include <stdexcept> // Para runtime_error
|
#include <stdexcept> // Para runtime_error
|
||||||
#include <string> // Para char_traits, operator==, basic_string, string
|
#include <string> // Para char_traits, operator==, basic_string, string
|
||||||
|
|
||||||
namespace GIF
|
namespace GIF {
|
||||||
{
|
inline void readBytes(const uint8_t *&buffer, void *dst, size_t size) {
|
||||||
inline void readBytes(const uint8_t *&buffer, void *dst, size_t size)
|
std::memcpy(dst, buffer, size);
|
||||||
{
|
buffer += size;
|
||||||
std::memcpy(dst, buffer, size);
|
}
|
||||||
buffer += size;
|
|
||||||
|
void Gif::decompress(int code_length, const uint8_t *input, int input_length, uint8_t *out) {
|
||||||
|
if (code_length < 2 || code_length > 12) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid LZW code length: %d", code_length);
|
||||||
|
throw std::runtime_error("Invalid LZW code length");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gif::decompress(int code_length, const uint8_t *input, int input_length, uint8_t *out)
|
int i, bit;
|
||||||
{
|
int prev = -1;
|
||||||
if (code_length < 2 || code_length > 12)
|
std::vector<DictionaryEntry> dictionary;
|
||||||
{
|
int dictionary_ind;
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid LZW code length: %d", code_length);
|
unsigned int mask = 0x01;
|
||||||
throw std::runtime_error("Invalid LZW code length");
|
int reset_code_length = code_length;
|
||||||
|
int clear_code = 1 << code_length;
|
||||||
|
int stop_code = clear_code + 1;
|
||||||
|
int match_len = 0;
|
||||||
|
|
||||||
|
dictionary.resize(1 << (code_length + 1));
|
||||||
|
for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++) {
|
||||||
|
dictionary[dictionary_ind].byte = static_cast<uint8_t>(dictionary_ind);
|
||||||
|
dictionary[dictionary_ind].prev = -1;
|
||||||
|
dictionary[dictionary_ind].len = 1;
|
||||||
|
}
|
||||||
|
dictionary_ind += 2;
|
||||||
|
|
||||||
|
while (input_length > 0) {
|
||||||
|
int code = 0;
|
||||||
|
for (i = 0; i < (code_length + 1); i++) {
|
||||||
|
if (input_length <= 0) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unexpected end of input in decompress");
|
||||||
|
throw std::runtime_error("Unexpected end of input in decompress");
|
||||||
|
}
|
||||||
|
bit = ((*input & mask) != 0) ? 1 : 0;
|
||||||
|
mask <<= 1;
|
||||||
|
if (mask == 0x100) {
|
||||||
|
mask = 0x01;
|
||||||
|
input++;
|
||||||
|
input_length--;
|
||||||
|
}
|
||||||
|
code |= (bit << i);
|
||||||
}
|
}
|
||||||
|
|
||||||
int i, bit;
|
if (code == clear_code) {
|
||||||
int prev = -1;
|
code_length = reset_code_length;
|
||||||
std::vector<DictionaryEntry> dictionary;
|
dictionary.resize(1 << (code_length + 1));
|
||||||
int dictionary_ind;
|
for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++) {
|
||||||
unsigned int mask = 0x01;
|
dictionary[dictionary_ind].byte = static_cast<uint8_t>(dictionary_ind);
|
||||||
int reset_code_length = code_length;
|
dictionary[dictionary_ind].prev = -1;
|
||||||
int clear_code = 1 << code_length;
|
dictionary[dictionary_ind].len = 1;
|
||||||
int stop_code = clear_code + 1;
|
}
|
||||||
int match_len = 0;
|
dictionary_ind += 2;
|
||||||
|
prev = -1;
|
||||||
dictionary.resize(1 << (code_length + 1));
|
continue;
|
||||||
for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++)
|
} else if (code == stop_code) {
|
||||||
{
|
break;
|
||||||
dictionary[dictionary_ind].byte = static_cast<uint8_t>(dictionary_ind);
|
|
||||||
dictionary[dictionary_ind].prev = -1;
|
|
||||||
dictionary[dictionary_ind].len = 1;
|
|
||||||
}
|
}
|
||||||
dictionary_ind += 2;
|
|
||||||
|
|
||||||
while (input_length > 0)
|
if (prev > -1 && code_length < 12) {
|
||||||
{
|
if (code > dictionary_ind) {
|
||||||
int code = 0;
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "LZW error: code (%d) exceeds dictionary_ind (%d)", code, dictionary_ind);
|
||||||
for (i = 0; i < (code_length + 1); i++)
|
throw std::runtime_error("LZW error: code exceeds dictionary_ind.");
|
||||||
{
|
|
||||||
if (input_length <= 0)
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unexpected end of input in decompress");
|
|
||||||
throw std::runtime_error("Unexpected end of input in decompress");
|
|
||||||
}
|
|
||||||
bit = ((*input & mask) != 0) ? 1 : 0;
|
|
||||||
mask <<= 1;
|
|
||||||
if (mask == 0x100)
|
|
||||||
{
|
|
||||||
mask = 0x01;
|
|
||||||
input++;
|
|
||||||
input_length--;
|
|
||||||
}
|
|
||||||
code |= (bit << i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code == clear_code)
|
int ptr;
|
||||||
{
|
if (code == dictionary_ind) {
|
||||||
code_length = reset_code_length;
|
ptr = prev;
|
||||||
|
while (dictionary[ptr].prev != -1)
|
||||||
|
ptr = dictionary[ptr].prev;
|
||||||
|
dictionary[dictionary_ind].byte = dictionary[ptr].byte;
|
||||||
|
} else {
|
||||||
|
ptr = code;
|
||||||
|
while (dictionary[ptr].prev != -1)
|
||||||
|
ptr = dictionary[ptr].prev;
|
||||||
|
dictionary[dictionary_ind].byte = dictionary[ptr].byte;
|
||||||
|
}
|
||||||
|
dictionary[dictionary_ind].prev = prev;
|
||||||
|
dictionary[dictionary_ind].len = dictionary[prev].len + 1;
|
||||||
|
dictionary_ind++;
|
||||||
|
|
||||||
|
if ((dictionary_ind == (1 << (code_length + 1))) && (code_length < 11)) {
|
||||||
|
code_length++;
|
||||||
dictionary.resize(1 << (code_length + 1));
|
dictionary.resize(1 << (code_length + 1));
|
||||||
for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++)
|
|
||||||
{
|
|
||||||
dictionary[dictionary_ind].byte = static_cast<uint8_t>(dictionary_ind);
|
|
||||||
dictionary[dictionary_ind].prev = -1;
|
|
||||||
dictionary[dictionary_ind].len = 1;
|
|
||||||
}
|
|
||||||
dictionary_ind += 2;
|
|
||||||
prev = -1;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
else if (code == stop_code)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prev > -1 && code_length < 12)
|
|
||||||
{
|
|
||||||
if (code > dictionary_ind)
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "LZW error: code (%d) exceeds dictionary_ind (%d)", code, dictionary_ind);
|
|
||||||
throw std::runtime_error("LZW error: code exceeds dictionary_ind.");
|
|
||||||
}
|
|
||||||
|
|
||||||
int ptr;
|
|
||||||
if (code == dictionary_ind)
|
|
||||||
{
|
|
||||||
ptr = prev;
|
|
||||||
while (dictionary[ptr].prev != -1)
|
|
||||||
ptr = dictionary[ptr].prev;
|
|
||||||
dictionary[dictionary_ind].byte = dictionary[ptr].byte;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ptr = code;
|
|
||||||
while (dictionary[ptr].prev != -1)
|
|
||||||
ptr = dictionary[ptr].prev;
|
|
||||||
dictionary[dictionary_ind].byte = dictionary[ptr].byte;
|
|
||||||
}
|
|
||||||
dictionary[dictionary_ind].prev = prev;
|
|
||||||
dictionary[dictionary_ind].len = dictionary[prev].len + 1;
|
|
||||||
dictionary_ind++;
|
|
||||||
|
|
||||||
if ((dictionary_ind == (1 << (code_length + 1))) && (code_length < 11))
|
|
||||||
{
|
|
||||||
code_length++;
|
|
||||||
dictionary.resize(1 << (code_length + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prev = code;
|
|
||||||
|
|
||||||
if (code < 0 || static_cast<size_t>(code) >= dictionary.size())
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid LZW code %d, dictionary size %lu", code, static_cast<unsigned long>(dictionary.size()));
|
|
||||||
throw std::runtime_error("LZW error: invalid code encountered");
|
|
||||||
}
|
|
||||||
|
|
||||||
int curCode = code;
|
|
||||||
match_len = dictionary[curCode].len;
|
|
||||||
while (curCode != -1)
|
|
||||||
{
|
|
||||||
out[dictionary[curCode].len - 1] = dictionary[curCode].byte;
|
|
||||||
if (dictionary[curCode].prev == curCode)
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Internal error; self-reference detected.");
|
|
||||||
throw std::runtime_error("Internal error in decompress: self-reference");
|
|
||||||
}
|
|
||||||
curCode = dictionary[curCode].prev;
|
|
||||||
}
|
|
||||||
out += match_len;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint8_t> Gif::readSubBlocks(const uint8_t *&buffer)
|
prev = code;
|
||||||
{
|
|
||||||
std::vector<uint8_t> data;
|
if (code < 0 || static_cast<size_t>(code) >= dictionary.size()) {
|
||||||
uint8_t block_size = *buffer;
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid LZW code %d, dictionary size %lu", code, static_cast<unsigned long>(dictionary.size()));
|
||||||
|
throw std::runtime_error("LZW error: invalid code encountered");
|
||||||
|
}
|
||||||
|
|
||||||
|
int curCode = code;
|
||||||
|
match_len = dictionary[curCode].len;
|
||||||
|
while (curCode != -1) {
|
||||||
|
out[dictionary[curCode].len - 1] = dictionary[curCode].byte;
|
||||||
|
if (dictionary[curCode].prev == curCode) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Internal error; self-reference detected.");
|
||||||
|
throw std::runtime_error("Internal error in decompress: self-reference");
|
||||||
|
}
|
||||||
|
curCode = dictionary[curCode].prev;
|
||||||
|
}
|
||||||
|
out += match_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> Gif::readSubBlocks(const uint8_t *&buffer) {
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
uint8_t block_size = *buffer;
|
||||||
|
buffer++;
|
||||||
|
while (block_size != 0) {
|
||||||
|
data.insert(data.end(), buffer, buffer + block_size);
|
||||||
|
buffer += block_size;
|
||||||
|
block_size = *buffer;
|
||||||
buffer++;
|
buffer++;
|
||||||
while (block_size != 0)
|
}
|
||||||
{
|
return data;
|
||||||
data.insert(data.end(), buffer, buffer + block_size);
|
}
|
||||||
buffer += block_size;
|
|
||||||
block_size = *buffer;
|
std::vector<uint8_t> Gif::processImageDescriptor(const uint8_t *&buffer, const std::vector<RGB> &gct, int resolution_bits) {
|
||||||
buffer++;
|
ImageDescriptor image_descriptor;
|
||||||
|
readBytes(buffer, &image_descriptor, sizeof(ImageDescriptor));
|
||||||
|
|
||||||
|
uint8_t lzw_code_size;
|
||||||
|
readBytes(buffer, &lzw_code_size, sizeof(uint8_t));
|
||||||
|
|
||||||
|
std::vector<uint8_t> compressed_data = readSubBlocks(buffer);
|
||||||
|
int uncompressed_data_length = image_descriptor.image_width * image_descriptor.image_height;
|
||||||
|
std::vector<uint8_t> uncompressed_data(uncompressed_data_length);
|
||||||
|
|
||||||
|
decompress(lzw_code_size, compressed_data.data(), static_cast<int>(compressed_data.size()), uncompressed_data.data());
|
||||||
|
return uncompressed_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> Gif::loadPalette(const uint8_t *buffer) {
|
||||||
|
uint8_t header[6];
|
||||||
|
std::memcpy(header, buffer, 6);
|
||||||
|
buffer += 6;
|
||||||
|
|
||||||
|
ScreenDescriptor screen_descriptor;
|
||||||
|
std::memcpy(&screen_descriptor, buffer, sizeof(ScreenDescriptor));
|
||||||
|
buffer += sizeof(ScreenDescriptor);
|
||||||
|
|
||||||
|
std::vector<uint32_t> global_color_table;
|
||||||
|
if (screen_descriptor.fields & 0x80) {
|
||||||
|
int global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1));
|
||||||
|
global_color_table.resize(global_color_table_size);
|
||||||
|
for (int i = 0; i < global_color_table_size; ++i) {
|
||||||
|
uint8_t r = buffer[0];
|
||||||
|
uint8_t g = buffer[1];
|
||||||
|
uint8_t b = buffer[2];
|
||||||
|
global_color_table[i] = (r << 16) | (g << 8) | b;
|
||||||
|
buffer += 3;
|
||||||
}
|
}
|
||||||
return data;
|
}
|
||||||
|
return global_color_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> Gif::processGifStream(const uint8_t *buffer, uint16_t &w, uint16_t &h) {
|
||||||
|
uint8_t header[6];
|
||||||
|
std::memcpy(header, buffer, 6);
|
||||||
|
buffer += 6;
|
||||||
|
|
||||||
|
std::string headerStr(reinterpret_cast<char *>(header), 6);
|
||||||
|
if (headerStr != "GIF87a" && headerStr != "GIF89a") {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Formato de archivo GIF inválido: %s", headerStr.c_str());
|
||||||
|
throw std::runtime_error("Formato de archivo GIF inválido.");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> Gif::processImageDescriptor(const uint8_t *&buffer, const std::vector<RGB> &gct, int resolution_bits)
|
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "Procesando GIF con cabecera: %s", headerStr.c_str());
|
||||||
{
|
|
||||||
ImageDescriptor image_descriptor;
|
|
||||||
readBytes(buffer, &image_descriptor, sizeof(ImageDescriptor));
|
|
||||||
|
|
||||||
uint8_t lzw_code_size;
|
ScreenDescriptor screen_descriptor;
|
||||||
readBytes(buffer, &lzw_code_size, sizeof(uint8_t));
|
readBytes(buffer, &screen_descriptor, sizeof(ScreenDescriptor));
|
||||||
|
|
||||||
std::vector<uint8_t> compressed_data = readSubBlocks(buffer);
|
w = screen_descriptor.width;
|
||||||
int uncompressed_data_length = image_descriptor.image_width * image_descriptor.image_height;
|
h = screen_descriptor.height;
|
||||||
std::vector<uint8_t> uncompressed_data(uncompressed_data_length);
|
|
||||||
|
|
||||||
decompress(lzw_code_size, compressed_data.data(), static_cast<int>(compressed_data.size()), uncompressed_data.data());
|
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "Resolución del GIF: %dx%d", w, h);
|
||||||
return uncompressed_data;
|
|
||||||
|
int color_resolution_bits = ((screen_descriptor.fields & 0x70) >> 4) + 1;
|
||||||
|
std::vector<RGB> global_color_table;
|
||||||
|
if (screen_descriptor.fields & 0x80) {
|
||||||
|
int global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1));
|
||||||
|
global_color_table.resize(global_color_table_size);
|
||||||
|
std::memcpy(global_color_table.data(), buffer, 3 * global_color_table_size);
|
||||||
|
buffer += 3 * global_color_table_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> Gif::loadPalette(const uint8_t *buffer)
|
uint8_t block_type = *buffer++;
|
||||||
{
|
while (block_type != TRAILER) {
|
||||||
uint8_t header[6];
|
if (block_type == EXTENSION_INTRODUCER) {
|
||||||
std::memcpy(header, buffer, 6);
|
uint8_t extension_label = *buffer++;
|
||||||
buffer += 6;
|
switch (extension_label) {
|
||||||
|
case GRAPHIC_CONTROL: {
|
||||||
ScreenDescriptor screen_descriptor;
|
|
||||||
std::memcpy(&screen_descriptor, buffer, sizeof(ScreenDescriptor));
|
|
||||||
buffer += sizeof(ScreenDescriptor);
|
|
||||||
|
|
||||||
std::vector<uint32_t> global_color_table;
|
|
||||||
if (screen_descriptor.fields & 0x80)
|
|
||||||
{
|
|
||||||
int global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1));
|
|
||||||
global_color_table.resize(global_color_table_size);
|
|
||||||
for (int i = 0; i < global_color_table_size; ++i)
|
|
||||||
{
|
|
||||||
uint8_t r = buffer[0];
|
|
||||||
uint8_t g = buffer[1];
|
|
||||||
uint8_t b = buffer[2];
|
|
||||||
global_color_table[i] = (r << 16) | (g << 8) | b;
|
|
||||||
buffer += 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return global_color_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint8_t> Gif::processGifStream(const uint8_t *buffer, uint16_t &w, uint16_t &h)
|
|
||||||
{
|
|
||||||
uint8_t header[6];
|
|
||||||
std::memcpy(header, buffer, 6);
|
|
||||||
buffer += 6;
|
|
||||||
|
|
||||||
std::string headerStr(reinterpret_cast<char *>(header), 6);
|
|
||||||
if (headerStr != "GIF87a" && headerStr != "GIF89a")
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Formato de archivo GIF inválido: %s", headerStr.c_str());
|
|
||||||
throw std::runtime_error("Formato de archivo GIF inválido.");
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "Procesando GIF con cabecera: %s", headerStr.c_str());
|
|
||||||
|
|
||||||
ScreenDescriptor screen_descriptor;
|
|
||||||
readBytes(buffer, &screen_descriptor, sizeof(ScreenDescriptor));
|
|
||||||
|
|
||||||
w = screen_descriptor.width;
|
|
||||||
h = screen_descriptor.height;
|
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "Resolución del GIF: %dx%d", w, h);
|
|
||||||
|
|
||||||
int color_resolution_bits = ((screen_descriptor.fields & 0x70) >> 4) + 1;
|
|
||||||
std::vector<RGB> global_color_table;
|
|
||||||
if (screen_descriptor.fields & 0x80)
|
|
||||||
{
|
|
||||||
int global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1));
|
|
||||||
global_color_table.resize(global_color_table_size);
|
|
||||||
std::memcpy(global_color_table.data(), buffer, 3 * global_color_table_size);
|
|
||||||
buffer += 3 * global_color_table_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t block_type = *buffer++;
|
|
||||||
while (block_type != TRAILER)
|
|
||||||
{
|
|
||||||
if (block_type == EXTENSION_INTRODUCER)
|
|
||||||
{
|
|
||||||
uint8_t extension_label = *buffer++;
|
|
||||||
switch (extension_label)
|
|
||||||
{
|
|
||||||
case GRAPHIC_CONTROL:
|
|
||||||
{
|
|
||||||
uint8_t blockSize = *buffer++;
|
uint8_t blockSize = *buffer++;
|
||||||
buffer += blockSize;
|
buffer += blockSize;
|
||||||
uint8_t subBlockSize = *buffer++;
|
uint8_t subBlockSize = *buffer++;
|
||||||
while (subBlockSize != 0)
|
while (subBlockSize != 0) {
|
||||||
{
|
|
||||||
buffer += subBlockSize;
|
buffer += subBlockSize;
|
||||||
subBlockSize = *buffer++;
|
subBlockSize = *buffer++;
|
||||||
}
|
}
|
||||||
@@ -251,51 +216,42 @@ namespace GIF
|
|||||||
}
|
}
|
||||||
case APPLICATION_EXTENSION:
|
case APPLICATION_EXTENSION:
|
||||||
case COMMENT_EXTENSION:
|
case COMMENT_EXTENSION:
|
||||||
case PLAINTEXT_EXTENSION:
|
case PLAINTEXT_EXTENSION: {
|
||||||
{
|
|
||||||
uint8_t blockSize = *buffer++;
|
uint8_t blockSize = *buffer++;
|
||||||
buffer += blockSize;
|
buffer += blockSize;
|
||||||
uint8_t subBlockSize = *buffer++;
|
uint8_t subBlockSize = *buffer++;
|
||||||
while (subBlockSize != 0)
|
while (subBlockSize != 0) {
|
||||||
{
|
|
||||||
buffer += subBlockSize;
|
buffer += subBlockSize;
|
||||||
subBlockSize = *buffer++;
|
subBlockSize = *buffer++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default: {
|
||||||
{
|
|
||||||
uint8_t blockSize = *buffer++;
|
uint8_t blockSize = *buffer++;
|
||||||
buffer += blockSize;
|
buffer += blockSize;
|
||||||
uint8_t subBlockSize = *buffer++;
|
uint8_t subBlockSize = *buffer++;
|
||||||
while (subBlockSize != 0)
|
while (subBlockSize != 0) {
|
||||||
{
|
|
||||||
buffer += subBlockSize;
|
buffer += subBlockSize;
|
||||||
subBlockSize = *buffer++;
|
subBlockSize = *buffer++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (block_type == IMAGE_DESCRIPTOR)
|
} else if (block_type == IMAGE_DESCRIPTOR) {
|
||||||
{
|
return processImageDescriptor(buffer, global_color_table, color_resolution_bits);
|
||||||
return processImageDescriptor(buffer, global_color_table, color_resolution_bits);
|
} else {
|
||||||
}
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Unrecognized block type: 0x%X", block_type);
|
||||||
else
|
return std::vector<uint8_t>{};
|
||||||
{
|
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Unrecognized block type: 0x%X", block_type);
|
|
||||||
return std::vector<uint8_t>{};
|
|
||||||
}
|
|
||||||
block_type = *buffer++;
|
|
||||||
}
|
}
|
||||||
|
block_type = *buffer++;
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "GIF procesado correctamente.");
|
|
||||||
return std::vector<uint8_t>{};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> Gif::loadGif(const uint8_t *buffer, uint16_t &w, uint16_t &h)
|
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "GIF procesado correctamente.");
|
||||||
{
|
return std::vector<uint8_t>{};
|
||||||
return processGifStream(buffer, w, h);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace GIF
|
std::vector<uint8_t> Gif::loadGif(const uint8_t *buffer, uint16_t &w, uint16_t &h) {
|
||||||
|
return processGifStream(buffer, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace GIF
|
||||||
Vendored
+71
-81
@@ -1,102 +1,92 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint> // Para uint8_t, uint16_t, uint32_t
|
#include <cstdint> // Para uint8_t, uint16_t, uint32_t
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
namespace GIF
|
namespace GIF {
|
||||||
{
|
|
||||||
|
|
||||||
// Constantes definidas con constexpr, en lugar de macros
|
// Constantes definidas con constexpr, en lugar de macros
|
||||||
constexpr uint8_t EXTENSION_INTRODUCER = 0x21;
|
constexpr uint8_t EXTENSION_INTRODUCER = 0x21;
|
||||||
constexpr uint8_t IMAGE_DESCRIPTOR = 0x2C;
|
constexpr uint8_t IMAGE_DESCRIPTOR = 0x2C;
|
||||||
constexpr uint8_t TRAILER = 0x3B;
|
constexpr uint8_t TRAILER = 0x3B;
|
||||||
constexpr uint8_t GRAPHIC_CONTROL = 0xF9;
|
constexpr uint8_t GRAPHIC_CONTROL = 0xF9;
|
||||||
constexpr uint8_t APPLICATION_EXTENSION = 0xFF;
|
constexpr uint8_t APPLICATION_EXTENSION = 0xFF;
|
||||||
constexpr uint8_t COMMENT_EXTENSION = 0xFE;
|
constexpr uint8_t COMMENT_EXTENSION = 0xFE;
|
||||||
constexpr uint8_t PLAINTEXT_EXTENSION = 0x01;
|
constexpr uint8_t PLAINTEXT_EXTENSION = 0x01;
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct ScreenDescriptor
|
struct ScreenDescriptor {
|
||||||
{
|
uint16_t width;
|
||||||
uint16_t width;
|
uint16_t height;
|
||||||
uint16_t height;
|
uint8_t fields;
|
||||||
uint8_t fields;
|
uint8_t background_color_index;
|
||||||
uint8_t background_color_index;
|
uint8_t pixel_aspect_ratio;
|
||||||
uint8_t pixel_aspect_ratio;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
struct RGB
|
struct RGB {
|
||||||
{
|
uint8_t r, g, b;
|
||||||
uint8_t r, g, b;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
struct ImageDescriptor
|
struct ImageDescriptor {
|
||||||
{
|
uint16_t image_left_position;
|
||||||
uint16_t image_left_position;
|
uint16_t image_top_position;
|
||||||
uint16_t image_top_position;
|
uint16_t image_width;
|
||||||
uint16_t image_width;
|
uint16_t image_height;
|
||||||
uint16_t image_height;
|
uint8_t fields;
|
||||||
uint8_t fields;
|
};
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
struct DictionaryEntry
|
struct DictionaryEntry {
|
||||||
{
|
uint8_t byte;
|
||||||
uint8_t byte;
|
int prev;
|
||||||
int prev;
|
int len;
|
||||||
int len;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
struct Extension
|
struct Extension {
|
||||||
{
|
uint8_t extension_code;
|
||||||
uint8_t extension_code;
|
uint8_t block_size;
|
||||||
uint8_t block_size;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
struct GraphicControlExtension
|
struct GraphicControlExtension {
|
||||||
{
|
uint8_t fields;
|
||||||
uint8_t fields;
|
uint16_t delay_time;
|
||||||
uint16_t delay_time;
|
uint8_t transparent_color_index;
|
||||||
uint8_t transparent_color_index;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
struct ApplicationExtension
|
struct ApplicationExtension {
|
||||||
{
|
uint8_t application_id[8];
|
||||||
uint8_t application_id[8];
|
uint8_t version[3];
|
||||||
uint8_t version[3];
|
};
|
||||||
};
|
|
||||||
|
|
||||||
struct PlaintextExtension
|
struct PlaintextExtension {
|
||||||
{
|
uint16_t left, top, width, height;
|
||||||
uint16_t left, top, width, height;
|
uint8_t cell_width, cell_height;
|
||||||
uint8_t cell_width, cell_height;
|
uint8_t foreground_color, background_color;
|
||||||
uint8_t foreground_color, background_color;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
class Gif
|
class Gif {
|
||||||
{
|
public:
|
||||||
public:
|
// Descompone (uncompress) el bloque comprimido usando LZW.
|
||||||
// Descompone (uncompress) el bloque comprimido usando LZW.
|
// Este método puede lanzar std::runtime_error en caso de error.
|
||||||
// Este método puede lanzar std::runtime_error en caso de error.
|
void decompress(int code_length, const uint8_t *input, int input_length, uint8_t *out);
|
||||||
void decompress(int code_length, const uint8_t *input, int input_length, uint8_t *out);
|
|
||||||
|
|
||||||
// Carga la paleta (global color table) a partir de un buffer,
|
// Carga la paleta (global color table) a partir de un buffer,
|
||||||
// retornándola en un vector de uint32_t (cada color se compone de R, G, B).
|
// retornándola en un vector de uint32_t (cada color se compone de R, G, B).
|
||||||
std::vector<uint32_t> loadPalette(const uint8_t *buffer);
|
std::vector<uint32_t> loadPalette(const uint8_t *buffer);
|
||||||
|
|
||||||
// Carga el stream GIF; devuelve un vector con los datos de imagen sin comprimir y
|
// Carga el stream GIF; devuelve un vector con los datos de imagen sin comprimir y
|
||||||
// asigna el ancho y alto mediante referencias.
|
// asigna el ancho y alto mediante referencias.
|
||||||
std::vector<uint8_t> loadGif(const uint8_t *buffer, uint16_t &w, uint16_t &h);
|
std::vector<uint8_t> loadGif(const uint8_t *buffer, uint16_t &w, uint16_t &h);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Lee los sub-bloques de datos y los acumula en un std::vector<uint8_t>.
|
// Lee los sub-bloques de datos y los acumula en un std::vector<uint8_t>.
|
||||||
std::vector<uint8_t> readSubBlocks(const uint8_t *&buffer);
|
std::vector<uint8_t> readSubBlocks(const uint8_t *&buffer);
|
||||||
|
|
||||||
// Procesa el Image Descriptor y retorna el vector de datos sin comprimir.
|
// Procesa el Image Descriptor y retorna el vector de datos sin comprimir.
|
||||||
std::vector<uint8_t> processImageDescriptor(const uint8_t *&buffer, const std::vector<RGB> &gct, int resolution_bits);
|
std::vector<uint8_t> processImageDescriptor(const uint8_t *&buffer, const std::vector<RGB> &gct, int resolution_bits);
|
||||||
|
|
||||||
// Procesa el stream completo del GIF y devuelve los datos sin comprimir.
|
// Procesa el stream completo del GIF y devuelve los datos sin comprimir.
|
||||||
std::vector<uint8_t> processGifStream(const uint8_t *buffer, uint16_t &w, uint16_t &h);
|
std::vector<uint8_t> processGifStream(const uint8_t *buffer, uint16_t &w, uint16_t &h);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace GIF
|
} // namespace GIF
|
||||||
Vendored
+66
-132
@@ -1,26 +1,24 @@
|
|||||||
#ifndef JA_USESDLMIXER
|
#ifndef JA_USESDLMIXER
|
||||||
#include "jail_audio.h"
|
#include "jail_audio.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_AudioFormat, SDL_BindAudioStream, SDL_Se...
|
#include <SDL3/SDL.h> // Para SDL_AudioFormat, SDL_BindAudioStream, SDL_Se...
|
||||||
#include <stdint.h> // Para uint32_t, uint8_t
|
#include <stdint.h> // Para uint32_t, uint8_t
|
||||||
#include <stdio.h> // Para NULL, fseek, printf, fclose, fopen, fread
|
#include <stdio.h> // Para NULL, fseek, printf, fclose, fopen, fread
|
||||||
#include <stdlib.h> // Para free, malloc
|
#include <stdlib.h> // Para free, malloc
|
||||||
#include <string.h> // Para strcpy, strlen
|
#include <string.h> // Para strcpy, strlen
|
||||||
|
|
||||||
#include "stb_vorbis.h" // Para stb_vorbis_decode_memory
|
#include "stb_vorbis.h" // Para stb_vorbis_decode_memory
|
||||||
|
|
||||||
#define JA_MAX_SIMULTANEOUS_CHANNELS 20
|
#define JA_MAX_SIMULTANEOUS_CHANNELS 20
|
||||||
#define JA_MAX_GROUPS 2
|
#define JA_MAX_GROUPS 2
|
||||||
|
|
||||||
struct JA_Sound_t
|
struct JA_Sound_t {
|
||||||
{
|
|
||||||
SDL_AudioSpec spec{SDL_AUDIO_S16, 2, 48000};
|
SDL_AudioSpec spec{SDL_AUDIO_S16, 2, 48000};
|
||||||
Uint32 length{0};
|
Uint32 length{0};
|
||||||
Uint8 *buffer{NULL};
|
Uint8 *buffer{NULL};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct JA_Channel_t
|
struct JA_Channel_t {
|
||||||
{
|
|
||||||
JA_Sound_t *sound{nullptr};
|
JA_Sound_t *sound{nullptr};
|
||||||
int pos{0};
|
int pos{0};
|
||||||
int times{0};
|
int times{0};
|
||||||
@@ -29,8 +27,7 @@ struct JA_Channel_t
|
|||||||
JA_Channel_state state{JA_CHANNEL_FREE};
|
JA_Channel_state state{JA_CHANNEL_FREE};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct JA_Music_t
|
struct JA_Music_t {
|
||||||
{
|
|
||||||
SDL_AudioSpec spec{SDL_AUDIO_S16, 2, 48000};
|
SDL_AudioSpec spec{SDL_AUDIO_S16, 2, 48000};
|
||||||
Uint32 length{0};
|
Uint32 length{0};
|
||||||
Uint8 *buffer{nullptr};
|
Uint8 *buffer{nullptr};
|
||||||
@@ -58,59 +55,43 @@ int fade_start_time;
|
|||||||
int fade_duration;
|
int fade_duration;
|
||||||
int fade_initial_volume;
|
int fade_initial_volume;
|
||||||
|
|
||||||
Uint32 JA_UpdateCallback(void *userdata, SDL_TimerID timerID, Uint32 interval)
|
Uint32 JA_UpdateCallback(void *userdata, SDL_TimerID timerID, Uint32 interval) {
|
||||||
{
|
if (JA_musicEnabled && current_music && current_music->state == JA_MUSIC_PLAYING) {
|
||||||
if (JA_musicEnabled && current_music && current_music->state == JA_MUSIC_PLAYING)
|
if (fading) {
|
||||||
{
|
|
||||||
if (fading)
|
|
||||||
{
|
|
||||||
int time = SDL_GetTicks();
|
int time = SDL_GetTicks();
|
||||||
if (time > (fade_start_time + fade_duration))
|
if (time > (fade_start_time + fade_duration)) {
|
||||||
{
|
|
||||||
fading = false;
|
fading = false;
|
||||||
JA_StopMusic();
|
JA_StopMusic();
|
||||||
return 30;
|
return 30;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
const int time_passed = time - fade_start_time;
|
const int time_passed = time - fade_start_time;
|
||||||
const float percent = (float)time_passed / (float)fade_duration;
|
const float percent = (float)time_passed / (float)fade_duration;
|
||||||
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume * (1.0 - percent));
|
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume * (1.0 - percent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_music->times != 0)
|
if (current_music->times != 0) {
|
||||||
{
|
if ((Uint32)SDL_GetAudioStreamAvailable(current_music->stream) < (current_music->length / 2)) {
|
||||||
if ((Uint32)SDL_GetAudioStreamAvailable(current_music->stream) < (current_music->length / 2))
|
|
||||||
{
|
|
||||||
SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length);
|
SDL_PutAudioStreamData(current_music->stream, current_music->buffer, current_music->length);
|
||||||
}
|
}
|
||||||
if (current_music->times > 0)
|
if (current_music->times > 0)
|
||||||
current_music->times--;
|
current_music->times--;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
if (SDL_GetAudioStreamAvailable(current_music->stream) == 0)
|
if (SDL_GetAudioStreamAvailable(current_music->stream) == 0)
|
||||||
JA_StopMusic();
|
JA_StopMusic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JA_soundEnabled)
|
if (JA_soundEnabled) {
|
||||||
{
|
|
||||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; ++i)
|
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; ++i)
|
||||||
if (channels[i].state == JA_CHANNEL_PLAYING)
|
if (channels[i].state == JA_CHANNEL_PLAYING) {
|
||||||
{
|
if (channels[i].times != 0) {
|
||||||
if (channels[i].times != 0)
|
if ((Uint32)SDL_GetAudioStreamAvailable(channels[i].stream) < (channels[i].sound->length / 2)) {
|
||||||
{
|
|
||||||
if ((Uint32)SDL_GetAudioStreamAvailable(channels[i].stream) < (channels[i].sound->length / 2))
|
|
||||||
{
|
|
||||||
SDL_PutAudioStreamData(channels[i].stream, channels[i].sound->buffer, channels[i].sound->length);
|
SDL_PutAudioStreamData(channels[i].stream, channels[i].sound->buffer, channels[i].sound->length);
|
||||||
if (channels[i].times > 0)
|
if (channels[i].times > 0)
|
||||||
channels[i].times--;
|
channels[i].times--;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
if (SDL_GetAudioStreamAvailable(channels[i].stream) == 0)
|
if (SDL_GetAudioStreamAvailable(channels[i].stream) == 0)
|
||||||
JA_StopChannel(i);
|
JA_StopChannel(i);
|
||||||
}
|
}
|
||||||
@@ -120,8 +101,7 @@ Uint32 JA_UpdateCallback(void *userdata, SDL_TimerID timerID, Uint32 interval)
|
|||||||
return 30;
|
return 30;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_Init(const int freq, const SDL_AudioFormat format, const int num_channels)
|
void JA_Init(const int freq, const SDL_AudioFormat format, const int num_channels) {
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
|
SDL_SetLogPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_DEBUG);
|
||||||
#endif
|
#endif
|
||||||
@@ -140,8 +120,7 @@ void JA_Init(const int freq, const SDL_AudioFormat format, const int num_channel
|
|||||||
JA_timerID = SDL_AddTimer(30, JA_UpdateCallback, nullptr);
|
JA_timerID = SDL_AddTimer(30, JA_UpdateCallback, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_Quit()
|
void JA_Quit() {
|
||||||
{
|
|
||||||
if (JA_timerID)
|
if (JA_timerID)
|
||||||
SDL_RemoveTimer(JA_timerID);
|
SDL_RemoveTimer(JA_timerID);
|
||||||
|
|
||||||
@@ -150,8 +129,7 @@ void JA_Quit()
|
|||||||
sdlAudioDevice = 0;
|
sdlAudioDevice = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
JA_Music_t *JA_LoadMusic(Uint8 *buffer, Uint32 length)
|
JA_Music_t *JA_LoadMusic(Uint8 *buffer, Uint32 length) {
|
||||||
{
|
|
||||||
JA_Music_t *music = new JA_Music_t();
|
JA_Music_t *music = new JA_Music_t();
|
||||||
|
|
||||||
int chan, samplerate;
|
int chan, samplerate;
|
||||||
@@ -170,8 +148,7 @@ JA_Music_t *JA_LoadMusic(Uint8 *buffer, Uint32 length)
|
|||||||
return music;
|
return music;
|
||||||
}
|
}
|
||||||
|
|
||||||
JA_Music_t *JA_LoadMusic(const char *filename)
|
JA_Music_t *JA_LoadMusic(const char *filename) {
|
||||||
{
|
|
||||||
// [RZC 28/08/22] Carreguem primer el arxiu en memòria i després el descomprimim. Es algo més rapid.
|
// [RZC 28/08/22] Carreguem primer el arxiu en memòria i després el descomprimim. Es algo més rapid.
|
||||||
FILE *f = fopen(filename, "rb");
|
FILE *f = fopen(filename, "rb");
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
@@ -191,8 +168,7 @@ JA_Music_t *JA_LoadMusic(const char *filename)
|
|||||||
return music;
|
return music;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_PlayMusic(JA_Music_t *music, const int loop)
|
void JA_PlayMusic(JA_Music_t *music, const int loop) {
|
||||||
{
|
|
||||||
if (!JA_musicEnabled)
|
if (!JA_musicEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -212,15 +188,13 @@ void JA_PlayMusic(JA_Music_t *music, const int loop)
|
|||||||
// SDL_ResumeAudioStreamDevice(current_music->stream);
|
// SDL_ResumeAudioStreamDevice(current_music->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *JA_GetMusicFilename(JA_Music_t *music)
|
char *JA_GetMusicFilename(JA_Music_t *music) {
|
||||||
{
|
|
||||||
if (!music)
|
if (!music)
|
||||||
music = current_music;
|
music = current_music;
|
||||||
return music->filename;
|
return music->filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_PauseMusic()
|
void JA_PauseMusic() {
|
||||||
{
|
|
||||||
if (!JA_musicEnabled)
|
if (!JA_musicEnabled)
|
||||||
return;
|
return;
|
||||||
if (!current_music || current_music->state == JA_MUSIC_INVALID)
|
if (!current_music || current_music->state == JA_MUSIC_INVALID)
|
||||||
@@ -231,8 +205,7 @@ void JA_PauseMusic()
|
|||||||
SDL_UnbindAudioStream(current_music->stream);
|
SDL_UnbindAudioStream(current_music->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_ResumeMusic()
|
void JA_ResumeMusic() {
|
||||||
{
|
|
||||||
if (!JA_musicEnabled)
|
if (!JA_musicEnabled)
|
||||||
return;
|
return;
|
||||||
if (!current_music || current_music->state == JA_MUSIC_INVALID)
|
if (!current_music || current_music->state == JA_MUSIC_INVALID)
|
||||||
@@ -243,8 +216,7 @@ void JA_ResumeMusic()
|
|||||||
SDL_BindAudioStream(sdlAudioDevice, current_music->stream);
|
SDL_BindAudioStream(sdlAudioDevice, current_music->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_StopMusic()
|
void JA_StopMusic() {
|
||||||
{
|
|
||||||
if (!JA_musicEnabled)
|
if (!JA_musicEnabled)
|
||||||
return;
|
return;
|
||||||
if (!current_music || current_music->state == JA_MUSIC_INVALID)
|
if (!current_music || current_music->state == JA_MUSIC_INVALID)
|
||||||
@@ -259,8 +231,7 @@ void JA_StopMusic()
|
|||||||
current_music->filename = nullptr;
|
current_music->filename = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_FadeOutMusic(const int milliseconds)
|
void JA_FadeOutMusic(const int milliseconds) {
|
||||||
{
|
|
||||||
if (!JA_musicEnabled)
|
if (!JA_musicEnabled)
|
||||||
return;
|
return;
|
||||||
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID)
|
if (current_music == NULL || current_music->state == JA_MUSIC_INVALID)
|
||||||
@@ -272,8 +243,7 @@ void JA_FadeOutMusic(const int milliseconds)
|
|||||||
fade_initial_volume = JA_musicVolume;
|
fade_initial_volume = JA_musicVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
JA_Music_state JA_GetMusicState()
|
JA_Music_state JA_GetMusicState() {
|
||||||
{
|
|
||||||
if (!JA_musicEnabled)
|
if (!JA_musicEnabled)
|
||||||
return JA_MUSIC_DISABLED;
|
return JA_MUSIC_DISABLED;
|
||||||
if (!current_music)
|
if (!current_music)
|
||||||
@@ -282,8 +252,7 @@ JA_Music_state JA_GetMusicState()
|
|||||||
return current_music->state;
|
return current_music->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_DeleteMusic(JA_Music_t *music)
|
void JA_DeleteMusic(JA_Music_t *music) {
|
||||||
{
|
|
||||||
if (current_music == music)
|
if (current_music == music)
|
||||||
current_music = nullptr;
|
current_music = nullptr;
|
||||||
SDL_free(music->buffer);
|
SDL_free(music->buffer);
|
||||||
@@ -292,68 +261,59 @@ void JA_DeleteMusic(JA_Music_t *music)
|
|||||||
delete music;
|
delete music;
|
||||||
}
|
}
|
||||||
|
|
||||||
float JA_SetMusicVolume(float volume)
|
float JA_SetMusicVolume(float volume) {
|
||||||
{
|
|
||||||
JA_musicVolume = SDL_clamp(volume, 0.0f, 1.0f);
|
JA_musicVolume = SDL_clamp(volume, 0.0f, 1.0f);
|
||||||
if (current_music)
|
if (current_music)
|
||||||
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume);
|
SDL_SetAudioStreamGain(current_music->stream, JA_musicVolume);
|
||||||
return JA_musicVolume;
|
return JA_musicVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_SetMusicPosition(float value)
|
void JA_SetMusicPosition(float value) {
|
||||||
{
|
|
||||||
if (!current_music)
|
if (!current_music)
|
||||||
return;
|
return;
|
||||||
current_music->pos = value * current_music->spec.freq;
|
current_music->pos = value * current_music->spec.freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
float JA_GetMusicPosition()
|
float JA_GetMusicPosition() {
|
||||||
{
|
|
||||||
if (!current_music)
|
if (!current_music)
|
||||||
return 0;
|
return 0;
|
||||||
return float(current_music->pos) / float(current_music->spec.freq);
|
return float(current_music->pos) / float(current_music->spec.freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_EnableMusic(const bool value)
|
void JA_EnableMusic(const bool value) {
|
||||||
{
|
|
||||||
if (!value && current_music && (current_music->state == JA_MUSIC_PLAYING))
|
if (!value && current_music && (current_music->state == JA_MUSIC_PLAYING))
|
||||||
JA_StopMusic();
|
JA_StopMusic();
|
||||||
|
|
||||||
JA_musicEnabled = value;
|
JA_musicEnabled = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
JA_Sound_t *JA_NewSound(Uint8 *buffer, Uint32 length)
|
JA_Sound_t *JA_NewSound(Uint8 *buffer, Uint32 length) {
|
||||||
{
|
|
||||||
JA_Sound_t *sound = new JA_Sound_t();
|
JA_Sound_t *sound = new JA_Sound_t();
|
||||||
sound->buffer = buffer;
|
sound->buffer = buffer;
|
||||||
sound->length = length;
|
sound->length = length;
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
JA_Sound_t *JA_LoadSound(uint8_t *buffer, uint32_t size)
|
JA_Sound_t *JA_LoadSound(uint8_t *buffer, uint32_t size) {
|
||||||
{
|
|
||||||
JA_Sound_t *sound = new JA_Sound_t();
|
JA_Sound_t *sound = new JA_Sound_t();
|
||||||
SDL_LoadWAV_IO(SDL_IOFromMem(buffer, size), 1, &sound->spec, &sound->buffer, &sound->length);
|
SDL_LoadWAV_IO(SDL_IOFromMem(buffer, size), 1, &sound->spec, &sound->buffer, &sound->length);
|
||||||
|
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
JA_Sound_t *JA_LoadSound(const char *filename)
|
JA_Sound_t *JA_LoadSound(const char *filename) {
|
||||||
{
|
|
||||||
JA_Sound_t *sound = new JA_Sound_t();
|
JA_Sound_t *sound = new JA_Sound_t();
|
||||||
SDL_LoadWAV(filename, &sound->spec, &sound->buffer, &sound->length);
|
SDL_LoadWAV(filename, &sound->spec, &sound->buffer, &sound->length);
|
||||||
|
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
int JA_PlaySound(JA_Sound_t *sound, const int loop, const int group)
|
int JA_PlaySound(JA_Sound_t *sound, const int loop, const int group) {
|
||||||
{
|
|
||||||
if (!JA_soundEnabled)
|
if (!JA_soundEnabled)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int channel = 0;
|
int channel = 0;
|
||||||
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE)
|
while (channel < JA_MAX_SIMULTANEOUS_CHANNELS && channels[channel].state != JA_CHANNEL_FREE) {
|
||||||
{
|
|
||||||
channel++;
|
channel++;
|
||||||
}
|
}
|
||||||
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS)
|
if (channel == JA_MAX_SIMULTANEOUS_CHANNELS)
|
||||||
@@ -372,8 +332,7 @@ int JA_PlaySound(JA_Sound_t *sound, const int loop, const int group)
|
|||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
int JA_PlaySoundOnChannel(JA_Sound_t *sound, const int channel, const int loop, const int group)
|
int JA_PlaySoundOnChannel(JA_Sound_t *sound, const int channel, const int loop, const int group) {
|
||||||
{
|
|
||||||
if (!JA_soundEnabled)
|
if (!JA_soundEnabled)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -393,10 +352,8 @@ int JA_PlaySoundOnChannel(JA_Sound_t *sound, const int channel, const int loop,
|
|||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_DeleteSound(JA_Sound_t *sound)
|
void JA_DeleteSound(JA_Sound_t *sound) {
|
||||||
{
|
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
|
||||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
|
||||||
{
|
|
||||||
if (channels[i].sound == sound)
|
if (channels[i].sound == sound)
|
||||||
JA_StopChannel(i);
|
JA_StopChannel(i);
|
||||||
}
|
}
|
||||||
@@ -404,25 +361,19 @@ void JA_DeleteSound(JA_Sound_t *sound)
|
|||||||
delete sound;
|
delete sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_PauseChannel(const int channel)
|
void JA_PauseChannel(const int channel) {
|
||||||
{
|
|
||||||
if (!JA_soundEnabled)
|
if (!JA_soundEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (channel == -1)
|
if (channel == -1) {
|
||||||
{
|
|
||||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
||||||
if (channels[i].state == JA_CHANNEL_PLAYING)
|
if (channels[i].state == JA_CHANNEL_PLAYING) {
|
||||||
{
|
|
||||||
channels[i].state = JA_CHANNEL_PAUSED;
|
channels[i].state = JA_CHANNEL_PAUSED;
|
||||||
// SDL_PauseAudioStreamDevice(channels[i].stream);
|
// SDL_PauseAudioStreamDevice(channels[i].stream);
|
||||||
SDL_UnbindAudioStream(channels[i].stream);
|
SDL_UnbindAudioStream(channels[i].stream);
|
||||||
}
|
}
|
||||||
}
|
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
|
||||||
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
|
if (channels[channel].state == JA_CHANNEL_PLAYING) {
|
||||||
{
|
|
||||||
if (channels[channel].state == JA_CHANNEL_PLAYING)
|
|
||||||
{
|
|
||||||
channels[channel].state = JA_CHANNEL_PAUSED;
|
channels[channel].state = JA_CHANNEL_PAUSED;
|
||||||
// SDL_PauseAudioStreamDevice(channels[channel].stream);
|
// SDL_PauseAudioStreamDevice(channels[channel].stream);
|
||||||
SDL_UnbindAudioStream(channels[channel].stream);
|
SDL_UnbindAudioStream(channels[channel].stream);
|
||||||
@@ -430,25 +381,19 @@ void JA_PauseChannel(const int channel)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_ResumeChannel(const int channel)
|
void JA_ResumeChannel(const int channel) {
|
||||||
{
|
|
||||||
if (!JA_soundEnabled)
|
if (!JA_soundEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (channel == -1)
|
if (channel == -1) {
|
||||||
{
|
|
||||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
||||||
if (channels[i].state == JA_CHANNEL_PAUSED)
|
if (channels[i].state == JA_CHANNEL_PAUSED) {
|
||||||
{
|
|
||||||
channels[i].state = JA_CHANNEL_PLAYING;
|
channels[i].state = JA_CHANNEL_PLAYING;
|
||||||
// SDL_ResumeAudioStreamDevice(channels[i].stream);
|
// SDL_ResumeAudioStreamDevice(channels[i].stream);
|
||||||
SDL_BindAudioStream(sdlAudioDevice, channels[i].stream);
|
SDL_BindAudioStream(sdlAudioDevice, channels[i].stream);
|
||||||
}
|
}
|
||||||
}
|
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
|
||||||
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
|
if (channels[channel].state == JA_CHANNEL_PAUSED) {
|
||||||
{
|
|
||||||
if (channels[channel].state == JA_CHANNEL_PAUSED)
|
|
||||||
{
|
|
||||||
channels[channel].state = JA_CHANNEL_PLAYING;
|
channels[channel].state = JA_CHANNEL_PLAYING;
|
||||||
// SDL_ResumeAudioStreamDevice(channels[channel].stream);
|
// SDL_ResumeAudioStreamDevice(channels[channel].stream);
|
||||||
SDL_BindAudioStream(sdlAudioDevice, channels[channel].stream);
|
SDL_BindAudioStream(sdlAudioDevice, channels[channel].stream);
|
||||||
@@ -456,15 +401,12 @@ void JA_ResumeChannel(const int channel)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_StopChannel(const int channel)
|
void JA_StopChannel(const int channel) {
|
||||||
{
|
|
||||||
if (!JA_soundEnabled)
|
if (!JA_soundEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (channel == -1)
|
if (channel == -1) {
|
||||||
{
|
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
|
||||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
|
||||||
{
|
|
||||||
if (channels[i].state != JA_CHANNEL_FREE)
|
if (channels[i].state != JA_CHANNEL_FREE)
|
||||||
SDL_DestroyAudioStream(channels[i].stream);
|
SDL_DestroyAudioStream(channels[i].stream);
|
||||||
channels[i].stream = nullptr;
|
channels[i].stream = nullptr;
|
||||||
@@ -472,9 +414,7 @@ void JA_StopChannel(const int channel)
|
|||||||
channels[i].pos = 0;
|
channels[i].pos = 0;
|
||||||
channels[i].sound = NULL;
|
channels[i].sound = NULL;
|
||||||
}
|
}
|
||||||
}
|
} else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS) {
|
||||||
else if (channel >= 0 && channel < JA_MAX_SIMULTANEOUS_CHANNELS)
|
|
||||||
{
|
|
||||||
if (channels[channel].state != JA_CHANNEL_FREE)
|
if (channels[channel].state != JA_CHANNEL_FREE)
|
||||||
SDL_DestroyAudioStream(channels[channel].stream);
|
SDL_DestroyAudioStream(channels[channel].stream);
|
||||||
channels[channel].stream = nullptr;
|
channels[channel].stream = nullptr;
|
||||||
@@ -484,8 +424,7 @@ void JA_StopChannel(const int channel)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JA_Channel_state JA_GetChannelState(const int channel)
|
JA_Channel_state JA_GetChannelState(const int channel) {
|
||||||
{
|
|
||||||
if (!JA_soundEnabled)
|
if (!JA_soundEnabled)
|
||||||
return JA_SOUND_DISABLED;
|
return JA_SOUND_DISABLED;
|
||||||
|
|
||||||
@@ -495,11 +434,9 @@ JA_Channel_state JA_GetChannelState(const int channel)
|
|||||||
return channels[channel].state;
|
return channels[channel].state;
|
||||||
}
|
}
|
||||||
|
|
||||||
float JA_SetSoundVolume(float volume, const int group)
|
float JA_SetSoundVolume(float volume, const int group) {
|
||||||
{
|
|
||||||
const float v = SDL_clamp(volume, 0.0f, 1.0f);
|
const float v = SDL_clamp(volume, 0.0f, 1.0f);
|
||||||
for (int i = 0; i < JA_MAX_GROUPS; ++i)
|
for (int i = 0; i < JA_MAX_GROUPS; ++i) {
|
||||||
{
|
|
||||||
if (group == -1 || group == i)
|
if (group == -1 || group == i)
|
||||||
JA_soundVolume[i] = v;
|
JA_soundVolume[i] = v;
|
||||||
}
|
}
|
||||||
@@ -512,18 +449,15 @@ float JA_SetSoundVolume(float volume, const int group)
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void JA_EnableSound(const bool value)
|
void JA_EnableSound(const bool value) {
|
||||||
{
|
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++) {
|
||||||
for (int i = 0; i < JA_MAX_SIMULTANEOUS_CHANNELS; i++)
|
|
||||||
{
|
|
||||||
if (channels[i].state == JA_CHANNEL_PLAYING)
|
if (channels[i].state == JA_CHANNEL_PLAYING)
|
||||||
JA_StopChannel(i);
|
JA_StopChannel(i);
|
||||||
}
|
}
|
||||||
JA_soundEnabled = value;
|
JA_soundEnabled = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
float JA_SetVolume(float volume)
|
float JA_SetVolume(float volume) {
|
||||||
{
|
|
||||||
JA_SetSoundVolume(JA_SetMusicVolume(volume) / 2.0f);
|
JA_SetSoundVolume(JA_SetMusicVolume(volume) / 2.0f);
|
||||||
|
|
||||||
return JA_musicVolume;
|
return JA_musicVolume;
|
||||||
|
|||||||
Vendored
+2
-4
@@ -1,16 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
enum JA_Channel_state
|
enum JA_Channel_state {
|
||||||
{
|
|
||||||
JA_CHANNEL_INVALID,
|
JA_CHANNEL_INVALID,
|
||||||
JA_CHANNEL_FREE,
|
JA_CHANNEL_FREE,
|
||||||
JA_CHANNEL_PLAYING,
|
JA_CHANNEL_PLAYING,
|
||||||
JA_CHANNEL_PAUSED,
|
JA_CHANNEL_PAUSED,
|
||||||
JA_SOUND_DISABLED
|
JA_SOUND_DISABLED
|
||||||
};
|
};
|
||||||
enum JA_Music_state
|
enum JA_Music_state {
|
||||||
{
|
|
||||||
JA_MUSIC_INVALID,
|
JA_MUSIC_INVALID,
|
||||||
JA_MUSIC_PLAYING,
|
JA_MUSIC_PLAYING,
|
||||||
JA_MUSIC_PAUSED,
|
JA_MUSIC_PAUSED,
|
||||||
|
|||||||
Vendored
+355
-400
@@ -1,461 +1,416 @@
|
|||||||
#include "jail_shader.h"
|
#include "jail_shader.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_GL_GetProcAddress, SDL_LogError
|
#include <SDL3/SDL.h> // Para SDL_GL_GetProcAddress, SDL_LogError
|
||||||
#include <stdint.h> // Para uintptr_t
|
#include <stdint.h> // Para uintptr_t
|
||||||
|
|
||||||
#include <cstring> // Para strncmp
|
#include <cstring> // Para strncmp
|
||||||
#include <stdexcept> // Para runtime_error
|
#include <stdexcept> // Para runtime_error
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <OpenGL/OpenGL.h> // Para OpenGL en macOS
|
#include <OpenGL/OpenGL.h> // Para OpenGL en macOS
|
||||||
|
|
||||||
#include "CoreFoundation/CoreFoundation.h" // Para Core Foundation en macOS
|
#include "CoreFoundation/CoreFoundation.h" // Para Core Foundation en macOS
|
||||||
#if ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
|
#if ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
|
||||||
#include <OpenGL/gl3.h> // Para OpenGL 3 en macOS
|
#include <OpenGL/gl3.h> // Para OpenGL 3 en macOS
|
||||||
#else // NO ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
|
#else // NO ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
|
||||||
#include <OpenGL/gl.h> // Para OpenGL (compatibilidad) en macOS
|
#include <OpenGL/gl.h> // Para OpenGL (compatibilidad) en macOS
|
||||||
#endif // ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
|
#endif // ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
|
||||||
#else // SI NO ES __APPLE__
|
#else // SI NO ES __APPLE__
|
||||||
#include <SDL3/SDL_opengl.h> // Para GLuint, GLint, glTexCoord2f, glVertex2f
|
#include <SDL3/SDL_opengl.h> // Para GLuint, GLint, glTexCoord2f, glVertex2f
|
||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
|
||||||
namespace shader
|
namespace shader {
|
||||||
{
|
// Constantes
|
||||||
// Constantes
|
const GLuint INVALID_SHADER_ID = 0;
|
||||||
const GLuint INVALID_SHADER_ID = 0;
|
const GLuint INVALID_PROGRAM_ID = 0;
|
||||||
const GLuint INVALID_PROGRAM_ID = 0;
|
const GLuint DEFAULT_TEXTURE_ID = 1;
|
||||||
const GLuint DEFAULT_TEXTURE_ID = 1;
|
|
||||||
|
|
||||||
// Variables globales
|
// Variables globales
|
||||||
SDL_Window *win = nullptr;
|
SDL_Window *win = nullptr;
|
||||||
SDL_Renderer *renderer = nullptr;
|
SDL_Renderer *renderer = nullptr;
|
||||||
GLuint programId = 0;
|
GLuint programId = 0;
|
||||||
SDL_Texture *backBuffer = nullptr;
|
SDL_Texture *backBuffer = nullptr;
|
||||||
SDL_Point win_size = {320 * 4, 256 * 4};
|
SDL_Point win_size = {320 * 4, 256 * 4};
|
||||||
SDL_FPoint tex_size = {320, 256};
|
SDL_FPoint tex_size = {320, 256};
|
||||||
bool usingOpenGL = false;
|
bool usingOpenGL = false;
|
||||||
|
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
// Declaración de funciones de extensión de OpenGL (evitando GLEW)
|
// Declaración de funciones de extensión de OpenGL (evitando GLEW)
|
||||||
PFNGLCREATESHADERPROC glCreateShader;
|
PFNGLCREATESHADERPROC glCreateShader;
|
||||||
PFNGLSHADERSOURCEPROC glShaderSource;
|
PFNGLSHADERSOURCEPROC glShaderSource;
|
||||||
PFNGLCOMPILESHADERPROC glCompileShader;
|
PFNGLCOMPILESHADERPROC glCompileShader;
|
||||||
PFNGLGETSHADERIVPROC glGetShaderiv;
|
PFNGLGETSHADERIVPROC glGetShaderiv;
|
||||||
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
|
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
|
||||||
PFNGLDELETESHADERPROC glDeleteShader;
|
PFNGLDELETESHADERPROC glDeleteShader;
|
||||||
PFNGLATTACHSHADERPROC glAttachShader;
|
PFNGLATTACHSHADERPROC glAttachShader;
|
||||||
PFNGLCREATEPROGRAMPROC glCreateProgram;
|
PFNGLCREATEPROGRAMPROC glCreateProgram;
|
||||||
PFNGLLINKPROGRAMPROC glLinkProgram;
|
PFNGLLINKPROGRAMPROC glLinkProgram;
|
||||||
PFNGLVALIDATEPROGRAMPROC glValidateProgram;
|
PFNGLVALIDATEPROGRAMPROC glValidateProgram;
|
||||||
PFNGLGETPROGRAMIVPROC glGetProgramiv;
|
PFNGLGETPROGRAMIVPROC glGetProgramiv;
|
||||||
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
|
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
|
||||||
PFNGLUSEPROGRAMPROC glUseProgram;
|
PFNGLUSEPROGRAMPROC glUseProgram;
|
||||||
PFNGLDELETEPROGRAMPROC glDeleteProgram;
|
PFNGLDELETEPROGRAMPROC glDeleteProgram;
|
||||||
|
|
||||||
bool initGLExtensions()
|
bool initGLExtensions() {
|
||||||
{
|
glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader");
|
||||||
glCreateShader = (PFNGLCREATESHADERPROC)SDL_GL_GetProcAddress("glCreateShader");
|
glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource");
|
||||||
glShaderSource = (PFNGLSHADERSOURCEPROC)SDL_GL_GetProcAddress("glShaderSource");
|
glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader");
|
||||||
glCompileShader = (PFNGLCOMPILESHADERPROC)SDL_GL_GetProcAddress("glCompileShader");
|
glGetShaderiv = (PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv");
|
||||||
glGetShaderiv = (PFNGLGETSHADERIVPROC)SDL_GL_GetProcAddress("glGetShaderiv");
|
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog");
|
||||||
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)SDL_GL_GetProcAddress("glGetShaderInfoLog");
|
glDeleteShader = (PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader");
|
||||||
glDeleteShader = (PFNGLDELETESHADERPROC)SDL_GL_GetProcAddress("glDeleteShader");
|
glAttachShader = (PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader");
|
||||||
glAttachShader = (PFNGLATTACHSHADERPROC)SDL_GL_GetProcAddress("glAttachShader");
|
glCreateProgram = (PFNGLCREATEPROGRAMPROC)SDL_GL_GetProcAddress("glCreateProgram");
|
||||||
glCreateProgram = (PFNGLCREATEPROGRAMPROC)SDL_GL_GetProcAddress("glCreateProgram");
|
glLinkProgram = (PFNGLLINKPROGRAMPROC)SDL_GL_GetProcAddress("glLinkProgram");
|
||||||
glLinkProgram = (PFNGLLINKPROGRAMPROC)SDL_GL_GetProcAddress("glLinkProgram");
|
glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)SDL_GL_GetProcAddress("glValidateProgram");
|
||||||
glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)SDL_GL_GetProcAddress("glValidateProgram");
|
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)SDL_GL_GetProcAddress("glGetProgramiv");
|
||||||
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)SDL_GL_GetProcAddress("glGetProgramiv");
|
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)SDL_GL_GetProcAddress("glGetProgramInfoLog");
|
||||||
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)SDL_GL_GetProcAddress("glGetProgramInfoLog");
|
glUseProgram = (PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram");
|
||||||
glUseProgram = (PFNGLUSEPROGRAMPROC)SDL_GL_GetProcAddress("glUseProgram");
|
glDeleteProgram = (PFNGLDELETEPROGRAMPROC)SDL_GL_GetProcAddress("glDeleteProgram");
|
||||||
glDeleteProgram = (PFNGLDELETEPROGRAMPROC)SDL_GL_GetProcAddress("glDeleteProgram");
|
|
||||||
|
|
||||||
return glCreateShader && glShaderSource && glCompileShader && glGetShaderiv &&
|
return glCreateShader && glShaderSource && glCompileShader && glGetShaderiv &&
|
||||||
glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram &&
|
glGetShaderInfoLog && glDeleteShader && glAttachShader && glCreateProgram &&
|
||||||
glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog &&
|
glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog &&
|
||||||
glUseProgram && glDeleteProgram;
|
glUseProgram && glDeleteProgram;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Función para verificar errores de OpenGL
|
// Función para verificar errores de OpenGL
|
||||||
void checkGLError(const char *operation)
|
void checkGLError(const char *operation) {
|
||||||
{
|
GLenum error = glGetError();
|
||||||
GLenum error = glGetError();
|
if (error != GL_NO_ERROR) {
|
||||||
if (error != GL_NO_ERROR)
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
{
|
"Error OpenGL en %s: 0x%x",
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
operation,
|
||||||
"Error OpenGL en %s: 0x%x", operation, error);
|
error);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Función para compilar un shader a partir de un std::string
|
||||||
|
GLuint compileShader(const std::string &source, GLuint shader_type) {
|
||||||
|
if (source.empty()) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "ERROR FATAL: El código fuente del shader está vacío.");
|
||||||
|
throw std::runtime_error("ERROR FATAL: El código fuente del shader está vacío.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Función para compilar un shader a partir de un std::string
|
// Crear identificador del shader
|
||||||
GLuint compileShader(const std::string &source, GLuint shader_type)
|
GLuint shader_id = glCreateShader(shader_type);
|
||||||
{
|
if (shader_id == INVALID_SHADER_ID) {
|
||||||
if (source.empty())
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error al crear el shader.");
|
||||||
{
|
checkGLError("glCreateShader");
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "ERROR FATAL: El código fuente del shader está vacío.");
|
return INVALID_SHADER_ID;
|
||||||
throw std::runtime_error("ERROR FATAL: El código fuente del shader está vacío.");
|
}
|
||||||
|
|
||||||
|
// Agregar una directiva según el tipo de shader
|
||||||
|
std::string directive = (shader_type == GL_VERTEX_SHADER)
|
||||||
|
? "#define VERTEX\n"
|
||||||
|
: "#define FRAGMENT\n";
|
||||||
|
|
||||||
|
const char *sources[2] = {directive.c_str(), source.c_str()};
|
||||||
|
|
||||||
|
// Especificar el código fuente del shader
|
||||||
|
glShaderSource(shader_id, 2, sources, nullptr);
|
||||||
|
checkGLError("glShaderSource");
|
||||||
|
|
||||||
|
// Compilar el shader
|
||||||
|
glCompileShader(shader_id);
|
||||||
|
checkGLError("glCompileShader");
|
||||||
|
|
||||||
|
// Verificar si la compilación fue exitosa
|
||||||
|
GLint compiled_ok = GL_FALSE;
|
||||||
|
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &compiled_ok);
|
||||||
|
if (compiled_ok != GL_TRUE) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error en la compilación del shader (%d)!", shader_id);
|
||||||
|
GLint log_length;
|
||||||
|
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length);
|
||||||
|
if (log_length > 0) {
|
||||||
|
std::vector<GLchar> log(log_length);
|
||||||
|
glGetShaderInfoLog(shader_id, log_length, &log_length, log.data());
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Registro de compilación del shader: %s", log.data());
|
||||||
}
|
}
|
||||||
|
glDeleteShader(shader_id);
|
||||||
|
return INVALID_SHADER_ID;
|
||||||
|
}
|
||||||
|
return shader_id;
|
||||||
|
}
|
||||||
|
|
||||||
// Crear identificador del shader
|
// Función para compilar un programa de shaders (vertex y fragment) a partir de std::string
|
||||||
GLuint shader_id = glCreateShader(shader_type);
|
GLuint compileProgram(const std::string &vertex_shader_source, const std::string &fragment_shader_source) {
|
||||||
if (shader_id == INVALID_SHADER_ID)
|
GLuint program_id = glCreateProgram();
|
||||||
{
|
if (program_id == INVALID_PROGRAM_ID) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error al crear el shader.");
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error al crear el programa de shaders.");
|
||||||
checkGLError("glCreateShader");
|
checkGLError("glCreateProgram");
|
||||||
return INVALID_SHADER_ID;
|
return INVALID_PROGRAM_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Agregar una directiva según el tipo de shader
|
// Si el fragment shader está vacío, reutilizamos el código del vertex shader
|
||||||
std::string directive = (shader_type == GL_VERTEX_SHADER)
|
GLuint vertex_shader_id = compileShader(vertex_shader_source, GL_VERTEX_SHADER);
|
||||||
? "#define VERTEX\n"
|
GLuint fragment_shader_id = compileShader(fragment_shader_source.empty() ? vertex_shader_source : fragment_shader_source, GL_FRAGMENT_SHADER);
|
||||||
: "#define FRAGMENT\n";
|
|
||||||
|
|
||||||
const char *sources[2] = {directive.c_str(), source.c_str()};
|
if (vertex_shader_id != INVALID_SHADER_ID && fragment_shader_id != INVALID_SHADER_ID) {
|
||||||
|
// Asociar los shaders al programa
|
||||||
|
glAttachShader(program_id, vertex_shader_id);
|
||||||
|
checkGLError("glAttachShader vertex");
|
||||||
|
glAttachShader(program_id, fragment_shader_id);
|
||||||
|
checkGLError("glAttachShader fragment");
|
||||||
|
|
||||||
// Especificar el código fuente del shader
|
glLinkProgram(program_id);
|
||||||
glShaderSource(shader_id, 2, sources, nullptr);
|
checkGLError("glLinkProgram");
|
||||||
checkGLError("glShaderSource");
|
|
||||||
|
|
||||||
// Compilar el shader
|
// Verificar el estado del enlace
|
||||||
glCompileShader(shader_id);
|
GLint isLinked = GL_FALSE;
|
||||||
checkGLError("glCompileShader");
|
glGetProgramiv(program_id, GL_LINK_STATUS, &isLinked);
|
||||||
|
if (isLinked == GL_FALSE) {
|
||||||
// Verificar si la compilación fue exitosa
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error al enlazar el programa de shaders.");
|
||||||
GLint compiled_ok = GL_FALSE;
|
|
||||||
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &compiled_ok);
|
|
||||||
if (compiled_ok != GL_TRUE)
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error en la compilación del shader (%d)!", shader_id);
|
|
||||||
GLint log_length;
|
GLint log_length;
|
||||||
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length);
|
glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &log_length);
|
||||||
if (log_length > 0)
|
if (log_length > 0) {
|
||||||
{
|
std::vector<char> log(log_length);
|
||||||
std::vector<GLchar> log(log_length);
|
glGetProgramInfoLog(program_id, log_length, &log_length, log.data());
|
||||||
glGetShaderInfoLog(shader_id, log_length, &log_length, log.data());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Registro de enlace del programa: %s", log.data());
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Registro de compilación del shader: %s", log.data());
|
|
||||||
}
|
}
|
||||||
glDeleteShader(shader_id);
|
|
||||||
return INVALID_SHADER_ID;
|
|
||||||
}
|
|
||||||
return shader_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Función para compilar un programa de shaders (vertex y fragment) a partir de std::string
|
|
||||||
GLuint compileProgram(const std::string &vertex_shader_source, const std::string &fragment_shader_source)
|
|
||||||
{
|
|
||||||
GLuint program_id = glCreateProgram();
|
|
||||||
if (program_id == INVALID_PROGRAM_ID)
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error al crear el programa de shaders.");
|
|
||||||
checkGLError("glCreateProgram");
|
|
||||||
return INVALID_PROGRAM_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si el fragment shader está vacío, reutilizamos el código del vertex shader
|
|
||||||
GLuint vertex_shader_id = compileShader(vertex_shader_source, GL_VERTEX_SHADER);
|
|
||||||
GLuint fragment_shader_id = compileShader(fragment_shader_source.empty() ? vertex_shader_source : fragment_shader_source, GL_FRAGMENT_SHADER);
|
|
||||||
|
|
||||||
if (vertex_shader_id != INVALID_SHADER_ID && fragment_shader_id != INVALID_SHADER_ID)
|
|
||||||
{
|
|
||||||
// Asociar los shaders al programa
|
|
||||||
glAttachShader(program_id, vertex_shader_id);
|
|
||||||
checkGLError("glAttachShader vertex");
|
|
||||||
glAttachShader(program_id, fragment_shader_id);
|
|
||||||
checkGLError("glAttachShader fragment");
|
|
||||||
|
|
||||||
glLinkProgram(program_id);
|
|
||||||
checkGLError("glLinkProgram");
|
|
||||||
|
|
||||||
// Verificar el estado del enlace
|
|
||||||
GLint isLinked = GL_FALSE;
|
|
||||||
glGetProgramiv(program_id, GL_LINK_STATUS, &isLinked);
|
|
||||||
if (isLinked == GL_FALSE)
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error al enlazar el programa de shaders.");
|
|
||||||
GLint log_length;
|
|
||||||
glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &log_length);
|
|
||||||
if (log_length > 0)
|
|
||||||
{
|
|
||||||
std::vector<char> log(log_length);
|
|
||||||
glGetProgramInfoLog(program_id, log_length, &log_length, log.data());
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Registro de enlace del programa: %s", log.data());
|
|
||||||
}
|
|
||||||
glDeleteProgram(program_id);
|
|
||||||
program_id = INVALID_PROGRAM_ID;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glValidateProgram(program_id);
|
|
||||||
checkGLError("glValidateProgram");
|
|
||||||
|
|
||||||
// Log de información del programa (solo si hay información)
|
|
||||||
GLint log_length;
|
|
||||||
glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &log_length);
|
|
||||||
if (log_length > 1) // > 1 porque algunos drivers devuelven 1 para cadena vacía
|
|
||||||
{
|
|
||||||
std::vector<char> log(log_length);
|
|
||||||
glGetProgramInfoLog(program_id, log_length, &log_length, log.data());
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Registro de información del programa:\n%s", log.data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudieron compilar los shaders.");
|
|
||||||
glDeleteProgram(program_id);
|
glDeleteProgram(program_id);
|
||||||
program_id = INVALID_PROGRAM_ID;
|
program_id = INVALID_PROGRAM_ID;
|
||||||
}
|
} else {
|
||||||
|
glValidateProgram(program_id);
|
||||||
|
checkGLError("glValidateProgram");
|
||||||
|
|
||||||
// Limpiar los shaders (ya no son necesarios después del enlace)
|
// Log de información del programa (solo si hay información)
|
||||||
if (vertex_shader_id != INVALID_SHADER_ID)
|
GLint log_length;
|
||||||
{
|
glGetProgramiv(program_id, GL_INFO_LOG_LENGTH, &log_length);
|
||||||
glDeleteShader(vertex_shader_id);
|
if (log_length > 1) // > 1 porque algunos drivers devuelven 1 para cadena vacía
|
||||||
|
{
|
||||||
|
std::vector<char> log(log_length);
|
||||||
|
glGetProgramInfoLog(program_id, log_length, &log_length, log.data());
|
||||||
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Registro de información del programa:\n%s", log.data());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (fragment_shader_id != INVALID_SHADER_ID)
|
} else {
|
||||||
{
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudieron compilar los shaders.");
|
||||||
glDeleteShader(fragment_shader_id);
|
glDeleteProgram(program_id);
|
||||||
}
|
program_id = INVALID_PROGRAM_ID;
|
||||||
|
|
||||||
return program_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Función para obtener el ID de textura OpenGL desde SDL3
|
// Limpiar los shaders (ya no son necesarios después del enlace)
|
||||||
GLuint getTextureID(SDL_Texture *texture)
|
if (vertex_shader_id != INVALID_SHADER_ID) {
|
||||||
{
|
glDeleteShader(vertex_shader_id);
|
||||||
if (!texture)
|
}
|
||||||
return DEFAULT_TEXTURE_ID;
|
if (fragment_shader_id != INVALID_SHADER_ID) {
|
||||||
|
glDeleteShader(fragment_shader_id);
|
||||||
// Intentar obtener el ID de textura OpenGL desde las propiedades de SDL3
|
|
||||||
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
|
|
||||||
GLuint textureId = 0;
|
|
||||||
|
|
||||||
// Intentar diferentes nombres de propiedades según la versión de SDL3
|
|
||||||
textureId = (GLuint)(uintptr_t)SDL_GetPointerProperty(props, "SDL.texture.opengl.texture", nullptr);
|
|
||||||
|
|
||||||
// Si la primera no funciona, intentar con el nombre alternativo
|
|
||||||
if (textureId == 0)
|
|
||||||
{
|
|
||||||
textureId = (GLuint)(uintptr_t)SDL_GetPointerProperty(props, "texture.opengl.texture", nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si aún no funciona, intentar obtener como número
|
|
||||||
if (textureId == 0)
|
|
||||||
{
|
|
||||||
textureId = (GLuint)SDL_GetNumberProperty(props, "SDL.texture.opengl.texture", DEFAULT_TEXTURE_ID);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si ninguna funciona, usar el método manual de bindeo de textura
|
|
||||||
if (textureId == 0)
|
|
||||||
{
|
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
|
||||||
"No se pudo obtener el ID de textura OpenGL, usando ID por defecto (%d)", DEFAULT_TEXTURE_ID);
|
|
||||||
textureId = DEFAULT_TEXTURE_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
return textureId;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool init(SDL_Window *window, SDL_Texture *back_buffer_texture, const std::string &vertex_shader, const std::string &fragment_shader)
|
return program_id;
|
||||||
{
|
}
|
||||||
shader::win = window;
|
|
||||||
shader::renderer = SDL_GetRenderer(window);
|
|
||||||
shader::backBuffer = back_buffer_texture;
|
|
||||||
|
|
||||||
if (!shader::renderer)
|
// Función para obtener el ID de textura OpenGL desde SDL3
|
||||||
{
|
GLuint getTextureID(SDL_Texture *texture) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo obtener el renderer de la ventana.");
|
if (!texture)
|
||||||
return false;
|
return DEFAULT_TEXTURE_ID;
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GetWindowSize(window, &win_size.x, &win_size.y);
|
// Intentar obtener el ID de textura OpenGL desde las propiedades de SDL3
|
||||||
SDL_GetTextureSize(back_buffer_texture, &tex_size.x, &tex_size.y);
|
SDL_PropertiesID props = SDL_GetTextureProperties(texture);
|
||||||
|
GLuint textureId = 0;
|
||||||
|
|
||||||
const auto render_name = SDL_GetRendererName(renderer);
|
// Intentar diferentes nombres de propiedades según la versión de SDL3
|
||||||
if (!render_name)
|
textureId = (GLuint)(uintptr_t)SDL_GetPointerProperty(props, "SDL.texture.opengl.texture", nullptr);
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo obtener el nombre del renderer.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verificar que el renderer sea OpenGL
|
// Si la primera no funciona, intentar con el nombre alternativo
|
||||||
if (!strncmp(render_name, "opengl", 6))
|
if (textureId == 0) {
|
||||||
{
|
textureId = (GLuint)(uintptr_t)SDL_GetPointerProperty(props, "texture.opengl.texture", nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si aún no funciona, intentar obtener como número
|
||||||
|
if (textureId == 0) {
|
||||||
|
textureId = (GLuint)SDL_GetNumberProperty(props, "SDL.texture.opengl.texture", DEFAULT_TEXTURE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si ninguna funciona, usar el método manual de bindeo de textura
|
||||||
|
if (textureId == 0) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"No se pudo obtener el ID de textura OpenGL, usando ID por defecto (%d)",
|
||||||
|
DEFAULT_TEXTURE_ID);
|
||||||
|
textureId = DEFAULT_TEXTURE_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return textureId;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool init(SDL_Window *window, SDL_Texture *back_buffer_texture, const std::string &vertex_shader, const std::string &fragment_shader) {
|
||||||
|
shader::win = window;
|
||||||
|
shader::renderer = SDL_GetRenderer(window);
|
||||||
|
shader::backBuffer = back_buffer_texture;
|
||||||
|
|
||||||
|
if (!shader::renderer) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo obtener el renderer de la ventana.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_GetWindowSize(window, &win_size.x, &win_size.y);
|
||||||
|
SDL_GetTextureSize(back_buffer_texture, &tex_size.x, &tex_size.y);
|
||||||
|
|
||||||
|
const auto render_name = SDL_GetRendererName(renderer);
|
||||||
|
if (!render_name) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo obtener el nombre del renderer.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verificar que el renderer sea OpenGL
|
||||||
|
if (!strncmp(render_name, "opengl", 6)) {
|
||||||
#ifndef __APPLE__
|
#ifndef __APPLE__
|
||||||
if (!initGLExtensions())
|
if (!initGLExtensions()) {
|
||||||
{
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "ERROR: No se han podido inicializar las extensiones de OpenGL.");
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "ERROR: No se han podido inicializar las extensiones de OpenGL.");
|
|
||||||
usingOpenGL = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// Compilar el programa de shaders utilizando std::string
|
|
||||||
programId = compileProgram(vertex_shader, fragment_shader);
|
|
||||||
if (programId == INVALID_PROGRAM_ID)
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "ERROR: No se pudo compilar el programa de shaders.");
|
|
||||||
usingOpenGL = false;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "ADVERTENCIA: El driver del renderer no es OpenGL (%s).", render_name);
|
|
||||||
usingOpenGL = false;
|
usingOpenGL = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
usingOpenGL = true;
|
// Compilar el programa de shaders utilizando std::string
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Shader system initialized successfully.");
|
programId = compileProgram(vertex_shader, fragment_shader);
|
||||||
return true;
|
if (programId == INVALID_PROGRAM_ID) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "ERROR: No se pudo compilar el programa de shaders.");
|
||||||
|
usingOpenGL = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "ADVERTENCIA: El driver del renderer no es OpenGL (%s).", render_name);
|
||||||
|
usingOpenGL = false;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void render()
|
usingOpenGL = true;
|
||||||
{
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Shader system initialized successfully.");
|
||||||
// Establece el color de fondo
|
return true;
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
}
|
||||||
SDL_SetRenderTarget(renderer, nullptr);
|
|
||||||
SDL_RenderClear(renderer);
|
|
||||||
|
|
||||||
if (usingOpenGL && programId != INVALID_PROGRAM_ID)
|
void render() {
|
||||||
{
|
// Establece el color de fondo
|
||||||
// Guardar estados de OpenGL
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
|
||||||
GLint oldProgramId;
|
SDL_SetRenderTarget(renderer, nullptr);
|
||||||
glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgramId);
|
SDL_RenderClear(renderer);
|
||||||
|
|
||||||
GLint oldViewport[4];
|
if (usingOpenGL && programId != INVALID_PROGRAM_ID) {
|
||||||
glGetIntegerv(GL_VIEWPORT, oldViewport);
|
// Guardar estados de OpenGL
|
||||||
|
GLint oldProgramId;
|
||||||
|
glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgramId);
|
||||||
|
|
||||||
GLboolean wasTextureEnabled = glIsEnabled(GL_TEXTURE_2D);
|
GLint oldViewport[4];
|
||||||
GLint oldTextureId;
|
glGetIntegerv(GL_VIEWPORT, oldViewport);
|
||||||
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTextureId);
|
|
||||||
|
|
||||||
// Obtener y bindear la textura
|
GLboolean wasTextureEnabled = glIsEnabled(GL_TEXTURE_2D);
|
||||||
GLuint textureId = getTextureID(backBuffer);
|
GLint oldTextureId;
|
||||||
glEnable(GL_TEXTURE_2D);
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTextureId);
|
||||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
|
||||||
checkGLError("glBindTexture");
|
|
||||||
|
|
||||||
// Usar nuestro programa de shaders
|
// Obtener y bindear la textura
|
||||||
glUseProgram(programId);
|
GLuint textureId = getTextureID(backBuffer);
|
||||||
checkGLError("glUseProgram");
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||||
|
checkGLError("glBindTexture");
|
||||||
|
|
||||||
// Recupera el tamaño lógico configurado con SDL_RenderSetLogicalSize
|
// Usar nuestro programa de shaders
|
||||||
int logicalW, logicalH;
|
glUseProgram(programId);
|
||||||
SDL_RendererLogicalPresentation mode;
|
checkGLError("glUseProgram");
|
||||||
SDL_GetRenderLogicalPresentation(renderer, &logicalW, &logicalH, &mode);
|
|
||||||
if (logicalW == 0 || logicalH == 0)
|
// Recupera el tamaño lógico configurado con SDL_RenderSetLogicalSize
|
||||||
{
|
int logicalW, logicalH;
|
||||||
logicalW = win_size.x;
|
SDL_RendererLogicalPresentation mode;
|
||||||
logicalH = win_size.y;
|
SDL_GetRenderLogicalPresentation(renderer, &logicalW, &logicalH, &mode);
|
||||||
|
if (logicalW == 0 || logicalH == 0) {
|
||||||
|
logicalW = win_size.x;
|
||||||
|
logicalH = win_size.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cálculo del viewport
|
||||||
|
int viewportX = 0, viewportY = 0, viewportW = win_size.x, viewportH = win_size.y;
|
||||||
|
const bool USE_INTEGER_SCALE = mode == SDL_LOGICAL_PRESENTATION_INTEGER_SCALE;
|
||||||
|
if (USE_INTEGER_SCALE) {
|
||||||
|
// Calcula el factor de escalado entero máximo que se puede aplicar
|
||||||
|
int scaleX = win_size.x / logicalW;
|
||||||
|
int scaleY = win_size.y / logicalH;
|
||||||
|
int scale = (scaleX < scaleY ? scaleX : scaleY);
|
||||||
|
if (scale < 1) {
|
||||||
|
scale = 1;
|
||||||
}
|
}
|
||||||
|
viewportW = logicalW * scale;
|
||||||
// Cálculo del viewport
|
viewportH = logicalH * scale;
|
||||||
int viewportX = 0, viewportY = 0, viewportW = win_size.x, viewportH = win_size.y;
|
viewportX = (win_size.x - viewportW) / 2;
|
||||||
const bool USE_INTEGER_SCALE = mode == SDL_LOGICAL_PRESENTATION_INTEGER_SCALE;
|
viewportY = (win_size.y - viewportH) / 2;
|
||||||
if (USE_INTEGER_SCALE)
|
} else {
|
||||||
{
|
// Letterboxing: preserva la relación de aspecto usando una escala flotante
|
||||||
// Calcula el factor de escalado entero máximo que se puede aplicar
|
float windowAspect = static_cast<float>(win_size.x) / win_size.y;
|
||||||
int scaleX = win_size.x / logicalW;
|
float logicalAspect = static_cast<float>(logicalW) / logicalH;
|
||||||
int scaleY = win_size.y / logicalH;
|
if (windowAspect > logicalAspect) {
|
||||||
int scale = (scaleX < scaleY ? scaleX : scaleY);
|
viewportW = static_cast<int>(logicalAspect * win_size.y);
|
||||||
if (scale < 1)
|
|
||||||
{
|
|
||||||
scale = 1;
|
|
||||||
}
|
|
||||||
viewportW = logicalW * scale;
|
|
||||||
viewportH = logicalH * scale;
|
|
||||||
viewportX = (win_size.x - viewportW) / 2;
|
viewportX = (win_size.x - viewportW) / 2;
|
||||||
|
} else {
|
||||||
|
viewportH = static_cast<int>(win_size.x / logicalAspect);
|
||||||
viewportY = (win_size.y - viewportH) / 2;
|
viewportY = (win_size.y - viewportH) / 2;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Letterboxing: preserva la relación de aspecto usando una escala flotante
|
|
||||||
float windowAspect = static_cast<float>(win_size.x) / win_size.y;
|
|
||||||
float logicalAspect = static_cast<float>(logicalW) / logicalH;
|
|
||||||
if (windowAspect > logicalAspect)
|
|
||||||
{
|
|
||||||
viewportW = static_cast<int>(logicalAspect * win_size.y);
|
|
||||||
viewportX = (win_size.x - viewportW) / 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
viewportH = static_cast<int>(win_size.x / logicalAspect);
|
|
||||||
viewportY = (win_size.y - viewportH) / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glViewport(viewportX, viewportY, viewportW, viewportH);
|
|
||||||
checkGLError("glViewport");
|
|
||||||
|
|
||||||
// Configurar la proyección ortográfica usando el espacio lógico
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadIdentity();
|
|
||||||
|
|
||||||
// Queremos que el origen esté en la esquina superior izquierda del espacio lógico.
|
|
||||||
glOrtho(0, static_cast<GLdouble>(logicalW), static_cast<GLdouble>(logicalH), 0, -1, 1);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glLoadIdentity();
|
|
||||||
|
|
||||||
// Dibuja el quad con las coordenadas ajustadas.
|
|
||||||
// Se asignan las coordenadas de textura "normales" para que no quede espejado horizontalmente,
|
|
||||||
// y se mantiene el flip vertical para que la imagen no aparezca volteada.
|
|
||||||
glBegin(GL_TRIANGLE_STRIP);
|
|
||||||
// Vértice superior izquierdo
|
|
||||||
glTexCoord2f(0.0f, 1.0f);
|
|
||||||
glVertex2f(0.0f, 0.0f);
|
|
||||||
// Vértice superior derecho
|
|
||||||
glTexCoord2f(1.0f, 1.0f);
|
|
||||||
glVertex2f(static_cast<GLfloat>(logicalW), 0.0f);
|
|
||||||
// Vértice inferior izquierdo
|
|
||||||
glTexCoord2f(0.0f, 0.0f);
|
|
||||||
glVertex2f(0.0f, static_cast<GLfloat>(logicalH));
|
|
||||||
// Vértice inferior derecho
|
|
||||||
glTexCoord2f(1.0f, 0.0f);
|
|
||||||
glVertex2f(static_cast<GLfloat>(logicalW), static_cast<GLfloat>(logicalH));
|
|
||||||
glEnd();
|
|
||||||
checkGLError("render quad");
|
|
||||||
|
|
||||||
SDL_GL_SwapWindow(win);
|
|
||||||
|
|
||||||
// Restaurar estados de OpenGL
|
|
||||||
glUseProgram(oldProgramId);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, oldTextureId);
|
|
||||||
if (!wasTextureEnabled)
|
|
||||||
{
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
}
|
|
||||||
glViewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
|
|
||||||
}
|
}
|
||||||
else
|
glViewport(viewportX, viewportY, viewportW, viewportH);
|
||||||
{
|
checkGLError("glViewport");
|
||||||
// Fallback a renderizado normal de SDL
|
|
||||||
SDL_RenderTexture(renderer, backBuffer, nullptr, nullptr);
|
// Configurar la proyección ortográfica usando el espacio lógico
|
||||||
SDL_RenderPresent(renderer);
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
// Queremos que el origen esté en la esquina superior izquierda del espacio lógico.
|
||||||
|
glOrtho(0, static_cast<GLdouble>(logicalW), static_cast<GLdouble>(logicalH), 0, -1, 1);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
// Dibuja el quad con las coordenadas ajustadas.
|
||||||
|
// Se asignan las coordenadas de textura "normales" para que no quede espejado horizontalmente,
|
||||||
|
// y se mantiene el flip vertical para que la imagen no aparezca volteada.
|
||||||
|
glBegin(GL_TRIANGLE_STRIP);
|
||||||
|
// Vértice superior izquierdo
|
||||||
|
glTexCoord2f(0.0f, 1.0f);
|
||||||
|
glVertex2f(0.0f, 0.0f);
|
||||||
|
// Vértice superior derecho
|
||||||
|
glTexCoord2f(1.0f, 1.0f);
|
||||||
|
glVertex2f(static_cast<GLfloat>(logicalW), 0.0f);
|
||||||
|
// Vértice inferior izquierdo
|
||||||
|
glTexCoord2f(0.0f, 0.0f);
|
||||||
|
glVertex2f(0.0f, static_cast<GLfloat>(logicalH));
|
||||||
|
// Vértice inferior derecho
|
||||||
|
glTexCoord2f(1.0f, 0.0f);
|
||||||
|
glVertex2f(static_cast<GLfloat>(logicalW), static_cast<GLfloat>(logicalH));
|
||||||
|
glEnd();
|
||||||
|
checkGLError("render quad");
|
||||||
|
|
||||||
|
SDL_GL_SwapWindow(win);
|
||||||
|
|
||||||
|
// Restaurar estados de OpenGL
|
||||||
|
glUseProgram(oldProgramId);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, oldTextureId);
|
||||||
|
if (!wasTextureEnabled) {
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
}
|
}
|
||||||
|
glViewport(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
|
||||||
|
} else {
|
||||||
|
// Fallback a renderizado normal de SDL
|
||||||
|
SDL_RenderTexture(renderer, backBuffer, nullptr, nullptr);
|
||||||
|
SDL_RenderPresent(renderer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup() {
|
||||||
|
if (programId != INVALID_PROGRAM_ID) {
|
||||||
|
glDeleteProgram(programId);
|
||||||
|
programId = INVALID_PROGRAM_ID;
|
||||||
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Programa de shaders liberado.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup()
|
// Reinicializar variables
|
||||||
{
|
win = nullptr;
|
||||||
if (programId != INVALID_PROGRAM_ID)
|
renderer = nullptr;
|
||||||
{
|
backBuffer = nullptr;
|
||||||
glDeleteProgram(programId);
|
usingOpenGL = false;
|
||||||
programId = INVALID_PROGRAM_ID;
|
}
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Programa de shaders liberado.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reinicializar variables
|
bool isUsingOpenGL() {
|
||||||
win = nullptr;
|
return usingOpenGL;
|
||||||
renderer = nullptr;
|
}
|
||||||
backBuffer = nullptr;
|
|
||||||
usingOpenGL = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isUsingOpenGL()
|
GLuint getProgramId() {
|
||||||
{
|
return programId;
|
||||||
return usingOpenGL;
|
}
|
||||||
}
|
} // namespace shader
|
||||||
|
|
||||||
GLuint getProgramId()
|
|
||||||
{
|
|
||||||
return programId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
+7
-7
@@ -1,10 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_Texture, SDL_Window
|
#include <SDL3/SDL.h> // Para SDL_Texture, SDL_Window
|
||||||
#include <string> // Para basic_string, string
|
|
||||||
|
|
||||||
namespace shader
|
#include <string> // Para basic_string, string
|
||||||
{
|
|
||||||
bool init(SDL_Window *ventana, SDL_Texture *texturaBackBuffer, const std::string &vertexShader, const std::string &fragmentShader = "");
|
namespace shader {
|
||||||
void render();
|
bool init(SDL_Window *ventana, SDL_Texture *texturaBackBuffer, const std::string &vertexShader, const std::string &fragmentShader = "");
|
||||||
}
|
void render();
|
||||||
|
} // namespace shader
|
||||||
Vendored
+5915
-6851
File diff suppressed because it is too large.
Load diff
Vendored
+4088
-4709
File diff suppressed because it is too large.
Load diff
+243
-292
@@ -1,374 +1,325 @@
|
|||||||
#include "fade.h"
|
#include "fade.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_SetRenderTarget, SDL_FRect, SDL_GetRenderT...
|
#include <SDL3/SDL.h> // Para SDL_SetRenderTarget, SDL_FRect, SDL_GetRenderT...
|
||||||
#include <stdlib.h> // Para rand, size_t
|
#include <stdlib.h> // Para rand, size_t
|
||||||
|
|
||||||
#include <algorithm> // Para min, max
|
#include <algorithm> // Para min, max
|
||||||
|
|
||||||
#include "param.h" // Para Param, param, ParamGame, ParamFade
|
#include "param.h" // Para Param, param, ParamGame, ParamFade
|
||||||
#include "screen.h" // Para Screen
|
#include "screen.h" // Para Screen
|
||||||
#include "utils.h" // Para Color
|
#include "utils.h" // Para Color
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Fade::Fade()
|
Fade::Fade()
|
||||||
: renderer_(Screen::get()->getRenderer())
|
: renderer_(Screen::get()->getRenderer()) {
|
||||||
{
|
// Crea la textura donde dibujar el fade
|
||||||
// Crea la textura donde dibujar el fade
|
backbuffer_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);
|
||||||
backbuffer_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);
|
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
|
||||||
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
|
|
||||||
|
|
||||||
// Inicializa las variables
|
// Inicializa las variables
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
Fade::~Fade()
|
Fade::~Fade() {
|
||||||
{
|
SDL_DestroyTexture(backbuffer_);
|
||||||
SDL_DestroyTexture(backbuffer_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa las variables
|
// Inicializa las variables
|
||||||
void Fade::init()
|
void Fade::init() {
|
||||||
{
|
type_ = FadeType::CENTER;
|
||||||
type_ = FadeType::CENTER;
|
mode_ = FadeMode::OUT;
|
||||||
mode_ = FadeMode::OUT;
|
counter_ = 0;
|
||||||
counter_ = 0;
|
r_ = 0;
|
||||||
r_ = 0;
|
g_ = 0;
|
||||||
g_ = 0;
|
b_ = 0;
|
||||||
b_ = 0;
|
a_ = 0;
|
||||||
a_ = 0;
|
post_duration_ = 0;
|
||||||
post_duration_ = 0;
|
post_counter_ = 0;
|
||||||
post_counter_ = 0;
|
pre_duration_ = 0;
|
||||||
pre_duration_ = 0;
|
pre_counter_ = 0;
|
||||||
pre_counter_ = 0;
|
num_squares_width_ = param.fade.num_squares_width;
|
||||||
num_squares_width_ = param.fade.num_squares_width;
|
num_squares_height_ = param.fade.num_squares_height;
|
||||||
num_squares_height_ = param.fade.num_squares_height;
|
fade_random_squares_delay_ = param.fade.random_squares_delay;
|
||||||
fade_random_squares_delay_ = param.fade.random_squares_delay;
|
fade_random_squares_mult_ = param.fade.random_squares_mult;
|
||||||
fade_random_squares_mult_ = param.fade.random_squares_mult;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resetea algunas variables para volver a hacer el fade sin perder ciertos parametros
|
// Resetea algunas variables para volver a hacer el fade sin perder ciertos parametros
|
||||||
void Fade::reset()
|
void Fade::reset() {
|
||||||
{
|
state_ = FadeState::NOT_ENABLED;
|
||||||
state_ = FadeState::NOT_ENABLED;
|
counter_ = 0;
|
||||||
counter_ = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pinta una transición en pantalla
|
// Pinta una transición en pantalla
|
||||||
void Fade::render()
|
void Fade::render() {
|
||||||
{
|
if (state_ != FadeState::NOT_ENABLED) {
|
||||||
if (state_ != FadeState::NOT_ENABLED)
|
SDL_RenderTexture(renderer_, backbuffer_, nullptr, nullptr);
|
||||||
{
|
}
|
||||||
SDL_RenderTexture(renderer_, backbuffer_, nullptr, nullptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza las variables internas
|
// Actualiza las variables internas
|
||||||
void Fade::update()
|
void Fade::update() {
|
||||||
{
|
if (state_ == FadeState::PRE) {
|
||||||
if (state_ == FadeState::PRE)
|
// Actualiza el contador
|
||||||
{
|
if (pre_counter_ == pre_duration_) {
|
||||||
// Actualiza el contador
|
state_ = FadeState::FADING;
|
||||||
if (pre_counter_ == pre_duration_)
|
} else {
|
||||||
{
|
pre_counter_++;
|
||||||
state_ = FadeState::FADING;
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
pre_counter_++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state_ == FadeState::FADING)
|
if (state_ == FadeState::FADING) {
|
||||||
{
|
switch (type_) {
|
||||||
switch (type_)
|
case FadeType::FULLSCREEN: {
|
||||||
{
|
// Modifica la transparencia
|
||||||
case FadeType::FULLSCREEN:
|
a_ = mode_ == FadeMode::OUT ? std::min(counter_ * 4, 255) : 255 - std::min(counter_ * 4, 255);
|
||||||
{
|
|
||||||
// Modifica la transparencia
|
|
||||||
a_ = mode_ == FadeMode::OUT ? std::min(counter_ * 4, 255) : 255 - std::min(counter_ * 4, 255);
|
|
||||||
|
|
||||||
SDL_SetTextureAlphaMod(backbuffer_, a_);
|
SDL_SetTextureAlphaMod(backbuffer_, a_);
|
||||||
|
|
||||||
// Comprueba si ha terminado
|
// Comprueba si ha terminado
|
||||||
if (counter_ >= 255 / 4)
|
if (counter_ >= 255 / 4) {
|
||||||
{
|
state_ = FadeState::POST;
|
||||||
state_ = FadeState::POST;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FadeType::CENTER:
|
case FadeType::CENTER: {
|
||||||
{
|
// Dibuja sobre el backbuffer_
|
||||||
// Dibuja sobre el backbuffer_
|
auto temp = SDL_GetRenderTarget(renderer_);
|
||||||
auto temp = SDL_GetRenderTarget(renderer_);
|
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
|
||||||
|
|
||||||
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
||||||
|
|
||||||
for (int i = 0; i < counter_; i++)
|
for (int i = 0; i < counter_; i++) {
|
||||||
{
|
rect1_.h = rect2_.h = i * 4;
|
||||||
rect1_.h = rect2_.h = i * 4;
|
rect2_.y = param.game.height - (i * 4);
|
||||||
rect2_.y = param.game.height - (i * 4);
|
|
||||||
|
|
||||||
SDL_RenderFillRect(renderer_, &rect1_);
|
SDL_RenderFillRect(renderer_, &rect1_);
|
||||||
SDL_RenderFillRect(renderer_, &rect2_);
|
SDL_RenderFillRect(renderer_, &rect2_);
|
||||||
|
|
||||||
value_ = calculateValue(0, counter_, i);
|
value_ = calculateValue(0, counter_, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deja el renderizador como estaba
|
// Deja el renderizador como estaba
|
||||||
SDL_SetRenderTarget(renderer_, temp);
|
SDL_SetRenderTarget(renderer_, temp);
|
||||||
|
|
||||||
// Comprueba si ha terminado
|
// Comprueba si ha terminado
|
||||||
if ((counter_ * 4) > param.game.height)
|
if ((counter_ * 4) > param.game.height) {
|
||||||
{
|
state_ = FadeState::POST;
|
||||||
state_ = FadeState::POST;
|
a_ = 255;
|
||||||
a_ = 255;
|
}
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
case FadeType::RANDOM_SQUARE:
|
case FadeType::RANDOM_SQUARE: {
|
||||||
{
|
if (counter_ % fade_random_squares_delay_ == 0) {
|
||||||
if (counter_ % fade_random_squares_delay_ == 0)
|
// Cambia el renderizador al backbuffer_ y modifica sus opciones
|
||||||
{
|
auto temp = SDL_GetRenderTarget(renderer_);
|
||||||
// Cambia el renderizador al backbuffer_ y modifica sus opciones
|
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||||
auto temp = SDL_GetRenderTarget(renderer_);
|
SDL_BlendMode blend_mode;
|
||||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
SDL_GetRenderDrawBlendMode(renderer_, &blend_mode);
|
||||||
SDL_BlendMode blend_mode;
|
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
|
||||||
SDL_GetRenderDrawBlendMode(renderer_, &blend_mode);
|
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
||||||
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
|
|
||||||
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
|
||||||
|
|
||||||
// Dibuja el cuadrado correspondiente
|
// Dibuja el cuadrado correspondiente
|
||||||
const int INDEX = std::min(counter_ / fade_random_squares_delay_, (num_squares_width_ * num_squares_height_) - 1);
|
const int INDEX = std::min(counter_ / fade_random_squares_delay_, (num_squares_width_ * num_squares_height_) - 1);
|
||||||
for (int i = 0; i < fade_random_squares_mult_; ++i)
|
for (int i = 0; i < fade_random_squares_mult_; ++i) {
|
||||||
{
|
const int INDEX2 = std::min(INDEX * fade_random_squares_mult_ + i, (int)square_.size() - 1);
|
||||||
const int INDEX2 = std::min(INDEX * fade_random_squares_mult_ + i, (int)square_.size() - 1);
|
SDL_RenderFillRect(renderer_, &square_[INDEX2]);
|
||||||
SDL_RenderFillRect(renderer_, &square_[INDEX2]);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Deja el renderizador como estaba
|
// Deja el renderizador como estaba
|
||||||
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
|
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
|
||||||
SDL_SetRenderTarget(renderer_, temp);
|
SDL_SetRenderTarget(renderer_, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
value_ = calculateValue(0, static_cast<int>(num_squares_width_ * num_squares_height_), static_cast<int>(counter_ * fade_random_squares_mult_ / fade_random_squares_delay_));
|
value_ = calculateValue(0, static_cast<int>(num_squares_width_ * num_squares_height_), static_cast<int>(counter_ * fade_random_squares_mult_ / fade_random_squares_delay_));
|
||||||
|
|
||||||
// Comprueba si ha terminado
|
// Comprueba si ha terminado
|
||||||
if (counter_ * fade_random_squares_mult_ / fade_random_squares_delay_ >= num_squares_width_ * num_squares_height_)
|
if (counter_ * fade_random_squares_mult_ / fade_random_squares_delay_ >= num_squares_width_ * num_squares_height_) {
|
||||||
{
|
state_ = FadeState::POST;
|
||||||
state_ = FadeState::POST;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FadeType::VENETIAN:
|
case FadeType::VENETIAN: {
|
||||||
{
|
// Counter debe ir de 0 a 150 <-- comprobar si esto es aún cierto
|
||||||
// Counter debe ir de 0 a 150 <-- comprobar si esto es aún cierto
|
if (square_.back().h < param.fade.venetian_size) {
|
||||||
if (square_.back().h < param.fade.venetian_size)
|
// Dibuja sobre el backbuffer_
|
||||||
{
|
auto temp = SDL_GetRenderTarget(renderer_);
|
||||||
// Dibuja sobre el backbuffer_
|
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||||
auto temp = SDL_GetRenderTarget(renderer_);
|
SDL_BlendMode blend_mode;
|
||||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
SDL_GetRenderDrawBlendMode(renderer_, &blend_mode);
|
||||||
SDL_BlendMode blend_mode;
|
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
|
||||||
SDL_GetRenderDrawBlendMode(renderer_, &blend_mode);
|
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
||||||
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_NONE);
|
|
||||||
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
|
|
||||||
|
|
||||||
// Dibuja el cuadrado correspondiente
|
// Dibuja el cuadrado correspondiente
|
||||||
for (const auto rect : square_)
|
for (const auto rect : square_) {
|
||||||
{
|
SDL_RenderFillRect(renderer_, &rect);
|
||||||
SDL_RenderFillRect(renderer_, &rect);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Deja el renderizador como estaba
|
// Deja el renderizador como estaba
|
||||||
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
|
SDL_SetRenderDrawBlendMode(renderer_, blend_mode);
|
||||||
SDL_SetRenderTarget(renderer_, temp);
|
SDL_SetRenderTarget(renderer_, temp);
|
||||||
|
|
||||||
// Modifica el tamaño de los rectangulos
|
// Modifica el tamaño de los rectangulos
|
||||||
const auto h = counter_ / 2;
|
const auto h = counter_ / 2;
|
||||||
for (size_t i = 0; i < square_.size(); ++i)
|
for (size_t i = 0; i < square_.size(); ++i) {
|
||||||
{
|
// A partir del segundo rectangulo se pinta en función del anterior
|
||||||
// A partir del segundo rectangulo se pinta en función del anterior
|
square_.at(i).h = i == 0 ? h : std::max(static_cast<int>(square_.at(i - 1).h) - 2, 0);
|
||||||
square_.at(i).h = i == 0 ? h : std::max(static_cast<int>(square_.at(i - 1).h) - 2, 0);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int completed = 0;
|
int completed = 0;
|
||||||
for (const auto &square : square_)
|
for (const auto &square : square_) {
|
||||||
{
|
if (square.h >= param.fade.venetian_size) {
|
||||||
if (square.h >= param.fade.venetian_size)
|
++completed;
|
||||||
{
|
}
|
||||||
++completed;
|
}
|
||||||
}
|
value_ = calculateValue(0, square_.size() - 1, completed);
|
||||||
}
|
} else {
|
||||||
value_ = calculateValue(0, square_.size() - 1, completed);
|
state_ = FadeState::POST;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
state_ = FadeState::POST;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
counter_++;
|
counter_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state_ == FadeState::POST)
|
if (state_ == FadeState::POST) {
|
||||||
{
|
// Actualiza el contador
|
||||||
// Actualiza el contador
|
if (post_counter_ == post_duration_) {
|
||||||
if (post_counter_ == post_duration_)
|
state_ = FadeState::FINISHED;
|
||||||
{
|
} else {
|
||||||
state_ = FadeState::FINISHED;
|
post_counter_++;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
post_counter_++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deja el backbuffer_ todo del mismo color
|
// Deja el backbuffer_ todo del mismo color
|
||||||
cleanBackbuffer(r_, g_, b_, a_);
|
cleanBackbuffer(r_, g_, b_, a_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activa el fade
|
// Activa el fade
|
||||||
void Fade::activate()
|
void Fade::activate() {
|
||||||
{
|
// Si ya está habilitado, no hay que volverlo a activar
|
||||||
// Si ya está habilitado, no hay que volverlo a activar
|
if (state_ != FadeState::NOT_ENABLED) {
|
||||||
if (state_ != FadeState::NOT_ENABLED)
|
return;
|
||||||
{
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
state_ = FadeState::PRE;
|
state_ = FadeState::PRE;
|
||||||
counter_ = 0;
|
counter_ = 0;
|
||||||
post_counter_ = 0;
|
post_counter_ = 0;
|
||||||
pre_counter_ = 0;
|
pre_counter_ = 0;
|
||||||
|
|
||||||
switch (type_)
|
switch (type_) {
|
||||||
{
|
case FadeType::FULLSCREEN: {
|
||||||
case FadeType::FULLSCREEN:
|
// Pinta el backbuffer_ de color sólido
|
||||||
{
|
cleanBackbuffer(r_, g_, b_, 255);
|
||||||
// Pinta el backbuffer_ de color sólido
|
break;
|
||||||
cleanBackbuffer(r_, g_, b_, 255);
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case FadeType::CENTER:
|
case FadeType::CENTER: {
|
||||||
{
|
rect1_ = {0, 0, static_cast<float>(param.game.width), 0};
|
||||||
rect1_ = {0, 0, static_cast<float>(param.game.width), 0};
|
rect2_ = {0, 0, static_cast<float>(param.game.width), 0};
|
||||||
rect2_ = {0, 0, static_cast<float>(param.game.width), 0};
|
a_ = 64;
|
||||||
a_ = 64;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
case FadeType::RANDOM_SQUARE:
|
case FadeType::RANDOM_SQUARE: {
|
||||||
{
|
rect1_ = {0, 0, static_cast<float>(param.game.width / num_squares_width_), static_cast<float>(param.game.height / num_squares_height_)};
|
||||||
rect1_ = {0, 0, static_cast<float>(param.game.width / num_squares_width_), static_cast<float>(param.game.height / num_squares_height_)};
|
square_.clear();
|
||||||
square_.clear();
|
|
||||||
|
|
||||||
// Añade los cuadrados al vector
|
// Añade los cuadrados al vector
|
||||||
for (int i = 0; i < num_squares_width_ * num_squares_height_; ++i)
|
for (int i = 0; i < num_squares_width_ * num_squares_height_; ++i) {
|
||||||
{
|
rect1_.x = (i % num_squares_width_) * rect1_.w;
|
||||||
rect1_.x = (i % num_squares_width_) * rect1_.w;
|
rect1_.y = (i / num_squares_width_) * rect1_.h;
|
||||||
rect1_.y = (i / num_squares_width_) * rect1_.h;
|
square_.push_back(rect1_);
|
||||||
square_.push_back(rect1_);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Desordena el vector de cuadrados
|
// Desordena el vector de cuadrados
|
||||||
auto num = num_squares_width_ * num_squares_height_;
|
auto num = num_squares_width_ * num_squares_height_;
|
||||||
while (num > 1)
|
while (num > 1) {
|
||||||
{
|
auto num_arreu = rand() % num;
|
||||||
auto num_arreu = rand() % num;
|
SDL_FRect temp = square_[num_arreu];
|
||||||
SDL_FRect temp = square_[num_arreu];
|
square_[num_arreu] = square_[num - 1];
|
||||||
square_[num_arreu] = square_[num - 1];
|
square_[num - 1] = temp;
|
||||||
square_[num - 1] = temp;
|
num--;
|
||||||
num--;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Limpia la textura
|
// Limpia la textura
|
||||||
a_ = mode_ == FadeMode::OUT ? 0 : 255;
|
a_ = mode_ == FadeMode::OUT ? 0 : 255;
|
||||||
cleanBackbuffer(r_, g_, b_, a_);
|
cleanBackbuffer(r_, g_, b_, a_);
|
||||||
|
|
||||||
// Deja el color listo para usar
|
// Deja el color listo para usar
|
||||||
a_ = mode_ == FadeMode::OUT ? 255 : 0;
|
a_ = mode_ == FadeMode::OUT ? 255 : 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case FadeType::VENETIAN:
|
case FadeType::VENETIAN: {
|
||||||
{
|
// Limpia la textura
|
||||||
// Limpia la textura
|
a_ = mode_ == FadeMode::OUT ? 0 : 255;
|
||||||
a_ = mode_ == FadeMode::OUT ? 0 : 255;
|
cleanBackbuffer(r_, g_, b_, a_);
|
||||||
cleanBackbuffer(r_, g_, b_, a_);
|
|
||||||
|
|
||||||
// Deja el color listo para usar
|
// Deja el color listo para usar
|
||||||
a_ = mode_ == FadeMode::OUT ? 255 : 0;
|
a_ = mode_ == FadeMode::OUT ? 255 : 0;
|
||||||
|
|
||||||
// Añade los cuadrados al vector
|
// Añade los cuadrados al vector
|
||||||
square_.clear();
|
square_.clear();
|
||||||
rect1_ = {0, 0, static_cast<float>(param.game.width), 0};
|
rect1_ = {0, 0, static_cast<float>(param.game.width), 0};
|
||||||
const int MAX = param.game.height / param.fade.venetian_size;
|
const int MAX = param.game.height / param.fade.venetian_size;
|
||||||
|
|
||||||
for (int i = 0; i < MAX; ++i)
|
for (int i = 0; i < MAX; ++i) {
|
||||||
{
|
rect1_.y = i * param.fade.venetian_size;
|
||||||
rect1_.y = i * param.fade.venetian_size;
|
square_.push_back(rect1_);
|
||||||
square_.push_back(rect1_);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el color del fade
|
// Establece el color del fade
|
||||||
void Fade::setColor(Uint8 r, Uint8 g, Uint8 b)
|
void Fade::setColor(Uint8 r, Uint8 g, Uint8 b) {
|
||||||
{
|
r_ = r;
|
||||||
r_ = r;
|
g_ = g;
|
||||||
g_ = g;
|
b_ = b;
|
||||||
b_ = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el color del fade
|
// Establece el color del fade
|
||||||
void Fade::setColor(Color color)
|
void Fade::setColor(Color color) {
|
||||||
{
|
r_ = color.r;
|
||||||
r_ = color.r;
|
g_ = color.g;
|
||||||
g_ = color.g;
|
b_ = color.b;
|
||||||
b_ = color.b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limpia el backbuffer
|
// Limpia el backbuffer
|
||||||
void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
|
void Fade::cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a) {
|
||||||
{
|
// Dibujamos sobre el backbuffer_
|
||||||
// Dibujamos sobre el backbuffer_
|
auto temp = SDL_GetRenderTarget(renderer_);
|
||||||
auto temp = SDL_GetRenderTarget(renderer_);
|
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
|
||||||
|
|
||||||
// Pintamos la textura con el color del fade
|
// Pintamos la textura con el color del fade
|
||||||
SDL_SetRenderDrawColor(renderer_, r, g, b, a);
|
SDL_SetRenderDrawColor(renderer_, r, g, b, a);
|
||||||
SDL_RenderClear(renderer_);
|
SDL_RenderClear(renderer_);
|
||||||
|
|
||||||
// Vuelve a dejar el renderizador como estaba
|
// Vuelve a dejar el renderizador como estaba
|
||||||
SDL_SetRenderTarget(renderer_, temp);
|
SDL_SetRenderTarget(renderer_, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calcula el valor del estado del fade
|
// Calcula el valor del estado del fade
|
||||||
int Fade::calculateValue(int min, int max, int current)
|
int Fade::calculateValue(int min, int max, int current) {
|
||||||
{
|
if (current < min) {
|
||||||
if (current < min)
|
return 0;
|
||||||
{
|
}
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current > max)
|
if (current > max) {
|
||||||
{
|
return 100;
|
||||||
return 100;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<int>(100.0 * (current - min) / (max - min));
|
return static_cast<int>(100.0 * (current - min) / (max - min));
|
||||||
}
|
}
|
||||||
+65
-68
@@ -1,93 +1,90 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para Uint8, SDL_FRect, SDL_Renderer, SDL_Texture, Uint16
|
#include <SDL3/SDL.h> // Para Uint8, SDL_FRect, SDL_Renderer, SDL_Texture, Uint16
|
||||||
#include <vector> // Para vector
|
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
struct Color;
|
struct Color;
|
||||||
|
|
||||||
// Tipos de fundido
|
// Tipos de fundido
|
||||||
enum class FadeType : Uint8
|
enum class FadeType : Uint8 {
|
||||||
{
|
FULLSCREEN = 0,
|
||||||
FULLSCREEN = 0,
|
CENTER = 1,
|
||||||
CENTER = 1,
|
RANDOM_SQUARE = 2,
|
||||||
RANDOM_SQUARE = 2,
|
VENETIAN = 3,
|
||||||
VENETIAN = 3,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Modos de fundido
|
// Modos de fundido
|
||||||
enum class FadeMode : Uint8
|
enum class FadeMode : Uint8 {
|
||||||
{
|
IN = 0,
|
||||||
IN = 0,
|
OUT = 1,
|
||||||
OUT = 1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Estados del objeto
|
// Estados del objeto
|
||||||
enum class FadeState : Uint8
|
enum class FadeState : Uint8 {
|
||||||
{
|
NOT_ENABLED = 0,
|
||||||
NOT_ENABLED = 0,
|
PRE = 1,
|
||||||
PRE = 1,
|
FADING = 2,
|
||||||
FADING = 2,
|
POST = 3,
|
||||||
POST = 3,
|
FINISHED = 4,
|
||||||
FINISHED = 4,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Fade
|
class Fade {
|
||||||
{
|
public:
|
||||||
public:
|
// --- Constructores y destructor ---
|
||||||
// --- Constructores y destructor ---
|
Fade();
|
||||||
Fade();
|
~Fade();
|
||||||
~Fade();
|
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
void reset(); // Resetea variables para reutilizar el fade
|
void reset(); // Resetea variables para reutilizar el fade
|
||||||
void render(); // Dibuja la transición en pantalla
|
void render(); // Dibuja la transición en pantalla
|
||||||
void update(); // Actualiza el estado interno
|
void update(); // Actualiza el estado interno
|
||||||
void activate(); // Activa el fade
|
void activate(); // Activa el fade
|
||||||
|
|
||||||
// --- Configuración ---
|
// --- Configuración ---
|
||||||
void setColor(Uint8 r, Uint8 g, Uint8 b);
|
void setColor(Uint8 r, Uint8 g, Uint8 b);
|
||||||
void setColor(Color color);
|
void setColor(Color color);
|
||||||
void setType(FadeType type) { type_ = type; }
|
void setType(FadeType type) { type_ = type; }
|
||||||
void setMode(FadeMode mode) { mode_ = mode; }
|
void setMode(FadeMode mode) { mode_ = mode; }
|
||||||
void setPostDuration(int value) { post_duration_ = value; }
|
void setPostDuration(int value) { post_duration_ = value; }
|
||||||
void setPreDuration(int value) { pre_duration_ = value; }
|
void setPreDuration(int value) { pre_duration_ = value; }
|
||||||
|
|
||||||
// --- Getters ---
|
// --- Getters ---
|
||||||
int getValue() const { return value_; }
|
int getValue() const { return value_; }
|
||||||
bool isEnabled() const { return state_ != FadeState::NOT_ENABLED; }
|
bool isEnabled() const { return state_ != FadeState::NOT_ENABLED; }
|
||||||
bool hasEnded() const { return state_ == FadeState::FINISHED; }
|
bool hasEnded() const { return state_ == FadeState::FINISHED; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
SDL_Renderer *renderer_; // Renderizador de la ventana
|
SDL_Renderer *renderer_; // Renderizador de la ventana
|
||||||
SDL_Texture *backbuffer_; // Backbuffer para efectos
|
SDL_Texture *backbuffer_; // Backbuffer para efectos
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
FadeType type_; // Tipo de fade
|
FadeType type_; // Tipo de fade
|
||||||
FadeMode mode_; // Modo de fade
|
FadeMode mode_; // Modo de fade
|
||||||
FadeState state_ = FadeState::NOT_ENABLED; // Estado actual
|
FadeState state_ = FadeState::NOT_ENABLED; // Estado actual
|
||||||
Uint16 counter_; // Contador interno
|
Uint16 counter_; // Contador interno
|
||||||
|
|
||||||
// --- Parámetros de color y geometría ---
|
// --- Parámetros de color y geometría ---
|
||||||
Uint8 r_, g_, b_, a_; // Color del fade
|
Uint8 r_, g_, b_, a_; // Color del fade
|
||||||
SDL_FRect rect1_, rect2_; // Rectángulos para efectos
|
SDL_FRect rect1_, rect2_; // Rectángulos para efectos
|
||||||
|
|
||||||
// --- Parámetros para RANDOM_SQUARE ---
|
// --- Parámetros para RANDOM_SQUARE ---
|
||||||
int num_squares_width_; // Cuadrados en horizontal
|
int num_squares_width_; // Cuadrados en horizontal
|
||||||
int num_squares_height_; // Cuadrados en vertical
|
int num_squares_height_; // Cuadrados en vertical
|
||||||
std::vector<SDL_FRect> square_; // Vector de cuadrados
|
std::vector<SDL_FRect> square_; // Vector de cuadrados
|
||||||
int fade_random_squares_delay_; // Delay entre cuadrados
|
int fade_random_squares_delay_; // Delay entre cuadrados
|
||||||
int fade_random_squares_mult_; // Cuadrados por paso
|
int fade_random_squares_mult_; // Cuadrados por paso
|
||||||
|
|
||||||
// --- Temporizadores ---
|
// --- Temporizadores ---
|
||||||
int post_duration_ = 0, post_counter_ = 0;
|
int post_duration_ = 0, post_counter_ = 0;
|
||||||
int pre_duration_ = 0, pre_counter_ = 0;
|
int pre_duration_ = 0, pre_counter_ = 0;
|
||||||
|
|
||||||
// --- Valor de progreso ---
|
// --- Valor de progreso ---
|
||||||
int value_ = 0; // Estado del fade (0-100)
|
int value_ = 0; // Estado del fade (0-100)
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void init(); // Inicializa variables
|
void init(); // Inicializa variables
|
||||||
void cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Limpia el backbuffer
|
void cleanBackbuffer(Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Limpia el backbuffer
|
||||||
int calculateValue(int min, int max, int current); // Calcula el valor del fade
|
int calculateValue(int min, int max, int current); // Calcula el valor del fade
|
||||||
};
|
};
|
||||||
+96
-124
@@ -1,18 +1,19 @@
|
|||||||
#include "game_logo.h"
|
#include "game_logo.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_SetTextureScaleMode, SDL_FlipMode
|
#include <SDL3/SDL.h> // Para SDL_SetTextureScaleMode, SDL_FlipMode
|
||||||
|
|
||||||
#include <algorithm> // Para max
|
#include <algorithm> // Para max
|
||||||
#include <string> // Para basic_string
|
#include <string> // Para basic_string
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
#include "audio.h" // Para Audio
|
#include "audio.h" // Para Audio
|
||||||
#include "param.h" // Para Param, param, ParamGame, ParamTitle
|
#include "param.h" // Para Param, param, ParamGame, ParamTitle
|
||||||
#include "resource.h" // Para Resource
|
#include "resource.h" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "screen.h" // Para Screen
|
||||||
#include "smart_sprite.h" // Para SmartSprite
|
#include "smart_sprite.h" // Para SmartSprite
|
||||||
#include "sprite.h" // Para Sprite
|
#include "sprite.h" // Para Sprite
|
||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
#include "utils.h" // Para Color
|
#include "utils.h" // Para Color
|
||||||
|
|
||||||
constexpr int ZOOM_FACTOR = 5;
|
constexpr int ZOOM_FACTOR = 5;
|
||||||
constexpr int FLASH_DELAY = 3;
|
constexpr int FLASH_DELAY = 3;
|
||||||
@@ -33,8 +34,7 @@ GameLogo::GameLogo(int x, int y)
|
|||||||
y_(y) {}
|
y_(y) {}
|
||||||
|
|
||||||
// Inicializa las variables
|
// Inicializa las variables
|
||||||
void GameLogo::init()
|
void GameLogo::init() {
|
||||||
{
|
|
||||||
const auto xp = x_ - coffee_texture_->getWidth() / 2;
|
const auto xp = x_ - coffee_texture_->getWidth() / 2;
|
||||||
const auto desp = getInitialVerticalDesp();
|
const auto desp = getInitialVerticalDesp();
|
||||||
|
|
||||||
@@ -97,14 +97,12 @@ void GameLogo::init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pinta la clase en pantalla
|
// Pinta la clase en pantalla
|
||||||
void GameLogo::render()
|
void GameLogo::render() {
|
||||||
{
|
|
||||||
// Dibuja el logo
|
// Dibuja el logo
|
||||||
coffee_sprite_->render();
|
coffee_sprite_->render();
|
||||||
crisis_sprite_->render();
|
crisis_sprite_->render();
|
||||||
|
|
||||||
if (arcade_edition_status_ != Status::DISABLED)
|
if (arcade_edition_status_ != Status::DISABLED) {
|
||||||
{
|
|
||||||
arcade_edition_sprite_->render();
|
arcade_edition_sprite_->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,145 +112,119 @@ void GameLogo::render()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza la lógica de la clase
|
// Actualiza la lógica de la clase
|
||||||
void GameLogo::update()
|
void GameLogo::update() {
|
||||||
{
|
switch (coffee_crisis_status_) {
|
||||||
switch (coffee_crisis_status_)
|
case Status::MOVING: {
|
||||||
{
|
coffee_sprite_->update();
|
||||||
case Status::MOVING:
|
crisis_sprite_->update();
|
||||||
{
|
|
||||||
coffee_sprite_->update();
|
|
||||||
crisis_sprite_->update();
|
|
||||||
|
|
||||||
// Si los objetos han llegado a su destino, cambia el estado
|
// Si los objetos han llegado a su destino, cambia el estado
|
||||||
if (coffee_sprite_->hasFinished() && crisis_sprite_->hasFinished())
|
if (coffee_sprite_->hasFinished() && crisis_sprite_->hasFinished()) {
|
||||||
{
|
coffee_crisis_status_ = Status::SHAKING;
|
||||||
coffee_crisis_status_ = Status::SHAKING;
|
|
||||||
|
|
||||||
// Reproduce el efecto sonoro
|
// Reproduce el efecto sonoro
|
||||||
Audio::get()->playSound("title.wav");
|
Audio::get()->playSound("title.wav");
|
||||||
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
|
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
|
||||||
Screen::get()->shake();
|
Screen::get()->shake();
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Status::SHAKING:
|
|
||||||
{
|
|
||||||
// Agita "COFFEE CRISIS"
|
|
||||||
if (shake_.remaining > 0)
|
|
||||||
{
|
|
||||||
if (shake_.counter > 0)
|
|
||||||
{
|
|
||||||
shake_.counter--;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
break;
|
||||||
shake_.counter = shake_.delay;
|
}
|
||||||
const auto desp = shake_.remaining % 2 == 0 ? shake_.desp * (-1) : shake_.desp;
|
|
||||||
coffee_sprite_->setPosX(shake_.origin + desp);
|
case Status::SHAKING: {
|
||||||
crisis_sprite_->setPosX(shake_.origin + desp + 15);
|
// Agita "COFFEE CRISIS"
|
||||||
shake_.remaining--;
|
if (shake_.remaining > 0) {
|
||||||
|
if (shake_.counter > 0) {
|
||||||
|
shake_.counter--;
|
||||||
|
} else {
|
||||||
|
shake_.counter = shake_.delay;
|
||||||
|
const auto desp = shake_.remaining % 2 == 0 ? shake_.desp * (-1) : shake_.desp;
|
||||||
|
coffee_sprite_->setPosX(shake_.origin + desp);
|
||||||
|
crisis_sprite_->setPosX(shake_.origin + desp + 15);
|
||||||
|
shake_.remaining--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
coffee_sprite_->setPosX(shake_.origin);
|
||||||
|
crisis_sprite_->setPosX(shake_.origin + 15);
|
||||||
|
coffee_crisis_status_ = Status::FINISHED;
|
||||||
|
arcade_edition_status_ = Status::MOVING;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
dust_right_sprite_->update();
|
||||||
{
|
dust_left_sprite_->update();
|
||||||
coffee_sprite_->setPosX(shake_.origin);
|
|
||||||
crisis_sprite_->setPosX(shake_.origin + 15);
|
break;
|
||||||
coffee_crisis_status_ = Status::FINISHED;
|
|
||||||
arcade_edition_status_ = Status::MOVING;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dust_right_sprite_->update();
|
case Status::FINISHED: {
|
||||||
dust_left_sprite_->update();
|
dust_right_sprite_->update();
|
||||||
|
dust_left_sprite_->update();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Status::FINISHED:
|
switch (arcade_edition_status_) {
|
||||||
{
|
case Status::MOVING: {
|
||||||
dust_right_sprite_->update();
|
zoom_ -= 0.1f * ZOOM_FACTOR;
|
||||||
dust_left_sprite_->update();
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (arcade_edition_status_)
|
|
||||||
{
|
|
||||||
case Status::MOVING:
|
|
||||||
{
|
|
||||||
zoom_ -= 0.1f * ZOOM_FACTOR;
|
|
||||||
arcade_edition_sprite_->setZoom(zoom_);
|
|
||||||
if (zoom_ <= 1.0f)
|
|
||||||
{
|
|
||||||
arcade_edition_status_ = Status::SHAKING;
|
|
||||||
zoom_ = 1.0f;
|
|
||||||
arcade_edition_sprite_->setZoom(zoom_);
|
arcade_edition_sprite_->setZoom(zoom_);
|
||||||
shake_.init(1, 2, 8, arcade_edition_sprite_->getX());
|
if (zoom_ <= 1.0f) {
|
||||||
Audio::get()->playSound("title.wav");
|
arcade_edition_status_ = Status::SHAKING;
|
||||||
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
|
zoom_ = 1.0f;
|
||||||
Screen::get()->shake();
|
arcade_edition_sprite_->setZoom(zoom_);
|
||||||
}
|
shake_.init(1, 2, 8, arcade_edition_sprite_->getX());
|
||||||
break;
|
Audio::get()->playSound("title.wav");
|
||||||
}
|
Screen::get()->flash(Color(0xFF, 0xFF, 0xFF), FLASH_LENGHT, FLASH_DELAY);
|
||||||
|
Screen::get()->shake();
|
||||||
case Status::SHAKING:
|
|
||||||
{
|
|
||||||
// Agita "ARCADE EDITION"
|
|
||||||
if (shake_.remaining > 0)
|
|
||||||
{
|
|
||||||
if (shake_.counter > 0)
|
|
||||||
{
|
|
||||||
shake_.counter--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shake_.counter = shake_.delay;
|
|
||||||
const auto desp = shake_.remaining % 2 == 0 ? shake_.desp * (-1) : shake_.desp;
|
|
||||||
arcade_edition_sprite_->setX(shake_.origin + desp);
|
|
||||||
shake_.remaining--;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
arcade_edition_sprite_->setX(shake_.origin);
|
|
||||||
arcade_edition_status_ = Status::FINISHED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
case Status::SHAKING: {
|
||||||
break;
|
// Agita "ARCADE EDITION"
|
||||||
|
if (shake_.remaining > 0) {
|
||||||
|
if (shake_.counter > 0) {
|
||||||
|
shake_.counter--;
|
||||||
|
} else {
|
||||||
|
shake_.counter = shake_.delay;
|
||||||
|
const auto desp = shake_.remaining % 2 == 0 ? shake_.desp * (-1) : shake_.desp;
|
||||||
|
arcade_edition_sprite_->setX(shake_.origin + desp);
|
||||||
|
shake_.remaining--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
arcade_edition_sprite_->setX(shake_.origin);
|
||||||
|
arcade_edition_status_ = Status::FINISHED;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coffee_crisis_status_ == Status::FINISHED &&
|
if (coffee_crisis_status_ == Status::FINISHED &&
|
||||||
arcade_edition_status_ == Status::FINISHED &&
|
arcade_edition_status_ == Status::FINISHED &&
|
||||||
post_finished_counter_ > 0)
|
post_finished_counter_ > 0) {
|
||||||
{
|
|
||||||
--post_finished_counter_;
|
--post_finished_counter_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activa la clase
|
// Activa la clase
|
||||||
void GameLogo::enable()
|
void GameLogo::enable() {
|
||||||
{
|
|
||||||
init();
|
init();
|
||||||
coffee_crisis_status_ = Status::MOVING;
|
coffee_crisis_status_ = Status::MOVING;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indica si ha terminado la animación
|
// Indica si ha terminado la animación
|
||||||
bool GameLogo::hasFinished() const
|
bool GameLogo::hasFinished() const {
|
||||||
{
|
|
||||||
return post_finished_counter_ == 0;
|
return post_finished_counter_ == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calcula el desplazamiento vertical inicial
|
// Calcula el desplazamiento vertical inicial
|
||||||
int GameLogo::getInitialVerticalDesp()
|
int GameLogo::getInitialVerticalDesp() {
|
||||||
{
|
|
||||||
const float OFFSET_UP = y_;
|
const float OFFSET_UP = y_;
|
||||||
const float OFFSET_DOWN = param.game.height - y_;
|
const float OFFSET_DOWN = param.game.height - y_;
|
||||||
|
|
||||||
|
|||||||
+38
-42
@@ -1,54 +1,50 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory> // Para unique_ptr, shared_ptr
|
#include <memory> // Para unique_ptr, shared_ptr
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
#include "smart_sprite.h" // Para SmartSprite
|
#include "smart_sprite.h" // Para SmartSprite
|
||||||
#include "sprite.h" // Para Sprite
|
#include "sprite.h" // Para Sprite
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Clase GameLogo
|
// Clase GameLogo
|
||||||
class GameLogo
|
class GameLogo {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor ---
|
||||||
GameLogo(int x, int y);
|
GameLogo(int x, int y);
|
||||||
~GameLogo() = default;
|
~GameLogo() = default;
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
void render(); // Pinta la clase en pantalla
|
void render(); // Pinta la clase en pantalla
|
||||||
void update(); // Actualiza la lógica de la clase
|
void update(); // Actualiza la lógica de la clase
|
||||||
void enable(); // Activa la clase
|
void enable(); // Activa la clase
|
||||||
|
|
||||||
// --- Getters ---
|
// --- Getters ---
|
||||||
bool hasFinished() const; // Indica si ha terminado la animación
|
bool hasFinished() const; // Indica si ha terminado la animación
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Tipos internos ---
|
// --- Tipos internos ---
|
||||||
enum class Status
|
enum class Status {
|
||||||
{
|
|
||||||
DISABLED,
|
DISABLED,
|
||||||
MOVING,
|
MOVING,
|
||||||
SHAKING,
|
SHAKING,
|
||||||
FINISHED,
|
FINISHED,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Shake
|
struct Shake {
|
||||||
{
|
int desp = 1; // Pixels de desplazamiento para agitar la pantalla en el eje x
|
||||||
int desp = 1; // Pixels de desplazamiento para agitar la pantalla en el eje x
|
int delay = 2; // Retraso entre cada desplazamiento de la pantalla al agitarse
|
||||||
int delay = 2; // Retraso entre cada desplazamiento de la pantalla al agitarse
|
int lenght = 8; // Cantidad de desplazamientos a realizar
|
||||||
int lenght = 8; // Cantidad de desplazamientos a realizar
|
int remaining = lenght; // Cantidad de desplazamientos pendientes a realizar
|
||||||
int remaining = lenght; // Cantidad de desplazamientos pendientes a realizar
|
int counter = delay; // Contador para el retraso
|
||||||
int counter = delay; // Contador para el retraso
|
int origin = 0; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
|
||||||
int origin = 0; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
|
|
||||||
|
|
||||||
Shake() = default;
|
Shake() = default;
|
||||||
Shake(int d, int de, int l, int o)
|
Shake(int d, int de, int l, int o)
|
||||||
: desp(d), delay(de), lenght(l), remaining(l), counter(de), origin(o) {}
|
: desp(d), delay(de), lenght(l), remaining(l), counter(de), origin(o) {}
|
||||||
|
|
||||||
void init(int d, int de, int l, int o)
|
void init(int d, int de, int l, int o) {
|
||||||
{
|
|
||||||
desp = d;
|
desp = d;
|
||||||
delay = de;
|
delay = de;
|
||||||
lenght = l;
|
lenght = l;
|
||||||
@@ -59,28 +55,28 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
std::shared_ptr<Texture> dust_texture_; // Textura con los graficos del polvo
|
std::shared_ptr<Texture> dust_texture_; // Textura con los graficos del polvo
|
||||||
std::shared_ptr<Texture> coffee_texture_; // Textura con los graficos de la palabra "COFFEE"
|
std::shared_ptr<Texture> coffee_texture_; // Textura con los graficos de la palabra "COFFEE"
|
||||||
std::shared_ptr<Texture> crisis_texture_; // Textura con los graficos de la palabra "CRISIS"
|
std::shared_ptr<Texture> crisis_texture_; // Textura con los graficos de la palabra "CRISIS"
|
||||||
std::shared_ptr<Texture> arcade_edition_texture_; // Textura con los graficos de "Arcade Edition"
|
std::shared_ptr<Texture> arcade_edition_texture_; // Textura con los graficos de "Arcade Edition"
|
||||||
|
|
||||||
std::unique_ptr<AnimatedSprite> dust_left_sprite_; // Sprite del polvo (izquierda)
|
std::unique_ptr<AnimatedSprite> dust_left_sprite_; // Sprite del polvo (izquierda)
|
||||||
std::unique_ptr<AnimatedSprite> dust_right_sprite_; // Sprite del polvo (derecha)
|
std::unique_ptr<AnimatedSprite> dust_right_sprite_; // Sprite del polvo (derecha)
|
||||||
std::unique_ptr<SmartSprite> coffee_sprite_; // Sprite de "COFFEE"
|
std::unique_ptr<SmartSprite> coffee_sprite_; // Sprite de "COFFEE"
|
||||||
std::unique_ptr<SmartSprite> crisis_sprite_; // Sprite de "CRISIS"
|
std::unique_ptr<SmartSprite> crisis_sprite_; // Sprite de "CRISIS"
|
||||||
std::unique_ptr<Sprite> arcade_edition_sprite_; // Sprite de "Arcade Edition"
|
std::unique_ptr<Sprite> arcade_edition_sprite_; // Sprite de "Arcade Edition"
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
float x_; // Posición X del logo
|
float x_; // Posición X del logo
|
||||||
float y_; // Posición Y del logo
|
float y_; // Posición Y del logo
|
||||||
float zoom_ = 1.0f; // Zoom aplicado al texto "ARCADE EDITION"
|
float zoom_ = 1.0f; // Zoom aplicado al texto "ARCADE EDITION"
|
||||||
int post_finished_counter_ = 1; // Contador final tras animaciones
|
int post_finished_counter_ = 1; // Contador final tras animaciones
|
||||||
|
|
||||||
Status coffee_crisis_status_ = Status::DISABLED; // Estado de "COFFEE CRISIS"
|
Status coffee_crisis_status_ = Status::DISABLED; // Estado de "COFFEE CRISIS"
|
||||||
Status arcade_edition_status_ = Status::DISABLED; // Estado de "ARCADE EDITION"
|
Status arcade_edition_status_ = Status::DISABLED; // Estado de "ARCADE EDITION"
|
||||||
Shake shake_; // Efecto de agitación
|
Shake shake_; // Efecto de agitación
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void init(); // Inicializa las variables
|
void init(); // Inicializa las variables
|
||||||
int getInitialVerticalDesp(); // Calcula el desplazamiento vertical inicial
|
int getInitialVerticalDesp(); // Calcula el desplazamiento vertical inicial
|
||||||
};
|
};
|
||||||
+11
-14
@@ -1,19 +1,16 @@
|
|||||||
#include "global_events.h"
|
#include "global_events.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory
|
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory
|
||||||
|
|
||||||
#include "mouse.h" // Para handleEvent
|
#include "mouse.h" // Para handleEvent
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "section.h" // Para Name, Options, name, options
|
#include "section.h" // Para Name, Options, name, options
|
||||||
|
|
||||||
namespace GlobalEvents
|
namespace GlobalEvents {
|
||||||
{
|
// Comprueba los eventos que se pueden producir en cualquier sección del juego
|
||||||
// Comprueba los eventos que se pueden producir en cualquier sección del juego
|
void check(const SDL_Event &event) {
|
||||||
void check(const SDL_Event &event)
|
switch (event.type) {
|
||||||
{
|
case SDL_EVENT_QUIT: // Evento de salida de la aplicación
|
||||||
switch (event.type)
|
|
||||||
{
|
|
||||||
case SDL_EVENT_QUIT: // Evento de salida de la aplicación
|
|
||||||
Section::name = Section::Name::QUIT;
|
Section::name = Section::Name::QUIT;
|
||||||
Section::options = Section::Options::NONE;
|
Section::options = Section::Options::NONE;
|
||||||
return;
|
return;
|
||||||
@@ -29,8 +26,8 @@ namespace GlobalEvents
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
Mouse::handleEvent(event);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
Mouse::handleEvent(event);
|
||||||
|
}
|
||||||
|
} // namespace GlobalEvents
|
||||||
@@ -2,8 +2,7 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
namespace GlobalEvents
|
namespace GlobalEvents {
|
||||||
{
|
// Comprueba los eventos que se pueden producir en cualquier sección del juego
|
||||||
// Comprueba los eventos que se pueden producir en cualquier sección del juego
|
void check(const SDL_Event &event);
|
||||||
void check(const SDL_Event &event);
|
} // namespace GlobalEvents
|
||||||
}
|
|
||||||
+261
-327
@@ -1,87 +1,72 @@
|
|||||||
#include "global_inputs.h"
|
#include "global_inputs.h"
|
||||||
|
|
||||||
#include <string> // Para basic_string, operator+, allocator, cha...
|
#include <string> // Para basic_string, operator+, allocator, cha...
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "asset.h" // Para Asset
|
#include "asset.h" // Para Asset
|
||||||
#include "audio.h" // Para Audio
|
#include "audio.h" // Para Audio
|
||||||
#include "input.h" // Para Input, INPUT_DO_NOT_ALLOW_REPEAT, Input...
|
#include "input.h" // Para Input, INPUT_DO_NOT_ALLOW_REPEAT, Input...
|
||||||
#include "lang.h" // Para getText, Code, getNextLangCode, loadFro...
|
#include "lang.h" // Para getText, Code, getNextLangCode, loadFro...
|
||||||
#include "notifier.h" // Para Notifier
|
#include "notifier.h" // Para Notifier
|
||||||
#include "options.h" // Para SettingsOptions, settings, VideoOptions
|
#include "options.h" // Para SettingsOptions, settings, VideoOptions
|
||||||
#include "screen.h" // Para Screen
|
#include "screen.h" // Para Screen
|
||||||
#include "section.h" // Para Name, name, Options, options, AttractMode
|
#include "section.h" // Para Name, name, Options, options, AttractMode
|
||||||
#include "ui/service_menu.h" // Para ServiceMenu
|
#include "ui/service_menu.h" // Para ServiceMenu
|
||||||
#include "utils.h" // Para boolToOnOff
|
#include "utils.h" // Para boolToOnOff
|
||||||
|
|
||||||
namespace GlobalInputs
|
namespace GlobalInputs {
|
||||||
{
|
// Termina
|
||||||
// Termina
|
void quit() {
|
||||||
void quit()
|
const std::string CODE = "QUIT";
|
||||||
{
|
if (Notifier::get()->checkCode(CODE)) {
|
||||||
const std::string CODE = "QUIT";
|
// Si la notificación de salir está activa, cambia de sección
|
||||||
if (Notifier::get()->checkCode(CODE))
|
Section::name = Section::Name::QUIT;
|
||||||
{
|
Section::options = Section::Options::NONE;
|
||||||
// Si la notificación de salir está activa, cambia de sección
|
} else {
|
||||||
Section::name = Section::Name::QUIT;
|
// Si la notificación de salir no está activa, muestra la notificación
|
||||||
Section::options = Section::Options::NONE;
|
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 01"), std::string()}, -1, CODE);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Si la notificación de salir no está activa, muestra la notificación
|
|
||||||
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 01"), std::string()}, -1, CODE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Reinicia
|
// Reinicia
|
||||||
void reset()
|
void reset() {
|
||||||
{
|
const std::string CODE = "RESET";
|
||||||
const std::string CODE = "RESET";
|
if (Notifier::get()->checkCode(CODE)) {
|
||||||
if (Notifier::get()->checkCode(CODE))
|
Section::name = Section::Name::RESET;
|
||||||
{
|
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 15")});
|
||||||
Section::name = Section::Name::RESET;
|
} else {
|
||||||
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 15")});
|
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 03"), std::string()}, -1, CODE);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 03"), std::string()}, -1, CODE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Activa o desactiva el audio
|
// Activa o desactiva el audio
|
||||||
void toggleAudio()
|
void toggleAudio() {
|
||||||
{
|
Options::audio.enabled = !Options::audio.enabled;
|
||||||
Options::audio.enabled = !Options::audio.enabled;
|
Audio::get()->enable(Options::audio.enabled);
|
||||||
Audio::get()->enable(Options::audio.enabled);
|
Notifier::get()->show({"Audio " + boolToOnOff(Options::audio.enabled)});
|
||||||
Notifier::get()->show({"Audio " + boolToOnOff(Options::audio.enabled)});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Cambia el modo de escalado entero
|
// Cambia el modo de escalado entero
|
||||||
void toggleIntegerScale()
|
void toggleIntegerScale() {
|
||||||
{
|
Screen::get()->toggleIntegerScale();
|
||||||
Screen::get()->toggleIntegerScale();
|
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 12") + " " + boolToOnOff(Options::video.integer_scale)});
|
||||||
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 12") + " " + boolToOnOff(Options::video.integer_scale)});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Activa / desactiva el vsync
|
// Activa / desactiva el vsync
|
||||||
void toggleVSync()
|
void toggleVSync() {
|
||||||
{
|
Screen::get()->toggleVSync();
|
||||||
Screen::get()->toggleVSync();
|
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 14") + " " + boolToOnOff(Options::video.v_sync)});
|
||||||
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 14") + " " + boolToOnOff(Options::video.v_sync)});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Activa o desactiva los shaders
|
// Activa o desactiva los shaders
|
||||||
void toggleShaders()
|
void toggleShaders() {
|
||||||
{
|
Screen::get()->toggleShaders();
|
||||||
Screen::get()->toggleShaders();
|
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 13") + " " + boolToOnOff(Options::video.shaders)});
|
||||||
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 13") + " " + boolToOnOff(Options::video.shaders)});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Obtiene una fichero a partir de un lang::Code
|
// Obtiene una fichero a partir de un lang::Code
|
||||||
std::string getLangFile(Lang::Code code)
|
std::string getLangFile(Lang::Code code) {
|
||||||
{
|
switch (code) {
|
||||||
switch (code)
|
|
||||||
{
|
|
||||||
case Lang::Code::VALENCIAN:
|
case Lang::Code::VALENCIAN:
|
||||||
return Asset::get()->get("ba_BA.json");
|
return Asset::get()->get("ba_BA.json");
|
||||||
break;
|
break;
|
||||||
@@ -91,14 +76,12 @@ namespace GlobalInputs
|
|||||||
default:
|
default:
|
||||||
return Asset::get()->get("en_UK.json");
|
return Asset::get()->get("en_UK.json");
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Obtiene una cadena a partir de un lang::Code
|
// Obtiene una cadena a partir de un lang::Code
|
||||||
std::string getLangName(Lang::Code code)
|
std::string getLangName(Lang::Code code) {
|
||||||
{
|
switch (code) {
|
||||||
switch (code)
|
|
||||||
{
|
|
||||||
case Lang::Code::VALENCIAN:
|
case Lang::Code::VALENCIAN:
|
||||||
return " \"ba_BA\"";
|
return " \"ba_BA\"";
|
||||||
break;
|
break;
|
||||||
@@ -108,47 +91,39 @@ namespace GlobalInputs
|
|||||||
default:
|
default:
|
||||||
return " \"en_UK\"";
|
return " \"en_UK\"";
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Cambia el idioma
|
// Cambia el idioma
|
||||||
void changeLang()
|
void changeLang() {
|
||||||
{
|
const std::string CODE = "LANG";
|
||||||
const std::string CODE = "LANG";
|
if (Notifier::get()->checkCode(CODE)) {
|
||||||
if (Notifier::get()->checkCode(CODE))
|
Options::settings.language = Lang::getNextLangCode(Options::settings.language);
|
||||||
{
|
Lang::loadFromFile(getLangFile(static_cast<Lang::Code>(Options::settings.language)));
|
||||||
Options::settings.language = Lang::getNextLangCode(Options::settings.language);
|
Section::name = Section::Name::RESET;
|
||||||
Lang::loadFromFile(getLangFile(static_cast<Lang::Code>(Options::settings.language)));
|
Section::options = Section::Options::RELOAD;
|
||||||
Section::name = Section::Name::RESET;
|
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 05") + getLangName(Options::settings.language)});
|
||||||
Section::options = Section::Options::RELOAD;
|
} else {
|
||||||
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 05") + getLangName(Options::settings.language)});
|
const auto NEXT = Lang::getNextLangCode(Options::settings.language);
|
||||||
}
|
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 04") + getLangName(NEXT), std::string()}, -1, CODE);
|
||||||
else
|
|
||||||
{
|
|
||||||
const auto NEXT = Lang::getNextLangCode(Options::settings.language);
|
|
||||||
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 04") + getLangName(NEXT), std::string()}, -1, CODE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Cambia el modo de disparo
|
// Cambia el modo de disparo
|
||||||
void toggleFireMode()
|
void toggleFireMode() {
|
||||||
{
|
Options::settings.autofire = !Options::settings.autofire;
|
||||||
Options::settings.autofire = !Options::settings.autofire;
|
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 08") + " " + boolToOnOff(Options::settings.autofire)});
|
||||||
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 08") + " " + boolToOnOff(Options::settings.autofire)});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Salta una sección del juego
|
// Salta una sección del juego
|
||||||
void skipSection()
|
void skipSection() {
|
||||||
{
|
switch (Section::name) {
|
||||||
switch (Section::name)
|
|
||||||
{
|
|
||||||
case Section::Name::INTRO:
|
case Section::Name::INTRO:
|
||||||
Audio::get()->stopMusic();
|
Audio::get()->stopMusic();
|
||||||
/* Continua en el case de abajo */
|
/* Continua en el case de abajo */
|
||||||
case Section::Name::LOGO:
|
case Section::Name::LOGO:
|
||||||
case Section::Name::HI_SCORE_TABLE:
|
case Section::Name::HI_SCORE_TABLE:
|
||||||
case Section::Name::INSTRUCTIONS:
|
case Section::Name::INSTRUCTIONS: {
|
||||||
{
|
|
||||||
Section::name = Section::Name::TITLE;
|
Section::name = Section::Name::TITLE;
|
||||||
Section::options = Section::Options::TITLE_1;
|
Section::options = Section::Options::TITLE_1;
|
||||||
Section::attract_mode = Section::AttractMode::TITLE_TO_DEMO;
|
Section::attract_mode = Section::AttractMode::TITLE_TO_DEMO;
|
||||||
@@ -156,284 +131,243 @@ namespace GlobalInputs
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activa el menu de servicio
|
||||||
|
void toggleServiceMenu() {
|
||||||
|
ServiceMenu::get()->toggle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cambia el modo de pantalla completa
|
||||||
|
void toggleFullscreen() {
|
||||||
|
Screen::get()->toggleFullscreen();
|
||||||
|
const std::string MODE = Options::video.fullscreen ? Lang::getText("[NOTIFICATIONS] 11") : Lang::getText("[NOTIFICATIONS] 10");
|
||||||
|
Notifier::get()->show({MODE});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reduce el tamaño de la ventana
|
||||||
|
void decWindowSize() {
|
||||||
|
if (Screen::get()->decWindowSize()) {
|
||||||
|
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.size)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aumenta el tamaño de la ventana
|
||||||
|
void incWindowSize() {
|
||||||
|
if (Screen::get()->incWindowSize()) {
|
||||||
|
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.size)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Comprueba el boton de servicio
|
||||||
|
bool checkServiceButton() {
|
||||||
|
// Teclado
|
||||||
|
if (Input::get()->checkInput(InputAction::SERVICE, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
|
toggleServiceMenu();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mandos
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Input::get()->getNumControllers(); ++i) {
|
||||||
|
if (Input::get()->checkInput(InputAction::SERVICE, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i)) {
|
||||||
|
toggleServiceMenu();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Activa el menu de servicio
|
// Comprueba las entradas del menú de servicio
|
||||||
void toggleServiceMenu()
|
bool checkServiceInputs() {
|
||||||
{
|
if (!ServiceMenu::get()->isEnabled())
|
||||||
ServiceMenu::get()->toggle();
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
// Cambia el modo de pantalla completa
|
// Teclado
|
||||||
void toggleFullscreen()
|
|
||||||
{
|
{
|
||||||
Screen::get()->toggleFullscreen();
|
// Arriba
|
||||||
const std::string MODE = Options::video.fullscreen ? Lang::getText("[NOTIFICATIONS] 11") : Lang::getText("[NOTIFICATIONS] 10");
|
if (Input::get()->checkInput(InputAction::UP, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
Notifier::get()->show({MODE});
|
ServiceMenu::get()->setSelectorUp();
|
||||||
}
|
|
||||||
|
|
||||||
// Reduce el tamaño de la ventana
|
|
||||||
void decWindowSize()
|
|
||||||
{
|
|
||||||
if (Screen::get()->decWindowSize())
|
|
||||||
{
|
|
||||||
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.size)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Aumenta el tamaño de la ventana
|
|
||||||
void incWindowSize()
|
|
||||||
{
|
|
||||||
if (Screen::get()->incWindowSize())
|
|
||||||
{
|
|
||||||
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.size)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba el boton de servicio
|
|
||||||
bool checkServiceButton()
|
|
||||||
{
|
|
||||||
// Teclado
|
|
||||||
if (Input::get()->checkInput(InputAction::SERVICE, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
|
||||||
{
|
|
||||||
toggleServiceMenu();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mandos
|
// Abajo
|
||||||
{
|
if (Input::get()->checkInput(InputAction::DOWN, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
for (int i = 0; i < Input::get()->getNumControllers(); ++i)
|
ServiceMenu::get()->setSelectorDown();
|
||||||
{
|
return true;
|
||||||
if (Input::get()->checkInput(InputAction::SERVICE, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i))
|
}
|
||||||
{
|
|
||||||
toggleServiceMenu();
|
// Derecha
|
||||||
return true;
|
if (Input::get()->checkInput(InputAction::RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
}
|
ServiceMenu::get()->adjustOption(true);
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Izquierda
|
||||||
|
if (Input::get()->checkInput(InputAction::LEFT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
|
ServiceMenu::get()->adjustOption(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aceptar
|
||||||
|
if (Input::get()->checkInput(InputAction::SM_SELECT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
|
ServiceMenu::get()->selectOption();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Atras
|
||||||
|
if (Input::get()->checkInput(InputAction::SM_BACK, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
|
ServiceMenu::get()->moveBack();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba las entradas del menú de servicio
|
// Mandos
|
||||||
bool checkServiceInputs()
|
|
||||||
{
|
{
|
||||||
if (!ServiceMenu::get()->isEnabled())
|
for (int i = 0; i < Input::get()->getNumControllers(); ++i) {
|
||||||
return false;
|
|
||||||
|
|
||||||
// Teclado
|
|
||||||
{
|
|
||||||
// Arriba
|
// Arriba
|
||||||
if (Input::get()->checkInput(InputAction::UP, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::UP, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i)) {
|
||||||
{
|
|
||||||
ServiceMenu::get()->setSelectorUp();
|
ServiceMenu::get()->setSelectorUp();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Abajo
|
// Abajo
|
||||||
if (Input::get()->checkInput(InputAction::DOWN, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::DOWN, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i)) {
|
||||||
{
|
|
||||||
ServiceMenu::get()->setSelectorDown();
|
ServiceMenu::get()->setSelectorDown();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Derecha
|
// Derecha
|
||||||
if (Input::get()->checkInput(InputAction::RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i)) {
|
||||||
{
|
|
||||||
ServiceMenu::get()->adjustOption(true);
|
ServiceMenu::get()->adjustOption(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Izquierda
|
// Izquierda
|
||||||
if (Input::get()->checkInput(InputAction::LEFT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::LEFT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i)) {
|
||||||
{
|
|
||||||
ServiceMenu::get()->adjustOption(false);
|
ServiceMenu::get()->adjustOption(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aceptar
|
// Aceptar
|
||||||
if (Input::get()->checkInput(InputAction::SM_SELECT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::SM_SELECT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i)) {
|
||||||
{
|
|
||||||
ServiceMenu::get()->selectOption();
|
ServiceMenu::get()->selectOption();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atras
|
// Atras
|
||||||
if (Input::get()->checkInput(InputAction::SM_BACK, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::SM_BACK, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i)) {
|
||||||
{
|
|
||||||
ServiceMenu::get()->moveBack();
|
ServiceMenu::get()->moveBack();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mandos
|
|
||||||
{
|
|
||||||
for (int i = 0; i < Input::get()->getNumControllers(); ++i)
|
|
||||||
{
|
|
||||||
// Arriba
|
|
||||||
if (Input::get()->checkInput(InputAction::UP, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i))
|
|
||||||
{
|
|
||||||
ServiceMenu::get()->setSelectorUp();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Abajo
|
|
||||||
if (Input::get()->checkInput(InputAction::DOWN, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i))
|
|
||||||
{
|
|
||||||
ServiceMenu::get()->setSelectorDown();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Derecha
|
|
||||||
if (Input::get()->checkInput(InputAction::RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i))
|
|
||||||
{
|
|
||||||
ServiceMenu::get()->adjustOption(true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Izquierda
|
|
||||||
if (Input::get()->checkInput(InputAction::LEFT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i))
|
|
||||||
{
|
|
||||||
ServiceMenu::get()->adjustOption(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Aceptar
|
|
||||||
if (Input::get()->checkInput(InputAction::SM_SELECT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i))
|
|
||||||
{
|
|
||||||
ServiceMenu::get()->selectOption();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Atras
|
|
||||||
if (Input::get()->checkInput(InputAction::SM_BACK, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::CONTROLLER, i))
|
|
||||||
{
|
|
||||||
ServiceMenu::get()->moveBack();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Comprueba las entradas fuera del menú de servicio
|
// Comprueba las entradas fuera del menú de servicio
|
||||||
bool checkInputs()
|
bool checkInputs() {
|
||||||
|
// Teclado
|
||||||
{
|
{
|
||||||
// Teclado
|
// Comprueba el teclado para cambiar entre pantalla completa y ventana
|
||||||
{
|
if (Input::get()->checkInput(InputAction::WINDOW_FULLSCREEN, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
// Comprueba el teclado para cambiar entre pantalla completa y ventana
|
Screen::get()->toggleFullscreen();
|
||||||
if (Input::get()->checkInput(InputAction::WINDOW_FULLSCREEN, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
const std::string MODE = Options::video.fullscreen ? Lang::getText("[NOTIFICATIONS] 11") : Lang::getText("[NOTIFICATIONS] 10");
|
||||||
{
|
Notifier::get()->show({MODE});
|
||||||
Screen::get()->toggleFullscreen();
|
return true;
|
||||||
const std::string MODE = Options::video.fullscreen ? Lang::getText("[NOTIFICATIONS] 11") : Lang::getText("[NOTIFICATIONS] 10");
|
}
|
||||||
Notifier::get()->show({MODE});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba el teclado para decrementar el tamaño de la ventana
|
// Comprueba el teclado para decrementar el tamaño de la ventana
|
||||||
if (Input::get()->checkInput(InputAction::WINDOW_DEC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::WINDOW_DEC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
{
|
if (Screen::get()->decWindowSize()) {
|
||||||
if (Screen::get()->decWindowSize())
|
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.size)});
|
||||||
{
|
|
||||||
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.size)});
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Comprueba el teclado para incrementar el tamaño de la ventana
|
// Comprueba el teclado para incrementar el tamaño de la ventana
|
||||||
if (Input::get()->checkInput(InputAction::WINDOW_INC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::WINDOW_INC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
{
|
if (Screen::get()->incWindowSize()) {
|
||||||
if (Screen::get()->incWindowSize())
|
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.size)});
|
||||||
{
|
|
||||||
Notifier::get()->show({Lang::getText("[NOTIFICATIONS] 09") + " x" + std::to_string(Options::window.size)});
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Salir
|
// Salir
|
||||||
if (Input::get()->checkInput(InputAction::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
{
|
quit();
|
||||||
quit();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Saltar sección
|
// Saltar sección
|
||||||
if (Input::get()->checkAnyButton() && !ServiceMenu::get()->isEnabled())
|
if (Input::get()->checkAnyButton() && !ServiceMenu::get()->isEnabled()) {
|
||||||
{
|
skipSection();
|
||||||
skipSection();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Reset
|
// Reset
|
||||||
if (Input::get()->checkInput(InputAction::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
{
|
reset();
|
||||||
reset();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Audio
|
// Audio
|
||||||
if (Input::get()->checkInput(InputAction::TOGGLE_AUDIO, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::TOGGLE_AUDIO, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
{
|
toggleAudio();
|
||||||
toggleAudio();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Autofire
|
// Autofire
|
||||||
if (Input::get()->checkInput(InputAction::TOGGLE_AUTO_FIRE, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::TOGGLE_AUTO_FIRE, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
{
|
toggleFireMode();
|
||||||
toggleFireMode();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Idioma
|
// Idioma
|
||||||
if (Input::get()->checkInput(InputAction::CHANGE_LANG, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::CHANGE_LANG, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
{
|
changeLang();
|
||||||
changeLang();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Shaders
|
// Shaders
|
||||||
if (Input::get()->checkInput(InputAction::TOGGLE_VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::TOGGLE_VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
{
|
toggleShaders();
|
||||||
toggleShaders();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Integer Scale
|
// Integer Scale
|
||||||
if (Input::get()->checkInput(InputAction::TOGGLE_VIDEO_INTEGER_SCALE, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::TOGGLE_VIDEO_INTEGER_SCALE, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
{
|
toggleIntegerScale();
|
||||||
toggleIntegerScale();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// VSync
|
// VSync
|
||||||
if (Input::get()->checkInput(InputAction::TOGGLE_VIDEO_VSYNC, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::TOGGLE_VIDEO_VSYNC, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
{
|
toggleVSync();
|
||||||
toggleVSync();
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// Debug info
|
// Debug info
|
||||||
if (Input::get()->checkInput(InputAction::SHOW_INFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD))
|
if (Input::get()->checkInput(InputAction::SHOW_INFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDevice::KEYBOARD)) {
|
||||||
{
|
Screen::get()->toggleDebugInfo();
|
||||||
Screen::get()->toggleDebugInfo();
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return false;
|
#endif
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
||||||
bool check()
|
bool check() {
|
||||||
{
|
if (checkServiceButton())
|
||||||
if (checkServiceButton())
|
return true;
|
||||||
return true;
|
if (checkServiceInputs())
|
||||||
if (checkServiceInputs())
|
return true;
|
||||||
return true;
|
if (checkInputs())
|
||||||
if (checkInputs())
|
return true;
|
||||||
return true;
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
} // namespace GlobalInputs
|
||||||
}
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace GlobalInputs
|
namespace GlobalInputs {
|
||||||
{
|
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
||||||
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
bool check();
|
||||||
bool check();
|
} // namespace GlobalInputs
|
||||||
}
|
|
||||||
+274
-351
@@ -1,11 +1,12 @@
|
|||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_GetGamepa...
|
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_GetGamepa...
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
#include <algorithm> // Para find
|
|
||||||
#include <iterator> // Para distance
|
#include <algorithm> // Para find
|
||||||
#include <unordered_map> // Para unordered_map, _Node_const_iterator, operat...
|
#include <iterator> // Para distance
|
||||||
#include <utility> // Para pair
|
#include <unordered_map> // Para unordered_map, _Node_const_iterator, operat...
|
||||||
|
#include <utility> // Para pair
|
||||||
|
|
||||||
// Singleton
|
// Singleton
|
||||||
Input *Input::instance_ = nullptr;
|
Input *Input::instance_ = nullptr;
|
||||||
@@ -21,232 +22,188 @@ Input *Input::get() { return Input::instance_; }
|
|||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Input::Input(const std::string &game_controller_db_path)
|
Input::Input(const std::string &game_controller_db_path)
|
||||||
: game_controller_db_path_(game_controller_db_path)
|
: game_controller_db_path_(game_controller_db_path) {
|
||||||
{
|
// Inicializa el subsistema SDL_INIT_GAMEPAD
|
||||||
// Inicializa el subsistema SDL_INIT_GAMEPAD
|
initSDLGamePad();
|
||||||
initSDLGamePad();
|
|
||||||
|
|
||||||
// Inicializa los vectores
|
// Inicializa los vectores
|
||||||
key_bindings_.resize(static_cast<int>(InputAction::SIZE), KeyBindings());
|
key_bindings_.resize(static_cast<int>(InputAction::SIZE), KeyBindings());
|
||||||
controller_bindings_.resize(num_gamepads_, std::vector<ControllerBindings>(static_cast<int>(InputAction::SIZE), ControllerBindings()));
|
controller_bindings_.resize(num_gamepads_, std::vector<ControllerBindings>(static_cast<int>(InputAction::SIZE), ControllerBindings()));
|
||||||
|
|
||||||
// Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
|
// Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
|
||||||
button_inputs_ = {InputAction::FIRE_LEFT, InputAction::FIRE_CENTER, InputAction::FIRE_RIGHT, InputAction::START};
|
button_inputs_ = {InputAction::FIRE_LEFT, InputAction::FIRE_CENTER, InputAction::FIRE_RIGHT, InputAction::START};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Asigna inputs a teclas
|
// Asigna inputs a teclas
|
||||||
void Input::bindKey(InputAction input, SDL_Scancode code)
|
void Input::bindKey(InputAction input, SDL_Scancode code) {
|
||||||
{
|
key_bindings_.at(static_cast<int>(input)).scancode = code;
|
||||||
key_bindings_.at(static_cast<int>(input)).scancode = code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Asigna inputs a botones del mando
|
// Asigna inputs a botones del mando
|
||||||
void Input::bindGameControllerButton(int controller_index, InputAction input, SDL_GamepadButton button)
|
void Input::bindGameControllerButton(int controller_index, InputAction input, SDL_GamepadButton button) {
|
||||||
{
|
if (controller_index < num_gamepads_) {
|
||||||
if (controller_index < num_gamepads_)
|
controller_bindings_.at(controller_index).at(static_cast<int>(input)).button = button;
|
||||||
{
|
}
|
||||||
controller_bindings_.at(controller_index).at(static_cast<int>(input)).button = button;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Asigna inputs a botones del mando
|
// Asigna inputs a botones del mando
|
||||||
void Input::bindGameControllerButton(int controller_index, InputAction input_target, InputAction input_source)
|
void Input::bindGameControllerButton(int controller_index, InputAction input_target, InputAction input_source) {
|
||||||
{
|
if (controller_index < num_gamepads_) {
|
||||||
if (controller_index < num_gamepads_)
|
controller_bindings_.at(controller_index).at(static_cast<int>(input_target)).button = controller_bindings_.at(controller_index).at(static_cast<int>(input_source)).button;
|
||||||
{
|
}
|
||||||
controller_bindings_.at(controller_index).at(static_cast<int>(input_target)).button = controller_bindings_.at(controller_index).at(static_cast<int>(input_source)).button;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba si un input esta activo
|
// Comprueba si un input esta activo
|
||||||
bool Input::checkInput(InputAction input, bool repeat, InputDevice device, int controller_index)
|
bool Input::checkInput(InputAction input, bool repeat, InputDevice device, int controller_index) {
|
||||||
{
|
bool success_keyboard = false;
|
||||||
bool success_keyboard = false;
|
bool success_controller = false;
|
||||||
bool success_controller = false;
|
const int input_index = static_cast<int>(input);
|
||||||
const int input_index = static_cast<int>(input);
|
|
||||||
|
|
||||||
if (device == InputDevice::KEYBOARD || device == InputDevice::ANY)
|
if (device == InputDevice::KEYBOARD || device == InputDevice::ANY) {
|
||||||
{
|
if (repeat) { // El usuario quiere saber si está pulsada (estado mantenido)
|
||||||
if (repeat)
|
success_keyboard = key_bindings_[input_index].is_held;
|
||||||
{ // El usuario quiere saber si está pulsada (estado mantenido)
|
} else { // El usuario quiere saber si ACABA de ser pulsada (evento de un solo fotograma)
|
||||||
success_keyboard = key_bindings_[input_index].is_held;
|
success_keyboard = key_bindings_[input_index].just_pressed;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{ // El usuario quiere saber si ACABA de ser pulsada (evento de un solo fotograma)
|
|
||||||
success_keyboard = key_bindings_[input_index].just_pressed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_)
|
if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_) {
|
||||||
{
|
if ((device == InputDevice::CONTROLLER) || (device == InputDevice::ANY)) {
|
||||||
if ((device == InputDevice::CONTROLLER) || (device == InputDevice::ANY))
|
success_controller = checkAxisInput(input, controller_index, repeat);
|
||||||
{
|
|
||||||
success_controller = checkAxisInput(input, controller_index, repeat);
|
|
||||||
|
|
||||||
if (!success_controller)
|
if (!success_controller) {
|
||||||
{
|
if (repeat) { // El usuario quiere saber si está pulsada (estado mantenido)
|
||||||
if (repeat)
|
success_controller = controller_bindings_.at(controller_index).at(input_index).is_held;
|
||||||
{ // El usuario quiere saber si está pulsada (estado mantenido)
|
} else { // El usuario quiere saber si ACABA de ser pulsada (evento de un solo fotograma)
|
||||||
success_controller = controller_bindings_.at(controller_index).at(input_index).is_held;
|
success_controller = controller_bindings_.at(controller_index).at(input_index).just_pressed;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{ // El usuario quiere saber si ACABA de ser pulsada (evento de un solo fotograma)
|
}
|
||||||
success_controller = controller_bindings_.at(controller_index).at(input_index).just_pressed;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (success_keyboard || success_controller);
|
return (success_keyboard || success_controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba si hay almenos un input activo
|
// Comprueba si hay almenos un input activo
|
||||||
bool Input::checkAnyInput(InputDevice device, int controller_index)
|
bool Input::checkAnyInput(InputDevice device, int controller_index) {
|
||||||
{
|
// Obtenemos el número total de acciones posibles para iterar sobre ellas.
|
||||||
// Obtenemos el número total de acciones posibles para iterar sobre ellas.
|
const int num_actions = static_cast<int>(InputAction::SIZE);
|
||||||
const int num_actions = static_cast<int>(InputAction::SIZE);
|
|
||||||
|
|
||||||
// --- Comprobación del Teclado ---
|
// --- Comprobación del Teclado ---
|
||||||
if (device == InputDevice::KEYBOARD || device == InputDevice::ANY)
|
if (device == InputDevice::KEYBOARD || device == InputDevice::ANY) {
|
||||||
{
|
for (int i = 0; i < num_actions; ++i) {
|
||||||
for (int i = 0; i < num_actions; ++i)
|
// Simplemente leemos el estado pre-calculado por Input::update().
|
||||||
{
|
// Ya no se llama a SDL_GetKeyboardState ni se modifica el estado '.active'.
|
||||||
// Simplemente leemos el estado pre-calculado por Input::update().
|
if (key_bindings_.at(i).just_pressed) {
|
||||||
// Ya no se llama a SDL_GetKeyboardState ni se modifica el estado '.active'.
|
return true; // Se encontró una acción recién pulsada.
|
||||||
if (key_bindings_.at(i).just_pressed)
|
}
|
||||||
{
|
}
|
||||||
return true; // Se encontró una acción recién pulsada.
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Comprobación del Mando ---
|
// --- Comprobación del Mando ---
|
||||||
// Comprobamos si hay mandos y si el índice solicitado es válido.
|
// Comprobamos si hay mandos y si el índice solicitado es válido.
|
||||||
if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_)
|
if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_) {
|
||||||
{
|
if (device == InputDevice::CONTROLLER || device == InputDevice::ANY) {
|
||||||
if (device == InputDevice::CONTROLLER || device == InputDevice::ANY)
|
// Bucle CORREGIDO: Iteramos sobre todas las acciones, no sobre el número de mandos.
|
||||||
{
|
for (int i = 0; i < num_actions; ++i) {
|
||||||
// Bucle CORREGIDO: Iteramos sobre todas las acciones, no sobre el número de mandos.
|
// Leemos el estado pre-calculado para el mando y la acción específicos.
|
||||||
for (int i = 0; i < num_actions; ++i)
|
if (controller_bindings_.at(controller_index).at(i).just_pressed) {
|
||||||
{
|
return true; // Se encontró una acción recién pulsada en el mando.
|
||||||
// Leemos el estado pre-calculado para el mando y la acción específicos.
|
}
|
||||||
if (controller_bindings_.at(controller_index).at(i).just_pressed)
|
}
|
||||||
{
|
}
|
||||||
return true; // Se encontró una acción recién pulsada en el mando.
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si llegamos hasta aquí, no se detectó ninguna nueva pulsación.
|
// Si llegamos hasta aquí, no se detectó ninguna nueva pulsación.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba si hay algún botón pulsado. Devuelve 0 en caso de no encontrar nada o el indice del dispositivo + 1. Se hace así para poder gastar el valor devuelto como un valor "booleano"
|
// Comprueba si hay algún botón pulsado. Devuelve 0 en caso de no encontrar nada o el indice del dispositivo + 1. Se hace así para poder gastar el valor devuelto como un valor "booleano"
|
||||||
int Input::checkAnyButton(bool repeat)
|
int Input::checkAnyButton(bool repeat) {
|
||||||
{
|
// Solo comprueba los botones definidos previamente
|
||||||
// Solo comprueba los botones definidos previamente
|
for (auto bi : button_inputs_) {
|
||||||
for (auto bi : button_inputs_)
|
// Comprueba el teclado
|
||||||
{
|
if (checkInput(bi, repeat, InputDevice::KEYBOARD)) {
|
||||||
// Comprueba el teclado
|
return 1;
|
||||||
if (checkInput(bi, repeat, InputDevice::KEYBOARD))
|
}
|
||||||
{
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba los mandos
|
// Comprueba los mandos
|
||||||
for (int i = 0; i < num_gamepads_; ++i)
|
for (int i = 0; i < num_gamepads_; ++i) {
|
||||||
{
|
if (checkInput(bi, repeat, InputDevice::CONTROLLER, i)) {
|
||||||
if (checkInput(bi, repeat, InputDevice::CONTROLLER, i))
|
return i + 1;
|
||||||
{
|
}
|
||||||
return i + 1;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Busca si hay mandos conectados
|
// Busca si hay mandos conectados
|
||||||
bool Input::discoverGameControllers()
|
bool Input::discoverGameControllers() {
|
||||||
{
|
bool found = false;
|
||||||
bool found = false;
|
|
||||||
|
|
||||||
if (SDL_AddGamepadMappingsFromFile(game_controller_db_path_.c_str()) < 0)
|
if (SDL_AddGamepadMappingsFromFile(game_controller_db_path_.c_str()) < 0) {
|
||||||
{
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: could not load %s file: %s", game_controller_db_path_.c_str(), SDL_GetError());
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: could not load %s file: %s", game_controller_db_path_.c_str(), SDL_GetError());
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// En SDL3, SDL_GetJoysticks devuelve un array de IDs, no un contador
|
// En SDL3, SDL_GetJoysticks devuelve un array de IDs, no un contador
|
||||||
SDL_JoystickID *joystick_ids = SDL_GetJoysticks(&num_joysticks_);
|
SDL_JoystickID *joystick_ids = SDL_GetJoysticks(&num_joysticks_);
|
||||||
num_gamepads_ = 0;
|
num_gamepads_ = 0;
|
||||||
|
|
||||||
// Cuenta el número de mandos
|
// Cuenta el número de mandos
|
||||||
joysticks_.clear();
|
joysticks_.clear();
|
||||||
for (int i = 0; i < num_joysticks_; ++i)
|
for (int i = 0; i < num_joysticks_; ++i) {
|
||||||
{
|
// Usar el ID del joystick, no el índice
|
||||||
// Usar el ID del joystick, no el índice
|
auto joy = SDL_OpenJoystick(joystick_ids[i]);
|
||||||
auto joy = SDL_OpenJoystick(joystick_ids[i]);
|
joysticks_.push_back(joy);
|
||||||
joysticks_.push_back(joy);
|
|
||||||
|
|
||||||
// En SDL3, SDL_IsGamepad toma un SDL_JoystickID, no un índice
|
// En SDL3, SDL_IsGamepad toma un SDL_JoystickID, no un índice
|
||||||
if (SDL_IsGamepad(joystick_ids[i]))
|
if (SDL_IsGamepad(joystick_ids[i])) {
|
||||||
{
|
num_gamepads_++;
|
||||||
num_gamepads_++;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, ">> LOOKING FOR GAME CONTROLLERS");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, ">> LOOKING FOR GAME CONTROLLERS");
|
||||||
if (num_joysticks_ != num_gamepads_)
|
if (num_joysticks_ != num_gamepads_) {
|
||||||
{
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Joysticks found: %d", num_joysticks_);
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Joysticks found: %d", num_joysticks_);
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Gamepads found : %d", num_gamepads_);
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Gamepads found : %d", num_gamepads_);
|
} else {
|
||||||
}
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Gamepads found: %d", num_gamepads_);
|
||||||
else
|
}
|
||||||
{
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Gamepads found: %d", num_gamepads_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (num_gamepads_ > 0)
|
if (num_gamepads_ > 0) {
|
||||||
{
|
found = true;
|
||||||
found = true;
|
|
||||||
|
|
||||||
// Recorrer los joysticks y abrir solo los que son gamepads
|
// Recorrer los joysticks y abrir solo los que son gamepads
|
||||||
for (int i = 0; i < num_joysticks_; i++)
|
for (int i = 0; i < num_joysticks_; i++) {
|
||||||
{
|
if (SDL_IsGamepad(joystick_ids[i])) {
|
||||||
if (SDL_IsGamepad(joystick_ids[i]))
|
// Abre el mando usando el ID del joystick
|
||||||
{
|
auto pad = SDL_OpenGamepad(joystick_ids[i]);
|
||||||
// Abre el mando usando el ID del joystick
|
if (pad != nullptr) {
|
||||||
auto pad = SDL_OpenGamepad(joystick_ids[i]);
|
connected_controllers_.push_back(pad);
|
||||||
if (pad != nullptr)
|
|
||||||
{
|
|
||||||
connected_controllers_.push_back(pad);
|
|
||||||
|
|
||||||
// Obtener el nombre usando el ID del joystick
|
// Obtener el nombre usando el ID del joystick
|
||||||
const char *name_cstr = SDL_GetGamepadNameForID(joystick_ids[i]);
|
const char *name_cstr = SDL_GetGamepadNameForID(joystick_ids[i]);
|
||||||
std::string name = name_cstr ? name_cstr : "Unknown Gamepad";
|
std::string name = name_cstr ? name_cstr : "Unknown Gamepad";
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "#%d: %s", i, name.c_str());
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "#%d: %s", i, name.c_str());
|
||||||
controller_names_.push_back(name);
|
controller_names_.push_back(name);
|
||||||
}
|
} else {
|
||||||
else
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to open gamepad %d: %s", joystick_ids[i], SDL_GetError());
|
||||||
{
|
}
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to open gamepad %d: %s", joystick_ids[i], SDL_GetError());
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_SetGamepadEventsEnabled(true);
|
SDL_SetGamepadEventsEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Liberar el array de IDs
|
// Liberar el array de IDs
|
||||||
if (joystick_ids)
|
if (joystick_ids) {
|
||||||
{
|
SDL_free(joystick_ids);
|
||||||
SDL_free(joystick_ids);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> FINISHED LOOKING FOR GAME CONTROLLERS");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> FINISHED LOOKING FOR GAME CONTROLLERS");
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba si hay algun mando conectado
|
// Comprueba si hay algun mando conectado
|
||||||
@@ -259,202 +216,168 @@ std::string Input::getControllerName(int controller_index) const { return num_ga
|
|||||||
int Input::getNumControllers() const { return num_gamepads_; }
|
int Input::getNumControllers() const { return num_gamepads_; }
|
||||||
|
|
||||||
// Obtiene el indice del controlador a partir de un event.id
|
// Obtiene el indice del controlador a partir de un event.id
|
||||||
int Input::getJoyIndex(SDL_JoystickID id) const
|
int Input::getJoyIndex(SDL_JoystickID id) const {
|
||||||
{
|
for (int i = 0; i < num_joysticks_; ++i) {
|
||||||
for (int i = 0; i < num_joysticks_; ++i)
|
if (SDL_GetJoystickID(joysticks_[i]) == id) {
|
||||||
{
|
return i;
|
||||||
if (SDL_GetJoystickID(joysticks_[i]) == id)
|
}
|
||||||
{
|
}
|
||||||
return i;
|
return -1;
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Muestra por consola los controles asignados
|
// Muestra por consola los controles asignados
|
||||||
void Input::printBindings(InputDevice device, int controller_index) const
|
void Input::printBindings(InputDevice device, int controller_index) const {
|
||||||
{
|
if (device == InputDevice::ANY || device == InputDevice::KEYBOARD) {
|
||||||
if (device == InputDevice::ANY || device == InputDevice::KEYBOARD)
|
return;
|
||||||
{
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (device == InputDevice::CONTROLLER)
|
if (device == InputDevice::CONTROLLER) {
|
||||||
{
|
if (controller_index >= num_gamepads_) {
|
||||||
if (controller_index >= num_gamepads_)
|
return;
|
||||||
{
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Muestra el nombre del mando
|
// Muestra el nombre del mando
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n%s", controller_names_.at(controller_index).c_str());
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n%s", controller_names_.at(controller_index).c_str());
|
||||||
|
|
||||||
// Muestra los botones asignados
|
// Muestra los botones asignados
|
||||||
for (auto bi : button_inputs_)
|
for (auto bi : button_inputs_) {
|
||||||
{
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%s : %d", to_string(bi).c_str(), controller_bindings_.at(controller_index).at(static_cast<int>(bi)).button);
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "%s : %d", to_string(bi).c_str(), controller_bindings_.at(controller_index).at(static_cast<int>(bi)).button);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el SDL_GamepadButton asignado a un input
|
// Obtiene el SDL_GamepadButton asignado a un input
|
||||||
SDL_GamepadButton Input::getControllerBinding(int controller_index, InputAction input) const
|
SDL_GamepadButton Input::getControllerBinding(int controller_index, InputAction input) const {
|
||||||
{
|
return controller_bindings_[controller_index][static_cast<int>(input)].button;
|
||||||
return controller_bindings_[controller_index][static_cast<int>(input)].button;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el indice a partir del nombre del mando
|
// Obtiene el indice a partir del nombre del mando
|
||||||
int Input::getIndexByName(const std::string &name) const
|
int Input::getIndexByName(const std::string &name) const {
|
||||||
{
|
auto it = std::find(controller_names_.begin(), controller_names_.end(), name);
|
||||||
auto it = std::find(controller_names_.begin(), controller_names_.end(), name);
|
return it != controller_names_.end() ? std::distance(controller_names_.begin(), it) : -1;
|
||||||
return it != controller_names_.end() ? std::distance(controller_names_.begin(), it) : -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convierte un InputAction a std::string
|
// Convierte un InputAction a std::string
|
||||||
std::string Input::to_string(InputAction input) const
|
std::string Input::to_string(InputAction input) const {
|
||||||
{
|
switch (input) {
|
||||||
switch (input)
|
case InputAction::FIRE_LEFT:
|
||||||
{
|
return "input_fire_left";
|
||||||
case InputAction::FIRE_LEFT:
|
case InputAction::FIRE_CENTER:
|
||||||
return "input_fire_left";
|
return "input_fire_center";
|
||||||
case InputAction::FIRE_CENTER:
|
case InputAction::FIRE_RIGHT:
|
||||||
return "input_fire_center";
|
return "input_fire_right";
|
||||||
case InputAction::FIRE_RIGHT:
|
case InputAction::START:
|
||||||
return "input_fire_right";
|
return "input_start";
|
||||||
case InputAction::START:
|
case InputAction::SERVICE:
|
||||||
return "input_start";
|
return "input_service";
|
||||||
case InputAction::SERVICE:
|
default:
|
||||||
return "input_service";
|
return "";
|
||||||
default:
|
}
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convierte un std::string a InputAction
|
// Convierte un std::string a InputAction
|
||||||
InputAction Input::to_inputs_e(const std::string &name) const
|
InputAction Input::to_inputs_e(const std::string &name) const {
|
||||||
{
|
static const std::unordered_map<std::string, InputAction> inputMap = {
|
||||||
static const std::unordered_map<std::string, InputAction> inputMap = {
|
{"input_fire_left", InputAction::FIRE_LEFT},
|
||||||
{"input_fire_left", InputAction::FIRE_LEFT},
|
{"input_fire_center", InputAction::FIRE_CENTER},
|
||||||
{"input_fire_center", InputAction::FIRE_CENTER},
|
{"input_fire_right", InputAction::FIRE_RIGHT},
|
||||||
{"input_fire_right", InputAction::FIRE_RIGHT},
|
{"input_start", InputAction::START},
|
||||||
{"input_start", InputAction::START},
|
{"input_service", InputAction::SERVICE}};
|
||||||
{"input_service", InputAction::SERVICE}};
|
|
||||||
|
|
||||||
auto it = inputMap.find(name);
|
auto it = inputMap.find(name);
|
||||||
return it != inputMap.end() ? it->second : InputAction::NONE;
|
return it != inputMap.end() ? it->second : InputAction::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba el eje del mando
|
// Comprueba el eje del mando
|
||||||
bool Input::checkAxisInput(InputAction input, int controller_index, bool repeat)
|
bool Input::checkAxisInput(InputAction input, int controller_index, bool repeat) {
|
||||||
{
|
// Umbral para considerar el eje como activo
|
||||||
// Umbral para considerar el eje como activo
|
bool axis_active_now = false;
|
||||||
bool axis_active_now = false;
|
|
||||||
|
|
||||||
switch (input)
|
switch (input) {
|
||||||
{
|
case InputAction::LEFT:
|
||||||
case InputAction::LEFT:
|
axis_active_now = SDL_GetGamepadAxis(connected_controllers_[controller_index], SDL_GAMEPAD_AXIS_LEFTX) < -AXIS_THRESHOLD_;
|
||||||
axis_active_now = SDL_GetGamepadAxis(connected_controllers_[controller_index], SDL_GAMEPAD_AXIS_LEFTX) < -AXIS_THRESHOLD_;
|
break;
|
||||||
break;
|
case InputAction::RIGHT:
|
||||||
case InputAction::RIGHT:
|
axis_active_now = SDL_GetGamepadAxis(connected_controllers_[controller_index], SDL_GAMEPAD_AXIS_LEFTX) > AXIS_THRESHOLD_;
|
||||||
axis_active_now = SDL_GetGamepadAxis(connected_controllers_[controller_index], SDL_GAMEPAD_AXIS_LEFTX) > AXIS_THRESHOLD_;
|
break;
|
||||||
break;
|
case InputAction::UP:
|
||||||
case InputAction::UP:
|
axis_active_now = SDL_GetGamepadAxis(connected_controllers_[controller_index], SDL_GAMEPAD_AXIS_LEFTY) < -AXIS_THRESHOLD_;
|
||||||
axis_active_now = SDL_GetGamepadAxis(connected_controllers_[controller_index], SDL_GAMEPAD_AXIS_LEFTY) < -AXIS_THRESHOLD_;
|
break;
|
||||||
break;
|
case InputAction::DOWN:
|
||||||
case InputAction::DOWN:
|
axis_active_now = SDL_GetGamepadAxis(connected_controllers_[controller_index], SDL_GAMEPAD_AXIS_LEFTY) > AXIS_THRESHOLD_;
|
||||||
axis_active_now = SDL_GetGamepadAxis(connected_controllers_[controller_index], SDL_GAMEPAD_AXIS_LEFTY) > AXIS_THRESHOLD_;
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Referencia al binding correspondiente
|
// Referencia al binding correspondiente
|
||||||
auto &binding = controller_bindings_.at(controller_index).at(static_cast<int>(input));
|
auto &binding = controller_bindings_.at(controller_index).at(static_cast<int>(input));
|
||||||
|
|
||||||
if (repeat)
|
if (repeat) {
|
||||||
{
|
// Si se permite repetir, simplemente devolvemos el estado actual
|
||||||
// Si se permite repetir, simplemente devolvemos el estado actual
|
return axis_active_now;
|
||||||
return axis_active_now;
|
} else {
|
||||||
}
|
// Si no se permite repetir, aplicamos la lógica de transición
|
||||||
else
|
if (axis_active_now && !binding.axis_active) {
|
||||||
{
|
// Transición de inactivo a activo
|
||||||
// Si no se permite repetir, aplicamos la lógica de transición
|
binding.axis_active = true;
|
||||||
if (axis_active_now && !binding.axis_active)
|
return true;
|
||||||
{
|
} else if (!axis_active_now && binding.axis_active) {
|
||||||
// Transición de inactivo a activo
|
// Transición de activo a inactivo
|
||||||
binding.axis_active = true;
|
binding.axis_active = false;
|
||||||
return true;
|
}
|
||||||
}
|
// Mantener el estado actual
|
||||||
else if (!axis_active_now && binding.axis_active)
|
return false;
|
||||||
{
|
}
|
||||||
// Transición de activo a inactivo
|
|
||||||
binding.axis_active = false;
|
|
||||||
}
|
|
||||||
// Mantener el estado actual
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::initSDLGamePad()
|
void Input::initSDLGamePad() {
|
||||||
{
|
if (SDL_WasInit(SDL_INIT_GAMEPAD) != 1) {
|
||||||
if (SDL_WasInit(SDL_INIT_GAMEPAD) != 1)
|
if (!SDL_InitSubSystem(SDL_INIT_GAMEPAD)) {
|
||||||
{
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GAMEPAD could not initialize! SDL Error: %s", SDL_GetError());
|
||||||
if (!SDL_InitSubSystem(SDL_INIT_GAMEPAD))
|
} else {
|
||||||
{
|
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "\n** SDL_GAMEPAD: INITIALIZING");
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_GAMEPAD could not initialize! SDL Error: %s", SDL_GetError());
|
discoverGameControllers();
|
||||||
}
|
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "** SDL_GAMEPAD: INITIALIZATION COMPLETE\n");
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "\n** SDL_GAMEPAD: INITIALIZING");
|
|
||||||
discoverGameControllers();
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "** SDL_GAMEPAD: INITIALIZATION COMPLETE\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::resetInputStates()
|
void Input::resetInputStates() {
|
||||||
{
|
// Resetear todos los KeyBindings.active a false
|
||||||
// Resetear todos los KeyBindings.active a false
|
for (auto &key : key_bindings_) {
|
||||||
for (auto &key : key_bindings_)
|
key.is_held = false;
|
||||||
{
|
key.just_pressed = false;
|
||||||
key.is_held = false;
|
}
|
||||||
key.just_pressed = false;
|
// Resetear todos los ControllerBindings.active a false
|
||||||
}
|
for (auto &controller_vec : controller_bindings_) {
|
||||||
// Resetear todos los ControllerBindings.active a false
|
for (auto &binding : controller_vec) {
|
||||||
for (auto &controller_vec : controller_bindings_)
|
binding.is_held = false;
|
||||||
{
|
binding.just_pressed = false;
|
||||||
for (auto &binding : controller_vec)
|
}
|
||||||
{
|
}
|
||||||
binding.is_held = false;
|
|
||||||
binding.just_pressed = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::update()
|
void Input::update() {
|
||||||
{
|
// --- TECLADO ---
|
||||||
// --- TECLADO ---
|
const bool *key_states = SDL_GetKeyboardState(nullptr);
|
||||||
const bool *key_states = SDL_GetKeyboardState(nullptr);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < key_bindings_.size(); ++i)
|
for (size_t i = 0; i < key_bindings_.size(); ++i) {
|
||||||
{
|
bool key_is_down_now = key_states[key_bindings_[i].scancode];
|
||||||
bool key_is_down_now = key_states[key_bindings_[i].scancode];
|
|
||||||
|
|
||||||
// El estado .is_held del fotograma anterior nos sirve para saber si es un pulso nuevo
|
// El estado .is_held del fotograma anterior nos sirve para saber si es un pulso nuevo
|
||||||
key_bindings_[i].just_pressed = key_is_down_now && !key_bindings_[i].is_held;
|
key_bindings_[i].just_pressed = key_is_down_now && !key_bindings_[i].is_held;
|
||||||
key_bindings_[i].is_held = key_is_down_now;
|
key_bindings_[i].is_held = key_is_down_now;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- MANDOS ---
|
// --- MANDOS ---
|
||||||
for (int c = 0; c < num_gamepads_; ++c)
|
for (int c = 0; c < num_gamepads_; ++c) {
|
||||||
{
|
for (size_t i = 0; i < controller_bindings_[c].size(); ++i) {
|
||||||
for (size_t i = 0; i < controller_bindings_[c].size(); ++i)
|
bool button_is_down_now = SDL_GetGamepadButton(connected_controllers_.at(c), controller_bindings_.at(c).at(i).button) != 0;
|
||||||
{
|
|
||||||
bool button_is_down_now = SDL_GetGamepadButton(connected_controllers_.at(c), controller_bindings_.at(c).at(i).button) != 0;
|
|
||||||
|
|
||||||
// El estado .is_held del fotograma anterior nos sirve para saber si es un pulso nuevo
|
// El estado .is_held del fotograma anterior nos sirve para saber si es un pulso nuevo
|
||||||
controller_bindings_[c][i].just_pressed = button_is_down_now && !controller_bindings_[c][i].is_held;
|
controller_bindings_[c][i].just_pressed = button_is_down_now && !controller_bindings_[c][i].is_held;
|
||||||
controller_bindings_[c][i].is_held = button_is_down_now;
|
controller_bindings_[c][i].is_held = button_is_down_now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+112
-116
@@ -1,154 +1,150 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_GamepadButton, Uint8, SDL_Gamepad, SDL_Joystick, SDL_JoystickID, SDL_Scancode, Sint16
|
#include <SDL3/SDL.h> // Para SDL_GamepadButton, Uint8, SDL_Gamepad, SDL_Joystick, SDL_JoystickID, SDL_Scancode, Sint16
|
||||||
#include <string> // Para basic_string, string
|
|
||||||
#include <vector> // Para vector
|
#include <string> // Para basic_string, string
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
/*
|
/*
|
||||||
connectedControllers es un vector donde están todos los mandos encontrados [0 .. n]
|
connectedControllers es un vector donde están todos los mandos encontrados [0 .. n]
|
||||||
checkInput requiere de un índice para comprobar las pulsaciones de un controlador en concreto [0 .. n]
|
checkInput requiere de un índice para comprobar las pulsaciones de un controlador en concreto [0 .. n]
|
||||||
device contiene el tipo de dispositivo a comprobar:
|
device contiene el tipo de dispositivo a comprobar:
|
||||||
InputDeviceToUse::KEYBOARD solo mirará el teclado
|
InputDeviceToUse::KEYBOARD solo mirará el teclado
|
||||||
InputDeviceToUse::CONTROLLER solo mirará el controlador especificado (Si no se especifica, el primero)
|
InputDeviceToUse::CONTROLLER solo mirará el controlador especificado (Si no se especifica, el primero)
|
||||||
InputDeviceToUse::ANY mirará tanto el teclado como el PRIMER controlador
|
InputDeviceToUse::ANY mirará tanto el teclado como el PRIMER controlador
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Acciones de entrada posibles en el juego
|
// Acciones de entrada posibles en el juego
|
||||||
enum class InputAction : int
|
enum class InputAction : int {
|
||||||
{
|
// Inputs de movimiento
|
||||||
// Inputs de movimiento
|
UP,
|
||||||
UP,
|
DOWN,
|
||||||
DOWN,
|
LEFT,
|
||||||
LEFT,
|
RIGHT,
|
||||||
RIGHT,
|
|
||||||
|
|
||||||
// Inputs personalizados
|
// Inputs personalizados
|
||||||
FIRE_LEFT,
|
FIRE_LEFT,
|
||||||
FIRE_CENTER,
|
FIRE_CENTER,
|
||||||
FIRE_RIGHT,
|
FIRE_RIGHT,
|
||||||
START,
|
START,
|
||||||
|
|
||||||
// Service Menu
|
// Service Menu
|
||||||
SM_SELECT,
|
SM_SELECT,
|
||||||
SM_BACK,
|
SM_BACK,
|
||||||
|
|
||||||
// Inputs de control
|
// Inputs de control
|
||||||
BACK,
|
BACK,
|
||||||
EXIT,
|
EXIT,
|
||||||
PAUSE,
|
PAUSE,
|
||||||
SERVICE,
|
SERVICE,
|
||||||
WINDOW_FULLSCREEN,
|
WINDOW_FULLSCREEN,
|
||||||
WINDOW_INC_SIZE,
|
WINDOW_INC_SIZE,
|
||||||
WINDOW_DEC_SIZE,
|
WINDOW_DEC_SIZE,
|
||||||
TOGGLE_VIDEO_SHADERS,
|
TOGGLE_VIDEO_SHADERS,
|
||||||
TOGGLE_VIDEO_INTEGER_SCALE,
|
TOGGLE_VIDEO_INTEGER_SCALE,
|
||||||
TOGGLE_VIDEO_VSYNC,
|
TOGGLE_VIDEO_VSYNC,
|
||||||
RESET,
|
RESET,
|
||||||
TOGGLE_AUDIO,
|
TOGGLE_AUDIO,
|
||||||
CHANGE_LANG,
|
CHANGE_LANG,
|
||||||
SHOW_INFO,
|
SHOW_INFO,
|
||||||
CONFIG,
|
CONFIG,
|
||||||
SWAP_CONTROLLERS,
|
SWAP_CONTROLLERS,
|
||||||
TOGGLE_AUTO_FIRE,
|
TOGGLE_AUTO_FIRE,
|
||||||
|
|
||||||
// Input obligatorio
|
// Input obligatorio
|
||||||
NONE,
|
NONE,
|
||||||
SIZE,
|
SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr bool INPUT_ALLOW_REPEAT = true;
|
constexpr bool INPUT_ALLOW_REPEAT = true;
|
||||||
constexpr bool INPUT_DO_NOT_ALLOW_REPEAT = false;
|
constexpr bool INPUT_DO_NOT_ALLOW_REPEAT = false;
|
||||||
|
|
||||||
// Tipos de dispositivos de entrada
|
// Tipos de dispositivos de entrada
|
||||||
enum class InputDevice : int
|
enum class InputDevice : int {
|
||||||
{
|
KEYBOARD = 0,
|
||||||
KEYBOARD = 0,
|
CONTROLLER = 1,
|
||||||
CONTROLLER = 1,
|
ANY = 2,
|
||||||
ANY = 2,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clase Input: gestiona la entrada de teclado y mandos (singleton)
|
// Clase Input: gestiona la entrada de teclado y mandos (singleton)
|
||||||
class Input
|
class Input {
|
||||||
{
|
public:
|
||||||
public:
|
// --- Métodos de singleton ---
|
||||||
// --- Métodos de singleton ---
|
static void init(const std::string &game_controller_db_path); // Inicializa el singleton
|
||||||
static void init(const std::string &game_controller_db_path); // Inicializa el singleton
|
static void destroy(); // Libera el singleton
|
||||||
static void destroy(); // Libera el singleton
|
static Input *get(); // Obtiene la instancia
|
||||||
static Input *get(); // Obtiene la instancia
|
|
||||||
|
|
||||||
// --- Métodos de configuración de controles ---
|
// --- Métodos de configuración de controles ---
|
||||||
void bindKey(InputAction input, SDL_Scancode code); // Asigna inputs a teclas
|
void bindKey(InputAction input, SDL_Scancode code); // Asigna inputs a teclas
|
||||||
void bindGameControllerButton(int controller_index, InputAction input, SDL_GamepadButton button); // Asigna inputs a botones del mando
|
void bindGameControllerButton(int controller_index, InputAction input, SDL_GamepadButton button); // Asigna inputs a botones del mando
|
||||||
void bindGameControllerButton(int controller_index, InputAction inputTarget, InputAction inputSource); // Asigna inputs a otros inputs del mando
|
void bindGameControllerButton(int controller_index, InputAction inputTarget, InputAction inputSource); // Asigna inputs a otros inputs del mando
|
||||||
|
|
||||||
// --- Métodos de consulta de entrada ---
|
// --- Métodos de consulta de entrada ---
|
||||||
void update(); // Comprueba fisicamente los botones y teclas que se han pulsado
|
void update(); // Comprueba fisicamente los botones y teclas que se han pulsado
|
||||||
bool checkInput(InputAction input, bool repeat = true, InputDevice device = InputDevice::ANY, int controller_index = 0); // Comprueba si un input está activo
|
bool checkInput(InputAction input, bool repeat = true, InputDevice device = InputDevice::ANY, int controller_index = 0); // Comprueba si un input está activo
|
||||||
bool checkAnyInput(InputDevice device = InputDevice::ANY, int controller_index = 0); // Comprueba si hay al menos un input activo
|
bool checkAnyInput(InputDevice device = InputDevice::ANY, int controller_index = 0); // Comprueba si hay al menos un input activo
|
||||||
int checkAnyButton(bool repeat = INPUT_DO_NOT_ALLOW_REPEAT); // Comprueba si hay algún botón pulsado
|
int checkAnyButton(bool repeat = INPUT_DO_NOT_ALLOW_REPEAT); // Comprueba si hay algún botón pulsado
|
||||||
|
|
||||||
// --- Métodos de gestión de mandos ---
|
// --- Métodos de gestión de mandos ---
|
||||||
bool discoverGameControllers(); // Busca si hay mandos conectados
|
bool discoverGameControllers(); // Busca si hay mandos conectados
|
||||||
bool gameControllerFound(); // Comprueba si hay algún mando conectado
|
bool gameControllerFound(); // Comprueba si hay algún mando conectado
|
||||||
int getNumControllers() const; // Obtiene el número de mandos conectados
|
int getNumControllers() const; // Obtiene el número de mandos conectados
|
||||||
std::string getControllerName(int controller_index) const; // Obtiene el nombre de un mando de juego
|
std::string getControllerName(int controller_index) const; // Obtiene el nombre de un mando de juego
|
||||||
int getJoyIndex(SDL_JoystickID id) const; // Obtiene el índice del controlador a partir de un event.id
|
int getJoyIndex(SDL_JoystickID id) const; // Obtiene el índice del controlador a partir de un event.id
|
||||||
|
|
||||||
// --- Métodos de consulta y utilidades ---
|
// --- Métodos de consulta y utilidades ---
|
||||||
void printBindings(InputDevice device = InputDevice::KEYBOARD, int controller_index = 0) const; // Muestra por consola los controles asignados
|
void printBindings(InputDevice device = InputDevice::KEYBOARD, int controller_index = 0) const; // Muestra por consola los controles asignados
|
||||||
SDL_GamepadButton getControllerBinding(int controller_index, InputAction input) const; // Obtiene el SDL_GamepadButton asignado a un input
|
SDL_GamepadButton getControllerBinding(int controller_index, InputAction input) const; // Obtiene el SDL_GamepadButton asignado a un input
|
||||||
std::string to_string(InputAction input) const; // Convierte un InputAction a std::string
|
std::string to_string(InputAction input) const; // Convierte un InputAction a std::string
|
||||||
InputAction to_inputs_e(const std::string &name) const; // Convierte un std::string a InputAction
|
InputAction to_inputs_e(const std::string &name) const; // Convierte un std::string a InputAction
|
||||||
int getIndexByName(const std::string &name) const; // Obtiene el índice a partir del nombre del mando
|
int getIndexByName(const std::string &name) const; // Obtiene el índice a partir del nombre del mando
|
||||||
|
|
||||||
// --- Métodos de reseteo de estado de entrada ---
|
// --- Métodos de reseteo de estado de entrada ---
|
||||||
void resetInputStates(); // Pone todos los KeyBindings.active y ControllerBindings.active a false
|
void resetInputStates(); // Pone todos los KeyBindings.active y ControllerBindings.active a false
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Singleton ---
|
// --- Singleton ---
|
||||||
static Input *instance_;
|
static Input *instance_;
|
||||||
|
|
||||||
// --- Estructuras internas ---
|
// --- Estructuras internas ---
|
||||||
struct KeyBindings
|
struct KeyBindings {
|
||||||
{
|
Uint8 scancode; // Scancode asociado
|
||||||
Uint8 scancode; // Scancode asociado
|
bool is_held; // Está pulsada ahora mismo
|
||||||
bool is_held; // Está pulsada ahora mismo
|
bool just_pressed; // Se acaba de pulsar en este fotograma
|
||||||
bool just_pressed; // Se acaba de pulsar en este fotograma
|
|
||||||
|
|
||||||
KeyBindings(Uint8 scancode = 0, bool is_held = false, bool just_pressed = false)
|
KeyBindings(Uint8 scancode = 0, bool is_held = false, bool just_pressed = false)
|
||||||
: scancode(scancode), is_held(is_held), just_pressed(just_pressed) {}
|
: scancode(scancode), is_held(is_held), just_pressed(just_pressed) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ControllerBindings
|
struct ControllerBindings {
|
||||||
{
|
SDL_GamepadButton button; // GameControllerButton asociado
|
||||||
SDL_GamepadButton button; // GameControllerButton asociado
|
bool is_held; // Está pulsada ahora mismo
|
||||||
bool is_held; // Está pulsada ahora mismo
|
bool just_pressed; // Se acaba de pulsar en este fotograma
|
||||||
bool just_pressed; // Se acaba de pulsar en este fotograma
|
bool axis_active; // Estado del eje
|
||||||
bool axis_active; // Estado del eje
|
|
||||||
|
|
||||||
ControllerBindings(SDL_GamepadButton btn = SDL_GAMEPAD_BUTTON_INVALID, bool is_held = false, bool just_pressed = false, bool axis_act = false)
|
ControllerBindings(SDL_GamepadButton btn = SDL_GAMEPAD_BUTTON_INVALID, bool is_held = false, bool just_pressed = false, bool axis_act = false)
|
||||||
: button(btn), is_held(is_held), just_pressed(just_pressed), axis_active(axis_act) {}
|
: button(btn), is_held(is_held), just_pressed(just_pressed), axis_active(axis_act) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr Sint16 AXIS_THRESHOLD_ = 30000;
|
static constexpr Sint16 AXIS_THRESHOLD_ = 30000;
|
||||||
|
|
||||||
// --- Variables internas ---
|
// --- Variables internas ---
|
||||||
std::vector<SDL_Gamepad *> connected_controllers_; // Vector con todos los mandos conectados
|
std::vector<SDL_Gamepad *> connected_controllers_; // Vector con todos los mandos conectados
|
||||||
std::vector<SDL_Joystick *> joysticks_; // Vector con todos los joysticks conectados
|
std::vector<SDL_Joystick *> joysticks_; // Vector con todos los joysticks conectados
|
||||||
std::vector<KeyBindings> key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos
|
std::vector<KeyBindings> key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos
|
||||||
std::vector<std::vector<ControllerBindings>> controller_bindings_; // Vector con los botones asociados a los inputs predefinidos para cada mando
|
std::vector<std::vector<ControllerBindings>> controller_bindings_; // Vector con los botones asociados a los inputs predefinidos para cada mando
|
||||||
std::vector<std::string> controller_names_; // Vector con los nombres de los mandos
|
std::vector<std::string> controller_names_; // Vector con los nombres de los mandos
|
||||||
std::vector<InputAction> button_inputs_; // Inputs asignados al jugador y a botones, excluyendo direcciones
|
std::vector<InputAction> button_inputs_; // Inputs asignados al jugador y a botones, excluyendo direcciones
|
||||||
int num_joysticks_ = 0; // Número de joysticks conectados
|
int num_joysticks_ = 0; // Número de joysticks conectados
|
||||||
int num_gamepads_ = 0; // Número de mandos conectados
|
int num_gamepads_ = 0; // Número de mandos conectados
|
||||||
std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt
|
std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void initSDLGamePad(); // Inicializa SDL para la gestión de mandos
|
void initSDLGamePad(); // Inicializa SDL para la gestión de mandos
|
||||||
bool checkAxisInput(InputAction input, int controller_index, bool repeat); // Comprueba el eje del mando
|
bool checkAxisInput(InputAction input, int controller_index, bool repeat); // Comprueba el eje del mando
|
||||||
|
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
explicit Input(const std::string &game_controller_db_path); // Constructor privado
|
explicit Input(const std::string &game_controller_db_path); // Constructor privado
|
||||||
~Input() = default; // Destructor privado
|
~Input() = default; // Destructor privado
|
||||||
};
|
};
|
||||||
+163
-204
@@ -1,249 +1,208 @@
|
|||||||
#include "item.h"
|
#include "item.h"
|
||||||
|
|
||||||
#include <stdlib.h> // Para rand
|
#include <stdlib.h> // Para rand
|
||||||
#include <algorithm> // Para clamp
|
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include <algorithm> // Para clamp
|
||||||
#include "param.h" // Para Param, ParamGame, param
|
|
||||||
|
|
||||||
class Texture; // lines 6-6
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
|
#include "param.h" // Para Param, ParamGame, param
|
||||||
|
|
||||||
|
class Texture; // lines 6-6
|
||||||
|
|
||||||
Item::Item(ItemType type, float x, float y, SDL_FRect &play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
|
Item::Item(ItemType type, float x, float y, SDL_FRect &play_area, std::shared_ptr<Texture> texture, const std::vector<std::string> &animation)
|
||||||
: sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
|
: sprite_(std::make_unique<AnimatedSprite>(texture, animation)),
|
||||||
type_(type),
|
type_(type),
|
||||||
play_area_(play_area)
|
play_area_(play_area) {
|
||||||
{
|
switch (type) {
|
||||||
switch (type)
|
case ItemType::COFFEE_MACHINE: {
|
||||||
{
|
width_ = COFFEE_MACHINE_WIDTH;
|
||||||
case ItemType::COFFEE_MACHINE:
|
height_ = COFFEE_MACHINE_HEIGHT;
|
||||||
{
|
pos_x_ = getCoffeeMachineSpawn(x, width_, play_area_.w);
|
||||||
width_ = COFFEE_MACHINE_WIDTH;
|
pos_y_ = y;
|
||||||
height_ = COFFEE_MACHINE_HEIGHT;
|
vel_x_ = ((rand() % 3) - 1) * 0.5f;
|
||||||
pos_x_ = getCoffeeMachineSpawn(x, width_, play_area_.w);
|
vel_y_ = -0.1f;
|
||||||
pos_y_ = y;
|
accel_y_ = 0.1f;
|
||||||
vel_x_ = ((rand() % 3) - 1) * 0.5f;
|
collider_.r = 10;
|
||||||
vel_y_ = -0.1f;
|
break;
|
||||||
accel_y_ = 0.1f;
|
}
|
||||||
collider_.r = 10;
|
default: {
|
||||||
break;
|
width_ = param.game.item_size;
|
||||||
}
|
height_ = param.game.item_size;
|
||||||
default:
|
pos_x_ = x;
|
||||||
{
|
pos_y_ = y;
|
||||||
width_ = param.game.item_size;
|
vel_x_ = -1.0f + ((rand() % 5) * 0.5f);
|
||||||
height_ = param.game.item_size;
|
vel_y_ = -4.0f;
|
||||||
pos_x_ = x;
|
accel_y_ = 0.2f;
|
||||||
pos_y_ = y;
|
collider_.r = width_ / 2;
|
||||||
vel_x_ = -1.0f + ((rand() % 5) * 0.5f);
|
break;
|
||||||
vel_y_ = -4.0f;
|
}
|
||||||
accel_y_ = 0.2f;
|
}
|
||||||
collider_.r = width_ / 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza el sprite
|
// Actualiza el sprite
|
||||||
shiftSprite();
|
shiftSprite();
|
||||||
shiftColliders();
|
shiftColliders();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::alignTo(int x)
|
void Item::alignTo(int x) {
|
||||||
{
|
const float min_x = param.game.play_area.rect.x + 1;
|
||||||
const float min_x = param.game.play_area.rect.x + 1;
|
const float max_x = play_area_.w - width_ - 1;
|
||||||
const float max_x = play_area_.w - width_ - 1;
|
|
||||||
|
|
||||||
pos_x_ = x - (width_ / 2);
|
pos_x_ = x - (width_ / 2);
|
||||||
|
|
||||||
// Ajusta para que no quede fuera de la zona de juego
|
// Ajusta para que no quede fuera de la zona de juego
|
||||||
pos_x_ = std::clamp(pos_x_, min_x, max_x);
|
pos_x_ = std::clamp(pos_x_, min_x, max_x);
|
||||||
|
|
||||||
// Actualiza el sprite
|
// Actualiza el sprite
|
||||||
shiftSprite();
|
shiftSprite();
|
||||||
shiftColliders();
|
shiftColliders();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::render()
|
void Item::render() {
|
||||||
{
|
if (enabled_) {
|
||||||
if (enabled_)
|
if (time_to_live_ > 200) {
|
||||||
{
|
sprite_->render();
|
||||||
if (time_to_live_ > 200)
|
} else if (time_to_live_ % 20 > 10) {
|
||||||
{
|
sprite_->render();
|
||||||
sprite_->render();
|
}
|
||||||
}
|
}
|
||||||
else if (time_to_live_ % 20 > 10)
|
|
||||||
{
|
|
||||||
sprite_->render();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::move()
|
void Item::move() {
|
||||||
{
|
floor_collision_ = false;
|
||||||
floor_collision_ = false;
|
|
||||||
|
|
||||||
// Calcula la nueva posición
|
// Calcula la nueva posición
|
||||||
pos_x_ += vel_x_;
|
pos_x_ += vel_x_;
|
||||||
pos_y_ += vel_y_;
|
pos_y_ += vel_y_;
|
||||||
|
|
||||||
// Aplica las aceleraciones a la velocidad
|
// Aplica las aceleraciones a la velocidad
|
||||||
vel_x_ += accel_x_;
|
vel_x_ += accel_x_;
|
||||||
vel_y_ += accel_y_;
|
vel_y_ += accel_y_;
|
||||||
|
|
||||||
// Comprueba los laterales de la zona de juego
|
// Comprueba los laterales de la zona de juego
|
||||||
const float MIN_X = param.game.play_area.rect.x;
|
const float MIN_X = param.game.play_area.rect.x;
|
||||||
const float MAX_X = play_area_.w - width_;
|
const float MAX_X = play_area_.w - width_;
|
||||||
pos_x_ = std::clamp(pos_x_, MIN_X, MAX_X);
|
pos_x_ = std::clamp(pos_x_, MIN_X, MAX_X);
|
||||||
|
|
||||||
// Si toca el borde lateral, invierte la velocidad horizontal
|
// Si toca el borde lateral, invierte la velocidad horizontal
|
||||||
if (pos_x_ == MIN_X || pos_x_ == MAX_X)
|
if (pos_x_ == MIN_X || pos_x_ == MAX_X) {
|
||||||
{
|
vel_x_ = -vel_x_;
|
||||||
vel_x_ = -vel_x_;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Si colisiona por arriba, rebota (excepto la máquina de café)
|
// Si colisiona por arriba, rebota (excepto la máquina de café)
|
||||||
if ((pos_y_ < param.game.play_area.rect.y) && !(type_ == ItemType::COFFEE_MACHINE))
|
if ((pos_y_ < param.game.play_area.rect.y) && !(type_ == ItemType::COFFEE_MACHINE)) {
|
||||||
{
|
// Corrige
|
||||||
// Corrige
|
pos_y_ = param.game.play_area.rect.y;
|
||||||
pos_y_ = param.game.play_area.rect.y;
|
|
||||||
|
|
||||||
// Invierte la velocidad
|
// Invierte la velocidad
|
||||||
vel_y_ = -vel_y_;
|
vel_y_ = -vel_y_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si colisiona con la parte inferior
|
// Si colisiona con la parte inferior
|
||||||
if (pos_y_ > play_area_.h - height_)
|
if (pos_y_ > play_area_.h - height_) {
|
||||||
{
|
// Corrige la posición
|
||||||
// Corrige la posición
|
pos_y_ = play_area_.h - height_;
|
||||||
pos_y_ = play_area_.h - height_;
|
|
||||||
|
|
||||||
switch (type_)
|
switch (type_) {
|
||||||
{
|
case ItemType::COFFEE_MACHINE:
|
||||||
case ItemType::COFFEE_MACHINE:
|
// La máquina de café es mas pesada y tiene una fisica diferente, ademas hace ruido
|
||||||
// La máquina de café es mas pesada y tiene una fisica diferente, ademas hace ruido
|
floor_collision_ = true;
|
||||||
floor_collision_ = true;
|
if (vel_y_ < 1.0f) {
|
||||||
if (vel_y_ < 1.0f)
|
// Si la velocidad vertical es baja, detiene el objeto
|
||||||
{
|
vel_y_ = vel_x_ = accel_x_ = accel_y_ = 0;
|
||||||
// Si la velocidad vertical es baja, detiene el objeto
|
} else {
|
||||||
vel_y_ = vel_x_ = accel_x_ = accel_y_ = 0;
|
// Si la velocidad vertical es alta, el objeto rebota y pierde velocidad
|
||||||
}
|
vel_y_ *= -0.20f;
|
||||||
else
|
vel_x_ *= 0.75f;
|
||||||
{
|
}
|
||||||
// Si la velocidad vertical es alta, el objeto rebota y pierde velocidad
|
break;
|
||||||
vel_y_ *= -0.20f;
|
default:
|
||||||
vel_x_ *= 0.75f;
|
// Si no es una máquina de café
|
||||||
}
|
if (vel_y_ < 1.0f) {
|
||||||
break;
|
// Si la velocidad vertical es baja, detiene el objeto
|
||||||
default:
|
vel_y_ = vel_x_ = accel_x_ = accel_y_ = 0;
|
||||||
// Si no es una máquina de café
|
} else {
|
||||||
if (vel_y_ < 1.0f)
|
// Si la velocidad vertical es alta, el objeto rebota y pierde velocidad
|
||||||
{
|
vel_y_ *= -0.5f;
|
||||||
// Si la velocidad vertical es baja, detiene el objeto
|
vel_x_ *= 0.75f;
|
||||||
vel_y_ = vel_x_ = accel_x_ = accel_y_ = 0;
|
}
|
||||||
}
|
break;
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
// Si la velocidad vertical es alta, el objeto rebota y pierde velocidad
|
|
||||||
vel_y_ *= -0.5f;
|
|
||||||
vel_x_ *= 0.75f;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Actualiza la posición del sprite
|
// Actualiza la posición del sprite
|
||||||
shiftSprite();
|
shiftSprite();
|
||||||
shiftColliders();
|
shiftColliders();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::disable() { enabled_ = false; }
|
void Item::disable() { enabled_ = false; }
|
||||||
|
|
||||||
void Item::update()
|
void Item::update() {
|
||||||
{
|
move();
|
||||||
move();
|
sprite_->update();
|
||||||
sprite_->update();
|
updateTimeToLive();
|
||||||
updateTimeToLive();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::updateTimeToLive()
|
void Item::updateTimeToLive() {
|
||||||
{
|
if (time_to_live_ > 0) {
|
||||||
if (time_to_live_ > 0)
|
time_to_live_--;
|
||||||
{
|
} else {
|
||||||
time_to_live_--;
|
disable();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
disable();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::shiftColliders()
|
void Item::shiftColliders() {
|
||||||
{
|
collider_.x = static_cast<int>(pos_x_ + (width_ / 2));
|
||||||
collider_.x = static_cast<int>(pos_x_ + (width_ / 2));
|
collider_.y = static_cast<int>(pos_y_ + (height_ / 2));
|
||||||
collider_.y = static_cast<int>(pos_y_ + (height_ / 2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::shiftSprite()
|
void Item::shiftSprite() {
|
||||||
{
|
sprite_->setPosX(pos_x_);
|
||||||
sprite_->setPosX(pos_x_);
|
sprite_->setPosY(pos_y_);
|
||||||
sprite_->setPosY(pos_y_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calcula la zona de aparición de la máquina de café
|
// Calcula la zona de aparición de la máquina de café
|
||||||
int Item::getCoffeeMachineSpawn(int player_x, int item_width, int area_width, int margin)
|
int Item::getCoffeeMachineSpawn(int player_x, int item_width, int area_width, int margin) {
|
||||||
{
|
// Distancia mínima del jugador (ajusta según necesites)
|
||||||
// Distancia mínima del jugador (ajusta según necesites)
|
const int MIN_DISTANCE_FROM_PLAYER = area_width / 2;
|
||||||
const int MIN_DISTANCE_FROM_PLAYER = area_width / 2;
|
|
||||||
|
|
||||||
const int LEFT_BOUND = margin;
|
const int LEFT_BOUND = margin;
|
||||||
const int RIGHT_BOUND = area_width - item_width - margin;
|
const int RIGHT_BOUND = area_width - item_width - margin;
|
||||||
|
|
||||||
// Calcular zona de exclusión alrededor del jugador
|
// Calcular zona de exclusión alrededor del jugador
|
||||||
int exclude_left = player_x - MIN_DISTANCE_FROM_PLAYER;
|
int exclude_left = player_x - MIN_DISTANCE_FROM_PLAYER;
|
||||||
int exclude_right = player_x + MIN_DISTANCE_FROM_PLAYER;
|
int exclude_right = player_x + MIN_DISTANCE_FROM_PLAYER;
|
||||||
|
|
||||||
// Verificar si hay espacio suficiente a la izquierda
|
// Verificar si hay espacio suficiente a la izquierda
|
||||||
bool can_spawn_left = (exclude_left > LEFT_BOUND) && (exclude_left - LEFT_BOUND > item_width);
|
bool can_spawn_left = (exclude_left > LEFT_BOUND) && (exclude_left - LEFT_BOUND > item_width);
|
||||||
|
|
||||||
// Verificar si hay espacio suficiente a la derecha
|
// Verificar si hay espacio suficiente a la derecha
|
||||||
bool can_spawn_right = (exclude_right < RIGHT_BOUND) && (RIGHT_BOUND - exclude_right > item_width);
|
bool can_spawn_right = (exclude_right < RIGHT_BOUND) && (RIGHT_BOUND - exclude_right > item_width);
|
||||||
|
|
||||||
if (can_spawn_left && can_spawn_right)
|
if (can_spawn_left && can_spawn_right) {
|
||||||
{
|
// Ambos lados disponibles, elegir aleatoriamente
|
||||||
// Ambos lados disponibles, elegir aleatoriamente
|
if (rand() % 2 == 0) {
|
||||||
if (rand() % 2 == 0)
|
// Lado izquierdo
|
||||||
{
|
return rand() % (exclude_left - LEFT_BOUND) + LEFT_BOUND;
|
||||||
// Lado izquierdo
|
} else {
|
||||||
return rand() % (exclude_left - LEFT_BOUND) + LEFT_BOUND;
|
// Lado derecho
|
||||||
}
|
return rand() % (RIGHT_BOUND - exclude_right) + exclude_right;
|
||||||
else
|
}
|
||||||
{
|
} else if (can_spawn_left) {
|
||||||
// Lado derecho
|
// Solo lado izquierdo disponible
|
||||||
return rand() % (RIGHT_BOUND - exclude_right) + exclude_right;
|
return rand() % (exclude_left - LEFT_BOUND) + LEFT_BOUND;
|
||||||
}
|
} else if (can_spawn_right) {
|
||||||
}
|
// Solo lado derecho disponible
|
||||||
else if (can_spawn_left)
|
return rand() % (RIGHT_BOUND - exclude_right) + exclude_right;
|
||||||
{
|
} else {
|
||||||
// Solo lado izquierdo disponible
|
// No hay espacio suficiente lejos del jugador
|
||||||
return rand() % (exclude_left - LEFT_BOUND) + LEFT_BOUND;
|
// Por ahora, intentar spawn en el extremo más lejano posible
|
||||||
}
|
int distance_to_left = abs(player_x - LEFT_BOUND);
|
||||||
else if (can_spawn_right)
|
int distance_to_right = abs(RIGHT_BOUND - player_x);
|
||||||
{
|
|
||||||
// Solo lado derecho disponible
|
|
||||||
return rand() % (RIGHT_BOUND - exclude_right) + exclude_right;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No hay espacio suficiente lejos del jugador
|
|
||||||
// Por ahora, intentar spawn en el extremo más lejano posible
|
|
||||||
int distance_to_left = abs(player_x - LEFT_BOUND);
|
|
||||||
int distance_to_right = abs(RIGHT_BOUND - player_x);
|
|
||||||
|
|
||||||
if (distance_to_left > distance_to_right)
|
if (distance_to_left > distance_to_right) {
|
||||||
{
|
return LEFT_BOUND;
|
||||||
return LEFT_BOUND;
|
} else {
|
||||||
}
|
return RIGHT_BOUND - item_width;
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
return RIGHT_BOUND - item_width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+34
-35
@@ -1,34 +1,33 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FRect, Uint16
|
#include <SDL3/SDL.h> // Para SDL_FRect, Uint16
|
||||||
#include <memory> // Para shared_ptr, unique_ptr
|
|
||||||
#include <string> // Para string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include <memory> // Para shared_ptr, unique_ptr
|
||||||
#include "utils.h" // Para Circle
|
#include <string> // Para string
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
|
#include "utils.h" // Para Circle
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Tipos de objetos disponibles en el juego.
|
// Tipos de objetos disponibles en el juego.
|
||||||
// Define los diferentes tipos de objetos que pueden existir en el juego.
|
// Define los diferentes tipos de objetos que pueden existir en el juego.
|
||||||
enum class ItemType : int
|
enum class ItemType : int {
|
||||||
{
|
DISK = 1, // Disco
|
||||||
DISK = 1, // Disco
|
GAVINA = 2, // Gavina
|
||||||
GAVINA = 2, // Gavina
|
PACMAR = 3, // Pacman
|
||||||
PACMAR = 3, // Pacman
|
CLOCK = 4, // Reloj
|
||||||
CLOCK = 4, // Reloj
|
COFFEE = 5, // Café
|
||||||
COFFEE = 5, // Café
|
DEBIAN = 6, // Debian
|
||||||
DEBIAN = 6, // Debian
|
COFFEE_MACHINE = 7, // Máquina de café
|
||||||
COFFEE_MACHINE = 7, // Máquina de café
|
NONE = 8, // Ninguno
|
||||||
NONE = 8, // Ninguno
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clase Item.
|
// Clase Item.
|
||||||
// Representa un objeto en el juego, con sus propiedades y métodos para gestionar su comportamiento.
|
// Representa un objeto en el juego, con sus propiedades y métodos para gestionar su comportamiento.
|
||||||
class Item
|
class Item {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// Constantes
|
// Constantes
|
||||||
static constexpr int COFFEE_MACHINE_WIDTH = 30;
|
static constexpr int COFFEE_MACHINE_WIDTH = 30;
|
||||||
static constexpr int COFFEE_MACHINE_HEIGHT = 39;
|
static constexpr int COFFEE_MACHINE_HEIGHT = 39;
|
||||||
@@ -64,25 +63,25 @@ public:
|
|||||||
bool isOnFloor() const { return floor_collision_; }
|
bool isOnFloor() const { return floor_collision_; }
|
||||||
Circle &getCollider() { return collider_; }
|
Circle &getCollider() { return collider_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Objetos y punteros
|
// Objetos y punteros
|
||||||
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos del objeto
|
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos del objeto
|
||||||
|
|
||||||
// Variables de estado y físicas
|
// Variables de estado y físicas
|
||||||
float pos_x_; // Posición X del objeto
|
float pos_x_; // Posición X del objeto
|
||||||
float pos_y_; // Posición Y del objeto
|
float pos_y_; // Posición Y del objeto
|
||||||
int width_; // Ancho del objeto
|
int width_; // Ancho del objeto
|
||||||
int height_; // Alto del objeto
|
int height_; // Alto del objeto
|
||||||
float vel_x_; // Velocidad en el eje X
|
float vel_x_; // Velocidad en el eje X
|
||||||
float vel_y_; // Velocidad en el eje Y
|
float vel_y_; // Velocidad en el eje Y
|
||||||
float accel_x_ = 0.0f; // Aceleración en el eje X
|
float accel_x_ = 0.0f; // Aceleración en el eje X
|
||||||
float accel_y_; // Aceleración en el eje Y
|
float accel_y_; // Aceleración en el eje Y
|
||||||
bool floor_collision_ = false; // Indica si el objeto colisiona con el suelo
|
bool floor_collision_ = false; // Indica si el objeto colisiona con el suelo
|
||||||
ItemType type_; // Tipo de objeto
|
ItemType type_; // Tipo de objeto
|
||||||
bool enabled_ = true; // Indica si el objeto está habilitado
|
bool enabled_ = true; // Indica si el objeto está habilitado
|
||||||
Circle collider_; // Círculo de colisión del objeto
|
Circle collider_; // Círculo de colisión del objeto
|
||||||
SDL_FRect play_area_; // Rectángulo con la zona de juego
|
SDL_FRect play_area_; // Rectángulo con la zona de juego
|
||||||
Uint16 time_to_live_ = 600; // Tiempo que el objeto está presente
|
Uint16 time_to_live_ = 600; // Tiempo que el objeto está presente
|
||||||
|
|
||||||
// Alinea el círculo de colisión con la posición del objeto.
|
// Alinea el círculo de colisión con la posición del objeto.
|
||||||
// Actualiza las coordenadas X e Y del colisionador.
|
// Actualiza las coordenadas X e Y del colisionador.
|
||||||
|
|||||||
+102
-126
@@ -1,123 +1,105 @@
|
|||||||
#include "lang.h"
|
#include "lang.h"
|
||||||
|
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
#include <exception> // Para exception
|
|
||||||
#include <fstream> // Para basic_ifstream, basic_istream, ifstream
|
|
||||||
#include <unordered_map> // Para unordered_map, _Node_iterator, operator==
|
|
||||||
#include <utility> // Para pair
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "asset.h" // Para Asset
|
#include <exception> // Para exception
|
||||||
#include "external/json.hpp" // Para basic_json, iteration_proxy_value, oper...
|
#include <fstream> // Para basic_ifstream, basic_istream, ifstream
|
||||||
#include "options.h" // Para Difficulty, DifficultyCode, SettingsOpt...
|
#include <unordered_map> // Para unordered_map, _Node_iterator, operator==
|
||||||
|
#include <utility> // Para pair
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
|
#include "asset.h" // Para Asset
|
||||||
|
#include "external/json.hpp" // Para basic_json, iteration_proxy_value, oper...
|
||||||
|
#include "options.h" // Para Difficulty, DifficultyCode, SettingsOpt...
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
namespace Lang
|
namespace Lang {
|
||||||
{
|
std::unordered_map<std::string, std::string> texts;
|
||||||
std::unordered_map<std::string, std::string> texts;
|
|
||||||
|
|
||||||
// Vector con los idiomas soportados
|
// Vector con los idiomas soportados
|
||||||
std::vector<Language> languages = {
|
std::vector<Language> languages = {
|
||||||
{Code::SPANISH, "Castellano", "es_ES.json"},
|
{Code::SPANISH, "Castellano", "es_ES.json"},
|
||||||
{Code::VALENCIAN, "Balooncia", "ba_BA.json"},
|
{Code::VALENCIAN, "Balooncia", "ba_BA.json"},
|
||||||
{Code::ENGLISH, "Ingles", "en_UK.json"}};
|
{Code::ENGLISH, "Ingles", "en_UK.json"}};
|
||||||
|
|
||||||
// Inicializa los textos del juego en el idioma seleccionado
|
// Inicializa los textos del juego en el idioma seleccionado
|
||||||
bool loadFromFile(const std::string &file_path)
|
bool loadFromFile(const std::string &file_path) {
|
||||||
{
|
texts.clear();
|
||||||
texts.clear();
|
|
||||||
|
|
||||||
std::ifstream rfile(file_path);
|
std::ifstream rfile(file_path);
|
||||||
if (!rfile.is_open())
|
if (!rfile.is_open())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
try
|
try {
|
||||||
{
|
json j;
|
||||||
json j;
|
rfile >> j;
|
||||||
rfile >> j;
|
|
||||||
|
|
||||||
for (auto &el : j.items())
|
for (auto &el : j.items()) {
|
||||||
{
|
texts[el.key()] = el.value();
|
||||||
texts[el.key()] = el.value();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
} catch (const std::exception &e) {
|
||||||
{
|
// Puedes loguear el error si quieres
|
||||||
// Puedes loguear el error si quieres
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el texto por clave
|
return true;
|
||||||
std::string getText(const std::string &key)
|
}
|
||||||
{
|
|
||||||
auto it = texts.find(key);
|
|
||||||
if (it != texts.end())
|
|
||||||
return it->second;
|
|
||||||
else
|
|
||||||
return "[missing text: " + key + "]";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtiene el código del siguiente idioma disponible
|
// Obtiene el texto por clave
|
||||||
Code getNextLangCode(Code lang)
|
std::string getText(const std::string &key) {
|
||||||
{
|
auto it = texts.find(key);
|
||||||
for (size_t i = 0; i < languages.size(); ++i)
|
if (it != texts.end())
|
||||||
{
|
return it->second;
|
||||||
if (languages[i].code == lang)
|
else
|
||||||
{
|
return "[missing text: " + key + "]";
|
||||||
return languages[(i + 1) % languages.size()].code;
|
}
|
||||||
}
|
|
||||||
|
// Obtiene el código del siguiente idioma disponible
|
||||||
|
Code getNextLangCode(Code lang) {
|
||||||
|
for (size_t i = 0; i < languages.size(); ++i) {
|
||||||
|
if (languages[i].code == lang) {
|
||||||
|
return languages[(i + 1) % languages.size()].code;
|
||||||
}
|
}
|
||||||
// Si no se encuentra, devuelve el primero por defecto
|
|
||||||
return languages[0].code;
|
|
||||||
}
|
}
|
||||||
|
// Si no se encuentra, devuelve el primero por defecto
|
||||||
|
return languages[0].code;
|
||||||
|
}
|
||||||
|
|
||||||
// Obtiene un idioma del vector de idiomas a partir de un código
|
// Obtiene un idioma del vector de idiomas a partir de un código
|
||||||
Language getLanguage(Code code)
|
Language getLanguage(Code code) {
|
||||||
{
|
for (const auto &lang : languages) {
|
||||||
for (const auto &lang : languages)
|
if (lang.code == code)
|
||||||
{
|
return lang;
|
||||||
if (lang.code == code)
|
|
||||||
return lang;
|
|
||||||
}
|
|
||||||
// Si no se encuentra, devuelve el primero por defecto
|
|
||||||
return languages[0];
|
|
||||||
}
|
}
|
||||||
|
// Si no se encuentra, devuelve el primero por defecto
|
||||||
|
return languages[0];
|
||||||
|
}
|
||||||
|
|
||||||
// Devuelve el código de un idioma a partir de un nombre
|
// Devuelve el código de un idioma a partir de un nombre
|
||||||
Code getCodeFromName(const std::string &name)
|
Code getCodeFromName(const std::string &name) {
|
||||||
{
|
for (const auto &lang : languages) {
|
||||||
for (const auto &lang : languages)
|
if (lang.name == name)
|
||||||
{
|
return lang.code;
|
||||||
if (lang.name == name)
|
|
||||||
return lang.code;
|
|
||||||
}
|
|
||||||
// Si no se encuentra, devuelve el primero por defecto
|
|
||||||
return languages[0].code;
|
|
||||||
}
|
}
|
||||||
|
// Si no se encuentra, devuelve el primero por defecto
|
||||||
|
return languages[0].code;
|
||||||
|
}
|
||||||
|
|
||||||
// Devuelve el nombre de un idioma a partir de un código
|
// Devuelve el nombre de un idioma a partir de un código
|
||||||
std::string getNameFromCode(Code code)
|
std::string getNameFromCode(Code code) {
|
||||||
{
|
for (const auto &lang : languages) {
|
||||||
for (const auto &lang : languages)
|
if (lang.code == code)
|
||||||
{
|
return lang.name;
|
||||||
if (lang.code == code)
|
|
||||||
return lang.name;
|
|
||||||
}
|
|
||||||
// Si no se encuentra, devuelve el nombre del primer idioma por defecto
|
|
||||||
return languages[0].name;
|
|
||||||
}
|
}
|
||||||
|
// Si no se encuentra, devuelve el nombre del primer idioma por defecto
|
||||||
|
return languages[0].name;
|
||||||
|
}
|
||||||
|
|
||||||
// Actualiza los nombres de los idiomas
|
// Actualiza los nombres de los idiomas
|
||||||
void updateLanguageNames()
|
void updateLanguageNames() {
|
||||||
{
|
for (auto &lang : languages) {
|
||||||
for (auto &lang : languages)
|
switch (lang.code) {
|
||||||
{
|
|
||||||
switch (lang.code)
|
|
||||||
{
|
|
||||||
case Code::SPANISH:
|
case Code::SPANISH:
|
||||||
lang.name = Lang::getText("[SERVICE_MENU] LANG_ES");
|
lang.name = Lang::getText("[SERVICE_MENU] LANG_ES");
|
||||||
break;
|
break;
|
||||||
@@ -130,17 +112,14 @@ namespace Lang
|
|||||||
default:
|
default:
|
||||||
lang.name = "Unknown";
|
lang.name = "Unknown";
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Actualiza los nombres de las dificultades
|
// Actualiza los nombres de las dificultades
|
||||||
void updateDifficultyNames()
|
void updateDifficultyNames() {
|
||||||
{
|
for (auto &difficulty : Options::difficulties) {
|
||||||
for (auto &difficulty : Options::difficulties)
|
switch (difficulty.code) {
|
||||||
{
|
|
||||||
switch (difficulty.code)
|
|
||||||
{
|
|
||||||
case Options::DifficultyCode::EASY:
|
case Options::DifficultyCode::EASY:
|
||||||
difficulty.name = Lang::getText("[SERVICE_MENU] EASY");
|
difficulty.name = Lang::getText("[SERVICE_MENU] EASY");
|
||||||
break;
|
break;
|
||||||
@@ -153,28 +132,25 @@ namespace Lang
|
|||||||
default:
|
default:
|
||||||
difficulty.name = "Unknown";
|
difficulty.name = "Unknown";
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene una fichero a partir de un lang::Code
|
|
||||||
std::string getLanguageFileName(Lang::Code code)
|
|
||||||
{
|
|
||||||
for (const auto &lang : languages)
|
|
||||||
{
|
|
||||||
if (lang.code == code)
|
|
||||||
return Asset::get()->get(lang.file_name);
|
|
||||||
}
|
|
||||||
// Si no se encuentra, devuelve el fichero del primer idioma por defecto
|
|
||||||
return Asset::get()->get(languages[0].file_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Establece el idioma
|
|
||||||
void setLanguage(Code lang)
|
|
||||||
{
|
|
||||||
Options::settings.language = lang;
|
|
||||||
loadFromFile(Asset::get()->get(getLanguage(lang).file_name));
|
|
||||||
updateLanguageNames();
|
|
||||||
updateDifficultyNames();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Obtiene una fichero a partir de un lang::Code
|
||||||
|
std::string getLanguageFileName(Lang::Code code) {
|
||||||
|
for (const auto &lang : languages) {
|
||||||
|
if (lang.code == code)
|
||||||
|
return Asset::get()->get(lang.file_name);
|
||||||
|
}
|
||||||
|
// Si no se encuentra, devuelve el fichero del primer idioma por defecto
|
||||||
|
return Asset::get()->get(languages[0].file_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establece el idioma
|
||||||
|
void setLanguage(Code lang) {
|
||||||
|
Options::settings.language = lang;
|
||||||
|
loadFromFile(Asset::get()->get(getLanguage(lang).file_name));
|
||||||
|
updateLanguageNames();
|
||||||
|
updateDifficultyNames();
|
||||||
|
}
|
||||||
|
} // namespace Lang
|
||||||
+35
-38
@@ -1,52 +1,49 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string> // Para string, basic_string
|
#include <string> // Para string, basic_string
|
||||||
|
|
||||||
namespace Lang
|
namespace Lang {
|
||||||
{
|
// --- Códigos de idioma soportados ---
|
||||||
// --- Códigos de idioma soportados ---
|
enum class Code : int {
|
||||||
enum class Code : int
|
SPANISH = 0,
|
||||||
{
|
VALENCIAN = 1,
|
||||||
SPANISH = 0,
|
ENGLISH = 2
|
||||||
VALENCIAN = 1,
|
};
|
||||||
ENGLISH = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
// Estructura que representa un idioma
|
// Estructura que representa un idioma
|
||||||
struct Language
|
struct Language {
|
||||||
{
|
Code code; // Código que identifica al idioma
|
||||||
Code code; // Código que identifica al idioma
|
std::string name; // Nombre que identifica el idioma
|
||||||
std::string name; // Nombre que identifica el idioma
|
std::string file_name; // Nombre del fichero con los textos
|
||||||
std::string file_name; // Nombre del fichero con los textos
|
|
||||||
|
|
||||||
Language(Code c, const std::string &n, const std::string &fn)
|
Language(Code c, const std::string &n, const std::string &fn)
|
||||||
: code(c), name(n), file_name(fn) {}
|
: code(c), name(n), file_name(fn) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Carga los textos desde el fichero JSON especificado
|
// Carga los textos desde el fichero JSON especificado
|
||||||
bool loadFromFile(const std::string &file_path);
|
bool loadFromFile(const std::string &file_path);
|
||||||
|
|
||||||
// Obtiene el texto por clave
|
// Obtiene el texto por clave
|
||||||
std::string getText(const std::string &key);
|
std::string getText(const std::string &key);
|
||||||
|
|
||||||
// Obtiene el código del siguiente idioma (circular)
|
// Obtiene el código del siguiente idioma (circular)
|
||||||
Code getNextLangCode(Code current_lang);
|
Code getNextLangCode(Code current_lang);
|
||||||
|
|
||||||
// Obtiene el idioma correspondiente al código proporcionado
|
// Obtiene el idioma correspondiente al código proporcionado
|
||||||
Language getLanguage(Code code);
|
Language getLanguage(Code code);
|
||||||
|
|
||||||
// Devuelve el código de un idioma a partir de un nombre
|
// Devuelve el código de un idioma a partir de un nombre
|
||||||
Code getCodeFromName(const std::string &name);
|
Code getCodeFromName(const std::string &name);
|
||||||
|
|
||||||
// Devuelve el nombre de un idioma a partir de un código
|
// Devuelve el nombre de un idioma a partir de un código
|
||||||
std::string getNameFromCode(Code code);
|
std::string getNameFromCode(Code code);
|
||||||
|
|
||||||
// Actualiza los nombres de los idiomas
|
// Actualiza los nombres de los idiomas
|
||||||
void updateLanguageNames();
|
void updateLanguageNames();
|
||||||
|
|
||||||
// Obtiene el nombre del fichero de textos asociado a un código de idioma
|
// Obtiene el nombre del fichero de textos asociado a un código de idioma
|
||||||
std::string getLanguageFileName(Code code);
|
std::string getLanguageFileName(Code code);
|
||||||
|
|
||||||
// Establece el idioma actual
|
// Establece el idioma actual
|
||||||
void setLanguage(Code lang);
|
void setLanguage(Code lang);
|
||||||
}
|
} // namespace Lang
|
||||||
+3
-4
@@ -7,12 +7,11 @@ Actualizando a la versión "Arcade Edition" en 08/05/2024
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <memory> // Para make_unique, unique_ptr
|
#include <memory> // Para make_unique, unique_ptr
|
||||||
|
|
||||||
#include "director.h" // Para Director
|
#include "director.h" // Para Director
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[]) {
|
||||||
{
|
|
||||||
// Crea el objeto Director
|
// Crea el objeto Director
|
||||||
auto director = std::make_unique<Director>(argc, const_cast<const char **>(argv));
|
auto director = std::make_unique<Director>(argc, const_cast<const char **>(argv));
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
#include "manage_hiscore_table.h"
|
#include "manage_hiscore_table.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_ReadIO, SDL_WriteIO, SDL_CloseIO, SDL_GetE...
|
#include <SDL3/SDL.h> // Para SDL_ReadIO, SDL_WriteIO, SDL_CloseIO, SDL_GetE...
|
||||||
|
|
||||||
#include <algorithm> // Para find_if, sort
|
#include <algorithm> // Para find_if, sort
|
||||||
#include <iterator> // Para distance
|
#include <iterator> // Para distance
|
||||||
|
|
||||||
#include "utils.h" // Para getFileName
|
#include "utils.h" // Para getFileName
|
||||||
|
|
||||||
// Resetea la tabla a los valores por defecto
|
// Resetea la tabla a los valores por defecto
|
||||||
void ManageHiScoreTable::clear()
|
void ManageHiScoreTable::clear() {
|
||||||
{
|
|
||||||
// Limpia la tabla
|
// Limpia la tabla
|
||||||
table_.clear();
|
table_.clear();
|
||||||
|
|
||||||
@@ -28,8 +28,7 @@ void ManageHiScoreTable::clear()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Añade un elemento a la tabla
|
// Añade un elemento a la tabla
|
||||||
int ManageHiScoreTable::add(const HiScoreEntry &entry)
|
int ManageHiScoreTable::add(const HiScoreEntry &entry) {
|
||||||
{
|
|
||||||
// Añade la entrada a la tabla
|
// Añade la entrada a la tabla
|
||||||
table_.push_back(entry);
|
table_.push_back(entry);
|
||||||
|
|
||||||
@@ -37,26 +36,22 @@ int ManageHiScoreTable::add(const HiScoreEntry &entry)
|
|||||||
sort();
|
sort();
|
||||||
|
|
||||||
// Encontrar la posición del nuevo elemento
|
// Encontrar la posición del nuevo elemento
|
||||||
auto it = std::find_if(table_.begin(), table_.end(), [&](const HiScoreEntry &e)
|
auto it = std::find_if(table_.begin(), table_.end(), [&](const HiScoreEntry &e) { return e.name == entry.name &&
|
||||||
{ return e.name == entry.name &&
|
e.score == entry.score &&
|
||||||
e.score == entry.score &&
|
e.one_credit_complete == entry.one_credit_complete; });
|
||||||
e.one_credit_complete == entry.one_credit_complete; });
|
|
||||||
|
|
||||||
int position = -1;
|
int position = -1;
|
||||||
if (it != table_.end())
|
if (it != table_.end()) {
|
||||||
{
|
|
||||||
position = std::distance(table_.begin(), it);
|
position = std::distance(table_.begin(), it);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deja solo las 10 primeras entradas
|
// Deja solo las 10 primeras entradas
|
||||||
if (table_.size() > 10)
|
if (table_.size() > 10) {
|
||||||
{
|
|
||||||
table_.resize(10);
|
table_.resize(10);
|
||||||
|
|
||||||
// Si el nuevo elemento quedó fuera del top 10
|
// Si el nuevo elemento quedó fuera del top 10
|
||||||
if (position >= 10)
|
if (position >= 10) {
|
||||||
{
|
position = -1; // No entró en el top 10
|
||||||
position = -1; // No entró en el top 10
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,8 +60,7 @@ int ManageHiScoreTable::add(const HiScoreEntry &entry)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ordena la tabla
|
// Ordena la tabla
|
||||||
void ManageHiScoreTable::sort()
|
void ManageHiScoreTable::sort() {
|
||||||
{
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool operator()(const HiScoreEntry &a, const HiScoreEntry &b) const { return a.score > b.score; }
|
bool operator()(const HiScoreEntry &a, const HiScoreEntry &b) const { return a.score > b.score; }
|
||||||
@@ -76,23 +70,20 @@ void ManageHiScoreTable::sort()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Carga la tabla desde un fichero
|
// Carga la tabla desde un fichero
|
||||||
bool ManageHiScoreTable::loadFromFile(const std::string &file_path)
|
bool ManageHiScoreTable::loadFromFile(const std::string &file_path) {
|
||||||
{
|
|
||||||
clear();
|
clear();
|
||||||
auto success = true;
|
auto success = true;
|
||||||
auto file = SDL_IOFromFile(file_path.c_str(), "rb");
|
auto file = SDL_IOFromFile(file_path.c_str(), "rb");
|
||||||
|
|
||||||
if (file)
|
if (file) {
|
||||||
{
|
table_.clear(); // Limpia la tabla actual
|
||||||
table_.clear(); // Limpia la tabla actual
|
|
||||||
|
|
||||||
// Lee el número de entradas en la tabla
|
// Lee el número de entradas en la tabla
|
||||||
int table_size = 0;
|
int table_size = 0;
|
||||||
SDL_ReadIO(file, &table_size, sizeof(int));
|
SDL_ReadIO(file, &table_size, sizeof(int));
|
||||||
|
|
||||||
// Lee los datos de cada entrada
|
// Lee los datos de cada entrada
|
||||||
for (int i = 0; i < table_size; ++i)
|
for (int i = 0; i < table_size; ++i) {
|
||||||
{
|
|
||||||
HiScoreEntry entry;
|
HiScoreEntry entry;
|
||||||
|
|
||||||
// Lee la puntuación
|
// Lee la puntuación
|
||||||
@@ -104,7 +95,7 @@ bool ManageHiScoreTable::loadFromFile(const std::string &file_path)
|
|||||||
|
|
||||||
std::vector<char> name_buffer(name_size + 1);
|
std::vector<char> name_buffer(name_size + 1);
|
||||||
SDL_ReadIO(file, name_buffer.data(), name_size);
|
SDL_ReadIO(file, name_buffer.data(), name_size);
|
||||||
name_buffer[name_size] = '\0'; // Asegurar el fin de la cadena
|
name_buffer[name_size] = '\0'; // Asegurar el fin de la cadena
|
||||||
entry.name = std::string(name_buffer.data());
|
entry.name = std::string(name_buffer.data());
|
||||||
|
|
||||||
// Lee el valor de one_credit_complete
|
// Lee el valor de one_credit_complete
|
||||||
@@ -118,9 +109,7 @@ bool ManageHiScoreTable::loadFromFile(const std::string &file_path)
|
|||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\nReading file: %s", getFileName(file_path).c_str());
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\nReading file: %s", getFileName(file_path).c_str());
|
||||||
SDL_CloseIO(file);
|
SDL_CloseIO(file);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Unable to load %s file! %s", getFileName(file_path).c_str(), SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Unable to load %s file! %s", getFileName(file_path).c_str(), SDL_GetError());
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
@@ -128,20 +117,17 @@ bool ManageHiScoreTable::loadFromFile(const std::string &file_path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Guarda la tabla en un fichero
|
// Guarda la tabla en un fichero
|
||||||
bool ManageHiScoreTable::saveToFile(const std::string &file_path)
|
bool ManageHiScoreTable::saveToFile(const std::string &file_path) {
|
||||||
{
|
|
||||||
auto success = true;
|
auto success = true;
|
||||||
auto file = SDL_IOFromFile(file_path.c_str(), "w+b");
|
auto file = SDL_IOFromFile(file_path.c_str(), "w+b");
|
||||||
|
|
||||||
if (file)
|
if (file) {
|
||||||
{
|
|
||||||
// Guarda el número de entradas en la tabla
|
// Guarda el número de entradas en la tabla
|
||||||
int table_size = static_cast<int>(table_.size());
|
int table_size = static_cast<int>(table_.size());
|
||||||
SDL_WriteIO(file, &table_size, sizeof(int));
|
SDL_WriteIO(file, &table_size, sizeof(int));
|
||||||
|
|
||||||
// Guarda los datos de cada entrada
|
// Guarda los datos de cada entrada
|
||||||
for (int i = 0; i < table_size; ++i)
|
for (int i = 0; i < table_size; ++i) {
|
||||||
{
|
|
||||||
const HiScoreEntry &entry = table_.at(i);
|
const HiScoreEntry &entry = table_.at(i);
|
||||||
|
|
||||||
// Guarda la puntuación
|
// Guarda la puntuación
|
||||||
@@ -159,9 +145,7 @@ bool ManageHiScoreTable::saveToFile(const std::string &file_path)
|
|||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Writing file: %s", getFileName(file_path).c_str());
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Writing file: %s", getFileName(file_path).c_str());
|
||||||
SDL_CloseIO(file);
|
SDL_CloseIO(file);
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Unable to save %s file! %s", getFileName(file_path).c_str(), SDL_GetError());
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Unable to save %s file! %s", getFileName(file_path).c_str(), SDL_GetError());
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string> // Para std::string
|
#include <string> // Para std::string
|
||||||
#include <vector> // Para std::vector
|
#include <vector> // Para std::vector
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Esta clase sirve para añadir elementos HiScoreEntry a un vector (tabla), de manera
|
Esta clase sirve para añadir elementos HiScoreEntry a un vector (tabla), de manera
|
||||||
@@ -12,11 +12,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// --- Estructura para las entradas de la tabla de records ---
|
// --- Estructura para las entradas de la tabla de records ---
|
||||||
struct HiScoreEntry
|
struct HiScoreEntry {
|
||||||
{
|
std::string name; // Nombre
|
||||||
std::string name; // Nombre
|
int score; // Puntuación
|
||||||
int score; // Puntuación
|
bool one_credit_complete; // Indica si se ha conseguido 1CC
|
||||||
bool one_credit_complete; // Indica si se ha conseguido 1CC
|
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
explicit HiScoreEntry(const std::string &n = "", int s = 0, bool occ = false)
|
explicit HiScoreEntry(const std::string &n = "", int s = 0, bool occ = false)
|
||||||
@@ -24,9 +23,8 @@ struct HiScoreEntry
|
|||||||
};
|
};
|
||||||
|
|
||||||
// --- Clase ManageHiScoreTable ---
|
// --- Clase ManageHiScoreTable ---
|
||||||
class ManageHiScoreTable
|
class ManageHiScoreTable {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// Constructor
|
// Constructor
|
||||||
explicit ManageHiScoreTable(std::vector<HiScoreEntry> &table)
|
explicit ManageHiScoreTable(std::vector<HiScoreEntry> &table)
|
||||||
: table_(table) {}
|
: table_(table) {}
|
||||||
@@ -46,7 +44,7 @@ public:
|
|||||||
// Guarda la tabla en un fichero
|
// Guarda la tabla en un fichero
|
||||||
bool saveToFile(const std::string &file_path);
|
bool saveToFile(const std::string &file_path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Referencia a la tabla con los records
|
// Referencia a la tabla con los records
|
||||||
std::vector<HiScoreEntry> &table_;
|
std::vector<HiScoreEntry> &table_;
|
||||||
|
|
||||||
|
|||||||
+20
-26
@@ -1,33 +1,27 @@
|
|||||||
#include "mouse.h"
|
#include "mouse.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_GetTicks, Uint32, SDL_HideCursor, SDL_Show...
|
#include <SDL3/SDL.h> // Para SDL_GetTicks, Uint32, SDL_HideCursor, SDL_Show...
|
||||||
|
|
||||||
namespace Mouse
|
namespace Mouse {
|
||||||
{
|
Uint32 cursor_hide_time = 3000; // Tiempo en milisegundos para ocultar el cursor
|
||||||
Uint32 cursor_hide_time = 3000; // Tiempo en milisegundos para ocultar el cursor
|
Uint32 last_mouse_move_time = 0; // Última vez que el ratón se movió
|
||||||
Uint32 last_mouse_move_time = 0; // Última vez que el ratón se movió
|
bool cursor_visible = true; // Estado del cursor
|
||||||
bool cursor_visible = true; // Estado del cursor
|
|
||||||
|
|
||||||
void handleEvent(const SDL_Event &event)
|
void handleEvent(const SDL_Event &event) {
|
||||||
{
|
if (event.type == SDL_EVENT_MOUSE_MOTION) {
|
||||||
if (event.type == SDL_EVENT_MOUSE_MOTION)
|
last_mouse_move_time = SDL_GetTicks();
|
||||||
{
|
if (!cursor_visible) {
|
||||||
last_mouse_move_time = SDL_GetTicks();
|
SDL_ShowCursor();
|
||||||
if (!cursor_visible)
|
cursor_visible = true;
|
||||||
{
|
|
||||||
SDL_ShowCursor();
|
|
||||||
cursor_visible = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateCursorVisibility()
|
|
||||||
{
|
|
||||||
Uint32 current_time = SDL_GetTicks();
|
|
||||||
if (cursor_visible && (current_time - last_mouse_move_time > cursor_hide_time))
|
|
||||||
{
|
|
||||||
SDL_HideCursor();
|
|
||||||
cursor_visible = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateCursorVisibility() {
|
||||||
|
Uint32 current_time = SDL_GetTicks();
|
||||||
|
if (cursor_visible && (current_time - last_mouse_move_time > cursor_hide_time)) {
|
||||||
|
SDL_HideCursor();
|
||||||
|
cursor_visible = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace Mouse
|
||||||
+10
-11
@@ -1,15 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para Uint32, SDL_Event
|
#include <SDL3/SDL.h> // Para Uint32, SDL_Event
|
||||||
|
|
||||||
namespace Mouse
|
namespace Mouse {
|
||||||
{
|
// --- Variables de estado del cursor ---
|
||||||
// --- Variables de estado del cursor ---
|
extern Uint32 cursor_hide_time; // Tiempo en milisegundos para ocultar el cursor tras inactividad
|
||||||
extern Uint32 cursor_hide_time; // Tiempo en milisegundos para ocultar el cursor tras inactividad
|
extern Uint32 last_mouse_move_time; // Última vez (en ms) que el ratón se movió
|
||||||
extern Uint32 last_mouse_move_time; // Última vez (en ms) que el ratón se movió
|
extern bool cursor_visible; // Indica si el cursor está visible
|
||||||
extern bool cursor_visible; // Indica si el cursor está visible
|
|
||||||
|
|
||||||
// --- Gestión de eventos y visibilidad ---
|
// --- Gestión de eventos y visibilidad ---
|
||||||
void handleEvent(const SDL_Event &event); // Procesa eventos de ratón (movimiento, clic, etc.)
|
void handleEvent(const SDL_Event &event); // Procesa eventos de ratón (movimiento, clic, etc.)
|
||||||
void updateCursorVisibility(); // Actualiza la visibilidad del cursor según la inactividad
|
void updateCursorVisibility(); // Actualiza la visibilidad del cursor según la inactividad
|
||||||
}
|
} // namespace Mouse
|
||||||
+70
-81
@@ -1,130 +1,119 @@
|
|||||||
#include "moving_sprite.h"
|
#include "moving_sprite.h"
|
||||||
|
|
||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos, Rotate rotate, float zoom_w, float zoom_h, SDL_FlipMode flip)
|
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos, Rotate rotate, float zoom_w, float zoom_h, SDL_FlipMode flip)
|
||||||
: Sprite(texture, pos),
|
: Sprite(texture, pos),
|
||||||
x_(pos.x),
|
x_(pos.x),
|
||||||
y_(pos.y),
|
y_(pos.y),
|
||||||
rotate_(rotate),
|
rotate_(rotate),
|
||||||
zoom_w_(zoom_w),
|
zoom_w_(zoom_w),
|
||||||
zoom_h_(zoom_h),
|
zoom_h_(zoom_h),
|
||||||
flip_(flip) {}
|
flip_(flip) {}
|
||||||
|
|
||||||
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos)
|
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture, SDL_FRect pos)
|
||||||
: Sprite(texture, pos),
|
: Sprite(texture, pos),
|
||||||
x_(pos.x),
|
x_(pos.x),
|
||||||
y_(pos.y),
|
y_(pos.y),
|
||||||
rotate_(Rotate()),
|
rotate_(Rotate()),
|
||||||
zoom_w_(1.0f),
|
zoom_w_(1.0f),
|
||||||
zoom_h_(1.0f),
|
zoom_h_(1.0f),
|
||||||
flip_(SDL_FLIP_NONE) {}
|
flip_(SDL_FLIP_NONE) {}
|
||||||
|
|
||||||
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture)
|
MovingSprite::MovingSprite(std::shared_ptr<Texture> texture)
|
||||||
: Sprite(texture),
|
: Sprite(texture),
|
||||||
x_(0.0f),
|
x_(0.0f),
|
||||||
y_(0.0f),
|
y_(0.0f),
|
||||||
rotate_(Rotate()),
|
rotate_(Rotate()),
|
||||||
zoom_w_(1.0f),
|
zoom_w_(1.0f),
|
||||||
zoom_h_(1.0f),
|
zoom_h_(1.0f),
|
||||||
flip_(SDL_FLIP_NONE) { Sprite::clear(); }
|
flip_(SDL_FLIP_NONE) { Sprite::clear(); }
|
||||||
|
|
||||||
// Reinicia todas las variables
|
// Reinicia todas las variables
|
||||||
void MovingSprite::clear()
|
void MovingSprite::clear() {
|
||||||
{
|
x_ = 0.0f; // Posición en el eje X
|
||||||
x_ = 0.0f; // Posición en el eje X
|
y_ = 0.0f; // Posición en el eje Y
|
||||||
y_ = 0.0f; // Posición en el eje Y
|
|
||||||
|
|
||||||
vx_ = 0.0f; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
|
vx_ = 0.0f; // Velocidad en el eje X. Cantidad de pixeles a desplazarse
|
||||||
vy_ = 0.0f; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
|
vy_ = 0.0f; // Velocidad en el eje Y. Cantidad de pixeles a desplazarse
|
||||||
|
|
||||||
ax_ = 0.0f; // Aceleración en el eje X. Variación de la velocidad
|
ax_ = 0.0f; // Aceleración en el eje X. Variación de la velocidad
|
||||||
ay_ = 0.0f; // Aceleración en el eje Y. Variación de la velocidad
|
ay_ = 0.0f; // Aceleración en el eje Y. Variación de la velocidad
|
||||||
|
|
||||||
rotate_ = Rotate(); // Inicializa la estructura
|
rotate_ = Rotate(); // Inicializa la estructura
|
||||||
|
|
||||||
zoom_w_ = 1.0f; // Zoom aplicado a la anchura
|
zoom_w_ = 1.0f; // Zoom aplicado a la anchura
|
||||||
zoom_h_ = 1.0f; // Zoom aplicado a la altura
|
zoom_h_ = 1.0f; // Zoom aplicado a la altura
|
||||||
|
|
||||||
flip_ = SDL_FLIP_NONE; // Establece como se ha de voltear el sprite
|
flip_ = SDL_FLIP_NONE; // Establece como se ha de voltear el sprite
|
||||||
|
|
||||||
Sprite::clear();
|
Sprite::clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mueve el sprite
|
// Mueve el sprite
|
||||||
void MovingSprite::move()
|
void MovingSprite::move() {
|
||||||
{
|
x_ += vx_;
|
||||||
x_ += vx_;
|
y_ += vy_;
|
||||||
y_ += vy_;
|
|
||||||
|
|
||||||
vx_ += ax_;
|
vx_ += ax_;
|
||||||
vy_ += ay_;
|
vy_ += ay_;
|
||||||
|
|
||||||
pos_.x = static_cast<int>(x_);
|
pos_.x = static_cast<int>(x_);
|
||||||
pos_.y = static_cast<int>(y_);
|
pos_.y = static_cast<int>(y_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza las variables internas del objeto
|
// Actualiza las variables internas del objeto
|
||||||
void MovingSprite::update()
|
void MovingSprite::update() {
|
||||||
{
|
move();
|
||||||
move();
|
rotate();
|
||||||
rotate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Muestra el sprite por pantalla
|
// Muestra el sprite por pantalla
|
||||||
void MovingSprite::render() { texture_->render(pos_.x, pos_.y, &sprite_clip_, zoom_w_, zoom_h_, rotate_.angle, &rotate_.center, flip_); }
|
void MovingSprite::render() { texture_->render(pos_.x, pos_.y, &sprite_clip_, zoom_w_, zoom_h_, rotate_.angle, &rotate_.center, flip_); }
|
||||||
|
|
||||||
// Establece la rotacion
|
// Establece la rotacion
|
||||||
void MovingSprite::rotate()
|
void MovingSprite::rotate() {
|
||||||
{
|
if (rotate_.enabled) {
|
||||||
if (rotate_.enabled)
|
++rotate_.counter;
|
||||||
{
|
if (rotate_.counter % rotate_.speed == 0) {
|
||||||
++rotate_.counter;
|
updateAngle();
|
||||||
if (rotate_.counter % rotate_.speed == 0)
|
rotate_.counter = 0;
|
||||||
{
|
}
|
||||||
updateAngle();
|
}
|
||||||
rotate_.counter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activa o desactiva el efecto de rotación
|
// Activa o desactiva el efecto de rotación
|
||||||
void MovingSprite::setRotate(bool enable)
|
void MovingSprite::setRotate(bool enable) {
|
||||||
{
|
rotate_.enabled = enable;
|
||||||
rotate_.enabled = enable;
|
rotate_.counter = 0;
|
||||||
rotate_.counter = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece la posición y_ el tamaño del objeto
|
// Establece la posición y_ el tamaño del objeto
|
||||||
void MovingSprite::setPos(SDL_FRect rect)
|
void MovingSprite::setPos(SDL_FRect rect) {
|
||||||
{
|
x_ = static_cast<float>(rect.x);
|
||||||
x_ = static_cast<float>(rect.x);
|
y_ = static_cast<float>(rect.y);
|
||||||
y_ = static_cast<float>(rect.y);
|
|
||||||
|
|
||||||
pos_ = rect;
|
pos_ = rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el valor de las variables
|
// Establece el valor de las variables
|
||||||
void MovingSprite::setPos(float x, float y)
|
void MovingSprite::setPos(float x, float y) {
|
||||||
{
|
x_ = x;
|
||||||
x_ = x;
|
y_ = y;
|
||||||
y_ = y;
|
|
||||||
|
|
||||||
pos_.x = static_cast<int>(x_);
|
pos_.x = static_cast<int>(x_);
|
||||||
pos_.y = static_cast<int>(y_);
|
pos_.y = static_cast<int>(y_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el valor de la variable
|
// Establece el valor de la variable
|
||||||
void MovingSprite::setPosX(float value)
|
void MovingSprite::setPosX(float value) {
|
||||||
{
|
x_ = value;
|
||||||
x_ = value;
|
pos_.x = static_cast<int>(x_);
|
||||||
pos_.x = static_cast<int>(x_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el valor de la variable
|
// Establece el valor de la variable
|
||||||
void MovingSprite::setPosY(float value)
|
void MovingSprite::setPosY(float value) {
|
||||||
{
|
y_ = value;
|
||||||
y_ = value;
|
pos_.y = static_cast<int>(y_);
|
||||||
pos_.y = static_cast<int>(y_);
|
|
||||||
}
|
}
|
||||||
+35
-36
@@ -1,26 +1,25 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FlipMode, SDL_FPoint, SDL_FRect
|
#include <SDL3/SDL.h> // Para SDL_FlipMode, SDL_FPoint, SDL_FRect
|
||||||
|
|
||||||
#include <algorithm> // Para max
|
#include <algorithm> // Para max
|
||||||
#include <memory> // Para shared_ptr
|
#include <memory> // Para shared_ptr
|
||||||
|
|
||||||
#include "sprite.h" // Para Sprite
|
#include "sprite.h" // Para Sprite
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Clase MovingSprite. Añade movimiento y efectos de rotación, zoom y flip al sprite
|
// Clase MovingSprite. Añade movimiento y efectos de rotación, zoom y flip al sprite
|
||||||
class MovingSprite : public Sprite
|
class MovingSprite : public Sprite {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// --- Estructura para la rotación ---
|
// --- Estructura para la rotación ---
|
||||||
struct Rotate
|
struct Rotate {
|
||||||
{
|
bool enabled; // Indica si ha de rotar
|
||||||
bool enabled; // Indica si ha de rotar
|
int counter; // Contador
|
||||||
int counter; // Contador
|
int speed; // Velocidad de giro
|
||||||
int speed; // Velocidad de giro
|
double angle; // Ángulo para dibujarlo
|
||||||
double angle; // Ángulo para dibujarlo
|
float amount; // Cantidad de grados a girar en cada iteración
|
||||||
float amount; // Cantidad de grados a girar en cada iteración
|
SDL_FPoint center; // Centro de rotación
|
||||||
SDL_FPoint center; // Centro de rotación
|
|
||||||
|
|
||||||
Rotate() : enabled(false), counter(0), speed(1), angle(0.0), amount(0.0f), center({0.0f, 0.0f}) {}
|
Rotate() : enabled(false), counter(0), speed(1), angle(0.0), amount(0.0f), center({0.0f, 0.0f}) {}
|
||||||
};
|
};
|
||||||
@@ -32,9 +31,9 @@ public:
|
|||||||
virtual ~MovingSprite() override = default;
|
virtual ~MovingSprite() override = default;
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
virtual void update(); // Actualiza las variables internas del objeto
|
virtual void update(); // Actualiza las variables internas del objeto
|
||||||
void clear() override; // Reinicia todas las variables a cero
|
void clear() override; // Reinicia todas las variables a cero
|
||||||
void render() override; // Muestra el sprite por pantalla
|
void render() override; // Muestra el sprite por pantalla
|
||||||
|
|
||||||
// --- Getters de posición y movimiento ---
|
// --- Getters de posición y movimiento ---
|
||||||
float getPosX() const { return x_; }
|
float getPosX() const { return x_; }
|
||||||
@@ -56,10 +55,10 @@ public:
|
|||||||
void setZoomH(float value) { zoom_h_ = value; }
|
void setZoomH(float value) { zoom_h_ = value; }
|
||||||
void setAngle(double value) { rotate_.angle = value; }
|
void setAngle(double value) { rotate_.angle = value; }
|
||||||
void setRotatingCenter(SDL_FPoint point) { rotate_.center = point; }
|
void setRotatingCenter(SDL_FPoint point) { rotate_.center = point; }
|
||||||
void setRotate(bool enable); // Activa o desactiva el efecto de rotación
|
void setRotate(bool enable); // Activa o desactiva el efecto de rotación
|
||||||
void setRotateSpeed(int value) { rotate_.speed = std::max(1, value); }
|
void setRotateSpeed(int value) { rotate_.speed = std::max(1, value); }
|
||||||
void setRotateAmount(double value) { rotate_.amount = value; }
|
void setRotateAmount(double value) { rotate_.amount = value; }
|
||||||
void switchRotate() { rotate_.amount *= -1; } // Cambia el sentido de la rotación
|
void switchRotate() { rotate_.amount *= -1; } // Cambia el sentido de la rotación
|
||||||
|
|
||||||
// --- Flip ---
|
// --- Flip ---
|
||||||
void setFlip(SDL_FlipMode flip) { flip_ = flip; }
|
void setFlip(SDL_FlipMode flip) { flip_ = flip; }
|
||||||
@@ -67,30 +66,30 @@ public:
|
|||||||
SDL_FlipMode getFlip() { return flip_; }
|
SDL_FlipMode getFlip() { return flip_; }
|
||||||
|
|
||||||
// --- Posición y tamaño ---
|
// --- Posición y tamaño ---
|
||||||
void setPos(SDL_FRect rect); // Establece la posición y el tamaño del objeto
|
void setPos(SDL_FRect rect); // Establece la posición y el tamaño del objeto
|
||||||
void setPos(float x, float y); // Establece la posición del objeto
|
void setPos(float x, float y); // Establece la posición del objeto
|
||||||
void setPosX(float value); // Establece la posición X
|
void setPosX(float value); // Establece la posición X
|
||||||
void setPosY(float value); // Establece la posición Y
|
void setPosY(float value); // Establece la posición Y
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// --- Variables de posición y movimiento ---
|
// --- Variables de posición y movimiento ---
|
||||||
float x_ = 0.0f; // Posición en el eje X
|
float x_ = 0.0f; // Posición en el eje X
|
||||||
float y_ = 0.0f; // Posición en el eje Y
|
float y_ = 0.0f; // Posición en el eje Y
|
||||||
|
|
||||||
float vx_ = 0.0f; // Velocidad en el eje X. Cantidad de píxeles a desplazarse
|
float vx_ = 0.0f; // Velocidad en el eje X. Cantidad de píxeles a desplazarse
|
||||||
float vy_ = 0.0f; // Velocidad en el eje Y. Cantidad de píxeles a desplazarse
|
float vy_ = 0.0f; // Velocidad en el eje Y. Cantidad de píxeles a desplazarse
|
||||||
|
|
||||||
float ax_ = 0.0f; // Aceleración en el eje X. Variación de la velocidad
|
float ax_ = 0.0f; // Aceleración en el eje X. Variación de la velocidad
|
||||||
float ay_ = 0.0f; // Aceleración en el eje Y. Variación de la velocidad
|
float ay_ = 0.0f; // Aceleración en el eje Y. Variación de la velocidad
|
||||||
|
|
||||||
// --- Efectos visuales ---
|
// --- Efectos visuales ---
|
||||||
Rotate rotate_; // Variables usadas para controlar la rotación del sprite
|
Rotate rotate_; // Variables usadas para controlar la rotación del sprite
|
||||||
float zoom_w_; // Zoom aplicado a la anchura
|
float zoom_w_; // Zoom aplicado a la anchura
|
||||||
float zoom_h_; // Zoom aplicado a la altura
|
float zoom_h_; // Zoom aplicado a la altura
|
||||||
SDL_FlipMode flip_; // Indica cómo se voltea el sprite
|
SDL_FlipMode flip_; // Indica cómo se voltea el sprite
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void updateAngle() { rotate_.angle += rotate_.amount; } // Incrementa el valor del ángulo
|
void updateAngle() { rotate_.angle += rotate_.amount; } // Incrementa el valor del ángulo
|
||||||
void move(); // Mueve el sprite según velocidad y aceleración
|
void move(); // Mueve el sprite según velocidad y aceleración
|
||||||
void rotate(); // Rota el sprite según los parámetros de rotación
|
void rotate(); // Rota el sprite según los parámetros de rotación
|
||||||
};
|
};
|
||||||
+59
-98
@@ -1,16 +1,17 @@
|
|||||||
#include "notifier.h"
|
#include "notifier.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_RenderFillRect, SDL_FRect, SDL_RenderClear
|
#include <SDL3/SDL.h> // Para SDL_RenderFillRect, SDL_FRect, SDL_RenderClear
|
||||||
|
|
||||||
#include <algorithm> // Para remove_if
|
#include <algorithm> // Para remove_if
|
||||||
#include <string> // Para basic_string, string
|
#include <string> // Para basic_string, string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "audio.h" // Para Audio
|
#include "audio.h" // Para Audio
|
||||||
#include "param.h" // Para Param, param, ParamNotification, ParamGame
|
#include "param.h" // Para Param, param, ParamNotification, ParamGame
|
||||||
#include "screen.h" // Para Screen
|
#include "screen.h" // Para Screen
|
||||||
#include "sprite.h" // Para Sprite
|
#include "sprite.h" // Para Sprite
|
||||||
#include "text.h" // Para Text
|
#include "text.h" // Para Text
|
||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
|
|
||||||
// Singleton
|
// Singleton
|
||||||
Notifier *Notifier::instance_ = nullptr;
|
Notifier *Notifier::instance_ = nullptr;
|
||||||
@@ -35,24 +36,18 @@ Notifier::Notifier(std::string icon_file, std::shared_ptr<Text> text)
|
|||||||
has_icons_(!icon_file.empty()) {}
|
has_icons_(!icon_file.empty()) {}
|
||||||
|
|
||||||
// Dibuja las notificaciones por pantalla
|
// Dibuja las notificaciones por pantalla
|
||||||
void Notifier::render()
|
void Notifier::render() {
|
||||||
{
|
for (int i = (int)notifications_.size() - 1; i >= 0; --i) {
|
||||||
for (int i = (int)notifications_.size() - 1; i >= 0; --i)
|
|
||||||
{
|
|
||||||
notifications_[i].sprite->render();
|
notifications_[i].sprite->render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el estado de las notificaiones
|
// Actualiza el estado de las notificaiones
|
||||||
void Notifier::update()
|
void Notifier::update() {
|
||||||
{
|
for (int i = 0; i < (int)notifications_.size(); ++i) {
|
||||||
for (int i = 0; i < (int)notifications_.size(); ++i)
|
|
||||||
{
|
|
||||||
// Si la notificación anterior está "saliendo", no hagas nada
|
// Si la notificación anterior está "saliendo", no hagas nada
|
||||||
if (i > 0)
|
if (i > 0) {
|
||||||
{
|
if (notifications_[i - 1].state == NotificationStatus::RISING) {
|
||||||
if (notifications_[i - 1].state == NotificationStatus::RISING)
|
|
||||||
{
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,12 +55,9 @@ void Notifier::update()
|
|||||||
notifications_[i].counter++;
|
notifications_[i].counter++;
|
||||||
|
|
||||||
// Hace sonar la notificación en el primer frame
|
// Hace sonar la notificación en el primer frame
|
||||||
if (notifications_[i].counter == 1)
|
if (notifications_[i].counter == 1) {
|
||||||
{
|
if (param.notification.sound) {
|
||||||
if (param.notification.sound)
|
if (notifications_[i].state == NotificationStatus::RISING) {
|
||||||
{
|
|
||||||
if (notifications_[i].state == NotificationStatus::RISING)
|
|
||||||
{
|
|
||||||
// Reproduce el sonido de la notificación
|
// Reproduce el sonido de la notificación
|
||||||
Audio::get()->playSound("notify.wav", Audio::Group::INTERFACE);
|
Audio::get()->playSound("notify.wav", Audio::Group::INTERFACE);
|
||||||
}
|
}
|
||||||
@@ -73,55 +65,41 @@ void Notifier::update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba los estados
|
// Comprueba los estados
|
||||||
if (notifications_[i].state == NotificationStatus::RISING)
|
if (notifications_[i].state == NotificationStatus::RISING) {
|
||||||
{
|
|
||||||
const float step = ((float)notifications_[i].counter / notifications_[i].travel_dist);
|
const float step = ((float)notifications_[i].counter / notifications_[i].travel_dist);
|
||||||
const int alpha = 255 * step;
|
const int alpha = 255 * step;
|
||||||
|
|
||||||
if (param.notification.pos_v == NotifyPosition::TOP)
|
if (param.notification.pos_v == NotifyPosition::TOP) {
|
||||||
{
|
|
||||||
notifications_[i].rect.y++;
|
notifications_[i].rect.y++;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
notifications_[i].rect.y--;
|
notifications_[i].rect.y--;
|
||||||
}
|
}
|
||||||
notifications_[i].texture->setAlpha(alpha);
|
notifications_[i].texture->setAlpha(alpha);
|
||||||
|
|
||||||
if (notifications_[i].rect.y == notifications_[i].y)
|
if (notifications_[i].rect.y == notifications_[i].y) {
|
||||||
{
|
|
||||||
notifications_[i].state = NotificationStatus::STAY;
|
notifications_[i].state = NotificationStatus::STAY;
|
||||||
notifications_[i].texture->setAlpha(255);
|
notifications_[i].texture->setAlpha(255);
|
||||||
notifications_[i].counter = 0;
|
notifications_[i].counter = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (notifications_[i].state == NotificationStatus::STAY)
|
else if (notifications_[i].state == NotificationStatus::STAY) {
|
||||||
{
|
if (notifications_[i].counter == wait_time_) {
|
||||||
if (notifications_[i].counter == wait_time_)
|
|
||||||
{
|
|
||||||
notifications_[i].state = NotificationStatus::VANISHING;
|
notifications_[i].state = NotificationStatus::VANISHING;
|
||||||
notifications_[i].counter = 0;
|
notifications_[i].counter = 0;
|
||||||
}
|
}
|
||||||
}
|
} else if (notifications_[i].state == NotificationStatus::VANISHING) {
|
||||||
else if (notifications_[i].state == NotificationStatus::VANISHING)
|
|
||||||
{
|
|
||||||
|
|
||||||
const float step = (notifications_[i].counter / (float)notifications_[i].travel_dist);
|
const float step = (notifications_[i].counter / (float)notifications_[i].travel_dist);
|
||||||
const int alpha = 255 * (1 - step);
|
const int alpha = 255 * (1 - step);
|
||||||
|
|
||||||
if (param.notification.pos_v == NotifyPosition::TOP)
|
if (param.notification.pos_v == NotifyPosition::TOP) {
|
||||||
{
|
|
||||||
notifications_[i].rect.y--;
|
notifications_[i].rect.y--;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
notifications_[i].rect.y++;
|
notifications_[i].rect.y++;
|
||||||
}
|
}
|
||||||
notifications_[i].texture->setAlpha(alpha);
|
notifications_[i].texture->setAlpha(alpha);
|
||||||
|
|
||||||
if (notifications_[i].rect.y == notifications_[i].y - notifications_[i].travel_dist)
|
if (notifications_[i].rect.y == notifications_[i].y - notifications_[i].travel_dist) {
|
||||||
{
|
|
||||||
notifications_[i].state = NotificationStatus::FINISHED;
|
notifications_[i].state = NotificationStatus::FINISHED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,40 +111,32 @@ void Notifier::update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Elimina las notificaciones finalizadas
|
// Elimina las notificaciones finalizadas
|
||||||
void Notifier::clearFinishedNotifications()
|
void Notifier::clearFinishedNotifications() {
|
||||||
{
|
for (int i = (int)notifications_.size() - 1; i >= 0; --i) {
|
||||||
for (int i = (int)notifications_.size() - 1; i >= 0; --i)
|
if (notifications_[i].state == NotificationStatus::FINISHED) {
|
||||||
{
|
|
||||||
if (notifications_[i].state == NotificationStatus::FINISHED)
|
|
||||||
{
|
|
||||||
notifications_.erase(notifications_.begin() + i);
|
notifications_.erase(notifications_.begin() + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Notifier::show(std::vector<std::string> texts, int icon, const std::string &code)
|
void Notifier::show(std::vector<std::string> texts, int icon, const std::string &code) {
|
||||||
{
|
|
||||||
// Si no hay texto, acaba
|
// Si no hay texto, acaba
|
||||||
if (texts.empty())
|
if (texts.empty()) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si las notificaciones no se apilan, elimina las anteriores
|
// Si las notificaciones no se apilan, elimina las anteriores
|
||||||
if (!stack_)
|
if (!stack_) {
|
||||||
{
|
|
||||||
clearAllNotifications();
|
clearAllNotifications();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Elimina las cadenas vacías
|
// Elimina las cadenas vacías
|
||||||
texts.erase(std::remove_if(texts.begin(), texts.end(), [](const std::string &s)
|
texts.erase(std::remove_if(texts.begin(), texts.end(), [](const std::string &s) { return s.empty(); }),
|
||||||
{ return s.empty(); }),
|
texts.end());
|
||||||
texts.end());
|
|
||||||
|
|
||||||
// Encuentra la cadena más larga
|
// Encuentra la cadena más larga
|
||||||
std::string longest;
|
std::string longest;
|
||||||
for (const auto &text : texts)
|
for (const auto &text : texts) {
|
||||||
{
|
|
||||||
if (text.length() > longest.length())
|
if (text.length() > longest.length())
|
||||||
longest = text;
|
longest = text;
|
||||||
}
|
}
|
||||||
@@ -183,23 +153,22 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string
|
|||||||
|
|
||||||
// Posición horizontal
|
// Posición horizontal
|
||||||
float desp_h = 0;
|
float desp_h = 0;
|
||||||
switch (param.notification.pos_h)
|
switch (param.notification.pos_h) {
|
||||||
{
|
case NotifyPosition::LEFT:
|
||||||
case NotifyPosition::LEFT:
|
desp_h = PADDING_OUT;
|
||||||
desp_h = PADDING_OUT;
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case NotifyPosition::MIDDLE:
|
case NotifyPosition::MIDDLE:
|
||||||
desp_h = ((param.game.width / 2) - (WIDTH / 2));
|
desp_h = ((param.game.width / 2) - (WIDTH / 2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NotifyPosition::RIGHT:
|
case NotifyPosition::RIGHT:
|
||||||
desp_h = param.game.width - WIDTH - PADDING_OUT;
|
desp_h = param.game.width - WIDTH - PADDING_OUT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
desp_h = 0;
|
desp_h = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Posición vertical
|
// Posición vertical
|
||||||
@@ -208,8 +177,8 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string
|
|||||||
// Offset
|
// Offset
|
||||||
const auto TRAVEL_DIST = HEIGHT + PADDING_OUT;
|
const auto TRAVEL_DIST = HEIGHT + PADDING_OUT;
|
||||||
auto OFFSET = notifications_.empty()
|
auto OFFSET = notifications_.empty()
|
||||||
? DESP_V
|
? DESP_V
|
||||||
: notifications_.back().y + (param.notification.pos_v == NotifyPosition::TOP ? TRAVEL_DIST : -TRAVEL_DIST);
|
: notifications_.back().y + (param.notification.pos_v == NotifyPosition::TOP ? TRAVEL_DIST : -TRAVEL_DIST);
|
||||||
|
|
||||||
// Crea la notificacion
|
// Crea la notificacion
|
||||||
Notification n;
|
Notification n;
|
||||||
@@ -234,8 +203,7 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string
|
|||||||
// Dibuja el fondo de la notificación
|
// Dibuja el fondo de la notificación
|
||||||
SDL_SetRenderDrawColor(renderer_, bg_color_.r, bg_color_.g, bg_color_.b, 255);
|
SDL_SetRenderDrawColor(renderer_, bg_color_.r, bg_color_.g, bg_color_.b, 255);
|
||||||
SDL_FRect rect;
|
SDL_FRect rect;
|
||||||
if (SHAPE == NotificationShape::ROUNDED)
|
if (SHAPE == NotificationShape::ROUNDED) {
|
||||||
{
|
|
||||||
rect = {4, 0, WIDTH - (4 * 2), HEIGHT};
|
rect = {4, 0, WIDTH - (4 * 2), HEIGHT};
|
||||||
SDL_RenderFillRect(renderer_, &rect);
|
SDL_RenderFillRect(renderer_, &rect);
|
||||||
|
|
||||||
@@ -249,14 +217,12 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string
|
|||||||
SDL_RenderFillRect(renderer_, &rect);
|
SDL_RenderFillRect(renderer_, &rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (SHAPE == NotificationShape::SQUARED)
|
else if (SHAPE == NotificationShape::SQUARED) {
|
||||||
{
|
|
||||||
SDL_RenderClear(renderer_);
|
SDL_RenderClear(renderer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja el icono de la notificación
|
// Dibuja el icono de la notificación
|
||||||
if (has_icons_ && icon >= 0 && texts.size() >= 2)
|
if (has_icons_ && icon >= 0 && texts.size() >= 2) {
|
||||||
{
|
|
||||||
auto sp = std::make_unique<Sprite>(icon_texture_, (SDL_FRect){0, 0, ICON_SIZE, ICON_SIZE});
|
auto sp = std::make_unique<Sprite>(icon_texture_, (SDL_FRect){0, 0, ICON_SIZE, ICON_SIZE});
|
||||||
sp->setPosition({PADDING_IN_H, PADDING_IN_V, ICON_SIZE, ICON_SIZE});
|
sp->setPosition({PADDING_IN_H, PADDING_IN_V, ICON_SIZE, ICON_SIZE});
|
||||||
sp->setSpriteClip(SDL_FRect{
|
sp->setSpriteClip(SDL_FRect{
|
||||||
@@ -270,8 +236,7 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string
|
|||||||
// Escribe el texto de la notificación
|
// Escribe el texto de la notificación
|
||||||
const Color color{255, 255, 255};
|
const Color color{255, 255, 255};
|
||||||
int iterator = 0;
|
int iterator = 0;
|
||||||
for (const auto &text : texts)
|
for (const auto &text : texts) {
|
||||||
{
|
|
||||||
text_->writeColored(PADDING_IN_H + ICON_SPACE, PADDING_IN_V + iterator * (text_->getCharacterSize() + 1), text, color);
|
text_->writeColored(PADDING_IN_H + ICON_SPACE, PADDING_IN_V + iterator * (text_->getCharacterSize() + 1), text, color);
|
||||||
++iterator;
|
++iterator;
|
||||||
}
|
}
|
||||||
@@ -290,10 +255,8 @@ void Notifier::show(std::vector<std::string> texts, int icon, const std::string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finaliza y elimnina todas las notificaciones activas
|
// Finaliza y elimnina todas las notificaciones activas
|
||||||
void Notifier::clearAllNotifications()
|
void Notifier::clearAllNotifications() {
|
||||||
{
|
for (auto ¬ification : notifications_) {
|
||||||
for (auto ¬ification : notifications_)
|
|
||||||
{
|
|
||||||
notification.state = NotificationStatus::FINISHED;
|
notification.state = NotificationStatus::FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,11 +264,9 @@ void Notifier::clearAllNotifications()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene los códigos de las notificaciones
|
// Obtiene los códigos de las notificaciones
|
||||||
std::vector<std::string> Notifier::getCodes()
|
std::vector<std::string> Notifier::getCodes() {
|
||||||
{
|
|
||||||
std::vector<std::string> codes;
|
std::vector<std::string> codes;
|
||||||
for (const auto ¬ification : notifications_)
|
for (const auto ¬ification : notifications_) {
|
||||||
{
|
|
||||||
codes.emplace_back(notification.code);
|
codes.emplace_back(notification.code);
|
||||||
}
|
}
|
||||||
return codes;
|
return codes;
|
||||||
|
|||||||
+44
-48
@@ -1,91 +1,87 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FRect, SDL_Renderer
|
#include <SDL3/SDL.h> // Para SDL_FRect, SDL_Renderer
|
||||||
#include <memory> // Para shared_ptr
|
|
||||||
#include <string> // Para basic_string, string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "utils.h" // Para stringInVector, Color
|
#include <memory> // Para shared_ptr
|
||||||
|
#include <string> // Para basic_string, string
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
|
#include "utils.h" // Para stringInVector, Color
|
||||||
|
|
||||||
class Sprite;
|
class Sprite;
|
||||||
class Text;
|
class Text;
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// --- Clase Notifier: gestiona las notificaciones en pantalla (singleton) ---
|
// --- Clase Notifier: gestiona las notificaciones en pantalla (singleton) ---
|
||||||
class Notifier
|
class Notifier {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// --- Métodos de singleton ---
|
// --- Métodos de singleton ---
|
||||||
static void init(const std::string &icon_file, std::shared_ptr<Text> text); // Inicializa el singleton
|
static void init(const std::string &icon_file, std::shared_ptr<Text> text); // Inicializa el singleton
|
||||||
static void destroy(); // Libera el singleton
|
static void destroy(); // Libera el singleton
|
||||||
static Notifier *get(); // Obtiene la instancia
|
static Notifier *get(); // Obtiene la instancia
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
void render(); // Dibuja las notificaciones por pantalla
|
void render(); // Dibuja las notificaciones por pantalla
|
||||||
void update(); // Actualiza el estado de las notificaciones
|
void update(); // Actualiza el estado de las notificaciones
|
||||||
|
|
||||||
// --- Gestión de notificaciones ---
|
// --- Gestión de notificaciones ---
|
||||||
void show(std::vector<std::string> texts, int icon = -1, const std::string &code = std::string()); // Muestra una notificación de texto por pantalla
|
void show(std::vector<std::string> texts, int icon = -1, const std::string &code = std::string()); // Muestra una notificación de texto por pantalla
|
||||||
bool isActive() const { return !notifications_.empty(); } // Indica si hay notificaciones activas
|
bool isActive() const { return !notifications_.empty(); } // Indica si hay notificaciones activas
|
||||||
std::vector<std::string> getCodes(); // Obtiene los códigos de las notificaciones activas
|
std::vector<std::string> getCodes(); // Obtiene los códigos de las notificaciones activas
|
||||||
bool checkCode(const std::string &code) { return stringInVector(getCodes(), code); } // Comprueba si hay alguna notificación con un código concreto
|
bool checkCode(const std::string &code) { return stringInVector(getCodes(), code); } // Comprueba si hay alguna notificación con un código concreto
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Singleton ---
|
// --- Singleton ---
|
||||||
static Notifier *instance_;
|
static Notifier *instance_;
|
||||||
|
|
||||||
// --- Tipos internos ---
|
// --- Tipos internos ---
|
||||||
enum class NotificationStatus
|
enum class NotificationStatus {
|
||||||
{
|
|
||||||
RISING,
|
RISING,
|
||||||
STAY,
|
STAY,
|
||||||
VANISHING,
|
VANISHING,
|
||||||
FINISHED,
|
FINISHED,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class NotificationShape
|
enum class NotificationShape {
|
||||||
{
|
|
||||||
ROUNDED,
|
ROUNDED,
|
||||||
SQUARED,
|
SQUARED,
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estructura Notification ---
|
// --- Estructura Notification ---
|
||||||
struct Notification
|
struct Notification {
|
||||||
{
|
std::shared_ptr<Texture> texture; // Textura de la notificación
|
||||||
std::shared_ptr<Texture> texture; // Textura de la notificación
|
std::shared_ptr<Sprite> sprite; // Sprite asociado
|
||||||
std::shared_ptr<Sprite> sprite; // Sprite asociado
|
std::vector<std::string> texts; // Textos a mostrar
|
||||||
std::vector<std::string> texts; // Textos a mostrar
|
int counter; // Contador de tiempo
|
||||||
int counter; // Contador de tiempo
|
NotificationStatus state; // Estado de la notificación
|
||||||
NotificationStatus state; // Estado de la notificación
|
NotificationShape shape; // Forma de la notificación
|
||||||
NotificationShape shape; // Forma de la notificación
|
SDL_FRect rect; // Rectángulo de la notificación
|
||||||
SDL_FRect rect; // Rectángulo de la notificación
|
int y; // Posición vertical
|
||||||
int y; // Posición vertical
|
int travel_dist; // Distancia a recorrer
|
||||||
int travel_dist; // Distancia a recorrer
|
std::string code; // Código identificador de la notificación
|
||||||
std::string code; // Código identificador de la notificación
|
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
explicit Notification()
|
explicit Notification()
|
||||||
: texture(nullptr), sprite(nullptr), texts(), counter(0), state(NotificationStatus::RISING),
|
: texture(nullptr), sprite(nullptr), texts(), counter(0), state(NotificationStatus::RISING), shape(NotificationShape::SQUARED), rect{0, 0, 0, 0}, y(0), travel_dist(0), code("") {}
|
||||||
shape(NotificationShape::SQUARED), rect{0, 0, 0, 0}, y(0), travel_dist(0), code("") {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
SDL_Renderer *renderer_; // El renderizador de la ventana
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
std::shared_ptr<Texture> icon_texture_; // Textura para los iconos de las notificaciones
|
std::shared_ptr<Texture> icon_texture_; // Textura para los iconos de las notificaciones
|
||||||
std::shared_ptr<Text> text_; // Objeto para dibujar texto
|
std::shared_ptr<Text> text_; // Objeto para dibujar texto
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
Color bg_color_; // Color de fondo de las notificaciones
|
Color bg_color_; // Color de fondo de las notificaciones
|
||||||
int wait_time_; // Tiempo que se ve la notificación
|
int wait_time_; // Tiempo que se ve la notificación
|
||||||
std::vector<Notification> notifications_; // Lista de notificaciones activas
|
std::vector<Notification> notifications_; // Lista de notificaciones activas
|
||||||
bool stack_; // Indica si las notificaciones se apilan
|
bool stack_; // Indica si las notificaciones se apilan
|
||||||
bool has_icons_; // Indica si el notificador tiene textura para iconos
|
bool has_icons_; // Indica si el notificador tiene textura para iconos
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void clearFinishedNotifications(); // Elimina las notificaciones finalizadas
|
void clearFinishedNotifications(); // Elimina las notificaciones finalizadas
|
||||||
void clearAllNotifications(); // Finaliza y elimina todas las notificaciones activas
|
void clearAllNotifications(); // Finaliza y elimina todas las notificaciones activas
|
||||||
|
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
Notifier(std::string icon_file, std::shared_ptr<Text> text); // Constructor privado
|
Notifier(std::string icon_file, std::shared_ptr<Text> text); // Constructor privado
|
||||||
~Notifier() = default; // Destructor privado
|
~Notifier() = default; // Destructor privado
|
||||||
};
|
};
|
||||||
+281
-376
@@ -1,423 +1,328 @@
|
|||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_LogCategory, SDL_LogInfo, SDL_LogError
|
#include <SDL3/SDL.h> // Para SDL_LogCategory, SDL_LogInfo, SDL_LogError
|
||||||
|
|
||||||
#include <algorithm> // Para clamp
|
#include <algorithm> // Para clamp
|
||||||
#include <fstream> // Para basic_ostream, operator<<, basic_ostream::...
|
#include <fstream> // Para basic_ostream, operator<<, basic_ostream::...
|
||||||
#include <utility> // Para swap
|
#include <utility> // Para swap
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "asset.h"
|
#include "asset.h"
|
||||||
#include "input.h" // Para InputDeviceToUse
|
#include "input.h" // Para InputDeviceToUse
|
||||||
#include "lang.h" // Para Code
|
#include "lang.h" // Para Code
|
||||||
#include "utils.h" // Para boolToString, stringToBool, getFileName
|
#include "utils.h" // Para boolToString, stringToBool, getFileName
|
||||||
|
|
||||||
namespace Options
|
namespace Options {
|
||||||
{
|
// --- Variables globales ---
|
||||||
// --- Variables globales ---
|
WindowOptions window; // Opciones de la ventana
|
||||||
WindowOptions window; // Opciones de la ventana
|
SettingsOptions settings; // Opciones del juego
|
||||||
SettingsOptions settings; // Opciones del juego
|
VideoOptions video; // Opciones de vídeo
|
||||||
VideoOptions video; // Opciones de vídeo
|
AudioOptions audio; // Opciones de audio
|
||||||
AudioOptions audio; // Opciones de audio
|
std::vector<GamepadOptions> controllers; // Opciones de mando para cada jugador
|
||||||
std::vector<GamepadOptions> controllers; // Opciones de mando para cada jugador
|
PendingChanges pending_changes; // Opciones que se aplican al cerrar
|
||||||
PendingChanges pending_changes; // Opciones que se aplican al cerrar
|
|
||||||
|
|
||||||
// Vector con las dificultades
|
// Vector con las dificultades
|
||||||
std::vector<Difficulty> difficulties = {
|
std::vector<Difficulty> difficulties = {
|
||||||
{DifficultyCode::EASY, "Easy"},
|
{DifficultyCode::EASY, "Easy"},
|
||||||
{DifficultyCode::NORMAL, "Normal"},
|
{DifficultyCode::NORMAL, "Normal"},
|
||||||
{DifficultyCode::HARD, "Hard"}};
|
{DifficultyCode::HARD, "Hard"}};
|
||||||
|
|
||||||
// Declaraciones
|
// Declaraciones
|
||||||
bool set(const std::string &var, const std::string &value);
|
bool set(const std::string &var, const std::string &value);
|
||||||
|
|
||||||
// Inicializa las opciones del programa
|
// Inicializa las opciones del programa
|
||||||
void init()
|
void init() {
|
||||||
{
|
// Settings
|
||||||
// Settings
|
settings.config_file = Asset::get()->get("config.txt");
|
||||||
settings.config_file = Asset::get()->get("config.txt");
|
|
||||||
|
|
||||||
// Opciones de control
|
// Opciones de control
|
||||||
controllers.clear();
|
controllers.clear();
|
||||||
controllers.resize(2);
|
controllers.resize(2);
|
||||||
controllers.at(0).player_id = 1;
|
controllers.at(0).player_id = 1;
|
||||||
controllers.at(1).player_id = 2;
|
controllers.at(1).player_id = 2;
|
||||||
setKeyboardToPlayer(1);
|
setKeyboardToPlayer(1);
|
||||||
|
|
||||||
// Opciones pendientes
|
// Opciones pendientes
|
||||||
pending_changes.new_language = settings.language;
|
pending_changes.new_language = settings.language;
|
||||||
pending_changes.new_difficulty = settings.difficulty;
|
pending_changes.new_difficulty = settings.difficulty;
|
||||||
pending_changes.has_pending_changes = false;
|
pending_changes.has_pending_changes = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carga el fichero de configuración
|
// Carga el fichero de configuración
|
||||||
bool loadFromFile()
|
bool loadFromFile() {
|
||||||
{
|
// Inicializa las opciones del programa
|
||||||
// Inicializa las opciones del programa
|
init();
|
||||||
init();
|
|
||||||
|
|
||||||
// Indicador de éxito en la carga
|
// Indicador de éxito en la carga
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
// Variables para manejar el fichero
|
// Variables para manejar el fichero
|
||||||
std::ifstream file(settings.config_file);
|
std::ifstream file(settings.config_file);
|
||||||
|
|
||||||
// Si el fichero se puede abrir
|
// Si el fichero se puede abrir
|
||||||
if (file.good())
|
if (file.good()) {
|
||||||
{
|
// Procesa el fichero línea a línea
|
||||||
// Procesa el fichero línea a línea
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\nReading file: %s", getFileName(settings.config_file).c_str());
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\nReading file: %s", getFileName(settings.config_file).c_str());
|
std::string line;
|
||||||
std::string line;
|
while (std::getline(file, line)) {
|
||||||
while (std::getline(file, line))
|
// Comprueba que la línea no sea un comentario
|
||||||
{
|
if (line.substr(0, 1) != "#") {
|
||||||
// Comprueba que la línea no sea un comentario
|
// Encuentra la posición del carácter '='
|
||||||
if (line.substr(0, 1) != "#")
|
int pos = line.find("=");
|
||||||
{
|
// Procesa las dos subcadenas
|
||||||
// Encuentra la posición del carácter '='
|
if (!set(line.substr(0, pos), line.substr(pos + 1, line.length()))) {
|
||||||
int pos = line.find("=");
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Unknown parameter: %s", line.substr(0, pos).c_str());
|
||||||
// Procesa las dos subcadenas
|
success = false;
|
||||||
if (!set(line.substr(0, pos), line.substr(pos + 1, line.length())))
|
}
|
||||||
{
|
}
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Unknown parameter: %s", line.substr(0, pos).c_str());
|
}
|
||||||
success = false;
|
file.close();
|
||||||
}
|
}
|
||||||
}
|
// El fichero no existe
|
||||||
}
|
else {
|
||||||
file.close();
|
saveToFile(); // Crea el fichero con los valores por defecto
|
||||||
}
|
}
|
||||||
// El fichero no existe
|
|
||||||
else
|
|
||||||
{
|
|
||||||
saveToFile(); // Crea el fichero con los valores por defecto
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normaliza los valores
|
// Normaliza los valores
|
||||||
if (settings.language != Lang::Code::ENGLISH &&
|
if (settings.language != Lang::Code::ENGLISH &&
|
||||||
settings.language != Lang::Code::VALENCIAN &&
|
settings.language != Lang::Code::VALENCIAN &&
|
||||||
settings.language != Lang::Code::SPANISH)
|
settings.language != Lang::Code::SPANISH) {
|
||||||
{
|
settings.language = Lang::Code::ENGLISH;
|
||||||
settings.language = Lang::Code::ENGLISH;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Guarda el fichero de configuración
|
// Guarda el fichero de configuración
|
||||||
bool saveToFile()
|
bool saveToFile() {
|
||||||
{
|
std::ofstream file(settings.config_file);
|
||||||
std::ofstream file(settings.config_file);
|
|
||||||
|
|
||||||
if (!file.good())
|
if (!file.good()) {
|
||||||
{
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: %s can't be opened", getFileName(settings.config_file).c_str());
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: %s can't be opened", getFileName(settings.config_file).c_str());
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Writing file: %s", getFileName(settings.config_file).c_str());
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Writing file: %s", getFileName(settings.config_file).c_str());
|
||||||
|
|
||||||
applyPendingChanges();
|
applyPendingChanges();
|
||||||
|
|
||||||
// Opciones de video
|
// Opciones de video
|
||||||
file << "## VIDEO\n";
|
file << "## VIDEO\n";
|
||||||
file << "## video.scale_mode [" << static_cast<int>(SDL_ScaleMode::SDL_SCALEMODE_NEAREST) << ": nearest, " << static_cast<int>(SDL_ScaleMode::SDL_SCALEMODE_LINEAR) << ": lineal]\n";
|
file << "## video.scale_mode [" << static_cast<int>(SDL_ScaleMode::SDL_SCALEMODE_NEAREST) << ": nearest, " << static_cast<int>(SDL_ScaleMode::SDL_SCALEMODE_LINEAR) << ": lineal]\n";
|
||||||
file << "\n";
|
file << "\n";
|
||||||
|
|
||||||
file << "window.zoom=" << window.size << "\n";
|
file << "window.zoom=" << window.size << "\n";
|
||||||
file << "video.fullscreen=" << boolToString(video.fullscreen) << "\n";
|
file << "video.fullscreen=" << boolToString(video.fullscreen) << "\n";
|
||||||
file << "video.scale_mode=" << static_cast<int>(video.scale_mode) << "\n";
|
file << "video.scale_mode=" << static_cast<int>(video.scale_mode) << "\n";
|
||||||
file << "video.v_sync=" << boolToString(video.v_sync) << "\n";
|
file << "video.v_sync=" << boolToString(video.v_sync) << "\n";
|
||||||
file << "video.integer_scale=" << boolToString(video.integer_scale) << "\n";
|
file << "video.integer_scale=" << boolToString(video.integer_scale) << "\n";
|
||||||
file << "video.shaders=" << boolToString(video.shaders) << "\n";
|
file << "video.shaders=" << boolToString(video.shaders) << "\n";
|
||||||
|
|
||||||
// Opciones de audio
|
// Opciones de audio
|
||||||
file << "\n\n## AUDIO\n";
|
file << "\n\n## AUDIO\n";
|
||||||
file << "## volume [0 .. 100]\n";
|
file << "## volume [0 .. 100]\n";
|
||||||
file << "\n";
|
file << "\n";
|
||||||
|
|
||||||
file << "audio.enabled=" << boolToString(audio.enabled) << "\n";
|
file << "audio.enabled=" << boolToString(audio.enabled) << "\n";
|
||||||
file << "audio.volume=" << audio.volume << "\n";
|
file << "audio.volume=" << audio.volume << "\n";
|
||||||
file << "audio.music.enabled=" << boolToString(audio.music.enabled) << "\n";
|
file << "audio.music.enabled=" << boolToString(audio.music.enabled) << "\n";
|
||||||
file << "audio.music.volume=" << audio.music.volume << "\n";
|
file << "audio.music.volume=" << audio.music.volume << "\n";
|
||||||
file << "audio.sound.enabled=" << boolToString(audio.sound.enabled) << "\n";
|
file << "audio.sound.enabled=" << boolToString(audio.sound.enabled) << "\n";
|
||||||
file << "audio.sound.volume=" << audio.sound.volume << "\n";
|
file << "audio.sound.volume=" << audio.sound.volume << "\n";
|
||||||
|
|
||||||
// Opciones del juego
|
// Opciones del juego
|
||||||
file << "\n\n## GAME\n";
|
file << "\n\n## GAME\n";
|
||||||
file << "## game.language [0: spanish, 1: valencian, 2: english]\n";
|
file << "## game.language [0: spanish, 1: valencian, 2: english]\n";
|
||||||
file << "## game.difficulty [" << static_cast<int>(DifficultyCode::EASY) << ": easy, " << static_cast<int>(DifficultyCode::NORMAL) << ": normal, " << static_cast<int>(DifficultyCode::HARD) << ": hard]\n";
|
file << "## game.difficulty [" << static_cast<int>(DifficultyCode::EASY) << ": easy, " << static_cast<int>(DifficultyCode::NORMAL) << ": normal, " << static_cast<int>(DifficultyCode::HARD) << ": hard]\n";
|
||||||
file << "\n";
|
file << "\n";
|
||||||
|
|
||||||
file << "game.language=" << static_cast<int>(settings.language) << "\n";
|
file << "game.language=" << static_cast<int>(settings.language) << "\n";
|
||||||
file << "game.difficulty=" << static_cast<int>(settings.difficulty) << "\n";
|
file << "game.difficulty=" << static_cast<int>(settings.difficulty) << "\n";
|
||||||
file << "game.autofire=" << boolToString(settings.autofire) << "\n";
|
file << "game.autofire=" << boolToString(settings.autofire) << "\n";
|
||||||
file << "game.shutdown_enabled=" << boolToString(settings.shutdown_enabled) << "\n";
|
file << "game.shutdown_enabled=" << boolToString(settings.shutdown_enabled) << "\n";
|
||||||
|
|
||||||
// Opciones de mandos
|
// Opciones de mandos
|
||||||
file << "\n\n## CONTROLLERS\n";
|
file << "\n\n## CONTROLLERS\n";
|
||||||
|
|
||||||
int controller_index = 0;
|
int controller_index = 0;
|
||||||
for (const auto &controller : controllers)
|
for (const auto &controller : controllers) {
|
||||||
{
|
file << "\n";
|
||||||
file << "\n";
|
file << "controller." << controller_index << ".name=" << controller.name << "\n";
|
||||||
file << "controller." << controller_index << ".name=" << controller.name << "\n";
|
file << "controller." << controller_index << ".player=" << controller.player_id << "\n";
|
||||||
file << "controller." << controller_index << ".player=" << controller.player_id << "\n";
|
file << "controller." << controller_index << ".type=" << static_cast<int>(controller.type) << "\n";
|
||||||
file << "controller." << controller_index << ".type=" << static_cast<int>(controller.type) << "\n";
|
file << "controller." << controller_index << ".button.fire_left=" << controller.buttons.at(0) << "\n";
|
||||||
file << "controller." << controller_index << ".button.fire_left=" << controller.buttons.at(0) << "\n";
|
file << "controller." << controller_index << ".button.fire_center=" << controller.buttons.at(1) << "\n";
|
||||||
file << "controller." << controller_index << ".button.fire_center=" << controller.buttons.at(1) << "\n";
|
file << "controller." << controller_index << ".button.fire_right=" << controller.buttons.at(2) << "\n";
|
||||||
file << "controller." << controller_index << ".button.fire_right=" << controller.buttons.at(2) << "\n";
|
file << "controller." << controller_index << ".button.start=" << controller.buttons.at(3) << "\n";
|
||||||
file << "controller." << controller_index << ".button.start=" << controller.buttons.at(3) << "\n";
|
file << "controller." << controller_index << ".button.service=" << controller.buttons.at(4) << "\n";
|
||||||
file << "controller." << controller_index << ".button.service=" << controller.buttons.at(4) << "\n";
|
|
||||||
|
|
||||||
// Incrementa el índice
|
// Incrementa el índice
|
||||||
++controller_index;
|
++controller_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cierra el fichero
|
// Cierra el fichero
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Asigna variables a partir de dos cadenas
|
// Asigna variables a partir de dos cadenas
|
||||||
bool set(const std::string &var, const std::string &value)
|
bool set(const std::string &var, const std::string &value) {
|
||||||
{
|
// Indicador de éxito en la asignación
|
||||||
// Indicador de éxito en la asignación
|
auto success = true;
|
||||||
auto success = true;
|
|
||||||
|
|
||||||
// Opciones de video
|
// Opciones de video
|
||||||
if (var == "video.fullscreen")
|
if (var == "video.fullscreen") {
|
||||||
{
|
video.fullscreen = stringToBool(value);
|
||||||
video.fullscreen = stringToBool(value);
|
} else if (var == "window.zoom") {
|
||||||
}
|
window.size = std::stoi(value);
|
||||||
else if (var == "window.zoom")
|
} else if (var == "video.scale_mode") {
|
||||||
{
|
video.scale_mode = static_cast<SDL_ScaleMode>(std::stoi(value));
|
||||||
window.size = std::stoi(value);
|
} else if (var == "video.shaders") {
|
||||||
}
|
video.shaders = stringToBool(value);
|
||||||
else if (var == "video.scale_mode")
|
} else if (var == "video.integer_scale") {
|
||||||
{
|
video.integer_scale = stringToBool(value);
|
||||||
video.scale_mode = static_cast<SDL_ScaleMode>(std::stoi(value));
|
} else if (var == "video.v_sync") {
|
||||||
}
|
video.v_sync = stringToBool(value);
|
||||||
else if (var == "video.shaders")
|
}
|
||||||
{
|
|
||||||
video.shaders = stringToBool(value);
|
|
||||||
}
|
|
||||||
else if (var == "video.integer_scale")
|
|
||||||
{
|
|
||||||
video.integer_scale = stringToBool(value);
|
|
||||||
}
|
|
||||||
else if (var == "video.v_sync")
|
|
||||||
{
|
|
||||||
video.v_sync = stringToBool(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opciones de audio
|
// Opciones de audio
|
||||||
else if (var == "audio.enabled")
|
else if (var == "audio.enabled") {
|
||||||
{
|
audio.enabled = stringToBool(value);
|
||||||
audio.enabled = stringToBool(value);
|
} else if (var == "audio.volume") {
|
||||||
}
|
audio.volume = std::clamp(std::stoi(value), 0, 100);
|
||||||
else if (var == "audio.volume")
|
} else if (var == "audio.music.enabled") {
|
||||||
{
|
audio.music.enabled = stringToBool(value);
|
||||||
audio.volume = std::clamp(std::stoi(value), 0, 100);
|
} else if (var == "audio.music.volume") {
|
||||||
}
|
audio.music.volume = std::clamp(std::stoi(value), 0, 100);
|
||||||
else if (var == "audio.music.enabled")
|
} else if (var == "audio.sound.enabled") {
|
||||||
{
|
audio.sound.enabled = stringToBool(value);
|
||||||
audio.music.enabled = stringToBool(value);
|
} else if (var == "audio.sound.volume") {
|
||||||
}
|
audio.sound.volume = std::clamp(std::stoi(value), 0, 100);
|
||||||
else if (var == "audio.music.volume")
|
}
|
||||||
{
|
|
||||||
audio.music.volume = std::clamp(std::stoi(value), 0, 100);
|
|
||||||
}
|
|
||||||
else if (var == "audio.sound.enabled")
|
|
||||||
{
|
|
||||||
audio.sound.enabled = stringToBool(value);
|
|
||||||
}
|
|
||||||
else if (var == "audio.sound.volume")
|
|
||||||
{
|
|
||||||
audio.sound.volume = std::clamp(std::stoi(value), 0, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opciones de juego
|
// Opciones de juego
|
||||||
else if (var == "game.language")
|
else if (var == "game.language") {
|
||||||
{
|
settings.language = static_cast<Lang::Code>(std::stoi(value));
|
||||||
settings.language = static_cast<Lang::Code>(std::stoi(value));
|
pending_changes.new_language = settings.language;
|
||||||
pending_changes.new_language = settings.language;
|
} else if (var == "game.difficulty") {
|
||||||
}
|
settings.difficulty = static_cast<DifficultyCode>(std::stoi(value));
|
||||||
else if (var == "game.difficulty")
|
pending_changes.new_difficulty = settings.difficulty;
|
||||||
{
|
} else if (var == "game.autofire") {
|
||||||
settings.difficulty = static_cast<DifficultyCode>(std::stoi(value));
|
settings.autofire = stringToBool(value);
|
||||||
pending_changes.new_difficulty = settings.difficulty;
|
} else if (var == "game.shutdown_enabled") {
|
||||||
}
|
settings.shutdown_enabled = stringToBool(value);
|
||||||
else if (var == "game.autofire")
|
}
|
||||||
{
|
|
||||||
settings.autofire = stringToBool(value);
|
|
||||||
}
|
|
||||||
else if (var == "game.shutdown_enabled")
|
|
||||||
{
|
|
||||||
settings.shutdown_enabled = stringToBool(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opciones de mandos
|
// Opciones de mandos
|
||||||
else if (var == "controller.0.name")
|
else if (var == "controller.0.name") {
|
||||||
{
|
controllers.at(0).name = value;
|
||||||
controllers.at(0).name = value;
|
} else if (var == "controller.0.player") {
|
||||||
}
|
controllers.at(0).player_id = std::clamp(std::stoi(value), 1, 2);
|
||||||
else if (var == "controller.0.player")
|
} else if (var == "controller.0.type") {
|
||||||
{
|
controllers.at(0).type = static_cast<InputDevice>(std::stoi(value));
|
||||||
controllers.at(0).player_id = std::clamp(std::stoi(value), 1, 2);
|
} else if (var == "controller.0.button.fire_left") {
|
||||||
}
|
controllers.at(0).buttons.at(0) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
||||||
else if (var == "controller.0.type")
|
} else if (var == "controller.0.button.fire_center") {
|
||||||
{
|
controllers.at(0).buttons.at(1) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
||||||
controllers.at(0).type = static_cast<InputDevice>(std::stoi(value));
|
} else if (var == "controller.0.button.fire_right") {
|
||||||
}
|
controllers.at(0).buttons.at(2) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
||||||
else if (var == "controller.0.button.fire_left")
|
} else if (var == "controller.0.button.start") {
|
||||||
{
|
controllers.at(0).buttons.at(3) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
||||||
controllers.at(0).buttons.at(0) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
} else if (var == "controller.0.button.service") {
|
||||||
}
|
controllers.at(0).buttons.at(4) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
||||||
else if (var == "controller.0.button.fire_center")
|
} else if (var == "controller.1.name") {
|
||||||
{
|
controllers.at(1).name = value;
|
||||||
controllers.at(0).buttons.at(1) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
} else if (var == "controller.1.player") {
|
||||||
}
|
controllers.at(1).player_id = std::clamp(std::stoi(value), 1, 2);
|
||||||
else if (var == "controller.0.button.fire_right")
|
} else if (var == "controller.1.type") {
|
||||||
{
|
controllers.at(1).type = static_cast<InputDevice>(std::stoi(value));
|
||||||
controllers.at(0).buttons.at(2) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
} else if (var == "controller.1.button.fire_left") {
|
||||||
}
|
controllers.at(1).buttons.at(0) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
||||||
else if (var == "controller.0.button.start")
|
} else if (var == "controller.1.button.fire_center") {
|
||||||
{
|
controllers.at(1).buttons.at(1) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
||||||
controllers.at(0).buttons.at(3) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
} else if (var == "controller.1.button.fire_right") {
|
||||||
}
|
controllers.at(1).buttons.at(2) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
||||||
else if (var == "controller.0.button.service")
|
} else if (var == "controller.1.button.start") {
|
||||||
{
|
controllers.at(1).buttons.at(3) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
||||||
controllers.at(0).buttons.at(4) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
} else if (var == "controller.1.button.service") {
|
||||||
}
|
controllers.at(1).buttons.at(4) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
||||||
else if (var == "controller.1.name")
|
}
|
||||||
{
|
|
||||||
controllers.at(1).name = value;
|
|
||||||
}
|
|
||||||
else if (var == "controller.1.player")
|
|
||||||
{
|
|
||||||
controllers.at(1).player_id = std::clamp(std::stoi(value), 1, 2);
|
|
||||||
}
|
|
||||||
else if (var == "controller.1.type")
|
|
||||||
{
|
|
||||||
controllers.at(1).type = static_cast<InputDevice>(std::stoi(value));
|
|
||||||
}
|
|
||||||
else if (var == "controller.1.button.fire_left")
|
|
||||||
{
|
|
||||||
controllers.at(1).buttons.at(0) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
|
||||||
}
|
|
||||||
else if (var == "controller.1.button.fire_center")
|
|
||||||
{
|
|
||||||
controllers.at(1).buttons.at(1) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
|
||||||
}
|
|
||||||
else if (var == "controller.1.button.fire_right")
|
|
||||||
{
|
|
||||||
controllers.at(1).buttons.at(2) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
|
||||||
}
|
|
||||||
else if (var == "controller.1.button.start")
|
|
||||||
{
|
|
||||||
controllers.at(1).buttons.at(3) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
|
||||||
}
|
|
||||||
else if (var == "controller.1.button.service")
|
|
||||||
{
|
|
||||||
controllers.at(1).buttons.at(4) = static_cast<SDL_GamepadButton>(std::stoi(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lineas vacias o que empiezan por comentario
|
// Lineas vacias o que empiezan por comentario
|
||||||
else if (var.empty() || var.starts_with("#"))
|
else if (var.empty() || var.starts_with("#")) {
|
||||||
{
|
} else {
|
||||||
}
|
success = false;
|
||||||
else
|
}
|
||||||
{
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Asigna el teclado al jugador
|
// Asigna el teclado al jugador
|
||||||
void setKeyboardToPlayer(int player_id)
|
void setKeyboardToPlayer(int player_id) {
|
||||||
{
|
for (auto &controller : controllers) {
|
||||||
for (auto &controller : controllers)
|
if (controller.player_id == player_id) {
|
||||||
{
|
controller.type = InputDevice::ANY;
|
||||||
if (controller.player_id == player_id)
|
} else {
|
||||||
{
|
controller.type = InputDevice::CONTROLLER;
|
||||||
controller.type = InputDevice::ANY;
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
controller.type = InputDevice::CONTROLLER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Intercambia el teclado de jugador
|
// Intercambia el teclado de jugador
|
||||||
void swapKeyboard()
|
void swapKeyboard() {
|
||||||
{
|
std::swap(controllers.at(0).type, controllers.at(1).type);
|
||||||
std::swap(controllers.at(0).type, controllers.at(1).type);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Intercambia los jugadores asignados a los dos primeros mandos
|
// Intercambia los jugadores asignados a los dos primeros mandos
|
||||||
void swapControllers()
|
void swapControllers() {
|
||||||
{
|
std::swap(controllers.at(0).player_id, controllers.at(1).player_id);
|
||||||
std::swap(controllers.at(0).player_id, controllers.at(1).player_id);
|
std::swap(controllers.at(0).type, controllers.at(1).type);
|
||||||
std::swap(controllers.at(0).type, controllers.at(1).type);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Averigua quien está usando el teclado
|
// Averigua quien está usando el teclado
|
||||||
int getPlayerWhoUsesKeyboard()
|
int getPlayerWhoUsesKeyboard() {
|
||||||
{
|
for (const auto &controller : controllers) {
|
||||||
for (const auto &controller : controllers)
|
if (controller.type == InputDevice::ANY) {
|
||||||
{
|
return controller.player_id;
|
||||||
if (controller.type == InputDevice::ANY)
|
}
|
||||||
{
|
}
|
||||||
return controller.player_id;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Aplica los cambios pendientes copiando los valores a sus variables
|
// Aplica los cambios pendientes copiando los valores a sus variables
|
||||||
void applyPendingChanges()
|
void applyPendingChanges() {
|
||||||
{
|
if (pending_changes.has_pending_changes) {
|
||||||
if (pending_changes.has_pending_changes)
|
settings.language = pending_changes.new_language;
|
||||||
{
|
settings.difficulty = pending_changes.new_difficulty;
|
||||||
settings.language = pending_changes.new_language;
|
pending_changes.has_pending_changes = false;
|
||||||
settings.difficulty = pending_changes.new_difficulty;
|
}
|
||||||
pending_changes.has_pending_changes = false;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkPendingChanges()
|
void checkPendingChanges() {
|
||||||
{
|
if (settings.language != pending_changes.new_language ||
|
||||||
if (settings.language != pending_changes.new_language ||
|
settings.difficulty != pending_changes.new_difficulty) {
|
||||||
settings.difficulty != pending_changes.new_difficulty)
|
pending_changes.has_pending_changes = true;
|
||||||
{
|
} else {
|
||||||
pending_changes.has_pending_changes = true;
|
pending_changes.has_pending_changes = false;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
pending_changes.has_pending_changes = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DifficultyCode getDifficultyCodeFromName(const std::string &name)
|
DifficultyCode getDifficultyCodeFromName(const std::string &name) {
|
||||||
{
|
for (const auto &difficulty : difficulties) {
|
||||||
for (const auto &difficulty : difficulties)
|
if (difficulty.name == name)
|
||||||
{
|
return difficulty.code;
|
||||||
if (difficulty.name == name)
|
}
|
||||||
return difficulty.code;
|
// Si no se encuentra, devuelve el primero por defecto
|
||||||
}
|
return difficulties[0].code;
|
||||||
// Si no se encuentra, devuelve el primero por defecto
|
}
|
||||||
return difficulties[0].code;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getDifficultyNameFromCode(DifficultyCode code)
|
std::string getDifficultyNameFromCode(DifficultyCode code) {
|
||||||
{
|
for (const auto &difficulty : difficulties) {
|
||||||
for (const auto &difficulty : difficulties)
|
if (difficulty.code == code)
|
||||||
{
|
return difficulty.name;
|
||||||
if (difficulty.code == code)
|
}
|
||||||
return difficulty.name;
|
// Si no se encuentra, devuelve el nombre del primero por defecto
|
||||||
}
|
return difficulties[0].name;
|
||||||
// Si no se encuentra, devuelve el nombre del primero por defecto
|
}
|
||||||
return difficulties[0].name;
|
} // namespace Options
|
||||||
}
|
|
||||||
} // namespace Options
|
|
||||||
+164
-175
@@ -1,202 +1,191 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_GamepadButton, SDL_ScaleMode
|
#include <SDL3/SDL.h> // Para SDL_GamepadButton, SDL_ScaleMode
|
||||||
#include <string> // Para string, basic_string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "input.h" // Para InputAction, InputDevice
|
#include <string> // Para string, basic_string
|
||||||
#include "lang.h" // Para Code
|
#include <vector> // Para vector
|
||||||
#include "manage_hiscore_table.h" // Para HiScoreEntry
|
|
||||||
|
#include "input.h" // Para InputAction, InputDevice
|
||||||
|
#include "lang.h" // Para Code
|
||||||
|
#include "manage_hiscore_table.h" // Para HiScoreEntry
|
||||||
|
|
||||||
static constexpr int INVALID_INDEX = -1;
|
static constexpr int INVALID_INDEX = -1;
|
||||||
|
|
||||||
namespace Options
|
namespace Options {
|
||||||
{
|
// --- Dificultad del juego ---
|
||||||
// --- Dificultad del juego ---
|
enum class DifficultyCode {
|
||||||
enum class DifficultyCode
|
EASY = 0,
|
||||||
{
|
NORMAL = 1,
|
||||||
EASY = 0,
|
HARD = 2,
|
||||||
NORMAL = 1,
|
};
|
||||||
HARD = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
// --- Estructura que representa un nivel de dificultad
|
// --- Estructura que representa un nivel de dificultad
|
||||||
struct Difficulty
|
struct Difficulty {
|
||||||
{
|
DifficultyCode code; // Código que identifica la dificultad
|
||||||
DifficultyCode code; // Código que identifica la dificultad
|
std::string name; // Nombre que identifica la dificultad
|
||||||
std::string name; // Nombre que identifica la dificultad
|
|
||||||
|
|
||||||
Difficulty(DifficultyCode c, const std::string &n)
|
Difficulty(DifficultyCode c, const std::string &n)
|
||||||
: code(c), name(n) {}
|
: code(c), name(n) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Opciones de ventana ---
|
// --- Opciones de ventana ---
|
||||||
struct WindowOptions
|
struct WindowOptions {
|
||||||
{
|
std::string caption; // Texto que aparece en la barra de título de la ventana
|
||||||
std::string caption; // Texto que aparece en la barra de título de la ventana
|
int size; // Valor por el que se multiplica el tamaño de la ventana
|
||||||
int size; // Valor por el que se multiplica el tamaño de la ventana
|
int max_size; // Tamaño máximo para que la ventana no sea mayor que la pantalla
|
||||||
int max_size; // Tamaño máximo para que la ventana no sea mayor que la pantalla
|
|
||||||
|
|
||||||
// Constructor por defecto con valores iniciales
|
// Constructor por defecto con valores iniciales
|
||||||
WindowOptions()
|
WindowOptions()
|
||||||
: caption("Coffee Crisis Arcade Edition"),
|
: caption("Coffee Crisis Arcade Edition"),
|
||||||
size(2),
|
size(2),
|
||||||
max_size(2) {}
|
max_size(2) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Opciones de vídeo ---
|
// --- Opciones de vídeo ---
|
||||||
struct VideoOptions
|
struct VideoOptions {
|
||||||
{
|
SDL_ScaleMode scale_mode; // Filtro usado para el escalado de la imagen
|
||||||
SDL_ScaleMode scale_mode; // Filtro usado para el escalado de la imagen
|
bool fullscreen; // Indica si se usa pantalla completa
|
||||||
bool fullscreen; // Indica si se usa pantalla completa
|
bool v_sync; // Indica si se usa vsync
|
||||||
bool v_sync; // Indica si se usa vsync
|
bool integer_scale; // Indica si se usa escalado entero
|
||||||
bool integer_scale; // Indica si se usa escalado entero
|
bool shaders; // Indica si se usan shaders para los filtros de vídeo
|
||||||
bool shaders; // Indica si se usan shaders para los filtros de vídeo
|
std::string info; // Información sobre el modo de vídeo
|
||||||
std::string info; // Información sobre el modo de vídeo
|
|
||||||
|
|
||||||
// Constructor por defecto con valores iniciales
|
// Constructor por defecto con valores iniciales
|
||||||
VideoOptions()
|
VideoOptions()
|
||||||
: scale_mode(SDL_ScaleMode::SDL_SCALEMODE_NEAREST),
|
: scale_mode(SDL_ScaleMode::SDL_SCALEMODE_NEAREST),
|
||||||
fullscreen(false),
|
fullscreen(false),
|
||||||
v_sync(true),
|
v_sync(true),
|
||||||
integer_scale(true),
|
integer_scale(true),
|
||||||
shaders(false),
|
shaders(false),
|
||||||
info() {}
|
info() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Opciones de música ---
|
// --- Opciones de música ---
|
||||||
struct MusicOptions
|
struct MusicOptions {
|
||||||
{
|
bool enabled; // Indica si la música suena o no
|
||||||
bool enabled; // Indica si la música suena o no
|
int volume; // Volumen de la música
|
||||||
int volume; // Volumen de la música
|
|
||||||
|
|
||||||
// Constructor por defecto
|
// Constructor por defecto
|
||||||
MusicOptions()
|
MusicOptions()
|
||||||
: enabled(true),
|
: enabled(true),
|
||||||
volume(100) {}
|
volume(100) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Opciones de sonido ---
|
// --- Opciones de sonido ---
|
||||||
struct SoundOptions
|
struct SoundOptions {
|
||||||
{
|
bool enabled; // Indica si los sonidos suenan o no
|
||||||
bool enabled; // Indica si los sonidos suenan o no
|
int volume; // Volumen de los sonidos
|
||||||
int volume; // Volumen de los sonidos
|
|
||||||
|
|
||||||
// Constructor por defecto
|
// Constructor por defecto
|
||||||
SoundOptions()
|
SoundOptions()
|
||||||
: enabled(true),
|
: enabled(true),
|
||||||
volume(100) {}
|
volume(100) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Opciones de audio ---
|
// --- Opciones de audio ---
|
||||||
struct AudioOptions
|
struct AudioOptions {
|
||||||
{
|
MusicOptions music; // Opciones para la música
|
||||||
MusicOptions music; // Opciones para la música
|
SoundOptions sound; // Opciones para los efectos de sonido
|
||||||
SoundOptions sound; // Opciones para los efectos de sonido
|
bool enabled; // Indica si el audio está activo o no
|
||||||
bool enabled; // Indica si el audio está activo o no
|
int volume; // Volumen general del audio
|
||||||
int volume; // Volumen general del audio
|
|
||||||
|
|
||||||
// Constructor por defecto
|
// Constructor por defecto
|
||||||
AudioOptions()
|
AudioOptions()
|
||||||
: music(),
|
: music(),
|
||||||
sound(),
|
sound(),
|
||||||
enabled(true),
|
enabled(true),
|
||||||
volume(100) {}
|
volume(100) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Opciones de configuración ---
|
// --- Opciones de configuración ---
|
||||||
struct SettingsOptions
|
struct SettingsOptions {
|
||||||
{
|
DifficultyCode difficulty; // Dificultad del juego
|
||||||
DifficultyCode difficulty; // Dificultad del juego
|
Lang::Code language; // Idioma usado en el juego
|
||||||
Lang::Code language; // Idioma usado en el juego
|
bool autofire; // Indicador de autofire
|
||||||
bool autofire; // Indicador de autofire
|
bool shutdown_enabled; // Especifica si se puede apagar el sistema
|
||||||
bool shutdown_enabled; // Especifica si se puede apagar el sistema
|
std::vector<HiScoreEntry> hi_score_table; // Tabla de mejores puntuaciones
|
||||||
std::vector<HiScoreEntry> hi_score_table; // Tabla de mejores puntuaciones
|
std::vector<int> last_hi_score_entry; // Últimas posiciones de entrada en la tabla
|
||||||
std::vector<int> last_hi_score_entry; // Últimas posiciones de entrada en la tabla
|
std::string config_file; // Ruta al fichero donde guardar la configuración y las opciones del juego
|
||||||
std::string config_file; // Ruta al fichero donde guardar la configuración y las opciones del juego
|
|
||||||
|
|
||||||
// Constructor por defecto con valores iniciales
|
// Constructor por defecto con valores iniciales
|
||||||
SettingsOptions()
|
SettingsOptions()
|
||||||
: difficulty(DifficultyCode::NORMAL),
|
: difficulty(DifficultyCode::NORMAL),
|
||||||
language(Lang::Code::VALENCIAN),
|
language(Lang::Code::VALENCIAN),
|
||||||
autofire(true),
|
autofire(true),
|
||||||
shutdown_enabled(false),
|
shutdown_enabled(false),
|
||||||
last_hi_score_entry({INVALID_INDEX, INVALID_INDEX}),
|
last_hi_score_entry({INVALID_INDEX, INVALID_INDEX}),
|
||||||
config_file() {}
|
config_file() {}
|
||||||
|
|
||||||
// Reinicia las últimas entradas de puntuación
|
// Reinicia las últimas entradas de puntuación
|
||||||
void clearLastHiScoreEntries()
|
void clearLastHiScoreEntries() {
|
||||||
{
|
last_hi_score_entry[0] = INVALID_INDEX;
|
||||||
last_hi_score_entry[0] = INVALID_INDEX;
|
last_hi_score_entry[1] = INVALID_INDEX;
|
||||||
last_hi_score_entry[1] = INVALID_INDEX;
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// --- Opciones de mando ---
|
// --- Opciones de mando ---
|
||||||
struct GamepadOptions
|
struct GamepadOptions {
|
||||||
{
|
int index; // Índice en el vector de mandos
|
||||||
int index; // Índice en el vector de mandos
|
int player_id; // Jugador asociado al mando
|
||||||
int player_id; // Jugador asociado al mando
|
InputDevice type; // Indica si se usará teclado, mando o ambos
|
||||||
InputDevice type; // Indica si se usará teclado, mando o ambos
|
std::string name; // Nombre del dispositivo
|
||||||
std::string name; // Nombre del dispositivo
|
bool plugged; // Indica si el mando está conectado
|
||||||
bool plugged; // Indica si el mando está conectado
|
std::vector<InputAction> inputs; // Listado de acciones asignadas
|
||||||
std::vector<InputAction> inputs; // Listado de acciones asignadas
|
std::vector<SDL_GamepadButton> buttons; // Listado de botones asignados a cada acción
|
||||||
std::vector<SDL_GamepadButton> buttons; // Listado de botones asignados a cada acción
|
|
||||||
|
|
||||||
// Constructor por defecto
|
// Constructor por defecto
|
||||||
GamepadOptions()
|
GamepadOptions()
|
||||||
: index(INVALID_INDEX),
|
: index(INVALID_INDEX),
|
||||||
player_id(INVALID_INDEX),
|
player_id(INVALID_INDEX),
|
||||||
type(InputDevice::CONTROLLER),
|
type(InputDevice::CONTROLLER),
|
||||||
name(),
|
name(),
|
||||||
plugged(false),
|
plugged(false),
|
||||||
inputs{
|
inputs{
|
||||||
InputAction::FIRE_LEFT,
|
InputAction::FIRE_LEFT,
|
||||||
InputAction::FIRE_CENTER,
|
InputAction::FIRE_CENTER,
|
||||||
InputAction::FIRE_RIGHT,
|
InputAction::FIRE_RIGHT,
|
||||||
InputAction::START,
|
InputAction::START,
|
||||||
InputAction::SERVICE},
|
InputAction::SERVICE},
|
||||||
buttons{
|
buttons{
|
||||||
SDL_GAMEPAD_BUTTON_WEST,
|
SDL_GAMEPAD_BUTTON_WEST,
|
||||||
SDL_GAMEPAD_BUTTON_NORTH,
|
SDL_GAMEPAD_BUTTON_NORTH,
|
||||||
SDL_GAMEPAD_BUTTON_EAST,
|
SDL_GAMEPAD_BUTTON_EAST,
|
||||||
SDL_GAMEPAD_BUTTON_START,
|
SDL_GAMEPAD_BUTTON_START,
|
||||||
SDL_GAMEPAD_BUTTON_BACK} {}
|
SDL_GAMEPAD_BUTTON_BACK} {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Opciones pendientes de aplicar ---
|
// --- Opciones pendientes de aplicar ---
|
||||||
struct PendingChanges
|
struct PendingChanges {
|
||||||
{
|
Lang::Code new_language; // Idioma en espera de aplicar
|
||||||
Lang::Code new_language; // Idioma en espera de aplicar
|
DifficultyCode new_difficulty; // Dificultad en espera de aplicar
|
||||||
DifficultyCode new_difficulty; // Dificultad en espera de aplicar
|
bool has_pending_changes; // Indica si hay cambios pendientes
|
||||||
bool has_pending_changes; // Indica si hay cambios pendientes
|
|
||||||
|
|
||||||
// Constructor por defecto con valores iniciales
|
// Constructor por defecto con valores iniciales
|
||||||
PendingChanges()
|
PendingChanges()
|
||||||
: new_language(Lang::Code::VALENCIAN),
|
: new_language(Lang::Code::VALENCIAN),
|
||||||
new_difficulty(DifficultyCode::NORMAL),
|
new_difficulty(DifficultyCode::NORMAL),
|
||||||
has_pending_changes(false) {}
|
has_pending_changes(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Variables globales ---
|
// --- Variables globales ---
|
||||||
extern WindowOptions window; // Opciones de la ventana
|
extern WindowOptions window; // Opciones de la ventana
|
||||||
extern SettingsOptions settings; // Opciones del juego
|
extern SettingsOptions settings; // Opciones del juego
|
||||||
extern VideoOptions video; // Opciones de vídeo
|
extern VideoOptions video; // Opciones de vídeo
|
||||||
extern AudioOptions audio; // Opciones de audio
|
extern AudioOptions audio; // Opciones de audio
|
||||||
extern std::vector<GamepadOptions> controllers; // Opciones de mando para cada jugador
|
extern std::vector<GamepadOptions> controllers; // Opciones de mando para cada jugador
|
||||||
extern PendingChanges pending_changes; // Opciones que se aplican al cerrar
|
extern PendingChanges pending_changes; // Opciones que se aplican al cerrar
|
||||||
extern std::vector<Difficulty> difficulties; // Lista de los diferentes tipos de dificultad
|
extern std::vector<Difficulty> difficulties; // Lista de los diferentes tipos de dificultad
|
||||||
|
|
||||||
// --- Funciones de configuración ---
|
// --- Funciones de configuración ---
|
||||||
void init(); // Inicializa las opciones del programa
|
void init(); // Inicializa las opciones del programa
|
||||||
bool loadFromFile(); // Carga el fichero de configuración
|
bool loadFromFile(); // Carga el fichero de configuración
|
||||||
bool saveToFile(); // Guarda el fichero de configuración
|
bool saveToFile(); // Guarda el fichero de configuración
|
||||||
void setKeyboardToPlayer(int player_id); // Asigna el teclado al jugador
|
void setKeyboardToPlayer(int player_id); // Asigna el teclado al jugador
|
||||||
void swapKeyboard(); // Intercambia el teclado de jugador
|
void swapKeyboard(); // Intercambia el teclado de jugador
|
||||||
void swapControllers(); // Intercambia los jugadores asignados a los dos primeros mandos
|
void swapControllers(); // Intercambia los jugadores asignados a los dos primeros mandos
|
||||||
int getPlayerWhoUsesKeyboard(); // Averigua quién está usando el teclado
|
int getPlayerWhoUsesKeyboard(); // Averigua quién está usando el teclado
|
||||||
void applyPendingChanges(); // Aplica los cambios pendientes copiando los valores a sus variables
|
void applyPendingChanges(); // Aplica los cambios pendientes copiando los valores a sus variables
|
||||||
void checkPendingChanges(); // Verifica si hay cambios pendientes
|
void checkPendingChanges(); // Verifica si hay cambios pendientes
|
||||||
DifficultyCode getDifficultyCodeFromName(const std::string &name); // Obtiene el código de dificultad a partir del nombre
|
DifficultyCode getDifficultyCodeFromName(const std::string &name); // Obtiene el código de dificultad a partir del nombre
|
||||||
std::string getDifficultyNameFromCode(DifficultyCode code); // Obtiene el nombre de la dificultad a partir del código
|
std::string getDifficultyNameFromCode(DifficultyCode code); // Obtiene el nombre de la dificultad a partir del código
|
||||||
} // namespace Options
|
} // namespace Options
|
||||||
+398
-477
@@ -1,12 +1,13 @@
|
|||||||
#include "param.h"
|
#include "param.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_LogCategory, SDL_LogError, SDL_LogInfo
|
#include <SDL3/SDL.h> // Para SDL_LogCategory, SDL_LogError, SDL_LogInfo
|
||||||
#include <fstream> // Para basic_istream, basic_ifstream, ifstream
|
|
||||||
#include <sstream> // Para basic_istringstream
|
|
||||||
#include <stdexcept> // Para runtime_error
|
|
||||||
#include <string> // Para operator==, stoi, char_traits, string, ope...
|
|
||||||
|
|
||||||
#include "utils.h" // Para Zone, Color, NotifyPosition, getFileName
|
#include <fstream> // Para basic_istream, basic_ifstream, ifstream
|
||||||
|
#include <sstream> // Para basic_istringstream
|
||||||
|
#include <stdexcept> // Para runtime_error
|
||||||
|
#include <string> // Para operator==, stoi, char_traits, string, ope...
|
||||||
|
|
||||||
|
#include "utils.h" // Para Zone, Color, NotifyPosition, getFileName
|
||||||
|
|
||||||
Param param;
|
Param param;
|
||||||
|
|
||||||
@@ -17,500 +18,420 @@ void precalculateZones();
|
|||||||
bool setParams(const std::string &var, const std::string &value);
|
bool setParams(const std::string &var, const std::string &value);
|
||||||
|
|
||||||
// Establece valores por defecto a las variables
|
// Establece valores por defecto a las variables
|
||||||
void initParam()
|
void initParam() {
|
||||||
{
|
// GAME
|
||||||
// GAME
|
param.game.width = 320;
|
||||||
param.game.width = 320;
|
param.game.height = 256;
|
||||||
param.game.height = 256;
|
param.game.item_size = 20;
|
||||||
param.game.item_size = 20;
|
param.game.game_area.rect = {0, 0, param.game.width, param.game.height};
|
||||||
param.game.game_area.rect = {0, 0, param.game.width, param.game.height};
|
param.game.play_area.rect = {0, 0, param.game.width, 216};
|
||||||
param.game.play_area.rect = {0, 0, param.game.width, 216};
|
param.game.name_entry_idle_time = 10;
|
||||||
param.game.name_entry_idle_time = 10;
|
param.game.name_entry_total_time = 60;
|
||||||
param.game.name_entry_total_time = 60;
|
param.game.speed = 15;
|
||||||
param.game.speed = 15;
|
param.game.hit_stop = true;
|
||||||
param.game.hit_stop = true;
|
param.game.hit_stop_ms = 300;
|
||||||
param.game.hit_stop_ms = 300;
|
precalculateZones();
|
||||||
precalculateZones();
|
|
||||||
|
|
||||||
// SCOREBOARD
|
// SCOREBOARD
|
||||||
param.scoreboard.rect = {0, 216, param.game.width, 40};
|
param.scoreboard.rect = {0, 216, param.game.width, 40};
|
||||||
param.scoreboard.separator_autocolor = false;
|
param.scoreboard.separator_autocolor = false;
|
||||||
param.scoreboard.separator_color = Color();
|
param.scoreboard.separator_color = Color();
|
||||||
param.scoreboard.easy_color = Color();
|
param.scoreboard.easy_color = Color();
|
||||||
param.scoreboard.normal_color = Color();
|
param.scoreboard.normal_color = Color();
|
||||||
param.scoreboard.hard_color = Color();
|
param.scoreboard.hard_color = Color();
|
||||||
param.scoreboard.text_autocolor = false;
|
param.scoreboard.text_autocolor = false;
|
||||||
param.scoreboard.text_color1 = Color();
|
param.scoreboard.text_color1 = Color();
|
||||||
param.scoreboard.text_color2 = Color();
|
param.scoreboard.text_color2 = Color();
|
||||||
param.scoreboard.skip_countdown_value = 8;
|
param.scoreboard.skip_countdown_value = 8;
|
||||||
|
|
||||||
// FADE
|
// FADE
|
||||||
param.fade.num_squares_width = param.game.width / 2;
|
param.fade.num_squares_width = param.game.width / 2;
|
||||||
param.fade.num_squares_height = param.game.height / 2;
|
param.fade.num_squares_height = param.game.height / 2;
|
||||||
param.fade.random_squares_delay = 1;
|
param.fade.random_squares_delay = 1;
|
||||||
param.fade.random_squares_mult = 500;
|
param.fade.random_squares_mult = 500;
|
||||||
param.fade.post_duration = 80;
|
param.fade.post_duration = 80;
|
||||||
param.fade.venetian_size = 16;
|
param.fade.venetian_size = 16;
|
||||||
|
|
||||||
// TITLE
|
// TITLE
|
||||||
param.title.press_start_position = 160;
|
param.title.press_start_position = 160;
|
||||||
param.title.title_duration = 800;
|
param.title.title_duration = 800;
|
||||||
param.title.arcade_edition_position = 123;
|
param.title.arcade_edition_position = 123;
|
||||||
param.title.title_c_c_position = 11;
|
param.title.title_c_c_position = 11;
|
||||||
param.title.bg_color = Color(255, 255, 255);
|
param.title.bg_color = Color(255, 255, 255);
|
||||||
|
|
||||||
// BACKGROUND
|
// BACKGROUND
|
||||||
param.background.attenuate_color = Color(255, 255, 255, 0);
|
param.background.attenuate_color = Color(255, 255, 255, 0);
|
||||||
|
|
||||||
// BALLOONS
|
// BALLOONS
|
||||||
param.balloon.settings.at(0) = ParamBalloon::Settings(0.09f, 2.60f);
|
param.balloon.settings.at(0) = ParamBalloon::Settings(0.09f, 2.60f);
|
||||||
param.balloon.settings.at(1) = ParamBalloon::Settings(0.10f, 3.50f);
|
param.balloon.settings.at(1) = ParamBalloon::Settings(0.10f, 3.50f);
|
||||||
param.balloon.settings.at(2) = ParamBalloon::Settings(0.10f, 4.50f);
|
param.balloon.settings.at(2) = ParamBalloon::Settings(0.10f, 4.50f);
|
||||||
param.balloon.settings.at(3) = ParamBalloon::Settings(0.10f, 4.95f);
|
param.balloon.settings.at(3) = ParamBalloon::Settings(0.10f, 4.95f);
|
||||||
|
|
||||||
param.balloon.color.at(0) = "blue";
|
param.balloon.color.at(0) = "blue";
|
||||||
param.balloon.color.at(1) = "orange";
|
param.balloon.color.at(1) = "orange";
|
||||||
param.balloon.color.at(2) = "red";
|
param.balloon.color.at(2) = "red";
|
||||||
param.balloon.color.at(3) = "green";
|
param.balloon.color.at(3) = "green";
|
||||||
|
|
||||||
param.balloon.bouncing_sound = false;
|
param.balloon.bouncing_sound = false;
|
||||||
|
|
||||||
// NOTIFICATION
|
// NOTIFICATION
|
||||||
param.notification.pos_v = NotifyPosition::TOP;
|
param.notification.pos_v = NotifyPosition::TOP;
|
||||||
param.notification.pos_h = NotifyPosition::LEFT;
|
param.notification.pos_h = NotifyPosition::LEFT;
|
||||||
param.notification.sound = false;
|
param.notification.sound = false;
|
||||||
param.notification.color = Color(48, 48, 48);
|
param.notification.color = Color(48, 48, 48);
|
||||||
|
|
||||||
// INTRO
|
// INTRO
|
||||||
param.intro.bg_color = Color::fromHex("543149");
|
param.intro.bg_color = Color::fromHex("543149");
|
||||||
param.intro.card_color = Color::fromHex("CBDBFC");
|
param.intro.card_color = Color::fromHex("CBDBFC");
|
||||||
param.intro.shadow_color = Color::fromHex("00000080");
|
param.intro.shadow_color = Color::fromHex("00000080");
|
||||||
param.intro.text_distance_from_bottom = 48;
|
param.intro.text_distance_from_bottom = 48;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carga los parámetros desde un archivo
|
// Carga los parámetros desde un archivo
|
||||||
void loadParamsFromFile(const std::string &file_path)
|
void loadParamsFromFile(const std::string &file_path) {
|
||||||
{
|
// Inicializa los parámetros con valores por defecto
|
||||||
// Inicializa los parámetros con valores por defecto
|
initParam();
|
||||||
initParam();
|
|
||||||
|
|
||||||
// Abre el archivo
|
// Abre el archivo
|
||||||
std::ifstream file(file_path);
|
std::ifstream file(file_path);
|
||||||
if (!file.is_open())
|
if (!file.is_open()) {
|
||||||
{
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo abrir el archivo %s", file_path.c_str());
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo abrir el archivo %s", file_path.c_str());
|
throw std::runtime_error("No se pudo abrir el archivo: " + file_path);
|
||||||
throw std::runtime_error("No se pudo abrir el archivo: " + file_path);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\nReading file: %s", getFileName(file_path).c_str());
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\nReading file: %s", getFileName(file_path).c_str());
|
||||||
|
|
||||||
std::string line, param1, param2;
|
std::string line, param1, param2;
|
||||||
while (std::getline(file, line))
|
while (std::getline(file, line)) {
|
||||||
{
|
// Elimina comentarios
|
||||||
// Elimina comentarios
|
auto comment_pos = line.find('#');
|
||||||
auto comment_pos = line.find('#');
|
if (comment_pos != std::string::npos) {
|
||||||
if (comment_pos != std::string::npos)
|
line.resize(comment_pos);
|
||||||
{
|
}
|
||||||
line.resize(comment_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Usa un stream para separar palabras
|
// Usa un stream para separar palabras
|
||||||
std::istringstream iss(line);
|
std::istringstream iss(line);
|
||||||
if (iss >> param1 >> param2)
|
if (iss >> param1 >> param2) {
|
||||||
{
|
if (!setParams(param1, param2)) {
|
||||||
if (!setParams(param1, param2))
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Parámetro desconocido: %s", param1.c_str());
|
||||||
{
|
}
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Parámetro desconocido: %s", param1.c_str());
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cierra el archivo
|
// Cierra el archivo
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
// Realiza cálculos adicionales después de cargar los parámetros
|
// Realiza cálculos adicionales después de cargar los parámetros
|
||||||
precalculateZones();
|
precalculateZones();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Asigna variables a partir de dos cadenas
|
// Asigna variables a partir de dos cadenas
|
||||||
bool setParams(const std::string &var, const std::string &value)
|
bool setParams(const std::string &var, const std::string &value) {
|
||||||
{
|
// Indicador de éxito en la asignación
|
||||||
// Indicador de éxito en la asignación
|
auto success = true;
|
||||||
auto success = true;
|
|
||||||
|
// GAME
|
||||||
// GAME
|
if (var == "game.width") {
|
||||||
if (var == "game.width")
|
param.game.width = std::stoi(value);
|
||||||
{
|
}
|
||||||
param.game.width = std::stoi(value);
|
|
||||||
}
|
else if (var == "game.height") {
|
||||||
|
param.game.height = std::stoi(value);
|
||||||
else if (var == "game.height")
|
}
|
||||||
{
|
|
||||||
param.game.height = std::stoi(value);
|
else if (var == "game.item_size") {
|
||||||
}
|
param.game.item_size = std::stoi(value);
|
||||||
|
}
|
||||||
else if (var == "game.item_size")
|
|
||||||
{
|
else if (var == "game.play_area.rect.x") {
|
||||||
param.game.item_size = std::stoi(value);
|
param.game.play_area.rect.x = std::stoi(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (var == "game.play_area.rect.x")
|
else if (var == "game.play_area.rect.y") {
|
||||||
{
|
param.game.play_area.rect.y = std::stoi(value);
|
||||||
param.game.play_area.rect.x = std::stoi(value);
|
}
|
||||||
}
|
|
||||||
|
else if (var == "game.play_area.rect.w") {
|
||||||
else if (var == "game.play_area.rect.y")
|
param.game.play_area.rect.w = std::stoi(value);
|
||||||
{
|
}
|
||||||
param.game.play_area.rect.y = std::stoi(value);
|
|
||||||
}
|
else if (var == "game.play_area.rect.h") {
|
||||||
|
param.game.play_area.rect.h = std::stoi(value);
|
||||||
else if (var == "game.play_area.rect.w")
|
}
|
||||||
{
|
|
||||||
param.game.play_area.rect.w = std::stoi(value);
|
else if (var == "game.name_entry_idle_time") {
|
||||||
}
|
param.game.name_entry_idle_time = std::stoi(value);
|
||||||
|
}
|
||||||
else if (var == "game.play_area.rect.h")
|
|
||||||
{
|
else if (var == "game.name_entry_total_time") {
|
||||||
param.game.play_area.rect.h = std::stoi(value);
|
param.game.name_entry_total_time = std::stoi(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (var == "game.name_entry_idle_time")
|
else if (var == "game.hit_stop") {
|
||||||
{
|
param.game.hit_stop = stringToBool(value);
|
||||||
param.game.name_entry_idle_time = std::stoi(value);
|
}
|
||||||
}
|
|
||||||
|
else if (var == "game.hit_stop_ms") {
|
||||||
else if (var == "game.name_entry_total_time")
|
param.game.hit_stop_ms = std::stoi(value);
|
||||||
{
|
}
|
||||||
param.game.name_entry_total_time = std::stoi(value);
|
|
||||||
}
|
// FADE
|
||||||
|
else if (var == "fade.color") {
|
||||||
else if (var == "game.hit_stop")
|
param.fade.color = Color::fromHex(value);
|
||||||
{
|
}
|
||||||
param.game.hit_stop = stringToBool(value);
|
|
||||||
}
|
else if (var == "fade.num_squares_width") {
|
||||||
|
param.fade.num_squares_width = std::stoi(value);
|
||||||
else if (var == "game.hit_stop_ms")
|
}
|
||||||
{
|
|
||||||
param.game.hit_stop_ms = std::stoi(value);
|
else if (var == "fade.num_squares_height") {
|
||||||
}
|
param.fade.num_squares_height = std::stoi(value);
|
||||||
|
}
|
||||||
// FADE
|
|
||||||
else if (var == "fade.color")
|
else if (var == "fade.random_squares_delay") {
|
||||||
{
|
param.fade.random_squares_delay = std::stoi(value);
|
||||||
param.fade.color = Color::fromHex(value);
|
}
|
||||||
}
|
|
||||||
|
else if (var == "fade.random_squares_mult") {
|
||||||
else if (var == "fade.num_squares_width")
|
param.fade.random_squares_mult = std::stoi(value);
|
||||||
{
|
}
|
||||||
param.fade.num_squares_width = std::stoi(value);
|
|
||||||
}
|
else if (var == "fade.post_duration") {
|
||||||
|
param.fade.post_duration = std::stoi(value);
|
||||||
else if (var == "fade.num_squares_height")
|
}
|
||||||
{
|
|
||||||
param.fade.num_squares_height = std::stoi(value);
|
else if (var == "fade.venetian_size") {
|
||||||
}
|
param.fade.venetian_size = std::stoi(value);
|
||||||
|
}
|
||||||
else if (var == "fade.random_squares_delay")
|
|
||||||
{
|
// SCOREBOARD
|
||||||
param.fade.random_squares_delay = std::stoi(value);
|
else if (var == "scoreboard.rect.x") {
|
||||||
}
|
param.scoreboard.rect.x = std::stoi(value);
|
||||||
|
}
|
||||||
else if (var == "fade.random_squares_mult")
|
|
||||||
{
|
else if (var == "scoreboard.rect.y") {
|
||||||
param.fade.random_squares_mult = std::stoi(value);
|
param.scoreboard.rect.y = std::stoi(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (var == "fade.post_duration")
|
else if (var == "scoreboard.rect.w") {
|
||||||
{
|
param.scoreboard.rect.w = std::stoi(value);
|
||||||
param.fade.post_duration = std::stoi(value);
|
}
|
||||||
}
|
|
||||||
|
else if (var == "scoreboard.rect.h") {
|
||||||
else if (var == "fade.venetian_size")
|
param.scoreboard.rect.h = std::stoi(value);
|
||||||
{
|
}
|
||||||
param.fade.venetian_size = std::stoi(value);
|
|
||||||
}
|
else if (var == "scoreboard.separator_autocolor") {
|
||||||
|
param.scoreboard.separator_autocolor = stringToBool(value);
|
||||||
// SCOREBOARD
|
}
|
||||||
else if (var == "scoreboard.rect.x")
|
|
||||||
{
|
else if (var == "scoreboard.separator_color") {
|
||||||
param.scoreboard.rect.x = std::stoi(value);
|
param.scoreboard.separator_color = Color::fromHex(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (var == "scoreboard.rect.y")
|
else if (var == "scoreboard.easy_color") {
|
||||||
{
|
param.scoreboard.easy_color = Color::fromHex(value);
|
||||||
param.scoreboard.rect.y = std::stoi(value);
|
}
|
||||||
}
|
|
||||||
|
else if (var == "scoreboard.normal_color") {
|
||||||
else if (var == "scoreboard.rect.w")
|
param.scoreboard.normal_color = Color::fromHex(value);
|
||||||
{
|
}
|
||||||
param.scoreboard.rect.w = std::stoi(value);
|
|
||||||
}
|
else if (var == "scoreboard.hard_color") {
|
||||||
|
param.scoreboard.hard_color = Color::fromHex(value);
|
||||||
else if (var == "scoreboard.rect.h")
|
}
|
||||||
{
|
|
||||||
param.scoreboard.rect.h = std::stoi(value);
|
else if (var == "scoreboard.text_autocolor") {
|
||||||
}
|
param.scoreboard.text_autocolor = stringToBool(value);
|
||||||
|
}
|
||||||
else if (var == "scoreboard.separator_autocolor")
|
|
||||||
{
|
else if (var == "scoreboard.text_color1") {
|
||||||
param.scoreboard.separator_autocolor = stringToBool(value);
|
param.scoreboard.text_color1 = Color::fromHex(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (var == "scoreboard.separator_color")
|
else if (var == "scoreboard.text_color2") {
|
||||||
{
|
param.scoreboard.text_color2 = Color::fromHex(value);
|
||||||
param.scoreboard.separator_color = Color::fromHex(value);
|
}
|
||||||
}
|
|
||||||
|
else if (var == "scoreboard.skip_countdown_value") {
|
||||||
else if (var == "scoreboard.easy_color")
|
param.scoreboard.skip_countdown_value = std::stoi(value);
|
||||||
{
|
}
|
||||||
param.scoreboard.easy_color = Color::fromHex(value);
|
|
||||||
}
|
// TITLE
|
||||||
|
else if (var == "title.press_start_position") {
|
||||||
else if (var == "scoreboard.normal_color")
|
param.title.press_start_position = std::stoi(value);
|
||||||
{
|
}
|
||||||
param.scoreboard.normal_color = Color::fromHex(value);
|
|
||||||
}
|
else if (var == "title.title_duration") {
|
||||||
|
param.title.title_duration = std::stoi(value);
|
||||||
else if (var == "scoreboard.hard_color")
|
}
|
||||||
{
|
|
||||||
param.scoreboard.hard_color = Color::fromHex(value);
|
else if (var == "title.arcade_edition_position") {
|
||||||
}
|
param.title.arcade_edition_position = std::stoi(value);
|
||||||
|
}
|
||||||
else if (var == "scoreboard.text_autocolor")
|
|
||||||
{
|
else if (var == "title.title_c_c_position") {
|
||||||
param.scoreboard.text_autocolor = stringToBool(value);
|
param.title.title_c_c_position = std::stoi(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (var == "scoreboard.text_color1")
|
else if (var == "title.bg_color") {
|
||||||
{
|
param.title.bg_color = Color::fromHex(value);
|
||||||
param.scoreboard.text_color1 = Color::fromHex(value);
|
}
|
||||||
}
|
|
||||||
|
// BACKGROUND
|
||||||
else if (var == "scoreboard.text_color2")
|
else if (var == "background.attenuate_color") {
|
||||||
{
|
param.background.attenuate_color = Color::fromHex(value);
|
||||||
param.scoreboard.text_color2 = Color::fromHex(value);
|
}
|
||||||
}
|
|
||||||
|
// BALLOON
|
||||||
else if (var == "scoreboard.skip_countdown_value")
|
else if (var == "balloon.settings[0].vel") {
|
||||||
{
|
param.balloon.settings.at(0).vel = std::stof(value);
|
||||||
param.scoreboard.skip_countdown_value = std::stoi(value);
|
}
|
||||||
}
|
|
||||||
|
else if (var == "balloon.settings[0].grav") {
|
||||||
// TITLE
|
param.balloon.settings.at(0).grav = std::stof(value);
|
||||||
else if (var == "title.press_start_position")
|
}
|
||||||
{
|
|
||||||
param.title.press_start_position = std::stoi(value);
|
else if (var == "balloon.settings[1].vel") {
|
||||||
}
|
param.balloon.settings.at(1).vel = std::stof(value);
|
||||||
|
}
|
||||||
else if (var == "title.title_duration")
|
|
||||||
{
|
else if (var == "balloon.settings[1].grav") {
|
||||||
param.title.title_duration = std::stoi(value);
|
param.balloon.settings.at(1).grav = std::stof(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (var == "title.arcade_edition_position")
|
else if (var == "balloon.settings[2].vel") {
|
||||||
{
|
param.balloon.settings.at(2).vel = std::stof(value);
|
||||||
param.title.arcade_edition_position = std::stoi(value);
|
}
|
||||||
}
|
|
||||||
|
else if (var == "balloon.settings[2].grav") {
|
||||||
else if (var == "title.title_c_c_position")
|
param.balloon.settings.at(2).grav = std::stof(value);
|
||||||
{
|
}
|
||||||
param.title.title_c_c_position = std::stoi(value);
|
|
||||||
}
|
else if (var == "balloon.settings[3].vel") {
|
||||||
|
param.balloon.settings.at(3).vel = std::stof(value);
|
||||||
else if (var == "title.bg_color")
|
}
|
||||||
{
|
|
||||||
param.title.bg_color = Color::fromHex(value);
|
else if (var == "balloon.settings[3].grav") {
|
||||||
}
|
param.balloon.settings.at(3).grav = std::stof(value);
|
||||||
|
}
|
||||||
// BACKGROUND
|
|
||||||
else if (var == "background.attenuate_color")
|
else if (var == "balloon.color[0]") {
|
||||||
{
|
param.balloon.color.at(0) = value;
|
||||||
param.background.attenuate_color = Color::fromHex(value);
|
}
|
||||||
}
|
|
||||||
|
else if (var == "balloon.color[1]") {
|
||||||
// BALLOON
|
param.balloon.color.at(1) = value;
|
||||||
else if (var == "balloon.settings[0].vel")
|
}
|
||||||
{
|
|
||||||
param.balloon.settings.at(0).vel = std::stof(value);
|
else if (var == "balloon.color[2]") {
|
||||||
}
|
param.balloon.color.at(2) = value;
|
||||||
|
}
|
||||||
else if (var == "balloon.settings[0].grav")
|
|
||||||
{
|
else if (var == "balloon.color[3]") {
|
||||||
param.balloon.settings.at(0).grav = std::stof(value);
|
param.balloon.color.at(3) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (var == "balloon.settings[1].vel")
|
else if (var == "balloon.bouncing_sound") {
|
||||||
{
|
param.balloon.bouncing_sound = stringToBool(value);
|
||||||
param.balloon.settings.at(1).vel = std::stof(value);
|
}
|
||||||
}
|
|
||||||
|
// NOTIFICACIONES
|
||||||
else if (var == "balloon.settings[1].grav")
|
else if (var == "notification.pos_h") {
|
||||||
{
|
if (value == "LEFT") {
|
||||||
param.balloon.settings.at(1).grav = std::stof(value);
|
param.notification.pos_h = NotifyPosition::LEFT;
|
||||||
}
|
} else if (value == "MIDDLE") {
|
||||||
|
param.notification.pos_h = NotifyPosition::MIDDLE;
|
||||||
else if (var == "balloon.settings[2].vel")
|
} else {
|
||||||
{
|
param.notification.pos_h = NotifyPosition::RIGHT;
|
||||||
param.balloon.settings.at(2).vel = std::stof(value);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (var == "balloon.settings[2].grav")
|
else if (var == "notification.pos_v") {
|
||||||
{
|
param.notification.pos_v = value == "TOP" ? NotifyPosition::TOP : NotifyPosition::BOTTOM;
|
||||||
param.balloon.settings.at(2).grav = std::stof(value);
|
}
|
||||||
}
|
|
||||||
|
else if (var == "notification.sound") {
|
||||||
else if (var == "balloon.settings[3].vel")
|
param.notification.sound = stringToBool(value);
|
||||||
{
|
}
|
||||||
param.balloon.settings.at(3).vel = std::stof(value);
|
|
||||||
}
|
else if (var == "notification.color") {
|
||||||
|
param.notification.color = Color::fromHex(value);
|
||||||
else if (var == "balloon.settings[3].grav")
|
}
|
||||||
{
|
|
||||||
param.balloon.settings.at(3).grav = std::stof(value);
|
// SERVICE MENU
|
||||||
}
|
else if (var == "service_menu.title_color") {
|
||||||
|
param.service_menu.title_color = Color::fromHex(value);
|
||||||
else if (var == "balloon.color[0]")
|
}
|
||||||
{
|
|
||||||
param.balloon.color.at(0) = value;
|
else if (var == "service_menu.text_color") {
|
||||||
}
|
param.service_menu.text_color = Color::fromHex(value);
|
||||||
|
}
|
||||||
else if (var == "balloon.color[1]")
|
|
||||||
{
|
else if (var == "service_menu.selected_color") {
|
||||||
param.balloon.color.at(1) = value;
|
param.service_menu.selected_color = Color::fromHex(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (var == "balloon.color[2]")
|
else if (var == "service_menu.bg_color") {
|
||||||
{
|
param.service_menu.bg_color = Color::fromHex(value);
|
||||||
param.balloon.color.at(2) = value;
|
}
|
||||||
}
|
|
||||||
|
else if (var == "service_menu.drop_shadow") {
|
||||||
else if (var == "balloon.color[3]")
|
param.service_menu.drop_shadow = stringToBool(value);
|
||||||
{
|
}
|
||||||
param.balloon.color.at(3) = value;
|
|
||||||
}
|
// INTRO
|
||||||
|
else if (var == "intro.bg_color") {
|
||||||
else if (var == "balloon.bouncing_sound")
|
param.intro.bg_color = Color::fromHex(value);
|
||||||
{
|
}
|
||||||
param.balloon.bouncing_sound = stringToBool(value);
|
|
||||||
}
|
else if (var == "intro.card_color") {
|
||||||
|
param.intro.card_color = Color::fromHex(value);
|
||||||
// NOTIFICACIONES
|
}
|
||||||
else if (var == "notification.pos_h")
|
|
||||||
{
|
else if (var == "intro.shadow_color") {
|
||||||
if (value == "LEFT")
|
param.intro.shadow_color = Color::fromHex(value);
|
||||||
{
|
}
|
||||||
param.notification.pos_h = NotifyPosition::LEFT;
|
|
||||||
}
|
else if (var == "intro.text_distance_from_bottom") {
|
||||||
else if (value == "MIDDLE")
|
param.intro.text_distance_from_bottom = std::stoi(value);
|
||||||
{
|
}
|
||||||
param.notification.pos_h = NotifyPosition::MIDDLE;
|
|
||||||
}
|
// DEBUG
|
||||||
else
|
else if (var == "debug.color") {
|
||||||
{
|
param.debug.color = Color::fromHex(value);
|
||||||
param.notification.pos_h = NotifyPosition::RIGHT;
|
}
|
||||||
}
|
|
||||||
}
|
// RESOURCE
|
||||||
|
else if (var == "resource.color") {
|
||||||
else if (var == "notification.pos_v")
|
param.resource.color = Color::fromHex(value);
|
||||||
{
|
}
|
||||||
param.notification.pos_v = value == "TOP" ? NotifyPosition::TOP : NotifyPosition::BOTTOM;
|
|
||||||
}
|
// RESTO
|
||||||
|
else {
|
||||||
else if (var == "notification.sound")
|
success = false;
|
||||||
{
|
}
|
||||||
param.notification.sound = stringToBool(value);
|
|
||||||
}
|
return success;
|
||||||
|
|
||||||
else if (var == "notification.color")
|
|
||||||
{
|
|
||||||
param.notification.color = Color::fromHex(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// SERVICE MENU
|
|
||||||
else if (var == "service_menu.title_color")
|
|
||||||
{
|
|
||||||
param.service_menu.title_color = Color::fromHex(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (var == "service_menu.text_color")
|
|
||||||
{
|
|
||||||
param.service_menu.text_color = Color::fromHex(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (var == "service_menu.selected_color")
|
|
||||||
{
|
|
||||||
param.service_menu.selected_color = Color::fromHex(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (var == "service_menu.bg_color")
|
|
||||||
{
|
|
||||||
param.service_menu.bg_color = Color::fromHex(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (var == "service_menu.drop_shadow")
|
|
||||||
{
|
|
||||||
param.service_menu.drop_shadow = stringToBool(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// INTRO
|
|
||||||
else if (var == "intro.bg_color")
|
|
||||||
{
|
|
||||||
param.intro.bg_color = Color::fromHex(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (var == "intro.card_color")
|
|
||||||
{
|
|
||||||
param.intro.card_color = Color::fromHex(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (var == "intro.shadow_color")
|
|
||||||
{
|
|
||||||
param.intro.shadow_color = Color::fromHex(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (var == "intro.text_distance_from_bottom")
|
|
||||||
{
|
|
||||||
param.intro.text_distance_from_bottom = std::stoi(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
else if (var == "debug.color")
|
|
||||||
{
|
|
||||||
param.debug.color = Color::fromHex(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// RESOURCE
|
|
||||||
else if (var == "resource.color")
|
|
||||||
{
|
|
||||||
param.resource.color = Color::fromHex(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// RESTO
|
|
||||||
else
|
|
||||||
{
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calcula variables a partir de otras variables
|
// Calcula variables a partir de otras variables
|
||||||
void precalculateZones()
|
void precalculateZones() {
|
||||||
{
|
// playArea
|
||||||
// playArea
|
param.game.play_area.center_x = param.game.play_area.rect.w / 2;
|
||||||
param.game.play_area.center_x = param.game.play_area.rect.w / 2;
|
param.game.play_area.first_quarter_x = param.game.play_area.rect.w / 4;
|
||||||
param.game.play_area.first_quarter_x = param.game.play_area.rect.w / 4;
|
param.game.play_area.third_quarter_x = param.game.play_area.rect.w / 4 * 3;
|
||||||
param.game.play_area.third_quarter_x = param.game.play_area.rect.w / 4 * 3;
|
param.game.play_area.center_y = param.game.play_area.rect.h / 2;
|
||||||
param.game.play_area.center_y = param.game.play_area.rect.h / 2;
|
param.game.play_area.first_quarter_y = param.game.play_area.rect.h / 4;
|
||||||
param.game.play_area.first_quarter_y = param.game.play_area.rect.h / 4;
|
param.game.play_area.third_quarter_y = param.game.play_area.rect.h / 4 * 3;
|
||||||
param.game.play_area.third_quarter_y = param.game.play_area.rect.h / 4 * 3;
|
|
||||||
|
|
||||||
// gameArea
|
// gameArea
|
||||||
param.game.game_area.rect = {0, 0, param.game.width, param.game.height};
|
param.game.game_area.rect = {0, 0, param.game.width, param.game.height};
|
||||||
param.game.game_area.center_x = param.game.game_area.rect.w / 2;
|
param.game.game_area.center_x = param.game.game_area.rect.w / 2;
|
||||||
param.game.game_area.first_quarter_x = param.game.game_area.rect.w / 4;
|
param.game.game_area.first_quarter_x = param.game.game_area.rect.w / 4;
|
||||||
param.game.game_area.third_quarter_x = param.game.game_area.rect.w / 4 * 3;
|
param.game.game_area.third_quarter_x = param.game.game_area.rect.w / 4 * 3;
|
||||||
param.game.game_area.center_y = param.game.game_area.rect.h / 2;
|
param.game.game_area.center_y = param.game.game_area.rect.h / 2;
|
||||||
param.game.game_area.first_quarter_y = param.game.game_area.rect.h / 4;
|
param.game.game_area.first_quarter_y = param.game.game_area.rect.h / 4;
|
||||||
param.game.game_area.third_quarter_y = param.game.game_area.rect.h / 4 * 3;
|
param.game.game_area.third_quarter_y = param.game.game_area.rect.h / 4 * 3;
|
||||||
}
|
}
|
||||||
+71
-84
@@ -1,61 +1,56 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para Uint32, SDL_FRect
|
#include <SDL3/SDL.h> // Para Uint32, SDL_FRect
|
||||||
#include <array> // Para array
|
|
||||||
#include <string> // Para basic_string, string
|
|
||||||
|
|
||||||
#include "utils.h" // Para Color, NotifyPosition (ptr only), Zone
|
#include <array> // Para array
|
||||||
|
#include <string> // Para basic_string, string
|
||||||
|
|
||||||
|
#include "utils.h" // Para Color, NotifyPosition (ptr only), Zone
|
||||||
|
|
||||||
// --- Parámetros del juego ---
|
// --- Parámetros del juego ---
|
||||||
struct ParamGame
|
struct ParamGame {
|
||||||
{
|
float width; // Ancho de la resolución nativa del juego
|
||||||
float width; // Ancho de la resolución nativa del juego
|
float height; // Alto de la resolución nativa del juego
|
||||||
float height; // Alto de la resolución nativa del juego
|
float item_size; // Tamaño de los ítems del juego
|
||||||
float item_size; // Tamaño de los ítems del juego
|
Zone play_area; // Rectángulo con la posición de la zona de juego
|
||||||
Zone play_area; // Rectángulo con la posición de la zona de juego
|
Zone game_area; // Rectángulo con las dimensiones del juego
|
||||||
Zone game_area; // Rectángulo con las dimensiones del juego
|
int name_entry_idle_time; // Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
|
||||||
int name_entry_idle_time; // Segundos para introducir el nombre al finalizar la partida si no se pulsa nada
|
int name_entry_total_time; // Segundos totales para introducir el nombre al finalizar la partida
|
||||||
int name_entry_total_time; // Segundos totales para introducir el nombre al finalizar la partida
|
Uint32 speed; // Velocidad a la que transcurre el juego
|
||||||
Uint32 speed; // Velocidad a la que transcurre el juego
|
bool hit_stop; // Indica si debe haber un paro cuando el jugador es golpeado por un globo
|
||||||
bool hit_stop; // Indica si debe haber un paro cuando el jugador es golpeado por un globo
|
Uint32 hit_stop_ms; // Cantidad de milisegundos que dura el hit_stop
|
||||||
Uint32 hit_stop_ms; // Cantidad de milisegundos que dura el hit_stop
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros del fade ---
|
// --- Parámetros del fade ---
|
||||||
struct ParamFade
|
struct ParamFade {
|
||||||
{
|
Color color; // Color del fade
|
||||||
Color color; // Color del fade
|
float num_squares_width; // Cantidad total de cuadraditos en horizontal para el FadeType::RANDOM_SQUARE
|
||||||
float num_squares_width; // Cantidad total de cuadraditos en horizontal para el FadeType::RANDOM_SQUARE
|
float num_squares_height; // Cantidad total de cuadraditos en vertical para el FadeType::RANDOM_SQUARE
|
||||||
float num_squares_height; // Cantidad total de cuadraditos en vertical para el FadeType::RANDOM_SQUARE
|
int random_squares_delay; // Duración entre cada pintado de cuadrados
|
||||||
int random_squares_delay; // Duración entre cada pintado de cuadrados
|
int random_squares_mult; // Cantidad de cuadrados que se pintarán cada vez
|
||||||
int random_squares_mult; // Cantidad de cuadrados que se pintarán cada vez
|
int post_duration; // Duración final del fade
|
||||||
int post_duration; // Duración final del fade
|
float venetian_size; // Altura de los rectángulos para FadeType::VENETIAN
|
||||||
float venetian_size; // Altura de los rectángulos para FadeType::VENETIAN
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros de la pantalla de título ---
|
// --- Parámetros de la pantalla de título ---
|
||||||
struct ParamTitle
|
struct ParamTitle {
|
||||||
{
|
int press_start_position; // Posición del texto para empezar a jugar
|
||||||
int press_start_position; // Posición del texto para empezar a jugar
|
int title_duration; // Tiempo de inactividad del título
|
||||||
int title_duration; // Tiempo de inactividad del título
|
int arcade_edition_position; // Posición del bitmap "Arcade Edition"
|
||||||
int arcade_edition_position; // Posición del bitmap "Arcade Edition"
|
int title_c_c_position; // Posición del bitmap "Coffee Crisis"
|
||||||
int title_c_c_position; // Posición del bitmap "Coffee Crisis"
|
Color bg_color; // Color para los tiles de fondo
|
||||||
Color bg_color; // Color para los tiles de fondo
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros del fondo ---
|
// --- Parámetros del fondo ---
|
||||||
struct ParamBackground
|
struct ParamBackground {
|
||||||
{
|
Color attenuate_color; // Color para atenuar el fondo
|
||||||
Color attenuate_color; // Color para atenuar el fondo
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros de los globos ---
|
// --- Parámetros de los globos ---
|
||||||
struct ParamBalloon
|
struct ParamBalloon {
|
||||||
{
|
struct Settings {
|
||||||
struct Settings
|
float grav; // Aceleración en el eje Y. Modifica la velocidad
|
||||||
{
|
float vel; // Velocidad inicial al rebotar contra el suelo
|
||||||
float grav; // Aceleración en el eje Y. Modifica la velocidad
|
|
||||||
float vel; // Velocidad inicial al rebotar contra el suelo
|
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
explicit Settings(float grav_val = 0.0f, float vel_val = 0.0f)
|
explicit Settings(float grav_val = 0.0f, float vel_val = 0.0f)
|
||||||
@@ -64,36 +59,33 @@ struct ParamBalloon
|
|||||||
|
|
||||||
std::array<Settings, 4> settings;
|
std::array<Settings, 4> settings;
|
||||||
std::array<std::string, 4> color;
|
std::array<std::string, 4> color;
|
||||||
bool bouncing_sound; // Indica si los globos hacer sonido al rebotar
|
bool bouncing_sound; // Indica si los globos hacer sonido al rebotar
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros de las notificaciones ---
|
// --- Parámetros de las notificaciones ---
|
||||||
struct ParamNotification
|
struct ParamNotification {
|
||||||
{
|
NotifyPosition pos_h; // Ubicación horizontal de las notificaciones en pantalla
|
||||||
NotifyPosition pos_h; // Ubicación horizontal de las notificaciones en pantalla
|
NotifyPosition pos_v; // Ubicación vertical de las notificaciones en pantalla
|
||||||
NotifyPosition pos_v; // Ubicación vertical de las notificaciones en pantalla
|
bool sound; // Indica si las notificaciones suenan
|
||||||
bool sound; // Indica si las notificaciones suenan
|
Color color; // Color de las notificaciones
|
||||||
Color color; // Color de las notificaciones
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros del marcador ---
|
// --- Parámetros del marcador ---
|
||||||
struct ParamScoreboard
|
struct ParamScoreboard {
|
||||||
{
|
SDL_FRect rect; // Posición y tamaño del marcador
|
||||||
SDL_FRect rect; // Posición y tamaño del marcador
|
bool separator_autocolor; // El separado establece su color de forma automatica
|
||||||
bool separator_autocolor; // El separado establece su color de forma automatica
|
Color separator_color; // Color del separador si se pone de forma manual
|
||||||
Color separator_color; // Color del separador si se pone de forma manual
|
Color easy_color; // Color del marcador segun la dificultad
|
||||||
Color easy_color; // Color del marcador segun la dificultad
|
Color normal_color; // Color del marcador segun la dificultad
|
||||||
Color normal_color; // Color del marcador segun la dificultad
|
Color hard_color; // Color del marcador segun la dificultad
|
||||||
Color hard_color; // Color del marcador segun la dificultad
|
bool text_autocolor; // El texto establece su color de forma automatica
|
||||||
bool text_autocolor; // El texto establece su color de forma automatica
|
Color text_color1; // Color del texto
|
||||||
Color text_color1; // Color del texto
|
Color text_color2; // Color del texto
|
||||||
Color text_color2; // Color del texto
|
int skip_countdown_value; // Valor a partir del cual se puede saltar la cuenta atras
|
||||||
int skip_countdown_value; // Valor a partir del cual se puede saltar la cuenta atras
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros del menú de servicio ---
|
// --- Parámetros del menú de servicio ---
|
||||||
struct ParamServiceMenu
|
struct ParamServiceMenu {
|
||||||
{
|
|
||||||
Color title_color;
|
Color title_color;
|
||||||
Color text_color;
|
Color text_color;
|
||||||
Color selected_color;
|
Color selected_color;
|
||||||
@@ -102,8 +94,7 @@ struct ParamServiceMenu
|
|||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros de la intro ---
|
// --- Parámetros de la intro ---
|
||||||
struct ParamIntro
|
struct ParamIntro {
|
||||||
{
|
|
||||||
Color bg_color;
|
Color bg_color;
|
||||||
Color card_color;
|
Color card_color;
|
||||||
Color shadow_color;
|
Color shadow_color;
|
||||||
@@ -111,40 +102,36 @@ struct ParamIntro
|
|||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros para Debug ---
|
// --- Parámetros para Debug ---
|
||||||
struct ParamDebug
|
struct ParamDebug {
|
||||||
{
|
|
||||||
Color color;
|
Color color;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Parámetros para Resource ---
|
// --- Parámetros para Resource ---
|
||||||
struct ParamResource
|
struct ParamResource {
|
||||||
{
|
|
||||||
Color color;
|
Color color;
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estructura principal para almacenar todos los parámetros del juego ---
|
// --- Estructura principal para almacenar todos los parámetros del juego ---
|
||||||
struct Param
|
struct Param {
|
||||||
{
|
ParamGame game; // Parámetros del juego
|
||||||
ParamGame game; // Parámetros del juego
|
ParamFade fade; // Parámetros del fade
|
||||||
ParamFade fade; // Parámetros del fade
|
ParamScoreboard scoreboard; // Rectángulo del marcador
|
||||||
ParamScoreboard scoreboard; // Rectángulo del marcador
|
ParamTitle title; // Parámetros de la pantalla de título
|
||||||
ParamTitle title; // Parámetros de la pantalla de título
|
ParamBackground background; // Parámetros del fondo
|
||||||
ParamBackground background; // Parámetros del fondo
|
ParamBalloon balloon; // Parámetros de los globos
|
||||||
ParamBalloon balloon; // Parámetros de los globos
|
ParamNotification notification; // Parámetros de las notificaciones
|
||||||
ParamNotification notification; // Parámetros de las notificaciones
|
ParamServiceMenu service_menu; // Parámetros del menú de servicio
|
||||||
ParamServiceMenu service_menu; // Parámetros del menú de servicio
|
ParamIntro intro; // Parámetros de la intro
|
||||||
ParamIntro intro; // Parámetros de la intro
|
ParamDebug debug; // Parámetros para Debug
|
||||||
ParamDebug debug; // Parámetros para Debug
|
ParamResource resource; // Parámetros para Resource
|
||||||
ParamResource resource; // Parámetros para Resource
|
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Param()
|
Param()
|
||||||
: game(), fade(), scoreboard(), title(), background(), balloon(),
|
: game(), fade(), scoreboard(), title(), background(), balloon(), notification(), service_menu(), intro(), debug(), resource() {}
|
||||||
notification(), service_menu(), intro(), debug(), resource() {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Variable global con los parámetros del juego ---
|
// --- Variable global con los parámetros del juego ---
|
||||||
extern Param param;
|
extern Param param;
|
||||||
|
|
||||||
// --- Funciones globales ---
|
// --- Funciones globales ---
|
||||||
void loadParamsFromFile(const std::string &file_path); // Establece valores para los parámetros a partir de un fichero de texto
|
void loadParamsFromFile(const std::string &file_path); // Establece valores para los parámetros a partir de un fichero de texto
|
||||||
+100
-126
@@ -1,169 +1,143 @@
|
|||||||
// IWYU pragma: no_include <bits/std_abs.h>
|
// IWYU pragma: no_include <bits/std_abs.h>
|
||||||
#include "path_sprite.h"
|
#include "path_sprite.h"
|
||||||
|
|
||||||
#include <cmath> // Para abs
|
#include <cmath> // Para abs
|
||||||
#include <functional> // Para function
|
#include <functional> // Para function
|
||||||
#include <utility> // Para move
|
#include <utility> // Para move
|
||||||
|
|
||||||
// Devuelve un vector con los puntos que conforman la ruta
|
// Devuelve un vector con los puntos que conforman la ruta
|
||||||
std::vector<SDL_FPoint> createPath(float start, float end, PathType type, float fixed_pos, int steps, const std::function<double(double)> &easingFunction)
|
std::vector<SDL_FPoint> createPath(float start, float end, PathType type, float fixed_pos, int steps, const std::function<double(double)> &easingFunction) {
|
||||||
{
|
std::vector<SDL_FPoint> v;
|
||||||
std::vector<SDL_FPoint> v;
|
v.reserve(steps);
|
||||||
v.reserve(steps);
|
|
||||||
|
|
||||||
for (int i = 0; i < steps; ++i)
|
for (int i = 0; i < steps; ++i) {
|
||||||
{
|
double t = static_cast<double>(i) / (steps - 1);
|
||||||
double t = static_cast<double>(i) / (steps - 1);
|
double value = start + (end - start) * easingFunction(t);
|
||||||
double value = start + (end - start) * easingFunction(t);
|
|
||||||
|
|
||||||
if ((start > 0 && end < 0) || (start < 0 && end > 0))
|
if ((start > 0 && end < 0) || (start < 0 && end > 0)) {
|
||||||
{
|
value = start + (end > 0 ? 1 : -1) * std::abs(end - start) * easingFunction(t);
|
||||||
value = start + (end > 0 ? 1 : -1) * std::abs(end - start) * easingFunction(t);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
switch (type)
|
switch (type) {
|
||||||
{
|
case PathType::HORIZONTAL:
|
||||||
case PathType::HORIZONTAL:
|
v.emplace_back(SDL_FPoint{static_cast<float>(value), fixed_pos});
|
||||||
v.emplace_back(SDL_FPoint{static_cast<float>(value), fixed_pos});
|
break;
|
||||||
break;
|
case PathType::VERTICAL:
|
||||||
case PathType::VERTICAL:
|
v.emplace_back(SDL_FPoint{fixed_pos, static_cast<float>(value)});
|
||||||
v.emplace_back(SDL_FPoint{fixed_pos, static_cast<float>(value)});
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza la posición y comprueba si ha llegado a su destino
|
// Actualiza la posición y comprueba si ha llegado a su destino
|
||||||
void PathSprite::update()
|
void PathSprite::update() {
|
||||||
{
|
if (enabled_ && !has_finished_) {
|
||||||
if (enabled_ && !has_finished_)
|
moveThroughCurrentPath();
|
||||||
{
|
goToNextPathOrDie();
|
||||||
moveThroughCurrentPath();
|
}
|
||||||
goToNextPathOrDie();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Muestra el sprite por pantalla
|
// Muestra el sprite por pantalla
|
||||||
void PathSprite::render()
|
void PathSprite::render() {
|
||||||
{
|
if (enabled_) {
|
||||||
if (enabled_)
|
Sprite::render();
|
||||||
{
|
}
|
||||||
Sprite::render();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Añade un recorrido
|
// Añade un recorrido
|
||||||
void PathSprite::addPath(Path path, bool centered)
|
void PathSprite::addPath(Path path, bool centered) {
|
||||||
{
|
PathCentered path_centered = PathCentered::NONE;
|
||||||
PathCentered path_centered = PathCentered::NONE;
|
if (centered)
|
||||||
if (centered)
|
path_centered = (path.spots.back().x == path.spots.front().x) ? PathCentered::ON_X : PathCentered::ON_Y;
|
||||||
path_centered = (path.spots.back().x == path.spots.front().x) ? PathCentered::ON_X : PathCentered::ON_Y;
|
|
||||||
|
|
||||||
switch (path_centered)
|
switch (path_centered) {
|
||||||
{
|
case PathCentered::ON_X: {
|
||||||
case PathCentered::ON_X:
|
const int x = path.spots.back().x - pos_.w / 2;
|
||||||
{
|
for (auto &spot : path.spots)
|
||||||
const int x = path.spots.back().x - pos_.w / 2;
|
spot.x = x;
|
||||||
for (auto &spot : path.spots)
|
paths_.emplace_back(path);
|
||||||
spot.x = x;
|
break;
|
||||||
paths_.emplace_back(path);
|
}
|
||||||
break;
|
case PathCentered::ON_Y: {
|
||||||
}
|
const int y = path.spots.back().y - pos_.h / 2;
|
||||||
case PathCentered::ON_Y:
|
for (auto &spot : path.spots)
|
||||||
{
|
spot.y = y;
|
||||||
const int y = path.spots.back().y - pos_.h / 2;
|
paths_.emplace_back(path);
|
||||||
for (auto &spot : path.spots)
|
break;
|
||||||
spot.y = y;
|
}
|
||||||
paths_.emplace_back(path);
|
default:
|
||||||
break;
|
paths_.emplace_back(path);
|
||||||
}
|
break;
|
||||||
default:
|
}
|
||||||
paths_.emplace_back(path);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Añade un recorrido
|
// Añade un recorrido
|
||||||
void PathSprite::addPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function<double(double)> &easingFunction, int waiting_counter)
|
void PathSprite::addPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function<double(double)> &easingFunction, int waiting_counter) {
|
||||||
{
|
paths_.emplace_back(createPath(start, end, type, fixed_pos, steps, easingFunction), waiting_counter);
|
||||||
paths_.emplace_back(createPath(start, end, type, fixed_pos, steps, easingFunction), waiting_counter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Añade un recorrido
|
// Añade un recorrido
|
||||||
void PathSprite::addPath(std::vector<SDL_FPoint> spots, int waiting_counter)
|
void PathSprite::addPath(std::vector<SDL_FPoint> spots, int waiting_counter) {
|
||||||
{
|
paths_.emplace_back(std::move(spots), waiting_counter);
|
||||||
paths_.emplace_back(std::move(spots), waiting_counter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Habilita el objeto
|
// Habilita el objeto
|
||||||
void PathSprite::enable()
|
void PathSprite::enable() {
|
||||||
{
|
if (paths_.size() == 0 || enabled_) {
|
||||||
if (paths_.size() == 0 || enabled_)
|
return;
|
||||||
{
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
enabled_ = true;
|
enabled_ = true;
|
||||||
|
|
||||||
// Establece la posición
|
// Establece la posición
|
||||||
auto &path = paths_.at(current_path_);
|
auto &path = paths_.at(current_path_);
|
||||||
const auto &P = path.spots.at(path.counter);
|
const auto &P = path.spots.at(path.counter);
|
||||||
setPosition(P);
|
setPosition(P);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Coloca el sprite en los diferentes puntos del recorrido
|
// Coloca el sprite en los diferentes puntos del recorrido
|
||||||
void PathSprite::moveThroughCurrentPath()
|
void PathSprite::moveThroughCurrentPath() {
|
||||||
{
|
auto &path = paths_.at(current_path_);
|
||||||
auto &path = paths_.at(current_path_);
|
|
||||||
|
|
||||||
// Establece la posición
|
// Establece la posición
|
||||||
const auto &p = path.spots.at(path.counter);
|
const auto &p = path.spots.at(path.counter);
|
||||||
setPosition(p);
|
setPosition(p);
|
||||||
|
|
||||||
// Comprobar si ha terminado el recorrido
|
// Comprobar si ha terminado el recorrido
|
||||||
if (!path.on_destination)
|
if (!path.on_destination) {
|
||||||
{
|
++path.counter;
|
||||||
++path.counter;
|
if (path.counter >= static_cast<int>(path.spots.size())) {
|
||||||
if (path.counter >= static_cast<int>(path.spots.size()))
|
path.on_destination = true;
|
||||||
{
|
path.counter = static_cast<int>(path.spots.size()) - 1;
|
||||||
path.on_destination = true;
|
}
|
||||||
path.counter = static_cast<int>(path.spots.size()) - 1;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprobar si ha terminado la espera
|
// Comprobar si ha terminado la espera
|
||||||
if (path.on_destination)
|
if (path.on_destination) {
|
||||||
{
|
if (path.waiting_counter == 0) {
|
||||||
if (path.waiting_counter == 0)
|
path.finished = true;
|
||||||
{
|
} else {
|
||||||
path.finished = true;
|
--path.waiting_counter;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
--path.waiting_counter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cambia de recorrido o finaliza
|
// Cambia de recorrido o finaliza
|
||||||
void PathSprite::goToNextPathOrDie()
|
void PathSprite::goToNextPathOrDie() {
|
||||||
{
|
// Comprueba si ha terminado el recorrdo actual
|
||||||
// Comprueba si ha terminado el recorrdo actual
|
if (paths_.at(current_path_).finished) {
|
||||||
if (paths_.at(current_path_).finished)
|
++current_path_;
|
||||||
{
|
}
|
||||||
++current_path_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si quedan mas recorridos
|
// Comprueba si quedan mas recorridos
|
||||||
if (current_path_ >= static_cast<int>(paths_.size()))
|
if (current_path_ >= static_cast<int>(paths_.size())) {
|
||||||
{
|
has_finished_ = true;
|
||||||
has_finished_ = true;
|
current_path_ = 0;
|
||||||
current_path_ = 0;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indica si ha terminado todos los recorridos
|
// Indica si ha terminado todos los recorridos
|
||||||
|
|||||||
+49
-52
@@ -1,79 +1,76 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FPoint
|
#include <SDL3/SDL.h> // Para SDL_FPoint
|
||||||
#include <functional> // Para std::function
|
|
||||||
#include <memory> // Para shared_ptr
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "sprite.h" // Para Sprite
|
#include <functional> // Para std::function
|
||||||
|
#include <memory> // Para shared_ptr
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
|
#include "sprite.h" // Para Sprite
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// --- Tipos de recorrido ---
|
// --- Tipos de recorrido ---
|
||||||
enum class PathType
|
enum class PathType {
|
||||||
{
|
VERTICAL,
|
||||||
VERTICAL,
|
HORIZONTAL,
|
||||||
HORIZONTAL,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Centrado del recorrido ---
|
// --- Centrado del recorrido ---
|
||||||
enum class PathCentered
|
enum class PathCentered {
|
||||||
{
|
ON_X,
|
||||||
ON_X,
|
ON_Y,
|
||||||
ON_Y,
|
NONE,
|
||||||
NONE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estructura Path: define un recorrido para el sprite ---
|
// --- Estructura Path: define un recorrido para el sprite ---
|
||||||
struct Path
|
struct Path {
|
||||||
{
|
std::vector<SDL_FPoint> spots; // Puntos por los que se desplazará el sprite
|
||||||
std::vector<SDL_FPoint> spots; // Puntos por los que se desplazará el sprite
|
int waiting_counter; // Tiempo de espera una vez en el destino
|
||||||
int waiting_counter; // Tiempo de espera una vez en el destino
|
bool on_destination = false; // Indica si ha llegado al destino
|
||||||
bool on_destination = false; // Indica si ha llegado al destino
|
bool finished = false; // Indica si ha terminado de esperarse
|
||||||
bool finished = false; // Indica si ha terminado de esperarse
|
int counter = 0; // Contador interno
|
||||||
int counter = 0; // Contador interno
|
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Path(const std::vector<SDL_FPoint> &spots_init, int waiting_counter_init)
|
Path(const std::vector<SDL_FPoint> &spots_init, int waiting_counter_init)
|
||||||
: spots(spots_init), waiting_counter(waiting_counter_init) {}
|
: spots(spots_init), waiting_counter(waiting_counter_init) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Devuelve un vector con los puntos que conforman la ruta
|
// Devuelve un vector con los puntos que conforman la ruta
|
||||||
std::vector<SDL_FPoint> createPath(float start, float end, PathType type, float fixed_pos, int steps, const std::function<double(double)> &easingFunction);
|
std::vector<SDL_FPoint> createPath(float start, float end, PathType type, float fixed_pos, int steps, const std::function<double(double)> &easingFunction);
|
||||||
|
|
||||||
// --- Clase PathSprite: Sprite que sigue uno o varios recorridos ---
|
// --- Clase PathSprite: Sprite que sigue uno o varios recorridos ---
|
||||||
class PathSprite : public Sprite
|
class PathSprite : public Sprite {
|
||||||
{
|
public:
|
||||||
public:
|
// --- Constructor y destructor ---
|
||||||
// --- Constructor y destructor ---
|
explicit PathSprite(std::shared_ptr<Texture> texture)
|
||||||
explicit PathSprite(std::shared_ptr<Texture> texture)
|
: Sprite(texture) {}
|
||||||
: Sprite(texture) {}
|
~PathSprite() override = default;
|
||||||
~PathSprite() override = default;
|
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
void update(); // Actualiza la posición del sprite según el recorrido
|
void update(); // Actualiza la posición del sprite según el recorrido
|
||||||
void render() override; // Muestra el sprite por pantalla
|
void render() override; // Muestra el sprite por pantalla
|
||||||
|
|
||||||
// --- Gestión de recorridos ---
|
// --- Gestión de recorridos ---
|
||||||
void addPath(Path path, bool centered = false); // Añade un recorrido (Path)
|
void addPath(Path path, bool centered = false); // Añade un recorrido (Path)
|
||||||
void addPath(std::vector<SDL_FPoint> spots, int waiting_counter = 0); // Añade un recorrido a partir de puntos
|
void addPath(std::vector<SDL_FPoint> spots, int waiting_counter = 0); // Añade un recorrido a partir de puntos
|
||||||
void addPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function<double(double)> &easingFunction, int waiting_counter = 0); // Añade un recorrido generado
|
void addPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function<double(double)> &easingFunction, int waiting_counter = 0); // Añade un recorrido generado
|
||||||
|
|
||||||
// --- Estado y control ---
|
// --- Estado y control ---
|
||||||
void enable(); // Habilita el objeto
|
void enable(); // Habilita el objeto
|
||||||
bool hasFinished(); // Indica si ha terminado todos los recorridos
|
bool hasFinished(); // Indica si ha terminado todos los recorridos
|
||||||
|
|
||||||
// --- Getters ---
|
// --- Getters ---
|
||||||
int getCurrentPath() const { return current_path_; } // Devuelve el índice del recorrido actual
|
int getCurrentPath() const { return current_path_; } // Devuelve el índice del recorrido actual
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Variables internas ---
|
// --- Variables internas ---
|
||||||
bool enabled_ = false; // Indica si el objeto está habilitado
|
bool enabled_ = false; // Indica si el objeto está habilitado
|
||||||
bool has_finished_ = false; // Indica si el objeto ha finalizado el recorrido
|
bool has_finished_ = false; // Indica si el objeto ha finalizado el recorrido
|
||||||
int current_path_ = 0; // Recorrido que se está recorriendo actualmente
|
int current_path_ = 0; // Recorrido que se está recorriendo actualmente
|
||||||
std::vector<Path> paths_; // Caminos a recorrer por el sprite
|
std::vector<Path> paths_; // Caminos a recorrer por el sprite
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void moveThroughCurrentPath(); // Coloca el sprite en los diferentes puntos del recorrido
|
void moveThroughCurrentPath(); // Coloca el sprite en los diferentes puntos del recorrido
|
||||||
void goToNextPathOrDie(); // Cambia de recorrido o finaliza
|
void goToNextPathOrDie(); // Cambia de recorrido o finaliza
|
||||||
};
|
};
|
||||||
+672
-819
File diff suppressed because it is too large.
Load diff
+123
-124
@@ -1,108 +1,107 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para Uint32, SDL_FRect
|
#include <SDL3/SDL.h> // Para Uint32, SDL_FRect
|
||||||
#include <memory> // Para unique_ptr, shared_ptr
|
|
||||||
#include <string> // Para basic_string, string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include <memory> // Para unique_ptr, shared_ptr
|
||||||
#include "enter_name.h" // Para EnterName
|
#include <string> // Para basic_string, string
|
||||||
#include "manage_hiscore_table.h" // Para HiScoreEntry
|
#include <vector> // Para vector
|
||||||
#include "options.h" // Para SettingsOptions, settings
|
|
||||||
#include "utils.h" // Para Circle
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
|
#include "enter_name.h" // Para EnterName
|
||||||
|
#include "manage_hiscore_table.h" // Para HiScoreEntry
|
||||||
|
#include "options.h" // Para SettingsOptions, settings
|
||||||
|
#include "utils.h" // Para Circle
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
enum class InputAction : int;
|
enum class InputAction : int;
|
||||||
enum class ScoreboardMode;
|
enum class ScoreboardMode;
|
||||||
|
|
||||||
// --- Estados posibles del jugador ---
|
// --- Estados posibles del jugador ---
|
||||||
enum class PlayerState
|
enum class PlayerState {
|
||||||
{
|
|
||||||
// Estados de movimiento
|
// Estados de movimiento
|
||||||
WALKING_LEFT, // Caminando hacia la izquierda
|
WALKING_LEFT, // Caminando hacia la izquierda
|
||||||
WALKING_RIGHT, // Caminando hacia la derecha
|
WALKING_RIGHT, // Caminando hacia la derecha
|
||||||
WALKING_STOP, // Parado, sin moverse
|
WALKING_STOP, // Parado, sin moverse
|
||||||
|
|
||||||
// Estados de disparo
|
// Estados de disparo
|
||||||
FIRING_UP, // Disparando hacia arriba
|
FIRING_UP, // Disparando hacia arriba
|
||||||
FIRING_LEFT, // Disparando hacia la izquierda
|
FIRING_LEFT, // Disparando hacia la izquierda
|
||||||
FIRING_RIGHT, // Disparando hacia la derecha
|
FIRING_RIGHT, // Disparando hacia la derecha
|
||||||
FIRING_NONE, // No está disparando
|
FIRING_NONE, // No está disparando
|
||||||
|
|
||||||
// Estados de retroceso tras disparar
|
// Estados de retroceso tras disparar
|
||||||
RECOILING_UP, // Retroceso tras disparar hacia arriba
|
RECOILING_UP, // Retroceso tras disparar hacia arriba
|
||||||
RECOILING_LEFT, // Retroceso tras disparar hacia la izquierda
|
RECOILING_LEFT, // Retroceso tras disparar hacia la izquierda
|
||||||
RECOILING_RIGHT, // Retroceso tras disparar hacia la derecha
|
RECOILING_RIGHT, // Retroceso tras disparar hacia la derecha
|
||||||
|
|
||||||
// Estados de enfriamiento tras disparar
|
// Estados de enfriamiento tras disparar
|
||||||
COOLING_UP, // Enfriando tras disparar hacia arriba
|
COOLING_UP, // Enfriando tras disparar hacia arriba
|
||||||
COOLING_LEFT, // Enfriando tras disparar hacia la izquierda
|
COOLING_LEFT, // Enfriando tras disparar hacia la izquierda
|
||||||
COOLING_RIGHT, // Enfriando tras disparar hacia la derecha
|
COOLING_RIGHT, // Enfriando tras disparar hacia la derecha
|
||||||
|
|
||||||
// Estados generales del jugador
|
// Estados generales del jugador
|
||||||
PLAYING, // Está jugando activamente
|
PLAYING, // Está jugando activamente
|
||||||
CONTINUE, // Cuenta atrás para continuar tras perder
|
CONTINUE, // Cuenta atrás para continuar tras perder
|
||||||
CONTINUE_TIME_OUT, // Se ha terminado la cuenta atras para continuar y se retira al jugador de la zona de juego
|
CONTINUE_TIME_OUT, // Se ha terminado la cuenta atras para continuar y se retira al jugador de la zona de juego
|
||||||
WAITING, // Esperando para entrar a jugar
|
WAITING, // Esperando para entrar a jugar
|
||||||
ENTERING_NAME, // Introduciendo nombre para la tabla de puntuaciones
|
ENTERING_NAME, // Introduciendo nombre para la tabla de puntuaciones
|
||||||
SHOWING_NAME, // Mostrando el nombre introducido
|
SHOWING_NAME, // Mostrando el nombre introducido
|
||||||
ROLLING, // El jugador está muriendo (animación de muerte)
|
ROLLING, // El jugador está muriendo (animación de muerte)
|
||||||
LYING_ON_THE_FLOOR_FOREVER, // El jugador está inconsciente para siempre en el suelo (demo)
|
LYING_ON_THE_FLOOR_FOREVER, // El jugador está inconsciente para siempre en el suelo (demo)
|
||||||
GAME_OVER, // Fin de la partida, no puede jugar
|
GAME_OVER, // Fin de la partida, no puede jugar
|
||||||
CELEBRATING, // Celebrando victoria (pose de victoria)
|
CELEBRATING, // Celebrando victoria (pose de victoria)
|
||||||
ENTERING_NAME_GAME_COMPLETED, // Introduciendo nombre tras completar el juego
|
ENTERING_NAME_GAME_COMPLETED, // Introduciendo nombre tras completar el juego
|
||||||
LEAVING_SCREEN, // Saliendo de la pantalla (animación)
|
LEAVING_SCREEN, // Saliendo de la pantalla (animación)
|
||||||
ENTERING_SCREEN, // Entrando a la pantalla (animación)
|
ENTERING_SCREEN, // Entrando a la pantalla (animación)
|
||||||
CREDITS, // Estado para mostrar los créditos del juego
|
CREDITS, // Estado para mostrar los créditos del juego
|
||||||
TITLE_ANIMATION, // Animacion para el titulo
|
TITLE_ANIMATION, // Animacion para el titulo
|
||||||
TITLE_HIDDEN, // Animacion para el titulo
|
TITLE_HIDDEN, // Animacion para el titulo
|
||||||
RESPAWNING, // Tras continuar y volver al juego
|
RESPAWNING, // Tras continuar y volver al juego
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Clase Player ---
|
// --- Clase Player ---
|
||||||
class Player
|
class Player {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// --- Constructor y destructor ---
|
// --- Constructor y destructor ---
|
||||||
Player(int id, float x, int y, bool demo, SDL_FRect &play_area, std::vector<std::shared_ptr<Texture>> texture, const std::vector<std::vector<std::string>> &animations);
|
Player(int id, float x, int y, bool demo, SDL_FRect &play_area, std::vector<std::shared_ptr<Texture>> texture, const std::vector<std::vector<std::string>> &animations);
|
||||||
~Player() = default;
|
~Player() = default;
|
||||||
|
|
||||||
// --- Inicialización y ciclo de vida ---
|
// --- Inicialización y ciclo de vida ---
|
||||||
void init(); // Inicializa el jugador
|
void init(); // Inicializa el jugador
|
||||||
void update(); // Actualiza estado, animación y contadores
|
void update(); // Actualiza estado, animación y contadores
|
||||||
void render(); // Dibuja el jugador en pantalla
|
void render(); // Dibuja el jugador en pantalla
|
||||||
|
|
||||||
// --- Entrada y control ---
|
// --- Entrada y control ---
|
||||||
void setInput(InputAction input); // Procesa entrada general
|
void setInput(InputAction input); // Procesa entrada general
|
||||||
void setInputPlaying(InputAction input); // Procesa entrada en modo jugando
|
void setInputPlaying(InputAction input); // Procesa entrada en modo jugando
|
||||||
void setInputEnteringName(InputAction input); // Procesa entrada al introducir nombre
|
void setInputEnteringName(InputAction input); // Procesa entrada al introducir nombre
|
||||||
|
|
||||||
// --- Movimiento y animación ---
|
// --- Movimiento y animación ---
|
||||||
void move(); // Mueve el jugador
|
void move(); // Mueve el jugador
|
||||||
void setAnimation(); // Establece la animación según el estado
|
void setAnimation(); // Establece la animación según el estado
|
||||||
|
|
||||||
// --- Texturas y animaciones ---
|
// --- Texturas y animaciones ---
|
||||||
void setPlayerTextures(const std::vector<std::shared_ptr<Texture>> &texture); // Cambia las texturas del jugador
|
void setPlayerTextures(const std::vector<std::shared_ptr<Texture>> &texture); // Cambia las texturas del jugador
|
||||||
|
|
||||||
// --- Estados y contadores ---
|
// --- Estados y contadores ---
|
||||||
void updateCooldown(); // Actualiza el cooldown de disparo
|
void updateCooldown(); // Actualiza el cooldown de disparo
|
||||||
|
|
||||||
// --- Puntuación y marcador ---
|
// --- Puntuación y marcador ---
|
||||||
void addScore(int score); // Añade puntos
|
void addScore(int score); // Añade puntos
|
||||||
void incScoreMultiplier(); // Incrementa el multiplicador
|
void incScoreMultiplier(); // Incrementa el multiplicador
|
||||||
void decScoreMultiplier(); // Decrementa el multiplicador
|
void decScoreMultiplier(); // Decrementa el multiplicador
|
||||||
|
|
||||||
// --- Estados de juego ---
|
// --- Estados de juego ---
|
||||||
void setPlayingState(PlayerState state); // Cambia el estado de juego
|
void setPlayingState(PlayerState state); // Cambia el estado de juego
|
||||||
void setInvulnerable(bool value); // Establece el valor del estado de invulnerabilidad
|
void setInvulnerable(bool value); // Establece el valor del estado de invulnerabilidad
|
||||||
void setPowerUp(); // Activa el modo PowerUp
|
void setPowerUp(); // Activa el modo PowerUp
|
||||||
void updatePowerUp(); // Actualiza el valor de PowerUp
|
void updatePowerUp(); // Actualiza el valor de PowerUp
|
||||||
void giveExtraHit(); // Concede un toque extra al jugador
|
void giveExtraHit(); // Concede un toque extra al jugador
|
||||||
void removeExtraHit(); // Quita el toque extra al jugador
|
void removeExtraHit(); // Quita el toque extra al jugador
|
||||||
void decContinueCounter(); // Decrementa el contador de continuar
|
void decContinueCounter(); // Decrementa el contador de continuar
|
||||||
|
|
||||||
// --- Getters y comprobaciones de estado ---
|
// --- Getters y comprobaciones de estado ---
|
||||||
int getRecordNamePos() const; // Obtiene la posición que se está editando del nombre del jugador para la tabla de mejores puntuaciones
|
int getRecordNamePos() const; // Obtiene la posición que se está editando del nombre del jugador para la tabla de mejores puntuaciones
|
||||||
|
|
||||||
// Comprobación de playing_state
|
// Comprobación de playing_state
|
||||||
bool isLyingOnTheFloorForever() const { return playing_state_ == PlayerState::LYING_ON_THE_FLOOR_FOREVER; }
|
bool isLyingOnTheFloorForever() const { return playing_state_ == PlayerState::LYING_ON_THE_FLOOR_FOREVER; }
|
||||||
@@ -160,73 +159,73 @@ public:
|
|||||||
void setWalkingState(PlayerState state) { walking_state_ = state; }
|
void setWalkingState(PlayerState state) { walking_state_ = state; }
|
||||||
void addCredit() { ++credits_used_; }
|
void addCredit() { ++credits_used_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr int POWERUP_COUNTER_ = 1500; // Duración del estado PowerUp
|
static constexpr int POWERUP_COUNTER_ = 1500; // Duración del estado PowerUp
|
||||||
static constexpr int INVULNERABLE_COUNTER_ = 200; // Duración del estado invulnerable
|
static constexpr int INVULNERABLE_COUNTER_ = 200; // Duración del estado invulnerable
|
||||||
static constexpr int WIDTH_ = 30; // Anchura
|
static constexpr int WIDTH_ = 30; // Anchura
|
||||||
static constexpr int HEIGHT_ = 30; // Altura
|
static constexpr int HEIGHT_ = 30; // Altura
|
||||||
static constexpr float BASE_SPEED_ = 1.5f; // Velocidad base del jugador
|
static constexpr float BASE_SPEED_ = 1.5f; // Velocidad base del jugador
|
||||||
static constexpr int COOLING_DURATION_ = 50;
|
static constexpr int COOLING_DURATION_ = 50;
|
||||||
static constexpr int COOLING_COMPLETE_ = 0;
|
static constexpr int COOLING_COMPLETE_ = 0;
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
std::unique_ptr<AnimatedSprite> player_sprite_; // Sprite para dibujar el jugador
|
std::unique_ptr<AnimatedSprite> player_sprite_; // Sprite para dibujar el jugador
|
||||||
std::unique_ptr<AnimatedSprite> power_sprite_; // Sprite para dibujar el aura del jugador con el poder a tope
|
std::unique_ptr<AnimatedSprite> power_sprite_; // Sprite para dibujar el aura del jugador con el poder a tope
|
||||||
std::unique_ptr<EnterName> enter_name_; // Clase utilizada para introducir el nombre
|
std::unique_ptr<EnterName> enter_name_; // Clase utilizada para introducir el nombre
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
int id_; // Número de identificación para el jugador. Player1 = 1, Player2 = 2
|
int id_; // Número de identificación para el jugador. Player1 = 1, Player2 = 2
|
||||||
SDL_FRect play_area_; // Rectángulo con la zona de juego
|
SDL_FRect play_area_; // Rectángulo con la zona de juego
|
||||||
float pos_x_ = 0.0f; // Posición en el eje X
|
float pos_x_ = 0.0f; // Posición en el eje X
|
||||||
int pos_y_ = 0; // Posición en el eje Y
|
int pos_y_ = 0; // Posición en el eje Y
|
||||||
float default_pos_x_; // Posición inicial para el jugador
|
float default_pos_x_; // Posición inicial para el jugador
|
||||||
int default_pos_y_; // Posición inicial para el jugador
|
int default_pos_y_; // Posición inicial para el jugador
|
||||||
float vel_x_ = 0.0f; // Cantidad de píxeles a desplazarse en el eje X
|
float vel_x_ = 0.0f; // Cantidad de píxeles a desplazarse en el eje X
|
||||||
int vel_y_ = 0.0f; // Cantidad de píxeles a desplazarse en el eje Y
|
int vel_y_ = 0.0f; // Cantidad de píxeles a desplazarse en el eje Y
|
||||||
int cant_fire_counter_ = 0; // Contador durante el cual no puede disparar
|
int cant_fire_counter_ = 0; // Contador durante el cual no puede disparar
|
||||||
int recoiling_state_counter_ = 0; // Contador para la animación del estado de retroceso
|
int recoiling_state_counter_ = 0; // Contador para la animación del estado de retroceso
|
||||||
int recoiling_state_duration_ = 0; // Numero de frames que dura el estado de retroceso
|
int recoiling_state_duration_ = 0; // Numero de frames que dura el estado de retroceso
|
||||||
int cooling_state_counter_ = 0; // Contador para la animación del estado cooling
|
int cooling_state_counter_ = 0; // Contador para la animación del estado cooling
|
||||||
int score_ = 0; // Puntos del jugador
|
int score_ = 0; // Puntos del jugador
|
||||||
float score_multiplier_ = 1.0f; // Multiplicador de puntos
|
float score_multiplier_ = 1.0f; // Multiplicador de puntos
|
||||||
PlayerState walking_state_ = PlayerState::WALKING_STOP; // Estado del jugador al moverse
|
PlayerState walking_state_ = PlayerState::WALKING_STOP; // Estado del jugador al moverse
|
||||||
PlayerState firing_state_ = PlayerState::FIRING_NONE; // Estado del jugador al disparar
|
PlayerState firing_state_ = PlayerState::FIRING_NONE; // Estado del jugador al disparar
|
||||||
PlayerState playing_state_ = PlayerState::WAITING; // Estado del jugador en el juego
|
PlayerState playing_state_ = PlayerState::WAITING; // Estado del jugador en el juego
|
||||||
bool invulnerable_ = true; // Indica si el jugador es invulnerable
|
bool invulnerable_ = true; // Indica si el jugador es invulnerable
|
||||||
int invulnerable_counter_ = INVULNERABLE_COUNTER_; // Contador para la invulnerabilidad
|
int invulnerable_counter_ = INVULNERABLE_COUNTER_; // Contador para la invulnerabilidad
|
||||||
bool extra_hit_ = false; // Indica si el jugador tiene un toque extra
|
bool extra_hit_ = false; // Indica si el jugador tiene un toque extra
|
||||||
int coffees_ = 0; // Indica cuántos cafés lleva acumulados
|
int coffees_ = 0; // Indica cuántos cafés lleva acumulados
|
||||||
bool power_up_ = false; // Indica si el jugador tiene activo el modo PowerUp
|
bool power_up_ = false; // Indica si el jugador tiene activo el modo PowerUp
|
||||||
int power_up_counter_ = POWERUP_COUNTER_; // Temporizador para el modo PowerUp
|
int power_up_counter_ = POWERUP_COUNTER_; // Temporizador para el modo PowerUp
|
||||||
int power_up_desp_x_ = 0; // Desplazamiento del sprite de PowerUp respecto al sprite del jugador
|
int power_up_desp_x_ = 0; // Desplazamiento del sprite de PowerUp respecto al sprite del jugador
|
||||||
Circle collider_ = Circle(0, 0, 9); // Círculo de colisión del jugador
|
Circle collider_ = Circle(0, 0, 9); // Círculo de colisión del jugador
|
||||||
int continue_counter_ = 10; // Contador para poder continuar
|
int continue_counter_ = 10; // Contador para poder continuar
|
||||||
Uint32 continue_ticks_ = 0; // Variable para poder cambiar el contador de continue en función del tiempo
|
Uint32 continue_ticks_ = 0; // Variable para poder cambiar el contador de continue en función del tiempo
|
||||||
int scoreboard_panel_ = 0; // Panel del marcador asociado al jugador
|
int scoreboard_panel_ = 0; // Panel del marcador asociado al jugador
|
||||||
std::string name_; // Nombre del jugador
|
std::string name_; // Nombre del jugador
|
||||||
int controller_index_ = 0; // Índice del array de mandos que utilizará para moverse
|
int controller_index_ = 0; // Índice del array de mandos que utilizará para moverse
|
||||||
bool demo_ = false; // Para que el jugador sepa si está en el modo demostración
|
bool demo_ = false; // Para que el jugador sepa si está en el modo demostración
|
||||||
int name_entry_idle_counter_ = 0; // Contador para poner nombre
|
int name_entry_idle_counter_ = 0; // Contador para poner nombre
|
||||||
int name_entry_total_counter_ = 0; // Segundos totales que lleva acumulados poniendo nombre
|
int name_entry_total_counter_ = 0; // Segundos totales que lleva acumulados poniendo nombre
|
||||||
Uint32 name_entry_ticks_ = 0; // Variable para poder cambiar el contador de poner nombre en función del tiempo
|
Uint32 name_entry_ticks_ = 0; // Variable para poder cambiar el contador de poner nombre en función del tiempo
|
||||||
Uint32 showing_name_ticks_ = 0; // Tiempo en el que se entra al estado SHOWING_NAME
|
Uint32 showing_name_ticks_ = 0; // Tiempo en el que se entra al estado SHOWING_NAME
|
||||||
int step_counter_ = 0; // Cuenta los pasos para los estados en los que camina automáticamente
|
int step_counter_ = 0; // Cuenta los pasos para los estados en los que camina automáticamente
|
||||||
bool game_completed_ = false; // Indica si ha completado el juego
|
bool game_completed_ = false; // Indica si ha completado el juego
|
||||||
int credits_used_ = 1; // Indica el número de veces que ha continuado
|
int credits_used_ = 1; // Indica el número de veces que ha continuado
|
||||||
std::string last_enter_name_; // Último nombre introducido en la tabla de puntuaciones
|
std::string last_enter_name_; // Último nombre introducido en la tabla de puntuaciones
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void shiftColliders(); // Actualiza el círculo de colisión a la posición del jugador
|
void shiftColliders(); // Actualiza el círculo de colisión a la posición del jugador
|
||||||
void shiftSprite(); // Recoloca el sprite
|
void shiftSprite(); // Recoloca el sprite
|
||||||
void updateInvulnerable(); // Monitoriza el estado de invulnerabilidad
|
void updateInvulnerable(); // Monitoriza el estado de invulnerabilidad
|
||||||
void updateContinueCounter(); // Actualiza el contador de continue
|
void updateContinueCounter(); // Actualiza el contador de continue
|
||||||
void updateEnterNameCounter(); // Actualiza el contador de entrar nombre
|
void updateEnterNameCounter(); // Actualiza el contador de entrar nombre
|
||||||
void updateShowingName(); // Actualiza el estado SHOWING_NAME
|
void updateShowingName(); // Actualiza el estado SHOWING_NAME
|
||||||
void decNameEntryCounter(); // Decrementa el contador de entrar nombre
|
void decNameEntryCounter(); // Decrementa el contador de entrar nombre
|
||||||
void updateScoreboard(); // Actualiza el panel del marcador
|
void updateScoreboard(); // Actualiza el panel del marcador
|
||||||
void setScoreboardMode(ScoreboardMode mode); // Cambia el modo del marcador
|
void setScoreboardMode(ScoreboardMode mode); // Cambia el modo del marcador
|
||||||
void playSound(const std::string &name); // Hace sonar un sonido
|
void playSound(const std::string &name); // Hace sonar un sonido
|
||||||
bool isRenderable() const { return !isWaiting() && !isGameOver() && !isTitleHidden(); }
|
bool isRenderable() const { return !isWaiting() && !isGameOver() && !isTitleHidden(); }
|
||||||
void addScoreToScoreBoard(); // Añade una puntuación a la tabla de records
|
void addScoreToScoreBoard(); // Añade una puntuación a la tabla de records
|
||||||
};
|
};
|
||||||
+86
-146
@@ -1,20 +1,21 @@
|
|||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_L...
|
#include <SDL3/SDL.h> // Para SDL_LogInfo, SDL_LogCategory, SDL_L...
|
||||||
#include <stdlib.h> // Para exit
|
#include <stdlib.h> // Para exit
|
||||||
|
|
||||||
#include <algorithm> // Para find_if
|
#include <algorithm> // Para find_if
|
||||||
#include <array> // Para array
|
#include <array> // Para array
|
||||||
#include <stdexcept> // Para runtime_error
|
#include <stdexcept> // Para runtime_error
|
||||||
|
|
||||||
#include "asset.h" // Para Asset, AssetType
|
#include "asset.h" // Para Asset, AssetType
|
||||||
#include "external/jail_audio.h" // Para JA_DeleteMusic, JA_DeleteSound, JA_...
|
#include "external/jail_audio.h" // Para JA_DeleteMusic, JA_DeleteSound, JA_...
|
||||||
#include "lang.h" // Para getText
|
#include "lang.h" // Para getText
|
||||||
#include "param.h" // Para Param, param, ParamResource, ParamGame
|
#include "param.h" // Para Param, param, ParamResource, ParamGame
|
||||||
#include "screen.h" // Para Screen
|
#include "screen.h" // Para Screen
|
||||||
#include "text.h" // Para Text, loadTextFile, TextFile (ptr o...
|
#include "text.h" // Para Text, loadTextFile, TextFile (ptr o...
|
||||||
|
|
||||||
struct JA_Music_t; // lines 11-11
|
struct JA_Music_t; // lines 11-11
|
||||||
struct JA_Sound_t; // lines 12-12
|
struct JA_Sound_t; // lines 12-12
|
||||||
|
|
||||||
// Singleton
|
// Singleton
|
||||||
Resource *Resource::instance_ = nullptr;
|
Resource *Resource::instance_ = nullptr;
|
||||||
@@ -35,8 +36,7 @@ Resource::Resource() : loading_text_(Screen::get()->getText()) { load(); }
|
|||||||
Resource::~Resource() { clear(); }
|
Resource::~Resource() { clear(); }
|
||||||
|
|
||||||
// Vacia todos los vectores de recursos
|
// Vacia todos los vectores de recursos
|
||||||
void Resource::clear()
|
void Resource::clear() {
|
||||||
{
|
|
||||||
clearSounds();
|
clearSounds();
|
||||||
clearMusics();
|
clearMusics();
|
||||||
textures_.clear();
|
textures_.clear();
|
||||||
@@ -47,8 +47,7 @@ void Resource::clear()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Carga todos los recursos del juego y muestra el progreso de carga
|
// Carga todos los recursos del juego y muestra el progreso de carga
|
||||||
void Resource::load()
|
void Resource::load() {
|
||||||
{
|
|
||||||
// Prepara la gestión del progreso de carga
|
// Prepara la gestión del progreso de carga
|
||||||
calculateTotalResources();
|
calculateTotalResources();
|
||||||
initProgressBar();
|
initProgressBar();
|
||||||
@@ -59,15 +58,15 @@ void Resource::load()
|
|||||||
screen->setVSync(false);
|
screen->setVSync(false);
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n** LOADING RESOURCES");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n** LOADING RESOURCES");
|
||||||
loadSounds(); // Carga sonidos
|
loadSounds(); // Carga sonidos
|
||||||
loadMusics(); // Carga músicas
|
loadMusics(); // Carga músicas
|
||||||
loadTextures(); // Carga texturas
|
loadTextures(); // Carga texturas
|
||||||
loadTextFiles(); // Carga ficheros de texto
|
loadTextFiles(); // Carga ficheros de texto
|
||||||
loadAnimations(); // Carga animaciones
|
loadAnimations(); // Carga animaciones
|
||||||
loadDemoData(); // Carga datos de demo
|
loadDemoData(); // Carga datos de demo
|
||||||
addPalettes(); // Añade paletas a las texturas
|
addPalettes(); // Añade paletas a las texturas
|
||||||
createText(); // Crea objetos de texto
|
createText(); // Crea objetos de texto
|
||||||
createTextures(); // Crea texturas a partir de texto
|
createTextures(); // Crea texturas a partir de texto
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n** RESOURCES LOADED");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n** RESOURCES LOADED");
|
||||||
|
|
||||||
// Restablece el sincronismo vertical a su valor original
|
// Restablece el sincronismo vertical a su valor original
|
||||||
@@ -75,28 +74,23 @@ void Resource::load()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Recarga todos los recursos (limpia y vuelve a cargar)
|
// Recarga todos los recursos (limpia y vuelve a cargar)
|
||||||
void Resource::reload()
|
void Resource::reload() {
|
||||||
{
|
|
||||||
clear();
|
clear();
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recarga solo las texturas y paletas
|
// Recarga solo las texturas y paletas
|
||||||
void Resource::reloadTextures()
|
void Resource::reloadTextures() {
|
||||||
{
|
|
||||||
loadTextures();
|
loadTextures();
|
||||||
addPalettes();
|
addPalettes();
|
||||||
createTextures();
|
createTextures();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el sonido a partir de un nombre. Lanza excepción si no existe.
|
// Obtiene el sonido a partir de un nombre. Lanza excepción si no existe.
|
||||||
JA_Sound_t *Resource::getSound(const std::string &name)
|
JA_Sound_t *Resource::getSound(const std::string &name) {
|
||||||
{
|
auto it = std::find_if(sounds_.begin(), sounds_.end(), [&name](const auto &s) { return s.name == name; });
|
||||||
auto it = std::find_if(sounds_.begin(), sounds_.end(), [&name](const auto &s)
|
|
||||||
{ return s.name == name; });
|
|
||||||
|
|
||||||
if (it != sounds_.end())
|
if (it != sounds_.end()) {
|
||||||
{
|
|
||||||
return it->sound;
|
return it->sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,13 +99,10 @@ JA_Sound_t *Resource::getSound(const std::string &name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene la música a partir de un nombre. Lanza excepción si no existe.
|
// Obtiene la música a partir de un nombre. Lanza excepción si no existe.
|
||||||
JA_Music_t *Resource::getMusic(const std::string &name)
|
JA_Music_t *Resource::getMusic(const std::string &name) {
|
||||||
{
|
auto it = std::find_if(musics_.begin(), musics_.end(), [&name](const auto &m) { return m.name == name; });
|
||||||
auto it = std::find_if(musics_.begin(), musics_.end(), [&name](const auto &m)
|
|
||||||
{ return m.name == name; });
|
|
||||||
|
|
||||||
if (it != musics_.end())
|
if (it != musics_.end()) {
|
||||||
{
|
|
||||||
return it->music;
|
return it->music;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,13 +111,10 @@ JA_Music_t *Resource::getMusic(const std::string &name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene la textura a partir de un nombre. Lanza excepción si no existe.
|
// Obtiene la textura a partir de un nombre. Lanza excepción si no existe.
|
||||||
std::shared_ptr<Texture> Resource::getTexture(const std::string &name)
|
std::shared_ptr<Texture> Resource::getTexture(const std::string &name) {
|
||||||
{
|
auto it = std::find_if(textures_.begin(), textures_.end(), [&name](const auto &t) { return t.name == name; });
|
||||||
auto it = std::find_if(textures_.begin(), textures_.end(), [&name](const auto &t)
|
|
||||||
{ return t.name == name; });
|
|
||||||
|
|
||||||
if (it != textures_.end())
|
if (it != textures_.end()) {
|
||||||
{
|
|
||||||
return it->texture;
|
return it->texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,13 +123,10 @@ std::shared_ptr<Texture> Resource::getTexture(const std::string &name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el fichero de texto a partir de un nombre. Lanza excepción si no existe.
|
// Obtiene el fichero de texto a partir de un nombre. Lanza excepción si no existe.
|
||||||
std::shared_ptr<TextFile> Resource::getTextFile(const std::string &name)
|
std::shared_ptr<TextFile> Resource::getTextFile(const std::string &name) {
|
||||||
{
|
auto it = std::find_if(text_files_.begin(), text_files_.end(), [&name](const auto &t) { return t.name == name; });
|
||||||
auto it = std::find_if(text_files_.begin(), text_files_.end(), [&name](const auto &t)
|
|
||||||
{ return t.name == name; });
|
|
||||||
|
|
||||||
if (it != text_files_.end())
|
if (it != text_files_.end()) {
|
||||||
{
|
|
||||||
return it->text_file;
|
return it->text_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,13 +135,10 @@ std::shared_ptr<TextFile> Resource::getTextFile(const std::string &name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el objeto de texto a partir de un nombre. Lanza excepción si no existe.
|
// Obtiene el objeto de texto a partir de un nombre. Lanza excepción si no existe.
|
||||||
std::shared_ptr<Text> Resource::getText(const std::string &name)
|
std::shared_ptr<Text> Resource::getText(const std::string &name) {
|
||||||
{
|
auto it = std::find_if(texts_.begin(), texts_.end(), [&name](const auto &t) { return t.name == name; });
|
||||||
auto it = std::find_if(texts_.begin(), texts_.end(), [&name](const auto &t)
|
|
||||||
{ return t.name == name; });
|
|
||||||
|
|
||||||
if (it != texts_.end())
|
if (it != texts_.end()) {
|
||||||
{
|
|
||||||
return it->text;
|
return it->text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,13 +147,10 @@ std::shared_ptr<Text> Resource::getText(const std::string &name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene la animación a partir de un nombre. Lanza excepción si no existe.
|
// Obtiene la animación a partir de un nombre. Lanza excepción si no existe.
|
||||||
AnimationsFileBuffer &Resource::getAnimation(const std::string &name)
|
AnimationsFileBuffer &Resource::getAnimation(const std::string &name) {
|
||||||
{
|
auto it = std::find_if(animations_.begin(), animations_.end(), [&name](const auto &a) { return a.name == name; });
|
||||||
auto it = std::find_if(animations_.begin(), animations_.end(), [&name](const auto &a)
|
|
||||||
{ return a.name == name; });
|
|
||||||
|
|
||||||
if (it != animations_.end())
|
if (it != animations_.end()) {
|
||||||
{
|
|
||||||
return it->animation;
|
return it->animation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,20 +159,17 @@ AnimationsFileBuffer &Resource::getAnimation(const std::string &name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el fichero con los datos para el modo demostración a partir de un índice
|
// Obtiene el fichero con los datos para el modo demostración a partir de un índice
|
||||||
DemoData &Resource::getDemoData(int index)
|
DemoData &Resource::getDemoData(int index) {
|
||||||
{
|
|
||||||
return demos_.at(index);
|
return demos_.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carga los sonidos del juego
|
// Carga los sonidos del juego
|
||||||
void Resource::loadSounds()
|
void Resource::loadSounds() {
|
||||||
{
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> SOUND FILES");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> SOUND FILES");
|
||||||
auto list = Asset::get()->getListByType(AssetType::SOUND);
|
auto list = Asset::get()->getListByType(AssetType::SOUND);
|
||||||
sounds_.clear();
|
sounds_.clear();
|
||||||
|
|
||||||
for (const auto &l : list)
|
for (const auto &l : list) {
|
||||||
{
|
|
||||||
auto name = getFileName(l);
|
auto name = getFileName(l);
|
||||||
updateLoadingProgress(name);
|
updateLoadingProgress(name);
|
||||||
sounds_.emplace_back(Resource::ResourceSound(name, JA_LoadSound(l.c_str())));
|
sounds_.emplace_back(Resource::ResourceSound(name, JA_LoadSound(l.c_str())));
|
||||||
@@ -202,14 +178,12 @@ void Resource::loadSounds()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Carga las músicas del juego
|
// Carga las músicas del juego
|
||||||
void Resource::loadMusics()
|
void Resource::loadMusics() {
|
||||||
{
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> MUSIC FILES");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> MUSIC FILES");
|
||||||
auto list = Asset::get()->getListByType(AssetType::MUSIC);
|
auto list = Asset::get()->getListByType(AssetType::MUSIC);
|
||||||
musics_.clear();
|
musics_.clear();
|
||||||
|
|
||||||
for (const auto &l : list)
|
for (const auto &l : list) {
|
||||||
{
|
|
||||||
auto name = getFileName(l);
|
auto name = getFileName(l);
|
||||||
updateLoadingProgress(name);
|
updateLoadingProgress(name);
|
||||||
musics_.emplace_back(Resource::ResourceMusic(name, JA_LoadMusic(l.c_str())));
|
musics_.emplace_back(Resource::ResourceMusic(name, JA_LoadMusic(l.c_str())));
|
||||||
@@ -218,14 +192,12 @@ void Resource::loadMusics()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Carga las texturas del juego
|
// Carga las texturas del juego
|
||||||
void Resource::loadTextures()
|
void Resource::loadTextures() {
|
||||||
{
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> TEXTURES");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> TEXTURES");
|
||||||
auto list = Asset::get()->getListByType(AssetType::BITMAP);
|
auto list = Asset::get()->getListByType(AssetType::BITMAP);
|
||||||
textures_.clear();
|
textures_.clear();
|
||||||
|
|
||||||
for (const auto &l : list)
|
for (const auto &l : list) {
|
||||||
{
|
|
||||||
auto name = getFileName(l);
|
auto name = getFileName(l);
|
||||||
updateLoadingProgress(name);
|
updateLoadingProgress(name);
|
||||||
textures_.emplace_back(Resource::ResourceTexture(name, std::make_shared<Texture>(Screen::get()->getRenderer(), l)));
|
textures_.emplace_back(Resource::ResourceTexture(name, std::make_shared<Texture>(Screen::get()->getRenderer(), l)));
|
||||||
@@ -233,14 +205,12 @@ void Resource::loadTextures()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Carga los ficheros de texto del juego
|
// Carga los ficheros de texto del juego
|
||||||
void Resource::loadTextFiles()
|
void Resource::loadTextFiles() {
|
||||||
{
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> TEXT FILES");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> TEXT FILES");
|
||||||
auto list = Asset::get()->getListByType(AssetType::FONT);
|
auto list = Asset::get()->getListByType(AssetType::FONT);
|
||||||
text_files_.clear();
|
text_files_.clear();
|
||||||
|
|
||||||
for (const auto &l : list)
|
for (const auto &l : list) {
|
||||||
{
|
|
||||||
auto name = getFileName(l);
|
auto name = getFileName(l);
|
||||||
updateLoadingProgress(name);
|
updateLoadingProgress(name);
|
||||||
text_files_.emplace_back(Resource::ResourceTextFile(name, loadTextFile(l)));
|
text_files_.emplace_back(Resource::ResourceTextFile(name, loadTextFile(l)));
|
||||||
@@ -248,14 +218,12 @@ void Resource::loadTextFiles()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Carga las animaciones del juego
|
// Carga las animaciones del juego
|
||||||
void Resource::loadAnimations()
|
void Resource::loadAnimations() {
|
||||||
{
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> ANIMATIONS");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> ANIMATIONS");
|
||||||
auto list = Asset::get()->getListByType(AssetType::ANIMATION);
|
auto list = Asset::get()->getListByType(AssetType::ANIMATION);
|
||||||
animations_.clear();
|
animations_.clear();
|
||||||
|
|
||||||
for (const auto &l : list)
|
for (const auto &l : list) {
|
||||||
{
|
|
||||||
auto name = getFileName(l);
|
auto name = getFileName(l);
|
||||||
updateLoadingProgress(name);
|
updateLoadingProgress(name);
|
||||||
animations_.emplace_back(Resource::ResourceAnimation(name, loadAnimationsFromFile(l)));
|
animations_.emplace_back(Resource::ResourceAnimation(name, loadAnimationsFromFile(l)));
|
||||||
@@ -263,22 +231,19 @@ void Resource::loadAnimations()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Carga los datos para el modo demostración
|
// Carga los datos para el modo demostración
|
||||||
void Resource::loadDemoData()
|
void Resource::loadDemoData() {
|
||||||
{
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> DEMO FILES");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> DEMO FILES");
|
||||||
|
|
||||||
constexpr std::array<const char *, 2> demo_files = {"demo1.bin", "demo2.bin"};
|
constexpr std::array<const char *, 2> demo_files = {"demo1.bin", "demo2.bin"};
|
||||||
|
|
||||||
for (const auto &file : demo_files)
|
for (const auto &file : demo_files) {
|
||||||
{
|
|
||||||
updateLoadingProgress(file);
|
updateLoadingProgress(file);
|
||||||
demos_.emplace_back(loadDemoDataFromFile(Asset::get()->get(file)));
|
demos_.emplace_back(loadDemoDataFromFile(Asset::get()->get(file)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Añade paletas de colores a las texturas principales
|
// Añade paletas de colores a las texturas principales
|
||||||
void Resource::addPalettes()
|
void Resource::addPalettes() {
|
||||||
{
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> PALETTES");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> PALETTES");
|
||||||
|
|
||||||
// Paletas para el jugador 1
|
// Paletas para el jugador 1
|
||||||
@@ -293,10 +258,8 @@ void Resource::addPalettes()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Crea texturas a partir de textos para mostrar puntuaciones y mensajes
|
// Crea texturas a partir de textos para mostrar puntuaciones y mensajes
|
||||||
void Resource::createTextures()
|
void Resource::createTextures() {
|
||||||
{
|
struct NameAndText {
|
||||||
struct NameAndText
|
|
||||||
{
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
@@ -317,8 +280,7 @@ void Resource::createTextures()
|
|||||||
{"game_text_1000000_points", Lang::getText("[GAME_TEXT] 8")}};
|
{"game_text_1000000_points", Lang::getText("[GAME_TEXT] 8")}};
|
||||||
|
|
||||||
auto text = getText("04b_25");
|
auto text = getText("04b_25");
|
||||||
for (const auto &s : strings)
|
for (const auto &s : strings) {
|
||||||
{
|
|
||||||
textures_.emplace_back(Resource::ResourceTexture(s.name, text->writeToTexture(s.text, 1, -2)));
|
textures_.emplace_back(Resource::ResourceTexture(s.name, text->writeToTexture(s.text, 1, -2)));
|
||||||
printWithDots("Texture : ", s.name, "[ DONE ]");
|
printWithDots("Texture : ", s.name, "[ DONE ]");
|
||||||
}
|
}
|
||||||
@@ -332,18 +294,15 @@ void Resource::createTextures()
|
|||||||
{"game_text_game_over", "Game Over"}};
|
{"game_text_game_over", "Game Over"}};
|
||||||
|
|
||||||
auto text2 = getText("04b_25_2x");
|
auto text2 = getText("04b_25_2x");
|
||||||
for (const auto &s : strings2X)
|
for (const auto &s : strings2X) {
|
||||||
{
|
|
||||||
textures_.emplace_back(Resource::ResourceTexture(s.name, text2->writeToTexture(s.text, 1, -4)));
|
textures_.emplace_back(Resource::ResourceTexture(s.name, text2->writeToTexture(s.text, 1, -4)));
|
||||||
printWithDots("Texture : ", s.name, "[ DONE ]");
|
printWithDots("Texture : ", s.name, "[ DONE ]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea los objetos de texto a partir de los archivos de textura y texto
|
// Crea los objetos de texto a partir de los archivos de textura y texto
|
||||||
void Resource::createText()
|
void Resource::createText() {
|
||||||
{
|
struct ResourceInfo {
|
||||||
struct ResourceInfo
|
|
||||||
{
|
|
||||||
std::string key;
|
std::string key;
|
||||||
std::string textureFile;
|
std::string textureFile;
|
||||||
std::string textFile;
|
std::string textFile;
|
||||||
@@ -368,22 +327,16 @@ void Resource::createText()
|
|||||||
{"smb2", "smb2.png", "smb2.txt"},
|
{"smb2", "smb2.png", "smb2.txt"},
|
||||||
{"smb2_grad", "smb2_grad.png", "smb2.txt"}};
|
{"smb2_grad", "smb2_grad.png", "smb2.txt"}};
|
||||||
|
|
||||||
for (const auto &resource : resources)
|
for (const auto &resource : resources) {
|
||||||
{
|
texts_.emplace_back(Resource::ResourceText(resource.key, std::make_shared<Text>(getTexture(resource.textureFile), getTextFile(resource.textFile))));
|
||||||
texts_.emplace_back(Resource::ResourceText(resource.key, std::make_shared<Text>(
|
|
||||||
getTexture(resource.textureFile),
|
|
||||||
getTextFile(resource.textFile))));
|
|
||||||
printWithDots("Text : ", resource.key, "[ DONE ]");
|
printWithDots("Text : ", resource.key, "[ DONE ]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vacía el vector de sonidos y libera la memoria asociada
|
// Vacía el vector de sonidos y libera la memoria asociada
|
||||||
void Resource::clearSounds()
|
void Resource::clearSounds() {
|
||||||
{
|
for (auto &sound : sounds_) {
|
||||||
for (auto &sound : sounds_)
|
if (sound.sound) {
|
||||||
{
|
|
||||||
if (sound.sound)
|
|
||||||
{
|
|
||||||
JA_DeleteSound(sound.sound);
|
JA_DeleteSound(sound.sound);
|
||||||
sound.sound = nullptr;
|
sound.sound = nullptr;
|
||||||
}
|
}
|
||||||
@@ -392,12 +345,9 @@ void Resource::clearSounds()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Vacía el vector de músicas y libera la memoria asociada
|
// Vacía el vector de músicas y libera la memoria asociada
|
||||||
void Resource::clearMusics()
|
void Resource::clearMusics() {
|
||||||
{
|
for (auto &music : musics_) {
|
||||||
for (auto &music : musics_)
|
if (music.music) {
|
||||||
{
|
|
||||||
if (music.music)
|
|
||||||
{
|
|
||||||
JA_DeleteMusic(music.music);
|
JA_DeleteMusic(music.music);
|
||||||
music.music = nullptr;
|
music.music = nullptr;
|
||||||
}
|
}
|
||||||
@@ -406,8 +356,7 @@ void Resource::clearMusics()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calcula el número total de recursos a cargar y reinicia el contador de carga
|
// Calcula el número total de recursos a cargar y reinicia el contador de carga
|
||||||
void Resource::calculateTotalResources()
|
void Resource::calculateTotalResources() {
|
||||||
{
|
|
||||||
const std::array<AssetType, 6> ASSET_TYPES = {
|
const std::array<AssetType, 6> ASSET_TYPES = {
|
||||||
AssetType::SOUND,
|
AssetType::SOUND,
|
||||||
AssetType::MUSIC,
|
AssetType::MUSIC,
|
||||||
@@ -417,8 +366,7 @@ void Resource::calculateTotalResources()
|
|||||||
AssetType::DEMODATA};
|
AssetType::DEMODATA};
|
||||||
|
|
||||||
size_t total = 0;
|
size_t total = 0;
|
||||||
for (const auto &asset_type : ASSET_TYPES)
|
for (const auto &asset_type : ASSET_TYPES) {
|
||||||
{
|
|
||||||
auto list = Asset::get()->getListByType(asset_type);
|
auto list = Asset::get()->getListByType(asset_type);
|
||||||
total += list.size();
|
total += list.size();
|
||||||
}
|
}
|
||||||
@@ -427,8 +375,7 @@ void Resource::calculateTotalResources()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Muestra el progreso de carga en pantalla (barra y texto)
|
// Muestra el progreso de carga en pantalla (barra y texto)
|
||||||
void Resource::renderProgress()
|
void Resource::renderProgress() {
|
||||||
{
|
|
||||||
// Obtiene la pantalla y el renderer
|
// Obtiene la pantalla y el renderer
|
||||||
auto screen = Screen::get();
|
auto screen = Screen::get();
|
||||||
auto renderer = screen->getRenderer();
|
auto renderer = screen->getRenderer();
|
||||||
@@ -462,29 +409,24 @@ void Resource::renderProgress()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba los eventos durante la carga (permite salir con ESC o cerrar ventana)
|
// Comprueba los eventos durante la carga (permite salir con ESC o cerrar ventana)
|
||||||
void Resource::checkEvents()
|
void Resource::checkEvents() {
|
||||||
{
|
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event))
|
while (SDL_PollEvent(&event)) {
|
||||||
{
|
switch (event.type) {
|
||||||
switch (event.type)
|
case SDL_EVENT_QUIT:
|
||||||
{
|
|
||||||
case SDL_EVENT_QUIT:
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
case SDL_EVENT_KEY_DOWN:
|
|
||||||
if (event.key.key == SDLK_ESCAPE)
|
|
||||||
{
|
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
break;
|
||||||
break;
|
case SDL_EVENT_KEY_DOWN:
|
||||||
|
if (event.key.key == SDLK_ESCAPE) {
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el progreso de carga, muestra la barra y procesa eventos
|
// Actualiza el progreso de carga, muestra la barra y procesa eventos
|
||||||
void Resource::updateLoadingProgress(std::string name)
|
void Resource::updateLoadingProgress(std::string name) {
|
||||||
{
|
|
||||||
loading_resource_name_ = name;
|
loading_resource_name_ = name;
|
||||||
loading_count_.increase();
|
loading_count_.increase();
|
||||||
updateProgressBar();
|
updateProgressBar();
|
||||||
@@ -493,8 +435,7 @@ void Resource::updateLoadingProgress(std::string name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa los rectangulos que definen la barra de progreso
|
// Inicializa los rectangulos que definen la barra de progreso
|
||||||
void Resource::initProgressBar()
|
void Resource::initProgressBar() {
|
||||||
{
|
|
||||||
constexpr float X_PADDING = 20.0f;
|
constexpr float X_PADDING = 20.0f;
|
||||||
constexpr float Y_PADDING = 20.0f;
|
constexpr float Y_PADDING = 20.0f;
|
||||||
constexpr float BAR_HEIGHT = 10.0f;
|
constexpr float BAR_HEIGHT = 10.0f;
|
||||||
@@ -508,7 +449,6 @@ void Resource::initProgressBar()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza la barra de estado
|
// Actualiza la barra de estado
|
||||||
void Resource::updateProgressBar()
|
void Resource::updateProgressBar() {
|
||||||
{
|
|
||||||
loading_full_rect_.w = loading_wired_rect_.w * loading_count_.getPercentage();
|
loading_full_rect_.w = loading_wired_rect_.w * loading_count_.getPercentage();
|
||||||
}
|
}
|
||||||
+79
-87
@@ -1,157 +1,149 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FRect
|
#include <SDL3/SDL.h> // Para SDL_FRect
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
#include <memory> // Para shared_ptr
|
|
||||||
#include <string> // Para basic_string, string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimationsFileBuffer
|
#include <memory> // Para shared_ptr
|
||||||
#include "text.h" // Para Text, TextFile
|
#include <string> // Para basic_string, string
|
||||||
#include "texture.h" // Para Texture
|
#include <vector> // Para vector
|
||||||
#include "utils.h" // Para DemoData
|
|
||||||
|
#include "animated_sprite.h" // Para AnimationsFileBuffer
|
||||||
|
#include "text.h" // Para Text, TextFile
|
||||||
|
#include "texture.h" // Para Texture
|
||||||
|
#include "utils.h" // Para DemoData
|
||||||
|
|
||||||
struct JA_Music_t;
|
struct JA_Music_t;
|
||||||
struct JA_Sound_t;
|
struct JA_Sound_t;
|
||||||
|
|
||||||
// --- Clase Resource: gestiona todos los recursos del juego (singleton) ---
|
// --- Clase Resource: gestiona todos los recursos del juego (singleton) ---
|
||||||
class Resource
|
class Resource {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// --- Métodos de singleton ---
|
// --- Métodos de singleton ---
|
||||||
static void init(); // Inicializa el objeto Resource
|
static void init(); // Inicializa el objeto Resource
|
||||||
static void destroy(); // Libera el objeto Resource
|
static void destroy(); // Libera el objeto Resource
|
||||||
static Resource *get(); // Obtiene el puntero al objeto Resource
|
static Resource *get(); // Obtiene el puntero al objeto Resource
|
||||||
|
|
||||||
// --- Métodos de acceso a recursos ---
|
// --- Métodos de acceso a recursos ---
|
||||||
JA_Sound_t *getSound(const std::string &name); // Obtiene el sonido por nombre
|
JA_Sound_t *getSound(const std::string &name); // Obtiene el sonido por nombre
|
||||||
JA_Music_t *getMusic(const std::string &name); // Obtiene la música por nombre
|
JA_Music_t *getMusic(const std::string &name); // Obtiene la música por nombre
|
||||||
std::shared_ptr<Texture> getTexture(const std::string &name); // Obtiene la textura por nombre
|
std::shared_ptr<Texture> getTexture(const std::string &name); // Obtiene la textura por nombre
|
||||||
std::shared_ptr<TextFile> getTextFile(const std::string &name); // Obtiene el fichero de texto por nombre
|
std::shared_ptr<TextFile> getTextFile(const std::string &name); // Obtiene el fichero de texto por nombre
|
||||||
std::shared_ptr<Text> getText(const std::string &name); // Obtiene el objeto de texto por nombre
|
std::shared_ptr<Text> getText(const std::string &name); // Obtiene el objeto de texto por nombre
|
||||||
AnimationsFileBuffer &getAnimation(const std::string &name); // Obtiene la animación por nombre
|
AnimationsFileBuffer &getAnimation(const std::string &name); // Obtiene la animación por nombre
|
||||||
DemoData &getDemoData(int index); // Obtiene los datos de demo por índice
|
DemoData &getDemoData(int index); // Obtiene los datos de demo por índice
|
||||||
|
|
||||||
// --- Métodos de recarga de recursos ---
|
// --- Métodos de recarga de recursos ---
|
||||||
void reload(); // Recarga todos los recursos
|
void reload(); // Recarga todos los recursos
|
||||||
void reloadTextures(); // Recarga solo las texturas
|
void reloadTextures(); // Recarga solo las texturas
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Estructuras para recursos individuales ---
|
// --- Estructuras para recursos individuales ---
|
||||||
struct ResourceSound
|
struct ResourceSound {
|
||||||
{
|
std::string name; // Nombre del sonido
|
||||||
std::string name; // Nombre del sonido
|
JA_Sound_t *sound; // Objeto con el sonido
|
||||||
JA_Sound_t *sound; // Objeto con el sonido
|
|
||||||
|
|
||||||
ResourceSound(const std::string &name, JA_Sound_t *sound)
|
ResourceSound(const std::string &name, JA_Sound_t *sound)
|
||||||
: name(name), sound(sound) {}
|
: name(name), sound(sound) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ResourceMusic
|
struct ResourceMusic {
|
||||||
{
|
std::string name; // Nombre de la música
|
||||||
std::string name; // Nombre de la música
|
JA_Music_t *music; // Objeto con la música
|
||||||
JA_Music_t *music; // Objeto con la música
|
|
||||||
|
|
||||||
ResourceMusic(const std::string &name, JA_Music_t *music)
|
ResourceMusic(const std::string &name, JA_Music_t *music)
|
||||||
: name(name), music(music) {}
|
: name(name), music(music) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ResourceTexture
|
struct ResourceTexture {
|
||||||
{
|
std::string name; // Nombre de la textura
|
||||||
std::string name; // Nombre de la textura
|
std::shared_ptr<Texture> texture; // Objeto con la textura
|
||||||
std::shared_ptr<Texture> texture; // Objeto con la textura
|
|
||||||
|
|
||||||
ResourceTexture(const std::string &name, std::shared_ptr<Texture> texture)
|
ResourceTexture(const std::string &name, std::shared_ptr<Texture> texture)
|
||||||
: name(name), texture(texture) {}
|
: name(name), texture(texture) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ResourceTextFile
|
struct ResourceTextFile {
|
||||||
{
|
std::string name; // Nombre del fichero
|
||||||
std::string name; // Nombre del fichero
|
std::shared_ptr<TextFile> text_file; // Objeto con los descriptores de la fuente de texto
|
||||||
std::shared_ptr<TextFile> text_file; // Objeto con los descriptores de la fuente de texto
|
|
||||||
|
|
||||||
ResourceTextFile(const std::string &name, std::shared_ptr<TextFile> text_file)
|
ResourceTextFile(const std::string &name, std::shared_ptr<TextFile> text_file)
|
||||||
: name(name), text_file(text_file) {}
|
: name(name), text_file(text_file) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ResourceText
|
struct ResourceText {
|
||||||
{
|
std::string name; // Nombre del objeto
|
||||||
std::string name; // Nombre del objeto
|
std::shared_ptr<Text> text; // Objeto de texto
|
||||||
std::shared_ptr<Text> text; // Objeto de texto
|
|
||||||
|
|
||||||
ResourceText(const std::string &name, std::shared_ptr<Text> text)
|
ResourceText(const std::string &name, std::shared_ptr<Text> text)
|
||||||
: name(name), text(text) {}
|
: name(name), text(text) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ResourceAnimation
|
struct ResourceAnimation {
|
||||||
{
|
std::string name; // Nombre de la animación
|
||||||
std::string name; // Nombre de la animación
|
AnimationsFileBuffer animation; // Objeto con las animaciones
|
||||||
AnimationsFileBuffer animation; // Objeto con las animaciones
|
|
||||||
|
|
||||||
ResourceAnimation(const std::string &name, const AnimationsFileBuffer &animation)
|
ResourceAnimation(const std::string &name, const AnimationsFileBuffer &animation)
|
||||||
: name(name), animation(animation) {}
|
: name(name), animation(animation) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estructura para el progreso de carga ---
|
// --- Estructura para el progreso de carga ---
|
||||||
struct ResourceCount
|
struct ResourceCount {
|
||||||
{
|
size_t total; // Número total de recursos
|
||||||
size_t total; // Número total de recursos
|
size_t loaded; // Número de recursos cargados
|
||||||
size_t loaded; // Número de recursos cargados
|
|
||||||
|
|
||||||
ResourceCount() : total(0), loaded(0) {}
|
ResourceCount() : total(0), loaded(0) {}
|
||||||
ResourceCount(size_t total) : total(total), loaded(0) {}
|
ResourceCount(size_t total) : total(total), loaded(0) {}
|
||||||
|
|
||||||
void add(size_t amount) { loaded += amount; }
|
void add(size_t amount) { loaded += amount; }
|
||||||
void increase() { loaded++; }
|
void increase() { loaded++; }
|
||||||
float getPercentage() const
|
float getPercentage() const {
|
||||||
{
|
|
||||||
return total > 0 ? static_cast<float>(loaded) / static_cast<float>(total) : 0.0f;
|
return total > 0 ? static_cast<float>(loaded) / static_cast<float>(total) : 0.0f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Instancia singleton ---
|
// --- Instancia singleton ---
|
||||||
static Resource *instance_; // Instancia única de Resource
|
static Resource *instance_; // Instancia única de Resource
|
||||||
|
|
||||||
// --- Vectores de recursos ---
|
// --- Vectores de recursos ---
|
||||||
std::vector<ResourceSound> sounds_; // Vector con los sonidos
|
std::vector<ResourceSound> sounds_; // Vector con los sonidos
|
||||||
std::vector<ResourceMusic> musics_; // Vector con las músicas
|
std::vector<ResourceMusic> musics_; // Vector con las músicas
|
||||||
std::vector<ResourceTexture> textures_; // Vector con las texturas
|
std::vector<ResourceTexture> textures_; // Vector con las texturas
|
||||||
std::vector<ResourceTextFile> text_files_; // Vector con los ficheros de texto
|
std::vector<ResourceTextFile> text_files_; // Vector con los ficheros de texto
|
||||||
std::vector<ResourceText> texts_; // Vector con los objetos de texto
|
std::vector<ResourceText> texts_; // Vector con los objetos de texto
|
||||||
std::vector<ResourceAnimation> animations_; // Vector con las animaciones
|
std::vector<ResourceAnimation> animations_; // Vector con las animaciones
|
||||||
std::vector<DemoData> demos_; // Vector con los ficheros de datos para el modo demostración
|
std::vector<DemoData> demos_; // Vector con los ficheros de datos para el modo demostración
|
||||||
|
|
||||||
// --- Progreso de carga ---
|
// --- Progreso de carga ---
|
||||||
ResourceCount loading_count_; // Contador de recursos cargados
|
ResourceCount loading_count_; // Contador de recursos cargados
|
||||||
std::shared_ptr<Text> loading_text_; // Texto para escribir en pantalla
|
std::shared_ptr<Text> loading_text_; // Texto para escribir en pantalla
|
||||||
std::string loading_resource_name_; // Nombre del recurso que se está cargando
|
std::string loading_resource_name_; // Nombre del recurso que se está cargando
|
||||||
SDL_FRect loading_wired_rect_;
|
SDL_FRect loading_wired_rect_;
|
||||||
SDL_FRect loading_full_rect_;
|
SDL_FRect loading_full_rect_;
|
||||||
|
|
||||||
// --- Métodos internos de carga y gestión ---
|
// --- Métodos internos de carga y gestión ---
|
||||||
void loadSounds(); // Carga los sonidos
|
void loadSounds(); // Carga los sonidos
|
||||||
void loadMusics(); // Carga las músicas
|
void loadMusics(); // Carga las músicas
|
||||||
void loadTextures(); // Carga las texturas
|
void loadTextures(); // Carga las texturas
|
||||||
void loadTextFiles(); // Carga los ficheros de texto
|
void loadTextFiles(); // Carga los ficheros de texto
|
||||||
void loadAnimations(); // Carga las animaciones
|
void loadAnimations(); // Carga las animaciones
|
||||||
void loadDemoData(); // Carga los datos para el modo demostración
|
void loadDemoData(); // Carga los datos para el modo demostración
|
||||||
void addPalettes(); // Añade paletas a las texturas
|
void addPalettes(); // Añade paletas a las texturas
|
||||||
void createTextures(); // Crea las texturas a partir de los datos cargados
|
void createTextures(); // Crea las texturas a partir de los datos cargados
|
||||||
void createText(); // Crea los objetos de texto
|
void createText(); // Crea los objetos de texto
|
||||||
void clear(); // Vacía todos los vectores de recursos
|
void clear(); // Vacía todos los vectores de recursos
|
||||||
void load(); // Carga todos los recursos
|
void load(); // Carga todos los recursos
|
||||||
void clearSounds(); // Vacía el vector de sonidos
|
void clearSounds(); // Vacía el vector de sonidos
|
||||||
void clearMusics(); // Vacía el vector de músicas
|
void clearMusics(); // Vacía el vector de músicas
|
||||||
|
|
||||||
// --- Métodos internos para gestionar el progreso ---
|
// --- Métodos internos para gestionar el progreso ---
|
||||||
void calculateTotalResources(); // Calcula el número de recursos para cargar
|
void calculateTotalResources(); // Calcula el número de recursos para cargar
|
||||||
void renderProgress(); // Muestra el progreso de carga
|
void renderProgress(); // Muestra el progreso de carga
|
||||||
void checkEvents(); // Comprueba los eventos durante la carga
|
void checkEvents(); // Comprueba los eventos durante la carga
|
||||||
void updateLoadingProgress(std::string name); // Actualiza el progreso de carga
|
void updateLoadingProgress(std::string name); // Actualiza el progreso de carga
|
||||||
void initProgressBar(); // Inicializa los rectangulos que definen la barra de progreso
|
void initProgressBar(); // Inicializa los rectangulos que definen la barra de progreso
|
||||||
void updateProgressBar(); // Actualiza la barra de estado
|
void updateProgressBar(); // Actualiza la barra de estado
|
||||||
|
|
||||||
// --- Constructores y destructor privados (singleton) ---
|
// --- Constructores y destructor privados (singleton) ---
|
||||||
Resource(); // Constructor privado
|
Resource(); // Constructor privado
|
||||||
~Resource(); // Destructor privado
|
~Resource(); // Destructor privado
|
||||||
};
|
};
|
||||||
+303
-351
@@ -1,460 +1,412 @@
|
|||||||
#include "scoreboard.h"
|
#include "scoreboard.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_DestroyTexture, SDL_SetRenderDrawColor
|
#include <SDL3/SDL.h> // Para SDL_DestroyTexture, SDL_SetRenderDrawColor
|
||||||
#include <math.h> // Para roundf
|
#include <math.h> // Para roundf
|
||||||
#include <iomanip> // Para operator<<, setfill, setw
|
|
||||||
#include <sstream> // Para basic_ostringstream, basic_ostream, basic_os...
|
|
||||||
|
|
||||||
#include "enter_name.h" // Para NAME_SIZE
|
#include <iomanip> // Para operator<<, setfill, setw
|
||||||
#include "lang.h" // Para getText
|
#include <sstream> // Para basic_ostringstream, basic_ostream, basic_os...
|
||||||
#include "param.h" // Para Param, ParamScoreboard, param
|
|
||||||
#include "resource.h" // Para Resource
|
#include "enter_name.h" // Para NAME_SIZE
|
||||||
#include "screen.h" // Para Screen
|
#include "lang.h" // Para getText
|
||||||
#include "sprite.h" // Para Sprite
|
#include "param.h" // Para Param, ParamScoreboard, param
|
||||||
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR
|
#include "resource.h" // Para Resource
|
||||||
#include "texture.h" // Para Texture
|
#include "screen.h" // Para Screen
|
||||||
|
#include "sprite.h" // Para Sprite
|
||||||
|
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR
|
||||||
|
#include "texture.h" // Para Texture
|
||||||
|
|
||||||
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
|
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
|
||||||
Scoreboard *Scoreboard::scoreboard_ = nullptr;
|
Scoreboard *Scoreboard::scoreboard_ = nullptr;
|
||||||
|
|
||||||
// [SINGLETON] Crearemos el objeto score_board con esta función estática
|
// [SINGLETON] Crearemos el objeto score_board con esta función estática
|
||||||
void Scoreboard::init()
|
void Scoreboard::init() {
|
||||||
{
|
Scoreboard::scoreboard_ = new Scoreboard();
|
||||||
Scoreboard::scoreboard_ = new Scoreboard();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// [SINGLETON] Destruiremos el objeto score_board con esta función estática
|
// [SINGLETON] Destruiremos el objeto score_board con esta función estática
|
||||||
void Scoreboard::destroy()
|
void Scoreboard::destroy() {
|
||||||
{
|
delete Scoreboard::scoreboard_;
|
||||||
delete Scoreboard::scoreboard_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// [SINGLETON] Con este método obtenemos el objeto score_board y podemos trabajar con él
|
// [SINGLETON] Con este método obtenemos el objeto score_board y podemos trabajar con él
|
||||||
Scoreboard *Scoreboard::get()
|
Scoreboard *Scoreboard::get() {
|
||||||
{
|
return Scoreboard::scoreboard_;
|
||||||
return Scoreboard::scoreboard_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Scoreboard::Scoreboard()
|
Scoreboard::Scoreboard()
|
||||||
: renderer_(Screen::get()->getRenderer()),
|
: renderer_(Screen::get()->getRenderer()),
|
||||||
game_power_meter_texture_(Resource::get()->getTexture("game_power_meter.png")),
|
game_power_meter_texture_(Resource::get()->getTexture("game_power_meter.png")),
|
||||||
power_meter_sprite_(std::make_unique<Sprite>(game_power_meter_texture_)),
|
power_meter_sprite_(std::make_unique<Sprite>(game_power_meter_texture_)),
|
||||||
text_scoreboard_(Resource::get()->getText("8bithud"))
|
text_scoreboard_(Resource::get()->getText("8bithud")) {
|
||||||
{
|
// Inicializa variables
|
||||||
// Inicializa variables
|
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i) {
|
||||||
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i)
|
name_[i].clear();
|
||||||
{
|
record_name_[i].clear();
|
||||||
name_[i].clear();
|
selector_pos_[i] = 0;
|
||||||
record_name_[i].clear();
|
score_[i] = 0;
|
||||||
selector_pos_[i] = 0;
|
mult_[i] = 0;
|
||||||
score_[i] = 0;
|
continue_counter_[i] = 0;
|
||||||
mult_[i] = 0;
|
}
|
||||||
continue_counter_[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
panel_[SCOREBOARD_LEFT_PANEL].mode = ScoreboardMode::SCORE;
|
panel_[SCOREBOARD_LEFT_PANEL].mode = ScoreboardMode::SCORE;
|
||||||
panel_[SCOREBOARD_RIGHT_PANEL].mode = ScoreboardMode::SCORE;
|
panel_[SCOREBOARD_RIGHT_PANEL].mode = ScoreboardMode::SCORE;
|
||||||
panel_[SCOREBOARD_CENTER_PANEL].mode = ScoreboardMode::STAGE_INFO;
|
panel_[SCOREBOARD_CENTER_PANEL].mode = ScoreboardMode::STAGE_INFO;
|
||||||
|
|
||||||
// Recalcula las anclas de los elementos
|
// Recalcula las anclas de los elementos
|
||||||
recalculateAnchors();
|
recalculateAnchors();
|
||||||
power_meter_sprite_->setPosition(SDL_FRect{
|
power_meter_sprite_->setPosition(SDL_FRect{
|
||||||
static_cast<float>(slot4_2_.x - 20),
|
static_cast<float>(slot4_2_.x - 20),
|
||||||
static_cast<float>(slot4_2_.y),
|
static_cast<float>(slot4_2_.y),
|
||||||
40,
|
40,
|
||||||
7});
|
7});
|
||||||
|
|
||||||
// Crea la textura de fondo
|
// Crea la textura de fondo
|
||||||
background_ = nullptr;
|
background_ = nullptr;
|
||||||
createBackgroundTexture();
|
createBackgroundTexture();
|
||||||
|
|
||||||
// Crea las texturas de los paneles
|
// Crea las texturas de los paneles
|
||||||
createPanelTextures();
|
createPanelTextures();
|
||||||
|
|
||||||
// Rellena la textura de fondo
|
// Rellena la textura de fondo
|
||||||
fillBackgroundTexture();
|
fillBackgroundTexture();
|
||||||
|
|
||||||
// Inicializa el vector de colores para el nombre
|
// Inicializa el vector de colores para el nombre
|
||||||
iniNameColors();
|
iniNameColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
Scoreboard::~Scoreboard()
|
Scoreboard::~Scoreboard() {
|
||||||
{
|
if (background_) {
|
||||||
if (background_)
|
SDL_DestroyTexture(background_);
|
||||||
{
|
}
|
||||||
SDL_DestroyTexture(background_);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto texture : panel_texture_)
|
for (auto texture : panel_texture_) {
|
||||||
{
|
if (texture) {
|
||||||
if (texture)
|
SDL_DestroyTexture(texture);
|
||||||
{
|
}
|
||||||
SDL_DestroyTexture(texture);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transforma un valor numérico en una cadena de 7 cifras
|
// Transforma un valor numérico en una cadena de 7 cifras
|
||||||
std::string Scoreboard::updateScoreText(int num)
|
std::string Scoreboard::updateScoreText(int num) {
|
||||||
{
|
std::ostringstream oss;
|
||||||
std::ostringstream oss;
|
oss << std::setw(7) << std::setfill('0') << num;
|
||||||
oss << std::setw(7) << std::setfill('0') << num;
|
return oss.str();
|
||||||
return oss.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el contador
|
// Actualiza el contador
|
||||||
void Scoreboard::updateTimeCounter()
|
void Scoreboard::updateTimeCounter() {
|
||||||
{
|
constexpr int TICKS_SPEED = 100;
|
||||||
constexpr int TICKS_SPEED = 100;
|
|
||||||
|
|
||||||
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
|
if (SDL_GetTicks() - ticks_ > TICKS_SPEED) {
|
||||||
{
|
ticks_ = SDL_GetTicks();
|
||||||
ticks_ = SDL_GetTicks();
|
++time_counter_;
|
||||||
++time_counter_;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza la lógica del marcador
|
// Actualiza la lógica del marcador
|
||||||
void Scoreboard::update()
|
void Scoreboard::update() {
|
||||||
{
|
fillBackgroundTexture();
|
||||||
fillBackgroundTexture();
|
updateTimeCounter();
|
||||||
updateTimeCounter();
|
++loop_counter_;
|
||||||
++loop_counter_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pinta el marcador
|
// Pinta el marcador
|
||||||
void Scoreboard::render()
|
void Scoreboard::render() {
|
||||||
{
|
SDL_RenderTexture(renderer_, background_, nullptr, &rect_);
|
||||||
SDL_RenderTexture(renderer_, background_, nullptr, &rect_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el valor de la variable
|
// Establece el valor de la variable
|
||||||
void Scoreboard::setColor(Color color)
|
void Scoreboard::setColor(Color color) {
|
||||||
{
|
// Actualiza las variables de colores
|
||||||
// Actualiza las variables de colores
|
color_ = color;
|
||||||
color_ = color;
|
text_color1_ = param.scoreboard.text_autocolor ? color_.lighten(100) : param.scoreboard.text_color1;
|
||||||
text_color1_ = param.scoreboard.text_autocolor ? color_.lighten(100) : param.scoreboard.text_color1;
|
text_color2_ = param.scoreboard.text_autocolor ? color_.lighten(150) : param.scoreboard.text_color2;
|
||||||
text_color2_ = param.scoreboard.text_autocolor ? color_.lighten(150) : param.scoreboard.text_color2;
|
|
||||||
|
|
||||||
// Aplica los colores
|
// Aplica los colores
|
||||||
power_meter_sprite_->getTexture()->setColor(text_color2_);
|
power_meter_sprite_->getTexture()->setColor(text_color2_);
|
||||||
fillBackgroundTexture();
|
fillBackgroundTexture();
|
||||||
iniNameColors();
|
iniNameColors();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el valor de la variable
|
// Establece el valor de la variable
|
||||||
void Scoreboard::setPos(SDL_FRect rect)
|
void Scoreboard::setPos(SDL_FRect rect) {
|
||||||
{
|
rect_ = rect;
|
||||||
rect_ = rect;
|
|
||||||
|
|
||||||
recalculateAnchors(); // Recalcula las anclas de los elementos
|
recalculateAnchors(); // Recalcula las anclas de los elementos
|
||||||
createBackgroundTexture(); // Crea la textura de fondo
|
createBackgroundTexture(); // Crea la textura de fondo
|
||||||
createPanelTextures(); // Crea las texturas de los paneles
|
createPanelTextures(); // Crea las texturas de los paneles
|
||||||
fillBackgroundTexture(); // Rellena la textura de fondo
|
fillBackgroundTexture(); // Rellena la textura de fondo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rellena los diferentes paneles del marcador
|
// Rellena los diferentes paneles del marcador
|
||||||
void Scoreboard::fillPanelTextures()
|
void Scoreboard::fillPanelTextures() {
|
||||||
{
|
// Guarda a donde apunta actualmente el renderizador
|
||||||
// Guarda a donde apunta actualmente el renderizador
|
auto temp = SDL_GetRenderTarget(renderer_);
|
||||||
auto temp = SDL_GetRenderTarget(renderer_);
|
|
||||||
|
|
||||||
// Genera el contenido de cada panel_
|
// Genera el contenido de cada panel_
|
||||||
for (size_t i = 0; i < SCOREBOARD_MAX_PANELS; ++i)
|
for (size_t i = 0; i < SCOREBOARD_MAX_PANELS; ++i) {
|
||||||
{
|
// Cambia el destino del renderizador
|
||||||
// Cambia el destino del renderizador
|
SDL_SetRenderTarget(renderer_, panel_texture_[i]);
|
||||||
SDL_SetRenderTarget(renderer_, panel_texture_[i]);
|
|
||||||
|
|
||||||
// Dibuja el fondo de la textura
|
// Dibuja el fondo de la textura
|
||||||
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
||||||
SDL_RenderClear(renderer_);
|
SDL_RenderClear(renderer_);
|
||||||
|
|
||||||
switch (panel_[i].mode)
|
switch (panel_[i].mode) {
|
||||||
{
|
case ScoreboardMode::SCORE: {
|
||||||
case ScoreboardMode::SCORE:
|
// SCORE
|
||||||
{
|
text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_1_.x, slot4_1_.y, name_[i], 1, text_color1_);
|
||||||
// SCORE
|
text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]), 1, text_color2_);
|
||||||
text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_1_.x, slot4_1_.y, name_[i], 1, text_color1_);
|
|
||||||
text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]), 1, text_color2_);
|
|
||||||
|
|
||||||
// MULT
|
// MULT
|
||||||
text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 3"), 1, text_color1_);
|
text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 3"), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_4_.x, slot4_4_.y, "x" + std::to_string(mult_[i]).substr(0, 3), 1, text_color2_);
|
text_scoreboard_->writeDX(TEXT_COLOR | TEXT_CENTER, slot4_4_.x, slot4_4_.y, "x" + std::to_string(mult_[i]).substr(0, 3), 1, text_color2_);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ScoreboardMode::DEMO:
|
case ScoreboardMode::DEMO: {
|
||||||
{
|
// DEMO MODE
|
||||||
// DEMO MODE
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 6"), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 6"), 1, text_color1_);
|
|
||||||
|
|
||||||
// PRESS START TO PLAY
|
// PRESS START TO PLAY
|
||||||
if (time_counter_ % 10 < 8)
|
if (time_counter_ % 10 < 8) {
|
||||||
{
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 8"), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 8"), 1, text_color1_);
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, Lang::getText("[SCOREBOARD] 9"), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, Lang::getText("[SCOREBOARD] 9"), 1, text_color1_);
|
}
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
case ScoreboardMode::WAITING:
|
case ScoreboardMode::WAITING: {
|
||||||
{
|
// GAME OVER
|
||||||
// GAME OVER
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 7"), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 7"), 1, text_color1_);
|
|
||||||
|
|
||||||
// PRESS START TO PLAY
|
// PRESS START TO PLAY
|
||||||
if (time_counter_ % 10 < 8)
|
if (time_counter_ % 10 < 8) {
|
||||||
{
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 8"), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 8"), 1, text_color1_);
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, Lang::getText("[SCOREBOARD] 9"), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, Lang::getText("[SCOREBOARD] 9"), 1, text_color1_);
|
}
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
case ScoreboardMode::GAME_OVER:
|
case ScoreboardMode::GAME_OVER: {
|
||||||
{
|
// GAME OVER
|
||||||
// GAME OVER
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 7"), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 7"), 1, text_color1_);
|
|
||||||
|
|
||||||
// PLEASE WAIT
|
// PLEASE WAIT
|
||||||
if (time_counter_ % 10 < 8)
|
if (time_counter_ % 10 < 8) {
|
||||||
{
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 12"), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 12"), 1, text_color1_);
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, Lang::getText("[SCOREBOARD] 13"), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, Lang::getText("[SCOREBOARD] 13"), 1, text_color1_);
|
}
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
case ScoreboardMode::STAGE_INFO:
|
case ScoreboardMode::STAGE_INFO: {
|
||||||
{
|
// STAGE
|
||||||
// STAGE
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, Lang::getText("[SCOREBOARD] 5") + std::to_string(stage_), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, Lang::getText("[SCOREBOARD] 5") + std::to_string(stage_), 1, text_color1_);
|
|
||||||
|
|
||||||
// POWERMETER
|
// POWERMETER
|
||||||
power_meter_sprite_->setSpriteClip(0, 0, 40, 7);
|
power_meter_sprite_->setSpriteClip(0, 0, 40, 7);
|
||||||
power_meter_sprite_->render();
|
power_meter_sprite_->render();
|
||||||
power_meter_sprite_->setSpriteClip(40, 0, int(power_ * 40.0f), 7);
|
power_meter_sprite_->setSpriteClip(40, 0, int(power_ * 40.0f), 7);
|
||||||
power_meter_sprite_->render();
|
power_meter_sprite_->render();
|
||||||
|
|
||||||
// HI-SCORE
|
// HI-SCORE
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 4"), 1, text_color1_);
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 4"), 1, text_color1_);
|
||||||
const std::string name = hi_score_name_ == "" ? "" : hi_score_name_ + " - ";
|
const std::string name = hi_score_name_ == "" ? "" : hi_score_name_ + " - ";
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y, name + updateScoreText(hi_score_), 1, text_color2_);
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y, name + updateScoreText(hi_score_), 1, text_color2_);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ScoreboardMode::CONTINUE:
|
case ScoreboardMode::CONTINUE: {
|
||||||
{
|
// SCORE
|
||||||
// SCORE
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, name_[i], 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, name_[i], 1, text_color1_);
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]), 1, text_color2_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]), 1, text_color2_);
|
|
||||||
|
|
||||||
// CONTINUE
|
// CONTINUE
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 10"), 1, text_color1_);
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 10"), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y, std::to_string(continue_counter_[i]), 1, text_color2_);
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y, std::to_string(continue_counter_[i]), 1, text_color2_);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ScoreboardMode::ENTER_NAME:
|
case ScoreboardMode::ENTER_NAME: {
|
||||||
{
|
// SCORE
|
||||||
// SCORE
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, name_[i], 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, name_[i], 1, text_color1_);
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]), 1, text_color2_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]), 1, text_color2_);
|
|
||||||
|
|
||||||
// ENTER NAME
|
// ENTER NAME
|
||||||
{
|
{
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_);
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_);
|
||||||
SDL_FRect rect = {enter_name_pos_.x, enter_name_pos_.y, 5.0f, 7.0f};
|
SDL_FRect rect = {enter_name_pos_.x, enter_name_pos_.y, 5.0f, 7.0f};
|
||||||
|
|
||||||
// Recorre todos los slots de letras del nombre
|
// Recorre todos los slots de letras del nombre
|
||||||
for (size_t j = 0; j < NAME_SIZE; ++j)
|
for (size_t j = 0; j < NAME_SIZE; ++j) {
|
||||||
{
|
// Selecciona el color
|
||||||
// Selecciona el color
|
const Color color = j < selector_pos_[i] ? text_color2_ : text_color1_;
|
||||||
const Color color = j < selector_pos_[i] ? text_color2_ : text_color1_;
|
|
||||||
|
|
||||||
if (j != selector_pos_[i] || time_counter_ % 3 == 0)
|
if (j != selector_pos_[i] || time_counter_ % 3 == 0) {
|
||||||
{
|
// Dibuja la linea
|
||||||
// Dibuja la linea
|
if (j >= selector_pos_[i]) {
|
||||||
if (j >= selector_pos_[i])
|
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 255);
|
||||||
{
|
SDL_RenderLine(renderer_, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h);
|
||||||
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 255);
|
}
|
||||||
SDL_RenderLine(renderer_, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja la letra
|
// Dibuja la letra
|
||||||
if (j < record_name_[i].size())
|
if (j < record_name_[i].size()) {
|
||||||
{
|
text_scoreboard_->writeColored(rect.x, rect.y, record_name_[i].substr(j, 1), color);
|
||||||
text_scoreboard_->writeColored(rect.x, rect.y, record_name_[i].substr(j, 1), color);
|
}
|
||||||
}
|
}
|
||||||
}
|
rect.x += 7;
|
||||||
rect.x += 7;
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
}
|
||||||
}
|
case ScoreboardMode::SHOW_NAME: {
|
||||||
case ScoreboardMode::SHOW_NAME:
|
// SCORE
|
||||||
{
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, name_[i], 1, text_color1_);
|
||||||
// SCORE
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]), 1, text_color2_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y, name_[i], 1, text_color1_);
|
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]), 1, text_color2_);
|
|
||||||
|
|
||||||
// NAME
|
// NAME
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_);
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y, Lang::getText("[SCOREBOARD] 11"), 1, text_color1_);
|
||||||
|
|
||||||
/* TEXTO CENTRADO */
|
/* TEXTO CENTRADO */
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y, record_name_[i], 1, getColorLikeKnightRider(name_colors_, loop_counter_ / 5));
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y, record_name_[i], 1, getColorLikeKnightRider(name_colors_, loop_counter_ / 5));
|
||||||
|
|
||||||
/* TEXTO A LA IZQUIERDA */
|
/* TEXTO A LA IZQUIERDA */
|
||||||
// text_scoreboard_->writeColored(enter_name_pos_.x, enter_name_pos_.y, record_name_[i], getColorLikeKnightRider(name_colors_, loop_counter_ / 5));
|
// text_scoreboard_->writeColored(enter_name_pos_.x, enter_name_pos_.y, record_name_[i], getColorLikeKnightRider(name_colors_, loop_counter_ / 5));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ScoreboardMode::GAME_COMPLETED:
|
case ScoreboardMode::GAME_COMPLETED: {
|
||||||
{
|
// GAME OVER
|
||||||
// GAME OVER
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 7"), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_1_.x, slot4_1_.y + 4, Lang::getText("[SCOREBOARD] 7"), 1, text_color1_);
|
|
||||||
|
|
||||||
// SCORE
|
// SCORE
|
||||||
if (time_counter_ % 10 < 8)
|
if (time_counter_ % 10 < 8) {
|
||||||
{
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 14"), 1, text_color1_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_3_.x, slot4_3_.y - 2, Lang::getText("[SCOREBOARD] 14"), 1, text_color1_);
|
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, updateScoreText(score_[i]), 1, text_color2_);
|
||||||
text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y - 2, updateScoreText(score_[i]), 1, text_color2_);
|
}
|
||||||
}
|
}
|
||||||
}
|
default:
|
||||||
default:
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Deja el renderizador apuntando donde estaba
|
// Deja el renderizador apuntando donde estaba
|
||||||
SDL_SetRenderTarget(renderer_, temp);
|
SDL_SetRenderTarget(renderer_, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rellena la textura de fondo
|
// Rellena la textura de fondo
|
||||||
void Scoreboard::fillBackgroundTexture()
|
void Scoreboard::fillBackgroundTexture() {
|
||||||
{
|
// Rellena los diferentes paneles del marcador
|
||||||
// Rellena los diferentes paneles del marcador
|
fillPanelTextures();
|
||||||
fillPanelTextures();
|
|
||||||
|
|
||||||
// Cambia el destino del renderizador
|
// Cambia el destino del renderizador
|
||||||
SDL_Texture *temp = SDL_GetRenderTarget(renderer_);
|
SDL_Texture *temp = SDL_GetRenderTarget(renderer_);
|
||||||
SDL_SetRenderTarget(renderer_, background_);
|
SDL_SetRenderTarget(renderer_, background_);
|
||||||
|
|
||||||
// Dibuja el fondo del marcador
|
// Dibuja el fondo del marcador
|
||||||
SDL_SetRenderDrawColor(renderer_, color_.r, color_.g, color_.b, 255);
|
SDL_SetRenderDrawColor(renderer_, color_.r, color_.g, color_.b, 255);
|
||||||
SDL_RenderClear(renderer_);
|
SDL_RenderClear(renderer_);
|
||||||
|
|
||||||
// Copia las texturas de los paneles
|
// Copia las texturas de los paneles
|
||||||
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i)
|
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i) {
|
||||||
{
|
SDL_RenderTexture(renderer_, panel_texture_[i], nullptr, &panel_[i].pos);
|
||||||
SDL_RenderTexture(renderer_, panel_texture_[i], nullptr, &panel_[i].pos);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Dibuja la linea que separa la zona de juego del marcador
|
// Dibuja la linea que separa la zona de juego del marcador
|
||||||
renderSeparator();
|
renderSeparator();
|
||||||
|
|
||||||
// Deja el renderizador apuntando donde estaba
|
// Deja el renderizador apuntando donde estaba
|
||||||
SDL_SetRenderTarget(renderer_, temp);
|
SDL_SetRenderTarget(renderer_, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recalcula las anclas de los elementos
|
// Recalcula las anclas de los elementos
|
||||||
void Scoreboard::recalculateAnchors()
|
void Scoreboard::recalculateAnchors() {
|
||||||
{
|
// Recalcula la posición y el tamaño de los paneles
|
||||||
// Recalcula la posición y el tamaño de los paneles
|
const float panel_width = (float)rect_.w / (float)SCOREBOARD_MAX_PANELS;
|
||||||
const float panel_width = (float)rect_.w / (float)SCOREBOARD_MAX_PANELS;
|
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i) {
|
||||||
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i)
|
panel_[i].pos.x = roundf(panel_width * i);
|
||||||
{
|
panel_[i].pos.y = 0;
|
||||||
panel_[i].pos.x = roundf(panel_width * i);
|
panel_[i].pos.w = roundf(panel_width * (i + 1)) - panel_[i].pos.x;
|
||||||
panel_[i].pos.y = 0;
|
panel_[i].pos.h = rect_.h;
|
||||||
panel_[i].pos.w = roundf(panel_width * (i + 1)) - panel_[i].pos.x;
|
}
|
||||||
panel_[i].pos.h = rect_.h;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constantes para definir las zonas del panel_: 4 filas y 1 columna
|
// Constantes para definir las zonas del panel_: 4 filas y 1 columna
|
||||||
const int ROW_SIZE = rect_.h / 4;
|
const int ROW_SIZE = rect_.h / 4;
|
||||||
const int TEXT_HEIGHT = 7;
|
const int TEXT_HEIGHT = 7;
|
||||||
|
|
||||||
// Filas
|
// Filas
|
||||||
const float ROW1 = 1 + (ROW_SIZE * 0) + (TEXT_HEIGHT / 2);
|
const float ROW1 = 1 + (ROW_SIZE * 0) + (TEXT_HEIGHT / 2);
|
||||||
const float ROW2 = 1 + (ROW_SIZE * 1) + (TEXT_HEIGHT / 2) - 1;
|
const float ROW2 = 1 + (ROW_SIZE * 1) + (TEXT_HEIGHT / 2) - 1;
|
||||||
const float ROW3 = 1 + (ROW_SIZE * 2) + (TEXT_HEIGHT / 2) - 2;
|
const float ROW3 = 1 + (ROW_SIZE * 2) + (TEXT_HEIGHT / 2) - 2;
|
||||||
const float ROW4 = 1 + (ROW_SIZE * 3) + (TEXT_HEIGHT / 2) - 3;
|
const float ROW4 = 1 + (ROW_SIZE * 3) + (TEXT_HEIGHT / 2) - 3;
|
||||||
|
|
||||||
// Columna
|
// Columna
|
||||||
const float COL = panel_width / 2;
|
const float COL = panel_width / 2;
|
||||||
|
|
||||||
// Slots de 4
|
// Slots de 4
|
||||||
slot4_1_ = {COL, ROW1};
|
slot4_1_ = {COL, ROW1};
|
||||||
slot4_2_ = {COL, ROW2};
|
slot4_2_ = {COL, ROW2};
|
||||||
slot4_3_ = {COL, ROW3};
|
slot4_3_ = {COL, ROW3};
|
||||||
slot4_4_ = {COL, ROW4};
|
slot4_4_ = {COL, ROW4};
|
||||||
|
|
||||||
// Primer cuadrado para poner el nombre de record
|
// Primer cuadrado para poner el nombre de record
|
||||||
const int enter_name_lenght = text_scoreboard_->lenght(std::string(NAME_SIZE, 'A'));
|
const int enter_name_lenght = text_scoreboard_->lenght(std::string(NAME_SIZE, 'A'));
|
||||||
enter_name_pos_.x = COL - (enter_name_lenght / 2);
|
enter_name_pos_.x = COL - (enter_name_lenght / 2);
|
||||||
enter_name_pos_.y = ROW4;
|
enter_name_pos_.y = ROW4;
|
||||||
|
|
||||||
// Recoloca los sprites
|
// Recoloca los sprites
|
||||||
if (power_meter_sprite_)
|
if (power_meter_sprite_) {
|
||||||
{
|
power_meter_sprite_->setX(slot4_2_.x - 20);
|
||||||
power_meter_sprite_->setX(slot4_2_.x - 20);
|
power_meter_sprite_->setY(slot4_2_.y);
|
||||||
power_meter_sprite_->setY(slot4_2_.y);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea la textura de fondo
|
// Crea la textura de fondo
|
||||||
void Scoreboard::createBackgroundTexture()
|
void Scoreboard::createBackgroundTexture() {
|
||||||
{
|
// Elimina la textura en caso de existir
|
||||||
// Elimina la textura en caso de existir
|
if (background_) {
|
||||||
if (background_)
|
SDL_DestroyTexture(background_);
|
||||||
{
|
}
|
||||||
SDL_DestroyTexture(background_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recrea la textura de fondo
|
// Recrea la textura de fondo
|
||||||
background_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
|
background_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, rect_.w, rect_.h);
|
||||||
SDL_SetTextureBlendMode(background_, SDL_BLENDMODE_BLEND);
|
SDL_SetTextureBlendMode(background_, SDL_BLENDMODE_BLEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea las texturas de los paneles
|
// Crea las texturas de los paneles
|
||||||
void Scoreboard::createPanelTextures()
|
void Scoreboard::createPanelTextures() {
|
||||||
{
|
// Elimina las texturas en caso de existir
|
||||||
// Elimina las texturas en caso de existir
|
for (auto texture : panel_texture_) {
|
||||||
for (auto texture : panel_texture_)
|
if (texture != nullptr) {
|
||||||
{
|
SDL_DestroyTexture(texture);
|
||||||
if (texture != nullptr)
|
}
|
||||||
{
|
}
|
||||||
SDL_DestroyTexture(texture);
|
panel_texture_.clear();
|
||||||
}
|
|
||||||
}
|
|
||||||
panel_texture_.clear();
|
|
||||||
|
|
||||||
// Crea las texturas para cada panel_
|
// Crea las texturas para cada panel_
|
||||||
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i)
|
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i) {
|
||||||
{
|
SDL_Texture *tex = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, panel_[i].pos.w, panel_[i].pos.h);
|
||||||
SDL_Texture *tex = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, panel_[i].pos.w, panel_[i].pos.h);
|
SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND);
|
||||||
SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND);
|
panel_texture_.push_back(tex);
|
||||||
panel_texture_.push_back(tex);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja la linea que separa la zona de juego del marcador
|
// Dibuja la linea que separa la zona de juego del marcador
|
||||||
void Scoreboard::renderSeparator()
|
void Scoreboard::renderSeparator() {
|
||||||
{
|
// Dibuja la linea que separa el marcador de la zona de juego
|
||||||
// Dibuja la linea que separa el marcador de la zona de juego
|
auto color = param.scoreboard.separator_autocolor ? color_.darken() : param.scoreboard.separator_color;
|
||||||
auto color = param.scoreboard.separator_autocolor ? color_.darken() : param.scoreboard.separator_color;
|
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 255);
|
||||||
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 255);
|
SDL_RenderLine(renderer_, 0, 0, rect_.w, 0);
|
||||||
SDL_RenderLine(renderer_, 0, 0, rect_.w, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa el vector de colores para el nombre
|
// Inicializa el vector de colores para el nombre
|
||||||
void Scoreboard::iniNameColors()
|
void Scoreboard::iniNameColors() {
|
||||||
{
|
Color color = color_.inverse();
|
||||||
Color color = color_.inverse();
|
|
||||||
|
|
||||||
name_colors_.clear();
|
name_colors_.clear();
|
||||||
name_colors_.emplace_back(color.lighten(50));
|
name_colors_.emplace_back(color.lighten(50));
|
||||||
name_colors_.emplace_back(color.lighten(25));
|
name_colors_.emplace_back(color.lighten(25));
|
||||||
name_colors_.emplace_back(color);
|
name_colors_.emplace_back(color);
|
||||||
name_colors_.emplace_back(color.darken(25));
|
name_colors_.emplace_back(color.darken(25));
|
||||||
}
|
}
|
||||||
+90
-92
@@ -1,12 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FPoint, SDL_GetTicks, SDL_FRect, SDL_Texture, SDL_Renderer, Uint64
|
#include <SDL3/SDL.h> // Para SDL_FPoint, SDL_GetTicks, SDL_FRect, SDL_Texture, SDL_Renderer, Uint64
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
#include <memory> // Para shared_ptr, unique_ptr
|
|
||||||
#include <string> // Para basic_string, string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "utils.h" // Para Color
|
#include <memory> // Para shared_ptr, unique_ptr
|
||||||
|
#include <string> // Para basic_string, string
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
|
#include "utils.h" // Para Color
|
||||||
|
|
||||||
class Sprite;
|
class Sprite;
|
||||||
class Text;
|
class Text;
|
||||||
@@ -19,105 +20,102 @@ constexpr int SCOREBOARD_RIGHT_PANEL = 2;
|
|||||||
constexpr int SCOREBOARD_MAX_PANELS = 3;
|
constexpr int SCOREBOARD_MAX_PANELS = 3;
|
||||||
|
|
||||||
// --- Enums ---
|
// --- Enums ---
|
||||||
enum class ScoreboardMode : int
|
enum class ScoreboardMode : int {
|
||||||
{
|
SCORE,
|
||||||
SCORE,
|
STAGE_INFO,
|
||||||
STAGE_INFO,
|
CONTINUE,
|
||||||
CONTINUE,
|
WAITING,
|
||||||
WAITING,
|
GAME_OVER,
|
||||||
GAME_OVER,
|
DEMO,
|
||||||
DEMO,
|
ENTER_NAME,
|
||||||
ENTER_NAME,
|
SHOW_NAME,
|
||||||
SHOW_NAME,
|
GAME_COMPLETED,
|
||||||
GAME_COMPLETED,
|
NUM_MODES,
|
||||||
NUM_MODES,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Structs ---
|
// --- Structs ---
|
||||||
struct Panel
|
struct Panel {
|
||||||
{
|
ScoreboardMode mode; // Modo en el que se encuentra el panel
|
||||||
ScoreboardMode mode; // Modo en el que se encuentra el panel
|
SDL_FRect pos; // Posición donde dibujar el panel dentro del marcador
|
||||||
SDL_FRect pos; // Posición donde dibujar el panel dentro del marcador
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Clase Scoreboard ---
|
// --- Clase Scoreboard ---
|
||||||
class Scoreboard
|
class Scoreboard {
|
||||||
{
|
public:
|
||||||
public:
|
// --- Métodos de singleton ---
|
||||||
// --- Métodos de singleton ---
|
static void init(); // Crea el objeto Scoreboard
|
||||||
static void init(); // Crea el objeto Scoreboard
|
static void destroy(); // Libera el objeto Scoreboard
|
||||||
static void destroy(); // Libera el objeto Scoreboard
|
static Scoreboard *get(); // Obtiene el puntero al objeto Scoreboard
|
||||||
static Scoreboard *get(); // Obtiene el puntero al objeto Scoreboard
|
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
void update(); // Actualiza la lógica del marcador
|
void update(); // Actualiza la lógica del marcador
|
||||||
void render(); // Pinta el marcador
|
void render(); // Pinta el marcador
|
||||||
|
|
||||||
// --- Setters ---
|
// --- Setters ---
|
||||||
void setColor(Color color); // Establece el color del marcador
|
void setColor(Color color); // Establece el color del marcador
|
||||||
void setPos(SDL_FRect rect); // Establece la posición y tamaño del marcador
|
void setPos(SDL_FRect rect); // Establece la posición y tamaño del marcador
|
||||||
void setContinue(int panel, int continue_counter) { continue_counter_[panel] = continue_counter; }
|
void setContinue(int panel, int continue_counter) { continue_counter_[panel] = continue_counter; }
|
||||||
void setHiScore(int hi_score) { hi_score_ = hi_score; }
|
void setHiScore(int hi_score) { hi_score_ = hi_score; }
|
||||||
void setHiScoreName(const std::string &name) { hi_score_name_ = name; }
|
void setHiScoreName(const std::string &name) { hi_score_name_ = name; }
|
||||||
void setMode(int index, ScoreboardMode mode) { panel_[index].mode = mode; }
|
void setMode(int index, ScoreboardMode mode) { panel_[index].mode = mode; }
|
||||||
void setMult(int panel, float mult) { mult_[panel] = mult; }
|
void setMult(int panel, float mult) { mult_[panel] = mult; }
|
||||||
void setName(int panel, const std::string &name) { name_[panel] = name; }
|
void setName(int panel, const std::string &name) { name_[panel] = name; }
|
||||||
void setPower(float power) { power_ = power; }
|
void setPower(float power) { power_ = power; }
|
||||||
void setRecordName(int panel, const std::string &record_name) { record_name_[panel] = record_name; }
|
void setRecordName(int panel, const std::string &record_name) { record_name_[panel] = record_name; }
|
||||||
void setScore(int panel, int score) { score_[panel] = score; }
|
void setScore(int panel, int score) { score_[panel] = score; }
|
||||||
void setSelectorPos(int panel, int pos) { selector_pos_[panel] = pos; }
|
void setSelectorPos(int panel, int pos) { selector_pos_[panel] = pos; }
|
||||||
void setStage(int stage) { stage_ = stage; }
|
void setStage(int stage) { stage_ = stage; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Singleton ---
|
// --- Singleton ---
|
||||||
static Scoreboard *scoreboard_;
|
static Scoreboard *scoreboard_;
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
SDL_Renderer *renderer_; // El renderizador de la ventana
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
std::shared_ptr<Texture> game_power_meter_texture_; // Textura con el marcador de poder de la fase
|
std::shared_ptr<Texture> game_power_meter_texture_; // Textura con el marcador de poder de la fase
|
||||||
std::unique_ptr<Sprite> power_meter_sprite_; // Sprite para el medidor de poder de la fase
|
std::unique_ptr<Sprite> power_meter_sprite_; // Sprite para el medidor de poder de la fase
|
||||||
std::shared_ptr<Text> text_scoreboard_; // Fuente para el marcador del juego
|
std::shared_ptr<Text> text_scoreboard_; // Fuente para el marcador del juego
|
||||||
SDL_Texture *background_ = nullptr; // Textura para dibujar el marcador
|
SDL_Texture *background_ = nullptr; // Textura para dibujar el marcador
|
||||||
std::vector<SDL_Texture *> panel_texture_; // Texturas para dibujar cada panel
|
std::vector<SDL_Texture *> panel_texture_; // Texturas para dibujar cada panel
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
std::string name_[SCOREBOARD_MAX_PANELS] = {}; // Nombre de cada jugador
|
std::string name_[SCOREBOARD_MAX_PANELS] = {}; // Nombre de cada jugador
|
||||||
std::string record_name_[SCOREBOARD_MAX_PANELS] = {}; // Nombre introducido para la tabla de records
|
std::string record_name_[SCOREBOARD_MAX_PANELS] = {}; // Nombre introducido para la tabla de records
|
||||||
size_t selector_pos_[SCOREBOARD_MAX_PANELS] = {}; // Posición del selector de letra para introducir el nombre
|
size_t selector_pos_[SCOREBOARD_MAX_PANELS] = {}; // Posición del selector de letra para introducir el nombre
|
||||||
int score_[SCOREBOARD_MAX_PANELS] = {}; // Puntuación de los jugadores
|
int score_[SCOREBOARD_MAX_PANELS] = {}; // Puntuación de los jugadores
|
||||||
float mult_[SCOREBOARD_MAX_PANELS] = {}; // Multiplicador de los jugadores
|
float mult_[SCOREBOARD_MAX_PANELS] = {}; // Multiplicador de los jugadores
|
||||||
int continue_counter_[SCOREBOARD_MAX_PANELS] = {}; // Tiempo para continuar de los jugadores
|
int continue_counter_[SCOREBOARD_MAX_PANELS] = {}; // Tiempo para continuar de los jugadores
|
||||||
Panel panel_[SCOREBOARD_MAX_PANELS] = {}; // Lista con todos los paneles del marcador
|
Panel panel_[SCOREBOARD_MAX_PANELS] = {}; // Lista con todos los paneles del marcador
|
||||||
int stage_ = 1; // Número de fase actual
|
int stage_ = 1; // Número de fase actual
|
||||||
int hi_score_ = 0; // Máxima puntuación
|
int hi_score_ = 0; // Máxima puntuación
|
||||||
float power_ = 0; // Poder actual de la fase
|
float power_ = 0; // Poder actual de la fase
|
||||||
std::string hi_score_name_ = std::string(); // Nombre del jugador con la máxima puntuación
|
std::string hi_score_name_ = std::string(); // Nombre del jugador con la máxima puntuación
|
||||||
Color color_ = Color(); // Color del marcador
|
Color color_ = Color(); // Color del marcador
|
||||||
SDL_FRect rect_ = {0, 0, 320, 40}; // Posición y dimensiones del marcador
|
SDL_FRect rect_ = {0, 0, 320, 40}; // Posición y dimensiones del marcador
|
||||||
Uint64 ticks_ = SDL_GetTicks(); // Variable donde almacenar el valor de SDL_GetTicks()
|
Uint64 ticks_ = SDL_GetTicks(); // Variable donde almacenar el valor de SDL_GetTicks()
|
||||||
int time_counter_ = 0; // Contador de segundos
|
int time_counter_ = 0; // Contador de segundos
|
||||||
int loop_counter_ = 0; // Contador de bucle
|
int loop_counter_ = 0; // Contador de bucle
|
||||||
std::vector<Color> name_colors_; // Colores para destacar el nombre una vez introducido
|
std::vector<Color> name_colors_; // Colores para destacar el nombre una vez introducido
|
||||||
|
|
||||||
// --- Variables de aspecto ---
|
// --- Variables de aspecto ---
|
||||||
Color text_color1_, text_color2_; // Colores para los marcadores del texto;
|
Color text_color1_, text_color2_; // Colores para los marcadores del texto;
|
||||||
|
|
||||||
// --- Puntos predefinidos para colocar elementos en los paneles ---
|
// --- Puntos predefinidos para colocar elementos en los paneles ---
|
||||||
SDL_FPoint slot4_1_, slot4_2_, slot4_3_, slot4_4_;
|
SDL_FPoint slot4_1_, slot4_2_, slot4_3_, slot4_4_;
|
||||||
SDL_FPoint enter_name_pos_;
|
SDL_FPoint enter_name_pos_;
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void recalculateAnchors(); // Recalcula las anclas de los elementos
|
void recalculateAnchors(); // Recalcula las anclas de los elementos
|
||||||
std::string updateScoreText(int num); // Transforma un valor numérico en una cadena de 7 cifras
|
std::string updateScoreText(int num); // Transforma un valor numérico en una cadena de 7 cifras
|
||||||
void createBackgroundTexture(); // Crea la textura de fondo
|
void createBackgroundTexture(); // Crea la textura de fondo
|
||||||
void createPanelTextures(); // Crea las texturas de los paneles
|
void createPanelTextures(); // Crea las texturas de los paneles
|
||||||
void fillPanelTextures(); // Rellena los diferentes paneles del marcador
|
void fillPanelTextures(); // Rellena los diferentes paneles del marcador
|
||||||
void fillBackgroundTexture(); // Rellena la textura de fondo
|
void fillBackgroundTexture(); // Rellena la textura de fondo
|
||||||
void updateTimeCounter(); // Actualiza el contador
|
void updateTimeCounter(); // Actualiza el contador
|
||||||
void renderSeparator(); // Dibuja la línea que separa la zona de juego del marcador
|
void renderSeparator(); // Dibuja la línea que separa la zona de juego del marcador
|
||||||
void iniNameColors(); // Inicializa el vector de colores para el nombre
|
void iniNameColors(); // Inicializa el vector de colores para el nombre
|
||||||
|
|
||||||
// --- Constructor y destructor privados (singleton) ---
|
// --- Constructor y destructor privados (singleton) ---
|
||||||
Scoreboard();
|
Scoreboard();
|
||||||
~Scoreboard();
|
~Scoreboard();
|
||||||
};
|
};
|
||||||
+96
-147
@@ -1,21 +1,22 @@
|
|||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_SetRenderTarget, SDL_LogCategory
|
#include <SDL3/SDL.h> // Para SDL_SetRenderTarget, SDL_LogCategory
|
||||||
|
|
||||||
#include <algorithm> // Para min, max
|
#include <algorithm> // Para min, max
|
||||||
#include <fstream> // Para basic_ifstream, ifstream
|
#include <fstream> // Para basic_ifstream, ifstream
|
||||||
#include <iterator> // Para istreambuf_iterator, operator==
|
#include <iterator> // Para istreambuf_iterator, operator==
|
||||||
#include <memory> // Para allocator, shared_ptr, __shared_pt...
|
#include <memory> // Para allocator, shared_ptr, __shared_pt...
|
||||||
#include <string> // Para basic_string, char_traits, operator+
|
#include <string> // Para basic_string, char_traits, operator+
|
||||||
|
|
||||||
#include "asset.h" // Para Asset
|
#include "asset.h" // Para Asset
|
||||||
#include "external/jail_shader.h" // Para init, render
|
#include "external/jail_shader.h" // Para init, render
|
||||||
#include "mouse.h" // Para updateCursorVisibility
|
#include "mouse.h" // Para updateCursorVisibility
|
||||||
#include "notifier.h" // Para Notifier
|
#include "notifier.h" // Para Notifier
|
||||||
#include "options.h" // Para VideoOptions, video, WindowOptions
|
#include "options.h" // Para VideoOptions, video, WindowOptions
|
||||||
#include "param.h" // Para Param, param, ParamGame, ParamDebug
|
#include "param.h" // Para Param, param, ParamGame, ParamDebug
|
||||||
#include "text.h" // Para Text, TEXT_COLOR, TEXT_STROKE
|
#include "text.h" // Para Text, TEXT_COLOR, TEXT_STROKE
|
||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
#include "ui/service_menu.h" // Para ServiceMenu
|
#include "ui/service_menu.h" // Para ServiceMenu
|
||||||
|
|
||||||
// Singleton
|
// Singleton
|
||||||
Screen *Screen::instance_ = nullptr;
|
Screen *Screen::instance_ = nullptr;
|
||||||
@@ -27,7 +28,7 @@ void Screen::init() { Screen::instance_ = new Screen(); }
|
|||||||
void Screen::destroy() { delete Screen::instance_; }
|
void Screen::destroy() { delete Screen::instance_; }
|
||||||
|
|
||||||
// Obtiene la instancia
|
// Obtiene la instancia
|
||||||
Screen *Screen::get() { return Screen::instance_; }
|
auto Screen::get() -> Screen * { return Screen::instance_; }
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Screen::Screen()
|
Screen::Screen()
|
||||||
@@ -36,9 +37,8 @@ Screen::Screen()
|
|||||||
game_canvas_(nullptr),
|
game_canvas_(nullptr),
|
||||||
service_menu_(nullptr),
|
service_menu_(nullptr),
|
||||||
notifier_(nullptr),
|
notifier_(nullptr),
|
||||||
src_rect_(SDL_FRect{0, 0, static_cast<float>(param.game.width), static_cast<float>(param.game.height)}),
|
src_rect_(SDL_FRect{0, 0, param.game.width, param.game.height}),
|
||||||
dst_rect_(SDL_FRect{0, 0, static_cast<float>(param.game.width), static_cast<float>(param.game.height)})
|
dst_rect_(SDL_FRect{0, 0, param.game.width, param.game.height}) {
|
||||||
{
|
|
||||||
// Arranca SDL VIDEO, crea la ventana y el renderizador
|
// Arranca SDL VIDEO, crea la ventana y el renderizador
|
||||||
initSDLVideo();
|
initSDLVideo();
|
||||||
|
|
||||||
@@ -61,16 +61,14 @@ Screen::Screen()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
Screen::~Screen()
|
Screen::~Screen() {
|
||||||
{
|
|
||||||
SDL_DestroyTexture(game_canvas_);
|
SDL_DestroyTexture(game_canvas_);
|
||||||
SDL_DestroyRenderer(renderer_);
|
SDL_DestroyRenderer(renderer_);
|
||||||
SDL_DestroyWindow(window_);
|
SDL_DestroyWindow(window_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Limpia la pantalla
|
// Limpia la pantalla
|
||||||
void Screen::clean(Color color)
|
void Screen::clean(Color color) {
|
||||||
{
|
|
||||||
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 0xFF);
|
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 0xFF);
|
||||||
SDL_RenderClear(renderer_);
|
SDL_RenderClear(renderer_);
|
||||||
}
|
}
|
||||||
@@ -79,75 +77,59 @@ void Screen::clean(Color color)
|
|||||||
void Screen::start() { SDL_SetRenderTarget(renderer_, game_canvas_); }
|
void Screen::start() { SDL_SetRenderTarget(renderer_, game_canvas_); }
|
||||||
|
|
||||||
// Vuelca el contenido del renderizador en pantalla
|
// Vuelca el contenido del renderizador en pantalla
|
||||||
void Screen::render()
|
void Screen::render() {
|
||||||
{
|
|
||||||
fps_.increment();
|
fps_.increment();
|
||||||
|
renderOverlays(); // Renderiza todos los overlays y efectos
|
||||||
// Renderiza todos los overlays y efectos
|
renderScreen(); // Renderiza el contenido del game_canvas_
|
||||||
renderOverlays();
|
|
||||||
|
|
||||||
// Renderiza el contenido del game_canvas_
|
|
||||||
renderScreen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vuelca el contenido del renderizador en pantalla exceptuando ciertas partes
|
// Vuelca el contenido del renderizador en pantalla exceptuando ciertas partes
|
||||||
void Screen::coreRender()
|
void Screen::coreRender() {
|
||||||
{
|
|
||||||
fps_.increment();
|
fps_.increment();
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
renderInfo();
|
renderInfo();
|
||||||
#endif
|
#endif
|
||||||
renderScreen();
|
renderScreen(); // Renderiza el contenido del game_canvas_
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderiza el contenido del game_canvas_
|
// Renderiza el contenido del game_canvas_
|
||||||
void Screen::renderScreen()
|
void Screen::renderScreen() {
|
||||||
{
|
|
||||||
SDL_SetRenderTarget(renderer_, nullptr);
|
SDL_SetRenderTarget(renderer_, nullptr);
|
||||||
clean();
|
clean();
|
||||||
|
|
||||||
if (Options::video.shaders)
|
if (Options::video.shaders) {
|
||||||
{
|
|
||||||
shader::render();
|
shader::render();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
SDL_RenderTexture(renderer_, game_canvas_, nullptr, nullptr);
|
SDL_RenderTexture(renderer_, game_canvas_, nullptr, nullptr);
|
||||||
SDL_RenderPresent(renderer_);
|
SDL_RenderPresent(renderer_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el modo de video
|
// Establece el modo de video
|
||||||
void Screen::setFullscreenMode()
|
void Screen::setFullscreenMode() {
|
||||||
{
|
|
||||||
SDL_SetWindowFullscreen(window_, Options::video.fullscreen);
|
SDL_SetWindowFullscreen(window_, Options::video.fullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Camibia entre pantalla completa y ventana
|
// Camibia entre pantalla completa y ventana
|
||||||
void Screen::toggleFullscreen()
|
void Screen::toggleFullscreen() {
|
||||||
{
|
|
||||||
Options::video.fullscreen = !Options::video.fullscreen;
|
Options::video.fullscreen = !Options::video.fullscreen;
|
||||||
setFullscreenMode();
|
setFullscreenMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cambia el tamaño de la ventana
|
// Cambia el tamaño de la ventana
|
||||||
void Screen::setWindowZoom(int zoom)
|
void Screen::setWindowZoom(int zoom) {
|
||||||
{
|
|
||||||
Options::window.size = zoom;
|
Options::window.size = zoom;
|
||||||
adjustWindowSize();
|
adjustWindowSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reduce el tamaño de la ventana
|
// Reduce el tamaño de la ventana
|
||||||
bool Screen::decWindowSize()
|
auto Screen::decWindowSize() -> bool {
|
||||||
{
|
if (!Options::video.fullscreen) {
|
||||||
if (!Options::video.fullscreen)
|
|
||||||
{
|
|
||||||
const int PREVIOUS_ZOOM = Options::window.size;
|
const int PREVIOUS_ZOOM = Options::window.size;
|
||||||
--Options::window.size;
|
--Options::window.size;
|
||||||
Options::window.size = std::max(Options::window.size, 1);
|
Options::window.size = std::max(Options::window.size, 1);
|
||||||
|
|
||||||
if (Options::window.size != PREVIOUS_ZOOM)
|
if (Options::window.size != PREVIOUS_ZOOM) {
|
||||||
{
|
|
||||||
adjustWindowSize();
|
adjustWindowSize();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -157,16 +139,13 @@ bool Screen::decWindowSize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Aumenta el tamaño de la ventana
|
// Aumenta el tamaño de la ventana
|
||||||
bool Screen::incWindowSize()
|
auto Screen::incWindowSize() -> bool {
|
||||||
{
|
if (!Options::video.fullscreen) {
|
||||||
if (!Options::video.fullscreen)
|
|
||||||
{
|
|
||||||
const int PREVIOUS_ZOOM = Options::window.size;
|
const int PREVIOUS_ZOOM = Options::window.size;
|
||||||
++Options::window.size;
|
++Options::window.size;
|
||||||
Options::window.size = std::min(Options::window.size, Options::window.max_size);
|
Options::window.size = std::min(Options::window.size, Options::window.max_size);
|
||||||
|
|
||||||
if (Options::window.size != PREVIOUS_ZOOM)
|
if (Options::window.size != PREVIOUS_ZOOM) {
|
||||||
{
|
|
||||||
adjustWindowSize();
|
adjustWindowSize();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -176,45 +155,41 @@ bool Screen::incWindowSize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza la lógica de la clase
|
// Actualiza la lógica de la clase
|
||||||
void Screen::update()
|
void Screen::update() {
|
||||||
{
|
|
||||||
fps_.calculate(SDL_GetTicks());
|
fps_.calculate(SDL_GetTicks());
|
||||||
shake_effect_.update(src_rect_, dst_rect_);
|
shake_effect_.update(src_rect_, dst_rect_);
|
||||||
flash_effect_.update();
|
flash_effect_.update();
|
||||||
if (service_menu_)
|
if (service_menu_ != nullptr) {
|
||||||
service_menu_->update();
|
service_menu_->update();
|
||||||
if (notifier_)
|
}
|
||||||
|
if (notifier_ != nullptr) {
|
||||||
notifier_->update();
|
notifier_->update();
|
||||||
|
}
|
||||||
Mouse::updateCursorVisibility();
|
Mouse::updateCursorVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza los elementos mínimos
|
// Actualiza los elementos mínimos
|
||||||
void Screen::coreUpdate()
|
void Screen::coreUpdate() {
|
||||||
{
|
|
||||||
fps_.calculate(SDL_GetTicks());
|
fps_.calculate(SDL_GetTicks());
|
||||||
Mouse::updateCursorVisibility();
|
Mouse::updateCursorVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza y dibuja el efecto de flash en la pantalla
|
// Actualiza y dibuja el efecto de flash en la pantalla
|
||||||
void Screen::renderFlash()
|
void Screen::renderFlash() {
|
||||||
{
|
if (flash_effect_.isRendarable()) {
|
||||||
if (flash_effect_.isRendarable())
|
|
||||||
{
|
|
||||||
SDL_SetRenderDrawColor(renderer_, flash_effect_.color.r, flash_effect_.color.g, flash_effect_.color.b, 0xFF);
|
SDL_SetRenderDrawColor(renderer_, flash_effect_.color.r, flash_effect_.color.g, flash_effect_.color.b, 0xFF);
|
||||||
SDL_RenderClear(renderer_);
|
SDL_RenderClear(renderer_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aplica el efecto de agitar la pantalla
|
// Aplica el efecto de agitar la pantalla
|
||||||
void Screen::renderShake()
|
void Screen::renderShake() {
|
||||||
{
|
if (shake_effect_.enabled) {
|
||||||
if (shake_effect_.enabled)
|
|
||||||
{
|
|
||||||
// Guarda el renderizador actual para dejarlo despues como estaba
|
// Guarda el renderizador actual para dejarlo despues como estaba
|
||||||
auto current_target = SDL_GetRenderTarget(renderer_);
|
auto *current_target = SDL_GetRenderTarget(renderer_);
|
||||||
|
|
||||||
// Crea una textura temporal
|
// Crea una textura temporal
|
||||||
auto temp_texture = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);
|
auto *temp_texture = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);
|
||||||
|
|
||||||
// Vuelca game_canvas_ a la textura temporal
|
// Vuelca game_canvas_ a la textura temporal
|
||||||
SDL_SetRenderTarget(renderer_, temp_texture);
|
SDL_SetRenderTarget(renderer_, temp_texture);
|
||||||
@@ -233,10 +208,8 @@ void Screen::renderShake()
|
|||||||
}
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// Muestra información por pantalla
|
// Muestra información por pantalla
|
||||||
void Screen::renderInfo()
|
void Screen::renderInfo() {
|
||||||
{
|
if (debug_info_.show) {
|
||||||
if (debug_info_.show)
|
|
||||||
{
|
|
||||||
// Resolution
|
// Resolution
|
||||||
debug_info_.text->writeDX(TEXT_COLOR | TEXT_STROKE, param.game.width - debug_info_.text->lenght(Options::video.info) - 2, 1, Options::video.info, 1, param.debug.color, 1, param.debug.color.darken(150));
|
debug_info_.text->writeDX(TEXT_COLOR | TEXT_STROKE, param.game.width - debug_info_.text->lenght(Options::video.info) - 2, 1, Options::video.info, 1, param.debug.color, 1, param.debug.color.darken(150));
|
||||||
|
|
||||||
@@ -247,10 +220,8 @@ void Screen::renderInfo()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Carga el contenido del archivo GLSL
|
// Carga el contenido del archivo GLSL
|
||||||
void Screen::loadShaders()
|
void Screen::loadShaders() {
|
||||||
{
|
if (shader_source_.empty()) {
|
||||||
if (shader_source_.empty())
|
|
||||||
{
|
|
||||||
const std::string GLSL_FILE = param.game.game_area.rect.h == 256 ? "crtpi_256.glsl" : "crtpi_240.glsl";
|
const std::string GLSL_FILE = param.game.game_area.rect.h == 256 ? "crtpi_256.glsl" : "crtpi_240.glsl";
|
||||||
std::ifstream f(Asset::get()->get(GLSL_FILE).c_str());
|
std::ifstream f(Asset::get()->get(GLSL_FILE).c_str());
|
||||||
shader_source_ = std::string((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
|
shader_source_ = std::string((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
|
||||||
@@ -258,32 +229,30 @@ void Screen::loadShaders()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa los shaders
|
// Inicializa los shaders
|
||||||
void Screen::initShaders()
|
void Screen::initShaders() {
|
||||||
{
|
if (Options::video.shaders) {
|
||||||
if (Options::video.shaders)
|
|
||||||
{
|
|
||||||
loadShaders();
|
loadShaders();
|
||||||
shader::init(window_, game_canvas_, shader_source_);
|
shader::init(window_, game_canvas_, shader_source_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calcula el tamaño de la ventana
|
// Calcula el tamaño de la ventana
|
||||||
void Screen::adjustWindowSize()
|
void Screen::adjustWindowSize() {
|
||||||
{
|
if (!Options::video.fullscreen) {
|
||||||
if (!Options::video.fullscreen)
|
|
||||||
{
|
|
||||||
// Establece el nuevo tamaño
|
// Establece el nuevo tamaño
|
||||||
const int WIDTH = param.game.width * Options::window.size;
|
const int WIDTH = param.game.width * Options::window.size;
|
||||||
const int HEIGHT = param.game.height * Options::window.size;
|
const int HEIGHT = param.game.height * Options::window.size;
|
||||||
|
|
||||||
int old_width, old_height;
|
int old_width;
|
||||||
|
int old_height;
|
||||||
SDL_GetWindowSize(window_, &old_width, &old_height);
|
SDL_GetWindowSize(window_, &old_width, &old_height);
|
||||||
|
|
||||||
int old_pos_x, old_pos_y;
|
int old_pos_x;
|
||||||
|
int old_pos_y;
|
||||||
SDL_GetWindowPosition(window_, &old_pos_x, &old_pos_y);
|
SDL_GetWindowPosition(window_, &old_pos_x, &old_pos_y);
|
||||||
|
|
||||||
const int NEW_POS_X = old_pos_x + (old_width - WIDTH) / 2;
|
const int NEW_POS_X = old_pos_x + ((old_width - WIDTH) / 2);
|
||||||
const int NEW_POS_Y = old_pos_y + (old_height - HEIGHT) / 2;
|
const int NEW_POS_Y = old_pos_y + ((old_height - HEIGHT) / 2);
|
||||||
|
|
||||||
SDL_SetWindowPosition(window_, std::max(NEW_POS_X, WINDOWS_DECORATIONS_), std::max(NEW_POS_Y, 0));
|
SDL_SetWindowPosition(window_, std::max(NEW_POS_X, WINDOWS_DECORATIONS_), std::max(NEW_POS_Y, 0));
|
||||||
SDL_SetWindowSize(window_, WIDTH, HEIGHT);
|
SDL_SetWindowSize(window_, WIDTH, HEIGHT);
|
||||||
@@ -291,8 +260,7 @@ void Screen::adjustWindowSize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Renderiza todos los overlays y efectos
|
// Renderiza todos los overlays y efectos
|
||||||
void Screen::renderOverlays()
|
void Screen::renderOverlays() {
|
||||||
{
|
|
||||||
// Dibuja efectos y elementos sobre el game_canvas_
|
// Dibuja efectos y elementos sobre el game_canvas_
|
||||||
renderShake();
|
renderShake();
|
||||||
renderFlash();
|
renderFlash();
|
||||||
@@ -305,24 +273,20 @@ void Screen::renderOverlays()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Atenua la pantalla
|
// Atenua la pantalla
|
||||||
void Screen::renderAttenuate()
|
void Screen::renderAttenuate() {
|
||||||
{
|
if (attenuate_effect_) {
|
||||||
if (attenuate_effect_)
|
|
||||||
{
|
|
||||||
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 64);
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 64);
|
||||||
SDL_RenderFillRect(renderer_, nullptr);
|
SDL_RenderFillRect(renderer_, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Arranca SDL VIDEO y crea la ventana
|
// Arranca SDL VIDEO y crea la ventana
|
||||||
bool Screen::initSDLVideo()
|
auto Screen::initSDLVideo() -> bool {
|
||||||
{
|
|
||||||
// Inicializar SDL
|
// Inicializar SDL
|
||||||
if (!SDL_Init(SDL_INIT_VIDEO))
|
if (!SDL_Init(SDL_INIT_VIDEO)) {
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"FATAL: Failed to initialize SDL_VIDEO! SDL Error: %s",
|
"FATAL: Failed to initialize SDL_VIDEO! SDL Error: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,16 +294,14 @@ bool Screen::initSDLVideo()
|
|||||||
getDisplayInfo();
|
getDisplayInfo();
|
||||||
|
|
||||||
// Configurar hint para OpenGL
|
// Configurar hint para OpenGL
|
||||||
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"))
|
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl")) {
|
||||||
{
|
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"Warning: Failed to set OpenGL hint!");
|
"Warning: Failed to set OpenGL hint!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crear ventana
|
// Crear ventana
|
||||||
SDL_WindowFlags window_flags = SDL_WINDOW_OPENGL;
|
SDL_WindowFlags window_flags = SDL_WINDOW_OPENGL;
|
||||||
if (Options::video.fullscreen)
|
if (Options::video.fullscreen) {
|
||||||
{
|
|
||||||
window_flags |= SDL_WINDOW_FULLSCREEN;
|
window_flags |= SDL_WINDOW_FULLSCREEN;
|
||||||
}
|
}
|
||||||
window_ = SDL_CreateWindow(
|
window_ = SDL_CreateWindow(
|
||||||
@@ -348,22 +310,20 @@ bool Screen::initSDLVideo()
|
|||||||
param.game.height * Options::window.size,
|
param.game.height * Options::window.size,
|
||||||
window_flags);
|
window_flags);
|
||||||
|
|
||||||
if (!window_)
|
if (window_ == nullptr) {
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"FATAL: Failed to create window! SDL Error: %s",
|
"FATAL: Failed to create window! SDL Error: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crear renderer
|
// Crear renderer
|
||||||
renderer_ = SDL_CreateRenderer(window_, nullptr);
|
renderer_ = SDL_CreateRenderer(window_, nullptr);
|
||||||
if (!renderer_)
|
if (renderer_ == nullptr) {
|
||||||
{
|
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
"FATAL: Failed to create renderer! SDL Error: %s",
|
"FATAL: Failed to create renderer! SDL Error: %s",
|
||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
SDL_DestroyWindow(window_);
|
SDL_DestroyWindow(window_);
|
||||||
window_ = nullptr;
|
window_ = nullptr;
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
@@ -382,39 +342,35 @@ bool Screen::initSDLVideo()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene información sobre la pantalla
|
// Obtiene información sobre la pantalla
|
||||||
void Screen::getDisplayInfo()
|
void Screen::getDisplayInfo() {
|
||||||
{
|
int i;
|
||||||
int i, num_displays = 0;
|
int num_displays = 0;
|
||||||
SDL_DisplayID *displays = SDL_GetDisplays(&num_displays);
|
SDL_DisplayID *displays = SDL_GetDisplays(&num_displays);
|
||||||
if (displays)
|
if (displays != nullptr) {
|
||||||
{
|
for (i = 0; i < num_displays; ++i) {
|
||||||
for (i = 0; i < num_displays; ++i)
|
|
||||||
{
|
|
||||||
SDL_DisplayID instance_id = displays[i];
|
SDL_DisplayID instance_id = displays[i];
|
||||||
const char *name = SDL_GetDisplayName(instance_id);
|
const char *name = SDL_GetDisplayName(instance_id);
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Display %" SDL_PRIu32 ": %s", instance_id, name ? name : "Unknown");
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Display %" SDL_PRIu32 ": %s", instance_id, (name != nullptr) ? name : "Unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto DM = SDL_GetCurrentDisplayMode(displays[0]);
|
const auto *dm = SDL_GetCurrentDisplayMode(displays[0]);
|
||||||
|
|
||||||
// Calcula el máximo factor de zoom que se puede aplicar a la pantalla
|
// Calcula el máximo factor de zoom que se puede aplicar a la pantalla
|
||||||
Options::window.max_size = std::min(DM->w / param.game.width, DM->h / param.game.height);
|
Options::window.max_size = std::min(dm->w / param.game.width, dm->h / param.game.height);
|
||||||
Options::window.size = std::min(Options::window.size, Options::window.max_size);
|
Options::window.size = std::min(Options::window.size, Options::window.max_size);
|
||||||
|
|
||||||
// Muestra información sobre el tamaño de la pantalla y de la ventana de juego
|
// Muestra información sobre el tamaño de la pantalla y de la ventana de juego
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Current display mode: %dx%d @ %dHz",
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Current display mode: %dx%d @ %dHz", static_cast<int>(dm->w), static_cast<int>(dm->h), static_cast<int>(dm->refresh_rate));
|
||||||
static_cast<int>(DM->w), static_cast<int>(DM->h), static_cast<int>(DM->refresh_rate));
|
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Window resolution: %dx%d x%d",
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Window resolution: %dx%d x%d", static_cast<int>(param.game.width), static_cast<int>(param.game.height), Options::window.size);
|
||||||
static_cast<int>(param.game.width), static_cast<int>(param.game.height), Options::window.size);
|
|
||||||
|
|
||||||
Options::video.info = std::to_string(static_cast<int>(DM->w)) + "x" +
|
Options::video.info = std::to_string(static_cast<int>(dm->w)) + "x" +
|
||||||
std::to_string(static_cast<int>(DM->h)) + " @ " +
|
std::to_string(static_cast<int>(dm->h)) + " @ " +
|
||||||
std::to_string(static_cast<int>(DM->refresh_rate)) + " Hz";
|
std::to_string(static_cast<int>(dm->refresh_rate)) + " Hz";
|
||||||
|
|
||||||
// Calcula el máximo factor de zoom que se puede aplicar a la pantalla
|
// Calcula el máximo factor de zoom que se puede aplicar a la pantalla
|
||||||
const int MAX_ZOOM = std::min(DM->w / param.game.width, (DM->h - WINDOWS_DECORATIONS_) / param.game.height);
|
const int MAX_ZOOM = std::min(dm->w / param.game.width, (dm->h - WINDOWS_DECORATIONS_) / param.game.height);
|
||||||
|
|
||||||
// Normaliza los valores de zoom
|
// Normaliza los valores de zoom
|
||||||
Options::window.size = std::min(Options::window.size, MAX_ZOOM);
|
Options::window.size = std::min(Options::window.size, MAX_ZOOM);
|
||||||
@@ -424,43 +380,37 @@ void Screen::getDisplayInfo()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Alterna entre activar y desactivar los shaders
|
// Alterna entre activar y desactivar los shaders
|
||||||
void Screen::toggleShaders()
|
void Screen::toggleShaders() {
|
||||||
{
|
|
||||||
Options::video.shaders = !Options::video.shaders;
|
Options::video.shaders = !Options::video.shaders;
|
||||||
initShaders();
|
initShaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alterna entre activar y desactivar el escalado entero
|
// Alterna entre activar y desactivar el escalado entero
|
||||||
void Screen::toggleIntegerScale()
|
void Screen::toggleIntegerScale() {
|
||||||
{
|
|
||||||
Options::video.integer_scale = !Options::video.integer_scale;
|
Options::video.integer_scale = !Options::video.integer_scale;
|
||||||
SDL_SetRenderLogicalPresentation(renderer_, param.game.width, param.game.height, Options::video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX);
|
SDL_SetRenderLogicalPresentation(renderer_, param.game.width, param.game.height, Options::video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alterna entre activar y desactivar el V-Sync
|
// Alterna entre activar y desactivar el V-Sync
|
||||||
void Screen::toggleVSync()
|
void Screen::toggleVSync() {
|
||||||
{
|
|
||||||
Options::video.v_sync = !Options::video.v_sync;
|
Options::video.v_sync = !Options::video.v_sync;
|
||||||
SDL_SetRenderVSync(renderer_, Options::video.v_sync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
|
SDL_SetRenderVSync(renderer_, Options::video.v_sync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el estado del V-Sync
|
// Establece el estado del V-Sync
|
||||||
void Screen::setVSync(bool enabled)
|
void Screen::setVSync(bool enabled) {
|
||||||
{
|
|
||||||
Options::video.v_sync = enabled;
|
Options::video.v_sync = enabled;
|
||||||
SDL_SetRenderVSync(renderer_, enabled ? 1 : SDL_RENDERER_VSYNC_DISABLED);
|
SDL_SetRenderVSync(renderer_, enabled ? 1 : SDL_RENDERER_VSYNC_DISABLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene los punteros a los singletones
|
// Obtiene los punteros a los singletones
|
||||||
void Screen::getSingletons()
|
void Screen::getSingletons() {
|
||||||
{
|
|
||||||
service_menu_ = ServiceMenu::get();
|
service_menu_ = ServiceMenu::get();
|
||||||
notifier_ = Notifier::get();
|
notifier_ = Notifier::get();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aplica los valores de las opciones
|
// Aplica los valores de las opciones
|
||||||
void Screen::applySettings()
|
void Screen::applySettings() {
|
||||||
{
|
|
||||||
SDL_SetRenderVSync(renderer_, Options::video.v_sync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
|
SDL_SetRenderVSync(renderer_, Options::video.v_sync ? 1 : SDL_RENDERER_VSYNC_DISABLED);
|
||||||
SDL_SetRenderLogicalPresentation(Screen::get()->getRenderer(), param.game.width, param.game.height, Options::video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX);
|
SDL_SetRenderLogicalPresentation(Screen::get()->getRenderer(), param.game.width, param.game.height, Options::video.integer_scale ? SDL_LOGICAL_PRESENTATION_INTEGER_SCALE : SDL_LOGICAL_PRESENTATION_LETTERBOX);
|
||||||
setFullscreenMode();
|
setFullscreenMode();
|
||||||
@@ -468,8 +418,7 @@ void Screen::applySettings()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Crea el objeto de texto
|
// Crea el objeto de texto
|
||||||
void Screen::createText()
|
void Screen::createText() {
|
||||||
{
|
|
||||||
auto texture = std::make_shared<Texture>(getRenderer(), Asset::get()->get("aseprite.png"));
|
auto texture = std::make_shared<Texture>(getRenderer(), Asset::get()->get("aseprite.png"));
|
||||||
text_ = std::make_shared<Text>(texture, Asset::get()->get("aseprite.txt"));
|
text_ = std::make_shared<Text>(texture, Asset::get()->get("aseprite.txt"));
|
||||||
}
|
}
|
||||||
+169
-183
@@ -1,225 +1,211 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FRect, SDL_HideWindow, SDL_Renderer, SDL_ShowWindow, Uint32, SDL_Texture, SDL_Window
|
#include <SDL3/SDL.h> // Para SDL_FRect, SDL_HideWindow, SDL_Renderer, SDL_ShowWindow, Uint32, SDL_Texture, SDL_Window
|
||||||
#include <memory> // Para shared_ptr
|
|
||||||
#include <string> // Para basic_string, string
|
|
||||||
|
|
||||||
#include "options.h" // Para VideoOptions, video
|
#include <memory> // Para shared_ptr
|
||||||
#include "utils.h" // Para Color
|
#include <string> // Para basic_string, string
|
||||||
|
|
||||||
|
#include "options.h" // Para VideoOptions, video
|
||||||
|
#include "utils.h" // Para Color
|
||||||
|
|
||||||
class Notifier;
|
class Notifier;
|
||||||
class ServiceMenu;
|
class ServiceMenu;
|
||||||
class Text;
|
class Text;
|
||||||
|
|
||||||
// Clase Screen: gestiona la ventana, el renderizador y los efectos visuales globales
|
// Clase Screen: gestiona la ventana, el renderizador y los efectos visuales globales
|
||||||
class Screen
|
class Screen {
|
||||||
{
|
public:
|
||||||
public:
|
// --- Métodos de singleton ---
|
||||||
// --- Métodos de singleton ---
|
static void init(); // Inicializa el objeto Screen
|
||||||
static void init(); // Inicializa el objeto Screen
|
static void destroy(); // Libera el objeto Screen
|
||||||
static void destroy(); // Libera el objeto Screen
|
static Screen *get(); // Obtiene el puntero al objeto Screen
|
||||||
static Screen *get(); // Obtiene el puntero al objeto Screen
|
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
void update(); // Actualiza la lógica de la clase
|
void update(); // Actualiza la lógica de la clase
|
||||||
void coreUpdate(); // Actualiza los elementos mínimos
|
void coreUpdate(); // Actualiza los elementos mínimos
|
||||||
void clean(Color color = Color(0x00, 0x00, 0x00)); // Limpia la pantalla
|
void clean(Color color = Color(0x00, 0x00, 0x00)); // Limpia la pantalla
|
||||||
void start(); // Prepara para empezar a dibujar en la textura de juego
|
void start(); // Prepara para empezar a dibujar en la textura de juego
|
||||||
void render(); // Vuelca el contenido del renderizador en pantalla
|
void render(); // Vuelca el contenido del renderizador en pantalla
|
||||||
void coreRender(); // Vuelca el contenido del renderizador en pantalla exceptuando ciertas partes
|
void coreRender(); // Vuelca el contenido del renderizador en pantalla exceptuando ciertas partes
|
||||||
|
|
||||||
// --- Configuración de ventana y render ---
|
// --- Configuración de ventana y render ---
|
||||||
void setFullscreenMode(); // Establece el modo de pantalla completa
|
void setFullscreenMode(); // Establece el modo de pantalla completa
|
||||||
void toggleFullscreen(); // Cambia entre pantalla completa y ventana
|
void toggleFullscreen(); // Cambia entre pantalla completa y ventana
|
||||||
void setWindowZoom(int size); // Cambia el tamaño de la ventana
|
void setWindowZoom(int size); // Cambia el tamaño de la ventana
|
||||||
bool decWindowSize(); // Reduce el tamaño de la ventana
|
bool decWindowSize(); // Reduce el tamaño de la ventana
|
||||||
bool incWindowSize(); // Aumenta el tamaño de la ventana
|
bool incWindowSize(); // Aumenta el tamaño de la ventana
|
||||||
void applySettings(); // Aplica los valores de las opciones
|
void applySettings(); // Aplica los valores de las opciones
|
||||||
void initShaders(); // Inicializa los shaders
|
void initShaders(); // Inicializa los shaders
|
||||||
|
|
||||||
// --- Efectos visuales ---
|
// --- Efectos visuales ---
|
||||||
void shake(int desp = 2, int delay = 3, int lenght = 8) { shake_effect_.enable(src_rect_, dst_rect_, desp, delay, lenght); } // Agita la pantalla
|
void shake(int desp = 2, int delay = 3, int lenght = 8) { shake_effect_.enable(src_rect_, dst_rect_, desp, delay, lenght); } // Agita la pantalla
|
||||||
void flash(Color color, int lenght = 10, int delay = 0) { flash_effect_ = FlashEffect(true, lenght, delay, color); } // Pone la pantalla de color
|
void flash(Color color, int lenght = 10, int delay = 0) { flash_effect_ = FlashEffect(true, lenght, delay, color); } // Pone la pantalla de color
|
||||||
void toggleShaders(); // Alterna entre activar y desactivar los shaders
|
void toggleShaders(); // Alterna entre activar y desactivar los shaders
|
||||||
void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero
|
void toggleIntegerScale(); // Alterna entre activar y desactivar el escalado entero
|
||||||
void toggleVSync(); // Alterna entre activar y desactivar el V-Sync
|
void toggleVSync(); // Alterna entre activar y desactivar el V-Sync
|
||||||
void setVSync(bool enabled); // Establece el estado del V-Sync
|
void setVSync(bool enabled); // Establece el estado del V-Sync
|
||||||
void attenuate(bool value) { attenuate_effect_ = value; } // Atenúa la pantalla
|
void attenuate(bool value) { attenuate_effect_ = value; } // Atenúa la pantalla
|
||||||
|
|
||||||
// --- Getters ---
|
// --- Getters ---
|
||||||
SDL_Renderer *getRenderer() { return renderer_; } // Obtiene el renderizador
|
SDL_Renderer *getRenderer() { return renderer_; } // Obtiene el renderizador
|
||||||
void show() { SDL_ShowWindow(window_); } // Muestra la ventana
|
void show() { SDL_ShowWindow(window_); } // Muestra la ventana
|
||||||
void hide() { SDL_HideWindow(window_); } // Oculta la ventana
|
void hide() { SDL_HideWindow(window_); } // Oculta la ventana
|
||||||
void getSingletons(); // Obtiene los punteros a los singletones
|
void getSingletons(); // Obtiene los punteros a los singletones
|
||||||
bool getVSync() const { return Options::video.v_sync; } // Obtiene el valor de V-Sync
|
bool getVSync() const { return Options::video.v_sync; } // Obtiene el valor de V-Sync
|
||||||
std::shared_ptr<Text> getText() const { return text_; } // Obtiene el puntero al texto de Screen
|
std::shared_ptr<Text> getText() const { return text_; } // Obtiene el puntero al texto de Screen
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// --- Debug ---
|
// --- Debug ---
|
||||||
void toggleDebugInfo() { debug_info_.show = !debug_info_.show; }
|
void toggleDebugInfo() { debug_info_.show = !debug_info_.show; }
|
||||||
void setDebugInfoEnabled(bool value) { debug_info_.show = value; }
|
void setDebugInfoEnabled(bool value) { debug_info_.show = value; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr int WINDOWS_DECORATIONS_ = 35;
|
static constexpr int WINDOWS_DECORATIONS_ = 35;
|
||||||
|
|
||||||
// --- Estructuras internas ---
|
// --- Estructuras internas ---
|
||||||
struct FPS
|
struct FPS {
|
||||||
{
|
Uint32 ticks; // Tiempo en milisegundos desde que se comenzó a contar.
|
||||||
Uint32 ticks; // Tiempo en milisegundos desde que se comenzó a contar.
|
int frameCount; // Número acumulado de frames en el intervalo.
|
||||||
int frameCount; // Número acumulado de frames en el intervalo.
|
int lastValue; // Número de frames calculado en el último segundo.
|
||||||
int lastValue; // Número de frames calculado en el último segundo.
|
|
||||||
|
|
||||||
FPS() : ticks(0), frameCount(0), lastValue(0) {}
|
FPS() : ticks(0), frameCount(0), lastValue(0) {}
|
||||||
void increment() { frameCount++; }
|
void increment() { frameCount++; }
|
||||||
int calculate(Uint32 currentTicks)
|
int calculate(Uint32 currentTicks) {
|
||||||
{
|
if (currentTicks - ticks >= 1000) {
|
||||||
if (currentTicks - ticks >= 1000)
|
lastValue = frameCount;
|
||||||
{
|
frameCount = 0;
|
||||||
lastValue = frameCount;
|
ticks = currentTicks;
|
||||||
frameCount = 0;
|
}
|
||||||
ticks = currentTicks;
|
return lastValue;
|
||||||
}
|
}
|
||||||
return lastValue;
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Efecto de flash en pantalla: pinta la pantalla de un color durante unos frames
|
// Efecto de flash en pantalla: pinta la pantalla de un color durante unos frames
|
||||||
struct FlashEffect
|
struct FlashEffect {
|
||||||
{
|
bool enabled; // Indica si el efecto está activo
|
||||||
bool enabled; // Indica si el efecto está activo
|
int lenght; // Duración total del efecto en frames
|
||||||
int lenght; // Duración total del efecto en frames
|
int delay; // Retraso antes de mostrar el flash
|
||||||
int delay; // Retraso antes de mostrar el flash
|
int counter; // Contador de frames restantes
|
||||||
int counter; // Contador de frames restantes
|
Color color; // Color del flash
|
||||||
Color color; // Color del flash
|
|
||||||
|
|
||||||
explicit FlashEffect(bool enabled = false, int lenght = 0, int delay = 0, Color color = Color(0xFF, 0xFF, 0xFF))
|
explicit FlashEffect(bool enabled = false, int lenght = 0, int delay = 0, Color color = Color(0xFF, 0xFF, 0xFF))
|
||||||
: enabled(enabled), lenght(lenght), delay(delay), counter(lenght), color(color) {}
|
: enabled(enabled), lenght(lenght), delay(delay), counter(lenght), color(color) {}
|
||||||
|
|
||||||
void update() { (enabled && counter > 0) ? counter-- : enabled = false; }
|
void update() { (enabled && counter > 0) ? counter-- : enabled = false; }
|
||||||
bool isRendarable() { return enabled && counter < lenght - delay; }
|
bool isRendarable() { return enabled && counter < lenght - delay; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Efecto de sacudida/agitación de pantalla: mueve la imagen para simular un temblor
|
// Efecto de sacudida/agitación de pantalla: mueve la imagen para simular un temblor
|
||||||
struct ShakeEffect
|
struct ShakeEffect {
|
||||||
{
|
int desp; // Desplazamiento máximo de la sacudida (en píxeles)
|
||||||
int desp; // Desplazamiento máximo de la sacudida (en píxeles)
|
int delay; // Frames entre cada movimiento de sacudida
|
||||||
int delay; // Frames entre cada movimiento de sacudida
|
int counter; // Contador de frames para el siguiente movimiento
|
||||||
int counter; // Contador de frames para el siguiente movimiento
|
int lenght; // Duración total del efecto en frames
|
||||||
int lenght; // Duración total del efecto en frames
|
int remaining; // Frames restantes de sacudida
|
||||||
int remaining; // Frames restantes de sacudida
|
int original_pos; // Posición original de la imagen (x)
|
||||||
int original_pos; // Posición original de la imagen (x)
|
int original_width; // Ancho original de la imagen
|
||||||
int original_width; // Ancho original de la imagen
|
bool enabled; // Indica si el efecto está activo
|
||||||
bool enabled; // Indica si el efecto está activo
|
|
||||||
|
|
||||||
explicit ShakeEffect(bool en = false, int dp = 2, int dl = 3, int cnt = 0, int len = 8, int rem = 0, int origPos = 0, int origWidth = 800)
|
explicit ShakeEffect(bool en = false, int dp = 2, int dl = 3, int cnt = 0, int len = 8, int rem = 0, int origPos = 0, int origWidth = 800)
|
||||||
: desp(dp), delay(dl), counter(cnt), lenght(len), remaining(rem), original_pos(origPos), original_width(origWidth), enabled(en) {}
|
: desp(dp), delay(dl), counter(cnt), lenght(len), remaining(rem), original_pos(origPos), original_width(origWidth), enabled(en) {}
|
||||||
|
|
||||||
// Activa el efecto de sacudida y guarda la posición y tamaño originales
|
// Activa el efecto de sacudida y guarda la posición y tamaño originales
|
||||||
void enable(SDL_FRect &src_rect, SDL_FRect &dst_rect, int new_desp = -1, int new_delay = -1, int new_lenght = -1)
|
void enable(SDL_FRect &src_rect, SDL_FRect &dst_rect, int new_desp = -1, int new_delay = -1, int new_lenght = -1) {
|
||||||
{
|
if (!enabled) {
|
||||||
if (!enabled)
|
enabled = true;
|
||||||
{
|
original_pos = src_rect.x;
|
||||||
enabled = true;
|
original_width = src_rect.w;
|
||||||
original_pos = src_rect.x;
|
|
||||||
original_width = src_rect.w;
|
|
||||||
|
|
||||||
// Usar nuevos valores si se proporcionan, sino mantener los actuales
|
// Usar nuevos valores si se proporcionan, sino mantener los actuales
|
||||||
if (new_desp != -1)
|
if (new_desp != -1)
|
||||||
desp = new_desp;
|
desp = new_desp;
|
||||||
if (new_delay != -1)
|
if (new_delay != -1)
|
||||||
delay = new_delay;
|
delay = new_delay;
|
||||||
if (new_lenght != -1)
|
if (new_lenght != -1)
|
||||||
lenght = new_lenght;
|
lenght = new_lenght;
|
||||||
|
|
||||||
src_rect.w -= desp;
|
src_rect.w -= desp;
|
||||||
dst_rect.w = src_rect.w;
|
dst_rect.w = src_rect.w;
|
||||||
}
|
}
|
||||||
remaining = lenght;
|
remaining = lenght;
|
||||||
counter = delay;
|
counter = delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el estado del efecto de sacudida
|
// Actualiza el estado del efecto de sacudida
|
||||||
void update(SDL_FRect &src_rect, SDL_FRect &dst_rect)
|
void update(SDL_FRect &src_rect, SDL_FRect &dst_rect) {
|
||||||
{
|
if (enabled) {
|
||||||
if (enabled)
|
if (counter > 0) {
|
||||||
{
|
counter--;
|
||||||
if (counter > 0)
|
} else {
|
||||||
{
|
counter = delay;
|
||||||
counter--;
|
const auto SRC_DESP = (remaining % 2 == 0) ? 0 : desp;
|
||||||
}
|
const auto DST_DESP = (remaining % 2 == 1) ? 0 : desp;
|
||||||
else
|
src_rect.x = original_pos + SRC_DESP;
|
||||||
{
|
dst_rect.x = original_pos + DST_DESP;
|
||||||
counter = delay;
|
remaining--;
|
||||||
const auto SRC_DESP = (remaining % 2 == 0) ? 0 : desp;
|
if (remaining == -1) {
|
||||||
const auto DST_DESP = (remaining % 2 == 1) ? 0 : desp;
|
enabled = false;
|
||||||
src_rect.x = original_pos + SRC_DESP;
|
src_rect.x = original_pos;
|
||||||
dst_rect.x = original_pos + DST_DESP;
|
src_rect.w = original_width;
|
||||||
remaining--;
|
dst_rect.x = original_pos;
|
||||||
if (remaining == -1)
|
dst_rect.w = original_width;
|
||||||
{
|
}
|
||||||
enabled = false;
|
}
|
||||||
src_rect.x = original_pos;
|
}
|
||||||
src_rect.w = original_width;
|
}
|
||||||
dst_rect.x = original_pos;
|
|
||||||
dst_rect.w = original_width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isEnabled() const { return enabled; }
|
bool isEnabled() const { return enabled; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
struct Debug
|
struct Debug {
|
||||||
{
|
std::shared_ptr<Text> text;
|
||||||
std::shared_ptr<Text> text;
|
bool show = false;
|
||||||
bool show = false;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --- Singleton ---
|
// --- Singleton ---
|
||||||
static Screen *instance_;
|
static Screen *instance_;
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
SDL_Window *window_; // Ventana de la aplicación
|
SDL_Window *window_; // Ventana de la aplicación
|
||||||
SDL_Renderer *renderer_; // El renderizador de la ventana
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
SDL_Texture *game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador
|
SDL_Texture *game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador
|
||||||
ServiceMenu *service_menu_; // Objeto para mostrar el menú de servicio
|
ServiceMenu *service_menu_; // Objeto para mostrar el menú de servicio
|
||||||
Notifier *notifier_; // Objeto para mostrar las notificaciones por pantalla
|
Notifier *notifier_; // Objeto para mostrar las notificaciones por pantalla
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
SDL_FRect src_rect_; // Coordenadas de origen para dibujar la textura del juego
|
SDL_FRect src_rect_; // Coordenadas de origen para dibujar la textura del juego
|
||||||
SDL_FRect dst_rect_; // Coordenadas destino para dibujar la textura del juego
|
SDL_FRect dst_rect_; // Coordenadas destino para dibujar la textura del juego
|
||||||
FPS fps_; // Gestión de frames por segundo
|
FPS fps_; // Gestión de frames por segundo
|
||||||
std::string shader_source_; // Almacena el contenido del archivo GLSL
|
std::string shader_source_; // Almacena el contenido del archivo GLSL
|
||||||
FlashEffect flash_effect_; // Efecto de flash en pantalla
|
FlashEffect flash_effect_; // Efecto de flash en pantalla
|
||||||
ShakeEffect shake_effect_; // Efecto de agitar la pantalla
|
ShakeEffect shake_effect_; // Efecto de agitar la pantalla
|
||||||
bool attenuate_effect_ = false; // Indica si la pantalla ha de estar atenuada
|
bool attenuate_effect_ = false; // Indica si la pantalla ha de estar atenuada
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
Debug debug_info_; // Información de debug
|
Debug debug_info_; // Información de debug
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --- Texto ---
|
// --- Texto ---
|
||||||
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
|
std::shared_ptr<Text> text_; // Objeto para escribir texto en pantalla
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
bool initSDLVideo(); // Arranca SDL VIDEO y crea la ventana
|
bool initSDLVideo(); // Arranca SDL VIDEO y crea la ventana
|
||||||
void renderFlash(); // Dibuja el efecto de flash en la pantalla
|
void renderFlash(); // Dibuja el efecto de flash en la pantalla
|
||||||
void renderShake(); // Aplica el efecto de agitar la pantalla
|
void renderShake(); // Aplica el efecto de agitar la pantalla
|
||||||
void renderInfo(); // Muestra información por pantalla
|
void renderInfo(); // Muestra información por pantalla
|
||||||
void renderScreen(); // Selecciona y ejecuta el método de renderizado adecuado
|
void renderScreen(); // Selecciona y ejecuta el método de renderizado adecuado
|
||||||
void loadShaders(); // Carga el contenido del archivo GLSL
|
void loadShaders(); // Carga el contenido del archivo GLSL
|
||||||
void adjustWindowSize(); // Calcula el tamaño de la ventana
|
void adjustWindowSize(); // Calcula el tamaño de la ventana
|
||||||
void getDisplayInfo(); // Obtiene información sobre la pantalla
|
static void getDisplayInfo(); // Obtiene información sobre la pantalla
|
||||||
void renderOverlays(); // Renderiza todos los overlays y efectos
|
void renderOverlays(); // Renderiza todos los overlays y efectos
|
||||||
void renderAttenuate(); // Atenúa la pantalla
|
void renderAttenuate(); // Atenúa la pantalla
|
||||||
void createText(); // Crea el objeto de texto
|
void createText(); // Crea el objeto de texto
|
||||||
|
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor ---
|
||||||
Screen();
|
Screen();
|
||||||
~Screen();
|
~Screen();
|
||||||
};
|
};
|
||||||
+5
-6
@@ -1,8 +1,7 @@
|
|||||||
#include "section.h"
|
#include "section.h"
|
||||||
|
|
||||||
namespace Section
|
namespace Section {
|
||||||
{
|
Name name;
|
||||||
Name name;
|
Options options;
|
||||||
Options options;
|
AttractMode attract_mode;
|
||||||
AttractMode attract_mode;
|
} // namespace Section
|
||||||
}
|
|
||||||
+37
-41
@@ -6,47 +6,43 @@
|
|||||||
Proporciona variables globales para gestionar el flujo entre secciones.
|
Proporciona variables globales para gestionar el flujo entre secciones.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Section
|
namespace Section {
|
||||||
{
|
// --- Enumeraciones de secciones del programa ---
|
||||||
// --- Enumeraciones de secciones del programa ---
|
enum class Name {
|
||||||
enum class Name
|
RESET, // Inicialización
|
||||||
{
|
LOGO, // Pantalla de logo
|
||||||
RESET, // Inicialización
|
INTRO, // Introducción
|
||||||
LOGO, // Pantalla de logo
|
TITLE, // Pantalla de título/menú principal
|
||||||
INTRO, // Introducción
|
GAME, // Juego principal
|
||||||
TITLE, // Pantalla de título/menú principal
|
HI_SCORE_TABLE, // Tabla de récords
|
||||||
GAME, // Juego principal
|
GAME_DEMO, // Modo demo
|
||||||
HI_SCORE_TABLE, // Tabla de récords
|
INSTRUCTIONS, // Instrucciones
|
||||||
GAME_DEMO, // Modo demo
|
CREDITS, // Créditos
|
||||||
INSTRUCTIONS, // Instrucciones
|
QUIT, // Salir del juego
|
||||||
CREDITS, // Créditos
|
};
|
||||||
QUIT, // Salir del juego
|
|
||||||
};
|
|
||||||
|
|
||||||
// --- Opciones para la sección actual ---
|
// --- Opciones para la sección actual ---
|
||||||
enum class Options
|
enum class Options {
|
||||||
{
|
GAME_PLAY_1P, // Iniciar el juego con el jugador 1
|
||||||
GAME_PLAY_1P, // Iniciar el juego con el jugador 1
|
GAME_PLAY_2P, // Iniciar el juego con el jugador 2
|
||||||
GAME_PLAY_2P, // Iniciar el juego con el jugador 2
|
GAME_PLAY_BOTH, // Iniciar el juego con los dos jugadores
|
||||||
GAME_PLAY_BOTH, // Iniciar el juego con los dos jugadores
|
TITLE_TIME_OUT, // Timeout en el título
|
||||||
TITLE_TIME_OUT, // Timeout en el título
|
TITLE_1, // Opción 1 en el título
|
||||||
TITLE_1, // Opción 1 en el título
|
TITLE_2, // Opción 2 en el título
|
||||||
TITLE_2, // Opción 2 en el título
|
RELOAD, // Recargar sección
|
||||||
RELOAD, // Recargar sección
|
HI_SCORE_AFTER_PLAYING, // Mostrar récord tras jugar
|
||||||
HI_SCORE_AFTER_PLAYING, // Mostrar récord tras jugar
|
SHUTDOWN, // Apagar el sistema
|
||||||
SHUTDOWN, // Apagar el sistema
|
NONE, // Sin opción
|
||||||
NONE, // Sin opción
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// --- Modos para el Attract Mode ---
|
// --- Modos para el Attract Mode ---
|
||||||
enum class AttractMode
|
enum class AttractMode {
|
||||||
{
|
TITLE_TO_DEMO, // Pasar de título a demo
|
||||||
TITLE_TO_DEMO, // Pasar de título a demo
|
TITLE_TO_LOGO, // Pasar de título a logo
|
||||||
TITLE_TO_LOGO, // Pasar de título a logo
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// --- Variables globales de estado ---
|
// --- Variables globales de estado ---
|
||||||
extern Name name; // Sección actual
|
extern Name name; // Sección actual
|
||||||
extern Options options; // Opción seleccionada en la sección
|
extern Options options; // Opción seleccionada en la sección
|
||||||
extern AttractMode attract_mode; // Estado del Attract Mode
|
extern AttractMode attract_mode; // Estado del Attract Mode
|
||||||
}
|
} // namespace Section
|
||||||
+83
-142
@@ -1,7 +1,8 @@
|
|||||||
// IWYU pragma: no_include <bits/std_abs.h>
|
// IWYU pragma: no_include <bits/std_abs.h>
|
||||||
#include "credits.h"
|
#include "credits.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_RenderFillRect, SDL_RenderTexture
|
#include <SDL3/SDL.h> // Para SDL_RenderFillRect, SDL_RenderTexture
|
||||||
|
|
||||||
#include <algorithm> // Para max, min, clamp
|
#include <algorithm> // Para max, min, clamp
|
||||||
#include <array> // Para array
|
#include <array> // Para array
|
||||||
#include <cmath> // Para abs
|
#include <cmath> // Para abs
|
||||||
@@ -9,24 +10,24 @@
|
|||||||
#include <string> // Para basic_string, string
|
#include <string> // Para basic_string, string
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
#include "audio.h" // Para Audio
|
#include "audio.h" // Para Audio
|
||||||
#include "balloon_manager.h" // Para BalloonManager
|
#include "balloon_manager.h" // Para BalloonManager
|
||||||
#include "fade.h" // Para Fade, FadeType, FadeMode
|
#include "fade.h" // Para Fade, FadeType, FadeMode
|
||||||
#include "global_events.h" // Para check
|
#include "global_events.h" // Para check
|
||||||
#include "global_inputs.h" // Para check
|
#include "global_inputs.h" // Para check
|
||||||
#include "input.h" // Para Input, INPUT_ALLOW_REPEAT
|
#include "input.h" // Para Input, INPUT_ALLOW_REPEAT
|
||||||
#include "lang.h" // Para getText
|
#include "lang.h" // Para getText
|
||||||
#include "param.h" // Para Param, param, ParamGame, ParamFade
|
#include "param.h" // Para Param, param, ParamGame, ParamFade
|
||||||
#include "player.h" // Para Player, PlayerState
|
#include "player.h" // Para Player, PlayerState
|
||||||
#include "resource.h" // Para Resource
|
#include "resource.h" // Para Resource
|
||||||
#include "screen.h" // Para Screen
|
#include "screen.h" // Para Screen
|
||||||
#include "section.h" // Para Name, name
|
#include "section.h" // Para Name, name
|
||||||
#include "sprite.h" // Para Sprite
|
#include "sprite.h" // Para Sprite
|
||||||
#include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW
|
#include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW
|
||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
|
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
|
||||||
#include "ui/service_menu.h" // Para ServiceMenu
|
#include "ui/service_menu.h" // Para ServiceMenu
|
||||||
#include "utils.h" // Para Color, Zone, SHADOW_TEXT_COLOR, NO_TEXT...
|
#include "utils.h" // Para Color, Zone, SHADOW_TEXT_COLOR, NO_TEXT...
|
||||||
|
|
||||||
// Textos
|
// Textos
|
||||||
constexpr const char TEXT_COPYRIGHT[] = "@2020,2025 JailDesigner";
|
constexpr const char TEXT_COPYRIGHT[] = "@2020,2025 JailDesigner";
|
||||||
@@ -38,10 +39,8 @@ Credits::Credits()
|
|||||||
fade_in_(std::make_unique<Fade>()),
|
fade_in_(std::make_unique<Fade>()),
|
||||||
fade_out_(std::make_unique<Fade>()),
|
fade_out_(std::make_unique<Fade>()),
|
||||||
text_texture_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
text_texture_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
||||||
canvas_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height))
|
canvas_(SDL_CreateTexture(Screen::get()->getRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)) {
|
||||||
{
|
if (!text_texture_) {
|
||||||
if (!text_texture_)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("Failed to create SDL texture for text.");
|
throw std::runtime_error("Failed to create SDL texture for text.");
|
||||||
}
|
}
|
||||||
Section::name = Section::Name::CREDITS;
|
Section::name = Section::Name::CREDITS;
|
||||||
@@ -67,8 +66,7 @@ Credits::Credits()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
Credits::~Credits()
|
Credits::~Credits() {
|
||||||
{
|
|
||||||
SDL_DestroyTexture(text_texture_);
|
SDL_DestroyTexture(text_texture_);
|
||||||
SDL_DestroyTexture(canvas_);
|
SDL_DestroyTexture(canvas_);
|
||||||
resetVolume();
|
resetVolume();
|
||||||
@@ -76,26 +74,21 @@ Credits::~Credits()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Bucle principal
|
// Bucle principal
|
||||||
void Credits::run()
|
void Credits::run() {
|
||||||
{
|
while (Section::name == Section::Name::CREDITS) {
|
||||||
while (Section::name == Section::Name::CREDITS)
|
|
||||||
{
|
|
||||||
checkInput();
|
checkInput();
|
||||||
update();
|
update();
|
||||||
checkEvents(); // Tiene que ir antes del render
|
checkEvents(); // Tiene que ir antes del render
|
||||||
render();
|
render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza las variables
|
// Actualiza las variables
|
||||||
void Credits::update()
|
void Credits::update() {
|
||||||
{
|
if (SDL_GetTicks() - ticks_ > param.game.speed) {
|
||||||
if (SDL_GetTicks() - ticks_ > param.game.speed)
|
|
||||||
{
|
|
||||||
ticks_ = SDL_GetTicks();
|
ticks_ = SDL_GetTicks();
|
||||||
const int REPEAT = want_to_pass_ ? 4 : 1;
|
const int REPEAT = want_to_pass_ ? 4 : 1;
|
||||||
for (int i = 0; i < REPEAT; ++i)
|
for (int i = 0; i < REPEAT; ++i) {
|
||||||
{
|
|
||||||
tiled_bg_->update();
|
tiled_bg_->update();
|
||||||
cycleColors();
|
cycleColors();
|
||||||
balloon_manager_->update();
|
balloon_manager_->update();
|
||||||
@@ -113,8 +106,7 @@ void Credits::update()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja Credits::en patalla
|
// Dibuja Credits::en patalla
|
||||||
void Credits::render()
|
void Credits::render() {
|
||||||
{
|
|
||||||
// Prepara para empezar a dibujar en la textura de juego
|
// Prepara para empezar a dibujar en la textura de juego
|
||||||
Screen::get()->start();
|
Screen::get()->start();
|
||||||
|
|
||||||
@@ -126,30 +118,23 @@ void Credits::render()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba el manejador de eventos
|
// Comprueba el manejador de eventos
|
||||||
void Credits::checkEvents()
|
void Credits::checkEvents() {
|
||||||
{
|
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
while (SDL_PollEvent(&event))
|
while (SDL_PollEvent(&event)) {
|
||||||
{
|
|
||||||
GlobalEvents::check(event);
|
GlobalEvents::check(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba las entradas
|
// Comprueba las entradas
|
||||||
void Credits::checkInput()
|
void Credits::checkInput() {
|
||||||
{
|
|
||||||
Input::get()->update();
|
Input::get()->update();
|
||||||
|
|
||||||
if (!ServiceMenu::get()->isEnabled())
|
if (!ServiceMenu::get()->isEnabled()) {
|
||||||
{
|
|
||||||
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
|
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
|
||||||
if (Input::get()->checkAnyButton(INPUT_ALLOW_REPEAT))
|
if (Input::get()->checkAnyButton(INPUT_ALLOW_REPEAT)) {
|
||||||
{
|
|
||||||
want_to_pass_ = true;
|
want_to_pass_ = true;
|
||||||
fading_ = mini_logo_on_position_;
|
fading_ = mini_logo_on_position_;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
want_to_pass_ = false;
|
want_to_pass_ = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,8 +144,7 @@ void Credits::checkInput()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Crea la textura con el texto
|
// Crea la textura con el texto
|
||||||
void Credits::fillTextTexture()
|
void Credits::fillTextTexture() {
|
||||||
{
|
|
||||||
auto text = Resource::get()->getText("smb2");
|
auto text = Resource::get()->getText("smb2");
|
||||||
auto text_grad = Resource::get()->getText("smb2_grad");
|
auto text_grad = Resource::get()->getText("smb2_grad");
|
||||||
SDL_SetRenderTarget(Screen::get()->getRenderer(), text_texture_);
|
SDL_SetRenderTarget(Screen::get()->getRenderer(), text_texture_);
|
||||||
@@ -248,8 +232,7 @@ void Credits::fillTextTexture()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja todos los sprites en la textura
|
// Dibuja todos los sprites en la textura
|
||||||
void Credits::fillCanvas()
|
void Credits::fillCanvas() {
|
||||||
{
|
|
||||||
// Cambia el destino del renderizador
|
// Cambia el destino del renderizador
|
||||||
auto temp = SDL_GetRenderTarget(Screen::get()->getRenderer());
|
auto temp = SDL_GetRenderTarget(Screen::get()->getRenderer());
|
||||||
SDL_SetRenderTarget(Screen::get()->getRenderer(), canvas_);
|
SDL_SetRenderTarget(Screen::get()->getRenderer(), canvas_);
|
||||||
@@ -279,8 +262,7 @@ void Credits::fillCanvas()
|
|||||||
SDL_RenderRect(Screen::get()->getRenderer(), &red_rect);
|
SDL_RenderRect(Screen::get()->getRenderer(), &red_rect);
|
||||||
|
|
||||||
// Si el mini_logo está en su destino, lo dibuja encima de lo anterior
|
// Si el mini_logo está en su destino, lo dibuja encima de lo anterior
|
||||||
if (mini_logo_on_position_)
|
if (mini_logo_on_position_) {
|
||||||
{
|
|
||||||
SDL_RenderTexture(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_);
|
SDL_RenderTexture(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,72 +275,57 @@ void Credits::fillCanvas()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el destino de los rectangulos de las texturas
|
// Actualiza el destino de los rectangulos de las texturas
|
||||||
void Credits::updateTextureDstRects()
|
void Credits::updateTextureDstRects() {
|
||||||
{
|
if (counter_ % 10 == 0) {
|
||||||
if (counter_ % 10 == 0)
|
|
||||||
{
|
|
||||||
// Comprueba la posición de la textura con los titulos de credito
|
// Comprueba la posición de la textura con los titulos de credito
|
||||||
if (credits_rect_dst_.y + credits_rect_dst_.h > play_area_.y)
|
if (credits_rect_dst_.y + credits_rect_dst_.h > play_area_.y) {
|
||||||
{
|
|
||||||
--credits_rect_dst_.y;
|
--credits_rect_dst_.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba la posición de la textura con el mini_logo
|
// Comprueba la posición de la textura con el mini_logo
|
||||||
if (mini_logo_rect_dst_.y == mini_logo_final_pos_)
|
if (mini_logo_rect_dst_.y == mini_logo_final_pos_) {
|
||||||
{
|
|
||||||
mini_logo_on_position_ = true;
|
mini_logo_on_position_ = true;
|
||||||
|
|
||||||
// Si el jugador quiere pasar los titulos de credito, el fade se inicia solo
|
// Si el jugador quiere pasar los titulos de credito, el fade se inicia solo
|
||||||
if (want_to_pass_)
|
if (want_to_pass_) {
|
||||||
{
|
|
||||||
fading_ = true;
|
fading_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Se activa el contador para evitar que la sección sea infinita
|
// Se activa el contador para evitar que la sección sea infinita
|
||||||
if (counter_prevent_endless_ == 1000)
|
if (counter_prevent_endless_ == 1000) {
|
||||||
{
|
|
||||||
fading_ = true;
|
fading_ = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
++counter_prevent_endless_;
|
++counter_prevent_endless_;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
--mini_logo_rect_dst_.y;
|
--mini_logo_rect_dst_.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tira globos al escenario
|
// Tira globos al escenario
|
||||||
void Credits::throwBalloons()
|
void Credits::throwBalloons() {
|
||||||
{
|
|
||||||
constexpr int speed = 200;
|
constexpr int speed = 200;
|
||||||
const std::vector<int> sets = {0, 63, 25, 67, 17, 75, 13, 50};
|
const std::vector<int> sets = {0, 63, 25, 67, 17, 75, 13, 50};
|
||||||
|
|
||||||
if (counter_ > ((sets.size() - 1) * speed) * 3)
|
if (counter_ > ((sets.size() - 1) * speed) * 3) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (counter_ % speed == 0)
|
if (counter_ % speed == 0) {
|
||||||
{
|
|
||||||
const int index = (counter_ / speed) % sets.size();
|
const int index = (counter_ / speed) % sets.size();
|
||||||
balloon_manager_->deploySet(sets.at(index), -60);
|
balloon_manager_->deploySet(sets.at(index), -60);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (counter_ % (speed * 4) == 0 && counter_ > 0)
|
if (counter_ % (speed * 4) == 0 && counter_ > 0) {
|
||||||
{
|
|
||||||
balloon_manager_->createPowerBall();
|
balloon_manager_->createPowerBall();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa los jugadores
|
// Inicializa los jugadores
|
||||||
void Credits::initPlayers()
|
void Credits::initPlayers() {
|
||||||
{
|
std::vector<std::vector<std::shared_ptr<Texture>>> player_textures; // Vector con todas las texturas de los jugadores;
|
||||||
std::vector<std::vector<std::shared_ptr<Texture>>> player_textures; // Vector con todas las texturas de los jugadores;
|
std::vector<std::vector<std::string>> player_animations; // Vector con las animaciones del jugador
|
||||||
std::vector<std::vector<std::string>> player_animations; // Vector con las animaciones del jugador
|
|
||||||
|
|
||||||
// Texturas - Player1
|
// Texturas - Player1
|
||||||
{
|
{
|
||||||
@@ -397,14 +364,11 @@ void Credits::initPlayers()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza los rectangulos negros
|
// Actualiza los rectangulos negros
|
||||||
void Credits::updateBlackRects()
|
void Credits::updateBlackRects() {
|
||||||
{
|
|
||||||
static int current_step = steps_;
|
static int current_step = steps_;
|
||||||
if (top_black_rect_.h != param.game.game_area.center_y - 1 && bottom_black_rect_.y != param.game.game_area.center_y + 1)
|
if (top_black_rect_.h != param.game.game_area.center_y - 1 && bottom_black_rect_.y != param.game.game_area.center_y + 1) {
|
||||||
{
|
|
||||||
// Si los rectangulos superior e inferior no han llegado al centro
|
// Si los rectangulos superior e inferior no han llegado al centro
|
||||||
if (counter_ % 4 == 0)
|
if (counter_ % 4 == 0) {
|
||||||
{
|
|
||||||
// Incrementa la altura del rectangulo superior
|
// Incrementa la altura del rectangulo superior
|
||||||
top_black_rect_.h = std::min(top_black_rect_.h + 1, param.game.game_area.center_y - 1);
|
top_black_rect_.h = std::min(top_black_rect_.h + 1, param.game.game_area.center_y - 1);
|
||||||
|
|
||||||
@@ -415,12 +379,9 @@ void Credits::updateBlackRects()
|
|||||||
--current_step;
|
--current_step;
|
||||||
setVolume(static_cast<int>(initial_volume_ * current_step / steps_));
|
setVolume(static_cast<int>(initial_volume_ * current_step / steps_));
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Si los rectangulos superior e inferior han llegado al centro
|
// Si los rectangulos superior e inferior han llegado al centro
|
||||||
if (left_black_rect_.w != param.game.game_area.center_x && right_black_rect_.x != param.game.game_area.center_x)
|
if (left_black_rect_.w != param.game.game_area.center_x && right_black_rect_.x != param.game.game_area.center_x) {
|
||||||
{
|
|
||||||
constexpr int SPEED = 2;
|
constexpr int SPEED = 2;
|
||||||
// Si los rectangulos izquierdo y derecho no han llegado al centro
|
// Si los rectangulos izquierdo y derecho no han llegado al centro
|
||||||
// Incrementa la anchura del rectangulo situado a la izquierda
|
// Incrementa la anchura del rectangulo situado a la izquierda
|
||||||
@@ -432,18 +393,13 @@ void Credits::updateBlackRects()
|
|||||||
|
|
||||||
--current_step;
|
--current_step;
|
||||||
setVolume(static_cast<int>(initial_volume_ * current_step / steps_));
|
setVolume(static_cast<int>(initial_volume_ * current_step / steps_));
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
// Si los rectangulos izquierdo y derecho han llegado al centro
|
// Si los rectangulos izquierdo y derecho han llegado al centro
|
||||||
setVolume(0);
|
setVolume(0);
|
||||||
Audio::get()->stopMusic();
|
Audio::get()->stopMusic();
|
||||||
if (counter_pre_fade_ == 400)
|
if (counter_pre_fade_ == 400) {
|
||||||
{
|
|
||||||
fade_out_->activate();
|
fade_out_->activate();
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
++counter_pre_fade_;
|
++counter_pre_fade_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -451,8 +407,7 @@ void Credits::updateBlackRects()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el rectangulo rojo
|
// Actualiza el rectangulo rojo
|
||||||
void Credits::updateRedRect()
|
void Credits::updateRedRect() {
|
||||||
{
|
|
||||||
red_rect.x = left_black_rect_.x + left_black_rect_.w;
|
red_rect.x = left_black_rect_.x + left_black_rect_.w;
|
||||||
red_rect.y = top_black_rect_.y + top_black_rect_.h - 1;
|
red_rect.y = top_black_rect_.y + top_black_rect_.h - 1;
|
||||||
red_rect.w = right_black_rect_.x - red_rect.x;
|
red_rect.w = right_black_rect_.x - red_rect.x;
|
||||||
@@ -460,76 +415,66 @@ void Credits::updateRedRect()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el estado de fade
|
// Actualiza el estado de fade
|
||||||
void Credits::updateAllFades()
|
void Credits::updateAllFades() {
|
||||||
{
|
if (fading_) {
|
||||||
if (fading_)
|
|
||||||
{
|
|
||||||
updateBlackRects();
|
updateBlackRects();
|
||||||
updateRedRect();
|
updateRedRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
fade_in_->update();
|
fade_in_->update();
|
||||||
if (fade_in_->hasEnded())
|
if (fade_in_->hasEnded()) {
|
||||||
{
|
|
||||||
Audio::get()->playMusic("credits.ogg");
|
Audio::get()->playMusic("credits.ogg");
|
||||||
}
|
}
|
||||||
|
|
||||||
fade_out_->update();
|
fade_out_->update();
|
||||||
if (fade_out_->hasEnded())
|
if (fade_out_->hasEnded()) {
|
||||||
{
|
|
||||||
Section::name = Section::Name::HI_SCORE_TABLE;
|
Section::name = Section::Name::HI_SCORE_TABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el nivel de volumen
|
// Establece el nivel de volumen
|
||||||
void Credits::setVolume(int amount)
|
void Credits::setVolume(int amount) {
|
||||||
{
|
|
||||||
Options::audio.music.volume = std::clamp(amount, 0, 100);
|
Options::audio.music.volume = std::clamp(amount, 0, 100);
|
||||||
Audio::get()->setMusicVolume(Options::audio.music.volume);
|
Audio::get()->setMusicVolume(Options::audio.music.volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reestablece el nivel de volumen
|
// Reestablece el nivel de volumen
|
||||||
void Credits::resetVolume()
|
void Credits::resetVolume() {
|
||||||
{
|
|
||||||
Options::audio.music.volume = initial_volume_;
|
Options::audio.music.volume = initial_volume_;
|
||||||
Audio::get()->setMusicVolume(Options::audio.music.volume);
|
Audio::get()->setMusicVolume(Options::audio.music.volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cambia el color del fondo
|
// Cambia el color del fondo
|
||||||
void Credits::cycleColors()
|
void Credits::cycleColors() {
|
||||||
{
|
|
||||||
// constexpr int UPPER_LIMIT = 255; // Límite superior
|
// constexpr int UPPER_LIMIT = 255; // Límite superior
|
||||||
// constexpr int LOWER_LIMIT = 80; // Límite inferior
|
// constexpr int LOWER_LIMIT = 80; // Límite inferior
|
||||||
|
|
||||||
constexpr int UPPER_LIMIT = 140; // Límite superior
|
constexpr int UPPER_LIMIT = 140; // Límite superior
|
||||||
constexpr int LOWER_LIMIT = 30; // Límite inferior
|
constexpr int LOWER_LIMIT = 30; // Límite inferior
|
||||||
|
|
||||||
static float r = static_cast<float>(UPPER_LIMIT);
|
static float r = static_cast<float>(UPPER_LIMIT);
|
||||||
static float g = static_cast<float>(LOWER_LIMIT);
|
static float g = static_cast<float>(LOWER_LIMIT);
|
||||||
static float b = static_cast<float>(LOWER_LIMIT);
|
static float b = static_cast<float>(LOWER_LIMIT);
|
||||||
static float stepR = -0.5f; // Paso flotante para transiciones suaves
|
static float stepR = -0.5f; // Paso flotante para transiciones suaves
|
||||||
static float stepG = 0.3f;
|
static float stepG = 0.3f;
|
||||||
static float stepB = 0.1f;
|
static float stepB = 0.1f;
|
||||||
|
|
||||||
// Ajustar valores de R
|
// Ajustar valores de R
|
||||||
r += stepR;
|
r += stepR;
|
||||||
if (r >= UPPER_LIMIT || r <= LOWER_LIMIT)
|
if (r >= UPPER_LIMIT || r <= LOWER_LIMIT) {
|
||||||
{
|
stepR = -stepR; // Cambia de dirección al alcanzar los límites
|
||||||
stepR = -stepR; // Cambia de dirección al alcanzar los límites
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ajustar valores de G
|
// Ajustar valores de G
|
||||||
g += stepG;
|
g += stepG;
|
||||||
if (g >= UPPER_LIMIT || g <= LOWER_LIMIT)
|
if (g >= UPPER_LIMIT || g <= LOWER_LIMIT) {
|
||||||
{
|
stepG = -stepG; // Cambia de dirección al alcanzar los límites
|
||||||
stepG = -stepG; // Cambia de dirección al alcanzar los límites
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ajustar valores de B
|
// Ajustar valores de B
|
||||||
b += stepB;
|
b += stepB;
|
||||||
if (b >= UPPER_LIMIT || b <= LOWER_LIMIT)
|
if (b >= UPPER_LIMIT || b <= LOWER_LIMIT) {
|
||||||
{
|
stepB = -stepB; // Cambia de dirección al alcanzar los límites
|
||||||
stepB = -stepB; // Cambia de dirección al alcanzar los límites
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aplicar el color, redondeando a enteros antes de usar
|
// Aplicar el color, redondeando a enteros antes de usar
|
||||||
@@ -538,19 +483,15 @@ void Credits::cycleColors()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actualza los jugadores
|
// Actualza los jugadores
|
||||||
void Credits::updatePlayers()
|
void Credits::updatePlayers() {
|
||||||
{
|
for (auto &player : players_) {
|
||||||
for (auto &player : players_)
|
|
||||||
{
|
|
||||||
player->update();
|
player->update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderiza los jugadores
|
// Renderiza los jugadores
|
||||||
void Credits::renderPlayers()
|
void Credits::renderPlayers() {
|
||||||
{
|
for (auto const &player : players_) {
|
||||||
for (auto const &player : players_)
|
|
||||||
{
|
|
||||||
player->render();
|
player->render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+47
-47
@@ -1,12 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FRect, Uint32, SDL_Texture, Uint64
|
#include <SDL3/SDL.h> // Para SDL_FRect, Uint32, SDL_Texture, Uint64
|
||||||
#include <memory> // Para unique_ptr, shared_ptr
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "options.h" // Para AudioOptions, MusicOptions, audio
|
#include <memory> // Para unique_ptr, shared_ptr
|
||||||
#include "param.h" // Para Param, ParamGame, param
|
#include <vector> // Para vector
|
||||||
#include "utils.h" // Para Zone, Color
|
|
||||||
|
#include "options.h" // Para AudioOptions, MusicOptions, audio
|
||||||
|
#include "param.h" // Para Param, ParamGame, param
|
||||||
|
#include "utils.h" // Para Zone, Color
|
||||||
|
|
||||||
// Declaraciones adelantadas
|
// Declaraciones adelantadas
|
||||||
class BalloonManager;
|
class BalloonManager;
|
||||||
@@ -14,9 +15,8 @@ class Fade;
|
|||||||
class Player;
|
class Player;
|
||||||
class TiledBG;
|
class TiledBG;
|
||||||
|
|
||||||
class Credits
|
class Credits {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor ---
|
||||||
Credits();
|
Credits();
|
||||||
~Credits();
|
~Credits();
|
||||||
@@ -24,40 +24,40 @@ public:
|
|||||||
// --- Bucle principal ---
|
// --- Bucle principal ---
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Constantes de clase ---
|
// --- Constantes de clase ---
|
||||||
static constexpr int PLAY_AREA_HEIGHT = 200;
|
static constexpr int PLAY_AREA_HEIGHT = 200;
|
||||||
|
|
||||||
// --- Objetos principales ---
|
// --- Objetos principales ---
|
||||||
std::unique_ptr<BalloonManager> balloon_manager_; // Gestión de globos
|
std::unique_ptr<BalloonManager> balloon_manager_; // Gestión de globos
|
||||||
std::unique_ptr<TiledBG> tiled_bg_; // Mosaico animado de fondo
|
std::unique_ptr<TiledBG> tiled_bg_; // Mosaico animado de fondo
|
||||||
std::unique_ptr<Fade> fade_in_; // Fundido de entrada
|
std::unique_ptr<Fade> fade_in_; // Fundido de entrada
|
||||||
std::unique_ptr<Fade> fade_out_; // Fundido de salida
|
std::unique_ptr<Fade> fade_out_; // Fundido de salida
|
||||||
std::vector<std::shared_ptr<Player>> players_; // Vector de jugadores
|
std::vector<std::shared_ptr<Player>> players_; // Vector de jugadores
|
||||||
|
|
||||||
// --- Gestión de texturas ---
|
// --- Gestión de texturas ---
|
||||||
SDL_Texture *text_texture_; // Textura con el texto de créditos
|
SDL_Texture *text_texture_; // Textura con el texto de créditos
|
||||||
SDL_Texture *canvas_; // Textura donde se dibuja todo
|
SDL_Texture *canvas_; // Textura donde se dibuja todo
|
||||||
|
|
||||||
// --- Temporización y contadores ---
|
// --- Temporización y contadores ---
|
||||||
Uint64 ticks_ = 0; // Control de velocidad del programa
|
Uint64 ticks_ = 0; // Control de velocidad del programa
|
||||||
Uint32 counter_ = 0; // Contador principal de lógica
|
Uint32 counter_ = 0; // Contador principal de lógica
|
||||||
Uint32 counter_pre_fade_ = 0; // Activación del fundido final
|
Uint32 counter_pre_fade_ = 0; // Activación del fundido final
|
||||||
Uint32 counter_prevent_endless_ = 0; // Prevención de bucle infinito
|
Uint32 counter_prevent_endless_ = 0; // Prevención de bucle infinito
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
bool fading_ = false; // Estado del fade final
|
bool fading_ = false; // Estado del fade final
|
||||||
bool want_to_pass_ = false; // Jugador quiere saltarse créditos
|
bool want_to_pass_ = false; // Jugador quiere saltarse créditos
|
||||||
bool mini_logo_on_position_ = false; // Minilogo en posición final
|
bool mini_logo_on_position_ = false; // Minilogo en posición final
|
||||||
|
|
||||||
// --- Diseño y posicionamiento ---
|
// --- Diseño y posicionamiento ---
|
||||||
float black_bars_size_ = (param.game.game_area.rect.h - PLAY_AREA_HEIGHT) / 2; // Tamaño de las barras negras
|
float black_bars_size_ = (param.game.game_area.rect.h - PLAY_AREA_HEIGHT) / 2; // Tamaño de las barras negras
|
||||||
int mini_logo_final_pos_ = 0; // Posición final del minilogo
|
int mini_logo_final_pos_ = 0; // Posición final del minilogo
|
||||||
Color color_; // Color usado para los efectos
|
Color color_; // Color usado para los efectos
|
||||||
|
|
||||||
// --- Control de audio ---
|
// --- Control de audio ---
|
||||||
int initial_volume_ = Options::audio.music.volume; // Volumen inicial
|
int initial_volume_ = Options::audio.music.volume; // Volumen inicial
|
||||||
int steps_ = 0; // Pasos para reducir audio
|
int steps_ = 0; // Pasos para reducir audio
|
||||||
|
|
||||||
// --- Rectángulos de renderizado ---
|
// --- Rectángulos de renderizado ---
|
||||||
// Texto de créditos
|
// Texto de créditos
|
||||||
@@ -98,32 +98,32 @@ private:
|
|||||||
2};
|
2};
|
||||||
|
|
||||||
// Borde para la ventana
|
// Borde para la ventana
|
||||||
SDL_FRect red_rect = play_area_; // Delimitador de ventana
|
SDL_FRect red_rect = play_area_; // Delimitador de ventana
|
||||||
|
|
||||||
// --- Métodos del bucle principal ---
|
// --- Métodos del bucle principal ---
|
||||||
void update(); // Actualización principal de la lógica
|
void update(); // Actualización principal de la lógica
|
||||||
void render(); // Renderizado de la escena
|
void render(); // Renderizado de la escena
|
||||||
void checkEvents(); // Manejo de eventos
|
void checkEvents(); // Manejo de eventos
|
||||||
void checkInput(); // Procesamiento de entrada
|
void checkInput(); // Procesamiento de entrada
|
||||||
|
|
||||||
// --- Métodos de renderizado ---
|
// --- Métodos de renderizado ---
|
||||||
void fillTextTexture(); // Crear textura de texto de créditos
|
void fillTextTexture(); // Crear textura de texto de créditos
|
||||||
void fillCanvas(); // Renderizar todos los sprites y fondos
|
void fillCanvas(); // Renderizar todos los sprites y fondos
|
||||||
void updateTextureDstRects(); // Actualizar destinos de texturas
|
void updateTextureDstRects(); // Actualizar destinos de texturas
|
||||||
void renderPlayers(); // Renderiza los jugadores
|
void renderPlayers(); // Renderiza los jugadores
|
||||||
|
|
||||||
// --- Métodos de lógica del juego ---
|
// --- Métodos de lógica del juego ---
|
||||||
void throwBalloons(); // Lanzar globos al escenario
|
void throwBalloons(); // Lanzar globos al escenario
|
||||||
void initPlayers(); // Inicializar jugadores
|
void initPlayers(); // Inicializar jugadores
|
||||||
void updateAllFades(); // Actualizar estados de fade
|
void updateAllFades(); // Actualizar estados de fade
|
||||||
void cycleColors(); // Cambiar colores de fondo
|
void cycleColors(); // Cambiar colores de fondo
|
||||||
void updatePlayers(); // Actualza los jugadores
|
void updatePlayers(); // Actualza los jugadores
|
||||||
|
|
||||||
// --- Métodos de interfaz ---
|
// --- Métodos de interfaz ---
|
||||||
void updateBlackRects(); // Actualizar rectángulos negros (letterbox)
|
void updateBlackRects(); // Actualizar rectángulos negros (letterbox)
|
||||||
void updateRedRect(); // Actualizar rectángulo rojo (borde)
|
void updateRedRect(); // Actualizar rectángulo rojo (borde)
|
||||||
|
|
||||||
// --- Métodos de audio ---
|
// --- Métodos de audio ---
|
||||||
void setVolume(int amount); // Establecer volumen
|
void setVolume(int amount); // Establecer volumen
|
||||||
void resetVolume(); // Restablecer volumen
|
void resetVolume(); // Restablecer volumen
|
||||||
};
|
};
|
||||||
+1404
-1729
File diff suppressed because it is too large.
Load diff
+195
-197
@@ -1,14 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_Event, SDL_Renderer, SDL_Texture, Uint64, Uint8
|
#include <SDL3/SDL.h> // Para SDL_Event, SDL_Renderer, SDL_Texture, Uint64, Uint8
|
||||||
#include <memory> // Para shared_ptr, unique_ptr
|
|
||||||
#include <string> // Para string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "manage_hiscore_table.h" // Para HiScoreEntry
|
#include <memory> // Para shared_ptr, unique_ptr
|
||||||
#include "options.h" // Para SettingsOptions, settings, DifficultyCode (ptr only)
|
#include <string> // Para string
|
||||||
#include "player.h" // Para Player
|
#include <vector> // Para vector
|
||||||
#include "utils.h" // Para Demo
|
|
||||||
|
#include "manage_hiscore_table.h" // Para HiScoreEntry
|
||||||
|
#include "options.h" // Para SettingsOptions, settings, DifficultyCode (ptr only)
|
||||||
|
#include "player.h" // Para Player
|
||||||
|
#include "utils.h" // Para Demo
|
||||||
|
|
||||||
class Background;
|
class Background;
|
||||||
class Balloon;
|
class Balloon;
|
||||||
@@ -35,216 +36,213 @@ constexpr bool GAME_MODE_DEMO_ON = true;
|
|||||||
constexpr int TOTAL_SCORE_DATA = 3;
|
constexpr int TOTAL_SCORE_DATA = 3;
|
||||||
|
|
||||||
// Clase Game
|
// Clase Game
|
||||||
class Game
|
class Game {
|
||||||
{
|
public:
|
||||||
public:
|
// Constructor
|
||||||
// Constructor
|
Game(int playerID, int current_stage, bool demo);
|
||||||
Game(int playerID, int current_stage, bool demo);
|
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~Game();
|
~Game();
|
||||||
|
|
||||||
// Bucle principal del juego
|
// Bucle principal del juego
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Tipos internos ---
|
// --- Tipos internos ---
|
||||||
enum class GameState
|
enum class GameState {
|
||||||
{
|
FADE_IN,
|
||||||
FADE_IN,
|
ENTERING_PLAYER,
|
||||||
ENTERING_PLAYER,
|
SHOWING_GET_READY_MESSAGE,
|
||||||
SHOWING_GET_READY_MESSAGE,
|
PLAYING,
|
||||||
PLAYING,
|
COMPLETED,
|
||||||
COMPLETED,
|
GAME_OVER,
|
||||||
GAME_OVER,
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// --- Constantes internas ---
|
// --- Constantes internas ---
|
||||||
static constexpr int HELP_COUNTER_ = 1000;
|
static constexpr int HELP_COUNTER_ = 1000;
|
||||||
static constexpr int GAME_COMPLETED_START_FADE_ = 500;
|
static constexpr int GAME_COMPLETED_START_FADE_ = 500;
|
||||||
static constexpr int GAME_COMPLETED_END_ = 700;
|
static constexpr int GAME_COMPLETED_END_ = 700;
|
||||||
static constexpr int GAME_OVER_COUNTER_ = 350;
|
static constexpr int GAME_OVER_COUNTER_ = 350;
|
||||||
static constexpr int TIME_STOPPED_COUNTER_ = 360;
|
static constexpr int TIME_STOPPED_COUNTER_ = 360;
|
||||||
static constexpr int ITEM_POINTS_1_DISK_ODDS_ = 10;
|
static constexpr int ITEM_POINTS_1_DISK_ODDS_ = 10;
|
||||||
static constexpr int ITEM_POINTS_2_GAVINA_ODDS_ = 6;
|
static constexpr int ITEM_POINTS_2_GAVINA_ODDS_ = 6;
|
||||||
static constexpr int ITEM_POINTS_3_PACMAR_ODDS_ = 3;
|
static constexpr int ITEM_POINTS_3_PACMAR_ODDS_ = 3;
|
||||||
static constexpr int ITEM_CLOCK_ODDS_ = 5;
|
static constexpr int ITEM_CLOCK_ODDS_ = 5;
|
||||||
static constexpr int ITEM_COFFEE_ODDS_ = 5;
|
static constexpr int ITEM_COFFEE_ODDS_ = 5;
|
||||||
static constexpr int ITEM_POWER_BALL_ODDS_ = 0;
|
static constexpr int ITEM_POWER_BALL_ODDS_ = 0;
|
||||||
static constexpr int ITEM_COFFEE_MACHINE_ODDS_ = 4;
|
static constexpr int ITEM_COFFEE_MACHINE_ODDS_ = 4;
|
||||||
|
|
||||||
// --- Estructuras ---
|
// --- Estructuras ---
|
||||||
struct Helper
|
struct Helper {
|
||||||
{
|
bool need_coffee; // Indica si se necesitan cafes
|
||||||
bool need_coffee; // Indica si se necesitan cafes
|
bool need_coffee_machine; // Indica si se necesita PowerUp
|
||||||
bool need_coffee_machine; // Indica si se necesita PowerUp
|
bool need_power_ball; // Indica si se necesita una PowerBall
|
||||||
bool need_power_ball; // Indica si se necesita una PowerBall
|
int counter; // Contador para no dar ayudas consecutivas
|
||||||
int counter; // Contador para no dar ayudas consecutivas
|
int item_disk_odds; // Probabilidad de aparición del objeto
|
||||||
int item_disk_odds; // Probabilidad de aparición del objeto
|
int item_gavina_odds; // Probabilidad de aparición del objeto
|
||||||
int item_gavina_odds; // Probabilidad de aparición del objeto
|
int item_pacmar_odds; // Probabilidad de aparición del objeto
|
||||||
int item_pacmar_odds; // Probabilidad de aparición del objeto
|
int item_clock_odds; // Probabilidad de aparición del objeto
|
||||||
int item_clock_odds; // Probabilidad de aparición del objeto
|
int item_coffee_odds; // Probabilidad de aparición del objeto
|
||||||
int item_coffee_odds; // Probabilidad de aparición del objeto
|
int item_coffee_machine_odds; // Probabilidad de aparición del objeto
|
||||||
int item_coffee_machine_odds; // Probabilidad de aparición del objeto
|
|
||||||
|
|
||||||
Helper()
|
Helper()
|
||||||
: need_coffee(false),
|
: need_coffee(false),
|
||||||
need_coffee_machine(false),
|
need_coffee_machine(false),
|
||||||
need_power_ball(false),
|
need_power_ball(false),
|
||||||
counter(HELP_COUNTER_),
|
counter(HELP_COUNTER_),
|
||||||
item_disk_odds(ITEM_POINTS_1_DISK_ODDS_),
|
item_disk_odds(ITEM_POINTS_1_DISK_ODDS_),
|
||||||
item_gavina_odds(ITEM_POINTS_2_GAVINA_ODDS_),
|
item_gavina_odds(ITEM_POINTS_2_GAVINA_ODDS_),
|
||||||
item_pacmar_odds(ITEM_POINTS_3_PACMAR_ODDS_),
|
item_pacmar_odds(ITEM_POINTS_3_PACMAR_ODDS_),
|
||||||
item_clock_odds(ITEM_CLOCK_ODDS_),
|
item_clock_odds(ITEM_CLOCK_ODDS_),
|
||||||
item_coffee_odds(ITEM_COFFEE_ODDS_),
|
item_coffee_odds(ITEM_COFFEE_ODDS_),
|
||||||
item_coffee_machine_odds(ITEM_COFFEE_MACHINE_ODDS_) {}
|
item_coffee_machine_odds(ITEM_COFFEE_MACHINE_ODDS_) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
SDL_Renderer *renderer_; // El renderizador de la ventana
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
Screen *screen_; // Objeto encargado de dibujar en pantalla
|
Screen *screen_; // Objeto encargado de dibujar en pantalla
|
||||||
Input *input_; // Manejador de entrada
|
Input *input_; // Manejador de entrada
|
||||||
Scoreboard *scoreboard_; // Objeto para dibujar el marcador
|
Scoreboard *scoreboard_; // Objeto para dibujar el marcador
|
||||||
|
|
||||||
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
|
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
|
||||||
|
|
||||||
SDL_Texture *canvas_; // Textura para dibujar la zona de juego
|
SDL_Texture *canvas_; // Textura para dibujar la zona de juego
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
|
std::vector<std::shared_ptr<Player>> players_; // Vector con los jugadores
|
||||||
std::vector<std::unique_ptr<Bullet>> bullets_; // Vector con las balas
|
std::vector<std::unique_ptr<Bullet>> bullets_; // Vector con las balas
|
||||||
std::vector<std::unique_ptr<Item>> items_; // Vector con los items
|
std::vector<std::unique_ptr<Item>> items_; // Vector con los items
|
||||||
std::vector<std::unique_ptr<SmartSprite>> smart_sprites_; // Vector con los smartsprites
|
std::vector<std::unique_ptr<SmartSprite>> smart_sprites_; // Vector con los smartsprites
|
||||||
std::vector<std::unique_ptr<PathSprite>> path_sprites_; // Vector con los pathsprites
|
std::vector<std::unique_ptr<PathSprite>> path_sprites_; // Vector con los pathsprites
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
|
std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
|
||||||
std::vector<std::vector<std::shared_ptr<Texture>>> player_textures_; // Vector con todas las texturas de los jugadores
|
std::vector<std::vector<std::shared_ptr<Texture>>> player_textures_; // Vector con todas las texturas de los jugadores
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Texture>> game_text_textures_; // Vector con las texturas para los sprites con textos
|
std::vector<std::shared_ptr<Texture>> game_text_textures_; // Vector con las texturas para los sprites con textos
|
||||||
|
|
||||||
std::vector<std::vector<std::string>> item_animations_; // Vector con las animaciones de los items
|
std::vector<std::vector<std::string>> item_animations_; // Vector con las animaciones de los items
|
||||||
std::vector<std::vector<std::string>> player_animations_; // Vector con las animaciones del jugador
|
std::vector<std::vector<std::string>> player_animations_; // Vector con las animaciones del jugador
|
||||||
|
|
||||||
std::unique_ptr<Fade> fade_in_; // Objeto para renderizar fades
|
std::unique_ptr<Fade> fade_in_; // Objeto para renderizar fades
|
||||||
std::unique_ptr<Fade> fade_out_; // Objeto para renderizar fades
|
std::unique_ptr<Fade> fade_out_; // Objeto para renderizar fades
|
||||||
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
|
std::unique_ptr<BalloonManager> balloon_manager_; // Objeto para gestionar los globos
|
||||||
std::unique_ptr<Tabe> tabe_; // Objeto para gestionar el Tabe Volaor
|
std::unique_ptr<Tabe> tabe_; // Objeto para gestionar el Tabe Volaor
|
||||||
std::vector<Path> paths_; // Vector con los recorridos precalculados almacenados
|
std::vector<Path> paths_; // Vector con los recorridos precalculados almacenados
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
HiScoreEntry hi_score_ = HiScoreEntry(
|
HiScoreEntry hi_score_ = HiScoreEntry(
|
||||||
Options::settings.hi_score_table[0].name,
|
Options::settings.hi_score_table[0].name,
|
||||||
Options::settings.hi_score_table[0].score); // Máxima puntuación y nombre de quien la ostenta
|
Options::settings.hi_score_table[0].score); // Máxima puntuación y nombre de quien la ostenta
|
||||||
|
|
||||||
Demo demo_; // Variable con todas las variables relacionadas con el modo demo
|
Demo demo_; // Variable con todas las variables relacionadas con el modo demo
|
||||||
Options::DifficultyCode difficulty_ = Options::settings.difficulty; // Dificultad del juego
|
Options::DifficultyCode difficulty_ = Options::settings.difficulty; // Dificultad del juego
|
||||||
Helper helper_; // Variable para gestionar las ayudas
|
Helper helper_; // Variable para gestionar las ayudas
|
||||||
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
||||||
bool coffee_machine_enabled_ = false; // Indica si hay una máquina de café en el terreno de juego
|
bool coffee_machine_enabled_ = false; // Indica si hay una máquina de café en el terreno de juego
|
||||||
bool hi_score_achieved_ = false; // Indica si se ha superado la puntuación máxima
|
bool hi_score_achieved_ = false; // Indica si se ha superado la puntuación máxima
|
||||||
bool paused_ = false; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade)
|
bool paused_ = false; // Indica si el juego está pausado (no se deberia de poder utilizar en el modo arcade)
|
||||||
// bool paused_by_service_menu_ = false;
|
// bool paused_by_service_menu_ = false;
|
||||||
float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
|
float difficulty_score_multiplier_; // Multiplicador de puntos en función de la dificultad
|
||||||
int counter_ = 0; // Contador para el juego
|
int counter_ = 0; // Contador para el juego
|
||||||
int game_completed_counter_ = 0; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos
|
int game_completed_counter_ = 0; // Contador para el tramo final, cuando se ha completado la partida y ya no aparecen más enemigos
|
||||||
int game_over_counter_ = GAME_OVER_COUNTER_; // Contador para el estado de fin de partida
|
int game_over_counter_ = GAME_OVER_COUNTER_; // Contador para el estado de fin de partida
|
||||||
int time_stopped_counter_ = 0; // Temporizador para llevar la cuenta del tiempo detenido
|
int time_stopped_counter_ = 0; // Temporizador para llevar la cuenta del tiempo detenido
|
||||||
int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
|
int total_power_to_complete_game_; // La suma del poder necesario para completar todas las fases
|
||||||
int menace_current_ = 0; // Nivel de amenaza actual
|
int menace_current_ = 0; // Nivel de amenaza actual
|
||||||
int menace_threshold_ = 0; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos
|
int menace_threshold_ = 0; // Umbral del nivel de amenaza. Si el nivel de amenaza cae por debajo del umbral, se generan más globos. Si el umbral aumenta, aumenta el número de globos
|
||||||
GameState state_ = GameState::FADE_IN; // Estado
|
GameState state_ = GameState::FADE_IN; // Estado
|
||||||
std::vector<std::shared_ptr<Player>> players_to_reorder;
|
std::vector<std::shared_ptr<Player>> players_to_reorder;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados
|
bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados
|
||||||
|
|
||||||
// Comprueba los eventos en el modo DEBUG
|
// Comprueba los eventos en el modo DEBUG
|
||||||
void checkDebugEvents(const SDL_Event &event);
|
void checkDebugEvents(const SDL_Event &event);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void update(); // Actualiza el juego
|
void update(); // Actualiza el juego
|
||||||
void render(); // Dibuja el juego
|
void render(); // Dibuja el juego
|
||||||
void checkEvents(); // Comprueba los eventos que hay en cola
|
void checkEvents(); // Comprueba los eventos que hay en cola
|
||||||
void setResources(); // Asigna texturas y animaciones
|
void setResources(); // Asigna texturas y animaciones
|
||||||
void updateHiScore(); // Actualiza el valor de HiScore en caso necesario
|
void updateHiScore(); // Actualiza el valor de HiScore en caso necesario
|
||||||
void updatePlayers(); // Actualiza las variables del jugador
|
void updatePlayers(); // Actualiza las variables del jugador
|
||||||
void renderPlayers(); // Dibuja a los jugadores
|
void renderPlayers(); // Dibuja a los jugadores
|
||||||
void updateStage(); // Comprueba si hay cambio de fase y actualiza las variables
|
void updateStage(); // Comprueba si hay cambio de fase y actualiza las variables
|
||||||
void updateGameStateGameOver(); // Actualiza el estado de fin de la partida
|
void updateGameStateGameOver(); // Actualiza el estado de fin de la partida
|
||||||
void destroyAllItems(); // Destruye todos los items
|
void destroyAllItems(); // Destruye todos los items
|
||||||
std::shared_ptr<Balloon> checkPlayerBalloonCollision(std::shared_ptr<Player> &player); // Comprueba la colisión entre el jugador y los globos activos
|
std::shared_ptr<Balloon> checkPlayerBalloonCollision(std::shared_ptr<Player> &player); // Comprueba la colisión entre el jugador y los globos activos
|
||||||
void checkPlayerItemCollision(std::shared_ptr<Player> &player); // Comprueba la colisión entre el jugador y los items
|
void checkPlayerItemCollision(std::shared_ptr<Player> &player); // Comprueba la colisión entre el jugador y los items
|
||||||
void checkBulletCollision(); // Comprueba y procesa la colisión de las balas
|
void checkBulletCollision(); // Comprueba y procesa la colisión de las balas
|
||||||
void updateBullets(); // Mueve las balas activas
|
void updateBullets(); // Mueve las balas activas
|
||||||
void renderBullets(); // Pinta las balas activas
|
void renderBullets(); // Pinta las balas activas
|
||||||
void createBullet(int x, int y, BulletType kind, bool powered_up, int owner); // Crea un objeto bala
|
void createBullet(int x, int y, BulletType kind, bool powered_up, int owner); // Crea un objeto bala
|
||||||
void freeBullets(); // Vacia el vector de balas
|
void freeBullets(); // Vacia el vector de balas
|
||||||
void updateItems(); // Actualiza los items
|
void updateItems(); // Actualiza los items
|
||||||
void renderItems(); // Pinta los items activos
|
void renderItems(); // Pinta los items activos
|
||||||
ItemType dropItem(); // Devuelve un item en función del azar
|
ItemType dropItem(); // Devuelve un item en función del azar
|
||||||
void createItem(ItemType type, float x, float y); // Crea un objeto item
|
void createItem(ItemType type, float x, float y); // Crea un objeto item
|
||||||
void freeItems(); // Vacia el vector de items
|
void freeItems(); // Vacia el vector de items
|
||||||
void createItemText(int x, std::shared_ptr<Texture> texture); // Crea un objeto PathSprite
|
void createItemText(int x, std::shared_ptr<Texture> texture); // Crea un objeto PathSprite
|
||||||
void createMessage(const std::vector<Path> &paths, std::shared_ptr<Texture> texture); // Crea un objeto PathSprite
|
void createMessage(const std::vector<Path> &paths, std::shared_ptr<Texture> texture); // Crea un objeto PathSprite
|
||||||
void freeSmartSprites(); // Vacia el vector de smartsprites
|
void freeSmartSprites(); // Vacia el vector de smartsprites
|
||||||
void freePathSprites(); // Vacia el vector de pathsprites
|
void freePathSprites(); // Vacia el vector de pathsprites
|
||||||
void throwCoffee(int x, int y); // Crea un SpriteSmart para arrojar el item café al recibir un impacto
|
void throwCoffee(int x, int y); // Crea un SpriteSmart para arrojar el item café al recibir un impacto
|
||||||
void updateSmartSprites(); // Actualiza los SpriteSmarts
|
void updateSmartSprites(); // Actualiza los SpriteSmarts
|
||||||
void renderSmartSprites(); // Pinta los SpriteSmarts activos
|
void renderSmartSprites(); // Pinta los SpriteSmarts activos
|
||||||
void updatePathSprites(); // Actualiza los PathSprites
|
void updatePathSprites(); // Actualiza los PathSprites
|
||||||
void renderPathSprites(); // Pinta los PathSprites activos
|
void renderPathSprites(); // Pinta los PathSprites activos
|
||||||
void handlePlayerCollision(std::shared_ptr<Player> &player); // Acciones a realizar cuando el jugador colisiona con un globo
|
void handlePlayerCollision(std::shared_ptr<Player> &player); // Acciones a realizar cuando el jugador colisiona con un globo
|
||||||
void updateTimeStopped(); // Actualiza y comprueba el valor de la variable
|
void updateTimeStopped(); // Actualiza y comprueba el valor de la variable
|
||||||
void updateBackground(); // Actualiza el fondo
|
void updateBackground(); // Actualiza el fondo
|
||||||
void initPaths(); // Inicializa las variables que contienen puntos de ruta para mover objetos
|
void initPaths(); // Inicializa las variables que contienen puntos de ruta para mover objetos
|
||||||
void enableTimeStopItem(); // Habilita el efecto del item de detener el tiempo
|
void enableTimeStopItem(); // Habilita el efecto del item de detener el tiempo
|
||||||
void disableTimeStopItem(); // Deshabilita el efecto del item de detener el tiempo
|
void disableTimeStopItem(); // Deshabilita el efecto del item de detener el tiempo
|
||||||
void updateHelper(); // Actualiza las variables de ayuda
|
void updateHelper(); // Actualiza las variables de ayuda
|
||||||
bool allPlayersAreWaitingOrGameOver(); // Comprueba si todos los jugadores han terminado de jugar
|
bool allPlayersAreWaitingOrGameOver(); // Comprueba si todos los jugadores han terminado de jugar
|
||||||
bool allPlayersAreGameOver(); // Comprueba si todos los jugadores han terminado de jugar
|
bool allPlayersAreGameOver(); // Comprueba si todos los jugadores han terminado de jugar
|
||||||
bool allPlayersAreNotPlaying(); // Comprueba si todos los jugadores han terminado de jugar
|
bool allPlayersAreNotPlaying(); // Comprueba si todos los jugadores han terminado de jugar
|
||||||
void updateScoreboard(); // Actualiza el marcador
|
void updateScoreboard(); // Actualiza el marcador
|
||||||
void fillCanvas(); // Dibuja los elementos de la zona de juego en su textura
|
void fillCanvas(); // Dibuja los elementos de la zona de juego en su textura
|
||||||
void pause(bool value); // Pausa el juego
|
void pause(bool value); // Pausa el juego
|
||||||
void addScoreToScoreBoard(const std::shared_ptr<Player> &player); // Añade una puntuación a la tabla de records
|
void addScoreToScoreBoard(const std::shared_ptr<Player> &player); // Añade una puntuación a la tabla de records
|
||||||
void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index); // Saca del estado de GAME OVER al jugador si el otro está activo
|
void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index); // Saca del estado de GAME OVER al jugador si el otro está activo
|
||||||
void checkPlayersStatusPlaying(); // Comprueba el estado de juego de los jugadores
|
void checkPlayersStatusPlaying(); // Comprueba el estado de juego de los jugadores
|
||||||
std::shared_ptr<Player> getPlayer(int id); // Obtiene un jugador a partir de su "id"
|
std::shared_ptr<Player> getPlayer(int id); // Obtiene un jugador a partir de su "id"
|
||||||
int getController(int playerId); // Obtiene un controlador a partir del "id" del jugador
|
int getController(int playerId); // Obtiene un controlador a partir del "id" del jugador
|
||||||
void checkInput(); // Gestiona la entrada durante el juego
|
void checkInput(); // Gestiona la entrada durante el juego
|
||||||
void checkPauseInput(); // Verifica si alguno de los controladores ha solicitado una pausa y actualiza el estado de pausa del juego.
|
void checkPauseInput(); // Verifica si alguno de los controladores ha solicitado una pausa y actualiza el estado de pausa del juego.
|
||||||
void DEMO_handleInput(); // Gestiona las entradas de los jugadores en el modo demo, incluyendo movimientos y disparos automáticos.
|
void DEMO_handleInput(); // Gestiona las entradas de los jugadores en el modo demo, incluyendo movimientos y disparos automáticos.
|
||||||
void DEMO_handlePassInput(); // Gestiona las entradas de los jugadores en el modo demo para saltarse la demo.
|
void DEMO_handlePassInput(); // Gestiona las entradas de los jugadores en el modo demo para saltarse la demo.
|
||||||
void DEMO_handlePlayerInput(const std::shared_ptr<Player> &player, int index); // Procesa las entradas para un jugador específico durante el modo demo.
|
void DEMO_handlePlayerInput(const std::shared_ptr<Player> &player, int index); // Procesa las entradas para un jugador específico durante el modo demo.
|
||||||
void handleFireInput(const std::shared_ptr<Player> &player, BulletType bulletType); // Maneja el disparo de un jugador, incluyendo la creación de balas y la gestión del tiempo de espera entre disparos.
|
void handleFireInput(const std::shared_ptr<Player> &player, BulletType bulletType); // Maneja el disparo de un jugador, incluyendo la creación de balas y la gestión del tiempo de espera entre disparos.
|
||||||
void handlePlayersInput(); // Gestiona las entradas de todos los jugadores en el modo normal (fuera del modo demo).
|
void handlePlayersInput(); // Gestiona las entradas de todos los jugadores en el modo normal (fuera del modo demo).
|
||||||
void handleNormalPlayerInput(const std::shared_ptr<Player> &player); // Maneja las entradas de movimiento y disparo para un jugador en modo normal.
|
void handleNormalPlayerInput(const std::shared_ptr<Player> &player); // Maneja las entradas de movimiento y disparo para un jugador en modo normal.
|
||||||
void handleFireInputs(const std::shared_ptr<Player> &player, bool autofire, int controllerIndex); // Procesa las entradas de disparo del jugador, permitiendo disparos automáticos si está habilitado.
|
void handleFireInputs(const std::shared_ptr<Player> &player, bool autofire, int controllerIndex); // Procesa las entradas de disparo del jugador, permitiendo disparos automáticos si está habilitado.
|
||||||
void handlePlayerContinue(const std::shared_ptr<Player> &player); // Maneja la continuación del jugador cuando no está jugando, permitiendo que continúe si se pulsa el botón de inicio.
|
void handlePlayerContinue(const std::shared_ptr<Player> &player); // Maneja la continuación del jugador cuando no está jugando, permitiendo que continúe si se pulsa el botón de inicio.
|
||||||
void handleNameInput(const std::shared_ptr<Player> &player); // Procesa las entradas para la introducción del nombre del jugador.
|
void handleNameInput(const std::shared_ptr<Player> &player); // Procesa las entradas para la introducción del nombre del jugador.
|
||||||
void initDemo(int player_id); // Inicializa las variables para el modo DEMO
|
void initDemo(int player_id); // Inicializa las variables para el modo DEMO
|
||||||
void setTotalPower(); // Calcula el poder total necesario para completar el juego
|
void setTotalPower(); // Calcula el poder total necesario para completar el juego
|
||||||
void initScoreboard(); // Inicializa el marcador
|
void initScoreboard(); // Inicializa el marcador
|
||||||
void initDifficultyVars(); // Inicializa las opciones relacionadas con la dificultad
|
void initDifficultyVars(); // Inicializa las opciones relacionadas con la dificultad
|
||||||
void initPlayers(int player_id); // Inicializa los jugadores
|
void initPlayers(int player_id); // Inicializa los jugadores
|
||||||
void playMusic(); // Hace sonar la música
|
void playMusic(); // Hace sonar la música
|
||||||
void stopMusic(); // Detiene la música
|
void stopMusic(); // Detiene la música
|
||||||
void playSound(const std::string &name); // Hace sonar un sonido
|
void playSound(const std::string &name); // Hace sonar un sonido
|
||||||
void updateDemo(); // Actualiza las variables durante el modo demo
|
void updateDemo(); // Actualiza las variables durante el modo demo
|
||||||
void updateGameStateFadeIn(); // Actualiza las variables durante dicho estado
|
void updateGameStateFadeIn(); // Actualiza las variables durante dicho estado
|
||||||
void updateGameStateEnteringPlayer(); // Actualiza las variables durante dicho estado
|
void updateGameStateEnteringPlayer(); // Actualiza las variables durante dicho estado
|
||||||
void updateGameStateShowingGetReadyMessage(); // Actualiza las variables durante dicho estado
|
void updateGameStateShowingGetReadyMessage(); // Actualiza las variables durante dicho estado
|
||||||
void updateGameStatePlaying(); // Actualiza las variables durante el transcurso normal del juego
|
void updateGameStatePlaying(); // Actualiza las variables durante el transcurso normal del juego
|
||||||
void updateGameStateCompleted(); // Gestiona eventos para el estado del final del juego
|
void updateGameStateCompleted(); // Gestiona eventos para el estado del final del juego
|
||||||
void checkState(); // Comprueba el estado del juego
|
void checkState(); // Comprueba el estado del juego
|
||||||
void cleanVectors(); // Vacía los vectores de elementos deshabilitados
|
void cleanVectors(); // Vacía los vectores de elementos deshabilitados
|
||||||
void updateMenace(); // Gestiona el nivel de amenaza
|
void updateMenace(); // Gestiona el nivel de amenaza
|
||||||
void evaluateAndSetMenace(); // Calcula y establece el valor de amenaza en funcion de los globos activos
|
void evaluateAndSetMenace(); // Calcula y establece el valor de amenaza en funcion de los globos activos
|
||||||
void checkAndUpdateBalloonSpeed(); // Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
|
void checkAndUpdateBalloonSpeed(); // Actualiza la velocidad de los globos en funcion del poder acumulado de la fase
|
||||||
void setState(GameState state); // Cambia el estado del juego
|
void setState(GameState state); // Cambia el estado del juego
|
||||||
void movePlayersToFront(); // Organiza los jugadores para que los vivos se pinten sobre los muertos
|
void movePlayersToFront(); // Organiza los jugadores para que los vivos se pinten sobre los muertos
|
||||||
void checkServiceMenu(); // Comprueba si está activo el menu de servicio para poner el juego en pausa
|
void checkServiceMenu(); // Comprueba si está activo el menu de servicio para poner el juego en pausa
|
||||||
#ifdef RECORDING
|
#ifdef RECORDING
|
||||||
void updateRecording(); // Actualiza las variables durante el modo de grabación
|
void updateRecording(); // Actualiza las variables durante el modo de grabación
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
+293
-336
@@ -1,432 +1,389 @@
|
|||||||
#include "hiscore_table.h"
|
#include "hiscore_table.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_GetTicks, SDL_SetRenderTarget
|
#include <SDL3/SDL.h> // Para SDL_GetTicks, SDL_SetRenderTarget
|
||||||
#include <stdlib.h> // Para rand, size_t
|
#include <stdlib.h> // Para rand, size_t
|
||||||
#include <algorithm> // Para max
|
|
||||||
#include <functional> // Para function
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "audio.h" // Para Audio
|
#include <algorithm> // Para max
|
||||||
#include "background.h" // Para Background
|
#include <functional> // Para function
|
||||||
#include "fade.h" // Para Fade, FadeMode, FadeType
|
#include <vector> // Para vector
|
||||||
#include "global_events.h" // Para check
|
|
||||||
#include "global_inputs.h" // Para check
|
#include "audio.h" // Para Audio
|
||||||
#include "input.h" // Para Input
|
#include "background.h" // Para Background
|
||||||
#include "lang.h" // Para getText
|
#include "fade.h" // Para Fade, FadeMode, FadeType
|
||||||
#include "manage_hiscore_table.h" // Para HiScoreEntry
|
#include "global_events.h" // Para check
|
||||||
#include "options.h" // Para SettingsOptions, settings
|
#include "global_inputs.h" // Para check
|
||||||
#include "param.h" // Para Param, param, ParamGame, ParamFade
|
#include "input.h" // Para Input
|
||||||
#include "path_sprite.h" // Para PathSprite, Path, PathType
|
#include "lang.h" // Para getText
|
||||||
#include "resource.h" // Para Resource
|
#include "manage_hiscore_table.h" // Para HiScoreEntry
|
||||||
#include "screen.h" // Para Screen
|
#include "options.h" // Para SettingsOptions, settings
|
||||||
#include "section.h" // Para Name, name, Options, options
|
#include "param.h" // Para Param, param, ParamGame, ParamFade
|
||||||
#include "sprite.h" // Para Sprite
|
#include "path_sprite.h" // Para PathSprite, Path, PathType
|
||||||
#include "text.h" // Para Text, TEXT_SHADOW, TEXT_COLOR
|
#include "resource.h" // Para Resource
|
||||||
#include "texture.h" // Para Texture
|
#include "screen.h" // Para Screen
|
||||||
#include "utils.h" // Para Color, easeOutQuint, NO_TEXT_COLOR
|
#include "section.h" // Para Name, name, Options, options
|
||||||
|
#include "sprite.h" // Para Sprite
|
||||||
|
#include "text.h" // Para Text, TEXT_SHADOW, TEXT_COLOR
|
||||||
|
#include "texture.h" // Para Texture
|
||||||
|
#include "utils.h" // Para Color, easeOutQuint, NO_TEXT_COLOR
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
HiScoreTable::HiScoreTable()
|
HiScoreTable::HiScoreTable()
|
||||||
: renderer_(Screen::get()->getRenderer()),
|
: renderer_(Screen::get()->getRenderer()),
|
||||||
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
||||||
fade_(std::make_unique<Fade>()),
|
fade_(std::make_unique<Fade>()),
|
||||||
background_(std::make_unique<Background>()),
|
background_(std::make_unique<Background>()),
|
||||||
counter_(0),
|
counter_(0),
|
||||||
ticks_(0),
|
ticks_(0),
|
||||||
view_area_(SDL_FRect{0, 0, static_cast<float>(param.game.width), static_cast<float>(param.game.height)}),
|
view_area_(SDL_FRect{0, 0, static_cast<float>(param.game.width), static_cast<float>(param.game.height)}),
|
||||||
fade_mode_(FadeMode::IN),
|
fade_mode_(FadeMode::IN),
|
||||||
background_fade_color_(Color(0, 0, 0))
|
background_fade_color_(Color(0, 0, 0)) {
|
||||||
{
|
// Inicializa el resto
|
||||||
// Inicializa el resto
|
Section::name = Section::Name::HI_SCORE_TABLE;
|
||||||
Section::name = Section::Name::HI_SCORE_TABLE;
|
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
|
||||||
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
|
initFade();
|
||||||
initFade();
|
initBackground();
|
||||||
initBackground();
|
iniEntryColors();
|
||||||
iniEntryColors();
|
createSprites();
|
||||||
createSprites();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
HiScoreTable::~HiScoreTable()
|
HiScoreTable::~HiScoreTable() {
|
||||||
{
|
SDL_DestroyTexture(backbuffer_);
|
||||||
SDL_DestroyTexture(backbuffer_);
|
Options::settings.clearLastHiScoreEntries();
|
||||||
Options::settings.clearLastHiScoreEntries();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza las variables
|
// Actualiza las variables
|
||||||
void HiScoreTable::update()
|
void HiScoreTable::update() {
|
||||||
{
|
if (SDL_GetTicks() - ticks_ > param.game.speed) {
|
||||||
if (SDL_GetTicks() - ticks_ > param.game.speed)
|
// Actualiza el contador de ticks
|
||||||
{
|
ticks_ = SDL_GetTicks();
|
||||||
// Actualiza el contador de ticks
|
|
||||||
ticks_ = SDL_GetTicks();
|
|
||||||
|
|
||||||
// Actualiza las posiciones de los sprites de texto
|
// Actualiza las posiciones de los sprites de texto
|
||||||
updateSprites();
|
updateSprites();
|
||||||
|
|
||||||
// Actualiza el fondo
|
// Actualiza el fondo
|
||||||
background_->update();
|
background_->update();
|
||||||
|
|
||||||
// Gestiona el fade
|
// Gestiona el fade
|
||||||
updateFade();
|
updateFade();
|
||||||
|
|
||||||
// Gestiona el contador y sus eventos
|
// Gestiona el contador y sus eventos
|
||||||
updateCounter();
|
updateCounter();
|
||||||
|
|
||||||
// Dibuja los sprites en la textura
|
// Dibuja los sprites en la textura
|
||||||
fillTexture();
|
fillTexture();
|
||||||
|
|
||||||
// Actualiza el objeto screen
|
// Actualiza el objeto screen
|
||||||
Screen::get()->update();
|
Screen::get()->update();
|
||||||
|
|
||||||
// Actualiza las variables de globalInputs
|
// Actualiza las variables de globalInputs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja los sprites en la textura
|
// Dibuja los sprites en la textura
|
||||||
void HiScoreTable::fillTexture()
|
void HiScoreTable::fillTexture() {
|
||||||
{
|
// Pinta en el backbuffer el texto y los sprites
|
||||||
// Pinta en el backbuffer el texto y los sprites
|
auto temp = SDL_GetRenderTarget(renderer_);
|
||||||
auto temp = SDL_GetRenderTarget(renderer_);
|
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
||||||
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
SDL_RenderClear(renderer_);
|
||||||
SDL_RenderClear(renderer_);
|
|
||||||
|
|
||||||
// Escribe el texto: Mejores puntuaciones
|
// Escribe el texto: Mejores puntuaciones
|
||||||
header_->render();
|
header_->render();
|
||||||
|
|
||||||
// Escribe los nombres de la tabla de puntuaciones
|
// Escribe los nombres de la tabla de puntuaciones
|
||||||
for (auto const &entry : entry_names_)
|
for (auto const &entry : entry_names_) {
|
||||||
{
|
entry->render();
|
||||||
entry->render();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Cambia el destino de renderizado
|
// Cambia el destino de renderizado
|
||||||
SDL_SetRenderTarget(renderer_, temp);
|
SDL_SetRenderTarget(renderer_, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pinta en pantalla
|
// Pinta en pantalla
|
||||||
void HiScoreTable::render()
|
void HiScoreTable::render() {
|
||||||
{
|
// Prepara para empezar a dibujar en la textura de juego
|
||||||
// Prepara para empezar a dibujar en la textura de juego
|
Screen::get()->start();
|
||||||
Screen::get()->start();
|
|
||||||
|
|
||||||
// Limpia la pantalla
|
// Limpia la pantalla
|
||||||
Screen::get()->clean();
|
Screen::get()->clean();
|
||||||
|
|
||||||
// Pinta el fondo
|
// Pinta el fondo
|
||||||
background_->render();
|
background_->render();
|
||||||
|
|
||||||
// Establece la ventana del backbuffer
|
// Establece la ventana del backbuffer
|
||||||
view_area_.y = std::max(0.0f, param.game.height - counter_ + 100);
|
view_area_.y = std::max(0.0f, param.game.height - counter_ + 100);
|
||||||
|
|
||||||
// Copia el backbuffer al renderizador
|
// Copia el backbuffer al renderizador
|
||||||
SDL_RenderTexture(renderer_, backbuffer_, nullptr, &view_area_);
|
SDL_RenderTexture(renderer_, backbuffer_, nullptr, &view_area_);
|
||||||
|
|
||||||
// Renderiza el fade
|
// Renderiza el fade
|
||||||
fade_->render();
|
fade_->render();
|
||||||
|
|
||||||
// Vuelca el contenido del renderizador en pantalla
|
// Vuelca el contenido del renderizador en pantalla
|
||||||
Screen::get()->render();
|
Screen::get()->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba los eventos
|
// Comprueba los eventos
|
||||||
void HiScoreTable::checkEvents()
|
void HiScoreTable::checkEvents() {
|
||||||
{
|
SDL_Event event;
|
||||||
SDL_Event event;
|
while (SDL_PollEvent(&event)) {
|
||||||
while (SDL_PollEvent(&event))
|
GlobalEvents::check(event);
|
||||||
{
|
}
|
||||||
GlobalEvents::check(event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba las entradas
|
// Comprueba las entradas
|
||||||
void HiScoreTable::checkInput()
|
void HiScoreTable::checkInput() {
|
||||||
{
|
Input::get()->update();
|
||||||
Input::get()->update();
|
GlobalInputs::check();
|
||||||
GlobalInputs::check();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bucle para la pantalla de instrucciones
|
// Bucle para la pantalla de instrucciones
|
||||||
void HiScoreTable::run()
|
void HiScoreTable::run() {
|
||||||
{
|
Audio::get()->playMusic("title.ogg");
|
||||||
Audio::get()->playMusic("title.ogg");
|
while (Section::name == Section::Name::HI_SCORE_TABLE) {
|
||||||
while (Section::name == Section::Name::HI_SCORE_TABLE)
|
checkInput();
|
||||||
{
|
update();
|
||||||
checkInput();
|
checkEvents(); // Tiene que ir antes del render
|
||||||
update();
|
render();
|
||||||
checkEvents(); // Tiene que ir antes del render
|
}
|
||||||
render();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gestiona el fade
|
// Gestiona el fade
|
||||||
void HiScoreTable::updateFade()
|
void HiScoreTable::updateFade() {
|
||||||
{
|
fade_->update();
|
||||||
fade_->update();
|
|
||||||
|
|
||||||
if (fade_->hasEnded() && fade_mode_ == FadeMode::IN)
|
if (fade_->hasEnded() && fade_mode_ == FadeMode::IN) {
|
||||||
{
|
fade_->reset();
|
||||||
fade_->reset();
|
fade_mode_ = FadeMode::OUT;
|
||||||
fade_mode_ = FadeMode::OUT;
|
fade_->setMode(fade_mode_);
|
||||||
fade_->setMode(fade_mode_);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (fade_->hasEnded() && fade_mode_ == FadeMode::OUT)
|
if (fade_->hasEnded() && fade_mode_ == FadeMode::OUT) {
|
||||||
{
|
Section::name = (Section::options == Section::Options::HI_SCORE_AFTER_PLAYING)
|
||||||
Section::name = (Section::options == Section::Options::HI_SCORE_AFTER_PLAYING)
|
? Section::Name::TITLE
|
||||||
? Section::Name::TITLE
|
: Section::Name::INSTRUCTIONS;
|
||||||
: Section::Name::INSTRUCTIONS;
|
Section::options = Section::Options::NONE;
|
||||||
Section::options = Section::Options::NONE;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convierte un entero a un string con separadores de miles
|
// Convierte un entero a un string con separadores de miles
|
||||||
std::string HiScoreTable::format(int number)
|
std::string HiScoreTable::format(int number) {
|
||||||
{
|
const std::string separator = ".";
|
||||||
const std::string separator = ".";
|
const std::string score = std::to_string(number);
|
||||||
const std::string score = std::to_string(number);
|
|
||||||
|
|
||||||
auto index = (int)score.size() - 1;
|
auto index = (int)score.size() - 1;
|
||||||
std::string result;
|
std::string result;
|
||||||
auto i = 0;
|
auto i = 0;
|
||||||
while (index >= 0)
|
while (index >= 0) {
|
||||||
{
|
result = score.at(index) + result;
|
||||||
result = score.at(index) + result;
|
index--;
|
||||||
index--;
|
i++;
|
||||||
i++;
|
if (i == 3) {
|
||||||
if (i == 3)
|
i = 0;
|
||||||
{
|
result = separator + result;
|
||||||
i = 0;
|
}
|
||||||
result = separator + result;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea los sprites con los textos
|
// Crea los sprites con los textos
|
||||||
void HiScoreTable::createSprites()
|
void HiScoreTable::createSprites() {
|
||||||
{
|
auto header_text = Resource::get()->getText("04b_25_grey");
|
||||||
auto header_text = Resource::get()->getText("04b_25_grey");
|
auto entry_text = Resource::get()->getText("smb2");
|
||||||
auto entry_text = Resource::get()->getText("smb2");
|
|
||||||
|
|
||||||
// Obtiene el tamaño de la textura
|
// Obtiene el tamaño de la textura
|
||||||
float backbuffer_width;
|
float backbuffer_width;
|
||||||
float backbuffer_height;
|
float backbuffer_height;
|
||||||
SDL_GetTextureSize(backbuffer_, &backbuffer_width, &backbuffer_height);
|
SDL_GetTextureSize(backbuffer_, &backbuffer_width, &backbuffer_height);
|
||||||
|
|
||||||
constexpr int ENTRY_LENGHT = 22;
|
constexpr int ENTRY_LENGHT = 22;
|
||||||
constexpr int MAX_NAMES = 10;
|
constexpr int MAX_NAMES = 10;
|
||||||
const int space_between_header = entry_text->getCharacterSize() * 4;
|
const int space_between_header = entry_text->getCharacterSize() * 4;
|
||||||
const int space_between_lines = entry_text->getCharacterSize() * 2;
|
const int space_between_lines = entry_text->getCharacterSize() * 2;
|
||||||
const int size = space_between_header + space_between_lines * (MAX_NAMES - 1) + entry_text->getCharacterSize();
|
const int size = space_between_header + space_between_lines * (MAX_NAMES - 1) + entry_text->getCharacterSize();
|
||||||
const int first_line = (param.game.height - size) / 2;
|
const int first_line = (param.game.height - size) / 2;
|
||||||
|
|
||||||
// Crea el sprite para el texto de cabecera
|
// Crea el sprite para el texto de cabecera
|
||||||
header_ = std::make_unique<Sprite>(header_text->writeDXToTexture(TEXT_COLOR, Lang::getText("[HIGHSCORE_TABLE] CAPTION"), -2, background_fade_color_.inverse().lighten(25)));
|
header_ = std::make_unique<Sprite>(header_text->writeDXToTexture(TEXT_COLOR, Lang::getText("[HIGHSCORE_TABLE] CAPTION"), -2, background_fade_color_.inverse().lighten(25)));
|
||||||
header_->setPosition(param.game.game_area.center_x - (header_->getWidth() / 2), first_line);
|
header_->setPosition(param.game.game_area.center_x - (header_->getWidth() / 2), first_line);
|
||||||
|
|
||||||
// Crea los sprites para las entradas en la tabla de puntuaciones
|
// Crea los sprites para las entradas en la tabla de puntuaciones
|
||||||
const int animation = rand() % 4;
|
const int animation = rand() % 4;
|
||||||
const std::string sample_line(ENTRY_LENGHT + 3, ' ');
|
const std::string sample_line(ENTRY_LENGHT + 3, ' ');
|
||||||
auto sample_entry = std::make_unique<Sprite>(entry_text->writeDXToTexture(TEXT_SHADOW, sample_line, 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR));
|
auto sample_entry = std::make_unique<Sprite>(entry_text->writeDXToTexture(TEXT_SHADOW, sample_line, 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR));
|
||||||
const auto entry_width = sample_entry->getWidth();
|
const auto entry_width = sample_entry->getWidth();
|
||||||
for (int i = 0; i < MAX_NAMES; ++i)
|
for (int i = 0; i < MAX_NAMES; ++i) {
|
||||||
{
|
const auto table_position = format(i + 1) + ". ";
|
||||||
const auto table_position = format(i + 1) + ". ";
|
const auto score = format(Options::settings.hi_score_table.at(i).score);
|
||||||
const auto score = format(Options::settings.hi_score_table.at(i).score);
|
const auto num_dots = ENTRY_LENGHT - Options::settings.hi_score_table.at(i).name.size() - score.size();
|
||||||
const auto num_dots = ENTRY_LENGHT - Options::settings.hi_score_table.at(i).name.size() - score.size();
|
const auto one_cc = Options::settings.hi_score_table.at(i).one_credit_complete ? " }" : "";
|
||||||
const auto one_cc = Options::settings.hi_score_table.at(i).one_credit_complete ? " }" : "";
|
std::string dots;
|
||||||
std::string dots;
|
for (int j = 0; j < (int)num_dots; ++j) {
|
||||||
for (int j = 0; j < (int)num_dots; ++j)
|
dots = dots + ".";
|
||||||
{
|
}
|
||||||
dots = dots + ".";
|
const auto line = table_position + Options::settings.hi_score_table.at(i).name + dots + score + one_cc;
|
||||||
}
|
|
||||||
const auto line = table_position + Options::settings.hi_score_table.at(i).name + dots + score + one_cc;
|
|
||||||
|
|
||||||
entry_names_.emplace_back(std::make_shared<PathSprite>(entry_text->writeDXToTexture(TEXT_SHADOW, line, 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR)));
|
entry_names_.emplace_back(std::make_shared<PathSprite>(entry_text->writeDXToTexture(TEXT_SHADOW, line, 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR)));
|
||||||
const int default_pos_x = (backbuffer_width - entry_width) / 2;
|
const int default_pos_x = (backbuffer_width - entry_width) / 2;
|
||||||
const int pos_x = (i < 9) ? default_pos_x : default_pos_x - entry_text->getCharacterSize();
|
const int pos_x = (i < 9) ? default_pos_x : default_pos_x - entry_text->getCharacterSize();
|
||||||
const int pos_y = (i * space_between_lines) + first_line + space_between_header;
|
const int pos_y = (i * space_between_lines) + first_line + space_between_header;
|
||||||
constexpr int steps = 80;
|
constexpr int steps = 80;
|
||||||
switch (animation)
|
switch (animation) {
|
||||||
{
|
case 0: // Ambos lados alternativamente
|
||||||
case 0: // Ambos lados alternativamente
|
{
|
||||||
{
|
if (i % 2 == 0) {
|
||||||
if (i % 2 == 0)
|
entry_names_.back()->addPath(-entry_names_.back()->getWidth(), pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
|
||||||
{
|
entry_names_.back()->setPosition(-entry_names_.back()->getWidth(), 0);
|
||||||
entry_names_.back()->addPath(-entry_names_.back()->getWidth(), pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
|
} else {
|
||||||
entry_names_.back()->setPosition(-entry_names_.back()->getWidth(), 0);
|
entry_names_.back()->addPath(backbuffer_width, pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
|
||||||
}
|
entry_names_.back()->setPosition(backbuffer_width, 0);
|
||||||
else
|
}
|
||||||
{
|
break;
|
||||||
entry_names_.back()->addPath(backbuffer_width, pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
|
}
|
||||||
entry_names_.back()->setPosition(backbuffer_width, 0);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 1: // Entran por la izquierda
|
case 1: // Entran por la izquierda
|
||||||
{
|
{
|
||||||
entry_names_.back()->addPath(-entry_names_.back()->getWidth(), pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
|
entry_names_.back()->addPath(-entry_names_.back()->getWidth(), pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
|
||||||
entry_names_.back()->setPosition(-entry_names_.back()->getWidth(), 0);
|
entry_names_.back()->setPosition(-entry_names_.back()->getWidth(), 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 2: // Entran por la derecha
|
case 2: // Entran por la derecha
|
||||||
{
|
{
|
||||||
entry_names_.back()->addPath(backbuffer_width, pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
|
entry_names_.back()->addPath(backbuffer_width, pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
|
||||||
entry_names_.back()->setPosition(backbuffer_width, 0);
|
entry_names_.back()->setPosition(backbuffer_width, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 3: // Entran desde la parte inferior
|
case 3: // Entran desde la parte inferior
|
||||||
{
|
{
|
||||||
entry_names_.back()->addPath(backbuffer_height, pos_y, PathType::VERTICAL, pos_x, steps, easeOutQuint);
|
entry_names_.back()->addPath(backbuffer_height, pos_y, PathType::VERTICAL, pos_x, steps, easeOutQuint);
|
||||||
entry_names_.back()->setPosition(0, backbuffer_height);
|
entry_names_.back()->setPosition(0, backbuffer_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza las posiciones de los sprites de texto
|
// Actualiza las posiciones de los sprites de texto
|
||||||
void HiScoreTable::updateSprites()
|
void HiScoreTable::updateSprites() {
|
||||||
{
|
constexpr int init_counter = 190;
|
||||||
constexpr int init_counter = 190;
|
const int counter_between_entries = 16;
|
||||||
const int counter_between_entries = 16;
|
if (counter_ >= init_counter) {
|
||||||
if (counter_ >= init_counter)
|
const int counter2 = counter_ - init_counter;
|
||||||
{
|
if (counter2 % counter_between_entries == 0) {
|
||||||
const int counter2 = counter_ - init_counter;
|
int index = counter2 / counter_between_entries;
|
||||||
if (counter2 % counter_between_entries == 0)
|
if (index < static_cast<int>(entry_names_.size())) {
|
||||||
{
|
entry_names_.at(index)->enable();
|
||||||
int index = counter2 / counter_between_entries;
|
}
|
||||||
if (index < static_cast<int>(entry_names_.size()))
|
}
|
||||||
{
|
}
|
||||||
entry_names_.at(index)->enable();
|
for (auto const &entry : entry_names_) {
|
||||||
}
|
entry->update();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
for (auto const &entry : entry_names_)
|
|
||||||
{
|
|
||||||
entry->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
glowEntryNames();
|
glowEntryNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa el fade
|
// Inicializa el fade
|
||||||
void HiScoreTable::initFade()
|
void HiScoreTable::initFade() {
|
||||||
{
|
fade_->setColor(param.fade.color);
|
||||||
fade_->setColor(param.fade.color);
|
fade_->setType(FadeType::RANDOM_SQUARE);
|
||||||
fade_->setType(FadeType::RANDOM_SQUARE);
|
fade_->setPostDuration(param.fade.post_duration);
|
||||||
fade_->setPostDuration(param.fade.post_duration);
|
fade_->setMode(fade_mode_);
|
||||||
fade_->setMode(fade_mode_);
|
fade_->activate();
|
||||||
fade_->activate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa el fondo
|
// Inicializa el fondo
|
||||||
void HiScoreTable::initBackground()
|
void HiScoreTable::initBackground() {
|
||||||
{
|
background_->setPos(param.game.game_area.rect);
|
||||||
background_->setPos(param.game.game_area.rect);
|
background_->setCloudsSpeed(-0.1f);
|
||||||
background_->setCloudsSpeed(-0.1f);
|
|
||||||
|
|
||||||
const int lucky = rand() % 3;
|
const int lucky = rand() % 3;
|
||||||
switch (lucky)
|
switch (lucky) {
|
||||||
{
|
case 0: // Fondo verde
|
||||||
case 0: // Fondo verde
|
{
|
||||||
{
|
background_->setGradientNumber(2);
|
||||||
background_->setGradientNumber(2);
|
background_->setTransition(0.0f);
|
||||||
background_->setTransition(0.0f);
|
background_->setSunProgression(1.0f);
|
||||||
background_->setSunProgression(1.0f);
|
background_->setMoonProgression(0.0f);
|
||||||
background_->setMoonProgression(0.0f);
|
background_fade_color_ = GREEN_SKY_COLOR;
|
||||||
background_fade_color_ = GREEN_SKY_COLOR;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
case 1: // Fondo naranja
|
case 1: // Fondo naranja
|
||||||
{
|
{
|
||||||
background_->setGradientNumber(1);
|
background_->setGradientNumber(1);
|
||||||
background_->setTransition(0.0f);
|
background_->setTransition(0.0f);
|
||||||
background_->setSunProgression(0.65f);
|
background_->setSunProgression(0.65f);
|
||||||
background_->setMoonProgression(0.0f);
|
background_->setMoonProgression(0.0f);
|
||||||
background_fade_color_ = PINK_SKY_COLOR;
|
background_fade_color_ = PINK_SKY_COLOR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 2: // Fondo azul
|
case 2: // Fondo azul
|
||||||
{
|
{
|
||||||
background_->setGradientNumber(0);
|
background_->setGradientNumber(0);
|
||||||
background_->setTransition(0.0f);
|
background_->setTransition(0.0f);
|
||||||
background_->setSunProgression(0.0f);
|
background_->setSunProgression(0.0f);
|
||||||
background_->setMoonProgression(0.0f);
|
background_->setMoonProgression(0.0f);
|
||||||
background_fade_color_ = BLUE_SKY_COLOR;
|
background_fade_color_ = BLUE_SKY_COLOR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene un color del vector de colores de entradas
|
// Obtiene un color del vector de colores de entradas
|
||||||
Color HiScoreTable::getEntryColor(int counter_)
|
Color HiScoreTable::getEntryColor(int counter_) {
|
||||||
{
|
int cycle_length = entry_colors_.size() * 2 - 2;
|
||||||
int cycle_length = entry_colors_.size() * 2 - 2;
|
size_t n = counter_ % cycle_length;
|
||||||
size_t n = counter_ % cycle_length;
|
|
||||||
|
|
||||||
size_t index;
|
size_t index;
|
||||||
if (n < entry_colors_.size())
|
if (n < entry_colors_.size()) {
|
||||||
{
|
index = n; // Avanza: 0,1,2,3
|
||||||
index = n; // Avanza: 0,1,2,3
|
} else {
|
||||||
}
|
index = 2 * (entry_colors_.size() - 1) - n; // Retrocede: 2,1
|
||||||
else
|
}
|
||||||
{
|
|
||||||
index = 2 * (entry_colors_.size() - 1) - n; // Retrocede: 2,1
|
|
||||||
}
|
|
||||||
|
|
||||||
return entry_colors_[index];
|
return entry_colors_[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa los colores de las entradas
|
// Inicializa los colores de las entradas
|
||||||
void HiScoreTable::iniEntryColors()
|
void HiScoreTable::iniEntryColors() {
|
||||||
{
|
entry_colors_.clear();
|
||||||
entry_colors_.clear();
|
entry_colors_.emplace_back(background_fade_color_.inverse().lighten(75));
|
||||||
entry_colors_.emplace_back(background_fade_color_.inverse().lighten(75));
|
entry_colors_.emplace_back(background_fade_color_.inverse().lighten(50));
|
||||||
entry_colors_.emplace_back(background_fade_color_.inverse().lighten(50));
|
entry_colors_.emplace_back(background_fade_color_.inverse().lighten(25));
|
||||||
entry_colors_.emplace_back(background_fade_color_.inverse().lighten(25));
|
entry_colors_.emplace_back(background_fade_color_.inverse());
|
||||||
entry_colors_.emplace_back(background_fade_color_.inverse());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hace brillar los nombres de la tabla de records
|
// Hace brillar los nombres de la tabla de records
|
||||||
void HiScoreTable::glowEntryNames()
|
void HiScoreTable::glowEntryNames() {
|
||||||
{
|
const Color entry_color = getEntryColor(counter_ / 5);
|
||||||
const Color entry_color = getEntryColor(counter_ / 5);
|
for (const auto &entry_index : Options::settings.last_hi_score_entry) {
|
||||||
for (const auto &entry_index : Options::settings.last_hi_score_entry)
|
if (entry_index != -1) {
|
||||||
{
|
entry_names_.at(entry_index)->getTexture()->setColor(entry_color);
|
||||||
if (entry_index != -1)
|
}
|
||||||
{
|
}
|
||||||
entry_names_.at(entry_index)->getTexture()->setColor(entry_color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gestiona el contador
|
// Gestiona el contador
|
||||||
void HiScoreTable::updateCounter()
|
void HiScoreTable::updateCounter() {
|
||||||
{
|
++counter_;
|
||||||
++counter_;
|
|
||||||
|
|
||||||
if (counter_ == 150)
|
if (counter_ == 150) {
|
||||||
{
|
background_->setColor(background_fade_color_.darken());
|
||||||
background_->setColor(background_fade_color_.darken());
|
background_->setAlpha(96);
|
||||||
background_->setAlpha(96);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (counter_ == COUNTER_END_)
|
if (counter_ == COUNTER_END_) {
|
||||||
{
|
fade_->activate();
|
||||||
fade_->activate();
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para Uint16, SDL_FRect, SDL_Renderer, SDL_Texture, Uint64, Uint8
|
#include <SDL3/SDL.h> // Para Uint16, SDL_FRect, SDL_Renderer, SDL_Texture, Uint64, Uint8
|
||||||
#include <memory> // Para unique_ptr, shared_ptr
|
|
||||||
#include <string> // Para string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "utils.h" // Para Color
|
#include <memory> // Para unique_ptr, shared_ptr
|
||||||
|
#include <string> // Para string
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
|
#include "utils.h" // Para Color
|
||||||
|
|
||||||
class Background;
|
class Background;
|
||||||
class Fade;
|
class Fade;
|
||||||
@@ -15,64 +16,63 @@ enum class FadeMode : Uint8;
|
|||||||
struct Path;
|
struct Path;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Esta clase gestiona un estado del programa. Se encarga de mostrar la tabla con las puntuaciones
|
Esta clase gestiona un estado del programa. Se encarga de mostrar la tabla con las puntuaciones
|
||||||
más altas. Para ello utiliza un objeto que se encarga de pintar el fondo y una textura
|
más altas. Para ello utiliza un objeto que se encarga de pintar el fondo y una textura
|
||||||
sobre la que escribe las puntuaciones. Esta textura se recorre modificando la ventana de vista
|
sobre la que escribe las puntuaciones. Esta textura se recorre modificando la ventana de vista
|
||||||
para dar el efecto de que la textura se mueve sobre la pantalla.
|
para dar el efecto de que la textura se mueve sobre la pantalla.
|
||||||
|
|
||||||
Para mejorar la legibilidad de los textos, el objeto que dibuja el fondo es capaz de modificar
|
Para mejorar la legibilidad de los textos, el objeto que dibuja el fondo es capaz de modificar
|
||||||
su atenuación.
|
su atenuación.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Clase HiScoreTable
|
// Clase HiScoreTable
|
||||||
class HiScoreTable
|
class HiScoreTable {
|
||||||
{
|
public:
|
||||||
public:
|
// Constructor
|
||||||
// Constructor
|
HiScoreTable();
|
||||||
HiScoreTable();
|
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~HiScoreTable();
|
~HiScoreTable();
|
||||||
|
|
||||||
// Bucle principal
|
// Bucle principal
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr Uint16 COUNTER_END_ = 800; // Valor final para el contador
|
static constexpr Uint16 COUNTER_END_ = 800; // Valor final para el contador
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
SDL_Renderer *renderer_; // El renderizador de la ventana
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
SDL_Texture *backbuffer_; // Textura para usar como backbuffer
|
SDL_Texture *backbuffer_; // Textura para usar como backbuffer
|
||||||
|
|
||||||
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
|
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
|
||||||
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
|
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
|
||||||
std::unique_ptr<Sprite> header_; // Sprite con la cabecera del texto
|
std::unique_ptr<Sprite> header_; // Sprite con la cabecera del texto
|
||||||
std::vector<std::shared_ptr<PathSprite>> entry_names_; // Lista con los sprites de cada uno de los nombres de la tabla de records
|
std::vector<std::shared_ptr<PathSprite>> entry_names_; // Lista con los sprites de cada uno de los nombres de la tabla de records
|
||||||
std::vector<Path> paths_; // Vector con los recorridos precalculados
|
std::vector<Path> paths_; // Vector con los recorridos precalculados
|
||||||
|
|
||||||
// --- Variables ---
|
// --- Variables ---
|
||||||
Uint16 counter_ = 0; // Contador
|
Uint16 counter_ = 0; // Contador
|
||||||
Uint64 ticks_; // Contador de ticks para ajustar la velocidad del programa
|
Uint64 ticks_; // Contador de ticks para ajustar la velocidad del programa
|
||||||
SDL_FRect view_area_; // Parte de la textura que se muestra en pantalla
|
SDL_FRect view_area_; // Parte de la textura que se muestra en pantalla
|
||||||
FadeMode fade_mode_; // Modo de fade a utilizar
|
FadeMode fade_mode_; // Modo de fade a utilizar
|
||||||
Color background_fade_color_; // Color de atenuación del fondo
|
Color background_fade_color_; // Color de atenuación del fondo
|
||||||
std::vector<Color> entry_colors_; // Colores para destacar las entradas en la tabla
|
std::vector<Color> entry_colors_; // Colores para destacar las entradas en la tabla
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void update(); // Actualiza las variables
|
void update(); // Actualiza las variables
|
||||||
void render(); // Pinta en pantalla
|
void render(); // Pinta en pantalla
|
||||||
void checkEvents(); // Comprueba los eventos
|
void checkEvents(); // Comprueba los eventos
|
||||||
void checkInput(); // Comprueba las entradas
|
void checkInput(); // Comprueba las entradas
|
||||||
std::string format(int number); // Convierte un entero a un string con separadores de miles
|
std::string format(int number); // Convierte un entero a un string con separadores de miles
|
||||||
void fillTexture(); // Dibuja los sprites en la textura
|
void fillTexture(); // Dibuja los sprites en la textura
|
||||||
void updateFade(); // Gestiona el fade
|
void updateFade(); // Gestiona el fade
|
||||||
void createSprites(); // Crea los sprites con los textos
|
void createSprites(); // Crea los sprites con los textos
|
||||||
void updateSprites(); // Actualiza las posiciones de los sprites de texto
|
void updateSprites(); // Actualiza las posiciones de los sprites de texto
|
||||||
void initFade(); // Inicializa el fade
|
void initFade(); // Inicializa el fade
|
||||||
void initBackground(); // Inicializa el fondo
|
void initBackground(); // Inicializa el fondo
|
||||||
Color getEntryColor(int counter_); // Obtiene un color del vector de colores de entradas
|
Color getEntryColor(int counter_); // Obtiene un color del vector de colores de entradas
|
||||||
void iniEntryColors(); // Inicializa los colores de las entradas
|
void iniEntryColors(); // Inicializa los colores de las entradas
|
||||||
void glowEntryNames(); // Hace brillar los nombres de la tabla de records
|
void glowEntryNames(); // Hace brillar los nombres de la tabla de records
|
||||||
void updateCounter(); // Gestiona el contador
|
void updateCounter(); // Gestiona el contador
|
||||||
};
|
};
|
||||||
+255
-286
@@ -1,382 +1,351 @@
|
|||||||
#include "instructions.h"
|
#include "instructions.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_GetTicks, SDL_SetRenderTarget, SDL_Re...
|
#include <SDL3/SDL.h> // Para SDL_GetTicks, SDL_SetRenderTarget, SDL_Re...
|
||||||
#include <algorithm> // Para max
|
|
||||||
#include <array> // Para array
|
|
||||||
#include <string> // Para basic_string, string
|
|
||||||
#include <utility> // Para move
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "audio.h" // Para Audio
|
#include <algorithm> // Para max
|
||||||
#include "fade.h" // Para Fade, FadeMode, FadeType
|
#include <array> // Para array
|
||||||
#include "global_events.h" // Para check
|
#include <string> // Para basic_string, string
|
||||||
#include "global_inputs.h" // Para check
|
#include <utility> // Para move
|
||||||
#include "input.h" // Para Input
|
#include <vector> // Para vector
|
||||||
#include "lang.h" // Para getText
|
|
||||||
#include "param.h" // Para Param, param, ParamGame, ParamFade, Param...
|
#include "audio.h" // Para Audio
|
||||||
#include "resource.h" // Para Resource
|
#include "fade.h" // Para Fade, FadeMode, FadeType
|
||||||
#include "screen.h" // Para Screen
|
#include "global_events.h" // Para check
|
||||||
#include "section.h" // Para Name, name, Options, options
|
#include "global_inputs.h" // Para check
|
||||||
#include "sprite.h" // Para Sprite
|
#include "input.h" // Para Input
|
||||||
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR, TEXT_SHADOW
|
#include "lang.h" // Para getText
|
||||||
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
|
#include "param.h" // Para Param, param, ParamGame, ParamFade, Param...
|
||||||
#include "utils.h" // Para Color, SHADOW_TEXT_COLOR, Zone, NO_TEXT_C...
|
#include "resource.h" // Para Resource
|
||||||
|
#include "screen.h" // Para Screen
|
||||||
|
#include "section.h" // Para Name, name, Options, options
|
||||||
|
#include "sprite.h" // Para Sprite
|
||||||
|
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR, TEXT_SHADOW
|
||||||
|
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
|
||||||
|
#include "utils.h" // Para Color, SHADOW_TEXT_COLOR, Zone, NO_TEXT_C...
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Instructions::Instructions()
|
Instructions::Instructions()
|
||||||
: renderer_(Screen::get()->getRenderer()),
|
: renderer_(Screen::get()->getRenderer()),
|
||||||
texture_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
texture_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
||||||
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
|
||||||
text_(Resource::get()->getText("smb2")),
|
text_(Resource::get()->getText("smb2")),
|
||||||
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::STATIC)),
|
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::STATIC)),
|
||||||
fade_(std::make_unique<Fade>())
|
fade_(std::make_unique<Fade>()) {
|
||||||
{
|
// Configura las texturas
|
||||||
// Configura las texturas
|
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
|
||||||
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
|
SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);
|
||||||
SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);
|
|
||||||
|
|
||||||
// Inicializa variables
|
// Inicializa variables
|
||||||
Section::name = Section::Name::INSTRUCTIONS;
|
Section::name = Section::Name::INSTRUCTIONS;
|
||||||
view_ = param.game.game_area.rect;
|
view_ = param.game.game_area.rect;
|
||||||
|
|
||||||
// Inicializa objetos
|
// Inicializa objetos
|
||||||
tiled_bg_->setColor(param.title.bg_color);
|
tiled_bg_->setColor(param.title.bg_color);
|
||||||
fade_->setColor(param.fade.color);
|
fade_->setColor(param.fade.color);
|
||||||
fade_->setType(FadeType::FULLSCREEN);
|
fade_->setType(FadeType::FULLSCREEN);
|
||||||
fade_->setPostDuration(param.fade.post_duration);
|
fade_->setPostDuration(param.fade.post_duration);
|
||||||
fade_->setMode(FadeMode::IN);
|
fade_->setMode(FadeMode::IN);
|
||||||
fade_->activate();
|
fade_->activate();
|
||||||
|
|
||||||
// Inicializa las líneas con un retraso progresivo de 50 ms
|
// Inicializa las líneas con un retraso progresivo de 50 ms
|
||||||
lines_ = initializeLines(256);
|
lines_ = initializeLines(256);
|
||||||
|
|
||||||
// Rellena la textura de texto
|
// Rellena la textura de texto
|
||||||
fillTexture();
|
fillTexture();
|
||||||
|
|
||||||
// Inicializa los sprites de los items
|
// Inicializa los sprites de los items
|
||||||
iniSprites();
|
iniSprites();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
Instructions::~Instructions()
|
Instructions::~Instructions() {
|
||||||
{
|
item_textures_.clear();
|
||||||
item_textures_.clear();
|
sprites_.clear();
|
||||||
sprites_.clear();
|
|
||||||
|
|
||||||
SDL_DestroyTexture(backbuffer_);
|
SDL_DestroyTexture(backbuffer_);
|
||||||
SDL_DestroyTexture(texture_);
|
SDL_DestroyTexture(texture_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa los sprites de los items
|
// Inicializa los sprites de los items
|
||||||
void Instructions::iniSprites()
|
void Instructions::iniSprites() {
|
||||||
{
|
// Inicializa las texturas
|
||||||
// Inicializa las texturas
|
item_textures_.emplace_back(Resource::get()->getTexture("item_points1_disk.png"));
|
||||||
item_textures_.emplace_back(Resource::get()->getTexture("item_points1_disk.png"));
|
item_textures_.emplace_back(Resource::get()->getTexture("item_points2_gavina.png"));
|
||||||
item_textures_.emplace_back(Resource::get()->getTexture("item_points2_gavina.png"));
|
item_textures_.emplace_back(Resource::get()->getTexture("item_points3_pacmar.png"));
|
||||||
item_textures_.emplace_back(Resource::get()->getTexture("item_points3_pacmar.png"));
|
item_textures_.emplace_back(Resource::get()->getTexture("item_clock.png"));
|
||||||
item_textures_.emplace_back(Resource::get()->getTexture("item_clock.png"));
|
item_textures_.emplace_back(Resource::get()->getTexture("item_coffee.png"));
|
||||||
item_textures_.emplace_back(Resource::get()->getTexture("item_coffee.png"));
|
|
||||||
|
|
||||||
// Inicializa los sprites
|
// Inicializa los sprites
|
||||||
for (int i = 0; i < (int)item_textures_.size(); ++i)
|
for (int i = 0; i < (int)item_textures_.size(); ++i) {
|
||||||
{
|
auto sprite = std::make_unique<Sprite>(item_textures_[i], 0, 0, param.game.item_size, param.game.item_size);
|
||||||
auto sprite = std::make_unique<Sprite>(item_textures_[i], 0, 0, param.game.item_size, param.game.item_size);
|
sprite->setPosition((SDL_FPoint){sprite_pos_.x, sprite_pos_.y + ((param.game.item_size + item_space_) * i)});
|
||||||
sprite->setPosition((SDL_FPoint){sprite_pos_.x, sprite_pos_.y + ((param.game.item_size + item_space_) * i)});
|
sprites_.push_back(std::move(sprite));
|
||||||
sprites_.push_back(std::move(sprite));
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza los sprites
|
// Actualiza los sprites
|
||||||
void Instructions::updateSprites()
|
void Instructions::updateSprites() {
|
||||||
{
|
SDL_FRect src_rect = {0, 0, param.game.item_size, param.game.item_size};
|
||||||
SDL_FRect src_rect = {0, 0, param.game.item_size, param.game.item_size};
|
|
||||||
|
|
||||||
// Disquito
|
// Disquito
|
||||||
src_rect.y = param.game.item_size * (((counter_ + 12) / 36) % 2);
|
src_rect.y = param.game.item_size * (((counter_ + 12) / 36) % 2);
|
||||||
sprites_[0]->setSpriteClip(src_rect);
|
sprites_[0]->setSpriteClip(src_rect);
|
||||||
|
|
||||||
// Gavina
|
// Gavina
|
||||||
src_rect.y = param.game.item_size * (((counter_ + 9) / 36) % 2);
|
src_rect.y = param.game.item_size * (((counter_ + 9) / 36) % 2);
|
||||||
sprites_[1]->setSpriteClip(src_rect);
|
sprites_[1]->setSpriteClip(src_rect);
|
||||||
|
|
||||||
// Pacmar
|
// Pacmar
|
||||||
src_rect.y = param.game.item_size * (((counter_ + 6) / 36) % 2);
|
src_rect.y = param.game.item_size * (((counter_ + 6) / 36) % 2);
|
||||||
sprites_[2]->setSpriteClip(src_rect);
|
sprites_[2]->setSpriteClip(src_rect);
|
||||||
|
|
||||||
// Time Stopper
|
// Time Stopper
|
||||||
src_rect.y = param.game.item_size * (((counter_ + 3) / 36) % 2);
|
src_rect.y = param.game.item_size * (((counter_ + 3) / 36) % 2);
|
||||||
sprites_[3]->setSpriteClip(src_rect);
|
sprites_[3]->setSpriteClip(src_rect);
|
||||||
|
|
||||||
// Coffee
|
// Coffee
|
||||||
src_rect.y = param.game.item_size * (((counter_ + 0) / 36) % 2);
|
src_rect.y = param.game.item_size * (((counter_ + 0) / 36) % 2);
|
||||||
sprites_[4]->setSpriteClip(src_rect);
|
sprites_[4]->setSpriteClip(src_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rellena la textura de texto
|
// Rellena la textura de texto
|
||||||
void Instructions::fillTexture()
|
void Instructions::fillTexture() {
|
||||||
{
|
const int desp_x = param.game.item_size + 8;
|
||||||
const int desp_x = param.game.item_size + 8;
|
|
||||||
|
|
||||||
// Modifica el renderizador para pintar en la textura
|
// Modifica el renderizador para pintar en la textura
|
||||||
auto temp = SDL_GetRenderTarget(renderer_);
|
auto temp = SDL_GetRenderTarget(renderer_);
|
||||||
SDL_SetRenderTarget(renderer_, texture_);
|
SDL_SetRenderTarget(renderer_, texture_);
|
||||||
|
|
||||||
// Limpia la textura
|
// Limpia la textura
|
||||||
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
||||||
SDL_RenderClear(renderer_);
|
SDL_RenderClear(renderer_);
|
||||||
|
|
||||||
// Constantes
|
// Constantes
|
||||||
constexpr int num_lines = 4;
|
constexpr int num_lines = 4;
|
||||||
constexpr int num_item_lines = 4;
|
constexpr int num_item_lines = 4;
|
||||||
constexpr int num_post_headers = 2;
|
constexpr int num_post_headers = 2;
|
||||||
constexpr int num_pre_headers = 1;
|
constexpr int num_pre_headers = 1;
|
||||||
|
|
||||||
constexpr int space_post_header = 20;
|
constexpr int space_post_header = 20;
|
||||||
constexpr int space_pre_header = 28;
|
constexpr int space_pre_header = 28;
|
||||||
const int space_between_lines = text_->getCharacterSize() * 1.5f;
|
const int space_between_lines = text_->getCharacterSize() * 1.5f;
|
||||||
const int space_between_item_lines = param.game.item_size + item_space_;
|
const int space_between_item_lines = param.game.item_size + item_space_;
|
||||||
const int space_new_paragraph = space_between_lines * 0.5f;
|
const int space_new_paragraph = space_between_lines * 0.5f;
|
||||||
|
|
||||||
const int size = (num_lines * space_between_lines) + (num_item_lines * space_between_item_lines) + (num_post_headers * space_post_header) + (num_pre_headers * space_pre_header) + (space_new_paragraph);
|
const int size = (num_lines * space_between_lines) + (num_item_lines * space_between_item_lines) + (num_post_headers * space_post_header) + (num_pre_headers * space_pre_header) + (space_new_paragraph);
|
||||||
const int first_line = (param.game.height - size) / 2;
|
const int first_line = (param.game.height - size) / 2;
|
||||||
|
|
||||||
// Calcula cual es el texto más largo de las descripciones de los items
|
// Calcula cual es el texto más largo de las descripciones de los items
|
||||||
int lenght = 0;
|
int lenght = 0;
|
||||||
const std::array<std::string, 5> ITEM_DESCRIPTIONS = {
|
const std::array<std::string, 5> ITEM_DESCRIPTIONS = {
|
||||||
Lang::getText("[INSTRUCTIONS] 07"),
|
Lang::getText("[INSTRUCTIONS] 07"),
|
||||||
Lang::getText("[INSTRUCTIONS] 08"),
|
Lang::getText("[INSTRUCTIONS] 08"),
|
||||||
Lang::getText("[INSTRUCTIONS] 09"),
|
Lang::getText("[INSTRUCTIONS] 09"),
|
||||||
Lang::getText("[INSTRUCTIONS] 10"),
|
Lang::getText("[INSTRUCTIONS] 10"),
|
||||||
Lang::getText("[INSTRUCTIONS] 11")};
|
Lang::getText("[INSTRUCTIONS] 11")};
|
||||||
for (const auto &desc : ITEM_DESCRIPTIONS)
|
for (const auto &desc : ITEM_DESCRIPTIONS) {
|
||||||
{
|
const int l = text_->lenght(desc);
|
||||||
const int l = text_->lenght(desc);
|
lenght = l > lenght ? l : lenght;
|
||||||
lenght = l > lenght ? l : lenght;
|
}
|
||||||
}
|
const int ANCHOR_ITEM = (param.game.width - (lenght + desp_x)) / 2;
|
||||||
const int ANCHOR_ITEM = (param.game.width - (lenght + desp_x)) / 2;
|
|
||||||
|
|
||||||
constexpr Color ORANGE_COLOR = Color(0XFF, 0X7A, 0X00);
|
constexpr Color ORANGE_COLOR = Color(0XFF, 0X7A, 0X00);
|
||||||
|
|
||||||
// Escribe el texto de las instrucciones
|
// Escribe el texto de las instrucciones
|
||||||
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, first_line, Lang::getText("[INSTRUCTIONS] 01"), 1, ORANGE_COLOR, 1, SHADOW_TEXT_COLOR);
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, first_line, Lang::getText("[INSTRUCTIONS] 01"), 1, ORANGE_COLOR, 1, SHADOW_TEXT_COLOR);
|
||||||
|
|
||||||
const int anchor1 = first_line + space_post_header;
|
const int anchor1 = first_line + space_post_header;
|
||||||
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_between_lines * 0, Lang::getText("[INSTRUCTIONS] 02"), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_between_lines * 0, Lang::getText("[INSTRUCTIONS] 02"), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
||||||
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_between_lines * 1, Lang::getText("[INSTRUCTIONS] 03"), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_between_lines * 1, Lang::getText("[INSTRUCTIONS] 03"), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
||||||
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_new_paragraph + space_between_lines * 2, Lang::getText("[INSTRUCTIONS] 04"), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_new_paragraph + space_between_lines * 2, Lang::getText("[INSTRUCTIONS] 04"), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
||||||
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_new_paragraph + space_between_lines * 3, Lang::getText("[INSTRUCTIONS] 05"), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor1 + space_new_paragraph + space_between_lines * 3, Lang::getText("[INSTRUCTIONS] 05"), 1, NO_TEXT_COLOR, 1, SHADOW_TEXT_COLOR);
|
||||||
|
|
||||||
// Escribe el texto de los objetos y sus puntos
|
// Escribe el texto de los objetos y sus puntos
|
||||||
const int anchor2 = anchor1 + space_pre_header + space_new_paragraph + space_between_lines * 3;
|
const int anchor2 = anchor1 + space_pre_header + space_new_paragraph + space_between_lines * 3;
|
||||||
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor2, Lang::getText("[INSTRUCTIONS] 06"), 1, ORANGE_COLOR, 1, SHADOW_TEXT_COLOR);
|
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor2, Lang::getText("[INSTRUCTIONS] 06"), 1, ORANGE_COLOR, 1, SHADOW_TEXT_COLOR);
|
||||||
|
|
||||||
const int anchor3 = anchor2 + space_post_header;
|
const int anchor3 = anchor2 + space_post_header;
|
||||||
text_->writeShadowed(ANCHOR_ITEM + desp_x, anchor3 + space_between_item_lines * 0, Lang::getText("[INSTRUCTIONS] 07"), SHADOW_TEXT_COLOR);
|
text_->writeShadowed(ANCHOR_ITEM + desp_x, anchor3 + space_between_item_lines * 0, Lang::getText("[INSTRUCTIONS] 07"), SHADOW_TEXT_COLOR);
|
||||||
text_->writeShadowed(ANCHOR_ITEM + desp_x, anchor3 + space_between_item_lines * 1, Lang::getText("[INSTRUCTIONS] 08"), SHADOW_TEXT_COLOR);
|
text_->writeShadowed(ANCHOR_ITEM + desp_x, anchor3 + space_between_item_lines * 1, Lang::getText("[INSTRUCTIONS] 08"), SHADOW_TEXT_COLOR);
|
||||||
text_->writeShadowed(ANCHOR_ITEM + desp_x, anchor3 + space_between_item_lines * 2, Lang::getText("[INSTRUCTIONS] 09"), SHADOW_TEXT_COLOR);
|
text_->writeShadowed(ANCHOR_ITEM + desp_x, anchor3 + space_between_item_lines * 2, Lang::getText("[INSTRUCTIONS] 09"), SHADOW_TEXT_COLOR);
|
||||||
text_->writeShadowed(ANCHOR_ITEM + desp_x, anchor3 + space_between_item_lines * 3, Lang::getText("[INSTRUCTIONS] 10"), SHADOW_TEXT_COLOR);
|
text_->writeShadowed(ANCHOR_ITEM + desp_x, anchor3 + space_between_item_lines * 3, Lang::getText("[INSTRUCTIONS] 10"), SHADOW_TEXT_COLOR);
|
||||||
text_->writeShadowed(ANCHOR_ITEM + desp_x, anchor3 + space_between_item_lines * 4, Lang::getText("[INSTRUCTIONS] 11"), SHADOW_TEXT_COLOR);
|
text_->writeShadowed(ANCHOR_ITEM + desp_x, anchor3 + space_between_item_lines * 4, Lang::getText("[INSTRUCTIONS] 11"), SHADOW_TEXT_COLOR);
|
||||||
|
|
||||||
// Deja el renderizador como estaba
|
// Deja el renderizador como estaba
|
||||||
SDL_SetRenderTarget(renderer_, temp);
|
SDL_SetRenderTarget(renderer_, temp);
|
||||||
|
|
||||||
// Da valor a la variable
|
// Da valor a la variable
|
||||||
sprite_pos_.x = ANCHOR_ITEM;
|
sprite_pos_.x = ANCHOR_ITEM;
|
||||||
sprite_pos_.y = anchor3 - ((param.game.item_size - text_->getCharacterSize()) / 2);
|
sprite_pos_.y = anchor3 - ((param.game.item_size - text_->getCharacterSize()) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rellena el backbuffer
|
// Rellena el backbuffer
|
||||||
void Instructions::fillBackbuffer()
|
void Instructions::fillBackbuffer() {
|
||||||
{
|
// Modifica el renderizador para pintar en la textura
|
||||||
// Modifica el renderizador para pintar en la textura
|
auto temp = SDL_GetRenderTarget(renderer_);
|
||||||
auto temp = SDL_GetRenderTarget(renderer_);
|
SDL_SetRenderTarget(renderer_, backbuffer_);
|
||||||
SDL_SetRenderTarget(renderer_, backbuffer_);
|
|
||||||
|
|
||||||
// Limpia la textura
|
// Limpia la textura
|
||||||
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
||||||
SDL_RenderClear(renderer_);
|
SDL_RenderClear(renderer_);
|
||||||
|
|
||||||
// Coloca el texto de fondo
|
// Coloca el texto de fondo
|
||||||
SDL_RenderTexture(renderer_, texture_, nullptr, nullptr);
|
SDL_RenderTexture(renderer_, texture_, nullptr, nullptr);
|
||||||
|
|
||||||
// Dibuja los sprites
|
// Dibuja los sprites
|
||||||
for (auto &sprite : sprites_)
|
for (auto &sprite : sprites_) {
|
||||||
{
|
sprite->render();
|
||||||
sprite->render();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Deja el renderizador como estaba
|
// Deja el renderizador como estaba
|
||||||
SDL_SetRenderTarget(renderer_, temp);
|
SDL_SetRenderTarget(renderer_, temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza las variables
|
// Actualiza las variables
|
||||||
void Instructions::update()
|
void Instructions::update() {
|
||||||
{
|
if (SDL_GetTicks() - ticks_ > param.game.speed) {
|
||||||
if (SDL_GetTicks() - ticks_ > param.game.speed)
|
// Actualiza el contador de ticks
|
||||||
{
|
ticks_ = SDL_GetTicks();
|
||||||
// Actualiza el contador de ticks
|
|
||||||
ticks_ = SDL_GetTicks();
|
|
||||||
|
|
||||||
// Actualiza el objeto screen
|
// Actualiza el objeto screen
|
||||||
Screen::get()->update();
|
Screen::get()->update();
|
||||||
|
|
||||||
// Incrementa el contador
|
// Incrementa el contador
|
||||||
counter_++;
|
counter_++;
|
||||||
|
|
||||||
// Actualiza los sprites
|
// Actualiza los sprites
|
||||||
updateSprites();
|
updateSprites();
|
||||||
|
|
||||||
// Gestiona la textura con los graficos
|
// Gestiona la textura con los graficos
|
||||||
updateBackbuffer();
|
updateBackbuffer();
|
||||||
|
|
||||||
// Actualiza el mosaico de fondo
|
// Actualiza el mosaico de fondo
|
||||||
tiled_bg_->update();
|
tiled_bg_->update();
|
||||||
|
|
||||||
// Actualiza el objeto "fade"
|
// Actualiza el objeto "fade"
|
||||||
fade_->update();
|
fade_->update();
|
||||||
|
|
||||||
// Rellena el backbuffer
|
// Rellena el backbuffer
|
||||||
fillBackbuffer();
|
fillBackbuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pinta en pantalla
|
// Pinta en pantalla
|
||||||
void Instructions::render()
|
void Instructions::render() {
|
||||||
{
|
// Prepara para empezar a dibujar en la textura de juego
|
||||||
// Prepara para empezar a dibujar en la textura de juego
|
Screen::get()->start();
|
||||||
Screen::get()->start();
|
|
||||||
|
|
||||||
// Limpia la pantalla
|
// Limpia la pantalla
|
||||||
Screen::get()->clean();
|
Screen::get()->clean();
|
||||||
|
|
||||||
// Dibuja el mosacico de fondo
|
// Dibuja el mosacico de fondo
|
||||||
tiled_bg_->render();
|
tiled_bg_->render();
|
||||||
|
|
||||||
// Copia la textura y el backbuffer al renderizador
|
// Copia la textura y el backbuffer al renderizador
|
||||||
if (view_.y == 0)
|
if (view_.y == 0)
|
||||||
renderLines(renderer_, backbuffer_, lines_);
|
renderLines(renderer_, backbuffer_, lines_);
|
||||||
else
|
else
|
||||||
SDL_RenderTexture(renderer_, backbuffer_, nullptr, &view_);
|
SDL_RenderTexture(renderer_, backbuffer_, nullptr, &view_);
|
||||||
|
|
||||||
fade_->render();
|
fade_->render();
|
||||||
|
|
||||||
// Vuelca el contenido del renderizador en pantalla
|
// Vuelca el contenido del renderizador en pantalla
|
||||||
Screen::get()->render();
|
Screen::get()->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba los eventos
|
// Comprueba los eventos
|
||||||
void Instructions::checkEvents()
|
void Instructions::checkEvents() {
|
||||||
{
|
SDL_Event event;
|
||||||
SDL_Event event;
|
while (SDL_PollEvent(&event)) {
|
||||||
while (SDL_PollEvent(&event))
|
GlobalEvents::check(event);
|
||||||
{
|
}
|
||||||
GlobalEvents::check(event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba las entradas
|
// Comprueba las entradas
|
||||||
void Instructions::checkInput()
|
void Instructions::checkInput() {
|
||||||
{
|
Input::get()->update();
|
||||||
Input::get()->update();
|
GlobalInputs::check();
|
||||||
GlobalInputs::check();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bucle para la pantalla de instrucciones
|
// Bucle para la pantalla de instrucciones
|
||||||
void Instructions::run()
|
void Instructions::run() {
|
||||||
{
|
Audio::get()->playMusic("title.ogg");
|
||||||
Audio::get()->playMusic("title.ogg");
|
while (Section::name == Section::Name::INSTRUCTIONS) {
|
||||||
while (Section::name == Section::Name::INSTRUCTIONS)
|
checkInput();
|
||||||
{
|
update();
|
||||||
checkInput();
|
checkEvents(); // Tiene que ir antes del render
|
||||||
update();
|
render();
|
||||||
checkEvents(); // Tiene que ir antes del render
|
}
|
||||||
render();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Método para inicializar las líneas
|
// Método para inicializar las líneas
|
||||||
std::vector<Line> Instructions::initializeLines(int height)
|
std::vector<Line> Instructions::initializeLines(int height) {
|
||||||
{
|
std::vector<Line> lines;
|
||||||
std::vector<Line> lines;
|
for (int y = 0; y < height; y++) {
|
||||||
for (int y = 0; y < height; y++)
|
int direction = (y % 2 == 0) ? -1 : 1; // Pares a la izquierda, impares a la derecha
|
||||||
{
|
lines.emplace_back(y, 0.0f, direction);
|
||||||
int direction = (y % 2 == 0) ? -1 : 1; // Pares a la izquierda, impares a la derecha
|
}
|
||||||
lines.emplace_back(y, 0.0f, direction);
|
return lines;
|
||||||
}
|
|
||||||
return lines;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Método para mover las líneas con suavizado
|
// Método para mover las líneas con suavizado
|
||||||
bool Instructions::moveLines(std::vector<Line> &lines, int width, float duration, Uint32 startDelay)
|
bool Instructions::moveLines(std::vector<Line> &lines, int width, float duration, Uint32 startDelay) {
|
||||||
{
|
Uint32 current_time = SDL_GetTicks();
|
||||||
Uint32 current_time = SDL_GetTicks();
|
bool all_lines_off_screen = true;
|
||||||
bool all_lines_off_screen = true;
|
|
||||||
|
|
||||||
for (auto &line : lines)
|
for (auto &line : lines) {
|
||||||
{
|
// Establecer startTime en el primer cuadro de animación
|
||||||
// Establecer startTime en el primer cuadro de animación
|
if (line.startTime == 0) {
|
||||||
if (line.startTime == 0)
|
line.startTime = current_time + line.y * startDelay;
|
||||||
{
|
}
|
||||||
line.startTime = current_time + line.y * startDelay;
|
|
||||||
}
|
|
||||||
|
|
||||||
float elapsed_time = (current_time - line.startTime) / 1000.0f; // Convertir a segundos
|
float elapsed_time = (current_time - line.startTime) / 1000.0f; // Convertir a segundos
|
||||||
if (elapsed_time < 0)
|
if (elapsed_time < 0) {
|
||||||
{
|
all_lines_off_screen = false; // Si aún no se debe mover esta línea, no están todas fuera de pantalla
|
||||||
all_lines_off_screen = false; // Si aún no se debe mover esta línea, no están todas fuera de pantalla
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
if (elapsed_time >= duration) {
|
||||||
if (elapsed_time >= duration)
|
continue; // Si la línea ha salido de los límites, no la muevas más
|
||||||
{
|
}
|
||||||
continue; // Si la línea ha salido de los límites, no la muevas más
|
|
||||||
}
|
|
||||||
|
|
||||||
float t = elapsed_time / duration;
|
float t = elapsed_time / duration;
|
||||||
float smooth_factor = easeInOutQuint(t);
|
float smooth_factor = easeInOutQuint(t);
|
||||||
line.x = line.direction * smooth_factor * width;
|
line.x = line.direction * smooth_factor * width;
|
||||||
all_lines_off_screen = false; // Si alguna línea aún se está moviendo, no están todas fuera de pantalla
|
all_lines_off_screen = false; // Si alguna línea aún se está moviendo, no están todas fuera de pantalla
|
||||||
}
|
}
|
||||||
|
|
||||||
return all_lines_off_screen;
|
return all_lines_off_screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Método para renderizar las líneas
|
// Método para renderizar las líneas
|
||||||
void Instructions::renderLines(SDL_Renderer *renderer, SDL_Texture *texture, const std::vector<Line> &lines)
|
void Instructions::renderLines(SDL_Renderer *renderer, SDL_Texture *texture, const std::vector<Line> &lines) {
|
||||||
{
|
for (const auto &LINE : lines) {
|
||||||
for (const auto &LINE : lines)
|
SDL_FRect srcRect = {0, static_cast<float>(LINE.y), 320, 1};
|
||||||
{
|
SDL_FRect dstRect = {static_cast<float>(LINE.x), static_cast<float>(LINE.y), 320, 1};
|
||||||
SDL_FRect srcRect = {0, static_cast<float>(LINE.y), 320, 1};
|
SDL_RenderTexture(renderer, texture, &srcRect, &dstRect);
|
||||||
SDL_FRect dstRect = {static_cast<float>(LINE.x), static_cast<float>(LINE.y), 320, 1};
|
}
|
||||||
SDL_RenderTexture(renderer, texture, &srcRect, &dstRect);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gestiona la textura con los graficos
|
// Gestiona la textura con los graficos
|
||||||
void Instructions::updateBackbuffer()
|
void Instructions::updateBackbuffer() {
|
||||||
{
|
// Establece la ventana del backbuffer
|
||||||
// Establece la ventana del backbuffer
|
view_.y = std::max(0.0f, param.game.height - counter_ + 100);
|
||||||
view_.y = std::max(0.0f, param.game.height - counter_ + 100);
|
|
||||||
|
|
||||||
// Verifica si view_.y == 0 y gestiona el temporizador
|
// Verifica si view_.y == 0 y gestiona el temporizador
|
||||||
if (view_.y == 0)
|
if (view_.y == 0) {
|
||||||
{
|
if (!start_delay_triggered_) {
|
||||||
if (!start_delay_triggered_)
|
// Activa el temporizador si no ha sido activado
|
||||||
{
|
start_delay_triggered_ = true;
|
||||||
// Activa el temporizador si no ha sido activado
|
start_delay_time_ = SDL_GetTicks();
|
||||||
start_delay_triggered_ = true;
|
} else if (SDL_GetTicks() - start_delay_time_ >= 4000) {
|
||||||
start_delay_time_ = SDL_GetTicks();
|
// Han pasado tres segundos, mover líneas
|
||||||
}
|
all_lines_off_screen_ = moveLines(lines_, 320, 1.0f, 5);
|
||||||
else if (SDL_GetTicks() - start_delay_time_ >= 4000)
|
}
|
||||||
{
|
}
|
||||||
// Han pasado tres segundos, mover líneas
|
|
||||||
all_lines_off_screen_ = moveLines(lines_, 320, 1.0f, 5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si el contador ha llegado al final
|
// Comprueba si el contador ha llegado al final
|
||||||
if (all_lines_off_screen_)
|
if (all_lines_off_screen_) {
|
||||||
{
|
Section::name = Section::Name::TITLE;
|
||||||
Section::name = Section::Name::TITLE;
|
Section::options = Section::Options::TITLE_1;
|
||||||
Section::options = Section::Options::TITLE_1;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_Texture, Uint32, SDL_Renderer, SDL_FPoint, SDL_FRect, Uint64
|
#include <SDL3/SDL.h> // Para SDL_Texture, Uint32, SDL_Renderer, SDL_FPoint, SDL_FRect, Uint64
|
||||||
#include <memory> // Para unique_ptr, shared_ptr
|
|
||||||
#include <vector> // Para vector
|
#include <memory> // Para unique_ptr, shared_ptr
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
class Fade;
|
class Fade;
|
||||||
class Sprite;
|
class Sprite;
|
||||||
@@ -11,78 +12,76 @@ class Texture;
|
|||||||
class TiledBG;
|
class TiledBG;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Esta clase gestiona un estado del programa. Se encarga de poner en pantalla
|
Esta clase gestiona un estado del programa. Se encarga de poner en pantalla
|
||||||
un texto explicativo para entender cómo se juega.
|
un texto explicativo para entender cómo se juega.
|
||||||
|
|
||||||
Además muestra algunos items y explica para qué sirven.
|
Además muestra algunos items y explica para qué sirven.
|
||||||
|
|
||||||
Utiliza dos texturas de apoyo, una con el texto ya escrito y otra donde se combina
|
Utiliza dos texturas de apoyo, una con el texto ya escrito y otra donde se combina
|
||||||
tanto el texto de la primera textura como los sprites de los items.
|
tanto el texto de la primera textura como los sprites de los items.
|
||||||
|
|
||||||
Finalmente, una ventana recorre la textura para dar el efecto de que todo se desplaza
|
Finalmente, una ventana recorre la textura para dar el efecto de que todo se desplaza
|
||||||
por la pantalla sobre el mosaico de fondo (gestionado por el correspondiente objeto).
|
por la pantalla sobre el mosaico de fondo (gestionado por el correspondiente objeto).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Estructura para almacenar información de línea animada
|
// Estructura para almacenar información de línea animada
|
||||||
struct Line
|
struct Line {
|
||||||
{
|
int y; // Coordenada Y de la línea
|
||||||
int y; // Coordenada Y de la línea
|
float x; // Coordenada X inicial (usamos float para mayor precisión en el suavizado)
|
||||||
float x; // Coordenada X inicial (usamos float para mayor precisión en el suavizado)
|
int direction; // Dirección de movimiento: -1 para izquierda, 1 para derecha
|
||||||
int direction; // Dirección de movimiento: -1 para izquierda, 1 para derecha
|
Uint32 startTime; // Tiempo de inicio del movimiento
|
||||||
Uint32 startTime; // Tiempo de inicio del movimiento
|
|
||||||
|
|
||||||
// Constructor de Line
|
// Constructor de Line
|
||||||
Line(int y, float x, int direction)
|
Line(int y, float x, int direction)
|
||||||
: y(y), x(x), direction(direction), startTime(0) {}
|
: y(y), x(x), direction(direction), startTime(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Clase Instructions
|
// Clase Instructions
|
||||||
class Instructions
|
class Instructions {
|
||||||
{
|
public:
|
||||||
public:
|
// Constructor
|
||||||
// Constructor
|
Instructions();
|
||||||
Instructions();
|
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~Instructions();
|
~Instructions();
|
||||||
|
|
||||||
// Bucle principal
|
// Bucle principal
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
SDL_Renderer *renderer_; // El renderizador de la ventana
|
SDL_Renderer *renderer_; // El renderizador de la ventana
|
||||||
SDL_Texture *texture_; // Textura fija con el texto
|
SDL_Texture *texture_; // Textura fija con el texto
|
||||||
SDL_Texture *backbuffer_; // Textura para usar como backbuffer
|
SDL_Texture *backbuffer_; // Textura para usar como backbuffer
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
|
std::vector<std::shared_ptr<Texture>> item_textures_; // Vector con las texturas de los items
|
||||||
std::vector<std::unique_ptr<Sprite>> sprites_; // Vector con los sprites de los items
|
std::vector<std::unique_ptr<Sprite>> sprites_; // Vector con los sprites de los items
|
||||||
std::shared_ptr<Text> text_; // Objeto para escribir texto
|
std::shared_ptr<Text> text_; // Objeto para escribir texto
|
||||||
std::unique_ptr<TiledBG> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo
|
std::unique_ptr<TiledBG> tiled_bg_; // Objeto para dibujar el mosaico animado de fondo
|
||||||
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
|
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
|
||||||
|
|
||||||
// --- Variables ---
|
// --- Variables ---
|
||||||
int counter_ = 0; // Contador para manejar el progreso en la pantalla de instrucciones
|
int counter_ = 0; // Contador para manejar el progreso en la pantalla de instrucciones
|
||||||
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
||||||
SDL_FRect view_; // Vista del backbuffer que se va a mostrar por pantalla
|
SDL_FRect view_; // Vista del backbuffer que se va a mostrar por pantalla
|
||||||
SDL_FPoint sprite_pos_ = {0, 0}; // Posición del primer sprite en la lista
|
SDL_FPoint sprite_pos_ = {0, 0}; // Posición del primer sprite en la lista
|
||||||
float item_space_ = 2.0; // Espacio entre los items en pantalla
|
float item_space_ = 2.0; // Espacio entre los items en pantalla
|
||||||
std::vector<Line> lines_; // Vector que contiene las líneas animadas en la pantalla
|
std::vector<Line> lines_; // Vector que contiene las líneas animadas en la pantalla
|
||||||
bool all_lines_off_screen_ = false; // Indica si todas las líneas han salido de la pantalla
|
bool all_lines_off_screen_ = false; // Indica si todas las líneas han salido de la pantalla
|
||||||
Uint32 start_delay_time_ = 0; // Tiempo de inicio del retraso para mover las líneas
|
Uint32 start_delay_time_ = 0; // Tiempo de inicio del retraso para mover las líneas
|
||||||
bool start_delay_triggered_ = false; // Bandera para determinar si el retraso ha comenzado
|
bool start_delay_triggered_ = false; // Bandera para determinar si el retraso ha comenzado
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void update(); // Actualiza las variables
|
void update(); // Actualiza las variables
|
||||||
void render(); // Pinta en pantalla
|
void render(); // Pinta en pantalla
|
||||||
void checkEvents(); // Comprueba los eventos
|
void checkEvents(); // Comprueba los eventos
|
||||||
void checkInput(); // Comprueba las entradas
|
void checkInput(); // Comprueba las entradas
|
||||||
void fillTexture(); // Rellena la textura de texto
|
void fillTexture(); // Rellena la textura de texto
|
||||||
void fillBackbuffer(); // Rellena el backbuffer
|
void fillBackbuffer(); // Rellena el backbuffer
|
||||||
void iniSprites(); // Inicializa los sprites de los items
|
void iniSprites(); // Inicializa los sprites de los items
|
||||||
void updateSprites(); // Actualiza los sprites
|
void updateSprites(); // Actualiza los sprites
|
||||||
std::vector<Line> initializeLines(int height); // Inicializa las líneas animadas
|
std::vector<Line> initializeLines(int height); // Inicializa las líneas animadas
|
||||||
bool moveLines(std::vector<Line> &lines, int width, float duration, Uint32 startDelay); // Mueve las líneas
|
bool moveLines(std::vector<Line> &lines, int width, float duration, Uint32 startDelay); // Mueve las líneas
|
||||||
void renderLines(SDL_Renderer *renderer, SDL_Texture *texture, const std::vector<Line> &lines); // Renderiza las líneas
|
void renderLines(SDL_Renderer *renderer, SDL_Texture *texture, const std::vector<Line> &lines); // Renderiza las líneas
|
||||||
void updateBackbuffer(); // Gestiona la textura con los gráficos
|
void updateBackbuffer(); // Gestiona la textura con los gráficos
|
||||||
};
|
};
|
||||||
+446
-505
File diff suppressed because it is too large.
Load diff
+56
-58
@@ -1,74 +1,72 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para Uint32, Uint64
|
#include <SDL3/SDL.h> // Para Uint32, Uint64
|
||||||
#include <memory> // Para unique_ptr
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "param.h" // Para Param, ParamIntro, param
|
#include <memory> // Para unique_ptr
|
||||||
#include "path_sprite.h" // Para PathSprite
|
#include <vector> // Para vector
|
||||||
#include "tiled_bg.h" // Para TiledBG
|
|
||||||
#include "utils.h" // Para Color
|
#include "param.h" // Para Param, ParamIntro, param
|
||||||
#include "writer.h" // Para Writer
|
#include "path_sprite.h" // Para PathSprite
|
||||||
|
#include "tiled_bg.h" // Para TiledBG
|
||||||
|
#include "utils.h" // Para Color
|
||||||
|
#include "writer.h" // Para Writer
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Esta clase gestiona un estado del programa. Se encarga de mostrar la secuencia
|
Esta clase gestiona un estado del programa. Se encarga de mostrar la secuencia
|
||||||
de introducción.
|
de introducción.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Clase Intro
|
// Clase Intro
|
||||||
class Intro
|
class Intro {
|
||||||
{
|
public:
|
||||||
public:
|
// Constructor
|
||||||
// Constructor
|
Intro();
|
||||||
Intro();
|
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~Intro() = default;
|
~Intro() = default;
|
||||||
|
|
||||||
// Bucle principal
|
// Bucle principal
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Estados internos ---
|
// --- Estados internos ---
|
||||||
enum class IntroState
|
enum class IntroState {
|
||||||
{
|
SCENES,
|
||||||
SCENES,
|
POST,
|
||||||
POST,
|
};
|
||||||
};
|
|
||||||
|
|
||||||
enum class IntroPostState
|
enum class IntroPostState {
|
||||||
{
|
STOP_BG,
|
||||||
STOP_BG,
|
END,
|
||||||
END,
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// --- Objetos ---
|
// --- Objetos ---
|
||||||
std::vector<std::unique_ptr<PathSprite>> card_sprites_; // Vector con los sprites inteligentes para los dibujos de la intro
|
std::vector<std::unique_ptr<PathSprite>> card_sprites_; // Vector con los sprites inteligentes para los dibujos de la intro
|
||||||
std::vector<std::unique_ptr<PathSprite>> shadow_sprites_; // Vector con los sprites inteligentes para las sombras
|
std::vector<std::unique_ptr<PathSprite>> shadow_sprites_; // Vector con los sprites inteligentes para las sombras
|
||||||
std::vector<std::unique_ptr<Writer>> texts_; // Textos de la intro
|
std::vector<std::unique_ptr<Writer>> texts_; // Textos de la intro
|
||||||
std::unique_ptr<TiledBG> tiled_bg_; // Fondo en mosaico
|
std::unique_ptr<TiledBG> tiled_bg_; // Fondo en mosaico
|
||||||
// std::unique_ptr<Sprite> shadow_square_for_text_; // Sprite
|
// std::unique_ptr<Sprite> shadow_square_for_text_; // Sprite
|
||||||
|
|
||||||
// --- Variables ---
|
// --- Variables ---
|
||||||
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
||||||
int scene_ = 0; // Indica qué escena está activa
|
int scene_ = 0; // Indica qué escena está activa
|
||||||
IntroState state_ = IntroState::SCENES; // Estado principal de la intro
|
IntroState state_ = IntroState::SCENES; // Estado principal de la intro
|
||||||
IntroPostState post_state_ = IntroPostState::STOP_BG; // Estado POST
|
IntroPostState post_state_ = IntroPostState::STOP_BG; // Estado POST
|
||||||
Uint32 state_start_time_; // Tiempo de inicio del estado actual
|
Uint32 state_start_time_; // Tiempo de inicio del estado actual
|
||||||
Color bg_color_ = param.intro.bg_color; // Color de fondo
|
Color bg_color_ = param.intro.bg_color; // Color de fondo
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void update(); // Actualiza las variables del objeto
|
void update(); // Actualiza las variables del objeto
|
||||||
void render(); // Dibuja el objeto en pantalla
|
void render(); // Dibuja el objeto en pantalla
|
||||||
void checkEvents(); // Comprueba los eventos
|
void checkEvents(); // Comprueba los eventos
|
||||||
void checkInput(); // Comprueba las entradas
|
void checkInput(); // Comprueba las entradas
|
||||||
void updateScenes(); // Actualiza las escenas de la intro
|
void updateScenes(); // Actualiza las escenas de la intro
|
||||||
void initSprites(); // Inicializa las imágenes
|
void initSprites(); // Inicializa las imágenes
|
||||||
void initTexts(); // Inicializa los textos
|
void initTexts(); // Inicializa los textos
|
||||||
void updateSprites(); // Actualiza los sprites
|
void updateSprites(); // Actualiza los sprites
|
||||||
void updateTexts(); // Actualiza los textos
|
void updateTexts(); // Actualiza los textos
|
||||||
void renderSprites(); // Dibuja los sprites
|
void renderSprites(); // Dibuja los sprites
|
||||||
void renderTexts(); // Dibuja los textos
|
void renderTexts(); // Dibuja los textos
|
||||||
void renderTextRect(); // Dibuja el rectangulo de fondo del texto;
|
void renderTextRect(); // Dibuja el rectangulo de fondo del texto;
|
||||||
void updatePostState(); // Actualiza el estado POST
|
void updatePostState(); // Actualiza el estado POST
|
||||||
};
|
};
|
||||||
+134
-164
@@ -1,211 +1,181 @@
|
|||||||
#include "logo.h"
|
#include "logo.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_GetTicks, SDL_PollEvent, SDL_Event
|
#include <SDL3/SDL.h> // Para SDL_GetTicks, SDL_PollEvent, SDL_Event
|
||||||
#include <string> // Para basic_string
|
|
||||||
#include <utility> // Para move
|
|
||||||
|
|
||||||
#include "audio.h" // Para Audio
|
#include <string> // Para basic_string
|
||||||
#include "global_events.h" // Para check
|
#include <utility> // Para move
|
||||||
#include "global_inputs.h" // Para check
|
|
||||||
#include "input.h" // Para Input
|
#include "audio.h" // Para Audio
|
||||||
#include "param.h" // Para Param, ParamGame, param
|
#include "global_events.h" // Para check
|
||||||
#include "resource.h" // Para Resource
|
#include "global_inputs.h" // Para check
|
||||||
#include "screen.h" // Para Screen
|
#include "input.h" // Para Input
|
||||||
#include "section.h" // Para Name, name
|
#include "param.h" // Para Param, ParamGame, param
|
||||||
#include "sprite.h" // Para Sprite
|
#include "resource.h" // Para Resource
|
||||||
#include "texture.h" // Para Texture
|
#include "screen.h" // Para Screen
|
||||||
#include "utils.h" // Para Color, Zone
|
#include "section.h" // Para Name, name
|
||||||
|
#include "sprite.h" // Para Sprite
|
||||||
|
#include "texture.h" // Para Texture
|
||||||
|
#include "utils.h" // Para Color, Zone
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Logo::Logo()
|
Logo::Logo()
|
||||||
: since_texture_(Resource::get()->getTexture("logo_since_1998.png")),
|
: since_texture_(Resource::get()->getTexture("logo_since_1998.png")),
|
||||||
since_sprite_(std::make_unique<Sprite>(since_texture_)),
|
since_sprite_(std::make_unique<Sprite>(since_texture_)),
|
||||||
jail_texture_(Resource::get()->getTexture("logo_jailgames.png"))
|
jail_texture_(Resource::get()->getTexture("logo_jailgames.png")) {
|
||||||
{
|
// Inicializa variables
|
||||||
|
Section::name = Section::Name::LOGO;
|
||||||
|
dest_.x = param.game.game_area.center_x - jail_texture_->getWidth() / 2;
|
||||||
|
dest_.y = param.game.game_area.center_y - jail_texture_->getHeight() / 2;
|
||||||
|
since_sprite_->setPosition(SDL_FRect{
|
||||||
|
static_cast<float>((param.game.width - since_texture_->getWidth()) / 2),
|
||||||
|
static_cast<float>(83 + jail_texture_->getHeight() + 5),
|
||||||
|
static_cast<float>(since_texture_->getWidth()),
|
||||||
|
static_cast<float>(since_texture_->getHeight())});
|
||||||
|
since_sprite_->setY(dest_.y + jail_texture_->getHeight() + 5);
|
||||||
|
since_sprite_->setSpriteClip(0, 0, since_texture_->getWidth(), since_texture_->getHeight());
|
||||||
|
since_texture_->setColor(0x00, 0x00, 0x00);
|
||||||
|
|
||||||
// Inicializa variables
|
// Crea los sprites de cada linea
|
||||||
Section::name = Section::Name::LOGO;
|
for (int i = 0; i < jail_texture_->getHeight(); ++i) {
|
||||||
dest_.x = param.game.game_area.center_x - jail_texture_->getWidth() / 2;
|
auto temp = std::make_unique<Sprite>(jail_texture_, 0, i, jail_texture_->getWidth(), 1);
|
||||||
dest_.y = param.game.game_area.center_y - jail_texture_->getHeight() / 2;
|
temp->setSpriteClip(0, i, jail_texture_->getWidth(), 1);
|
||||||
since_sprite_->setPosition(SDL_FRect{
|
const int POS_X = (i % 2 == 0) ? param.game.width + (i * 3) : -jail_texture_->getWidth() - (i * 3);
|
||||||
static_cast<float>((param.game.width - since_texture_->getWidth()) / 2),
|
temp->setX(POS_X);
|
||||||
static_cast<float>(83 + jail_texture_->getHeight() + 5),
|
temp->setY(dest_.y + i);
|
||||||
static_cast<float>(since_texture_->getWidth()),
|
jail_sprite_.push_back(std::move(temp));
|
||||||
static_cast<float>(since_texture_->getHeight())});
|
}
|
||||||
since_sprite_->setY(dest_.y + jail_texture_->getHeight() + 5);
|
|
||||||
since_sprite_->setSpriteClip(0, 0, since_texture_->getWidth(), since_texture_->getHeight());
|
|
||||||
since_texture_->setColor(0x00, 0x00, 0x00);
|
|
||||||
|
|
||||||
// Crea los sprites de cada linea
|
// Inicializa el vector de colores
|
||||||
for (int i = 0; i < jail_texture_->getHeight(); ++i)
|
color_.push_back(Color(0x00, 0x00, 0x00)); // Black
|
||||||
{
|
color_.push_back(Color(0x00, 0x00, 0xd8)); // Blue
|
||||||
auto temp = std::make_unique<Sprite>(jail_texture_, 0, i, jail_texture_->getWidth(), 1);
|
color_.push_back(Color(0xd8, 0x00, 0x00)); // Red
|
||||||
temp->setSpriteClip(0, i, jail_texture_->getWidth(), 1);
|
color_.push_back(Color(0xd8, 0x00, 0xd8)); // Magenta
|
||||||
const int POS_X = (i % 2 == 0) ? param.game.width + (i * 3) : -jail_texture_->getWidth() - (i * 3);
|
color_.push_back(Color(0x00, 0xd8, 0x00)); // Green
|
||||||
temp->setX(POS_X);
|
color_.push_back(Color(0x00, 0xd8, 0xd8)); // Cyan
|
||||||
temp->setY(dest_.y + i);
|
color_.push_back(Color(0xd8, 0xd8, 0x00)); // Yellow
|
||||||
jail_sprite_.push_back(std::move(temp));
|
color_.push_back(Color(0xFF, 0xFF, 0xFF)); // Bright white
|
||||||
}
|
|
||||||
|
|
||||||
// Inicializa el vector de colores
|
|
||||||
color_.push_back(Color(0x00, 0x00, 0x00)); // Black
|
|
||||||
color_.push_back(Color(0x00, 0x00, 0xd8)); // Blue
|
|
||||||
color_.push_back(Color(0xd8, 0x00, 0x00)); // Red
|
|
||||||
color_.push_back(Color(0xd8, 0x00, 0xd8)); // Magenta
|
|
||||||
color_.push_back(Color(0x00, 0xd8, 0x00)); // Green
|
|
||||||
color_.push_back(Color(0x00, 0xd8, 0xd8)); // Cyan
|
|
||||||
color_.push_back(Color(0xd8, 0xd8, 0x00)); // Yellow
|
|
||||||
color_.push_back(Color(0xFF, 0xFF, 0xFF)); // Bright white
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
Logo::~Logo()
|
Logo::~Logo() {
|
||||||
{
|
jail_texture_->setColor(255, 255, 255);
|
||||||
jail_texture_->setColor(255, 255, 255);
|
since_texture_->setColor(255, 255, 255);
|
||||||
since_texture_->setColor(255, 255, 255);
|
Audio::get()->stopAllSounds();
|
||||||
Audio::get()->stopAllSounds();
|
Audio::get()->stopMusic();
|
||||||
Audio::get()->stopMusic();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba el manejador de eventos
|
// Comprueba el manejador de eventos
|
||||||
void Logo::checkEvents()
|
void Logo::checkEvents() {
|
||||||
{
|
SDL_Event event;
|
||||||
SDL_Event event;
|
while (SDL_PollEvent(&event)) {
|
||||||
while (SDL_PollEvent(&event))
|
GlobalEvents::check(event);
|
||||||
{
|
}
|
||||||
GlobalEvents::check(event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba las entradas
|
// Comprueba las entradas
|
||||||
void Logo::checkInput()
|
void Logo::checkInput() {
|
||||||
{
|
Input::get()->update();
|
||||||
Input::get()->update();
|
GlobalInputs::check();
|
||||||
GlobalInputs::check();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gestiona el logo de JAILGAMES
|
// Gestiona el logo de JAILGAMES
|
||||||
void Logo::updateJAILGAMES()
|
void Logo::updateJAILGAMES() {
|
||||||
{
|
if (counter_ == 30) {
|
||||||
if (counter_ == 30)
|
Audio::get()->playSound("logo.wav");
|
||||||
{
|
}
|
||||||
Audio::get()->playSound("logo.wav");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (counter_ > 30)
|
if (counter_ > 30) {
|
||||||
{
|
for (int i = 0; i < (int)jail_sprite_.size(); ++i) {
|
||||||
for (int i = 0; i < (int)jail_sprite_.size(); ++i)
|
if (jail_sprite_[i]->getX() != dest_.x) {
|
||||||
{
|
if (i % 2 == 0) {
|
||||||
if (jail_sprite_[i]->getX() != dest_.x)
|
jail_sprite_[i]->incX(-SPEED);
|
||||||
{
|
if (jail_sprite_[i]->getX() < dest_.x) {
|
||||||
if (i % 2 == 0)
|
jail_sprite_[i]->setX(dest_.x);
|
||||||
{
|
}
|
||||||
jail_sprite_[i]->incX(-SPEED);
|
} else {
|
||||||
if (jail_sprite_[i]->getX() < dest_.x)
|
jail_sprite_[i]->incX(SPEED);
|
||||||
{
|
if (jail_sprite_[i]->getX() > dest_.x) {
|
||||||
jail_sprite_[i]->setX(dest_.x);
|
jail_sprite_[i]->setX(dest_.x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
}
|
||||||
jail_sprite_[i]->incX(SPEED);
|
}
|
||||||
if (jail_sprite_[i]->getX() > dest_.x)
|
|
||||||
{
|
|
||||||
jail_sprite_[i]->setX(dest_.x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba si ha terminado el logo
|
// Comprueba si ha terminado el logo
|
||||||
if (counter_ == END_LOGO_COUNTER_MARK + POST_LOGO_DURATION)
|
if (counter_ == END_LOGO_COUNTER_MARK + POST_LOGO_DURATION) {
|
||||||
{
|
Section::name = Section::Name::INTRO;
|
||||||
Section::name = Section::Name::INTRO;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gestiona el color de las texturas
|
// Gestiona el color de las texturas
|
||||||
void Logo::updateTextureColors()
|
void Logo::updateTextureColors() {
|
||||||
{
|
constexpr int inc = 4;
|
||||||
constexpr int inc = 4;
|
|
||||||
|
|
||||||
// Manejo de 'sinceTexture'
|
// Manejo de 'sinceTexture'
|
||||||
for (int i = 0; i <= 7; ++i)
|
for (int i = 0; i <= 7; ++i) {
|
||||||
{
|
if (counter_ == SHOW_SINCE_SPRITE_COUNTER_MARK + inc * i) {
|
||||||
if (counter_ == SHOW_SINCE_SPRITE_COUNTER_MARK + inc * i)
|
since_texture_->setColor(color_[i].r, color_[i].g, color_[i].b);
|
||||||
{
|
}
|
||||||
since_texture_->setColor(color_[i].r, color_[i].g, color_[i].b);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manejo de 'jailTexture' y 'sinceTexture' en el fade
|
// Manejo de 'jailTexture' y 'sinceTexture' en el fade
|
||||||
for (int i = 0; i <= 6; ++i)
|
for (int i = 0; i <= 6; ++i) {
|
||||||
{
|
if (counter_ == INIT_FADE_COUNTER_MARK + inc * i) {
|
||||||
if (counter_ == INIT_FADE_COUNTER_MARK + inc * i)
|
jail_texture_->setColor(color_[6 - i].r, color_[6 - i].g, color_[6 - i].b);
|
||||||
{
|
since_texture_->setColor(color_[6 - i].r, color_[6 - i].g, color_[6 - i].b);
|
||||||
jail_texture_->setColor(color_[6 - i].r, color_[6 - i].g, color_[6 - i].b);
|
}
|
||||||
since_texture_->setColor(color_[6 - i].r, color_[6 - i].g, color_[6 - i].b);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza las variables
|
// Actualiza las variables
|
||||||
void Logo::update()
|
void Logo::update() {
|
||||||
{
|
if (SDL_GetTicks() - ticks_ > param.game.speed) {
|
||||||
if (SDL_GetTicks() - ticks_ > param.game.speed)
|
// Actualiza el contador de ticks
|
||||||
{
|
ticks_ = SDL_GetTicks();
|
||||||
// Actualiza el contador de ticks
|
|
||||||
ticks_ = SDL_GetTicks();
|
|
||||||
|
|
||||||
// Actualiza el objeto screen
|
// Actualiza el objeto screen
|
||||||
Screen::get()->update();
|
Screen::get()->update();
|
||||||
|
|
||||||
// Comprueba las entradas
|
// Comprueba las entradas
|
||||||
checkInput();
|
checkInput();
|
||||||
|
|
||||||
updateJAILGAMES();
|
updateJAILGAMES();
|
||||||
updateTextureColors();
|
updateTextureColors();
|
||||||
|
|
||||||
// Gestiona el contador
|
// Gestiona el contador
|
||||||
++counter_;
|
++counter_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja en pantalla
|
// Dibuja en pantalla
|
||||||
void Logo::render()
|
void Logo::render() {
|
||||||
{
|
Screen::get()->start();
|
||||||
Screen::get()->start();
|
Screen::get()->clean();
|
||||||
Screen::get()->clean();
|
|
||||||
|
|
||||||
renderJAILGAMES();
|
renderJAILGAMES();
|
||||||
|
|
||||||
Screen::get()->render();
|
Screen::get()->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bucle para el logo del juego
|
// Bucle para el logo del juego
|
||||||
void Logo::run()
|
void Logo::run() {
|
||||||
{
|
while (Section::name == Section::Name::LOGO) {
|
||||||
while (Section::name == Section::Name::LOGO)
|
checkInput();
|
||||||
{
|
update();
|
||||||
checkInput();
|
checkEvents(); // Tiene que ir antes del render
|
||||||
update();
|
render();
|
||||||
checkEvents(); // Tiene que ir antes del render
|
}
|
||||||
render();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderiza el logo de JAILGAMES
|
// Renderiza el logo de JAILGAMES
|
||||||
void Logo::renderJAILGAMES()
|
void Logo::renderJAILGAMES() {
|
||||||
{
|
// Dibuja los sprites
|
||||||
// Dibuja los sprites
|
for (auto &sprite : jail_sprite_) {
|
||||||
for (auto &sprite : jail_sprite_)
|
sprite->render();
|
||||||
{
|
}
|
||||||
sprite->render();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (counter_ >= SHOW_SINCE_SPRITE_COUNTER_MARK)
|
if (counter_ >= SHOW_SINCE_SPRITE_COUNTER_MARK) {
|
||||||
{
|
since_sprite_->render();
|
||||||
since_sprite_->render();
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+42
-42
@@ -1,60 +1,60 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FPoint, Uint64
|
#include <SDL3/SDL.h> // Para SDL_FPoint, Uint64
|
||||||
#include <memory> // Para shared_ptr, unique_ptr
|
|
||||||
#include <vector> // Para vector
|
#include <memory> // Para shared_ptr, unique_ptr
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
class Sprite;
|
class Sprite;
|
||||||
class Texture;
|
class Texture;
|
||||||
struct Color;
|
struct Color;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Esta clase gestiona un estado del programa. Se encarga de dibujar por pantalla el
|
Esta clase gestiona un estado del programa. Se encarga de dibujar por pantalla el
|
||||||
logo de "JAILGAMES" utilizando un sencillo efecto consistente en generar un sprite por
|
logo de "JAILGAMES" utilizando un sencillo efecto consistente en generar un sprite por
|
||||||
cada línea del bitmap que forma la palabra "JAILGAMES". Posteriormente realiza una
|
cada línea del bitmap que forma la palabra "JAILGAMES". Posteriormente realiza una
|
||||||
modulación de color sobre la textura para simular un fade to black al estilo
|
modulación de color sobre la textura para simular un fade to black al estilo
|
||||||
ZX Spectrum.
|
ZX Spectrum.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// --- Clase Logo ---
|
// --- Clase Logo ---
|
||||||
class Logo
|
class Logo {
|
||||||
{
|
public:
|
||||||
public:
|
// Constructor
|
||||||
// Constructor
|
Logo();
|
||||||
Logo();
|
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
~Logo();
|
~Logo();
|
||||||
|
|
||||||
// Bucle principal
|
// Bucle principal
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr int SHOW_SINCE_SPRITE_COUNTER_MARK = 70; // Tiempo del contador en el que empieza a verse el sprite de "SINCE 1998"
|
static constexpr int SHOW_SINCE_SPRITE_COUNTER_MARK = 70; // Tiempo del contador en el que empieza a verse el sprite de "SINCE 1998"
|
||||||
static constexpr int INIT_FADE_COUNTER_MARK = 300; // Tiempo del contador cuando inicia el fade a negro
|
static constexpr int INIT_FADE_COUNTER_MARK = 300; // Tiempo del contador cuando inicia el fade a negro
|
||||||
static constexpr int END_LOGO_COUNTER_MARK = 400; // Tiempo del contador para terminar el logo
|
static constexpr int END_LOGO_COUNTER_MARK = 400; // Tiempo del contador para terminar el logo
|
||||||
static constexpr int POST_LOGO_DURATION = 20; // Tiempo que dura el logo con el fade al máximo
|
static constexpr int POST_LOGO_DURATION = 20; // Tiempo que dura el logo con el fade al máximo
|
||||||
static constexpr int SPEED = 8; // Velocidad de desplazamiento de cada línea
|
static constexpr int SPEED = 8; // Velocidad de desplazamiento de cada línea
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
std::shared_ptr<Texture> since_texture_; // Textura con los gráficos "Since 1998"
|
std::shared_ptr<Texture> since_texture_; // Textura con los gráficos "Since 1998"
|
||||||
std::unique_ptr<Sprite> since_sprite_; // Sprite para manejar la since_texture
|
std::unique_ptr<Sprite> since_sprite_; // Sprite para manejar la since_texture
|
||||||
std::shared_ptr<Texture> jail_texture_; // Textura con los gráficos "JAILGAMES"
|
std::shared_ptr<Texture> jail_texture_; // Textura con los gráficos "JAILGAMES"
|
||||||
std::vector<std::unique_ptr<Sprite>> jail_sprite_; // Vector con los sprites de cada línea que forman el bitmap JAILGAMES
|
std::vector<std::unique_ptr<Sprite>> jail_sprite_; // Vector con los sprites de cada línea que forman el bitmap JAILGAMES
|
||||||
|
|
||||||
// --- Variables ---
|
// --- Variables ---
|
||||||
std::vector<Color> color_; // Vector con los colores para el fade
|
std::vector<Color> color_; // Vector con los colores para el fade
|
||||||
int counter_ = 0; // Contador
|
int counter_ = 0; // Contador
|
||||||
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
|
||||||
SDL_FPoint dest_; // Posición donde dibujar el logo
|
SDL_FPoint dest_; // Posición donde dibujar el logo
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void update(); // Actualiza las variables
|
void update(); // Actualiza las variables
|
||||||
void render(); // Dibuja en pantalla
|
void render(); // Dibuja en pantalla
|
||||||
void checkEvents(); // Comprueba el manejador de eventos
|
void checkEvents(); // Comprueba el manejador de eventos
|
||||||
void checkInput(); // Comprueba las entradas
|
void checkInput(); // Comprueba las entradas
|
||||||
void updateJAILGAMES(); // Gestiona el logo de JAILGAMES
|
void updateJAILGAMES(); // Gestiona el logo de JAILGAMES
|
||||||
void renderJAILGAMES(); // Renderiza el logo de JAILGAMES
|
void renderJAILGAMES(); // Renderiza el logo de JAILGAMES
|
||||||
void updateTextureColors(); // Gestiona el color de las texturas
|
void updateTextureColors(); // Gestiona el color de las texturas
|
||||||
};
|
};
|
||||||
+400
-456
@@ -1,579 +1,523 @@
|
|||||||
#include "title.h"
|
#include "title.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_GetTicks, Uint32, SDL_EventType
|
#include <SDL3/SDL.h> // Para SDL_GetTicks, Uint32, SDL_EventType
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
#include <algorithm> // Para find_if
|
|
||||||
#include <iostream> // Para basic_ostream, basic_ostream::operator<<
|
|
||||||
#include <string> // Para basic_string, char_traits, operator+
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "audio.h" // Para Audio
|
#include <algorithm> // Para find_if
|
||||||
#include "define_buttons.h" // Para DefineButtons
|
#include <iostream> // Para basic_ostream, basic_ostream::operator<<
|
||||||
#include "fade.h" // Para Fade, FadeType
|
#include <string> // Para basic_string, char_traits, operator+
|
||||||
#include "game_logo.h" // Para GameLogo
|
#include <vector> // Para vector
|
||||||
#include "global_events.h" // Para check
|
|
||||||
#include "global_inputs.h" // Para check
|
#include "audio.h" // Para Audio
|
||||||
#include "input.h" // Para Input, INPUT_DO_NOT_ALLOW_REPEAT, Input...
|
#include "define_buttons.h" // Para DefineButtons
|
||||||
#include "lang.h" // Para getText
|
#include "fade.h" // Para Fade, FadeType
|
||||||
#include "notifier.h" // Para Notifier
|
#include "game_logo.h" // Para GameLogo
|
||||||
#include "options.h" // Para GamepadOptions, controllers, getPlayerW...
|
#include "global_events.h" // Para check
|
||||||
#include "param.h" // Para Param, param, ParamGame, ParamTitle
|
#include "global_inputs.h" // Para check
|
||||||
#include "player.h" // Para Player, PlayerState
|
#include "input.h" // Para Input, INPUT_DO_NOT_ALLOW_REPEAT, Input...
|
||||||
#include "resource.h" // Para Resource
|
#include "lang.h" // Para getText
|
||||||
#include "screen.h" // Para Screen
|
#include "notifier.h" // Para Notifier
|
||||||
#include "section.h" // Para Name, name, Options, options, AttractMode
|
#include "options.h" // Para GamepadOptions, controllers, getPlayerW...
|
||||||
#include "sprite.h" // Para Sprite
|
#include "param.h" // Para Param, param, ParamGame, ParamTitle
|
||||||
#include "text.h" // Para TEXT_CENTER, TEXT_SHADOW, Text
|
#include "player.h" // Para Player, PlayerState
|
||||||
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
|
#include "resource.h" // Para Resource
|
||||||
#include "ui/service_menu.h" // Para ServiceMenu
|
#include "screen.h" // Para Screen
|
||||||
#include "utils.h" // Para Color, Zone, NO_TEXT_COLOR, TITLE_SHADO...
|
#include "section.h" // Para Name, name, Options, options, AttractMode
|
||||||
|
#include "sprite.h" // Para Sprite
|
||||||
|
#include "text.h" // Para TEXT_CENTER, TEXT_SHADOW, Text
|
||||||
|
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
|
||||||
|
#include "ui/service_menu.h" // Para ServiceMenu
|
||||||
|
#include "utils.h" // Para Color, Zone, NO_TEXT_COLOR, TITLE_SHADO...
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#include <iomanip> // Para operator<<, setfill, setw
|
#include <iomanip> // Para operator<<, setfill, setw
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Title::Title()
|
Title::Title()
|
||||||
: text_(Resource::get()->getText("smb2_grad")),
|
: text_(Resource::get()->getText("smb2_grad")),
|
||||||
fade_(std::make_unique<Fade>()),
|
fade_(std::make_unique<Fade>()),
|
||||||
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::RANDOM)),
|
tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::RANDOM)),
|
||||||
game_logo_(std::make_unique<GameLogo>(param.game.game_area.center_x, param.title.title_c_c_position)),
|
game_logo_(std::make_unique<GameLogo>(param.game.game_area.center_x, param.title.title_c_c_position)),
|
||||||
mini_logo_sprite_(std::make_unique<Sprite>(Resource::get()->getTexture("logo_jailgames_mini.png"))),
|
mini_logo_sprite_(std::make_unique<Sprite>(Resource::get()->getTexture("logo_jailgames_mini.png"))),
|
||||||
define_buttons_(std::make_unique<DefineButtons>()),
|
define_buttons_(std::make_unique<DefineButtons>()),
|
||||||
num_controllers_(Input::get()->getNumControllers()),
|
num_controllers_(Input::get()->getNumControllers()),
|
||||||
state_(TitleState::LOGO_ANIMATING)
|
state_(TitleState::LOGO_ANIMATING) {
|
||||||
{
|
// Configura objetos
|
||||||
// Configura objetos
|
tiled_bg_->setColor(param.title.bg_color);
|
||||||
tiled_bg_->setColor(param.title.bg_color);
|
game_logo_->enable();
|
||||||
game_logo_->enable();
|
mini_logo_sprite_->setX(param.game.game_area.center_x - mini_logo_sprite_->getWidth() / 2);
|
||||||
mini_logo_sprite_->setX(param.game.game_area.center_x - mini_logo_sprite_->getWidth() / 2);
|
fade_->setColor(param.fade.color);
|
||||||
fade_->setColor(param.fade.color);
|
fade_->setType(FadeType::RANDOM_SQUARE);
|
||||||
fade_->setType(FadeType::RANDOM_SQUARE);
|
fade_->setPostDuration(param.fade.post_duration);
|
||||||
fade_->setPostDuration(param.fade.post_duration);
|
initPlayers();
|
||||||
initPlayers();
|
|
||||||
|
|
||||||
// Asigna valores a otras variables
|
// Asigna valores a otras variables
|
||||||
Section::options = Section::Options::TITLE_1;
|
Section::options = Section::Options::TITLE_1;
|
||||||
const bool IS_TITLE_TO_DEMO = (Section::attract_mode == Section::AttractMode::TITLE_TO_DEMO);
|
const bool IS_TITLE_TO_DEMO = (Section::attract_mode == Section::AttractMode::TITLE_TO_DEMO);
|
||||||
next_section_ = IS_TITLE_TO_DEMO ? Section::Name::GAME_DEMO : Section::Name::LOGO;
|
next_section_ = IS_TITLE_TO_DEMO ? Section::Name::GAME_DEMO : Section::Name::LOGO;
|
||||||
Section::attract_mode = IS_TITLE_TO_DEMO ? Section::AttractMode::TITLE_TO_LOGO : Section::AttractMode::TITLE_TO_DEMO;
|
Section::attract_mode = IS_TITLE_TO_DEMO ? Section::AttractMode::TITLE_TO_LOGO : Section::AttractMode::TITLE_TO_DEMO;
|
||||||
|
|
||||||
// Define los anclajes de los elementos
|
// Define los anclajes de los elementos
|
||||||
anchor_.mini_logo = (param.game.height / 5 * 4) + BLOCK;
|
anchor_.mini_logo = (param.game.height / 5 * 4) + BLOCK;
|
||||||
mini_logo_sprite_->setY(anchor_.mini_logo);
|
mini_logo_sprite_->setY(anchor_.mini_logo);
|
||||||
anchor_.copyright_text = anchor_.mini_logo + mini_logo_sprite_->getHeight() + 3;
|
anchor_.copyright_text = anchor_.mini_logo + mini_logo_sprite_->getHeight() + 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
Title::~Title()
|
Title::~Title() {
|
||||||
{
|
Audio::get()->stopAllSounds();
|
||||||
Audio::get()->stopAllSounds();
|
if (Section::name == Section::Name::LOGO) {
|
||||||
if (Section::name == Section::Name::LOGO)
|
Audio::get()->fadeOutMusic(300);
|
||||||
{
|
}
|
||||||
Audio::get()->fadeOutMusic(300);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza las variables del objeto
|
// Actualiza las variables del objeto
|
||||||
void Title::update()
|
void Title::update() {
|
||||||
{
|
if (SDL_GetTicks() - ticks_ > param.game.speed) {
|
||||||
if (SDL_GetTicks() - ticks_ > param.game.speed)
|
ticks_ = SDL_GetTicks();
|
||||||
{
|
updateFade();
|
||||||
ticks_ = SDL_GetTicks();
|
updateState();
|
||||||
updateFade();
|
updateStartPrompt();
|
||||||
updateState();
|
updatePlayers();
|
||||||
updateStartPrompt();
|
Screen::get()->update();
|
||||||
updatePlayers();
|
}
|
||||||
Screen::get()->update();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja el objeto en pantalla
|
// Dibuja el objeto en pantalla
|
||||||
void Title::render()
|
void Title::render() {
|
||||||
{
|
Screen::get()->start();
|
||||||
Screen::get()->start();
|
Screen::get()->clean();
|
||||||
Screen::get()->clean();
|
|
||||||
|
|
||||||
tiled_bg_->render();
|
tiled_bg_->render();
|
||||||
game_logo_->render();
|
game_logo_->render();
|
||||||
renderPlayers();
|
renderPlayers();
|
||||||
renderStartPrompt();
|
renderStartPrompt();
|
||||||
renderCopyright();
|
renderCopyright();
|
||||||
|
|
||||||
define_buttons_->render();
|
define_buttons_->render();
|
||||||
fade_->render();
|
fade_->render();
|
||||||
|
|
||||||
Screen::get()->render();
|
Screen::get()->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba los eventos
|
// Comprueba los eventos
|
||||||
void Title::checkEvents()
|
void Title::checkEvents() {
|
||||||
{
|
SDL_Event event;
|
||||||
SDL_Event event;
|
while (SDL_PollEvent(&event)) {
|
||||||
while (SDL_PollEvent(&event))
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (event.type == SDL_EVENT_KEY_DOWN && event.key.repeat == 1)
|
if (event.type == SDL_EVENT_KEY_DOWN && event.key.repeat == 1) {
|
||||||
{
|
static Color color = param.title.bg_color;
|
||||||
static Color color = param.title.bg_color;
|
switch (event.key.key) {
|
||||||
switch (event.key.key)
|
case SDLK_A:
|
||||||
{
|
if (color.r < 255)
|
||||||
case SDLK_A:
|
++color.r;
|
||||||
if (color.r < 255)
|
break;
|
||||||
++color.r;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDLK_Z:
|
case SDLK_Z:
|
||||||
if (color.r > 0)
|
if (color.r > 0)
|
||||||
--color.r;
|
--color.r;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_S:
|
case SDLK_S:
|
||||||
if (color.g < 255)
|
if (color.g < 255)
|
||||||
++color.g;
|
++color.g;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_X:
|
case SDLK_X:
|
||||||
if (color.g > 0)
|
if (color.g > 0)
|
||||||
--color.g;
|
--color.g;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_D:
|
case SDLK_D:
|
||||||
if (color.b < 255)
|
if (color.b < 255)
|
||||||
++color.b;
|
++color.b;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_C:
|
case SDLK_C:
|
||||||
if (color.b > 0)
|
if (color.b > 0)
|
||||||
--color.b;
|
--color.b;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_F:
|
case SDLK_F:
|
||||||
if (color.r < 255)
|
if (color.r < 255)
|
||||||
++color.r;
|
++color.r;
|
||||||
if (color.g < 255)
|
if (color.g < 255)
|
||||||
++color.g;
|
++color.g;
|
||||||
if (color.b < 255)
|
if (color.b < 255)
|
||||||
++color.b;
|
++color.b;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_V:
|
case SDLK_V:
|
||||||
if (color.r > 0)
|
if (color.r > 0)
|
||||||
--color.r;
|
--color.r;
|
||||||
if (color.g > 0)
|
if (color.g > 0)
|
||||||
--color.g;
|
--color.g;
|
||||||
if (color.b > 0)
|
if (color.b > 0)
|
||||||
--color.b;
|
--color.b;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
counter_ = 0;
|
counter_ = 0;
|
||||||
tiled_bg_->setColor(color);
|
tiled_bg_->setColor(color);
|
||||||
std::cout << "#"
|
std::cout << "#"
|
||||||
<< std::hex << std::setw(2) << std::setfill('0') << (int)color.r
|
<< std::hex << std::setw(2) << std::setfill('0') << (int)color.r
|
||||||
<< std::setw(2) << std::setfill('0') << (int)color.g
|
<< std::setw(2) << std::setfill('0') << (int)color.g
|
||||||
<< std::setw(2) << std::setfill('0') << (int)color.b
|
<< std::setw(2) << std::setfill('0') << (int)color.b
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (event.type == SDL_EVENT_KEY_DOWN && event.key.repeat == 0)
|
if (event.type == SDL_EVENT_KEY_DOWN && event.key.repeat == 0) {
|
||||||
{
|
switch (event.key.key) {
|
||||||
switch (event.key.key)
|
case SDLK_1: // Redefine los botones del mando #0
|
||||||
{
|
define_buttons_->enable(0);
|
||||||
case SDLK_1: // Redefine los botones del mando #0
|
resetCounter();
|
||||||
define_buttons_->enable(0);
|
break;
|
||||||
resetCounter();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDLK_2: // Redefine los botones del mando #1
|
case SDLK_2: // Redefine los botones del mando #1
|
||||||
define_buttons_->enable(1);
|
define_buttons_->enable(1);
|
||||||
resetCounter();
|
resetCounter();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_3: // Intercambia los mandos entre los dos jugadores
|
case SDLK_3: // Intercambia los mandos entre los dos jugadores
|
||||||
swapControllers();
|
swapControllers();
|
||||||
resetCounter();
|
resetCounter();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_4: // Intercambia la asignación del teclado
|
case SDLK_4: // Intercambia la asignación del teclado
|
||||||
swapKeyboard();
|
swapKeyboard();
|
||||||
resetCounter();
|
resetCounter();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDLK_5: // Muestra la asignación de mandos y teclado
|
case SDLK_5: // Muestra la asignación de mandos y teclado
|
||||||
showControllers();
|
showControllers();
|
||||||
resetCounter();
|
resetCounter();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalEvents::check(event);
|
GlobalEvents::check(event);
|
||||||
define_buttons_->checkEvents(event);
|
define_buttons_->checkEvents(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba las entradas
|
// Comprueba las entradas
|
||||||
void Title::checkInput()
|
void Title::checkInput() {
|
||||||
{
|
// Comprueba las entradas solo si no se estan definiendo los botones
|
||||||
// Comprueba las entradas solo si no se estan definiendo los botones
|
if (define_buttons_->isEnabled())
|
||||||
if (define_buttons_->isEnabled())
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
Input::get()->update();
|
Input::get()->update();
|
||||||
|
|
||||||
if (!ServiceMenu::get()->isEnabled())
|
if (!ServiceMenu::get()->isEnabled()) {
|
||||||
{
|
// Comprueba todos los métodos de control
|
||||||
// Comprueba todos los métodos de control
|
for (const auto &CONTROLLER : Options::controllers) {
|
||||||
for (const auto &CONTROLLER : Options::controllers)
|
// Boton START
|
||||||
{
|
if (Input::get()->checkInput(InputAction::START, INPUT_DO_NOT_ALLOW_REPEAT, CONTROLLER.type, CONTROLLER.index)) {
|
||||||
// Boton START
|
if ((state_ != TitleState::LOGO_ANIMATING || ALLOW_TITLE_ANIMATION_SKIP)) {
|
||||||
if (Input::get()->checkInput(InputAction::START, INPUT_DO_NOT_ALLOW_REPEAT, CONTROLLER.type, CONTROLLER.index))
|
if (CONTROLLER.player_id == 1) {
|
||||||
{
|
if (!player1_start_pressed_) {
|
||||||
if ((state_ != TitleState::LOGO_ANIMATING || ALLOW_TITLE_ANIMATION_SKIP))
|
player1_start_pressed_ = true;
|
||||||
{
|
getPlayer(1)->setPlayingState(PlayerState::TITLE_ANIMATION);
|
||||||
if (CONTROLLER.player_id == 1)
|
setState(TitleState::START_HAS_BEEN_PRESSED);
|
||||||
{
|
counter_ = 0;
|
||||||
if (!player1_start_pressed_)
|
}
|
||||||
{
|
}
|
||||||
player1_start_pressed_ = true;
|
|
||||||
getPlayer(1)->setPlayingState(PlayerState::TITLE_ANIMATION);
|
|
||||||
setState(TitleState::START_HAS_BEEN_PRESSED);
|
|
||||||
counter_ = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CONTROLLER.player_id == 2)
|
if (CONTROLLER.player_id == 2) {
|
||||||
{
|
if (!player2_start_pressed_) {
|
||||||
if (!player2_start_pressed_)
|
player2_start_pressed_ = true;
|
||||||
{
|
getPlayer(2)->setPlayingState(PlayerState::TITLE_ANIMATION);
|
||||||
player2_start_pressed_ = true;
|
setState(TitleState::START_HAS_BEEN_PRESSED);
|
||||||
getPlayer(2)->setPlayingState(PlayerState::TITLE_ANIMATION);
|
counter_ = 0;
|
||||||
setState(TitleState::START_HAS_BEEN_PRESSED);
|
}
|
||||||
counter_ = 0;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
|
||||||
GlobalInputs::check();
|
GlobalInputs::check();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bucle para el titulo del juego
|
// Bucle para el titulo del juego
|
||||||
void Title::run()
|
void Title::run() {
|
||||||
{
|
while (Section::name == Section::Name::TITLE) {
|
||||||
while (Section::name == Section::Name::TITLE)
|
checkInput();
|
||||||
{
|
update();
|
||||||
checkInput();
|
checkEvents(); // Tiene que ir antes del render
|
||||||
update();
|
render();
|
||||||
checkEvents(); // Tiene que ir antes del render
|
}
|
||||||
render();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reinicia el contador interno
|
// Reinicia el contador interno
|
||||||
void Title::resetCounter() { counter_ = 0; }
|
void Title::resetCounter() { counter_ = 0; }
|
||||||
|
|
||||||
// Intercambia la asignación de mandos a los jugadores
|
// Intercambia la asignación de mandos a los jugadores
|
||||||
void Title::swapControllers()
|
void Title::swapControllers() {
|
||||||
{
|
if (Input::get()->getNumControllers() == 0)
|
||||||
if (Input::get()->getNumControllers() == 0)
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
Options::swapControllers();
|
Options::swapControllers();
|
||||||
showControllers();
|
showControllers();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intercambia el teclado de jugador
|
// Intercambia el teclado de jugador
|
||||||
void Title::swapKeyboard()
|
void Title::swapKeyboard() {
|
||||||
{
|
Options::swapKeyboard();
|
||||||
Options::swapKeyboard();
|
std::string text = Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(Options::getPlayerWhoUsesKeyboard()) + ": " + Lang::getText("[DEFINE_BUTTONS] KEYBOARD");
|
||||||
std::string text = Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(Options::getPlayerWhoUsesKeyboard()) + ": " + Lang::getText("[DEFINE_BUTTONS] KEYBOARD");
|
Notifier::get()->show({text});
|
||||||
Notifier::get()->show({text});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Muestra información sobre los controles y los jugadores
|
// Muestra información sobre los controles y los jugadores
|
||||||
void Title::showControllers()
|
void Title::showControllers() {
|
||||||
{
|
// Crea vectores de texto vacíos para un número máximo de mandos
|
||||||
// Crea vectores de texto vacíos para un número máximo de mandos
|
constexpr size_t NUM_CONTROLLERS = 2;
|
||||||
constexpr size_t NUM_CONTROLLERS = 2;
|
std::vector<std::string> text(NUM_CONTROLLERS);
|
||||||
std::vector<std::string> text(NUM_CONTROLLERS);
|
std::vector<int> player_controller_index(NUM_CONTROLLERS, -1);
|
||||||
std::vector<int> player_controller_index(NUM_CONTROLLERS, -1);
|
|
||||||
|
|
||||||
// Obtiene de cada jugador el índice del mando que tiene asignado
|
// Obtiene de cada jugador el índice del mando que tiene asignado
|
||||||
for (size_t i = 0; i < NUM_CONTROLLERS; ++i)
|
for (size_t i = 0; i < NUM_CONTROLLERS; ++i) {
|
||||||
{
|
// Ejemplo: el jugador 1 tiene el mando 2
|
||||||
// Ejemplo: el jugador 1 tiene el mando 2
|
player_controller_index.at(Options::controllers.at(i).player_id - 1) = i;
|
||||||
player_controller_index.at(Options::controllers.at(i).player_id - 1) = i;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Genera el texto correspondiente
|
// Genera el texto correspondiente
|
||||||
for (size_t i = 0; i < NUM_CONTROLLERS; ++i)
|
for (size_t i = 0; i < NUM_CONTROLLERS; ++i) {
|
||||||
{
|
const size_t index = player_controller_index.at(i);
|
||||||
const size_t index = player_controller_index.at(i);
|
if (Options::controllers.at(index).plugged) {
|
||||||
if (Options::controllers.at(index).plugged)
|
text.at(i) = Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(i + 1) + ": " + Options::controllers.at(index).name;
|
||||||
{
|
}
|
||||||
text.at(i) = Lang::getText("[DEFINE_BUTTONS] PLAYER") + std::to_string(i + 1) + ": " + Options::controllers.at(index).name;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Muestra la notificación
|
// Muestra la notificación
|
||||||
Notifier::get()->show({text.at(0), text.at(1)});
|
Notifier::get()->show({text.at(0), text.at(1)});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el fade
|
// Actualiza el fade
|
||||||
void Title::updateFade()
|
void Title::updateFade() {
|
||||||
{
|
fade_->update();
|
||||||
fade_->update();
|
if (fade_->hasEnded()) {
|
||||||
if (fade_->hasEnded())
|
const int COMBO = (player1_start_pressed_ ? 1 : 0) | (player2_start_pressed_ ? 2 : 0);
|
||||||
{
|
|
||||||
const int COMBO = (player1_start_pressed_ ? 1 : 0) | (player2_start_pressed_ ? 2 : 0);
|
|
||||||
|
|
||||||
switch (COMBO)
|
switch (COMBO) {
|
||||||
{
|
case 0: // Ningún jugador ha pulsado Start
|
||||||
case 0: // Ningún jugador ha pulsado Start
|
Section::name = next_section_;
|
||||||
Section::name = next_section_;
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: // Solo el jugador 1 ha pulsado Start
|
case 1: // Solo el jugador 1 ha pulsado Start
|
||||||
Section::name = Section::Name::GAME;
|
Section::name = Section::Name::GAME;
|
||||||
Section::options = Section::Options::GAME_PLAY_1P;
|
Section::options = Section::Options::GAME_PLAY_1P;
|
||||||
Audio::get()->stopMusic();
|
Audio::get()->stopMusic();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: // Solo el jugador 2 ha pulsado Start
|
case 2: // Solo el jugador 2 ha pulsado Start
|
||||||
Section::name = Section::Name::GAME;
|
Section::name = Section::Name::GAME;
|
||||||
Section::options = Section::Options::GAME_PLAY_2P;
|
Section::options = Section::Options::GAME_PLAY_2P;
|
||||||
Audio::get()->stopMusic();
|
Audio::get()->stopMusic();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // Ambos jugadores han pulsado Start
|
case 3: // Ambos jugadores han pulsado Start
|
||||||
Section::name = Section::Name::GAME;
|
Section::name = Section::Name::GAME;
|
||||||
Section::options = Section::Options::GAME_PLAY_BOTH;
|
Section::options = Section::Options::GAME_PLAY_BOTH;
|
||||||
Audio::get()->stopMusic();
|
Audio::get()->stopMusic();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el estado
|
// Actualiza el estado
|
||||||
void Title::updateState()
|
void Title::updateState() {
|
||||||
{
|
// Establece la lógica según el estado
|
||||||
// Establece la lógica según el estado
|
switch (state_) {
|
||||||
switch (state_)
|
case TitleState::LOGO_ANIMATING: {
|
||||||
{
|
game_logo_->update();
|
||||||
case TitleState::LOGO_ANIMATING:
|
if (game_logo_->hasFinished()) {
|
||||||
{
|
setState(TitleState::LOGO_FINISHED);
|
||||||
game_logo_->update();
|
}
|
||||||
if (game_logo_->hasFinished())
|
break;
|
||||||
{
|
}
|
||||||
setState(TitleState::LOGO_FINISHED);
|
case TitleState::LOGO_FINISHED: {
|
||||||
}
|
// El contador solo sube si no estamos definiendo botones
|
||||||
break;
|
counter_ = define_buttons_->isEnabled() ? 0 : counter_ + 1;
|
||||||
}
|
|
||||||
case TitleState::LOGO_FINISHED:
|
|
||||||
{
|
|
||||||
// El contador solo sube si no estamos definiendo botones
|
|
||||||
counter_ = define_buttons_->isEnabled() ? 0 : counter_ + 1;
|
|
||||||
|
|
||||||
// Actualiza el logo con el título del juego
|
// Actualiza el logo con el título del juego
|
||||||
game_logo_->update();
|
game_logo_->update();
|
||||||
|
|
||||||
// Actualiza el mosaico de fondo
|
// Actualiza el mosaico de fondo
|
||||||
tiled_bg_->update();
|
tiled_bg_->update();
|
||||||
|
|
||||||
if (counter_ == param.title.title_duration)
|
if (counter_ == param.title.title_duration) {
|
||||||
{
|
// El menu ha hecho time out
|
||||||
// El menu ha hecho time out
|
fade_->setPostDuration(0);
|
||||||
fade_->setPostDuration(0);
|
fade_->activate();
|
||||||
fade_->activate();
|
selection_ = Section::Options::TITLE_TIME_OUT;
|
||||||
selection_ = Section::Options::TITLE_TIME_OUT;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TitleState::START_HAS_BEEN_PRESSED:
|
case TitleState::START_HAS_BEEN_PRESSED: {
|
||||||
{
|
// Actualiza el logo con el título del juego
|
||||||
// Actualiza el logo con el título del juego
|
game_logo_->update();
|
||||||
game_logo_->update();
|
|
||||||
|
|
||||||
// Actualiza el mosaico de fondo
|
// Actualiza el mosaico de fondo
|
||||||
tiled_bg_->update();
|
tiled_bg_->update();
|
||||||
|
|
||||||
if (counter_ == 100)
|
if (counter_ == 100) {
|
||||||
{
|
fade_->activate();
|
||||||
fade_->activate();
|
}
|
||||||
}
|
++counter_;
|
||||||
++counter_;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Title::updateStartPrompt()
|
void Title::updateStartPrompt() {
|
||||||
{
|
constexpr Uint32 LOGO_BLINK_PERIOD = 833; // milisegundos
|
||||||
constexpr Uint32 LOGO_BLINK_PERIOD = 833; // milisegundos
|
constexpr Uint32 LOGO_BLINK_ON_TIME = 583; // 833 - 250
|
||||||
constexpr Uint32 LOGO_BLINK_ON_TIME = 583; // 833 - 250
|
|
||||||
|
|
||||||
constexpr Uint32 START_BLINK_PERIOD = 167;
|
constexpr Uint32 START_BLINK_PERIOD = 167;
|
||||||
constexpr Uint32 START_BLINK_ON_TIME = 83; // 167 - 83
|
constexpr Uint32 START_BLINK_ON_TIME = 83; // 167 - 83
|
||||||
|
|
||||||
Uint32 time_ms = SDL_GetTicks();
|
Uint32 time_ms = SDL_GetTicks();
|
||||||
bool condition_met = false;
|
bool condition_met = false;
|
||||||
|
|
||||||
if (!define_buttons_->isEnabled())
|
if (!define_buttons_->isEnabled()) {
|
||||||
{
|
switch (state_) {
|
||||||
switch (state_)
|
case TitleState::LOGO_FINISHED:
|
||||||
{
|
condition_met = (time_ms % LOGO_BLINK_PERIOD) >= (LOGO_BLINK_PERIOD - LOGO_BLINK_ON_TIME);
|
||||||
case TitleState::LOGO_FINISHED:
|
break;
|
||||||
condition_met = (time_ms % LOGO_BLINK_PERIOD) >= (LOGO_BLINK_PERIOD - LOGO_BLINK_ON_TIME);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TitleState::START_HAS_BEEN_PRESSED:
|
case TitleState::START_HAS_BEEN_PRESSED:
|
||||||
condition_met = (time_ms % START_BLINK_PERIOD) >= (START_BLINK_PERIOD - START_BLINK_ON_TIME);
|
condition_met = (time_ms % START_BLINK_PERIOD) >= (START_BLINK_PERIOD - START_BLINK_ON_TIME);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
should_render_start_prompt = condition_met;
|
should_render_start_prompt = condition_met;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Title::renderStartPrompt()
|
void Title::renderStartPrompt() {
|
||||||
{
|
if (should_render_start_prompt) {
|
||||||
if (should_render_start_prompt)
|
text_->writeDX(TEXT_CENTER | TEXT_SHADOW,
|
||||||
{
|
param.game.game_area.center_x,
|
||||||
text_->writeDX(TEXT_CENTER | TEXT_SHADOW,
|
param.title.press_start_position,
|
||||||
param.game.game_area.center_x,
|
Lang::getText("[TITLE] PRESS_BUTTON_TO_PLAY"),
|
||||||
param.title.press_start_position,
|
1,
|
||||||
Lang::getText("[TITLE] PRESS_BUTTON_TO_PLAY"),
|
NO_TEXT_COLOR,
|
||||||
1,
|
1,
|
||||||
NO_TEXT_COLOR,
|
TITLE_SHADOW_TEXT_COLOR);
|
||||||
1,
|
}
|
||||||
TITLE_SHADOW_TEXT_COLOR);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Title::renderCopyright()
|
void Title::renderCopyright() {
|
||||||
{
|
if (state_ != TitleState::LOGO_ANIMATING) {
|
||||||
if (state_ != TitleState::LOGO_ANIMATING)
|
// Mini logo
|
||||||
{
|
mini_logo_sprite_->render();
|
||||||
// Mini logo
|
|
||||||
mini_logo_sprite_->render();
|
|
||||||
|
|
||||||
// Texto con el copyright
|
// Texto con el copyright
|
||||||
text_->writeDX(TEXT_CENTER | TEXT_SHADOW,
|
text_->writeDX(TEXT_CENTER | TEXT_SHADOW,
|
||||||
param.game.game_area.center_x,
|
param.game.game_area.center_x,
|
||||||
anchor_.copyright_text,
|
anchor_.copyright_text,
|
||||||
TEXT_COPYRIGHT,
|
TEXT_COPYRIGHT,
|
||||||
1,
|
1,
|
||||||
NO_TEXT_COLOR,
|
NO_TEXT_COLOR,
|
||||||
1,
|
1,
|
||||||
TITLE_SHADOW_TEXT_COLOR);
|
TITLE_SHADOW_TEXT_COLOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cambia el estado
|
// Cambia el estado
|
||||||
void Title::setState(TitleState state)
|
void Title::setState(TitleState state) {
|
||||||
{
|
if (state_ == state)
|
||||||
if (state_ == state)
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
state_ = state;
|
state_ = state;
|
||||||
switch (state_)
|
switch (state_) {
|
||||||
{
|
case TitleState::LOGO_ANIMATING:
|
||||||
case TitleState::LOGO_ANIMATING:
|
break;
|
||||||
break;
|
case TitleState::LOGO_FINISHED:
|
||||||
case TitleState::LOGO_FINISHED:
|
Audio::get()->playMusic("title.ogg");
|
||||||
Audio::get()->playMusic("title.ogg");
|
break;
|
||||||
break;
|
case TitleState::START_HAS_BEEN_PRESSED:
|
||||||
case TitleState::START_HAS_BEEN_PRESSED:
|
Audio::get()->fadeOutMusic(1500);
|
||||||
Audio::get()->fadeOutMusic(1500);
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa los jugadores
|
// Inicializa los jugadores
|
||||||
void Title::initPlayers()
|
void Title::initPlayers() {
|
||||||
{
|
std::vector<std::vector<std::shared_ptr<Texture>>> player_textures; // Vector con todas las texturas de los jugadores;
|
||||||
std::vector<std::vector<std::shared_ptr<Texture>>> player_textures; // Vector con todas las texturas de los jugadores;
|
std::vector<std::vector<std::string>> player_animations; // Vector con las animaciones del jugador
|
||||||
std::vector<std::vector<std::string>> player_animations; // Vector con las animaciones del jugador
|
|
||||||
|
|
||||||
// Texturas - Player1
|
// Texturas - Player1
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<Texture>> player_texture;
|
std::vector<std::shared_ptr<Texture>> player_texture;
|
||||||
player_texture.emplace_back(Resource::get()->getTexture("player1.gif"));
|
player_texture.emplace_back(Resource::get()->getTexture("player1.gif"));
|
||||||
player_texture.emplace_back(Resource::get()->getTexture("player1_power.png"));
|
player_texture.emplace_back(Resource::get()->getTexture("player1_power.png"));
|
||||||
player_textures.push_back(player_texture);
|
player_textures.push_back(player_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Texturas - Player2
|
// Texturas - Player2
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<Texture>> player_texture;
|
std::vector<std::shared_ptr<Texture>> player_texture;
|
||||||
player_texture.emplace_back(Resource::get()->getTexture("player2.gif"));
|
player_texture.emplace_back(Resource::get()->getTexture("player2.gif"));
|
||||||
player_texture.emplace_back(Resource::get()->getTexture("player2_power.png"));
|
player_texture.emplace_back(Resource::get()->getTexture("player2_power.png"));
|
||||||
player_textures.push_back(player_texture);
|
player_textures.push_back(player_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Animaciones -- Jugador
|
// Animaciones -- Jugador
|
||||||
{
|
{
|
||||||
player_animations.emplace_back(Resource::get()->getAnimation("player.ani"));
|
player_animations.emplace_back(Resource::get()->getAnimation("player.ani"));
|
||||||
player_animations.emplace_back(Resource::get()->getAnimation("player_power.ani"));
|
player_animations.emplace_back(Resource::get()->getAnimation("player_power.ani"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea los dos jugadores
|
// Crea los dos jugadores
|
||||||
constexpr int PLAYER_WIDTH = 32;
|
constexpr int PLAYER_WIDTH = 32;
|
||||||
constexpr int PLAYER_HEIGHT = 32;
|
constexpr int PLAYER_HEIGHT = 32;
|
||||||
const int Y = param.title.press_start_position - (PLAYER_HEIGHT / 2);
|
const int Y = param.title.press_start_position - (PLAYER_HEIGHT / 2);
|
||||||
constexpr bool DEMO = false;
|
constexpr bool DEMO = false;
|
||||||
players_.emplace_back(std::make_unique<Player>(1, param.game.game_area.center_x - (PLAYER_WIDTH / 2), Y, DEMO, param.game.play_area.rect, player_textures.at(0), player_animations));
|
players_.emplace_back(std::make_unique<Player>(1, param.game.game_area.center_x - (PLAYER_WIDTH / 2), Y, DEMO, param.game.play_area.rect, player_textures.at(0), player_animations));
|
||||||
players_.back()->setPlayingState(PlayerState::TITLE_HIDDEN);
|
players_.back()->setPlayingState(PlayerState::TITLE_HIDDEN);
|
||||||
|
|
||||||
players_.emplace_back(std::make_unique<Player>(2, param.game.game_area.center_x - (PLAYER_WIDTH / 2), Y, DEMO, param.game.play_area.rect, player_textures.at(1), player_animations));
|
players_.emplace_back(std::make_unique<Player>(2, param.game.game_area.center_x - (PLAYER_WIDTH / 2), Y, DEMO, param.game.play_area.rect, player_textures.at(1), player_animations));
|
||||||
players_.back()->setPlayingState(PlayerState::TITLE_HIDDEN);
|
players_.back()->setPlayingState(PlayerState::TITLE_HIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualza los jugadores
|
// Actualza los jugadores
|
||||||
void Title::updatePlayers()
|
void Title::updatePlayers() {
|
||||||
{
|
for (auto &player : players_) {
|
||||||
for (auto &player : players_)
|
player->update();
|
||||||
{
|
}
|
||||||
player->update();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderiza los jugadores
|
// Renderiza los jugadores
|
||||||
void Title::renderPlayers()
|
void Title::renderPlayers() {
|
||||||
{
|
for (auto const &player : players_) {
|
||||||
for (auto const &player : players_)
|
player->render();
|
||||||
{
|
}
|
||||||
player->render();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene un jugador a partir de su "id"
|
// Obtiene un jugador a partir de su "id"
|
||||||
std::shared_ptr<Player> Title::getPlayer(int id)
|
std::shared_ptr<Player> Title::getPlayer(int id) {
|
||||||
{
|
auto it = std::find_if(players_.begin(), players_.end(), [id](const auto &player) { return player->getId() == id; });
|
||||||
auto it = std::find_if(players_.begin(), players_.end(), [id](const auto &player)
|
|
||||||
{ return player->getId() == id; });
|
|
||||||
|
|
||||||
if (it != players_.end())
|
if (it != players_.end()) {
|
||||||
{
|
return *it;
|
||||||
return *it;
|
}
|
||||||
}
|
return nullptr;
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
+65
-67
@@ -1,10 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para Uint32
|
#include <SDL3/SDL.h> // Para Uint32
|
||||||
#include <memory> // Para unique_ptr, shared_ptr
|
|
||||||
|
#include <memory> // Para unique_ptr, shared_ptr
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "section.h" // Para Options
|
#include "section.h" // Para Options
|
||||||
|
|
||||||
class DefineButtons;
|
class DefineButtons;
|
||||||
class Fade;
|
class Fade;
|
||||||
@@ -21,78 +22,75 @@ constexpr const char TEXT_COPYRIGHT[] = "@2020,2025 JailDesigner";
|
|||||||
constexpr bool ALLOW_TITLE_ANIMATION_SKIP = false;
|
constexpr bool ALLOW_TITLE_ANIMATION_SKIP = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Clase que gestiona el estado de título/menú principal del juego.
|
Clase que gestiona el estado de título/menú principal del juego.
|
||||||
Responsable de mostrar el logo, el fondo animado y gestionar la entrada para comenzar la partida.
|
Responsable de mostrar el logo, el fondo animado y gestionar la entrada para comenzar la partida.
|
||||||
No permite saltar la animación del título salvo que se cambie el define.
|
No permite saltar la animación del título salvo que se cambie el define.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Clase Title
|
// Clase Title
|
||||||
class Title
|
class Title {
|
||||||
{
|
public:
|
||||||
public:
|
// --- Constructores y destructor ---
|
||||||
// --- Constructores y destructor ---
|
Title();
|
||||||
Title();
|
~Title();
|
||||||
~Title();
|
|
||||||
|
|
||||||
// --- Método principal ---
|
// --- Método principal ---
|
||||||
void run(); // Bucle para el título del juego
|
void run(); // Bucle para el título del juego
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Enumeraciones ---
|
// --- Enumeraciones ---
|
||||||
enum class TitleState
|
enum class TitleState {
|
||||||
{
|
LOGO_ANIMATING, // El logo está animándose
|
||||||
LOGO_ANIMATING, // El logo está animándose
|
LOGO_FINISHED, // El logo ha terminado de animarse
|
||||||
LOGO_FINISHED, // El logo ha terminado de animarse
|
START_HAS_BEEN_PRESSED, // Se ha pulsado el botón de start
|
||||||
START_HAS_BEEN_PRESSED, // Se ha pulsado el botón de start
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// --- Estructura para definir anclas ---
|
// --- Estructura para definir anclas ---
|
||||||
struct Anchor
|
struct Anchor {
|
||||||
{
|
int mini_logo;
|
||||||
int mini_logo;
|
int copyright_text;
|
||||||
int copyright_text;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
std::shared_ptr<Text> text_; // Objeto de texto para escribir en pantalla
|
std::shared_ptr<Text> text_; // Objeto de texto para escribir en pantalla
|
||||||
std::unique_ptr<Fade> fade_; // Fundido en pantalla
|
std::unique_ptr<Fade> fade_; // Fundido en pantalla
|
||||||
std::unique_ptr<TiledBG> tiled_bg_; // Fondo animado de tiles
|
std::unique_ptr<TiledBG> tiled_bg_; // Fondo animado de tiles
|
||||||
std::unique_ptr<GameLogo> game_logo_; // Logo del juego
|
std::unique_ptr<GameLogo> game_logo_; // Logo del juego
|
||||||
std::unique_ptr<Sprite> mini_logo_sprite_; // Logo JailGames mini
|
std::unique_ptr<Sprite> mini_logo_sprite_; // Logo JailGames mini
|
||||||
std::unique_ptr<DefineButtons> define_buttons_; // Definición de botones del joystick
|
std::unique_ptr<DefineButtons> define_buttons_; // Definición de botones del joystick
|
||||||
std::vector<std::shared_ptr<Player>> players_; // Vector de jugadores
|
std::vector<std::shared_ptr<Player>> players_; // Vector de jugadores
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
int counter_ = 0; // Temporizador para la pantalla de título
|
int counter_ = 0; // Temporizador para la pantalla de título
|
||||||
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad
|
Uint64 ticks_ = 0; // Contador de ticks para ajustar la velocidad
|
||||||
Section::Name next_section_; // Siguiente sección a cargar
|
Section::Name next_section_; // Siguiente sección a cargar
|
||||||
Section::Options selection_ = Section::Options::TITLE_TIME_OUT; // Opción elegida en el título
|
Section::Options selection_ = Section::Options::TITLE_TIME_OUT; // Opción elegida en el título
|
||||||
int num_controllers_; // Número de mandos conectados
|
int num_controllers_; // Número de mandos conectados
|
||||||
TitleState state_; // Estado actual de la sección
|
TitleState state_; // Estado actual de la sección
|
||||||
bool should_render_start_prompt = false; // Indica si se muestra o no el texto de PRESS START BUTTON TO PLAY
|
bool should_render_start_prompt = false; // Indica si se muestra o no el texto de PRESS START BUTTON TO PLAY
|
||||||
bool player1_start_pressed_ = false; // Indica si se ha pulsdo el boton de empezar a jugar para el jugador 1
|
bool player1_start_pressed_ = false; // Indica si se ha pulsdo el boton de empezar a jugar para el jugador 1
|
||||||
bool player2_start_pressed_ = false; // Indica si se ha pulsdo el boton de empezar a jugar para el jugador 2
|
bool player2_start_pressed_ = false; // Indica si se ha pulsdo el boton de empezar a jugar para el jugador 2
|
||||||
|
|
||||||
// -- Variables de diseño ---
|
// -- Variables de diseño ---
|
||||||
Anchor anchor_; // Anclas para definir la posición de los elementos del titulo
|
Anchor anchor_; // Anclas para definir la posición de los elementos del titulo
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void update(); // Actualiza las variables del objeto
|
void update(); // Actualiza las variables del objeto
|
||||||
void render(); // Dibuja el objeto en pantalla
|
void render(); // Dibuja el objeto en pantalla
|
||||||
void checkEvents(); // Comprueba los eventos
|
void checkEvents(); // Comprueba los eventos
|
||||||
void checkInput(); // Comprueba las entradas
|
void checkInput(); // Comprueba las entradas
|
||||||
void resetCounter(); // Reinicia el contador interno
|
void resetCounter(); // Reinicia el contador interno
|
||||||
void swapControllers(); // Intercambia la asignación de mandos a los jugadores
|
void swapControllers(); // Intercambia la asignación de mandos a los jugadores
|
||||||
void swapKeyboard(); // Intercambia el teclado de jugador
|
void swapKeyboard(); // Intercambia el teclado de jugador
|
||||||
void showControllers(); // Muestra información sobre los controles y los jugadores
|
void showControllers(); // Muestra información sobre los controles y los jugadores
|
||||||
void updateFade(); // Actualiza el efecto de fundido (fade in/out)
|
void updateFade(); // Actualiza el efecto de fundido (fade in/out)
|
||||||
void updateState(); // Actualiza el estado actual del título
|
void updateState(); // Actualiza el estado actual del título
|
||||||
void updateStartPrompt(); // Actualiza el mensaje de "Pulsa Start"
|
void updateStartPrompt(); // Actualiza el mensaje de "Pulsa Start"
|
||||||
void renderStartPrompt(); // Dibuja el mensaje de "Pulsa Start" en pantalla
|
void renderStartPrompt(); // Dibuja el mensaje de "Pulsa Start" en pantalla
|
||||||
void renderCopyright(); // Dibuja el aviso de copyright
|
void renderCopyright(); // Dibuja el aviso de copyright
|
||||||
void setState(TitleState state); // Cambia el estado del título
|
void setState(TitleState state); // Cambia el estado del título
|
||||||
void initPlayers(); // Inicializa los jugadores
|
void initPlayers(); // Inicializa los jugadores
|
||||||
void renderPlayers(); // Renderiza los jugadores
|
void renderPlayers(); // Renderiza los jugadores
|
||||||
void updatePlayers(); // Actualza los jugadores
|
void updatePlayers(); // Actualza los jugadores
|
||||||
std::shared_ptr<Player> getPlayer(int id); // Obtiene un jugador a partir de su "id"
|
std::shared_ptr<Player> getPlayer(int id); // Obtiene un jugador a partir de su "id"
|
||||||
};
|
};
|
||||||
+66
-84
@@ -1,104 +1,86 @@
|
|||||||
#include "smart_sprite.h"
|
#include "smart_sprite.h"
|
||||||
|
|
||||||
#include "moving_sprite.h" // Para MovingSprite
|
#include "moving_sprite.h" // Para MovingSprite
|
||||||
|
|
||||||
// Actualiza la posición y comprueba si ha llegado a su destino
|
// Actualiza la posición y comprueba si ha llegado a su destino
|
||||||
void SmartSprite::update()
|
void SmartSprite::update() {
|
||||||
{
|
if (enabled_) {
|
||||||
if (enabled_)
|
MovingSprite::update();
|
||||||
{
|
checkMove();
|
||||||
MovingSprite::update();
|
checkFinished();
|
||||||
checkMove();
|
}
|
||||||
checkFinished();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja el sprite
|
// Dibuja el sprite
|
||||||
void SmartSprite::render()
|
void SmartSprite::render() {
|
||||||
{
|
if (enabled_) {
|
||||||
if (enabled_)
|
MovingSprite::render();
|
||||||
{
|
}
|
||||||
MovingSprite::render();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba el movimiento
|
// Comprueba el movimiento
|
||||||
void SmartSprite::checkMove()
|
void SmartSprite::checkMove() {
|
||||||
{
|
// Comprueba si se desplaza en el eje X hacia la derecha
|
||||||
// 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() > dest_x_) {
|
||||||
// Comprueba si ha llegado al destino
|
// Lo coloca en posición
|
||||||
if (getPosX() > dest_x_)
|
setPosX(dest_x_);
|
||||||
{
|
|
||||||
// Lo coloca en posición
|
|
||||||
setPosX(dest_x_);
|
|
||||||
|
|
||||||
// Lo detiene
|
// Lo detiene
|
||||||
setVelX(0.0f);
|
setVelX(0.0f);
|
||||||
setAccelX(0.0f);
|
setAccelX(0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Comprueba si se desplaza en el eje X hacia la izquierda
|
// 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
|
||||||
// Comprueba si ha llegado al destino
|
if (getPosX() < dest_x_) {
|
||||||
if (getPosX() < dest_x_)
|
// Lo coloca en posición
|
||||||
{
|
setPosX(dest_x_);
|
||||||
// Lo coloca en posición
|
|
||||||
setPosX(dest_x_);
|
|
||||||
|
|
||||||
// Lo detiene
|
// Lo detiene
|
||||||
setVelX(0.0f);
|
setVelX(0.0f);
|
||||||
setAccelX(0.0f);
|
setAccelX(0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba si se desplaza en el eje Y hacia abajo
|
// 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
|
||||||
// Comprueba si ha llegado al destino
|
if (getPosY() > dest_y_) {
|
||||||
if (getPosY() > dest_y_)
|
// Lo coloca en posición
|
||||||
{
|
setPosY(dest_y_);
|
||||||
// Lo coloca en posición
|
|
||||||
setPosY(dest_y_);
|
|
||||||
|
|
||||||
// Lo detiene
|
// Lo detiene
|
||||||
setVelY(0.0f);
|
setVelY(0.0f);
|
||||||
setAccelY(0.0f);
|
setAccelY(0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Comprueba si se desplaza en el eje Y hacia arriba
|
// 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
|
||||||
// Comprueba si ha llegado al destino
|
if (getPosY() < dest_y_) {
|
||||||
if (getPosY() < dest_y_)
|
// Lo coloca en posición
|
||||||
{
|
setPosY(dest_y_);
|
||||||
// Lo coloca en posición
|
|
||||||
setPosY(dest_y_);
|
|
||||||
|
|
||||||
// Lo detiene
|
// Lo detiene
|
||||||
setVelY(0.0f);
|
setVelY(0.0f);
|
||||||
setAccelY(0.0f);
|
setAccelY(0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Comprueba si ha terminado
|
// Comprueba si ha terminado
|
||||||
void SmartSprite::checkFinished()
|
void SmartSprite::checkFinished() {
|
||||||
{
|
// Comprueba si ha llegado a su destino
|
||||||
// Comprueba si ha llegado a su destino
|
on_destination_ = (getPosX() == dest_x_ && getPosY() == dest_y_);
|
||||||
on_destination_ = (getPosX() == dest_x_ && getPosY() == dest_y_);
|
|
||||||
|
|
||||||
if (on_destination_)
|
if (on_destination_) {
|
||||||
{
|
if (finished_counter_ == 0) {
|
||||||
if (finished_counter_ == 0)
|
finished_ = true;
|
||||||
{
|
} else {
|
||||||
finished_ = true;
|
--finished_counter_;
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
--finished_counter_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+32
-33
@@ -1,46 +1,45 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory> // Para shared_ptr
|
#include <memory> // Para shared_ptr
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Clase SmartSprite: Sprite animado que se mueve hacia un destino y puede deshabilitarse automáticamente
|
// Clase SmartSprite: Sprite animado que se mueve hacia un destino y puede deshabilitarse automáticamente
|
||||||
class SmartSprite : public AnimatedSprite
|
class SmartSprite : public AnimatedSprite {
|
||||||
{
|
public:
|
||||||
public:
|
// --- Constructor y destructor ---
|
||||||
// --- Constructor y destructor ---
|
explicit SmartSprite(std::shared_ptr<Texture> texture)
|
||||||
explicit SmartSprite(std::shared_ptr<Texture> texture)
|
: AnimatedSprite(texture) {}
|
||||||
: AnimatedSprite(texture) {}
|
~SmartSprite() override = default;
|
||||||
~SmartSprite() override = default;
|
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
void update() override; // Actualiza la posición y comprueba si ha llegado a su destino
|
void update() override; // Actualiza la posición y comprueba si ha llegado a su destino
|
||||||
void render() override; // Dibuja el sprite
|
void render() override; // Dibuja el sprite
|
||||||
|
|
||||||
// --- Getters ---
|
// --- Getters ---
|
||||||
int getDestX() const { return dest_x_; } // Obtiene la posición de destino en X
|
int getDestX() const { return dest_x_; } // Obtiene la posición de destino en X
|
||||||
int getDestY() const { return dest_y_; } // Obtiene la posición de destino en Y
|
int getDestY() const { return dest_y_; } // Obtiene la posición de destino en Y
|
||||||
bool isOnDestination() const { return on_destination_; } // Indica si está en el destino
|
bool isOnDestination() const { return on_destination_; } // Indica si está en el destino
|
||||||
bool hasFinished() const { return finished_; } // Indica si ya ha terminado
|
bool hasFinished() const { return finished_; } // Indica si ya ha terminado
|
||||||
|
|
||||||
// --- Setters ---
|
// --- Setters ---
|
||||||
void setFinishedCounter(int value) { finished_counter_ = value; } // Establece el contador para deshabilitarlo
|
void setFinishedCounter(int value) { finished_counter_ = value; } // Establece el contador para deshabilitarlo
|
||||||
void setDestX(int x) { dest_x_ = x; } // Establece la posición de destino en X
|
void setDestX(int x) { dest_x_ = x; } // Establece la posición de destino en X
|
||||||
void setDestY(int y) { dest_y_ = y; } // Establece la posición de destino en Y
|
void setDestY(int y) { dest_y_ = y; } // Establece la posición de destino en Y
|
||||||
void setEnabled(bool value) { enabled_ = value; } // Habilita o deshabilita el objeto
|
void setEnabled(bool value) { enabled_ = value; } // Habilita o deshabilita el objeto
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Variables internas ---
|
// --- Variables internas ---
|
||||||
bool on_destination_ = false; // Indica si está en el destino
|
bool on_destination_ = false; // Indica si está en el destino
|
||||||
int dest_x_ = 0; // Posición de destino en el eje X
|
int dest_x_ = 0; // Posición de destino en el eje X
|
||||||
int dest_y_ = 0; // Posición de destino en el eje Y
|
int dest_y_ = 0; // Posición de destino en el eje Y
|
||||||
int finished_counter_ = 0; // Contador para deshabilitarlo
|
int finished_counter_ = 0; // Contador para deshabilitarlo
|
||||||
bool finished_ = false; // Indica si ya ha terminado
|
bool finished_ = false; // Indica si ya ha terminado
|
||||||
bool enabled_ = false; // Indica si el objeto está habilitado
|
bool enabled_ = false; // Indica si el objeto está habilitado
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void checkFinished(); // Comprueba si ha terminado
|
void checkFinished(); // Comprueba si ha terminado
|
||||||
void checkMove(); // Comprueba el movimiento
|
void checkMove(); // Comprueba el movimiento
|
||||||
};
|
};
|
||||||
+21
-25
@@ -1,46 +1,42 @@
|
|||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
|
|
||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Sprite::Sprite(std::shared_ptr<Texture> texture, float x, float y, float w, float h)
|
Sprite::Sprite(std::shared_ptr<Texture> texture, float x, float y, float w, float h)
|
||||||
: texture_(texture),
|
: texture_(texture),
|
||||||
pos_((SDL_FRect){x, y, w, h}),
|
pos_((SDL_FRect){x, y, w, h}),
|
||||||
sprite_clip_((SDL_FRect){0, 0, pos_.w, pos_.h}) {}
|
sprite_clip_((SDL_FRect){0, 0, pos_.w, pos_.h}) {}
|
||||||
|
|
||||||
Sprite::Sprite(std::shared_ptr<Texture> texture, SDL_FRect rect)
|
Sprite::Sprite(std::shared_ptr<Texture> texture, SDL_FRect rect)
|
||||||
: texture_(texture),
|
: texture_(texture),
|
||||||
pos_(rect),
|
pos_(rect),
|
||||||
sprite_clip_((SDL_FRect){0, 0, pos_.w, pos_.h}) {}
|
sprite_clip_((SDL_FRect){0, 0, pos_.w, pos_.h}) {}
|
||||||
|
|
||||||
Sprite::Sprite(std::shared_ptr<Texture> texture)
|
Sprite::Sprite(std::shared_ptr<Texture> texture)
|
||||||
: texture_(texture),
|
: texture_(texture),
|
||||||
pos_(SDL_FRect{0, 0, static_cast<float>(texture_->getWidth()), static_cast<float>(texture_->getHeight())}),
|
pos_(SDL_FRect{0, 0, static_cast<float>(texture_->getWidth()), static_cast<float>(texture_->getHeight())}),
|
||||||
sprite_clip_(pos_) {}
|
sprite_clip_(pos_) {}
|
||||||
|
|
||||||
// Muestra el sprite por pantalla
|
// Muestra el sprite por pantalla
|
||||||
void Sprite::render()
|
void Sprite::render() {
|
||||||
{
|
texture_->render(pos_.x, pos_.y, &sprite_clip_, zoom_, zoom_);
|
||||||
texture_->render(pos_.x, pos_.y, &sprite_clip_, zoom_, zoom_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece la posición del objeto
|
// Establece la posición del objeto
|
||||||
void Sprite::setPosition(float x, float y)
|
void Sprite::setPosition(float x, float y) {
|
||||||
{
|
pos_.x = x;
|
||||||
pos_.x = x;
|
pos_.y = y;
|
||||||
pos_.y = y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece la posición del objeto
|
// Establece la posición del objeto
|
||||||
void Sprite::setPosition(SDL_FPoint p)
|
void Sprite::setPosition(SDL_FPoint p) {
|
||||||
{
|
pos_.x = p.x;
|
||||||
pos_.x = p.x;
|
pos_.y = p.y;
|
||||||
pos_.y = p.y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reinicia las variables a cero
|
// Reinicia las variables a cero
|
||||||
void Sprite::clear()
|
void Sprite::clear() {
|
||||||
{
|
pos_ = {0, 0, 0, 0};
|
||||||
pos_ = {0, 0, 0, 0};
|
sprite_clip_ = {0, 0, 0, 0};
|
||||||
sprite_clip_ = {0, 0, 0, 0};
|
|
||||||
}
|
}
|
||||||
+12
-12
@@ -1,14 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FRect, SDL_FPoint
|
#include <SDL3/SDL.h> // Para SDL_FRect, SDL_FPoint
|
||||||
#include <memory> // Para shared_ptr
|
|
||||||
|
#include <memory> // Para shared_ptr
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
// Clase Sprite: representa un objeto gráfico básico con posición, tamaño y textura
|
// Clase Sprite: representa un objeto gráfico básico con posición, tamaño y textura
|
||||||
class Sprite
|
class Sprite {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor ---
|
||||||
Sprite(std::shared_ptr<Texture> texture, float x, float y, float w, float h);
|
Sprite(std::shared_ptr<Texture> texture, float x, float y, float w, float h);
|
||||||
Sprite(std::shared_ptr<Texture> texture, SDL_FRect rect);
|
Sprite(std::shared_ptr<Texture> texture, SDL_FRect rect);
|
||||||
@@ -16,8 +16,8 @@ public:
|
|||||||
virtual ~Sprite() = default;
|
virtual ~Sprite() = default;
|
||||||
|
|
||||||
// --- Renderizado y control ---
|
// --- Renderizado y control ---
|
||||||
virtual void render(); // Muestra el sprite por pantalla
|
virtual void render(); // Muestra el sprite por pantalla
|
||||||
virtual void clear(); // Reinicia las variables a cero
|
virtual void clear(); // Reinicia las variables a cero
|
||||||
|
|
||||||
// --- Getters de posición y tamaño ---
|
// --- Getters de posición y tamaño ---
|
||||||
float getX() const { return pos_.x; }
|
float getX() const { return pos_.x; }
|
||||||
@@ -52,10 +52,10 @@ public:
|
|||||||
std::shared_ptr<Texture> getTexture() const { return texture_; }
|
std::shared_ptr<Texture> getTexture() const { return texture_; }
|
||||||
void setTexture(std::shared_ptr<Texture> texture) { texture_ = texture; }
|
void setTexture(std::shared_ptr<Texture> texture) { texture_ = texture; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// --- Variables internas ---
|
// --- Variables internas ---
|
||||||
std::shared_ptr<Texture> texture_; // Textura donde están todos los dibujos del sprite
|
std::shared_ptr<Texture> texture_; // Textura donde están todos los dibujos del sprite
|
||||||
SDL_FRect pos_; // Posición y tamaño donde dibujar el sprite
|
SDL_FRect pos_; // Posición y tamaño donde dibujar el sprite
|
||||||
SDL_FRect sprite_clip_; // Rectángulo de origen de la textura que se dibujará en pantalla
|
SDL_FRect sprite_clip_; // Rectángulo de origen de la textura que se dibujará en pantalla
|
||||||
double zoom_ = 1.0f; // Zoom aplicado a la textura
|
double zoom_ = 1.0f; // Zoom aplicado a la textura
|
||||||
};
|
};
|
||||||
+35
-39
@@ -1,47 +1,43 @@
|
|||||||
#include "stage.h"
|
#include "stage.h"
|
||||||
|
|
||||||
#include <algorithm> // Para min
|
#include <algorithm> // Para min
|
||||||
#include <vector> // Para vector
|
#include <vector> // Para vector
|
||||||
|
|
||||||
namespace Stage
|
namespace Stage {
|
||||||
{
|
|
||||||
|
|
||||||
std::vector<Stage> stages; // Variable con los datos de cada pantalla
|
std::vector<Stage> stages; // Variable con los datos de cada pantalla
|
||||||
int power = 0; // Poder acumulado en la fase
|
int power = 0; // Poder acumulado en la fase
|
||||||
int total_power = 0; // Poder total necesario para completar el juego
|
int total_power = 0; // Poder total necesario para completar el juego
|
||||||
int number = 0; // Fase actual
|
int number = 0; // Fase actual
|
||||||
bool power_can_be_added = true; // Habilita la recolecta de poder
|
bool power_can_be_added = true; // Habilita la recolecta de poder
|
||||||
|
|
||||||
// Devuelve una fase
|
// Devuelve una fase
|
||||||
Stage get(int index) { return stages.at(std::min(9, index)); }
|
Stage get(int index) { return stages.at(std::min(9, index)); }
|
||||||
|
|
||||||
// Inicializa las variables del namespace Stage
|
// Inicializa las variables del namespace Stage
|
||||||
void init()
|
void init() {
|
||||||
{
|
stages.clear();
|
||||||
stages.clear();
|
stages.emplace_back(Stage(200, 7 + (4 * 1), 7 + (4 * 3)));
|
||||||
stages.emplace_back(Stage(200, 7 + (4 * 1), 7 + (4 * 3)));
|
stages.emplace_back(Stage(300, 7 + (4 * 2), 7 + (4 * 4)));
|
||||||
stages.emplace_back(Stage(300, 7 + (4 * 2), 7 + (4 * 4)));
|
stages.emplace_back(Stage(600, 7 + (4 * 3), 7 + (4 * 5)));
|
||||||
stages.emplace_back(Stage(600, 7 + (4 * 3), 7 + (4 * 5)));
|
stages.emplace_back(Stage(600, 7 + (4 * 3), 7 + (4 * 5)));
|
||||||
stages.emplace_back(Stage(600, 7 + (4 * 3), 7 + (4 * 5)));
|
stages.emplace_back(Stage(600, 7 + (4 * 4), 7 + (4 * 6)));
|
||||||
stages.emplace_back(Stage(600, 7 + (4 * 4), 7 + (4 * 6)));
|
stages.emplace_back(Stage(600, 7 + (4 * 4), 7 + (4 * 6)));
|
||||||
stages.emplace_back(Stage(600, 7 + (4 * 4), 7 + (4 * 6)));
|
stages.emplace_back(Stage(650, 7 + (4 * 5), 7 + (4 * 7)));
|
||||||
stages.emplace_back(Stage(650, 7 + (4 * 5), 7 + (4 * 7)));
|
stages.emplace_back(Stage(750, 7 + (4 * 5), 7 + (4 * 7)));
|
||||||
stages.emplace_back(Stage(750, 7 + (4 * 5), 7 + (4 * 7)));
|
stages.emplace_back(Stage(850, 7 + (4 * 6), 7 + (4 * 8)));
|
||||||
stages.emplace_back(Stage(850, 7 + (4 * 6), 7 + (4 * 8)));
|
stages.emplace_back(Stage(950, 7 + (4 * 7), 7 + (4 * 10)));
|
||||||
stages.emplace_back(Stage(950, 7 + (4 * 7), 7 + (4 * 10)));
|
|
||||||
|
|
||||||
power = 0;
|
power = 0;
|
||||||
total_power = 0;
|
total_power = 0;
|
||||||
number = 0;
|
number = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Añade poder
|
||||||
|
void addPower(int amount) {
|
||||||
|
if (power_can_be_added) {
|
||||||
|
power += amount;
|
||||||
|
total_power += amount;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Añade poder
|
} // namespace Stage
|
||||||
void addPower(int amount)
|
|
||||||
{
|
|
||||||
if (power_can_be_added)
|
|
||||||
{
|
|
||||||
power += amount;
|
|
||||||
total_power += amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+21
-23
@@ -7,29 +7,27 @@
|
|||||||
Permite consultar y modificar el poder necesario, la amenaza y el estado de cada fase.
|
Permite consultar y modificar el poder necesario, la amenaza y el estado de cada fase.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Stage
|
namespace Stage {
|
||||||
{
|
// --- Estructura con los datos de una fase ---
|
||||||
// --- Estructura con los datos de una fase ---
|
struct Stage {
|
||||||
struct Stage
|
int power_to_complete; // Cantidad de poder que se necesita para completar la fase
|
||||||
{
|
int min_menace; // Umbral mínimo de amenaza de la fase
|
||||||
int power_to_complete; // Cantidad de poder que se necesita para completar la fase
|
int max_menace; // Umbral máximo de amenaza de la fase
|
||||||
int min_menace; // Umbral mínimo de amenaza de la fase
|
|
||||||
int max_menace; // Umbral máximo de amenaza de la fase
|
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Stage(int power_to_complete, int min_menace, int max_menace)
|
Stage(int power_to_complete, int min_menace, int max_menace)
|
||||||
: power_to_complete(power_to_complete), min_menace(min_menace), max_menace(max_menace) {}
|
: power_to_complete(power_to_complete), min_menace(min_menace), max_menace(max_menace) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Variables globales del estado de las fases ---
|
// --- Variables globales del estado de las fases ---
|
||||||
extern std::vector<Stage> stages; // Vector con los datos de cada pantalla
|
extern std::vector<Stage> stages; // Vector con los datos de cada pantalla
|
||||||
extern int power; // Poder acumulado en la fase actual
|
extern int power; // Poder acumulado en la fase actual
|
||||||
extern int total_power; // Poder total necesario para completar el juego
|
extern int total_power; // Poder total necesario para completar el juego
|
||||||
extern int number; // Índice de la fase actual
|
extern int number; // Índice de la fase actual
|
||||||
extern bool power_can_be_added; // Indica si se puede añadir poder a la fase
|
extern bool power_can_be_added; // Indica si se puede añadir poder a la fase
|
||||||
|
|
||||||
// --- Funciones principales ---
|
// --- Funciones principales ---
|
||||||
Stage get(int index); // Devuelve una fase por índice
|
Stage get(int index); // Devuelve una fase por índice
|
||||||
void init(); // Inicializa las variables del namespace Stage
|
void init(); // Inicializa las variables del namespace Stage
|
||||||
void addPower(int amount); // Añade poder a la fase actual
|
void addPower(int amount); // Añade poder a la fase actual
|
||||||
}
|
} // namespace Stage
|
||||||
+76
-108
@@ -1,16 +1,17 @@
|
|||||||
// IWYU pragma: no_include <bits/std_abs.h>
|
// IWYU pragma: no_include <bits/std_abs.h>
|
||||||
#include "tabe.h"
|
#include "tabe.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_FlipMode, SDL_GetTicks
|
#include <SDL3/SDL.h> // Para SDL_FlipMode, SDL_GetTicks
|
||||||
#include <stdlib.h> // Para rand, abs
|
#include <stdlib.h> // Para rand, abs
|
||||||
|
|
||||||
#include <algorithm> // Para max
|
#include <algorithm> // Para max
|
||||||
#include <cmath> // Para abs
|
#include <cmath> // Para abs
|
||||||
#include <string> // Para basic_string
|
#include <string> // Para basic_string
|
||||||
|
|
||||||
#include "audio.h" // Para Audio
|
#include "audio.h" // Para Audio
|
||||||
#include "param.h" // Para Param, ParamGame, param
|
#include "param.h" // Para Param, ParamGame, param
|
||||||
#include "resource.h" // Para Resource
|
#include "resource.h" // Para Resource
|
||||||
#include "utils.h" // Para Zone
|
#include "utils.h" // Para Zone
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Tabe::Tabe()
|
Tabe::Tabe()
|
||||||
@@ -18,33 +19,27 @@ Tabe::Tabe()
|
|||||||
timer_(TabeTimer(2.5f, 4.0f)) {}
|
timer_(TabeTimer(2.5f, 4.0f)) {}
|
||||||
|
|
||||||
// Actualiza la lógica
|
// Actualiza la lógica
|
||||||
void Tabe::update()
|
void Tabe::update() {
|
||||||
{
|
if (enabled_) {
|
||||||
if (enabled_)
|
|
||||||
{
|
|
||||||
sprite_->update();
|
sprite_->update();
|
||||||
move();
|
move();
|
||||||
updateState();
|
updateState();
|
||||||
}
|
}
|
||||||
timer_.update();
|
timer_.update();
|
||||||
if (timer_.should_spawn())
|
if (timer_.should_spawn()) {
|
||||||
{
|
|
||||||
enable();
|
enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dibuja el objeto
|
// Dibuja el objeto
|
||||||
void Tabe::render()
|
void Tabe::render() {
|
||||||
{
|
if (enabled_) {
|
||||||
if (enabled_)
|
|
||||||
{
|
|
||||||
sprite_->render();
|
sprite_->render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mueve el objeto
|
// Mueve el objeto
|
||||||
void Tabe::move()
|
void Tabe::move() {
|
||||||
{
|
|
||||||
const int x = static_cast<int>(x_);
|
const int x = static_cast<int>(x_);
|
||||||
speed_ += accel_;
|
speed_ += accel_;
|
||||||
x_ += speed_;
|
x_ += speed_;
|
||||||
@@ -53,48 +48,37 @@ void Tabe::move()
|
|||||||
// Comprueba si sale por los bordes
|
// Comprueba si sale por los bordes
|
||||||
const float min_x = param.game.game_area.rect.x - WIDTH_;
|
const float min_x = param.game.game_area.rect.x - WIDTH_;
|
||||||
const float max_x = param.game.game_area.rect.x + param.game.game_area.rect.w;
|
const float max_x = param.game.game_area.rect.x + param.game.game_area.rect.w;
|
||||||
switch (destiny_)
|
switch (destiny_) {
|
||||||
{
|
case TabeDirection::TO_THE_LEFT: {
|
||||||
case TabeDirection::TO_THE_LEFT:
|
if (x_ < min_x) {
|
||||||
{
|
disable();
|
||||||
if (x_ < min_x)
|
}
|
||||||
{
|
if (x_ > param.game.game_area.rect.x + param.game.game_area.rect.w - WIDTH_ && direction_ == TabeDirection::TO_THE_RIGHT) {
|
||||||
disable();
|
setRandomFlyPath(TabeDirection::TO_THE_LEFT, 80);
|
||||||
|
x_ = param.game.game_area.rect.x + param.game.game_area.rect.w - WIDTH_;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (x_ > param.game.game_area.rect.x + param.game.game_area.rect.w - WIDTH_ && direction_ == TabeDirection::TO_THE_RIGHT)
|
|
||||||
{
|
case TabeDirection::TO_THE_RIGHT: {
|
||||||
setRandomFlyPath(TabeDirection::TO_THE_LEFT, 80);
|
if (x_ > max_x) {
|
||||||
x_ = param.game.game_area.rect.x + param.game.game_area.rect.w - WIDTH_;
|
disable();
|
||||||
|
}
|
||||||
|
if (x_ < param.game.game_area.rect.x && direction_ == TabeDirection::TO_THE_LEFT) {
|
||||||
|
setRandomFlyPath(TabeDirection::TO_THE_RIGHT, 80);
|
||||||
|
x_ = param.game.game_area.rect.x;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TabeDirection::TO_THE_RIGHT:
|
if (fly_distance_ <= 0) {
|
||||||
{
|
if (waiting_counter_ > 0) {
|
||||||
if (x_ > max_x)
|
|
||||||
{
|
|
||||||
disable();
|
|
||||||
}
|
|
||||||
if (x_ < param.game.game_area.rect.x && direction_ == TabeDirection::TO_THE_LEFT)
|
|
||||||
{
|
|
||||||
setRandomFlyPath(TabeDirection::TO_THE_RIGHT, 80);
|
|
||||||
x_ = param.game.game_area.rect.x;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fly_distance_ <= 0)
|
|
||||||
{
|
|
||||||
if (waiting_counter_ > 0)
|
|
||||||
{
|
|
||||||
accel_ = speed_ = 0.0f;
|
accel_ = speed_ = 0.0f;
|
||||||
--waiting_counter_;
|
--waiting_counter_;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
constexpr int CHOICES = 4;
|
constexpr int CHOICES = 4;
|
||||||
const TabeDirection left[CHOICES] = {TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_RIGHT};
|
const TabeDirection left[CHOICES] = {TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_RIGHT};
|
||||||
const TabeDirection right[CHOICES] = {TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_RIGHT, TabeDirection::TO_THE_RIGHT, TabeDirection::TO_THE_RIGHT};
|
const TabeDirection right[CHOICES] = {TabeDirection::TO_THE_LEFT, TabeDirection::TO_THE_RIGHT, TabeDirection::TO_THE_RIGHT, TabeDirection::TO_THE_RIGHT};
|
||||||
@@ -107,10 +91,8 @@ void Tabe::move()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Habilita el objeto
|
// Habilita el objeto
|
||||||
void Tabe::enable()
|
void Tabe::enable() {
|
||||||
{
|
if (!enabled_) {
|
||||||
if (!enabled_)
|
|
||||||
{
|
|
||||||
enabled_ = true;
|
enabled_ = true;
|
||||||
has_bonus_ = true;
|
has_bonus_ = true;
|
||||||
hit_counter_ = 0;
|
hit_counter_ = 0;
|
||||||
@@ -130,8 +112,7 @@ void Tabe::enable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Establece un vuelo aleatorio
|
// Establece un vuelo aleatorio
|
||||||
void Tabe::setRandomFlyPath(TabeDirection direction, int lenght)
|
void Tabe::setRandomFlyPath(TabeDirection direction, int lenght) {
|
||||||
{
|
|
||||||
direction_ = direction;
|
direction_ = direction;
|
||||||
fly_distance_ = lenght;
|
fly_distance_ = lenght;
|
||||||
waiting_counter_ = 5 + rand() % 15;
|
waiting_counter_ = 5 + rand() % 15;
|
||||||
@@ -139,72 +120,61 @@ void Tabe::setRandomFlyPath(TabeDirection direction, int lenght)
|
|||||||
|
|
||||||
constexpr float SPEED = 2.0f;
|
constexpr float SPEED = 2.0f;
|
||||||
|
|
||||||
switch (direction)
|
switch (direction) {
|
||||||
{
|
case TabeDirection::TO_THE_LEFT: {
|
||||||
case TabeDirection::TO_THE_LEFT:
|
speed_ = -1.0f * SPEED;
|
||||||
{
|
accel_ = -1.0f * (1 + rand() % 10) / 30.0f;
|
||||||
speed_ = -1.0f * SPEED;
|
sprite_->setFlip(SDL_FLIP_NONE);
|
||||||
accel_ = -1.0f * (1 + rand() % 10) / 30.0f;
|
break;
|
||||||
sprite_->setFlip(SDL_FLIP_NONE);
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TabeDirection::TO_THE_RIGHT:
|
case TabeDirection::TO_THE_RIGHT: {
|
||||||
{
|
speed_ = SPEED;
|
||||||
speed_ = SPEED;
|
accel_ = (1 + rand() % 10) / 30.0f;
|
||||||
accel_ = (1 + rand() % 10) / 30.0f;
|
sprite_->setFlip(SDL_FLIP_HORIZONTAL);
|
||||||
sprite_->setFlip(SDL_FLIP_HORIZONTAL);
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el estado
|
// Establece el estado
|
||||||
void Tabe::setState(TabeState state)
|
void Tabe::setState(TabeState state) {
|
||||||
{
|
if (enabled_) {
|
||||||
if (enabled_)
|
|
||||||
{
|
|
||||||
state_ = state;
|
state_ = state;
|
||||||
|
|
||||||
switch (state)
|
switch (state) {
|
||||||
{
|
case TabeState::FLY:
|
||||||
case TabeState::FLY:
|
sprite_->setCurrentAnimation("fly");
|
||||||
sprite_->setCurrentAnimation("fly");
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
case TabeState::HIT:
|
case TabeState::HIT:
|
||||||
sprite_->setCurrentAnimation("hit");
|
sprite_->setCurrentAnimation("hit");
|
||||||
hit_counter_ = 5;
|
hit_counter_ = 5;
|
||||||
++number_of_hits_;
|
++number_of_hits_;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el estado
|
// Actualiza el estado
|
||||||
void Tabe::updateState()
|
void Tabe::updateState() {
|
||||||
{
|
if (state_ == TabeState::HIT) {
|
||||||
if (state_ == TabeState::HIT)
|
|
||||||
{
|
|
||||||
--hit_counter_;
|
--hit_counter_;
|
||||||
if (hit_counter_ == 0)
|
if (hit_counter_ == 0) {
|
||||||
{
|
|
||||||
setState(TabeState::FLY);
|
setState(TabeState::FLY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Intenta obtener el bonus
|
// Intenta obtener el bonus
|
||||||
bool Tabe::tryToGetBonus()
|
bool Tabe::tryToGetBonus() {
|
||||||
{
|
if (has_bonus_ && rand() % std::max(1, 15 - number_of_hits_) == 0) {
|
||||||
if (has_bonus_ && rand() % std::max(1, 15 - number_of_hits_) == 0)
|
|
||||||
{
|
|
||||||
has_bonus_ = false;
|
has_bonus_ = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -212,16 +182,14 @@ bool Tabe::tryToGetBonus()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el temporizador
|
// Actualiza el temporizador
|
||||||
void Tabe::updateTimer()
|
void Tabe::updateTimer() {
|
||||||
{
|
|
||||||
timer_.current_time = SDL_GetTicks();
|
timer_.current_time = SDL_GetTicks();
|
||||||
timer_.delta_time = timer_.current_time - timer_.last_time;
|
timer_.delta_time = timer_.current_time - timer_.last_time;
|
||||||
timer_.last_time = timer_.current_time;
|
timer_.last_time = timer_.current_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deshabilita el objeto
|
// Deshabilita el objeto
|
||||||
void Tabe::disable()
|
void Tabe::disable() {
|
||||||
{
|
|
||||||
enabled_ = false;
|
enabled_ = false;
|
||||||
timer_.reset();
|
timer_.reset();
|
||||||
}
|
}
|
||||||
+51
-62
@@ -1,122 +1,111 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para Uint32, SDL_GetTicks, SDL_FRect
|
#include <SDL3/SDL.h> // Para Uint32, SDL_GetTicks, SDL_FRect
|
||||||
#include <stdlib.h> // Para rand
|
#include <stdlib.h> // Para rand
|
||||||
#include <memory> // Para unique_ptr
|
|
||||||
|
|
||||||
#include "animated_sprite.h" // Para AnimatedSprite
|
#include <memory> // Para unique_ptr
|
||||||
|
|
||||||
|
#include "animated_sprite.h" // Para AnimatedSprite
|
||||||
|
|
||||||
// --- Enumeraciones para dirección y estado ---
|
// --- Enumeraciones para dirección y estado ---
|
||||||
enum class TabeDirection : int
|
enum class TabeDirection : int {
|
||||||
{
|
|
||||||
TO_THE_LEFT = 0,
|
TO_THE_LEFT = 0,
|
||||||
TO_THE_RIGHT = 1,
|
TO_THE_RIGHT = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class TabeState : int
|
enum class TabeState : int {
|
||||||
{
|
|
||||||
FLY = 0,
|
FLY = 0,
|
||||||
HIT = 1,
|
HIT = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Estructura para el temporizador del Tabe ---
|
// --- Estructura para el temporizador del Tabe ---
|
||||||
struct TabeTimer
|
struct TabeTimer {
|
||||||
{
|
Uint32 time_until_next_spawn; // Tiempo restante para la próxima aparición
|
||||||
Uint32 time_until_next_spawn; // Tiempo restante para la próxima aparición
|
Uint32 min_spawn_time; // Tiempo mínimo entre apariciones
|
||||||
Uint32 min_spawn_time; // Tiempo mínimo entre apariciones
|
Uint32 max_spawn_time; // Tiempo máximo entre apariciones
|
||||||
Uint32 max_spawn_time; // Tiempo máximo entre apariciones
|
Uint32 current_time; // Tiempo actual
|
||||||
Uint32 current_time; // Tiempo actual
|
Uint32 delta_time; // Diferencia de tiempo desde la última actualización
|
||||||
Uint32 delta_time; // Diferencia de tiempo desde la última actualización
|
Uint32 last_time; // Tiempo de la última actualización
|
||||||
Uint32 last_time; // Tiempo de la última actualización
|
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
TabeTimer(float minTime, float maxTime)
|
TabeTimer(float minTime, float maxTime)
|
||||||
: min_spawn_time(minTime * 60000), max_spawn_time(maxTime * 60000),
|
: min_spawn_time(minTime * 60000), max_spawn_time(maxTime * 60000), current_time(SDL_GetTicks()) {
|
||||||
current_time(SDL_GetTicks())
|
|
||||||
{
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restablece el temporizador con un nuevo tiempo hasta la próxima aparición
|
// Restablece el temporizador con un nuevo tiempo hasta la próxima aparición
|
||||||
void reset()
|
void reset() {
|
||||||
{
|
|
||||||
Uint32 range = max_spawn_time - min_spawn_time;
|
Uint32 range = max_spawn_time - min_spawn_time;
|
||||||
time_until_next_spawn = min_spawn_time + rand() % (range + 1);
|
time_until_next_spawn = min_spawn_time + rand() % (range + 1);
|
||||||
last_time = SDL_GetTicks();
|
last_time = SDL_GetTicks();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el temporizador, decrementando el tiempo hasta la próxima aparición
|
// Actualiza el temporizador, decrementando el tiempo hasta la próxima aparición
|
||||||
void update()
|
void update() {
|
||||||
{
|
|
||||||
current_time = SDL_GetTicks();
|
current_time = SDL_GetTicks();
|
||||||
delta_time = current_time - last_time;
|
delta_time = current_time - last_time;
|
||||||
last_time = current_time;
|
last_time = current_time;
|
||||||
|
|
||||||
if (time_until_next_spawn > delta_time)
|
if (time_until_next_spawn > delta_time) {
|
||||||
{
|
|
||||||
time_until_next_spawn -= delta_time;
|
time_until_next_spawn -= delta_time;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
time_until_next_spawn = 0;
|
time_until_next_spawn = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indica si el temporizador ha finalizado
|
// Indica si el temporizador ha finalizado
|
||||||
bool should_spawn() const
|
bool should_spawn() const {
|
||||||
{
|
|
||||||
return time_until_next_spawn == 0;
|
return time_until_next_spawn == 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Clase Tabe ---
|
// --- Clase Tabe ---
|
||||||
class Tabe
|
class Tabe {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor ---
|
||||||
Tabe();
|
Tabe();
|
||||||
~Tabe() = default;
|
~Tabe() = default;
|
||||||
|
|
||||||
// --- Métodos principales ---
|
// --- Métodos principales ---
|
||||||
void update(); // Actualiza la lógica
|
void update(); // Actualiza la lógica
|
||||||
void render(); // Dibuja el objeto
|
void render(); // Dibuja el objeto
|
||||||
void enable(); // Habilita el objeto
|
void enable(); // Habilita el objeto
|
||||||
void setState(TabeState state); // Establece el estado
|
void setState(TabeState state); // Establece el estado
|
||||||
bool tryToGetBonus(); // Intenta obtener el bonus
|
bool tryToGetBonus(); // Intenta obtener el bonus
|
||||||
|
|
||||||
// --- Getters ---
|
// --- Getters ---
|
||||||
SDL_FRect &getCollider() { return sprite_->getRect(); } // Obtiene el área de colisión
|
SDL_FRect &getCollider() { return sprite_->getRect(); } // Obtiene el área de colisión
|
||||||
bool isEnabled() const { return enabled_; } // Indica si el objeto está activo
|
bool isEnabled() const { return enabled_; } // Indica si el objeto está activo
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
static constexpr int WIDTH_ = 32;
|
static constexpr int WIDTH_ = 32;
|
||||||
static constexpr int HEIGHT_ = 32;
|
static constexpr int HEIGHT_ = 32;
|
||||||
|
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos y animaciones
|
std::unique_ptr<AnimatedSprite> sprite_; // Sprite con los gráficos y animaciones
|
||||||
|
|
||||||
// --- Variables de estado ---
|
// --- Variables de estado ---
|
||||||
float x_ = 0; // Posición X
|
float x_ = 0; // Posición X
|
||||||
float y_ = 0; // Posición Y
|
float y_ = 0; // Posición Y
|
||||||
float speed_ = 0.0f; // Velocidad de movimiento
|
float speed_ = 0.0f; // Velocidad de movimiento
|
||||||
float accel_ = 0.0f; // Aceleración
|
float accel_ = 0.0f; // Aceleración
|
||||||
int fly_distance_ = 0; // Distancia de vuelo
|
int fly_distance_ = 0; // Distancia de vuelo
|
||||||
int waiting_counter_ = 0; // Tiempo que pasa quieto
|
int waiting_counter_ = 0; // Tiempo que pasa quieto
|
||||||
bool enabled_ = false; // Indica si el objeto está activo
|
bool enabled_ = false; // Indica si el objeto está activo
|
||||||
TabeDirection direction_ = TabeDirection::TO_THE_LEFT; // Dirección actual
|
TabeDirection direction_ = TabeDirection::TO_THE_LEFT; // Dirección actual
|
||||||
TabeDirection destiny_ = TabeDirection::TO_THE_LEFT; // Destino
|
TabeDirection destiny_ = TabeDirection::TO_THE_LEFT; // Destino
|
||||||
TabeState state_ = TabeState::FLY; // Estado actual
|
TabeState state_ = TabeState::FLY; // Estado actual
|
||||||
int hit_counter_ = 0; // Contador para el estado HIT
|
int hit_counter_ = 0; // Contador para el estado HIT
|
||||||
int number_of_hits_ = 0; // Cantidad de disparos recibidos
|
int number_of_hits_ = 0; // Cantidad de disparos recibidos
|
||||||
bool has_bonus_ = true; // Indica si aún tiene el bonus para soltar
|
bool has_bonus_ = true; // Indica si aún tiene el bonus para soltar
|
||||||
TabeTimer timer_; // Temporizador para gestionar la aparición
|
TabeTimer timer_; // Temporizador para gestionar la aparición
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
void move(); // Mueve el objeto
|
void move(); // Mueve el objeto
|
||||||
void shiftSprite() { sprite_->setPos(x_, y_); } // Actualiza la posición del sprite
|
void shiftSprite() { sprite_->setPos(x_, y_); } // Actualiza la posición del sprite
|
||||||
void setRandomFlyPath(TabeDirection direction, int lenght); // Establece un vuelo aleatorio
|
void setRandomFlyPath(TabeDirection direction, int lenght); // Establece un vuelo aleatorio
|
||||||
void updateState(); // Actualiza el estado
|
void updateState(); // Actualiza el estado
|
||||||
void updateTimer(); // Actualiza el temporizador
|
void updateTimer(); // Actualiza el temporizador
|
||||||
void disable(); // Deshabilita el objeto
|
void disable(); // Deshabilita el objeto
|
||||||
};
|
};
|
||||||
+184
-216
@@ -1,290 +1,258 @@
|
|||||||
#include "text.h"
|
#include "text.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_SetRenderTarget, SDL_GetRenderTarget, Uint8
|
#include <SDL3/SDL.h> // Para SDL_SetRenderTarget, SDL_GetRenderTarget, Uint8
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
#include <fstream> // Para basic_ifstream, basic_istream, basic_ostream
|
|
||||||
#include <iostream> // Para cerr
|
#include <fstream> // Para basic_ifstream, basic_istream, basic_ostream
|
||||||
|
#include <iostream> // Para cerr
|
||||||
#include <stdexcept> // Para runtime_error
|
#include <stdexcept> // Para runtime_error
|
||||||
|
|
||||||
#include "screen.h" // Para Screen
|
#include "screen.h" // Para Screen
|
||||||
#include "sprite.h" // Para Sprite
|
#include "sprite.h" // Para Sprite
|
||||||
#include "texture.h" // Para Texture
|
#include "texture.h" // Para Texture
|
||||||
#include "utils.h" // Para Color, getFileName, printWithDots
|
#include "utils.h" // Para Color, getFileName, printWithDots
|
||||||
|
|
||||||
// Llena una estructuta TextFile desde un fichero
|
// Llena una estructuta TextFile desde un fichero
|
||||||
std::shared_ptr<TextFile> loadTextFile(const std::string &file_path)
|
std::shared_ptr<TextFile> loadTextFile(const std::string &file_path) {
|
||||||
{
|
auto tf = std::make_shared<TextFile>();
|
||||||
auto tf = std::make_shared<TextFile>();
|
|
||||||
|
|
||||||
// Inicializa a cero el vector con las coordenadas
|
// Inicializa a cero el vector con las coordenadas
|
||||||
for (int i = 0; i < 128; ++i)
|
for (int i = 0; i < 128; ++i) {
|
||||||
{
|
tf->offset[i].x = 0;
|
||||||
tf->offset[i].x = 0;
|
tf->offset[i].y = 0;
|
||||||
tf->offset[i].y = 0;
|
tf->offset[i].w = 0;
|
||||||
tf->offset[i].w = 0;
|
tf->box_width = 0;
|
||||||
tf->box_width = 0;
|
tf->box_height = 0;
|
||||||
tf->box_height = 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Abre el fichero para leer los valores
|
// Abre el fichero para leer los valores
|
||||||
std::ifstream file(file_path);
|
std::ifstream file(file_path);
|
||||||
|
|
||||||
if (file.is_open() && file.good())
|
if (file.is_open() && file.good()) {
|
||||||
{
|
std::string buffer;
|
||||||
std::string buffer;
|
|
||||||
|
|
||||||
// Lee los dos primeros valores del fichero
|
// Lee los dos primeros valores del fichero
|
||||||
std::getline(file, buffer);
|
std::getline(file, buffer);
|
||||||
std::getline(file, buffer);
|
std::getline(file, buffer);
|
||||||
tf->box_width = std::stoi(buffer);
|
tf->box_width = std::stoi(buffer);
|
||||||
|
|
||||||
std::getline(file, buffer);
|
std::getline(file, buffer);
|
||||||
std::getline(file, buffer);
|
std::getline(file, buffer);
|
||||||
tf->box_height = std::stoi(buffer);
|
tf->box_height = std::stoi(buffer);
|
||||||
|
|
||||||
// lee el resto de datos del fichero
|
// lee el resto de datos del fichero
|
||||||
auto index = 32;
|
auto index = 32;
|
||||||
auto line_read = 0;
|
auto line_read = 0;
|
||||||
while (std::getline(file, buffer))
|
while (std::getline(file, buffer)) {
|
||||||
{
|
// Almacena solo las lineas impares
|
||||||
// Almacena solo las lineas impares
|
if (line_read % 2 == 1)
|
||||||
if (line_read % 2 == 1)
|
tf->offset[index++].w = std::stoi(buffer);
|
||||||
tf->offset[index++].w = std::stoi(buffer);
|
|
||||||
|
|
||||||
// Limpia el buffer
|
// Limpia el buffer
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
line_read++;
|
line_read++;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Cierra el fichero
|
// Cierra el fichero
|
||||||
printWithDots("Text File : ", getFileName(file_path), "[ LOADED ]");
|
printWithDots("Text File : ", getFileName(file_path), "[ LOADED ]");
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// El fichero no se puede abrir
|
// El fichero no se puede abrir
|
||||||
else
|
else {
|
||||||
{
|
std::cerr << "Error: Fichero no encontrado " << getFileName(file_path) << std::endl;
|
||||||
std::cerr << "Error: Fichero no encontrado " << getFileName(file_path) << std::endl;
|
throw std::runtime_error("Fichero no encontrado: " + getFileName(file_path));
|
||||||
throw std::runtime_error("Fichero no encontrado: " + getFileName(file_path));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Establece las coordenadas para cada caracter ascii de la cadena y su ancho
|
// Establece las coordenadas para cada caracter ascii de la cadena y su ancho
|
||||||
for (int i = 32; i < 128; ++i)
|
for (int i = 32; i < 128; ++i) {
|
||||||
{
|
tf->offset[i].x = ((i - 32) % 15) * tf->box_width;
|
||||||
tf->offset[i].x = ((i - 32) % 15) * tf->box_width;
|
tf->offset[i].y = ((i - 32) / 15) * tf->box_height;
|
||||||
tf->offset[i].y = ((i - 32) / 15) * tf->box_height;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return tf;
|
return tf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Text::Text(std::shared_ptr<Texture> texture, const std::string &text_file)
|
Text::Text(std::shared_ptr<Texture> texture, const std::string &text_file) {
|
||||||
{
|
// Carga los offsets desde el fichero
|
||||||
// Carga los offsets desde el fichero
|
auto tf = loadTextFile(text_file);
|
||||||
auto tf = loadTextFile(text_file);
|
|
||||||
|
|
||||||
// Inicializa variables desde la estructura
|
// Inicializa variables desde la estructura
|
||||||
box_height_ = tf->box_height;
|
box_height_ = tf->box_height;
|
||||||
box_width_ = tf->box_width;
|
box_width_ = tf->box_width;
|
||||||
for (int i = 0; i < 128; ++i)
|
for (int i = 0; i < 128; ++i) {
|
||||||
{
|
offset_[i].x = tf->offset[i].x;
|
||||||
offset_[i].x = tf->offset[i].x;
|
offset_[i].y = tf->offset[i].y;
|
||||||
offset_[i].y = tf->offset[i].y;
|
offset_[i].w = tf->offset[i].w;
|
||||||
offset_[i].w = tf->offset[i].w;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Crea los objetos
|
// Crea los objetos
|
||||||
sprite_ = std::make_unique<Sprite>(texture, (SDL_FRect){0, 0, static_cast<float>(box_width_), static_cast<float>(box_height_)});
|
sprite_ = std::make_unique<Sprite>(texture, (SDL_FRect){0, 0, static_cast<float>(box_width_), static_cast<float>(box_height_)});
|
||||||
|
|
||||||
// Inicializa variables
|
// Inicializa variables
|
||||||
fixed_width_ = false;
|
fixed_width_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Text::Text(std::shared_ptr<Texture> texture, std::shared_ptr<TextFile> text_file)
|
Text::Text(std::shared_ptr<Texture> texture, std::shared_ptr<TextFile> text_file) {
|
||||||
{
|
// Inicializa variables desde la estructura
|
||||||
// Inicializa variables desde la estructura
|
box_height_ = text_file->box_height;
|
||||||
box_height_ = text_file->box_height;
|
box_width_ = text_file->box_width;
|
||||||
box_width_ = text_file->box_width;
|
for (int i = 0; i < 128; ++i) {
|
||||||
for (int i = 0; i < 128; ++i)
|
offset_[i].x = text_file->offset[i].x;
|
||||||
{
|
offset_[i].y = text_file->offset[i].y;
|
||||||
offset_[i].x = text_file->offset[i].x;
|
offset_[i].w = text_file->offset[i].w;
|
||||||
offset_[i].y = text_file->offset[i].y;
|
}
|
||||||
offset_[i].w = text_file->offset[i].w;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Crea los objetos
|
// Crea los objetos
|
||||||
sprite_ = std::make_unique<Sprite>(texture, (SDL_FRect){0, 0, static_cast<float>(box_width_), static_cast<float>(box_height_)});
|
sprite_ = std::make_unique<Sprite>(texture, (SDL_FRect){0, 0, static_cast<float>(box_width_), static_cast<float>(box_height_)});
|
||||||
|
|
||||||
// Inicializa variables
|
// Inicializa variables
|
||||||
fixed_width_ = false;
|
fixed_width_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escribe texto en pantalla
|
// Escribe texto en pantalla
|
||||||
void Text::write(int x, int y, const std::string &text, int kerning, int lenght)
|
void Text::write(int x, int y, const std::string &text, int kerning, int lenght) {
|
||||||
{
|
int shift = 0;
|
||||||
int shift = 0;
|
|
||||||
|
|
||||||
if (lenght == -1)
|
if (lenght == -1)
|
||||||
lenght = text.length();
|
lenght = text.length();
|
||||||
|
|
||||||
sprite_->setY(y);
|
sprite_->setY(y);
|
||||||
for (int i = 0; i < lenght; ++i)
|
for (int i = 0; i < lenght; ++i) {
|
||||||
{
|
auto index = static_cast<int>(text[i]);
|
||||||
auto index = static_cast<int>(text[i]);
|
sprite_->setSpriteClip(offset_[index].x, offset_[index].y, box_width_, box_height_);
|
||||||
sprite_->setSpriteClip(offset_[index].x, offset_[index].y, box_width_, box_height_);
|
sprite_->setX(x + shift);
|
||||||
sprite_->setX(x + shift);
|
sprite_->render();
|
||||||
sprite_->render();
|
shift += offset_[static_cast<int>(text[i])].w + kerning;
|
||||||
shift += offset_[static_cast<int>(text[i])].w + kerning;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escribe texto en pantalla
|
// Escribe texto en pantalla
|
||||||
void Text::write2X(int x, int y, const std::string &text, int kerning)
|
void Text::write2X(int x, int y, const std::string &text, int kerning) {
|
||||||
{
|
int shift = 0;
|
||||||
int shift = 0;
|
for (size_t i = 0; i < text.length(); ++i) {
|
||||||
for (size_t i = 0; i < text.length(); ++i)
|
auto index = static_cast<size_t>(text[i]);
|
||||||
{
|
SDL_FRect rect = {static_cast<float>(offset_[index].x), static_cast<float>(offset_[index].y), static_cast<float>(box_width_), static_cast<float>(box_height_)};
|
||||||
auto index = static_cast<size_t>(text[i]);
|
sprite_->getTexture()->render(x + shift, y, &rect, 2.0f, 2.0f);
|
||||||
SDL_FRect rect = {static_cast<float>(offset_[index].x), static_cast<float>(offset_[index].y), static_cast<float>(box_width_), static_cast<float>(box_height_)};
|
shift += (offset_[index].w + kerning) * 2;
|
||||||
sprite_->getTexture()->render(x + shift, y, &rect, 2.0f, 2.0f);
|
}
|
||||||
shift += (offset_[index].w + kerning) * 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escribe el texto en una textura
|
// Escribe el texto en una textura
|
||||||
std::shared_ptr<Texture> Text::writeToTexture(const std::string &text, int zoom, int kerning)
|
std::shared_ptr<Texture> Text::writeToTexture(const std::string &text, int zoom, int kerning) {
|
||||||
{
|
auto renderer = Screen::get()->getRenderer();
|
||||||
auto renderer = Screen::get()->getRenderer();
|
auto texture = std::make_shared<Texture>(renderer);
|
||||||
auto texture = std::make_shared<Texture>(renderer);
|
auto width = lenght(text, kerning) * zoom;
|
||||||
auto width = lenght(text, kerning) * zoom;
|
auto height = box_height_ * zoom;
|
||||||
auto height = box_height_ * zoom;
|
auto temp = SDL_GetRenderTarget(renderer);
|
||||||
auto temp = SDL_GetRenderTarget(renderer);
|
texture->createBlank(width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET);
|
||||||
texture->createBlank(width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET);
|
texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
||||||
texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
texture->setAsRenderTarget(renderer);
|
||||||
texture->setAsRenderTarget(renderer);
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
SDL_RenderClear(renderer);
|
||||||
SDL_RenderClear(renderer);
|
zoom == 1 ? write(0, 0, text, kerning) : write2X(0, 0, text, kerning);
|
||||||
zoom == 1 ? write(0, 0, text, kerning) : write2X(0, 0, text, kerning);
|
SDL_SetRenderTarget(renderer, temp);
|
||||||
SDL_SetRenderTarget(renderer, temp);
|
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escribe el texto con extras en una textura
|
// Escribe el texto con extras en una textura
|
||||||
std::shared_ptr<Texture> Text::writeDXToTexture(Uint8 flags, const std::string &text, int kerning, Color textColor, Uint8 shadow_distance, Color shadow_color, int lenght)
|
std::shared_ptr<Texture> Text::writeDXToTexture(Uint8 flags, const std::string &text, int kerning, Color textColor, Uint8 shadow_distance, Color shadow_color, int lenght) {
|
||||||
{
|
auto renderer = Screen::get()->getRenderer();
|
||||||
auto renderer = Screen::get()->getRenderer();
|
auto texture = std::make_shared<Texture>(renderer);
|
||||||
auto texture = std::make_shared<Texture>(renderer);
|
auto width = Text::lenght(text, kerning) + shadow_distance;
|
||||||
auto width = Text::lenght(text, kerning) + shadow_distance;
|
auto height = box_height_ + shadow_distance;
|
||||||
auto height = box_height_ + shadow_distance;
|
auto temp = SDL_GetRenderTarget(renderer);
|
||||||
auto temp = SDL_GetRenderTarget(renderer);
|
texture->createBlank(width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET);
|
||||||
texture->createBlank(width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET);
|
texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
||||||
texture->setBlendMode(SDL_BLENDMODE_BLEND);
|
texture->setAsRenderTarget(renderer);
|
||||||
texture->setAsRenderTarget(renderer);
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
||||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
SDL_RenderClear(renderer);
|
||||||
SDL_RenderClear(renderer);
|
writeDX(flags, 0, 0, text, kerning, textColor, shadow_distance, shadow_color, lenght);
|
||||||
writeDX(flags, 0, 0, text, kerning, textColor, shadow_distance, shadow_color, lenght);
|
SDL_SetRenderTarget(renderer, temp);
|
||||||
SDL_SetRenderTarget(renderer, temp);
|
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escribe el texto con colores
|
// Escribe el texto con colores
|
||||||
void Text::writeColored(int x, int y, const std::string &text, Color color, int kerning, int lenght)
|
void Text::writeColored(int x, int y, const std::string &text, Color color, int kerning, int lenght) {
|
||||||
{
|
sprite_->getTexture()->setColor(color.r, color.g, color.b);
|
||||||
sprite_->getTexture()->setColor(color.r, color.g, color.b);
|
write(x, y, text, kerning, lenght);
|
||||||
write(x, y, text, kerning, lenght);
|
sprite_->getTexture()->setColor(255, 255, 255);
|
||||||
sprite_->getTexture()->setColor(255, 255, 255);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escribe el texto con sombra
|
// Escribe el texto con sombra
|
||||||
void Text::writeShadowed(int x, int y, const std::string &text, Color color, Uint8 shadow_distance, int kerning, int lenght)
|
void Text::writeShadowed(int x, int y, const std::string &text, Color color, Uint8 shadow_distance, int kerning, int lenght) {
|
||||||
{
|
sprite_->getTexture()->setColor(color.r, color.g, color.b);
|
||||||
sprite_->getTexture()->setColor(color.r, color.g, color.b);
|
write(x + shadow_distance, y + shadow_distance, text, kerning, lenght);
|
||||||
write(x + shadow_distance, y + shadow_distance, text, kerning, lenght);
|
sprite_->getTexture()->setColor(255, 255, 255);
|
||||||
sprite_->getTexture()->setColor(255, 255, 255);
|
write(x, y, text, kerning, lenght);
|
||||||
write(x, y, text, kerning, lenght);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escribe el texto centrado en un punto x
|
// Escribe el texto centrado en un punto x
|
||||||
void Text::writeCentered(int x, int y, const std::string &text, int kerning, int lenght)
|
void Text::writeCentered(int x, int y, const std::string &text, int kerning, int lenght) {
|
||||||
{
|
x -= (Text::lenght(text, kerning) / 2);
|
||||||
x -= (Text::lenght(text, kerning) / 2);
|
write(x, y, text, kerning, lenght);
|
||||||
write(x, y, text, kerning, lenght);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Escribe texto con extras
|
// Escribe texto con extras
|
||||||
void Text::writeDX(Uint8 flags, int x, int y, const std::string &text, int kerning, Color textColor, Uint8 shadow_distance, Color shadow_color, int lenght)
|
void Text::writeDX(Uint8 flags, int x, int y, const std::string &text, int kerning, Color textColor, Uint8 shadow_distance, Color shadow_color, int lenght) {
|
||||||
{
|
const auto centered = ((flags & TEXT_CENTER) == TEXT_CENTER);
|
||||||
const auto centered = ((flags & TEXT_CENTER) == TEXT_CENTER);
|
const auto shadowed = ((flags & TEXT_SHADOW) == TEXT_SHADOW);
|
||||||
const auto shadowed = ((flags & TEXT_SHADOW) == TEXT_SHADOW);
|
const auto colored = ((flags & TEXT_COLOR) == TEXT_COLOR);
|
||||||
const auto colored = ((flags & TEXT_COLOR) == TEXT_COLOR);
|
const auto stroked = ((flags & TEXT_STROKE) == TEXT_STROKE);
|
||||||
const auto stroked = ((flags & TEXT_STROKE) == TEXT_STROKE);
|
|
||||||
|
|
||||||
if (centered)
|
if (centered) {
|
||||||
{
|
x -= (Text::lenght(text, kerning) / 2);
|
||||||
x -= (Text::lenght(text, kerning) / 2);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (shadowed)
|
if (shadowed) {
|
||||||
{
|
writeColored(x + shadow_distance, y + shadow_distance, text, shadow_color, kerning, lenght);
|
||||||
writeColored(x + shadow_distance, y + shadow_distance, text, shadow_color, kerning, lenght);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (stroked)
|
if (stroked) {
|
||||||
{
|
for (int dist = 1; dist <= shadow_distance; ++dist) {
|
||||||
for (int dist = 1; dist <= shadow_distance; ++dist)
|
for (int dy = -dist; dy <= dist; ++dy) {
|
||||||
{
|
for (int dx = -dist; dx <= dist; ++dx) {
|
||||||
for (int dy = -dist; dy <= dist; ++dy)
|
writeColored(x + dx, y + dy, text, shadow_color, kerning, lenght);
|
||||||
{
|
}
|
||||||
for (int dx = -dist; dx <= dist; ++dx)
|
}
|
||||||
{
|
}
|
||||||
writeColored(x + dx, y + dy, text, shadow_color, kerning, lenght);
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colored)
|
if (colored) {
|
||||||
{
|
writeColored(x, y, text, textColor, kerning, lenght);
|
||||||
writeColored(x, y, text, textColor, kerning, lenght);
|
} else {
|
||||||
}
|
write(x, y, text, kerning, lenght);
|
||||||
else
|
}
|
||||||
{
|
|
||||||
write(x, y, text, kerning, lenght);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene la longitud en pixels de una cadena
|
// Obtiene la longitud en pixels de una cadena
|
||||||
int Text::lenght(const std::string &text, int kerning) const
|
int Text::lenght(const std::string &text, int kerning) const {
|
||||||
{
|
int shift = 0;
|
||||||
int shift = 0;
|
for (size_t i = 0; i < text.length(); ++i)
|
||||||
for (size_t i = 0; i < text.length(); ++i)
|
shift += (offset_[static_cast<int>(text[i])].w + kerning);
|
||||||
shift += (offset_[static_cast<int>(text[i])].w + kerning);
|
|
||||||
|
|
||||||
// Descuenta el kerning del último caracter
|
// Descuenta el kerning del último caracter
|
||||||
return shift - kerning;
|
return shift - kerning;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Devuelve el valor de la variable
|
// Devuelve el valor de la variable
|
||||||
int Text::getCharacterSize() const
|
int Text::getCharacterSize() const {
|
||||||
{
|
return box_width_;
|
||||||
return box_width_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece si se usa un tamaño fijo de letra
|
// Establece si se usa un tamaño fijo de letra
|
||||||
void Text::setFixedWidth(bool value)
|
void Text::setFixedWidth(bool value) {
|
||||||
{
|
fixed_width_ = value;
|
||||||
fixed_width_ = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece una paleta
|
// Establece una paleta
|
||||||
void Text::setPalette(int number)
|
void Text::setPalette(int number) {
|
||||||
{
|
auto temp = SDL_GetRenderTarget(Screen::get()->getRenderer());
|
||||||
auto temp = SDL_GetRenderTarget(Screen::get()->getRenderer());
|
SDL_SetRenderTarget(Screen::get()->getRenderer(), nullptr);
|
||||||
SDL_SetRenderTarget(Screen::get()->getRenderer(), nullptr);
|
sprite_->getTexture()->setPalette(number);
|
||||||
sprite_->getTexture()->setPalette(number);
|
SDL_SetRenderTarget(Screen::get()->getRenderer(), temp);
|
||||||
SDL_SetRenderTarget(Screen::get()->getRenderer(), temp);
|
|
||||||
}
|
}
|
||||||
+43
-45
@@ -1,11 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para Uint8
|
#include <SDL3/SDL.h> // Para Uint8
|
||||||
#include <memory> // Para unique_ptr, shared_ptr
|
|
||||||
#include <string> // Para string
|
|
||||||
|
|
||||||
#include "sprite.h" // Para Sprite
|
#include <memory> // Para unique_ptr, shared_ptr
|
||||||
#include "utils.h" // Para Color
|
#include <string> // Para string
|
||||||
|
|
||||||
|
#include "sprite.h" // Para Sprite
|
||||||
|
#include "utils.h" // Para Color
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
|
||||||
@@ -16,59 +17,56 @@ constexpr int TEXT_CENTER = 4;
|
|||||||
constexpr int TEXT_STROKE = 8;
|
constexpr int TEXT_STROKE = 8;
|
||||||
|
|
||||||
// --- Estructuras auxiliares ---
|
// --- Estructuras auxiliares ---
|
||||||
struct TextOffset
|
struct TextOffset {
|
||||||
{
|
int x, y, w;
|
||||||
int x, y, w;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TextFile
|
struct TextFile {
|
||||||
{
|
int box_width; // Anchura de la caja de cada caracter en el png
|
||||||
int box_width; // Anchura de la caja de cada caracter en el png
|
int box_height; // Altura de la caja de cada caracter en el png
|
||||||
int box_height; // Altura de la caja de cada caracter en el png
|
TextOffset offset[128]; // Vector con las posiciones y ancho de cada letra
|
||||||
TextOffset offset[128]; // Vector con las posiciones y ancho de cada letra
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Llena una estructura TextFile desde un fichero
|
// Llena una estructura TextFile desde un fichero
|
||||||
std::shared_ptr<TextFile> loadTextFile(const std::string &file_path);
|
std::shared_ptr<TextFile> loadTextFile(const std::string &file_path);
|
||||||
|
|
||||||
// --- Clase Text: pinta texto en pantalla a partir de un bitmap ---
|
// --- Clase Text: pinta texto en pantalla a partir de un bitmap ---
|
||||||
class Text
|
class Text {
|
||||||
{
|
public:
|
||||||
public:
|
// --- Constructores y destructor ---
|
||||||
// --- Constructores y destructor ---
|
Text(std::shared_ptr<Texture> texture, const std::string &text_file);
|
||||||
Text(std::shared_ptr<Texture> texture, const std::string &text_file);
|
Text(std::shared_ptr<Texture> texture, std::shared_ptr<TextFile> text_file);
|
||||||
Text(std::shared_ptr<Texture> texture, std::shared_ptr<TextFile> text_file);
|
~Text() = default;
|
||||||
~Text() = default;
|
|
||||||
|
|
||||||
// --- Métodos de escritura en pantalla ---
|
// --- Métodos de escritura en pantalla ---
|
||||||
void write(int x, int y, const std::string &text, int kerning = 1, int lenght = -1); // Escribe el texto en pantalla
|
void write(int x, int y, const std::string &text, int kerning = 1, int lenght = -1); // Escribe el texto en pantalla
|
||||||
void write2X(int x, int y, const std::string &text, int kerning = 1); // Escribe el texto al doble de tamaño
|
void write2X(int x, int y, const std::string &text, int kerning = 1); // Escribe el texto al doble de tamaño
|
||||||
|
|
||||||
// --- Escritura en textura ---
|
// --- Escritura en textura ---
|
||||||
std::shared_ptr<Texture> writeToTexture(const std::string &text, int zoom = 1, int kerning = 1); // Escribe el texto en una textura
|
std::shared_ptr<Texture> writeToTexture(const std::string &text, int zoom = 1, int kerning = 1); // Escribe el texto en una textura
|
||||||
std::shared_ptr<Texture> writeDXToTexture(Uint8 flags, const std::string &text, int kerning = 1, Color textColor = Color(), Uint8 shadow_distance = 1, Color shadow_color = Color(), int lenght = -1); // Escribe el texto con extras en una textura
|
std::shared_ptr<Texture> writeDXToTexture(Uint8 flags, const std::string &text, int kerning = 1, Color textColor = Color(), Uint8 shadow_distance = 1, Color shadow_color = Color(), int lenght = -1); // Escribe el texto con extras en una textura
|
||||||
|
|
||||||
// --- Métodos de escritura avanzada ---
|
// --- Métodos de escritura avanzada ---
|
||||||
void writeColored(int x, int y, const std::string &text, Color color, int kerning = 1, int lenght = -1); // Escribe el texto con colores
|
void writeColored(int x, int y, const std::string &text, Color color, int kerning = 1, int lenght = -1); // Escribe el texto con colores
|
||||||
void writeShadowed(int x, int y, const std::string &text, Color color, Uint8 shadow_distance = 1, int kerning = 1, int lenght = -1); // Escribe el texto con sombra
|
void writeShadowed(int x, int y, const std::string &text, Color color, Uint8 shadow_distance = 1, int kerning = 1, int lenght = -1); // Escribe el texto con sombra
|
||||||
void writeCentered(int x, int y, const std::string &text, int kerning = 1, int lenght = -1); // Escribe el texto centrado en un punto x
|
void writeCentered(int x, int y, const std::string &text, int kerning = 1, int lenght = -1); // Escribe el texto centrado en un punto x
|
||||||
void writeDX(Uint8 flags, int x, int y, const std::string &text, int kerning = 1, Color textColor = Color(), Uint8 shadow_distance = 1, Color shadow_color = Color(), int lenght = -1); // Escribe texto con extras
|
void writeDX(Uint8 flags, int x, int y, const std::string &text, int kerning = 1, Color textColor = Color(), Uint8 shadow_distance = 1, Color shadow_color = Color(), int lenght = -1); // Escribe texto con extras
|
||||||
|
|
||||||
// --- Utilidades ---
|
// --- Utilidades ---
|
||||||
int lenght(const std::string &text, int kerning = 1) const; // Obtiene la longitud en pixels de una cadena
|
int lenght(const std::string &text, int kerning = 1) const; // Obtiene la longitud en pixels de una cadena
|
||||||
int getCharacterSize() const; // Devuelve el tamaño de caracter actual
|
int getCharacterSize() const; // Devuelve el tamaño de caracter actual
|
||||||
|
|
||||||
// --- Configuración ---
|
// --- Configuración ---
|
||||||
void setFixedWidth(bool value); // Establece si se usa un tamaño fijo de letra
|
void setFixedWidth(bool value); // Establece si se usa un tamaño fijo de letra
|
||||||
void setPalette(int number); // Establece una paleta
|
void setPalette(int number); // Establece una paleta
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
std::unique_ptr<Sprite> sprite_ = nullptr; // Objeto con los gráficos para el texto
|
std::unique_ptr<Sprite> sprite_ = nullptr; // Objeto con los gráficos para el texto
|
||||||
|
|
||||||
// --- Variables ---
|
// --- Variables ---
|
||||||
int box_width_ = 0; // Anchura de la caja de cada caracter en el png
|
int box_width_ = 0; // Anchura de la caja de cada caracter en el png
|
||||||
int box_height_ = 0; // Altura de la caja de cada caracter en el png
|
int box_height_ = 0; // Altura de la caja de cada caracter en el png
|
||||||
bool fixed_width_ = false; // Indica si el texto se ha de escribir con longitud fija en todas las letras
|
bool fixed_width_ = false; // Indica si el texto se ha de escribir con longitud fija en todas las letras
|
||||||
TextOffset offset_[128] = {}; // Vector con las posiciones y ancho de cada letra
|
TextOffset offset_[128] = {}; // Vector con las posiciones y ancho de cada letra
|
||||||
};
|
};
|
||||||
+265
-322
@@ -1,438 +1,381 @@
|
|||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_LogError, SDL_LogCategory, Uint8, SDL_...
|
#include <SDL3/SDL.h> // Para SDL_LogError, SDL_LogCategory, Uint8, SDL_...
|
||||||
#include <stdint.h> // Para uint32_t
|
#include <stdint.h> // Para uint32_t
|
||||||
#include <cstring> // Para memcpy
|
|
||||||
#include <fstream> // Para basic_ifstream, basic_istream, basic_ios
|
|
||||||
#include <sstream> // Para basic_istringstream
|
|
||||||
#include <stdexcept> // Para runtime_error
|
|
||||||
#include <string> // Para basic_string, char_traits, operator+, string
|
|
||||||
#include <vector> // Para vector
|
|
||||||
|
|
||||||
#include "external/gif.h" // Para Gif
|
#include <cstring> // Para memcpy
|
||||||
#include "stb_image.h" // Para stbi_image_free, stbi_load, STBI_rgb_alpha
|
#include <fstream> // Para basic_ifstream, basic_istream, basic_ios
|
||||||
#include "utils.h" // Para getFileName, Color, printWithDots
|
#include <sstream> // Para basic_istringstream
|
||||||
|
#include <stdexcept> // Para runtime_error
|
||||||
|
#include <string> // Para basic_string, char_traits, operator+, string
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
|
#include "external/gif.h" // Para Gif
|
||||||
|
#include "stb_image.h" // Para stbi_image_free, stbi_load, STBI_rgb_alpha
|
||||||
|
#include "utils.h" // Para getFileName, Color, printWithDots
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Texture::Texture(SDL_Renderer *renderer, const std::string &path)
|
Texture::Texture(SDL_Renderer *renderer, const std::string &path)
|
||||||
: renderer_(renderer),
|
: renderer_(renderer),
|
||||||
path_(path)
|
path_(path) {
|
||||||
{
|
// Carga el fichero en la textura
|
||||||
// Carga el fichero en la textura
|
if (!path_.empty()) {
|
||||||
if (!path_.empty())
|
// Obtiene la extensión
|
||||||
{
|
const std::string extension = path_.substr(path_.find_last_of(".") + 1);
|
||||||
// Obtiene la extensión
|
|
||||||
const std::string extension = path_.substr(path_.find_last_of(".") + 1);
|
|
||||||
|
|
||||||
// .png
|
// .png
|
||||||
if (extension == "png")
|
if (extension == "png") {
|
||||||
{
|
loadFromFile(path_);
|
||||||
loadFromFile(path_);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// .gif
|
// .gif
|
||||||
else if (extension == "gif")
|
else if (extension == "gif") {
|
||||||
{
|
// Crea la surface desde un fichero
|
||||||
// Crea la surface desde un fichero
|
surface_ = loadSurface(path_);
|
||||||
surface_ = loadSurface(path_);
|
|
||||||
|
|
||||||
// Añade la propia paleta del fichero a la lista
|
// Añade la propia paleta del fichero a la lista
|
||||||
addPaletteFromGifFile(path_);
|
addPaletteFromGifFile(path_);
|
||||||
|
|
||||||
// Crea la textura, establece el BlendMode y copia la surface a la textura
|
// Crea la textura, establece el BlendMode y copia la surface a la textura
|
||||||
createBlank(width_, height_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING);
|
createBlank(width_, height_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING);
|
||||||
SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);
|
SDL_SetTextureBlendMode(texture_, SDL_BLENDMODE_BLEND);
|
||||||
flipSurface();
|
flipSurface();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
Texture::~Texture()
|
Texture::~Texture() {
|
||||||
{
|
unloadTexture();
|
||||||
unloadTexture();
|
unloadSurface();
|
||||||
unloadSurface();
|
palettes_.clear();
|
||||||
palettes_.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carga una imagen desde un fichero
|
// Carga una imagen desde un fichero
|
||||||
bool Texture::loadFromFile(const std::string &file_path)
|
bool Texture::loadFromFile(const std::string &file_path) {
|
||||||
{
|
if (file_path.empty())
|
||||||
if (file_path.empty())
|
return false;
|
||||||
return false;
|
|
||||||
|
|
||||||
int req_format = STBI_rgb_alpha;
|
int req_format = STBI_rgb_alpha;
|
||||||
int width, height, orig_format;
|
int width, height, orig_format;
|
||||||
unsigned char *data = stbi_load(file_path.c_str(), &width, &height, &orig_format, req_format);
|
unsigned char *data = stbi_load(file_path.c_str(), &width, &height, &orig_format, req_format);
|
||||||
if (!data)
|
if (!data) {
|
||||||
{
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Fichero no encontrado %s", getFileName(file_path).c_str());
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Fichero no encontrado %s", getFileName(file_path).c_str());
|
throw std::runtime_error("Fichero no encontrado: " + getFileName(file_path));
|
||||||
throw std::runtime_error("Fichero no encontrado: " + getFileName(file_path));
|
} else {
|
||||||
}
|
printWithDots("Texture : ", getFileName(file_path), "[ LOADED ]");
|
||||||
else
|
}
|
||||||
{
|
|
||||||
printWithDots("Texture : ", getFileName(file_path), "[ LOADED ]");
|
|
||||||
}
|
|
||||||
|
|
||||||
int pitch;
|
int pitch;
|
||||||
SDL_PixelFormat pixel_format;
|
SDL_PixelFormat pixel_format;
|
||||||
|
|
||||||
// STBI_rgb_alpha (RGBA)
|
// STBI_rgb_alpha (RGBA)
|
||||||
pitch = 4 * width;
|
pitch = 4 * width;
|
||||||
pixel_format = SDL_PIXELFORMAT_RGBA32;
|
pixel_format = SDL_PIXELFORMAT_RGBA32;
|
||||||
|
|
||||||
// Limpia
|
// Limpia
|
||||||
unloadTexture();
|
unloadTexture();
|
||||||
|
|
||||||
// La textura final
|
// La textura final
|
||||||
SDL_Texture *new_texture = nullptr;
|
SDL_Texture *new_texture = nullptr;
|
||||||
|
|
||||||
// Carga la imagen desde una ruta específica
|
// Carga la imagen desde una ruta específica
|
||||||
auto loaded_surface = SDL_CreateSurfaceFrom(width, height, pixel_format, static_cast<void *>(data), pitch);
|
auto loaded_surface = SDL_CreateSurfaceFrom(width, height, pixel_format, static_cast<void *>(data), pitch);
|
||||||
if (loaded_surface == nullptr)
|
if (loaded_surface == nullptr) {
|
||||||
{
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to load image %s", file_path.c_str());
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to load image %s", file_path.c_str());
|
} else {
|
||||||
}
|
// Crea la textura desde los pixels de la surface
|
||||||
else
|
new_texture = SDL_CreateTextureFromSurface(renderer_, loaded_surface);
|
||||||
{
|
if (new_texture == nullptr) {
|
||||||
// Crea la textura desde los pixels de la surface
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create texture from %s! SDL Error: %s", file_path.c_str(), SDL_GetError());
|
||||||
new_texture = SDL_CreateTextureFromSurface(renderer_, loaded_surface);
|
} else {
|
||||||
if (new_texture == nullptr)
|
// Obtiene las dimensiones de la imagen
|
||||||
{
|
width_ = loaded_surface->w;
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create texture from %s! SDL Error: %s", file_path.c_str(), SDL_GetError());
|
height_ = loaded_surface->h;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Obtiene las dimensiones de la imagen
|
|
||||||
width_ = loaded_surface->w;
|
|
||||||
height_ = loaded_surface->h;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Elimina la textura cargada
|
// Elimina la textura cargada
|
||||||
SDL_DestroySurface(loaded_surface);
|
SDL_DestroySurface(loaded_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return success
|
// Return success
|
||||||
stbi_image_free(data);
|
stbi_image_free(data);
|
||||||
texture_ = new_texture;
|
texture_ = new_texture;
|
||||||
return texture_ != nullptr;
|
return texture_ != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea una textura en blanco
|
// Crea una textura en blanco
|
||||||
bool Texture::createBlank(int width, int height, SDL_PixelFormat format, SDL_TextureAccess access)
|
bool Texture::createBlank(int width, int height, SDL_PixelFormat format, SDL_TextureAccess access) {
|
||||||
{
|
// Crea una textura sin inicializar
|
||||||
// Crea una textura sin inicializar
|
texture_ = SDL_CreateTexture(renderer_, format, access, width, height);
|
||||||
texture_ = SDL_CreateTexture(renderer_, format, access, width, height);
|
if (!texture_) {
|
||||||
if (!texture_)
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create blank texture! SDL Error: %s", SDL_GetError());
|
||||||
{
|
} else {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create blank texture! SDL Error: %s", SDL_GetError());
|
width_ = width;
|
||||||
}
|
height_ = height;
|
||||||
else
|
}
|
||||||
{
|
|
||||||
width_ = width;
|
|
||||||
height_ = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
return texture_ != nullptr;
|
return texture_ != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Libera la memoria de la textura
|
// Libera la memoria de la textura
|
||||||
void Texture::unloadTexture()
|
void Texture::unloadTexture() {
|
||||||
{
|
// Libera la textura
|
||||||
// Libera la textura
|
if (texture_) {
|
||||||
if (texture_)
|
SDL_DestroyTexture(texture_);
|
||||||
{
|
texture_ = nullptr;
|
||||||
SDL_DestroyTexture(texture_);
|
width_ = 0;
|
||||||
texture_ = nullptr;
|
height_ = 0;
|
||||||
width_ = 0;
|
}
|
||||||
height_ = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el color para la modulacion
|
// 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);
|
||||||
SDL_SetTextureColorMod(texture_, red, green, blue);
|
|
||||||
}
|
}
|
||||||
void Texture::setColor(Color color)
|
void Texture::setColor(Color color) {
|
||||||
{
|
SDL_SetTextureColorMod(texture_, color.r, color.g, color.b);
|
||||||
SDL_SetTextureColorMod(texture_, color.r, color.g, color.b);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el blending
|
// Establece el blending
|
||||||
void Texture::setBlendMode(SDL_BlendMode blending)
|
void Texture::setBlendMode(SDL_BlendMode blending) {
|
||||||
{
|
SDL_SetTextureBlendMode(texture_, blending);
|
||||||
SDL_SetTextureBlendMode(texture_, blending);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece el alpha para la modulación
|
// Establece el alpha para la modulación
|
||||||
void Texture::setAlpha(Uint8 alpha)
|
void Texture::setAlpha(Uint8 alpha) {
|
||||||
{
|
SDL_SetTextureAlphaMod(texture_, alpha);
|
||||||
SDL_SetTextureAlphaMod(texture_, alpha);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderiza la textura en un punto específico
|
// Renderiza la textura en un punto específico
|
||||||
void Texture::render(int x, int y, SDL_FRect *clip, float zoomW, float zoomH, double angle, SDL_FPoint *center, SDL_FlipMode flip)
|
void Texture::render(int x, int y, SDL_FRect *clip, float zoomW, float zoomH, double angle, SDL_FPoint *center, SDL_FlipMode flip) {
|
||||||
{
|
// Establece el destino de renderizado en la pantalla
|
||||||
// Establece el destino de renderizado en la pantalla
|
SDL_FRect renderQuad = {static_cast<float>(x), static_cast<float>(y), static_cast<float>(width_), static_cast<float>(height_)};
|
||||||
SDL_FRect renderQuad = {static_cast<float>(x), static_cast<float>(y), static_cast<float>(width_), static_cast<float>(height_)};
|
|
||||||
|
|
||||||
// Obtiene las dimesiones del clip de renderizado
|
// Obtiene las dimesiones del clip de renderizado
|
||||||
if (clip != nullptr)
|
if (clip != nullptr) {
|
||||||
{
|
renderQuad.w = clip->w;
|
||||||
renderQuad.w = clip->w;
|
renderQuad.h = clip->h;
|
||||||
renderQuad.h = clip->h;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Calcula el zoom y las coordenadas
|
// Calcula el zoom y las coordenadas
|
||||||
if (zoomH != 1.0f || zoomW != 1.0f)
|
if (zoomH != 1.0f || zoomW != 1.0f) {
|
||||||
{
|
renderQuad.x = renderQuad.x + (renderQuad.w / 2);
|
||||||
renderQuad.x = renderQuad.x + (renderQuad.w / 2);
|
renderQuad.y = renderQuad.y + (renderQuad.h / 2);
|
||||||
renderQuad.y = renderQuad.y + (renderQuad.h / 2);
|
renderQuad.w = renderQuad.w * zoomW;
|
||||||
renderQuad.w = renderQuad.w * zoomW;
|
renderQuad.h = renderQuad.h * zoomH;
|
||||||
renderQuad.h = renderQuad.h * zoomH;
|
renderQuad.x = renderQuad.x - (renderQuad.w / 2);
|
||||||
renderQuad.x = renderQuad.x - (renderQuad.w / 2);
|
renderQuad.y = renderQuad.y - (renderQuad.h / 2);
|
||||||
renderQuad.y = renderQuad.y - (renderQuad.h / 2);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Renderiza a pantalla
|
// Renderiza a pantalla
|
||||||
SDL_RenderTextureRotated(renderer_, texture_, clip, &renderQuad, angle, center, flip);
|
SDL_RenderTextureRotated(renderer_, texture_, clip, &renderQuad, angle, center, flip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece la textura como objetivo de renderizado
|
// Establece la textura como objetivo de renderizado
|
||||||
void Texture::setAsRenderTarget(SDL_Renderer *renderer)
|
void Texture::setAsRenderTarget(SDL_Renderer *renderer) {
|
||||||
{
|
SDL_SetRenderTarget(renderer, texture_);
|
||||||
SDL_SetRenderTarget(renderer, texture_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el ancho de la imagen
|
// Obtiene el ancho de la imagen
|
||||||
int Texture::getWidth()
|
int Texture::getWidth() {
|
||||||
{
|
return width_;
|
||||||
return width_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el alto de la imagen
|
// Obtiene el alto de la imagen
|
||||||
int Texture::getHeight()
|
int Texture::getHeight() {
|
||||||
{
|
return height_;
|
||||||
return height_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recarga la textura
|
// Recarga la textura
|
||||||
bool Texture::reLoad()
|
bool Texture::reLoad() {
|
||||||
{
|
return loadFromFile(path_);
|
||||||
return loadFromFile(path_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene la textura
|
// Obtiene la textura
|
||||||
SDL_Texture *Texture::getSDLTexture()
|
SDL_Texture *Texture::getSDLTexture() {
|
||||||
{
|
return texture_;
|
||||||
return texture_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Desencadenar la superficie actual
|
// Desencadenar la superficie actual
|
||||||
void Texture::unloadSurface()
|
void Texture::unloadSurface() {
|
||||||
{
|
surface_.reset(); // Resetea el shared_ptr
|
||||||
surface_.reset(); // Resetea el shared_ptr
|
width_ = 0;
|
||||||
width_ = 0;
|
height_ = 0;
|
||||||
height_ = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crea una surface desde un fichero .gif
|
// Crea una surface desde un fichero .gif
|
||||||
std::shared_ptr<Surface> Texture::loadSurface(const std::string &file_path)
|
std::shared_ptr<Surface> Texture::loadSurface(const std::string &file_path) {
|
||||||
{
|
// Libera la superficie actual
|
||||||
// Libera la superficie actual
|
unloadSurface();
|
||||||
unloadSurface();
|
|
||||||
|
|
||||||
// Abrir el archivo usando std::ifstream para manejo automático del recurso
|
// Abrir el archivo usando std::ifstream para manejo automático del recurso
|
||||||
std::ifstream file(file_path, std::ios::binary | std::ios::ate);
|
std::ifstream file(file_path, std::ios::binary | std::ios::ate);
|
||||||
if (!file)
|
if (!file) {
|
||||||
{
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Fichero no encontrado %s", file_path.c_str());
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Fichero no encontrado %s", file_path.c_str());
|
throw std::runtime_error("Fichero no encontrado: " + file_path);
|
||||||
throw std::runtime_error("Fichero no encontrado: " + file_path);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Obtener el tamaño del archivo
|
// Obtener el tamaño del archivo
|
||||||
std::streamsize size = file.tellg();
|
std::streamsize size = file.tellg();
|
||||||
file.seekg(0, std::ios::beg);
|
file.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
// Leer el contenido del archivo en un buffer
|
// Leer el contenido del archivo en un buffer
|
||||||
std::vector<Uint8> buffer(size);
|
std::vector<Uint8> buffer(size);
|
||||||
if (!file.read(reinterpret_cast<char *>(buffer.data()), size))
|
if (!file.read(reinterpret_cast<char *>(buffer.data()), size)) {
|
||||||
{
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error al leer el fichero %s", file_path.c_str());
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error al leer el fichero %s", file_path.c_str());
|
throw std::runtime_error("Error al leer el fichero: " + file_path);
|
||||||
throw std::runtime_error("Error al leer el fichero: " + file_path);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Crear un objeto Gif y llamar a la función loadGif
|
// Crear un objeto Gif y llamar a la función loadGif
|
||||||
GIF::Gif gif;
|
GIF::Gif gif;
|
||||||
Uint16 w = 0, h = 0;
|
Uint16 w = 0, h = 0;
|
||||||
std::vector<Uint8> rawPixels = gif.loadGif(buffer.data(), w, h);
|
std::vector<Uint8> rawPixels = gif.loadGif(buffer.data(), w, h);
|
||||||
if (rawPixels.empty())
|
if (rawPixels.empty()) {
|
||||||
{
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo cargar el GIF %s", file_path.c_str());
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo cargar el GIF %s", file_path.c_str());
|
return nullptr;
|
||||||
return nullptr;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Si el constructor de Surface espera un std::shared_ptr<Uint8[]>:
|
// Si el constructor de Surface espera un std::shared_ptr<Uint8[]>:
|
||||||
size_t pixelCount = rawPixels.size();
|
size_t pixelCount = rawPixels.size();
|
||||||
auto pixels = std::shared_ptr<Uint8[]>(new Uint8[pixelCount], std::default_delete<Uint8[]>());
|
auto pixels = std::shared_ptr<Uint8[]>(new Uint8[pixelCount], std::default_delete<Uint8[]>());
|
||||||
std::memcpy(pixels.get(), rawPixels.data(), pixelCount);
|
std::memcpy(pixels.get(), rawPixels.data(), pixelCount);
|
||||||
|
|
||||||
auto surface = std::make_shared<Surface>(w, h, pixels);
|
auto surface = std::make_shared<Surface>(w, h, pixels);
|
||||||
|
|
||||||
// Actualizar las dimensiones
|
// Actualizar las dimensiones
|
||||||
width_ = w;
|
width_ = w;
|
||||||
height_ = h;
|
height_ = h;
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "GIF %s cargado correctamente.", file_path.c_str());
|
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "GIF %s cargado correctamente.", file_path.c_str());
|
||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vuelca la surface en la textura
|
// Vuelca la surface en la textura
|
||||||
void Texture::flipSurface()
|
void Texture::flipSurface() {
|
||||||
{
|
// Limpia la textura
|
||||||
// Limpia la textura
|
auto temp = SDL_GetRenderTarget(renderer_);
|
||||||
auto temp = SDL_GetRenderTarget(renderer_);
|
SDL_SetRenderTarget(renderer_, texture_);
|
||||||
SDL_SetRenderTarget(renderer_, texture_);
|
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
||||||
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 0);
|
SDL_RenderClear(renderer_);
|
||||||
SDL_RenderClear(renderer_);
|
SDL_SetRenderTarget(renderer_, temp);
|
||||||
SDL_SetRenderTarget(renderer_, temp);
|
|
||||||
|
|
||||||
// Vuelca los datos
|
// Vuelca los datos
|
||||||
Uint32 *pixels;
|
Uint32 *pixels;
|
||||||
int pitch;
|
int pitch;
|
||||||
SDL_LockTexture(texture_, nullptr, reinterpret_cast<void **>(&pixels), &pitch);
|
SDL_LockTexture(texture_, nullptr, reinterpret_cast<void **>(&pixels), &pitch);
|
||||||
for (int i = 0; i < width_ * height_; ++i)
|
for (int i = 0; i < width_ * height_; ++i) {
|
||||||
{
|
pixels[i] = palettes_[current_palette_][surface_->data[i]];
|
||||||
pixels[i] = palettes_[current_palette_][surface_->data[i]];
|
}
|
||||||
}
|
SDL_UnlockTexture(texture_);
|
||||||
SDL_UnlockTexture(texture_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establece un color de la paleta
|
// Establece un color de la paleta
|
||||||
void Texture::setPaletteColor(int palette, int index, Uint32 color)
|
void Texture::setPaletteColor(int palette, int index, Uint32 color) {
|
||||||
{
|
palettes_.at(palette)[index] = color;
|
||||||
palettes_.at(palette)[index] = color;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Carga una paleta desde un fichero
|
// Carga una paleta desde un fichero
|
||||||
Palette Texture::loadPaletteFromFile(const std::string &file_path)
|
Palette Texture::loadPaletteFromFile(const std::string &file_path) {
|
||||||
{
|
Palette palette;
|
||||||
Palette palette;
|
|
||||||
|
|
||||||
// Abrir el archivo GIF
|
// Abrir el archivo GIF
|
||||||
std::ifstream file(file_path, std::ios::binary | std::ios::ate);
|
std::ifstream file(file_path, std::ios::binary | std::ios::ate);
|
||||||
if (!file)
|
if (!file) {
|
||||||
{
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Fichero no encontrado %s", file_path.c_str());
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Fichero no encontrado %s", file_path.c_str());
|
throw std::runtime_error("Fichero no encontrado: " + file_path);
|
||||||
throw std::runtime_error("Fichero no encontrado: " + file_path);
|
} else {
|
||||||
}
|
printWithDots("Palette : ", getFileName(file_path), "[ LOADED ]");
|
||||||
else
|
}
|
||||||
{
|
|
||||||
printWithDots("Palette : ", getFileName(file_path), "[ LOADED ]");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Obtener el tamaño del archivo y leerlo en un buffer
|
// Obtener el tamaño del archivo y leerlo en un buffer
|
||||||
std::streamsize size = file.tellg();
|
std::streamsize size = file.tellg();
|
||||||
file.seekg(0, std::ios::beg);
|
file.seekg(0, std::ios::beg);
|
||||||
|
|
||||||
std::vector<Uint8> buffer(size);
|
std::vector<Uint8> buffer(size);
|
||||||
if (!file.read(reinterpret_cast<char *>(buffer.data()), size))
|
if (!file.read(reinterpret_cast<char *>(buffer.data()), size)) {
|
||||||
{
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo leer completamente el fichero %s", file_path.c_str());
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: No se pudo leer completamente el fichero %s", file_path.c_str());
|
throw std::runtime_error("Error al leer el fichero: " + file_path);
|
||||||
throw std::runtime_error("Error al leer el fichero: " + file_path);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Usar la nueva función loadPalette, que devuelve un vector<uint32_t>
|
// Usar la nueva función loadPalette, que devuelve un vector<uint32_t>
|
||||||
GIF::Gif gif;
|
GIF::Gif gif;
|
||||||
std::vector<uint32_t> pal = gif.loadPalette(buffer.data());
|
std::vector<uint32_t> pal = gif.loadPalette(buffer.data());
|
||||||
if (pal.empty())
|
if (pal.empty()) {
|
||||||
{
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Advertencia: No se encontró paleta en el archivo %s", file_path.c_str());
|
||||||
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Advertencia: No se encontró paleta en el archivo %s", file_path.c_str());
|
return palette; // Devuelve un vector vacío si no hay paleta
|
||||||
return palette; // Devuelve un vector vacío si no hay paleta
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Modificar la conversión para obtener formato RGBA (0xRRGGBBAA)
|
// Modificar la conversión para obtener formato RGBA (0xRRGGBBAA)
|
||||||
for (size_t i = 0; i < pal.size() && i < palette.size(); ++i)
|
for (size_t i = 0; i < pal.size() && i < palette.size(); ++i) {
|
||||||
{
|
palette[i] = (pal[i] << 8) | 0xFF; // Resultado: 0xRRGGBBAA
|
||||||
palette[i] = (pal[i] << 8) | 0xFF; // Resultado: 0xRRGGBBAA
|
}
|
||||||
}
|
|
||||||
|
|
||||||
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "Paleta cargada correctamente desde %s", file_path.c_str());
|
SDL_LogInfo(SDL_LOG_CATEGORY_TEST, "Paleta cargada correctamente desde %s", file_path.c_str());
|
||||||
return palette;
|
return palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Añade una paleta a la lista
|
// Añade una paleta a la lista
|
||||||
void Texture::addPaletteFromGifFile(const std::string &path)
|
void Texture::addPaletteFromGifFile(const std::string &path) {
|
||||||
{
|
palettes_.emplace_back(loadPaletteFromFile(path));
|
||||||
palettes_.emplace_back(loadPaletteFromFile(path));
|
setPaletteColor(palettes_.size() - 1, 0, 0x00000000);
|
||||||
setPaletteColor(palettes_.size() - 1, 0, 0x00000000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Añade una paleta a la lista
|
// Añade una paleta a la lista
|
||||||
void Texture::addPaletteFromPalFile(const std::string &path)
|
void Texture::addPaletteFromPalFile(const std::string &path) {
|
||||||
{
|
palettes_.emplace_back(readPalFile(path));
|
||||||
palettes_.emplace_back(readPalFile(path));
|
setPaletteColor(palettes_.size() - 1, 0, 0x00000000);
|
||||||
setPaletteColor(palettes_.size() - 1, 0, 0x00000000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cambia la paleta de la textura
|
// Cambia la paleta de la textura
|
||||||
void Texture::setPalette(size_t palette)
|
void Texture::setPalette(size_t palette) {
|
||||||
{
|
if (palette < palettes_.size()) {
|
||||||
if (palette < palettes_.size())
|
current_palette_ = palette;
|
||||||
{
|
flipSurface();
|
||||||
current_palette_ = palette;
|
}
|
||||||
flipSurface();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtiene el renderizador
|
// Obtiene el renderizador
|
||||||
SDL_Renderer *Texture::getRenderer() { return renderer_; }
|
SDL_Renderer *Texture::getRenderer() { return renderer_; }
|
||||||
|
|
||||||
// Carga una paleta desde un archivo .pal
|
// Carga una paleta desde un archivo .pal
|
||||||
Palette Texture::readPalFile(const std::string &file_path)
|
Palette Texture::readPalFile(const std::string &file_path) {
|
||||||
{
|
Palette palette{};
|
||||||
Palette palette{};
|
palette.fill(0); // Inicializar todo con 0 (transparente por defecto)
|
||||||
palette.fill(0); // Inicializar todo con 0 (transparente por defecto)
|
|
||||||
|
|
||||||
std::ifstream file(file_path);
|
std::ifstream file(file_path);
|
||||||
if (!file.is_open())
|
if (!file.is_open()) {
|
||||||
{
|
throw std::runtime_error("No se pudo abrir el archivo .pal");
|
||||||
throw std::runtime_error("No se pudo abrir el archivo .pal");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
int line_number = 0;
|
int line_number = 0;
|
||||||
int color_index = 0;
|
int color_index = 0;
|
||||||
|
|
||||||
while (std::getline(file, line))
|
while (std::getline(file, line)) {
|
||||||
{
|
++line_number;
|
||||||
++line_number;
|
|
||||||
|
|
||||||
// Ignorar las tres primeras líneas del archivo
|
// Ignorar las tres primeras líneas del archivo
|
||||||
if (line_number <= 3)
|
if (line_number <= 3) {
|
||||||
{
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Procesar las líneas restantes con valores RGB
|
// Procesar las líneas restantes con valores RGB
|
||||||
std::istringstream ss(line);
|
std::istringstream ss(line);
|
||||||
int r, g, b;
|
int r, g, b;
|
||||||
if (ss >> r >> g >> b)
|
if (ss >> r >> g >> b) {
|
||||||
{
|
// Construir el color RGBA (A = 255 por defecto)
|
||||||
// Construir el color RGBA (A = 255 por defecto)
|
Uint32 color = (r << 24) | (g << 16) | (b << 8) | 255;
|
||||||
Uint32 color = (r << 24) | (g << 16) | (b << 8) | 255;
|
palette[color_index++] = color;
|
||||||
palette[color_index++] = color;
|
|
||||||
|
|
||||||
// Limitar a un máximo de 256 colores (opcional)
|
// Limitar a un máximo de 256 colores (opcional)
|
||||||
if (color_index >= 256)
|
if (color_index >= 256) {
|
||||||
{
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
file.close();
|
file.close();
|
||||||
return palette;
|
return palette;
|
||||||
}
|
}
|
||||||
+42
-43
@@ -1,11 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para Uint8, SDL_Renderer, Uint16, SDL_FlipMode, SDL_PixelFormat, SDL_TextureAccess, SDL_Texture, Uint32, SDL_BlendMode, SDL_FPoint, SDL_FRect
|
#include <SDL3/SDL.h> // Para Uint8, SDL_Renderer, Uint16, SDL_FlipMode, SDL_PixelFormat, SDL_TextureAccess, SDL_Texture, Uint32, SDL_BlendMode, SDL_FPoint, SDL_FRect
|
||||||
#include <stddef.h> // Para size_t
|
#include <stddef.h> // Para size_t
|
||||||
#include <array> // Para array
|
|
||||||
#include <memory> // Para shared_ptr
|
#include <array> // Para array
|
||||||
#include <string> // Para string, basic_string
|
#include <memory> // Para shared_ptr
|
||||||
#include <vector> // Para vector
|
#include <string> // Para string, basic_string
|
||||||
|
#include <vector> // Para vector
|
||||||
|
|
||||||
struct Color;
|
struct Color;
|
||||||
|
|
||||||
@@ -13,8 +14,7 @@ struct Color;
|
|||||||
using Palette = std::array<Uint32, 256>;
|
using Palette = std::array<Uint32, 256>;
|
||||||
|
|
||||||
// Definición de Surface para imágenes con paleta
|
// Definición de Surface para imágenes con paleta
|
||||||
struct Surface
|
struct Surface {
|
||||||
{
|
|
||||||
std::shared_ptr<Uint8[]> data;
|
std::shared_ptr<Uint8[]> data;
|
||||||
Uint16 w, h;
|
Uint16 w, h;
|
||||||
|
|
||||||
@@ -24,58 +24,57 @@ struct Surface
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Clase Texture: gestiona texturas, paletas y renderizado
|
// Clase Texture: gestiona texturas, paletas y renderizado
|
||||||
class Texture
|
class Texture {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
// --- Constructores y destructor ---
|
// --- Constructores y destructor ---
|
||||||
explicit Texture(SDL_Renderer *renderer, const std::string &path = std::string());
|
explicit Texture(SDL_Renderer *renderer, const std::string &path = std::string());
|
||||||
~Texture();
|
~Texture();
|
||||||
|
|
||||||
// --- Carga y creación ---
|
// --- Carga y creación ---
|
||||||
bool loadFromFile(const std::string &path); // Carga una imagen desde un fichero
|
bool loadFromFile(const std::string &path); // Carga una imagen desde un fichero
|
||||||
bool createBlank(int width, int height, SDL_PixelFormat format = SDL_PIXELFORMAT_RGBA8888, SDL_TextureAccess access = SDL_TEXTUREACCESS_STREAMING); // Crea una textura en blanco
|
bool createBlank(int width, int height, SDL_PixelFormat format = SDL_PIXELFORMAT_RGBA8888, SDL_TextureAccess access = SDL_TEXTUREACCESS_STREAMING); // Crea una textura en blanco
|
||||||
bool reLoad(); // Recarga la textura
|
bool reLoad(); // Recarga la textura
|
||||||
|
|
||||||
// --- Renderizado ---
|
// --- Renderizado ---
|
||||||
void render(int x, int y, SDL_FRect *clip = nullptr, float zoomW = 1, float zoomH = 1, double angle = 0.0, SDL_FPoint *center = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE); // Renderiza la textura en un punto específico
|
void render(int x, int y, SDL_FRect *clip = nullptr, float zoomW = 1, float zoomH = 1, double angle = 0.0, SDL_FPoint *center = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE); // Renderiza la textura en un punto específico
|
||||||
void setAsRenderTarget(SDL_Renderer *renderer); // Establece la textura como objetivo de renderizado
|
void setAsRenderTarget(SDL_Renderer *renderer); // Establece la textura como objetivo de renderizado
|
||||||
|
|
||||||
// --- Modificadores de color y blending ---
|
// --- Modificadores de color y blending ---
|
||||||
void setColor(Uint8 red, Uint8 green, Uint8 blue); // Establece el color para la modulación
|
void setColor(Uint8 red, Uint8 green, Uint8 blue); // Establece el color para la modulación
|
||||||
void setColor(Color color); // Establece el color para la modulación
|
void setColor(Color color); // Establece el color para la modulación
|
||||||
void setBlendMode(SDL_BlendMode blending); // Establece el blending
|
void setBlendMode(SDL_BlendMode blending); // Establece el blending
|
||||||
void setAlpha(Uint8 alpha); // Establece el alpha para la modulación
|
void setAlpha(Uint8 alpha); // Establece el alpha para la modulación
|
||||||
|
|
||||||
// --- Paletas ---
|
// --- Paletas ---
|
||||||
void addPaletteFromGifFile(const std::string &path); // Añade una paleta a la lista
|
void addPaletteFromGifFile(const std::string &path); // Añade una paleta a la lista
|
||||||
void addPaletteFromPalFile(const std::string &path); // Añade una paleta a la lista
|
void addPaletteFromPalFile(const std::string &path); // Añade una paleta a la lista
|
||||||
void setPaletteColor(int palette, int index, Uint32 color); // Establece un color de la paleta
|
void setPaletteColor(int palette, int index, Uint32 color); // Establece un color de la paleta
|
||||||
void setPalette(size_t palette); // Cambia la paleta de la textura
|
void setPalette(size_t palette); // Cambia la paleta de la textura
|
||||||
|
|
||||||
// --- Getters ---
|
// --- Getters ---
|
||||||
int getWidth(); // Obtiene el ancho de la imagen
|
int getWidth(); // Obtiene el ancho de la imagen
|
||||||
int getHeight(); // Obtiene el alto de la imagen
|
int getHeight(); // Obtiene el alto de la imagen
|
||||||
SDL_Texture *getSDLTexture(); // Obtiene la textura SDL
|
SDL_Texture *getSDLTexture(); // Obtiene la textura SDL
|
||||||
SDL_Renderer *getRenderer(); // Obtiene el renderizador
|
SDL_Renderer *getRenderer(); // Obtiene el renderizador
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// --- Objetos y punteros ---
|
// --- Objetos y punteros ---
|
||||||
SDL_Renderer *renderer_; // Renderizador donde dibujar la textura
|
SDL_Renderer *renderer_; // Renderizador donde dibujar la textura
|
||||||
SDL_Texture *texture_ = nullptr; // La textura
|
SDL_Texture *texture_ = nullptr; // La textura
|
||||||
std::shared_ptr<Surface> surface_ = nullptr; // Surface para usar imágenes en formato gif con paleta
|
std::shared_ptr<Surface> surface_ = nullptr; // Surface para usar imágenes en formato gif con paleta
|
||||||
|
|
||||||
// --- Variables ---
|
// --- Variables ---
|
||||||
std::string path_; // Ruta de la imagen de la textura
|
std::string path_; // Ruta de la imagen de la textura
|
||||||
int width_ = 0; // Ancho de la imagen
|
int width_ = 0; // Ancho de la imagen
|
||||||
int height_ = 0; // Alto de la imagen
|
int height_ = 0; // Alto de la imagen
|
||||||
std::vector<Palette> palettes_; // Vector con las diferentes paletas
|
std::vector<Palette> palettes_; // Vector con las diferentes paletas
|
||||||
int current_palette_ = 0; // Índice de la paleta en uso
|
int current_palette_ = 0; // Índice de la paleta en uso
|
||||||
|
|
||||||
// --- Métodos internos ---
|
// --- Métodos internos ---
|
||||||
std::shared_ptr<Surface> loadSurface(const std::string &file_name); // Crea una surface desde un fichero .gif
|
std::shared_ptr<Surface> loadSurface(const std::string &file_name); // Crea una surface desde un fichero .gif
|
||||||
void flipSurface(); // Vuelca la surface en la textura
|
void flipSurface(); // Vuelca la surface en la textura
|
||||||
Palette loadPaletteFromFile(const std::string &file_name); // Carga una paleta desde un fichero
|
Palette loadPaletteFromFile(const std::string &file_name); // Carga una paleta desde un fichero
|
||||||
void unloadTexture(); // Libera la memoria de la textura
|
void unloadTexture(); // Libera la memoria de la textura
|
||||||
void unloadSurface(); // Libera la surface actual
|
void unloadSurface(); // Libera la surface actual
|
||||||
Palette readPalFile(const std::string &file_path); // Carga una paleta desde un archivo .pal
|
Palette readPalFile(const std::string &file_path); // Carga una paleta desde un archivo .pal
|
||||||
};
|
};
|
||||||
+56
-72
@@ -1,21 +1,21 @@
|
|||||||
#include "tiled_bg.h"
|
#include "tiled_bg.h"
|
||||||
|
|
||||||
#include <SDL3/SDL.h> // Para SDL_SetRenderTarget, SDL_CreateTexture, SDL_De...
|
#include <SDL3/SDL.h> // Para SDL_SetRenderTarget, SDL_CreateTexture, SDL_De...
|
||||||
#include <stdlib.h> // Para rand
|
#include <stdlib.h> // Para rand
|
||||||
#include <cmath> // Para sin
|
|
||||||
#include <memory> // Para unique_ptr, make_unique
|
|
||||||
#include <string> // Para basic_string
|
|
||||||
|
|
||||||
#include "resource.h" // Para Resource
|
#include <cmath> // Para sin
|
||||||
#include "screen.h" // Para Screen
|
#include <memory> // Para unique_ptr, make_unique
|
||||||
#include "sprite.h" // Para Sprite
|
#include <string> // Para basic_string
|
||||||
|
|
||||||
|
#include "resource.h" // Para Resource
|
||||||
|
#include "screen.h" // Para Screen
|
||||||
|
#include "sprite.h" // Para Sprite
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
TiledBG::TiledBG(SDL_FRect pos, TiledBGMode mode)
|
TiledBG::TiledBG(SDL_FRect pos, TiledBGMode mode)
|
||||||
: renderer_(Screen::get()->getRenderer()),
|
: renderer_(Screen::get()->getRenderer()),
|
||||||
pos_(pos),
|
pos_(pos),
|
||||||
mode_(mode == TiledBGMode::RANDOM ? static_cast<TiledBGMode>(rand() % 2) : mode)
|
mode_(mode == TiledBGMode::RANDOM ? static_cast<TiledBGMode>(rand() % 2) : mode) {
|
||||||
{
|
|
||||||
// Crea la textura para el mosaico de fondo
|
// Crea la textura para el mosaico de fondo
|
||||||
canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, pos_.w * 2, pos_.h * 2);
|
canvas_ = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, pos_.w * 2, pos_.h * 2);
|
||||||
|
|
||||||
@@ -23,39 +23,35 @@ TiledBG::TiledBG(SDL_FRect pos, TiledBGMode mode)
|
|||||||
fillTexture();
|
fillTexture();
|
||||||
|
|
||||||
// Inicializa variables
|
// Inicializa variables
|
||||||
switch (mode_)
|
switch (mode_) {
|
||||||
{
|
case TiledBGMode::STATIC:
|
||||||
case TiledBGMode::STATIC:
|
window_ = {0, 0, pos_.w, pos_.h};
|
||||||
window_ = {0, 0, pos_.w, pos_.h};
|
speed_ = 0.0f;
|
||||||
speed_ = 0.0f;
|
break;
|
||||||
break;
|
case TiledBGMode::DIAGONAL:
|
||||||
case TiledBGMode::DIAGONAL:
|
window_ = {0, 0, pos_.w, pos_.h};
|
||||||
window_ = {0, 0, pos_.w, pos_.h};
|
break;
|
||||||
break;
|
case TiledBGMode::CIRCLE:
|
||||||
case TiledBGMode::CIRCLE:
|
window_ = {128, 128, pos_.w, pos_.h};
|
||||||
window_ = {128, 128, pos_.w, pos_.h};
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
window_ = {0, 0, pos_.w, pos_.h};
|
||||||
window_ = {0, 0, pos_.w, pos_.h};
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inicializa los valores del vector con los valores del seno
|
// Inicializa los valores del vector con los valores del seno
|
||||||
for (int i = 0; i < 360; ++i)
|
for (int i = 0; i < 360; ++i) {
|
||||||
{
|
sin_[i] = std::sin(i * 3.14159 / 180.0); // Convierte grados a radianes y calcula el seno
|
||||||
sin_[i] = std::sin(i * 3.14159 / 180.0); // Convierte grados a radianes y calcula el seno
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor
|
// Destructor
|
||||||
TiledBG::~TiledBG()
|
TiledBG::~TiledBG() {
|
||||||
{
|
|
||||||
SDL_DestroyTexture(canvas_);
|
SDL_DestroyTexture(canvas_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rellena la textura con el contenido
|
// Rellena la textura con el contenido
|
||||||
void TiledBG::fillTexture()
|
void TiledBG::fillTexture() {
|
||||||
{
|
|
||||||
// Crea los objetos para pintar en la textura de fondo
|
// Crea los objetos para pintar en la textura de fondo
|
||||||
auto tile = std::make_unique<Sprite>(Resource::get()->getTexture("title_bg_tile.png"), (SDL_FRect){0, 0, TILE_WIDTH_, TILE_HEIGHT_});
|
auto tile = std::make_unique<Sprite>(Resource::get()->getTexture("title_bg_tile.png"), (SDL_FRect){0, 0, TILE_WIDTH_, TILE_HEIGHT_});
|
||||||
|
|
||||||
@@ -67,10 +63,8 @@ void TiledBG::fillTexture()
|
|||||||
const auto i_max = pos_.w * 2 / TILE_WIDTH_;
|
const auto i_max = pos_.w * 2 / TILE_WIDTH_;
|
||||||
const auto j_max = pos_.h * 2 / TILE_HEIGHT_;
|
const auto j_max = pos_.h * 2 / TILE_HEIGHT_;
|
||||||
tile->setSpriteClip(0, 0, TILE_WIDTH_, TILE_HEIGHT_);
|
tile->setSpriteClip(0, 0, TILE_WIDTH_, TILE_HEIGHT_);
|
||||||
for (int i = 0; i < i_max; ++i)
|
for (int i = 0; i < i_max; ++i) {
|
||||||
{
|
for (int j = 0; j < j_max; ++j) {
|
||||||
for (int j = 0; j < j_max; ++j)
|
|
||||||
{
|
|
||||||
tile->setX(i * TILE_WIDTH_);
|
tile->setX(i * TILE_WIDTH_);
|
||||||
tile->setY(j * TILE_HEIGHT_);
|
tile->setY(j * TILE_HEIGHT_);
|
||||||
tile->render();
|
tile->render();
|
||||||
@@ -82,65 +76,55 @@ void TiledBG::fillTexture()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pinta la clase en pantalla
|
// Pinta la clase en pantalla
|
||||||
void TiledBG::render()
|
void TiledBG::render() {
|
||||||
{
|
|
||||||
SDL_RenderTexture(renderer_, canvas_, &window_, &pos_);
|
SDL_RenderTexture(renderer_, canvas_, &window_, &pos_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza la lógica de la clase
|
// Actualiza la lógica de la clase
|
||||||
void TiledBG::update()
|
void TiledBG::update() {
|
||||||
{
|
|
||||||
updateDesp();
|
updateDesp();
|
||||||
updateStop();
|
updateStop();
|
||||||
|
|
||||||
switch (mode_)
|
switch (mode_) {
|
||||||
{
|
case TiledBGMode::DIAGONAL: {
|
||||||
case TiledBGMode::DIAGONAL:
|
// El tileado de fondo se desplaza en diagonal
|
||||||
{
|
window_.x = static_cast<int>(desp_) % TILE_WIDTH_;
|
||||||
// El tileado de fondo se desplaza en diagonal
|
window_.y = static_cast<int>(desp_) % TILE_HEIGHT_;
|
||||||
window_.x = static_cast<int>(desp_) % TILE_WIDTH_;
|
|
||||||
window_.y = static_cast<int>(desp_) % TILE_HEIGHT_;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TiledBGMode::CIRCLE:
|
case TiledBGMode::CIRCLE: {
|
||||||
{
|
// El tileado de fondo se desplaza en circulo
|
||||||
// El tileado de fondo se desplaza en circulo
|
const int INDEX = static_cast<int>(desp_) % 360;
|
||||||
const int INDEX = static_cast<int>(desp_) % 360;
|
|
||||||
|
|
||||||
window_.x = 128 + (static_cast<int>(sin_[(INDEX + 270) % 360] * 128));
|
window_.x = 128 + (static_cast<int>(sin_[(INDEX + 270) % 360] * 128));
|
||||||
window_.y = 128 + (static_cast<int>(sin_[(360 - INDEX) % 360] * 96));
|
window_.y = 128 + (static_cast<int>(sin_[(360 - INDEX) % 360] * 96));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detiene el desplazamiento de forma ordenada
|
// Detiene el desplazamiento de forma ordenada
|
||||||
void TiledBG::updateStop()
|
void TiledBG::updateStop() {
|
||||||
{
|
if (stopping_) {
|
||||||
if (stopping_)
|
const int UMBRAL = 20 * speed_; // Ajusta este valor según la precisión deseada
|
||||||
{
|
|
||||||
const int UMBRAL = 20 * speed_; // Ajusta este valor según la precisión deseada
|
|
||||||
|
|
||||||
// Desacelerar si estamos cerca de completar el ciclo (ventana a punto de regresar a 0)
|
// Desacelerar si estamos cerca de completar el ciclo (ventana a punto de regresar a 0)
|
||||||
if (window_.x >= TILE_WIDTH_ - UMBRAL)
|
if (window_.x >= TILE_WIDTH_ - UMBRAL) {
|
||||||
{
|
speed_ /= 1.05f; // Reduce gradualmente la velocidad
|
||||||
speed_ /= 1.05f; // Reduce gradualmente la velocidad
|
|
||||||
|
|
||||||
// Asegura que no baje demasiado
|
// Asegura que no baje demasiado
|
||||||
if (speed_ < 0.1f)
|
if (speed_ < 0.1f) {
|
||||||
{
|
|
||||||
speed_ = 0.1f;
|
speed_ = 0.1f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si estamos en 0, detener
|
// Si estamos en 0, detener
|
||||||
if (window_.x == 0)
|
if (window_.x == 0) {
|
||||||
{
|
|
||||||
speed_ = 0.0f;
|
speed_ = 0.0f;
|
||||||
stopping_ = false; // Desactivamos el estado de "stopping"
|
stopping_ = false; // Desactivamos el estado de "stopping"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loaded 100 of 112 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user