Monthly Archives: June 2009

Bresenham’s Circle and setVector()

Actionscript:
  1. var canvasSize:int = 400;
  2. var canvas:BitmapData = new BitmapData(canvasSize, canvasSize, false, 0xFFFFFF);
  3. addChild(new Bitmap(canvas));
  4. var size:int = canvas.width * canvas.height;
  5. var pixels:Vector.<uint> = canvas.getVector(canvas.rect);
  6.  
  7. addEventListener(Event.ENTER_FRAME, onLoop);
  8. function onLoop(evt:Event):void {
  9.      for (var i:int = 0; i<500; i++){
  10.       fillCircle(int(Math.random() * canvasSize),
  11.                       int(Math.random() * canvasSize),
  12.                       int(Math.random() * 5 + 3),
  13.                       uint(Math.random() * 0xFFFF));
  14.      }
  15.      canvas.lock();
  16.      canvas.setVector(canvas.rect, pixels);
  17.      canvas.unlock();
  18. }
  19.  
  20. function fillCircle(xp:int,yp:int, radius:int, col:uint = 0x000000):void {
  21.     var xoff:int =0;
  22.     var yoff:int = radius;
  23.     var balance:int = -radius;
  24.     while (xoff <= yoff) {
  25.          var p0:int = xp - xoff;
  26.          var p1:int = xp - yoff;
  27.          var w0:int = xoff + xoff;
  28.          var w1:int = yoff + yoff;
  29.          hLine(p0, yp + yoff, w0, col);
  30.          hLine(p0, yp - yoff, w0, col);
  31.          hLine(p1, yp + xoff, w1, col);
  32.          hLine(p1, yp - xoff, w1, col);
  33.         if ((balance += xoff++ + xoff)>= 0) {
  34.             balance-=--yoff+yoff;
  35.         }
  36.     }
  37. }
  38. function hLine(xp:int, yp:int, w:int, col:uint):void {
  39.     var index:int = xp + yp * canvasSize;
  40.     for (var i:int = 0; i <w; i++){
  41.         index++;
  42.         if (index> -1 && index <size){
  43.           pixels[index] = col;
  44.         }
  45.     }
  46. }

In the past I've posted examples of Bresenham's Circle (here and here). Both of those examples make use of setPixel(). Today's snippet demos a version of Bresenham's Circle that works with setVector().

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

2D Map Avoid

Actionscript:
  1. [SWF(width=401,height=401,background=0xEFEFEF)]
  2.  
  3. var w:Number = stage.stageWidth-1;
  4. var h:Number = stage.stageHeight-1;
  5. var tileSize:Number = 20;
  6. var halfTileSize:Number = 20;
  7. var hTiles:Number = w / tileSize;
  8. var vTiles:Number = h / tileSize;
  9. var world:Shape = Shape(addChild(new Shape()));
  10. var map:Array=[];
  11. populateMap();
  12. var gridColor:uint = 0xCCCCCC;
  13. grid(tileSize,  gridColor);
  14.  
  15. vTiles -= 1;
  16. var movers:Array = [];
  17. for (var i:int = 0; i<100; i++){
  18.     movers.push(makeMover(i % hTiles, int( i / hTiles),0x000000))
  19.     movers.push(makeMover(i % hTiles, vTiles - int( i / hTiles),0xFF0000))
  20. }
  21. var moverNum:int = movers.length;
  22. hTiles -= 1;
  23.  
  24. addEventListener(Event.ENTER_FRAME, onLoop);
  25. function onLoop(evt:Event):void {
  26.     world.graphics.clear();
  27.     for (var i:int = 0; i<moverNum; i++){
  28.        movers[i]();
  29.      }
  30. }
  31. function populateMap():void{
  32.     for (var i:int = 0; i<vTiles; i++){
  33.         map[i] = [];
  34.         for (var j:int = 0; j<hTiles; j++){
  35.             map[i][j] = 0;
  36.         }
  37.     }
  38. }
  39. function grid(size:Number=30, lineColor:uint=0xFFFF00, lineAlpha:Number=1):void {
  40.     with(graphics){
  41.         lineStyle(0, lineColor, lineAlpha);
  42.         drawRect(0,0,w,h);
  43.         for (var i:Number = size; i<w; i+=size) {
  44.             moveTo(i, 0);
  45.             lineTo(i, w);
  46.         }
  47.         for (i = size; i<h; i+=size) {
  48.             moveTo(0, i);
  49.             lineTo(h, i);
  50.         }
  51.     }
  52. }
  53. function makeMover(x:Number, y:Number, col:uint):Function{
  54.     var xp:Number = x;
  55.     var yp:Number = y;
  56.     var prevX:Number = x;
  57.     var prevY:Number = y;
  58.     map[yp][xp] = 1;
  59.     var dx:Number = xp;
  60.     var dy:Number = yp;
  61.     var counter:int = 0;
  62.     return function():void{
  63.         if (counter> 20){
  64.             if (int(Math.random()*30) == 1){
  65.                 xp += int(Math.random()*2) - 1 | 1;
  66.                 xp = xp <0 ? 0 : xp;
  67.                 xp = xp> hTiles ? hTiles : xp;
  68.                 if (map[yp][xp] == 1){
  69.                      xp = prevX;
  70.                 }else{
  71.                     map[prevY][prevX] = 0;
  72.                     map[yp][xp] = 1;
  73.                     counter = 0;
  74.                 }
  75.                 prevX = xp;
  76.             }else
  77.             if (int(Math.random()*30) == 1){
  78.                 yp += int(Math.random()*2) - 1 | 1;
  79.                 yp = yp <0 ? 0 : yp;
  80.                 yp = yp> vTiles ? vTiles : yp;
  81.                 if (map[yp][xp] == 1){
  82.                      yp = prevY;
  83.                 }else{
  84.                     map[prevY][prevX] = 0;
  85.                     map[yp][xp] = 1;
  86.                     counter = 0;
  87.                 }
  88.                 prevY = yp;
  89.             }
  90.         }
  91.         counter++;
  92.         dx += (xp - dx) * 0.5;
  93.         dy += (yp - dy) * 0.5;
  94.         with(world.graphics){
  95.             lineStyle(0, gridColor,1, true)
  96.             beginFill(col);
  97.             drawRect(dx * tileSize, dy * tileSize, tileSize, tileSize);
  98.         }
  99.     }
  100. }

This (somewhat long) snippet moves boxes around on a grid - the boxes avoid one another by reading values in a 2D array. This technique can also be used for collision detection in tile-based games.


Have a look at the swf here...

Posted in arrays, motion, random | Tagged , , | Leave a comment

2x mod 1 map

Actionscript:
  1. [SWF(width=800, height=600)]
  2. var xn1:Number;
  3. var xn:Number = Math.random() * Math.random() * .2;
  4. var inc:int = 0;
  5. var xp:Number = 10;
  6. var yp:Number = 10;
  7. var count:int = 1;
  8. scaleX = scaleY = 2;
  9. graphics.lineStyle(0,0x00000);
  10. addEventListener(Event.ENTER_FRAME, onLoop);
  11. function onLoop(evt:Event):void {
  12.    
  13.      xn1 = 2 * xn % 1;
  14.      xn = xn1;
  15.      if (inc == 0){
  16.           graphics.moveTo(xp + inc, yp + 30 - xn1 * 30);
  17.      }else{
  18.          graphics.lineTo(xp + inc, yp + 30 - xn1 * 30);
  19.      }
  20.      inc++
  21.      if (inc == 50){
  22.          inc = 0;
  23.          xp = 10 + count % 6 * 60;
  24.          yp = 10 + int(count / 6) * 60;
  25.          xn = Math.random() * Math.random() * .2;
  26.          trace(xn);
  27.          count++;
  28.      }
  29. }

This snippet plots 2x mod 1 maps with random starting values for xn. More info over at wikipedia and mathworld.

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

Math.random() * Math.random()

Actionscript:
  1. var rand:Number = Math.random() * Math.random() * Math.random();

This is a trick I use when I need more contrast in my random numbers. In this case, the variable rand will get closer to the number 1 significantly less frequently than if you just used Math.random() once.

To illustrate this I created this snippet:

Actionscript:
  1. [SWF(width=800, height=600)]
  2.  
  3. var r:Number = Math.random() * Math.random() * Math.random();
  4. var inc:int = 0;
  5. var xp:Number = 10;
  6. var yp:Number = 10;
  7. var count:int = 1;
  8.  
  9. var compare:Shape = Shape(addChild(new Shape()));
  10. compare.graphics.lineStyle(0,0x2222FF);
  11.  
  12. graphics.lineStyle(0,0x00000);
  13. scaleX = scaleY = 2;
  14.  
  15. addEventListener(Event.ENTER_FRAME, onLoop);
  16. function onLoop(evt:Event):void {
  17.    
  18.      r =  Math.random() * Math.random() * Math.random();
  19.  
  20.      if (inc == 0){
  21.          graphics.moveTo(xp + inc, yp + 30 - r * 30);
  22.      }else{
  23.          graphics.lineTo(xp + inc, yp + 30 - r * 30);
  24.      }
  25.      
  26.      r = Math.random();
  27.       if (inc == 0){
  28.          compare.graphics.moveTo(xp + inc, yp + 70 - r * 30);
  29.      }else{
  30.          compare.graphics.lineTo(xp + inc, yp + 70 - r * 30);
  31.      }
  32.      inc++;
  33.      if (inc == 50){
  34.          inc = 0;
  35.          xp = 10 + count % 6 * 60;
  36.          yp = 10 + int(count / 6) * 80;
  37.          r = Math.random()*Math.random();
  38.          count++;
  39.      }
  40. }

The blue lines plots normal Math.random() and the black lines plots Math.random()*Math.random()*Math.random()

Posted in one-liners, random | Tagged , , | 2 Comments