Students check the arrow keys every frame in update() to move a paddle, trace its position frame by frame, find why keyboard.LEFT fails before a key is pressed, keep the paddle on the screen, add up and down, and make a player with an extra key of their own.
Load these into Waypoints Prepare: choose Load URL and paste the copied address, or download the file and import it. In Prepare, the worksheet's Teacher edition shows the answers; the student copy hides them.
Predict and Run 10 min · Investigate 15 min · Modify 15 min · Make 10 min
Read the unit primer first. pressed(key) is a recipe: two lines students copy into every game. It is needed because microStudio's keyboard has no LEFT until the first key press, so keyboard.LEFT fails at the start (the bug task); hasattr(keyboard, key) asks first. Students need not understand hasattr yet. In microStudio the arrow names also answer to W, A, S and D. Games on our page need a click before they get the keys; so does the game in microStudio's run window.
Thinking in frames: a key held for a second is 60 small moves. The trace table is the moment to slow down.
| What you will see | A question to ask | The fix |
|---|---|---|
| The keys do nothing. | Did you click the game first? | Click inside the game, then press the keys. |
| AttributeError: 'Javascript Object' object has no attribute 'LEFT'. | Does the code use keyboard.LEFT directly? | Copy the pressed() helper in and write pressed("LEFT"). |
| The paddle goes up when DOWN is pressed. | Which way does y count in microStudio? | y goes up the screen: UP adds, DOWN takes away. |
| Only the first key works when two are held. | Is the second check an elif? | Use a separate if for each key. |
One possible solution for each task. Other correct programs are fine.
def pressed(key):
return hasattr(keyboard, key) and keyboard[key] != 0
def init():
global px
px = 0
def update():
global px
if pressed("LEFT"):
px -= 2
if pressed("RIGHT"):
px += 2
if px > 90:
px = 90
if px < -90:
px = -90
def draw():
screen.clear("rgb(10,10,40)")
screen.fillRect(px, -80, 24, 6, "rgb(100,200,255)")
screen.drawText("px = " + str(px), 0, 80, 10, "#FFF")
def pressed(key):
return hasattr(keyboard, key) and keyboard[key] != 0
def init():
global px, py
px = 0
py = -80
def update():
global px, py
if pressed("UP"):
py += 2
if pressed("DOWN"):
py -= 2
if pressed("LEFT"):
px -= 2
if pressed("RIGHT"):
px += 2
def draw():
screen.clear("rgb(10,10,40)")
screen.fillRect(px, py, 24, 6, "rgb(100,200,255)")
screen.drawText("px = " + str(px), 0, 80, 10, "#FFF")
def pressed(key):
return hasattr(keyboard, key) and keyboard[key] != 0
def init():
global x, y
x = 0
y = 0
def update():
global x, y
step = 1
if pressed("SPACE"):
step = 3
if pressed("LEFT"):
x -= step
if pressed("RIGHT"):
x += step
if pressed("UP"):
y += step
if pressed("DOWN"):
y -= step
def draw():
screen.clear("rgb(10,10,40)")
screen.fillRound(x, y, 14, 14, "rgb(120,255,160)")
screen.drawText("Hold SPACE to go fast", 0, 85, 8, "#FFF")
Stretch: Make the paddle wrap round to the other side at the edges, or give it a short dash on Space that only works every few seconds.
Support: Give the edge check for the right side and ask students to write the left one.
Why does the paddle stop when you let go of the key?
Each frame update() asks whether the key is down; when it is not, px is not changed, so the paddle stays where it is.
Next lesson: falling stars as objects, which they have already made with turtles. Polling (asking every frame) and events (a function called on a key) are the two ways every engine reads keys.