Category Archives: functions

Recursion Form

Actionscript:
  1. x = y = 10
  2. graphics.lineStyle(1,0);
  3. drawBox(6);
  4.  
  5. function drawBox(iter:Number=10, count:Number=1, y:Number=0, w:Number=500):void{
  6.        if (count <iter){
  7.                var width:Number = w / count
  8.                for (var i:int = 0; i<count; i++){
  9.                    graphics.drawRect(i * width, width * count/w, width, width);
  10.                }
  11.                count++;
  12.                drawBox(iter, count, y, width);
  13.        }
  14. }

This small snippet just draws this image:

If you have an idea for a short recursive snippet. Feel free to post it in the comments.

Also posted in Graphics | Tagged , , | 6 Comments

Haskell Inspired zipWith() Function

Actionscript:
  1. initOperators();
  2.  
  3. trace(zipWith("-", [1,2,3], [1,2,3]));
  4. trace(zipWith("+", [1,2,3], [1,2,3]));
  5. trace(zipWith("*", [1,2,3], [1,2,3]));
  6. trace(zipWith("+", [1,1,1,3], [4,5,6,7]));
  7. trace(zipWith("<<", [2, 4], [1,1]));
  8. /*
  9. outputs:
  10.  
  11. 0,0,0
  12. 2,4,6
  13. 1,4,9
  14. 5,6,7,10
  15. 4,8
  16. */
  17.  
  18. function zipWith(op:String, a:Array, b:Array):Array{
  19.     var aLeng:int = a.length;
  20.     var bLeng:int = b.length;
  21.     var leng:Number = (aLeng <bLeng) ? aLeng : bLeng;
  22.     var zipped:Array = [];
  23.    
  24.     if (!this[op])return [];
  25.    
  26.     for (var i:int = 0; i<leng; i++){
  27.         zipped[i]=this[op](a[i], b[i]);
  28.     }
  29.     return zipped;
  30. }
  31.  
  32. function initOperators():void{
  33.     this["+"]=function(a:Number, b:Number):Number{ return a + b };
  34.     this["-"]=function(a:Number, b:Number):Number{ return a - b };
  35.     this["/"]=function(a:Number, b:Number):Number{ return a / b };
  36.     this["*"]=function(a:Number, b:Number):Number{ return a * b };
  37.     this["%"]=function(a:Number, b:Number):Number{ return a % b };
  38.    
  39.     this["&"]=function(a:Number, b:Number):Number{ return a & b };
  40.     this["<<"]=function(a:Number, b:Number):Number{ return a <<b };
  41.     this["|"]=function(a:Number, b:Number):Number{ return a | b };
  42.     this[">>"]=function(a:Number, b:Number):Number{ return a>> b };
  43.     this[">>>"]=function(a:Number, b:Number):Number{ return a>>> b };
  44.     this["^"]=function(a:Number, b:Number):Number{ return a ^ b };
  45. }

This snippet is basically like the haskell zipWith() function. It can combines two arrays into one array given a single function. In this case I defined a bunch of operator functions, but it would work with any kind of function that takes two arguments and returns a value. You could extend this to work with strings and do other strange things I guess.

If you have yet to go play with haskell ... go do it now.

Also posted in Number, Operators, arrays, binary, misc, return values | Tagged , , , | 2 Comments

Functions as Object Review

Something I do a fair bit on this website is use functions as objects. Here is a simple example post on wonderfl. Timeline code and a brief description are available below.

Here is a still of what it generates and below you'll find the timeline as code:

Actionscript:
  1. [SWF(width = 500, height=500)]
  2.  
  3. var canvas:BitmapData = new BitmapData(800,800,false, 0x000000);
  4. addChild(new Bitmap(canvas,"auto",true));
  5. scaleX = scaleY = 500 / 800
  6.  
  7.  
  8. var walkerNum:int = 50;
  9. var walkers:Vector.<Function> = new Vector.<Function>(walkerNum, true);
  10.  
  11. makeWalkers();
  12. runWalkers();
  13.  
  14. function makeWalkers():void{
  15.     for (var i:int = 0; i<walkerNum; i++){
  16.         walkers[i] = makeWalker();
  17.     }
  18. }
  19. function runWalkers():void{
  20.     addEventListener(Event.ENTER_FRAME, onRun);
  21. }
  22. function onRun(evt:Event):void{
  23.     for (var i:int = 0; i<walkerNum; i++){
  24.         walkers[i]();
  25.     }
  26. }
  27.  
  28. function makeWalker(xp:Number=400, yp:Number=400):Function{
  29.     var x:Number = xp, y:Number = yp;
  30.     var rad:Number = Math.random() * 4;
  31.     var theta:Number = Math.random() * Math.PI * 2;
  32.     var speed:Number = 0.01 * Math.random() * 2
  33.     if (int(Math.random() * 2) == 1){
  34.         speed *= -1;
  35.     }
  36.     return function():void{
  37.         x += rad * Math.cos(theta);
  38.         y += rad * Math.sin(theta);
  39.         theta += speed
  40.         if (int(Math.random() * 100) == 1){
  41.             theta = Math.random() * Math.PI * 2;
  42.         }
  43.         if (x> 800 || x <0 || y> 800 || y <0){
  44.             x = xp, y = yp;
  45.         }
  46.         canvas.setPixel(x, y, 0xFFFFFF);
  47.     }
  48. }

The basic trick is to have a function return a function. The original function initializes typed local variables and the returned function has access to these values. This is one of many ways to do OOP style coding using functions alone. This is really only for fun and for speed coding reasons - it's worth noting that this method is is significantly slower than using actual classes. I still have lots of fun with it despite the downsides.

Also posted in BitmapData | Tagged , , | 7 Comments

Bracket Syntax Reminder

If you haven't looked at every post on this site it's possible you've missed one of my favorite actionscript features.... Bracket Syntax:

Actionscript:
  1. var s:Sprite = Sprite(addChild(new Sprite()));
  2. s["x"] = 100;
  3. s["y"] = 100;
  4.  
  5. s["graphics"]["beginFill"](0xFF0000);
  6. s["graphics"]["drawCircle"](0,0,10);
  7.  
  8. this["addChild"](s);

If you don't realize how powerful this is then there is something wrong with you (joking). If you don't see how powerful this is, take some time and think about it. You can use it to avoid lots of annoying repetitive code in state machines for instance. It's always important to keep things readable if you decide to go this route on a real project.

[EDIT ....and as Quasimondo mentioned there is a notable performance hit when using this syntax. So don't forget to keep that in mind.]


Here is a very old post showing some of the power of this trick.

Also posted in dynamic | Tagged , , | 4 Comments

Polar Coordinates Distribution

If you're at all interested in watching me free from code. I recorded a video of me coding this snippet (which is about 11 minutes long or so).

In the video I create a few functions that allow you to draw shapes like these:

Mathematically this stuff is really simple ... the free form nature of the video takes a less technical perspective as you'll see (I even made a few funny mistakes).



Actionscript:
  1. [SWF(width = 600, height = 600)]
  2. var dotNum:int = 1000;
  3. var dotRad:Number = 0.5;
  4.  
  5. x = 120
  6. y = 100;
  7.  
  8. // extra stuff to display what the functions can do
  9. stage.addEventListener(MouseEvent.CLICK, onDrawAll);
  10.  
  11. function onDrawAll(evt:Event):void{
  12.     graphics.clear();
  13.     for (var i:int = 0; i<16; i++){
  14.         var m:Number;
  15.    
  16.         var rad:Number = 120;
  17.         var xp:Number = i % 4 * rad
  18.         var yp:Number = int(i / 4) * rad
  19.    
  20.         var type:int = int(Math.random() * 4);
  21.         if (type == 0){
  22.           makeShape(xp, yp, rad-60, Math.random() , 1);
  23.         }else if (type == 1){
  24.            makeShape(xp, yp, rad-60, 1,  Math.random());
  25.         }
  26.         else if (type == 2){
  27.            m = Math.random() * 2;
  28.            makeShape(xp, yp, rad-Math.random()*120, m, m);
  29.         }
  30.         else if (type == 3){
  31.            m = Math.random() * 2;
  32.            makeShape(xp, yp, rad-Math.random()*120, m, m/2);
  33.         }
  34.     }
  35. }
  36.  
  37. // main part from the video
  38. function makeShape(xp:Number, yp:Number,
  39.                    maxRad:Number = 100,m0:Number=1,
  40.                    m1:Number=1):void{
  41.     var polarX:Number;
  42.     var polarY:Number;
  43.     var radius:Number;
  44.     graphics.lineStyle(0, 0);
  45.     var theta:Number = Math.random() * Math.PI * 2;
  46.     for (var i:int = 0; i<dotNum; i++){
  47.         radius = Math.random() * maxRad
  48.         polarX = xp + radius * Math.cos(theta * m0);
  49.         polarY = yp + radius * Math.sin(theta * m1);
  50.         theta += 0.1;
  51.          
  52.         makeDot(polarX, polarY);
  53.        
  54.     }
  55. }
  56.  
  57. function makeDot(xp:Number, yp:Number, fillColor:uint = 0x000000):void{
  58.     graphics.beginFill(fillColor);
  59.     graphics.drawCircle(xp, yp, dotRad);
  60.     graphics.endFill();
  61. }

Here it is over at wonderf:

Also posted in Graphics, Math, misc | Tagged , , | 4 Comments

Array map

Actionscript:
  1. var a:Array = [1,2,3,4,5,6];
  2. var double:Array = a.map(function():int{return arguments[0] * 2});
  3. trace(double);
  4. /*outputs:
  5. 2,4,6,8,10,12
  6. */

A condensed example of Array.map()

Here is the same thing written in haskell:

a = [1,2,3,4,5,6]
double = map (*2) a

main = print double
Also posted in arrays | Tagged , , | Leave a comment

Recursive Countdown

Actionscript:
  1. loop(20);
  2.  
  3. function loop(i:int):void {
  4.     if (i <0) return;
  5.       trace(i);
  6.       loop(i - 1);
  7. }
  8.  
  9. /* outputs:
  10. 20
  11. 19
  12. 18
  13. 17
  14. 16
  15. 15
  16. 14
  17. 13
  18. 12
  19. 11
  20. 10
  21. 9
  22. 8
  23. 7
  24. 6
  25. 5
  26. 4
  27. 3
  28. 2
  29. 1
  30. 0
  31. */

This snippet uses a recursive function to count down from some number. Recursion is pretty useless in actionscript, it will eventually cause an error... If you were to try to countdown from a higher number it would choke pretty fast...

Been writing haskell lately so I have recursion on the brain.

Also posted in misc | Tagged , , | 7 Comments

Functions Returning Functions

Actionscript:
  1. var connect:Function = function(xp:Number, yp:Number, col:uint=0):Function{
  2.     graphics.lineStyle(0,col);
  3.     graphics.moveTo(xp, yp);
  4.     var line:Function = function(xp:Number, yp:Number):Function{
  5.         graphics.lineTo(xp, yp);
  6.         return line;
  7.     }
  8.     return line;
  9. }
  10.  
  11. // draw a triangle
  12. connect(200,100)(300,300)(100,300)(200, 100);
  13.  
  14. // draw a box
  15. connect(100,100, 0xFF0000)(150,100)(150,150)(100, 150)(100,100);

This is one of those techniques that I never really get tired of. It's pretty useless, but fun to play around with every now and then. This draws the somewhat boring looking picture below:

[EDIT]
A few people pointed out that this could be simplified with arguments.callee... So here is an example... it does the same thing as the original code...

Actionscript:
  1. var connect:Function = function(xp:Number, yp:Number, col:uint=0):Function{
  2.     graphics.lineStyle(0,col);
  3.     graphics.moveTo(xp, yp);
  4.     return function(xp:Number, yp:Number):Function{
  5.         graphics.lineTo(xp, yp);
  6.         return arguments.callee;
  7.     }
  8. }

Also posted in misc | Tagged , , | 6 Comments

JS Sketch Experiment

Actionscript:
  1. [SWF(width=950, height=600)]
  2. with (graphics) beginFill(0xefefef), drawRect(0,0,stage.stageWidth, stage.stageHeight);
  3. var btn:Sprite = Sprite(addChild(new Sprite()));
  4. with (btn.graphics) beginFill(0x666666), drawRect(0,0,100,20);
  5. with(btn)  x=320, y=430, buttonMode = true;
  6. btn.addEventListener(MouseEvent.ROLL_OVER, function():void{
  7.   with(btn.graphics) clear(), beginFill(0x222222), drawRect(0,0,100,20);
  8. });
  9. btn.addEventListener(MouseEvent.ROLL_OUT, function():void{
  10.   with(btn.graphics) clear(), beginFill(0x666666), drawRect(0,0,100,20);
  11. });
  12. btn.addEventListener(MouseEvent.CLICK, function():void{
  13.     var res:*= ExternalInterface.call("function(){ plot=[]; colors=[]; " + txt.text + " return {plot:plot, colors:colors};}");
  14.     render((res == null) ? {plot:[], colors:[]} : res);
  15. });
  16.  
  17. var v:Shape = Shape(addChild(new Shape()));
  18. v.x = 700;
  19. v.y = 220;
  20. function render(obj:Object):void{
  21.     var plot:Array = obj.plot;
  22.     var colors:Array = obj.colors;
  23.     var leng:int = plot.length;
  24.     v.graphics.clear();
  25.     var inc:int = 0;
  26.     v.graphics.moveTo(plot[0], plot[1]);
  27.     for (var i:int = 2; i<leng; i+=2){
  28.         v.graphics.lineStyle(0,colors[inc++]);
  29.         v.graphics.lineTo(plot[i], plot[i + 1]);
  30.     }
  31. }
  32.  
  33.  
  34. var submit:TextField = TextField(btn.addChild(new TextField()));
  35. submit.defaultTextFormat = new TextFormat("_sans", 12);
  36. with(submit) textColor=0xFFFFFF, width=100, autoSize="center";
  37. with(submit) mouseEnabled = false,  text="submit";
  38.  
  39. var txt:TextField = TextField(addChild(new TextField()));
  40. with(txt) x = y = 20, type = "input", multiline=true;
  41. with(txt) width = 400, height = 400, border = true, background = 0xFFFFFF;
  42. txt.defaultTextFormat = new TextFormat("Monaco", 12);
  43. txt.text = "enter text";
  44. txt.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
  45. function onDown(evt:MouseEvent):void{
  46.     txt.text = "";
  47.     txt.removeEventListener(MouseEvent.MOUSE_DOWN, onDown);
  48. }

This snippet is a mini code editor that allows the user to write javascript into a textfield - the javascript is then run using external interface. Optionally the javascript code can populate two arrays (plot and colors). If these arrays are populated flash, will render the data in each array using the Graphics class.

Have a look at the demo:

If you do something nice with this... post your javascript snippet as a comment and I'll add it to the JS Sketch page...

Also posted in Graphics, Math, dynamic, external data | Tagged , , , | Leave a comment

ActionScript Eval (well, not really)

Actionscript:
  1. var txt:TextField = TextField(addChild(new TextField()));
  2. txt.autoSize = TextFieldAutoSize.LEFT;
  3.  
  4. var myVar:Number = 100;
  5. // works as an expression parser
  6. txt.text = js("return (" + myVar + " * 2 + 10) / 2");
  7. txt.appendText("\n\n");
  8.  
  9. // parses javascript
  10. txt.appendText(js("var a = []; for (var i = 0; i<10; i++){ a.push(i) } return a;"));
  11.  
  12. function js( data:String ):*{
  13.    var res:*= ExternalInterface.call("function(){" + data + "}");
  14.    return (res == null) ? "null" : res;
  15. }

This one made my day - CAN'T believe I never thought of it before... haven't done any speed tests yet... but it shows how to use ExternalInterface.call to parse math expressions and javascript code. This will only work when the swf is shown in an html page of course... so if your in flash cmd+f12...

I got the idea from this code snippet... which actually has an error in it... the decode() function should not return void... I found that snippet thanks to this tweet by makc3d.

Also posted in Math, external data, misc, string manipulation, strings | Tagged , , | Leave a comment