Difficulty¶
In this lesson we will learn
- how to let players choose a difficulty that suits their skill
- how to add a new Room between two existing Rooms
- how to store settings in Globals.py so every Room and object can use them
- how to change an object's image to show the player's choice
In Game Design we found that our game's difficulty never changes, so it doesn't suit every player. Let's add a difficulty menu.

Planning¶
What changes with difficulty?¶
The asteroids are the main danger in our game, so we'll change two things:
- how often Zork throws asteroids (the spawn timer)
- how fast the asteroids move
| Difficulty | Key | Asteroid spawn time (ticks) | Asteroid speed |
|---|---|---|---|
| Easy | E | 30 to 180 | 7 |
| Medium | M | 15 to 150 (what we have now) | 10 |
| Hard | H | 8 to 90 | 14 |
Where do the settings live?¶
The player chooses the difficulty in one Room, but Zork and Asteroid use it in another Room. Values that need to be shared across Rooms go in Globals.py, just like SCORE and LIVES. We'll add three new variables:
asteroid_spawn_minandasteroid_spawn_max→ the range for Zork's asteroid timerasteroid_speed→ how fast new asteroids move
A new Room¶
We'll add a DifficultySelect Room between the WelcomeScreen and GamePlay. It holds one RoomObject, the DifficultyMenu. Look in Images/Select_difficulty_frames: there are three images of the menu, each with a different choice highlighted.
| Input | Process | Output |
|---|---|---|
| the player presses E, M or H | save the matching settings in Globals, show the menu with that choice highlighted, then wait half a second |
the DifficultySelect Room ends and GamePlay starts |
The short wait means the player sees their choice highlighted before the game starts. We'll use a timer for that.
Add the settings¶
Open GameFrame/Globals.py, change the highlighted code below and save it.
Code explanation
- line 19 → adds
"DifficultySelect"to the list of Rooms, between the WelcomeScreen and GamePlay. - lines 46–47 → store the shortest and longest time between asteroids, starting with the Medium values.
- line 48 → stores the asteroid speed, starting with the Medium value.
Create the DifficultyMenu¶
Create a new file in the Objects folder, add the code below and save it as DifficultyMenu.py.
Code explanation
- lines 1–2 → import
RoomObject,Globalsand Pygame. - line 4 → defines the
DifficultyMenuclass as a subclass ofRoomObject. - lines 5–7 → a docstring that explains what the class is for.
- line 8 → defines the
__init__method. - lines 9–11 → a docstring that explains what the method does.
- line 12 → runs
RoomObject's__init__method. - lines 15–17 → load the three menu images into a list, just like we did for the lives in Lesson 14.
- line 18 → shows the menu with Medium highlighted (index
1), because Medium is the starting setting. - line 21 → registers the menu for key events.
- line 22 → creates a
chosenflag, so the player can only choose once. - line 24 → defines the
key_pressedevent handler. - lines 25–27 → a docstring that explains what the method does.
- line 28 → checks if a difficulty has already been chosen…
- line 29 → …and if so, leaves the method straight away with
return, so nothing else happens. - lines 31–32 → if E is pressed, chooses Easy: menu image
0, spawn time 30 to 180, speed 7. - lines 33–34 → if M is pressed, chooses Medium.
- lines 35–36 → if H is pressed, chooses Hard.
- line 38 → defines the
choosemethod, which takes the menu image to show and the three settings. - lines 39–41 → a docstring that explains what the method does.
- lines 42–44 → save the settings in
Globals, so Zork and the asteroids can use them. - line 45 → shows the menu image with the chosen difficulty highlighted.
- line 46 → sets the
chosenflag toTrue. - line 47 → starts a 15-tick (half a second) timer that calls
start_game. - line 49 → defines the
start_gamemethod. - lines 50–52 → a docstring that explains what the method does.
- line 53 → ends the DifficultySelect Room, so the game moves on to GamePlay.
Why a choose method?
Each key does the same four things with different values. Instead of writing those lines three times, we wrote them once in choose and passed in the values. If we want to change how choosing works later, we only change it in one place.
Open Objects/__init__.py, add the highlighted code below and save it.
| Objects/__init__.py | |
|---|---|
Code explanation
- line 8 → imports the
DifficultyMenuclass, so GameFrame can find it.
Create the DifficultySelect Room¶
Create a new file in the Rooms folder, add the code below and save it as DifficultySelect.py.
Code explanation
- lines 1–2 → import
Leveland theDifficultyMenuclass. - line 4 → defines the
DifficultySelectclass as a subclass ofLevel. - lines 5–7 → a docstring that explains what the class is for.
- lines 8–9 → define
__init__and runLevel's__init__method. - line 12 → sets the background image.
- line 15 → adds a DifficultyMenu in the middle of the screen. The menu is 500 × 78 pixels, so
x = (1280 - 500) / 2 = 390andy = (800 - 78) / 2 = 361.
Open Rooms/__init__.py, add the highlighted code below and save it.
| Rooms/__init__.py | |
|---|---|
Code explanation
- line 3 → imports the
DifficultySelectclass, so GameFrame can find it.
PRIMM
- Predict what will happen after you press space on the welcome screen.
- Run MainController.py and choose each difficulty in turn (you'll need to lose a game to get back to the menu).
- Investigate: does the game feel any different? Why not?
Use the settings¶
The menu saves the settings, but nothing uses them yet. Open Objects/Zork.py, change the highlighted code below and save it.
Code explanation
- line 25 → chooses the first asteroid's spawn time from the difficulty's range instead of
15to150. - line 54 → does the same when choosing the time for the next asteroid.
Open Objects/Asteroid.py, change the highlighted code below and save it.
| Objects/Asteroid.py | |
|---|---|
Code explanation
- line 22 → starts each asteroid moving at the difficulty's speed instead of
10.
PRIMM
- Predict how Easy and Hard will feel different.
- Run MainController.py and try all three difficulties.
- Modify: are the settings right for you? Get someone else to play too, then adjust the numbers in
key_presseduntil each level feels right.
Commit and push¶
- In GitHub Desktop, type Added difficulty menu in the Summary box.
- Click Commit to main.
- Click Push origin.