迭代两个数组进行命中检测时出现 Javascript 错误

标签 javascript arrays html canvas ecmascript-6

我正在用纯 JS 制作一个小型 html5 Canvas 游戏(采用 Ecmascript 6 标准)。 到目前为止,一切都很顺利,但现在我陷入了反复出现的 TypeError(Uncaught TypeError: Cannot read property 'position' of undefined)。

当游戏检查两个数组内的对象之间的碰撞(更具体地说:子弹和敌人之间的碰撞检测)时,这种情况经常发生。

大多数情况下,我的碰撞检测功能运行良好。当我认为我已经解决了问题时,过了一会儿,它又再次发生。

这是我的代码:

const collisionCheckBulletEnemy = () => {

    for(let i = bullets.length -1; i >= 0; i--){
        for(let j = enemies.length -1; j >= 0; j--){

            if(collisionCheck(bullets[i], enemies[j], 10, 10)){

                bullets.splice(i, 1);
                enemies.splice(j, 1);
            }
        }
    }
}

这是碰撞检测函数:

const collisionCheck = (a, b, marginA, marginB) => {
    // margins can be added to make things a little easier/harder on the user
    if(!marginA){
        marginA = 0;
    }
    if(!marginB){
        marginB = 0;
    }

    return !(
        a.position.x - marginA > b.position.x + b.width + marginB ||
        a.position.x + a.width + marginA < b.position.x - marginB ||
        a.position.y - marginA > b.position.y + b.height + marginB ||
        a.position.y + a.height + marginA < b.position.y - marginB
    );
}

最佳答案

发生这种情况是因为有时参数 ab 会传递到函数中,即使它只是一个 未定义 值。尝试执行 undefined.position 将导致您的类型错误。

简单、hacky 的解决方案就是在顶部放置一个条件:

if (!a || !b) {
  return 0; // or whatever your default value is supposed to be
};

真正更好的解决方案是找出为什么子弹敌人包含一些未定义的值。

阅读您的代码后,我认为这就是答案:

如果当i =bullets.length - 1时此条件通过:

if(collisionCheck(bullets[i], enemies[j], 10, 10)) {
  bullets.splice(i, 1);
  enemies.splice(j, 1);
}

具体来说,这部分 bullets.splice(i, 1); 将数组缩短 1,但绝不会递减 i

因此,如果 bullets[i] 是数组中的最后一个元素,那么 bullets[i]undefined 因为 javascript 不会抛出类似 indexOutOfBounds 的错误。

现在您开始发现代码中的巨大缺陷是,当从数组中删除项目符号时,它不会停止循环,并且您只注意到它是最后一个索引。即使它不是最后一个索引,它也会继续循环寻找另一个项目符号,这似乎不是您的意图。

相反,你应该跳出循环,因为如果你的子弹击中时会被摧毁,你不应该继续检查同一颗子弹的碰撞:

if(collisionCheck(bullets[i], enemies[j], 10, 10)) {
  bullets.splice(i, 1);
  enemies.splice(j, 1);
  break;
}

关于迭代两个数组进行命中检测时出现 Javascript 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34580726/

相关文章:

javascript - 如何从@google-cloud/storage读取文件?

javascript - 将图像序列绑定(bind)到滚动事件

javascript - 是否可以使用 jQuery xml 处理程序解析 SOAP 响应?

Javascript TypeError 指出列表未定义

html - 如何将一个 div 覆盖在另一个 div 之上

javascript - 清除 HTML5 文件系统 API

php - 按父/子 ID 重组数组。递归?

c - 如何重新分配一个空的二维数组

Javascript 复选框取消选中全部有效,但选中全部不起作用

javascript - 二级菜单粘在标题上