遍历两个数组以进行命中检测时出现 Javascript 错误

Posted

技术标签:

【中文标题】遍历两个数组以进行命中检测时出现 Javascript 错误【英文标题】:Javascript error on iterating through two arrays for hit detection 【发布时间】:2016-04-07 10:48:30 【问题描述】:

我正在用纯 JS 制作一个小型 html5 画布游戏(使用 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
    );

【问题讨论】:

使用调试器找出undefined是什么。 【参考方案1】:

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

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

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

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

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

如果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 错误的主要内容,如果未能解决你的问题,请参考以下文章

检测 Spinner 组件时出现问题

尝试结合使用 jQuery 的 window.open 函数和 for 循环来遍历数组时出现问题

vs2005使用自定义服务器时出现当前不会命中断点

统一进行光线投射时出现 NullReferenceException

AWS 认知;命中 /oauth2/token 时出现未授权客户端错误

检测 ios11 设备是不是处于低功耗模式,以防止正常正确自动播放视频时出现不良 UX