afinaments
This commit is contained in:
@@ -289,18 +289,14 @@ categories:
|
|||||||
- keyword: CHEAT
|
- keyword: CHEAT
|
||||||
handler: cmd_cheat
|
handler: cmd_cheat
|
||||||
description: "Game cheats (GAME only)"
|
description: "Game cheats (GAME only)"
|
||||||
usage: "CHEAT [INFINITE LIVES|INVINCIBILITY|OPEN THE JAIL|CLOSE THE JAIL]"
|
usage: "CHEAT [INFINITE LIVES|INVINCIBILITY]"
|
||||||
hidden: true
|
hidden: true
|
||||||
help_hidden: true
|
help_hidden: true
|
||||||
completions:
|
completions:
|
||||||
CHEAT: [INFINITE, INVINCIBILITY, OPEN, CLOSE]
|
CHEAT: [INFINITE, INVINCIBILITY]
|
||||||
CHEAT INFINITE: [LIVES]
|
CHEAT INFINITE: [LIVES]
|
||||||
CHEAT INFINITE LIVES: [ON, OFF]
|
CHEAT INFINITE LIVES: [ON, OFF]
|
||||||
CHEAT INVINCIBILITY: [ON, OFF]
|
CHEAT INVINCIBILITY: [ON, OFF]
|
||||||
CHEAT OPEN: [THE]
|
|
||||||
CHEAT OPEN THE: [JAIL]
|
|
||||||
CHEAT CLOSE: [THE]
|
|
||||||
CHEAT CLOSE THE: [JAIL]
|
|
||||||
debug_extras:
|
debug_extras:
|
||||||
hidden: false
|
hidden: false
|
||||||
help_hidden: false
|
help_hidden: false
|
||||||
|
|||||||
@@ -204,11 +204,22 @@ void Player::updateVelocity(float delta_time) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (target != 0.0F) {
|
if (target != 0.0F) {
|
||||||
|
// Reset al cambiar de dirección: un giro breve también para en seco.
|
||||||
|
if (vx_ != 0.0F && ((target > 0.0F) != (vx_ > 0.0F))) {
|
||||||
|
walk_time_ = 0.0F;
|
||||||
|
}
|
||||||
vx_ = target;
|
vx_ = target;
|
||||||
|
walk_time_ += delta_time;
|
||||||
|
} else if (walk_time_ < WALK_INERTIA_THRESHOLD) {
|
||||||
|
// Tap corto: parada seca, sin inercia (permite pasos finos).
|
||||||
|
vx_ = 0.0F;
|
||||||
|
walk_time_ = 0.0F;
|
||||||
} else if (vx_ > 0.0F) {
|
} else if (vx_ > 0.0F) {
|
||||||
vx_ = std::max(vx_ - STEP, 0.0F);
|
vx_ = std::max(vx_ - STEP, 0.0F);
|
||||||
|
if (vx_ == 0.0F) { walk_time_ = 0.0F; }
|
||||||
} else if (vx_ < 0.0F) {
|
} else if (vx_ < 0.0F) {
|
||||||
vx_ = std::min(vx_ + STEP, 0.0F);
|
vx_ = std::min(vx_ + STEP, 0.0F);
|
||||||
|
if (vx_ == 0.0F) { walk_time_ = 0.0F; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -551,6 +562,7 @@ void Player::transitionToState(State state) {
|
|||||||
case State::ON_AIR:
|
case State::ON_AIR:
|
||||||
last_grounded_position_ = static_cast<int>(y_);
|
last_grounded_position_ = static_cast<int>(y_);
|
||||||
current_carrier_ = nullptr; // Perder carry al despegar
|
current_carrier_ = nullptr; // Perder carry al despegar
|
||||||
|
walk_time_ = 0.0F; // Al aterrizar volverá a contar desde 0
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ class Player {
|
|||||||
// --- Constantes de física ---
|
// --- Constantes de física ---
|
||||||
static constexpr float HORIZONTAL_VELOCITY = 75.0F;
|
static constexpr float HORIZONTAL_VELOCITY = 75.0F;
|
||||||
static constexpr float HORIZONTAL_ACCEL = 500.0F;
|
static constexpr float HORIZONTAL_ACCEL = 500.0F;
|
||||||
|
static constexpr float WALK_INERTIA_THRESHOLD = 0.16F;
|
||||||
static constexpr float MAX_VY = 160.0F;
|
static constexpr float MAX_VY = 160.0F;
|
||||||
static constexpr float JUMP_VELOCITY = -178.5F;
|
static constexpr float JUMP_VELOCITY = -178.5F;
|
||||||
static constexpr float GRAVITY_FORCE = 360.0F;
|
static constexpr float GRAVITY_FORCE = 360.0F;
|
||||||
@@ -98,6 +99,7 @@ class Player {
|
|||||||
float y_ = 0.0F;
|
float y_ = 0.0F;
|
||||||
float vx_ = 0.0F;
|
float vx_ = 0.0F;
|
||||||
float vy_ = 0.0F;
|
float vy_ = 0.0F;
|
||||||
|
float walk_time_ = 0.0F;
|
||||||
|
|
||||||
Direction wanna_go_ = Direction::NONE;
|
Direction wanna_go_ = Direction::NONE;
|
||||||
bool wanna_jump_ = false;
|
bool wanna_jump_ = false;
|
||||||
|
|||||||
@@ -91,7 +91,11 @@ void SolidActorManager::forEachActor(Fn&& fn) const {
|
|||||||
// Devuelve el borde derecho del actor bloqueante "a la izquierda" del Player.
|
// Devuelve el borde derecho del actor bloqueante "a la izquierda" del Player.
|
||||||
// Criterio: el AABB del actor solapa el rect del Player y el borde izquierdo
|
// Criterio: el AABB del actor solapa el rect del Player y el borde izquierdo
|
||||||
// del actor está a la izquierda del borde izquierdo del Player (el Player se
|
// del actor está a la izquierda del borde izquierdo del Player (el Player se
|
||||||
// mete en él por la izquierda).
|
// mete en él por la izquierda). El test del borde derecho es contact-inclusive
|
||||||
|
// (>=) para que el contacto flush cuente como pared, igual que TileCollider.
|
||||||
|
// Sin esto, Player::stuckAgainstWall no detectaba puertas cerradas en contacto
|
||||||
|
// y la animación "walk" se reproducía aunque el clamp de moveHorizontal
|
||||||
|
// dejase x_ inmóvil.
|
||||||
auto SolidActorManager::checkWallLeft(float px, float py, float pw, float ph) const -> float {
|
auto SolidActorManager::checkWallLeft(float px, float py, float pw, float ph) const -> float {
|
||||||
float result = Collision::NONE;
|
float result = Collision::NONE;
|
||||||
forEachActor([&](const SolidActor* a, const SDL_FRect& r) {
|
forEachActor([&](const SolidActor* a, const SDL_FRect& r) {
|
||||||
@@ -100,9 +104,10 @@ auto SolidActorManager::checkWallLeft(float px, float py, float pw, float ph) co
|
|||||||
// Y-overlap
|
// Y-overlap
|
||||||
if (py + ph <= r.y) { return; }
|
if (py + ph <= r.y) { return; }
|
||||||
if (py >= r.y + r.h) { return; }
|
if (py >= r.y + r.h) { return; }
|
||||||
// X-overlap y "a la izquierda": el Player (px) está dentro del actor.
|
// X-overlap y "a la izquierda": el Player (px) está dentro del actor
|
||||||
|
// o en contacto exacto con su borde derecho.
|
||||||
const float RIGHT_EDGE = r.x + r.w;
|
const float RIGHT_EDGE = r.x + r.w;
|
||||||
if (r.x < px && RIGHT_EDGE > px) {
|
if (r.x < px && RIGHT_EDGE >= px) {
|
||||||
if (result == Collision::NONE || RIGHT_EDGE > result) {
|
if (result == Collision::NONE || RIGHT_EDGE > result) {
|
||||||
result = RIGHT_EDGE;
|
result = RIGHT_EDGE;
|
||||||
}
|
}
|
||||||
@@ -112,6 +117,7 @@ auto SolidActorManager::checkWallLeft(float px, float py, float pw, float ph) co
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Devuelve el borde izquierdo del actor bloqueante "a la derecha" del Player.
|
// Devuelve el borde izquierdo del actor bloqueante "a la derecha" del Player.
|
||||||
|
// Test contact-inclusive (<=) por las mismas razones que checkWallLeft.
|
||||||
auto SolidActorManager::checkWallRight(float px, float py, float pw, float ph) const -> float {
|
auto SolidActorManager::checkWallRight(float px, float py, float pw, float ph) const -> float {
|
||||||
float result = Collision::NONE;
|
float result = Collision::NONE;
|
||||||
forEachActor([&](const SolidActor* a, const SDL_FRect& r) {
|
forEachActor([&](const SolidActor* a, const SDL_FRect& r) {
|
||||||
@@ -120,9 +126,10 @@ auto SolidActorManager::checkWallRight(float px, float py, float pw, float ph) c
|
|||||||
// Y-overlap
|
// Y-overlap
|
||||||
if (py + ph <= r.y) { return; }
|
if (py + ph <= r.y) { return; }
|
||||||
if (py >= r.y + r.h) { return; }
|
if (py >= r.y + r.h) { return; }
|
||||||
// X-overlap y "a la derecha": el borde derecho del Player entra en el actor.
|
// X-overlap y "a la derecha": el borde derecho del Player entra en el
|
||||||
|
// actor o está en contacto exacto con su borde izquierdo.
|
||||||
const float PLAYER_RIGHT = px + pw;
|
const float PLAYER_RIGHT = px + pw;
|
||||||
if (r.x < PLAYER_RIGHT && r.x + r.w > PLAYER_RIGHT) {
|
if (r.x <= PLAYER_RIGHT && r.x + r.w > PLAYER_RIGHT) {
|
||||||
if (result == Collision::NONE || r.x < result) {
|
if (result == Collision::NONE || r.x < result) {
|
||||||
result = r.x;
|
result = r.x;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user