Robots w/Lasers

August 22, 2008

Simple Cellular Automata Example in AS3

To get a little more experience with ActionScript 3, I wrote up a very simple class which will take a rule number, and then generate a cellular automata based on that.

The movie below requires Flash 9 or above to be installed. Some rules to try out: 90, 30, 73, 110, 150. Valid numbers are 0-255, but not all produce interesting results.

This movie requires a newer Flash Player version

Direct link to flash movie (got some people complaining the SWFObject script doesn't work under Vista)

See Wikipedia for more info, and Wolfram.com has a list of all 256 possible results
Here's the code:

Actionscript:
  1. /**
  2. * Simple Cellular Automata example
  3. * by David Rorex, 2008
  4. */
  5. package
  6. {
  7.     import flash.display.*;
  8.     import flash.events.*;
  9.     import flash.geom.*;
  10.     import flash.text.*;
  11.     import flash.ui.Keyboard;
  12.     import flash.utils.getTimer;
  13.     import sim.EasyButton;
  14.        
  15.     public class Main extends Sprite
  16.     {
  17.         /// Holds the data we draw onto
  18.         private var bdata:BitmapData;
  19.        
  20.         /// Bitmap container for displaying our rendering
  21.         private var bitmap:Bitmap;
  22.  
  23.         /// Text field for typing in rule numbers
  24.         private var inp:TextField;
  25.        
  26.         /// Button to click to render
  27.         private var btn:EasyButton;
  28.        
  29.         /// Constructor
  30.         public function Main():void
  31.         {      
  32.             // set up the input textfield
  33.             inp = new TextField();
  34.             addChild(inp);
  35.             inp.type = TextFieldType.INPUT;
  36.             inp.border = true;
  37.             inp.text = "90";
  38.             inp.addEventListener(KeyboardEvent.KEY_UP, onEnter);
  39.             inp.height = 20;
  40.            
  41.             // set up the render button
  42.             btn = new EasyButton("Render");
  43.             btn.addEventListener(MouseEvent.CLICK, function(e:*):void { doRender(); } );
  44.             addChild(btn);
  45.                        
  46.             // set the stage to not scale, and to get an event if the window changes size
  47.             stage.scaleMode = StageScaleMode.NO_SCALE;
  48.             stage.align = StageAlign.TOP_LEFT;
  49.             stage.addEventListener(Event.RESIZE, onResize)
  50.            
  51.             // initialize the size
  52.             setSize(stage.stageWidth, stage.stageHeight);
  53.         }
  54.        
  55.         /**
  56.          * Event handler for when the stage changes size
  57.          * @param e
  58.          */
  59.         private function onResize(e:Event):void {
  60.             setSize(stage.stageWidth, stage.stageHeight);
  61.         }
  62.        
  63.         /**
  64.          * Event handler to catch the user pressing ENTER in the text field
  65.          * @param e
  66.          */
  67.         public function onEnter(e:KeyboardEvent):void {
  68.             if (e.charCode == Keyboard.ENTER)
  69.                 doRender();
  70.         }
  71.        
  72.         /**
  73.          * Simple method to call the render function
  74.          */
  75.         public function doRender():void {
  76.             render(parseInt(inp.text));
  77.         }
  78.        
  79.         /**
  80.          * Adjust the positioning of our elements based on a given size
  81.          * @param w
  82.          * @param h
  83.          */
  84.         public function setSize(w:Number, h:Number):void {
  85.             btn.x = w - btn.width;
  86.             inp.width = w - btn.width - 2;     
  87.         }
  88.        
  89.         /**
  90.          * Render cellular automata.
  91.          * @param ruleNum - the number of the rule to draw. Some interesting numbers are '30' and '90'
  92.          */
  93.         public function render(ruleNum:int):void {
  94.            
  95.             // clean up previous bitmap
  96.             if (bitmap != null) {
  97.                 removeChild(bitmap);
  98.                 bitmap = null;
  99.             }
  100.             if (bdata != null) {
  101.                 bdata.dispose();
  102.                 bdata = null
  103.             }
  104.            
  105.             // get width and height of the stage
  106.             var w:Number = stage.stageWidth;
  107.             var h:Number = stage.stageHeight - 20;
  108.                        
  109.             // build lookup table based on the rule number
  110.             var rule:Array = [];
  111.             for (var i:int = 0; i <8; i++)
  112.                 rule[i] = (ruleNum>> i) & 1;
  113.            
  114.             // create bitmap data that we will draw into
  115.             bdata = new BitmapData(w, h, false, 0);
  116.            
  117.             // lock the bitmap data, provides speedups when you are doing a lot of manipulations
  118.             bdata.lock();
  119.            
  120.             // set the starting data - a single pixel in the center
  121.             bdata.setPixel(Math.round(w/2), 0, 1);
  122.            
  123.             // loop row by row
  124.             for (var y:int = 1; y <h; y++)
  125.                 // loop pixel by pixel
  126.                 for (var x:int = 0; x <w; x++) {
  127.                    
  128.                     // use lookup table based up 3 neighboring pixels to calculate new pixel
  129.                     bdata.setPixel(x, y,
  130.                         rule[bdata.getPixel(x - 1, y - 1) <<2
  131.                            | bdata.getPixel(x    , y - 1) <<1
  132.                            | bdata.getPixel(x + 1, y - 1)]);
  133.                           
  134.                 }
  135.            
  136.             // map the pixels, 0-white, 1-black
  137.             bdata.paletteMap(bdata,
  138.                         new Rectangle(0, 0, w, h), new Point(0, 0),
  139.                         [], [], [0xffffff, 0]);
  140.            
  141.             bdata.unlock(); // unlock the bitmap data
  142.            
  143.             // create the bitmap to hold the data
  144.             bitmap = new Bitmap(bdata, PixelSnapping.ALWAYS, false);
  145.            
  146.             bitmap.y = 21;
  147.            
  148.             addChildAt(bitmap,0); // add it to our display list so we can see it
  149.         }
  150.     }
  151. }

Filed under: Flash,Software — davr @ 11:33 am

3 Comments »

  1. looks like your flash detection is broken for FP10/FF/vista

    Comment by felix — August 22, 2008 @ 12:40 pm

  2. It works for me with FP10/FF/XP…dunno why vista would would make a difference. It’s using swfobject which is supposed to be pretty good about that sort of thing. I can’t be bothered to debug a flash detection script for vista, so I added a direct link to the swf in the post.

    Comment by davr — August 22, 2008 @ 1:03 pm

  3. [...] public links >> positioning Simple Cellular Automata Example in AS3 Saved by RiN on Wed 22-10-2008 Advising Agencies That Get Positioning Saved by andrewwilles on [...]

    Pingback by Recent Links Tagged With "positioning" - JabberTags — October 23, 2008 @ 5:04 am

RSS feed for comments on this post. TrackBack URI

Leave a comment

Powered by WordPress

Bad Behavior has blocked 2578 access attempts in the last 7 days.




Paid Advertisements
British Virgin Islands - Aquariums - Costa Rica - Renegade Motorhome