You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实体误判被玩家阻挡无法移动的代码问题排查

问题

原本要实现「目标格子被其他实体占据时阻止实体移动」的功能,但出现异常:实体尝试移动到空格子时,却被误判为被玩家阻挡,日志输出“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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 10:34:56