eliminat sistema de colisió antic

This commit is contained in:
2026-04-06 23:05:22 +02:00
parent 6be93da929
commit 5414b0dfd4
9 changed files with 155 additions and 1157 deletions

View File

@@ -1,494 +1,8 @@
#include "collision_map.hpp"
#include <algorithm> // Para std::ranges::any_of
#include <utility> // Para std::move
#ifdef _DEBUG
#include "core/system/debug.hpp" // Para Debug
#endif
#include "utils/defines.hpp" // Para Collision
// Constructor
CollisionMap::CollisionMap(std::vector<int> collision_tile_map, int conveyor_belt_direction)
: collision_tile_map_(std::move(collision_tile_map)),
conveyor_belt_direction_(conveyor_belt_direction),
tile_collider_(collision_tile_map_) {
// Inicializa todas las superficies de colisión
initializeSurfaces();
}
// Inicializa todas las superficies de colisión
void CollisionMap::initializeSurfaces() {
setBottomSurfaces();
setTopSurfaces();
setLeftSurfaces();
setRightSurfaces();
setLeftSlopes();
setRightSlopes();
setAutoSurfaces();
}
// Devuelve el tipo de tile que hay en ese pixel
auto CollisionMap::getTile(SDL_FPoint point) const -> Tile {
const int ROW = static_cast<int>(point.y / TILE_SIZE);
const int COL = static_cast<int>(point.x / TILE_SIZE);
const int POS = (ROW * MAP_WIDTH) + COL;
return getTile(POS);
}
// Devuelve el tipo de tile que hay en ese indice (lee del collision_tile_map)
auto CollisionMap::getTile(int index) const -> Tile {
if (index < 0 || index >= static_cast<int>(collision_tile_map_.size())) {
return Tile::EMPTY;
}
switch (collision_tile_map_[index]) {
case 1:
return Tile::WALL;
case 2:
return Tile::PASSABLE;
case 3:
return Tile::SLOPE_L;
case 4:
return Tile::SLOPE_R;
case 5:
return Tile::KILL;
case 6:
return Tile::ANIMATED;
default:
return Tile::EMPTY;
}
}
// Obten la coordenada de la cuesta a partir de un punto perteneciente a ese tile
auto CollisionMap::getSlopeHeight(SDL_FPoint p, Tile slope) -> int {
// Calcula la base del tile
int base = ((p.y / TILE_SIZE) * TILE_SIZE) + TILE_SIZE;
#ifdef _DEBUG
Debug::get()->set("slope.BASE", std::to_string(base));
#endif
// Calcula cuanto se ha entrado en el tile horizontalmente
const int POS = (static_cast<int>(p.x) % TILE_SIZE); // Esto da un valor entre 0 y 7
#ifdef _DEBUG
Debug::get()->set("slope.POS", std::to_string(POS));
#endif
// Se resta a la base la cantidad de pixeles pos en funcion de la rampa
if (slope == Tile::SLOPE_R) {
base -= POS + 1;
#ifdef _DEBUG
Debug::get()->set("slope.result", "BASE_R=" + std::to_string(base));
#endif
} else {
base -= (TILE_SIZE - POS);
#ifdef _DEBUG
Debug::get()->set("slope.result", "BASE_L=" + std::to_string(base));
#endif
}
return base;
}
// === Queries de colisión ===
// Comprueba las colisiones con paredes derechas
auto CollisionMap::checkRightSurfaces(const SDL_FRect& rect) -> int { // NOLINT(readability-convert-member-functions-to-static)
for (const auto& s : right_walls_) {
if (checkCollision(s, rect)) {
return s.x;
}
}
return Collision::NONE;
}
// Comprueba las colisiones con paredes izquierdas
auto CollisionMap::checkLeftSurfaces(const SDL_FRect& rect) -> int { // NOLINT(readability-convert-member-functions-to-static)
for (const auto& s : left_walls_) {
if (checkCollision(s, rect)) {
return s.x;
}
}
return Collision::NONE;
}
// Comprueba las colisiones con techos
auto CollisionMap::checkTopSurfaces(const SDL_FRect& rect) -> int { // NOLINT(readability-convert-member-functions-to-static)
for (const auto& s : top_floors_) {
if (checkCollision(s, rect)) {
return s.y;
}
}
return Collision::NONE;
}
// Comprueba las colisiones punto con techos
auto CollisionMap::checkTopSurfaces(const SDL_FPoint& p) -> bool {
return std::ranges::any_of(top_floors_, [&](const auto& s) -> bool {
return checkCollision(s, p);
});
}
// Comprueba las colisiones con suelos
auto CollisionMap::checkBottomSurfaces(const SDL_FRect& rect) -> int { // NOLINT(readability-convert-member-functions-to-static)
for (const auto& s : bottom_floors_) {
if (checkCollision(s, rect)) {
return s.y;
}
}
return Collision::NONE;
}
// Comprueba las colisiones con conveyor belts
auto CollisionMap::checkAutoSurfaces(const SDL_FRect& rect) -> int { // NOLINT(readability-convert-member-functions-to-static)
for (const auto& s : conveyor_belt_floors_) {
if (checkCollision(s, rect)) {
return s.y;
}
}
return Collision::NONE;
}
// Comprueba las colisiones punto con conveyor belts
auto CollisionMap::checkConveyorBelts(const SDL_FPoint& p) -> bool {
return std::ranges::any_of(conveyor_belt_floors_, [&](const auto& s) -> bool {
return checkCollision(s, p);
});
}
// Comprueba las colisiones línea con rampas izquierdas
auto CollisionMap::checkLeftSlopes(const LineVertical& line) -> int { // NOLINT(readability-convert-member-functions-to-static)
for (const auto& slope : left_slopes_) {
const auto P = checkCollision(slope, line);
if (P.x != -1) {
return P.y;
}
}
return Collision::NONE;
}
// Comprueba las colisiones punto con rampas izquierdas
auto CollisionMap::checkLeftSlopes(const SDL_FPoint& p) -> bool {
return std::ranges::any_of(left_slopes_, [&](const auto& slope) -> bool {
return checkCollision(p, slope);
});
}
// Comprueba las colisiones línea con rampas derechas
auto CollisionMap::checkRightSlopes(const LineVertical& line) -> int { // NOLINT(readability-convert-member-functions-to-static)
for (const auto& slope : right_slopes_) {
const auto P = checkCollision(slope, line);
if (P.x != -1) {
return P.y;
}
}
return Collision::NONE;
}
// Comprueba las colisiones punto con rampas derechas
auto CollisionMap::checkRightSlopes(const SDL_FPoint& p) -> bool {
return std::ranges::any_of(right_slopes_, [&](const auto& slope) -> bool {
return checkCollision(p, slope);
});
}
// Obtiene puntero a slope en un punto (prioriza left_slopes_ sobre right_slopes_)
auto CollisionMap::getSlopeAtPoint(const SDL_FPoint& p) const -> const LineDiagonal* { // NOLINT(readability-convert-member-functions-to-static)
// Primero busca en rampas izquierdas
for (const auto& slope : left_slopes_) {
if (checkCollision(p, slope)) {
return &slope;
}
}
// Luego busca en rampas derechas
for (const auto& slope : right_slopes_) {
if (checkCollision(p, slope)) {
return &slope;
}
}
// No hay colisión con ninguna slope
return nullptr;
}
// === Helpers para recopilar tiles ===
// Helper: recopila tiles inferiores (muros sin muro debajo)
auto CollisionMap::collectBottomTiles() -> std::vector<int> { // NOLINT(readability-make-member-function-const)
std::vector<int> tile;
// Busca todos los tiles de tipo muro que no tengan debajo otro muro
// Hay que recorrer la habitación por filas (excepto los de la última fila)
for (int i = 0; i < (int)collision_tile_map_.size() - MAP_WIDTH; ++i) {
if (getTile(i) == Tile::WALL && getTile(i + MAP_WIDTH) != Tile::WALL) {
tile.push_back(i);
// Si llega al final de la fila, introduce un separador
if (i % MAP_WIDTH == MAP_WIDTH - 1) {
tile.push_back(-1);
}
}
}
// Añade un terminador
tile.push_back(-1);
return tile;
}
// Helper: recopila tiles superiores (muros o pasables sin muro encima)
auto CollisionMap::collectTopTiles() -> std::vector<int> { // NOLINT(readability-make-member-function-const)
std::vector<int> tile;
// Busca todos los tiles de tipo muro o pasable que no tengan encima un muro
// Hay que recorrer la habitación por filas (excepto los de la primera fila)
for (int i = MAP_WIDTH; i < (int)collision_tile_map_.size(); ++i) {
if ((getTile(i) == Tile::WALL || getTile(i) == Tile::PASSABLE) && getTile(i - MAP_WIDTH) != Tile::WALL) {
tile.push_back(i);
// Si llega al final de la fila, introduce un separador
if (i % MAP_WIDTH == MAP_WIDTH - 1) {
tile.push_back(-1);
}
}
}
// Añade un terminador
tile.push_back(-1);
return tile;
}
// Helper: recopila tiles conveyor belt
auto CollisionMap::collectConveyorTiles() -> std::vector<int> { // NOLINT(readability-make-member-function-const)
std::vector<int> tile;
// Busca todos los tiles de tipo conveyor
for (int i = MAP_WIDTH; i < (int)collision_tile_map_.size(); ++i) {
if (getTile(i) == Tile::ANIMATED) {
tile.push_back(i);
// Si llega al final de la fila, introduce un separador
if (i % MAP_WIDTH == MAP_WIDTH - 1) {
tile.push_back(-1);
}
}
}
// Añade un terminador si hay tiles
if (!tile.empty()) {
tile.push_back(-1);
}
return tile;
}
// Helper: construye lineas horizontales a partir de tiles consecutivos
void CollisionMap::buildHorizontalLines(const std::vector<int>& tiles, std::vector<LineHorizontal>& lines, bool is_bottom_surface) { // NOLINT(readability-convert-member-functions-to-static)
if (tiles.size() <= 1) {
return;
}
int i = 0;
while (i < static_cast<int>(tiles.size()) - 1) {
LineHorizontal line;
line.x1 = (tiles[i] % MAP_WIDTH) * TILE_SIZE;
// Calcula Y segun si es superficie inferior o superior
if (is_bottom_surface) {
line.y = ((tiles[i] / MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
} else {
line.y = (tiles[i] / MAP_WIDTH) * TILE_SIZE;
}
int last_one = i;
i++;
// Encuentra tiles consecutivos
if (i < static_cast<int>(tiles.size())) {
while (tiles[i] == tiles[i - 1] + 1) {
last_one = i;
i++;
if (i >= static_cast<int>(tiles.size())) {
break;
}
}
}
line.x2 = ((tiles[last_one] % MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
lines.push_back(line);
// Salta separadores
if (i < static_cast<int>(tiles.size()) && tiles[i] == -1) {
i++;
}
}
}
// === Métodos de generación de geometría ===
// Calcula las superficies inferiores
void CollisionMap::setBottomSurfaces() {
std::vector<int> tile = collectBottomTiles();
buildHorizontalLines(tile, bottom_floors_, true);
}
// Calcula las superficies superiores
void CollisionMap::setTopSurfaces() {
std::vector<int> tile = collectTopTiles();
buildHorizontalLines(tile, top_floors_, false);
}
// Calcula las superficies laterales izquierdas
void CollisionMap::setLeftSurfaces() { // NOLINT(readability-make-member-function-const)
std::vector<int> tile;
// Busca todos los tiles de tipo muro que no tienen a su izquierda un tile de tipo muro
// Hay que recorrer la habitación por columnas (excepto los de la primera columna)
for (int i = 1; i < MAP_WIDTH; ++i) {
for (int j = 0; j < MAP_HEIGHT; ++j) {
const int POS = ((j * MAP_WIDTH) + i);
if (getTile(POS) == Tile::WALL && getTile(POS - 1) != Tile::WALL) {
tile.push_back(POS);
}
}
}
// Añade un terminador
tile.push_back(-1);
// Recorre el vector de tiles buscando tiles consecutivos
// (Los tiles de la misma columna, la diferencia entre ellos es de mapWidth)
// para localizar las superficies
if ((int)tile.size() > 1) {
int i = 0;
do {
LineVertical line;
line.x = (tile[i] % MAP_WIDTH) * TILE_SIZE;
line.y1 = ((tile[i] / MAP_WIDTH) * TILE_SIZE);
while (tile[i] + MAP_WIDTH == tile[i + 1]) {
if (i == (int)tile.size() - 1) {
break;
}
i++;
}
line.y2 = ((tile[i] / MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
left_walls_.push_back(line);
i++;
} while (i < (int)tile.size() - 1);
}
}
// Calcula las superficies laterales derechas
void CollisionMap::setRightSurfaces() { // NOLINT(readability-make-member-function-const)
std::vector<int> tile;
// Busca todos los tiles de tipo muro que no tienen a su derecha un tile de tipo muro
// Hay que recorrer la habitación por columnas (excepto los de la última columna)
for (int i = 0; i < MAP_WIDTH - 1; ++i) {
for (int j = 0; j < MAP_HEIGHT; ++j) {
const int POS = ((j * MAP_WIDTH) + i);
if (getTile(POS) == Tile::WALL && getTile(POS + 1) != Tile::WALL) {
tile.push_back(POS);
}
}
}
// Añade un terminador
tile.push_back(-1);
// Recorre el vector de tiles buscando tiles consecutivos
// (Los tiles de la misma columna, la diferencia entre ellos es de mapWidth)
// para localizar las superficies
if ((int)tile.size() > 1) {
int i = 0;
do {
LineVertical line;
line.x = ((tile[i] % MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
line.y1 = ((tile[i] / MAP_WIDTH) * TILE_SIZE);
while (tile[i] + MAP_WIDTH == tile[i + 1]) {
if (i == (int)tile.size() - 1) {
break;
}
i++;
}
line.y2 = ((tile[i] / MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
right_walls_.push_back(line);
i++;
} while (i < (int)tile.size() - 1);
}
}
// Encuentra todas las rampas que suben hacia la izquierda
void CollisionMap::setLeftSlopes() { // NOLINT(readability-make-member-function-const)
// Recorre la habitación entera por filas buscando tiles de tipo t_slope_l
std::vector<int> found;
for (int i = 0; i < (int)collision_tile_map_.size(); ++i) {
if (getTile(i) == Tile::SLOPE_L) {
found.push_back(i);
}
}
// El primer elemento es el inicio de una rampa. Se añade ese elemento y se buscan los siguientes,
// que seran i + mapWidth + 1. Conforme se añaden se eliminan y se vuelve a escudriñar el vector de
// tiles encontrados hasta que esté vacío
while (!found.empty()) {
LineDiagonal line;
line.x1 = (found[0] % MAP_WIDTH) * TILE_SIZE;
line.y1 = (found[0] / MAP_WIDTH) * TILE_SIZE;
int looking_for = found[0] + MAP_WIDTH + 1;
int last_one_found = found[0];
found.erase(found.begin());
for (int i = 0; i < (int)found.size(); ++i) {
if (found[i] == looking_for) {
last_one_found = looking_for;
looking_for += MAP_WIDTH + 1;
found.erase(found.begin() + i);
i--;
}
}
line.x2 = ((last_one_found % MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
line.y2 = ((last_one_found / MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
left_slopes_.push_back(line);
}
}
// Encuentra todas las rampas que suben hacia la derecha
void CollisionMap::setRightSlopes() { // NOLINT(readability-make-member-function-const)
// Recorre la habitación entera por filas buscando tiles de tipo t_slope_r
std::vector<int> found;
for (int i = 0; i < (int)collision_tile_map_.size(); ++i) {
if (getTile(i) == Tile::SLOPE_R) {
found.push_back(i);
}
}
// El primer elemento es el inicio de una rampa. Se añade ese elemento y se buscan los siguientes,
// que seran i + mapWidth - 1. Conforme se añaden se eliminan y se vuelve a escudriñar el vector de
// tiles encontrados hasta que esté vacío
while (!found.empty()) {
LineDiagonal line;
line.x1 = ((found[0] % MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
line.y1 = (found[0] / MAP_WIDTH) * TILE_SIZE;
int looking_for = found[0] + MAP_WIDTH - 1;
int last_one_found = found[0];
found.erase(found.begin());
for (int i = 0; i < (int)found.size(); ++i) {
if (found[i] == looking_for) {
last_one_found = looking_for;
looking_for += MAP_WIDTH - 1;
found.erase(found.begin() + i);
i--;
}
}
line.x2 = (last_one_found % MAP_WIDTH) * TILE_SIZE;
line.y2 = ((last_one_found / MAP_WIDTH) * TILE_SIZE) + TILE_SIZE - 1;
right_slopes_.push_back(line);
}
}
// Calcula las superficies automaticas (conveyor belts)
void CollisionMap::setAutoSurfaces() {
std::vector<int> tile = collectConveyorTiles();
buildHorizontalLines(tile, conveyor_belt_floors_, false);
}
tile_collider_(collision_tile_map_) {}

View File

@@ -1,123 +1,31 @@
#pragma once
#include <SDL3/SDL.h>
#include <vector>
#include <vector> // Para vector
#include "game/gameplay/tile_collider.hpp" // Para TileCollider
#include "utils/defines.hpp" // Para Tile::SIZE, Map::WIDTH, Map::HEIGHT
#include "utils/utils.hpp" // Para LineHorizontal, LineDiagonal, LineVertical
#include "game/gameplay/tile_collider.hpp"
/**
* @brief Mapa de colisiones de una habitación
*
* Responsabilidades:
* - Almacenar la geometría de colisión (superficies, rampas, conveyor belts)
* - Generar geometría a partir del tilemap
* - Proporcionar queries de colisión para Player y otras entidades
* - Determinar tipo de tile en posiciones específicas
* Contiene el collision_tile_map (grid de tipos de tile) y el TileCollider
* que proporciona queries de colisión directas contra el grid.
*/
class CollisionMap {
public:
// Enumeración de tipos de tile (para colisiones)
enum class Tile {
EMPTY,
WALL,
PASSABLE,
SLOPE_L,
SLOPE_R,
KILL,
ANIMATED
};
/**
* @brief Constructor
* @param collision_tile_map Mapa de colisiones por tile (0=vacío, 1=muro, 2=passable, 3=slope_l, 4=slope_r, 5=kill, 6=conveyor)
* @param conveyor_belt_direction Dirección de las cintas transportadoras (-1, 0, +1)
*/
CollisionMap(std::vector<int> collision_tile_map, int conveyor_belt_direction);
~CollisionMap() = default;
// Prohibir copia y movimiento
CollisionMap(const CollisionMap&) = delete;
auto operator=(const CollisionMap&) -> CollisionMap& = delete;
CollisionMap(CollisionMap&&) = delete;
auto operator=(CollisionMap&&) -> CollisionMap& = delete;
// --- Queries de tipo de tile ---
[[nodiscard]] auto getTile(SDL_FPoint point) const -> Tile; // Devuelve el tipo de tile en un punto (pixel)
[[nodiscard]] auto getTile(int index) const -> Tile; // Devuelve el tipo de tile en un índice del tilemap
// --- Queries de colisión con superficies ---
auto checkRightSurfaces(const SDL_FRect& rect) -> int; // Colisión con paredes derechas (retorna X)
auto checkLeftSurfaces(const SDL_FRect& rect) -> int; // Colisión con paredes izquierdas (retorna X)
auto checkTopSurfaces(const SDL_FRect& rect) -> int; // Colisión con techos (retorna Y)
auto checkTopSurfaces(const SDL_FPoint& p) -> bool; // Colisión punto con techos
auto checkBottomSurfaces(const SDL_FRect& rect) -> int; // Colisión con suelos (retorna Y)
// --- Queries de colisión con superficies automáticas (conveyor belts) ---
auto checkAutoSurfaces(const SDL_FRect& rect) -> int; // Colisión con conveyor belts (retorna Y)
auto checkConveyorBelts(const SDL_FPoint& p) -> bool; // Colisión punto con conveyor belts
// --- Queries de colisión con rampas ---
auto checkLeftSlopes(const LineVertical& line) -> int; // Colisión línea con rampas izquierdas (retorna Y)
auto checkLeftSlopes(const SDL_FPoint& p) -> bool; // Colisión punto con rampas izquierdas
auto checkRightSlopes(const LineVertical& line) -> int; // Colisión línea con rampas derechas (retorna Y)
auto checkRightSlopes(const SDL_FPoint& p) -> bool; // Colisión punto con rampas derechas
[[nodiscard]] auto getSlopeAtPoint(const SDL_FPoint& p) const -> const LineDiagonal*; // Obtiene puntero a slope en un punto
// --- Métodos estáticos ---
static auto getTileSize() -> int { return TILE_SIZE; } // Tamaño del tile en pixels
static auto getSlopeHeight(SDL_FPoint p, Tile slope) -> int; // Altura de rampa en un punto
// --- Getters ---
[[nodiscard]] auto getConveyorBeltDirection() const -> int { return conveyor_belt_direction_; }
[[nodiscard]] auto getTileCollider() const -> const TileCollider& { return tile_collider_; }
// Getters para debug visualization
[[nodiscard]] auto getBottomFloors() const -> const std::vector<LineHorizontal>& { return bottom_floors_; }
[[nodiscard]] auto getTopFloors() const -> const std::vector<LineHorizontal>& { return top_floors_; }
[[nodiscard]] auto getLeftWalls() const -> const std::vector<LineVertical>& { return left_walls_; }
[[nodiscard]] auto getRightWalls() const -> const std::vector<LineVertical>& { return right_walls_; }
[[nodiscard]] auto getLeftSlopes() const -> const std::vector<LineDiagonal>& { return left_slopes_; }
[[nodiscard]] auto getRightSlopes() const -> const std::vector<LineDiagonal>& { return right_slopes_; }
[[nodiscard]] auto getConveyorBeltFloors() const -> const std::vector<LineHorizontal>& { return conveyor_belt_floors_; }
[[nodiscard]] auto getConveyorBeltDirection() const -> int { return conveyor_belt_direction_; }
[[nodiscard]] auto getCollisionTileMap() const -> const std::vector<int>& { return collision_tile_map_; }
private:
// --- Constantes ---
static constexpr int TILE_SIZE = ::Tile::SIZE; // Tamaño del tile en pixels
static constexpr int MAP_WIDTH = ::Map::WIDTH; // Ancho del mapa en tiles
static constexpr int MAP_HEIGHT = ::Map::HEIGHT; // Alto del mapa en tiles
// --- Datos de la habitación ---
std::vector<int> collision_tile_map_; // Mapa de colisiones por tile
int conveyor_belt_direction_; // Dirección de conveyor belts
TileCollider tile_collider_; // Sistema de colisión por tiles
// --- Geometría de colisión ---
std::vector<LineHorizontal> bottom_floors_; // Superficies inferiores (suelos)
std::vector<LineHorizontal> top_floors_; // Superficies superiores (techos)
std::vector<LineVertical> left_walls_; // Paredes izquierdas
std::vector<LineVertical> right_walls_; // Paredes derechas
std::vector<LineDiagonal> left_slopes_; // Rampas que suben hacia la izquierda
std::vector<LineDiagonal> right_slopes_; // Rampas que suben hacia la derecha
std::vector<LineHorizontal> conveyor_belt_floors_; // Superficies automáticas (conveyor belts)
// --- Métodos privados de generación de geometría ---
void initializeSurfaces(); // Inicializa todas las superficies de colisión
// Helpers para recopilar tiles
auto collectBottomTiles() -> std::vector<int>; // Tiles con superficie inferior
auto collectTopTiles() -> std::vector<int>; // Tiles con superficie superior
auto collectConveyorTiles() -> std::vector<int>; // Tiles conveyor belt
// Construcción de geometría
static void buildHorizontalLines(const std::vector<int>& tiles, std::vector<LineHorizontal>& lines, bool is_bottom_surface);
void setBottomSurfaces(); // Calcula superficies inferiores
void setTopSurfaces(); // Calcula superficies superiores
void setLeftSurfaces(); // Calcula paredes izquierdas
void setRightSurfaces(); // Calcula paredes derechas
void setLeftSlopes(); // Calcula rampas izquierdas
void setRightSlopes(); // Calcula rampas derechas
void setAutoSurfaces(); // Calcula conveyor belts
std::vector<int> collision_tile_map_;
int conveyor_belt_direction_;
TileCollider tile_collider_;
};

View File

@@ -31,7 +31,7 @@ Room::Room(const std::string& room_path, std::shared_ptr<Scoreboard::Data> data)
// Crea el renderizador del tilemap (necesita tile_map_, tile_set_width_, surface_, bg_color_, conveyor_belt_direction_)
tilemap_renderer_ = std::make_unique<TilemapRenderer>(tile_map_, tile_set_width_, surface_, bg_color_, conveyor_belt_direction_);
tilemap_renderer_->initialize(collision_map_.get()); // Inicializa (crea map_surface, pinta tiles, busca animados)
tilemap_renderer_->initialize(room->collision_tile_map);
Screen::get()->setBorderColor(border_color_); // Establece el color del borde
}
@@ -96,7 +96,7 @@ void Room::renderItems() {
#ifdef _DEBUG
// Redibuja el mapa (para actualizar modo debug)
void Room::redrawMap() {
tilemap_renderer_->redrawMap(collision_map_.get());
tilemap_renderer_->redrawMap(collision_map_->getCollisionTileMap());
}
// Actualiza animaciones sin mover enemigos (para editor de mapas)
@@ -123,7 +123,7 @@ void Room::setTile(int index, int tile_value) {
void Room::setBgColor(Uint8 color) {
bg_color_ = color;
tilemap_renderer_->setBgColor(color);
tilemap_renderer_->redrawMap(collision_map_.get());
tilemap_renderer_->redrawMap(collision_map_->getCollisionTileMap());
}
// Cambia colores de items en vivo (para editor)
@@ -181,99 +181,14 @@ auto Room::getRoom(Border border) -> std::string { // NOLINT(readability-conver
}
}
// Devuelve el tipo de tile que hay en ese pixel
auto Room::getTile(SDL_FPoint point) -> Tile { // NOLINT(readability-convert-member-functions-to-static)
// Delega a CollisionMap y convierte el resultado
const auto COLLISION_TILE = collision_map_->getTile(point);
return static_cast<Tile>(COLLISION_TILE);
}
// Devuelve el tipo de tile en un índice del tilemap
auto Room::getTile(int index) -> Tile { // NOLINT(readability-convert-member-functions-to-static)
// Delega a CollisionMap y convierte el resultado
const auto COLLISION_TILE = collision_map_->getTile(index);
return static_cast<Tile>(COLLISION_TILE);
}
// Indica si hay colision con un enemigo a partir de un rectangulo
auto Room::enemyCollision(SDL_FRect& rect) -> bool {
return enemy_manager_->checkCollision(rect);
}
// Indica si hay colision con un objeto a partir de un rectangulo
auto Room::itemCollision(SDL_FRect& rect) -> bool {
return item_manager_->checkCollision(rect);
}
// Obten la coordenada de la cuesta a partir de un punto perteneciente a ese tile
auto Room::getSlopeHeight(SDL_FPoint p, Tile slope) -> int {
// Delega a CollisionMap (método estático)
const auto COLLISION_TILE = static_cast<CollisionMap::Tile>(slope);
return CollisionMap::getSlopeHeight(p, COLLISION_TILE);
}
// === Métodos de colisión (delegados a CollisionMap) ===
// Comprueba las colisiones con paredes derechas
auto Room::checkRightSurfaces(const SDL_FRect& rect) -> int {
return collision_map_->checkRightSurfaces(rect);
}
// Comprueba las colisiones con paredes izquierdas
auto Room::checkLeftSurfaces(const SDL_FRect& rect) -> int {
return collision_map_->checkLeftSurfaces(rect);
}
// Comprueba las colisiones con techos
auto Room::checkTopSurfaces(const SDL_FRect& rect) -> int {
return collision_map_->checkTopSurfaces(rect);
}
// Comprueba las colisiones punto con techos
auto Room::checkTopSurfaces(const SDL_FPoint& p) -> bool {
return collision_map_->checkTopSurfaces(p);
}
// Comprueba las colisiones con suelos
auto Room::checkBottomSurfaces(const SDL_FRect& rect) -> int {
return collision_map_->checkBottomSurfaces(rect);
}
// Comprueba las colisiones con conveyor belts
auto Room::checkAutoSurfaces(const SDL_FRect& rect) -> int {
return collision_map_->checkAutoSurfaces(rect);
}
// Comprueba las colisiones punto con conveyor belts
auto Room::checkConveyorBelts(const SDL_FPoint& p) -> bool {
return collision_map_->checkConveyorBelts(p);
}
// Comprueba las colisiones línea con rampas izquierdas
auto Room::checkLeftSlopes(const LineVertical& line) -> int {
return collision_map_->checkLeftSlopes(line);
}
// Comprueba las colisiones punto con rampas izquierdas
auto Room::checkLeftSlopes(const SDL_FPoint& p) -> bool {
return collision_map_->checkLeftSlopes(p);
}
// Comprueba las colisiones línea con rampas derechas
auto Room::checkRightSlopes(const LineVertical& line) -> int {
return collision_map_->checkRightSlopes(line);
}
// Comprueba las colisiones punto con rampas derechas
auto Room::checkRightSlopes(const SDL_FPoint& p) -> bool {
return collision_map_->checkRightSlopes(p);
}
// Obtiene puntero a slope en un punto
auto Room::getSlopeAtPoint(const SDL_FPoint& p) const -> const LineDiagonal* {
return collision_map_->getSlopeAtPoint(p);
}
// Carga una habitación desde un archivo YAML (delegado a RoomLoader)
auto Room::loadYAML(const std::string& file_path, bool verbose) -> Data { // NOLINT(readability-convert-member-functions-to-static)
return RoomLoader::loadYAML(file_path, verbose);

View File

@@ -10,9 +10,7 @@
#include "game/entities/item.hpp" // Para ItemData
#include "game/gameplay/scoreboard.hpp" // Para Scoreboard::Data
#include "utils/defines.hpp" // Para Tile::SIZE, Map::WIDTH, Map::HEIGHT
#include "utils/utils.hpp" // Para LineHorizontal, LineDiagonal, LineVertical
class Sprite; // lines 12-12
class Surface; // lines 13-13
class Surface;
class EnemyManager;
class ItemManager;
class CollisionMap;
@@ -30,114 +28,84 @@ class Room {
NONE = 4
};
enum class Tile {
EMPTY,
WALL,
PASSABLE,
SLOPE_L,
SLOPE_R,
KILL,
ANIMATED
};
struct Data {
std::string number; // Numero de la habitación
Uint8 bg_color{0}; // Color de fondo de la habitación
Uint8 border_color{0}; // Color del borde de la pantalla
Uint8 item_color1{12}; // Color 1 para los items de la habitación
Uint8 item_color2{6}; // Color 2 para los items de la habitación
std::string upper_room; // Identificador de la habitación que se encuentra arriba
std::string lower_room; // Identificador de la habitación que se encuentra abajo
std::string left_room; // Identificador de la habitación que se encuentra a la izquierda
std::string right_room; // Identificador de la habitación que se encuentra a la derecha
std::string tile_set_file; // Imagen con los gráficos para la habitación
int conveyor_belt_direction{0}; // Sentido en el que arrastran las superficies automáticas de la habitación
std::vector<int> tile_map; // Índice de los tiles a dibujar en la habitación (embebido desde YAML)
std::vector<int> collision_tile_map; // Mapa de colisiones por tile (0=vacío, 1=sólido)
std::vector<Enemy::Data> enemies; // Listado con los enemigos de la habitación
std::vector<Item::Data> items; // Listado con los items que hay en la habitación
std::string number;
Uint8 bg_color{0};
Uint8 border_color{0};
Uint8 item_color1{12};
Uint8 item_color2{6};
std::string upper_room;
std::string lower_room;
std::string left_room;
std::string right_room;
std::string tile_set_file;
int conveyor_belt_direction{0};
std::vector<int> tile_map;
std::vector<int> collision_tile_map;
std::vector<Enemy::Data> enemies;
std::vector<Item::Data> items;
};
// Constructor y destructor
Room(const std::string& room_path, std::shared_ptr<Scoreboard::Data> data);
~Room(); // NOLINT(modernize-use-equals-default, performance-trivially-destructible) -- defined in .cpp for unique_ptr with forward declarations
~Room(); // NOLINT(modernize-use-equals-default, performance-trivially-destructible)
// --- Funciones ---
[[nodiscard]] auto getNumber() const -> const std::string& { return number_; } // Devuelve el numero de la habitación
[[nodiscard]] auto getBGColor() const -> Uint8 { return bg_color_; } // Devuelve el color de la habitación
[[nodiscard]] auto getBorderColor() const -> Uint8 { return border_color_; } // Devuelve el color del borde
void renderMap(); // Dibuja el mapa en pantalla
void renderEnemies(); // Dibuja los enemigos en pantalla
void renderItems(); // Dibuja los objetos en pantalla
[[nodiscard]] auto getNumber() const -> const std::string& { return number_; }
[[nodiscard]] auto getBGColor() const -> Uint8 { return bg_color_; }
[[nodiscard]] auto getBorderColor() const -> Uint8 { return border_color_; }
void renderMap();
void renderEnemies();
void renderItems();
#ifdef _DEBUG
void redrawMap(); // Redibuja el mapa (para actualizar modo debug)
void updateEditorMode(float delta_time); // Actualiza animaciones sin mover enemigos (para editor)
void resetEnemyPositions(const std::vector<Enemy::Data>& enemy_data); // Resetea enemigos a posiciones iniciales
auto getEnemyManager() -> EnemyManager* { return enemy_manager_.get(); } // Acceso al gestor de enemigos (para editor)
auto getItemManager() -> ItemManager* { return item_manager_.get(); } // Acceso al gestor de items (para editor)
void setBgColor(Uint8 color); // Cambia color de fondo y redibuja (para editor)
void setItemColors(Uint8 color1, Uint8 color2); // Cambia colores de items (para editor)
void setTile(int index, int tile_value); // Cambia un tile y redibuja (para editor)
void redrawMap();
void updateEditorMode(float delta_time);
void resetEnemyPositions(const std::vector<Enemy::Data>& enemy_data);
auto getEnemyManager() -> EnemyManager* { return enemy_manager_.get(); }
auto getItemManager() -> ItemManager* { return item_manager_.get(); }
void setBgColor(Uint8 color);
void setItemColors(Uint8 color1, Uint8 color2);
void setTile(int index, int tile_value);
[[nodiscard]] auto getTileSetFile() const -> const std::string& { return tile_set_file_; }
[[nodiscard]] auto getTileSetWidth() const -> int { return tile_set_width_; }
#endif
void update(float delta_time); // Actualiza las variables y objetos de la habitación
auto getRoom(Border border) -> std::string; // Devuelve la cadena del fichero de la habitación contigua segun el borde
auto getTile(SDL_FPoint point) -> Tile; // Devuelve el tipo de tile que hay en ese pixel
auto getTile(int index) -> Tile; // Devuelve el tipo de tile en un índice del tilemap
auto enemyCollision(SDL_FRect& rect) -> bool; // Indica si hay colision con un enemigo a partir de un rectangulo
auto itemCollision(SDL_FRect& rect) -> bool; // Indica si hay colision con un objeto a partir de un rectangulo
static auto getTileSize() -> int { return TILE_SIZE; } // Obten el tamaño del tile
static auto getSlopeHeight(SDL_FPoint p, Tile slope) -> int; // Obten la coordenada de la cuesta a partir de un punto perteneciente a ese tile
auto checkRightSurfaces(const SDL_FRect& rect) -> int; // Comprueba las colisiones
auto checkLeftSurfaces(const SDL_FRect& rect) -> int; // Comprueba las colisiones
auto checkTopSurfaces(const SDL_FRect& rect) -> int; // Comprueba las colisiones
auto checkBottomSurfaces(const SDL_FRect& rect) -> int; // Comprueba las colisiones
auto checkAutoSurfaces(const SDL_FRect& rect) -> int; // Comprueba las colisiones
auto checkTopSurfaces(const SDL_FPoint& p) -> bool; // Comprueba las colisiones
auto checkConveyorBelts(const SDL_FPoint& p) -> bool; // Comprueba las colisiones
auto checkLeftSlopes(const LineVertical& line) -> int; // Comprueba las colisiones
auto checkLeftSlopes(const SDL_FPoint& p) -> bool; // Comprueba las colisiones
auto checkRightSlopes(const LineVertical& line) -> int; // Comprueba las colisiones
auto checkRightSlopes(const SDL_FPoint& p) -> bool; // Comprueba las colisiones
[[nodiscard]] auto getSlopeAtPoint(const SDL_FPoint& p) const -> const LineDiagonal*; // Obtiene puntero a slope en un punto
void setPaused(bool value); // Pone el mapa en modo pausa
[[nodiscard]] auto getConveyorBeltDirection() const -> int { return conveyor_belt_direction_; } // Obten la direccion de las superficies automaticas
void update(float delta_time);
auto getRoom(Border border) -> std::string;
auto enemyCollision(SDL_FRect& rect) -> bool;
auto itemCollision(SDL_FRect& rect) -> bool;
void setPaused(bool value);
[[nodiscard]] auto getConveyorBeltDirection() const -> int { return conveyor_belt_direction_; }
[[nodiscard]] auto getTileCollider() const -> const TileCollider&;
// Método de carga de archivos YAML (delegado a RoomLoader)
static auto loadYAML(const std::string& file_path, bool verbose = false) -> Data; // Carga habitación desde archivo YAML unificado
static auto loadYAML(const std::string& file_path, bool verbose = false) -> Data;
private:
// Constantes
static constexpr int TILE_SIZE = ::Tile::SIZE; // Ancho del tile en pixels
static constexpr int MAP_WIDTH = ::Map::WIDTH; // Ancho del mapa en tiles
static constexpr int MAP_HEIGHT = ::Map::HEIGHT; // Alto del mapa en tiles
static constexpr int TILE_SIZE = ::Tile::SIZE;
static constexpr int MAP_WIDTH = ::Map::WIDTH;
static constexpr int MAP_HEIGHT = ::Map::HEIGHT;
// Objetos y punteros
std::unique_ptr<EnemyManager> enemy_manager_; // Gestor de enemigos de la habitación
std::unique_ptr<ItemManager> item_manager_; // Gestor de items de la habitación
std::unique_ptr<CollisionMap> collision_map_; // Mapa de colisiones de la habitación
std::unique_ptr<TilemapRenderer> tilemap_renderer_; // Renderizador del mapa de tiles
std::shared_ptr<Surface> surface_; // Textura con los graficos de la habitación
std::shared_ptr<Scoreboard::Data> data_; // Puntero a los datos del marcador
std::unique_ptr<EnemyManager> enemy_manager_;
std::unique_ptr<ItemManager> item_manager_;
std::unique_ptr<CollisionMap> collision_map_;
std::unique_ptr<TilemapRenderer> tilemap_renderer_;
std::shared_ptr<Surface> surface_;
std::shared_ptr<Scoreboard::Data> data_;
// --- Variables ---
std::string number_; // Numero de la habitación
Uint8 bg_color_{0}; // Color de fondo de la habitación
Uint8 border_color_{0}; // Color del borde de la pantalla
Uint8 item_color1_{12}; // Color 1 para los items de la habitación
Uint8 item_color2_{6}; // Color 2 para los items de la habitación
std::string upper_room_; // Identificador de la habitación que se encuentra arriba
std::string lower_room_; // Identificador de la habitación que se encuentra abajp
std::string left_room_; // Identificador de la habitación que se encuentra a la izquierda
std::string right_room_; // Identificador de la habitación que se encuentra a la derecha
std::string tile_set_file_; // Imagen con los graficos para la habitación
std::vector<int> tile_map_; // Indice de los tiles a dibujar en la habitación (embebido desde YAML)
int conveyor_belt_direction_{0}; // Sentido en el que arrastran las superficies automáticas de la habitación
bool is_paused_{false}; // Indica si el mapa esta en modo pausa
int tile_set_width_{0}; // Ancho del tileset en tiles
std::string number_;
Uint8 bg_color_{0};
Uint8 border_color_{0};
Uint8 item_color1_{12};
Uint8 item_color2_{6};
std::string upper_room_;
std::string lower_room_;
std::string left_room_;
std::string right_room_;
std::string tile_set_file_;
std::vector<int> tile_map_;
int conveyor_belt_direction_{0};
bool is_paused_{false};
int tile_set_width_{0};
// --- Funciones ---
void initializeRoom(const Data& room); // Inicializa los valores
};
void initializeRoom(const Data& room);
};

View File

@@ -4,48 +4,34 @@
#include "core/rendering/sprite/sprite.hpp"
#include "core/rendering/surface.hpp"
#ifdef _DEBUG
#include "core/resources/resource_cache.hpp" // Para Resource::Cache (collision.gif)
#include "core/system/debug.hpp"
#endif
#include "game/gameplay/collision_map.hpp"
#include "utils/utils.hpp"
// Constructor
TilemapRenderer::TilemapRenderer(std::vector<int> tile_map, int tile_set_width, std::shared_ptr<Surface> tileset_surface, Uint8 bg_color, int conveyor_belt_direction)
: tile_map_(std::move(tile_map)),
tile_set_width_(tile_set_width),
tileset_surface_(std::move(tileset_surface)),
bg_color_(bg_color),
conveyor_belt_direction_(conveyor_belt_direction) {
// Crear la surface del mapa
map_surface_ = std::make_shared<Surface>(PlayArea::WIDTH, PlayArea::HEIGHT);
}
// Inicializa el renderizador
void TilemapRenderer::initialize(const CollisionMap* collision_map) {
setAnimatedTiles(collision_map);
fillMapTexture(collision_map);
void TilemapRenderer::initialize(const std::vector<int>& collision_tile_map) {
setAnimatedTiles(collision_tile_map);
fillMapTexture(collision_tile_map);
}
// Actualiza las animaciones de tiles
void TilemapRenderer::update(float delta_time) {
if (is_paused_) {
return;
}
// Actualiza el acumulador de tiempo
if (is_paused_) { return; }
time_accumulator_ += delta_time;
// Actualiza los tiles animados
updateAnimatedTiles();
}
// Renderiza el mapa completo en pantalla
void TilemapRenderer::render() {
// Dibuja la textura con el mapa en pantalla
SDL_FRect dest = {.x = 0, .y = 0, .w = PlayArea::WIDTH, .h = PlayArea::HEIGHT};
map_surface_->render(nullptr, &dest);
// Dibuja los tiles animados
#ifdef _DEBUG
if (!Debug::get()->isEnabled()) {
renderAnimatedTiles();
@@ -56,52 +42,11 @@ void TilemapRenderer::render() {
}
#ifdef _DEBUG
// Renderiza las superficies de colisión en modo debug (función helper estática)
static void renderDebugCollisionSurfaces(const CollisionMap* collision_map) {
auto surface = Screen::get()->getRendererSurface();
// BottomSurfaces
for (auto l : collision_map->getBottomFloors()) {
surface->drawLine(l.x1, l.y, l.x2, l.y, 2);
}
// TopSurfaces
for (auto l : collision_map->getTopFloors()) {
surface->drawLine(l.x1, l.y, l.x2, l.y, 4);
}
// LeftSurfaces
for (auto l : collision_map->getLeftWalls()) {
surface->drawLine(l.x, l.y1, l.x, l.y2, 8);
}
// RightSurfaces
for (auto l : collision_map->getRightWalls()) {
surface->drawLine(l.x, l.y1, l.x, l.y2, 6);
}
// LeftSlopes
for (auto l : collision_map->getLeftSlopes()) {
surface->drawLine(l.x1, l.y1, l.x2, l.y2, 10);
}
// RightSlopes
for (auto l : collision_map->getRightSlopes()) {
surface->drawLine(l.x1, l.y1, l.x2, l.y2, 12);
}
// AutoSurfaces (Conveyor Belts)
for (auto l : collision_map->getConveyorBeltFloors()) {
surface->drawLine(l.x1, l.y, l.x2, l.y, 14);
}
// Redibuja el tilemap (para actualizar modo debug: pinta collision tilemap o tiles normales)
void TilemapRenderer::redrawMap(const std::vector<int>& collision_tile_map) {
fillMapTexture(collision_tile_map);
}
// Redibuja el tilemap (para actualizar modo debug)
void TilemapRenderer::redrawMap(const CollisionMap* collision_map) {
fillMapTexture(collision_map);
}
// Cambia un tile y repinta solo esa celda en la map_surface
void TilemapRenderer::setTile(int index, int tile_value) {
if (index < 0 || index >= static_cast<int>(tile_map_.size())) { return; }
@@ -113,11 +58,9 @@ void TilemapRenderer::setTile(int index, int tile_value) {
auto previous_renderer = Screen::get()->getRendererSurface();
Screen::get()->setRendererSurface(map_surface_);
// Borrar la celda con el color de fondo
SDL_FRect cell = {.x = static_cast<float>(col * TILE_SIZE), .y = static_cast<float>(row * TILE_SIZE), .w = static_cast<float>(TILE_SIZE), .h = static_cast<float>(TILE_SIZE)};
map_surface_->fillRect(&cell, bg_color_);
// Dibujar el nuevo tile (si no es vacío ni animado)
if (tile_value > -1) {
const bool IS_ANIMATED = (tile_value >= 18 * tile_set_width_) && (tile_value < 19 * tile_set_width_);
if (!IS_ANIMATED) {
@@ -131,27 +74,44 @@ void TilemapRenderer::setTile(int index, int tile_value) {
Screen::get()->setRendererSurface(previous_renderer);
}
// Renderiza el collision tilemap superpuesto (modo debug)
static void renderDebugCollisionTilemap(const std::vector<int>& collision_tile_map) {
auto collision_surface = Resource::Cache::get()->getSurface("collision.gif");
if (!collision_surface) { return; }
for (int y = 0; y < Map::HEIGHT; ++y) {
for (int x = 0; x < Map::WIDTH; ++x) {
int index = (y * Map::WIDTH) + x;
if (index >= static_cast<int>(collision_tile_map.size())) { continue; }
int tile = collision_tile_map[index];
if (tile <= 0) { continue; }
SDL_FRect clip = {
.x = static_cast<float>(tile * Tile::SIZE),
.y = 0,
.w = static_cast<float>(Tile::SIZE),
.h = static_cast<float>(Tile::SIZE)};
collision_surface->render(x * Tile::SIZE, y * Tile::SIZE, &clip);
}
}
}
#endif
// Pinta el mapa estático y debug lines
void TilemapRenderer::fillMapTexture(const CollisionMap* collision_map) { // NOLINT(readability-convert-member-functions-to-static)
// Pinta el mapa estático
void TilemapRenderer::fillMapTexture(const std::vector<int>& collision_tile_map) {
auto previous_renderer = Screen::get()->getRendererSurface();
Screen::get()->setRendererSurface(map_surface_);
map_surface_->clear(bg_color_);
// Los tileSetFiles son de 20x20 tiles. El primer tile es el 0. Cuentan hacia la derecha y hacia abajo
SDL_FRect clip = {.x = 0, .y = 0, .w = TILE_SIZE, .h = TILE_SIZE};
for (int y = 0; y < MAP_HEIGHT; ++y) {
for (int x = 0; x < MAP_WIDTH; ++x) {
// Tiled pone los tiles vacios del mapa como cero y empieza a contar de 1 a n.
// Al cargar el mapa en memoria, se resta uno, por tanto los tiles vacios son -1
// Tampoco hay que dibujar los tiles animados que estan en la fila 19 (indices)
const int INDEX = (y * MAP_WIDTH) + x;
const bool A = (tile_map_[INDEX] >= 18 * tile_set_width_) && (tile_map_[INDEX] < 19 * tile_set_width_);
const bool B = tile_map_[INDEX] > -1;
// Los tiles animados (fila 18 del tileset) no se pintan en la textura estática
const bool IS_ANIMATED = (tile_map_[INDEX] >= 18 * tile_set_width_) && (tile_map_[INDEX] < 19 * tile_set_width_);
const bool HAS_TILE = tile_map_[INDEX] > -1;
if (B && !A) {
if (HAS_TILE && !IS_ANIMATED) {
clip.x = (tile_map_[INDEX] % tile_set_width_) * TILE_SIZE;
clip.y = (tile_map_[INDEX] / tile_set_width_) * TILE_SIZE;
#ifdef _DEBUG
@@ -166,25 +126,21 @@ void TilemapRenderer::fillMapTexture(const CollisionMap* collision_map) { // NO
}
#ifdef _DEBUG
// Pinta las superficies en el modo debug
// En modo debug, pintar el collision tilemap en vez de las líneas de colisión antiguas
if (Debug::get()->isEnabled()) {
renderDebugCollisionSurfaces(collision_map);
renderDebugCollisionTilemap(collision_tile_map);
}
#endif // _DEBUG
#endif
Screen::get()->setRendererSurface(previous_renderer);
}
// Localiza todos los tiles animados
void TilemapRenderer::setAnimatedTiles(const CollisionMap* collision_map) { // NOLINT(readability-convert-member-functions-to-static)
// Recorre la habitación entera por filas buscando tiles de tipo t_animated
for (int i = 0; i < (int)tile_map_.size(); ++i) {
const auto TILE_TYPE = collision_map->getTile(i);
if (TILE_TYPE == CollisionMap::Tile::ANIMATED) {
// La i es la ubicación
// Localiza tiles animados (conveyor belts) usando el collision_tile_map
void TilemapRenderer::setAnimatedTiles(const std::vector<int>& collision_tile_map) {
for (int i = 0; i < static_cast<int>(tile_map_.size()); ++i) {
// Un tile es animado si su valor en el collision tilemap es COLLISION_ANIMATED (6)
if (i < static_cast<int>(collision_tile_map.size()) && collision_tile_map[i] == COLLISION_ANIMATED) {
const int X = (i % MAP_WIDTH) * TILE_SIZE;
const int Y = (i / MAP_WIDTH) * TILE_SIZE;
// TileMap[i] es el tile a poner
const int XC = (tile_map_[i] % tile_set_width_) * TILE_SIZE;
const int YC = (tile_map_[i] / tile_set_width_) * TILE_SIZE;
@@ -197,14 +153,10 @@ void TilemapRenderer::setAnimatedTiles(const CollisionMap* collision_map) { //
}
}
// Actualiza tiles animados
void TilemapRenderer::updateAnimatedTiles() { // NOLINT(readability-make-member-function-const)
void TilemapRenderer::updateAnimatedTiles() {
const int NUM_FRAMES = 4;
// Calcular frame actual basado en tiempo
const int CURRENT_FRAME = static_cast<int>(time_accumulator_ / CONVEYOR_FRAME_DURATION) % NUM_FRAMES;
// Calcular offset basado en dirección
int offset = 0;
if (conveyor_belt_direction_ == -1) {
offset = CURRENT_FRAME * TILE_SIZE;
@@ -219,7 +171,6 @@ void TilemapRenderer::updateAnimatedTiles() { // NOLINT(readability-make-member
}
}
// Renderiza tiles animados
void TilemapRenderer::renderAnimatedTiles() {
for (const auto& a : animated_tiles_) {
a.sprite->render();

View File

@@ -3,118 +3,63 @@
#include <SDL3/SDL.h>
#include <memory> // Para shared_ptr
#include <string> // Para string
#include <vector> // Para vector
#include "utils/defines.hpp"
class Surface;
class Sprite;
class CollisionMap;
/**
* @brief Renderizador de tilemap de una habitación
*
* Responsabilidades:
* - Renderizar el mapa de tiles estático
* - Gestionar tiles animados (conveyor belts)
* - Actualizar animaciones basadas en tiempo
* - Renderizar debug visualization (en modo DEBUG)
*/
class TilemapRenderer {
public:
/**
* @brief Constructor
* @param tile_map Vector con índices de tiles de la habitación
* @param tile_set_width Ancho del tileset en tiles
* @param tileset_surface Surface con los gráficos del tileset
* @param bg_color Color de fondo de la habitación (como string)
* @param conveyor_belt_direction Dirección de las cintas transportadoras (-1, 0, +1)
*/
TilemapRenderer(std::vector<int> tile_map, int tile_set_width, std::shared_ptr<Surface> tileset_surface, Uint8 bg_color, int conveyor_belt_direction);
~TilemapRenderer() = default;
// Prohibir copia y movimiento
TilemapRenderer(const TilemapRenderer&) = delete;
auto operator=(const TilemapRenderer&) -> TilemapRenderer& = delete;
TilemapRenderer(TilemapRenderer&&) = delete;
auto operator=(TilemapRenderer&&) -> TilemapRenderer& = delete;
/**
* @brief Inicializa el renderizador
* @param collision_map Mapa de colisiones para determinar tiles animados
*
* Crea la textura del mapa, pinta los tiles estáticos, y localiza tiles animados
*/
void initialize(const CollisionMap* collision_map);
/**
* @brief Actualiza las animaciones de tiles
* @param delta_time Tiempo transcurrido desde el último frame (segundos)
*/
void initialize(const std::vector<int>& collision_tile_map);
void update(float delta_time);
/**
* @brief Renderiza el mapa completo en pantalla
*
* Dibuja la textura del mapa y los tiles animados
*/
void render();
#ifdef _DEBUG
/**
* @brief Redibuja el tilemap (para actualizar modo debug)
* @param collision_map Mapa de colisiones para dibujar líneas de debug
*
* Llamado cuando se activa/desactiva el modo debug para actualizar la visualización
*/
void redrawMap(const CollisionMap* collision_map);
void redrawMap(const std::vector<int>& collision_tile_map);
void setBgColor(Uint8 color) { bg_color_ = color; }
void setTile(int index, int tile_value); // Cambia un tile y repinta esa celda
void setTile(int index, int tile_value);
#endif
/**
* @brief Activa/desactiva modo pausa
* @param paused true para pausar, false para reanudar
*
* Nota: Actualmente no afecta al renderizado, pero mantiene consistencia con Room
*/
void setPaused(bool paused) { is_paused_ = paused; }
// Getter para la surface del mapa (usado por Room para acceso directo si es necesario)
[[nodiscard]] auto getMapSurface() const -> std::shared_ptr<Surface> { return map_surface_; }
private:
// Estructura para tiles animados (conveyor belts)
struct AnimatedTile {
std::shared_ptr<Sprite> sprite{nullptr}; // SurfaceSprite para dibujar el tile
int x_orig{0}; // Posición X del primer tile de la animación en tilesheet
std::shared_ptr<Sprite> sprite{nullptr};
int x_orig{0};
};
// === Constantes ===
static constexpr int TILE_SIZE = Tile::SIZE; // Ancho del tile en pixels
static constexpr int MAP_WIDTH = Map::WIDTH; // Ancho del mapa en tiles
static constexpr int MAP_HEIGHT = Map::HEIGHT; // Alto del mapa en tiles
static constexpr int PLAY_AREA_WIDTH = PlayArea::WIDTH; // Ancho del área de juego en pixels
static constexpr int PLAY_AREA_HEIGHT = PlayArea::HEIGHT; // Alto del área de juego en pixels
static constexpr float CONVEYOR_FRAME_DURATION = 0.05F; // Duración de cada frame (3 frames @ 60fps)
static constexpr int TILE_SIZE = Tile::SIZE;
static constexpr int MAP_WIDTH = Map::WIDTH;
static constexpr int MAP_HEIGHT = Map::HEIGHT;
static constexpr int PLAY_AREA_WIDTH = PlayArea::WIDTH;
static constexpr int PLAY_AREA_HEIGHT = PlayArea::HEIGHT;
static constexpr float CONVEYOR_FRAME_DURATION = 0.05F;
static constexpr int COLLISION_ANIMATED = 6; // Valor del tile de conveyor en el collision tilemap
// === Datos de la habitación ===
std::vector<int> tile_map_; // Índices de tiles de la habitación
int tile_set_width_; // Ancho del tileset en tiles
std::shared_ptr<Surface> tileset_surface_; // Gráficos del tileset
Uint8 bg_color_{0}; // Color de fondo
int conveyor_belt_direction_; // Dirección de conveyor belts
std::vector<int> tile_map_;
int tile_set_width_;
std::shared_ptr<Surface> tileset_surface_;
Uint8 bg_color_{0};
int conveyor_belt_direction_;
// === Renderizado ===
std::shared_ptr<Surface> map_surface_; // Textura para el mapa de la habitación
std::vector<AnimatedTile> animated_tiles_; // Tiles animados (conveyor belts)
float time_accumulator_{0.0F}; // Acumulador de tiempo para animaciones
bool is_paused_{false}; // Indica si está en modo pausa
std::shared_ptr<Surface> map_surface_;
std::vector<AnimatedTile> animated_tiles_;
float time_accumulator_{0.0F};
bool is_paused_{false};
// === Métodos privados ===
void fillMapTexture(const CollisionMap* collision_map); // Pinta el mapa estático y debug lines
void setAnimatedTiles(const CollisionMap* collision_map); // Localiza todos los tiles animados
void updateAnimatedTiles(); // Actualiza tiles animados
void renderAnimatedTiles(); // Renderiza tiles animados
void fillMapTexture(const std::vector<int>& collision_tile_map);
void setAnimatedTiles(const std::vector<int>& collision_tile_map);
void updateAnimatedTiles();
void renderAnimatedTiles();
};