Triangle¶
the smallest custom-draw scene.
▶ Run in browserTags: 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_sizeis the size of the target the node draws into. Reading it insideon_drawkeeps 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;alignanchors each line’s centre onpos.x, so centring needs no width arithmetic.scalemultiplies 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())