Spherical forums

User-Made => Libraries => Topic started by: Metallix on April 14, 2013, 10:03:24 am

Title: [Script] Tweens
Post by: Metallix on April 14, 2013, 10:03:24 am
When you develop games you usually have a lot of animations like moving cursors, menu items, texts, images and more.
Tweening is a method that generates numeric in-between values of an animation from a origin value to a target value.
In the projects I made in the past I learned how convenient it can be to have a library that let you animate any numeric property of any object you provide. While working with ActionScript I used the TweenLite library from Greensock. They recently released a JavaScript solution of their tweening library but unfortunately it requires a global window object and the setTimeout function. Also it comes with a lot of overhead for browser support. So this was not really good for the usage in Sphere.

That's why I went to write my own plan JavaScript tween library. The usage is written in the file. But I will give you a small example how to use it:

Somewhere in your game loop you have to call this once every frame:
Code: (javascript) [Select]
tween.update( frameTime );


So a simple gameloop could look like this:
Code: (javascript) [Select]

RequireScript( "tween.js" );
while( true ) {
    tween.update( 1000 / 60 ); // Assuming we run with constant 60FPS. Use a calculated frame time in your final game!
    Delay( 1000 / 60 ); // Only supported in TurboSphere. In normal Sphere you have to implement an own Delay( ms ).
    FlipScreen();
}


With that game loop given lets prepare a tween and render something to the screen.
Code: (javascript) [Select]

RequireScript( "tween.js" );
var position = { x: 100, y: 200 };
// Tween position to 300,0 in 5 seconds using a smooth ease out:
tween.to( position, 5000, { x: 300, y: 0 }, { ease: tween.ease.quadOut } );

while( true ) {
    tween.update( 1000 / 60 ); // Assuming we run with constant 60FPS. Use a calculated frame time in your final game!
    Delay( 1000 / 60 ); // Only supported in TurboSphere. In normal Sphere you have to implement an own Delay( ms ).
    Rectangle( position.x, position.y, 50, 50, CreateColor( 255, 255, 255 ) ); // Render white 50x50 rectangle to position.
    FlipScreen();
}


et voila! ^^ You should see a moving white rectangle.
I also think of timelines, but will not do anything in this direction until I really need it. That would also require some refactoring in the tween.js I think. Sooner or later I will also put those scripts in one github repository. That will be easier with those RequireScripts you currently have to adjust based on your folder structure.

You can get the tween library here:
https://gist.github.com/Metallix/628de265d0a24e0c4acb (https://gist.github.com/Metallix/628de265d0a24e0c4acb)
It requires the linked list script I provided earlier here:
http://forums.spheredev.org/index.php/topic,30.0.html (http://forums.spheredev.org/index.php/topic,30.0.html)
https://gist.github.com/Metallix/5373204 (https://gist.github.com/Metallix/5373204)

The tween library:
Title: Re: [Script] Tweens
Post by: Radnen on April 14, 2013, 02:09:29 pm
Wow, that's certainly a useful library! I might check it out when I need to use it. :)
Title: Re: [Script] Tweens
Post by: alpha123 on April 14, 2013, 03:15:07 pm
Cool! I implemented a very ad-hoc version of something like this for my highly modified flik_menu.js; I think I'll replace that with this (which is much more powerful).
Title: Re: [Script] Tweens
Post by: Fat Cerberus on April 15, 2013, 12:37:00 am
Wow, this is nice, much more powerful than the version of this I did for Specs ("Fader"), which is exclusively linear.  I think I'll end up using this instead!
Title: Re: [Script] Tweens
Post by: Metallix on April 15, 2013, 03:22:25 am
Cool that you like it.

I hope it does not reveal too many bugs, when you use it ^^ So far it works fine in my small test game. But I wonder how it performs in other projects :)
Title: Re: [Script] Tweens
Post by: N E O on April 15, 2013, 04:02:05 pm
Two questions: 1. Is it possible to have a version of this that doesn't need the linked lists script? 2. For the easing functions, I know I've seen more standardized names somewhere than the ones you use (your names are very close but differ by like one or two letters per function); would you mind terribly changing the names at least to the versions used in jQuery and/or Prototype for consistency?
Title: Re: [Script] Tweens
Post by: Metallix on April 15, 2013, 04:39:10 pm
1: sure, by placing the linked list script into the same file. I really make use of the advantages of that class. But I would not upload it that way to gist. I made clear where to get that other script.
2: hmm, I see your point, but ... all of those standard names start with ease... that would lead to tween.ease.easeInOutSine for defining a ease method... that has this ugly double ease. I could go with tween.ease.inOutSine instead of tween.ease.sineInOut. I will maybe change that, when touching that script again.

Thanks for the input :)
Title: Re: [Script] Tweens
Post by: N E O on April 15, 2013, 08:19:50 pm
My bad, I forgot that jQuery prefixes all the easing function names with 'ease;' I meant consider them but without the prefix :).

Re linked list - I was more asking about whether the thing can be rewritten entirely to not require a custom linked list ADT and how long it would take to do so. If the functionality leans heavily on it, however, don't worry about it.
Title: Re: [Script] Tweens
Post by: Metallix on April 16, 2013, 03:23:02 am
I agree that the tween script would feel nicer without its dependency on the linked list. But the only alternative I can think of, would be putting a similar linked list implementation directly into the tween script. But hey, it is on gist. Open for everybody to fork and improve ^^
Title: Re: [Script] Tweens
Post by: Fat Cerberus on May 02, 2013, 02:10:18 pm
Just did a trial run with using tween.js in Spectacles, works wonderfully.  At some point I'll have to replace my linear-only Fader with this, it's going to be a pain as there's Fader references all over the place!
Title: Re: [Script] Tweens
Post by: Fat Cerberus on May 04, 2013, 12:03:18 pm
Found a bug: When using some easing methods, it never seems to reach the final value.  I noticed it when converting my menustrip class, doing an expoOut ease between 0.0 and 1.0 it got stuck at around 0.9998 and never budged after that.  This caused the menustrip to get stuck in the fading-in phase since I had it set not to change state until visibility >= 1.0.  Some of the easers work fine, others cause this bug.
Title: Re: [Script] Tweens
Post by: Metallix on May 05, 2013, 07:42:50 am
Hmm ok, I will take a look. I think I will just set the value to the target value after the timer reached the end... I thought I am doing this already o.O update coming soon.
Title: Re: [Script] Tweens
Post by: Metallix on May 05, 2013, 08:02:32 am
Updated. The gist is already displaying the updated version. Fancy :D

Before I was just setting the current time to the end time and calculating the result value based on the easing function what may cause rounding errors. Now I set the value directly to the value given in the property-hash.
Title: Re: [Script] Tweens
Post by: Fat Cerberus on May 05, 2013, 11:35:56 am
Thanks for the fix, I ended up reimplementing my own version of it in Spectacles though, since yours was a bit clunky to use alongside my custom threading library.  I guess it would have been easy enough to add a few lines to the file to make it play along, but I figured for such basic functionality it was better if the API was consistent with the rest of the Specs core.  I'll still be sure to give you credit anyway, since I'd be lying if I said I would have thought of this on my own! ;)

Mine is used like this:
Code: (javascript) [Select]
var tween = new Tween(obj, 2.0, 'easeOutQuad', {
    x: newX,
    y: newY
});


// in update method:
if (tween.isFinished()) {
    // change state...
}


I do have one question, though: How do you handle multiple active tweens on the same object? I don't have any checks in place right now, so if somebody tries to tween the same property in opposite directions simultaneously, this could result in a deadlock. I was curious how you handled that, since yours didn't deadlock when I played that trick on it.
Title: Re: [Script] Tweens
Post by: Metallix on May 05, 2013, 03:39:21 pm
Nice to hear, that this script inspired you to implement something similar in your engine. To be honest, I think 50% of the tween magic is done by the ease functions :)

Regarding your question:
I do not handle it. But the implementation should not allow any deadlocks. I am also creating internally Tween objects. If I create tweenA and tweenB for the same objects property the script is adding both to the list of active tweens. On update the script is first calculating tweenA and then tweenB, which always results in the objects property set to the value of the last tween added. It can result in some weird jumping of the value, if tweenA lasts longer than tweenB but I think that is okay for the simplicity of the script.
Also: to determine if a tween is finished, you should use the time and not the actual value of the tween.

hope I could help with this ^^
Title: Re: [Script] Tweens
Post by: Fat Cerberus on May 05, 2013, 05:18:45 pm
Yes, my isFinished() method is implemented to return true if elapsed >= duration.  When I was using yours though, it didn't have a method like that so I had to check against the actual value, which revealed the aforementioned bug.  You do have that onComplete option, but that's very unwieldy to use in a lot of situations, hence my redesign.

And yes, the easing functions are what's doing most of the work, haha.  I actually found more of those in the jQuery Easing Plugin project and incorporated them into my version: Bounce, Elastic and Back (that last one is neat--it purposely overshoots, then backs up).
Title: Re: [Script] Tweens
Post by: Fat Cerberus on May 16, 2013, 07:33:16 pm

I also think of timelines, but will not do anything in this direction until I really need it. That would also require some refactoring in the tween.js I think.


Just thought you might like to know Metallix, the latest versions of Scenario have a tween command built in. So if you needed to do timelines for animation, you can just use that. I'm already milking it for all it's worth in Spectacles. :)
Title: Re: [Script] Tweens
Post by: Metallix on May 17, 2013, 04:04:51 am
Very cool! A real project is actually the best way to test the tweens :) Milk it! ^^