Pygame Cheat Sheet
Overview
Pygame is a free, open-source Python library designed for writing video games and multimedia applications. Built on top of the SDL (Simple DirectMedia Layer) library, it provides Python bindings for graphics rendering, sound playback, input handling, and event management. Pygame is widely used for game prototyping, educational projects, and indie game development due to its simplicity and Python’s readable syntax. It handles the low-level details of interacting with display hardware, audio devices, and input peripherals.
Pygame supports 2D graphics with hardware-accelerated rendering, sprite groups for efficient game object management, collision detection, image loading and transformation, font rendering, and mixer-based audio playback. While not designed for high-performance 3D games, it excels at 2D game development, simulations, and interactive applications. The library runs on Windows, macOS, and Linux, and its straightforward API makes it an excellent choice for learning game development concepts.
Installation
# Install via pip
pip install pygame
# Install specific version
pip install pygame==2.6.0
# Install development version
pip install pygame --pre
# Verify installation
python -c "import pygame; print(pygame.ver)"
# Install with virtual environment (recommended)
python -m venv gamedev
source gamedev/bin/activate # Linux/macOS
# gamedev\Scripts\activate # Windows
pip install pygame
# Additional dependencies (Linux)
sudo apt-get install python3-dev libsdl2-dev libsdl2-image-dev \
libsdl2-mixer-dev libsdl2-ttf-dev
# Run example games
python -m pygame.examples.aliens
Basic Game Loop
import pygame
import sys
# Initialize
pygame.init()
# Constants
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
FPS = 60
# Setup
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("My Game")
clock = pygame.time.Clock()
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# Game loop
running = True
while running:
# Event handling
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
# Update
# (game logic here)
# Draw
screen.fill(BLACK)
# (draw calls here)
# Flip display
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
sys.exit()
Drawing Primitives
# Rectangle
pygame.draw.rect(screen, RED, (x, y, width, height))
pygame.draw.rect(screen, RED, (100, 100, 50, 30), 2) # 2px border
# Circle
pygame.draw.circle(screen, BLUE, (400, 300), 50) # Filled
pygame.draw.circle(screen, BLUE, (400, 300), 50, 3) # Outline
# Line
pygame.draw.line(screen, WHITE, (0, 0), (800, 600), 2)
# Polygon
points = [(300, 50), (450, 200), (150, 200)]
pygame.draw.polygon(screen, GREEN, points)
# Ellipse
pygame.draw.ellipse(screen, RED, (200, 150, 100, 50))
# Arc
import math
pygame.draw.arc(screen, WHITE, (200, 200, 100, 100), 0, math.pi, 2)
Input Handling
# Event-based input (in event loop)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
player.jump()
elif event.key == pygame.K_LEFT:
player.move_left()
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
player.stop()
elif event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # Left click
pos = event.pos
shoot(pos)
elif event.type == pygame.MOUSEMOTION:
mouse_x, mouse_y = event.pos
# Polling-based input (continuous)
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
player_x -= speed
if keys[pygame.K_RIGHT]:
player_x += speed
if keys[pygame.K_UP]:
player_y -= speed
if keys[pygame.K_DOWN]:
player_y += speed
# Mouse state
mouse_pos = pygame.mouse.get_pos()
mouse_buttons = pygame.mouse.get_pressed()
if mouse_buttons[0]: # Left button held
pass
Sprites and Groups
class Player(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.image.load("player.png").convert_alpha()
self.rect = self.image.get_rect(center=(x, y))
self.speed = 5
self.health = 100
self.velocity_y = 0
def update(self):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
self.rect.x -= self.speed
if keys[pygame.K_RIGHT]:
self.rect.x += self.speed
# Gravity
self.velocity_y += 0.5
self.rect.y += self.velocity_y
# Screen bounds
self.rect.clamp_ip(screen.get_rect())
def jump(self):
self.velocity_y = -12
class Enemy(pygame.sprite.Sprite):
def __init__(self, x, y):
super().__init__()
self.image = pygame.Surface((32, 32))
self.image.fill(RED)
self.rect = self.image.get_rect(center=(x, y))
self.speed = 2
def update(self):
self.rect.x -= self.speed
if self.rect.right < 0:
self.kill()
# Sprite groups
all_sprites = pygame.sprite.Group()
enemies = pygame.sprite.Group()
bullets = pygame.sprite.Group()
player = Player(400, 300)
all_sprites.add(player)
for i in range(5):
enemy = Enemy(800 + i * 100, 300)
all_sprites.add(enemy)
enemies.add(enemy)
# In game loop
all_sprites.update()
all_sprites.draw(screen)
# Collision detection
hits = pygame.sprite.spritecollide(player, enemies, False)
for hit in hits:
player.health -= 10
# Group vs group collision
bullet_hits = pygame.sprite.groupcollide(bullets, enemies, True, True)
Images and Surfaces
# Load image
image = pygame.image.load("sprite.png").convert_alpha()
# Scale image
scaled = pygame.transform.scale(image, (64, 64))
doubled = pygame.transform.scale2x(image)
# Rotate image
rotated = pygame.transform.rotate(image, 45) # degrees
# Flip image
flipped = pygame.transform.flip(image, True, False) # horizontal, vertical
# Create surface
surface = pygame.Surface((100, 100))
surface.fill(GREEN)
surface.set_alpha(128) # Semi-transparent
# Blit (draw surface onto another)
screen.blit(image, (x, y))
screen.blit(image, image.get_rect(center=(400, 300)))
# Spritesheet extraction
def load_spritesheet(filename, frame_width, frame_height):
sheet = pygame.image.load(filename).convert_alpha()
frames = []
for y in range(0, sheet.get_height(), frame_height):
for x in range(0, sheet.get_width(), frame_width):
frame = sheet.subsurface((x, y, frame_width, frame_height))
frames.append(frame)
return frames
Text and Fonts
# System font
font = pygame.font.SysFont("Arial", 36)
# Custom font
font = pygame.font.Font("fonts/custom.ttf", 24)
# Render text
text_surface = font.render("Score: 100", True, WHITE)
text_rect = text_surface.get_rect(center=(400, 50))
screen.blit(text_surface, text_rect)
# Anti-aliased text with background
text_surface = font.render("Game Over", True, RED, BLACK)
Sound and Music
# Initialize mixer
pygame.mixer.init(frequency=44100, size=-16, channels=2, buffer=512)
# Sound effects
shoot_sound = pygame.mixer.Sound("sounds/shoot.wav")
explosion_sound = pygame.mixer.Sound("sounds/explosion.wav")
shoot_sound.set_volume(0.5)
shoot_sound.play()
# Background music
pygame.mixer.music.load("music/background.mp3")
pygame.mixer.music.set_volume(0.3)
pygame.mixer.music.play(-1) # -1 = loop forever
pygame.mixer.music.pause()
pygame.mixer.music.unpause()
pygame.mixer.music.stop()
Configuration
# Display modes
screen = pygame.display.set_mode((800, 600)) # Windowed
screen = pygame.display.set_mode((0, 0), pygame.FULLSCREEN) # Fullscreen
screen = pygame.display.set_mode((800, 600), pygame.RESIZABLE) # Resizable
screen = pygame.display.set_mode((800, 600), pygame.SCALED) # Auto-scale
# Window settings
pygame.display.set_caption("My Game")
pygame.display.set_icon(pygame.image.load("icon.png"))
# Framerate
clock = pygame.time.Clock()
dt = clock.tick(60) / 1000.0 # Delta time in seconds
# Cursor
pygame.mouse.set_visible(False) # Hide cursor
pygame.mouse.set_cursor(pygame.SYSTEM_CURSOR_CROSSHAIR)
Advanced Usage
# Camera/scrolling system
class Camera:
def __init__(self, width, height):
self.rect = pygame.Rect(0, 0, width, height)
self.width = width
self.height = height
def apply(self, entity):
return entity.rect.move(-self.rect.x, -self.rect.y)
def update(self, target):
x = target.rect.centerx - SCREEN_WIDTH // 2
y = target.rect.centery - SCREEN_HEIGHT // 2
x = max(0, min(x, self.width - SCREEN_WIDTH))
y = max(0, min(y, self.height - SCREEN_HEIGHT))
self.rect = pygame.Rect(x, y, SCREEN_WIDTH, SCREEN_HEIGHT)
# Particle system
class Particle:
def __init__(self, x, y):
self.x = x
self.y = y
self.vx = random.uniform(-2, 2)
self.vy = random.uniform(-5, -1)
self.lifetime = random.randint(20, 40)
self.color = random.choice([RED, (255, 165, 0), (255, 255, 0)])
self.size = random.randint(2, 6)
def update(self):
self.x += self.vx
self.y += self.vy
self.vy += 0.1 # gravity
self.lifetime -= 1
self.size = max(0, self.size - 0.1)
def draw(self, surface):
if self.lifetime > 0:
pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), int(self.size))
# Tilemap loading
def load_tilemap(filename, tile_size):
tiles = []
with open(filename) as f:
for y, line in enumerate(f.readlines()):
for x, char in enumerate(line.strip()):
if char == '1':
rect = pygame.Rect(x * tile_size, y * tile_size, tile_size, tile_size)
tiles.append(rect)
return tiles
Troubleshooting
| Issue | Solution |
|---|---|
| ”No module named pygame” | Run pip install pygame in correct environment |
| Display not showing | Ensure pygame.display.flip() or update() called each frame |
| Image load error | Use absolute path or verify file exists; call .convert() after load |
| Sound not playing | Call pygame.mixer.init() before loading sounds |
| Game runs at different speeds | Use delta_time from clock.tick() for movement calculations |
| Transparent images not working | Use .convert_alpha() and ensure PNG has alpha channel |
| Sprite collision inaccurate | Use pygame.sprite.collide_mask for pixel-perfect collision |
| High CPU usage | Add clock.tick(60) to limit frame rate |
| Fullscreen resolution wrong | Use pygame.SCALED flag or query display info first |
| Event queue overflow | Always call pygame.event.get() or pygame.event.pump() each frame |