Adventures In Actionscript

Erik on Sep 21st 2006

I’ve been interested in porting Bee Commander to flash for a while, but I haven’t devoted much time to it. I did get the basic bee swarming working though. Let me tell you about my adventure.

When I wrote the main update loop I discovered that Actionscript lacks a foreach construct. Boo. I guess it’s back to C style for loops. So I came up with the following:

for(i = 0; i < length(bees); i++) {
	bees[i].update()
}

Looks reasonable, doesn’t it? It’s brutally slow. On my desktop the Python code can make 200 bees look good using hardware rendering, but in flash with this code it struggled to draw 25 bees at 30fps. I had to really fight to figure out where the problem was. It turns out that length(array) in Actionscript isn’t the same thing as len(array) in Python. The length function returns the number of characters in a string, not the length of an array. So why does the above work at all? And why does it run so slowly?

When I call length(bees), actionscript casts the array of bee objects into a single string containing the names of all the objects in the array, giving something like: “_level0.bee0,_level0.bee1,_level0.bee2…” It then walks the length of this string to count the characters, and returns that value. So what happens with the bees[i].update() when the index passes the end of the array? Nothing. The array access fails silently, and the loop continues. So the code calls update on every bee in the array, and the bees move correctly. It just happens very, very slowly. How slow? Well, if n is the number of elements in the array, length() walks a string of length 13n, and it does this 13n times before i < length(bees). So it's doing O(n^2) work to solve a problem that should be O(1). Throw in the overhead of the string conversion, and the extra length that it adds to the array, and it becomes easy to see why it is so painfully slow.

It seems that the correct way to loop across an array in Actionscript is like this:

for (i in bees) {
	bees[i].update()
}

After years of Perl and Python, this just seems weird. It’s like a foreach operator, but it returns the index instead of the value. Also, the magic “in” only seems to work in the context of the for loop. I guess it has something to do with the way arrays relate to objects in Actionscript. Take a look at this example:

a = [1,2,3]
a.myName = 'bob'
for (i in a) {
	trace(i)
}

The output is:

myName
2
1
0

Weird weird weird. You might think that this implies that array indexes can be accessed in the same manner as an object’s instance variables, and that a.1 is the same as a[1], but no that doesn’t work.

I don’t quite grok Actionscript yet, but I have bees swarming in flash reasonably well with the for(… in …) loop. If you have at least flash 7, you can check out my bad actionscript demo.

In other news I’ve been reading up on continuations. I’m fascinated by the way that Seaside takes tracking state in web based applications, and turns it into a list of imperative function calls. I wonder if I could do something similar for the structure of my games. Every time I work on handling levels and menus, animated clips, or any other number of tasks that require tracking state I feel like I’m writing bad hackish code and that there must be an elegant way to do it.

One last thing, Todd, Jay and I recently participated in the third PyWeek game programming competition. Shadow Runner is the name of our game, and it turned out to be kind of neat.

Filed in Games, Programing | 3 responses so far

3 Responses to “Adventures In Actionscript”

  1. Michael Peckham Sep 25th 2006 at 09:19 am 1

    Also try:

    for (var i = 0; i

  2. Michael Peckham Sep 25th 2006 at 09:20 am 2

    Oops — it ate my code… Let’s try this instead:

    for (var i = 0; i < myArray.length; i++)

  3. Michael Peckham Sep 25th 2006 at 09:23 am 3

    .length is an attribute of an Array object. length() is a function, which doesn’t even appear in the Actionscript 2.0 dictionary. Odd.

    I wonder if, when you called length(bees), it actually translated that as _root.length, which would cause no end of strangeness.

Comments RSS

Leave a Reply

Powered by WP Hashcash