If you check the HaxeFlixel’s particle demo page, you can see some basic examples of particle usage. In this tutorial, we’ll cover the following sections:
- Create default particle emitter
- Adding custom image
- Animating custom image
- Adjusting particle properties
Setup
Let’s create a new HaxeFlixel template project as usual:
1 |
flixel tpl -n "MyParticleTest" |
For assets, we can use any image for testing custom particle images, so let’s go for Julien’s Sparkles spritesheet. Download the zip and extract the sparkle.png into your /assets/images folder.
Introduction
Particles are generated from emitters. As such, you only need to check the API pages for FlxParticle and FlxEmitter for more info on how to implement particle effects. In a nutshell, you need an emitter (FlxEmitter) to “emit” particles (FlxParticle).
Default Particle Emitters
Following the code from FlashGameDojo (it’s in ActionScript 3, but it’s very similar to Haxe anyway) — here’s the most basic code to write an emitter:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
package; import flixel.FlxState; import flixel.FlxG; import flixel.effects.particles.FlxEmitter; import flixel.effects.particles.FlxParticle; class MenuState extends FlxState { override public function create():Void { super.create(); // Create an emitter at [200,100] position var emitter = new FlxEmitter(200, 100); // Remember that emitters are just FlxGroups // that help you recycle particles for repeated // usage. As such, we need to add the particles // into the emitters before we can use them. for (i in 0 ... 5) { var p = new FlxParticle(); p.makeGraphic(2, 2, 0xFFFFFFFF); p.exists = false; emitter.add(p); } // Add emitter to stage add(emitter); // Start emitter as non-explosion, at a rate // of 1 particle every 0.1 seconds. emitter.start(false, 1, 0.1); } override public function update():Void { super.update(); } override public function destroy():Void { super.destroy(); } } |
And when you build with lime test neko , you see the result:
You may notice the default white particles emitting correctly, but there seems to be a problem — the default HaxeFlixel logo gets emitted too. What went wrong?
Note that the white particles are the 2×2 pixel white squares we wrote in the p.makeGraphic(...) line above. We only created 5 particles for the emitter in the loop. Since the emitter needs to emit 1 particle per 0.1 second, it will run out of particles in its pool after 0.5 seconds. As a result, it generates its own FlxParticle objects that do not have a default image — resulting in the logo.
So the easiest fix is to adjust the loop to add more particles, from 5 to say, 15 or 20, so we’ll never run out of particles:
1 2 3 4 5 6 7 8 9 10 11 |
// Remember that emitters are just FlxGroups // that help you recycle particles for repeated // usage. As such, we need to add the particles // into the emitters before we can use them. for (i in 0 ... 20) { var p = new FlxParticle(); p.makeGraphic(2, 2, 0xFFFFFFFF); p.exists = false; emitter.add(p); } |
And now it looks fixed:
Custom Particle Images
To add custom images to particles, you just need to load a graphic during particle creation:
1 2 3 4 5 6 7 8 9 10 11 |
// Remember that emitters are just FlxGroups // that help you recycle particles for repeated // usage. As such, we need to add the particles // into the emitters before we can use them. for (i in 0 ... 20) { var p = new FlxParticle(); p.loadGraphic("assets/images/sparkle.png", false, 32, 32); p.exists = false; emitter.add(p); } |
Just note the size of each sprite in the spritesheet. In the case of sparkle.png, each frame is 32×32. Now when you test, the sparkle image is used:
It’s a little too small to see, but that’s the default size of the first sparkle frame’s image anyway.
Animating Particles
To animate the particles, you just need to add animation during creation, exactly like how you would for FlxSprites:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// Remember that emitters are just FlxGroups // that help you recycle particles for repeated // usage. As such, we need to add the particles // into the emitters before we can use them. for (i in 0 ... 20) { var p = new FlxParticle(); p.loadGraphic("assets/images/sparkle.png", false, 32, 32); p.animation.add("my-sparkle", [0,1,2,3], 10, true); p.animation.play("my-sparkle"); p.exists = false; emitter.add(p); } |
And the output:
Okay, using what we’ve learned so far, let’s try different examples on how to use the emitter:
- Fire smoke trail
- Explosion
- Explosion with particle gravity
Fire Smoke Trail
We’re going to create smoke puffs that goes upwards, slowly fading away. Among the attributes we set include alpha fading, color fading, and size changing, and particle origin jitter:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
override public function create():Void { super.create(); // Set the background color for visibility sake FlxG.camera.bgColor = 0xFFFF6666; // Create an emitter at [200,100] position var emitter = new FlxEmitter(200, 200); // Remember that emitters are just FlxGroups // that help you recycle particles for repeated // usage. As such, we need to add the particles // into the emitters before we can use them. for (i in 0 ... 100) { var p = new FlxParticle(); p.makeGraphic(10, 10, 0xFFFFFFFF); // p.loadGraphic("assets/images/sparkle.png", false, 32, 32); // p.animation.add("my-sparkle", [0,1,2,3], 10, true); // p.animation.play("my-sparkle"); p.exists = false; emitter.add(p); } // Add emitter to stage add(emitter); // Set radius around origin where particles will appear emitter.setSize(25, 25); // Set particle's range of x/y directional speed emitter.setXSpeed(-20, 20); emitter.setYSpeed(-100, -200); // goes upwards // Set particle to fade opacity as it goes upwards emitter.setAlpha(1,1,0,0); // Set particle to fade color as it goes upwards emitter.setColor(0xFFFFFFFF, 0xFF000000); // Set particle size (scale) range, and grow larger as it fades emitter.setScale(0.5, 1, 2, 2.5); // Start emitting at 1 particle per 0.02 seconds emitter.start(false, 1, 0.02); } |
And here is the result:
One thing I excluded was setting the rotation — by default, particles will rotate randomly. But if you don’t want particles to rotate, just set it like this:
1 |
emitter.setRotation(0,0); |
Explosions
Explosions are the default behaviour of FlxEmitter — as demonstrated at the beginning of this tutorial. Referring to the API, the emitter’s default start function only “emits” the explosion once, like this:
1 |
emitter.start(); |
Explosions With Particle Gravity
This is demonstrated in the Particle demo page — it’s as easy as adding gravity to the emitter:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
override public function create():Void { super.create(); // Set the background color for visibility sake FlxG.camera.bgColor = 0xFFFF6666; // Create an emitter at [200,100] position var emitter = new FlxEmitter(200, 200); // Remember that emitters are just FlxGroups // that help you recycle particles for repeated // usage. As such, we need to add the particles // into the emitters before we can use them. for (i in 0 ... 100) { var p = new FlxParticle(); p.makeGraphic(10, 10, 0xFFFFFFFF); // p.loadGraphic("assets/images/sparkle.png", false, 32, 32); // p.animation.add("my-sparkle", [0,1,2,3], 10, true); // p.animation.play("my-sparkle"); p.exists = false; emitter.add(p); } // Add emitter to stage add(emitter); // Add gravity to each particle emitter.gravity = 800; // Start emitting at 1 particle per 0.02 seconds emitter.start(false, 1, 0.02); } |
And the result:
Note the code above assumes we’re emitting the explosion in 0.02 second intervals. If you only want to do it once, set the interval to 0 instead of 0.02
One last thing — to stop the emitter, just do this:
1 |
emitter.kill(); |
Closure
Particle effects can be easily added to the game using FlxEmitter. The most common usage is explosion and smoke.
One example is “bursting coins out of a treasure chest”, where the emitter “emits” a single burst of coins. If you want an example of how to do this, check out PhotonStorm’s excellent Collectible Particles tutorial.
Check out his other Flixel tutorial series, they’re very helpful! They’re in ActionScript 3, but still relevant.
This concludes the tutorial on HaxeFlixel particles and emitters.
This site was… How does one say it? Applicable!! Ultimately I’ve found something which helped me. Lots of many thanks!
http://relocating05925.mybloglicious.com
Hello
YOU NEED QUALITY VISITORS FOR YOUR: coinflipstudios.com ?
WE PROVIDE HIGH-QUALITY VISITORS WITH:
– 100% safe for your site
– real visitors with unique IPs. No bots, proxies, or datacenters
– visitors from Search Engine (by keyword)
– visitors from Social Media Sites (referrals)
– visitors from any country you want (USA/UK/CA/EU…)
– very low bounce rate
– very long visit duration
– multiple pages visited
– tractable in google analytics
– custom URL tracking provided
– boost ranking in SERP, SEO, profit from CPM
CLAIM YOUR 24 HOURS FREE TEST HERE=> ventfara@mail.com
Thanks, Randy Degotardi
Great tutorial, would be cool if you could update for the latest HaxeFlixel (4.0) version though, as it’s not really clear what was refactored. Thanks!
Hey there, thanks for reading. I haven’t used HaxeFlixel for a while (no plans to get back to it yet), so I won’t be updating this article yet. Sorry! 🙁
Hi, it’s a very nice and simple tutorial. But I have a little problem with it: when I’m using the simple explosion particle several times, the game starts lagging like crazy each time the explosion is launched.
I must assume that the particle emiter is not killed properly, so maybe I should use emitter.kill() … But when do I know when to use it? Thanks for your help!
Hi Ats! I’m not sure what the problem is, but here’s a stab in the dark: Were you testing on Flash? Scaling is bad for performance on Flash targets, as noted on the API page (http://api.haxeflixel.com/flixel/effects/particles/FlxParticle.html#useScaling), so you may want to disable that.
If that wasn’t the problem, then I guess: If you only have one emitter that you want to re-use, then just kill() it when you don’t need it, then do a .start() on it.
I hope this helps! Do elaborate if your problem persists 🙂
Thanks for your help. I use my emiter several times (and often at the same time) for explosions. Lots of explosions.
I’m on HaxeFlixel latest git. After a few explosions at the same time, each explosion takes an exponential amount of time to work, until the flash player freeze with a kill process message.
I’d gladly try .kill/.start but I don’t know when to use it because I don’t know when the explosion is finished and all particles have vanished.
Maybe i should create several emitters instead of using the same?
Hi Ats,
When I tested on my sample project (using white squares for the particles only), each particle is 1 draw call; so if there are multiple explosion particles, e.g. 100 per explosion, then 10 explosions will invoke 1000 draw calls, which will slow/freeze the flash player no matter what.
If you only want to achieve an explosion effect, I think the easiest solution is to just use _emitter.start(true); (no need to use _emitter.kill).
I think using one emitter for multiple explosions is fine (but don’t take my word for it!).
Ok, I’ve found the problem:
You have to specify the maximum number of particles the emitter can store at his creation:
var emitter = new FlxEmitter(200, 100, 100);
Then everything is fine 🙂
A hint if you use the latest dev version of HaxeFlixel on github: things like emitter.setAlpha() or emitter.setColor() don’t exist anymore. Instead you have to use emitter.alpha.set() and emitter.color.set(), as those members are now special range types.
Hi ratking, thanks for the heads up, I appreciate it! 😀 I think your comment is enough as an addendum, so I won’t update the post (yet).