javascript - 发射器跟随 Canvas 中的粒子

标签 javascript html canvas html5-canvas

在此 HTML5 代码中,我尝试从对象 [0] 中的发射器发射粒子。 这可以在控制台中使用 objects[0].play 运行。 然而,发射器跟随发射的粒子。

我的问题是,为什么?

HTML 代码

<html>
<head>
    <style>
        #canv{
            border: 1px solid black;
        }
    </style>

    <script src = "setup.js"></script>
    <script src = "main.js"></script>
</head>

<body onLoad = "start()">
    <canvas width = "500" height = "500" id = "canv"></canvas>
</body>
</html>

setup.js

var objects = [];
var sprites = [];
var c;
var ctx;

var time;
var timeInterval;

function newSprite(url){
    var a = sprites.length;
    var b = new Image();
    b.src = url;

    b.onload = function(){
        sprites[a] = b;
    };
}

function randomN(min, max){
    return Math.floor((Math.random()*max) - min);
}

function Vector2(x,y){
    this.x = x;
    this.y = y;
}

function Particle(pos, life, vel, accel){
    this.pos = pos;
    this.life = life || Infinity;
    this.vel = vel || new Vector2(0,0);
    this.accel = accel || new Vector2(0,0);

    this.update = function(){
        this.pos.x += this.vel.x;
        this.pos.y += this.vel.y;
        this.vel.x += this.accel.x;
        this.vel.y += this.accel.y;

        this.life--;

        if(this.life <= 0){
            return false;
        }else{
            return true;
        }
    };
}

function Emitter(pos){
    this.pos = pos;
    this.actualPos = this.pos;

    this.particles = [];
    this.forces = [];
    this.playing = false;

    this.newParticle = function(life, vel, accel){
        var a = this.particles.length;
        this.particles[a] = new Particle(this.pos, life, vel, accel);
    };


    this.update = function(){
        console.log("(" + this.actualPos.x + ", " + this.actualPos.y + ") " + "(" + this.pos.x + ", " + this.pos.y + ")");
        for(var a = 0; a < this.particles.length; a++){
            for(var b = 0; b < this.forces.length; b++){
                this.forces[b](this.particles[a]);
            }
            var that = this.particles[a];
            var particleAlive = that.update();

            if(particleAlive == false){
                this.particles.splice(a, 1);
                a--;
            }
        }
    };


    this.play = function(){
        this.playing = true;
    };
}


function timeStep(){
    for(var a = 0; a < objects.length; a++){
        if(objects[a].__proto__.constructor.name == "Emitter"){
            if(objects[a].playing == true){
                objects[a].update();
            }
        }
    }

    objects[1].newParticle(1000, new Vector2(1, 0), new Vector2(0.1, 0));
    time++;
}

function gravity(p){
    //p.vel.y += 0.1;
}   

ma​​in.js

function start(){
    c = document.getElementById("canv");
    ctx = c.getContext('2d');


    newSprite("spark.png");
    objects[0] = new Emitter(new Vector2(50, 60));
    objects[0].forces.push(gravity);
    objects[0].newParticle(1000, new Vector2(1, 0), new Vector2(0.1, 0));

    objects[1] = new Emitter(new Vector2(100, 100));
    objects[1].forces.push(gravity);
    time = 0;
    timeInterval = window.setInterval(timeStep, 10);
    reDraw();
}

function reDraw(){
    ctx.clearRect(0, 0, c.width, c.height);
    for(var a = 0; a < objects.length; a++){
        if(objects[a].__proto__.constructor.name == "Emitter"){
            ctx.beginPath();
            ctx.arc(objects[a].pos.x, objects[a].pos.y, 5, 0, 2*Math.PI);
            ctx.fillStyle = "black";
            ctx.fill();
            ctx.closePath();
            if(objects[a].playing == true){
                for(var b = 0; b < objects[a].particles.length; b++){
                    ctx.beginPath();
                    ctx.drawImage(sprites[0], objects[a].particles[b].pos.x, objects[a].particles[b].pos.y, 8,8);
                    //ctx.arc(objects[a].particles[b].pos.x, objects[a].particles[b].pos.y, 5, 0, 2*Math.PI);
                    ctx.fillStyle = "black";
                    ctx.fill();
                    ctx.closePath();
                }
            }
        }
    }

    requestAnimationFrame(reDraw);
}

最佳答案

您的错误是使用对象引用而不是使用对象的值的一个非常经典的错误:当您创建一个新粒子时,您将其位置设置为发射器的非常位置。< br/> 因此,对粒子位置的任何后续更改都会更改发射器的位置:同样,位置 (pos) 对象是同一个对象。
您想要的是每个粒子都有自己的位置,即具有发射器位置的初始值。
例如,完成:

function Particle(pos, life, vel, accel){
      this.pos = new Vector2(pos.x, pos.y);
      //...

请注意,速度和加速度也是引用,这在这里不是问题,因为您使用新的 Vector2 来调用构造函数。
但是,您可能希望通过对这两个属性执行复制来保护您的代码免受将来可能出现的错误。

关于javascript - 发射器跟随 Canvas 中的粒子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29276441/

相关文章:

php - 从像素数组创建图像服务器端

javascript - 当一个 Canvas 放置在另一个 Canvas 之上时文本模糊

javascript - 如何获取鼠标坐标并调用.push()?

javascript - 我正在尝试将 header 中的 HTTP_X_FORWARDED_FOR 传递给 php 服务器,但未在服务器中获取其值

html - 删除边距响应缩略图网格

html - 仅用于 HTML 的 Sass

html - 防止在双击时选择多个 html 元素

javascript - 动态发送数据到服务器

javascript - 如何在 GSAP 中结合交错和时间线

javascript - 使用 new Object() 为定义为属性的方法获取未定义