Lesson 8 of 22, in world 2: Motion & Math
Angles & Trigonometry
You don’t need a trigonometry degree to make games — you need about three functions. They convert between angles (“face 30° to the right”) and directions (a vector), and they make smooth repeating motion.
Angles ↔ directions
- Angle → direction:
(cos θ, sin θ)is a vector of length 1 pointing at angle θ. - Direction → angle:
Math.atan2(dy, dx)gives the angle of a vector (note: y first).
Move the mouse to aim, click to fire. The turret turns toward the mouse using atan2(dy, dx). Each bullet's velocity is (cos θ, sin θ) × speed. The unit circle on the left shows the same angle.
// Aim at the mouse
const angle = Math.atan2(mouse.y - turret.y, mouse.x - turret.x)
// Fire in that direction
bullet.vel = { x: Math.cos(angle) * SPEED, y: Math.sin(angle) * SPEED }
// Draw the turret rotated
ctx.translate(turret.x, turret.y); ctx.rotate(angle); drawBarrel()Waves: sin() as an animation tool
sin(time) swings smoothly between −1 and 1 forever. Multiply by an amplitude for size, multiply time by a frequency for speed. One function gives you bobbing coins, pulsing lights and orbiting moons.
Rotating smoothly toward a target
Snapping straight to the target angle can look robotic. Instead, rotate by at most turnSpeed × dtper frame. The only trick is to take the shortest way round by wrapping the difference into [−π, π]:
let diff = targetAngle - angle
diff = Math.atan2(Math.sin(diff), Math.cos(diff)) // wrap to [-π, π]
angle += Math.sign(diff) * Math.min(Math.abs(diff), TURN_SPEED * dt)Key takeaways
- (cos θ, sin θ) turns an angle into a unit direction vector.
- atan2(dy, dx) turns a direction into an angle — y first!
- Angles are in radians; y-down means clockwise is positive.
- sin(time) is a free smooth oscillator for bobbing, pulsing and orbiting.
Check yourself
Q1. What is (cos 0, sin 0)?
Q2. Which call correctly gets the angle from enemy to player?
Q3. A coin should bob up and down 10 px, once per second. y offset = …
Exercises
- Make the turret fire a 3-bullet spread: angles θ − 0.2, θ, θ + 0.2.
- Combine an orbit with a pulse: a moon whose orbit radius itself changes with sin().
- Implement the "rotate toward" snippet so the turret turns at most 180°/s instead of snapping.