package com.quasimondo.tools { /* ************************************************ TITLE: Marching Ants Rectangle VERSION: 1.0 AUTHOR: Mario Klingemann CREATED: October 3, 2005 http://www.quasimondo.com Converted to AS3 and added support for non-rectangular objects Nov 2010, by jensa {a} flashgamer.com Basic Usage: var demo:MarchingAntsRect = new MarchingAntsRect(); demo.draw( some_canvas_mc, new Rectangle(50,50,100,100) ); Advanced Usage: var colors:Array = new Array(0xffff8000,0x00000000,0xff000000,0x00000000); var pattern:Array = new Array( 4,2,4,2 ); var updateSpeed:Number = 100; var stepSize:Number = -2; var demo:MarchingAntsRect = new MarchingAntsRect( colors, pattern); demo.draw( some_canvas_mc, new Rectangle(50,50,100,100) , updateSpeed, stepSize ); The rectangle will be automatically animated until the clear() method is called. To use a series of points rather than just a rect, use 'drawArray' instead: var myPoints:Array = new Array( new Point(0,0), new Point(50,0), new Point(50,50), new Point(100,50), new Point(100, 100), new Point(0, 75), new Point(0, 0) ); demo.drawArray( some_canvas_mc, myPoints, updateSpeed, stepSize ); A more complete example: var complexMC:MovieClip = new MovieClip(); this.addChild( complexMC ); var colors2:Array = new Array(0xffff0000,0xffff3333,0xffff6666,0xffff9999,0xffffcccc,0xffffffff); var pattern2:Array = new Array( 1,1,1,1,1,2 ); var myPoints:Array = new Array( new Point(0,0), new Point(50,0), new Point(50,50), new Point(100,50), new Point(100, 25), new Point(110, 25), new Point(110,50), new Point(50, 105), new Point(0, 75), new Point(0, 0) ); var demo3:MarchingAntsRect = new MarchingAntsRect( colors2, pattern2); demo3.drawArray( advancedMC, myPoints , updateSpeed, 3 ); ************************************************ */ import flash.display.BitmapData; import flash.display.MovieClip; import flash.geom.Matrix; import flash.geom.Point; import flash.geom.Rectangle; import flash.utils.clearInterval; import flash.utils.getTimer; import flash.utils.setInterval; public class MarchingAntsRect { private var patternLength:Number; private var colors:Array; private var pattern:Array; private var patternMap:BitmapData; private var copyRect:Rectangle; static private var copyPoint:Point = new Point(1,0); private var updateID:Number; private var lastUpdate:Number; public function MarchingAntsRect( colors:Array = null, pattern:Array = null ) { setPattern( colors, pattern ); } public function setPattern( colors:Array, pattern:Array ):void { if ( !colors ){ this.colors = new Array( 0xff000000, 0xffffffff ); } else { this.colors = colors.slice(); } if (!pattern || pattern.length != this.colors.length){ this.pattern = new Array( 2, 2 ); } else { this.pattern = pattern.slice(); } initBitmap(); } public function drawArray( canvas:MovieClip, arr:Array, speed:Number = 100, steps:Number = 1 ):void { paintArray( canvas, arr ); setupTimer( speed, steps ); } public function draw( canvas:MovieClip, rect:Rectangle, speed:Number = 100, steps:Number = 1 ):void { paint( canvas, rect ); setupTimer( speed, steps ); } private function setupTimer( speed:Number, steps:Number ):void { if (!speed) speed = 32; if (speed!=0 && speed < 10 ) speed = 10; if (!steps) steps = 1; steps = ((steps % patternLength) + patternLength ) % patternLength; clearInterval( updateID ); if (speed!=0){ updateID = setInterval( update, speed, steps ); } if (getTimer()-lastUpdate > speed) update(steps); } public function clear():void { clearInterval( updateID ); } private function paintArray( canvas:MovieClip, r:Array ):void { var i:int = 1; var l:int = r.length; var p:Point; var prevPoint:Point; var angle:Number; var pWidth:Number if(l>0){ prevPoint = r[0]; } while( i < l ){ p = r[i]; angle = ( findAngle(prevPoint,p)*RADTODEG )+180; pWidth = Math.abs( p.x-prevPoint.x ); if( angle > 45 && angle < 135){ // Line going right canvas.graphics.beginBitmapFill( patternMap, new Matrix( 1,0,0,1,p.x % patternLength ,0) ); canvas.graphics.moveTo( prevPoint.x, prevPoint.y ); canvas.graphics.lineTo (p.x, p.y ); canvas.graphics.lineTo (p.x, p.y+1 ); canvas.graphics.lineTo (prevPoint.x, prevPoint.y+1 ); canvas.graphics.lineTo (prevPoint.x, prevPoint.y ); } else if( angle > 135 && angle < 225 ){ // Line going upwards canvas.graphics.beginBitmapFill( patternMap, new Matrix( 0,-1,1,0,0, p.y % patternLength ) ); canvas.graphics.moveTo( prevPoint.x, prevPoint.y ); canvas.graphics.lineTo (p.x, p.y ); canvas.graphics.lineTo (p.x+1, p.y ); canvas.graphics.lineTo (prevPoint.x+1, prevPoint.y ); canvas.graphics.lineTo (prevPoint.x, prevPoint.y ); } else if( angle > 225 && angle < 315 ){ // Line going left canvas.graphics.beginBitmapFill( patternMap, new Matrix( -1,0,0,1, p.y % patternLength ,0) ); canvas.graphics.moveTo( prevPoint.x, prevPoint.y ); canvas.graphics.lineTo (p.x, p.y ); canvas.graphics.lineTo (p.x, p.y+1 ); canvas.graphics.lineTo (prevPoint.x, prevPoint.y+1 ); canvas.graphics.lineTo (prevPoint.x, prevPoint.y ); } else { // Line going downwards canvas.graphics.beginBitmapFill( patternMap, new Matrix( 0,1,1,0,0,1 + p.y % patternLength + patternLength - pWidth % patternLength) ); canvas.graphics.moveTo( prevPoint.x, prevPoint.y ); canvas.graphics.lineTo (p.x, p.y ); canvas.graphics.lineTo (p.x+1, p.y ); canvas.graphics.lineTo (prevPoint.x+1, prevPoint.y ); canvas.graphics.lineTo (prevPoint.x, prevPoint.y ); } canvas.graphics.endFill(); prevPoint = p; i++; } } public static const RADTODEG : Number = 180/Math.PI; public static const DEGTORAD : Number = Math.PI/180; // returns answer as radians public static function findAngle(point1:Point, point2:Point):Number { var dx:Number = point2.x - point1.x; var dy:Number = point2.y - point1.y; return Math.atan2(dx,dy); } private function paint( canvas:MovieClip, r:Rectangle ):void { var rect:Rectangle = new Rectangle( r.width < 0 ? r.x + r.width : r.x, r.height < 0 ? r.y + r.height : r.y, Math.abs(r.width), Math.abs(r.height)); canvas.graphics.lineStyle(); canvas.graphics.moveTo( rect.left, rect.top ); canvas.graphics.beginBitmapFill( patternMap, new Matrix( 1,0,0,1,rect.left % patternLength ,0) ); canvas.graphics.lineTo (rect.left + rect.width, rect.top ); canvas.graphics.lineTo (rect.left + rect.width, rect.top + 1 ); canvas.graphics.lineTo (rect.left, rect.top + 1 ); canvas.graphics.lineTo (rect.left, rect.top ); canvas.graphics.endFill(); canvas.graphics.moveTo( rect.left + rect.width, rect.top + 1 ); canvas.graphics.beginBitmapFill( patternMap, new Matrix( 0,1,1,0,0,1 + rect.top % patternLength + patternLength - rect.width % patternLength) ); canvas.graphics.lineTo (rect.left + rect.width, rect.top + rect.height ); canvas.graphics.lineTo (rect.left + rect.width - 1, rect.top + rect.height ); canvas.graphics.lineTo (rect.left + rect.width- 1, rect.top + 1); canvas.graphics.lineTo (rect.left + rect.width, rect.top + 1); canvas.graphics.endFill(); canvas.graphics.moveTo( rect.left, rect.top + rect.height - 1 ); canvas.graphics.beginBitmapFill( patternMap, new Matrix( -1,0,0,1, rect.left + rect.width - 1 - ( patternLength - ( rect.width + rect.height - 1) % patternLength),0) ); canvas.graphics.lineTo (rect.left + rect.width - 1, rect.top + rect.height -1 ); canvas.graphics.lineTo (rect.left + rect.width - 1, rect.top + rect.height ); canvas.graphics.lineTo (rect.left, rect.top + rect.height ); canvas.graphics.lineTo (rect.left, rect.top + rect.height - 1 ); canvas.graphics.endFill(); canvas.graphics.moveTo( rect.left, rect.top + 1 ); canvas.graphics.beginBitmapFill( patternMap, new Matrix( 0,-1,1,0,0, 1 + rect.top % patternLength ) ); canvas.graphics.lineTo (rect.left + 1, rect.top + 1 ); canvas.graphics.lineTo (rect.left + 1, rect.top + rect.height - 1 ); canvas.graphics.lineTo (rect.left, rect.top + rect.height - 1 ); canvas.graphics.lineTo (rect.left, rect.top + 1); canvas.graphics.endFill(); } private function update( steps:Number ):void { do{ var p:Number = patternMap.getPixel32( patternMap.width - 1, 0 ); patternMap.copyPixels( patternMap, copyRect, copyPoint ); patternMap.setPixel32( 0 , 0 , p ); } while ( --steps > 0 ); lastUpdate = getTimer(); } private function initBitmap():void { var i:int; var j:int; patternLength=0; for (i = 0; i < pattern.length; i++) { patternLength += pattern[i]; } patternMap = new BitmapData( patternLength, 1, true, 0); var x:Number = 0; for (i = 0 ; i < pattern.length; i++ ) { for (j = 0 ; j < pattern[i]; j++ ) { patternMap.setPixel32( x++ , 0, colors[i] ); } } copyRect = new Rectangle( 0 , 0 , patternLength - 1 , 1 ); } } }