Animation Tutorial
This tutorial shows how to author clips and controllers in the AxisPy editor UI, attach them to an entity, and drive animations from scripts using triggers and state changes.
What you will build
A looping Idle and Run clip from a spritesheet.
A controller with states and transitions.
An entity that plays Idle on start and switches to Run while a key is held.
Requirements
SpriteRendererto draw frames.AnimatorComponentto manage state/frames.Runtime already includes
AnimationSystem.
Create clips in the Editor (Clip Editor)
Open the Animation Editor tab
Main Window → “Animation Editor” tab (or Asset Manager → right‑click a clip → Open Animation Clip).
Create a new clip file (.anim)
Asset Manager → right‑click a folder → “New Animation Clip”.
Name it e.g.
idle.animorrun.anim.
Configure the clip
In the Clip Editor:
Set
FPSandLoop.Choose
Type: - Spritesheet: setsheet_path,frame_width/height,marginandspacing. - Image Sequence: addimage_paths(one per frame).Preview updates live; click “Save” to write the .anim via the editor.
Create a controller (.actrl) and add states/transitions
Create controller
Asset Manager → right‑click a folder → “New Animation Controller”. Name it e.g.
player.actrl.Double‑click to open it in the Controller view.
Add states (nodes) and assign clips
Click “Add Node”. Select the node to edit its properties.
Click the “…” next to “Clip (.anim)” and choose your clip (e.g.
idle.anim).The node’s preview plays in the right panel.
Repeat for
run.anim.
Set default state
Draw a transition from
Rootto your default node (double‑click a node, then click the target node). The editor stores a single Root→Default edge.
Add transitions between states
Double‑click a node, then click another to connect.
Select the arrow (edge) to edit properties: -
Trigger: a string (e.g.start_run) you’ll fire from scripts. -On Finish: when checked, transition fires after the source clip reaches its last frame (non‑looping).Save the controller (toolbar “Save”).
Attach to an entity (Inspector)
Ensure the entity has a
Transformand aSpriteRenderer.Add
AnimatorComponent. - Setcontroller_pathto your.actrl(relative to the project folder works; the engine also resolves by controller/clip folder andAXISPY_PROJECT_PATH). - Optional: setplay_on_startandspeed.
Drive animation from a script (Script Editor)
Use the script editor tab to add logic. The AnimationSystem will hot‑reload controller/clip files while the game runs.
from core.components import AnimatorComponent
import pygame
from core.input import Input
class PlayerAnim:
def on_start(self):
self.anim = self.entity.get_component(AnimatorComponent)
# Optionally force a state at startup
if self.anim and self.anim.controller:
default = self.anim.controller.get_default_state()
if default:
self.anim.play(default, restart=True)
def on_update(self, dt: float):
if not self.anim:
return
# Fire a trigger defined on a transition from the current state
if Input.get_key(pygame.K_LSHIFT):
self.anim.set_trigger("start_run")
else:
self.anim.set_trigger("stop_run")
Control API quick reference
anim.play(state_name, restart=False)— jump to a node by name.anim.set_trigger(name)— enqueue a trigger; consumed by the system if a matching transition exists.anim.pause()/anim.resume()/anim.stop(reset=False)— playback control.anim.speed— global speed multiplier (affects FPS).anim.current_state/anim.is_playing/anim.is_paused— status.
How transitions resolve (runtime)
On each frame, the system: - Reloads controller if the file changed (hot reload). - If no current state, uses the controller’s Root→Default. - Checks transitions out of the current state. If a transition has
triggerand that trigger was set (and not yet consumed), it switches immediately. - When a non‑looping clip reaches its last frame, any transition from the current state withon_finishis taken. - The current frame is assigned to the entity’sSpriteRenderer.
Tips and troubleshooting
If you don’t see frames: ensure the entity has a SpriteRenderer, and your .anim clip resolves its images/spritesheet correctly (paths are project‑relative in the editor; engine resolves via controller/clip folder, project root, or CWD).
To flip sprites, use negative
Transformscale values.To keep multiple triggers around, call
set_triggereach frame you need them. Triggers are “consumed” the next time the system sees a matching transition.Editor previews do not require the game to be running; runtime playback will match FPS/loop/segment settings.