barrallantse en la colisió en les habitacions dels costats
fix: surface no clipejava be la copia de surfaces a surfaces que eixien per la dreta amb el flip activat
This commit is contained in:
@@ -239,7 +239,7 @@ void Player::moveHorizontal(float delta_time) {
|
||||
auto [tc, ox, oy] = getCollisionContext();
|
||||
float new_x = x_ + (vx_ * delta_time);
|
||||
|
||||
// Colisión con paredes
|
||||
// Colisión con paredes (room actual)
|
||||
if (vx_ < 0.0F) {
|
||||
float wall = tc.checkWallLeft(new_x + ox, y_ + oy, WIDTH, HEIGHT);
|
||||
if (wall != Collision::NONE) {
|
||||
@@ -252,6 +252,10 @@ void Player::moveHorizontal(float delta_time) {
|
||||
}
|
||||
}
|
||||
|
||||
// Cross-room: comprobar muros en rooms adyacentes
|
||||
auto cross = getCrossRoomChecks();
|
||||
checkCrossRoomWallH(new_x, cross);
|
||||
|
||||
x_ = new_x;
|
||||
|
||||
// Si estamos en una slope, ajustar Y para seguirla
|
||||
@@ -352,6 +356,8 @@ void Player::moveVertical(float delta_time) {
|
||||
auto [tc, ox, oy] = getCollisionContext();
|
||||
float displacement = vy_ * delta_time;
|
||||
|
||||
float old_y = y_;
|
||||
|
||||
if (vy_ < 0.0F) {
|
||||
// Subiendo: comprobar techo
|
||||
float new_y = y_ + displacement;
|
||||
@@ -385,6 +391,10 @@ void Player::moveVertical(float delta_time) {
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Cross-room: comprobar suelo/techo en rooms adyacentes
|
||||
auto cross = getCrossRoomChecks();
|
||||
checkCrossRoomFloor(old_y, cross);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -423,6 +433,12 @@ void Player::checkFalling() {
|
||||
transitionToState(State::ON_SLOPE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cross-room: comprobar suelo en rooms adyacentes antes de declarar caída
|
||||
if (hasCrossRoomGround(getCrossRoomChecks())) {
|
||||
return;
|
||||
}
|
||||
|
||||
vy_ = 0.0F;
|
||||
transitionToState(State::ON_AIR);
|
||||
}
|
||||
@@ -553,6 +569,109 @@ void Player::syncSpriteAndCollider() {
|
||||
collider_box_ = getRect();
|
||||
}
|
||||
|
||||
// Cross-room collision: asigna una room adyacente por índice
|
||||
void Player::setBorderRoom(int index, std::shared_ptr<Room> room) {
|
||||
if (index >= 0 && index < BORDER_ROOM_COUNT) {
|
||||
border_rooms_[index] = std::move(room);
|
||||
}
|
||||
}
|
||||
|
||||
// Cross-room collision: limpia todas las rooms adyacentes
|
||||
void Player::clearBorderRooms() {
|
||||
for (auto& r : border_rooms_) {
|
||||
r.reset();
|
||||
}
|
||||
}
|
||||
|
||||
// Cross-room: construye la lista de rooms adyacentes que solapan con la bbox del jugador
|
||||
auto Player::getCrossRoomChecks() const -> CrossRoomChecks {
|
||||
// Offsets por room: TOP, RIGHT, BOTTOM, LEFT, TR, BR, BL, TL
|
||||
static constexpr float PW = static_cast<float>(PlayArea::WIDTH);
|
||||
static constexpr float PH = static_cast<float>(PlayArea::HEIGHT);
|
||||
static constexpr struct { float ox; float oy; } OFFSETS[BORDER_ROOM_COUNT] = {
|
||||
{0, PH}, {-PW, 0}, {0, -PH}, {PW, 0}, {-PW, PH}, {-PW, -PH}, {PW, -PH}, {PW, PH}
|
||||
};
|
||||
|
||||
bool over_top = y_ < 0.0F;
|
||||
bool over_right = (x_ + WIDTH) > PlayArea::RIGHT;
|
||||
bool over_bottom = (y_ + HEIGHT) > PlayArea::BOTTOM;
|
||||
bool over_left = x_ < 0.0F;
|
||||
bool needed[BORDER_ROOM_COUNT] = {
|
||||
over_top, over_right, over_bottom, over_left,
|
||||
over_top && over_right, over_bottom && over_right,
|
||||
over_bottom && over_left, over_top && over_left
|
||||
};
|
||||
|
||||
CrossRoomChecks result;
|
||||
for (int i = 0; i < BORDER_ROOM_COUNT; ++i) {
|
||||
if (needed[i] && border_rooms_[i]) {
|
||||
result.entries[result.count++] = {&border_rooms_[i]->getTileCollider(), OFFSETS[i].ox, OFFSETS[i].oy};
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Cross-room: comprueba muros horizontales en rooms adyacentes
|
||||
void Player::checkCrossRoomWallH(float& new_x, const CrossRoomChecks& checks) const {
|
||||
for (int i = 0; i < checks.count; ++i) {
|
||||
const auto& [tc, ox, oy] = checks.entries[i];
|
||||
if (vx_ < 0.0F) {
|
||||
float wall = tc->checkWallLeft(new_x + ox, y_ + oy, WIDTH, HEIGHT);
|
||||
if (wall != Collision::NONE) {
|
||||
float corrected = wall - ox;
|
||||
if (corrected > new_x) { new_x = corrected; }
|
||||
}
|
||||
} else if (vx_ > 0.0F) {
|
||||
float wall = tc->checkWallRight(new_x + ox, y_ + oy, WIDTH, HEIGHT);
|
||||
if (wall != Collision::NONE) {
|
||||
float corrected = wall - WIDTH - ox;
|
||||
if (corrected < new_x) { new_x = corrected; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cross-room: comprueba suelo/techo en rooms adyacentes (usa old_y para rango correcto de checkFloor)
|
||||
void Player::checkCrossRoomFloor(float old_y, const CrossRoomChecks& checks) {
|
||||
for (int i = 0; i < checks.count; ++i) {
|
||||
const auto& [tc, ox, oy] = checks.entries[i];
|
||||
if (vy_ < 0.0F) {
|
||||
float ceiling = tc->checkCeiling(x_ + ox, y_ + oy, WIDTH);
|
||||
if (ceiling != Collision::NONE) {
|
||||
float corrected = ceiling - oy;
|
||||
if (corrected > y_) {
|
||||
y_ = corrected;
|
||||
vy_ = 0.0F;
|
||||
}
|
||||
}
|
||||
} else if (vy_ > 0.0F) {
|
||||
float old_foot = old_y + oy + HEIGHT;
|
||||
float new_foot = y_ + oy + HEIGHT;
|
||||
auto hit = tc->checkFloor(x_ + ox, old_foot, WIDTH, new_foot);
|
||||
if (hit.y != Collision::NONE) {
|
||||
float corrected = hit.y - HEIGHT - oy;
|
||||
if (corrected < y_) {
|
||||
y_ = corrected;
|
||||
vy_ = 0.0F;
|
||||
transitionToState(State::ON_GROUND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cross-room: comprueba si hay suelo bajo el jugador en alguna room adyacente
|
||||
auto Player::hasCrossRoomGround(const CrossRoomChecks& checks) const -> bool {
|
||||
for (int i = 0; i < checks.count; ++i) {
|
||||
const auto& [tc, ox, oy] = checks.entries[i];
|
||||
float foot = y_ + oy + HEIGHT;
|
||||
if (tc->hasGroundBelow(x_ + ox, foot, WIDTH)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Aplica el desplazamiento de una plataforma móvil al jugador
|
||||
void Player::applyPlatformDisplacement(float dx, float surface_y) {
|
||||
y_ = surface_y - HEIGHT; // Snap vertical al top de la plataforma
|
||||
|
||||
@@ -76,6 +76,12 @@ class Player {
|
||||
[[nodiscard]] auto getVY() const -> float { return vy_; }
|
||||
void applyPlatformDisplacement(float dx, float surface_y);
|
||||
void clearPlatformFlag() { on_platform_ = false; }
|
||||
|
||||
// Cross-room collision: rooms adyacentes (TOP=0, RIGHT=1, BOTTOM=2, LEFT=3, TR=4, BR=5, BL=6, TL=7)
|
||||
static constexpr int BORDER_ROOM_COUNT = 8;
|
||||
void setBorderRoom(int index, std::shared_ptr<Room> room);
|
||||
void clearBorderRooms();
|
||||
|
||||
void setPaused(bool value) { is_paused_ = value; }
|
||||
void setIgnoreInput(bool value) { ignore_input_ = value; }
|
||||
[[nodiscard]] auto getIgnoreInput() const -> bool { return ignore_input_; }
|
||||
@@ -136,6 +142,9 @@ class Player {
|
||||
Room::Border border_ = Room::Border::TOP;
|
||||
int last_grounded_position_ = 0;
|
||||
|
||||
// --- Cross-room collision ---
|
||||
std::shared_ptr<Room> border_rooms_[BORDER_ROOM_COUNT]{};
|
||||
|
||||
// --- Renderizado y sonido ---
|
||||
JA_Sound_t* jump_sound_ = nullptr;
|
||||
JA_Sound_t* land_sound_ = nullptr;
|
||||
@@ -147,6 +156,21 @@ class Player {
|
||||
void handleJumpAndDrop();
|
||||
void moveHorizontal(float delta_time);
|
||||
void moveVertical(float delta_time);
|
||||
|
||||
// Cross-room collision helpers
|
||||
struct CrossRoomEntry {
|
||||
const TileCollider* tc;
|
||||
float ox;
|
||||
float oy;
|
||||
};
|
||||
struct CrossRoomChecks {
|
||||
CrossRoomEntry entries[BORDER_ROOM_COUNT]{};
|
||||
int count{0};
|
||||
};
|
||||
auto getCrossRoomChecks() const -> CrossRoomChecks;
|
||||
void checkCrossRoomWallH(float& new_x, const CrossRoomChecks& checks) const;
|
||||
void checkCrossRoomFloor(float old_y, const CrossRoomChecks& checks);
|
||||
auto hasCrossRoomGround(const CrossRoomChecks& checks) const -> bool;
|
||||
void followSlope();
|
||||
void exitSlope();
|
||||
void detectSlopeEntry();
|
||||
|
||||
@@ -310,6 +310,39 @@ 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);
|
||||
|
||||
Reference in New Issue
Block a user