Intermediate — Day 2
Movement Controls
Day Schedule
Online
| Time | Activity |
|---|---|
| 10:00 | Heading System Draw 0/90/180/270 on whiteboard; demo setheading() |
| 10:20 | Direction Functions go_up/down/left/right with direction guard |
| 10:40 | Event Listeners screen.listen(), screen.onkeypress(); order matters |
| 10:50 | Game Loop (intro) while True, screen.update, head.forward, time.sleep |
| 11:00 | Break |
| 11:10 | Breakout Groups Guided coding: moving snake with arrow keys |
| 12:20 | Reminders |
In-Person
| Time | Activity |
|---|---|
| 8:00 | Warm-Up Review Day 1: snake head visible for everyone? |
| 8:20 | Heading System Draw 0/90/180/270 on whiteboard; demo setheading() |
| 8:45 | Direction Functions go_up/down/left/right with direction guard |
| 9:10 | Event Listeners screen.listen(), screen.onkeypress(); order matters |
| 9:25 | Game Loop (intro) while True, screen.update, head.forward, time.sleep |
| 9:40 | Break |
| 9:50 | Breakout Groups Guided coding: moving snake with arrow keys |
| 11:00 | Break |
| 11:10 | Extra Activity Direction guard deep-dive: try removing guards and observe what breaks |
| 11:50 | Open Coding Catch up or experiment with speed and step size |
| 12:20 | Reminders |
Learning Objectives
- Know Turtle's heading system: 0=right, 90=up, 180=left, 270=down
- Write direction functions with direction-guard conditions
- Bind arrow keys using screen.listen() and screen.onkeypress()
- Understand the game loop pattern: update → move → sleep
Main Topic
# INSTRUCTOR — Day 2: Conditionals, Functions & Event Listeners (Intermediate)
# -----------------------------------------------
# TEACH: Event listeners are the new concept today.
# screen.listen() tells Turtle to watch the keyboard.
# screen.onkeypress(func, "Key") calls func whenever that key is pressed.
# The function runs automatically — students don't call it manually.
#
# TEACH: Turtle headings are numbers, not strings.
# 0 = right (east), 90 = up (north), 180 = left (west), 270 = down (south)
# head.setheading(90) points the turtle up. head.forward(20) moves it 20 pixels that way.
import turtle
import time
# TEACH: import time loads Python's built-in time module.
# time.sleep(n) pauses the program for n seconds — this is how we control game speed.
# Demo the difference before settling on 0.1:
# time.sleep(1.0) — very slow, one move per second
# time.sleep(0.05) — very fast, hard to control
# 0.1 seconds per frame ≈ 10 frames per second — a good starting speed for snake.
screen = turtle.Screen()
screen.bgcolor("black")
screen.setup(width=600, height=600)
screen.tracer(0)
head = turtle.Turtle()
head.shape("square")
head.color("white")
head.penup()
head.goto(0, 0)
# TEACH: direction guard — block the reverse direction.
# If heading UP (90), we must not allow DOWN (270) — that reverses into yourself.
def go_up():
if head.heading() != 270: # 270 is DOWN — the opposite of UP
head.setheading(90)
def go_down():
if head.heading() != 90: # 90 is UP — the opposite of DOWN
head.setheading(270)
def go_left():
if head.heading() != 0: # 0 is RIGHT — the opposite of LEFT
head.setheading(180)
def go_right():
if head.heading() != 180: # 180 is LEFT — the opposite of RIGHT
head.setheading(0)
# TEACH: order matters — listen() BEFORE binding keys
screen.listen()
screen.onkeypress(go_up, "Up")
screen.onkeypress(go_down, "Down")
screen.onkeypress(go_left, "Left")
screen.onkeypress(go_right, "Right")
# One move to verify it works
screen.update()
head.forward(20)
time.sleep(1)
Project — Snake Movement
# INSTRUCTOR — Day 2: Project: Snake: Movement Controls (Intermediate)
# -----------------------------------------------
# TEACH: Cumulative from Day 1. Students add direction functions, key bindings,
# and a basic loop so they can actually play with the moving snake.
# Check: press all four arrow keys — head should move and respect the direction guards.
# Common mistake: forgetting head.heading() (calling it as a method, not a property).
import turtle
import time
screen = turtle.Screen()
screen.title("Snake Game")
screen.bgcolor("black")
screen.setup(width=600, height=600)
screen.tracer(0)
head = turtle.Turtle()
head.shape("square")
head.color("white")
head.penup()
head.goto(0, 0)
# --- Direction functions ---
# TEACH: each function blocks the EXACT OPPOSITE heading
# Opposite pairs: UP(90) ↔ DOWN(270), LEFT(180) ↔ RIGHT(0)
def go_up():
if head.heading() != 270:
head.setheading(90)
def go_down():
if head.heading() != 90:
head.setheading(270)
def go_left():
if head.heading() != 0:
head.setheading(180)
def go_right():
if head.heading() != 180:
head.setheading(0)
screen.listen()
screen.onkeypress(go_up, "Up")
screen.onkeypress(go_down, "Down")
screen.onkeypress(go_left, "Left")
screen.onkeypress(go_right, "Right")
# --- Game loop (minimal — no collision yet) ---
# TEACH: while True runs forever. Every frame: update screen, move head, pause.
# time.sleep(0.1) controls speed — lower = faster.
while True:
screen.update()
head.forward(20) # TEACH: forward() uses the current heading automatically
time.sleep(0.1)
Extra — Direction Guard
# INSTRUCTOR — Day 2: Extra Activity: Direction Guard (Intermediate)
# -----------------------------------------------
# TEACH: Students fill in the four heading numbers that block a reverse.
# This reinforces the heading map: 0=right, 90=up, 180=left, 270=down.
# Common wrong answer: students put the same heading as the direction being guarded.
# Correct logic: go_up blocks 270 (DOWN), not 90 (UP).
# Headings: 0 = right, 90 = up, 180 = left, 270 = down
# Answers: go_up blocks 270, go_down blocks 90, go_left blocks 0, go_right blocks 180
# REFERENCE (complete answers):
def go_up():
if head.heading() != 270: # block DOWN (the reverse of UP)
head.setheading(90)
def go_down():
if head.heading() != 90: # block UP (the reverse of DOWN)
head.setheading(270)
def go_left():
if head.heading() != 0: # block RIGHT (the reverse of LEFT)
head.setheading(180)
def go_right():
if head.heading() != 180: # block LEFT (the reverse of RIGHT)
head.setheading(0)
# TEACH: challenge — add WASD key support
screen.onkeypress(go_up, "w")
screen.onkeypress(go_down, "s")
screen.onkeypress(go_left, "a")
screen.onkeypress(go_right, "d")
# TEACH: both sets of keys call the same functions — no duplicate logic needed