Browse the notebook

Category: arrays

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.

Read snippet: Script List Pattern

Dynamic Vars Dictionary


var vars:Dictionary = new Dictionary();

var sp:Sprite = new Sprite();

// associate variables with a sprite (or any non-dynamic class)
vars[sp] = {posX:100, posY:100, velX:1, velY:1};

// read
trace(vars[sp].posX);

I’ve heard people mention that they wish the sprite class were dynamic… meaning they wish they could add methods and properties to a Sprite instance at runtime. There’s no way I know of to do this, however… the dictionary class can be used to associate variables with any non-dynamic class instance… as it does in this the above example.

The dictionary class is similar to an associative array except that instead of using strings for keys, dictionaries use object instances.

Read snippet: Dynamic Vars Dictionary

2D Vector

var map:Vector.<Vector.<int>> = new Vector.<Vector.<int>>();
map[0] = new Vector.<int>();
map[0].push(1);
map[0].push(0);
map[0].push(0);

map[1] = new Vector.<int>();
map[1].push(0);
map[1].push(1);
map[1].push(0);

map[2] = new Vector.<int>();
map[2].push(0);
map[2].push(0);
map[2].push(1);

/*
map:
1,0,0
0,1,0
0,0,1
*/

This creates a two dimensional Vector of ints (flash 10 player only). The first line is the real snippet… took me a few minutes to get the syntax right the first time I needed a 2D Vector.

Read snippet: 2D Vector

Animate Along a Path

stage.frameRate = 30;
var pencil:Shape = new Shape();
addChild(pencil);

var index:int = 0;
var points:Array = new Array();
var circle:Shape = new Shape();
circle.graphics.beginFill(0x000000);
circle.graphics.drawCircle(0,0, 5);
addChild(circle);

stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);

circle.addEventListener(Event.ENTER_FRAME, onMoveCircle);

function onDown(evt:MouseEvent):void {
	pencil.graphics.lineStyle(0,0x000000);
	pencil.graphics.moveTo(mouseX, mouseY);
	stage.addEventListener(MouseEvent.MOUSE_MOVE, onDraw);
}

function onUp(evt:MouseEvent):void {
	stage.removeEventListener(MouseEvent.MOUSE_MOVE, onDraw);
}

function onDraw(evt:Event):void {
	pencil.graphics.lineTo(mouseX, mouseY);
	points.push(new Point(mouseX, mouseY));
}

function onMoveCircle(evt:Event):void {
	if (points.length>0) {
		circle.x += (points[index].x - circle.x) / 4;
		circle.y += (points[index].y - circle.y) / 4;
		index++;
		if (index==points.length) {
			index=0;
		}
	}
}

Wrote this in response to a student question. It causes a circle shape to animate along lines drawn by the user.

Read snippet: Animate Along a Path

2D Z-Sort

var shapes:Array = new Array();

for (var i:int = 0; i<300; i++){
	var s:Shape = new Shape();
	s.x = Math.random()* stage.stageWidth;
	s.y = Math.random()* stage.stageHeight;
	s.graphics.lineStyle(0,0x000000);
	s.graphics.beginFill(0xCCCCCC);
	s.graphics.drawCircle(0,0, Math.random()*s.y / 5);
	shapes.push(s);
}

// comment this out to remove sorting
shapes.sortOn("width", Array.NUMERIC);

for (i = 0; i<shapes.length; i++){
	addChild(shapes[i]);
}

This uses Array.sortOn() to do some basic z-sorting based on the width property of some circle shapes.

Read snippet: 2D Z-Sort

2D Array Map

var col:Array = [0x000000, 0xCCCCCC, 0xFF0000, 0xCCCC00, 0x000055, 0x00CCCC];

var map:Array = new Array();
map[0] = [0,0,0,0,0,0,0,0,0,0];
map[1] = [0,0,0,0,0,0,0,0,0,0];
map[2] = [0,5,4,5,4,5,4,5,4,0];
map[3] = [0,4,4,4,4,4,4,4,4,0];
map[4] = [0,4,0,0,0,0,0,0,4,0];
map[5] = [0,3,2,3,2,3,2,3,2,0];
map[6] = [1,1,1,1,1,1,1,1,1,1];
map[7] = [0,2,2,2,2,2,2,2,2,0];
map[8] = [1,1,1,1,1,1,1,1,1,1];

for (var i:int = 0; i<map.length; i++){
	for (var j:int = 0; j<map[i].length; j++){
		graphics.beginFill(col[map[i][j]]);
		graphics.drawRect(j * 10, i * 10, 10, 10);
	}
}

Use a 2D array to draw a map of colored rectangles. Lots of stuff you can do with this – like adding game tiles instead of drawing colored rects:

// add clip with multiple frames - each containing a tile graphic
var tile:MovieClip = TileClip();
tile.gotoAndStop(map[i][j]+1);
addChild(tile);
Read snippet: 2D Array Map

Associative Array Function Call

for (var i:int = 0; i<4; i++){
	this["phase"+i]();
}

function phase0():void{
	trace("phase 0");
}
function phase1():void{
	trace("phase 1");
}
function phase2():void{
	trace("phase 2");
}
function phase3():void{
	trace("phase 3");
}

/*
will output:
phase 0
phase 1
phase 2
phase 3
*/

/*
WARNING: This code was written for fun. Use at your own risk.
*/

I was pleasantly surprised back in the AS1 days… when I discovered that associative array syntax worked along with function calls (why wouldn’t it?). There are some interesting tricks you can do with this technique…. will post some later….

Read snippet: Associative Array Function Call

Quick Alphabet Array

var alphabet:Array = ("abcdefghijklmnopqrstuvwxyz").split("");
trace("this is the letter b...", alphabet[1]);
trace(alphabet);
/* outputs:
this is the letter b... b
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
*/

This is an easy way to create an array of the alphabet. It’s easier to type than:

var alphabet:Array = ["a","b","c".... etc];
Read snippet: Quick Alphabet Array