proves
This commit is contained in:
@@ -66,7 +66,8 @@ void Player::update(float delta_time) {
|
||||
checkFalling();
|
||||
|
||||
// 6. Kill tiles
|
||||
if (room_->getTileCollider().touchesKillTile(x_, y_, WIDTH, HEIGHT)) {
|
||||
auto [ktc, kox, koy] = getCollisionContext();
|
||||
if (ktc.touchesKillTile(x_ + kox, y_ + koy, WIDTH, HEIGHT)) {
|
||||
markAsDead();
|
||||
}
|
||||
|
||||
@@ -190,11 +191,11 @@ void Player::handleJumpAndDrop() {
|
||||
|
||||
// Drop-through: plataforma passable
|
||||
if (wanna_down_ && state_ == State::ON_GROUND) {
|
||||
const auto& tc = room_->getTileCollider();
|
||||
float foot_y = y_ + HEIGHT;
|
||||
auto [tc, ox, oy] = getCollisionContext();
|
||||
float foot_y = (y_ + oy) + HEIGHT;
|
||||
int foot_row = static_cast<int>(foot_y) / Tile::SIZE;
|
||||
int left_col = static_cast<int>(x_) / Tile::SIZE;
|
||||
int right_col = static_cast<int>(x_ + WIDTH - 1) / Tile::SIZE;
|
||||
int left_col = static_cast<int>(x_ + ox) / Tile::SIZE;
|
||||
int right_col = static_cast<int>((x_ + ox) + WIDTH - 1) / Tile::SIZE;
|
||||
|
||||
for (int col = left_col; col <= right_col; ++col) {
|
||||
if (tc.getTileAt(col, foot_row) == TileCollider::Tile::PASSABLE) {
|
||||
@@ -225,19 +226,19 @@ void Player::moveHorizontal(float delta_time) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& tc = room_->getTileCollider();
|
||||
auto [tc, ox, oy] = getCollisionContext();
|
||||
float new_x = x_ + (vx_ * delta_time);
|
||||
|
||||
// Colisión con paredes
|
||||
if (vx_ < 0.0F) {
|
||||
float wall = tc.checkWallLeft(new_x, y_, WIDTH, HEIGHT);
|
||||
float wall = tc.checkWallLeft(new_x + ox, y_ + oy, WIDTH, HEIGHT);
|
||||
if (wall != Collision::NONE) {
|
||||
new_x = wall;
|
||||
new_x = wall - ox;
|
||||
}
|
||||
} else {
|
||||
float wall = tc.checkWallRight(new_x, y_, WIDTH, HEIGHT);
|
||||
float wall = tc.checkWallRight(new_x + ox, y_ + oy, WIDTH, HEIGHT);
|
||||
if (wall != Collision::NONE) {
|
||||
new_x = wall - WIDTH;
|
||||
new_x = wall - WIDTH - ox;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,18 +260,18 @@ void Player::moveHorizontal(float delta_time) {
|
||||
// actual y la inferior (las slopes en escalera bajan una fila por tile).
|
||||
// Si no encuentra slope, llama a exitSlope().
|
||||
void Player::followSlope() {
|
||||
const auto& tc = room_->getTileCollider();
|
||||
auto [tc, ox, oy] = getCollisionContext();
|
||||
|
||||
// SLOPE_L (\): pie izquierdo. SLOPE_R (/): pie derecho.
|
||||
float foot_x = (slope_type_ == TileCollider::Tile::SLOPE_L) ? x_ : x_ + WIDTH - 1;
|
||||
float foot_x = (slope_type_ == TileCollider::Tile::SLOPE_L) ? (x_ + ox) : (x_ + ox) + WIDTH - 1;
|
||||
|
||||
// Calcular Y en la slope actual
|
||||
float surface_y = tc.getSlopeY(slope_tile_x_, slope_tile_y_, foot_x);
|
||||
y_ = surface_y - HEIGHT;
|
||||
y_ = surface_y - HEIGHT - oy;
|
||||
|
||||
// Comprobar si hemos salido del tile actual
|
||||
int foot_tile_x = static_cast<int>(foot_x) / Tile::SIZE;
|
||||
int foot_tile_y = static_cast<int>(y_ + HEIGHT) / Tile::SIZE;
|
||||
int foot_tile_y = static_cast<int>((y_ + oy) + HEIGHT) / Tile::SIZE;
|
||||
|
||||
if (foot_tile_x != slope_tile_x_ || foot_tile_y != slope_tile_y_) {
|
||||
// Buscar slope en el tile calculado y en el de abajo (la escalera de slopes
|
||||
@@ -282,7 +283,7 @@ void Player::followSlope() {
|
||||
slope_tile_y_ = row;
|
||||
slope_type_ = new_tile;
|
||||
surface_y = tc.getSlopeY(slope_tile_x_, slope_tile_y_, foot_x);
|
||||
y_ = surface_y - HEIGHT;
|
||||
y_ = surface_y - HEIGHT - oy;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -295,16 +296,16 @@ void Player::followSlope() {
|
||||
// entre filas cuando se sale por el extremo inferior de la slope).
|
||||
// Si hay suelo, snapea al borde del tile. Si no, empieza a caer.
|
||||
void Player::exitSlope() {
|
||||
const auto& tc = room_->getTileCollider();
|
||||
float foot_y = y_ + HEIGHT;
|
||||
auto [tc, ox, oy] = getCollisionContext();
|
||||
float foot_y = (y_ + oy) + HEIGHT;
|
||||
|
||||
// Comprobar suelo en la fila actual y la siguiente (al salir por abajo de una slope,
|
||||
// los pies pueden estar en el último pixel de la fila, justo antes del suelo)
|
||||
for (int check = 0; check <= 1; ++check) {
|
||||
float check_y = foot_y + check;
|
||||
if (tc.hasGroundBelow(x_, check_y, WIDTH)) {
|
||||
if (tc.hasGroundBelow(x_ + ox, check_y, WIDTH)) {
|
||||
int row = static_cast<int>(check_y) / Tile::SIZE;
|
||||
y_ = static_cast<float>(row * Tile::SIZE) - HEIGHT;
|
||||
y_ = static_cast<float>(row * Tile::SIZE) - HEIGHT - oy;
|
||||
transitionToState(State::ON_GROUND);
|
||||
return;
|
||||
}
|
||||
@@ -318,12 +319,12 @@ void Player::exitSlope() {
|
||||
// Las slopes en escalera están una fila arriba del suelo, así que checkSlopeBelow
|
||||
// también mira la fila superior.
|
||||
void Player::detectSlopeEntry() {
|
||||
const auto& tc = room_->getTileCollider();
|
||||
float foot_y = y_ + HEIGHT;
|
||||
auto [tc, ox, oy] = getCollisionContext();
|
||||
float foot_y = (y_ + oy) + HEIGHT;
|
||||
|
||||
auto slope = tc.checkSlopeBelow(x_, foot_y, WIDTH);
|
||||
auto slope = tc.checkSlopeBelow(x_ + ox, foot_y, WIDTH);
|
||||
if (slope.on_slope) {
|
||||
y_ = slope.surface_y - HEIGHT;
|
||||
y_ = slope.surface_y - HEIGHT - oy;
|
||||
slope_tile_x_ = slope.tile_x;
|
||||
slope_tile_y_ = slope.tile_y;
|
||||
slope_type_ = slope.type;
|
||||
@@ -338,27 +339,27 @@ void Player::detectSlopeEntry() {
|
||||
void Player::moveVertical(float delta_time) {
|
||||
if (state_ != State::ON_AIR) { return; }
|
||||
|
||||
const auto& tc = room_->getTileCollider();
|
||||
auto [tc, ox, oy] = getCollisionContext();
|
||||
float displacement = vy_ * delta_time;
|
||||
|
||||
if (vy_ < 0.0F) {
|
||||
// Subiendo: comprobar techo
|
||||
float new_y = y_ + displacement;
|
||||
float ceiling = tc.checkCeiling(x_, new_y, WIDTH);
|
||||
float ceiling = tc.checkCeiling(x_ + ox, new_y + oy, WIDTH);
|
||||
if (ceiling != Collision::NONE) {
|
||||
y_ = ceiling;
|
||||
y_ = ceiling - oy;
|
||||
vy_ = 0.0F;
|
||||
} else {
|
||||
y_ = new_y;
|
||||
}
|
||||
} else if (vy_ > 0.0F) {
|
||||
// Bajando: comprobar suelo
|
||||
float foot_y = y_ + HEIGHT;
|
||||
float foot_y = (y_ + oy) + HEIGHT;
|
||||
float new_foot_y = foot_y + displacement;
|
||||
auto hit = tc.checkFloor(x_, foot_y, WIDTH, new_foot_y);
|
||||
auto hit = tc.checkFloor(x_ + ox, foot_y, WIDTH, new_foot_y);
|
||||
|
||||
if (hit.y != Collision::NONE) {
|
||||
y_ = hit.y - HEIGHT;
|
||||
y_ = hit.y - HEIGHT - oy;
|
||||
if (hit.type == TileCollider::Tile::SLOPE_L || hit.type == TileCollider::Tile::SLOPE_R) {
|
||||
slope_tile_x_ = hit.tile_x;
|
||||
slope_tile_y_ = hit.tile_y;
|
||||
@@ -383,7 +384,7 @@ void Player::moveVertical(float delta_time) {
|
||||
void Player::checkFalling() {
|
||||
if (state_ == State::ON_AIR) { return; }
|
||||
|
||||
const auto& tc = room_->getTileCollider();
|
||||
auto [tc, ox, oy] = getCollisionContext();
|
||||
|
||||
if (state_ == State::ON_SLOPE) {
|
||||
// Verificar que el tile de slope sigue existiendo
|
||||
@@ -396,8 +397,8 @@ void Player::checkFalling() {
|
||||
}
|
||||
|
||||
// ON_GROUND: comprobar si sigue habiendo suelo
|
||||
float foot_y = y_ + HEIGHT;
|
||||
if (!tc.hasGroundBelow(x_, foot_y, WIDTH)) {
|
||||
float foot_y = (y_ + oy) + HEIGHT;
|
||||
if (!tc.hasGroundBelow(x_ + ox, foot_y, WIDTH)) {
|
||||
vy_ = 0.0F;
|
||||
transitionToState(State::ON_AIR);
|
||||
}
|
||||
@@ -445,8 +446,10 @@ auto Player::handleBorders() const -> Room::Border {
|
||||
return Room::Border::NONE;
|
||||
}
|
||||
|
||||
void Player::switchBorders() {
|
||||
switch (border_) {
|
||||
// Reposiciona al jugador al hacer commit definitivo a la room adyacente.
|
||||
// Se llama cuando el rectángulo completo del jugador ha salido de bounds.
|
||||
void Player::commitToRoom(Room::Border border) {
|
||||
switch (border) {
|
||||
case Room::Border::TOP:
|
||||
y_ += PlayArea::HEIGHT;
|
||||
last_grounded_position_ = static_cast<int>(y_);
|
||||
@@ -468,6 +471,69 @@ void Player::switchBorders() {
|
||||
syncSpriteAndCollider();
|
||||
}
|
||||
|
||||
void Player::setAdjacentRoom(std::shared_ptr<Room> room, Room::Border direction) {
|
||||
adjacent_room_ = std::move(room);
|
||||
adjacent_direction_ = direction;
|
||||
}
|
||||
|
||||
void Player::clearAdjacentRoom() {
|
||||
adjacent_room_.reset();
|
||||
adjacent_direction_ = Room::Border::NONE;
|
||||
}
|
||||
|
||||
auto Player::isFullyOutOfBounds() const -> bool {
|
||||
switch (adjacent_direction_) {
|
||||
case Room::Border::TOP:
|
||||
return (y_ + HEIGHT) <= PlayArea::TOP;
|
||||
case Room::Border::BOTTOM:
|
||||
return y_ >= PlayArea::BOTTOM;
|
||||
case Room::Border::LEFT:
|
||||
return (x_ + WIDTH) <= PlayArea::LEFT;
|
||||
case Room::Border::RIGHT:
|
||||
return x_ >= PlayArea::RIGHT;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Devuelve el TileCollider correcto y los offsets de traducción de coordenadas
|
||||
// según en qué room está el centro del jugador.
|
||||
auto Player::getCollisionContext() const -> CollisionContext {
|
||||
if (!adjacent_room_) {
|
||||
return {room_->getTileCollider(), 0.0F, 0.0F};
|
||||
}
|
||||
|
||||
const float CENTER_X = x_ + (WIDTH / 2.0F);
|
||||
const float CENTER_Y = y_ + (HEIGHT / 2.0F);
|
||||
|
||||
switch (adjacent_direction_) {
|
||||
case Room::Border::TOP:
|
||||
if (CENTER_Y < PlayArea::TOP) {
|
||||
return {adjacent_room_->getTileCollider(), 0.0F, static_cast<float>(PlayArea::HEIGHT)};
|
||||
}
|
||||
break;
|
||||
case Room::Border::BOTTOM:
|
||||
if (CENTER_Y > PlayArea::BOTTOM) {
|
||||
return {adjacent_room_->getTileCollider(), 0.0F, -static_cast<float>(PlayArea::HEIGHT)};
|
||||
}
|
||||
break;
|
||||
case Room::Border::LEFT:
|
||||
if (CENTER_X < PlayArea::LEFT) {
|
||||
return {adjacent_room_->getTileCollider(), static_cast<float>(PlayArea::WIDTH), 0.0F};
|
||||
}
|
||||
break;
|
||||
case Room::Border::RIGHT:
|
||||
if (CENTER_X > PlayArea::RIGHT) {
|
||||
return {adjacent_room_->getTileCollider(), -static_cast<float>(PlayArea::WIDTH), 0.0F};
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return {room_->getTileCollider(), 0.0F, 0.0F};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Geometría y renderizado
|
||||
// ============================================================================
|
||||
|
||||
Reference in New Issue
Block a user