Turtle Chase¶
By the end of this lab you'll be able to:
- Run two turtles at once inside a single animation loop
- Aim one turtle at another using
math.atan2(dy, dx) - Detect a "catch" by comparing the squared distance between turtles
A green prey turtle wanders randomly around the canvas while a red hunter turtle chases it — every frame the hunter re-aims straight at the prey and takes a slightly bigger step. The chase ends the moment the hunter gets within 10 pixels.
Welcome to Turtle Chase!
Two turtles, one canvas: a wanderer and a hunter.
This is your first program where two characters interact!
Let's code it together!
How It Works¶
Each frame does three things. The prey turns a random amount (up to ±30°) and steps forward 3.5 pixels — a random walk. The hunter computes the vector to the prey (dx, dy), converts it to a heading with math.atan2(dy, dx), and steps forward 4.0 pixels — slightly faster than the prey, so it always gains ground. Finally, if the squared distance dx*dx + dy*dy drops below 100 (that's 10 pixels), the prey is caught.
Sample Code¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
What Do You Think Will Happen?
The hunter moves 4.0 pixels per frame; the prey only 3.5.
Will the hunter catch the prey before the 300 frames run out?
Make your guess, then click Run and watch the chase!
Try It Now¶
The hunter closes in and "Caught!" appears — with a 0.5 pixel-per-frame speed edge and dead-straight aim, the hunter always wins eventually. Were you right?
How It Works¶
math.atan2(dy, dx) returns the angle of the vector (dx, dy) — unlike plain atan(dy/dx) it handles all four quadrants and never divides by zero. math.degrees() converts radians to the degrees that setheading() expects. Notice the wall check: when the prey wanders past ±160, it aims back toward the center (0, 0) using the same atan2 trick — pointing at a target and fleeing to safety are the same math.
Explanation Table¶
| Line | What it does |
|---|---|
prey.right(random.uniform(-30, 30)) |
Random walk: small random turn each frame |
math.atan2(dy, dx) |
Angle from hunter to prey, safe in all quadrants |
hunter.forward(4.0) |
Hunter is 0.5 px/frame faster than the prey |
dx * dx + dy * dy < 100 |
Within 10 px — squared distance avoids sqrt |
Learning Check¶
Your Turn — Give the Prey a Brain
This version adds an escape instinct: when the hunter gets within 80 pixels,
the prey stops wandering and runs directly away. The prey is still slower —
will smarter steering let it survive all 300 frames? Predict, then run it!
The fleeing prey survives much longer than the random walker — running directly away cancels most of the hunter's speed advantage, but the walls keep forcing it to turn. Smart steering matters as much as speed!
Experiments¶
-
Even the speeds. Set the hunter's step to 3.5 too. You'll know it worked when the hunter can no longer close the gap and "Got away!" appears.
-
Add a second hunter. Create
hunter2starting at (150, -140) with the same chase logic. You'll know it worked when the prey gets cornered between two red turtles. -
Lazy aim. Make the hunter re-aim only every 10th frame (
if frame % 10 == 0:). You'll know it worked when the red path becomes a series of straight line segments that lag behind the prey. -
Shrink the catch radius. Change
100to25(5 pixels). You'll know it worked when the hunter has to practically touch the prey to win.
Master of the Hunt!
Two interacting characters, targeting math, and collision detection —
you just wrote the core loop of every chase scene in video games!
Up next: Reaction-Diffusion Pattern — animal-skin patterns from pure chemistry math.