By Zevan | March 10, 2010
Something I do a fair bit on this website is use functions as objects. Here is a simple example post on wonderfl. Timeline code and a brief description are available below.
Here is a still of what it generates and below you'll find the timeline as code:
Actionscript:
-
[SWF(width = 500, height=500)]
-
-
var canvas:BitmapData = new BitmapData(800,800,false, 0x000000);
-
addChild(new Bitmap(canvas,"auto",true));
-
scaleX = scaleY = 500 / 800
-
-
-
var walkerNum:int = 50;
-
var walkers:Vector.<Function> = new Vector.<Function>(walkerNum, true);
-
-
makeWalkers();
-
runWalkers();
-
-
function makeWalkers():void{
-
for (var i:int = 0; i<walkerNum; i++){
-
walkers[i] = makeWalker();
-
}
-
}
-
function runWalkers():void{
-
addEventListener(Event.ENTER_FRAME, onRun);
-
}
-
function onRun(evt:Event):void{
-
for (var i:int = 0; i<walkerNum; i++){
-
walkers[i]();
-
}
-
}
-
-
function makeWalker(xp:Number=400, yp:Number=400):Function{
-
var x:Number = xp, y:Number = yp;
-
var rad:Number = Math.random() * 4;
-
var theta:Number = Math.random() * Math.PI * 2;
-
var speed:Number = 0.01 * Math.random() * 2
-
if (int(Math.random() * 2) == 1){
-
speed *= -1;
-
}
-
return function():void{
-
x += rad * Math.cos(theta);
-
y += rad * Math.sin(theta);
-
theta += speed
-
if (int(Math.random() * 100) == 1){
-
theta = Math.random() * Math.PI * 2;
-
}
-
if (x> 800 || x <0 || y> 800 || y <0){
-
x = xp, y = yp;
-
}
-
canvas.setPixel(x, y, 0xFFFFFF);
-
}
-
}
The basic trick is to have a function return a function. The original function initializes typed local variables and the returned function has access to these values. This is one of many ways to do OOP style coding using functions alone. This is really only for fun and for speed coding reasons - it's worth noting that this method is is significantly slower than using actual classes. I still have lots of fun with it despite the downsides.
Also posted in BitmapData | Tagged actionscript, as3, flash |
If you haven't looked at every post on this site it's possible you've missed one of my favorite actionscript features.... Bracket Syntax:
Actionscript:
-
var s:Sprite = Sprite(addChild(new Sprite()));
-
s["x"] = 100;
-
s["y"] = 100;
-
-
s["graphics"]["beginFill"](0xFF0000);
-
s["graphics"]["drawCircle"](0,0,10);
-
-
this["addChild"](s);
If you don't realize how powerful this is then there is something wrong with you (joking). If you don't see how powerful this is, take some time and think about it. You can use it to avoid lots of annoying repetitive code in state machines for instance. It's always important to keep things readable if you decide to go this route on a real project.
[EDIT ....and as Quasimondo mentioned there is a notable performance hit when using this syntax. So don't forget to keep that in mind.]
Here is a very old post showing some of the power of this trick.
Also posted in dynamic | Tagged actionscript, as3, flash |
If you're at all interested in watching me free from code. I recorded a video of me coding this snippet (which is about 11 minutes long or so).
In the video I create a few functions that allow you to draw shapes like these:
Mathematically this stuff is really simple ... the free form nature of the video takes a less technical perspective as you'll see (I even made a few funny mistakes).
Actionscript:
-
[SWF(width = 600, height = 600)]
-
var dotNum:int = 1000;
-
var dotRad:Number = 0.5;
-
-
x = 120
-
y = 100;
-
-
// extra stuff to display what the functions can do
-
stage.addEventListener(MouseEvent.CLICK, onDrawAll);
-
-
function onDrawAll(evt:Event):void{
-
graphics.clear();
-
for (var i:int = 0; i<16; i++){
-
var m:Number;
-
-
var rad:Number = 120;
-
var xp:Number = i % 4 * rad
-
var yp:Number = int(i / 4) * rad
-
-
var type:int = int(Math.random() * 4);
-
if (type == 0){
-
makeShape(xp, yp, rad-60, Math.random() , 1);
-
}else if (type == 1){
-
makeShape(xp, yp, rad-60, 1, Math.random());
-
}
-
else if (type == 2){
-
m = Math.random() * 2;
-
makeShape(xp, yp, rad-Math.random()*120, m, m);
-
}
-
else if (type == 3){
-
m = Math.random() * 2;
-
makeShape(xp, yp, rad-Math.random()*120, m, m/2);
-
}
-
}
-
}
-
-
// main part from the video
-
function makeShape(xp:Number, yp:Number,
-
maxRad:Number = 100,m0:Number=1,
-
m1:Number=1):void{
-
var polarX:Number;
-
var polarY:Number;
-
var radius:Number;
-
graphics.lineStyle(0, 0);
-
var theta:Number = Math.random() * Math.PI * 2;
-
for (var i:int = 0; i<dotNum; i++){
-
radius = Math.random() * maxRad
-
polarX = xp + radius * Math.cos(theta * m0);
-
polarY = yp + radius * Math.sin(theta * m1);
-
theta += 0.1;
-
-
makeDot(polarX, polarY);
-
-
}
-
}
-
-
function makeDot(xp:Number, yp:Number, fillColor:uint = 0x000000):void{
-
graphics.beginFill(fillColor);
-
graphics.drawCircle(xp, yp, dotRad);
-
graphics.endFill();
-
}
Here it is over at wonderf:
By Zevan | January 2, 2010
Actionscript:
-
var a:Array = [1,2,3,4,5,6];
-
var double:Array = a.map(function():int{return arguments[0] * 2});
-
trace(double);
-
/*outputs:
-
2,4,6,8,10,12
-
*/
A condensed example of Array.map()
Here is the same thing written in haskell:
a = [1,2,3,4,5,6]
double = map (*2) a
main = print double
Also posted in arrays | Tagged actionscript, as3, flash |