pyxen.Entity
An Entity is a lightweight handle — a container for components.
For an introduction to the entity-component system, see Entities and Components.
Built-in Components
| Component | Access |
|---|---|
| Transform | e.x, e.y, e.rotation, e.scale |
| Sprite | e.sprite, e.color |
| Animation | e.animation |
| Sound | e.sound |
| Music | e.music |
| GridBody | e.body |
| GridMap | e.map |
| Node | e.parent, e.children |
| Layer | e.layer |
| Name | e.name |
| Camera | e.camera |
Transform
e.x = 100
e.y = 50
e.rotation = 45
e.scale = (2, 2)
Reading scale returns a Vector2:
s = e.scale
print(s.x, s.y)
Sprite
e.sprite = sprite
e.color = (1.0, 0.5, 0.5, 1.0)
Reading color returns a Color:
c = e.color
print(c.r, c.g, c.b, c.a)
Sprite Animation
When a sprite is created with the animation parameter, the engine plays the animation automatically. You can read the animation state via e.animation:
player.sprite = Sprite("hero", animation="walk")
Properties
| Property | Type | Description |
|---|---|---|
name | str | Name of the current animation clip |
frame | int | Current frame index within the clip |
playing | bool | True if the animation is actively playing |
finished | bool | True if a one-shot animation has completed |
anim = player.animation
if anim:
print(anim.name) # "walk"
print(anim.frame) # 2
print(anim.playing) # True
print(anim.finished) # False
If no animation is active, e.animation returns None:
player.sprite = Sprite("hero", tile=(0, 0, 16, 16))
print(player.animation) # None
Cancelling
Set e.animation to None to stop playback:
player.animation = None
Assigning a new sprite automatically cancels any existing animation.
One-shot animations
Use loop=False for animations that play once:
player.sprite = Sprite("hero", animation="attack", loop=False)
def update():
if player.animation and player.animation.finished:
player.sprite = Sprite("hero", animation="idle")
Tweens
Tweens smoothly animate an entity’s properties over time. The engine handles interpolation automatically — no per-frame code needed.
entity.tween()
# Named property form
entity.tween("x", to=200, duration=1.0)
entity.tween("alpha", to=0, duration=0.5, ease="out_quad")
# Keyword shorthand — animate multiple properties at once
entity.tween(x=200, y=100, duration=1.0, ease="out_quad")
| Parameter | Type | Default | Description |
|---|---|---|---|
property | str | — | Property name (positional, or use keyword form) |
to | float | — | Target value |
by | float | — | Relative offset (alternative to to) |
start | float | current | Start value (defaults to the property’s current value) |
duration | float | 1.0 | Duration in seconds |
ease | str | "linear" | Easing function name |
Use to for an absolute target, or by for a relative offset:
entity.tween("x", to=200, duration=1.0) # move to x=200
entity.tween("x", by=50, duration=0.5) # move 50 pixels to the right
Use start to override the starting value:
entity.tween("x", to=200, start=0, duration=1.0) # always start from 0
Tweennable Properties
| Component | Properties |
|---|---|
| Transform | x, y, rotation, sx, sy |
| Sprite | r, g, b, alpha |
| Camera | zoom |
Easing Functions
| Name | Curve |
|---|---|
linear | Constant speed (default) |
in_quad | Slow start, accelerating |
out_quad | Fast start, decelerating |
in_out_quad | Slow start and end |
in_cubic | Slower start than quad |
out_cubic | Faster start than quad |
in_out_cubic | Smooth slow start and end |
in_expo | Very slow start, explosive acceleration |
in_out_expo | Explosive middle |
out_expo | Very fast start, gentle stop |
in_back | Pulls back before moving forward |
out_back | Overshoots target, then settles |
in_out_back | Pull back and overshoot |
in_elastic | Elastic wind-up |
out_elastic | Elastic overshoot and bounce |
in_out_elastic | Elastic on both ends |
entity.tweens.cancel()
Cancel tweens on an entity. Pass a property name to cancel a single tween, or call with no arguments to cancel all tweens. The value freezes at its current position.
entity.tweens.cancel("x") # cancel one property
entity.tweens.cancel() # cancel all
Conflict Resolution
Starting a new tween on the same entity and property replaces the previous one. Tweens on different properties run independently.
entity.tween("x", to=100, duration=1.0)
entity.tween("x", to=200, duration=0.5) # replaces the first tween
entity.tween("y", to=50, duration=1.0) # runs alongside the x tween
Tweens on destroyed entities are automatically cleaned up.
Starting an animate() on a property cancels any active tween() on that property, and vice versa.
Animations
Continuous animations that run indefinitely — sine-wave oscillation (pulsing, breathing, bobbing) and constant-rate spinning.
entity.animate() — Oscillate
Oscillate a property around a center value with a sine wave.
entity.animate("sx", "sy", by=0.15, speed=6.0) # coin pulse
entity.animate("alpha", by=0.3, center=0.7, speed=4.0) # flicker 0.4–1.0
The value follows: center + sin(elapsed * speed) * by
entity.animate() — Spin
Accumulate a value at a constant rate. Omit by= to use spin mode.
entity.animate("rotation", speed=180) # 180°/sec clockwise
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
*props | str | — | One or more property names (positional) |
by | float | — | Amplitude (oscillate mode). Omit for spin. |
center | float | current | Center value for oscillation |
speed | float | 1.0 | Angular frequency (oscillate) or units/sec (spin) |
Same 10 properties as tweens: x, y, rotation, sx, sy, r, g, b, alpha, zoom.
entity.animations.cancel()
Cancel animations on an entity. Pass a property name to cancel a single animation, or call with no arguments to cancel all animations.
entity.animations.cancel("rotation") # cancel one property
entity.animations.cancel() # cancel all
Parent / Children
child.parent = parent
Access children:
for c in parent.children:
print(c.name)
Get child count:
parent.children.count
Custom Components
Components are created by assigning:
- A dictionary — structured component
- A boolean — marker component
e.cell = {
'row': 0,
'col': 0
}
The first assignment creates the schema. Field types are inferred and the schema becomes fixed — you cannot add new fields later.
Using Components in Systems
for cell in world.all("cell"):
...
See: pyxen.world.all()
Marker Components
e.alive = True
Markers store no data — they only indicate presence. Query them like normal components:
for e in world.all("alive"):
...
Accessing Component Fields
e.cell.row
e.cell.col
e.cell.row = 5
Supported Field Types
| Python Type | Stored As |
|---|---|
int | 32-bit integer |
float | 32-bit float |
bool | Boolean |
str | Fixed string (max 31 chars) |
Entity | Entity reference |
Invalid types raise:
TypeError: invalid value type in dict
Schema Rules
- Max component size: 256 bytes
- Strings max: 31 characters
- Dict keys must be strings
- Cannot add new fields after schema creation
e.cell = {'row': 0}
e.cell = {'row': 0, 'new_field': 5}
ValueError: cannot create new fields after schema is complete
It’s valid to omit fields on subsequent assignments — they default to 0, 0.0, False, "", etc.
Checking for a Component
e.has("cell")
Returns True if the entity has the component, False otherwise.
This works for both custom and built-in component names:
e.has("sprite") # True if the entity has a sprite
e.has("body") # True if the entity has a grid body
Querying Descendants
entity.all(*components, without=(), include_self=False)
Returns an iterator over all descendants of the entity (depth-first through the scene graph hierarchy) that match the given component filter.
Works exactly like world.all(), but scoped to a subtree instead of the entire world.
# All descendants with "enemy" component
for e in parent.all("enemy"):
...
# With exclusion
for e in parent.all("enemy", without=("boss",)):
...
# Include the parent entity itself
for e in parent.all("tag", include_self=True):
...
| Parameter | Type | Default | Description |
|---|---|---|---|
*components | str | — | Component names to require |
without | tuple | () | Component names to exclude |
include_self | bool | False | Whether to include the entity itself |
Both built-in and custom component names are supported.
Removing Components
Remove a component from an entity using del or by assigning None:
# Both are equivalent:
del entity.health
entity.health = None
After removal, entity.has("health") returns False and the entity no longer matches queries for that component.
e = world.spawn()
e.health = {'hp': 100}
del e.health
e.has("health") # False
# world.all("health") won't include e
You can re-add a component after removing it:
del e.health
e.health = {'hp': 50} # works fine
Built-in components
All built-in components can be removed:
del e.sprite # clears sprite data
del e.body # clears physics body
del e.camera # removes camera
del e.text # removes text
del e.sound # removes sound
del e.music # removes music
del e.map # removes grid map
Sprite and body are zero-initialized (the entity still has the storage, but the data is empty). Camera, text, sound, music, and map are fully erased.
Markers
e.enemy = True
del e.enemy # or: e.enemy = None
e.has("enemy") # False
Entity Lifecycle
- Created with
world.spawn() - Modified via component assignment
- Components removed with
delor= None - Destroyed with
world.destroy()