pyxen.draw
The draw module draws shapes straight to the screen, frame by frame. Call it from
update(): what you draw belongs to that frame, and the next frame starts empty, so you
draw it again each frame for as long as it should show.
from pyxen import *
def update():
draw.circle(64, 64, 20, fill=(1, 0.2, 0.3, 1))
draw.line(0, 0, 128, 128, color=(1, 1, 1, 1))
Nothing is spawned: there is no entity to keep a handle on and nothing to destroy. The time-travel debugger keeps what each frame drew, so when you pause and go back through the frames, every frame shows its shapes as it did when the game ran.
draw or a Shape component?
Pyxen gives you the same primitives twice. They look identical on screen and differ only in lifetime.
| Shape component | draw | |
|---|---|---|
| Lifetime | Lives until you destroy the entity | Each frame draws it again |
| Position | Entity position, rotation, scale | World coordinates you pass in |
| Cost | A full entity: transform, layer, component storage | A few quads in the frame buffer |
| Debugger | Listed and inspected as an entity | Shown in each frame you go back to |
| Good for | Game objects — ships, walls, UI that stays put | Pictures of your game’s state: trails, overlays, HUD bars |
Reach for a Shape when the thing is something in your game. Reach for draw when you
are painting a picture of state your entities already hold: keep that state in entities and
components, where the debugger and the Inspector see it, and draw from it each frame.
Colours
Every colour argument takes an (r, g, b, a) tuple with components from 0.0 to 1.0, or
a Color.
draw.rect(10, 10, 40, 20, fill=(1, 0, 0, 1)) # opaque red
draw.rect(10, 40, 40, 20, fill=(1, 0, 0, 0.35)) # 35% red
The filled shapes draw nothing by default. draw.rect, draw.triangle and
draw.circle start with both fill and stroke fully transparent, so a call that passes
neither is invisible — that is the single most common surprise with this module. draw.line
and draw.polyline default to opaque white instead, so they always show up.
Functions
draw.line(x1, y1, x2, y2, color=(1,1,1,1), width=1)
A straight line between two points.
| Argument | Type | Description |
|---|---|---|
x1, y1 | float | Start point, in world coordinates. |
x2, y2 | float | End point. |
color | tuple | Line colour. Defaults to opaque white. |
width | float | Line thickness in pixels. Defaults to 1. |
def update():
draw.line(0, 64, 128, 64, color=(0.3, 1, 0.5, 1), width=2)
draw.polyline(points, color=(1,1,1,1), width=1, closed=False)
A run of connected line segments.
| Argument | Type | Description |
|---|---|---|
points | tuple or FloatBuffer | Flat sequence (x1, y1, x2, y2, …) — not a list of pairs. |
color | tuple | Line colour. Defaults to opaque white. |
width | float | Line thickness in pixels. |
closed | bool | When True, joins the last point back to the first. |
def update():
draw.polyline((10, 10, 40, 60, 80, 20, 110, 70),
color=(1, 0.8, 0.2, 1), width=2)
Points are flat on purpose: it is the shape a FloatBuffer already has, so a path you
compute once can be handed straight to draw.polyline every frame without rebuilding it.
draw.rect(x, y, width, height, fill=None, stroke=None, stroke_width=1)
An axis-aligned rectangle. x, y is its corner, not its centre.
| Argument | Type | Description |
|---|---|---|
x, y | float | Corner position. |
width, height | float | Size in pixels. |
fill | tuple | Interior colour. Omit for no fill. |
stroke | tuple | Outline colour. Omit for no outline. |
stroke_width | float | Outline thickness. Defaults to 1. |
def update():
# A health bar: dark backing, bright fill, thin outline.
draw.rect(4, 4, 60, 6, fill=(0.1, 0.1, 0.1, 1))
draw.rect(4, 4, 60 * health / max_health, 6, fill=(0.2, 1, 0.4, 1))
draw.rect(4, 4, 60, 6, stroke=(1, 1, 1, 0.5))
draw.triangle(x1, y1, x2, y2, x3, y3, fill=None, stroke=None, stroke_width=1)
A triangle through three points.
| Argument | Type | Description |
|---|---|---|
x1, y1, x2, y2, x3, y3 | float | The three corners. |
fill | tuple | Interior colour. Omit for no fill. |
stroke | tuple | Outline colour. Omit for no outline. |
stroke_width | float | Outline thickness. |
def update():
draw.triangle(64, 20, 84, 60, 44, 60, fill=(1, 1, 0.3, 1))
draw.circle(x, y, radius, fill=None, stroke=None, stroke_width=1, segments=12)
A circle around a centre point.
| Argument | Type | Description |
|---|---|---|
x, y | float | Centre position. |
radius | float | Radius in pixels. |
fill | tuple | Interior colour. Omit for no fill. |
stroke | tuple | Outline colour. Omit for no outline. |
stroke_width | float | Outline thickness. |
segments | int | Straight segments approximating the curve. Defaults to 12. |
A circle is really a polygon. Twelve segments reads as round at small sizes; raise it for large circles and lower it when you want a visible polygon.
def update():
draw.circle(64, 64, 24, fill=(0.2, 0.4, 1, 1), segments=32)
draw.circle(64, 64, 30, stroke=(1, 1, 1, 0.4), segments=32)
Notes
drawcalls belong inupdate(). Calling them fromstart()draws for a single frame and then vanishes.- Drawing happens in world coordinates, so the camera moves it. For a HUD that stays put,
draw relative to
cameraor keep the HUD on an unmoved camera. - Everything drawn in a frame lands above the sprites drawn that frame.