AS3 TweenMax-imumLove

So I’ve been working pretty hard on what started as a TowerDefense game for a tutorial here.  It has since become more complex, less tutorialtastic, and awesome.  … sort of.  I’m happy with where it’s going. Now that I’ve stroked my ego, let me stroke a few more.

First off I have to say one of the single-most priceless pieces of code ever is TweenMax.  I know I seem to mention them in every blogpost these days.  When I buy programming books, or browse thru Adobe AS3 Live-Docs , I’m reading to solve a problem.  My brains don’t encyclopedia-ize all of the things I come across.  I don’t need to keep them in my memory, that’s why they’re written elsewhere… in APIs and documentation and stuff that I don’t care about.  …Until I need something.

So I go grab TweenMax, TweenLite, TweenGroup, TweenAnythingThatsFreeAndMightBeUseful… read up on how to fix my specific issue at-hand, browse thru the rest of the functions not really paying attention, then go fix whatever it is.

All of my enemies have waypoints set and I’ve got all of my enemies going to each waypoint using their own TweenMax call.  All of my defenses have their projectiles being shot, flown, rolled, or walked around with Their own TweenMax call.  And still maintaining a pretty steady 45fps.  Granted my enemy animations are laughable if they exist. So it occurs to me that I need a way to pause the game.

Now, the first iteration of this code did not use TweenMax/Lite.  Everything ran off their own ENTER_FRAME call and it was so cool up until the point that I realized nothing was exactly “sync’ed.”  An enemy speed might have been 200 while a projectile speed might have been 4?  Who knows… I didn’t.. it was a mess.  So I needed to find a way to have a common speed. Then it occurs to me as I’m testing a build that I need to pause it as I’m in the game watching variables trace by like those stars you try to count on the Paramount Pictures logo at the beginning of movies ( there are 22 now ) and I dont want to miss anything.  I have no way to pause all that stuff in game yet.

I’m always reading and re-reading through 8bitrocket’s blogs and tutorials as they’re so jam-packed with deliciousness in optimized game loops and bitmap data techniques.  I stayed hard away from BitmapData/Bitmap stuff for the longest time.  MovieClips make sense.  It’s a big container that i can put my little image in and move it around on my medium stage.  The best non-code comparison I can make with me and BitmapData/Bitmaps is learning to play guitar and using barre chords. I picked up guitar maybe 7-8 years ago and for the first year or so, if I looked up song tabs for a song I really wanted to learn and it contained anything where my finger needed to go across all the frets… yeah I’m sure there are other songs I can learn.

But you buckle down and say, “Ya know what ya lazy bastard, quit being a wus about it, you know it’ll help you actually do what you need to do, so shut up and do it.”  So yeah this whole rabbit I’m chasing is to say that 8Bit wins and their tutorials finally bludgeoned it in my head what bitmaps are all about. Their optimized game loop is tight.  Check it out.

So…. pausing things that are flying around on my stage like damn gnats.

I came across TweenGroup.  A group of tweens?  Why?  Isn’t one tween per object all I really need?

Oh baby.  TweenGroup solves my pause/resume issue in just a few lines of code.

TweenMax Example – Projectile Firing at Enemy

This first line is easy.  An enemy is in range.  I’ve calculated the distance to the enemy while I was assessing which enemy was closest to shoot at.  I created the projectile that the tower is going to “shoot”, then here, I’m creating the Tween to send the projectile happily on it’s way.

proj.tween = new TweenMax( proj , calculatedTweenSpd , { x:targX , y:targY , onComplete:removeProj , onCompleteParams: proj });
proj.tweenIndex = parentMC.addTweenToGroup( proj );

I assign it to the projectile.tween property because I want the projectile to hold onto it’s own Tween.  So, to step thru the code… I’m creating a new TweenMax.

What am I tweening?  “proj”

How long do I want it to take?  “calculatedTweenSpd” which I derived from essentially the projectile speed value for whatever tower type is firing.

What is TweenMax doing?  Taking the projectile from where its at on the Stage ( the x & y of the tower shooting the projectile ) and sending it to “x:targX , y:targY” the x and y coords of the enemy.  This particular projectile is sortof “heat-seeking” at the moment.  For this projectile “targX” = enemy.x and as the enemy moves, this projectile will rotate and find that x y coord.  Other projectiles I grab enemy.x and y when I create the projectile and targX and Y are those “last known coords” of the enemy.

What happens after?  onComplete: … when the tween completes and my “proj” is snug inside some enemy’s.x/.y TweenMax kindly calls the “removeProj” function for me and, onCompleteParams: … passes the “proj” in to the removeProj function for cleaning and disposal.

I don’t have to do another thing to this Tween.  It cleans out of memory in a ridiculous amount of a few seconds and it’s done.

TweenGroup Example & Two Functions I’ve Added

Now that we’ve seen what that first line of code does, let’s look at one of the two functions I added.  The previous code was coming from the Defense Class, which, in the whole heirarchy of my class structure, is a couple parents away from where I’m keeping my TweenGroup ( in the GameManager Class which is the central “hub” of the in-game code ).

Image TweenGroup is just an array.  In all honesty there’ve been enough coder-friendly functions added in just the same way as AS3’s Array Class that you can use all the same calls for the most part.

[sourcecode lang=”php]

//Declared in the class variable portion of the code
private var gameObjectsTG:TweenGroup;

// Then initialized later
gameObjectsTG = new TweenGroup();

[/sourcecode]

Neat.  Now the functions that help me get things into TweenGroup.  Note, these functions were added because of the way I set up my code, not because Code-Wizard Iam Main at GreenSock neglected to add anything.

The first function shows how exactly like an array TweenGroup is. The obj(ect ) is going to be either a projectile, an enemy, or something else that I haven’t added yet. To make sure in the passing params in that I didn’t accidently pass something stupid, I made an interface called “ITweenable” that just contains 2 getters and 2 setters for .tween and .tweenIndex; These are two things I want to keep track of on the actual object, and if the object, say, an enemy moving thru it’s different waypoints… if the enemy hangs on to a copy of it’s own “index” inside the TweenGroup, then in my second function, I can most efficiently jump straight to it’s old tween which as completed, and just insert it’s new tween.

This keeps my TweenGroup from just adding and adding Tweens. Granted everything worked beautifully before I added the update function, I just wanted to make double sure that I was being most efficient. Most likely there is a function… actually I just re-looked through the functions and “setDestination” would’ve/will be interesting when I add some other things.

So in my code I create a whole new TweenMax with x/y coords to the next waypoint when really I could’ve just handled this inside the enemy class doing something like: enemy.tween.setDestination( newX , newY ); Anyways, read on those brave few who read my rambledrumbles!

[sourcecode lang=”php]

public function addTweenToGroup( obj:ITweenable ):int  {
gameObjectsTG.push( obj.tween );
return gameObjectsTG.length – 1;
}

public function updateTweenInGroup( obj:ITweenable ):void      {  gameObjectsTG[ obj.tweenIndex ] = obj.tween  }

[/sourcecode]

So I add every TweenMax I create into the TweenGroup. I keep every tween updated to the current Tween being used by every object. And now to pause Everything That’s Moving On My Stage!

gameObjectsTG.pause();

I’m not even going to explain it. I’m done.

oh, and when I want to resume… holycrap you guessed it!

gameObjectsTG.resume();

F’ing Genius!

FacebookTwitterGoogle+Share

Leave a Comment

Your email address will not be published.