Jump to content
Search Community

TimelineLite SNAFU

Axonn test
Moderator Tag

Recommended Posts

Hello everybody ::- ). I got myself into a very weird situation with Timeline Lite and I'm hoping maybe somebody can clear me up about how to manage its Play Head.

 

For my game, I created an Announcer component which shows various messages on the screen, in big red letters. To do this, I used a TimelineLite in which I got 4 TweenMax instances. One of them uses a YoYo (for the flashing the Text).

 

This is how I create the TimelineLite, in the Class Constructor (because I want to reuse it every-time I want to announce something):

 

     _AnnouncerTimeline = new TimelineLite();
     _AnnouncerTimeline.append(TweenMax.to(_AnnouncerHost, 0.5, { scaleX: 1, scaleY: 1, glowFilter: { color: 0xFF00D5, blurX: 40, blurY: 15, strength: 3 } } ) );
     _AnnouncerTimeline.append(TweenMax.to(_AnnouncerHost, 0.1, { glowFilter: { color: 0xFF00D5, blurX: 5, blurY: 5, strength: 2 } } ) );
     _AnnouncerTimeline.append(TweenMax.to(_AnnouncerHost, 0.1, { repeat: 20, yoyo: true, glowFilter: { color: 0xFF00D5, blurX: 40, blurY: 15, strength: 3 } } ) );
     _AnnouncerTimeline.append(TweenMax.to(_AnnouncerHost, 0.5, { scaleX: 0.01, scaleY: 0.01, onComplete: function(): void { _AnnouncerHost.visible = false; } } ), 2 );
     _AnnouncerTimeline.paused = true; //If I don't do this, when starting the TimeLine, it will always start from step 2, completely ignoring the GROW part.

 

I use this to 1. Grow 2. Blink-Glow 20 TIMES, 3. Shrink an announcer text on the screen.

 

I trigger the Announcement via this Function:

 

   private function Announce (text: String): void
   {
     _AnnouncerText.text = text; //This is contained within the AnnouncerHost Sprite and the basic properties are initialized elsewhere.
     _AnnouncerHost.visible = true;
     _AnnouncerHost.scaleX = _AnnouncerHost.scaleY = 0.01; //Reset Scale.
     _AnnouncerHost.filters = _AnnouncerGlow; //Refresh glow.
     //_AnnouncerTimeline.restart(true); //Tried to use it, but doesn't help. Obviously, should do the same thing as the line below, which also doesn't help.
     _AnnouncerTimeline.gotoAndPlay(0); //When I do this, if I hadn't PAUSED the TimeLine at the beginning, the Announcer will NOT grow.
   }

 

Usually it works OK. But during my game, sometimes I invoke TweenMax.pauseAll() and TweenMax.resumeAll() (when the game is Paused). And what happens when I do that, is that the Announcer Timeline goes crazy. Instead of the text appearing and flashing, it appears and just stays there for about 2 seconds, AND ONLY THEN it starts to Flash, and after that, it disappears. So the duration of the Timeline actually increases. It is interesting that it stays for 2 seconds, because that's exactly the time it should YoYo. Or, it appears seconds later.

 

The other weird thing is that if I didn't PAUSE the Timeline at the beginning, no matter how hard I would want to restart it, it will still start directly from step 2 (fully grown). This is even though in the Announcer Function I'm settings its scale to 0.01!

 

I'm definitely not using something the way I should. I think the Timeline doesn't restart the Tweens by itself, and somehow I'm mixing it up with resumeAll() as well.

 

LATER EDIT:

 

Ok and now I also noticed that if I let the Timeline PLAY FOR AT LEAST ONCE before starting to pause the game, IT WILL ALWAYS WORK OK AFTER THAT. *sigh*

Link to comment
Share on other sites

When a tween runs for the first time (its first render at a non-zero time), it initializes and captures/stores the starting and ending values. In a to() tween, you define the end values and the engine figures out the from (starting) values itself (again, this happens the first time it renders). This explains why you saw the scaleX/scaleY difference when you paused the TimelineLite vs. when you just let it run. I bet your _AnnouncerHost's scaleX/scaleY were initially 1 (normal) so when the tween rendered the first time, it said "okay, the starting values are....1 and 1. Record those. And we're tweening to....1 and 1". When you scale from 1 to 1, you ain't gonna see any difference :)

 

When you paused the TimelineLite initially, it wouldn't let the child tween(s) run, so the beginning values weren't recorded yet. Then, later, right before you restart() or gotoAndPlay(0), you set the scaleX and scaleY to 0.01, so when the tween did initialize, THAT value was recorded. Tweening from 0.01 to 1 is certainly apparent. So the issue you were running into simply had to do with when you were initializing your tweens and what the starting values were at that time. Kinda makes sense when you think about it, right? It probably looked like funky voodoo magic before, though, when you didn't understand the logic behind when tweens record their starting values, etc.

 

As for the pauseAll() and resumeAll(), I'd need to see a sample FLA to look at what you were doing, but those are legacy functions that were primarily for apps that used straight tweens to do everything rather than organizing them in TimelineLite or TimelineMax instances. Have you tried setting TweenMax.globalTimeScale to 0 to get the "pause" effect and then back to 1 to resume? I suspect that might work better for you. Or just organize your tweens into a root TimelineLite instance that you can pause() and resume() whenever you want.

 

Hope that helps.

Link to comment
Share on other sites

Hey! Thanks for answering ::- D.

 

After I corrected the error you pointed me, indeed, the behavior is much more predictable. I do see it as an error. It's obvious that tweening occurs between two values. When you explained it that well, I immediately realized why the .paused = true behaves the way it does: it's because it pauses the Tween and it doesn't get to render until I set the scaleX and scaleY to 0.01. And because of that, I first play the Timeline and it does get to render, it will start from 0.01. Should have seen it.

 

As for pauseAll and resumeAll, it's a bit more complicated. I'm not using Flash. I work in Flash Builder 4.5 and I'm developing two separate products: a UI library and a game (which uses the UI library). My game has a Pause function, as I said, and when it gets paused, it's very handy to pauseAll. Many objects have animations integrated in them rather than keeping everything in the Engine. You could say that keeping everything in one place is good, but not when you're dealing with a 45.000 lines of code game. I need to separate animations PER OBJECT because of concern separation. So then I got about 20 classes in which various animation occurs. It's very handy to pauseAll.

 

And I will give you an other reason why globalTimeScale won't work for me. You see, when I pause the Game, I need all the objects in the Game paused, but *NOT* the subsequent animation calls. Because when I pause the game, the UI Library menu comes into play, and that guy also uses TweenLite/Max. So if I use globalTimeScale I will effectively freeze everything which I *don't* want. pauseAll is actually ideal because (fortunately for me) it pauses all CURRENT Tweens, but not future ones. So you see, your "legacy" function is quite useful. Or maybe I'm using your library in a wrong way... (???)

 

I found the problem I had with pauseAll / resumeAll. You see, when I invoke the Menu, I do pauseAll. But if I click "Give up" in the Menu, then, it goes to another module and will *NOT* do resumeAll. When I return to the "animated" area and I try to Announce something, I restart the TimelineLite in the Announce() function. But all the TweenMax instances in the TimelineLite are still paused, because I didn't resume them. So, I also needed to do this in the Announce():

 

for each (var tw: TweenMax in _AnnouncerTimeline.getChildren()) tw.resume();

 

I suppose that if I would rebuild the entire game, I could create a sort of "Tween Register" where I have Dictionaries for Game-Related Tweens and for UI-Related Tweens. What do you think? Sounds like a reasonable solution?

 

Maybe I'll do that in my next game.

 

Damn, you know this library so well......... it's .......... it's ....... well... believe it or not... it's almost like YOU WROTE IT!

 

*grin*.

Link to comment
Share on other sites

Damn, unfortunately, my attempt for a workaround didn't turn out so well. When doing that "resume", apparently the Timeline gets "dirty", and the "totalDuration" getter is called internally in your library. And it crashes ::- (

 

TypeError: Error #1009: Cannot access a property or method of a null object reference.

at com.greensock::TimelineLite/get totalDuration()[TM_PATH\com\greensock\TimelineLite.as:926]

at com.greensock::TimelineLite/renderTime()[TM_PATH\com\greensock\TimelineLite.as:530]

at com.greensock.core::TweenCore/setTotalTime()[TM_PATH\com\greensock\core\TweenCore.as:270]

at com.greensock.core::TweenCore/restart()[TM_PATH\com\greensock\core\TweenCore.as:126]

at Gamaddiction.Games.AlienInvasion.Engine::LMRcade/Announce()[GAME_PATH\Engine\LMRcade.as:446]

 

I updated two weeks ago. The error is at "prevStart = tween.prevNode.cachedStartTime;".

 

prevNode is NULL.

 

I'm stuck again ::- (. Without that resume, I'm dead. My Timeline gets corrupted when I do resumeAll (I think! I'm not sure). What happens is that after I call resumeAll (when I close the game's menu), most of time (not always though), my Announcer text appears with a delay of ~1 second. And it *CONTINUES* to appear with that delay EACH time I call the Announcer EVEN IF I didn't pause the game any more! So it's like resumeAll somehow *permanently* nudges my Timeline Lite about 1 second and all subsequent calls occur with that delay.

 

Any idea how I could workaround this? Is it possible to somehow make resumeAll ignore my 4 tweens which are already handled by the TimelineLite instance?

 

I tried doing that " for each (var tw: TweenMax in _AnnouncerTimeline.getChildren()) tw.resume(); " inside the function which also does the resumeAll instead of the Announce() function. I get the same Error but without a stack trace inside my game (it's only the first 4 lines, TimelineLite.as only), so it crashes while the internal rendering occurs in the library.

 

I tried handling the error but to no avail: once it occurs, my TimelineLite crashes and I get no more Announcer Text *sigh*.

Link to comment
Share on other sites

Don't worry, I'm sure we can get this working for you, but I need you to create a separate FLA that has only the [minimal] necessary code to reproduce the problem. Either post here or shoot me a PM.

 

I'm kinda baffled by the crash you're talking about because in order for that piece of code to run, the tween's startTime would have to be less than negative Infinity (I can't imagine that). But I'm sure I'll be able to track things down once I have the simplified example FLA that you whip together.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...