Monthly Archives: April 2009

Swirl Gradient

Actionscript:
  1. var canvas:BitmapData=new BitmapData(200,200,false,0x000000);
  2. addChild(new Bitmap(canvas));
  3. scaleX=scaleY=2;
  4. var pixNum:int=canvas.width*canvas.height;
  5.  
  6. var xp:Vector.<int> = new Vector.<int>();
  7. var yp:Vector.<int> = new Vector.<int>();
  8. var radius:Vector.<Number> = new Vector.<Number>();
  9. var theta:Vector.<Number> = new Vector.<Number>();
  10. for (var i:int = 0; i<pixNum; i++) {
  11.     xp.push(i % 200);
  12.     yp.push(int(i / 200));
  13.     var dx:Number=100-xp[i];
  14.     var dy:Number=100-yp[i];
  15.     theta.push(Math.atan2(dy, dx));
  16.     radius.push(Math.sqrt(dx * dx + dy * dy)/20);
  17. }
  18.  
  19. addEventListener(Event.ENTER_FRAME, onLoop);
  20. function onLoop(evt:Event):void {
  21.     canvas.lock();
  22.     var n:Number = mouseX / 100;
  23.     for (var i:int = 0; i<pixNum; i++) {
  24.         var swirl:Number = 1+Math.sin(6*Math.cos(radius[i]) -n*theta[i]);
  25.         canvas.setPixel(xp[i], yp[i],  Math.abs(255 - swirl * 255));
  26.     }
  27.     canvas.unlock();
  28. }

This snippet creates a swirl gradient. While this snippet is not highly optimized, it does implement a basic optimization technique ... I cache some repetitive calculations in Vectors and then use them on the main loop.

I got the function for a swirl gradient from mathworld...

Posted in BitmapData, Math, pixel manipulation, setPixel | Tagged , | Leave a comment

2D Array to String

Actionscript:
  1. function format2D(a:Array):String {
  2.     var str:String="[";
  3.     for (var i:int = 0; i<a.length; i++) {
  4.         str+="["+a[i].toString()+"],";
  5.     }
  6.     str=str.substr(0,str.length-1);
  7.     str+="]";
  8.     return str;
  9. }
  10.  
  11. // test it out
  12. var array2D:Array = [[1,2,3], [4,5,6], [7,8,9]];
  13.  
  14. trace(array2D);
  15. trace(format2D(array2D));
  16.  
  17. /* outputs:
  18. 1,2,3,4,5,6,7,8,9
  19. [[1,2,3],[4,5,6],[7,8,9]]
  20.  
  21. */

When you trace a 2D array to the output window the actual structure of the array isn't clear. For some reason it just appears as a 1D array - this small function fixes that problem - it could also be used to save 2D arrays to text files etc...

Posted in string manipulation, strings | Tagged , | Leave a comment

Object Parsing (object from string #2)

Actionscript:
  1. var str:String = '{numA:100, numB:100, stringA:"hi there", object:{red:155, green:155, blue: 255}, array1D:[1, 2, 3, 4, 5, "six"], array2D:[[1,0,0], [0,1,0], [0,0,"z"]], color:0xFF0000}'
  2.  
  3. var obj:Object = toObject(str);//, true); // comment the "true" in for some debug info
  4.  
  5. // acess every value in the object for testing purposes
  6. trace(obj.numA);
  7. trace(obj.numB);
  8. trace(obj.stringA);
  9. trace(obj.object.red, obj.object.green, obj.object.blue);
  10. trace(obj.array1D +" testing access: " + obj.array1D[3]);
  11. trace(obj.array2D + " testing access: " + obj.array2D[1] + "  -  " + obj.array2D[2][2]);
  12. trace(obj.color);
  13.  
  14. /*outputs:
  15. 100
  16. 100
  17. hi there
  18. 155 155 255
  19. 1,2,3,4,5,six testing access: 4
  20. 1,0,0,0,1,0,0,0,z testing access: 0,1,0  -  z
  21. 16711680
  22. */
  23.  
  24. function toObject(str:String, debug:Boolean=false):Object{
  25.     var cmds:Array = new Array();
  26.     var stack:String = "";
  27.     // skip first {
  28.     str = str.replace(/^\s+\{|^\{/, "");
  29.     var obj:Object = new Object();
  30.     for (var i:int = 0; i<str.length; i++){
  31.         var char:String = str.charAt(i);
  32.         if (char == ":"){
  33.             cmds.push(["name:", stack])
  34.             stack = "";
  35.             char = "";
  36.         }else
  37.         if (char == "," || char == "}"){
  38.             if (stack != ""){
  39.               cmds.push(["value:", stack]);
  40.             }
  41.             stack = "";
  42.             char = "";
  43.         }else
  44.         if (char == '"'){
  45.             stack = '"';
  46.             for (j = i + 1; j <str.length; j++){
  47.                 char = str.charAt(j);
  48.                 stack+=char;
  49.                 i++;
  50.                 if (char == '"'){
  51.                      break;
  52.                 }
  53.             }
  54.             cmds.push(["value:", stack]);
  55.             stack = "";
  56.             char = "";
  57.         }else
  58.         if (char == "{"){
  59.             cmds.push(["object:", stack]);
  60.             for (var j:int = i; j <str.length; j++){
  61.                 char = str.charAt(j);
  62.                 stack+=char;
  63.                 i++;
  64.                 if (char == "}"){
  65.                      break;
  66.                 }
  67.             }
  68.             cmds.push(["value:", stack]);
  69.             stack = "";
  70.             char = "";
  71.         }else
  72.         if (char == "["){
  73.             cmds.push(["array:", stack]);
  74.             stack = "";
  75.             char = "";
  76.         }else if (char == "]"){
  77.             if (stack != ""){
  78.                 cmds.push(["value:", stack]);
  79.             }
  80.             stack = "";
  81.             char = "";
  82.             i++;
  83.         }
  84.         stack += char;
  85.     }
  86.     // show some debug info
  87.     if (debug){
  88.         for (i = 0; i<cmds.length; i++) trace(cmds[i]);
  89.     }
  90.     // build the object
  91.     var prop:String;
  92.     var arrayMode:Boolean = false;
  93.     var nest:int = 0;
  94.     for (i = 0; i<cmds.length; i++){
  95.         if (cmds[i][0] == "name:"){
  96.             prop = cmds[i][1].replace(/\s/g, "");
  97.             arrayMode = false;
  98.             nest = 0;
  99.         }else if (cmds[i][0] == "value:"){
  100.             if (arrayMode == false){
  101.               obj[prop] = valueType(cmds[i][1]);
  102.             }else{
  103.                 // populate array
  104.                 if (nest == 1){
  105.                   obj[prop].push(valueType(cmds[i][1]))
  106.                 }else{
  107.                   obj[prop][nest - 2].push(valueType(cmds[i][1]))
  108.                 }
  109.             }
  110.         }else if (cmds[i][0] == "object:"){
  111.             i++;
  112.             obj[prop] = toObject(cmds[i][1], debug);
  113.         }else if (cmds[i][0] == "array:"){
  114.             arrayMode = true;
  115.             nest++;
  116.             if (nest == 1){
  117.                 // create array
  118.                 obj[prop] = new Array()
  119.             }else{
  120.                 // nested array
  121.                 obj[prop].push(new Array());
  122.             }
  123.         }
  124.     }
  125.     return obj;
  126. }
  127.  
  128. function valueType(val:*):* {
  129.     if (isNaN(Number(val))) {
  130.            // remove leading and trailing white
  131.            // remove "" around strings
  132.            val = val.replace(/^s+|s+$/g,"").replace(/^"|"$/g,"");
  133.            //  see if it's a boolean
  134.            if (val == "true"){
  135.                val = true;
  136.            }else if (val == "false"){
  137.                val = false
  138.            }
  139.     } else {
  140.         val = Number(val);
  141.     }
  142.     return val;
  143. }

This rather large code snippet parses ActionScript style Object syntax. While this is by no means a complete parser - it was easy to write and saved me a great deal of time on a project recently....

I specifically needed support for 1D and 2D arrays as Object properties. If that weren't the case I would have used something simple like yesterdays method. The array support won't work with anything higher than a 2D array (for now... may fix that soon). For fun I also added nested Object support - this doesn't have any dimensional limitation so you can nest as many objects as you want. For instance.. this works just fine:

Actionscript:
  1. var gameUser:Object = toObject('{name:"Mr.S", alive:true, stats:{lives:100, points:1200, data:[100,12,40,12,90], plant:{branch:{leaves:["red, "green", "blue"]}}}');
  2.  
  3. trace(gameUser.stats.plant.branch.leaves[0]);
  4. trace(gameUser.stats.lives);
  5. // boolean support
  6. trace("not true is false: ", !gameUser.alive);
  7. /*outputs:
  8. red
  9. 100
  10. not true is false:  false
  11. */

You'll also notice the added boolean support in the above example. Which was suggested by katopz in the comments of yesterdays post.

Definitely need to add a word of warning here... I wouldn't be surprised if there were a bug or two lurking in this code. The Objects I've been parsing with it are all quite similar... so use at your own risk.

UPDATEs - Known Issues:
1) fixed a bug where if a String property contains a ,{}[] or : character the parser failed.

Posted in dynamic, string manipulation, strings | Tagged , | 4 Comments

Object from String

Actionscript:
  1. var str:String='{x: 10, y:10, width:100, heigth:100, name:"myClip", type:"clip"}';
  2.  
  3. var obj:Object=toObject(str);
  4.  
  5. trace(obj.x + obj.width, obj.name, obj.type);
  6.  
  7. function toObject(str:String):Object {
  8.     str=str.replace(/\{|\}/g,"");
  9.     // to an array of name value pairs [0] = name, [1] = value etc...
  10.     var pairs:Array=str.split(/\:|\,\s+/);
  11.     var obj:Object = new Object();
  12.     for (var i:int = 0; i<pairs.length; i+=2) {
  13.         obj[pairs[i]]=numOrString(pairs[i+1]);
  14.     }
  15.     return obj;
  16. }
  17. function numOrString(val:*):* {
  18.     if (isNaN(Number(val))) {
  19.         if (val.charAt(0) == '"' && val.charAt(val.length - 1) == '"'){
  20.             val = val.substr(1, val.length - 2);
  21.         }
  22.     } else {
  23.         val=Number(val);
  24.     }
  25.     return val;
  26. }

A very limited way to parse an object from a string... Tomorrow I'll post a better version of this that's a good deal more complex and doesn't really use regular expressions... This works nicely if you don't have arrays as Object properties...

Posted in dynamic, string manipulation, strings | Tagged , | 2 Comments