Мое взаимодействие между двумя объектами не работает, и в результате получается "Не удается прочитать свойство 'x' из неопределенного" - PullRequest
2 голосов
/ 26 февраля 2020

Хорошо! Поэтому, посмотрев некоторое время на переполнение стека, p5. js ссылки и отладку в течение нескольких часов, я решил, что мне нужна пара глаз * fre sh для просмотра моего кода. Прямо сейчас моя игра - это та, в которой пользователь использует 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>

Итак, проблема определенно где-то в объектах или в функции рисования, когда они используются. Если кто-то может помочь, это было бы здорово, и если вам нужно, чтобы я объяснил больше, просто скажите. Заранее спасибо!

1 Ответ

1 голос
/ 26 февраля 2020

Основная проблема заключается в том, что вы итерируете массивы, в то время как вы удаляете элементы из массивов. Вы пропустите элемент для каждого удаляемого элемента (кроме последнего удаляемого элемента).
См. Также (Looping through array and removing items, without breaking for loop)

Более того, вы 2 вложенных массива и удаляемые элементы образуют внешний список во внутренней l oop. Это приводит к ошибке, если последний элемент внешнего списка удален, а внутренний массив все еще итерирован:

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>
...