Scenes, Audio, and Tilemaps

Pygame Game Development Course

Felipe A. Moreno-Vera

πŸ”Š Audio

pygame.mixer Architecture

Pygame’s audio system has two main components:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  pygame.mixer                       β”‚
β”‚                                                     β”‚
β”‚  pygame.mixer.music      pygame.mixer.Sound         β”‚
β”‚  ─────────────────       ─────────────────          β”‚
β”‚  β€’ Streaming playback    β€’ Loaded fully in RAM      β”‚
β”‚  β€’ One track at a time   β€’ Multiple instances       β”‚
β”‚  β€’ MP3 / OGG / WAV       β€’ Short clips only         β”‚
β”‚  β€’ For background music  β€’ For sound effects        β”‚
β”‚                                                     β”‚
β”‚  Channels: 0 ──── 1 ──── 2 ──── ... ──── N-1       β”‚
β”‚  Each Sound plays on one channel at a time          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

pygame.mixer Architecture

Pygame’s audio system has two main components:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  pygame.mixer                       β”‚
β”‚                                                     β”‚
β”‚  pygame.mixer.music      pygame.mixer.Sound         β”‚
β”‚  ─────────────────       ─────────────────          β”‚
β”‚  β€’ Streaming playback    β€’ Loaded fully in RAM      β”‚
β”‚  β€’ One track at a time   β€’ Multiple instances       β”‚
β”‚  β€’ MP3 / OGG / WAV       β€’ Short clips only         β”‚
β”‚  β€’ For background music  β€’ For sound effects        β”‚
β”‚                                                     β”‚
β”‚  Channels: 0 ──── 1 ──── 2 ──── ... ──── N-1       β”‚
β”‚  Each Sound plays on one channel at a time          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Initialization

# MUST be called before pygame.init()
pygame.mixer.pre_init(
    frequency = 44100,   # Sample rate (Hz). 44100 = CD quality
    size      = -16,     # Bit depth. -16 = 16-bit signed
    channels  = 2,       # 1 = mono, 2 = stereo
    buffer    = 512      # Smaller = less latency, more CPU
)
pygame.init()

Background Music

# Load and stream (file stays on disk, not loaded into RAM)
pygame.mixer.music.load("music/background.ogg")
pygame.mixer.music.set_volume(0.7)    # 0.0 to 1.0
pygame.mixer.music.play(loops=-1)     # -1 = infinite loop
pygame.mixer.music.play(loops=3)      # Play 3 times

# Control
pygame.mixer.music.pause()
pygame.mixer.music.unpause()
pygame.mixer.music.stop()
pygame.mixer.music.fadeout(2000)      # Fade out over 2000ms

# Query state
pos_ms = pygame.mixer.music.get_pos()   # Current position in ms
is_playing = pygame.mixer.music.get_busy()

Sound Effects

# Load fully into memory (use for short clips)
jump_sfx = pygame.mixer.Sound("sfx/jump.wav")
jump_sfx.set_volume(0.8)

# Play β€” returns the Channel it plays on
channel = jump_sfx.play()             # Any free channel
channel = jump_sfx.play(loops=2)      # Play 3 times total
channel = jump_sfx.play(maxtime=500)  # Stop after 500ms

# If no free channel is available, returns None
if channel is None:
    print("No free channel!")

Channels

Pygame has N mixer channels (default 8). Each Sound plays on one channel at a time.

pygame.mixer.set_num_channels(16)

# Reserve a specific channel for a category
music_ch = pygame.mixer.Channel(7)
music_ch.play(bg_sound, loops=-1)
music_ch.set_volume(0.5)

# Stereo panning: set_volume(left, right)
music_ch.set_volume(0.8, 0.2)   # Panned left

# Query
music_ch.get_busy()             # Is something playing?
music_ch.stop()
music_ch.pause()
music_ch.fadeout(1000)

Channels

Spatial audio β€” stereo pan by position
=============================================
  x position     pan      left vol     right vol
  --------------------------------------------
  x=0             -1.00    1.0           0.0
  x=150           -0.67    1.0           0.33
  x=300           -0.33    1.0           0.67
  x=450           +0.00    1.0           1.0
  x=600           +0.33    0.67          1.0
  x=750           +0.67    0.33          1.0
  x=900           +1.00    0.0           1.0

Volume Hierarchy

# Three independent volume levels that multiply together
# Final volume = master * category * sound

# 1. Per-sound volume
sfx.set_volume(0.8)

# 2. Per-channel volume
channel.set_volume(0.7)

# 3. No true "master" in pygame β€” simulate with a multiplier
master_volume = 0.5

def play_sfx(sound, master=1.0):
    ch = sound.play()
    if ch:
        current = sound.get_volume()
        ch.set_volume(current * master)

Audios β€” Summary

  • pygame.mixer.pre_init() must be called before pygame.init()
  • music streams from disk β€” use for long background tracks
  • Sound loads fully into RAM β€” use for short SFX only
  • Each Sound plays on a Channel; reserve channels for categories
  • Stereo panning: channel.set_volume(left, right)
  • Distance attenuation: volume = max(0, 1 - distance / max_dist)