Monthly Archives: November 2009

Float as a Fraction

Actionscript:
  1. // print some floats as fractions
  2. printFraction(0.5);
  3. printFraction(0.75);
  4. printFraction(0.48);
  5.  
  6. // try something a little more complex
  7. var float:Number = 0.98765432;
  8. trace("\na more complex example:");
  9. printFraction(float);
  10. var frac:Array = asFraction(float);
  11. trace("double check it:");
  12. trace(frac[0] + "/" + frac[1] +" = " + frac[0] / frac[1]);
  13.  
  14. /* outputs:
  15. 0.5 = 1/2
  16. 0.75 = 3/4
  17. 0.48 = 12/25
  18.  
  19. a more complex example:
  20. 0.98765432 = 12345679/12500000
  21. double check it:
  22. 12345679/12500000 = 0.98765432
  23. */
  24.  
  25.  
  26. function printFraction(n:Number):void{
  27.     var frac:Array = asFraction(n);
  28.     trace(n + " = " + frac[0] + "/" + frac[1]);
  29. }
  30.  
  31. // takes any value less than one and returns an array
  32. // with the numerator at index 0 and the denominator at index 1
  33. function asFraction(num:Number):Array{
  34.     var decimalPlaces:int = num.toString().split(".")[1].length;
  35.     var denom:Number = Math.pow(10, decimalPlaces);
  36.     return reduceFraction(num * denom, denom);
  37. }
  38.  
  39. // divide the numerator and denominator by the GCF
  40. function reduceFraction(numerator:int, denominator:Number):Array{
  41.     // divide by the greatest common factor
  42.     var divisor:int = gcf(numerator, denominator);
  43.     if (divisor){
  44.         numerator /= divisor;
  45.         denominator /= divisor;
  46.     }
  47.     return [numerator, denominator];
  48. }
  49.                    
  50. // get the greatest common factor of two integers
  51. function gcf(a:int, b:int):int{
  52.     var remainder:int;
  53.     var factor:Number = 0;
  54.     var maxIter:int = 100;
  55.     var i:int = 0;
  56.     while (1){
  57.         if (b> a){
  58.            var swap:int = a;
  59.            a = b;
  60.            b = swap;
  61.         }
  62.         remainder = a % b;
  63.         a = b;
  64.         b = remainder
  65.         if (remainder == 0){
  66.             factor = a;
  67.             break;
  68.         }else if (remainder==1){
  69.             break;
  70.         }else if (i> maxIter){
  71.             trace("failed to calculate gcf");
  72.             break;
  73.         }
  74.         i++;
  75.     }
  76.     return factor;
  77. }

This snippet contains a few functions for calculating fractions based on float values. Writing this brought back some memories from grade school math.

Posted in Math, misc | Tagged , , | 4 Comments

Greatest Common Factor (divisor)

Actionscript:
  1. trace(gcf(75,145));
  2.  
  3. // outputs 5
  4.  
  5. function gcf(a:int, b:int):int{
  6.     var remainder:int;
  7.     var factor:Number = 0;
  8.     while (1){
  9.         if (b> a){
  10.            var swap:int = a;
  11.            a = b;
  12.            b = swap;
  13.         }
  14.         remainder = a % b;
  15.         a = b;
  16.         b = remainder
  17.         if (remainder == 0){
  18.             factor = a;
  19.             break;
  20.         }else if (remainder==1){
  21.          
  22.             break;
  23.         }
  24.     }
  25.     return factor;
  26. }

I was messing around with Egyptian Fractions and found myself in need of some interesting functions. The first function I realized I would be needing was for a greatest common factor (GCF or GCD).

The above snippet is a quick implementation of Euclid's algorithm. It will return 0 if no GCF is found...

I wrote a few helper functions while working with Egyptian fractions... will post them over the next few days.

Posted in Math | Tagged , , | 4 Comments

Ancient Egyptian Multiplication

Actionscript:
  1. egyptianMultiply(12, 99);
  2.  
  3. // trace(12 * 99) // test to make sure it works
  4.  
  5. /* outputs:
  6. /64 768
  7. /32 384
  8.  16 192
  9.  8 96
  10.  4 48
  11. /2 24
  12. /1 12
  13. ---
  14. 1188
  15. */
  16.  
  17.  
  18. function egyptianMultiply(valueA:Number, valueB:Number):void {
  19.    
  20.     var left:Array = [];
  21.     var right:Array = []
  22.    
  23.     // swap if valueB is smaller than value A
  24.     if (valueB <valueA){
  25.         var swap:int = valueB;
  26.         valueB = valueA;
  27.         valueA = swap;
  28.     }
  29.    
  30.     // create left and right columns
  31.     var currentLeft:int = 1;
  32.     var currentRight:int = valueA;
  33.    
  34.     while (currentLeft <valueB){
  35.         left.push(currentLeft);
  36.         right.push(currentRight);
  37.         currentRight += currentRight;
  38.         currentLeft += currentLeft;
  39.     }
  40.    
  41.    
  42.     // add up the right column based on the left
  43.     currentLeft = 0;
  44.     var rightSum:int;
  45.     var leftSum:int;
  46.     var i:int = left.length - 1;
  47.    
  48.     while (currentLeft != valueB){
  49.      
  50.       leftSum = currentLeft + left[i];
  51.       // if the next number causes the sum
  52.       // to go above valueB, skip it
  53.       if (leftSum <= valueB){
  54.         currentLeft = leftSum;
  55.         rightSum += right[i];
  56.         trace("/" + left[i]  + " " + right[i]);
  57.       } else {
  58.         trace(" " + left[i]  + " " + right[i]);
  59.       }
  60.       i--;
  61.     }
  62.     trace("---");
  63.     trace(rightSum);
  64. }

Someone mentioned egyptian multiplication to me yesterday... So read a little about it here and whipped up this example. For some reason I decided to do it in processing ... once it worked I ported it to ActionScript.

The above link describing the technique I used is from http://www.jimloy.com/... I haven't spent much time digging around the site, but it appears to have some pretty nice stuff on it...

If you're curious, here is the original processing version:

JAVA:
  1. Vector left = new Vector();
  2. Vector right = new Vector();
  3.  
  4. int valueA = 10;
  5. int valueB = 8;
  6.  
  7. if (valueB <valueA){
  8.     int swap = valueB;
  9.     valueB = valueA;
  10.     valueA = swap;
  11. }
  12.  
  13. int currentLeft = 1;
  14. int currentRight = valueA;
  15. while (currentLeft <valueB){
  16.     left.add(currentLeft);
  17.     right.add(currentRight);
  18.     currentRight += currentRight;
  19.     currentLeft += currentLeft;
  20. }
  21.  
  22. currentLeft = 0;
  23.  
  24. int result = 0;
  25. int i = left.size() - 1;
  26. while (currentLeft != valueB){
  27.  
  28.   int temp = currentLeft + (Integer) left.get(i);
  29.   if (temp <= valueB){
  30.    
  31.     currentLeft = temp;
  32.     result += (Integer) right.get(i);
  33.     println("/" + left.get(i) + " " + right.get(i));
  34.   } else {
  35.     println(" " + left.get(i)  + " " + right.get(i));
  36.   }
  37.    
  38.   i--;
  39. }
  40. println("---");
  41. println(result);

After writing, this I took a look at the wikipedia entry... I also found myself on this short page about a scribe called Ahmes. (I recommend reading this if you are interested in PI)

Posted in Math, misc | Tagged , , , | 1 Comment

Fp10 3d Logo

Actionscript:
  1. var container:Sprite = new Sprite();
  2. container.x = stage.stageWidth / 2;
  3. container.y = stage.stageHeight / 2;
  4. addChild(container);
  5.  
  6. var redBox:Sprite = new Sprite();
  7. redBox.graphics.beginFill(0xFF0000);
  8. redBox.graphics.drawRect(-50,-250,100,500);
  9. redBox.rotationZ = 10;
  10. container.addChild(redBox);
  11.  
  12. var logos:Array = []
  13. var elements:Array = [];
  14. elements.push({element:redBox, z:0});
  15.  
  16. // add the logos
  17. for (var i:int = 0; i<6; i++){
  18.     var logoContainer:MovieClip = new MovieClip();
  19.     var logoText:TextField = new TextField();
  20.     logoText.defaultTextFormat = new TextFormat("_sans", 50);
  21.     logoText.text = "LOGO";
  22.     logoText.autoSize = "left";
  23.     logoText.selectable= false;
  24.    
  25.     logoText.x = -logoText.width / 2;
  26.     logoText.y = -logoText.height / 2;
  27.     logoContainer.addChild(logoText);
  28.     logoText.backgroundColor = 0xFFFFFF;
  29.    
  30.     container.addChild(logoContainer);
  31.     logos.push(logoContainer);
  32.     elements.push({element:logoContainer, z:0});
  33. }
  34.  
  35. var ang:Number = -Math.PI / 2;
  36. var rotationSpeed:Number = 0.05;
  37. addEventListener(Event.ENTER_FRAME, onLoop);
  38. function onLoop(evt:Event):void {
  39.    
  40.      var dx:Number = (mouseY - stage.stageHeight / 2) / 10;
  41.      var dy:Number = (mouseX - stage.stageWidth / 2) / 10;
  42.      container.rotationX += (dx - container.rotationX) / 4;
  43.      container.rotationY += (dy - container.rotationY) / 4;
  44.      
  45.      ang += rotationSpeed;
  46.      for (var i:int = 0; i<logos.length; i++){
  47.          var logo:Sprite = logos[i];
  48.          logo.x = 150 * Math.cos(ang + i);
  49.          logo.z = 150 * Math.sin(ang + i);
  50.          logo.alpha = 1 - logo.z / 200;
  51.          logo.rotationY = -Math.atan2(logo.z, logo.x)  / Math.PI * 180  - 90;
  52.      }
  53.      
  54.      // z-sort
  55.      for (i = 0; i<elements.length; i++){
  56.           elements[i].z = elements[i].element.transform.getRelativeMatrix3D(this).position.z;
  57.      }
  58.      
  59.     elements.sortOn("z", Array.NUMERIC | Array.DESCENDING);
  60.     for (i = 0; i<elements.length; i++) {
  61.         container.addChild(elements[i].element);
  62.     }
  63. }

A student of mine was having trouble creating a 3D logo for a client. I created this snippet to help explain how some of the fp10 3D stuff works.... z-sorting etc... The code could be optimized a bit... but it works nicely...


Have a look at the swf...

Posted in 3D, misc, motion | Tagged , , , | 2 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. }

Posted in functions, misc | Tagged , , | 6 Comments

QuickBox2D Custom Debug Draw

Actionscript:
  1. import com.actionsnippet.qbox.*;
  2. import Box2D.Dynamics.*
  3.  
  4. stage.frameRate = 60;
  5.  
  6. var sim:QuickBox2D = new QuickBox2D(this, {debug:true});
  7.  
  8. // get at the b2DebugDraw instance
  9. var debug:b2DebugDraw = sim.w.m_debugDraw;
  10. debug.m_drawScale = 30.0;
  11. debug.m_fillAlpha = 0.5;
  12. debug.m_alpha = 0.5;
  13. debug.m_lineThickness = 1.0;
  14. debug.m_drawFlags = 0xFF;
  15.  
  16. sim.createStageWalls();  
  17.  
  18. for (var i:int = 0; i<10; i++){
  19.   sim.addBox({x:3 + i, y:3 + i, width:2, height:0.5});
  20. }
  21. sim.addCircle({x:12, y:5, radius:2});
  22.  
  23. sim.start();
  24. sim.mouseDrag();

Note: This snippet requires the QuickBox2D library

This snippet shows an easy way to get at the settings for Box2D's debug renderer.


Have a look at the swf...

Posted in Uncategorized | Tagged , , , , | 2 Comments

Obfuscated Slider

Actionscript:
  1. var slider:MovieClip = makeSlider();
  2. slider.addEventListener(Event.CHANGE, function(evt:Event):void{
  3.     trace(evt.currentTarget.percent);                                  
  4. });
  5.  
  6. function makeSlider():MovieClip{
  7.     var slider:MovieClip = MovieClip(addChild(new MovieClip()));
  8.     var circle:Sprite = Sprite(slider.addChild(new Sprite()));
  9.     with (circle.graphics) beginFill(0x000000), drawCircle(0,0,10);
  10.     var line:Shape = Shape(slider.addChild(new Shape()));
  11.     with (line.graphics) lineStyle(0,0x000000), lineTo(0, 100);
  12.     slider.x = slider.y = 100;
  13.     circle.addEventListener(MouseEvent.MOUSE_DOWN, function(evt:Event):void{ evt.currentTarget.startDrag(false, new Rectangle(0,0,0,100)), slider.addEventListener(Event.ENTER_FRAME, onChange) });
  14.     var stopIt:Function = function(){ stopDrag(), slider.removeEventListener(Event.ENTER_FRAME, onChange) };
  15.     stage.addEventListener(Event.MOUSE_LEAVE, stopIt);
  16.     stage.addEventListener(MouseEvent.MOUSE_UP, stopIt);
  17.     return slider;
  18. }
  19. function onChange(evt:Event):void { evt.currentTarget.percent = evt.currentTarget.getChildAt(0).y / 100, evt.currentTarget.dispatchEvent(new Event(Event.CHANGE)) }

This is a pretty nasty implementation of a basic slider. Just felt like writing some obfuscated code today... It could probably be made even more confusing with some additional tweaks...

Have a look at the swf over at wonderfl...

Posted in UI | Tagged , , | Comments closed

ActionSnippet Contest Winner

The other judge for the contest was Rich Shupe. We just reviewed the entries together and have decided on a winner....

The winner is Petri Leskinen (piXelero)

Have a look at the winning snippet if you haven't seen it already.

Rich and I thought that Kyle Phillips deserved honorable mention for his google analytics snippet.

Thanks to everyone who sent in snippets. Even though there were only a handful of submissions I had a good deal of fun reviewing and judging. I still have two more entries that I have yet to publish... so stay tuned...

Posted in misc | Tagged , , , | Leave a comment

Bounce Ball Inside a Circle

Actionscript:
  1. package  {
  2.     import flash.display.Shape;
  3.     import flash.display.Sprite;
  4.     import flash.geom.Point;
  5.  
  6.     /**
  7.      * Re: http://board.flashkit.com/board/showthread.php?t=797453
  8.      * @author makc
  9.      * @license WTFPLv2
  10.      */
  11.     public class BouncingBall extends Sprite{
  12.         public function BouncingBall () {
  13.             r = 10;
  14.             ball = new Shape;
  15.             ball.graphics.beginFill (0);
  16.             ball.graphics.drawCircle (0, 0, r);
  17.             addChild (ball);
  18.             v = new Point;
  19.             v.x = Math.random ();
  20.             v.y = Math.random ();
  21.             V = 1 + 20 * Math.random ();
  22.             v.normalize (V);
  23.             R = 200; X = 465 / 2; Y = 465 / 2;
  24.             graphics.lineStyle (0);
  25.             graphics.drawCircle (X, Y, R);
  26.             ball.x = X + 100;
  27.             ball.y = Y - 100;
  28.             addEventListener ("enterFrame", loop);
  29.         }
  30.         private var r:Number;
  31.         private var ball:Shape;
  32.         private var v:Point;
  33.         private var V:Number;
  34.         private var R:Number;
  35.         private var X:Number;
  36.         private var Y:Number;
  37.         private function loop (e:*):void {
  38.             ball.x += v.x;
  39.             ball.y += v.y;
  40.             // R-r vector
  41.             var P:Point = new Point (X - ball.x, Y - ball.y);
  42.             if (P.length> Math.sqrt ((R - r) * (R - r))) {
  43.                 // normalize R-r vector
  44.                 P.normalize (1);
  45.                 // project v onto it
  46.                 var vp:Number = v.x * P.x + v.y * P.y;
  47.                 // subtract projection
  48.                 v.x -= 2 * vp * P.x;
  49.                 v.y -= 2 * vp * P.y;
  50.                 v.normalize (V);
  51.                 // move away from bounding circle
  52.                 P = new Point (X - ball.x, Y - ball.y);
  53.                 while (P.length> Math.sqrt ((R - r) * (R - r))) {
  54.                     ball.x += v.x;
  55.                     ball.y += v.y;
  56.                     P = new Point (X - ball.x, Y - ball.y);
  57.                 }
  58.             }
  59.         }
  60.     }
  61. }

Makc3d said I could choose one of his excellent wonderfl.net pieces and submit it to the contest. This snippet creates a ball that bounces off the inside of a circle. I thought this was a pretty unique way to go about doing this - and found it easy to add gravity and other cool features to it.

Have a look at the swf over at wonderfl....

Some Makc3d links:
>> http://makc3d.wordpress.com/
>>http://code.google.com/p/makc/
>> http://wonderfl.net/user/makc3d

Makc3d elaborated on his code a bit via e-mail. He said that his technique sacrifices accuracy for simplicity... and that if you simplify too much it would be easy to break the code. "e.g. comment out piece of code where it says "move away from bounding circle""...

Here is a picture that Makc3d drew explaining why you need to multiply by 2:

Posted in motion | Tagged , , , | Comments closed

Google Analytics Utility

Actionscript:
  1. package com.hapticdata.utils
  2. {
  3.     import flash.external.ExternalInterface;
  4.     /**
  5.      * Simplifies posting to Google's Analytics Tracker, allows easily disabling for development phase
  6.      * and uses ExternalInterface rather than navigateToURL
  7.      * @class Urchin
  8.      * @author Kyle Phillips - <a href="http://www.haptic-data.com">http://www.haptic-data.com</a>
  9.      * @created October 28, 2008
  10.      * @example Analytics.post("section");
  11.      */
  12.    
  13.    
  14.     public class Analytics
  15.     {
  16.        
  17.         public static var enabled:Boolean = true;
  18.         //appended as a directory to all trackings
  19.         public static var swfID:String="/flashevent/";
  20.         //correct for default snippet. Change this if you have a custom-wrapped analytics method
  21.         public static var functionToCall:String = "pageTracker._trackPageview";
  22.        
  23.         /**
  24.          * Will invoke the set javascript function
  25.          * @param location:String - a string identifying where the user is in the site
  26.          */
  27.         public static function post(location:String):void
  28.         {
  29.             if(enabled && ExternalInterface.available)
  30.             {
  31.                 ExternalInterface.call(functionToCall,swfID+location);
  32.             }
  33.         }
  34.     }
  35. }

This contest entry by Kyle Phillips is a utility class for dealing with google analytics. If you haven't messed with google analytics I suggest you give it a try.

Kyle Phillips links:
>> http://workofkylephillips.com
>> http://labs.hapticdata.com

I usually find myself adding google analytics code in a very hacky way... usually because the client asks for it at the 11th hour. Using a class like Kyle's would enable you to simply add the tracking code from the start and then if the client doesn't ask for it... you can just keep the class disabled... or charge more when you offer google analytics tracking for "phase 2" of the project ;)

Posted in external data, misc | Tagged , , , , | 2 Comments