Module 1 of 20 Phase: Python Fundamentals

Python Refresher
Before You Build Games

Before Pygame ever enters the picture, you need a rock-solid grip on Python itself. This module condenses variables, control flow, loops, functions, and object-oriented programming into one focused refresher — the exact toolkit every future game in this course will lean on.

📚
6 Chapters
Core Python topics
⏱️
3–4 Hours
Estimated time
🟢
Beginner
Difficulty
🐍
Python 3.12
Primary tool
Section 1 · Chapter 1

Welcome to Game Development

Welcome to Complete Pygame Mastery 2026. Over the next 20 modules you'll go from "I know a little Python" to shipping full, playable games — platformers, shooters, puzzle games, and a final capstone project you design yourself. But first: what actually is game development?

At its core, a video game is just a program that runs the same three steps, over and over, dozens of times per second: it reads input from the player (keyboard, mouse, controller), updates the game's internal state (move the player, check collisions, update the score), and renders the new state to the screen. This repeating cycle is called the game loop, and everything you build in this course — from a bouncing ball to a full platformer — is built on top of it.

🎮
Step 1
Handle Input
⚙️
Step 2
Update State
🖼️
Step 3
Render Frame
🔁
Repeat
~60 Times/Sec

This module (and the roadmap for the rest of the course) assumes you're working in Python 3.10+ with VS Code as your editor and Pygame as your game library. Here's exactly how to get set up, and what the rest of the 20 modules cover.

🐍
Install Python
Download Python 3.10 or newer from python.org. On Windows, tick "Add python.exe to PATH" during install — this lets you run `python` from any terminal.
💻
Install VS Code
Download VS Code from code.visualstudio.com and install the official Python extension from Microsoft. This gives you syntax highlighting, autocomplete, and a built-in terminal.
🎮
Install Pygame
Open a terminal and run `pip install pygame`. This downloads the Pygame library so every module from Module 2 onward can `import pygame`.

Once installed, set up a dedicated workspace: create a folder called pygame-course, open it in VS Code, and inside it create your first file — hello.py. Type a single line, save, and run it from the integrated terminal to confirm everything works end to end.

hello.py
print("Hello, Pygame Mastery!")
print("If you can see this, Python is installed correctly.")
💡
Running a Python file: In VS Code's terminal, type python hello.py (or python3 hello.py on macOS/Linux) and press Enter. You should see both lines print to the terminal. That's the exact workflow you'll use for every single lesson in this course.
Section 2 · Chapter 2

Python Basics: Variables, Data, and Operators

A variable is a named box that stores a value in memory. In Python you don't declare a type — you just assign a value, and Python figures out the data type for you: whole numbers are int, decimals are float, text is str, and true/false values are bool. Every game you build will juggle dozens of variables — player health, score, position, velocity — so getting comfortable with them now matters.

You'll also constantly need to read what the player typed (input()) and print information back out (print()), plus combine values using arithmetic operators (+ - * / // % **), compare values with comparison operators (== != > < >= <=), and combine conditions with logical operators (and, or, not).

basics.py
# Variables and data types
player_name = "Nova"        # str
health = 100                # int
speed = 4.5                 # float
is_alive = True             # bool

# Reading user input (input() always returns a string)
chosen_name = input("Enter your player name: ")
print("Welcome, " + chosen_name + "!")

# Arithmetic operators
damage = 15
health = health - damage    # subtraction
score = 10 * 3               # multiplication
level_up_at = 100 // 7       # floor division
remainder = 100 % 7          # modulo (remainder)

# Comparison and logical operators
is_low_health = health < 30
can_level_up = score >= 20 and is_alive
print(f"Health: {health}, Low health? {is_low_health}, Can level up? {can_level_up}")
✏️
Practice exercise: Create variables for a player's name, health, and score. Ask the player to input a new name with input(), subtract 25 from health using arithmetic operators, and print a formatted summary using an f-string. This is the same pattern you'll use for score tracking and HUDs later in the course.
Section 3 · Chapter 3

Control Flow: Making Decisions

Games are constantly making decisions: is the player touching an enemy? Did they press the jump key? Is their score high enough to unlock a new level? Python handles all of this with if, elif (else-if), and else statements, which can be nested inside one another for more complex logic. Python 3.10 also introduced match/case, a cleaner way to branch on a single value with many possible options — perfect for handling game states like "menu", "playing", "paused", and "game_over".

control_flow.py
health = 45
has_shield = True

# if / elif / else
if health <= 0:
    print("Game Over")
elif health < 30:
    print("Danger! Health is critical.")
else:
    print("You're doing fine.")

# Nested condition
if health < 30:
    if has_shield:
        print("Shield absorbs the damage!")
    else:
        print("Take cover — no shield left!")

# match/case for game states (Python 3.10+)
game_state = "playing"
match game_state:
    case "menu":
        print("Showing main menu")
    case "playing":
        print("Game loop running")
    case "paused":
        print("Game paused")
    case "game_over":
        print("Showing final score")
    case _:
        print("Unknown state")
🎯
Mini challenge: Write a function-free script that checks a variable score against three thresholds (bronze, silver, gold) using if/elif/else, then rewrite the same logic using match/case to see how the two approaches compare.
Section 4 · Chapter 4

Loops: Repetition Is Everything

Remember the game loop from Section 1? It's literally a while loop that keeps running as long as a condition (like "game is running") stays true. A for loop, usually paired with the range() function, is perfect for repeating something a fixed number of times — spawning 10 enemies, looping through a list of high scores, or iterating every sprite on screen. Inside loops, break exits early and continue skips to the next iteration — both are essential once you start writing real gameplay logic. Loops can also be nested inside each other, which is exactly how you'll later draw grids and tile maps.

Loop TypeBest ForExample Use in a Game
whileRepeating until a condition changesThe main game loop — runs while running == True
for + range()Repeating a known number of timesSpawning a fixed wave of 5 enemies
for over a listProcessing a collection of itemsUpdating every bullet in a bullets list
Nested loopsGrids and 2D structuresDrawing every tile in a tile map (row × column)
loops.py
# while loop — the shape of every game loop you'll write
running = True
lives = 3
while running:
    lives -= 1
    print(f"Lives left: {lives}")
    if lives <= 0:
        running = False   # exits the loop

# for loop with range() — spawn 5 enemies
for i in range(5):
    print(f"Spawning enemy #{i + 1}")

# break and continue
for i in range(10):
    if i == 3:
        continue          # skip this iteration
    if i == 7:
        break              # stop the loop entirely
    print(i)

# nested loops — a simple 3x3 grid
for row in range(3):
    for col in range(3):
        print(f"Tile at row {row}, col {col}")
✏️
Practice: Use a nested for loop to print a 5x5 grid of coordinates, but use continue to skip every tile where row == col (the diagonal). This exact skill returns in Module 13 when you build real tile maps.
Section 5 · Chapter 5

Functions: Reusable Blocks of Logic

A function packages up a block of code so you can run it whenever you need it, instead of copy-pasting the same logic everywhere. Functions accept parameters (the values you pass in) and can send a result back with return. Variables created inside a function only exist inside that function — this is called scope, and understanding it prevents a huge class of confusing bugs. Python also supports tiny one-line anonymous functions called lambda functions, and functions that call themselves, known as recursion.

functions.py
# Function with parameters and a return value
def take_damage(current_health, damage_amount):
    new_health = current_health - damage_amount
    return max(new_health, 0)   # never go below 0

health = 100
health = take_damage(health, 35)
print(f"Health after hit: {health}")

# Scope: 'multiplier' only exists inside the function
def apply_score_bonus(base_score):
    multiplier = 1.5
    return base_score * multiplier

print(apply_score_bonus(200))
# print(multiplier)  # would raise NameError — out of scope

# Lambda function — a quick one-line function
square = lambda x: x * x
print(square(6))

# Recursion — a function calling itself
def countdown(n):
    if n <= 0:
        print("Go!")
        return
    print(n)
    countdown(n - 1)

countdown(3)
💡
Why this matters for Pygame: Almost every game you build will have functions like draw_player(), check_collision(), and spawn_enemy() — breaking logic into small, well-named functions is what keeps a 500-line game file readable.
Section 6 · Chapter 6

Object-Oriented Programming (OOP)

Every meaningful entity in a game — the player, an enemy, a bullet, a power-up — is naturally an object: it has data (position, health, speed) and behavior (move, attack, take damage). Python's class keyword lets you define a blueprint for these objects. A class's constructor (__init__) sets up an object's starting data, its methods define behavior, encapsulation keeps related data and logic bundled together, inheritance lets one class reuse and extend another, and polymorphism lets different classes respond differently to the same method call. This is the single most important concept for the rest of the course — starting in Module 6, every sprite you create will be a class.

🏗️
Class & Constructor
A class is the blueprint. The __init__ method runs automatically when you create an object, setting up its starting attributes like health, position, or name.
⚙️
Methods & Encapsulation
Methods are functions that live inside a class and act on its data (self). Encapsulation means an object's data and the logic that touches it stay bundled together.
🧬
Inheritance
A subclass like Enemy can inherit from a base class like Character, reusing shared logic (movement, health) while adding its own unique behavior.
🎭
Polymorphism
Different classes can implement the same method name differently — calling attack() on a Wizard and a Knight triggers completely different behavior.
oop.py
class Character:
    def __init__(self, name, health):
        self.name = name
        self.health = health   # encapsulated data

    def take_damage(self, amount):
        self.health -= amount
        print(f"{self.name} has {self.health} HP left")

    def attack(self):
        print(f"{self.name} attacks!")

# Inheritance — Enemy reuses Character's logic
class Enemy(Character):
    def __init__(self, name, health, damage):
        super().__init__(name, health)
        self.damage = damage

    def attack(self):   # polymorphism — overrides the parent method
        print(f"{self.name} lunges for {self.damage} damage!")

# Creating objects (instances) from the classes
hero = Character("Nova", 100)
goblin = Enemy("Goblin", 40, 12)

hero.attack()
goblin.attack()
hero.take_damage(20)
✏️
Practice: Build a Player class with name, health, and score attributes plus a gain_score(points) method. Then create a Boss class that inherits from it and overrides an attack() method. This exact pattern becomes your Sprite classes starting in Module 6.
Visual Reference

Inheritance in Practice: The GameObject Tree

The Character/Enemy example above is really a small inheritance tree. In the sprite classes you'll build starting in Module 6, the pattern is almost identical: a shared base class holds common data and behavior, and each subclass inherits it while overriding only what makes it unique.

GameObject base class Player (GameObject) Enemy (GameObject) inherits position, health, update() inherits position, health, update()
Both Player and Enemy inherit shared data and behavior from a common GameObject base class, then add or override their own unique logic.

🧠 Quick Knowledge Check

1. What does the game loop typically do, in order, every single frame?
2. What data type does Python's built-in input() function always return?
3. Inside a for loop, which keyword immediately exits the loop entirely?
4. In a Python function, what does the return keyword do?
5. In OOP, what is __init__ called and what does it do?
Finished Module 1?

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

← Previous No previous module
🗒 Cheat Sheet 📝 Worksheet