Tween onComplete with parameters?


(Firoz Jokhi) #1

Hi,

Is there a way to pass parameters to the onComplete function of a tween? I am not sure if this is not possible or if I am missing a simple trick here.

I am working on a tile game. When matched, tiles animate and move into your inventory using a multivartween. Now when the tween finishes, I want to add that tile to the inventory. So somehow, I need to pass the tile (or tile type) into the onComplete function of the multivartween.

I would really appreciate some help on this.

Thank you!


(Zachary Lewis) #2

If the tween is a member of Tile (or whatever your tiles are called), you should just be able to use this.

Here’s some psuedo code for Tile to explain what I mean.

function update
{
  if (matched) then
    tween.callback = tweenComplete
    start tween
  end if
}

function tweenComplete
{
  world.inventory.addTile(this)
}

(Firoz Jokhi) #3

Thanks for the reply @zachwlewis, but my tween is in the World. It’s not on the Tile.

So in my World, I have a

for each tile in world.tiles
      if (tile.matched) then
       var mytween:MultiVarTween = new MultiVarTween(tweenComplete)
       mytween.tween(tile, {}, easein)
        start tween
      end if
end for each

and another function

function tweenComplete
{
  world.inventory.addTile(this)
}

And in this case, obviously the this refers to the world, not the tile. Am I doing this wrong?


(Jacob Albano) #4

You can use a local function/closure for this;

for each (var tile in world.tiles)
{
    if (tile.matched)
    {
        function complete() { world.inventory.addTile(tile); }

        var mytween:MultiVarTween = new MultiVarTween(complete);
        mytween.tween(tile, {}, easein);
        addTween(myTween, true);
    }
}

The function exists in a scope where tile is a reference to the tile that’s being tweened, so it keeps that reference as long as the function instance exists.


(Firoz Jokhi) #5

Wonderful! Didn’t know I could have such a local function defined. Thanks so much @jacobalbano

Just out of curiosity though, which practice is considered better? Letting the world manage the tweening of the tiles or having the Tile manage it’s own tween?


(Jacob Albano) #6

Yeah, local functions are a really nice feature in languages that support them, like as3 and C#.

I personally let entities manage their tweens whenever I can; if I remove an entity from the world, I’d rather not have a bunch of unused tweens potentially clogging things up.


(Firoz Jokhi) #7

The more I think about it, the more I think that is the right approach.

I was going along the lines of letting the world be the orchestrator of the tiles and how things move and such. But now it feels like the Tile should take care of its own animation.


(Ultima2876) #8

The whole OOP paradigm is based on the idea that objects (or entities in this case) take care of their own responsibilities. It’s a good idea to follow that as much as possible! :slight_smile:

Another good reason for allowing entities to handle their own tweens is that it helps to keep things organised and easily understandable for someone else viewing your code (it’s logical that a Tile entity handles it own movement rather than being moved by the world).


(Jacob Albano) #9

Another weird trick that I’ve found to come in handy at times is exploiting how as3 resolves this when executing a function object.

function end():void
{
    //  get the class type of this
    trace(Object(this).constructor);
}

var alarm:Alarm = new Alarm(1, end);

You’d expect that this would refer to the current object; for example, running this code should trace “[class Player]”. Unfortunately that’s not the case; this always refers to the object that calls the function. In this case, the callback is being called by the Alarm, so it will trace “[class Alarm]”.

This can actually be helpful at times, such as if you pass a function to a GUI control, like so:

function click():void
{
    var self:Button = this as Button;
    //  from now on, self refers to the button that's being clicked
    //  this code will also compile with no problems
    //  while it wouldn't without the proxy object and cast
}

button.onClick = click;

In most cases, however, this behavior is just a pain and causes crashes that can’t be caught at compile-time. There’s a solution to that as well, though:


var self:Player = this;
function end():void
{
    trace(Object(self).constructor);
}

var alarm:Alarm = new Alarm(1, end);

Since self is captured by the function, it will always refer to the this object at the time of the function’s creation; in this case, the Player class instance. This code will trace out “[class Player]”, just as expected.

Edit: Should I maybe turn this into a tutorial? I remember having all kinds of trouble with this kind of thing when I was first starting out.


(Ultima2876) #10

Yes! This is very interesting stuff whether you use this a lot or not. Do it! :slight_smile:


(Zachary Lewis) #11

This would be a great Actionscript tutorial, but it’s not a FlashPunk tutorial. If you had a blog, I’d recommend writing this up!


(Jacob Albano) #12

Good call. I’ll put it into a post and leave the link in this thread.


(Abel Toy) #13

Yes, please. Didn’t even know about this particular thing! And I’ve been coding in AS3 for years…


(Jacob Albano) #14

Here we go!

Feel free to spread it around. :smiley: