Allow melee attacking diagonally as well

This commit is contained in:
Peter Stockings
2026-01-06 10:53:13 +11:00
parent 0263495d0b
commit a9779348e9
3 changed files with 149 additions and 22 deletions

View File

@@ -221,7 +221,23 @@ export class GameScene extends Phaser.Scene {
a.category === "combatant" && a.pos.x === tx && a.pos.y === ty && !a.isPlayer
);
const player = this.world.actors.get(this.playerId) as CombatantActor;
// Check for diagonal adjacency for immediate attack
const player = this.world.actors.get(this.playerId) as CombatantActor;
const dx = tx - player.pos.x;
const dy = ty - player.pos.y;
const isDiagonalNeighbor = Math.abs(dx) === 1 && Math.abs(dy) === 1;
if (isEnemy && isDiagonalNeighbor) {
// Check targetId again to get the ID... technically we just did .some() above.
const targetId = [...this.world.actors.values()].find(
a => a.category === "combatant" && a.pos.x === tx && a.pos.y === ty && !a.isPlayer
)?.id;
if (targetId !== undefined) {
this.commitPlayerAction({ type: "attack", targetId });
return;
}
}
const path = findPathAStar(
this.world,
this.dungeonRenderer.seenArray,
@@ -274,31 +290,64 @@ export class GameScene extends Phaser.Scene {
return;
}
// Arrow keys
// Arrow keys - Support diagonals for attacking only
let action: Action | null = null;
let dx = 0;
let dy = 0;
if (Phaser.Input.Keyboard.JustDown(this.cursors.left!)) dx = -1;
else if (Phaser.Input.Keyboard.JustDown(this.cursors.right!)) dx = 1;
else if (Phaser.Input.Keyboard.JustDown(this.cursors.up!)) dy = -1;
else if (Phaser.Input.Keyboard.JustDown(this.cursors.down!)) dy = 1;
// Check all keys to allow simultaneous presses
if (this.cursors.left!.isDown) dx -= 1;
if (this.cursors.right!.isDown) dx += 1;
if (this.cursors.up!.isDown) dy -= 1;
if (this.cursors.down!.isDown) dy += 1;
if (dx !== 0 || dy !== 0) {
const player = this.world.actors.get(this.playerId) as CombatantActor;
const targetX = player.pos.x + dx;
const targetY = player.pos.y + dy;
// Force single step input "just now" check to avoid super speed,
// OR we rely on `awaitingPlayer` to throttle us.
// `update` runs every frame. `awaitingPlayer` is set to false in `commitPlayerAction`.
// It remains false until `stepUntilPlayerTurn` returns true.
// So as long as we only act when `awaitingPlayer` is true, simple `isDown` works for direction combination.
// BUT we need to ensure we don't accidentally move if we just want to tap.
// However, common roguelike Input: if you hold, you repeat.
// We already have `awaitingPlayer` logic.
// One nuance: mixing JustDown and isDown.
// If we use isDown, we might act immediately.
// If we want to support "turn based", usually we wait for "JustDown" of *any* key.
// But if we want diagonal, we need 2 keys.
// Simpler approach:
// If any direction key is JustDown, capture the state of ALL direction keys.
const anyJustDown = Phaser.Input.Keyboard.JustDown(this.cursors.left!) ||
Phaser.Input.Keyboard.JustDown(this.cursors.right!) ||
Phaser.Input.Keyboard.JustDown(this.cursors.up!) ||
Phaser.Input.Keyboard.JustDown(this.cursors.down!);
// Check for enemy at target position
const targetId = [...this.world.actors.values()].find(
a => a.category === "combatant" && a.pos.x === targetX && a.pos.y === targetY && !a.isPlayer
)?.id;
if (anyJustDown) {
// Recalculate dx/dy based on currently held keys to catch the combo
dx = 0; dy = 0;
if (this.cursors.left!.isDown) dx -= 1;
if (this.cursors.right!.isDown) dx += 1;
if (this.cursors.up!.isDown) dy -= 1;
if (this.cursors.down!.isDown) dy += 1;
if (targetId !== undefined) {
action = { type: "attack", targetId };
} else {
action = { type: "move", dx, dy };
}
if (dx !== 0 || dy !== 0) {
const player = this.world.actors.get(this.playerId) as CombatantActor;
const targetX = player.pos.x + dx;
const targetY = player.pos.y + dy;
// Check for enemy at target position
const targetId = [...this.world.actors.values()].find(
a => a.category === "combatant" && a.pos.x === targetX && a.pos.y === targetY && !a.isPlayer
)?.id;
if (targetId !== undefined) {
action = { type: "attack", targetId };
} else {
// Only move if strictly cardinal (no diagonals)
if (Math.abs(dx) + Math.abs(dy) === 1) {
action = { type: "move", dx, dy };
}
}
}
}
if (action) {