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

@@ -71,6 +71,7 @@ Game::Game(Mode mode)
initPlayer(spawn_data_, room_);
game_backbuffer_surface_ = std::make_shared<Surface>(Options::game.width, Options::game.height);
changeRoom(current_room_);
buildCollisionBorders();
if (Console::get() != nullptr) {
#ifdef _DEBUG
@@ -131,6 +132,7 @@ Game::Game(Mode mode)
// Recargar la habitación desde disco (con los cambios del editor)
Resource::Cache::get()->reloadRoom(current_room_);
changeRoom(current_room_);
buildCollisionBorders();
player_->setRoom(room_);
};
GameControl::revert_editor = []() -> std::string {
@@ -310,39 +312,6 @@ void Game::updatePlaying(float delta_time) {
player_->clearPlatformFlag();
checkPlayerAndPlatforms();
// Cross-room collision: precargar rooms adyacentes para colisiones
{
player_->clearBorderRooms();
auto loadBorder = [&](Room::Border b) -> std::shared_ptr<Room> {
auto name = room_->getRoom(b);
return (name != "0") ? getOrCreateRoom(name) : nullptr;
};
auto top = loadBorder(Room::Border::TOP);
auto right = loadBorder(Room::Border::RIGHT);
auto bottom = loadBorder(Room::Border::BOTTOM);
auto left = loadBorder(Room::Border::LEFT);
if (top) { player_->setBorderRoom(0, top); }
if (right) { player_->setBorderRoom(1, right); }
if (bottom) { player_->setBorderRoom(2, bottom); }
if (left) { player_->setBorderRoom(3, left); }
// Diagonales
auto loadDiag = [&](const std::shared_ptr<Room>& a, Room::Border ab,
const std::shared_ptr<Room>& b, Room::Border ba) -> std::shared_ptr<Room> {
std::string name;
if (a) { name = a->getRoom(ab); }
if ((name.empty() || name == "0") && b) { name = b->getRoom(ba); }
return (!name.empty() && name != "0") ? getOrCreateRoom(name) : nullptr;
};
auto tr = loadDiag(top, Room::Border::RIGHT, right, Room::Border::TOP);
auto br = loadDiag(bottom, Room::Border::RIGHT, right, Room::Border::BOTTOM);
auto bl = loadDiag(bottom, Room::Border::LEFT, left, Room::Border::BOTTOM);
auto tl = loadDiag(top, Room::Border::LEFT, left, Room::Border::TOP);
if (tr) { player_->setBorderRoom(4, tr); }
if (br) { player_->setBorderRoom(5, br); }
if (bl) { player_->setBorderRoom(6, bl); }
if (tl) { player_->setBorderRoom(7, tl); }
}
#ifdef _DEBUG
// Maneja el arrastre del jugador con el ratón (debug)
handleDebugMouseDrag(delta_time);
@@ -452,6 +421,7 @@ void Game::transitionToState(State new_state) {
// Respawn room y player
room_ = getOrCreateRoom(current_room_);
initPlayer(spawn_data_, room_);
buildCollisionBorders();
// Pausar ambos
room_->setPaused(true);
player_->setPaused(true);
@@ -825,6 +795,47 @@ auto Game::getOrCreateRoom(const std::string& room_path) -> std::shared_ptr<Room
return room;
}
// Construye el tilemap extendido de la room actual con los bordes de las adyacentes
void Game::buildCollisionBorders() {
// Helper: obtiene el collision tilemap de una room adyacente (nullptr si no existe)
auto getAdjacentCollision = [&](Room::Border b) -> const std::vector<int>* {
auto name = room_->getRoom(b);
if (name == "0") { return nullptr; }
return &getOrCreateRoom(name)->getCollisionTileMap();
};
// Helper: obtiene el collision tilemap de una room diagonal (A→B o C→D)
auto getDiagCollision = [&](Room::Border first, Room::Border second) -> const std::vector<int>* {
// Camino 1: room en dirección 'first', luego su adyacente en dirección 'second'
auto name1 = room_->getRoom(first);
if (name1 != "0") {
auto r = getOrCreateRoom(name1);
auto name2 = r->getRoom(second);
if (name2 != "0") { return &getOrCreateRoom(name2)->getCollisionTileMap(); }
}
// Camino 2: room en dirección 'second', luego su adyacente en dirección 'first'
auto name3 = room_->getRoom(second);
if (name3 != "0") {
auto r = getOrCreateRoom(name3);
auto name4 = r->getRoom(first);
if (name4 != "0") { return &getOrCreateRoom(name4)->getCollisionTileMap(); }
}
return nullptr;
};
CollisionMap::AdjacentData adj;
adj.top = getAdjacentCollision(Room::Border::TOP);
adj.bottom = getAdjacentCollision(Room::Border::BOTTOM);
adj.left = getAdjacentCollision(Room::Border::LEFT);
adj.right = getAdjacentCollision(Room::Border::RIGHT);
adj.top_left = getDiagCollision(Room::Border::TOP, Room::Border::LEFT);
adj.top_right = getDiagCollision(Room::Border::TOP, Room::Border::RIGHT);
adj.bottom_left = getDiagCollision(Room::Border::BOTTOM, Room::Border::LEFT);
adj.bottom_right = getDiagCollision(Room::Border::BOTTOM, Room::Border::RIGHT);
room_->updateCollisionBorders(adj);
}
// Actualiza los enemigos de las habitaciones adyacentes a la actual
void Game::updateAdjacentRooms(float delta_time) {
for (auto border : {Room::Border::TOP, Room::Border::RIGHT, Room::Border::BOTTOM, Room::Border::LEFT}) {
@@ -869,26 +880,8 @@ void Game::checkPlayerIsOnBorder() {
// Crear nueva habitación y reposicionar jugador
if (changeRoom(ROOM_NAME)) {
// Pasar la room saliente como adyacente al player (para colisiones offscreen)
// La dirección es la opuesta: si salimos por TOP, la vieja queda en BOTTOM
Room::Border opposite = Room::Border::NONE;
switch (BORDER) {
case Room::Border::TOP:
opposite = Room::Border::BOTTOM;
break;
case Room::Border::BOTTOM:
opposite = Room::Border::TOP;
break;
case Room::Border::LEFT:
opposite = Room::Border::RIGHT;
break;
case Room::Border::RIGHT:
opposite = Room::Border::LEFT;
break;
default:
break;
}
player_->setAdjacentRoom(transition_old_room_, opposite);
// Construir el tilemap extendido de la nueva room con los bordes adyacentes
buildCollisionBorders();
player_->switchBorders();
spawn_data_ = player_->getSpawnParams();
@@ -908,10 +901,6 @@ void Game::checkPlayerIsOnBorder() {
killPlayer();
}
}
} else {
// Jugador dentro de los límites: liberar la room adyacente que se mantuvo
// tras endTransition() para evitar frames sin datos de colisión offscreen.
player_->clearAdjacentRoom();
}
}
@@ -925,9 +914,6 @@ void Game::endTransition() {
transition_timer_ = 0.0F;
transition_old_room_.reset();
transition_direction_ = Room::Border::NONE;
// No limpiar adjacent room aquí: el jugador puede estar más allá del borde
// y necesita los datos de colisión de la room adyacente en los frames siguientes.
// Se limpia en checkPlayerIsOnBorder() cuando el jugador está dentro de los límites.
Screen::get()->setRenderOffset(0, 0);
}