[F8] Looking for some Particle effect generator speed tips
Flash 8, AS2
So, this was just a goof around project at first, but now I have come up with a game idea that I like that uses it.
I've got lots of particles on the screen at once, hundreds, I have not taken the effort to count yet.
When the action gets heated, my fps drop to about 20. This isn't really that bad and it is still quite playable, but I would like to make improvements.
Things I have done so far:
1) Removed as much code from the particle enterframes as possible. They just update and check collisions if they are particles that can collide.
2) Collision checks were KILLING me so I made the stage into a grid and assigned each grid an array that stores the collidable things in that region of the stage, the particles now check what region they are in and just check collision with those objects (usually none). No hittests, just simple xy comparisons.
3) _quality = low.
4) storing PI as a root level variable, instead of recalculating it a million times
5) surprisingly, _root._width and _root._height seem really slow to check a bunch every frame. Storing them in as variable at the root level worked MUCH faster.
Things that disapointed me:
Originally my particles were tiny little 10px x 10px symbols and I figured there was a lot of overhead in redrawing the symbol.
I changed my particles to BitmapData objects on movieclips instead and expected a jump in fps, I was pretty surprised that the FPS didn't BUDGE. I get MAYBE 2-3 fps more in the worst case scenarios.
Am I missing any obvious tricks? Anyone know why the symbol - bitmap move didnt show any fps increase? I wasn't even using cacheAsBitmap before.
Wait so you have bitmapdatas inside movieclips? No wonder you didn't see any speed increase, you didn't really change anything as you still have hundreds of movieclips eating resources.
You're supposed to draw the bitmapdata objects on a single bitmap and display that.
If the particles are small enough and move fast enough I found best speed by using bitmapData.fillRect. Probably most speed increase would still come from going to AS3...
Wait so you have bitmapdatas inside movieclips? No wonder you didn't see any speed increase, you didn't really change anything as you still have hundreds of movieclips eating resources.
You're supposed to draw the bitmapdata objects on a single bitmap and display that.
Yeah, I know, but I still stink at using the BitmapData object. My brain just does not want to learn that for some reason.
And in theory it should have removed having to redraw the vector data on every frame for hundreds of objects, which I thought would have been a speed increase.
Might be time to try the whole particle effect generator as one big transparent bitmapdata over the rest of my stage. Could be fun to learn I guess.
So instead of movieclips, the particles would just track themselves as what? Objects with x, y, xpeed, yspeed, rotation, size, transparency etc... variables? Wouldnt all those object variables be just as much overhead as the movieclips or not?
Q, that test is a lot of sprites, but it runs really chuggy on my system, maybe 12 fps? I also can't open the fla, is that AS3? I am running flash 8 and as2.
I redid my emitters to instead make objects with velocity, x, y, variables, and pushed them into an array to track these objects,.
Once per frame I update all the object data and draw them to a fullscreen transparent bitmap with the .draw method.
Is this the right way to draw then onto the bitmap object? Is copypixels better?
How do you clear the stage after each frame? I decided to make the past events slowly fade away since I was looking for a fire effect on this particular emitter. So I did this every frame, letting the old objects fade away.
_root.bmpstage.colorTransform(_root.bmpstage.recta ngle, new ColorTransform(1, 1, 1, 1, 0, 0, 0, -10));
The problem is what runs at 43 fps with a ton of movieclips now runs at EIGHT frames per second drawing the objects to the bitmapdata in a loop. There is the same amount of calculation in each, actually less in the bitmap version. All collision testing is out of the bitmap version for testing.
Never read a good tutorial on this, so am I using the right methods? .draw to copy a bitmapdata object to my fullstage bitmap and a colorTransform on the fullstage bitmap to clear it each frame?
Excellent! Gotta learn these things. What is a decent way to clear the bitmap between frames?
I am using colorTransform right now with the alpha add at -255 if I want to wipe it, and less than that if I want a fade effect. Thinking of adding some kind of blur as well to each frame if the copy pixels does the trick.
Draw must be awful slow, because the movieclip method is destroying it for speed, and that is with twice the number of emitters and the collision logic running.
To clear the bitmapdata object each frame, use fillRect.
To increase your particle performance even more, use an array of objects, and loop through them with a single onEnterFrame event rather than onEnterFrames for each particle.
Hrm. Just seeing that you can't rotate the image with copy pixels. Not sure if that will work for me. The emitter looks goofy if all the non circular particles coming out have the same alignment. I'll try it tonight and see if the speed blows me away.
To clear the bitmapdata object each frame, use fillRect.
Will fillRect work with a fully transparent bitmapobject? Won't putting a fully transparent rectange on it just do nothing?
Originally Posted by JerryScript
To increase your particle performance even more, use an array of objects, and loop through them with a single onEnterFrame event rather than onEnterFrames for each particle.
The array of objects is what I did for my bitmapdata test, and with half the emitters and no collision detection my fps tests dropped from 40ish to 8. But I was using draw, I will try copy pixels tonight, but the loss of rotation is almost a deal breaker.
Will fillRect work with a fully transparent bitmapobject? Won't putting a fully transparent rectange on it just do nothing?
You aren't putting a rectangle on it. Using fillRect doesn't apply a color over the existing color (nor does it add or blend), it changes the color to the new one.
You can rotate by using a matrix transform when you draw, but then you are applying the rendering engine again in an intermediate step, and that will affect performance a bit. If you need rotations quickly, use a sprite sheet with the rotations applied to the individual sprites on it, and copyPixels.
Make sure your loop is optimized, local vars, for in, no object calls, etc. Without the vector rendering engine, you should see an increase in performance of at least 10x by using only sprites and bitmapdata.