Skip to content

Latest commit

 

History

History
327 lines (273 loc) · 8.62 KB

File metadata and controls

327 lines (273 loc) · 8.62 KB

Week 11 – Timed Coin Collector (Timer + Random)

Objectives

  • Use the time module to track elapsed time
  • Implement game timer (countdown or count-up)
  • Create win/lose conditions based on time
  • Combine all previous Turtle concepts
  • Understand time.time() vs game loops

Concept explanation (kid-friendly)

  • We add time pressure to make game more exciting
  • Timer creates urgency (collect coins before time runs out!)
  • time.time() tells us current time in seconds
  • We calculate "time remaining" by subtracting start time

Connection to previous weeks

  • Week 10: Basic collection game
  • Week 11: Add time limit (more challenging!)
  • This is a complete game now with win/lose condition

Lesson flow (60–75 min)

1) Warm-up (5–10 min)

  • Review: "How do we collect coins?" (Week 10)
  • Question: "How can we make the game end after 30 seconds?"
  • Demo: Run week11.py and try to get high score before time runs out
  • Observe: Timer counts down, game ends with message

2) New concept (10–15 min)

Part A: The time module (5 min)

import time

# Get current time (seconds since Jan 1, 1970)
now = time.time()
print(now)  # Example: 1705849234.567

# Wait 2 seconds
time.sleep(2)

# Calculate elapsed time
start = time.time()
# ... do stuff ...
elapsed = time.time() - start
print(f"That took {elapsed} seconds")

Part B: Game timer pattern (5 min)

GAME_SECONDS = 20
start_time = time.time()

# Later, check how much time has passed
def check_time():
    elapsed = time.time() - start_time
    if elapsed >= GAME_SECONDS:
        return True  # Time's up!
    return False

# Calculate remaining time
remaining = int(GAME_SECONDS - (time.time() - start_time))

Part C: Game states (5 min) Games have different "states":

  • Playing: Normal gameplay
  • Game Over: Time expired or win condition met
  • We check state before allowing actions

Example:

game_over = False

def move(dx, dy):
    if game_over:
        return  # Don't allow movement if game over
    hero.goto(hero.xcor() + dx, hero.ycor() + dy)

3) Guided build (20–25 min)

Part A: Setup with timer (5 min)

import turtle
import random
import time

# Game constants
STEP = 20
GAME_SECONDS = 20

# Track start time
start_time = time.time()
score = 0

Part B: UI update function (8 min)

def draw_ui():
    """Update score and timer display"""
    # Calculate remaining time
    elapsed = time.time() - start_time
    remaining = max(0, int(GAME_SECONDS - elapsed))
    
    # Update display
    writer.clear()
    writer.write(f"Score: {score}   Time: {remaining}", 
                 font=("Arial", 16, "normal"))

Key points:

  • max(0, ...) ensures timer doesn't go negative
  • int() converts to whole number (no decimals)
  • Update both score and time in same function
  • Clear old text before drawing new

Part C: Time checking (7 min)

def check_time():
    """Returns True if time is up"""
    if time.time() - start_time >= GAME_SECONDS:
        return True
    return False

def game_over():
    """Display game over message"""
    writer.goto(-80, 0)  # Center of screen
    writer.write("GAME OVER", font=("Arial", 24, "bold"))

Part D: Movement with time check (10 min)

def move(dx, dy):
    """Move hero and check collection"""
    # Check if game already over
    if check_time():
        game_over()
        return  # Don't move if time's up
    
    # Move hero
    hero.goto(hero.xcor() + dx, hero.ycor() + dy)
    
    # Check collection
    check_collect()

# Redefine arrow key functions to use move()
def up():    move(0, STEP)
def down():  move(0, -STEP)
def left():  move(-STEP, 0)
def right(): move(STEP, 0)

Benefits of move() helper:

  • Reduces code duplication
  • Time check in one place (not four)
  • Easier to modify movement logic

Part E: Updated collection (5 min)

def check_collect():
    """Check if hero collected coin"""
    global score
    
    # Check time first
    if check_time():
        game_over()
        return
    
    # Check distance
    if hero.distance(coin) < 25:
        score += 1
        place_coin()
    
    # Update display (both score and timer)
    draw_ui()

4) Independent challenge (15–20 min)

Task A: Run and observe

  • Play the game and note your score
  • Watch timer count down
  • Observe "GAME OVER" message
  • Try to beat your high score

Task B: Modifications (from student_tasks.md)

  • Change GAME_SECONDS to 30 (easier)
  • Change GAME_SECONDS to 10 (harder)
  • Change STEP to 30 (move faster)
  • Add a win condition:
    if score >= 15:
        writer.goto(-70, 0)
        writer.write("YOU WIN!", font=("Arial", 24, "bold"))
        return

Task C: Enhancements

  • Display final score at game over
    def game_over():
        writer.goto(-120, 20)
        writer.write("GAME OVER", font=("Arial", 24, "bold"))
        writer.goto(-80, -20)
        writer.write(f"Final Score: {score}", font=("Arial", 18, "normal"))
  • Add difficulty: coin moves every 3 seconds
  • Show "Last 5 seconds!" warning when time < 5
  • Track high score between games
  • Add countdown "3... 2... 1... GO!" at start

Advanced challenge:

# Increasing difficulty: coins get smaller over time
def place_coin():
    coin.goto(random.randint(-320, 320), random.randint(-200, 200))
    # Shrink coin as time passes
    time_ratio = (time.time() - start_time) / GAME_SECONDS
    size = 1.0 - (time_ratio * 0.5)  # 100% to 50% size
    coin.shapesize(size, size)

5) Wrap-up (5 min)

Students explain:

  • "How do we track how much time has passed?"
  • "Why do we check time in both move() and check_collect()?"
  • "What does max(0, remaining) do?"
  • "How would you add a 'YOU WIN' condition?"

Common errors to demo on purpose

  1. Not checking time consistently

    def up():
        hero.sety(hero.ycor() + STEP)
        check_collect()
        # Forgot to check time!
    • Shows: Can keep playing after time expires
    • Fix: Check time in every movement or use helper function
  2. Timer shows negative numbers

    remaining = int(GAME_SECONDS - (time.time() - start_time))
    # No max(0, ...)
    • Shows: Timer shows -1, -2, -3...
    • Fix: Use max(0, remaining) to stop at 0
  3. start_time not initialized

    # Forgot: start_time = time.time()
    remaining = GAME_SECONDS - (time.time() - start_time)
    • Shows: NameError or wrong time
    • Fix: Set start_time before mainloop()
  4. Game over shown repeatedly

    def move(dx, dy):
        if check_time():
            game_over()  # Called every frame!
        hero.goto(...)
    • Shows: "GAME OVER" written many times (messy)
    • Fix: Use return after game_over() or use game state flag
  5. Wrong time comparison

    if time.time() - start_time < GAME_SECONDS:  # Wrong operator
        game_over()
    • Shows: Game ends immediately
    • Fix: Use >= for "time's up" condition

Success criteria

  • Student can run timed game and get final score
  • Student can explain how time tracking works
  • Student can modify game duration
  • Student can add win condition based on score
  • Student understands when to check time in game loop

Differentiation

For students who need support:

  • Start with longer time (60 seconds)
  • Remove time checking initially, just display timer
  • Provide template with comments
  • Use flowchart showing game loop logic

For advanced students:

  • Add "READY... SET... GO!" countdown at start
  • Implement high score tracking (best score so far)
  • Add bonus time pickups (collect to add 5 seconds)
  • Create difficulty levels (easy=30s, normal=20s, hard=10s)
  • Add pause functionality (press P to pause)
  • Implement "lives" system with obstacles
  • Make coins spawn more frequently as time passes

Materials needed

  • Thonny IDE
  • week11.py file
  • Timer/stopwatch for reference
  • Flowchart showing game loop with time checks

Key vocabulary

  • time.time(): Get current time in seconds
  • Elapsed time: How much time has passed
  • Countdown: Timer counting down to zero
  • Game state: Current condition of game (playing, paused, game over)
  • Win condition: Rule that determines victory
  • Lose condition: Rule that determines defeat

Real-world connections

  • All timed games use this pattern
  • Sports: Shot clock, game clock
  • Tests: Timed exams
  • Cooking: Timers for recipes
  • Apps: Countdown timers

Homework/practice

  • Add a "YOU WIN" condition at score = 20
  • Change to count-up timer (show elapsed time instead)
  • Add warning message when time < 5 seconds
  • Create "levels" - each level has different time limit
  • Research: How do real games handle frame-rate independent timing?