treballant en el extendedMap per a les colisións fora de pantalla
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user