
In this tutorial, you'll learn how to create an animated sprite using a spritesheet in Python. Spritesheet animation is the heart and soul of most 2d games. We'll build a program that cycles through animation frames and lets users switch between different animation states by clicking.
We'll create a program that:
Start by importing tkinter for the GUI and PIL for image processing:
import tkinter as tk
from PIL import Image, ImageTktkinter provides the window and canvas, while PIL helps us load and manipulate images.
You can download the full source code here: spritesheet.py or copy-paste from steps below.
Define a class to organize our sprite animator:
class SpriteAnimator:
def __init__(self, root):
self.root = root
self.root.title("Spritesheet Animator")The __init__ method initializes our animator with a tkinter root window.
Load your spritesheet image and set up animation parameters:
# Load spritesheet
self.spritesheet = Image.open("spritesheet.png")
# Animation parameters
self.frame_width = 60
self.frame_height = 60
self.num_frames = 20
self.num_rows = 5
self.current_frame = 0
self.current_row = 0 # 0-4 for five rowsCut the spritesheet into individual frames using the crop() method:
# Extract all frames from all rows
self.frames = [] # List of lists: frames[row][frame]
for row in range(self.num_rows):
row_frames = []
for i in range(self.num_frames):
frame = self.spritesheet.crop((
i * self.frame_width, # left
row * self.frame_height, # top
(i + 1) * self.frame_width, # right
(row + 1) * self.frame_height # bottom
))
row_frames.append(ImageTk.PhotoImage(frame))
self.frames.append(row_frames)How it works:
Set up a tkinter canvas to display the sprite:
# Create canvas
self.canvas = tk.Canvas(root, width=self.frame_width, height=self.frame_height)
self.canvas.pack()
# Display first frame
self.sprite = self.canvas.create_image(0, 0, anchor=tk.NW, image=self.frames[0][0])The canvas acts as a drawing surface. We place the first frame at position (0,0) with anchor=tk.NW (northwest/top-left corner).
Bind a mouse click to switch animation rows:
# Bind click event
self.canvas.bind("<Button-1>", self.on_click)
# Later in the class:
def on_click(self, event):
# Cycle through rows 0 → 1 → 2 → 3 → 4 → 0
self.current_row = (self.current_row + 1) % self.num_rowsThe modulo operator % ensures the row number wraps back to 0 after reaching 4.
Create a method that continuously updates the displayed frame:
def animate(self):
# Get current frame from current row
current_image = self.frames[self.current_row][self.current_frame]
# Update sprite image
self.canvas.itemconfig(self.sprite, image=current_image)
# Move to next frame
self.current_frame = (self.current_frame + 1) % self.num_frames
# Schedule next frame (60 FPS = ~16.67ms per frame)
self.root.after(17, self.animate)Key concepts:
Call the animate method in the constructor and start the application:
# In __init__, after setting up canvas:
self.animate()
# At the bottom of the file:
if __name__ == "__main__":
root = tk.Tk()
app = SpriteAnimator(root)
root.mainloop()mainloop() keeps the window open and responsive to events.
We're using the spritesheet from my game Goldmine:

Dimensions: 1200×300 pixels (20 frames × 60px wide, 5 rows × 60px tall)Next tutorial: Animated plasma effect