Tween

animate any property over time with easing.

▶ Run in browser

Tags: 2d animation tween

tween() smoothly drives a property from its current value to a target over a duration, optionally with an easing curve and repeats. It is a coroutine: hand it to start_coroutine() and the node’s lifecycle runs it. This example races a marker along each row using a different easing function so you can see how the curves differ; every marker covers the same distance in the same time.

What it demonstrates

  • tween(obj, prop, target, duration, easing=...) – interpolate a scalar or a Vec2 property (here, each marker’s position).

  • The easing module (easing.ease_linear, easing.ease_in_quad, easing.ease_out_quad, easing.ease_in_out_cubic, …) shapes the motion: slow-in, slow-out, both, or none.

  • repeat + repeat_mode="yoyo" to ping-pong the animation back and forth.

  • yield from tween(...) inside your own coroutine to sequence or loop tweens.

  • start_coroutine() to run a tween from a node.

Source

 1"""Tween: animate any property over time with easing.
 2
 3`tween()` smoothly drives a property from its current value to a target over a
 4duration, optionally with an easing curve and repeats. It is a coroutine: hand it
 5to `start_coroutine()` and the node's lifecycle runs it. This example races a
 6marker along each row using a different easing function so you can see how the
 7curves differ; every marker covers the same distance in the same time.
 8
 9# /// simvx
10# tags = ["2d", "animation", "tween"]
11# web = { root = "TweenDemo", width = 800, height = 600, responsive = true }
12# ///
13
14## What it demonstrates
15
16- `tween(obj, prop, target, duration, easing=...)` -- interpolate a scalar or a
17  `Vec2` property (here, each marker's `position`).
18- The `easing` module (`easing.ease_linear`, `easing.ease_in_quad`,
19  `easing.ease_out_quad`, `easing.ease_in_out_cubic`, ...) shapes the motion:
20  slow-in, slow-out, both, or none.
21- `repeat` + `repeat_mode="yoyo"` to ping-pong the animation back and forth.
22- `yield from tween(...)` inside your own coroutine to sequence or loop tweens.
23- `start_coroutine()` to run a tween from a node.
24"""
25
26from simvx.core import Node2D, Vec2, easing, tween
27from simvx.graphics import App
28
29WIDTH, HEIGHT = 800, 600
30LEFT_X, RIGHT_X = 210, WIDTH - 60
31
32CURVES = [
33    ("linear", easing.ease_linear),
34    ("ease_in_quad", easing.ease_in_quad),
35    ("ease_out_quad", easing.ease_out_quad),
36    ("ease_in_cubic", easing.ease_in_cubic),
37    ("ease_out_cubic", easing.ease_out_cubic),
38    ("ease_in_out_cubic", easing.ease_in_out_cubic),
39]
40
41
42def ping_pong(marker, target, curve):
43    """Run a there-and-back tween over and over.
44
45    A tween is an ordinary coroutine, so it composes: `yield from` runs one
46    two-leg yoyo (out and back), and the loop starts the next one.
47    """
48    while True:
49        yield from tween(marker, "position", target, duration=2.0, easing=curve, repeat=2, repeat_mode="yoyo")
50
51
52class Marker(Node2D):
53    def on_draw(self, renderer):
54        renderer.draw_circle(self.position, 14, colour=(0.4, 0.8, 1.0, 1.0), filled=True)
55
56
57class TweenDemo(Node2D):
58    def on_ready(self):
59        self.markers = []
60        for i, (name, curve) in enumerate(CURVES):
61            y = 90 + i * 80
62            marker = self.add_child(Marker(position=Vec2(LEFT_X, y)))
63            self.markers.append((name, y, marker))
64            # Animate position from the left edge to the right and back, forever,
65            # shaped by this row's easing curve.
66            self.start_coroutine(ping_pong(marker, Vec2(RIGHT_X, y), curve))
67
68    def on_draw(self, renderer):
69        renderer.draw_text("Tween: easing curves", (20, 20), scale=2, colour=(1, 1, 1))
70        for name, y, _ in self.markers:
71            renderer.draw_text(name, (20, y - 8), scale=1, colour=(0.7, 0.7, 0.7))
72
73
74if __name__ == "__main__":
75    App(title="Tween", width=WIDTH, height=HEIGHT).run(TweenDemo())