2D Fire Effect in ActionScript 3
r3dux | May 31, 2012I 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.
Sneaky!
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:
// NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO!!!!!!!!! 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!
Cheers!
Download Link: 2D-Fire-Effect.fla (Flash CS4 fla – but CS5 and later will convert on load).










