Array.forEach 单击时更新数组中的每个项目

Array.forEach Updating each Item in Array on click

当程序运行时,单击鼠标会从屏幕中心创建一个射弹,每一帧都沿发射方向移动(单击鼠标位置)。

当 N+1 颗射弹发射完毕后,屏幕上的所有射弹都会移动到新的点击位置,而不是继续它们的路径。

我无法弄清楚为什么当新弹丸的速度应该对先前的弹丸没有影响时,当前的弹丸会改变方向。

index.html

<canvas></canvas>
<script src="./guns.js"></script>
<script src="./indexh.js"></script>
<script src="./runh.js"></script>

runh.html

const projectilesArray = [];
let frameCount = 0;

function animate() {
    animationID = requestAnimationFrame(animate);
    c.fillStyle = "rgba(0, 0, 0, 1)";
    c.fillRect(0, 0, canvas.width, canvas.height);

    projectilesArray.forEach((Projectile, pIndex) => {
        Projectile.update();
        console.log(Projectile)
  
        if (
          Projectile.x + Projectile.radius < 0 ||
          Projectile.x - Projectile.radius > canvas.width ||
          Projectile.y + Projectile.radius < 0 ||
          Projectile.y - Projectile.radius > canvas.height
        ) {
          setTimeout(() => {
            projectilesArray.splice(pIndex, 1);
          }, 0);
        }
      });
    
    frameCount++;
    if (frameCount > 150) {
        
    }
}
var fire = 1;
let fireRate = 1;
const mouse = {
    x: 0,
    y: 0,
    click: true,
  };

canvas.addEventListener('mousedown', (event) => {

    if (fire % fireRate == 0) {
      if (mouse.click == true) {
        mouse.x = event.x;
        mouse.y = event.y;

        const angle = Math.atan2(mouse.y - (canvas.height / 2), mouse.x - (canvas.width / 2));
        const fireY = Math.sin(angle);
        const fireX = Math.cos(angle);
        //score -= 0;
        //scoreL.innerHTML = score;
        var weapon = new Projectile(cannon);
        weapon.velocity.x = fireX * 9;
        weapon.velocity.y = fireY * 9;
       
        projectilesArray.push(weapon);
     

        //var gun = object.constructor()
      }
    }
  });

  animate();

indexh.js

const canvas = document.querySelector("canvas");
const c = canvas.getContext("2d");

canvas.width = innerWidth;
canvas.height = innerHeight;



class Projectile {
    constructor(config) {
        this.color = config.color || "rgb(60, 179, 113)";
        this.radius = config.radius || 1;
        this.speed = config.speed || 5;
        this.rounds = config.rounds || 2;
        this.x = config.x || canvas.width / 2;
        this.y = config.y || canvas.height /2;
        this.velocity = config.velocity;
    }
    draw() {
        c.beginPath();
        c.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
        c.fillStyle = this.color;
        c.fill();
    }
    update() {
        this.draw();
        this.x = this.x + this.velocity.x * this.speed;
        this.y = this.y + this.velocity.y * this.speed;
    }
}

gums.js

let pistol = {
    color : "rgb(255, 0, 0)",
    radius : 10,
    speed : 1,
    rounds : 1,

    velocity : {
        x: 1,
        y: 1
    }
}

let cannon = {
    color : "rgb(0, 0, 255)",
    radius : 30,
    speed : .5,
    rounds : 1,

    velocity : {
        x: 1,
        y: 1
    }
}

谢谢

问题是您将此 cannon 对象用作配置对象:

let cannon = {
    color : "rgb(0, 0, 255)",
    radius : 30,
    speed : .5,
    rounds : 1,

    velocity : {
        x: 1,
        y: 1
    }
}

并且在您的 Projectile 构造函数中,您分配 this.velocity = config.velocity; 您正在分配 this.velocity 为所有 Projectile 的相同对象实例。要修复它,请尝试复制对象,例如:

this.velocity = {...config.velocity};

这将创建对象的副本而不是共享相同的对象实例。

另请注意,您有一个错误,但您没有在此行中询问:

projectilesArray.splice(pIndex, 1);

如果两个超时在同一个循环中排队,当第一个超时触发时数组将移动,第二个超时将在错误的索引上操作。