2011-05-17 59 views
2

我剛開始學習flash/actionscript 3,並決定編寫一個簡單的粒子模擬器。在Flash中重繪數百個粒子的有效方法?

非常最初的設計只涉及與從光標如果你點擊撒走了buncha顆粒填充屏幕。

這個工作,但有點反應遲鈍。我使用graphics.drawCircle()繪製粒子,每個粒子都從Sprite繼承。

監聽器鼠標點擊事件:

private function mouseClick(e:MouseEvent):void 
{ 
    trace("click"); 
    var now:Date = new Date(); 
    trace("Before: "+now.getTime()); 
    for each (var p:Particle in particleList) 
    { 
     var dist:Number = distance(e.localX,e.localY,p.x,p.y); 
     if (dist < 50) 
     { 
      var xVel:Number = p.x - e.localX; 
      var yVel:Number = p.y - e.localY; 

      xVel *= Math.max(0,50 - dist) * 0.05; 
      yVel *= Math.max(0,50 - dist) * 0.05; 
      p.xVel += xVel; 
      p.yVel += yVel; 
     } 
    } 

    var later:Date = new Date(); 
    trace("After: "+later.getTime()); 
    trace("Total: "+(later.getTime()-now.getTime())); 

    //e. 
} 

顆粒,有運行此每一幀的幀監聽器:

public function loop(e:Event):void 
{ 
    if (xVel != 0 || yVel != 0 || setup) 
    { 
     setup = false; 
     x += xVel; 
     y += yVel; 


     if (x < 0) 
     { 
      x = 0; 
      xVel = - xVel; 
     } 
     if (x > stageRef.stageWidth) 
     { 
      x = stageRef.stageWidth; 
      xVel = - xVel; 
     } 
     if (y < 0) 
     { 
      y = 0; 
      yVel = - yVel; 
     } 
     if (y > stageRef.stageHeight) 
     { 
      y = stageRef.stageHeight; 
      yVel = - yVel; 
     } 


     graphics.clear(); 
     graphics.lineStyle(.25,0xFFFFFF,0.5); 
     graphics.drawCircle(0,0,1); 

     xVel *= Engine.friction; 
     yVel *= Engine.friction; 
    } 

    if (xVel < 0.01 && xVel > -0.01) 
    { 
     xVel = 0; 
    } 

    if (yVel < 0.01 && yVel > -0.01) 
    { 
     yVel = 0; 
    } 
} 

我應該如何使這種更有效率?我打算以後再做碰撞檢測和其他物理交互,即使沒有我打算稍後添加的大量數據處理代碼,這個速度已經有點慢了。

+0

恕我直言,最快捷的選擇是從@礁的答案setPixel方法。如果你需要更大的粒子,你可以爲每個像素設置三個/四個/任何像素。但是如果粒子真的很大,使用'BitmapData.draw'。 – alxx 2011-05-17 10:36:50

回答

3

使用圖形是太多的形狀......沒有在你的代碼,你可以嘗試,每一幀,畫出你的形狀在一個BitmapData太大的變化相當緩慢(無論是先畫他們在一個單一的形狀,或在許多形狀,然後使用BitmapData繪製,然後清除所有圖形)。我認爲你應該得到一點改善。基本碼是這樣的:

for(...) { 
    shape.graphics.drawCircle(0,0,1); 
} 
bitmapData.draw(shape); 
shape.graphics.clear(); 

在另一方面,我知道1個像素顆粒的最快方式是使用的BitmapData和setPixel每個粒子:

bitmapData.fillRect(bitmapData.rect, 0); 
bitmapData.lock(); 
for(...) { 
    bitmapData.setPixel(x,y,0xFFFFFF); 
} 
bitmapData.unlock(); 

對於更大或更復雜的顆粒,我聽說copyPixels是要走的路,但你需要blitt所有不同顆粒的事前(我沒有太多的經驗,這一次,雖然,我發現很多情況下,當它已經更好地使用位圖數據繪製,或甚至具有不同的子畫面位圖數據的每個):

bitmapData.fillRect(bitmapData.rect, 0); 
for(...) { 
    bitmapData.copyPixels(myParticle10, myParticle10.rect, new Point(tx, ty)); 
} 

我希望這有助於。

+1

copyPixels只適用於長方形,不是嗎?如果粒子具有透明邊緣,則必須繪製,而不是僅複製。 – alxx 2011-05-17 08:51:23

+0

是的,你是對的:) – Cay 2011-05-17 09:10:34

+0

我應該只有一個bitmapdata實例嗎?每個粒子沒有一個 – 2011-05-17 15:19:55