Game Programming
Senior 2 · ICT
Game Programming
Lesson 4 of 4
25 min
You will now build a complete game from start to finish, adapted from the Raspberry Pi Foundation's Catch the Dots project. Our version uses the three colours of Rwanda's flag, blue, yellow and green, so we call it Catch the Colours. The player turns a wheel of blue, yellow and green sections. Dots of the same three colours fly in from the corners, and the player must turn the matching colour to meet each dot. You need Scratch 3, either online at scratch.mit.edu or in the offline Scratch app.
| Element | Type | What it does |
|---|---|---|
| controller | Sprite: a wheel with blue, yellow and green sections | Turns left and right with the arrow keys |
| blue, yellow, green | Sprites that make clones | Each clone flies from a random corner to the wheel |
| score, lives | Variables | Start at 0 and 3 |
| delay | Variable | Seconds between new dots; starts at 8 and falls to 2 |
| high score | Variable | Best score so far; never reset |
| start positions | List with the items −180 and 180 | Used to pick a random corner |
Draw or choose a wheel sprite split into blue, yellow and green sections, and name it controller. Give it the steering script from Lesson 3 (turn right (3) degrees for the right arrow and turn left (3) degrees for the left arrow, inside forever). Test it: the wheel should turn both ways.
Create a small blue dot sprite called blue. Make the list start positions, add the items −180 and 180, and untick the list so it does not show on the stage. Then give the blue sprite this script:
The original sprite stays hidden and works as a factory: every delay seconds it makes a clone. Each clone runs the when I start as a clone script from Lesson 3, which flies it to the wheel and checks the colour. Add that script to the blue sprite now.
Create the variables score, lives, delay and high score. Give the stage the lose-condition script from Lesson 3: set lives to 3 and score to 0, wait until <(lives) < (1)>, then show Game Over and stop [all]. Test it: let three blue dots hit the wrong colour, and the game should end.
Duplicate the blue sprite twice and name the copies yellow and green. For each copy:
Add a second script to the stage:
The delay goes 8, 7.5, 7, … down to 2. It must fall by 6 seconds in steps of 0.5, which is 12 steps of 10 seconds each: after 120 seconds the dots arrive at their fastest rate, one of each colour every 2 seconds.
On the stage, use My Blocks to make a custom block called check high score, and define it:
Put check high score into the stage's lose-condition script, just before stop [all]. Because high score is never reset when the green flag is clicked, it survives from one game to the next. Note the strict >: equalling the high score does not replace it.
| Problem | Likely cause | Fix |
|---|---|---|
| Dots appear on top of each other | All three factories start at the same moment | Use different first waits: 2, 4 and 6 seconds |
| A dot of the matching colour costs a life | The colour in touching color is not exactly the wheel's colour | Pick the colour from the wheel with the colour picker |
| The score does not start at 0 | set [score] to (0) is missing | Add it to the stage's green-flag script |
| The dots never speed up | A factory still uses a fixed wait instead of the delay variable | Use wait (delay) seconds in all three factories |
Text-based languages express exactly the same game rules. This Python program replays one game from a list of catches, using the same scoring rule, lose condition and high-score check. Run it and compare each part with your Scratch scripts.
for … in works like a Scratch loop over the list of catches. if dot == wheel is the scoring rule and else takes away a life. break is the lose condition: once lives reach 0 the loop stops, so the ninth catch is never played. The last lines are check high score. The final score equals the old high score, 5, and 5 > 5 is false, so the high score stays 5.
Tip
Build a little, test a little. Add one step, click the green flag and check it before you add the next. When something breaks, you will know it was the last thing you changed. Save a new copy of the project after each step that works.
The delay starts at 8 seconds and drops by 0.5 every 10 seconds. What is the delay after 60 seconds?
Solution: 60 ÷ 10 = 6 drops, so delay = 8 − 6 × 0.5 = 8 − 3 = 5 seconds.
A clone starts at (180, −180). Which corner of the stage is that?
Solution: x = 180 is on the right and y = −180 is at the bottom, so it is the bottom-right corner.
Trace the Python program. What are score and lives after the first four catches?
Solution: blue/blue: score 1. green/green: score 2. yellow/blue: lives 2. green/green: score 3. So score = 3, lives = 2.
Add a golden dot worth 2 points. What do you need?
Solution: A new dot sprite with a gold costume and the same two scripts (factory and clone), with a wheel section of the same colour and change [score] by (2) instead of 1. Give it a long first wait so that it appears less often.
Summary
Sources and credits
Changes by Ganzaa: the Rwandan-flag colour scheme, the step-by-step explanations, the debugging table, the Python version and the practice items.
This lesson adapts CC BY-SA material and is shared under CC BY-SA 4.0.
when green flag clicked
hide
wait (2) seconds
forever
create clone of [myself]
wait (delay) seconds
endwhen green flag clicked
set [delay] to (8)
repeat until <(delay) = (2)>
wait (10) seconds
change [delay] by (-0.5)
enddefine check high score
if <(score) > (high score)> then
set [high score] to (score)
end# Catch the Colours: the game rules, simulated in Python
lives = 3
score = 0
high_score = 5 # best score from an earlier game
# Each pair is (colour of the dot, colour of the wheel where it lands)
catches = [("blue", "blue"), ("green", "green"), ("yellow", "blue"),
("green", "green"), ("blue", "yellow"), ("yellow", "yellow"),
("blue", "blue"), ("green", "yellow"), ("yellow", "yellow")]
for dot, wheel in catches:
if lives < 1: # lose condition: no lives left
break
if dot == wheel: # scoring rule: colours match
score = score + 1
print(dot, "matched: score =", score)
else: # colours do not match
lives = lives - 1
print(dot, "missed: lives =", lives)
print("Game over. Final score:", score)
if score > high_score: # check high score
high_score = score
print("High score:", high_score)