Question

I am just starting to learn flash/actionscript 3 and decided to code up a simple particle simulator.

The very initial design simply involves filling the screen with a buncha particles which scatter away from the cursor if you were to click.

This works, but is a bit unresponsive. I am using graphics.drawCircle() to draw the particles, and each particle is inherited from Sprite.

Listener for mouseclick event:

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.
}

In Particle, there is a frame listener that runs this every frame:

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;
    }
}

How should I make this more efficient? I plan on doing collision detection and other physics interactions later, and this is already a bit slow even without the hefty number crunching code I intend to add later.

Was it helpful?

Solution

Using graphics is quite slow for too many shapes... Without much change in your code you could try to, each frame, draw your shapes in a BitmapData (either draw them first in a single shape, or in many shapes, and then use BitmapData draw followed by clearing all your graphics). I think you should get a small improvement. The basic code is this:

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

On the other hand, the fastest way I know for 1 pixel particles is using BitmapData and setPixel for each particle:

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

For bigger or more complex particles, I've heard copyPixels is the way to go, but you need to blitt all of your different particles beforehand (I don't have much experience with this one though, and I've found many situations when it has been better to use BitmapData draw, or even having each bitmapData in a different sprite):

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

I hope this helps.

OTHER TIPS

The best and fastest way to have a huge number of particles in Actionscript is to blit them to a bitmapdata. I'm kind of a nut for particles, and I really like this method. Here is a tutorial about how to do it, with a cool looking particle effect clock.

http://plasticsturgeon.com/2010/08/make-super-cool-as3-particle-effects-for-flash-games-with-bitmapdata/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top