遍历两个数组以进行命中检测时出现 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】:
发生这种情况是因为有时参数a
或b
被传递到函数中,即使它只是一个undefined
值。尝试执行undefined.position
会导致您的类型错误。
简单、hacky 的解决方案就是在顶部放置一个条件:
if (!a || !b)
return 0; // or whatever your default value is supposed to be
;
真正更好的解决方案是找出为什么bullets
和enemies
包含一些未定义的值。
阅读您的代码后,我认为这就是答案:
如果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 错误的主要内容,如果未能解决你的问题,请参考以下文章
尝试结合使用 jQuery 的 window.open 函数和 for 循环来遍历数组时出现问题
统一进行光线投射时出现 NullReferenceException