picogame – Rendering core for games
The picogame module composites sprites, tilemaps, drawing canvases,
particle layers, 3D triangle batches and immediate-mode callbacks into a
small reusable strip buffer and sends each strip to the display, so a full-screen game does not
need a full-screen buffer. A Scene tracks what changed and
repaints only those regions when Scene.refresh() is called.
A scene targets a BusDisplay, an accelerated
Display or a RAM Framebuffer. picogame drives the
display itself, so it requires display.auto_refresh = False and cannot
show displayio groups on the same display at the same time.
Most programs start with Scene, Sprite and
Bitmap.
Note
This module is the engine’s rendering and compute core and is fully
usable on its own. The pure-Python picogame helper libraries
(picogame_game, picogame_ray and others) build a complete game
framework on top of it: display, input and audio setup that adapts to
the board, game-loop timing, sprite pools and collision helpers,
animation, text, HUD and menus, sound effects and music, visual
effects, saved games, scene loading and pseudo-3D cameras. A desktop
simulator, asset-conversion tools, examples and tutorials live in the
picogame repository, with
documentation at picogame.makerclass.cz.
Example:
import array
import board
import time
import picogame
display = board.DISPLAY
display.auto_refresh = False
size = display.width * picogame.STRIP_H * 2
scene = picogame.Scene(display, bytearray(size), bytearray(size))
# One solid white 8x8 frame.
white = picogame.rgb565(255, 255, 255)
bitmap = picogame.Bitmap(array.array("H", [white] * 64), 8, 8)
player = scene.add(picogame.Sprite(bitmap, x=0, y=display.height // 2))
while True:
player.x = (player.x + 1) % display.width
scene.refresh()
time.sleep(0.02)
This moves a white square across the screen, repainting only the pixels that changed each frame.
Available on these boards
- picogame.STRIP_H: int
Recommended render-strip height in rows for this build. Sizing a
Scenestrip buffer asdisplay.width * STRIP_H * 2bytes yields strips this tall.
- picogame.FPU: int
1whenprojectuses hardware floating point (its buffers arefloat32),0when it uses signed 16.16 fixed-pointint32.
- picogame.API_LEVEL: int
Version of the picogame API. Helper libraries compare this value against the API level they target.
- picogame.FAST_DISPLAY_SUPPORTED: bool
Whether the accelerated
Displaybackend is available on this board.
- picogame.FRAMEBUFFER_SUPPORTED: bool
Whether
Framebufferis available on this board.
- picogame.rgb565(r: int, g: int, b: int) int
Build an RGB565 color in the display’s transfer byte order from 8-bit components. Every color integer in this module is such a value.
- picogame.invert(display: Display | busdisplay.BusDisplay | Framebuffer, on: bool) None
Enable or disable color inversion.
Bus displays receive the controller’s inversion command (INVON/INVOFF), which takes effect immediately and sends no pixel data; the controller must support it (ST7789 and ST7735 do). A
Framebuffertarget is instead inverted during composition, starting with the next refresh.
- picogame.render(display: Display | busdisplay.BusDisplay | Framebuffer, layers: List[Sprite | Tilemap | Canvas | Particles | StripDraw | Triangles], buffer: circuitpython_typing.WriteableBuffer | None, x0: int, y0: int, x1: int, y1: int, *, background: int = 0) None
Render
layersinto the screen region from(x0, y0)up to, but not including,(x1, y1), and push it todisplay, without aScene.- Parameters:
display – the render target
layers – layers of any kind, drawn bottom to top
buffer (WriteableBuffer) – a reusable strip buffer of at least
(x1 - x0) * 2bytes; ignored (may beNone) on aFramebuffertargetx0 (int) – left edge of the region
y0 (int) – top edge of the region
x1 (int) – right edge of the region (exclusive)
y1 (int) – bottom edge of the region (exclusive)
background (int) – color the region is cleared to first
- picogame.collide(x1: int, y1: int, x2: int, y2: int, ax1: int, ay1: int, ax2: int = ..., ay2: int = ...) bool
Return whether an inclusive rectangle overlaps another rectangle or contains a point. Both corners are part of the rectangle, so touching edges count as an overlap.
With six arguments, test rectangle
(x1, y1, x2, y2)against the point(ax1, ay1); with eight, test it against the rectangle(ax1, ay1, ax2, ay2).Unlike the pixel regions used by
render, whose upper bounds are excluded, collision bounds are inclusive.
- picogame.fbm2d(x: float, y: float, *, octaves: int = 4, seed: int = 0, lacunarity: float = 2.0, gain: float = 0.5) float
Fractal (fBm) 2-D noise in
0..1:octaveslayers ofvalue2d(), eachlacunaritytimes finer andgaintimes weaker than the last.
- picogame.fbm1d(x: float, *, octaves: int = 4, seed: int = 0, lacunarity: float = 2.0, gain: float = 0.5) float
Fractal (fBm) 1-D noise in
0..1:octaveslayers ofvalue1d(), eachlacunaritytimes finer andgaintimes weaker than the last.
- picogame.project(cam: circuitpython_typing.ReadableBuffer, pts: circuitpython_typing.ReadableBuffer, n: int, out_sx: circuitpython_typing.WriteableBuffer, out_sy: circuitpython_typing.WriteableBuffer) None
Batch-project
n3D world points to screen coordinates.When
FPUis1,camandptsholdfloat32elements; otherwise they hold signed 16.16 fixed-pointint32elements.- Parameters:
cam (ReadableBuffer) – 15 camera parameters, in order: eye x/y/z, right x/z (the camera cannot roll, so right has no y component), up x/y/z, forward x/y/z, focal length, screen center x/y, near-plane distance
pts (ReadableBuffer) –
3 * nworld coordinates (x, y, z per point)n (int) – number of points
out_sx (WriteableBuffer) – at least
nint16values; receives screen x, or the sentinel-32768for a point behind the near planeout_sy (WriteableBuffer) – at least
nint16values; receives screen y, or-32768for a point behind the near plane
- picogame.raycast(map: circuitpython_typing.ReadableBuffer, mw: int, mh: int, posx: int, posy: int, lrx: int, lry: int, srx: int, sry: int, sh: int, stride: int, ncols: int, wcolors: circuitpython_typing.ReadableBuffer, top: circuitpython_typing.WriteableBuffer, bot: circuitpython_typing.WriteableBuffer, col: circuitpython_typing.WriteableBuffer, dist: circuitpython_typing.WriteableBuffer, runs: circuitpython_typing.WriteableBuffer | None = None) int | None
Cast one frame of wall-finding rays across the screen columns of a grid-map view. A low-level interface used by the
picogame_rayhelper, which computes these inputs.All fixed-point arguments are signed 16.16 integers.
- Parameters:
map (ReadableBuffer) – at least
mw * mhwall-type bytes, row-major; 0 is emptymw (int) – map width in cells
mh (int) – map height in cells
posx (int) – camera x position (fixed-point)
posy (int) – camera y position (fixed-point)
lrx (int) – x of the column-0 ray direction (fixed-point)
lry (int) – y of the column-0 ray direction (fixed-point)
srx (int) – per-column ray step x (fixed-point)
sry (int) – per-column ray step y (fixed-point)
sh (int) – screen height in pixels
stride (int) – pixel width of one column
ncols (int) – number of columns to cast
wcolors (ReadableBuffer) – two
uint16colors per wall type: near face at[type * 2], side face at[type * 2 + 1]top (WriteableBuffer) – at least
ncolsuint16values; receives each column’s wall top rowbot (WriteableBuffer) – at least
ncolsuint16values; receives each column’s wall bottom rowcol (WriteableBuffer) – at least
ncolsuint16values; receives each column’s wall colordist (WriteableBuffer) – at least
ncolsint32values; receives each column’s perpendicular distance (fixed-point)runs (WriteableBuffer) – optional; at least
5 * ncolsuint16values, laid out as fivencols-long planes (x0s, x1s, tops, bots, colors). When given, adjacent equal columns are merged into wall runs suitable forCanvas.vspans()and the run count is returned; otherwiseNoneis returned.
- picogame.road_edges(rl: circuitpython_typing.WriteableBuffer, rr: circuitpython_typing.WriteableBuffer, hw: circuitpython_typing.ReadableBuffer, n: int, cx0: int, dist: int, cfg: circuitpython_typing.ReadableBuffer) None
Compute one racing-road frame’s left and right edge columns. A low-level interface used by the
picogame_roadhelper, which packs these inputs.Walks
nscreen rows bottom-up, accumulating the road curve, and writes the edge x coordinates intorlandrr.- Parameters:
rl (WriteableBuffer) – at least
nint16values; receives the left edge per rowrr (WriteableBuffer) – at least
nint16values; receives the right edge per rowhw (ReadableBuffer) – at least
nint32per-row half-widths (signed 16.16 fixed-point)n (int) – number of rows to compute
cx0 (int) – screen center x including lateral offset (signed 16.16 fixed-point)
dist (int) – integer world distance
cfg (ReadableBuffer) – seven
int32curve parameters, in order:f1_q20,f2_q20,amp1k_q16,amp2k_q16,world_step,curve_step,d_row_off
- class picogame.Bitmap(data: circuitpython_typing.ReadableBuffer, width: int, height: int, *, format: int = RGB565, palette: circuitpython_typing.ReadableBuffer | None = None, frames: int = 1, stride: int = 0, transparent: int | None = None)
An image atlas of one or more frames that all share one size. RGB565 pixel data and palette entries must be in the display’s transfer byte order (use
rgb565()to build colors); PAL8 pixel data are palette indices.The bitmap references the caller-provided data without copying or modifying it. The backing buffer may live in RAM or in read-only memory.
- Parameters:
data (ReadableBuffer) – RGB565 pixel data in the display’s transfer byte order, or palette indices for
PAL8width (int) – width of one frame in pixels
height (int) – height of one frame in pixels
format (int) –
RGB565(2 bytes per pixel) orPAL8(1 byte per pixel, indexingpalette)palette (ReadableBuffer) – for
PAL8, a buffer of transfer-order RGB565 colors, two bytes per entry. Every byte indatamust be a valid palette index, that is, less thanlen(palette) // 2.frames (int) – number of equal-size frames, laid out left to right in one horizontal atlas
stride (int) – distance between two rows in pixels.
0, the default, meanswidth * frames; set it explicitly to reference a sub-region of a wider image.transparent (int) – color (
RGB565) or index (PAL8) that is skipped when drawing. Defaults toNone, fully opaque.
- palette: circuitpython_typing.ReadableBuffer | None
The
PAL8palette buffer this Bitmap was built with, orNoneforRGB565. (read-only)
- class picogame.Canvas(width: int, height: int, *, transparent: int | None = None, buffer: circuitpython_typing.WriteableBuffer | None = None)
A RAM drawing surface composited as a
Scenelayer. Draw primitives into it; only redrawn areas repaint. Colors come fromrgb565().- Parameters:
width (int) – surface width in pixels
height (int) – surface height in pixels
transparent (int) – color that is skipped when the canvas is composited;
Nonemakes every pixel opaquebuffer (WriteableBuffer) – optional caller-owned pixel buffer of at least
width * height * 2bytes (for example abytearrayor a writablememoryview). The canvas draws into it instead of allocating its own.
- blit(bitmap: Bitmap, x: int, y: int, frame: int = 0, flip_x: bool = False, flip_y: bool = False) None
Copy one frame of
bitmap, selected byframe, into the canvas at(x, y), honoring the bitmap’s transparent color.
- mode7(texture: Bitmap, horizon: int, y_off: int, z: int, rx0: int, ry0: int, rsx: int, rsy: int, cam_x: int, cam_y: int) None
Fill rows below
horizonwith a perspective projection oftexture. Thepicogame_mode7helper computes the camera terms from an angle, position and field of view.- Parameters:
texture (Bitmap) – texture whose width and height are powers of two
horizon (int) – first canvas row to fill
y_off (int) – vertical offset of the projection, in rows
z (int) – camera height (signed 16.16 fixed-point)
rx0 (int) – ray x at the left column (signed 16.16 fixed-point)
ry0 (int) – ray y at the left column (signed 16.16 fixed-point)
rsx (int) – per-column ray step x (signed 16.16 fixed-point)
rsy (int) – per-column ray step y (signed 16.16 fixed-point)
cam_x (int) – camera x position (signed 16.16 fixed-point)
cam_y (int) – camera y position (signed 16.16 fixed-point)
- fill_triangles(verts: circuitpython_typing.ReadableBuffer, colors: circuitpython_typing.ReadableBuffer, n: int, x_off: int = 0, y_off: int = 0) None
Fill a batch of triangles in one call, which is faster than repeated
fill_triangle()calls for many triangles.- Parameters:
verts (ReadableBuffer) –
6 * nint16values: x0, y0, x1, y1, x2, y2 per trianglecolors (ReadableBuffer) –
nuint16colors, one per trianglen (int) – number of triangles
x_off (int) – added to every x before clipping
y_off (int) – added to every y before clipping
The offsets translate the whole batch, so one screen-space batch can be replayed into each
StripDrawview by passing the negated view origin (x_off=-vx, y_off=-vy); triangles outside the view are skipped.
- vspans(x0s: circuitpython_typing.ReadableBuffer, x1s: circuitpython_typing.ReadableBuffer, tops: circuitpython_typing.ReadableBuffer, bots: circuitpython_typing.ReadableBuffer, colors: circuitpython_typing.ReadableBuffer, n: int, x_off: int = 0, y_off: int = 0) None
Fill a batch of vertical color spans in one call. Span
icovers columnsx0s[i]throughx1s[i](exclusive) and rowstops[i]throughbots[i](exclusive) in colorcolors[i].- Parameters:
x0s (ReadableBuffer) –
nuint16left edgesx1s (ReadableBuffer) –
nuint16exclusive right edgestops (ReadableBuffer) –
nuint16top rowsbots (ReadableBuffer) –
nuint16exclusive bottom rowscolors (ReadableBuffer) –
nuint16colorsn (int) – number of spans
x_off (int) – added to every x before clipping
y_off (int) – added to every y before clipping
The offsets translate the whole batch, so one screen-space batch (for example
raycastwall runs) can be replayed into eachStripDrawview by passing the negated view origin; spans outside the view are skipped.
- road(ri0: int, tab: circuitpython_typing.ReadableBuffer, rl: circuitpython_typing.ReadableBuffer, rr: circuitpython_typing.ReadableBuffer, d05_q8: int, d07_q8: int, colors: circuitpython_typing.ReadableBuffer) None
Draw one racing-road strip from precomputed tables. A low-level interface used by the
picogame_roadhelper, which builds the tables.- Parameters:
ri0 (int) – road-table row of this surface’s row 0; negative values are sky rows
tab (ReadableBuffer) –
int16rows ofedge_w,dash_hw,wb05_q8,wb07_q8,flagsrl (ReadableBuffer) –
int16per-row left edges, as computed byroad_edges()rr (ReadableBuffer) –
int16per-row right edgesd05_q8 (int) – scroll phase (Q8 fixed-point)
d07_q8 (int) – scroll phase (Q8 fixed-point)
colors (ReadableBuffer) – six
uint16colors, in order: sky, road a, road b, rumble a, rumble b, dash
- line(x0: int, y0: int, x1: int, y1: int, color: int) None
Draw a one-pixel line between two points.
- fill_circle(cx: int, cy: int, r: int, color: int) None
Fill a circle of radius
rcentered on(cx, cy).
- ring(cx: int, cy: int, r: int, thickness: int, color: int) None
Draw a circle outline
thicknesspixels wide, grown inwards from radiusr.
- triangle(x0: int, y0: int, x1: int, y1: int, x2: int, y2: int, color: int) None
Draw a one-pixel triangle outline through the three points.
- fill_triangle(x0: int, y0: int, x1: int, y1: int, x2: int, y2: int, color: int) None
Fill a triangle. See
fill_triangles()to submit a whole batch in one call.
- ellipse(cx: int, cy: int, rx: int, ry: int, color: int) None
Draw a one-pixel ellipse outline with radii
rx/ry.
- fill_ellipse(cx: int, cy: int, rx: int, ry: int, color: int) None
Fill an ellipse with radii
rx/ry.
- fill_round_rect(x: int, y: int, w: int, h: int, r: int, color: int) None
Fill a rectangle with corners rounded to radius
r.
- frame3d(x: int, y: int, w: int, h: int, light: int, dark: int) None
Draw a one-pixel bevelled frame: top and left edges in
light, bottom and right indark, giving a raised look (swap the two for a sunken one).
- text(x: int, y: int, s: str, fg: int, font: fontio.BuiltinFont, bg: int | None = None) None
Draw
sinto the surface, rasterizing each glyph fromfontas it is drawn; no memory is retained between calls. Only ASCII characters are supported. Ifbgis given the glyph background is filled with it, otherwise it is transparent. Inside aStripDrawcallback the view is a Canvas, soview.text(...)draws text directly into the frame.
- class picogame.Display(display: busdisplay.BusDisplay, *, rgb444: bool = False)
An accelerated display backend that wraps an existing
BusDisplayand sends pixels with asynchronous, double-buffered DMA. It reuses the wrapped display’s bus, window commands and dimensions.Constructing it raises
NotImplementedErrorwhenFAST_DISPLAY_SUPPORTEDisFalse.- Parameters:
display (BusDisplay) – the display to wrap
rgb444 (bool) – drive the panel in 12-bit RGB444 instead of 16-bit RGB565, reducing bus traffic at the cost of color depth (4,096 colors instead of 65,536). The panel controller must support 12-bit color; ST7789 and ST7735 do, ILI9341 does not. See
RGB444_SUPPORTED.
- render(sprites: List[Sprite], buffer_a: circuitpython_typing.WriteableBuffer, buffer_b: circuitpython_typing.WriteableBuffer, x0: int, y0: int, x1: int, y1: int, *, background: int = 0) None
Render
spritesinto the screen region from(x0, y0)up to, but not including,(x1, y1), and send it with asynchronous DMA.buffer_aandbuffer_bare two equal strip buffers of at least(x1 - x0) * 2bytes each, used for double buffering.This method accepts sprites only. For mixed layer kinds use a
Sceneor the module-levelrender().
- class picogame.Framebuffer(buffer: circuitpython_typing.WriteableBuffer, width: int, height: int, *, native_rgb565: bool = False, rgb332: bool = False)
A RAM framebuffer render target that a
Sceneorrender()can draw into instead of aBusDisplay, for example the scanout buffer of apicodvi.Framebuffer.Constructing it raises
NotImplementedErrorwhenFRAMEBUFFER_SUPPORTEDisFalse.- Parameters:
buffer (WriteableBuffer) – caller-owned target buffer of at least
width * height * 2bytes, orwidth * heightbytes withrgb332=Truewidth (int) – target width in pixels
height (int) – target height in pixels
native_rgb565 (bool) – fill the buffer with native-endian RGB565, the format 16-bit scanout targets expect. By default the buffer holds transfer-order RGB565.
rgb332 (bool) – fill the buffer with 8-bit RGB332, the format of 8-bit scanout targets
native_rgb565andrgb332cannot both be true. Bitmaps, palettes andrgb565()values stay transfer-order RGB565 regardless of the output format.
- class picogame.Particles(capacity: int, *, size: int = 1, gravity: float = 0.0, fade: bool = False)
A pooled particle layer (small moving dots), drawn as one Scene layer. Add it to a Scene,
emit()bursts, and calltick()each frame.capacityis how many particles may be alive at once; the pool is allocated once here and never grows. Ifemit()would exceed it, the excess particles are dropped.sizeis the square side of one particle in pixels.gravityis added to each particle’s vertical speed everytick().fade=Truedims particles towards the end of their life instead of letting them vanish at full brightness.
- class picogame.Scene(display: Display | busdisplay.BusDisplay | Framebuffer, buffer_a: circuitpython_typing.WriteableBuffer | None = None, buffer_b: circuitpython_typing.WriteableBuffer | None = None, *, background: int = 0, top: int = 0, bottom: int = 0, left: int = 0, right: int = 0)
A retained-mode scene with dirty-rectangle rendering for a
Display,BusDisplayorFramebuffertarget. Add layers once (insertion order is bottom to top), mutate them each frame, then callrefresh(); only the regions reported changed are repainted.- Parameters:
display – the render target
buffer_a (WriteableBuffer) – a strip buffer, typically
display.width * STRIP_H * 2bytes. Its size sets the strip height: each strip issize // (display.width * 2)rows. Two buffers let the next strip be composited while the previous one is being sent. On aFramebuffertarget there are no strips and the buffers are unused; both default toNone.buffer_b (WriteableBuffer) – the second strip buffer, sized like
buffer_abackground (int) – color that exposed areas are cleared to
top (int) – rows at the top edge the scene never renders into
bottom (int) – rows at the bottom edge the scene never renders into
left (int) – columns at the left edge the scene never renders into
right (int) – columns at the right edge the scene never renders into
The four border insets reserve screen edges for content the application draws itself, for example with
render(); the scene renders only the inner rectangle and never repaints the border.- add(item: Sprite | Tilemap | Canvas | Particles | StripDraw | Triangles, *, fixed: bool = False) Sprite | Tilemap | Canvas | Particles | StripDraw | Triangles
Add a layer of any kind, drawn starting with the next refresh; insertion order is bottom to top. Returns the added item.
fixed=Truepins the item to the screen so it ignores the view offset set byset_view(), for example for a HUD over a scrolling world.StripDrawandTriangleslayers always draw in screen coordinates and are unaffected by bothfixedand the view offset.
- add_all(items: Iterable[Sprite | Tilemap | Canvas | Particles | StripDraw | Triangles]) None
Add several layers at once, bottom to top in iteration order.
- remove(item: Sprite | Tilemap | Canvas | Particles | StripDraw | Triangles) None
Remove a previously added item; the draw order of the rest is unchanged. The next refresh repaints the scene, so the item leaves no ghost. The item itself is untouched and may be added again later. Raises
ValueErrorif the item is not in the scene.
- set_view(ox: int, oy: int) None
Set the screen position
(ox, oy)of scene coordinate(0, 0): a scene point(x, y)is drawn at(x + ox, y + oy). Use a constant offset to center a small scene, or update it each frame to scroll, which repaints the whole render area.
- view: Tuple[int, int]
The current view offset
(ox, oy)as set byset_view(). (read-only)
- display: Display | busdisplay.BusDisplay | Framebuffer
The render target this Scene was built with. (read-only)
- class picogame.Sprite(bitmap: Bitmap, x: int = 0, y: int = 0, *, frame: int = 0, visible: bool = True, flip_x: bool = False, flip_y: bool = False)
A positioned, animatable instance of a
Bitmap.Place
bitmapwith its top-left corner at(x, y)in scene coordinates, showing the frame selected byframe. Scene coordinates follow the view offset, so the sprite moves with a scrolling world.visible=Falsecreates the sprite without drawing it, for example to pre-allocate a pool of sprites up front.flip_xandflip_ymirror the frame at draw time.- frame: int
Which frame of the bitmap’s atlas to draw, starting at 0. Stepping this animates the sprite.
- x: int
Horizontal pixel position in scene coordinates. Setting accepts a float for sub-pixel placement; reading returns the floored pixel.
- y: int
Vertical pixel position in scene coordinates. Setting accepts a float for sub-pixel placement; reading returns the floored pixel.
- scale: float
Uniform draw scale using nearest-neighbor sampling.
1.0is native size; fractional values are allowed. The anchor point stays put.
- angle: float
Rotation in degrees about the anchor;
0is unrotated. Values are stored as whole degrees. Rotation uses nearest-neighbor sampling.
- shadow: bool
Draw opaque pixels by darkening the destination instead of writing color, producing a shadow silhouette or a dimming overlay. Mutually exclusive with
flash,ditherandtint.
- flash: int
Draw opaque pixels as one solid color instead of their own, for example as a brief hit flash. Set to a color from
rgb565()to enable,0to disable. Because0disables the effect, pure black cannot be the flash color; use a near-black color instead. Mutually exclusive withshadow,ditherandtint.
- dither: int
Approximate transparency with an ordered (Bayer) dither pattern; there is no alpha blending.
0is opaque (off),8is about half transparent and16is invisible. Mutually exclusive withshadow,flashandtint.
- tint: int
Multiply opaque pixels by a color from
rgb565(), preserving the sprite’s shading (unlikeflash, which replaces it).0disables, so pure black cannot be the tint color. Mutually exclusive withshadow,flashanddither.
- transpose: bool
Transpose the frame by swapping its x and y axes. Combined with
flip_xandflip_ythis yields all 8 orthogonal orientations. Applies only atscale == 1.0andangle == 0; for rotation combined with scaling useangle. The drawn footprint swaps width and height.
- data: Any
Arbitrary per-sprite user payload for game state (default None).
- bitmap: Bitmap
The sprite’s source bitmap. Assigning a new one swaps the graphics and may change the sprite’s size; the scene repaints both the old and new bounds on the next refresh.
- anchor: Tuple[float, float]
Pivot as fractions of the bitmap size:
(0, 0)= top-left (default),(0.5, 0.5)= center,(0.5, 1.0)= bottom-center.x/ythen refer to this point, so rotating frames or swapping to a different size stays aligned. Stored in 1/256 steps.
- touch() None
Force this sprite to repaint on the next
Scene.refresh()even though none of its tracked properties (position, frame, scale, angle, bitmap) changed. Call it after mutating the bitmap’s backing buffer in place, which the dirty-region tracking cannot otherwise detect.
- overlaps(other: Sprite | Tuple[int, int] | Tuple[int, int, int, int], inset: int = 0) bool
Return
Trueif this sprite’s drawn rectangle overlapsother. Bounds are inclusive, so touching edges count as an overlap.othermay be anotherSprite, a point(x, y)or a rectangle(x1, y1, x2, y2). The rectangle accounts for anchor, scale and rotation.insetshrinks this sprite’s rectangle by that many pixels on each side.
- class picogame.StripDraw(callback: Callable[[Canvas, int, int, int, int], None], x: int = 0, y: int = 0, width: int = 0, height: int = 0, *, always_dirty: bool = True)
An immediate-mode draw layer that holds no pixel buffer. On each refresh, for every render strip overlapping its rectangle,
callback(view, vx, vy, vw, vh)is called with aCanvasview of the live strip buffer, so the callback draws primitives directly into the frame. StripDraw layers always draw in screen coordinates and ignore the scene’s view offset.(vx, vy)is the view origin in screen coordinates and(vw, vh)is its size: to draw a screen point(sx, sy), draw at(sx - vx, sy - vy)inview. The view may span the full render-region width even when the layer is narrower (the layer’s rectangle only limits which rows are drawn), so fill your own rectangle withCanvas.fill_rect()rather thanview.clear(), which fills the whole width.Moving or resizing the layer by assigning
x,y,widthorheightcan leave the old area stale; callScene.invalidate()afterwards for a clean repaint.- Parameters:
callback – called for each overlapping render strip as
callback(view, vx, vy, vw, vh)x (int) – left edge of the layer’s screen rectangle
y (int) – top edge of the layer’s screen rectangle
width (int) – rectangle width in pixels
height (int) – rectangle height in pixels
always_dirty (bool) – when
Truethe layer redraws every refresh; whenFalse, callinvalidate()after its content changes
- always_dirty: bool
When
True(the default) the rectangle repaints every frame, for animated content. WhenFalsethe layer renders once initially and then repaints only after aninvalidate()call or when overlapped by another dirty layer; callinvalidate()after each content change.
- invalidate(x: int = 0, y: int = 0, w: int = 0, h: int = 0) None
Mark the layer dirty so it repaints on the next refresh; only needed when
always_dirtyisFalse.With no arguments the whole layer repaints. To repaint one region, pass all four values as a rectangle in the view-local coordinates the draw callback uses; passing only some of them raises
ValueError. Repeated calls accumulate, and the rectangle is clamped to the layer.
- class picogame.Tilemap(tileset: Bitmap, cols: int, rows: int)
A grid of tile indices into a tileset
Bitmap, where each bitmap frame is one tile. Add it to aSceneas a background layer; setting tiles or moving the map marks only the affected area dirty.- Parameters:
- set_tile(tx: int, ty: int, value: int, *, flip_x: bool = False, flip_y: bool = False, transpose: bool = False) None
Set the tile at
(tx, ty)and mark it dirty. The keyword flags orient the tile at draw time; together they yield all 8 orientations (4 rotations times mirror), so one stored tile can serve as several. The flags can represent the remap table emitted by thepng2picogame.py --deduptool. Out-of-range writes are ignored.
- class picogame.Triangles(verts: circuitpython_typing.ReadableBuffer, colors: circuitpython_typing.ReadableBuffer)
A retained triangle batch drawn as a
Scenelayer. The batch is rasterized directly into each render strip; no per-strip Python runs and no pixel buffer is held. Triangles layers always draw in screen coordinates and ignore the scene’s view offset.For each frame: project points with
project(), write triangles into the buffers in back-to-front order, setcount, then callScene.refresh().- Parameters:
verts (ReadableBuffer) – caller-owned buffer of
int16values, six per triangle: x0, y0, x1, y1, x2, y2. Refill it in place each frame.colors (ReadableBuffer) – caller-owned buffer of
uint16colors, one per triangle