After my last plasma experiments, I feel motivated to play again with pixels and old school demoscene effects. I continued to explore the same great C++ CG resource
So, here’s another one effect that I’m glad to share. This is the old shool fire effect.
No tricks deployed this time to optimize Flash rendering. That’s a standard implementation.
Here’s the source code. Enjoy !
package { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageQuality; import flash.display.StageScaleMode; import flash.events.Event; import flash.filters.BlurFilter; import flash.geom.Point; import flash.geom.Rectangle; [SWF( width="450", height="175", frameRate="25" , backgroundColor="0x000000")] public class Fire extends Sprite { protected const w : int = 450; protected const h : int = 175; protected var bd : BitmapData; protected var p : Point; protected var rect : Rectangle; protected var blur : BlurFilter; protected var palette : Vector.<int>; protected var fire : Array; public function Fire() { stage.scaleMode = StageScaleMode.NO_SCALE; stage.align = StageAlign.TOP_LEFT; stage.quality = StageQuality.LOW; p = new Point(0, 0); rect = new Rectangle( 0, 0, w, h ); blur = new BlurFilter( 4, 4, 1 ); bd = new BitmapData( w, h, false, 0xFFFFFF ); addChild( new Bitmap( bd ) ); var x : int, y : int; palette = new Vector.<int>( 256, false ); fire = []; for ( x = 0; x < w; x++ ) fire[x] = new Vector.<int>( h, false ); for ( x = 0; x < w; x++ ) for ( y = 0; y < h; y++ ) fire[x][y] = 256; for ( x = 0; x < 256; x++ ) palette[x++] = HSLtoRGB( x/(3 * 256), 1, Math.min( 256, x * 2 )/256 ); addEventListener( Event.ENTER_FRAME, enterFrame ); } protected function enterFrame( e : Event ) : void { bd.lock(); var x : int, y : int; for ( x = 0; x < w; x++ ) fire[x][h - 1] = Math.random()*32768 % 256; for ( y = 0; y < h - 1; y++ ) for ( x = 0; x < w; x++ ) fire[x][y] = ((fire[(x - 1 + w) % w][(y + 1) % h] + fire[(x) % w][(y + 1) % h] + fire[(x + 1) % w][(y + 1) % h] + fire[(x) % w][(y + 2) % h]) * 32) / 129; for ( x = 0; x < w; x++ ) for ( y = 0; y < h-1; y++ ) bd.setPixel( x, y, palette[fire[x][y]]); bd.applyFilter( bd, bd.rect, p, blur ); bd.unlock(); } public static function HSLtoRGB( h :Number, s : Number , l : Number ) : Number { var r : Number = 0, g : Number = 0, b : Number = 0, v1 : Number, v2 : Number; if ( s == 0 ) { r = l * 255; g = l * 255; b = l * 255; } else { v2 = ( l < .5 ) ? l * ( 1 + s ) : ( l + s ) - ( s * l ); v1 = 2 * l - v2; r = 255 * HueToRGB( v1, v2, h + ( 1 / 3 ) ); g = 255 * HueToRGB( v1, v2, h ); b = 255 * HueToRGB( v1, v2, h - ( 1 / 3 ) ); } return ((r << 16)|(g << 8)|b); } private static function HueToRGB( v1 : Number, v2 : Number, vH : Number ) : Number { if ( vH < 0 ) vH += 1; if ( vH > 1 ) vH -= 1; if ( ( 6 * vH ) < 1 ) return ( v1 + ( v2 - v1 ) * 6 * vH ); if ( ( 2 * vH ) < 1 ) return ( v2 ); if ( ( 3 * vH ) < 2 ) return ( v1 + ( v2 - v1 ) * ( ( 2 / 3 ) - vH ) * 6 ); return ( v1 ); } } }
Très sympa, beau boulot Francis !