Sprites & Rendering
Pyxen renders your game using a Metal-backed 2D renderer. Everything visible on screen is an entity with a Sprite component.
Sprites
A sprite tells the engine what to draw for an entity. You create one by referencing an image from your project:
player = world.spawn(sprite=Sprite("hero"))
The string "hero" refers to an image named hero in your project’s assets.
Tile sheets
Most games use tile sheets — a single image containing many frames or tiles arranged in a grid. You select a region of the image with the tile parameter:
Sprite("characters", tile=(0, 0, 16, 16)) # first tile
Sprite("characters", tile=(16, 0, 16, 16)) # second tile
Sprite("characters", tile=(0, 16, 16, 16)) # tile on second row
The four values are (x, y, width, height) in pixels, measured from the top-left of the image.
Sprite animations
If you create named animations in the sprite editor, you can play them directly:
player = world.spawn(
sprite=Sprite("hero", animation="walk"),
x=100, y=50
)
The engine reads the animation’s frame sequence and FPS from the sprite’s metadata and advances frames automatically. To switch animations, assign a new sprite:
player.sprite = Sprite("hero", animation="jump")
For one-shot animations (like an attack or death), set loop=False and check when it finishes:
player.sprite = Sprite("hero", animation="attack", loop=False)
def update():
if player.animation and player.animation.finished:
player.sprite = Sprite("hero", animation="idle")
The e.animation component gives you read-only access to the current state: .name, .frame, .playing, .finished. See the Entity reference for details.
You can also animate manually by changing the tile each frame:
def update():
frame = time.frame % 4
player.sprite = Sprite("hero", tile=(frame * 16, 0, 16, 16))
Pivot point
By default, a sprite is drawn from its top-left corner. You can change the pivot point to control where the sprite is anchored:
Sprite("hero", tile=(0, 0, 16, 16), pivot=(8, 8))
This centers the sprite on the entity’s position. The pivot is in pixel coordinates relative to the tile. Setting the pivot to the center of the tile is the most common choice — it makes rotation and scaling behave intuitively.
Color tinting
You can tint any entity’s sprite by setting its color:
player.color = (1.0, 0.5, 0.5, 1.0) # reddish tint
Color is an RGBA tuple with values from 0.0 to 1.0. White (1, 1, 1, 1) means no tinting. You can use the alpha channel for transparency:
ghost.color = (1, 1, 1, 0.5) # 50% transparent
You can also animate color and alpha smoothly using tweens:
ghost.tween("alpha", to=0, duration=0.5, ease="out_quad") # fade out
For continuous effects like pulsing or flickering, use animations:
ghost.animate("alpha", by=0.3, center=0.7, speed=4.0) # flicker
Camera
The camera controls what part of the world is visible. Create one by spawning an entity with a Camera component:
cam = world.spawn(camera=Camera(), x=160, y=90)
Move the camera to follow the player:
def update():
cam.x = player.x
cam.y = player.y
The camera supports zoom:
cam.camera.zoom = 2.0 # zoom in 2x
You can animate zoom smoothly with a tween:
cam.tween("zoom", to=2.0, duration=0.5, ease="out_quad")
Resolution
Pyxen games run at a default resolution of 320x180 pixels. This is a deliberate choice — low resolution makes pixel art look sharp and keeps rendering fast. The engine scales the output to fill the screen.
Text
The Text component renders bitmap text. Create a text entity like this:
label = world.spawn(text=Text("Hello, world!"))
By default, text uses the built-in pixel font. To use a custom font created with the Font Editor:
title = world.spawn(text=Text("Game Over", font="myfont"))
Update text at runtime by modifying the text property:
def update():
score_label.text = Text(f"Score: {score}")
See the Text reference for the full API.
Draw order
Entities are drawn in this order:
- Layer — lower layers draw first (layer 0 behind layer 1)
- Depth — within a layer, determined by scene graph position
- Entities without sprites are not drawn but still exist in the world
See Scene Graph for more on layers and depth.