Fix ladder entry/exit logic to handle top entry and prevent premature exits

This commit is contained in:
Brian Fertig 2026-02-22 22:41:45 -07:00
parent a8262f4bbf
commit be160ed954
1 changed files with 24 additions and 4 deletions

View File

@ -14,6 +14,7 @@ export default class Player {
this.lives = 3; this.lives = 3;
this.onLadder = false; this.onLadder = false;
this.atLadderTop = false; this.atLadderTop = false;
this._enteredFromTop = false;
// Create physics sprite // Create physics sprite
this._sprite = scene.physics.add.sprite(x, y, 'player', 0); this._sprite = scene.physics.add.sprite(x, y, 'player', 0);
@ -51,11 +52,13 @@ export default class Player {
_handleLadder() { _handleLadder() {
const sprite = this._sprite; const sprite = this._sprite;
const cursors = this._cursors; const cursors = this._cursors;
const body = sprite.body;
// Tile at player center (for body-of-ladder detection) // Tile at player center (for body-of-ladder detection)
const centerTile = this._laddersLayer.getTileAtWorldXY(sprite.x, sprite.y); const centerTile = this._laddersLayer.getTileAtWorldXY(sprite.x, sprite.y);
// Tile at player feet (for ladder-top detection) // Tile just below body bottom (body bottom = sprite.y + 120; +2 puts us inside
const feetTile = this._laddersLayer.getTileAtWorldXY(sprite.x, sprite.y + 116); // the tile when standing on it, since physics places body bottom at tile top)
const feetTile = this._laddersLayer.getTileAtWorldXY(sprite.x, sprite.y + 122);
const centerIsLadder = centerTile && TilePropertyHelper.isLadder(centerTile.index); const centerIsLadder = centerTile && TilePropertyHelper.isLadder(centerTile.index);
const feetIsLadderTop = feetTile && TilePropertyHelper.isLadderTop(feetTile.index); const feetIsLadderTop = feetTile && TilePropertyHelper.isLadderTop(feetTile.index);
@ -79,8 +82,16 @@ export default class Player {
return; return;
} }
// Exit ladder if center is no longer over a ladder tile // Once the center reaches a ladder tile we are fully on the ladder
if (!centerIsLadder) { if (centerIsLadder) {
this._enteredFromTop = false;
}
// Exit if center is no longer over a ladder tile.
// Exception: when we entered from the top the center starts above the ladder;
// suppress the exit until the player descends into the rungs, or until
// they press up (changing their mind).
if (!centerIsLadder && (!this._enteredFromTop || cursors.up.isDown)) {
this._exitLadder(); this._exitLadder();
} }
} else { } else {
@ -92,12 +103,21 @@ export default class Player {
sprite.body.setVelocityX(0); sprite.body.setVelocityX(0);
// Snap horizontally to ladder center // Snap horizontally to ladder center
sprite.x = centerTile.pixelX + 64; sprite.x = centerTile.pixelX + 64;
// Enter from the top: standing on the top rung tile, pressing down
} else if (feetIsLadderTop && cursors.down.isDown && body.blocked.down) {
this._enteredFromTop = true;
this.onLadder = true;
sprite.body.setGravityY(-800);
sprite.body.setVelocityY(200);
sprite.body.setVelocityX(0);
sprite.x = feetTile.pixelX + 64;
} }
} }
} }
_exitLadder() { _exitLadder() {
this.onLadder = false; this.onLadder = false;
this._enteredFromTop = false;
this._sprite.body.setGravityY(0); // Remove local gravity override; world gravity resumes this._sprite.body.setGravityY(0); // Remove local gravity override; world gravity resumes
} }