实体误判被玩家阻挡无法移动的代码问题排查
问题
原本要实现「目标格子被其他实体占据时阻止实体移动」的功能,但出现异常:实体尝试移动到空格子时,却被误判为被玩家阻挡,日志输出“space occupied by player”,导致实体无法移动。
相关代码
perform 方法
perform(engine: Engine, entity: Entity) { const destX = entity.x + this.dx; // 计算玩家的目标坐标 const destY = entity.y + this.dy; // //----------------------------------玩家回合----------------------- if (!engine.gameMap.isInBounds(destX, destY)) return; // 检查目标是否在地图范围内,不在则返回 if (!engine.gameMap.tiles[destY][destX].walkable) return; // 检查目标格子是否可行走,不可则返回 if (engine.entityAtPosition(destX, destY) !== null && engine.entityAtPosition(destX, destY) !== undefined) { entity.h = entity.h - engine.entityAtPosition(destX, destY)?.attk console.log(entity.name + " attacks " + engine.entityAtPosition(destX, destY)?.name + " for " + entity.attk + " damage") entityTurn(); // 进入敌人回合 } else { // 目标被实体占据则发起攻击 entity.move(this.dx, this.dy); // 不攻击则移动 console.log(entity.name + " moves to " + entity.x + ", " + entity.y) entityTurn(); // 进入敌人回合 } //----------------------------------敌人回合------------------------ function entityTurn() { engine.entities.forEach((e) => { // 敌人寻路(敌人可斜向移动) if (e.name !== 'player') { // 处理除玩家外的所有实体 console.log("-----" + e.name + "'s turn-----") const distanceToPlayer = Math.abs(e.x - engine.player.x) + Math.abs(e.y - engine.player.y); const dirX = Math.sign(engine.player.x - e.x); // 计算与玩家的位置差方向,Math.sign返回-1/0/1 const dirY = Math.sign(engine.player.y - e.y); // if (distanceToPlayer < 10) { console.log(e.name + " sees player") if (!engine.gameMap.isInBounds(destX, destY)) { console.log("not in bounds"); return }; // 检查目标是否在范围内 if (!engine.gameMap.tiles[destY][destX].walkable) { console.log("tile not walkable"); return }; // 检查目标格子是否可走 if (engine.entityAtPosition(destX, destY) !== null && engine.entityAtPosition(destX, destY) !== undefined) { // 检查目标是否被实体占据 console.log("space occupied by " + engine.entityAtPosition(destX, destY)?.name); return }; e.move(dirX, dirY); console.log(e.name + " moves to " + e.x + ", " + e.y) } } }); console.log("-----player's turn-----") } }
entityAtPosition 方法
entityAtPosition(x: number, y: number): Entity | null { return this.entities.find((e) => e.x === x && e.y === y) || null; }
问题原因
敌人回合的代码错误复用了玩家的目标坐标destX/destY,没有计算敌人自己的移动目标坐标。玩家回合定义的destX/destY是玩家要移动到的位置,但敌人移动时,应该计算的是敌人自身位置加上移动方向的坐标,现在敌人的所有移动检查都用了玩家的目标坐标,导致判断的是玩家目标位置是否有实体,从而误判为被玩家阻挡。
修复方案
在entityTurn函数中,为每个敌人计算自己的目标坐标,替换掉原本复用的destX/destY:
修改后的entityTurn函数:
function entityTurn() { engine.entities.forEach((e) => { if (e.name !== 'player') { console.log("-----" + e.name + "'s turn-----") const distanceToPlayer = Math.abs(e.x - engine.player.x) + Math.abs(e.y - engine.player.y); const dirX = Math.sign(engine.player.x - e.x); const dirY = Math.sign(engine.player.y - e.y); if (distanceToPlayer < 10) { console.log(e.name + " sees player") // 计算敌人自己的目标坐标 const enemyDestX = e.x + dirX; const enemyDestY = e.y + dirY; if (!engine.gameMap.isInBounds(enemyDestX, enemyDestY)) { console.log("not in bounds"); return; }; if (!engine.gameMap.tiles[enemyDestY][enemyDestX].walkable) { console.log("tile not walkable"); return; }; if (engine.entityAtPosition(enemyDestX, enemyDestY) !== null) { console.log("space occupied by " + engine.entityAtPosition(enemyDestX, enemyDestY)?.name); return; }; e.move(dirX, dirY); console.log(e.name + " moves to " + e.x + ", " + e.y) } } }); console.log("-----player's turn-----") }
另外可以优化entityAtPosition的判断逻辑,因为该方法已经返回null,不需要额外判断undefined。
内容的提问来源于stack exchange,提问作者Gogo Gig
相关产品推荐
相关产品推荐

