Category Archives: Graphics

Recursion Form

Actionscript:
  1. x = y = 10
  2. graphics.lineStyle(1,0);
  3. drawBox(6);
  4.  
  5. function drawBox(iter:Number=10, count:Number=1, y:Number=0, w:Number=500):void{
  6.        if (count <iter){
  7.                var width:Number = w / count
  8.                for (var i:int = 0; i<count; i++){
  9.                    graphics.drawRect(i * width, width * count/w, width, width);
  10.                }
  11.                count++;
  12.                drawBox(iter, count, y, width);
  13.        }
  14. }

This small snippet just draws this image:

If you have an idea for a short recursive snippet. Feel free to post it in the comments.

Also posted in functions | Tagged , , | 6 Comments

Logistic Map Play

Actionscript:
  1. var offX:Number = 100;
  2. var offY:Number = 300;
  3. var scalarX:Number = 6;
  4. var scalarY:Number = 200;
  5. addEventListener(Event.ENTER_FRAME, onLoop);
  6. function onLoop(evt:Event):void{
  7.     var r:Number = mouseY / 100;
  8.     var xn:Number = (mouseX - 100) / 650;
  9.     var xn1:Number = 0;
  10.     graphics.clear();
  11.     graphics.lineStyle(0,0);
  12.     for (var i:int = 0; i<100; i++){
  13.       xn1 = r * xn * (1 - xn);
  14.       xn = xn1;
  15.       if (i == 0){
  16.         graphics.moveTo(offX+i*scalarX,offY+xn1*scalarY);  
  17.       }else{
  18.         graphics.lineTo(offX+i*scalarX, offY+xn1*scalarY);
  19.       }
  20.     }
  21. }

Whenever I can't decide what kind of snippet to make, I simply go to wikipedia or mathworld for a bit and I always end up with something. I've messed with Logistic Maps before (when learning about strange attractors). This is a simple rendering where the x and y axis change the biotic potential (r) and the starting value for x.

Here is the link I used for reference.


Have a look at the swf (just move your mouse around).

Also posted in Math, misc | Tagged , , | 2 Comments

Connect The Dots E8

Actionscript:
  1. [SWF(width = 500, height = 500)]
  2. const TWO_PI:Number = Math.PI * 2;
  3. var centerX:Number = stage.stageWidth / 2;
  4. var centerY:Number = stage.stageHeight / 2;
  5. addEventListener(Event.ENTER_FRAME, onLoop);
  6. function onLoop(evt:Event):void{
  7.     // data
  8.     var points:Array = [];
  9.     var i:int = 0;
  10.     var pointNum : int = Math.max(2,int(mouseX / 12))
  11.    
  12.     var radius:Number = 200;
  13.     var step:Number = TWO_PI / pointNum;
  14.     var theta:Number = step / 2;
  15.     for (i = 0; i<pointNum; i++){
  16.         var xp:Number = centerX + radius * Math.cos(theta);
  17.         var yp:Number = centerY + radius * Math.sin(theta);
  18.         points[i] = new Point(xp, yp);
  19.         theta += step;
  20.     }
  21.     // render
  22.     graphics.clear();
  23.     graphics.lineStyle(0,0);
  24.     for ( i = 0; i<pointNum; i++){
  25.      var a:Point = points[i];
  26.      for (var j:int = 0; j<pointNum; j++){
  27.         var b:Point = points[j];
  28.         if (a != b){
  29.            graphics.drawCircle(a.x, a.y, 10);
  30.            graphics.moveTo(a.x, a.y);
  31.            graphics.lineTo(b.x, b.y);
  32.         }
  33.      }
  34.    }
  35. }

I've been using this geometric shape for lots of different things recently. Including during consulting gigs as a helpful visualization. Just move your mouse left and right... I particularly like the simpler forms you get by moving your mouse to the left (triangles squares and simple polygons):

While not entirely related this wikipedia article is interesting.

[EDIT : Thanks to martin for reminding me that I can do away with the if statement here in the above code ]

Actionscript:
  1. graphics.clear();
  2. graphics.lineStyle(0,0);
  3. for (i = 0; i<pointNum; i++) {
  4.     var a:Point=points[i];
  5.     for (var j:int = i+1; j<pointNum; j++) {
  6.         var b:Point=points[j];
  7.         graphics.drawCircle(a.x, a.y, 10);
  8.         graphics.moveTo(a.x, a.y);
  9.         graphics.lineTo(b.x, b.y);
  10.     }
  11. }
  12. graphics.drawCircle(a.x, a.y, 10);

I implemented that change over at wonderfl and it works nicely

Also posted in Math, misc | Tagged , , | 4 Comments

Nonsense Clocks

Actionscript:
  1. [SWF(width = 500, height=500, backgroundColor=0x000000)]
  2.  
  3. var clockNum:int = 100;
  4. var clocks:Vector.<Function> = new Vector.<Function>(clockNum, true);
  5.  
  6. var clockContainer:Sprite = Sprite(addChild(new Sprite()));
  7. clockContainer.x = stage.stageWidth / 2;
  8. clockContainer.y = stage.stageHeight / 2;
  9. buildClocks();
  10. runClocks();
  11.  
  12. function buildClocks():void{
  13.     for (var i:int = 0; i<clockNum; i++){
  14.         var theta:Number = Math.random() * Math.PI * 2;
  15.         var radius:Number = Math.random() * 200;
  16.         var xp:Number = radius * Math.cos(theta);
  17.         var yp:Number = radius * Math.sin(theta);
  18.         clocks[i] = makeClock(xp,yp,Math.random() * Math.PI * 2);
  19.     }
  20. }
  21. function runClocks():void{
  22.     addEventListener(Event.ENTER_FRAME, onRunClocks);
  23. }
  24. function onRunClocks(evt:Event):void{
  25.     for (var i:int = 0; i<clockNum; i++){
  26.         clocks[i]();
  27.     }
  28.     clockContainer.rotationX = clockContainer.mouseY / 30;
  29.     clockContainer.rotationY = -clockContainer.mouseX / 30;
  30. }
  31. function makeClock(x:Number, y:Number, time:Number=0):Function{
  32.     var radius:Number = Math.random() * 20 + 5;
  33.     var border:Number = radius * 0.2;
  34.     var smallRadius:Number = radius - radius * 0.3;
  35.    
  36.     var clock:Sprite = Sprite(clockContainer.addChild(new Sprite()));
  37.     clock.x = x;
  38.     clock.y = y;
  39.     clock.z = 100 - Math.random() * 200;
  40.     clock.rotationX = Math.random() * 40 - 20;
  41.     clock.rotationY = Math.random() * 40 - 20;
  42.     clock.rotationZ = Math.random() * 360;
  43.     return function():void{
  44.         with (clock.graphics){
  45.             clear();
  46.             lineStyle(1,0xFFFFFF);
  47.             drawCircle(0,0,radius + border);
  48.             var xp:Number = smallRadius * Math.cos(time/2);
  49.             var yp:Number = smallRadius * Math.sin(time/2);
  50.             moveTo(0,0);
  51.             lineTo(xp, yp);
  52.             xp = radius * Math.cos(time);
  53.             yp = radius * Math.sin(time);
  54.             moveTo(0,0);
  55.             lineTo(xp, yp);
  56.         }
  57.         time+=0.1;
  58.     }
  59. }


You can go check the swf out at wonderfl.net...

Also posted in 3D, misc, motion | Tagged , , | 3 Comments

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:

Also posted in Math, functions, misc | Tagged , , | 4 Comments

AS Quiz #8

Today's quiz is not multiple choice. Instead, your task is to write a function that draws stairs that look like this:

Your function should have the following arguments:

drawStairs(graphics, stairNum);
// you may include additional arguments for size, depth etc..

Feel free to post your solution in the comments.

I'll post my solution for this in the comments tomorrow. There is also another multiple choice quiz in the pipeline for tomorrow...

BONUS: Try to use as few Graphics class method calls as possible.

You can see my solutions here.

Also posted in Quiz | Tagged , , , | 19 Comments

Graphics Class and Twitter

Actionscript:
  1. [SWF(width = 700, height=700, frameRate=12)]
  2. var cmds:Array = [];
  3.  
  4. var loader:URLLoader = new URLLoader();
  5. var req:URLRequest = new URLRequest("http://search.twitter.com/search.atom");
  6. var vars:URLVariables = new URLVariables();
  7. vars.q = "#asgraph";
  8. // results per page
  9. vars.rpp = "100";
  10. vars.page = 1;
  11.  
  12. req.data = vars;
  13. req.method = URLRequestMethod.GET;
  14.  
  15. loader.addEventListener(Event.COMPLETE, onLoaded);
  16. loader.load(req);
  17.  
  18. var txt:TextField = TextField(addChild(new TextField()));
  19. txt.defaultTextFormat = new TextFormat("_sans", 12);
  20. with (txt){ x=10, y=10, autoSize="left"; }
  21. txt.htmlText = "loading...";
  22.  
  23. function onLoaded(evt:Event):void{
  24.        removeChild(txt);
  25.    var searchData:XML = new XML(loader.data);
  26.    var atom:Namespace = searchData.namespace("");
  27.  
  28.    var leng:int = searchData.atom::entry.length() -1;
  29.   for (var i:int = leng; i>=0; i--){
  30.        var cmd:String =
  31. searchData.atom::entry[i].atom::title.toString().replace(/\#asgraph/g,
  32. "");
  33.       // added this to ignore words starting with @
  34.       cmd = cmd.replace(/@(\w+)/g, "");
  35.        cmds.push(cmd);
  36.    }
  37.  
  38.        var time:Timer = new Timer(100, cmds.length);
  39.        time.addEventListener(TimerEvent.TIMER, onTick);
  40.    time.start();
  41. }
  42. function onTick(evt:TimerEvent):void{
  43.        render(parseFunctions(cmds[evt.target.currentCount - 1]));
  44.        graphics.endFill();
  45.        graphics.lineStyle();
  46. }
  47.  
  48. // parse and run Graphics class commands
  49. function parseFunctions(dat:String):Array{
  50.    var a:Array = dat.split(";") ;
  51.    for (var i:int = 0; i<a.length-1; i++){
  52.        a[i] = a[i].split(/\(\)|\(|\)/g);
  53.        var f:String = a[i][0] = a[i][0].replace(/\s/g,"");
  54.        a[i] = a[i].splice(0, a[i].length - 1);
  55.        if (a[i].length> 1){
  56.         a[i] = a[i][1].split(",");
  57.         a[i].unshift(f);
  58.        }
  59.    }
  60.    return a.splice(0,a.length - 1);
  61. }
  62. function render(p:Array):void {
  63.    for (var i:int = 0; i<p.length; i++) {
  64.        try{
  65.        graphics[p[i][0]].apply(graphics,p[i].splice(1));
  66.        }catch(e:Error){};
  67.    }
  68. }

This is a simple idea I had awhile back... This snippet searches twitter for the #asgraph hashtag and if it finds standard Graphics class method calls it renders them.

So if you tweet something likethis :

#asgraph beginFill(0xFF); drawCircle(200,200,10);

it will get rendered into the below swf (you'll need to refresh to see your tweet get rendered):

This movie requires Flash Player 9

Here is a direct link to the swf

Also posted in external data | Tagged , , | 3 Comments

Three Color Triangle

Actionscript:
  1. /*
  2. *       Petri Leskinen, Finland
  3. *       25 October 2009
  4. *       pixelero.wordpress.com
  5. *
  6. *       Actionscript 3.0, Flash CS3, Flash Player 10
  7. *
  8. *       threeColorTriangle
  9. *       draws a triangle with a gradient fill of three colors for each vertex
  10. *       using graphics.drawTriangles and a BitmapData of size 2x2
  11. */
  12. function threeColorTriangle(
  13.       point0:Point, color0:uint,
  14.       point1:Point, color1:uint,
  15.       point2:Point, color2:uint):void {
  16.  
  17.       //      create a  bitmap of size 2x2 pixels
  18.       var bmd:BitmapData = new BitmapData(2,2,true);
  19.       //      copy colors to bitmap
  20.       //      the fourth color is average of color1 and color2
  21.       bmd.setVector(bmd.rect,
  22.               Vector.<uint>([color0,color1,color2,
  23.                                          (color1+color2)>>1
  24.                                          ]));
  25.  
  26.       //      draw triangle
  27.       this.graphics.beginBitmapFill(bmd,null,false,true /* =smooth */ );
  28.       this.graphics.drawTriangles(
  29.               // x,y -coordinates
  30.               Vector.<Number>([
  31.                       point0.x,point0.y,
  32.                       point1.x,point1.y,
  33.                       point2.x,point2.y]),
  34.               // indices
  35.               Vector.<int>([0,1,2]),
  36.               // texture coordinates
  37.               Vector.<Number>([0,0, 1,0, 0,1])
  38.               );
  39. }
  40.  
  41.  
  42. // demo, let's draw some of these on the stage
  43. randomize();
  44. function randomize():void {
  45.       this.graphics.clear();
  46.  
  47.       for (var i:int = 0;i<128;i++) {
  48.               //      pick some random colors
  49.               var color0:uint = 0xFFFFFFFF;
  50.               var color1:uint = 0xFFFFFF*Math.random() | 0xFF000000;
  51.               var color2:uint = 0xFFFFFF*Math.random() | 0xFF000000;
  52.  
  53.               //      random points
  54. var point0:Point = new Point(Math.random()*stage.stageWidth,
  55.             Math.random()*stage.stageHeight);
  56. var point1:Point = new Point(point0.x+200*(Math.random()-Math.random()),
  57.             point0.y+200*(Math.random()-Math.random()));
  58. var point2:Point = new Point(point0.x+200*(Math.random()-Math.random()),
  59.             point0.y+200*(Math.random()-Math.random()));
  60.  
  61.         threeColorTriangle(point0, color0, point1, color1, point2,  color2);
  62.       }
  63. }

This snippet is by Petri Leskinen (pixelero). It draws a triangle with a gradient fill of three colors for each vertex using Graphics.drawTriangles and a BitmapData of size 2x2. This is the simplest case, it can easily be extended to four colors or maybe to use a larger 3x3, 4x4 etc... bitmap.

Here's a still...

Also posted in Vector | Tagged , , , | 5 Comments

Flowing Leaves (optical illusion)


Saw this optical illusion today... figured I'd make a snippet to create a few variations on the illusion...

Actionscript:
  1. [SWF( backgroundColor=0x2E7999, width=780, height = 600) ]
  2.  
  3. var leafNum:Number = 375;
  4. var spacing:Number = 12;
  5. var cols:Number = 25;
  6. var hh:Number = stage.stageHeight / 2;
  7. var hw:Number = stage.stageWidth / 2;
  8.  
  9. for (var i:Number = 0; i<leafNum; i++){
  10.     var leaf:Shape = makeLeaf();
  11.     leaf.scaleX = leaf.scaleY = 0.25;
  12.     leaf.rotation = 90;
  13.     leaf.x = 50 + (i % cols) * (leaf.width + spacing);
  14.     leaf.y = 40 + int(i / cols) * (leaf.height + spacing);
  15.     var dx:Number = leaf.x - hw;
  16.     var dy:Number = leaf.y - hh;
  17.     leaf.rotation = Math.sqrt(dx * dx + dy * dy);
  18. }
  19.  
  20. function makeLeaf():Shape{
  21.     var leaf:Shape = Shape(addChild(new Shape()));
  22.     leaf.graphics.beginFill(0x9DC4D4);
  23.     scaleYcircle(leaf.graphics, 50, .65, false);
  24.     leaf.graphics.endFill();
  25.     leaf.graphics.lineStyle(2, 0x003366, 1, false, "none", CapsStyle.SQUARE, JointStyle.MITER);
  26.     scaleYcircle(leaf.graphics, 50, .65);
  27.     leaf.graphics.lineStyle(2, 0xFFFFFF, 1, false, "none", CapsStyle.SQUARE, JointStyle.MITER);
  28.     scaleYcircle(leaf.graphics, -50, .65);
  29.     return leaf;
  30. }
  31.  
  32.  
  33. // original circle function by senocular (www.senocular.com) from here http://www.actionscript.org/forums/showthread.php3?s=&threadid=30328
  34. // circle that can be scaled on the y axis
  35. function scaleYcircle(g:Graphics, r:Number, s:Number = 1, isHalf:Boolean=true):void {
  36.      
  37.     var c1:Number = r * (Math.SQRT2 - 1);
  38.     var c2:Number = r * Math.SQRT2 / 2;
  39.     var rs:Number = r * s, c1s:Number = c1 * s, c2s:Number = c2 * s;
  40.     var x_r:Number =  -r, y_r:Number = -rs, x_c2:Number =  -c2;
  41.     var y_c2:Number =  -c2s, x_c1:Number =  -c1, y_c1:Number =  -c1s
  42.     g.moveTo(r, 0), g.curveTo(r, c1s, c2, c2s);
  43.     g.curveTo(c1, rs, 0, rs), g.curveTo(x_c1,rs, x_c2, c2s);
  44.     g.curveTo(x_r, c1s, x_r, 0);
  45.     if (!isHalf){
  46.      g.curveTo(x_r,y_c1,x_c2,y_c2);
  47.      g.curveTo(x_c1,y_r,0,y_r), g.curveTo(c1,y_r,c2,y_c2);
  48.      g.curveTo(r,y_c1,r,0);
  49.     }
  50. }

Also posted in Math, Vector, misc, motion, pixel manipulation | Tagged , , , | 5 Comments

JS Sketch Experiment

Actionscript:
  1. [SWF(width=950, height=600)]
  2. with (graphics) beginFill(0xefefef), drawRect(0,0,stage.stageWidth, stage.stageHeight);
  3. var btn:Sprite = Sprite(addChild(new Sprite()));
  4. with (btn.graphics) beginFill(0x666666), drawRect(0,0,100,20);
  5. with(btn)  x=320, y=430, buttonMode = true;
  6. btn.addEventListener(MouseEvent.ROLL_OVER, function():void{
  7.   with(btn.graphics) clear(), beginFill(0x222222), drawRect(0,0,100,20);
  8. });
  9. btn.addEventListener(MouseEvent.ROLL_OUT, function():void{
  10.   with(btn.graphics) clear(), beginFill(0x666666), drawRect(0,0,100,20);
  11. });
  12. btn.addEventListener(MouseEvent.CLICK, function():void{
  13.     var res:*= ExternalInterface.call("function(){ plot=[]; colors=[]; " + txt.text + " return {plot:plot, colors:colors};}");
  14.     render((res == null) ? {plot:[], colors:[]} : res);
  15. });
  16.  
  17. var v:Shape = Shape(addChild(new Shape()));
  18. v.x = 700;
  19. v.y = 220;
  20. function render(obj:Object):void{
  21.     var plot:Array = obj.plot;
  22.     var colors:Array = obj.colors;
  23.     var leng:int = plot.length;
  24.     v.graphics.clear();
  25.     var inc:int = 0;
  26.     v.graphics.moveTo(plot[0], plot[1]);
  27.     for (var i:int = 2; i<leng; i+=2){
  28.         v.graphics.lineStyle(0,colors[inc++]);
  29.         v.graphics.lineTo(plot[i], plot[i + 1]);
  30.     }
  31. }
  32.  
  33.  
  34. var submit:TextField = TextField(btn.addChild(new TextField()));
  35. submit.defaultTextFormat = new TextFormat("_sans", 12);
  36. with(submit) textColor=0xFFFFFF, width=100, autoSize="center";
  37. with(submit) mouseEnabled = false,  text="submit";
  38.  
  39. var txt:TextField = TextField(addChild(new TextField()));
  40. with(txt) x = y = 20, type = "input", multiline=true;
  41. with(txt) width = 400, height = 400, border = true, background = 0xFFFFFF;
  42. txt.defaultTextFormat = new TextFormat("Monaco", 12);
  43. txt.text = "enter text";
  44. txt.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
  45. function onDown(evt:MouseEvent):void{
  46.     txt.text = "";
  47.     txt.removeEventListener(MouseEvent.MOUSE_DOWN, onDown);
  48. }

This snippet is a mini code editor that allows the user to write javascript into a textfield - the javascript is then run using external interface. Optionally the javascript code can populate two arrays (plot and colors). If these arrays are populated flash, will render the data in each array using the Graphics class.

Have a look at the demo:

If you do something nice with this... post your javascript snippet as a comment and I'll add it to the JS Sketch page...

Also posted in Math, dynamic, external data, functions | Tagged , , , | Leave a comment