treballant en el extendedMap per a les colisións fora de pantalla

This commit is contained in:
2026-04-09 21:46:45 +02:00
parent 2120641c3d
commit 4f890586f1
20 changed files with 326 additions and 383 deletions

View File

@@ -1,8 +1,91 @@
#include "collision_map.hpp"
#include <utility> // Para std::move
#include <algorithm> // Para std::ranges::fill
#include <utility> // Para std::move
CollisionMap::CollisionMap(std::vector<int> collision_tile_map, int conveyor_belt_direction)
: collision_tile_map_(std::move(collision_tile_map)),
extended_tile_map_(EW * EH, 0),
conveyor_belt_direction_(conveyor_belt_direction),
tile_collider_(collision_tile_map_) {}
tile_collider_(extended_tile_map_, EW, EH, CollisionBorder::PX) {
buildExtendedCenter();
}
// Copia los tiles de la room actual al centro del mapa extendido
void CollisionMap::buildExtendedCenter() {
std::ranges::fill(extended_tile_map_, 0);
for (int row = 0; row < MH; ++row) {
for (int col = 0; col < MW; ++col) {
extended_tile_map_[((row + B) * EW) + (col + B)] =
collision_tile_map_[(row * MW) + col];
}
}
}
// Copia una región rectangular de src (MW×MH) al mapa extendido
void CollisionMap::copyRegion(const std::vector<int>& src,
int src_col, int src_row,
int dst_col, int dst_row,
int cols, int rows) {
for (int r = 0; r < rows; ++r) {
for (int c = 0; c < cols; ++c) {
extended_tile_map_[((dst_row + r) * EW) + (dst_col + c)] =
src[((src_row + r) * MW) + (src_col + c)];
}
}
}
// Rellena los bordes del mapa extendido con tiles de las habitaciones adyacentes
void CollisionMap::updateBorders(const AdjacentData& adj) {
// Reconstruir: limpiar bordes y copiar centro
buildExtendedCenter();
// Cardinales
// TOP: últimas B filas de la room de arriba → filas 0..B-1 del extendido
if (adj.top != nullptr) {
copyRegion(*adj.top, 0, MH - B, B, 0, MW, B);
}
// BOTTOM: primeras B filas de la room de abajo → filas B+MH..B+MH+B-1
if (adj.bottom != nullptr) {
copyRegion(*adj.bottom, 0, 0, B, B + MH, MW, B);
}
// LEFT: últimas B columnas de la room izquierda → cols 0..B-1
if (adj.left != nullptr) {
copyRegion(*adj.left, MW - B, 0, 0, B, B, MH);
}
// RIGHT: primeras B columnas de la room derecha → cols B+MW..B+MW+B-1
if (adj.right != nullptr) {
copyRegion(*adj.right, 0, 0, B + MW, B, B, MH);
}
// Diagonales (esquinas B×B)
// TOP-LEFT: esquina inferior-derecha de la room diagonal
if (adj.top_left != nullptr) {
copyRegion(*adj.top_left, MW - B, MH - B, 0, 0, B, B);
}
// TOP-RIGHT: esquina inferior-izquierda de la room diagonal
if (adj.top_right != nullptr) {
copyRegion(*adj.top_right, 0, MH - B, B + MW, 0, B, B);
}
// BOTTOM-LEFT: esquina superior-derecha de la room diagonal
if (adj.bottom_left != nullptr) {
copyRegion(*adj.bottom_left, MW - B, 0, 0, B + MH, B, B);
}
// BOTTOM-RIGHT: esquina superior-izquierda de la room diagonal
if (adj.bottom_right != nullptr) {
copyRegion(*adj.bottom_right, 0, 0, B + MW, B + MH, B, B);
}
}
#ifdef _DEBUG
void CollisionMap::setCollisionTile(int index, int value) {
if (index >= 0 && index < static_cast<int>(collision_tile_map_.size())) {
collision_tile_map_[index] = value;
// Actualizar también el tile correspondiente en el mapa extendido
int row = index / MW;
int col = index % MW;
extended_tile_map_[((row + B) * EW) + (col + B)] = value;
}
}
#endif

View File

@@ -3,15 +3,31 @@
#include <vector>
#include "game/gameplay/tile_collider.hpp"
#include "utils/defines.hpp"
/**
* @brief Mapa de colisiones de una habitación
*
* Contiene el collision_tile_map (grid de tipos de tile) y el TileCollider
* que proporciona queries de colisión directas contra el grid.
* Contiene el collision_tile_map original (32×21) y un tilemap extendido (38×27)
* que incluye tiles de borde de las habitaciones adyacentes.
* El TileCollider opera sobre el mapa extendido, permitiendo colisiones cross-room
* sin lógica especial en el Player.
*/
class CollisionMap {
public:
// Datos de colisión de las habitaciones adyacentes (punteros a sus collision_tile_map).
// nullptr = sin habitación en esa dirección (borde queda como EMPTY).
struct AdjacentData {
const std::vector<int>* top{nullptr};
const std::vector<int>* bottom{nullptr};
const std::vector<int>* left{nullptr};
const std::vector<int>* right{nullptr};
const std::vector<int>* top_left{nullptr};
const std::vector<int>* top_right{nullptr};
const std::vector<int>* bottom_left{nullptr};
const std::vector<int>* bottom_right{nullptr};
};
CollisionMap(std::vector<int> collision_tile_map, int conveyor_belt_direction);
~CollisionMap() = default;
@@ -20,21 +36,36 @@ class CollisionMap {
CollisionMap(CollisionMap&&) = delete;
auto operator=(CollisionMap&&) -> CollisionMap& = delete;
// Rellena los bordes del mapa extendido con tiles de las habitaciones adyacentes.
void updateBorders(const AdjacentData& adjacent);
[[nodiscard]] auto getTileCollider() const -> const TileCollider& { return tile_collider_; }
[[nodiscard]] auto getConveyorBeltDirection() const -> int { return conveyor_belt_direction_; }
[[nodiscard]] auto getCollisionTileMap() const -> const std::vector<int>& { return collision_tile_map_; }
#ifdef _DEBUG
void setCollisionTile(int index, int value) {
if (index >= 0 && index < static_cast<int>(collision_tile_map_.size())) {
collision_tile_map_[index] = value;
}
}
void setCollisionTile(int index, int value);
void setConveyorBeltDirection(int direction) { conveyor_belt_direction_ = direction; }
#endif
private:
std::vector<int> collision_tile_map_;
static constexpr int B = CollisionBorder::TILES; // Tiles de borde
static constexpr int MW = Map::WIDTH; // Ancho original (32)
static constexpr int MH = Map::HEIGHT; // Alto original (21)
static constexpr int EW = ExtendedMap::WIDTH; // Ancho extendido (38)
static constexpr int EH = ExtendedMap::HEIGHT; // Alto extendido (27)
std::vector<int> collision_tile_map_; // Original (32×21)
std::vector<int> extended_tile_map_; // Extendido (38×27) — referenciado por TileCollider
int conveyor_belt_direction_;
TileCollider tile_collider_;
TileCollider tile_collider_; // Debe ir después de extended_tile_map_ (usa referencia)
// Copia el centro (room actual) al mapa extendido. Los bordes quedan como EMPTY (0).
void buildExtendedCenter();
// Copia una región rectangular de un tilemap fuente (MW×MH) al mapa extendido.
void copyRegion(const std::vector<int>& src,
int src_col, int src_row,
int dst_col, int dst_row,
int cols, int rows);
};

View File

@@ -215,6 +215,14 @@ auto Room::getTileCollider() const -> const TileCollider& {
return collision_map_->getTileCollider();
}
auto Room::getCollisionTileMap() const -> const std::vector<int>& {
return collision_map_->getCollisionTileMap();
}
void Room::updateCollisionBorders(const CollisionMap::AdjacentData& adjacent) {
collision_map_->updateBorders(adjacent);
}
// Devuelve la cadena del fichero de la habitación contigua segun el borde
auto Room::getRoom(Border border) -> std::string { // NOLINT(readability-convert-member-functions-to-static)
switch (border) {

View File

@@ -6,17 +6,17 @@
#include <string> // Para string
#include <vector> // Para vector
#include "game/defaults.hpp" // Para Defaults::Game::Room
#include "game/entities/enemy.hpp" // Para EnemyData
#include "game/entities/item.hpp" // Para ItemData
#include "game/entities/moving_platform.hpp" // Para MovingPlatform::Data
#include "game/gameplay/scoreboard.hpp" // Para Scoreboard::Data
#include "utils/defines.hpp" // Para Tile::SIZE, Map::WIDTH, Map::HEIGHT
#include "game/defaults.hpp" // Para Defaults::Game::Room
#include "game/entities/enemy.hpp" // Para EnemyData
#include "game/entities/item.hpp" // Para ItemData
#include "game/entities/moving_platform.hpp" // Para MovingPlatform::Data
#include "game/gameplay/collision_map.hpp" // Para CollisionMap::AdjacentData
#include "game/gameplay/scoreboard.hpp" // Para Scoreboard::Data
#include "utils/defines.hpp" // Para Tile::SIZE, Map::WIDTH, Map::HEIGHT
class Surface;
class EnemyManager;
class ItemManager;
class PlatformManager;
class CollisionMap;
class TileCollider;
class TilemapRenderer;
@@ -84,6 +84,8 @@ class Room {
void setPaused(bool value);
[[nodiscard]] auto getConveyorBeltDirection() const -> int { return conveyor_belt_direction_; }
[[nodiscard]] auto getTileCollider() const -> const TileCollider&;
[[nodiscard]] auto getCollisionTileMap() const -> const std::vector<int>&;
void updateCollisionBorders(const CollisionMap::AdjacentData& adjacent);
// Método de carga de archivos YAML (delegado a RoomLoader)
static auto loadYAML(const std::string& file_path, bool verbose = false) -> Data;

View File

@@ -1,20 +1,19 @@
#include "game/gameplay/tile_collider.hpp"
#include <algorithm> // Para std::min, std::max
#include <cmath> // Para std::ceil
#include <algorithm> // Para std::min, std::max, std::clamp
#include "utils/defines.hpp"
TileCollider::TileCollider(const std::vector<int>& collision_tile_map)
: tile_map_(collision_tile_map) {}
TileCollider::TileCollider(const std::vector<int>& extended_tile_map, int width, int height, int border_px)
: width_(width), height_(height), border_px_(border_px), tile_map_(extended_tile_map) {}
// --- Queries básicas ---
auto TileCollider::getTileAt(int tile_x, int tile_y) const -> Tile {
if (tile_x < 0 || tile_x >= MW || tile_y < 0 || tile_y >= MH) {
if (tile_x < 0 || tile_x >= width_ || tile_y < 0 || tile_y >= height_) {
return Tile::EMPTY;
}
int value = tile_map_[(tile_y * MW) + tile_x];
int value = tile_map_[(tile_y * width_) + tile_x];
if (value >= 0 && value <= 5) {
return static_cast<Tile>(value);
}
@@ -30,8 +29,8 @@ auto TileCollider::isSolid(int tile_x, int tile_y) const -> bool {
// SLOPE_L (\): alto a la izquierda, bajo a la derecha. surface = bottom - (7 - x_in_tile)
// SLOPE_R (/): alto a la derecha, bajo a la izquierda. surface = bottom - x_in_tile
auto TileCollider::getSlopeY(int tile_x, int tile_y, float px) const -> float {
auto tile_bottom = static_cast<float>(((tile_y + 1) * TS) - 1);
float x_in_tile = px - static_cast<float>(tile_x * TS);
float tile_bottom = toPixel(tile_y + 1) - 1;
float x_in_tile = px - toPixel(tile_x);
x_in_tile = std::clamp(x_in_tile, 0.0F, static_cast<float>(TS - 1));
auto tile = getTileAt(tile_x, tile_y);
@@ -54,7 +53,7 @@ auto TileCollider::checkWallLeft(float x, float y, float w, float h) const -> fl
for (int row = top_row; row <= bot_row; ++row) {
if (isSolid(col, row)) {
return static_cast<float>((col + 1) * TS);
return toPixel(col + 1);
}
}
return Collision::NONE;
@@ -67,7 +66,7 @@ auto TileCollider::checkWallRight(float x, float y, float w, float h) const -> f
for (int row = top_row; row <= bot_row; ++row) {
if (isSolid(col, row)) {
return static_cast<float>(col * TS);
return toPixel(col);
}
}
return Collision::NONE;
@@ -84,7 +83,7 @@ auto TileCollider::checkCeiling(float x, float y, float w) const -> float {
auto tile = getTileAt(col, top_row);
// Slopes actúan como techo (no se atraviesan desde abajo)
if (tile == Tile::WALL || tile == Tile::SLOPE_L || tile == Tile::SLOPE_R) {
return static_cast<float>((top_row + 1) * TS);
return toPixel(top_row + 1);
}
}
return Collision::NONE;
@@ -93,7 +92,7 @@ auto TileCollider::checkCeiling(float x, float y, float w) const -> float {
// --- Colisión con suelo (landing) ---
// Busca suelo entre foot_y_current y foot_y_new (rango de caída del frame).
// WALL: siempre bloquea.
// WALL: bloquea si los pies estaban por encima (como PASSABLE).
// PASSABLE: solo si los pies estaban por encima del borde superior del tile.
// SLOPE: siempre bloquea (las slopes son sólidas, como muros en diagonal).
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
@@ -111,9 +110,12 @@ auto TileCollider::checkFloor(float x, float foot_y_current, float w, float foot
float floor_y = Collision::NONE;
if (tile == Tile::WALL) {
floor_y = static_cast<float>(row * TS);
float tile_top = toPixel(row);
if (foot_y_current <= tile_top) {
floor_y = tile_top;
}
} else if (tile == Tile::PASSABLE) {
auto tile_top = static_cast<float>(row * TS);
float tile_top = toPixel(row);
// Solo cuenta como suelo si los pies estaban por encima antes del movimiento
if (foot_y_current <= tile_top) {
floor_y = tile_top;

View File

@@ -30,7 +30,9 @@ class TileCollider {
float surface_y{0};
};
explicit TileCollider(const std::vector<int>& collision_tile_map);
// Constructor: recibe el tilemap extendido y sus dimensiones.
// border_px es el offset en píxeles para traducir coordenadas de room-space a extended-map.
TileCollider(const std::vector<int>& extended_tile_map, int width, int height, int border_px);
// Queries básicas
[[nodiscard]] auto getTileAt(int tile_x, int tile_y) const -> Tile;
@@ -53,10 +55,19 @@ class TileCollider {
private:
static constexpr int TS = ::Tile::SIZE;
static constexpr int MW = ::Map::WIDTH;
static constexpr int MH = ::Map::HEIGHT;
int width_; // Ancho total del tilemap extendido (en tiles)
int height_; // Alto total del tilemap extendido (en tiles)
int border_px_; // Offset en píxeles (CollisionBorder::PX)
const std::vector<int>& tile_map_;
[[nodiscard]] static auto toTile(int px) -> int { return px / TS; }
// Convierte píxeles en room-space a índice de tile en el mapa extendido.
// Nota: asume que px >= -border_px_ (el jugador no puede estar más allá del borde).
[[nodiscard]] auto toTile(int px) const -> int { return (px + border_px_) / TS; }
// Convierte índice de tile del mapa extendido a píxeles en room-space.
[[nodiscard]] auto toPixel(int tile) const -> float {
return static_cast<float>((tile * TS) - border_px_);
}
};