Monthly Archives: April 2009

Pendulums

Actionscript:
  1. var mouseSpeedX:Number = 0;
  2. var prevX:Number = 0;
  3.  
  4. var pends:Array = new Array();
  5. for (var i:int = 0; i<10; i++){
  6.        pends.push(makePendulum(100+ i * 40, 100, 15, 100 + i * 10));
  7. }
  8.  
  9. addEventListener(Event.ENTER_FRAME, onRun);
  10. function onRun(evt:Event):void {
  11.        // mouseSpeed
  12.        mouseSpeedX = prevX - mouseX;
  13.        prevX = mouseX;
  14.  
  15.        for (var i:int = 0; i<pends.length; i++) pends[i]();
  16. }
  17.  
  18. function makePendulum(xp:Number, yp:Number, rad:Number, leng:Number):Function {
  19.        var rot:Number = 0;
  20.        var rotDest :Number = 0;
  21.        var rotVel:Number = 0
  22.        var string:Shape = Shape(addChild(new Shape()));
  23.        var ball:Sprite = Sprite(addChild(new Sprite()));
  24.        ball.buttonMode = true;
  25.        with(ball.graphics) beginFill(0xFF0000), drawCircle(0,leng, rad);
  26.        ball.x = xp;
  27.        ball.y = yp;
  28.        string.x = ball.x;
  29.        string.y = ball.y;
  30.        ball.addEventListener(MouseEvent.ROLL_OVER,function(){
  31.              rotDest = mouseSpeedX;
  32.        });
  33.        return function(){
  34.            // force rotDest back to 0
  35.            rotDest *= .8;
  36.                // elasticity (hooke's)
  37.                rotVel += (-1.9 * (rot - rotDest) - rotVel) / 4;
  38.                rot += rotVel
  39.                ball.rotation = rot;
  40.                // draw string:
  41.                string.graphics.clear();
  42.                string.graphics.lineStyle(0,0);
  43.                var pnt:Point = ball.localToGlobal(new Point(0, leng))
  44.                string.graphics.curveTo(0, leng / 2, pnt.x - ball.x, pnt.y-ball.y);
  45.   }
  46. }

This is a variation on something I wrote in response to a student question. It creates a few pendulums that can be pushed with the mouse.

Posted in motion | Tagged , | 5 Comments

Dynamic Shapes

Actionscript:
  1. // build some functions:
  2. var redGradient:Function = sl(16, add(100, mult(5)));
  3.  
  4. // grid positioning
  5. var xPos:Function = add(50, mult(30, cInt(div(4))));
  6. var yPos:Function = add(50, mult(30, mod(4)));
  7.  
  8. // create some shapes:
  9. var shapes:Array = createShapes(this, 22, [["beginFill", 0xCCCCCC], ["drawCircle", 0, 0, 10], ["endFill"], ["lineStyle",1, redGradient], ["drawRect", -5, -5, 10, 10]], {x:yPos, y:xPos, rotation:mult(10)});
  10.                                                                  
  11. function createShapes(par:DisplayObjectContainer,  num:Number,
  12.                                          funcs:Array, props:Object):Array {
  13.     var shapes:Array = [];
  14.     for (var i:int = 0; i<num; i++){
  15.         shapes[i] = par.addChild(new Shape());
  16.         for (var j:int = 0; j<funcs.length; j++) {
  17.             var a:Array = funcs[j].concat();
  18.             for (var k:int = 0; k<a.length; k++){
  19.                 if (a[k] is Function){
  20.                     a[k] = a[k](i);
  21.                 }
  22.             }
  23.             for (var key:String in props){
  24.                 var v:* = props[key];
  25.                 if (v is Function){
  26.                   shapes[i][key] = v(i);
  27.                 }else{
  28.                   shapes[i][key] = v;
  29.                 }
  30.             }
  31.             shapes[i].graphics[a[0]].apply(shapes[i].graphics, a.slice(1));
  32.         }
  33.     }
  34.     return shapes;
  35. }
  36.  
  37. // function building blocks
  38. const F:Function = function(a:*):*{return a};
  39.  
  40. function cInt(f:Function=null):Function{
  41.     if (f == null) f = F;
  42.     return function(n:Number):Number {
  43.         return int(f(n));
  44.     }
  45. }
  46.  
  47. function mod(m:Number, f:Function=null):Function{
  48.     if (f == null) f = F;
  49.     return function(n:Number):Number {
  50.         return f(n) % m;
  51.     }
  52. }
  53.  
  54. function div(d:Number, f:Function=null):Function{
  55.     if (f == null) f = F;
  56.     return function(n:Number):Number {
  57.         return f(n) / d;
  58.     }
  59. }
  60.  
  61. function mult(scalar:Number, f:Function=null):Function{
  62.     if (f == null) f = F;
  63.      return function(n:Number):Number {
  64.         return f(n) * scalar;
  65.     }
  66. }
  67.  
  68. function add(off:Number, f:Function=null):Function{
  69.      if (f == null) f = F;
  70.      return function(n:Number):Number {
  71.         return f(n) + off;
  72.     }
  73. }
  74. // shift left
  75. function sl(amount:int, f:Function=null):Function{
  76.      if (f == null) f = F;
  77.      return function(n:Number):Number {
  78.         return f(n) <<amount
  79.     }
  80. }

This is an unusual snippet I wrote a couple weeks back.... not sure where I was going with this really... has some interesting ideas in it.

Posted in misc | Tagged , | Leave a comment

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.

Posted in dynamic, functions | Tagged , | 3 Comments

Drawing Gears

Actionscript:
  1. const TWO_PI:Number=Math.PI*2;
  2. // x, y, max radius, notch number
  3. drawVerts(calcGear(200, 200, 50, 9));
  4.  
  5. drawVerts(calcGear(400, 200, 30, 3));
  6.  
  7. drawVerts(calcGear(300, 350, 30, 5));
  8.  
  9. drawVerts(calcGear(400,400, 30, 2));
  10.  
  11. function calcGear(x:Number, y:Number, maxRad:Number, s:int):Array {
  12.     var verts:Array = new Array();
  13.     var step:Number=TWO_PI / (s * 4);
  14.     var mod:Number=0;
  15.     for (var i:Number = 0; i<=TWO_PI; i+=step) {
  16.         var r:Number = (int(mod)%2+1) * maxRad;
  17.         mod+=.5;
  18.         verts.push(x + r * Math.cos(i));
  19.         verts.push(y + r * Math.sin(i));
  20.     }
  21.     return verts;
  22. }
  23.  
  24. // could  use draw path here instead;
  25. function drawVerts(verts:Array):void{
  26.     graphics.lineStyle(0,0x000000);
  27.     graphics.moveTo(verts[0], verts[1]);
  28.     for (var i:int = 2; i<verts.length; i+=2) {
  29.         graphics.lineTo(verts[i], verts[i + 1]);
  30.     }
  31.     graphics.lineTo(verts[0], verts[1]);
  32. }

Needed to draw some gear shapes today...

Posted in Graphics | Tagged , | Leave a comment