一个阵列的重置影响另一个阵列

The reset of one array affecting a different array

我不完全确定这里发生了什么。当您发射所有三颗子弹并且最后一颗子弹离开屏幕时,"asteroids" 数组也会重置。

编辑: 是不是因为bullets数组在全部离开屏幕的时候最后拼接成了一个undefined?还是 return 基本空数组?即便如此,它也没有解释为什么小行星阵列也被取消了。我还发现,除非我至少射击一次,否则小行星甚至不会开始坠落。

Code on p5web editor

造成这种情况的原因是什么?这是我第一次编写这么大的代码,代码量很大,但我确保在大多数情况下使用明显的变量名。

问题出在你的asteroids class:

check(bullets) {
    for (let i = 0; i < bullets.length; i++) {
        if (dist(bullets[i].x, bullets[i].y, this.pos.x, this.pos.y) < this.r) {
            return false;
        } else {
            return true;
        }
    }
}

如果没有要检查的子弹,这个函数 returns undefined 隐含地被调用代码认为是假的,它会立即摧毁小行星,就像它与子弹相撞一样.

此外,如果有子弹需要检查,而第一个恰好没有发生碰撞,则循环会过早中断 else { return true; },可能会丢失碰撞。

改为:

check(bullets) {
    for (let i = 0; i < bullets.length; i++) {
        if (dist(bullets[i].x, bullets[i].y, this.pos.x, this.pos.y) < this.r) {
            return false;
        }
    }

    return true; // no collisions (or bullets.length === 0)
}

话虽如此,函数名称 check 还是很不清楚。我将其重命名为 collidesWith(bullets) 并反转布尔值——"true, yes, we did collide with a bullet" 比 "false, yes, we did collide with a bullet" 更有意义。我们还可以使用 for ... of 循环结构。这给了我们:

collidesWith(bullets) {
    for (const bullet of bullets) {
        if (dist(bullet.x, bullet.y, this.pos.x, this.pos.y) < this.r) {
            return true;
        }
    }

    return false;
}

您可以进一步缩短为:

collidesWith(bullets) {
  return bullets.some(e => dist(e.x, e.y, this.pos.x, this.pos.y) < this.r);
}

同样,我会将 bullet.check() 更改为 bullet.outOfBounds() 或类似的。

另一个提示:反向迭代您计划从以下位置切片当前元素的任何数组:

for (let j = asteroids.length - 1; j >= 0; j--) {
   // code that could call `.splice(j, 1)`
}

否则,在拼接后,您的循环将跳过一个元素,您可能会错过碰撞。

一个小设计点,但 player.controls() 看起来很奇怪——为什么玩家要负责监听按键?我会在 keyPressed() 函数中收听并发送更改以从那里更新玩家位置。我还会将 draw 分解成更小的函数。但这些都是次要的设计决定,因此以上内容足以让您滚动。

这是 draw 函数的第一个修订版,经过调整以匹配修改后的布尔值:

function draw() {
  background(0);
  scene();

  if (tick <= 0) {
    if (asteroids.length < asteroidsLimit) {
      asteroids.push(new Asteroid());
    }

    tick = 60;
  }

  for (let i = asteroids.length - 1; i >= 0; i--) {
    if (asteroids[i].collidesWith(bullets)) {
      asteroids.splice(i, 1);
    } 
    else {
      asteroids[i].update();
      asteroids[i].display();
    }
  }

  for (let i = bullets.length - 1; i >= 0; i--) {
    if (bullets[i].outOfBounds()) {
      bullets.splice(i, 1);
    } 
    else {
      bullets[i].update();
      bullets[i].display();
    }
  }

  image(ship, player.x, player.y);
  player.controls();
  tick--;
}