Category Archives: motion

Low Precision Sine and Cosine

Actionscript:
  1. var t:Number=0, cos:Number, sin:Number;
  2.  
  3. var canvas:BitmapData = new BitmapData(400,400,false, 0x000000);
  4. addChild(new Bitmap(canvas));
  5.  
  6. var shape:Shape = new Shape();
  7. with(shape.graphics) beginFill(0x568338, .2), drawCircle(0,0,10);
  8.  
  9. addEventListener(Event.ENTER_FRAME, onLoop);
  10. function onLoop(evt:Event):void {
  11.    
  12.          t += .1;
  13.         // -- low precision sine/cosine
  14.         //always wrap input angle to -PI..PI
  15.         if (t <-3.14159265){
  16.             t += 6.28318531;
  17.         }else{
  18.         if (t>  3.14159265)
  19.             t -= 6.28318531;
  20.         }
  21.        
  22.         //compute sine
  23.         if (t <0){
  24.             sin = 1.27323954 * t + .405284735 * t * t;
  25.         }else{
  26.             sin = 1.27323954 * t - 0.405284735 * t * t;
  27.         }
  28.        
  29.         //compute cosine: sin(t + PI/2) = cos(t)
  30.         t += 1.57079632;
  31.         if (t>  3.14159265){
  32.             t -= 6.28318531;
  33.         }
  34.        
  35.         if (t <0){
  36.             cos = 1.27323954 * t + 0.405284735 * t * t
  37.         }else{
  38.             cos = 1.27323954 * t - 0.405284735 * t * t;
  39.         }
  40.         t -= 1.57079632;
  41.        
  42.         // move the shape
  43.         shape.x = 200 + 100 * cos;
  44.         shape.y = 200 + 100 * sin;
  45.        
  46.         // draw to the canvas
  47.         canvas.draw(shape, shape.transform.matrix);
  48. }

This snippet draws a circle using low precision sine and cosine... you'll notice that its not a perfect looking circle:


Back in January I saw this blog post by Michael Baczynski over at http://lab.polygonal.de/. The blog post describes a technique for fast sine and cosine approximation - (I highly recommend giving it a read - very fun stuff).

It's worth noting that there is a higher precision sine and cosine that will likely draw a better looking circle but will be about half as fast. According to the original post ... the low precision technique is approximately 14x faster than using Math.cos()/Math.sin().

There some other really great posts over at polygonal go check them out.

Also posted in Math | Tagged , | 2 Comments

Circle of Particles #2

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

This is an interesting variation on yesterdays post. The result will looks like this...


Click to view swf...

I also decided to do a processing port of this with 3,000 particles:

Processing Version

The processing version eventually evolved into this:


Click for enlarged version...

Also posted in BitmapData, setPixel | Tagged , , | 2 Comments

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, functions, setPixel | Tagged , | Leave a comment

Functional Pseudo-Objects

Actionscript:
  1. var moverNum:int = 40;
  2. var movers:Array = new Array();
  3.  
  4. for (var i:int = 0; i<moverNum; i++){
  5.     movers.push(makeMover());
  6. }
  7.  
  8. addEventListener(Event.ENTER_FRAME, onLoop);
  9. function onLoop(evt:Event):void {
  10.     for (var i:int = 0; i<moverNum; i++){
  11.         movers[i]();
  12.     }
  13. }
  14.  
  15. function makeMover():Function{
  16.     // mover vars & setup
  17.     var xVel:Number = Math.random() * 5 + 1;
  18.     var right:Number = stage.stageWidth + 30;
  19.     var s:Shape = Shape(addChild(new Shape()));
  20.     with(s.graphics) beginFill(0xFF0000), drawCircle(0,0,5);
  21.     s.x = Math.random() * stage.stageWidth;
  22.     s.y = Math.random() * stage.stageHeight;
  23.     // return a "run" function
  24.     return function():void {
  25.          s.x += xVel;
  26.          if (s.x> right){
  27.             s.x = -30;
  28.          }
  29.     }
  30. }

This snippet creates 40 shapes that move to the right at a random velocity. When they animate off the right hand side of the stage they return from the left.

The makeMover() function has a series of variable definitions related to the x velocity and position of a Shape. The makeMover() function then returns an anonymous function that contains some logic to move the Shape "s". The anonymous function has access to the makeMover() functions temporary variables...

On the main loop we run all of the anonymous functions - animating all the shapes by their random x velocities.

It would be interesting to write the same program using classes and test the for speed differences. My assumption is that anonymous functions are expensive, but it would still be interesting to see...

Also posted in functions | Tagged , | Leave a comment