Skip to main content
View

Animation foundations

PSDK animates everything through Yuki::Animation, a time-based system where you build small animation blocks and combine them in sequence or in parallel. This page explains that core logic; specific uses are covered in their own guides.

How an animation works

A Yuki animation is time-based, not frame-based. It has a duration in seconds and progresses from 0 (start) to 1 (end) over that time, reading the elapsed time from the current scene's clock so it stays consistent at any frame rate.

Whatever it animates, it answers the same four messages: start, update, done? and duration. Driving one is always the same loop: start it, then update it every frame until it reports it is done.

animation.start
until animation.done?
animation.update
Graphics.update
end

Inside a scene you do not write that loop yourself: the scene updates the animation for you each frame. You write it in standalone scripts, or to picture what the system does.

Every helper lives in the Yuki::Animation module, usually aliased to a short local variable:

ya = Yuki::Animation

The building blocks

A building block animates one thing, and they all share the same shape: the duration first, then the object to animate, then the start and end values. The most general is scalar, which interpolates a single numeric property through its setter method:

# Fade a sprite out over 0.5s (opacity 255 -> 0)
ya.scalar(0.5, sprite, :opacity=, 255, 0)

move is the same idea for a position vector (x, y):

# Move a sprite from (0, 5) to (100, 32) in 3s
ya.move(3, sprite, 0, 5, 100, 32)

And wait simply does nothing for a duration, to hold a pause inside a sequence:

ya.wait(1.0)

That is the whole pattern. Dedicated helpers exist for the other common cases (opacity, rotation, origin shift, sprite-sheet cells); they all follow the same duration, object, from, to shape.

Sequencing and parallelism

The real power is composition. Two combinators assemble blocks, and both behave like a single animation, so you can nest them freely:

  • ya.player(a, b, c) runs its animations one after another (sequential).
  • ya.parallel(a, b, c) runs them at the same time (simultaneous).
ya = Yuki::Animation

# Fade in while sliding down, hold one second, then fade out
animation = ya.player(
ya.parallel(
ya.scalar(0.3, sprite, :opacity=, 0, 255),
ya.move(0.3, sprite, sprite.x, sprite.y - 20, sprite.x, sprite.y)
),
ya.wait(1.0),
ya.scalar(0.3, sprite, :opacity=, 255, 0)
)

animation.start
until animation.done?
animation.update
Graphics.update
end

player waits for each step (including any parallel group inside it) to finish before moving to the next. That sequential and parallel nesting is enough to describe most animations.

Conclusion

  • A Yuki animation is time-based: a duration, progress from 0 to 1, driven by start / update / done?.
  • Build with blocks that share one shape: ya.scalar for a numeric property, ya.move for a position, ya.wait for a pause; the other helpers follow the same shape.
  • Compose with ya.player (sequential) and ya.parallel (simultaneous), nested as needed.
  • In a scene the scene drives update; standalone, loop until done?.
  • Everything else (UI integration, distortions, saving, commands) lives in dedicated guides.