Simple Particle System in ActionScript 3
It was time to start posting tutorials and source code as I promised earlier and so I will start by continuing my recent experience with particle systems in both Processing and Flash. I will teach you how to make a simple particle system and explain along with it, why traditional particle systems are CPU savy. I will also go through some of the particle engines present for Action Script.
If you don’t know what Particle systems are, then this may not be the right place for you. I would recommend you google “Particle System” or wiki it, you may also visit Daniel Shiffman‘s website. He has an amazing resource of information regarding Particle Based Systems and how they have evolved. The example used in this tutorial has been modified from his source code present on the website. I converted it to Action Script to demonstrate certain differences between Flash and Java. Enough chit chat, let us get on with it.
We will first need some Mathematics to calculate vectors and directions for particles. You don’t need to work on that and download Vector3D class for AS3, I posted a few days ago. This makes our work easier. Here’s a preview of what we’ll be making:
I’ll explain each step of class creation for our particle as we move on:
Particle.as
package
External classes in Flash need to be inside a package. If you are not creating complex hierarchies, then I would recommend you keep all the classes in the root package. Packages are necessarily paths to classes. A subpath translates to a hierarchy of other classes. This is the same behavior as Java and many other languages that use packages nowadays.
import flash.display.Shape;
We only need to import this, since we are creating a simple particle for now. We will add imports once we create more complex particle systems.
public class Particle extends Shape{
We create a particle class and inherit the properties of Shape from Flash primitive types. Inheritance is pretty easy in flash and VERY useful. If you are not familiar with the term inheritance or Object Orientation, then Google it :P.
var location:Vector3D; // The location in x,y coordinate of our particlevar velocity:Vector3D; // The velocity of our particle (amount of travelling it does in a given time)var acceleration:Vector3D; // The constant addition to the speed of our particlevar radius:Number; // The radius/size of our particlevar timer:Number; // A timer that can help us in performing events as needed
Some particle properties that will help us animate or change our particle’s behavior over time. Although the meaning of the properties is very much obvious by their names, I’ve explained what they are used for.
public function Particle(v:Vector3D){ acceleration=new Vector3D(,0.05,); velocity=new Vector3D((Math.random() * -1.0 + Math.random() * 1.0),(Math.random() * -2.0 + Math.random() * 0.0),); location=v.construct(); radius=10.0; timer=1.0;}
Action Script does not support multiple Constructors for now, but this is the one we’ll be using here. This constructor takes a Vector(location) and creates a particle object at that location. The constructor initializes the values for the particle. Values in this construcor will transform how our particles appear on screen at the initial frame.
public function run():void{ update(); render();}
This function is called whenever a particle is to be updated. It simply calls two other functions. The update function updates the variables (location, acceleration) of the particle and the render function draws the changes to the screen.
// Method to update locationpublic function update():void{ velocity.addition(acceleration); location.addition(velocity); timer -= 0.01;}
Our particle needs to move, or else it would appear like a dot on the screen. We update the location of the particle by adding a constant acceleration to its velocity and then by changing its location. The timer object here is used to detect, how long has it been since the particle was born. We will use this information to make it die and remove it from the screen.
// Method to displaypublic function render():void{ graphics.clear(); // Clears any thing drawn on the previous frame. graphics.beginFill(0xffffff,timer); // Start drawing using white color and timer alpha graphics.lineStyle(,0xffffff,timer); // We don't want a boundary on our particle. graphics.drawEllipse(loc.x,loc.y,r,r); // Draw a particle on location.x and location.y position graphics.endFill(); // Not necessary but a good practice}
This function renders the changes to the screeen. The purpose of each line is explained next to it. If you are not familiar with Flash scripting, you might wanna skip this and learn basic flash drawing using API first.
// Is the particle still useful?public function dead():Boolean{ if (timer <= 0.0){ return true; } else{ return false; }}
This function checks if the particle needs to be removed from the screen. Clearly this is the timer object we created for each particle. Each particle is traced through its timer based value and will be removed from memory when this timer reaches zero. More detail on this in the Particle System class.
}}
Ok, now to our Particle System class:
ParticleSystem.as
package {import flash.display.MovieClip; public class ParticleSystem extends MovieClip {
Our particle system class hosts particles, and this is where all the particles are born. This class creates and deletes particles. We have inherited the MovieClip properties for this class since we want our particles to be animated inside a DisplayObject, but this is not really necessary.
var particles:Array; // An arraylist for all the particlesvar origin:Vector3D; // An origin point for where particles are created
We create an array of particles. This array should hold a number of particles as they are created and is resized / expanded as required. The origin is a vector object that is used to define the originating position of our particles e.g. every particle should be created at x=0,y=0.
public function ParticleSystem(num:int,v:Vector3D){ particles=new Array(); // Initialize the arraylist origin=v.construct(); // Store the origin point</em></strong> for (var i:uint=; i < num; i++){ particles.push(new Particle(origin)); // Add "num" amount of emitters to the arraylist }}
This is the default constructor for the Particle System. The copy1() function returns a vector position and creates a Vector3D object, this is a copy constructor. The loop in this constructor runs for a specific number of emitters provided during the creation of the particle system. An emitter creates particles. The more the emitters, the more the particles. For Example: An emitter is like a fountain, the more pipes in the fountain the more water goodness.
public function run(){ // Cycle through the ArrayList backwards because we are deleting for (var i:uint=particles.length - 1 ; i > 0 ; i--) { var p:Particle = Particle(particles[i]); addChild(p); p.run(); if (particles[i].dead()){ particles.splice(i,1); } }}
Each emitter then creates a particle inside it and keeps track of it. Once the particle has finished its lifetime, the emitter is responsible for removing it from the array of particles. This is handled through the addparticle and particle.isdead() function. What we are doing in the above function is fairly simple. Run the loop for the length of the particle array. Create a particle object and add it to the Flash Display List. If you don’t know what Display Lists are or what Display Objects are, you might wanna visit Flash’s Documentation at LiveDocs. We then call the particle’s run function, which will essentially update the position of the particle with each run and draw it to the screen. We check the timer object of the particle and fade it over time and where the particle.isdead() would tell us if the particle has completely faded away. We then remove that particle from the particles array using the splice function. The splice function removes elements from the Array object ranging n number of times.
public function addParticle(){ particles.push(new Particle(origin));}
We add a particle to the particles array. This is simply creating a particle.
// A method to test if the particle system still has particlespublic function dead():Boolean{ if (particles.length <= ){ return true; } else{ return false; }}
This function checks if all particles from the array have been removed, if the movie is not running in a loop, this will remove the particle system object and no more particles will be generated from the emitter.
}}
The hard part is over here, we now need to create a particle system instance on our Flash Stage. Create an FLA and on its first frame, write this code:
var ps:ParticleSystem = new ParticleSystem(1,new Vector3D(stage.stageWidth/2,stage.stageHeight/2,));
Create a particle system instance. The number of emitters in it are 1 and the default position for our particle system should be the center of the stage, since this is a 2D particle system, we set Z to 0.
addChild(ps);
We need to add this Display Object to our Flash Display List. This tells Flash to draw the object to the screen.
function update(e:Event){ ps.addParticle(); ps.run();}this.addEventListener(Event.ENTER_FRAME,update);
This is more likely an “onEnterFrame” function for users who are familiar with ActionScript 2.0. What this function is doing is to be called every n number of frames. If the Frame Rate for the FLA is 30 FPS, then this function is called every 30th second. This function is adding a particle to the Particle array and then calls its update function. The hierarchy is pretty simple to understand:
ParticleSystem (Hosts emitters and calls an update function)
- Emitter (Hosts particles and calls their update function)
- Particle (Hosts Vectors and uses them to update locations and other variables).
Ok, now compile everything and run the code. If you can’t seem to run it, then go through the tutorial once again. Remember this is ActionScript 3. If you still can’t seem to run it, then go ahead ask me. We now analyze our particle system.
The CPU usage for this particle system should not exceed 2% of your CPU no matter what. Creating the same particle System in Flint or Pulse would render much different results and the CPU usage should rise upto 10%. Why the CPU usage, you ask? Well, this is not a problem with the Particle Engines themselves but with how Flash manages Display Objects. Adobe needs to concentrate on the Display engine and optimize it. If you need another example, try doing this and see how this affects the CPU usage and you’ll know what I mean:
in the particle class, go to the render function and change the following line:
graphics.drawEllipse(loc.x1,loc.y1,r,r);
to
graphics.drawEllipse(loc.x,loc.y,r*timer,r*timer);
You will notice a CPU increase from 7%-15%. This is fairly large and the reason why Pulse and Flint both end up using too much CPU. In a previous post, I stated how Flash compares to other graphic APIs and this holds true here as well.
I hope you enjoyed and learned how to create simple particle systems in Flash ActionScript 3. I will soon post more tutorials on particle systems and we will then move on to create complex particle Systems based on this one. We will further analyze how we can port this code to create a particle engine. So keep an eye out for more stuff to come.
Download simpleparticlesystem.zip
© 2016 Most of the work on this site is mine, ask before using. Thanks. –