我在两个对象之间的交互不起作用,结果为 "Cannot read property 'x' of undefined"

My interaction between two objects aren't working and result with "Cannot read property 'x' of undefined"

好的!因此,在查看了一段时间的堆栈溢出、p5.js 参考和调试几个小时之后,我决定需要一双新的眼睛来检查我的代码。现在,我的游戏是用户使用 WASD 移动并点击射击子弹的游戏,唯一的问题是,当子弹在敌人的射程内(特别是不止一个)时,我收到一条错误消息,提示 x 未定义。现在,我知道这与对象问题以及这些行周围的问题有关,我只是找不到位置。有人可以帮忙吗?

//Character Position
let playX = 300;
let playY = 300;

let up = false;
let down = false;
let left = false;
let right = false;
let working = false;

let bulletSpeed = 3;
var bullets = [];
var shadows = [];
var angleEn;
var enemySpeed = 1;
var spawnRate = 300;

function setup() {
  var canvas = createCanvas(600, 600);
  generateEnemy();
}

function generateEnemy() {
  side = floor(random(0, 2));
  side2 = floor(random(0, 2));
  if (side % 2 === 0) { // top and bottom
    shadows.push(new Enemy(random(0, width), height * (side2 % 2)));
  } else { // sides
    shadows.push(new Enemy(width * (side2 % 2), random(0, height)));
  }
}

function timeEnter() {
  if (frameCount % spawnRate === 0) {
    generateEnemy();
    if (enemySpeed < 3) {
      enemySpeed += 0.1;
    }
    if (spawnRate > 50) {
      spawnRate -= 10;
    }
  }
}

function character() {
  fill(0);
  rect(playerX, playerY, 50, 50);
}

function movement() {
  if (up) {
    playY -= 2;
  }
  if (down) {
    playY += 2;
  }
  if (left) {
    playX -= 2;
  }
  if (right) {
    playX += 2;
  }
}

function draw() {
  //Setting up background
  playerX = playX - 25;
  playerY = playY - 25;
  background(0);
  fill(255);
  rect(100, 100, 400, 400);

  //Basic movement and display of character
  movement();
  character();
  timeEnter();

  //Updating and moving bullets
  for (let i = 0; i < bullets.length; i++) {
    bullets[i].update();
    bullets[i].display();

    if (bullets[i].x < -50 || bullets[i].x > 650 || bullets[i].y < -50 || bullets[i].y > 650) {
      bullets.splice(i, 1);
    }
  }

  //Updating and moving shadows
  for (let s = 0; s < shadows.length; s++) {
    shadows[s].update();
    shadows[s].display();
    for (let e = 0; e < bullets.length; e++) {
      if (abs(bullets[e].x - shadows[s].x) < 25 && abs(bullets[e].y - shadows[s].y) < 25) {
        bullets.splice(e, 1);
        shadows.splice(s, 1);
      }
    }

  }

}

function keyTyped() {
  if (key === 'w') {
    up = true;
  }
  if (key === 's') {
    down = true;
  }
  if (key === 'a') {
    left = true;
  }
  if (key === 'd') {
    right = true;
  }
}

function keyReleased() {
  if (key === 'w') {
    up = false;
  }
  if (key === 's') {
    down = false;
  }
  if (key === 'a') {
    left = false;
  }
  if (key === 'd') {
    right = false;
  }

}

function mousePressed() {
  dx = mouseX - 25 - playerX;
  dy = mouseY - 25 - playerY;
  angle = atan2(dy, dx);
  vx = bulletSpeed * cos(angle);
  vy = bulletSpeed * sin(angle);
  bullets.push(new Bullet(playX, playY, vx, vy));

}


function Enemy(x, y) {
  this.x = x;
  this.y = y;


  this.update = function() {
    angleEn = atan2(playerY - this.y, playerX - this.x);
    this.vx = cos(angleEn);
    this.vy = sin(angleEn);
    this.x += this.vx * enemySpeed;
    this.y += this.vy * enemySpeed;
  }

  this.display = function() {
    stroke(255);
    strokeWeight(4);
    fill(0);
    rect(this.x, this.y, 50, 50);
  }
}


function Bullet(x, y) {
  this.x = x;
  this.y = y;
  this.vx = vx;
  this.vy = vy;


  this.update = function() {
    this.x += this.vx;
    this.y += this.vy;
  }

  this.display = function() {
    ellipse(this.x, this.y, 25, 25);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.min.js"></script>

所以,问题肯定出在对象或绘图函数使用时的某个地方。如果有人能提供帮助那就太好了,如果您需要我解释更多,请直说。提前致谢!

主要问题是,在从数组中删除元素的同时迭代数组。对于每个被移除的元素,您将错过一个元素(除了最后一个被移除的元素)。
另请参阅 ()

此外,您 2 个嵌套数组和删除元素构成了内部循环中的外部列表。如果外部列表的最后一个元素被删除并且内部数组仍然被迭代,则会导致错误:

for (let s = 0; s < shadows.length; s++) {
   // [...]

   for (let e = 0; e < bullets.length; e++) {
      if (abs(bullets[e].x - shadows[s].x) < 25 && abs(bullets[e].y - shadows[s].y) < 25) {
           bullets.splice(e, 1);
           shadows.splice(s, 1); // <--- causes error if last element is removed 
                                 //      but inner loop still runs  
       }
   }
}

另一个问题是碰撞测试无法正常工作,因为 (shadows[s].x, shadows[s].y) 是矩形的左上角而不是中心。

以相反的顺序迭代数组并使用 (shadows[s].x+25, shadows[s].y+25) 进行碰撞测试,解决问题:

//Updating and moving bullets
for (let i = bullets.length-1; i >=0 ; i--) {
      bullets[i].update();
      bullets[i].display();

    if (bullets[i].x < -50 || bullets[i].x > 650 || bullets[i].y < -50 || bullets[i].y > 650) {
        bullets.splice(i, 1);
    }
}

//Updating and moving shadows
for (let s = shadows.length-1; s >= 0; s--) {
    shadows[s].update();
    shadows[s].display();

    let remove_enemy = false;
    for (let e = bullets.length-1; e >=0 ; e--) {
        if (abs(bullets[e].x - (shadows[s].x+25)) < 25 && abs(bullets[e].y - (shadows[s].y+25)) < 25) {
            bullets.splice(e, 1);
            remove_enemy = true;
        }
    }
    if (remove_enemy) {
        shadows.splice(s, 1);
    }
}

完整示例:

//Character Position
let playX = 300;
let playY = 300;

let up = false;
let down = false;
let left = false;
let right = false;
let working = false;

let bulletSpeed = 3;
var bullets = [];
var shadows = [];
var angleEn;
var enemySpeed = 1;
var spawnRate = 300;

function setup() {
  var canvas = createCanvas(600, 600);
  generateEnemy();
}

function generateEnemy() {
  side = floor(random(0, 2));
  side2 = floor(random(0, 2));
  if (side % 2 === 0) { // top and bottom
    shadows.push(new Enemy(random(0, width), height * (side2 % 2)));
  } else { // sides
    shadows.push(new Enemy(width * (side2 % 2), random(0, height)));
  }
}

function timeEnter() {
  if (frameCount % spawnRate === 0) {
    generateEnemy();
    if (enemySpeed < 3) {
      enemySpeed += 0.1;
    }
    if (spawnRate > 50) {
      spawnRate -= 10;
    }
  }
}

function character() {
  fill(0);
  rect(playerX, playerY, 50, 50);
}

function movement() {
  if (up) {
    playY -= 2;
  }
  if (down) {
    playY += 2;
  }
  if (left) {
    playX -= 2;
  }
  if (right) {
    playX += 2;
  }
}

function draw() {
  //Setting up background
  playerX = playX - 25;
  playerY = playY - 25;
  background(0);
  fill(255);
  rect(100, 100, 400, 400);

  //Basic movement and display of character
  movement();
  character();
  timeEnter();

    //Updating and moving bullets
    for (let i = bullets.length-1; i >=0 ; i--) {
          bullets[i].update();
          bullets[i].display();

        if (bullets[i].x < -50 || bullets[i].x > 650 || bullets[i].y < -50 || bullets[i].y > 650) {
            bullets.splice(i, 1);
        }
    }

    //Updating and moving shadows
    for (let s = shadows.length-1; s >= 0; s--) {
        shadows[s].update();
        shadows[s].display();
        
        let remove_enemy = false;
        for (let e = bullets.length-1; e >=0 ; e--) {
            if (abs(bullets[e].x - (shadows[s].x+25)) < 25 && abs(bullets[e].y - (shadows[s].y+25)) < 25) {
                bullets.splice(e, 1);
                remove_enemy = true;
            }
        }
        if (remove_enemy) {
            shadows.splice(s, 1);
        }
    }
}

function keyTyped() {
  if (key === 'w') {
    up = true;
  }
  if (key === 's') {
    down = true;
  }
  if (key === 'a') {
    left = true;
  }
  if (key === 'd') {
    right = true;
  }
}

function keyReleased() {
  if (key === 'w') {
    up = false;
  }
  if (key === 's') {
    down = false;
  }
  if (key === 'a') {
    left = false;
  }
  if (key === 'd') {
    right = false;
  }

}

function mousePressed() {
  dx = mouseX - 25 - playerX;
  dy = mouseY - 25 - playerY;
  angle = atan2(dy, dx);
  vx = bulletSpeed * cos(angle);
  vy = bulletSpeed * sin(angle);
  bullets.push(new Bullet(playX, playY, vx, vy));
}


function Enemy(x, y) {
  this.x = x;
  this.y = y;


  this.update = function() {
    angleEn = atan2(playerY - this.y, playerX - this.x);
    this.vx = cos(angleEn);
    this.vy = sin(angleEn);
    this.x += this.vx * enemySpeed;
    this.y += this.vy * enemySpeed;
  }

  this.display = function() {
    stroke(255);
    strokeWeight(4);
    fill(0);
    rect(this.x, this.y, 50, 50);
  }
}


function Bullet(x, y) {
  this.x = x;
  this.y = y;
  this.vx = vx;
  this.vy = vy;


  this.update = function() {
    this.x += this.vx;
    this.y += this.vy;
  }

  this.display = function() {
    ellipse(this.x, this.y, 25, 25);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.10.2/p5.js"></script>