- Combine all Turtle graphics concepts from weeks 7-11
- Implement mouse click events
- Create complete game with clear objectives
- Use ontimer() for continuous updates
- Polish a complete project for showcase
- This is our first complete game from scratch!
- Uses everything we learned: turtles, events, timers, random
- Mouse clicks instead of keyboard - different interaction style
- Continuous timer updates (not just on key press)
- Synthesizes 6 weeks of Turtle learning
- Students apply knowledge independently
- Creates portfolio-worthy project
- Demonstrates readiness for next phase (Pygame Zero)
- Week 7: Turtle basics (drawing, positioning)
- Week 8: Loops and patterns
- Week 9: Events (keyboard)
- Week 10: Collision detection, random positioning
- Week 11: Time tracking
- Week 12: Everything together + mouse events!
- Review: "What are all the games we've made with Turtle?"
- Challenge: "Design a game on paper using these concepts"
- Demo: Run week12.py - "How is this different from Week 11?"
- Key difference: Click the target (mouse) vs move hero (keyboard)
Part A: Mouse events (5 min)
# Keyboard events (Week 9)
screen.onkey(jump, "space")
# Mouse click events (Week 12)
target.onclick(handle_click) # Click on specific turtle
screen.onclick(handle_click) # Click anywhere on screenClick handler receives coordinates:
def handle_click(x, y):
print(f"Clicked at ({x}, {y})")
if target.distance(x, y) < 25:
print("Hit the target!")Part B: Continuous updates with ontimer() (5 min) Previous games: Update only on key press This game: Update continuously
def tick():
"""Called repeatedly to update game"""
update_display()
draw_ui()
screen.ontimer(tick, 250) # Call again in 250ms (0.25 sec)
# Start the loop
tick()Pattern:
- Do updates
- Schedule next call
- Repeat forever (until game ends)
Part C: Game loop pattern (5 min)
┌─────────────────┐
│ Start game │
└────────┬────────┘
│
┌────▼────┐
│ tick() │◄────┐
└────┬────┘ │
│ │
┌────▼──────────┴──┐
│ Update timer │
│ Check conditions │
│ Redraw UI │
└────┬──────────────┘
│
┌────▼────────────┐
│ If not game over│
│ schedule next │
│ tick() │
└─────────────────┘
Part A: Setup (5 min)
import turtle
import random
import time
screen = turtle.Screen()
screen.title("Turtle Catcher")
screen.setup(width=700, height=500)
# Target to click
target = turtle.Turtle()
target.shape("circle")
target.color("red")
target.penup()
target.speed(0)
# Score display
writer = turtle.Turtle()
writer.hideturtle()
writer.penup()
writer.goto(-330, 210)
# Game variables
score = 0
GAME_SECONDS = 25
start_time = time.time()Part B: Helper functions (8 min)
def move_target():
"""Move target to random position"""
x = random.randint(-320, 320)
y = random.randint(-200, 200)
target.goto(x, y)
def draw_ui():
"""Update score and timer display"""
remaining = max(0, int(GAME_SECONDS - (time.time() - start_time)))
writer.clear()
writer.write(f"Score: {score} Time: {remaining}",
font=("Arial", 16, "normal"))
def time_up():
"""Check if game time expired"""
return (time.time() - start_time) >= GAME_SECONDSPart C: Click handler (7 min)
def on_click(x, y):
"""Handle mouse click on target"""
global score
# Don't allow clicks if game over
if time_up():
return
# Check if click is close to target
if target.distance(x, y) < 25:
score += 1
move_target() # Move to new position
draw_ui() # Update displayWhy pass x, y?
- Click events provide click coordinates
- We check distance from click to target
- More forgiving than clicking exact center
Part D: Game loop (10 min)
def tick():
"""Main game loop - called repeatedly"""
if time_up():
# Show game over message
writer.goto(-90, 0)
writer.write("TIME UP!", font=("Arial", 24, "bold"))
return # Stop the loop (don't schedule next tick)
# Update UI
draw_ui()
# Schedule next update (250ms = 0.25 seconds = 4 times/sec)
screen.ontimer(tick, 250)
# Connect click event
target.onclick(on_click)
# Initialize game
move_target()
tick() # Start the loop
screen.mainloop()Key points:
- tick() updates UI continuously
- ontimer(function, milliseconds) schedules future call
- When game ends, don't schedule next tick (loop stops)
- 250ms = updates 4 times per second (smooth enough)
Task A: Run and test
- Play the game, try to beat score of 10
- Notice: Timer updates automatically
- Observe: Target jumps when clicked
- Test: What happens if you miss the target?
Task B: Modifications (from student_tasks.md)
- Change GAME_SECONDS to 30
- Change target color to "blue"
- Change target shape to "square"
- Make target bigger: target.shapesize(2, 2)
- Make clicks more forgiving: distance < 40
Task C: Enhancements
-
Add difficulty levels
# At top difficulty = input("Difficulty (easy/normal/hard): ") if difficulty == "easy": GAME_SECONDS = 40 target.shapesize(2, 2) elif difficulty == "hard": GAME_SECONDS = 15 target.shapesize(0.5, 0.5)
-
Increasing speed
# In tick(), make timer update faster as time passes time_passed = time.time() - start_time if time_passed > 15: update_speed = 100 # Faster near end else: update_speed = 250 screen.ontimer(tick, update_speed)
-
Shrinking target
def move_target(): target.goto(random.randint(-320, 320), random.randint(-200, 200)) # Shrink based on score size = max(0.5, 1.5 - (score * 0.1)) target.shapesize(size, size)
-
Show final score
def time_up_message(): writer.goto(-120, 20) writer.write("TIME UP!", font=("Arial", 24, "bold")) writer.goto(-100, -20) writer.write(f"Final Score: {score}", font=("Arial", 18, "normal"))
-
Click anywhere (not just target)
def screen_click(x, y): global score if time_up(): return if target.distance(x, y) < 25: score += 1 move_target() else: score = max(0, score - 1) # Penalty for missing draw_ui() screen.onclick(screen_click) # Instead of target.onclick
Portfolio presentation:
- Each student demonstrates their game
- Explain one modification they made
- Share their high score
- Discuss: "What was most challenging?"
Reflection questions:
- "What's the difference between keyboard and mouse events?"
- "Why do we need ontimer() in this game?"
- "How could you make this game harder?"
- "What other games could you make with these concepts?"
-
Forgetting to return in tick()
def tick(): if time_up(): writer.write("TIME UP!") # Missing return! draw_ui() screen.ontimer(tick, 250) # Still schedules!
- Shows: "TIME UP!" written many times
- Fix: Add return to stop loop
-
Wrong onclick syntax
target.onclick(on_click(x, y)) # Wrong! Calling function
- Shows: Error immediately
- Fix: Pass function name: target.onclick(on_click)
-
Forgetting global in handler
def on_click(x, y): score = score + 1 # Error! No global
- Shows: UnboundLocalError
- Fix: Add global score
-
ontimer with wrong arguments
screen.ontimer(tick(), 250) # Wrong! Has ()
- Shows: Function called immediately, not scheduled
- Fix: Pass function name without (): tick
-
Infinite immediate loop
def tick(): draw_ui() tick() # Recursion! No delay
- Shows: Program freezes, max recursion error
- Fix: Use ontimer, not direct call
- Student completes working game with score and timer
- Student can explain mouse click handling
- Student understands ontimer() game loop
- Student adds at least one enhancement
- Student can present their game to class
For students who need support:
- Use provided template with TODOs
- Start with longer time (60 seconds)
- Larger target size
- Skip enhancements, focus on core game
- Pair programming allowed
For advanced students:
- Add multiple targets (different colors, point values)
- Implement combo system (faster clicks = bonus)
- Add "bad" targets that decrease score
- Create start screen and replay button
- Track high score across sessions (use file I/O)
- Add sound effects (research turtle/winsound)
- Create multiple levels with different challenges
See docs/week12_milestone_rubric.md for detailed assessment.
- Thonny IDE
- week12.py file
- Timer for testing game duration
- Optional: Projector for student presentations
- Portfolio documentation template
- Capstone: Project that demonstrates all learned skills
- onclick: Event triggered by mouse click
- ontimer: Schedule function to run after delay
- Game loop: Continuous cycle of update and render
- Tick: One iteration of game loop
- Frame rate: How often game updates (4 FPS = 250ms)
- Game jam: Students create original game in 2 hours
- Game swap: Play each other's games, give feedback
- Showcase: Present to other classes or parents
- Iteration: Based on feedback, improve game
This capstone prepares for Pygame Zero (weeks 13-18):
- Game loop concept carries over
- Event handling similar
- Score/timer patterns reused
- Ready for more complex graphics!
- Polish game with at least 3 enhancements
- Write brief description of game mechanics
- Record high score and challenge family
- Design next game idea on paper
- Optional: Research Pygame Zero examples online