- 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
- 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
- Week 10: Basic collection game
- Week 11: Add time limit (more challenging!)
- This is a complete game now with win/lose condition
- 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
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)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 = 0Part 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 negativeint()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()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)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?"
-
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
-
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
-
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()
-
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
-
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
- 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
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
- Thonny IDE
- week11.py file
- Timer/stopwatch for reference
- Flowchart showing game loop with time checks
- 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
- All timed games use this pattern
- Sports: Shot clock, game clock
- Tests: Timed exams
- Cooking: Timers for recipes
- Apps: Countdown timers
- 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?