我在两个对象之间的交互不起作用,结果为 "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>
好的!因此,在查看了一段时间的堆栈溢出、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>