Skip to content

Latest commit

 

History

History
398 lines (336 loc) · 10.7 KB

File metadata and controls

398 lines (336 loc) · 10.7 KB

Week 12 – Turtle Catcher (Capstone Project)

Objectives

  • 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

Concept explanation (kid-friendly)

  • 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)

Why this is a capstone

  • Synthesizes 6 weeks of Turtle learning
  • Students apply knowledge independently
  • Creates portfolio-worthy project
  • Demonstrates readiness for next phase (Pygame Zero)

Connection to previous weeks

  • 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!

Lesson flow (60–75 min)

1) Warm-up (5–10 min)

  • 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)

2) New concept (10–15 min)

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 screen

Click 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:

  1. Do updates
  2. Schedule next call
  3. 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()          │
    └─────────────────┘

3) Guided build (20–25 min)

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_SECONDS

Part 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 display

Why 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)

4) Independent challenge (15–20 min)

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

  1. 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)
  2. 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)
  3. 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)
  4. 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"))
  5. 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

5) Wrap-up (5 min)

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?"

Common errors to demo on purpose

  1. 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
  2. Wrong onclick syntax

    target.onclick(on_click(x, y))  # Wrong! Calling function
    • Shows: Error immediately
    • Fix: Pass function name: target.onclick(on_click)
  3. Forgetting global in handler

    def on_click(x, y):
        score = score + 1  # Error! No global
    • Shows: UnboundLocalError
    • Fix: Add global score
  4. ontimer with wrong arguments

    screen.ontimer(tick(), 250)  # Wrong! Has ()
    • Shows: Function called immediately, not scheduled
    • Fix: Pass function name without (): tick
  5. Infinite immediate loop

    def tick():
        draw_ui()
        tick()  # Recursion! No delay
    • Shows: Program freezes, max recursion error
    • Fix: Use ontimer, not direct call

Success criteria

  • 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

Differentiation

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

Assessment rubric (Week 12 Milestone)

See docs/week12_milestone_rubric.md for detailed assessment.

Materials needed

  • Thonny IDE
  • week12.py file
  • Timer for testing game duration
  • Optional: Projector for student presentations
  • Portfolio documentation template

Key vocabulary

  • 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)

Extension activities

  • 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

Preparation for next phase

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!

Homework/practice

  • 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