Advertisement
  1. Code
  2. Effects
Code

Create a Sparkling Bomb Mouse Cursor with FLiNT Particles

by
Difficulty:IntermediateLength:LongLanguages:

This is a beginner to intermediate level tutorial in which I will explain the basics of the FLiNT particle system. We'll also take a look at how to create a sparkling bomb mouse cursor. It's something I created and used in a memory game which you can check out here if you're curious.

I'm assuming you have knowledge of ActionScript 3.0, basic object oriented programming and setting up the classpath. This is all knowledge that easily can be found on Activetuts+ however, so don't be discouraged if you don't know it all just yet.

With that said, let's start making particles!

What is FLiNT?

The FLiNT particle system is a library written in ActionScript 3 by Richard Lord. It is released under the MIT license and it is open source. In other words, Mr.Lord is doing us all a huge favor.

The project's webpage is here: http://www.flintparticles.org/.

ASDocs can be found here: http://flintparticles.org/docs/. This page is a must have. I suggest you go there a few times to get to know the layout of all the classes a bit better. Seriously, use this page. There will be times when you can follow this tutorial fine without it, but as soon as you want to know the exact details of a class constructor or similar, you must go here and read up on it.

So, what does it do? It is simply a way to create particles. Particles can be anything from a pixel - or possibly fractions of a pixel - to larger bitmaps. The great thing about FLiNT is the numerous ways you can create and manipulate these particles. FLiNT even supports rendering particles in 3D, supporting both Papervision 3D and Away3D.

Ultimately FLiNT is a programmatic design tool. The best results, in my opinion, are achieved when you visualize the outcome of the effect you want to create by perhaps drawing it in photoshop. After that you simply convert it into code. To do that, however, you must of course know where to start.

Check out the FLiNT examples page for a scratch on the surface of what is possible with FLiNT: http://flintparticles.org/examples.

Also, I want you to check out a terrific example of how to successfully use this as a design tool. A french MMORPG called "Dofus" with production status unknown has this on their blog, using FLiNT: http://devblog.dofus.com/fr/billets/52-lumiere.html. So simple, yet stunningly beautiful!

Preparations and Setup

I'll be working on the code for this tutorial using FlashDevelop. If you don't know what it is or haven't tried it yet I suggest you do. Not only is it an amazing tool, it's also free of charge so you really have nothing to lose. If you're using Flex/Flash Builder or Powerflasher FDT I'm guessing you'll have no trouble following along with this tutorial.

If you only wish to work with the Flash IDE and perhaps some other text editor of your choice you can still follow along without any problems at all. Just make sure you understand how things work when you set a document Class instead of working with code on the timeline.

Since we're dealing with a library of code you will need to set up your classpath correctly.

Download FLiNT from here: http://code.google.com/p/flint-particle-system/downloads/list. At the time of writing this tutorial the latest version is 2.1.2. Go ahead and download either the swc library files or the source code. I'll be using the SWC files and importing them into my FlashDevelop project. Using SWC files of pure code (no regular Flash "components") is only supported in Flash CS4 however, so make sure you use the regular source code if you're on CS3.

Should this page ever change you'll always find links to the latest download on the main FLiNT project page.

Step 1: Create a New Project

First off, create a new Flash AS3 project in the Flash IDE. Make it 600x400 pixels, 30 FPS and set the background color to something darkish gray, like #4A4A4A. Set the document class to Main.

Save this project in the folder you will be working in.

In FlashDevelop, create a new Flash IDE Project. Type in a package name if you're inclined, this tutorial will however only involve a couple of classes so there's no need for tidy organising.

Save this project in the same folder as the fla you just created to have the Flash project find the Main class.

In FlashDevelop, create a new class Main, have it extend Sprite. This is what my Main.as class looks like at the start:

If you haven't already, now would be a good time to set up the classpath and put the org.flintparticles files into it.

Step 2: Creating Our on/off Button

There's a good reason for creating this button. Chances are that you come across situations where you want to control where and when you start and stop your particle effects. Perhaps you're making a shooting game and you want some particles from the muzzle of a gun show whenever it's fired. If I show you the way to control it with a button you can most definitely solve it the way you prefer in your own project later on.

In Flash, bring out the components panel and drag out a Button component onto the stage, placing it in the upper middle, like so:

Give it an instance name of 'button'. Use the component inspector to change the label to "Show/hide effect".

Inside our Main.as we have to import the MouseEvent class, add a click listener to the button and write a listener function that responds to the click. Our Main.as should look like this:

Test the movie and make sure clicking on the button traces out the message.

Step 3: Creating a Toggle Class

Create a new class called MyParticles.as in the same directory as the Main class. Have it extend Sprite as well. In the Main class, create a variable myParticles of type MyParticles and instantiate it, then add it to stage. Also set it's mouseEnabled property to false. Otherwise the renderer in the particle class will block clicks on our toggle button.

Our plan is to have the MyParticles class contain everything FLiNT related in this tutorial. It will also have a public start and stop function, plus a 'isRunning' Boolean variable that is either true or false depending on the particles being alive or not. Our onButtonClick function can then check if it is running and ask it to start or stop depending on its state. The Main.as should look something like this:

Let's also not forget to set up the start and stop functions in our MyParticles class. Also we should set a public getter isRunning. Like so:

Test the movie to see that the toggling works as it should.

The Anatomy of the FLiNT Particle System Part 1

Let's focus on the theory for a bit and look at how the FLiNT system works.

The absolute minimum of elements required to display some particles are:

  • The renderer
  • The emitter
  • The counter
  • The particle initializer
  • The position inititalizer

The Renderer

The renderer is what draws the particles on the screen. At the time of writing this tutorial, the current FLiNT version has five different 2D renderers:

  • BitmapRenderer
  • DisplayObjectRenderer
  • PixelRenderer
  • BitmapLineRenderer
  • VectorLineRenderer

They work in different ways, but how they work differently is a topic I won't cover in detail. Suffice to say that the BitmapRenderer draws to a single Bitmap and then updates it, which tends to be generally faster than the DisplayObjectRenderer which lets Flash update each particle by itself as different objects. For this tutorial we will only use the BitmapRenderer.

The renderer extends SpriteRendererBase which in turns extends Sprite. This brings us to the visual flow of our tutorial:

  • Main document class is our stage
  • We add our sprite-extending 'myParticles' to the stage using addChild
  • The MyParticles class adds the renderer to its own display list using addChild
  • In MyParticles we will let the renderer add our emitter to itself (the renderer)
  • The emitter emits particles inside the renderer which in turn adds these to the display list

The Emitter

There are only two emitters, one for 2D and one for 3D. The emitter is exactly what it sounds like; an object that emits particles onto its parent renderer. You can add actions, activities and initializers to the emitter. More on that later.

An emitter is added to a renderer to be displayed. A renderer can have multiple emitters, and an emitter can be added to multiple renderers.

The Counter

An emitter needs a counter to emit particles. It's what decides when and how many particles to emit. For example:

This would add a Steady counter to the emitter. The Steady counter emits x amount of particles (50 in our case) every second. The particles are emitted evenly over the second. The Pulse counter will emit particles at a set interval. Another useful counter is the Blast which emits particles but only once. Useful when you need an exploding effect.

The Particle Initializer

We need to add a particle initializer to the emitter for it to have something to emit. The particle initializers are:

  • SharedImage
  • SharedImages
  • ImageClass
  • ImageClasses

SharedImage and SharedImages are most efficient when used with the BitmapRenderer. The others are better suited for the DisplayObjectRenderer. The difference between SharedImage and SharedImages is that the second initializer supports multiple images. You add the images to an array which goes to the initializers constructor, and you can add an optional "weight" array that decides what priority to give the images when randomizing them. Same thing with ImageClass and ImageClasses.

The Position Initializer - Zones

The emitter needs to know where to place particles. This is done by adding a Position initializer. The Position initializer takes a Zone in its constructor. The emitter will then add particles at random positions within the zone. There are several types of zones, I'll mention a few here:

  • PointZone
  • LineZone
  • RectangleZone
  • DiscZone
  • MultiZone
  • BitmapDataZone

The point zone is exactly what it sounds like; it takes a Point object in its constructor and will only make particles appear at that point. The LineZone takes two Point objects and will create particles along the line created between the two points. The RectangleZone emits particles within a Rectangle, the DiscZone emits particles within a circle. The MultiZone puts several different zones together and make it act like one.

The BitmapDataZone is my favorite zone because of its special ability: It takes a BitmapData object and makes particles appear within any pixel of that BitmapData that isn't transparent. In other words, you can take an image and use as a blueprint of where you want pixels to appear.

There are of course other ways to achieve this, like with the GreyscaleZone which acts similarly to the BitmapDataZone. The difference is that it gives pixels different weighting; different probability to have a particle spawn at that pixel. Black pixels never spawn any particles, but any others do, and the lighter they are the higher the chance of having a pixel spawn there.

Hopefully you can see the incredible flexibility and power of the FLiNT particle system, and this is just scratching the surface! Now pat yourself on the back for coping with that amount of information. Let's get back to work!

Step 4: Importing the Necessary Classes

In this short step we'll just import the following classes:

It's easier if we import all of them now rather than one by one as we go along.

A word of caution: If you use FlashDevelop you might get some problems with the auto-importing. I've had trouble where I type out a specific initializer or renderer type which exists both as 2D and 3D versions and let FlashDevelop import that class. Make sure FlashDevelop has imported the 2D version if you're using 2D, and vice versa with 3D! The reason for this is that many classes have the same name in both the 2D and 3D packages.

Step 5: Creating the Renderer

We need to create a renderer to display our particles in our MyParticles class. Add a private variable 'renderer' of type BitMapRenderer.

Instantiate it like this:

The constructor of the BitmapRenderer takes a Rectangle as its canvas. This is the canvas the renderer is allowed to draw upon. Particles can exist (and draw CPU power) both in and outside the canvas, but will only be displayed within the bounds of the canvas. By defining the Rectangle as 600 by 400, and x/y as 0/0, we essentially create a canvas the size and position of our stage. The larger the canvas, the more performance is required, so generally try to keep the size as small as possible for the desired result.

The constructor has a second optional parameter 'smoothing' which is the same kind of smoothing you might recognize from the Bitmap class, or the properties of an image imported into the library in the Flash IDE. The smoothing defaults to false and we won't deal with it any more in this tutorial, but it's good to know where to access it.

Finish up by adding the renderer to the display list by calling addChild. Our class MyParticles should now look like this:

Step 6: Creating the Emitter, Counter and Initializers

Create a private var 'emitter' of type Emitter2D and instantiate it. Also set the counter property of the emitter to a new Steady with 50 particles per second, like this:

Now we'll look at the SharedImage initializer. This initializer is what defines what the actual particles that we will generate looks like. I'll show you the code to write first:

As you can see, an emitter has a function called addInitializer which takes an object 'Initializer' as the parameter. The SharedImage extends the InitializerBase class which implements the Initializer interface.

The SharedImage initializer takes a DisplayObject as the constructor parameter. Here we give it a new Dot. The Dot class is part of the FLiNT library and it is simply a small dot display object that extends Shape. The Dot constructor takes a Number which is the radius of the dot, and it defaults to 1. FLiNT comes with a few different display object classes that are very useful in many cases. Please note that it is possible to add other images from your flash library. It is even possible to add animated MovieClips as particles and have them animate as they spawn. The possibilities are virtually endless!

Next, we'll add the position initializer and a zone like this:

We define the LineZone with two Point objects, and the x/y values of these points make out the line.

Lastly, a very important step is to add the emitter to the renderer:

Our class should now look like this (showing only class members and constructor):

Step 7: Starting our Particle Engine

Since we've already set up the public start and stop functions we can now easily wire this up to the particle system so we can finally start seeing some particles.

In the start function, simply add emitter.start(); - and in the stop function add emitter.stop();. Could it get any easier?

You should now have a particle system that can activate and deactive by the press of the toggle button:

Not that fun to look at yet though, is it? We have a line where the emitter emits dots indefinitely until either the end of time or when your CPU fries, whichever comes first. Speaking of CPU power, try temporarily setting the Steady counter to 5000 instead of 50. When you try this out you should notice extreme CPU usage. Either try it or take my word for it and consider that you have to plan out how your particles will be used so they don't end up crashing your flash application.

Ok, enough of the boring responsible talk, let's think of some quick improvements and get them done:

  • We could use some movement on the particles to spice things up
  • We need the particles to die out after a while and not live indefinitely
  • We could make the particles look different from each other to add more variety
  • To add even more variety we could make the particles change over time

To accomplish all these changes we need to add both initializers and actions. Let's take a look at some more theory. Don't worry, this time it will be shorter.

The Anatomy of the FLiNT Particle System Part 2

When we want to add or change something in our particle system it is a matter of adding initializers and actions. Quoting the FLiNT documentation:

A particle system in Flint is created by combining emitters, counters, initializers, actions, activities and renderers.

Actions

You already know about emitters, counters, initializers and renderers. Initializers control how particles are initialized. Actions affect the particles over time. Have a look at the list of 2D actions in the documentation, there is a ton of different kinds of actions available. There's also a few in the common package. Here are a few important ones that are good to know about:

  • Accelerate - Adds a constant acceleration to the particles.
  • Age - Makes particle age, more on this later.
  • BoundingBox - Use this to keep particles inside a defined area, making sure they don't escape out of it.
  • Fade - Makes the particle fade its alpha over time.
  • Friction - Just what it sounds like. Use this to slow the particle down as it moves.
  • Linear/QuadraticDrag - These also slow the particle down, but with a force proportional to the speed of the particle. Compare to friction which slows the particle with a constant force rather than proportional.
  • Move - This is an essential action. It must be added to update the particles position. Without it, your particles wont ever move!
  • RandomDrift - An action for special use cases, but one of my favorites. It makes the particle randomly drift in all directions within values you define yourself.
  • ScaleImage - Used to scale the particle in size, both increasing and decreasing.

Activities

Activities are like actions but for the emitter itself. There's only three 2D activities; FollowMouse that makes the emitter follow the mouse, MoveEmitter that moves the emitter at a set velocity, and RotateEmitter that simply rotates the emitter. Nothing too hard in this department!

ZonedAction; a Smart Action

The ZonedAction takes both an Action and a Zone in its constructor. What it does it really great - it applies an Action to particles, but only if they're within the Zone. Want to create a waterfall? Have your particles move towards the drop, and at the drop you have a zoned action to make the water accelerate downwards. With this Action you become somewhat of a director.

Let's get going on those changes!

Step 8: Making the Particles Move

This should be easy as pie now. Since we know the particles will have to move, we start by adding the Move Action. We can set an initial speed with an initializer, add some negative acceleration and top it off with some random drifting, like this:

Already we're taxing the CPU quite heavily, so feel free to drop the Steady counter down to 10 or 20, or more if your computer is up to the challenge.

Explanation of the code we just wrote:

The Move action speaks for itself.

The Velocity initializer takes a Zone in it's constructor. We feed it a Point with negative 150 pixels in the y-axis, which becomes the velocity of each individual pixel. The Velocity initializer uses a random point within the zone you define. In the case of a Point it can only be that point. And it is really important to note here that the Zone defined is in the perspective of the particle - not the emitter or the renderer or anything else. If you want to control the exact velocity of the particles, use a PointZone. For more random behaviour, use something bigger. A LineZone can often be sufficient for some randomness, but a RectangleZone would enable even more random behaviour.

The Accelerate action also kind of speaks for itself - we tell it to constantly accelerate with a value of positive 45 in the y-axis, so down it goes.

The RandomDrift is also easy to grasp - you define the maximum amount to drift in both x and y-axis.

Our MyParticle.as constructor should now look something like this:

Before going to the next step, feel free to try and comment out the different actions/initializer to see how they act individually.

Step 9: Killing our Particles

Since we know the particles draw CPU power if they're never removed, we now need a way to remove them. There are a few ways to do this:

  • Using the DeathZone action. Create a Zone and feed it to a DeathZone Action object and it will kill any particle entering that zone.
  • Using the DeathSpeed action. You can define a speed limit which kills particles whenever they cross it.
  • My prefered way, in this case - The LifeTime initializer and the Age action. The LifeTime simply sets the lifetime of the particle. Like the Move action is needed to actually move the particles, so is Age needed to make the particles age and finally die at the end of their lifetime. This is also needed when you use the Fade action.

Let's go with the LifeTime initializer and Age action, like this:

This simply removes the particles after 5 seconds of life. The effect isn't that pretty, so let's throw in the Fade action:

Already looking a lot better! If you've done any tweening work you might be thinking "I'd sure like to apply a different easing to that fade!". Ok maybe you're not thinking exactly that, but I'm thinking that, because I know just how awesome FLiNT is - you can apply different easings to the Age action in its constructor! Change our previous Age line of code to this:

This easing keeps the particle in "good health" a lot longer and quickly fades out in the end. If you're browsing around the packages you might've noticed this is part of the energyEasing package. These easings are modified forms of Robert Penner's easing equations specifically for the Age action. There is also a package called just easing which are easings made for the TimePeriod counter.

Step 10: Creating Different Particles

Right now we have particles that move in a defined pattern with some random variation and they eventually fade out and die. Let's spice things up by adding different kinds of particles to our emitter, with different colors!

What we'll do is create four different kinds of particles and use the SharedImages initializer instead of the SharedImage initializer. Notice the lack of an 's' on the end there. The cool thing about it is the optional weight array I mentioned in the first theory section in this tutorial. It is simply an array that the initializer reads from. For example, the first element in the image array relates to the first element in the weight array. If the first element in the weight array has a value of 10, and the second a value of 1, then the first image in the image array will have 10 times better chance to be spawned than the second image.

We'll only be using FLiNT's own display object classes here. Also, please excuse my poor choice of colors. Go ahead and go to the line where you have the SharedImage initializer and remove it. In its place type in this:

So what are we doing here? We're creating two arrays, one to hold the images and one to hold the weights that correspond to the images. I could've separated the two in the code, but I put them on alternating lines to quickly see which weight relates to which image. Right now the Rect and RadialDot won't appear as much as the other two.

This is what the constructor looks like at the moment:

Step 11: Changing Particles Over Time

Now let's try and change the particles over time to add even more variety. We'll use a ScaleAll action to make particles change size over time. There is a ScaleImage action that we could use, but ScaleAll also scales the collision radius and mass. There are two actions - ChangeCollisionRadius and ChangeMass - that are used for this separately for this purpose if need be. We'll use a Collide to make particles collide with each other. Note however that this is not a physics engine and will not give you similar accuracy, rather it will focus on performance than an exact simulation. We'll use a RotateToDirection to make sure our Rectangles point where they are going. Finally, we'll add something really cool, the MouseGravity. Let's have a quick look at the ridiculously small amount of code:

Some things here are worth explaining. The ScaleAll follows the aging of the particle defined in the LifeTime initializer. Right now we ask it to scale from 100% at 'birth' to 500% at the end of the lifetime. Collide's parameter is the amount of energy kept after a collision, 1 being 100%. Setting it at 3 will produce results where particles gain more energy after colliding. Lastly, the MouseGravity has two parameters you should set and one optional. The first is how powerful the gravity is. The second one, "renderer", is a DisplayObject whose coordinates the mouse position is converted to.

This is the last step we're playing with this particle system, so I'd like to mention one very useful function in emitters - the runAhead function. You simply call this function on an emitter and define the time for the emitter to run ahead. This is useful when you have an emitter emitting particles that cover a large area and you don't want to wait for the particles to fill up the area. In this case you make it run ahead with this function. The function takes two parameters, time and FPS. Add this line of code under the emitter.start() function, in our public start function in our MyParticles class:

This will make our emitter run ahead for 5 seconds at 30 fps each time we start it, so the screen is already filled with particles when we start it!

Now, have a look at what looks a bit like a intergalactic battle which you can direct with the mouse.

This is what MyParticles.as looks like at the end of this first part of the tutorial:

And this is what our Main.as looks like:

End of Introduction - Start of Creating the Main Effect

What we've done so far is just toy around and add stuff to the particle system to get to know how to use it. It may not be very useful or pretty, but if you've gone through it you should have a better understanding of the relationship between emitters, renderers, initializers and actions.

There is still a ton of stuff to learn so make sure you use the documentation and experiment away.

So, remember the beginning of this tutorial? You were promised to learn how to turn the mouse cursor into a bomb with a burning fuse that uses FLiNT for particles. We'll dial up the tempo a whole lot for this part, now that you're adept FLiNT programmers after reading that lengthy introduction.

Step 12: Switching out our Mouse Cursor

First off we'll create a new class called AnimatedCursor. Let your Main.as point to this instead of the Myparticles class. Also, we don't want any mouseChildren since that will make our bomb graphic block any mouse click. We also need to update our cursor class with the mouse position. The code will look like this:

Secondly, we will let the AnimatedCursor class take care of switching out the mouse cursor with the bomb image. Import the bomb image into your Flash file and make it a MovieClip, which you export for ActionScript as "Bomb", as a Sprite. You should find the smallbomb.png in this tutorial's zip file.

The code for AnimatedCursor.as looks like this as we start off:

Step 13: Adding and Designing Particles

This is what we'll do:

  • Add a BlurFilter to our renderer.
  • Add a Steady counter with a value of 30
  • Create an image array and weights array to put into a SharedImages initializer
  • Create three Line objects and put them in the array, then add weights to the weights array
  • Add a ColorInit to get some yellow/reddish fire particles
  • Add a Velocity that is based on a DiscSectorZone
  • Add a LifeTime
  • Add a Position with a small offset to make sure particles spawn at the end of the fuse on the bomb image
  • Make the particles Age with a Cubic easeIn.
  • Add Move, Fade and RotateToDirection
  • Add our first Activity - the FollowMouse
  • When stopping our particles, clear out the bitmapData of our renderer to avoid straying fire blurs

Here's the code:

Try commenting out the fillRect function in the stop function to see how the blurred fire lingers after stopping the particle system.

You should understand most items dealt with here after our lengthy introduction, and if there's anything unclear you can go to the documentation to check out the specifics for each constructor etc.

One thing that might seem unfamiliar to you is the DiscSectorZone, or its constructor to be specific. The paremeters are:

  • center:Point - Here I just pass in a 0,0 Point since I do not want to change the center
  • outerRadius:Number - The outer radius of the disc
  • innerRadius:Number - The inner radius of the disc
  • minAngle:Number - The minimum angle in radians
  • maxAngle:Number - The maximum angle in radians

The zone is defined between the outer and inner radius, within the min and max angle. I did not do any degree to radian conversion in the code, instead just eyeballed it with radians since it works fine that way. Worth mentioning is that an angle of 0 equals horizontal to the right.

Guess what? We're finished! This is the end result, which you've already seen at the top:


End of Tutorial: Extra Challenge

If you've come this far you should know a lot more about FLiNT. Yet there's even more to learn. A good way to learn more is to challenge yourself. Being the kind writer I am, I therefore present you with an extra challenge - the smoking chimney!

The challenge is for you to try and copy this effect, or perhaps improve it. It's something I made when just toying around with FLiNT so it is by no means perfect. Rather it is a great showcase of how you quickly can make something that brings life to your design using FLiNT.

To give you a starting idea, I drew a mask inside Flash that makes sure the smoke only comes up the chimney. The rest is all programmed. As soon as someone comes up with a good counter example I will post the source to this example. So make sure you check back!

The house graphic is free for use, from Lost Garden, a blog about games and game art among other things.

Remember, use FLiNT as a programmatic design tool. Visualize the effect in your head then break it down into smaller parts and code each part. With some practice you can create amazing effects!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.