Module 2 of 20 Phase: Pygame Foundations

Getting Started with Pygame

This is the single most important module in the course. You'll install and import Pygame, open your first window, and write a correct, complete game loop — the exact skeleton every game you build from here on will be built inside. Get this right, and every future module becomes easier.

🪟
14 Topics
Covered in this module
⏱️
2–3 Hours
Estimated time
🟢
Beginner
Difficulty
🎮
Pygame
Primary library
Section 1

What Is Pygame, and Getting It Installed

Pygame is a free, open-source Python library built on top of SDL (Simple DirectMedia Layer) that gives you everything a 2D game needs: a window to draw in, image and sound loading, keyboard/mouse/controller input, collision helpers, and drawing primitives. It's been the go-to library for learning game development in Python for over two decades because it's simple to install, well-documented, and lets you see results in minutes rather than hours.

If you haven't already, install it with pip from your terminal. Then confirm the install worked by importing pygame in a new file — if no error appears, you're ready to build.

terminal
pip install pygame
check_install.py
import pygame
print(pygame.ver)   # prints the installed Pygame version, e.g. "2.6.0"
💡
If pip install pygame fails: make sure Python was added to PATH during installation (Module 1), and try python -m pip install pygame instead — this forces pip to install for the exact Python interpreter you're running.
Section 2

Initializing Pygame and Creating the Window

Before you can use any Pygame feature, you must call pygame.init() — this starts up all of Pygame's internal modules (display, sound, fonts, etc.) in one call. Next, pygame.display.set_mode((width, height)) opens the game window and returns a Surface object — think of a Surface as a rectangular canvas of pixels you can draw on. This particular Surface is special: it's the display surface, the one that actually gets shown on screen. You can also set the text in the window's title bar with pygame.display.set_caption().

window.py
import pygame

pygame.init()                                  # start up all Pygame modules

WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))   # the display surface
pygame.display.set_caption("My First Pygame Window")
🚀
pygame.init()
Initializes every Pygame subsystem at once (display, mixer, font). Always call this first, before touching any other Pygame function.
🖼️
The Display Surface
set_mode() returns a Surface — a grid of pixels in memory. Anything you draw onto this specific surface appears on screen once the display updates.
Section 3

The Game Loop, Clock, and Frame Rate

A window that opens and instantly closes isn't a game — you need a loop that keeps the window alive and redraws it continuously. This is the game loop: a while loop that runs until the player quits. Left unchecked, this loop would run as fast as your CPU possibly can — hundreds or thousands of times a second, wasting power and running inconsistently across different machines. That's why every Pygame loop uses a pygame.time.Clock() object and calls clock.tick(60) once per frame: this caps the loop at a steady frame rate (60 frames per second is standard) and makes movement speed consistent regardless of hardware.

🎮
1
Process Events
⚙️
2
Update Game State
🖌️
3
Draw / Update Display
⏱️
4
clock.tick(60)
🎯
Why 60 FPS? 60 frames per second matches most monitors' refresh rates and feels smooth to the human eye. Locking your loop to a target frame rate also means "move 3 pixels per frame" behaves the same on a fast gaming PC and a budget laptop.
Section 4

Handling Events and Closing the Window Properly

Pygame reports everything that happens — key presses, mouse clicks, window close requests — as events, delivered through pygame.event.get(). This returns a list of every event that occurred since the last time you checked, and you loop through them each frame. The most critical event to handle is pygame.QUIT, fired when the player clicks the window's close button — if you don't listen for it, your window will freeze and become unresponsive (unkillable except by force-quitting the process).

To close the window properly, catch that QUIT event, flip a running flag to False so the loop exits, and then call pygame.quit() after the loop ends to clean up Pygame's internal resources before the script finishes.

events.py
for event in pygame.event.get():
    if event.type == pygame.QUIT:
        running = False
    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_ESCAPE:
            running = False
Event TypeFires WhenCommon Use
pygame.QUITPlayer clicks the window's close buttonAlways handle this — stops the loop
pygame.KEYDOWNAny key is pressed downOne-time actions: jump, pause, shoot
pygame.KEYUPA key is releasedStop movement, cancel charging an attack
pygame.MOUSEBUTTONDOWNA mouse button is clickedMenu clicks, aiming, placing objects
Section 5

Your First Interactive Program: The Complete Loop

Now let's assemble everything from this module into one complete, correct, runnable program. This is the minimal skeleton you will copy at the start of nearly every project in this course: initialize Pygame, open a window, create a clock, run the loop (handle events → update → draw → tick), and quit cleanly when the window closes.

first_game.py
import pygame

# --- Setup ---
pygame.init()
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("First Interactive Program")
clock = pygame.time.Clock()

running = True

# --- Game loop ---
while running:
    # 1. Handle events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 2. Update game state (nothing to update yet)

    # 3. Draw everything
    screen.fill((15, 20, 40))          # clear the screen with a dark blue
    pygame.draw.circle(screen, (52, 211, 153), (WIDTH // 2, HEIGHT // 2), 40)
    pygame.display.update()             # push the new frame to the window

    # 4. Cap the frame rate
    clock.tick(60)

# --- Clean shutdown ---
pygame.quit()
💡
Try it now: Save this file and run it — you should see a dark window with a green circle in the center that stays open until you close it. If the window doesn't close cleanly, double-check your pygame.QUIT handling.
Section 6 · Mini Project

Mini Project: A Window That Reacts to Keypresses

Let's make the window slightly interactive by combining events with drawing — pressing the spacebar changes the background color. This mini project ties together everything you've learned: initialization, the display surface, the game loop, clock, events, and clean shutdown.

mini_project.py
import pygame

pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Mini Project: Color Switcher")
clock = pygame.time.Clock()

bg_color = (15, 20, 40)
running = True

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
            bg_color = (5, 150, 105) if bg_color == (15, 20, 40) else (15, 20, 40)

    screen.fill(bg_color)
    pygame.display.update()
    clock.tick(60)

pygame.quit()
Window Opens
A single call to set_mode() gets you an 800×600 window with a proper title.
Stays Responsive
The clock keeps the loop at a steady 60 FPS instead of maxing out the CPU.
Closes Properly
Clicking the close button triggers pygame.quit() with no freezing or hanging process.
Visual Reference

The Loop as a Cycle, Not a Straight Line

pygame.init() only ever runs once, right at the start. Everything after it — handling events, updating state, and drawing the frame — repeats endlessly in a cycle until running becomes False. Seeing it as a loop, rather than a list of four steps, makes it obvious why the game "does the same thing" every single frame.

Init runs once Events poll input Update game state Draw render frame loop repeats ~60 times per second until running = False
Init runs once; Events → Update → Draw then cycles continuously, looping back to Events every frame.

🧠 Quick Knowledge Check

1. What must you call before using any other Pygame function?
2. What does pygame.display.set_mode((800, 600)) return?
3. Why do you call clock.tick(60) inside the game loop?
4. Which event MUST you handle so the window closes properly?
5. What are the four steps every frame of the game loop performs, in order?
Finished Module 2?

Mark it complete to track your progress through the Pygame Mastery course.

🗒 Cheat Sheet 📝 Worksheet