First Scene¶
Open a window and add a node.
▶ Run in browserTags: beginner tutorial
First Scene¶
Your first SimVX scene in under thirty lines. By the end you will have opened a window, drawn a pulsing circle, and seen the three lifecycle hooks every node has access to.
Step 1: Subclass Node2D¶
Every visible thing in SimVX is a node. Node2D is the 2D-aware variant:
it knows about position, rotation, and lets you override on_draw()
to issue immediate-mode draw commands.
from simvx.core import Node2D
class FirstScene(Node2D):
pass
Step 2: Hook into the frame loop¶
Three hooks fire automatically once the node is in the scene tree:
on_ready(): called once after the node enters the tree. Initialise state here.on_update(dt): called every frame with the seconds since the last frame.on_draw(renderer): issue draw commands here. The 2D renderer is retained: it re-runson_drawonly when the node changes, so a node whose drawing animates every frame (like our pulsing circle) setsdynamic = Trueto opt into per-frame redraws.
class FirstScene(Node2D):
dynamic = True # the circle pulses every frame, so redraw it every frame
def on_ready(self):
self.t = 0.0
def on_update(self, dt: float):
self.t += dt
def on_draw(self, renderer):
renderer.draw_circle((400, 300), 80, colour=(0.4, 0.8, 1.0, 1.0), filled=True)
Step 3: Launch it¶
App creates a Vulkan-backed window and runs your scene tree.
from simvx.graphics import App
App(title="First Scene", width=800, height=600).run(FirstScene())
Run it¶
uv run python examples/tutorials/first_scene/main.py
A window opens with a pulsing blue circle and a welcome message.
What’s next¶
Nodes and Signals – the next tutorial: wire several nodes together so they react to each other.
Input and Movement – drive a node from the keyboard with input actions.
Bouncing Balls –
Propertydescriptors and many children at once.
Source¶
1"""First Scene: Open a window and add a node.
2
3A two-minute tour: subclass `Node2D`, override `on_draw()` to paint a circle,
4launch with `App`. The companion README explains the lifecycle hooks called
5along the way.
6
7# /// simvx
8# tags = ["beginner", "tutorial"]
9# web = { root = "FirstScene", width = 800, height = 600, responsive = true }
10# ///
11"""
12
13import math
14
15from simvx.core import Node2D
16from simvx.graphics import App
17
18WIDTH, HEIGHT = 800, 600
19
20
21class FirstScene(Node2D):
22 # The circle pulses every frame -> opt this node into per-frame redraw so the
23 # retained 2D renderer re-runs on_draw each frame instead of freezing the geometry.
24 dynamic = True
25
26 def on_ready(self):
27 self.t = 0.0
28
29 def on_update(self, dt: float):
30 self.t += dt
31
32 def on_draw(self, renderer):
33 cx, cy = WIDTH / 2, HEIGHT / 2
34 radius = 80 + 20 * math.sin(self.t * 2) # gentle pulse, 60..100 px
35 renderer.draw_circle((cx, cy), radius, colour=(0.4, 0.8, 1.0, 1.0), filled=True)
36 renderer.draw_text("Welcome to SimVX", (cx - 110, cy + 140), scale=2, colour=(1.0, 1.0, 1.0))
37
38
39if __name__ == "__main__":
40 App(title="First Scene", width=WIDTH, height=HEIGHT).run(FirstScene())