2016-10-01 93 views
0

所以我用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

除了它是一个不完整的列表和想法不能被测试,只是转发给你 - 看起来显而易见的一点似乎是绘制函数。 5000弧似乎需要一段时间才能画出。我会尝试绘制5000个矩形。如果速度快得多,可能仍然值得使用合成材料绘制圆形透明png来为其着色。计算弧的轮廓将会很慢,我想可能不是硬件加速。另一方面,图像混合/缩放/着色可以。以下是时间安排:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now – enhzflep

回答

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(); 

帆布很快吸引,但5000张图纸需要一定的时间。

,而不是...

创建包含要显示的全明星变化的spritesheet。

复制像素从spritesheet到显示画布比执行绘图命令更快。绘制圆弧的地方尤其如此,因为在圆周上必须计算许多点。

重要!

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

然后使用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 
...