views:

161

answers:

2

I have the following code:

if (i==0)
  sprites[i].y = 0;
else
  sprites[i].y = sprites[i-1].y + sprites[i-1].height;

Every Sprite can have a different height. Height of a Sprite can change on user action.

When the height of some Sprite changes, I would like to update the position of other sprites accordingly.

I am looking for an object oriented (maybe event driven) solution. Any ideas?

Thanks

+2  A: 

there is no way of fully tracking changes to x, y, width, height properties of DisplayObjects ... you could override accessors, but still, that won't quite work ... for example, an object may become bigger, because a child is added, something is drawn, some loading operation finishes etc. ...

if the ammount of sprites is reasonably low (<200), you can easily just do the check on enterframe, without any measurable performance loss ... no, this is not a very nice approach, but it's really the most efficient and safest thing to do ...

good luck then ... ;)

back2dos
warpech
+1  A: 

If you have good control over when the height of any given sprite is going to change then you can use a custom event. The setup would look something like this:

var UPDATED_EVENT:String = "updated";
var i:int = 0;
var count:int = sprites.length; // this is the length of your array

for (i = 0; i < count; i++) {
  sprites[i].addEventListener(UPDATED_EVENT, calc);
}

function calc(e:Event = null):void {
// here goes your positioning code
  for (i = 0; i < count; i++) {
    if (i==0)
      sprites[i].y = 0;
    else
      sprites[i].y = sprites[i-1].y + sprites[i-1].height;
  }
}

calc();

Then just make sure that whenever you change the height of one of your sprites you do something like this:

mySprite.dispatchEvent(new Event(UPDATED_EVENT));

If you're spread across multiple classes (and you probably should be) then you can make the UPDATED_EVENT string a const in a separate event class and access it from both.

That's still not a perfect solution for you - if you want, you can figure out which sprite is changing its height and only recalc the sprites that come after it, and that'll make your code more efficient - but it beats calling an enterframe event every time.

Now, if you were using Flex you'd have even more tools at your disposal - you could probably use databinding to automate almost all of this, or at least use the changed event to automatically dispatch events for you, but that's neither here nor there!

Myk
1. try `function calc(e:Event = null) { var y:Number = 0; for each (var s:Sprite in sprites) y = (s.y = y) + s.height; }` . it's faster (no array access) and more concise. 2. this in not always more efficient. if your sprites change a lot (multiple times per frame), then you will call `calc` more often than needed and instantiate more events than needed. plus this is very unflexible, since any code accessing those sprites needs to care about the updates. this is quite contrary to OO concepts.
back2dos
Cool feedback, and good call about using the for each loop rather than array access. As far as OO principles go, you're right - the way I have this laid out you're going to have some tight coupling going on. You should be able to refactor it into a slightly more abstract arrangement, but without a CHANGED event like Flex offers you're still stuck manually dispatching UPDATED_EVENT every time something changes.
Myk
great answer! too bad I've already done it with ENTER_FRAME
warpech