Monthly Archives: March 2010

Frame Differencing

Actionscript:
  1. [SWF(width = 800, height= 600)]
  2. var sw:Number = 800;
  3. var sh:Number = 600;
  4. var pixelNum:int = sw * sh;
  5. var blurAmount:Number = 10;
  6. var pnt:Point = new Point(0,0);
  7. var rect:Rectangle = new Rectangle(0,0,sw,sh);
  8.  
  9. var canvas:BitmapData = new BitmapData(sw, sh, false, 0x000000);
  10. var buffer:BitmapData = new BitmapData(sw, sh, false, 0x000000);
  11. var feed  :BitmapData = new BitmapData(sw, sh, false, 0x000000);
  12. var prev  :BitmapData = new BitmapData(sw, sh, false, 0x000000);
  13.  
  14. var frame:Bitmap = new Bitmap(canvas, "auto", true);
  15. addChild(frame);
  16.  
  17. var cam:Camera =  Camera.getCamera();
  18. cam.setMode(sw,sh,12);
  19. var video:Video = new Video(sw, sh);
  20. video.attachCamera(cam);
  21.  
  22. cam.addEventListener(ActivityEvent.ACTIVITY, onActivityStart);
  23.  
  24. function onActivityStart(evt:ActivityEvent):void {
  25.     addEventListener(Event.ENTER_FRAME, onRun);
  26.     cam.removeEventListener(ActivityEvent.ACTIVITY, onActivityStart);
  27. }
  28.  
  29. function onRun(evt:Event):void{
  30.     buffer.draw(video);
  31.     feed.copyPixels(buffer, rect, pnt);
  32.     buffer.draw(prev, null, null, BlendMode.DIFFERENCE);
  33.     prev.draw(video);
  34.     canvas.copyPixels(buffer, rect, pnt);
  35. }

This snippet shows a simple method to do frame differencing with a web cam. This is useful for detecting which areas of the screen have change from frame to frame. This post assumes you pretty much know what frame differencing is.


You can view an swf file here:

This is one of those things I do a good deal but never wrapped up into a library... it's easy (for me at least) to forget exactly how to set it up from scratch.

I added an extra buffer because it's pretty common that you'll want to other things aside from just frame differencing alone, so it's nice to have it all wrapped up in a buffer BitmapData that you can use elsewhere. If speed is a real concern, you can do away with the buffer and just use the canvas instead - depending on what kind of analysis your doing on the frame differenced image it may be trickier without the buffer.

Posted in BitmapData, Video, graphics algorithms, pixel manipulation | Tagged , , | 5 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.

Posted in BitmapData, functions | 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.

Posted in dynamic, functions | Tagged , , | 4 Comments

URLVariables Replacement

Actionscript:
  1. function decode(str:String):Object {
  2.     var vars:Object={};
  3.     var parse:Array =str.split("&");
  4.     var i:int=0;
  5.     for (i = 0; i<parse.length; i++) {
  6.         var pair:Array=parse[i].split("=");
  7.         if (pair.length==2) {
  8.             vars[pair[0]]=pair[1];
  9.         }
  10.     }
  11.     return vars;
  12. }
  13.  
  14. var nameValuePairs="one=1&&two=éllo&three=1000&four=0xFF0000";
  15. var parsed:Object=decode(nameValuePairs);
  16.  
  17. trace(parsed.one);
  18. trace(parsed.two);
  19. trace(parsed.three);
  20. trace(parsed.four);
  21.  
  22. /*outputs:
  23. 1
  24. éllo
  25. 1000
  26. 0xFF0000
  27. */

Well not exactly a URLVariables replacement, but I often use the URLVariables.decode() function and find that its very picky... like if there is an extra & or something it freaks out and breaks, or if there are line returns. As a quick and simple solution the other day I wrote this function into part of a class (Model class) that I was working on. Fixed the problem and even handles Spanish characters nicely.

There is plenty of room for improvement with this simple function... feel free to post improvements in the comments.

Posted in external data, string manipulation, strings | Tagged , , | 3 Comments

Colors For Questions

I get lots of questions about actionscript and QuickBox2D. Too many questions to answer really. But if you enter 30 colors into this project I'm working on I'll help you by answering any question (within reason of course) and possibly giving you a code snippet related to your question.

To enter colors use you'll be using a simple color picker app. Select a color, give it a name "dark red, maroon" etc.. and Then post in the comments that you did so... You'll need to enter a contributer name as well... you can use a handle or your real name... doesn't matter. So go back to this post and watch how to go about adding colors. If you have a question about how to enter stuff, here is the place to ask it....

Posted in Uncategorized | 11 Comments

Polygon Problems

Lots of people have mentioned that they have problems with QuickBox2D Polygons. The simple solution is not to use the verts 2d array (which is more like how Box2D does polys). So when in doubt about polygons, simply use the points array which will nearly always work as long as the contour you define does not cross over itself. Here is a simple example on wonderfl:

Also... polygons are covered extensively in part two of the tutorial over at active tuts... more on that later.

Here is the timeline code:

Actionscript:
  1. import com.actionsnippet.qbox.*;
  2.             /*
  3.                0
  4.               / \
  5.              0_0 0
  6.                | |
  7.                0-0
  8.             */
  9.             var sim:QuickBox2D = new QuickBox2D(this);
  10.             sim.createStageWalls();
  11.             // define the contour of your poly
  12.             // no limits as long as it doesn't cross over
  13.             // itself
  14.             sim.addPoly({x:10, y:5, points:[0.5,0,
  15.                                             1, 1,
  16.                                             1, 2,
  17.                                             0.5, 2,
  18.                                             0.5, 1,
  19.                                             0,1,
  20.                                             0.5,0],
  21.                                             wireframe:false});
  22.             sim.addCircle({x:11, y:10});
  23.             sim.start();
  24.             sim.mouseDrag();

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

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:

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

Nested Tree Nav

This snippet takes xml and builds a multi-tiered navigation based on how nodes are nested etc...:

So that something like this:

XML:
  1. var menu:XML=<nav>
  2.    <element label="one">
  3.        <element label="a" />
  4.    <element label="b" />
  5.    <element label="c" />
  6. </element>
  7. <element label="two">
  8.      <element label="three">
  9.      <element label="aa">
  10.        <element label="zevan" />
  11.      </element>
  12.      <element label="bb" />
  13.      <element label="cc" />
  14.  </element>
  15.  </element>
  16. </nav>;

Turns into an expandable and collapsible menu that looks like this:

Here is the timeline code:

Actionscript:
  1. var menu:XML=<nav>
  2.    <element label="one">
  3.        <element label="a" />
  4.    <element label="b" />
  5.    <element label="c" />
  6. </element>
  7. <element label="two">
  8.      <element label="three">
  9.      <element label="aa">
  10.        <element label="zevan" />
  11.      </element>
  12.      <element label="bb" />
  13.      <element label="cc" />
  14.  </element>
  15.  </element>
  16. </nav>;
  17.  
  18. var elements:Array = new Array();
  19. setupMenu();
  20.  
  21. function setupMenu():void {
  22.     parse(menu);
  23.     // hide child elements
  24.     for (var i:int = 0; i<elements.length; i++) {
  25.         var mc:MovieClip = elements[i];
  26.         if (mc.parents != 1) {
  27.             removeChild(mc);
  28.         }
  29.     }
  30.     arrangeY();
  31. }
  32.  
  33. function parse(m:XML):void {
  34.     for each (var d:XML in m.children()) {
  35.         makeBtn(d, numParents(d));
  36.         parse(d);
  37.     }
  38. }
  39.  
  40. function makeBtn(d:XML, offsetX:int):void {
  41.     var btn:MovieClip = new MovieClip();
  42.     btn.x = offsetX * 20;
  43.     btn.y = numChildren * 20;
  44.     btn.data = d;
  45.     btn.parents = offsetX;
  46.     btn.value = d.@label;
  47.  
  48.     var txt:TextField = new TextField();
  49.     txt.text = d.@label;
  50.     txt.selectable = false;
  51.     txt.border = true;
  52.     txt.width = 100;
  53.     txt.mouseEnabled = false;
  54.     txt.height = 19;
  55.     btn.addChild(txt);
  56.     btn.buttonMode= true;
  57.     addChild(btn);
  58.    
  59.     // store references to btn
  60.     elements.push(btn);
  61.     elements[d.parent().@label+"_"+d.@label] = btn
  62.  
  63.     btn.addEventListener(MouseEvent.CLICK, onClick);
  64. }
  65.  
  66. function onClick(evt:MouseEvent):void {
  67.     showHide(MovieClip(evt.currentTarget));
  68.     arrangeY();
  69.     trace(evt.currentTarget.value);
  70. }
  71.  
  72. function showHide(btn:MovieClip, forceHide:Boolean=false):void {
  73.     for each (var d:XML in btn.data.children()) {
  74.         var mc:MovieClip = elements[btn.data.@label+"_"+d.@label];
  75.         if (contains(mc)) {
  76.             removeChild(mc);
  77.             showHide(mc, true);
  78.         } else if (forceHide == false) {
  79.             addChild(mc);
  80.         }
  81.     }
  82. }
  83.  
  84. function arrangeY():void {
  85.     var inc:Number = 0;
  86.     for (var i:int = 0; i<elements.length; i++) {
  87.         if (contains(elements[i])) {
  88.             elements[i].y = inc * 20;
  89.             inc++;
  90.         }
  91.     }
  92. }
  93.  
  94. function numParents(e:XML):int {
  95.     var num:int = 0;
  96.     while (e.parent()!= null) {
  97.         num++;
  98.         e = e.parent();
  99.     }
  100.     return num;
  101. }

This is one of those snippets I've had laying around but never got around to posting. Next time I need to do a multi-tiered nav I'll wrap it up into a nice class (the wondeful class was done just by using my script that auto-converts timeline code to doc class code).

Posted in Uncategorized | 2 Comments