views:

170

answers:

3

I have a Array of Characters objects (extends Sprite).

public static var charlist:Array;

When a Character die, I set a flag to indicate that.

char.die = true;

When I spawn a new player, I check against this flag, to reuse the slot. This is where the problem comes. What is the best way to do that? Actually I have this approach:

char = new Char();
/* ... */
for (var i:Number = 0; i < Char.charlist.length; i++) {
 if (Char.charlist[i].death) {
  Char.charlist[i] = char;
  return;
 }
}

But the problem is that I come from C++ and I think calculating the index every iteration is wasteful.
I would do this, but this doesn't work in AS3, since I can't access by reference the item:

char = new Char();
/* ... */
for (var i:Number = 0; i < Char.charlist.length; i++) {
 var char_it:Char = Char.charlist[i];
 if (char_it.death) {
  char_it = char;
  return;
 }
}

Just a note: charlist is a static member of class Char.

Do you have any ideas or better approaches?

Thanks!

A: 

Why not to use a list instead of array and simply remove dead ones from the list and add new one when needed?
Is there a good reason to try to reuse the slot?
What are you trying to optimize?

z-boss
A: 

Is there a reason you can't just splice out the desired character and push a new character onto the array?

var characters:Array = ["leo", "raph", "don", "mike"];
characters.splice(1, 1);
trace(characters);
characters.push("splinter");
trace(characters);

If you're looking for storage by reference, checkout AS3's Dictionary object or even Flash 10's Vector (if storage is consistent by type; quite fast):

http://www.gskinner.com/blog/archives/2006/07/as3_dictionary.html

Typeoneerror
+1  A: 

The "optimized" version doesn't optimize much, I think.

YOur code does not perform 2 accesses in every iteration. It does just when you happen to find a dead Char; and after that you return. So, no big deal, I think.

Personally, I don't think reusing array slots is going to make a big difference either. And, maybe it could be degrade (but the worst part is that your code could be simpler if you avoid it). Suppose you have 100 chars, 60 of which are dead, and you have a loop that runs every frame and performs some check / action on every live char. You'd be looping over 100 chars, when you could loop over 40 if you mantained a list of live objects and a separte list of dead objects, ready to reuse them. Also, the "dead list" could be handled as a stack, so no iteration is needed to get a char.

Anyway, I see 2 things you could easily optimize in your code:

1) retrieve the list length outside the loop:

Do this:

var len:int = Char.charlist.length;
for (var i:Number = 0; i < len; i++) {

Instead of this:

for (var i:Number = 0; i < Char.charlist.length; i++) {

The compiler won't optimize away the call to length (following the ecmascript spec).

2) Avoid static access (for charlist). It's known to be considerably slower than instance access.

Edit:

Re-reading your question, I realize I misunderstood part of it. You're not trying to reuse Char objects, but rather array slots. Still, I don't think reusing array slots is worth it (arrays in Actionscript are non fixed); but something that could help performance is reusing the Char objects themselves. Reseting a Sprite is generally cheaper than creating a new one. You could manage this with a pool of "dead" objects, from which you can take one and "bring it back to life" when you need, instead of creating a new one.

This post talks about object pools (the blog itself is a good source for Actionscript stuff, especially for performance and data structures topics; worth taking a look):

http://lab.polygonal.de/2008/06/18/using-object-pools/

Juan Pablo Califano
Great documentation, when I come back to that project, I will check out this information.
Veehmot