2D Fire Effect in ActionScript 3

I had a little bit of time today to do some me-coding (as opposed to work-coding), so I knocked up a quick 90’s era 2D fire effect. I’d actually written it C++ and OpenGL the other week and was meaning to transfer it into WebGL so it can run live rather than having a captured video, but my WebGL kung-fu is pretty weak at the moment so just to get it done I translated it to Flash.

How it works

The effect itself is incredibly simple, as the video below explains. You randomly add “hot-spots” to the bottom of the pixel array, then the new temperature value for a pixel is just the average of the pixel and the 3 pixels below it with a small amount subtracted so that the flames “cool”, which you then map to a colour gradient.


Flash implementation

In the OpenGL version I’d made the colours for the flames into a 1D texture which can be easily interpolated, but I had to find some functions to do that in AS3 as there don’t appear to be 1D textures! Also, getting and converting the colours from uints and hex-codes and stuff was a pain – but I finally nailed it after googling around and pulling functions from various places (referenced in the source).

I think the most important thing I learnt from getting this working in Flash was how to and how NOT to convert colours from uints into red/green/blue components. For example, a lot of code online will use a function like the following to convert red/green/blue values into a 24-bit uint:

function rgbToUint(red:uint, green:uint, blue:uint):uint
	var hex = "0x" + red.toString(16) + green.toString(16) + blue.toString(16);
  	return hex;

The above function looks like it works, and in fact in most cases does work – but if you get single digit values they aren’t zero-padded properly and craziness ensues!

The correct way to convert RGB to uint is by using the two functions below which ensure that values are capped AND zero-padded as appropriate, which means that everything works under all possible conditions:

function convertChannelToHexStr(hex:uint):String
	if (hex > 255)
		hex = 255;
		//trace("hex val overloaded");
	var hexStr:String = hex.toString(16);
 	if (hexStr.length < 2)
		hexStr = "0" + hexStr;
	return hexStr;
function getHexColourFromRGB(r:uint, g:uint, b:uint):uint
	var hexStr:String = convertChannelToHexStr(r);
	hexStr           += convertChannelToHexStr(g);
	hexStr           += convertChannelToHexStr(b);
	var strLength = hexStr.length;
	if (strLength < 6)
		for (var j:uint; j < (6-strLength); j++)
			hexStr += "0";
	var finalStr = "0x" + hexStr;
	return finalStr;

Wrap up

Overall, it’s a nice simple effect – but it’s pretty CPU intensive. In the above example I’m only using a stage size of 250px by 120px and the framerate takes a hit even then.

I could use a single loop instead of embedded x and y loops, and I could manipulate more colours directly as uints rather than pulling out the RGB components, but it’s prolly not going to improve more than about 10-15%. As usual, there’s source code after the jump, so if you have a play with it and manage to speed it up a bunch, feel free to let me know how you did it!


Download Link: 2D-Fire-Effect.fla (Flash CS4 fla – but CS5 and later will convert on load).

Continue reading 2D Fire Effect in ActionScript 3