Latest snippets

nesting(function(calls()))

[SWF(width=500, height=500, backgroundColor=0x000000, frameRate=30)]

for (var i:int = 0; i<10; i++){
       // draggable ellipse
	var dot:Sprite = drag(createSprite("Ellipse",  -10, -10, 20, 20));
	dot.x = Math.random() * stage.stageWidth ;
	dot.y = Math.random() * stage.stageHeight ;
}

for (i = 0; i<10; i++){
  
      var box:Sprite = drag(spin(createSprite("Rect", -20, -20, 40, 40, 0xFF0000), Math.random()*5 + 1));
	box.x = Math.random() * stage.stageWidth ;
	box.y = Math.random() * stage.stageHeight ;
}


 // createSprite can create ellipses or rectangles
function createSprite(shape:String, xp:Number, yp:Number, w:Number, h:Number, col:uint=0x444444):Sprite {
	var s:Sprite = new Sprite();
	s.graphics.beginFill(col);
	// trick from a previous post
	s.graphics["draw" + shape](xp, yp, w, h);
	addChild(s);
	return s;
}

// drag and spin add listeners to an untyped target and return that target for easy function nesting
function drag(target:*):*{
	target.addEventListener(MouseEvent.MOUSE_DOWN, function(evt:MouseEvent){ evt.currentTarget.startDrag(); });
	return target;
}

function spin(target:*, speed:Number):*{
	target.addEventListener(Event.ENTER_FRAME, function(evt:Event){ evt.currentTarget.rotation+=speed; });
	return target;
}

stage.addEventListener(MouseEvent.MOUSE_UP, function(){ stopDrag() });

The above will create some draggable circles and some rotating draggable rects… but that’s not really the point….

When prototyping and just playing around I write functions that take an Object as an argument, alter that Object in some way and pass that some Object out as a return value…. this makes it so I can write things like this:

drag(spin(createSprite("Rect", -20, -20, 40, 40, 0xFF0000), Math.random()*5 + 1));

Readability can be a problem so… consider that before using this for anything…

Image Airbrush

[SWF(width=500, height=500, backgroundColor=0x000000, frameRate=30)]

// draw an ugly gradient
var size:int = 500;
var pixNum:int = size * size;
var gradient:BitmapData = new BitmapData(size, size, true, 0xFF000000);

gradient.lock();
var xp:int, yp:int;
for (var i:int = 0; i<pixNum; i++){
	xp = i % size;
	yp = i / size;
	gradient.setPixel(xp, yp, (yp /= 2) << 16 | (255 - yp) << 8 | (xp / 2) );
}
gradient.unlock();

// draw an alphaChannel (radial gradient)
var radius:Number = 50;
var diameter:Number = radius * 2;

pixNum = diameter * diameter;

var brushAlpha = new BitmapData(diameter, diameter, true, 0x00000000);
var dx:int, dy:int;
var ratio:Number = 255 / radius;
var a:int;

brushAlpha.lock();
for (i = 0; i<pixNum; i++){
	xp = i % diameter;
	yp = i / diameter;
	dx = xp - radius;
	dy = yp - radius;
	a = int(255 - Math.min(255,Math.sqrt(dx * dx + dy * dy) * ratio));
	brushAlpha.setPixel32(xp, yp, a << 24);
}
brushAlpha.unlock();

// create a black canvas
var canvas:BitmapData = new BitmapData(size, size, true, 0xFF000000);
addChild(new Bitmap(canvas));

addEventListener(Event.ENTER_FRAME, onLoop);
function onLoop(evt:Event):void {
	// draw the gradient onto the canvas using the alphaChannel (brushAlpha);
	xp = mouseX - radius;
	yp = mouseY - radius;
	canvas.copyPixels(gradient, 
			        new Rectangle(xp, yp, diameter, diameter), 
			        new Point(xp, yp), brushAlpha, new Point(0,0), true);
}

This demo creates an airbrush that paints one BitmapData onto another. This is achieved by using the alpha related arguments of the BitmapData.copyPixels() function. If your not familiar with these you should take some time to play around with them… they’re very powerful.

copyPixels() is the fastest way to draw in flash, so if you need speed, copyPixels() is the way to go. It’s much faster than using draw().

Script List Pattern

var currentState:String = "";

var functionList:Vector.<Function> = new Vector.<Function>();

function clearFunctions():void{
	functionList = new Vector.<Function>();
}
function addFunction(f:Function):Function {
	functionList.push(f);
	return addFunction;
}

function removeFunction(f:Function):void {
	for (var i:int = 0 ; i<functionList.length; i++){
		if (f == functionList[i]){
			functionList.splice(i, 1);
		}
	}
}

function runProgram():void {
	
	currentState = "current: ";
	
	for (var i:int = 0; i<functionList.length; i++){
		functionList[i]();
	}
	
	trace(currentState);
}

function one():void{
	currentState += " one";
}

function two():void {
	currentState += " two";
}

function three():void {
	currentState += " three";
}

function dot():void{
	currentState += ".";
	
}

// test it: 
addFunction(one);
addFunction(two);
addFunction(three);

runProgram();

removeFunction(one);

runProgram();

addFunction(dot)(dot)(dot);

runProgram();

clearFunctions();

addFunction(dot)(dot)(dot);

addFunction(three)(two)(one)(dot)(dot)(dot);

runProgram();

/* outputs: 
current:  one two three
current:  two three
current:  two three...
current: ... three two one...
*/

This is a very quick implementation of a pattern that I use sometimes. The idea of this pattern is very simple and can easily be implemented in OOP or procedural style programming. The idea is to have a Vector/Array of functions or Class instances. Loop through this Vector/Array and run each function (or a given method of each Class instance). During runtime your client code can alter this list to change what the program does.

I use this technique for games quite often. All enemies get added to an enemy list – this list is looped through and each enemies run() method is called. If an enemy dies it dispatches an event that tells the enemy manager to remove it from the list. Some pseudo code:

function onMainLoop():void{
	if (!paused){
		
		runWorld();
		runKeys();
		runChar();
		
		enemyManager.runEnemies();
		
		runPickups();
		
	}else{
		// show pause screen
	}
}

//... inside EnemyManager class
function onRunEnemies():void{
	for (var i:int = 0; i<enemyList.length; i++){
			enemyList[i].run(i);
	}
}

I use the same technique for pickups (coins, lives etc….).

I first used this technique in Director with a list of parent scripts.

I’m aware of other more refined patterns that are meant to do similar things, but for small to medium sized apps this has worked very nicely for me.

BitmapData lock() & unlock()

var size:Number = 400;
var pixelNum:Number = size * size;
var pixels:Vector.<uint> = new Vector.<uint>();
var r:uint;
var g:uint;
var b:uint;

var canvas:BitmapData = new BitmapData(size,size,false,0x000000);
addChild(new Bitmap(canvas));

addEventListener(Event.ENTER_FRAME, onLoop);
function onLoop(evt:Event):void {

	canvas.lock();

	// do any kind of pixel manipulation here:
	
	for (var i:int = 0; i<pixelNum; i++) {
		// draw a gradient that changes based on
	    // mouse position
		r = i % size + mouseX;
		b = i / size + mouseY;
		g = (r + b) % mouseX;
		pixels[i] = r << 16 | g << 8 | b;
	}
	canvas.setVector(canvas.rect, pixels);
	//

	canvas.unlock();
}

Using BitmapData.lock() and BitmapData.unlock() can speed up BitmaData drawing operations significantly. Simply lock your BitmapData before you draw to it, and unlock it when your done.

I often forget to do this until I get to the optimize phase of a project… but I think I’d like to get in the habit of doing it all the time….

BitmapData Trails

[SWF(width=400, height=400, backgroundColor=0xCCCCCC, frameRate=30)]

var canvas:BitmapData = new BitmapData(400, 400, true, 0xCCCCCC);
var eraser:BitmapData = new BitmapData(400, 400, true, 0x22CCCCCC);
addChild(new Bitmap(canvas));

var circle:Shape = Shape(addChild(new Shape()));
with (circle.graphics) beginFill(0x000000), drawCircle(0,0,20);

addEventListener(Event.ENTER_FRAME, onLoop);

function onLoop(evt:Event):void {
	canvas.copyPixels(eraser, eraser.rect, new Point(0,0), null, null, true);
	circle.x = mouseX;
	circle.y = mouseY;
	
	canvas.draw(circle, circle.transform.matrix);
}

Create trails by slowly erasing the background with copyPixels(). The first time I ever saw this technique was back when setpixel.com contained a bunch of great director experiments by Charles Foreman (creator of iminlikewithyou.com).

At some point last semester I showed iminlikewithyou hamster battle to my undergrad students towards the end of class…. probably one of the funniest moments of that class.

Jumping on a 2D Circle

var circle:Shape = Shape(addChild(new Shape()));
with(circle.graphics) beginFill(0xCCCCCC), drawCircle(0,0,100);
circle.x = stage.stageWidth / 2;
circle.y = stage.stageHeight / 2;

var charWorld:MovieClip = MovieClip(addChild(new MovieClip()));
charWorld.x = circle.x ;
charWorld.y = circle.y - 100 - 10
charWorld.thetaSpeed = 0;
charWorld.theta  = -Math.PI / 2;

var char:MovieClip = MovieClip(charWorld.addChild(new MovieClip))
with(char.graphics) beginFill(0x000000), drawRect(-10,-10,10,10);
char.posY = 0;
char.velY = 0;

addEventListener(Event.ENTER_FRAME, onRunChar);
function onRunChar(evt:Event):void {
	
	char.velY += 1;
	char.posY += char.velY;
	
	charWorld.thetaSpeed *= .6;
    charWorld.theta += charWorld.thetaSpeed;
	
	if (key[Keyboard.UP]){
		if (char.y == 0){
		  char.velY = -10;
		}
	}
	
	if (key[Keyboard.RIGHT]){
		charWorld.thetaSpeed = .1;
	}
	
	if (key[Keyboard.LEFT]){
		charWorld.thetaSpeed = -.1;
	}
	
	if (char.posY > 0){
		char.posY = 0;
	}
	
	char.y = char.posY;
	
	charWorld.x = circle.x + 100 * Math.cos(charWorld.theta);
	charWorld.y = circle.y + 100 * Math.sin(charWorld.theta);
	charWorld.rotation = Math.atan2(circle.y- charWorld.y, circle.x - charWorld.x) / Math.PI * 180 - 90;
}

var key:Object = new Object();
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyReleased);
function onKeyPressed(evt:KeyboardEvent):void {
	key[evt.keyCode] = true;
	key.keyCode = evt.keyCode;
}

function onKeyReleased(evt:KeyboardEvent):void {
	key[evt.keyCode] = false
}

For some reason I felt like posting the swf…. have a look here .

This is one that’s been kicking around in my head for awhile – finally got around to writing it. It creates a circle and a small black box. The box walks and jumps on the circle with key input (left arrow, right arrow and up arrow).

There’s an odd trick going on here. Basically, the box (or char) movieClip is nested inside another clip. Within this clip (charWorld) the box moves on the y axis (jumping/up key). The charWorld clip orbits around the circle and rotates toward the center of the circle – sine/cosine are used for the orbit so the left and the right keys control the speed of theta.

Bezier Skin (smooth curveTo())

// graphics, vector of xy coords, closed boolean
function bezierSkin(g:Graphics, bez:Vector.<Number>, closed:Boolean = true):void {
	var avg:Vector.<Number> = calcAvgs(bez);
	var i:int, n:int;
	var leng:int = bez.length;

	if (closed){
		g.moveTo(avg[0], avg[1]);
		for (i = 2; i < leng; i+=2) {
			n=i+1;
			g.curveTo(bez[i], bez[n], avg[i], avg[n]);
		}
		g.curveTo(bez[0], bez[1], avg[0], avg[1]);
	}else{
		g.moveTo(bez[0], bez[1]);
	    g.lineTo(avg[0], avg[1]);
		for (i = 2; i < leng-2; i+=2) {
			n=i+1;
			g.curveTo(bez[i], bez[n], avg[i], avg[n]);
		}
		g.lineTo(bez[ leng - 2], bez[ leng - 1]);
	}
}

// create anchor points by averaging the control points
function calcAvgs(v:Vector.<Number>):Vector.<Number> {
	var avg:Vector.<Number> = new Vector.<Number>();
	var leng:int=v.length;
	for (var i:int = 2; i<leng; i+=1) {
		var prev:Number=i-2;
		avg.push( (v[prev] + v[i]) / 2 );
	}
	// close
	avg.push( (v[0] + v[ leng - 2]) / 2 );
	avg.push( (v[1] + v[ leng - 1]) / 2 );
	return avg;
}

// test out the functions:

graphics.lineStyle(0,0x000000);

// draw a very rounded rect
bezierSkin(graphics, Vector.<Number>([100,100,200,100,200,200,100,200]) );

// draw a random curve with 10 xy coords
var rnd:Vector.<Number> = new Vector.<Number>();
for (var i:int = 0; i<20; i++) rnd.push(Math.random()*100);
bezierSkin(graphics, rnd);
						
// erase everything and allow the used to draw a smooth curve with the mouse
stage.addEventListener(MouseEvent.MOUSE_DOWN, onLoop);
var index:int = 0;
var pnts:Vector.<Number> = new Vector.<Number>();

function onLoop(evt:MouseEvent):void {
	 pnts.push(mouseX);
	 pnts.push(mouseY);
	
     graphics.clear();
	 graphics.lineStyle(0,0x000000);
	 
	  // draw a smooth curved line
	 bezierSkin(graphics,pnts,false);
}

The above code uses averaging to generate anchor points for curveTo() calls. This is an easy way to always draw smooth curves.

This is an old one that I’ve seen floating around since the drawing api first came out… but I it’s an important snippet, so I figured I’d post it.

Quadratic Bezier

var canvas:BitmapData=new BitmapData(280,280,false,0x000000);
addChild(new Bitmap(canvas, PixelSnapping.AUTO, true));
var color:uint;
// anchor x1, anchor y1,
// control-handle x2, control-handle y2,
// anchor x3, anchor y3, [resolution incremental value between 0-1]
function quadBezier(x1:Number, y1:Number, x2:Number, y2:Number, x3:Number, y3:Number, resolution:Number=.03):void {
	var b:Number,pre1:Number,pre2:Number,pre3:Number,pre4:Number;
	for (var a:Number = 0; a <1;a+=resolution) {
	
		b=1-a;
		pre1=(a*a);
		pre2=2*a*b;
		pre3=(b*b);
		
		canvas.setPixel(pre1*x1 + pre2*x2  + pre3*x3 ,
						             pre1*y1 + pre2*y2 + pre3*y3, color);
	}
}

// draw a few
color = 0xFFFFFF;

for (var i:int = 0; i<20; i++){
quadBezier(40,100, 150 , 20 + i * 10 , 200, 100,.01);
}

color = 0xFF0000;

for (i= 0; i<20; i++){
quadBezier(150,200, 100 + i * 10, 100  , 120, 30,.01);
}

The above demos a function that draws quadratic bezier curves using setPixel().

One of the first posts on this site was a snippet that used setPixel() to draw a cubic bezier curve. I recently needed to do the exact same thing but I wanted to use a quadratic bezier… I knew I had the code laying around somewhere, but I couldn’t seem to find it so I just looked on wikipedia and changed the previous cubicBezier() function accordingly.

Bresenham Circle Filled

var canvas:BitmapData = new BitmapData(400, 400, false, 0xCCCCCC);
addChild(new Bitmap(canvas));

fillCircle(100,100,50,0xFF0000);

function fillCircle(xp:Number,yp:Number, radius:Number, col:uint = 0x000000):void {
    var xoff:int =0;
	var yoff:int = radius;
	var balance:int = -radius;

	while (xoff <= yoff) {
		 var p0:int = xp - xoff;
		 var p1:int = xp - yoff;
		 
		 var w0:int = xoff + xoff;
		 var w1:int = yoff + yoff;
		 
		 hLine(p0, yp + yoff, w0, col);
		 hLine(p0, yp - yoff, w0, col);
		 
		 hLine(p1, yp + xoff, w1, col);
		 hLine(p1, yp - xoff, w1, col);
		
		if ((balance += xoff++ + xoff) >= 0) {
			balance-=--yoff+yoff;
		}
	}
}
 
function hLine(xp:Number, yp:Number, w:Number, col:uint):void {
	for (var i:int = 0; i < w; i++){
		canvas.setPixel(xp + i, yp, col);
	}
}

An implementation of yesterdays post that draws a filled circle instead of an outlined circle.

Bresenham Circle No Multiplication

var canvas:BitmapData = new BitmapData(400, 400, false, 0xCCCCCC);
addChild(new Bitmap(canvas));

drawCircle(200,100, 50);

// y, y radius, color
function drawCircle(xp:Number,yp:Number, radius:Number, col:uint =0x000000):void {
	var balance:int;
	var xoff:int;
	var yoff:int;
	xoff=0;
	yoff=radius;
	balance=- radius;

	while (xoff <= yoff) {
		canvas.setPixel(xp+xoff, yp+yoff, col);
		canvas.setPixel(xp-xoff, yp+yoff, col);
		canvas.setPixel(xp-xoff, yp-yoff, col);
		canvas.setPixel(xp+xoff, yp-yoff, col);
		canvas.setPixel(xp+yoff, yp+xoff, col);
		canvas.setPixel(xp-yoff, yp+xoff, col);
		canvas.setPixel(xp-yoff, yp-xoff, col);
		canvas.setPixel(xp+yoff, yp-xoff, col);

		if ((balance += xoff++ + xoff) >= 0) {
			balance-=--yoff+yoff;
		}
	}
}

The above demos a circle drawing algorithm. This will draw an outlined circle with no fill. This implementation doesn’t use multiplication.

Using setPixel to draw primitive shapes can be a good learning experience. I found this basic implementation of the Bresenham Circle algorithm a few years back and lost the original link…. I dug around for a good hour trying to find the original but to no avail. So if someone recognizes this interesting implementation …. let me know 🙂

The original code was written in java I think.

If your curious. The standard implementation I keep finding online looks something like this:

// ported from http://www.codeuu.com/Bresenham_Circle
function drawCircle(cx:Number, cy:Number, r:Number, col:uint):void{
	var xp:int  = 0, yp:int= r ;
	var d:int = 3 - (2 * r);
	
	while(xp <= yp){
		
		canvas.setPixel(cx+xp,cy+yp,col);
		canvas.setPixel(cx+yp,cy+xp,col);
		canvas.setPixel(cx-xp,cy+yp,col);
		canvas.setPixel(cx+yp,cy-xp,col);
		canvas.setPixel(cx-xp,cy-yp,col);
		canvas.setPixel(cx-yp,cy-xp,col);
		canvas.setPixel(cx+xp,cy-yp,col);
		canvas.setPixel(cx-yp,cy+xp,col);
		
		if (d<0){
			d += (4*xp)+6;
		}else{
			d += (4*(xp-yp))+10;
			yp -= 1;
		}
		xp++;
	}
	
}

I did a few speed tests against the first one that doesn’t make use of multiplication and it is only ever so slightly faster….