Skip to main content

News

Topic: [Script] Tweens (Read 4504 times) previous topic - next topic

[Script] Tweens
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
It requires the linked list script I provided earlier here:
http://forums.spheredev.org/index.php/topic,30.0.html
https://gist.github.com/Metallix/5373204

The tween library:

  • Radnen
  • [*][*][*][*][*]
  • Senior Staff
  • Wise Warrior
Re: [Script] Tweens
Reply #1
Wow, that's certainly a useful library! I might check it out when I need to use it. :)
If you use code to help you code you can use less code to code. Also, I have approximate knowledge of many things.

Sphere-sfml here
Sphere Studio editor here

Re: [Script] Tweens
Reply #2
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).

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: [Script] Tweens
Reply #3
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!
  • Last Edit: April 15, 2013, 01:32:02 am by Lord English
miniSphere 5.0b2 (stable: 4.8.8) - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enormous man-eating pigs ~Rhuan

Re: [Script] Tweens
Reply #4
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 :)

  • N E O
  • [*][*][*][*][*]
  • Administrator
  • Senior Administrator
Re: [Script] Tweens
Reply #5
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?

Re: [Script] Tweens
Reply #6
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 :)

  • N E O
  • [*][*][*][*][*]
  • Administrator
  • Senior Administrator
Re: [Script] Tweens
Reply #7
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.

Re: [Script] Tweens
Reply #8
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 ^^

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: [Script] Tweens
Reply #9
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!
miniSphere 5.0b2 (stable: 4.8.8) - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enormous man-eating pigs ~Rhuan

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: [Script] Tweens
Reply #10
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.
miniSphere 5.0b2 (stable: 4.8.8) - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enormous man-eating pigs ~Rhuan

Re: [Script] Tweens
Reply #11
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.

Re: [Script] Tweens
Reply #12
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.

  • Fat Cerberus
  • [*][*][*][*][*]
  • Global Moderator
  • miniSphere Developer
Re: [Script] Tweens
Reply #13
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.
  • Last Edit: May 05, 2013, 11:51:32 am by Lord English
miniSphere 5.0b2 (stable: 4.8.8) - Cell compiler - SSj debugger - thread | on GitHub
For the sake of our continued health I very much hope that Fat Cerberus does not become skilled enough at whatever arcane art it would require to cause computers to spawn enormous man-eating pigs ~Rhuan

Re: [Script] Tweens
Reply #14
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 ^^