AgentStack
SKILL verified MIT Self-run

Universal Tween Engine

skill-kyu-n-gdx-claude-skills-universal-tween-engine · by kyu-n

Use when writing Java code using Universal Tween Engine (package aurelienribon.tweenengine, version 6.3.3) — Tween.to, Tween.from, Tween.set, Tween.call, Tween.mark, Timeline.createSequence, Timeline.createParallel, TweenAccessor, TweenManager, TweenCallback, easing equations (Quad, Cubic, Back, Elastic, Bounce, etc.), or waypoints/paths. Use when debugging tweens not starting, accessor not found…

No reviews yet
0 installs
7 views
0.0% view→install

Install

$ agentstack add skill-kyu-n-gdx-claude-skills-universal-tween-engine

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Universal Tween Engine? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Universal Tween Engine (6.3.3)

Quick reference for consumers of aurelienribon.tweenengine. Covers factory construction, accessor registration, defaults/limits, semantic traps, callbacks, pooling lifecycle, and timeline composition. Full method signatures in references/api.md.

Defaults & Limits

| Setting | Default | Override | |---|---|---| | Easing equation | Quad.INOUT | .ease(equation) | | Path algorithm | CatmullRom spline | .path(TweenPaths.linear) | | Combined attributes limit | 3 | Tween.setCombinedAttributesLimit(n) at startup | | Waypoints limit | 0 | Tween.setWaypointsLimit(n) at startup | | Callback trigger | COMPLETE only | .setCallbackTriggers(flags) | | Tween.call() trigger | START (overrides default) | .setCallbackTriggers(flags) | | Duration units | Unitless (matches manager.update(delta)) | N/A | | Repeat count | 0 (no repeat) | .repeat(count, delay) or .repeatYoyo(count, delay) | | Auto-remove from manager | true | TweenManager.setAutoRemove(tween, false) | | Auto-start on manager add | true | TweenManager.setAutoStart(tween, false) | | Tween pool initial capacity | 20 | Tween.ensurePoolCapacity(n) | | Timeline pool initial capacity | 10 | Timeline.ensurePoolCapacity(n) |

Combined attributes limit = 3 means: tweening 4+ float values simultaneously (e.g., RGBA) throws at runtime unless you call Tween.setCombinedAttributesLimit(4) first.

Waypoints limit = 0 means: ANY .waypoint() call throws unless you call Tween.setWaypointsLimit(n) first.

Factory-Only Construction

Tween and Timeline have private constructors. All instances come from internal object pools via static factories.

// Tween factories — NEVER use new Tween()
Tween.to(target, tweenType, duration)      // animate from current to target values
Tween.from(target, tweenType, duration)    // animate from target values to current (reversed)
Tween.set(target, tweenType)               // instantly set values (duration=0)
Tween.call(callback)                       // timer/callback only — no target needed
Tween.mark()                               // empty beacon for Timeline sequencing

// Timeline factories — NEVER use new Timeline()
Timeline.createSequence()                  // children play one after another
Timeline.createParallel()                  // children play all at once

TweenAccessor Registration

An accessor MUST be available before any tween on that type starts. Two approaches:

Approach 1: Register externally (most common)

// At application startup, once
Tween.registerAccessor(Sprite.class, new SpriteAccessor());

// Then anywhere:
Tween.to(mySprite, SpriteAccessor.POSITION_XY, 1f).target(100, 200).start(manager);

Approach 2: Target self-implements TweenAccessor

// No registration needed — engine detects TweenAccessor on the target
public class Particle implements TweenAccessor {
    public static final int XY = 0;
    float x, y;

    @Override
    public int getValues(Particle target, int tweenType, float[] returnValues) {
        returnValues[0] = target.x;
        returnValues[1] = target.y;
        return 2;  // MUST return count of values written
    }

    @Override
    public void setValues(Particle target, int tweenType, float[] newValues) {
        target.x = newValues[0];
        target.y = newValues[1];
    }
}

getValues() return value contract: The int returned is the count of float values written into returnValues[]. This count must be = 0 The javadoc on update(float delta) advertises negative delta for backward play. Do not use negative delta — backward play is unreliable and a source of bugs. Always clamp delta to >= 0 before passing to manager.update() or tween.update().

Default easing is NOT linear

Default is Quad.INOUT. For linear interpolation, explicitly set .ease(Linear.INOUT).

Default path is NOT linear

Default path is CatmullRom spline. Only matters when using waypoints. For straight-line waypoint interpolation, use .path(TweenPaths.linear).

Callback System

tween.setCallback((type, source) -> {
    // 'type' is a single flag (e.g., TweenCallback.COMPLETE), NOT a combined mask
    if (type == TweenCallback.COMPLETE) { /* ... */ }
}).setCallbackTriggers(TweenCallback.BEGIN | TweenCallback.COMPLETE);

Callback trigger constants (bitmask):

| Constant | Value | When | |---|---|---| | BEGIN | 0x01 | Right after initial delay ends (once) | | START | 0x02 | At each iteration beginning | | END | 0x04 | At each iteration ending, before repeat delay | | COMPLETE | 0x08 | At last END (once) | | BACK_BEGIN | 0x10 | First backward iteration beginning | | BACK_START | 0x20 | Each backward iteration beginning | | BACK_END | 0x40 | Each backward iteration ending | | BACK_COMPLETE | 0x80 | Last BACK_END (once) | | ANY_FORWARD | 0x0F | All forward events | | ANY_BACKWARD | 0xF0 | All backward events | | ANY | 0xFF | All events |

Timing diagram (canonical reference):

forward :      BEGIN                                   COMPLETE
forward :      START    END      START    END      START    END
|--------------[XXXXXXXXXX]------[XXXXXXXXXX]------[XXXXXXXXXX]
backward:      bEND  bSTART      bEND  bSTART      bEND  bSTART
backward:      bCOMPLETE                                 bBEGIN

Tween.call() overrides default trigger to START (not COMPLETE). All other factories default to COMPLETE.

Pooling Lifecycle

Managed tweens (started via .start(manager)) are fire-and-forget:

  1. Create via factory -> object pulled from pool
  2. .start(manager) -> manager adds and starts it
  3. manager.update(delta) -> two phases per call:
  • Phase 1: Sweep — removes tweens that finished on a previous update, calling free() on each (returns to pool)
  • Phase 2: Update — updates all remaining tweens with the delta

A tween that finishes during this frame's update is NOT removed until the next update() call. This means isFinished() returns true for one frame before the tween is freed.

Holding references to finished managed tweens is unsafe. After free(), the same object may be reused for a completely different tween.

To keep a tween reference alive after completion:

TweenManager.setAutoRemove(tween, false);  // prevents automatic removal and pooling
// You must manually call tween.free() when done, or it leaks

For unmanaged tweens (.start() with no manager): you must call tween.update(delta) yourself and tween.free() when done.

Timeline Composition

Timeline.createSequence()
    .push(Tween.set(obj, OPACITY).target(0))           // instant set
    .beginParallel()                                     // nested parallel
        .push(Tween.to(obj, OPACITY, 0.5f).target(1))
        .push(Tween.to(obj, SCALE, 0.5f).target(1, 1))
    .end()                                               // closes beginParallel
    .pushPause(1.0f)                                     // 1-second pause
    .push(Tween.to(obj, POS_X, 0.5f).target(100))
    .repeat(5, 0.5f)
    .start(manager);

Rules:

  • Every beginParallel() / beginSequence() MUST be balanced with .end()
  • Children with infinite repeat (Tween.INFINITY) throw on build when pushed to a Timeline
  • pushPause() accepts negative values for overlap with the preceding child
  • Nested timelines pushed via .push(timeline) must have their own end() calls balanced before being pushed

Parameterizable Equations

Back and Elastic have mutable parameters:

Back.IN.s(2.5f)                    // overshoot amount (default 1.70158)
Elastic.IN.a(1.2f).p(0.4f)        // amplitude / period

These mutate the static singleton instances. If you call Back.IN.s(2.5f) in one tween, ALL subsequent tweens using Back.IN see the changed value. This is NOT thread-safe and persists for the application lifetime.

Built-in Tweenables

The library includes MutableFloat and MutableInteger (in primitives subpackage) which self-implement TweenAccessor — no registration needed:

MutableFloat alpha = new MutableFloat(0f);
Tween.to(alpha, 0, 1f).target(1f).start(manager);
// alpha.floatValue() will interpolate from 0 to 1 over 1 unit of time

Common Mistakes

  1. new Tween(...) or new Timeline(...) — constructors are private. Use static factories.
  2. Forgetting Tween.registerAccessor() — throws "No TweenAccessor was found for the target" at .start() or .build().
  3. getValues() returning 0 or wrong count — engine interpolates 0 values; nothing visibly happens.
  4. Tweening 4+ values without raising limit — throws at runtime. Call Tween.setCombinedAttributesLimit(n) at startup.
  5. Using .waypoint() without raising limit — throws immediately (default limit is 0).
  6. Expecting Tween.from() target values to be the end — they're the START. Current values are the end.
  7. Assuming linear default easing — default is Quad.INOUT.
  8. Treating duration as milliseconds — it's unitless; matches update(delta) time scale.
  9. Holding reference to managed tween after completion — object is pooled and recycled.
  10. Unbalanced beginParallel()/end() — throws "Nothing to end..." or "You forgot to call end()".
  11. Pushing infinite-repeat child into Timeline — throws on build.
  12. Calling Back.IN.s() or Elastic.IN.a().p() without realizing it mutates the global static instance — affects all future tweens using that equation.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.