我正在用纯 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
);
}
最佳答案
发生这种情况是因为有时参数 a
或 b
会传递到函数中,即使它只是一个 未定义
值。尝试执行 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/