gale.animation
Animation cycles through a sequence of frames (they can be anything:
pygame.Rect regions of a spritesheet, image names, surfaces, etc.) at a
fixed time interval.
from gale.animation import Animation
# Loops forever, changing frame every 0.15 seconds.
idle_animation = Animation(["idle_0", "idle_1", "idle_2"], time_interval=0.15)
# Plays 3 times and then freezes on its last frame, invoking on_finish.
attack_animation = Animation(
["attack_0", "attack_1", "attack_2", "attack_3"],
time_interval=0.08,
loops=3,
on_finish=lambda: print("Attack animation finished"),
)
# In your update loop:
idle_animation.update(dt)
current_frame = idle_animation.get_current_frame()
# Play attack_animation again from the beginning, for instance when the
# player presses the attack button:
attack_animation.reset()
Switching between named animations
In practice, a character usually owns a dictionary of animations (one per
action) and switches between them, resetting the new one so it always
starts from its first frame. Most gameplay animations are left looping
forever (loops=None, the default), letting a state machine — see
gale.state — decide when to switch to a different
animation, instead of relying on on_finish:
from gale.animation import Animation
class Character:
def __init__(self) -> None:
self.animations = {
"idle": Animation(["idle_0", "idle_1"], time_interval=0.2),
"walk": Animation(["walk_0", "walk_1", "walk_2", "walk_3"], time_interval=0.1),
}
self.current_animation = self.animations["idle"]
def change_animation(self, animation_id: str) -> None:
new_animation = self.animations[animation_id]
if new_animation is not self.current_animation:
self.current_animation = new_animation
self.current_animation.reset()
def update(self, dt: float) -> None:
self.current_animation.update(dt)
def get_current_frame(self):
return self.current_animation.get_current_frame()