So you want to create a fireworks show on your website or have a cool flame effect around a holiday photographs but you don’t have the time to create hundreds of looping pictures for an animation? Well, you don’t need to.
For Glacial Flame we set out to build a particle system to handle all our environment and spell effects. Personally, I didn’t know where to start with this one, my day job has me building large scale applications not making things look cool using specs of colour. But after getting the gist of what a particle engine is from our old friend Wikipedia I pretty much knew what we needed, just not how.
For those who don’t already know, a particle engine can be basically thought of as a swarm of images or shapes which follow a ‘fuzzy’ set of programmable instructions. For example, you could emit a hundred particles from an origin point on the screen and tell them that they should travel upwards and live for two hundred frames. Ordinarily this would simply create a blob of particles moving from the starting point upwards and then vanishing, pretty boring. The fuzziness or randomness comes into play by allowing you to emit the particles in such a way that some move slower than others, some start after a delay and maybe live longer than other and yet others may simply move a bit left or right. Now you’re boring straight line suddenly sounds more interesting.
So how? I started off by researching how other games do it, games written for DirectX or OpenGL, and soon found little gems like this one on NeHe’s site. Ignoring all the OpenGL specific code for drawing, this lesson does show quite well how to implement some of the particle behaviour underpinning the engine. Things such as gravity, fade, movement speed and lifespan.
With this I was able to start forming ideas on how to implement something in JavaScript / Canvas but first I needed to find a way to draw a particle. In NeHe’s article and many others like it particles are drawn from an image or texture. Canvas would probably struggle with this method. Firstly canvas isn’t yet able to draw hundreds of images to the screen quickly at the same time and secondly many of the manipulation techniques available in big libraries like OpenGL around images aren’t available to canvas just yet.
In the end I settled on a simple rectangle using a radial gradient to create a smooth circle that could be any colour and size I chose.
function DrawParticle(x, y, radius, color1, color2) {
var gradient = ctx.createRadialGradient(x, y, 0, x, y, radius / 2);
gradient.addColorStop(0, color1);
gradient.addColorStop(1, color2);
ctx.fillStyle = gradient;
ctx.fillRect(x - radius, y - radius, radius * 2, radius * 2);
};
Give it a go. Try experiment by making a particle move across the screen changing colour as it goes. The below example should get you started, just copy it to a .html page and open it with your web browser.
<html>
<head>
<title>Glacial Flame Particle Tutorial Part 1</title>
<style type="text/css">
body
{
background-color:#fff;
color:#000;
text-align: center;
font-family: Verdana;
}
h2
{
font-size:10px;
font-weight:normal;
}
#main
{
width:400;
text-align:center;
margin:0 auto;
}
</style>
</head>
<body onload="init()">
<div id="main">
<h1>Tutorial Part 1</h1>
<canvas id="canvas" width="300" height="200" style="border: 1px solid black; background-color: #fff;">
Your browser does not support this content.
</canvas>
<h2>300 x 200</h2>
<h2>Glacial Flame - <a href="mailto:dev@glacialflame.com">Iain Hamilton</a> & <a href="mailto:dev@glacialflame.com">Craig Wright</a></h2>
</div>
<script type="text/javascript">
var ctx, canvasHeight, canvasWidth;
// Particles current position within the canvas
var px = 0, py = 100;
// Starting colors (0 - 255 rgb)
var r = 255, g = 255, b = 255;
// Call this function to start everything off after the page loads
function init() {
SetupCanvas();
if (ctx != null) {
// Run the draw function every 50 msec after canvas is setup
setInterval(Draw, 50);
}
};
function SetupCanvas() {
if (ctx == null) {
// Get the HTML canvas element
var canvas = document.getElementById('canvas');
if (canvas && canvas.getContext) {
// save the height and width for later use by javascript
canvasHeight = canvas.height;
canvasWidth = canvas.width;
// Start the particle in the middle of the screen for height
py = canvasHeight / 2;
// Get the canvas context, used to do all the drawing
ctx = canvas.getContext('2d');
}
}
ctx.globalCompositeOperation = 'lighter';
};
function Draw() {
// Clear the canvas before every draw
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
// Move the particle right 1 pixel every frame
px++;
// If the particle moves off the edge of the screen reset it
if (px > canvasWidth) px = 0;
// Every even number decrement the red intensity
if (px % 2) r--;
// Every third number decrement the green intensity
if (px % 3) g--;
// Decrement the blue intensity every frame
b--;
// Reset the color intensity when they hit 0
if (r < 0) r = 255;
if (g < 0) g = 255;
if (b < 0) b = 255;
// Draw the partcle itself
DrawParticle(px, py, 40, "rgba(" + r + ", " + g + ", " + b + ", 1)", "rgba(0, 0, 0, 0)");
};
function DrawParticle(x, y, radius, color1, color2) {
var gradient = ctx.createRadialGradient(x, y, 0, x, y, radius / 2);
gradient.addColorStop(0, color1);
gradient.addColorStop(1, color2);
ctx.fillStyle = gradient;
ctx.fillRect(x - radius, y - radius, radius * 2, radius * 2);
};
</script>
</body>
</html>
In the next tutorial I’ll discuss how you can add random fuzziness to particles to give you’re effects a more natural and fluid behaviour and introduce the emitter concept that we use to manage effects within Glacial Flame.





Pingback: Glacial Flame in full swing | Beakable
it was very interesting to read.
I want to quote your post in my blog. It can?
And you et an account on Twitter?
Glad you liked it.
Yes, feel free to quote any of our posts on the site with reference.
Sorry, we do not have a Twitter account setup yet, maybe in the future.