netejant capçaleres
This commit is contained in:
@@ -4,7 +4,9 @@
|
||||
"Bash(cmake --build:*)",
|
||||
"Bash(test:*)",
|
||||
"Bash(tools/linter/run_clang-tidy.sh:*)",
|
||||
"Bash(make resources.pack:*)"
|
||||
"Bash(make resources.pack:*)",
|
||||
"Bash(tools/linter/run_cppcheck.sh:*)",
|
||||
"Bash(cat:*)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
||||
@@ -345,7 +345,7 @@ void Screen::renderInfo() {
|
||||
|
||||
// FPS
|
||||
const std::string FPS_TEXT = std::to_string(fps_.last_value) + " FPS";
|
||||
text->writeColored(Options::game.width - text->lenght(FPS_TEXT), 0, FPS_TEXT, color);
|
||||
text->writeColored(Options::game.width - text->length(FPS_TEXT), 0, FPS_TEXT, color);
|
||||
|
||||
// Resolution
|
||||
text->writeColored(0, 0, info_resolution_, color);
|
||||
|
||||
@@ -15,17 +15,10 @@
|
||||
#include "utils/utils.hpp" // Para getFileName, stringToColor, printWithDots
|
||||
|
||||
// Llena una estructuta TextFile desde un fichero
|
||||
auto loadTextFile(const std::string& file_path) -> std::shared_ptr<TextFile> {
|
||||
auto tf = std::make_shared<TextFile>();
|
||||
auto Text::loadTextFile(const std::string& file_path) -> std::shared_ptr<File> {
|
||||
auto tf = std::make_shared<File>();
|
||||
|
||||
// Inicializa a cero el vector con las coordenadas
|
||||
for (auto& i : tf->offset) {
|
||||
i.x = 0;
|
||||
i.y = 0;
|
||||
i.w = 0;
|
||||
tf->box_width = 0;
|
||||
tf->box_height = 0;
|
||||
}
|
||||
// No es necesario inicializar - los miembros tienen valores por defecto
|
||||
|
||||
// Load file using ResourceHelper (supports both filesystem and pack)
|
||||
auto file_data = Resource::Helper::loadFile(file_path);
|
||||
@@ -101,35 +94,18 @@ Text::Text(const std::shared_ptr<Surface>& surface, const std::string& text_file
|
||||
// Inicializa variables desde la estructura
|
||||
box_height_ = tf->box_height;
|
||||
box_width_ = tf->box_width;
|
||||
for (int i = 0; i < 128; ++i) {
|
||||
offset_[i].x = tf->offset[i].x;
|
||||
offset_[i].y = tf->offset[i].y;
|
||||
offset_[i].w = tf->offset[i].w;
|
||||
}
|
||||
offset_ = tf->offset;
|
||||
|
||||
// Crea los objetos
|
||||
sprite_ = std::make_unique<SurfaceSprite>(surface, (SDL_FRect){0.0F, 0.0F, static_cast<float>(box_width_), static_cast<float>(box_height_)});
|
||||
|
||||
// Inicializa variables
|
||||
fixed_width_ = false;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
Text::Text(const std::shared_ptr<Surface>& surface, const std::shared_ptr<TextFile>& text_file) {
|
||||
// Inicializa variables desde la estructura
|
||||
box_height_ = text_file->box_height;
|
||||
box_width_ = text_file->box_width;
|
||||
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].w = text_file->offset[i].w;
|
||||
}
|
||||
|
||||
// Crea los objetos
|
||||
sprite_ = std::make_unique<SurfaceSprite>(surface, (SDL_FRect){0.0F, 0.0F, static_cast<float>(box_width_), static_cast<float>(box_height_)});
|
||||
|
||||
// Inicializa variables
|
||||
fixed_width_ = false;
|
||||
Text::Text(const std::shared_ptr<Surface>& surface, const std::shared_ptr<File>& text_file)
|
||||
: sprite_(std::make_unique<SurfaceSprite>(surface, (SDL_FRect){0.0F, 0.0F, static_cast<float>(text_file->box_width), static_cast<float>(text_file->box_height)})),
|
||||
box_width_(text_file->box_width),
|
||||
box_height_(text_file->box_height),
|
||||
offset_(text_file->offset) {
|
||||
}
|
||||
|
||||
// Escribe texto en pantalla
|
||||
@@ -152,7 +128,7 @@ void Text::write(int x, int y, const std::string& text, int kerning, int lenght)
|
||||
|
||||
// Escribe el texto en una surface
|
||||
auto Text::writeToSurface(const std::string& text, int zoom, int kerning) -> std::shared_ptr<Surface> {
|
||||
auto width = lenght(text, kerning) * zoom;
|
||||
auto width = length(text, kerning) * zoom;
|
||||
auto height = box_height_ * zoom;
|
||||
auto surface = std::make_shared<Surface>(width, height);
|
||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
||||
@@ -166,7 +142,7 @@ auto Text::writeToSurface(const std::string& text, int zoom, int kerning) -> std
|
||||
|
||||
// Escribe el texto con extras en una surface
|
||||
auto Text::writeDXToSurface(Uint8 flags, const std::string& text, int kerning, Uint8 text_color, Uint8 shadow_distance, Uint8 shadow_color, int lenght) -> std::shared_ptr<Surface> {
|
||||
auto width = Text::lenght(text, kerning) + shadow_distance;
|
||||
auto width = Text::length(text, kerning) + shadow_distance;
|
||||
auto height = box_height_ + shadow_distance;
|
||||
auto surface = std::make_shared<Surface>(width, height);
|
||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
||||
@@ -204,19 +180,19 @@ void Text::writeShadowed(int x, int y, const std::string& text, Uint8 color, Uin
|
||||
|
||||
// Escribe el texto centrado en un punto x
|
||||
void Text::writeCentered(int x, int y, const std::string& text, int kerning, int lenght) {
|
||||
x -= (Text::lenght(text, kerning) / 2);
|
||||
x -= (Text::length(text, kerning) / 2);
|
||||
write(x, y, text, kerning, lenght);
|
||||
}
|
||||
|
||||
// Escribe texto con extras
|
||||
void Text::writeDX(Uint8 flags, int x, int y, const std::string& text, int kerning, Uint8 text_color, Uint8 shadow_distance, Uint8 shadow_color, int lenght) {
|
||||
const auto CENTERED = ((flags & TEXT_CENTER) == TEXT_CENTER);
|
||||
const auto SHADOWED = ((flags & TEXT_SHADOW) == TEXT_SHADOW);
|
||||
const auto COLORED = ((flags & TEXT_COLOR) == TEXT_COLOR);
|
||||
const auto STROKED = ((flags & TEXT_STROKE) == TEXT_STROKE);
|
||||
const auto CENTERED = ((flags & CENTER_FLAG) == CENTER_FLAG);
|
||||
const auto SHADOWED = ((flags & SHADOW_FLAG) == SHADOW_FLAG);
|
||||
const auto COLORED = ((flags & COLOR_FLAG) == COLOR_FLAG);
|
||||
const auto STROKED = ((flags & STROKE_FLAG) == STROKE_FLAG);
|
||||
|
||||
if (CENTERED) {
|
||||
x -= (Text::lenght(text, kerning) / 2);
|
||||
x -= (Text::length(text, kerning) / 2);
|
||||
}
|
||||
|
||||
if (SHADOWED) {
|
||||
@@ -242,7 +218,7 @@ void Text::writeDX(Uint8 flags, int x, int y, const std::string& text, int kerni
|
||||
}
|
||||
|
||||
// Obtiene la longitud en pixels de una cadena
|
||||
auto Text::lenght(const std::string& text, int kerning) const -> int {
|
||||
auto Text::length(const std::string& text, int kerning) const -> int {
|
||||
int shift = 0;
|
||||
for (size_t i = 0; i < text.length(); ++i) {
|
||||
shift += (offset_[static_cast<int>(text[i])].w + kerning);
|
||||
|
||||
@@ -2,77 +2,63 @@
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <array> // Para std::array
|
||||
#include <memory> // Para shared_ptr, unique_ptr
|
||||
#include <string> // Para string
|
||||
|
||||
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||
class Surface; // lines 8-8
|
||||
|
||||
constexpr int TEXT_COLOR = 1;
|
||||
constexpr int TEXT_SHADOW = 2;
|
||||
constexpr int TEXT_CENTER = 4;
|
||||
constexpr int TEXT_STROKE = 8;
|
||||
|
||||
struct TextOffset {
|
||||
int x, y, w;
|
||||
};
|
||||
|
||||
struct TextFile {
|
||||
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
|
||||
TextOffset offset[128]; // Vector con las posiciones y ancho de cada letra
|
||||
};
|
||||
|
||||
// Llena una estructuta TextFile desde un fichero
|
||||
auto loadTextFile(const std::string& file_path) -> std::shared_ptr<TextFile>;
|
||||
|
||||
// Clase texto. Pinta texto en pantalla a partir de un bitmap
|
||||
class Text {
|
||||
public:
|
||||
// Tipos anidados públicos
|
||||
struct Offset {
|
||||
int x{0}, y{0}, w{0};
|
||||
};
|
||||
|
||||
struct File {
|
||||
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
|
||||
std::array<Offset, 128> offset{}; // Vector con las posiciones y ancho de cada letra
|
||||
};
|
||||
|
||||
// Constructor
|
||||
Text(const std::shared_ptr<Surface>& surface, const std::string& text_file);
|
||||
Text(const std::shared_ptr<Surface>& surface, const std::shared_ptr<File>& text_file);
|
||||
|
||||
// Destructor
|
||||
~Text() = default;
|
||||
|
||||
// Constantes de flags para writeDX
|
||||
static constexpr int COLOR_FLAG = 1;
|
||||
static constexpr int SHADOW_FLAG = 2;
|
||||
static constexpr int CENTER_FLAG = 4;
|
||||
static constexpr int STROKE_FLAG = 8;
|
||||
|
||||
void write(int x, int y, const std::string& text, int kerning = 1, int lenght = -1); // Escribe el texto en pantalla
|
||||
void writeColored(int x, int y, const std::string& text, Uint8 color, int kerning = 1, int lenght = -1); // Escribe el texto con colores
|
||||
void writeShadowed(int x, int y, const std::string& text, Uint8 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 writeDX(Uint8 flags, int x, int y, const std::string& text, int kerning = 1, Uint8 text_color = Uint8(), Uint8 shadow_distance = 1, Uint8 shadow_color = Uint8(), int lenght = -1); // Escribe texto con extras
|
||||
|
||||
auto writeToSurface(const std::string& text, int zoom = 1, int kerning = 1) -> std::shared_ptr<Surface>; // Escribe el texto en una textura
|
||||
auto writeDXToSurface(Uint8 flags, const std::string& text, int kerning = 1, Uint8 text_color = Uint8(), Uint8 shadow_distance = 1, Uint8 shadow_color = Uint8(), int lenght = -1) -> std::shared_ptr<Surface>; // Escribe el texto con extras en una textura
|
||||
|
||||
[[nodiscard]] auto length(const std::string& text, int kerning = 1) const -> int; // Obtiene la longitud en pixels de una cadena
|
||||
[[nodiscard]] auto getCharacterSize() const -> int; // Devuelve el tamaño del caracter
|
||||
|
||||
void setFixedWidth(bool value); // Establece si se usa un tamaño fijo de letra
|
||||
|
||||
static auto loadTextFile(const std::string& file_path) -> std::shared_ptr<File>; // Método de utilidad para cargar ficheros de texto
|
||||
|
||||
private:
|
||||
// Objetos y punteros
|
||||
std::unique_ptr<SurfaceSprite> sprite_ = nullptr; // Objeto con los graficos para el texto
|
||||
|
||||
// Variables
|
||||
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
|
||||
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
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
Text(const std::shared_ptr<Surface>& surface, const std::string& text_file);
|
||||
Text(const std::shared_ptr<Surface>& surface, const std::shared_ptr<TextFile>& text_file);
|
||||
|
||||
// Destructor
|
||||
~Text() = default;
|
||||
|
||||
// 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 una textura
|
||||
auto writeToSurface(const std::string& text, int zoom = 1, int kerning = 1) -> std::shared_ptr<Surface>;
|
||||
|
||||
// Escribe el texto con extras en una textura
|
||||
auto writeDXToSurface(Uint8 flags, const std::string& text, int kerning = 1, Uint8 text_color = Uint8(), Uint8 shadow_distance = 1, Uint8 shadow_color = Uint8(), int lenght = -1) -> std::shared_ptr<Surface>;
|
||||
|
||||
// Escribe el texto con colores
|
||||
void writeColored(int x, int y, const std::string& text, Uint8 color, int kerning = 1, int lenght = -1);
|
||||
|
||||
// Escribe el texto con sombra
|
||||
void writeShadowed(int x, int y, const std::string& text, Uint8 color, Uint8 shadow_distance = 1, 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 texto con extras
|
||||
void writeDX(Uint8 flags, int x, int y, const std::string& text, int kerning = 1, Uint8 text_color = Uint8(), Uint8 shadow_distance = 1, Uint8 shadow_color = Uint8(), int lenght = -1);
|
||||
|
||||
// Obtiene la longitud en pixels de una cadena
|
||||
[[nodiscard]] auto lenght(const std::string& text, int kerning = 1) const -> int;
|
||||
|
||||
// Devuelve el valor de la variable
|
||||
[[nodiscard]] auto getCharacterSize() const -> int;
|
||||
|
||||
// Establece si se usa un tamaño fijo de letra
|
||||
void setFixedWidth(bool value);
|
||||
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
|
||||
bool fixed_width_ = false; // Indica si el texto se ha de escribir con longitud fija en todas las letras
|
||||
std::array<Offset, 128> offset_{}; // Vector con las posiciones y ancho de cada letra
|
||||
};
|
||||
@@ -7,7 +7,30 @@
|
||||
struct Color; // lines 11-11
|
||||
|
||||
class Texture {
|
||||
public:
|
||||
explicit Texture(SDL_Renderer* renderer, std::string path = std::string()); // Constructor
|
||||
~Texture(); // Destructor
|
||||
|
||||
auto loadFromFile(const std::string& path) -> bool; // Carga una imagen desde un fichero
|
||||
auto createBlank(int width, int height, SDL_PixelFormat format = SDL_PIXELFORMAT_RGBA8888, SDL_TextureAccess access = SDL_TEXTUREACCESS_STREAMING) -> bool; // Crea una textura en blanco
|
||||
auto reLoad() -> bool; // Recarga la textura
|
||||
|
||||
void setColor(Uint8 red, Uint8 green, Uint8 blue); // Establece el color para la modulacion
|
||||
void setColor(Color color); // Establece el color para la modulacion
|
||||
void setBlendMode(SDL_BlendMode blending); // Establece el blending
|
||||
void setAlpha(Uint8 alpha); // Establece el alpha para la modulación
|
||||
void setAsRenderTarget(SDL_Renderer* renderer); // Establece la textura como objetivo de renderizado
|
||||
|
||||
void render(float x, float y, SDL_FRect* clip = nullptr, float zoom_w = 1, float zoom_h = 1, double angle = 0.0, SDL_FPoint* center = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE); // Renderiza la textura en un punto específico
|
||||
|
||||
[[nodiscard]] auto getWidth() const -> int { return width_; } // Obtiene el ancho de la imagen
|
||||
[[nodiscard]] auto getHeight() const -> int { return height_; } // Obtiene el alto de la imagen
|
||||
auto getSDLTexture() -> SDL_Texture*; // Obtiene la textura
|
||||
auto getRenderer() -> SDL_Renderer*; // Obtiene el renderizador
|
||||
|
||||
private:
|
||||
void unloadTexture(); // Libera la memoria de la textura
|
||||
|
||||
// Objetos y punteros
|
||||
SDL_Renderer* renderer_; // Renderizador donde dibujar la textura
|
||||
SDL_Texture* texture_ = nullptr; // La textura
|
||||
@@ -17,51 +40,4 @@ class Texture {
|
||||
float width_ = 0.0F; // Ancho de la imagen
|
||||
float height_ = 0.0F; // Alto de la imagen
|
||||
std::vector<std::vector<Uint32>> palettes_; // Vector con las diferentes paletas
|
||||
|
||||
// Libera la memoria de la textura
|
||||
void unloadTexture();
|
||||
|
||||
public:
|
||||
// Constructor
|
||||
explicit Texture(SDL_Renderer* renderer, std::string path = std::string());
|
||||
|
||||
// Destructor
|
||||
~Texture();
|
||||
|
||||
// Carga una imagen desde un fichero
|
||||
auto loadFromFile(const std::string& path) -> bool;
|
||||
|
||||
// Crea una textura en blanco
|
||||
auto createBlank(int width, int height, SDL_PixelFormat format = SDL_PIXELFORMAT_RGBA8888, SDL_TextureAccess access = SDL_TEXTUREACCESS_STREAMING) -> bool;
|
||||
|
||||
// Establece el color para la modulacion
|
||||
void setColor(Uint8 red, Uint8 green, Uint8 blue);
|
||||
void setColor(Color color);
|
||||
|
||||
// Establece el blending
|
||||
void setBlendMode(SDL_BlendMode blending);
|
||||
|
||||
// Establece el alpha para la modulación
|
||||
void setAlpha(Uint8 alpha);
|
||||
|
||||
// Renderiza la textura en un punto específico
|
||||
void render(float x, float y, SDL_FRect* clip = nullptr, float zoom_w = 1, float zoom_h = 1, double angle = 0.0, SDL_FPoint* center = nullptr, SDL_FlipMode flip = SDL_FLIP_NONE);
|
||||
|
||||
// Establece la textura como objetivo de renderizado
|
||||
void setAsRenderTarget(SDL_Renderer* renderer);
|
||||
|
||||
// Obtiene el ancho de la imagen
|
||||
[[nodiscard]] auto getWidth() const -> int { return width_; }
|
||||
|
||||
// Obtiene el alto de la imagen
|
||||
[[nodiscard]] auto getHeight() const -> int { return height_; }
|
||||
|
||||
// Recarga la textura
|
||||
auto reLoad() -> bool;
|
||||
|
||||
// Obtiene la textura
|
||||
auto getSDLTexture() -> SDL_Texture*;
|
||||
|
||||
// Obtiene el renderizador
|
||||
auto getRenderer() -> SDL_Renderer*;
|
||||
};
|
||||
@@ -125,7 +125,7 @@ auto Cache::getPalette(const std::string& name) -> Palette {
|
||||
}
|
||||
|
||||
// Obtiene el fichero de texto a partir de un nombre
|
||||
auto Cache::getTextFile(const std::string& name) -> std::shared_ptr<TextFile> {
|
||||
auto Cache::getTextFile(const std::string& name) -> std::shared_ptr<Text::File> {
|
||||
auto it = std::ranges::find_if(text_files_, [&name](const auto& t) { return t.name == name; });
|
||||
|
||||
if (it != text_files_.end()) {
|
||||
@@ -287,7 +287,7 @@ void Cache::loadTextFiles() {
|
||||
|
||||
for (const auto& l : list) {
|
||||
auto name = getFileName(l);
|
||||
text_files_.emplace_back(name, loadTextFile(l));
|
||||
text_files_.emplace_back(name, Text::loadTextFile(l));
|
||||
updateLoadingProgress();
|
||||
}
|
||||
}
|
||||
@@ -426,7 +426,7 @@ void Cache::renderProgress() {
|
||||
// Draw APP_NAME centered above center
|
||||
const std::string APP_NAME = spaceBetweenLetters(Version::APP_NAME);
|
||||
loading_text_->writeColored(
|
||||
CENTER_X - (loading_text_->lenght(APP_NAME) / 2),
|
||||
CENTER_X - (loading_text_->length(APP_NAME) / 2),
|
||||
CENTER_Y - TEXT_HEIGHT,
|
||||
APP_NAME,
|
||||
LOADING_TEXT_COLOR);
|
||||
@@ -434,7 +434,7 @@ void Cache::renderProgress() {
|
||||
// Draw VERSION centered below center
|
||||
const std::string VERSION_TEXT = "(" + std::string(Version::GIT_HASH) + ")";
|
||||
loading_text_->writeColored(
|
||||
CENTER_X - (loading_text_->lenght(VERSION_TEXT) / 2),
|
||||
CENTER_X - (loading_text_->length(VERSION_TEXT) / 2),
|
||||
CENTER_Y + TEXT_HEIGHT,
|
||||
VERSION_TEXT,
|
||||
LOADING_TEXT_COLOR);
|
||||
|
||||
@@ -58,11 +58,11 @@ struct ResourcePalette {
|
||||
|
||||
// Estructura para almacenar ficheros TextFile y su nombre
|
||||
struct ResourceTextFile {
|
||||
std::string name; // Nombre del fichero
|
||||
std::shared_ptr<TextFile> text_file; // Objeto con los descriptores de la fuente de texto
|
||||
std::string name; // Nombre del fichero
|
||||
std::shared_ptr<Text::File> text_file; // Objeto con los descriptores de la fuente de texto
|
||||
|
||||
// Constructor
|
||||
ResourceTextFile(std::string name, std::shared_ptr<TextFile> text_file)
|
||||
ResourceTextFile(std::string name, std::shared_ptr<Text::File> text_file)
|
||||
: name(std::move(name)),
|
||||
text_file(std::move(std::move(text_file))) {}
|
||||
};
|
||||
@@ -80,7 +80,7 @@ struct ResourceText {
|
||||
|
||||
// Estructura para almacenar ficheros animaciones y su nombre
|
||||
struct ResourceAnimation {
|
||||
std::string name; // Nombre del fichero
|
||||
std::string name; // Nombre del fichero
|
||||
SurfaceAnimatedSprite::Animations animation; // Objeto con las animaciones
|
||||
|
||||
// Constructor
|
||||
@@ -239,7 +239,7 @@ class Cache {
|
||||
auto getPalette(const std::string& name) -> Palette;
|
||||
|
||||
// Obtiene el fichero de texto a partir de un nombre
|
||||
auto getTextFile(const std::string& name) -> std::shared_ptr<TextFile>;
|
||||
auto getTextFile(const std::string& name) -> std::shared_ptr<Text::File>;
|
||||
|
||||
// Obtiene el objeto de texto a partir de un nombre
|
||||
auto getText(const std::string& name) -> std::shared_ptr<Text>;
|
||||
|
||||
@@ -8,35 +8,28 @@
|
||||
// Clase Debug
|
||||
class Debug {
|
||||
public:
|
||||
// [SINGLETON] Crearemos el objeto con esta función estática
|
||||
static void init();
|
||||
static void init(); // [SINGLETON] Crearemos el objeto con esta función estática
|
||||
static void destroy(); // [SINGLETON] Destruiremos el objeto con esta función estática
|
||||
static auto get() -> Debug*; // [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
|
||||
|
||||
// [SINGLETON] Destruiremos el objeto con esta función estática
|
||||
static void destroy();
|
||||
void render(); // Dibuja en pantalla
|
||||
|
||||
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
|
||||
static auto get() -> Debug*;
|
||||
void setPos(SDL_FPoint p); // Establece la posición donde se colocará la información de debug
|
||||
|
||||
// Dibuja en pantalla
|
||||
void render();
|
||||
[[nodiscard]] auto getEnabled() const -> bool { return enabled_; } // Obtiene si el debug está activo
|
||||
|
||||
// Establece la posición donde se colocará la información de debug
|
||||
void setPos(SDL_FPoint p);
|
||||
|
||||
// Getters
|
||||
[[nodiscard]] auto getEnabled() const -> bool { return enabled_; }
|
||||
|
||||
// Setters
|
||||
void add(const std::string& text) { slot_.push_back(text); }
|
||||
void clear() { slot_.clear(); }
|
||||
void addToLog(const std::string& text) { log_.push_back(text); }
|
||||
void clearLog() { log_.clear(); }
|
||||
void setEnabled(bool value) { enabled_ = value; }
|
||||
void toggleEnabled() { enabled_ = !enabled_; }
|
||||
void add(const std::string& text) { slot_.push_back(text); } // Añade texto al slot de debug
|
||||
void clear() { slot_.clear(); } // Limpia el slot de debug
|
||||
void addToLog(const std::string& text) { log_.push_back(text); } // Añade texto al log
|
||||
void clearLog() { log_.clear(); } // Limpia el log
|
||||
void setEnabled(bool value) { enabled_ = value; } // Establece si el debug está activo
|
||||
void toggleEnabled() { enabled_ = !enabled_; } // Alterna el estado del debug
|
||||
|
||||
private:
|
||||
// [SINGLETON] Objeto privado
|
||||
static Debug* debug;
|
||||
static Debug* debug; // [SINGLETON] Objeto privado
|
||||
|
||||
Debug() = default; // Constructor
|
||||
~Debug() = default; // Destructor
|
||||
|
||||
// Variables
|
||||
std::vector<std::string> slot_; // Vector con los textos a escribir
|
||||
@@ -44,10 +37,4 @@ class Debug {
|
||||
int x_ = 0; // Posicion donde escribir el texto de debug
|
||||
int y_ = 0; // Posición donde escribir el texto de debug
|
||||
bool enabled_ = false; // Indica si esta activo el modo debug
|
||||
|
||||
// Constructor
|
||||
Debug() = default;
|
||||
|
||||
// Destructor
|
||||
~Debug() = default;
|
||||
};
|
||||
@@ -8,58 +8,44 @@ class SurfaceAnimatedSprite; // lines 7-7
|
||||
|
||||
class Enemy {
|
||||
public:
|
||||
// --- Estructuras ---
|
||||
struct Data {
|
||||
/* [DOC:29/10/2025] la surface ara se pillarà del .ANI
|
||||
std::string surface_path{}; // Ruta al fichero con la textura
|
||||
[/DOC] */
|
||||
std::string animation_path; // Ruta al fichero con la animación
|
||||
/* [DOC:29/10/2025] w i h ja no fan falta, se pilla del .ANI
|
||||
int w = 0; // Anchura del enemigo
|
||||
int h = 0; // Altura del enemigo
|
||||
[/DOC] */
|
||||
float x = 0.0F; // Posición inicial en el eje X
|
||||
float y = 0.0F; // Posición inicial en el eje Y
|
||||
float vx = 0.0F; // Velocidad en el eje X
|
||||
float vy = 0.0F; // Velocidad en el eje Y
|
||||
int x1 = 0; // Límite izquierdo de la ruta en el eje X
|
||||
int x2 = 0; // Límite derecho de la ruta en el eje X
|
||||
int y1 = 0; // Límite superior de la ruta en el eje Y
|
||||
int y2 = 0; // Límite inferior de la ruta en el eje Y
|
||||
bool flip = false; // Indica si el enemigo hace flip al terminar su ruta
|
||||
bool mirror = false; // Indica si el enemigo está volteado verticalmente
|
||||
int frame = 0; // Frame inicial para la animación del enemigo
|
||||
std::string color; // Color del enemigo
|
||||
|
||||
// Constructor por defecto
|
||||
Data() = default;
|
||||
float x{0.0F}; // Posición inicial en el eje X
|
||||
float y{0.0F}; // Posición inicial en el eje Y
|
||||
float vx{0.0F}; // Velocidad en el eje X
|
||||
float vy{0.0F}; // Velocidad en el eje Y
|
||||
int x1{0}; // Límite izquierdo de la ruta en el eje X
|
||||
int x2{0}; // Límite derecho de la ruta en el eje X
|
||||
int y1{0}; // Límite superior de la ruta en el eje Y
|
||||
int y2{0}; // Límite inferior de la ruta en el eje Y
|
||||
bool flip{false}; // Indica si el enemigo hace flip al terminar su ruta
|
||||
bool mirror{false}; // Indica si el enemigo está volteado verticalmente
|
||||
int frame{0}; // Frame inicial para la animación del enemigo
|
||||
std::string color; // Color del enemigo
|
||||
};
|
||||
|
||||
// --- Constructor y Destructor ---
|
||||
explicit Enemy(const Data& enemy);
|
||||
~Enemy() = default;
|
||||
explicit Enemy(const Data& enemy); // Constructor
|
||||
~Enemy() = default; // Destructor
|
||||
|
||||
// --- Funciones ---
|
||||
void render(); // Pinta el enemigo en pantalla
|
||||
void update(float delta_time); // Actualiza las variables del objeto
|
||||
|
||||
auto getRect() -> SDL_FRect; // Devuelve el rectangulo que contiene al enemigo
|
||||
auto getCollider() -> SDL_FRect&; // Obtiene el rectangulo de colision del enemigo
|
||||
|
||||
private:
|
||||
// --- Objetos y punteros ---
|
||||
void checkPath(); // Comprueba si ha llegado al limite del recorrido para darse media vuelta
|
||||
|
||||
std::shared_ptr<SurfaceAnimatedSprite> sprite_; // Sprite del enemigo
|
||||
|
||||
// --- Variables ---
|
||||
Uint8 color_; // Color del enemigo
|
||||
std::string color_string_; // Color del enemigo en formato texto
|
||||
int x1_; // Limite izquierdo de la ruta en el eje X
|
||||
int x2_; // Limite derecho de la ruta en el eje X
|
||||
int y1_; // Limite superior de la ruta en el eje Y
|
||||
int y2_; // Limite inferior de la ruta en el eje Y
|
||||
SDL_FRect collider_; // Caja de colisión
|
||||
bool should_flip_; // Indica si el enemigo hace flip al terminar su ruta
|
||||
bool should_mirror_; // Indica si el enemigo se dibuja volteado verticalmente
|
||||
|
||||
// --- Comprueba si ha llegado al limite del recorrido para darse media vuelta ---
|
||||
void checkPath();
|
||||
// Variables
|
||||
Uint8 color_{0}; // Color del enemigo
|
||||
std::string color_string_; // Color del enemigo en formato texto
|
||||
int x1_{0}; // Limite izquierdo de la ruta en el eje X
|
||||
int x2_{0}; // Limite derecho de la ruta en el eje X
|
||||
int y1_{0}; // Limite superior de la ruta en el eje Y
|
||||
int y2_{0}; // Limite inferior de la ruta en el eje Y
|
||||
SDL_FRect collider_{}; // Caja de colisión
|
||||
bool should_flip_{false}; // Indica si el enemigo hace flip al terminar su ruta
|
||||
bool should_mirror_{false}; // Indica si el enemigo se dibuja volteado verticalmente
|
||||
};
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
// Constructor
|
||||
Item::Item(const Data& item)
|
||||
: sprite_(std::make_shared<SurfaceSprite>(Resource::Cache::get()->getSurface(item.tile_set_file), item.x, item.y, ITEM_SIZE, ITEM_SIZE)),
|
||||
time_accumulator_(static_cast<float>(item.counter) * COLOR_CHANGE_INTERVAL),
|
||||
is_paused_(false) {
|
||||
time_accumulator_(static_cast<float>(item.counter) * COLOR_CHANGE_INTERVAL) {
|
||||
// Inicia variables
|
||||
sprite_->setClip((item.tile % 10) * ITEM_SIZE, (item.tile / 10) * ITEM_SIZE, ITEM_SIZE, ITEM_SIZE);
|
||||
collider_ = sprite_->getRect();
|
||||
|
||||
@@ -9,43 +9,36 @@ class SurfaceSprite;
|
||||
|
||||
class Item {
|
||||
public:
|
||||
// --- Estructuras ---
|
||||
struct Data {
|
||||
std::string tile_set_file; // Ruta al fichero con los gráficos del item
|
||||
float x{0}; // Posición del item en pantalla
|
||||
float y{0}; // Posición del item en pantalla
|
||||
float x{0.0F}; // Posición del item en pantalla
|
||||
float y{0.0F}; // Posición del item en pantalla
|
||||
int tile{0}; // Número de tile dentro de la textura
|
||||
int counter{0}; // Contador inicial. Es el que lo hace cambiar de color
|
||||
Uint8 color1{}; // Uno de los dos colores que se utiliza para el item
|
||||
Uint8 color2{}; // Uno de los dos colores que se utiliza para el item
|
||||
|
||||
// Constructor
|
||||
Data() = default;
|
||||
Uint8 color1{0}; // Uno de los dos colores que se utiliza para el item
|
||||
Uint8 color2{0}; // Uno de los dos colores que se utiliza para el item
|
||||
};
|
||||
|
||||
// Constructor y Destructor
|
||||
explicit Item(const Data& item);
|
||||
~Item() = default;
|
||||
explicit Item(const Data& item); // Constructor
|
||||
~Item() = default; // Destructor
|
||||
|
||||
void render() const; // Pinta el objeto en pantalla
|
||||
void update(float delta_time); // Actualiza las variables del objeto
|
||||
|
||||
// --- Funciones ---
|
||||
void render() const; // Pinta el objeto en pantalla
|
||||
void update(float delta_time); // Actualiza las variables del objeto
|
||||
void setPaused(bool paused) { is_paused_ = paused; } // Pausa/despausa el item
|
||||
auto getCollider() -> SDL_FRect& { return collider_; } // Obtiene el rectangulo de colision del objeto
|
||||
auto getPos() -> SDL_FPoint; // Obtiene su ubicación
|
||||
void setColors(Uint8 col1, Uint8 col2); // Asigna los colores del objeto
|
||||
|
||||
private:
|
||||
// --- Constantes ---
|
||||
static constexpr float ITEM_SIZE = 8;
|
||||
static constexpr float ITEM_SIZE = 8.0F; // Tamaño del item en pixels
|
||||
static constexpr float COLOR_CHANGE_INTERVAL = 0.06F; // Intervalo de cambio de color en segundos (4 frames a 66.67fps)
|
||||
|
||||
// --- Objetos y punteros ---
|
||||
std::shared_ptr<SurfaceSprite> sprite_; // SSprite del objeto
|
||||
|
||||
// --- Variables ---
|
||||
std::vector<Uint8> color_; // Vector con los colores del objeto
|
||||
float time_accumulator_; // Acumulador de tiempo para cambio de color
|
||||
SDL_FRect collider_; // Rectangulo de colisión
|
||||
bool is_paused_; // Indica si el item está pausado
|
||||
// Variables
|
||||
std::vector<Uint8> color_; // Vector con los colores del objeto
|
||||
float time_accumulator_{0.0F}; // Acumulador de tiempo para cambio de color
|
||||
SDL_FRect collider_{}; // Rectangulo de colisión
|
||||
bool is_paused_{false}; // Indica si el item está pausado
|
||||
};
|
||||
@@ -1,628 +0,0 @@
|
||||
// IWYU pragma: no_include <bits/std_abs.h>
|
||||
#include "game/entities/player.hpp"
|
||||
|
||||
#include <algorithm> // Para max, min
|
||||
#include <cmath> // Para ceil, abs
|
||||
#include <iostream>
|
||||
#include <ranges> // Para std::ranges::any_of
|
||||
|
||||
#include "core/audio/audio.hpp" // Para Audio
|
||||
#include "core/input/input.hpp" // Para Input, InputAction
|
||||
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||
#include "core/resources/resource_cache.hpp" // Para Resource
|
||||
#include "game/gameplay/room.hpp" // Para Room, TileType
|
||||
#include "game/options.hpp" // Para Cheat, Options, options
|
||||
#include "utils/defines.hpp" // Para RoomBorder::BOTTOM, RoomBorder::LEFT, RoomBorder::RIGHT
|
||||
|
||||
// Constructor
|
||||
Player::Player(const Data& player)
|
||||
: room_(player.room) {
|
||||
// Inicializa algunas variables
|
||||
initSprite(player.animations_path);
|
||||
setColor();
|
||||
applySpawnValues(player.spawn_data);
|
||||
placeSprite();
|
||||
initSounds();
|
||||
|
||||
previous_state_ = state_;
|
||||
}
|
||||
|
||||
// Pinta el jugador en pantalla
|
||||
void Player::render() {
|
||||
sprite_->render(1, color_);
|
||||
}
|
||||
|
||||
// Actualiza las variables del objeto
|
||||
void Player::update(float delta_time) {
|
||||
if (!is_paused_) {
|
||||
handleInput(delta_time); // Comprueba las entradas y modifica variables
|
||||
move(delta_time); // Recalcula la posición del jugador
|
||||
animate(delta_time); // Establece la animación del jugador
|
||||
handleBorders(); // Comprueba si está situado en alguno de los cuatro bordes de la habitación
|
||||
handleJumpEnd(); // Comprueba si ha finalizado el salto al alcanzar la altura de inicio
|
||||
handleKillingTiles(); // Comprueba que el jugador no toque ningun tile de los que matan
|
||||
setColor(); // Establece el color del jugador
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba las entradas y modifica variables
|
||||
void Player::handleInput(float delta_time) {
|
||||
(void)delta_time; // No usado en este método, pero mantenido para consistencia
|
||||
|
||||
// Solo comprueba las entradas de dirección cuando está sobre una superficie
|
||||
if (state_ != State::STANDING) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!auto_movement_) {
|
||||
// Comprueba las entradas de desplazamiento lateral solo en el caso de no estar enganchado a una superficie automatica
|
||||
if (Input::get()->checkAction(InputAction::LEFT)) {
|
||||
vx_ = -HORIZONTAL_VELOCITY;
|
||||
sprite_->setFlip(SDL_FLIP_HORIZONTAL);
|
||||
}
|
||||
|
||||
else if (Input::get()->checkAction(InputAction::RIGHT)) {
|
||||
vx_ = HORIZONTAL_VELOCITY;
|
||||
sprite_->setFlip(SDL_FLIP_NONE);
|
||||
}
|
||||
|
||||
else {
|
||||
// No se pulsa ninguna dirección
|
||||
vx_ = 0.0F;
|
||||
if (isOnAutoSurface()) {
|
||||
// Si deja de moverse sobre una superficie se engancha
|
||||
auto_movement_ = true;
|
||||
}
|
||||
}
|
||||
} else { // El movimiento lo proporciona la superficie
|
||||
vx_ = HORIZONTAL_VELOCITY * room_->getAutoSurfaceDirection();
|
||||
|
||||
if (vx_ > 0.0F) {
|
||||
sprite_->setFlip(SDL_FLIP_NONE);
|
||||
} else {
|
||||
sprite_->setFlip(SDL_FLIP_HORIZONTAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (Input::get()->checkAction(InputAction::JUMP)) {
|
||||
// Solo puede saltar si ademas de estar (state == STANDING)
|
||||
// Esta sobre el suelo, rampa o suelo que se mueve
|
||||
// Esto es para evitar el salto desde el vacio al cambiar de pantalla verticalmente
|
||||
// Ya que se coloca el estado STANDING al cambiar de pantalla
|
||||
|
||||
if (isOnFloor() || isOnAutoSurface()) {
|
||||
transitionToState(State::JUMPING);
|
||||
vy_ = JUMP_VELOCITY;
|
||||
last_grounded_position_ = static_cast<int>(y_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba si está situado en alguno de los cuatro bordes de la habitación
|
||||
void Player::handleBorders() {
|
||||
if (x_ < PLAY_AREA_LEFT) {
|
||||
border_ = Room::Border::LEFT;
|
||||
is_on_border_ = true;
|
||||
}
|
||||
|
||||
else if (x_ + WIDTH > PLAY_AREA_RIGHT) {
|
||||
border_ = Room::Border::RIGHT;
|
||||
is_on_border_ = true;
|
||||
}
|
||||
|
||||
else if (y_ < PLAY_AREA_TOP) {
|
||||
border_ = Room::Border::TOP;
|
||||
is_on_border_ = true;
|
||||
}
|
||||
|
||||
else if (y_ + HEIGHT > PLAY_AREA_BOTTOM) {
|
||||
border_ = Room::Border::BOTTOM;
|
||||
is_on_border_ = true;
|
||||
}
|
||||
|
||||
else {
|
||||
is_on_border_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba el estado del jugador
|
||||
void Player::handleState(float delta_time) {
|
||||
(void)delta_time; // No usado actualmente
|
||||
|
||||
// Reproduce sonidos según el estado
|
||||
if (state_ == State::FALLING) {
|
||||
playFallSound();
|
||||
} else if (state_ == State::STANDING) {
|
||||
// Si no tiene suelo debajo y no está en rampa descendente -> FALLING
|
||||
if (!isOnFloor() && !isOnAutoSurface() && !isOnDownSlope()) {
|
||||
last_grounded_position_ = static_cast<int>(y_); // Guarda Y actual al SALIR de STANDING
|
||||
transitionToState(State::FALLING); // setState() establece vx_=0, vy_=MAX_VY
|
||||
playFallSound();
|
||||
}
|
||||
} else if (state_ == State::JUMPING) {
|
||||
playJumpSound();
|
||||
}
|
||||
}
|
||||
|
||||
// Cambia al jugador de un borde al opuesto. Util para el cambio de pantalla
|
||||
void Player::switchBorders() {
|
||||
switch (border_) {
|
||||
case Room::Border::TOP:
|
||||
y_ = PLAY_AREA_BOTTOM - HEIGHT - TILE_SIZE;
|
||||
transitionToState(State::STANDING);
|
||||
break;
|
||||
|
||||
case Room::Border::BOTTOM:
|
||||
y_ = PLAY_AREA_TOP;
|
||||
transitionToState(State::STANDING);
|
||||
break;
|
||||
|
||||
case Room::Border::RIGHT:
|
||||
x_ = PLAY_AREA_LEFT;
|
||||
break;
|
||||
|
||||
case Room::Border::LEFT:
|
||||
x_ = PLAY_AREA_RIGHT - WIDTH;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// CRÍTICO: Resetear last_grounded_position_ para evitar muerte falsa por diferencia de Y entre pantallas
|
||||
last_grounded_position_ = static_cast<int>(y_);
|
||||
is_on_border_ = false;
|
||||
placeSprite();
|
||||
}
|
||||
|
||||
// Aplica gravedad al jugador
|
||||
void Player::applyGravity(float delta_time) {
|
||||
// La gravedad solo se aplica cuando el jugador esta saltando
|
||||
// Nunca mientras cae o esta de pie
|
||||
if (state_ == State::JUMPING) {
|
||||
vy_ += GRAVITY_FORCE * delta_time;
|
||||
vy_ = std::min(vy_, MAX_VY);
|
||||
}
|
||||
}
|
||||
|
||||
// Maneja el movimiento sobre rampas
|
||||
// direction: -1 para izquierda, 1 para derecha
|
||||
void Player::handleSlopeMovement(int direction) {
|
||||
// No procesa rampas durante el salto (permite atravesarlas cuando salta con movimiento horizontal)
|
||||
// Pero SÍ procesa en STANDING y FALLING (para pegarse a las rampas)
|
||||
if (state_ == State::JUMPING) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Regla: Si está bajando la rampa, se pega a la slope
|
||||
if (isOnDownSlope()) {
|
||||
y_ += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// Regla: Si está STANDING y tropieza lateralmente con una Slope, se pega a la slope
|
||||
// Comprueba si hay rampa en contacto lateral (solo los dos pixels inferiores)
|
||||
const int SIDE_X = direction < 0 ? static_cast<int>(x_) : static_cast<int>(x_) + WIDTH - 1;
|
||||
const LineVertical SIDE = {
|
||||
.x = SIDE_X,
|
||||
.y1 = static_cast<int>(y_) + HEIGHT - 2,
|
||||
.y2 = static_cast<int>(y_) + HEIGHT - 1};
|
||||
|
||||
// Comprueba la rampa correspondiente según la dirección
|
||||
const int SLOPE_Y = direction < 0 ? room_->checkLeftSlopes(&SIDE) : room_->checkRightSlopes(&SIDE);
|
||||
|
||||
if (SLOPE_Y > -1) {
|
||||
// Hay rampa: sube al jugador para pegarlo a la rampa
|
||||
y_ = SLOPE_Y - HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
// Maneja el movimiento horizontal
|
||||
// direction: -1 para izquierda, 1 para derecha
|
||||
void Player::moveHorizontal(float delta_time, int direction) {
|
||||
const float DISPLACEMENT = vx_ * delta_time;
|
||||
|
||||
// Crea el rectangulo de proyección en el eje X para ver si colisiona
|
||||
SDL_FRect proj;
|
||||
if (direction < 0) {
|
||||
// Movimiento a la izquierda
|
||||
proj = {
|
||||
.x = x_ + DISPLACEMENT,
|
||||
.y = y_,
|
||||
.w = std::ceil(std::fabs(DISPLACEMENT)),
|
||||
.h = HEIGHT};
|
||||
} else {
|
||||
// Movimiento a la derecha
|
||||
proj = {
|
||||
.x = x_ + WIDTH,
|
||||
.y = y_,
|
||||
.w = std::ceil(DISPLACEMENT),
|
||||
.h = HEIGHT};
|
||||
}
|
||||
|
||||
// Comprueba la colisión con las superficies
|
||||
const int POS = direction < 0 ? room_->checkRightSurfaces(&proj) : room_->checkLeftSurfaces(&proj);
|
||||
|
||||
// Calcula la nueva posición
|
||||
if (POS == -1) {
|
||||
// No hay colisión: mueve al jugador
|
||||
x_ += DISPLACEMENT;
|
||||
} else {
|
||||
// Hay colisión: reposiciona al jugador en el punto de colisión
|
||||
x_ = direction < 0 ? POS + 1 : POS - WIDTH;
|
||||
}
|
||||
|
||||
// Maneja el movimiento sobre rampas
|
||||
handleSlopeMovement(direction);
|
||||
}
|
||||
|
||||
// Maneja el movimiento vertical hacia arriba
|
||||
void Player::moveVerticalUp(float delta_time) {
|
||||
// Crea el rectangulo de proyección en el eje Y para ver si colisiona
|
||||
const float DISPLACEMENT = vy_ * delta_time;
|
||||
SDL_FRect proj = {
|
||||
.x = x_,
|
||||
.y = y_ + DISPLACEMENT,
|
||||
.w = WIDTH,
|
||||
.h = std::ceil(std::fabs(DISPLACEMENT)) // Para evitar que tenga una altura de 0 pixels
|
||||
};
|
||||
|
||||
// Comprueba la colisión
|
||||
const int POS = room_->checkBottomSurfaces(&proj);
|
||||
|
||||
// Calcula la nueva posición
|
||||
if (POS == -1) {
|
||||
// Si no hay colisión
|
||||
y_ += DISPLACEMENT;
|
||||
} else {
|
||||
// Si hay colisión lo mueve hasta donde no colisiona
|
||||
// Regla: Si está JUMPING y tropieza contra el techo -> FALLING
|
||||
y_ = POS + 1;
|
||||
transitionToState(State::FALLING);
|
||||
}
|
||||
}
|
||||
|
||||
// Maneja el movimiento vertical hacia abajo
|
||||
void Player::moveVerticalDown(float delta_time) {
|
||||
// Crea el rectangulo de proyección en el eje Y para ver si colisiona
|
||||
const float DISPLACEMENT = vy_ * delta_time;
|
||||
SDL_FRect proj = {
|
||||
.x = x_,
|
||||
.y = y_ + HEIGHT,
|
||||
.w = WIDTH,
|
||||
.h = std::ceil(DISPLACEMENT) // Para evitar que tenga una altura de 0 pixels
|
||||
};
|
||||
|
||||
// Comprueba la colisión con las superficies normales y las automáticas
|
||||
const float POS = std::max(room_->checkTopSurfaces(&proj), room_->checkAutoSurfaces(&proj));
|
||||
if (POS > -1) {
|
||||
// Si hay colisión lo mueve hasta donde no colisiona y pasa a estar sobre la superficie
|
||||
y_ = POS - HEIGHT;
|
||||
|
||||
// VERIFICAR MUERTE ANTES de cambiar de estado (PLAYER_MECHANICS.md línea 1268-1274)
|
||||
const int FALL_DISTANCE = static_cast<int>(y_) - last_grounded_position_;
|
||||
if (previous_state_ == State::FALLING && FALL_DISTANCE > MAX_FALLING_HEIGHT) {
|
||||
is_alive_ = false; // Muere si cae más de 32 píxeles
|
||||
}
|
||||
|
||||
transitionToState(State::STANDING);
|
||||
last_grounded_position_ = static_cast<int>(y_); // Actualizar AL ENTRAR en STANDING
|
||||
// Deja de estar enganchado a la superficie automatica
|
||||
auto_movement_ = false;
|
||||
} else {
|
||||
// Si no hay colisión con los muros, comprueba la colisión con las rampas
|
||||
// CORRECCIÓN: FALLING siempre se pega a rampas, JUMPING se pega solo si vx_ == 0
|
||||
if (state_ == State::FALLING || (state_ == State::JUMPING && vx_ == 0.0F)) {
|
||||
// No está saltando O salta recto: se pega a las rampas
|
||||
auto rect = toSDLRect(proj);
|
||||
const LineVertical LEFT_SIDE = {.x = rect.x, .y1 = rect.y, .y2 = rect.y + rect.h - 1};
|
||||
const LineVertical RIGHT_SIDE = {.x = rect.x + rect.w - 1, .y1 = rect.y, .y2 = rect.y + rect.h - 1};
|
||||
const float POINT = std::max(room_->checkRightSlopes(&RIGHT_SIDE), room_->checkLeftSlopes(&LEFT_SIDE));
|
||||
if (POINT > -1) {
|
||||
// No está saltando y hay colisión con una rampa
|
||||
// Calcula la nueva posición
|
||||
y_ = POINT - HEIGHT;
|
||||
|
||||
// VERIFICAR MUERTE ANTES de cambiar de estado (PLAYER_MECHANICS.md línea 1268-1274)
|
||||
const int FALL_DISTANCE = static_cast<int>(y_) - last_grounded_position_;
|
||||
if (previous_state_ == State::FALLING && FALL_DISTANCE > MAX_FALLING_HEIGHT) {
|
||||
is_alive_ = false; // Muere si cae más de 32 píxeles
|
||||
}
|
||||
|
||||
transitionToState(State::STANDING);
|
||||
last_grounded_position_ = static_cast<int>(y_); // Actualizar AL ENTRAR en STANDING
|
||||
} else {
|
||||
// No está saltando y no hay colisón con una rampa
|
||||
// Calcula la nueva posición
|
||||
y_ += DISPLACEMENT;
|
||||
}
|
||||
} else {
|
||||
// Esta saltando con movimiento horizontal y no hay colisión con los muros
|
||||
// Calcula la nueva posición (atraviesa rampas)
|
||||
y_ += DISPLACEMENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Orquesta el movimiento del jugador
|
||||
void Player::move(float delta_time) {
|
||||
applyGravity(delta_time); // Aplica gravedad al jugador
|
||||
handleState(delta_time); // Comprueba el estado del jugador
|
||||
|
||||
// Movimiento horizontal
|
||||
if (vx_ < 0.0F) {
|
||||
moveHorizontal(delta_time, -1); // Izquierda
|
||||
} else if (vx_ > 0.0F) {
|
||||
moveHorizontal(delta_time, 1); // Derecha
|
||||
}
|
||||
|
||||
// Si ha salido del suelo, el jugador cae
|
||||
if (state_ == State::STANDING && !isOnFloor()) {
|
||||
transitionToState(State::FALLING);
|
||||
auto_movement_ = false;
|
||||
}
|
||||
|
||||
// Si ha salido de una superficie automatica, detiene el movimiento automatico
|
||||
if (state_ == State::STANDING && isOnFloor() && !isOnAutoSurface()) {
|
||||
auto_movement_ = false;
|
||||
}
|
||||
|
||||
// Movimiento vertical
|
||||
if (vy_ < 0.0F) {
|
||||
moveVerticalUp(delta_time);
|
||||
} else if (vy_ > 0.0F) {
|
||||
moveVerticalDown(delta_time);
|
||||
}
|
||||
|
||||
y_prev_ = y_; // Guarda Y DESPUÉS de todo el movimiento (para detectar hitos en sonidos)
|
||||
|
||||
// Actualiza la geometría del collider y sprite
|
||||
updateColliderGeometry();
|
||||
}
|
||||
|
||||
// Establece la animación del jugador
|
||||
void Player::animate(float delta_time) {
|
||||
if (vx_ != 0) {
|
||||
sprite_->update(delta_time);
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba si ha finalizado el salto al alcanzar la altura de inicio
|
||||
void Player::handleJumpEnd() {
|
||||
// Si el jugador vuelve EXACTAMENTE a la altura inicial, debe CONTINUAR en JUMPING
|
||||
// Solo cuando la SUPERA (desciende más allá) cambia a FALLING
|
||||
if (state_ == State::JUMPING && vy_ > 0.0F && static_cast<int>(y_) > last_grounded_position_) {
|
||||
transitionToState(State::FALLING);
|
||||
}
|
||||
}
|
||||
|
||||
// Calcula y reproduce el sonido de salto basado en distancia vertical recorrida
|
||||
void Player::playJumpSound() {
|
||||
// Sistema basado en distancia vertical, no en tiempo (PLAYER_MECHANICS.md línea 107-120)
|
||||
const float DISTANCE_FROM_START = std::abs(y_ - static_cast<float>(last_grounded_position_));
|
||||
const int SOUND_INDEX = static_cast<int>(DISTANCE_FROM_START / SOUND_DISTANCE_INTERVAL);
|
||||
|
||||
// Calcular índice previo (frame anterior)
|
||||
const float PREV_DISTANCE = std::abs(y_prev_ - static_cast<float>(last_grounded_position_));
|
||||
const int PREVIOUS_INDEX = static_cast<int>(PREV_DISTANCE / SOUND_DISTANCE_INTERVAL);
|
||||
|
||||
// Solo reproduce cuando cambia de índice (nuevo hito alcanzado)
|
||||
if (SOUND_INDEX != PREVIOUS_INDEX && SOUND_INDEX < static_cast<int>(jumping_sound_.size())) {
|
||||
Audio::get()->playSound(jumping_sound_[SOUND_INDEX], Audio::Group::GAME);
|
||||
}
|
||||
}
|
||||
|
||||
// Calcula y reproduce el sonido de caída basado en distancia vertical recorrida
|
||||
void Player::playFallSound() {
|
||||
// Sistema basado en distancia vertical, no en tiempo (PLAYER_MECHANICS.md línea 193-206)
|
||||
const float DISTANCE_FALLEN = y_ - static_cast<float>(last_grounded_position_);
|
||||
const int SOUND_INDEX = static_cast<int>(DISTANCE_FALLEN / SOUND_DISTANCE_INTERVAL);
|
||||
|
||||
// Calcular índice previo (frame anterior)
|
||||
const float PREV_DISTANCE = y_prev_ - static_cast<float>(last_grounded_position_);
|
||||
const int PREVIOUS_INDEX = static_cast<int>(PREV_DISTANCE / SOUND_DISTANCE_INTERVAL);
|
||||
|
||||
// Solo reproduce cuando cambia de índice (nuevo hito alcanzado)
|
||||
if (SOUND_INDEX != PREVIOUS_INDEX && SOUND_INDEX < static_cast<int>(falling_sound_.size())) {
|
||||
Audio::get()->playSound(falling_sound_[SOUND_INDEX], Audio::Group::GAME);
|
||||
}
|
||||
}
|
||||
|
||||
// Comprueba si el jugador tiene suelo debajo de los pies
|
||||
auto Player::isOnFloor() -> bool {
|
||||
bool on_floor = false;
|
||||
bool on_slope_l = false;
|
||||
bool on_slope_r = false;
|
||||
|
||||
updateFeet();
|
||||
|
||||
// Comprueba las superficies
|
||||
for (auto f : under_feet_) {
|
||||
on_floor |= room_->checkTopSurfaces(&f);
|
||||
on_floor |= room_->checkAutoSurfaces(&f);
|
||||
}
|
||||
|
||||
// Comprueba las rampas
|
||||
on_slope_l = room_->checkLeftSlopes(under_feet_.data());
|
||||
on_slope_r = room_->checkRightSlopes(&under_feet_[1]);
|
||||
|
||||
return on_floor || on_slope_l || on_slope_r;
|
||||
}
|
||||
|
||||
// Comprueba si el jugador esta sobre una superficie automática
|
||||
auto Player::isOnAutoSurface() -> bool {
|
||||
bool on_auto_surface = false;
|
||||
|
||||
updateFeet();
|
||||
|
||||
// Comprueba las superficies
|
||||
for (auto f : under_feet_) {
|
||||
on_auto_surface |= room_->checkAutoSurfaces(&f);
|
||||
}
|
||||
|
||||
return on_auto_surface;
|
||||
}
|
||||
|
||||
// Comprueba si el jugador está sobre una rampa hacia abajo
|
||||
auto Player::isOnDownSlope() -> bool {
|
||||
bool on_slope = false;
|
||||
|
||||
updateFeet();
|
||||
|
||||
// Cuando el jugador baja una escalera, se queda volando
|
||||
// Hay que mirar otro pixel más por debajo
|
||||
SDL_FPoint foot0 = under_feet_[0];
|
||||
SDL_FPoint foot1 = under_feet_[1];
|
||||
foot0.y += 1.0F;
|
||||
foot1.y += 1.0F;
|
||||
|
||||
// Comprueba las rampas
|
||||
on_slope |= room_->checkLeftSlopes(&foot0);
|
||||
on_slope |= room_->checkRightSlopes(&foot1);
|
||||
|
||||
return on_slope;
|
||||
}
|
||||
|
||||
// Comprueba que el jugador no toque ningun tile de los que matan
|
||||
auto Player::handleKillingTiles() -> bool {
|
||||
// Comprueba si hay contacto con algún tile que mata
|
||||
if (std::ranges::any_of(collider_points_, [this](const auto& c) {
|
||||
return room_->getTile(c) == Room::Tile::KILL;
|
||||
})) {
|
||||
is_alive_ = false; // Mata al jugador inmediatamente
|
||||
return true; // Retorna en cuanto se detecta una colisión
|
||||
}
|
||||
|
||||
return false; // No se encontró ninguna colisión
|
||||
}
|
||||
|
||||
// Establece el color del jugador
|
||||
void Player::setColor() {
|
||||
/*
|
||||
if (Options::cheats.invincible == Options::Cheat::State::ENABLED) {
|
||||
color_ = static_cast<Uint8>(PaletteColor::CYAN);
|
||||
} else if (Options::cheats.infinite_lives == Options::Cheat::State::ENABLED) {
|
||||
color_ = static_cast<Uint8>(PaletteColor::YELLOW);
|
||||
} else {
|
||||
color_ = static_cast<Uint8>(PaletteColor::WHITE);
|
||||
}
|
||||
*/
|
||||
|
||||
switch (state_) {
|
||||
case State::STANDING:
|
||||
color_ = static_cast<Uint8>(PaletteColor::YELLOW);
|
||||
break;
|
||||
|
||||
case State::JUMPING:
|
||||
color_ = static_cast<Uint8>(PaletteColor::GREEN);
|
||||
break;
|
||||
|
||||
case State::FALLING:
|
||||
color_ = static_cast<Uint8>(PaletteColor::RED);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Actualiza los puntos de colisión
|
||||
void Player::updateColliderPoints() {
|
||||
const SDL_FRect RECT = getRect();
|
||||
collider_points_[0] = {.x = RECT.x, .y = RECT.y};
|
||||
collider_points_[1] = {.x = RECT.x + 7, .y = RECT.y};
|
||||
collider_points_[2] = {.x = RECT.x + 7, .y = RECT.y + 7};
|
||||
collider_points_[3] = {.x = RECT.x, .y = RECT.y + 7};
|
||||
collider_points_[4] = {.x = RECT.x, .y = RECT.y + 8};
|
||||
collider_points_[5] = {.x = RECT.x + 7, .y = RECT.y + 8};
|
||||
collider_points_[6] = {.x = RECT.x + 7, .y = RECT.y + 15};
|
||||
collider_points_[7] = {.x = RECT.x, .y = RECT.y + 15};
|
||||
}
|
||||
|
||||
// Actualiza los puntos de los pies
|
||||
void Player::updateFeet() {
|
||||
const SDL_FPoint P = {x_, y_};
|
||||
|
||||
under_feet_[0] = {.x = P.x, .y = P.y + HEIGHT};
|
||||
under_feet_[1] = {.x = P.x + 7, .y = P.y + HEIGHT};
|
||||
|
||||
feet_[0] = {.x = P.x, .y = P.y + HEIGHT - 1};
|
||||
feet_[1] = {.x = P.x + 7, .y = P.y + HEIGHT - 1};
|
||||
}
|
||||
|
||||
// Cambia el estado del jugador
|
||||
void Player::transitionToState(State value) {
|
||||
previous_state_ = state_;
|
||||
state_ = value;
|
||||
|
||||
// Establecer velocidades INMEDIATAMENTE al cambiar de estado
|
||||
switch (state_) {
|
||||
case State::STANDING:
|
||||
vx_ = 0.0F;
|
||||
vy_ = 0.0F;
|
||||
break;
|
||||
|
||||
case State::JUMPING:
|
||||
// vx_ mantiene su valor actual (heredado de STANDING)
|
||||
vy_ = JUMP_VELOCITY;
|
||||
break;
|
||||
|
||||
case State::FALLING:
|
||||
vx_ = 0.0F; // CRÍTICO para pegarse a rampas
|
||||
vy_ = MAX_VY;
|
||||
auto_movement_ = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Inicializa los sonidos de salto y caida
|
||||
void Player::initSounds() {
|
||||
jumping_sound_.clear();
|
||||
falling_sound_.clear();
|
||||
|
||||
for (int i = 1; i <= 24; ++i) {
|
||||
std::string sound_file = "jump" + std::to_string(i) + ".wav";
|
||||
jumping_sound_.push_back(Resource::Cache::get()->getSound(sound_file));
|
||||
|
||||
if (i >= 11) {
|
||||
falling_sound_.push_back(Resource::Cache::get()->getSound(sound_file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Aplica los valores de spawn al jugador
|
||||
void Player::applySpawnValues(const SpawnData& spawn) {
|
||||
x_ = spawn.x;
|
||||
y_ = spawn.y;
|
||||
y_prev_ = spawn.y; // Inicializar y_prev_ igual a y_ para evitar saltos en primer frame
|
||||
vx_ = spawn.vx;
|
||||
vy_ = spawn.vy;
|
||||
last_grounded_position_ = spawn.last_grounded_position;
|
||||
state_ = spawn.state;
|
||||
sprite_->setFlip(spawn.flip);
|
||||
}
|
||||
|
||||
// Inicializa el sprite del jugador
|
||||
void Player::initSprite(const std::string& animations_path) {
|
||||
auto animations = Resource::Cache::get()->getAnimations(animations_path);
|
||||
|
||||
sprite_ = std::make_unique<SurfaceAnimatedSprite>(animations);
|
||||
sprite_->setWidth(WIDTH);
|
||||
sprite_->setHeight(HEIGHT);
|
||||
sprite_->setCurrentAnimation("walk");
|
||||
}
|
||||
|
||||
// Actualiza collider_box y collision points
|
||||
void Player::updateColliderGeometry() {
|
||||
placeSprite(); // Coloca el sprite en la posición del jugador
|
||||
collider_box_ = getRect(); // Actualiza el rectangulo de colisión
|
||||
updateColliderPoints(); // Actualiza los puntos de colisión
|
||||
}
|
||||
|
||||
// Coloca el sprite en la posición del jugador
|
||||
void Player::placeSprite() {
|
||||
sprite_->setPos(x_, y_);
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include <array> // Para array
|
||||
#include <memory> // Para shared_ptr, __shared_ptr_access
|
||||
#include <string> // Para string
|
||||
#include <utility>
|
||||
#include <vector> // Para vector
|
||||
|
||||
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||
#include "game/gameplay/room.hpp"
|
||||
#include "utils/defines.hpp" // Para BORDER_TOP, BLOCK
|
||||
#include "utils/utils.hpp" // Para Color
|
||||
struct JA_Sound_t; // lines 13-13
|
||||
|
||||
class Player {
|
||||
public:
|
||||
// --- Enums y Structs ---
|
||||
enum class State {
|
||||
STANDING,
|
||||
JUMPING,
|
||||
FALLING,
|
||||
};
|
||||
|
||||
struct SpawnData {
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float vx = 0;
|
||||
float vy = 0;
|
||||
int last_grounded_position = 0;
|
||||
State state = State::STANDING;
|
||||
SDL_FlipMode flip = SDL_FLIP_NONE;
|
||||
|
||||
// Constructor por defecto
|
||||
SpawnData() = default;
|
||||
|
||||
// Constructor con parámetros
|
||||
SpawnData(float x, float y, float vx, float vy, int last_grounded_position, State state, SDL_FlipMode flip)
|
||||
: x(x),
|
||||
y(y),
|
||||
vx(vx),
|
||||
vy(vy),
|
||||
last_grounded_position(last_grounded_position),
|
||||
state(state),
|
||||
flip(flip) {}
|
||||
};
|
||||
|
||||
struct Data {
|
||||
SpawnData spawn_data;
|
||||
std::string animations_path;
|
||||
std::shared_ptr<Room> room = nullptr;
|
||||
|
||||
// Constructor por defecto
|
||||
Data() = default;
|
||||
|
||||
// Constructor con parámetros
|
||||
Data(SpawnData spawn_data, const std::string& texture_path, std::string animations_path, std::shared_ptr<Room> room)
|
||||
: spawn_data(spawn_data),
|
||||
animations_path(std::move(animations_path)),
|
||||
room(std::move(room)) {}
|
||||
};
|
||||
|
||||
// --- Constructor y Destructor ---
|
||||
explicit Player(const Data& player);
|
||||
~Player() = default;
|
||||
|
||||
// --- Funciones ---
|
||||
void render(); // Pinta el enemigo en pantalla
|
||||
void update(float delta_time); // Actualiza las variables del objeto
|
||||
[[nodiscard]] auto isOnBorder() const -> bool { return is_on_border_; } // Indica si el jugador esta en uno de los cuatro bordes de la pantalla
|
||||
[[nodiscard]] auto getBorder() const -> Room::Border { return border_; } // Indica en cual de los cuatro bordes se encuentra
|
||||
void switchBorders(); // Cambia al jugador de un borde al opuesto. Util para el cambio de pantalla
|
||||
auto getRect() -> SDL_FRect { return {x_, y_, WIDTH, HEIGHT}; } // Obtiene el rectangulo que delimita al jugador
|
||||
auto getCollider() -> SDL_FRect& { return collider_box_; } // Obtiene el rectangulo de colision del jugador
|
||||
auto getSpawnParams() -> SpawnData { return {x_, y_, vx_, vy_, last_grounded_position_, state_, sprite_->getFlip()}; } // Obtiene el estado de reaparición del jugador
|
||||
void setColor(); // Establece el color del jugador
|
||||
void setRoom(std::shared_ptr<Room> room) { room_ = std::move(room); } // Establece la habitación en la que se encuentra el jugador
|
||||
[[nodiscard]] auto isAlive() const -> bool { return is_alive_; } // Comprueba si el jugador esta vivo
|
||||
void setPaused(bool value) { is_paused_ = value; } // Pone el jugador en modo pausa
|
||||
|
||||
private:
|
||||
// --- Constantes ---
|
||||
static constexpr int WIDTH = 8; // Ancho del jugador
|
||||
static constexpr int HEIGHT = 16; // ALto del jugador
|
||||
static constexpr int MAX_FALLING_HEIGHT = TILE_SIZE * 4; // Altura maxima permitida de caída en pixels
|
||||
|
||||
// --- Constantes de física (per-second values) ---
|
||||
static constexpr float HORIZONTAL_VELOCITY = 40.0F; // Velocidad horizontal en pixels/segundo (0.6 * 66.67fps)
|
||||
static constexpr float MAX_VY = 80.0F; // Velocidad vertical máxima en pixels/segundo (1.2 * 66.67fps)
|
||||
static constexpr float JUMP_VELOCITY = -80.0F; // Velocidad inicial del salto en pixels/segundo
|
||||
static constexpr float GRAVITY_FORCE = 155.6F; // Fuerza de gravedad en pixels/segundo² (0.035 * 66.67²)
|
||||
|
||||
// --- Constantes de sonido ---
|
||||
static constexpr float SOUND_DISTANCE_INTERVAL = 3.0F; // Distancia en píxeles entre cada sonido de salto/caída
|
||||
|
||||
// --- --- Objetos y punteros --- ---
|
||||
std::shared_ptr<Room> room_; // Objeto encargado de gestionar cada habitación del juego
|
||||
std::unique_ptr<SurfaceAnimatedSprite> sprite_; // Sprite del jugador
|
||||
|
||||
// --- Variables de posición y física ---
|
||||
float x_ = 0.0F; // Posición del jugador en el eje X
|
||||
float y_ = 0.0F; // Posición del jugador en el eje Y
|
||||
float y_prev_ = 0.0F; // Posición Y del frame anterior (para detectar hitos de distancia en sonidos)
|
||||
float vx_ = 0.0F; // Velocidad/desplazamiento del jugador en el eje X
|
||||
float vy_ = 0.0F; // Velocidad/desplazamiento del jugador en el eje Y
|
||||
|
||||
// --- Variables de estado ---
|
||||
State state_ = State::STANDING; // Estado en el que se encuentra el jugador. Util apara saber si está saltando o cayendo
|
||||
State previous_state_ = State::STANDING; // Estado previo en el que se encontraba el jugador
|
||||
|
||||
// --- Variables de colisión ---
|
||||
SDL_FRect collider_box_; // Caja de colisión con los enemigos u objetos
|
||||
std::array<SDL_FPoint, 8> collider_points_{}; // Puntos de colisión con el mapa
|
||||
std::array<SDL_FPoint, 2> under_feet_{}; // Contiene los puntos que hay bajo cada pie del jugador
|
||||
std::array<SDL_FPoint, 2> feet_{}; // Contiene los puntos que hay en el pie del jugador
|
||||
|
||||
// --- Variables de juego ---
|
||||
bool is_on_border_ = false; // Indica si el jugador esta en uno de los cuatro bordes de la pantalla
|
||||
bool is_alive_ = true; // Indica si el jugador esta vivo o no
|
||||
bool is_paused_ = false; // Indica si el jugador esta en modo pausa
|
||||
bool auto_movement_ = false; // Indica si esta siendo arrastrado por una superficie automatica
|
||||
Room::Border border_ = Room::Border::TOP; // Indica en cual de los cuatro bordes se encuentra
|
||||
int last_grounded_position_ = 0; // Ultima posición en Y en la que se estaba en contacto con el suelo (hace doble función: tracking de caída + altura inicial del salto)
|
||||
|
||||
// --- Variables de renderizado y sonido ---
|
||||
Uint8 color_ = 0; // Color del jugador
|
||||
std::vector<JA_Sound_t*> jumping_sound_; // Vecor con todos los sonidos del salto
|
||||
std::vector<JA_Sound_t*> falling_sound_; // Vecor con todos los sonidos de la caída
|
||||
|
||||
// --- Funciones de inicialización ---
|
||||
void initSprite(const std::string& animations_path); // Inicializa el sprite del jugador
|
||||
void initSounds(); // Inicializa los sonidos de salto y caida
|
||||
void applySpawnValues(const SpawnData& spawn); // Aplica los valores de spawn al jugador
|
||||
|
||||
// --- Funciones de procesamiento de entrada ---
|
||||
void handleInput(float delta_time); // Comprueba las entradas y modifica variables
|
||||
|
||||
// --- Funciones de gestión de estado ---
|
||||
void handleState(float delta_time); // Comprueba el estado del jugador y actualiza variables
|
||||
void transitionToState(State value); // Cambia el estado del jugador
|
||||
|
||||
// --- Funciones de física ---
|
||||
void applyGravity(float delta_time); // Aplica gravedad al jugador
|
||||
|
||||
// --- Funciones de movimiento y colisión ---
|
||||
void move(float delta_time); // Orquesta el movimiento del jugador
|
||||
void moveHorizontal(float delta_time, int direction); // Maneja el movimiento horizontal (-1: izq, 1: der)
|
||||
void moveVerticalUp(float delta_time); // Maneja el movimiento vertical hacia arriba
|
||||
void moveVerticalDown(float delta_time); // Maneja el movimiento vertical hacia abajo
|
||||
void handleSlopeMovement(int direction); // Maneja el movimiento sobre rampas
|
||||
|
||||
// --- Funciones de detección de superficies ---
|
||||
auto isOnFloor() -> bool; // Comprueba si el jugador tiene suelo debajo de los pies
|
||||
auto isOnAutoSurface() -> bool; // Comprueba si el jugador esta sobre una superficie automática
|
||||
auto isOnDownSlope() -> bool; // Comprueba si el jugador está sobre una rampa hacia abajo
|
||||
|
||||
// --- Funciones de actualización de geometría ---
|
||||
void updateColliderGeometry(); // Actualiza collider_box y collision points
|
||||
void updateColliderPoints(); // Actualiza los puntos de colisión
|
||||
void updateFeet(); // Actualiza los puntos de los pies
|
||||
void placeSprite(); // Coloca el sprite en la posición del jugador
|
||||
|
||||
// --- Funciones de finalización ---
|
||||
void animate(float delta_time); // Establece la animación del jugador
|
||||
void handleBorders(); // Comprueba si se halla en alguno de los cuatro bordes
|
||||
void handleJumpEnd(); // Comprueba si ha finalizado el salto al alcanzar la altura de inicio
|
||||
auto handleKillingTiles() -> bool; // Comprueba que el jugador no toque ningun tile de los que matan
|
||||
void playJumpSound(); // Calcula y reproduce el sonido de salto
|
||||
void playFallSound(); // Calcula y reproduce el sonido de caer
|
||||
};
|
||||
@@ -1,132 +0,0 @@
|
||||
handleInput()
|
||||
{
|
||||
if (checkAction(LEFT))
|
||||
{
|
||||
wannaGo::LEFT;
|
||||
}
|
||||
else if (checkAction(RIGHT))
|
||||
{
|
||||
wannaGo::RIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
wannaGo::STAY;
|
||||
}
|
||||
|
||||
wannaJUMP = (checkAction(JUMP));
|
||||
}
|
||||
|
||||
move()
|
||||
{
|
||||
handleHorizontalMovement();
|
||||
handleVerticalMovement();
|
||||
}
|
||||
|
||||
handleHorizontalMovement()
|
||||
{
|
||||
if (State!=STANDING)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (automovement)
|
||||
{
|
||||
vx = FIXED_BY_ROOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
vx = wannaGo::DIRECTION;
|
||||
}
|
||||
|
||||
moveAndCollide();
|
||||
|
||||
}
|
||||
|
||||
handleVerticalMovement()
|
||||
{
|
||||
if (State==STANDING)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (State==JUMPING)
|
||||
{
|
||||
applyGravity();
|
||||
}
|
||||
|
||||
moveAndCollide();
|
||||
|
||||
}
|
||||
|
||||
|
||||
handleConveyorBelts()
|
||||
{
|
||||
if (!automovement and isOnConveyorBelt and wannaGo::STAY)
|
||||
{
|
||||
automovement = true;
|
||||
}
|
||||
|
||||
if (automovement and !isOnConveyorBelt)
|
||||
{
|
||||
automovement = false;
|
||||
}
|
||||
}
|
||||
|
||||
handleShouldFall()
|
||||
{
|
||||
if (!isOnFloor and State::STANDING)
|
||||
{
|
||||
transitionToState(FALLING);
|
||||
}
|
||||
}
|
||||
|
||||
transitionToState(state)
|
||||
{
|
||||
prev = state_;
|
||||
state_ = state;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case STANDING:
|
||||
vy = 0;
|
||||
case JUMPING:
|
||||
if (prev==STANDING)
|
||||
{
|
||||
vy = -MAX_VY;
|
||||
last_ground_position = y;
|
||||
}
|
||||
case FALLING:
|
||||
last_ground_position = y;
|
||||
vy = MAX_VY;
|
||||
vx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
updateState()
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case STANDING:
|
||||
handleConveyorBelts();
|
||||
handleShouldFall();
|
||||
if (wannaJump)
|
||||
{
|
||||
transitionToState(JUMPING);
|
||||
}
|
||||
case JUMPING:
|
||||
automovement = false;
|
||||
playJumpingSound();
|
||||
handleEndJump();
|
||||
case FALLING:
|
||||
automovement = false;
|
||||
playFallingSound();
|
||||
}
|
||||
}
|
||||
|
||||
update()
|
||||
{
|
||||
hanldeInput();
|
||||
updateState();
|
||||
move();
|
||||
animate();
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "core/rendering/screen.hpp" // Para Screen
|
||||
#include "core/rendering/surface.hpp" // Para Surface
|
||||
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||
#include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR
|
||||
#include "core/rendering/text.hpp" // Para Text, Text::CENTER_FLAG, Text::COLOR_FLAG
|
||||
#include "core/resources/resource_cache.hpp" // Para Resource
|
||||
#include "core/system/global_events.hpp" // Para check
|
||||
#include "game/options.hpp" // Para Options, options, OptionsGame, Sectio...
|
||||
@@ -118,12 +118,12 @@ void Credits::fillTexture() {
|
||||
int pos_y = 0;
|
||||
|
||||
for (const auto& t : texts_) {
|
||||
text->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, pos_y * SIZE, t.label, 1, t.color);
|
||||
text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, pos_y * SIZE, t.label, 1, t.color);
|
||||
pos_y++;
|
||||
}
|
||||
|
||||
// Escribe el corazón
|
||||
const int TEXT_LENGHT = text->lenght(texts_[22].label, 1) - text->lenght(" ", 1); // Se resta el ultimo caracter que es un espacio
|
||||
const int TEXT_LENGHT = text->length(texts_[22].label, 1) - text->length(" ", 1); // Se resta el ultimo caracter que es un espacio
|
||||
const int POS_X = ((PLAY_AREA_WIDTH - TEXT_LENGHT) / 2) + TEXT_LENGHT;
|
||||
text->writeColored(POS_X, 176, "}", static_cast<Uint8>(PaletteColor::BRIGHT_RED));
|
||||
Screen::get()->setRendererSurface(previuos_renderer);
|
||||
|
||||
@@ -211,7 +211,7 @@ void Ending::iniTexts() {
|
||||
for (const auto& txt : texts) {
|
||||
auto text = Resource::Cache::get()->getText("smb2");
|
||||
|
||||
const float WIDTH = text->lenght(txt.caption, 1) + 2 + 2;
|
||||
const float WIDTH = text->length(txt.caption, 1) + 2 + 2;
|
||||
const float HEIGHT = text->getCharacterSize() + 2 + 2;
|
||||
auto text_color = static_cast<Uint8>(PaletteColor::WHITE);
|
||||
auto shadow_color = static_cast<Uint8>(PaletteColor::BLACK);
|
||||
@@ -222,7 +222,7 @@ void Ending::iniTexts() {
|
||||
st.image_surface = std::make_shared<Surface>(WIDTH, HEIGHT);
|
||||
auto previuos_renderer = Screen::get()->getRendererSurface();
|
||||
Screen::get()->setRendererSurface(st.image_surface);
|
||||
text->writeDX(TEXT_STROKE, 2, 2, txt.caption, 1, text_color, 2, shadow_color);
|
||||
text->writeDX(Text::STROKE_FLAG, 2, 2, txt.caption, 1, text_color, 2, shadow_color);
|
||||
|
||||
// Crea el sprite
|
||||
st.image_sprite = std::make_shared<SurfaceSprite>(st.image_surface, 0, 0, st.image_surface->getWidth(), st.image_surface->getHeight());
|
||||
|
||||
@@ -388,7 +388,7 @@ void Ending2::createSpriteTexts() {
|
||||
}
|
||||
|
||||
// Calcula las dimensiones del texto
|
||||
const float W = text->lenght(txt, 1);
|
||||
const float W = text->length(txt, 1);
|
||||
const float H = text->getCharacterSize();
|
||||
|
||||
// Determina la columna y la posición X del texto
|
||||
@@ -424,7 +424,7 @@ void Ending2::createTexts() {
|
||||
// Crea los sprites de texto a partir de la lista
|
||||
for (size_t i = 0; i < list.size(); ++i) {
|
||||
// Calcula constantes
|
||||
const float W = text->lenght(list[i], 1);
|
||||
const float W = text->length(list[i], 1);
|
||||
const float H = text->getCharacterSize();
|
||||
const float X = GAMECANVAS_CENTER_X;
|
||||
const float DX = -(W / 2);
|
||||
@@ -453,7 +453,7 @@ void Ending2::createTexts() {
|
||||
// Crea los sprites de texto a partir de la lista
|
||||
for (size_t i = 0; i < list.size(); ++i) {
|
||||
// Calcula constantes
|
||||
const float W = text->lenght(list[i], 1);
|
||||
const float W = text->length(list[i], 1);
|
||||
const float H = text->getCharacterSize();
|
||||
const float X = GAMECANVAS_CENTER_X;
|
||||
const float DX = -(W / 2);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "core/input/input.hpp" // Para Input, InputAction, Input::DO_NOT_ALLOW_REPEAT
|
||||
#include "core/rendering/screen.hpp" // Para Screen
|
||||
#include "core/rendering/surface.hpp" // Para Surface
|
||||
#include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR
|
||||
#include "core/rendering/text.hpp" // Para Text, Text::CENTER_FLAG, Text::COLOR_FLAG
|
||||
#include "core/resources/resource_cache.hpp" // Para ResourceRoom, Resource
|
||||
#include "core/resources/resource_list.hpp" // Para Asset
|
||||
#include "core/system/global_events.hpp" // Para check
|
||||
@@ -506,7 +506,7 @@ void Game::fillRoomNameTexture() {
|
||||
|
||||
// Escribe el texto en la textura
|
||||
auto text = Resource::Cache::get()->getText("smb2");
|
||||
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, text->getCharacterSize() / 2, room_->getName(), 1, room_->getBGColor());
|
||||
text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GAMECANVAS_CENTER_X, text->getCharacterSize() / 2, room_->getName(), 1, room_->getBGColor());
|
||||
|
||||
// Deja el renderizador por defecto
|
||||
Screen::get()->setRendererSurface(previuos_renderer);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "core/input/input.hpp" // Para Input
|
||||
#include "core/rendering/screen.hpp" // Para Screen
|
||||
#include "core/rendering/surface_animated_sprite.hpp" // Para SAnimatedSprite
|
||||
#include "core/rendering/text.hpp" // Para TEXT_CENTER, TEXT_COLOR, Text
|
||||
#include "core/rendering/text.hpp" // Para Text::CENTER_FLAG, Text::COLOR_FLAG, Text
|
||||
#include "core/resources/resource_cache.hpp" // Para Resource
|
||||
#include "core/system/global_events.hpp" // Para check
|
||||
#include "game/options.hpp" // Para Options, options, OptionsStats, Secti...
|
||||
@@ -68,7 +68,7 @@ void GameOver::render() {
|
||||
auto text = Resource::Cache::get()->getText("smb2");
|
||||
|
||||
// Escribe el texto de GAME OVER
|
||||
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, TEXT_Y, "G A M E O V E R", 1, color_);
|
||||
text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GAMECANVAS_CENTER_X, TEXT_Y, "G A M E O V E R", 1, color_);
|
||||
|
||||
// Dibuja los sprites (ya posicionados en el constructor, solo ajustamos Y)
|
||||
player_sprite_->setPosY(TEXT_Y + SPRITE_Y_OFFSET);
|
||||
@@ -78,12 +78,12 @@ void GameOver::render() {
|
||||
// Escribe el texto con las habitaciones y los items
|
||||
const std::string ITEMS_TEXT = std::to_string(Options::stats.items / 100) + std::to_string((Options::stats.items % 100) / 10) + std::to_string(Options::stats.items % 10);
|
||||
const std::string ROOMS_TEXT = std::to_string(Options::stats.rooms / 100) + std::to_string((Options::stats.rooms % 100) / 10) + std::to_string(Options::stats.rooms % 10);
|
||||
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, TEXT_Y + ITEMS_Y_OFFSET, "ITEMS: " + ITEMS_TEXT, 1, color_);
|
||||
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, TEXT_Y + ROOMS_Y_OFFSET, "ROOMS: " + ROOMS_TEXT, 1, color_);
|
||||
text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GAMECANVAS_CENTER_X, TEXT_Y + ITEMS_Y_OFFSET, "ITEMS: " + ITEMS_TEXT, 1, color_);
|
||||
text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GAMECANVAS_CENTER_X, TEXT_Y + ROOMS_Y_OFFSET, "ROOMS: " + ROOMS_TEXT, 1, color_);
|
||||
|
||||
// Escribe el texto con "Tu peor pesadilla"
|
||||
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, TEXT_Y + NIGHTMARE_TITLE_Y_OFFSET, "YOUR WORST NIGHTMARE IS", 1, color_);
|
||||
text->writeDX(TEXT_CENTER | TEXT_COLOR, GAMECANVAS_CENTER_X, TEXT_Y + NIGHTMARE_TEXT_Y_OFFSET, Options::stats.worst_nightmare, 1, color_);
|
||||
text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GAMECANVAS_CENTER_X, TEXT_Y + NIGHTMARE_TITLE_Y_OFFSET, "YOUR WORST NIGHTMARE IS", 1, color_);
|
||||
text->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, GAMECANVAS_CENTER_X, TEXT_Y + NIGHTMARE_TEXT_Y_OFFSET, Options::stats.worst_nightmare, 1, color_);
|
||||
|
||||
// Vuelca el contenido del renderizador en pantalla
|
||||
Screen::get()->render();
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "core/rendering/screen.hpp" // Para Screen
|
||||
#include "core/rendering/surface.hpp" // Para Surface
|
||||
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||
#include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR
|
||||
#include "core/rendering/text.hpp" // Para Text, Text::CENTER_FLAG, Text::COLOR_FLAG
|
||||
#include "core/resources/resource_cache.hpp" // Para Resource
|
||||
#include "core/resources/resource_list.hpp" // Para Asset
|
||||
#include "core/system/global_events.hpp" // Para check
|
||||
@@ -58,7 +58,7 @@ void Title::initMarquee() {
|
||||
Glyph l;
|
||||
l.letter = long_text_[i]; // char directo, no substring
|
||||
l.x = MARQUEE_START_X; // Usar constante
|
||||
l.width = marquee_text_->lenght(std::string(1, long_text_[i])); // Pre-calcular ancho
|
||||
l.width = marquee_text_->length(std::string(1, long_text_[i])); // Pre-calcular ancho
|
||||
l.enabled = false;
|
||||
letters_.push_back(l);
|
||||
}
|
||||
@@ -457,7 +457,7 @@ void Title::createCheevosTexture() {
|
||||
const std::string CHEEVOS_OWNER = "PROJECTS";
|
||||
const std::string CHEEVOS_LIST_CAPTION = CHEEVOS_OWNER + " (" + std::to_string(Cheevos::get()->getTotalUnlockedAchievements()) + " / " + std::to_string(Cheevos::get()->size()) + ")";
|
||||
int pos = 2;
|
||||
TEXT->writeDX(TEXT_CENTER | TEXT_COLOR, cheevos_surface_->getWidth() / 2, pos, CHEEVOS_LIST_CAPTION, 1, stringToColor("bright_green"));
|
||||
TEXT->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, cheevos_surface_->getWidth() / 2, pos, CHEEVOS_LIST_CAPTION, 1, stringToColor("bright_green"));
|
||||
pos += TEXT->getCharacterSize();
|
||||
const Uint8 CHEEVO_LOCKED_COLOR = stringToColor("white");
|
||||
const Uint8 CHEEVO_UNLOCKED_COLOR = stringToColor("bright_green");
|
||||
@@ -469,9 +469,9 @@ void Title::createCheevosTexture() {
|
||||
pos += CHEEVOS_PADDING;
|
||||
constexpr int HALF = CHEEVOS_PADDING / 2;
|
||||
cheevos_surface_->drawLine(LINE_X1, pos - HALF - 1, LINE_X2, pos - HALF - 1, CHEEVO_COLOR);
|
||||
TEXT->writeDX(TEXT_CENTER | TEXT_COLOR, CHEEVOS_TEXTURE_WIDTH / 2, pos, cheevo.caption, 1, CHEEVO_COLOR);
|
||||
TEXT->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, CHEEVOS_TEXTURE_WIDTH / 2, pos, cheevo.caption, 1, CHEEVO_COLOR);
|
||||
pos += TEXT->getCharacterSize() + 1;
|
||||
TEXT->writeDX(TEXT_CENTER | TEXT_COLOR, CHEEVOS_TEXTURE_WIDTH / 2, pos, cheevo.description, 1, CHEEVO_COLOR);
|
||||
TEXT->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, CHEEVOS_TEXTURE_WIDTH / 2, pos, cheevo.description, 1, CHEEVO_COLOR);
|
||||
pos += TEXT->getCharacterSize();
|
||||
}
|
||||
|
||||
@@ -522,10 +522,10 @@ void Title::renderMainMenu() {
|
||||
const int TOTAL_HEIGHT = 3 * SPACING; // 3 espacios entre 4 items
|
||||
const int START_Y = MENU_CENTER_Y - (TOTAL_HEIGHT / 2);
|
||||
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, START_Y, "1. PLAY", 1, COLOR);
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, START_Y + SPACING, "2. REDEFINE KEYBOARD", 1, COLOR);
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, START_Y + (2 * SPACING), "3. REDEFINE JOYSTICK", 1, COLOR);
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, START_Y + (3 * SPACING), "4. PROJECTS", 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, START_Y, "1. PLAY", 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, START_Y + SPACING, "2. REDEFINE KEYBOARD", 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, START_Y + (2 * SPACING), "3. REDEFINE JOYSTICK", 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, START_Y + (3 * SPACING), "4. PROJECTS", 1, COLOR);
|
||||
}
|
||||
|
||||
// Dibuja el menu de logros
|
||||
@@ -674,11 +674,11 @@ void Title::renderKeyboardRemap() {
|
||||
|
||||
// Mensaje principal: "PRESS KEY FOR [ACTION]" o "KEYS DEFINED" si completado
|
||||
if (remap_step_ >= 3) {
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, START_Y, "KEYS DEFINED", 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, START_Y, "KEYS DEFINED", 1, COLOR);
|
||||
} else {
|
||||
const std::string ACTION = getActionName(remap_step_);
|
||||
const std::string MESSAGE = "PRESS KEY FOR " + ACTION;
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, START_Y, MESSAGE, 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, START_Y, MESSAGE, 1, COLOR);
|
||||
}
|
||||
|
||||
// Mostrar teclas ya capturadas (con espaciado de 2 líneas desde el mensaje principal)
|
||||
@@ -686,22 +686,22 @@ void Title::renderKeyboardRemap() {
|
||||
if (remap_step_ > 0) {
|
||||
const std::string LEFT_KEY = SDL_GetScancodeName(temp_keys_[0]);
|
||||
const std::string LEFT_MSG = "LEFT: " + LEFT_KEY;
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, KEYS_START_Y, LEFT_MSG, 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, KEYS_START_Y, LEFT_MSG, 1, COLOR);
|
||||
}
|
||||
if (remap_step_ > 1) {
|
||||
const std::string RIGHT_KEY = SDL_GetScancodeName(temp_keys_[1]);
|
||||
const std::string RIGHT_MSG = "RIGHT: " + RIGHT_KEY;
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, KEYS_START_Y + LINE_SPACING, RIGHT_MSG, 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, KEYS_START_Y + LINE_SPACING, RIGHT_MSG, 1, COLOR);
|
||||
}
|
||||
if (remap_step_ >= 3) {
|
||||
const std::string JUMP_KEY = SDL_GetScancodeName(temp_keys_[2]);
|
||||
const std::string JUMP_MSG = "JUMP: " + JUMP_KEY;
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, KEYS_START_Y + (2 * LINE_SPACING), JUMP_MSG, 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, KEYS_START_Y + (2 * LINE_SPACING), JUMP_MSG, 1, COLOR);
|
||||
}
|
||||
|
||||
// Mensaje de error si existe (4 líneas después del inicio de las teclas)
|
||||
if (!remap_error_message_.empty()) {
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, KEYS_START_Y + (4 * LINE_SPACING), remap_error_message_, 1, ERROR_COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, KEYS_START_Y + (4 * LINE_SPACING), remap_error_message_, 1, ERROR_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -723,11 +723,11 @@ void Title::renderJoystickRemap() {
|
||||
|
||||
// Mensaje principal: "PRESS BUTTON FOR [ACTION]" o "BUTTONS DEFINED" si completado
|
||||
if (remap_step_ >= 3) {
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, START_Y, "BUTTONS DEFINED", 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, START_Y, "BUTTONS DEFINED", 1, COLOR);
|
||||
} else {
|
||||
const std::string ACTION = getActionName(remap_step_);
|
||||
const std::string MESSAGE = "PRESS BUTTON FOR " + ACTION;
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, START_Y, MESSAGE, 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, START_Y, MESSAGE, 1, COLOR);
|
||||
}
|
||||
|
||||
// Mostrar botones ya capturados (con espaciado de 2 líneas desde el mensaje principal)
|
||||
@@ -735,22 +735,22 @@ void Title::renderJoystickRemap() {
|
||||
if (remap_step_ > 0) {
|
||||
const std::string LEFT_BTN = getButtonName(temp_buttons_[0]);
|
||||
const std::string LEFT_MSG = "LEFT: " + LEFT_BTN;
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, BUTTONS_START_Y, LEFT_MSG, 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, BUTTONS_START_Y, LEFT_MSG, 1, COLOR);
|
||||
}
|
||||
if (remap_step_ > 1) {
|
||||
const std::string RIGHT_BTN = getButtonName(temp_buttons_[1]);
|
||||
const std::string RIGHT_MSG = "RIGHT: " + RIGHT_BTN;
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, BUTTONS_START_Y + LINE_SPACING, RIGHT_MSG, 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, BUTTONS_START_Y + LINE_SPACING, RIGHT_MSG, 1, COLOR);
|
||||
}
|
||||
if (remap_step_ >= 3) {
|
||||
const std::string JUMP_BTN = getButtonName(temp_buttons_[2]);
|
||||
const std::string JUMP_MSG = "JUMP: " + JUMP_BTN;
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, BUTTONS_START_Y + (2 * LINE_SPACING), JUMP_MSG, 1, COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, BUTTONS_START_Y + (2 * LINE_SPACING), JUMP_MSG, 1, COLOR);
|
||||
}
|
||||
|
||||
// Mensaje de error si existe (4 líneas después del inicio de los botones)
|
||||
if (!remap_error_message_.empty()) {
|
||||
menu_text_->writeDX(TEXT_CENTER | TEXT_COLOR, PLAY_AREA_CENTER_X, BUTTONS_START_Y + (4 * LINE_SPACING), remap_error_message_, 1, ERROR_COLOR);
|
||||
menu_text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, PLAY_AREA_CENTER_X, BUTTONS_START_Y + (4 * LINE_SPACING), remap_error_message_, 1, ERROR_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "core/rendering/screen.hpp" // Para Screen
|
||||
#include "core/rendering/surface.hpp" // Para Surface
|
||||
#include "core/rendering/surface_sprite.hpp" // Para SSprite
|
||||
#include "core/rendering/text.hpp" // Para Text, TEXT_CENTER, TEXT_COLOR
|
||||
#include "core/rendering/text.hpp" // Para Text, Text::CENTER_FLAG, Text::COLOR_FLAG
|
||||
#include "core/resources/resource_cache.hpp" // Para Resource
|
||||
#include "game/options.hpp" // Para Options, options, NotificationPosition
|
||||
#include "utils/delta_timer.hpp" // Para DeltaTimer
|
||||
@@ -220,7 +220,7 @@ void Notifier::show(std::vector<std::string> texts, TextAlign text_is, Uint32 di
|
||||
text_->writeColored(PADDING_IN_H + ICON_SPACE, PADDING_IN_V + (iterator * (TEXT_SIZE + 1)), text, COLOR);
|
||||
break;
|
||||
case TextAlign::CENTER:
|
||||
text_->writeDX(TEXT_CENTER | TEXT_COLOR, WIDTH / 2, PADDING_IN_V + (iterator * (TEXT_SIZE + 1)), text, 1, COLOR);
|
||||
text_->writeDX(Text::CENTER_FLAG | Text::COLOR_FLAG, WIDTH / 2, PADDING_IN_V + (iterator * (TEXT_SIZE + 1)), text, 1, COLOR);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user