Category Archives: functions

Recursive 2D Structure

Actionscript:
  1. [SWF(width = 600, height = 700, frameRate=24)]
  2. var canvas:BitmapData = new BitmapData(stage.stageWidth,stage.stageHeight,false, 0xFFFFFF);
  3. addChild(new Bitmap(canvas));
  4.  
  5. var maxBranches:int = 600;
  6. var branches:int = 0;
  7. var startX:Number = 300
  8. makeBranch(startX,690,30,-60, 60);
  9.  
  10. function makeBranch(xp:Number, yp:Number, step:Number, min:Number, max:Number):void {
  11.     var vectors:Shape = Shape(addChild(new Shape()));
  12.     var cX:Number, cY:Number, eX:Number, eY:Number
  13.     var dcX:Number=xp, dcY:Number=yp, deX:Number=xp, deY:Number=yp;
  14.     var theta:Number = (min + Math.random()*(max-min) - 90) * Math.PI / 180;
  15.     cX = xp + step * Math.cos(theta);
  16.     cY = yp + step * Math.sin(theta);
  17.     theta = (min + Math.random()*(max-min)-90) * Math.PI / 180;
  18.     eX = cX + step * Math.cos(theta);
  19.     eY = cY + step * Math.sin(theta);
  20.     var run:Function = function():void{
  21.          dcX +=  (cX - dcX) / 2;
  22.          dcY +=  (cY - dcY) / 2;
  23.          deX +=  (eX - deX) / 8;
  24.          deY +=  (eY - deY) / 8;
  25.          with(vectors.graphics){
  26.               clear();
  27.               beginFill(0xFFFFFF,0.8);
  28.               lineStyle(0,0x000000,0.8);
  29.               moveTo(startX, yp);
  30.               lineTo(xp, yp);
  31.               curveTo(dcX, dcY, deX, deY);
  32.               lineTo(startX, deY);
  33.          }
  34.          if (Math.abs(dcX - cX) <1 && Math.abs(deX - eX) <1 && Math.abs(dcY - cY) <1 && Math.abs(deY - eY) <1){
  35.              canvas.draw(vectors);
  36.              removeChild(vectors);
  37.              if (branches <maxBranches){
  38.                  setTimeout(makeBranch, 10, deX, deY, step - Math.random(), -90, 90);
  39.                  branches++;
  40.                  if (int(Math.random()*2) == 1){
  41.                     setTimeout(makeBranch, 10, deX, deY, step - Math.random()*3, -90, 90);
  42.                     branches++;
  43.                  }
  44.              }
  45.          }else{
  46.              setTimeout(arguments.callee,  1000 / 24);
  47.          }
  48.     }();
  49. }

This snippet uses a technique similar to what you might use to create a recursive tree. A bit of additional logic is added for bezier branches, filled shapes and animation.

WARNING: may run slow on older machines

Have a look at the swf...

Also posted in BitmapData, bezier, misc, motion | Tagged , , | 7 Comments

Counter Function

Actionscript:
  1. var counter:Function = function(count:Array):Function{
  2.     var leng:int = count.length;
  3.     var index:int = 0;
  4.     return counter = function(reset:*=""):Function{
  5.         if (reset=="reset"){
  6.             index = 0;
  7.             return counter;
  8.         }else
  9.         if (reset is Array){
  10.             count = reset;
  11.             return counter;
  12.         }
  13.         trace(count[index % leng]);
  14.         index++;
  15.         return counter;
  16.     }
  17. }
  18.  
  19. // first time it's called you pass an array
  20. trace("count through the array:");
  21. // you can optionally call trigger the counter by calling the newly
  22. // returned function
  23. counter(["a","b","c"])();
  24. counter();
  25. counter();
  26. trace("change the array:");
  27. // here we choose to simply set the array and not trigger the counter
  28. counter([10,20,40,60,80]);
  29. counter();
  30. counter()
  31. trace("reset the counter:");
  32. // reset and the counter is called 3 times
  33. counter("reset")()()();
  34.  
  35. /*outputs :
  36. count through the array:
  37. a
  38. b
  39. c
  40. change the array:
  41. 10
  42. 20
  43. reset the counter:
  44. 10
  45. 20
  46. 40
  47. */

Today I felt like messing around with functions and this is the result. This snippet shows a strange and interesting technique to create a function that iterates through a given array in a few different ways.

I believe the technical term for this kind of thing is a continuation...

There are a bunch of other posts like this on actionsnippet. Some are purely experimental, others are actually quite useful... these can all be found in the functions category.

Also posted in dynamic | Tagged , , | Leave a comment

Instantiate and Set Properties

Actionscript:
  1. function create(obj:Class, props:Object):*{
  2.     var o:* = new obj();
  3.     for (var p:String in props){
  4.         o[p] = props[p];
  5.     }
  6.     return o;
  7. }
  8.  
  9. // test out the function
  10.  
  11. var txt:TextField = create(TextField, {x:200, y:100, selectable:false, text:"hello there", textColor:0xFF0000, defaultTextFormat:new TextFormat("_sans", 20)});
  12. addChild(txt);
  13.  
  14. var s:Sprite = Sprite(addChild(create(Sprite, {x:100, y:100, rotation:45, alpha:.5})));
  15.  
  16. with (s.graphics) beginFill(0xFF0000), drawRect(-20,-20,40,40);
  17.  
  18. var blur:BlurFilter = create(BlurFilter, {blurX:2, blurY:8, quality:1});
  19.  
  20. s.filters = [blur];

This snippet shows a function called create() that takes two arguments. The first argument is the name of a class to instantiate. The second is an Object with a list of properties to set on a newly created instance of the class (referenced in the first argument).

This could be particularly useful for TextFields which for some reason have no arguments in their constructor.

This will currently only work for classes that have either all optional constructor arguments or no constructor arguments.

Also posted in dynamic, one-liners, properties | Tagged , | Comments closed

Object Argument w/ Defaults

Actionscript:
  1. var boxDefaults:Object = {x:10, y:10, width:100, height:100, lineThickness:0, lineColor:0x000000, lineAlpha:1, fillColor:0xCCCCCC, fillAlpha:1}
  2. function drawBox(params:Object=null):void {
  3.     var p:Object=setDefaults(boxDefaults, params);
  4.     graphics.lineStyle(p.lineThickness, p.lineColor, p.lineAlpha);
  5.     graphics.beginFill(p.fillColor, p.fillAlpha);
  6.     graphics.drawRect(p.x, p.y, p.width, p.height);
  7. }
  8.  
  9. function setDefaults(defaults:Object, params:Object=null):Object {
  10.     if (params==null) {
  11.         params = new Object();
  12.     }
  13.     for (var key:String in defaults) {
  14.         if (params[key]==null) {
  15.             params[key]=defaults[key];
  16.         }
  17.     }
  18.     return params;
  19. }
  20.  
  21. // test it out... notice that all object properties are optional and have default values                                         
  22. drawBox();
  23.  
  24. drawBox({x:200, y:200, lineColor:0xFF0000, lineThickness:2, fillColor:0xCCCC00});
  25.  
  26. drawBox({x:200, y:320, width:50, height:150, lineAlpha:0, fillColor:0x416CCF});

This is a technique I've been using recently... inspired by tweening engines. I find this to be suitable when a function or object constructor has lots and lots of arguments (80% of the time if I have a function or object constructor with too many arguments I re-think my design, but every now and then I use this technique).

Basically, the function or object constructor takes one argument of type Object - once passed into the function this Object argument is passed to the setDefault() function which populates it with any properties that it's missing - each property has a default value. As a result you end up with an easy to read function call with a variable number of arguments and well thought out default values.

This snippet just draws a box (not very interesting or usefull) - I wanted to showcase the technique using a simple function. As a real world example... I recently used this technique in a mini-library I created for use with Box2D... will be posting the library in the next few days.... it's a library for fast prototyping and custom rendering.

Also posted in dynamic | Tagged , | 3 Comments

Function Chaining & Classes

Actionscript:
  1. package {
  2.     import flash.display.Sprite;
  3.     public class Chaining extends Sprite{
  4.         public function Chaining(){
  5.               print(n(100).divide(2).plus(2));
  6.               // outputs 52              
  7.               print(n(100).plus(n(10).multiply(2)));
  8.               // outputs 120
  9.         }
  10.     }
  11. }
  12.  
  13. function print(n:Num):void{
  14.    trace(n.getValue());
  15. }
  16. function n(n:Number):Num{
  17.    return new Num(n);
  18. }
  19.  
  20. class Num{
  21.     private var value:Number;
  22.    
  23.     public function Num(n:Number):void{
  24.        value = n;
  25.     }
  26.     private function convert(n:*):Number{
  27.         if (n is Num) n = n.getValue();
  28.         return n;
  29.     }
  30.     public function getValue():Number{
  31.         return value;
  32.     }
  33.     public function plus(n:*):Num{
  34.         n = convert(n);
  35.         value += n;
  36.         return this;
  37.     }
  38.     public function minus(n:*):Num{
  39.         n = convert(n);
  40.         value -= n;
  41.         return this;
  42.     }
  43.     public function multiply(n:*):Num{
  44.         n = convert(n);
  45.         value *= n;
  46.         return this;
  47.     }
  48.     public function divide(n:*):Num{
  49.         n = convert(n);
  50.         value /= n;
  51.         return this;
  52.     }
  53. }

This snippet is meant to be run as a document class. It shows how one might go about designing a class to make extensive use of function chaining.

Also posted in OOP | Tagged , | 2 Comments

var obj:Object = new Function()

Actionscript:
  1. var Pnt:Function = function(xp:Number, yp:Number){
  2.    
  3.     var x:Number = xp;
  4.     var y:Number = yp
  5.    
  6.     this.setX = function(v:int):void{
  7.         x = v;
  8.     }
  9.     this.setY = function(v:int):void{
  10.         y = v;
  11.     }
  12.     this.getX = function():int {
  13.         return x;
  14.     }
  15.     this.getY = function():int {
  16.         return y;
  17.     }
  18. }
  19.  
  20. var p:Object = new Pnt(10,10);
  21.  
  22. trace(p.getX(), p.getY());
  23. p.setX(100);
  24. trace(p.getX());
  25.  
  26. /*
  27. outputs:
  28. 10, 10
  29. 100
  30. */

Another way to define and instantiate Objects on the timeline. Interesting, but I don't recommend it over actual classes...

Also posted in OOP, Object | Tagged , | Leave a comment

Interesting Function Composition

Actionscript:
  1. var multBy2Add3:Function = add(3, mult(2));
  2.  
  3. trace(multBy2Add3(10));
  4. // 10 * 2  = 20
  5. //  20 + 3 = 23
  6.  
  7. var add2AndSquare = sq(add(2));
  8.  
  9. trace(add2AndSquare(8));
  10. // 8 + 2 = 10
  11. // 10 * 10 = 100
  12.  
  13. var multBy2_3times:Function = repeat(3,mult(2));
  14.  
  15. trace(multBy2_3times(3));
  16. // 3 * 2 = 6;
  17. // 6 * 2 = 12;
  18. // 12 * 2 = 24
  19.  
  20. // you can also chain for even less readability
  21. trace(sq(mult(5,add(1)))(4));
  22. // 4 + 1 = 5
  23. // 5 * 5 = 25;
  24. // 25 * 25 = 625;
  25.  
  26. /*
  27. outputs:
  28. 12
  29. 100
  30. 24
  31. 625
  32. */
  33.  
  34. // function  composition
  35. const F:Function = function(a:*):*{return a};
  36. function mult(scalar:Number, f:Function=null):Function{
  37.     if (f == null) f = F;
  38.      return function(n:Number){
  39.         return f(n) * scalar;
  40.     }
  41. }
  42.  
  43. function add(off:Number, f:Function=null):Function{
  44.      if (f == null) f = F;
  45.      return function(n:Number){
  46.         return f(n) + off;
  47.     }
  48. }
  49. function sq(f:Function=null):Function{
  50.      if (f == null) f = F;
  51.      return function(n:Number){
  52.          var v:Number = f(n);
  53.         return  v * v;
  54.     }
  55. }
  56. function repeat(times:int, f:Function):Function {
  57.      if (f == null) f = F;
  58.      return function (n:Number){
  59.          var v:Number = n;
  60.          for (var i:int = 0; i<times; i++) v = f(v);
  61.          return v;
  62.      }
  63. }

The above shows some interesting function composition... this demo contains the following functions:

mult();
add();
sq();
repeat();

These functions are designed to be combined to create new functions.

Also posted in Math | Tagged , | Leave a comment

more(nesting(functions(graphDrawing)));

Actionscript:
  1. [SWF(width=800, height=600)]
  2.  
  3. var canvas:Graphics;
  4. var graphData:Array = sineData();
  5.  
  6. var graph0:Shape = Shape(addChild(new Shape()));
  7. graph0.x = 50;
  8. graph0.y = 150;
  9.  
  10. var graph1:Shape = Shape(addChild(new Shape()));
  11. graph1.x = 400;
  12. graph1.y = 150;
  13.  
  14. var graph2:Shape = Shape(addChild(new Shape()));
  15. graph2.x = 50;
  16. graph2.y = 400;
  17.  
  18. // use graphData to draw 3 different looking graphs:
  19.  
  20. canvas = graph0.graphics;
  21. axis(lines(graphData));
  22.  
  23. canvas = graph1.graphics;
  24. axis(dots(graphData, 0xFF0000), 0xFFCC00, 2);
  25.  
  26. canvas = graph2.graphics;
  27. axis(dots(dots(lines(lines(graphData, 0xCCCCCC, 20))), 0x0022FF, 0, 4), 0xFF);
  28.  
  29.  
  30. // generate data
  31. function sineData():Array{
  32.     var dat:Array = new Array();
  33.     for (var i:int = 0; i<60; i++){
  34.         dat.push(new Point(i * 4,  (30 + i) * Math.sin(i * 24 * Math.PI/180)));
  35.     }            
  36.     return dat;
  37. }
  38.  
  39. // render lines
  40. function lines(dat:Array, col:uint=0x000000, thick:Number=0):Array{
  41.     canvas.lineStyle(thick, col);
  42.     canvas.moveTo(dat[0].x, dat[0].y)
  43.     for (var i:int = 1; i<dat.length; i++){
  44.          canvas.lineTo(dat[i].x, dat[i].y);
  45.     }
  46.     return dat;
  47. }
  48.  
  49. // render dots
  50. function dots(dat:Array, col:uint=0xFF0000, thick:Number=0, rad:Number=1.5):Array{
  51.     canvas.lineStyle(thick, col);
  52.     for (var i:int = 0; i<dat.length; i++){
  53.          canvas.drawCircle(dat[i].x, dat[i].y, rad);
  54.     }
  55.     return dat;
  56. }
  57.  
  58. // render graph axis
  59. function axis(dat:Array, col:uint=0x000000, thick:Number=0):Array{
  60.     var d:Array = dat.concat();
  61.     d.sortOn("y", Array.NUMERIC);
  62.     var lastIndex:int = d.length - 1;
  63.     var minY:Number = d[0].y;
  64.     var maxY:Number = d[lastIndex].y;
  65.     d.sortOn("x", Array.NUMERIC);
  66.     var minX:Number = d[0].x;
  67.     var maxX:Number = d[lastIndex].x;
  68.     canvas.lineStyle(thick, col, .2);
  69.     canvas.moveTo(minX, 0);
  70.     canvas.lineTo(maxX, 0);
  71.     canvas.lineStyle(thick, col);
  72.     canvas.moveTo(minX, minY);
  73.     canvas.lineTo(minX, maxY);
  74.     canvas.lineTo(maxX, maxY);
  75.     return dat;
  76. }

This is something I've been meaning to post for awhile. Finally had time to write it today... It contains functions that are designed to be nested for the purpose of rendering a small data set in a few different ways...

The upper left image is rendered with axis labels and lines... and it defaults to the color black (line 21):

axis(lines(graphData));

The upper right image is rendered with yellow axis and red dots (line 24):

axis(dots(graphData, 0xFF0000), 0xFFCC00, 2);

etc... (line 27)
axis(dots(dots(lines(lines(graphData, 0xCCCCCC, 20))), 0x0022FF, 0, 4), 0xFF);

Alternatively you could write each function call on one line:

lines(graphData, 0xCCCCCC, 20);
lines(graphData);
dots(graphData);
dots(graphData, 0x0022FF, 0, 4)
axis(graphData, 0xFF);

NOTE: If you think this post is insane, please read the warning page of this site...

Also posted in Graphics, misc | Tagged , | Leave a comment

Object.constructor()

Actionscript:
  1. var Box:Function = {
  2.     constructor : function(color:uint, w:Number, h:Number):void {
  3.         this.color = color;
  4.         this.s = new Shape();
  5.         with(this.s.graphics) beginFill(this.color), drawRect(0,0,w,h);
  6.         addChild(this.s);
  7.        
  8.         this.setLoc = function(x:Number, y:Number):void{
  9.             this.s.x = x;
  10.             this.s.y = y;
  11.        }
  12.     }
  13. }.constructor;
  14.  
  15. var box0:Object = new Box(0xFF0000, 100, 100);
  16.  
  17. box0.setLoc(100, 10);
  18.  
  19. var box1:Object = new Box(0x000000, 50, 50);
  20.  
  21. box1.setLoc(210, 10);

This snippet makes use of Object.constructor() to allow creation of Object instances using the new keyword. This is for fun only, I don't recommend this over actual Classes.

Also posted in OOP, dynamic, misc | Tagged , | Leave a comment

Circle of Particles

Actionscript:
  1. var canvas:BitmapData = new BitmapData(400,400, false, 0xFFFFFF);
  2. addChild(new Bitmap(canvas));
  3. var eraser:BitmapData = new BitmapData(400,400, true, 0x33FFFFFF);
  4.  
  5. var particles:Array = new Array();
  6. for (var i:int = 0; i <1000; i++){
  7.     particles.push(makeParticle());
  8. }
  9.  
  10. addEventListener(Event.ENTER_FRAME, onLoop);
  11. function onLoop(evt:Event):void {
  12.     canvas.copyPixels(eraser, eraser.rect, new Point(0,0), null, null, true);
  13.     for (var i:int = 0; i <particles.length; i++){
  14.         particles[i]();
  15.     }
  16. }
  17.  
  18. function makeParticle():Function {
  19.     var dx:Number, dy:Number;
  20.     var x:Number = 200;
  21.     var y:Number = 200;
  22.     var vx:Number = Math.random() * 4 - 2;
  23.     var vy:Number = Math.random() * 4 - 2;
  24.     return function():void {
  25.               x += vx;
  26.               y += vy;
  27.               dx = x - 200;
  28.               dy= y - 200;
  29.                if (Math.sqrt((dx * dx) + (dy * dy))> 100){
  30.                  vx *= -1;
  31.                  vy *= -1;
  32.                }
  33.                canvas.setPixel(x, y, 0x000000);
  34.     }
  35. }

This creates a circular area filled with moving particles/pixels. It makes use of yesterdays functional programming techniques.

Also posted in BitmapData, motion, setPixel | Tagged , | Leave a comment