Sprite¶
Draw textured quads with Sprite2D.
▶ Run in browserTags: 2d
A Sprite2D draws one texture as a quad centred on its position. Its texture
takes a file path, encoded PNG bytes, or an RGBA uint8 NumPy array of shape
(height, width, 4); this example builds three arrays with NumPy, so it needs
no image files.
widthandheightgive the quad’s size in pixels beforescale. Leave them unset and the quad takes the texture’s native size.colourmultiplies every texel, so it tints the image and its alpha fades the whole sprite.position,rotationandscaleare the usualNode2Dtransform, and a child inherits them: the caption under the star is the star’s child, so it turns with it.
On screen: a checkerboard at 128 pixels; a green-tinted gradient that bobs up
and down; a star whose alpha falls off towards its tips, rotating; and the
same checkerboard with width 64 and scale 0.5, so it draws at 32 pixels,
tinted yellow and slightly transparent. The sprites are placed as fractions
of the window, so they follow a resize.
Source¶
1# /// simvx
2# web = { width = 900, height = 600 }
3# ///
4"""Sprite: Draw textured quads with Sprite2D.
5
6A `Sprite2D` draws one texture as a quad centred on its position. Its `texture`
7takes a file path, encoded PNG bytes, or an RGBA `uint8` NumPy array of shape
8`(height, width, 4)`; this example builds three arrays with NumPy, so it needs
9no image files.
10
11- `width` and `height` give the quad's size in pixels before `scale`. Leave
12 them unset and the quad takes the texture's native size.
13- `colour` multiplies every texel, so it tints the image and its alpha fades
14 the whole sprite.
15- `position`, `rotation` and `scale` are the usual `Node2D` transform, and a
16 child inherits them: the caption under the star is the star's child, so it
17 turns with it.
18
19On screen: a checkerboard at 128 pixels; a green-tinted gradient that bobs up
20and down; a star whose alpha falls off towards its tips, rotating; and the
21same checkerboard with width 64 and `scale` 0.5, so it draws at 32 pixels,
22tinted yellow and slightly transparent. The sprites are placed as fractions
23of the window, so they follow a resize.
24"""
25
26import math
27
28import numpy as np
29
30from simvx.core import Node2D, Sprite2D, Text2D
31from simvx.graphics import App
32
33SIZE = 64
34
35
36def checkerboard(cell: int = 8) -> np.ndarray:
37 ys, xs = np.mgrid[:SIZE, :SIZE]
38 even = ((xs // cell + ys // cell) % 2 == 0)[..., None]
39 return np.where(even, (200, 60, 60, 255), (60, 60, 200, 255)).astype(np.uint8)
40
41
42def gradient() -> np.ndarray:
43 t = np.linspace(0.0, 1.0, SIZE)
44 img = np.empty((SIZE, SIZE, 4), dtype=np.uint8)
45 img[..., 0] = 255 * t
46 img[..., 1] = 255 * (1 - t)
47 img[..., 2:] = (80, 255)
48 return img
49
50
51def star(points: int = 5) -> np.ndarray:
52 ys, xs = np.mgrid[:SIZE, :SIZE] - SIZE // 2
53 dist = np.hypot(xs, ys)
54 radius = SIZE * 0.4 * (0.5 + 0.5 * np.abs(np.cos(points / 2 * np.arctan2(ys, xs))))
55 img = np.empty((SIZE, SIZE, 4), dtype=np.uint8)
56 img[..., :3] = (255, 220, 50)
57 img[..., 3] = np.where(dist < radius, 255 * (1 - dist / radius), 0)
58 return img
59
60
61class SpriteScene(Node2D):
62 def on_ready(self):
63 self.time = 0.0
64 checker = checkerboard()
65 self.checker = self.add_child(Sprite2D(texture=checker, width=128, height=128))
66 self.gradient = self.add_child(Sprite2D(texture=gradient(), width=128, height=128, colour=(0.8, 1.0, 0.8, 1.0)))
67 self.star = self.add_child(Sprite2D(texture=star(), width=192, height=192))
68 self.star.add_child(Text2D(text="turning with the star", position=(-80, 110)))
69 self.small = self.add_child(
70 Sprite2D(texture=checker, width=64, height=64, scale=(0.5, 0.5), colour=(1.0, 1.0, 0.5, 0.8))
71 )
72 self.add_child(Text2D(text="Sprite2D", position=(10, 10), font_scale=1.5))
73 self.add_child(
74 Text2D(text="Checker | Gradient (tinted) | Star (rotating) | Checker (scaled, tinted)", position=(10, 40))
75 )
76
77 def on_update(self, dt: float):
78 self.time += dt
79 w, h = self.viewport_size
80 self.checker.position = (w * 0.22, h / 3)
81 self.gradient.position = (w * 0.56, h / 3 + 30 * math.sin(self.time * 2))
82 self.star.position = (w * 0.39, h * 2 / 3)
83 self.star.rotation = self.time * 0.5
84 self.small.position = (w * 0.78, h * 2 / 3)
85
86
87if __name__ == "__main__":
88 App(width=900, height=600, title="Sprite2D").run(SpriteScene())