如何使用粒子对象优化画布粒子系统

时间:2016-10-01 15:08:41

标签: javascript jquery canvas

所以我用canvas和javascript(一些jQuery)创建了一个简单的粒子系统,但我似乎无法让它在旧计算机上以超过8fps的速度运行,这就是代码:

var starList = [];

function Star(){
    this.x = getRandomInt(0, canvas.width);
    this.y = getRandomInt(0, canvas.height);
    this.vx = getRandomInt(2,5);
    this.size = this.vx/5;
    this.opacity = getRandomInt(0, 5000) / 10000;
    this.color = getRandomFromArray(["239, 207, 174", "162, 184, 229", "255, 255, 255"]);
    this.draw = function(){
        ctx.fillStyle = "rgba("+this.color+","+this.opacity+")";
        ctx.beginPath();
        ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, true);
        ctx.closePath();
        ctx.fill();
    },
    this.move = function(){
        this.x = this.x - this.vx;

        if(this.x < 0) {
            this.x = canvas.width;
            this.opacity = getRandomInt(0, 5000) / 10000;
            this.color = getRandomFromArray(["239, 207, 174", "162, 184, 229", "255, 255, 255"]);
            this.y = getRandomInt(0, canvas.height);
            this.size = this.vx/5;
            this.vx = getRandomInt(2,5);
        }
    }
}

var canvas, ctx;

function setCanvas(){
    canvas = $('canvas')[0];
    ctx = canvas.getContext("2d");

    canvas.width = $(window).width()/5;
    canvas.height = $(window).height()/5;
}

setCanvas();

function generateStars(){
    for(var i = 0; i < 5000; i++){
        var star = new Star();
        starList.push(star);
    }

    for(var i = 0; i < starList.length; i++) {
        star = starList[i];
        star.draw();
    }
}

generateStars();

function loop() {
    window.requestAnimationFrame(loop);

    //clear canvas
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    //draw and move stars
    for(var i = 0; i < starList.length; i++) {
        star = starList[i];
        star.draw();
        star.move();
    }
}

我假设使用粒子(星星)的对象并循环遍历5000个索引的对象数组,并且在处理器/ gpu上执行这两个函数很难但是如何优化这些代码呢?

我已经看到其他人避免在构造函数上使用函数,并在粒子循环遍历时移动和绘制粒子。这会让它更快吗?

编辑:忽略getRandomInt和类似的函数,它们是我用来生成随机内容的简单函数。

1 个答案:

答案 0 :(得分:2)

代码中最慢的部分是路径绘制命令:

ctx.fillStyle = "rgba("+this.color+","+this.opacity+")";
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();

Canvas绘制速度非常快,但5000张绘图需要一些时间。

<强>相反...

创建一个spritesheet,其中包含您要显示的所有星形变体。

将spriteesheet中的像素复制到显示画布比执行绘图命令快得多。对于绘制弧线尤其如此,其中必须围绕圆周计算许多点。

重要!

限制星星变化 - 观众不会注意到你的星星不是无限随机的。

然后使用drawimage的剪切版本快速从spritesheet中绘制每个所需的星形精灵:

// set the global alpha
ctx.globalAlpha = getRandomInt(0, 5000) / 10000;

// cut the desired star-sprite from the spritesheet
// and draw it on the visible canvas
ctx.drawImage( spritesheet,                             // take from the spritesheet
    this.sheetX, this.sheetY, this.width, this.height,  // at this sprite's x,y
    this.x, this.y, this.width, this.height)            // and draw sprite to canvas

spritesheet

您可以使用第二个内存中的画布作为spritesheet,并在应用首次启动时在客户端创建星形精灵。 drawImage命令将接受您的第二个内存中画布作为图像源(!)。

var spritesheet=document.createElement('canvas');
var spriteContext=spriteSheet.getContext('2d');
...
// draw every variation of your stars on the spritesheet canvas
...