Timer¶
run code on a delay or at a repeating interval.
▶ Run in browserTags: 2d timer signals
A Timer is a node that emits a timeout signal after its duration. Set
one_shot=False to repeat. Here a repeating timer spawns a pulse every 0.8s, and
each pulse uses its own one-shot timer to remove itself after one second, so the
screen stays lively without any per-frame bookkeeping in the root.
What it demonstrates¶
Timer(duration=, one_shot=, autostart=)– a node that firestimeoutafter a delay.timer.timeout.connect(fn)– run something when it fires (a signal, like any other).Repeating timers (
one_shot=False) for intervals; one-shot timers for delayed actions.
Source¶
1"""Timer: run code on a delay or at a repeating interval.
2
3A `Timer` is a node that emits a `timeout` signal after its `duration`. Set
4`one_shot=False` to repeat. Here a repeating timer spawns a pulse every 0.8s, and
5each pulse uses its own one-shot timer to remove itself after one second, so the
6screen stays lively without any per-frame bookkeeping in the root.
7
8# /// simvx
9# tags = ["2d", "timer", "signals"]
10# screenshot_frame = 90
11# web = { root = "TimerDemo", width = 800, height = 600, responsive = true }
12# ///
13
14## What it demonstrates
15
16- `Timer(duration=, one_shot=, autostart=)` -- a node that fires `timeout` after a delay.
17- `timer.timeout.connect(fn)` -- run something when it fires (a signal, like any other).
18- Repeating timers (`one_shot=False`) for intervals; one-shot timers for delayed actions.
19"""
20
21import random
22
23from simvx.core import Node2D, Timer, Vec2
24from simvx.graphics import App
25
26WIDTH, HEIGHT = 800, 600
27
28
29class Pulse(Node2D):
30 """An expanding, fading ring that deletes itself after one second."""
31
32 LIFE = 1.0
33 # The ring expands and fades every frame -> opt into per-frame redraw so the
34 # retained 2D renderer re-runs on_draw instead of freezing the first frame.
35 dynamic = True
36
37 def on_ready(self):
38 self.age = 0.0
39 timer = self.add_child(Timer(duration=self.LIFE, one_shot=True, autostart=True))
40 timer.timeout.connect(self.destroy) # one-shot: clean up after the delay
41
42 def on_update(self, dt: float):
43 self.age += dt
44
45 def on_draw(self, renderer):
46 f = min(1.0, self.age / self.LIFE)
47 renderer.draw_circle(self.position, 12 + f * 64, colour=(0.4, 0.8, 1.0, 1.0 - f), filled=True)
48
49
50class TimerDemo(Node2D):
51 def on_ready(self):
52 self.ticks = 0
53 spawner = self.add_child(Timer(duration=0.8, one_shot=False, autostart=True))
54 spawner.timeout.connect(self._spawn) # repeating: fires every 0.8s
55
56 def _spawn(self):
57 self.ticks += 1
58 # Spawn against the live window size so pulses keep filling the view
59 # after a resize (the web export runs this scene responsively).
60 w, h = self.app.width, self.app.height
61 self.add_child(Pulse(position=Vec2(random.uniform(120, w - 120), random.uniform(140, h - 100))))
62
63 def on_draw(self, renderer):
64 renderer.draw_text("Timer: repeating + one-shot", (20, 20), scale=2, colour=(1, 1, 1))
65 renderer.draw_text(f"ticks: {self.ticks}", (20, 52), scale=1, colour=(0.7, 0.7, 0.7))
66
67
68if __name__ == "__main__":
69 App(title="Timer", width=WIDTH, height=HEIGHT).run(TimerDemo())