For Independence Day set off some particle effects!

FireworkWith Independence Day (Fourth of July) just a couple days away, I thought I’d share some fireworks. But these ones are safe and eco-friendly. And, to save you some cash, I’ll show you how to make your own fireworks! Sorry, pyro-maniacs, we’ll be using Flash AS3 to generate safe particles. Take a look at the fireworks show I’ve created in Flash, and if you’re interested in creating your own, follow along with my instructions.

Here are our requirements:

  • create a particle effect that resembles a firework burst.
  • vary them in size and color.
  • celebrate our independence.

Let’s get started!

Here’s what it should look like:

Oooh!  Ahhh!

OK, so the first thing to do is to set up your assets. I made a six-pointed star thing for my particle. You could also just make a circle or use a bitmap. Be sure to set the linkage on the particle so we can grab it with code. I went out on a limb and called my particle Particle. I also made a gradient background, and threw some tree silhouettes in the foreground. My movie is set to 600 x 400 pixels and 30 frames per second. Between the foreground and background, I have a layer that contains an empty movieclip named fireworks_mc and another named explosions_mc. More on those later.

Now lets get to the code.  First, let’s make a function that will launch a firework.

1
2
3
4
5
6
7
8
function newFirework():void{
	var firework:Particle = new Particle();
	firework.x = Math.random()*400 + 100;
	firework.y = 400;
	firework.velx = (300 - firework.x) / 100;
	firework.vely = -8;
	fireworks_mc.addChild(firework);
}

The first line in the function creates a new particle object. Then, we set the starting position. My stage is 600 pixels wide, so I want the particle to start between 100 and 500 pixels. The y position is at the bottom of the stage, at 400 pixels. Next let’s set some dynamic variables on this object—velocity in both the x and y directions. Notice the formula I used for the x velocity. That’s to keep the firework shooting toward the center of the stage. And finally we add the firework to the fireworks_mc movieclip. This movie clip is just a container to hold all our fireworks, and display them behind the trees.

Before we can see this function do anything, let’s add a bit more code:

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var gravity:Number = 0.1;
 
newFirework();
addEventListener(Event.ENTER_FRAME, loop);
 
function loop(e:Event):void{
	var p:MovieClip;
	var i:uint;
	var ct:ColorTransform;
	for(i = 0; i<fireworks_mc.numChildren; i++){
		p = MovieClip(fireworks_mc.getChildAt(i));
		p.x += p.velx;
		p.y += p.vely;
		p.vely += gravity;
		if(p.vely >= -1){
			explode(p);
		}
	}
	//... clip ...
}

This chunk of code does a few things—defines our gravity, creates a new firework (by calling our function from above), and starts an event listener that calls a function every frame. In the loop function, we loop through all children of firework_mc and update its position, and apply gravity to the y velocity. Then we check if it’s high enough in the sky to explode. I wanted the firework to explode just before it reaches its apex. There’s more code to go into this function, but this will get you started. You can comment out the explode function and try your movie now. You should get a single particle flying into the air, and getting pulled back down by gravity. So let’s see the explode function.

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
function explode(fw:MovieClip):void{
	//get the position of the MC.
	var X:Number = fw.x;
	var Y:Number = fw.y;
	var numParts:uint = 50;
	var speed:uint = Math.random() * 6 + 4;	//this affects the overall size of the explosion
	var decay:Number = 0.97;
	var lifespan:Number = Math.random() + 3;	//approx lifespan in seconds.  This is +/- one second.
	var colorStepArr:Array = new Array(0, 255);
	var redshift:Number = colorStepArr[Math.floor(Math.random()*2)];
	var greenshift:Number = colorStepArr[Math.floor(Math.random()*2)];
	var blueshift:Number = colorStepArr[Math.floor(Math.random()*2)];
	//remove the MC.
	fireworks_mc.removeChild(fw);
	//add particles at this position.
	newExplosion(X,Y,numParts,speed,decay,lifespan,redshift,greenshift,blueshift);
}

The first thing this function does it make a note of the position of the firework. We then define the number of particles to use for the explosion, the speed of the particles, their decay (the rate of deceleration), their lifespan, and some color parameters. I’ll explain each of these variables a bit more. We want the particles to start from where the firework left off, so the X and Y variables define the start point. numParts is simply the number of particles to use in the explosion. The speed is a random number from 4 to 10 and it affects the size of the explosion. The decay is used to slow the particles down. Lifespan is the number of seconds before individual particles are removed (each particle will have its own lifespan, so this number is varied in the next function).

For the color changing effect, we need to pick a color to fade into. We could choose random values for the R,G, and B channels, but a lot of combinations make muddy colors. I want bright and vivid colors, so I created an array of all approved colors. After testing, I decided that I only need 0 and 255.

Because my particle is white, I want to remove 0 or 255 from each channel, giving me red, yellow, green, cyan, blue, magenta, black, or white. Using just these two values for each channel ensures that I will have vibrant colors. Note that black is not the best color for a firework, so you can write a condition that re-picks the numbers if it comes up black, but I left it in because I’ve never seen black fire (really, I just don’t care to fix it).

Finally, the code above removes the original firework and uses all those parameters to create a new explosion. Here’s the next function:

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
function newExplosion(X,Y,parts,speed,decay,life,red,green,blue):void{
	var p:Particle;
	var angle:Number;
	for(var i:uint = 0; i<parts; i++){
		p = new Particle();
		p.x = X;
		p.y = Y;
		p.scaleX = p.scaleY = .5;
		angle = Math.random() * 3.141592654 * 2;
		p.velx = Math.cos(angle) * Math.random() * speed;
		p.vely = Math.sin(angle) * Math.random() * speed;
		p.decay = decay;
		p.life = 30 * (life + Math.random() * 2 - 1);	//plus or minus one second
		p.age = 0;
		p.red = red / -p.life;
		p.green = green / -p.life;
		p.blue = blue / -p.life;
		p.deltaAlpha = 255 / p.life;
		explosions_mc.addChild(p);
	}
}

In this function we have a for loop to create new particles. It sets the particles’ start position and scales it down a bit. Then we get a direction for the particle to travel. If I had simply set the x and y velocities to any random number, the explosion would be squarish. By getting a random angle and getting it’s sine and cosines, it will be circular. I also randomize the speed, otherwise we would have a ring of particles.

I don’t want the particles to die all at the same time, so I add plus or minus one second on to the lifespan parameter. Each particle gets its own set of parameters so they’ll blink off at different times. I also convert the number from seconds to frames by multiplying it by the frame rate. We need to keep track of how old each particle is, so each one starts off at age 0.

These color calculations are a little backwards, so I’ll try to explain what’s going on. My particles are normally white and I want to fade them over time to another color. To go from white to red, I need to remove the green and blue channels. In this case, the red, green, and blue parameters should be 0, 255, and 255 respectively. That’s how much I want to remove from each channel to get the desired color. So I want to add the negated value that was passed in. But I also want to fade it over time, not all at once. So I divide the total change by the number of frames before the particle dies to get the change per frame. Each frame, the particle will become a little closer to the final color, and it will reach that color just before it dies.

And finally, we add the particle to the explosions_mc. If you test your movie now, it won’t do much ’cause we left a part out of the loop function. Let’s add it in:

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
	for(i=0; i<explosions_mc.numChildren; i++){
		p = MovieClip(explosions_mc.getChildAt(i));
		p.x += p.velx;
		p.y += p.vely;
		p.velx *= p.decay;
		p.vely *= p.decay;
		p.vely += gravity;
		//change color
		ct = new ColorTransform();
		ct.redOffset = p.transform.colorTransform.redOffset + p.red;
		ct.greenOffset = p.transform.colorTransform.greenOffset + p.green;
		ct.blueOffset = p.transform.colorTransform.blueOffset + p.blue;
		ct.alphaOffset = p.transform.colorTransform.alphaOffset - p.deltaAlpha;
		p.transform.colorTransform = ct;
		p.age += 1;
		if(p.age > p.life){
			//remove it
			explosions_mc.removeChild(p);
			i--;
			if(explosions_mc.numChildren == 0){
				newFirework();
			}
		}
	}

Just like the other for loop in the loop function, this for loop updates all the particles but in the explosions_mc. It updates the particle’s x and y position. Then it slows down the velocity by multiplying it by the decay value. It then applies gravity to the y velocity. And then it adjusts the color.

To fade the color, we first have to find out what color it currently is. We need to make a ColorTransform and get the red, green, and blue offsets. Then we add the values we assigned to the particle to those offsets. Then we set the modified Color Transform to the particle.

We need to update the particle’s age and then check if it’s time for it to expire. If it is time to remove it, we need to correct i so we don’t skip any particles in this for loop. And finally, if there are no more particles left, we start all over by calling the newFirework function.

So there you have it—the basics to particles. Go ahead and play with the parameters, add sounds, mouse events, aliens, etc.

Download the FLA

Tags: , ,

Leave a Reply