📝 Worksheet← Lesson
BitWithBite
Pygame Mastery · Quick Reference

Animation Cheat Sheet

Pygame Mastery
In one line: Frame animation cycles through a list of images at the right rate — measured in elapsed time, not loop iterations — to create walking, running, jumping, attacking and idle motion, wrapped in a reusable Animation Manager.

Key Ideas

1Frame Animation Fundamentals. Animation is just a list of frames swapped at a fixed rate. Always advance based on elapsed time (dt), never once per loop iteration, so speed stays consistent across machines.
2Movement Cycles. Walk, run, jump and dash each need their own frame list and speed. Group them in a dict keyed by state name so switching is one lookup, not if/elif chains.
3Attack, Death & Idle. Attack and death are one-shot (play once, don't loop); idle loops forever and is the default when nothing else is happening.
4Getting Timing Right. Advance by accumulated milliseconds, not per-frame ticks, and only reset frame_index when the animation NAME changes — not on every update.
5Reusable Animation Manager. Wrap timer, frame index and loop-flag logic in one class (play(), update(dt), get_frame()) that any sprite can own instead of duplicating timer code.

Core API

anim_timer += dt; if anim_timer >= ANIM_SPEED: advance frame
frame_index = (frame_index + 1) % len(frames)
AnimationManager.play(name, loop=True)
AnimationManager.update(dt) / .get_frame()

Common Mistakes

Advancing frame_index once per game-loop iteration
Advance based on elapsed dt milliseconds instead — FPS varies by machine
Resetting frame_index on every state check
Only reset it when the animation NAME actually changes
Looping death/attack animations back to frame 0
Hold the last frame or fire an event instead — they're one-shot
frame_indextime (dt accumulated)
frame_index climbs each ANIM_SPEED interval, then wraps back to 0 — a sawtooth, not a smooth ramp.