Triangle

the smallest custom-draw scene.

▶ Run in browser

Tags: 2d

A scene is a Node2D subclass, and on_draw(renderer) is where it paints itself with immediate-mode commands. This one draws a filled triangle and a caption, both centred in the window and sized from it, so they follow a resize.

How it works

  • self.viewport_size is the size of the target the node draws into. Reading it inside on_draw keeps the layout in step with the window; a resize repaints the scene.

  • renderer.polygon(points, fill=colour) fills the polygon through a list of (x, y) vertices, in the node’s own space. Colours are RGBA tuples in the 0 to 1 range.

  • renderer.text(text, pos, fill=colour, scale=..., align=HAlign.CENTRE) draws a string; align anchors each line’s centre on pos.x, so centring needs no width arithmetic. scale multiplies the 16-pixel em.

  • App(...).run(root) opens the window and runs the scene tree.

The drawing reads no changing state, so it is captured once and redrawn only when something invalidates it. A node whose on_draw animates every frame sets dynamic = True on its class.

Source

 1"""Triangle: the smallest custom-draw scene.
 2
 3A scene is a `Node2D` subclass, and `on_draw(renderer)` is where it paints itself with
 4immediate-mode commands. This one draws a filled triangle and a caption, both centred in
 5the window and sized from it, so they follow a resize.
 6
 7## How it works
 8
 9- `self.viewport_size` is the size of the target the node draws into. Reading it inside
10  `on_draw` keeps the layout in step with the window; a resize repaints the scene.
11- `renderer.polygon(points, fill=colour)` fills the polygon through a list of `(x, y)`
12  vertices, in the node's own space. Colours are RGBA tuples in the 0 to 1 range.
13- `renderer.text(text, pos, fill=colour, scale=..., align=HAlign.CENTRE)` draws a string;
14  `align` anchors each line's centre on `pos.x`, so centring needs no width arithmetic.
15  `scale` multiplies the 16-pixel em.
16- `App(...).run(root)` opens the window and runs the scene tree.
17
18The drawing reads no changing state, so it is captured once and redrawn only when
19something invalidates it. A node whose `on_draw` animates every frame sets
20`dynamic = True` on its class.
21"""
22
23from simvx.core import HAlign, Node2D
24from simvx.graphics import App
25
26
27class Triangle(Node2D):
28    def on_draw(self, renderer):
29        w, h = self.viewport_size
30        cx, cy = w / 2, h / 2
31        size = min(w, h) / 3
32        renderer.polygon([(cx, cy - size), (cx - size, cy + size), (cx + size, cy + size)], fill=(0.2, 0.86, 0.47, 1.0))
33        renderer.text(
34            "Hello, SimVX!", (cx, cy + size * 1.12), fill=(1.0, 1.0, 1.0, 1.0), scale=size / 100, align=HAlign.CENTRE
35        )
36
37
38if __name__ == "__main__":
39    App(title="Triangle", width=800, height=600).run(Triangle())