Universal Tween Engine

Introduction

The Universal Tween Engine enables the interpolation of every attributes from any object in any Java project (being Swing, SWT, OpenGL or even console-based). A tween is a static animation running for a fixed amount of time. Therefore, tweens are perfect candidates to animate your UIs, splash screens, and all the static animations of your characters. A tween can animate anything: position, rotation, opacity, color, scale, etc. The only limitation of the tween engine is your imagination.

Demos

Features

  • Zero allocation! Use your project safely on Android without fearing the garbage collector!
  • Supports every interpolation function defined by Robert Penner: http://www.robertpenner.com/easing/
  • Can be used with any object. You just have to implement the TweenAccessor interface when you want interpolation capacities.
  • Every attributes can be interpolated. The only requirement is that what you want to interpolate can be represented as a float number.
  • One line is sufficient to create and start a simple interpolation.
  • Tweens can be easily sequenced thanks to Timelines.
  • Tweens can act on more than one value at a time, so a single tween can change the whole position (X and Y) of a sprite for instance !
  • Tweens and Timelines can be repeated, with a yoyo style option.
  • Many callbacks can be specified (when tweens or timelines complete, start, end, etc.).
  • Simple timers can be built with Tween.call().
  • Source code extensively documented!
  • Wiki documentation to get you started!

The engine is mainly divided into Tweens and Timelines.

Tweens

Tweens are small one-line statements that let you start the animation of one or multiple attributes of an object. Better than a thousand lines of text, take a look at the following demo applet (link on the right). Don’t hesitate to change the easing function, and to add repetitions to your animation.

In this demonstration, we only use tween to animate the position of an object. However, when using the Tween Engine, you describe what you want to animate, so everything is possible. To start a tween, only thing needed is:

// Animation of an object position to the coordinates (100,200), in one second
Tween.to(myobject, Type.POSITION, 1.0f).target(100, 200).start(myManager);

Many options are available to customize the animation:

Tween.to(myobject, Type.POSITION, 1.0f)
    .targetRelative(10, -20)  // the target can be relative to the current values
    .delay(2.5f)              // a delay can be specified
    .ease(Quad.OUT)           // the easing function can be modified
    .repeat(2, 0.5f)          // repetitions are possible
    .repeatYoyo(2, 0.5f)      // yoyo repetitions too (one play forward, the other backward, etc)
    .setUserData(obj)         // custom objects can be attached
    .setCallback(cb)          // callbacks can be specified to get notified of the completion
    .setCallbackTriggers(...) // callbacks can be launched on many events, not just completion
    .start(myManager);

A tween is based on precise timings, as follows:

A tween under normal playing. It may start with a delay, and can be repeated any number of times (with an optional delay between repetitions).

Callbacks are very important, and let you trigger actions on precise events. There are callbacks for forward playing, and for backward playing:

You can get notified of many events, both during forward play and backward play!

Timelines

Timelines let you create powerful sequences of multiple tweens. They will be automatically delayed to be executed one after the other. See the following demo applet on the right.

Creating sequences is easy, just stack .push() calls! You can also nest timelines into other timelines.

Timeline.createSequence()
    .push(Tween.set(...)) // First, set all objects to their initial positions
    .push(Tween.set(...))
    .push(Tween.set(...))
    .pushPause(1000)      // Wait 1 second
    .push(Tween.to(...))  // Move the objects around, one after the other
    .push(Tween.to(...))
    .push(Tween.to(...))
    .beginParallel()      // Move them all at the same time now
        .push(Tween.to(...))
        .push(Tween.to(...))
        .push(Tween.to(...))
    .end()
    .repeatYoyo(2, 500)   // repeat the whole sequence 2 times
    .start(myManager);    // and finally start it!

The options of timelines are the same as the ones for tweens, including repetitions and callbacks! What was possible for tweens is also possible for timelines.

Download binaries and source code

The project is fully open-source, and currently hosted at Google Code using a Mercurial repository. Each time a revision is considered stable, it is released as a binary package.

Project page: http://code.google.com/p/java-universal-tween-engine/
Download page: http://code.google.com/p/java-universal-tween-engine/downloads/list

Get started

A detailed example is provided in the project wiki:
http://code.google.com/p/java-universal-tween-engine/wiki/GetStarted

Also, you may want to take a look at the source code of the demo:
http://code.google.com/p/java-universal-tween-engine/source/browse/#hg%2Ftween-engine-tests%2Fsrc%2Faurelienribon%2Ftweenengine%2Ftests

Javadoc

Sources for the library are shared within the zip file. Linking to them in your favorite IDE (eclipse, netbeans, idea) will let you access the javadocs directly from the editor itself.

Support

If you spotted a bug, or have a great improvement idea, feel free to submit it to the Issue Tracker.

For any other information, there is a dedicated forum for you.

31 Comments + Add Comment

  • [...] in order to present the library to new users, I wrote a new page dedicated to it (also available by clicking on its banner on the front page of this blog). The page features two [...]

  • Hi,

    Version 6.2.0:
    – No more .size() on TweenManager?

    Cheers

    • Hello. I removed it since its behavior was not coherent with its definition, but I’m planning to reintroduce it in a different way.

  • Hi,

    I am trying to build an app and facing issues with the delay and Timeline. Are there any constraints on the delay time values?
    Anyways, I cant get the timeline working. Any suggestions?

    Thanks

    • Well, I can’t really help you with your description of the issue :p
      One of the most common fix: are you sure all your timings use consistent time unit? I mean if the duration of a tween is expressed in milliseconds, then the duration of the delays and all other timings have to be expressed in milliseconds.

      I’ll try to setup a forum so you can explain your issue furthermore. Before that, send me a mail ;)

  • can you please make the android demo application’s code be available – it will help me to understand the implementations and get me started to zoom in and zoom out the layouts. thanks

  • Hey there,
    i am making a subtitling system in java.. i want my subtitles to have tweens like to make it bounce and stuff which i can later import..
    is it possible to get tweens on ur text using this engine??

    thanks!!

    • You can use the engine on everything, everywhere, that’s the spirit :)
      If you need help, make a post in the forum with code exctracts of what you’re trying to do.

      • Hey there.. quick question.. after adding tweens to the text i want to save the file as a subtitle file(.srt).. would the tweens be still there..??
        as far as i found.. (.srt) wouldn support animation..
        on the other hand .ass(advanced sub station aplha ) is used for more advanced metadata would that help?

        Thanks

  • [...] Universal Tween Engine integration with some Tweeners built in. [...]

  • I have problems getting the JavaDoc to work on an Android project. I tried to add the sources.jar to the Java Build Path, but I had no luck.

    Can you guide me please?

  • [...] silnika gry użyto Uniwersal Tween Engine, który odpowiada za animowanie elementów dekoracyjnych oraz animację samego robaczka. Biblioteka [...]

  • [...] silnika gry użyto Uniwersal Tween Engine, który odpowiada za animowanie elementów dekoracyjnych oraz animację samego robaczka. Biblioteka [...]

  • [...] la police de caractère avec Font Forge les sons avec Audacity, l’animation avec Universal Tween Engine et le moteur global du jeu avec Libgdx Le tout sous [...]

  • Hello, I think your web site might be having browser
    compatibility issues. Whenever I take a look at your site in Safari,
    it looks fine however when opening in Internet
    Explorer, it has some overlapping issues. I simply
    wanted to provide you with a quick heads up! Other than that, wonderful website!

  • Hello,

    How can I resize an object with animation?

    Cheers

  • Thank you for creating such a great tool~

    When playing around with Timeline,
    I wonder is there a way to replay established timeline?

    • Hello,
      First of all, thank to aurelien for this great job.
      I encountered the same problem I try to replay a timeline but nothing append. it seems to me that the philosophy of this framework is to create tween or timeline on the fly to be use only once, so reuse of already created animations is apparently not expected.
      After reading the source I found a workaround to restart a timeline once completed:
      In BaseTween.java in method start you can add these two lines:

      step=-2; //to pass isValid(step) conditions
      isFinished=false; //to avoid removing object on first update iteration if autoRemove is true see TweenManager.setAutoRemove

      After this patch, you can reuse an existing timeline simply with:
      mTimeline.start(mTweenManager);

      To reuse animation, I think that it’s better to set TweenManager.setAutoRemove(mTimeline,false);

      Mabye this patch can have some side effects, the best would be a feedback of aurélien.
      Best regards

      Valérian

  • Hello,

    the TweenEngine is really great, I’m just learning how to use it. I have one question though: I want to make an object “fly in” from below. That does not seem to work, I suppose because the initial position of the object is a negative number. Is there any possbility to do that?

    I’d be happy to get an answer but want to thank you anyway for creating this great piece of software.

  • Thanks , I have recently been looking for info approximately this subject for ages and yours is the greatest I’ve discovered so far. But, what in regards to the bottom line? Are you sure concerning the supply?

  • Thank you for ones good writeup. It actually was a amusement account it. Glimpse advanced to far added agreeable from you! However, how can we communicate?

  • Fixed the date. Thanks.

  • The link to your forum is broke so I’ll ask here. Hopefully you can help

    I have two different things happening when I try to scale an image.

    First I set the initial scale to 0.25f, 0.25f

    When I try to tween it to the actual size of the image nothing is shown until it reaches the actual size.

    Then I tried scaling to twice it’s actual size, and I see it tween from it’s actual size tow twice it’s size, but instead of growing in both the XY directions at once, it first tweens the Y position then the X position.

    Here’s a test screen that eliminates everything except the tweening.

    Can anyone tell me what I’m missing.

    By the way I can move and fade the image with no problems, it’s just the scaling that doesn’t do what I expect.

    package info.garycaine.tilepuzzle.TweenAccessors;

    import com.badlogic.gdx.scenes.scene2d.ui.Image;

    import aurelienribon.tweenengine.TweenAccessor;

    public class ImageAccessor implements TweenAccessor {

    public static final int ALPHA = 1;
    public static final int SCALE = 2;
    public static final int POSITION_XY = 3;

    @Override
    public int getValues(Image target, int tweenType, float[] returnValues) {
    switch (tweenType) {
    case ALPHA:
    returnValues[0] = target.getColor().a;
    return 1;
    case SCALE:
    returnValues[0] = target.getScaleX();
    returnValues[1] = target.getScaleY();
    return 2;
    case POSITION_XY:
    returnValues[0] = target.getX();
    returnValues[1] = target.getY();
    return 2;
    default:
    return 0;
    }
    }

    @Override
    public void setValues(Image target, int tweenType, float[] newValues) {
    switch (tweenType) {
    case ALPHA:
    // would use setAlpha but there is no getAlpha
    target.setColor(1, 1, 1, newValues[0]);
    break;
    case SCALE:
    target.setScale((int) newValues[0], newValues[1]);
    break;

    case POSITION_XY:
    target.setPosition(newValues[0], newValues[1]);
    break;
    }

    }
    }

    package info.garycaine.tilepuzzle.Screens;

    import info.garycaine.tilepuzzle.TweenAccessors.ImageAccessor;
    import aurelienribon.tweenengine.Timeline;
    import aurelienribon.tweenengine.Tween;
    import aurelienribon.tweenengine.TweenEquations;
    import aurelienribon.tweenengine.TweenManager;

    import com.badlogic.gdx.Gdx;
    import com.badlogic.gdx.Screen;
    import com.badlogic.gdx.graphics.GL20;
    import com.badlogic.gdx.graphics.Texture;
    import com.badlogic.gdx.scenes.scene2d.Stage;
    import com.badlogic.gdx.scenes.scene2d.ui.Image;
    import com.badlogic.gdx.utils.viewport.FitViewport;

    public class GameOptions implements Screen{

    private Stage stage;
    private TweenManager manager;
    private Texture texture;
    private Image image;

    private void setupTween() {
    Tween.registerAccessor(Image.class, new ImageAccessor());

    manager = new TweenManager();

    Timeline.createSequence()

    .push(Tween.to(image, ImageAccessor.SCALE, 3).target(1.0f,1.0f)
    .ease(TweenEquations.easeOutQuad)
    )

    /* scale to double size
    .push(Tween.to(image, ImageAccessor.SCALE, 3).target(2.0f,2.0f)
    .ease(TweenEquations.easeOutQuad)
    )
    */

    .start(manager);
    }

    @Override
    public void render(float delta) {
    manager.update(delta);
    Gdx.gl.glClearColor(1, 1, 1, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    stage.act();
    stage.draw();

    }

    @Override
    public void resize(int width, int height) {
    stage.getViewport().update(width, height, true);

    }

    @Override
    public void show() {
    stage = new Stage(new FitViewport(480,800));
    texture = new Texture(“badlogic.jpg”);
    image = new Image(texture);
    image.setColor(1, 1, 1, 1);

    image.setScale(0.25f, 0.25f);
    image.setOrigin(image.getWidth()/2, image.getHeight()/2);
    image.setPosition(130, 200);
    stage.addActor(image);
    setupTween();

    }

    @Override
    public void hide() {
    // TODO Auto-generated method stub

    }

    @Override
    public void pause() {
    // TODO Auto-generated method stub

    }

    @Override
    public void resume() {
    // TODO Auto-generated method stub

    }

    @Override
    public void dispose() {
    // TODO Auto-generated method stub

    }

    }

  • I found the proble, I had a cast to an int in my tween accessor.

  • Thank you I had a friend who had their gold crown fall off. She was really concerned about what she should do. Just like the patient above, money is a big issue for her too. Thanks for your helpful post Dr.Craig, I just printed it out and will show her what you recommended.

  • Normally I do not learn article on blogs, but I would like to say that this write-up very pressured me to take a look at and do it! Your writing style has been surprised me. Thanks, quite nice post.

  • [...] Universal Tween Engine (UTE) è un’utile e semplice libreria che permette di applicare delle trasformazioni agli attributi di un oggetto attraverso l’interpolazione, che detto diversamente, è ciò che consente di realizzare facilmente delle animazioni. Si tratta di uno strumento davvero universale perché può essere impiegato ovunque, richiede solo un oggetto Java (Swing, OpenGL, ecc) con delle proprietà numeriche. Per iniziare fatevi un’idea con questa demo. [...]

  • Very good website you have here but I was curious if you knew of any user discussion forums that cover the same topics talked about in this article? I’d really like to be a part of online community where I can get feedback from other knowledgeable people that share the same interest. If you have any recommendations, please let me know. Cheers!

  • I intended to post you this little bit of remark in order to say thanks as before for the pleasing strategies you have featured on this website. This has been certainly incredibly open-handed with you giving without restraint all a lot of folks might have made available for an ebook in making some bucks for their own end, and in particular considering that you might well have done it if you ever considered necessary. These creative ideas likewise acted like the great way to be aware that other individuals have similar keenness just like my personal own to understand a whole lot more on the topic of this problem. I am certain there are many more enjoyable periods up front for individuals who looked over your blog.

Got anything to say? Go ahead and leave a comment!

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>