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.
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.
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.
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.
print("Hello, Pygame Mastery!")
print("If you can see this, Python is installed correctly.")
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.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).
# 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}")
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.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".
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")
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.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 Type | Best For | Example Use in a Game |
|---|---|---|
while | Repeating until a condition changes | The main game loop — runs while running == True |
for + range() | Repeating a known number of times | Spawning a fixed wave of 5 enemies |
for over a list | Processing a collection of items | Updating every bullet in a bullets list |
| Nested loops | Grids and 2D structures | Drawing every tile in a tile map (row × column) |
# 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}")
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.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.
# 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)
draw_player(), check_collision(), and spawn_enemy() — breaking logic into small, well-named functions is what keeps a 500-line game file readable.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 is the blueprint. The __init__ method runs automatically when you create an object, setting up its starting attributes like health, position, or name.self). Encapsulation means an object's data and the logic that touches it stay bundled together.Enemy can inherit from a base class like Character, reusing shared logic (movement, health) while adding its own unique behavior.attack() on a Wizard and a Knight triggers completely different behavior.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)
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.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.
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
input() function always return?for loop, which keyword immediately exits the loop entirely?return keyword do?__init__ called and what does it do?