noves coses chules en la clase text

This commit is contained in:
2025-08-17 14:25:17 +02:00
parent fe0083abd4
commit ff2a51a507
7 changed files with 184 additions and 19 deletions

View File

@@ -626,9 +626,9 @@ void Resource::createTextTextures() {
{"game_text_stop", Lang::getText("[GAME_TEXT] 6")},
{"game_text_1000000_points", Lang::getText("[GAME_TEXT] 8")}};
auto text = getText("04b_25");
auto text = getText("04b_25_enhanced");
for (const auto &s : strings) {
textures_.emplace_back(s.name, text->writeToTexture(s.text, 1, -2));
textures_.emplace_back(s.name, text->writeDXToTexture(Text::STROKE, s.text, -2, NO_TEXT_COLOR, 1, Color(255, 255, 0, 255)));
printWithDots("Texture : ", s.name, "[ DONE ]");
}
@@ -653,15 +653,18 @@ void Resource::createText() {
std::string key;
std::string texture_file;
std::string text_file;
std::string white_texture_file; // Textura blanca opcional
ResourceInfo(std::string k, std::string t_file, std::string txt_file)
: key(std::move(k)), texture_file(std::move(t_file)), text_file(std::move(txt_file)) {}
ResourceInfo(std::string k, std::string t_file, std::string txt_file, std::string w_file = "")
: key(std::move(k)), texture_file(std::move(t_file)), text_file(std::move(txt_file)), white_texture_file(std::move(w_file)) {}
};
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "\n>> CREATING TEXT OBJECTS");
std::vector<ResourceInfo> resources = {
{"04b_25", "04b_25.png", "04b_25.txt"},
{"04b_25_enhanced", "04b_25.png", "04b_25.txt", "04b_25_white.png"}, // Nueva fuente con textura blanca
{"04b_25_white", "04b_25_white.png", "04b_25.txt"},
{"04b_25_2x", "04b_25_2x.png", "04b_25_2x.txt"},
{"04b_25_metal", "04b_25_metal.png", "04b_25.txt"},
{"04b_25_grey", "04b_25_grey.png", "04b_25.txt"},
@@ -675,7 +678,13 @@ void Resource::createText() {
{"smb2_grad", "smb2_grad.png", "smb2.txt"}};
for (const auto &resource : resources) {
texts_.emplace_back(resource.key, std::make_shared<Text>(getTexture(resource.texture_file), getTextFile(resource.text_file)));
if (!resource.white_texture_file.empty()) {
// Crear texto con textura blanca
texts_.emplace_back(resource.key, std::make_shared<Text>(getTexture(resource.texture_file), getTexture(resource.white_texture_file), getTextFile(resource.text_file)));
} else {
// Crear texto normal
texts_.emplace_back(resource.key, std::make_shared<Text>(getTexture(resource.texture_file), getTextFile(resource.text_file)));
}
printWithDots("Text : ", resource.key, "[ DONE ]");
}
}

View File

@@ -687,7 +687,8 @@ void Game::renderItems() {
// Devuelve un item al azar y luego segun sus probabilidades
auto Game::dropItem() -> ItemType {
const auto LUCKY_NUMBER = rand() % 100;
//const auto LUCKY_NUMBER = rand() % 100;
const auto LUCKY_NUMBER = 0;
const auto ITEM = rand() % 6;
switch (ITEM) {

View File

@@ -52,6 +52,47 @@ Text::Text(const std::shared_ptr<Texture> &texture, const std::shared_ptr<Text::
fixed_width_ = false;
}
// Constructor con textura blanca opcional
Text::Text(const std::shared_ptr<Texture> &texture, const std::shared_ptr<Texture> &white_texture, const std::string &text_file) {
// Carga los offsets desde el fichero
auto tf = loadFile(text_file);
// Inicializa variables desde la estructura
box_height_ = tf->box_height;
box_width_ = tf->box_width;
for (int i = 0; i < 128; ++i) {
offset_[i].x = tf->offset[i].x;
offset_[i].y = tf->offset[i].y;
offset_[i].w = tf->offset[i].w;
}
// Crea los objetos
sprite_ = std::make_unique<Sprite>(texture, (SDL_FRect){0, 0, static_cast<float>(box_width_), static_cast<float>(box_height_)});
white_sprite_ = std::make_unique<Sprite>(white_texture, (SDL_FRect){0, 0, static_cast<float>(box_width_), static_cast<float>(box_height_)});
// Inicializa variables
fixed_width_ = false;
}
// Constructor con textura blanca opcional
Text::Text(const std::shared_ptr<Texture> &texture, const std::shared_ptr<Texture> &white_texture, const std::shared_ptr<Text::File> &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<Sprite>(texture, (SDL_FRect){0, 0, static_cast<float>(box_width_), static_cast<float>(box_height_)});
white_sprite_ = std::make_unique<Sprite>(white_texture, (SDL_FRect){0, 0, static_cast<float>(box_width_), static_cast<float>(box_height_)});
// Inicializa variables
fixed_width_ = false;
}
// Escribe texto en pantalla
void Text::write(int x, int y, const std::string &text, int kerning, int length) {
int shift = 0;
@@ -114,8 +155,30 @@ auto Text::writeToTexture(const std::string &text, int zoom, int kerning, int le
auto Text::writeDXToTexture(Uint8 flags, const std::string &text, int kerning, Color text_color, Uint8 shadow_distance, Color shadow_color, int length) -> std::shared_ptr<Texture> {
auto *renderer = Screen::get()->getRenderer();
auto texture = std::make_shared<Texture>(renderer);
auto width = Text::length(text, kerning) + shadow_distance;
auto height = box_height_ + shadow_distance;
// Calcula las dimensiones considerando los efectos
auto base_width = Text::length(text, kerning);
auto base_height = box_height_;
auto width = base_width;
auto height = base_height;
auto offset_x = 0;
auto offset_y = 0;
const auto STROKED = ((flags & Text::STROKE) == Text::STROKE);
const auto SHADOWED = ((flags & Text::SHADOW) == Text::SHADOW);
if (STROKED) {
// Para stroke, el texto se expande en todas las direcciones por shadow_distance
width = base_width + (shadow_distance * 2);
height = base_height + (shadow_distance * 2);
offset_x = shadow_distance;
offset_y = shadow_distance;
} else if (SHADOWED) {
// Para shadow, solo se añade espacio a la derecha y abajo
width = base_width + shadow_distance;
height = base_height + shadow_distance;
}
auto *temp = SDL_GetRenderTarget(renderer);
texture->createBlank(width, height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET);
@@ -123,7 +186,7 @@ auto Text::writeDXToTexture(Uint8 flags, const std::string &text, int kerning, C
texture->setAsRenderTarget(renderer);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
writeDX(flags, 0, 0, text, kerning, text_color, shadow_distance, shadow_color, length);
writeDX(flags, offset_x, offset_y, text, kerning, text_color, shadow_distance, shadow_color, length);
SDL_SetRenderTarget(renderer, temp);
return texture;
@@ -131,9 +194,79 @@ auto Text::writeDXToTexture(Uint8 flags, const std::string &text, int kerning, C
// Escribe el texto con colores
void Text::writeColored(int x, int y, const std::string &text, Color color, int kerning, int length) {
sprite_->getTexture()->setColor(color.r, color.g, color.b);
write(x, y, text, kerning, length);
sprite_->getTexture()->setColor(255, 255, 255);
writeColoredWithSprite(sprite_.get(), x, y, text, color, kerning, length);
}
// Escribe el texto con colores usando un sprite específico
void Text::writeColoredWithSprite(Sprite* sprite, int x, int y, const std::string &text, Color color, int kerning, int length) {
int shift = 0;
const std::string_view VISIBLE_TEXT = (length == -1) ? std::string_view(text) : std::string_view(text).substr(0, length);
auto *texture = sprite->getTexture().get();
// Guarda el alpha original y aplica el nuevo
Uint8 original_alpha;
SDL_GetTextureAlphaMod(texture->getSDLTexture(), &original_alpha);
texture->setAlpha(color.a);
texture->setColor(color.r, color.g, color.b);
sprite->setY(y);
for (const auto CH : VISIBLE_TEXT) {
const auto INDEX = static_cast<unsigned char>(CH);
if (INDEX < offset_.size()) {
sprite->setSpriteClip(offset_[INDEX].x, offset_[INDEX].y, box_width_, box_height_);
sprite->setX(x + shift);
sprite->render();
shift += offset_[INDEX].w + kerning;
}
}
// Restaura los valores originales
texture->setColor(255, 255, 255);
texture->setAlpha(255);
}
// Escribe stroke con alpha correcto usando textura temporal
void Text::writeStrokeWithAlpha(int x, int y, const std::string &text, int kerning, Color stroke_color, Uint8 shadow_distance, int length) {
auto *renderer = Screen::get()->getRenderer();
auto *original_target = SDL_GetRenderTarget(renderer);
// Calcula dimensiones de la textura temporal
auto text_width = Text::length(text, kerning);
auto text_height = box_height_;
auto temp_width = text_width + (shadow_distance * 2);
auto temp_height = text_height + (shadow_distance * 2);
// Crea textura temporal
auto temp_texture = std::make_shared<Texture>(renderer);
temp_texture->createBlank(temp_width, temp_height, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET);
temp_texture->setBlendMode(SDL_BLENDMODE_BLEND);
// Renderiza el stroke en la textura temporal
temp_texture->setAsRenderTarget(renderer);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
// Selecciona el sprite apropiado para el stroke
auto *stroke_sprite = white_sprite_ ? white_sprite_.get() : sprite_.get();
// Renderiza stroke sin alpha (sólido) en textura temporal
Color solid_color = Color(stroke_color.r, stroke_color.g, stroke_color.b, 255);
for (int dist = 1; dist <= shadow_distance; ++dist) {
for (int dy = -dist; dy <= dist; ++dy) {
for (int dx = -dist; dx <= dist; ++dx) {
writeColoredWithSprite(stroke_sprite, shadow_distance + dx, shadow_distance + dy, text, solid_color, kerning, length);
}
}
}
// Restaura render target original
SDL_SetRenderTarget(renderer, original_target);
// Renderiza la textura temporal con el alpha deseado
temp_texture->setAlpha(stroke_color.a);
temp_texture->render(x - shadow_distance, y - shadow_distance);
}
// Escribe el texto con sombra
@@ -160,14 +293,28 @@ void Text::writeDX(Uint8 flags, int x, int y, const std::string &text, int kerni
}
if (SHADOWED) {
writeColored(x + shadow_distance, y + shadow_distance, text, shadow_color, kerning, length);
if (white_sprite_) {
writeColoredWithSprite(white_sprite_.get(), x + shadow_distance, y + shadow_distance, text, shadow_color, kerning, length);
} else {
writeColored(x + shadow_distance, y + shadow_distance, text, shadow_color, kerning, length);
}
}
if (STROKED) {
for (int dist = 1; dist <= shadow_distance; ++dist) {
for (int dy = -dist; dy <= dist; ++dy) {
for (int dx = -dist; dx <= dist; ++dx) {
writeColored(x + dx, y + dy, text, shadow_color, kerning, length);
if (shadow_color.a < 255) {
// Usa textura temporal para alpha correcto
writeStrokeWithAlpha(x, y, text, kerning, shadow_color, shadow_distance, length);
} else {
// Método tradicional para stroke sólido
for (int dist = 1; dist <= shadow_distance; ++dist) {
for (int dy = -dist; dy <= dist; ++dy) {
for (int dx = -dist; dx <= dist; ++dx) {
if (white_sprite_) {
writeColoredWithSprite(white_sprite_.get(), x + dx, y + dy, text, shadow_color, kerning, length);
} else {
writeColored(x + dx, y + dy, text, shadow_color, kerning, length);
}
}
}
}
}

View File

@@ -54,6 +54,8 @@ class Text {
// --- Constructores y destructor ---
Text(const std::shared_ptr<Texture> &texture, const std::string &text_file);
Text(const std::shared_ptr<Texture> &texture, const std::shared_ptr<Text::File> &text_file);
Text(const std::shared_ptr<Texture> &texture, const std::shared_ptr<Texture> &white_texture, const std::string &text_file);
Text(const std::shared_ptr<Texture> &texture, const std::shared_ptr<Texture> &white_texture, const std::shared_ptr<Text::File> &text_file);
~Text() = default;
// --- Métodos de escritura en pantalla ---
@@ -81,9 +83,14 @@ class Text {
// --- Métodos estáticos ---
static auto loadFile(const std::string &file_path) -> std::shared_ptr<Text::File>; // Llena una estructura Text::File desde un fichero
// --- Métodos privados ---
void writeColoredWithSprite(Sprite* sprite, int x, int y, const std::string &text, Color color, int kerning = 1, int length = -1); // Escribe con un sprite específico
void writeStrokeWithAlpha(int x, int y, const std::string &text, int kerning, Color stroke_color, Uint8 shadow_distance, int length = -1); // Escribe stroke con alpha correcto
private:
// --- 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
std::unique_ptr<Sprite> white_sprite_ = nullptr; // Objeto con los gráficos en blanco para efectos
// --- Variables de estado ---
std::array<Offset, 128> offset_ = {}; // Vector con las posiciones y ancho de cada letra