Have you ever wanted to make a character face towards the player, a turret track its target, or a missile home in on its destination? The atan2
function is your friend here. Let’s break it down from first principles and build up to practical game development applications.
Trigonometry Refresher
Can you think way back to your high school math classes? One of the topics you might remember is trigonometry, which deals with the relationships between the angles and sides of triangles.
A quick mnemonic to remember the trigonometric functions is SOHCAHTOA
:
S
ine =O
pposite /H
ypotenuseC
osine =A
djacent /H
ypotenuseT
angent =O
pposite /A
djacent
As a quick refresher, play around with the interactive demo below to see how the sine, cosine, and tangent functions work:
What is atan2
?
Now that we’ve refreshed our trigonometry basics, let’s dive into atan2
.
If you remember, each trigonometric function has an inverse function. An inverse function is like a “reverse” function that undoes the original function.
In this case, the inverse functions of each trig function simply means “given the ratio of the two sides, return the angle of a right triangle satisfying this”. This is usually denoted by adding a small -1
to the function name. For example, the inverse of \sin is \sin^{-1}.
However, this is hard to type out, so some mathematicians like to add an arc
prefix instead. So the inverse of \sin is also called \arcsin. This is then abbreviated as asin
in many cases.
So, what about atan2
? It’s the inverse of the tangent function, but with a twist. Instead of taking a single ratio of sides, it takes two separate values: the y
and x
coordinates of a point. This makes it more powerful and flexible than the regular atan
function.
Let’s recap this real quick. We know that the definition of \tan is:
\tan(\theta) = \frac{\text{opposite}}{\text{adjacent}}So, the inverse of this function, atan
, would take a single ratio and return the angle. In other words:
For convenience, the atan2
function unpacks this for us, taking the y
and x
coordinates separately:
atan2
in Action
Let’s see how atan2
works in practice. Imagine you have two points on a 2D plane: a source point and a target point. You want to find the angle between these two points.
You can represent this function as a triangle:
atan2
is a mathematical function that helps us find the angle between two points. While it might sound intimidating, it’s actually quite straightforward once you understand what it does.
Think of it this way: if you have two points on a 2D plane, atan2
tells you what angle you need to rotate to face from one point towards the other.
// Basic atan2 usage
const angle = Math.atan2(targetY - sourceY, targetX - sourceX)
Interactive Demo: Understanding atan2
import { useState } from 'react'
export default function Atan2Demo() {
const [mousePos, setMousePos] = useState({ x: 200, y: 200 })
const centerX = 200
const centerY = 200
const angle = Math.atan2(
mousePos.y - centerY,
mousePos.x - centerX
)
return (
<div
className="relative w-96 h-96 bg-slate-100 rounded-lg"
onMouseMove={(e) => {
const rect = e.currentTarget.getBoundingClientRect()
setMousePos({
x: e.clientX - rect.left,
y: e.clientY - rect.top
})
}}
>
{/* Center point */}
<div
className="absolute w-4 h-4 bg-blue-500 rounded-full"
style={{
left: centerX - 8,
top: centerY - 8
}}
/>
{/* Rotating arrow */}
<div
className="absolute w-20 h-1 bg-red-500 origin-left"
style={{
left: centerX,
top: centerY,
transform: `rotate(${angle}rad)`
}}
/>
{/* Angle display */}
<div className="absolute top-4 left-4 bg-white p-2 rounded shadow">
Angle: {(angle * 180 / Math.PI).toFixed(1)}°
</div>
</div>
)
}
In this interactive demo, move your mouse around to see how atan2
calculates the angle between the center point and your cursor. The red line will always point towards your mouse cursor.
Why atan2 Instead of Regular arctangent?
You might wonder why we use atan2
instead of just regular arctangent (atan
). The key difference is that atan2
takes two parameters (y and x) instead of one (y/x), which gives us two major advantages:
- No division by zero: If x is zero, regular arctangent would fail, but
atan2
handles this case correctly. - Full angle range: Regular arctangent only gives us angles between -90° and 90°, while
atan2
gives us the full 360° range.
Practical Application: Making Objects Face Each Other
Let’s create a practical example where we make a “turret” face towards a moving target.
import { useState, useEffect } from 'react'
export default function TurretDemo() {
const [targetPos, setTargetPos] = useState({ x: 300, y: 200 })
const turretPos = { x: 100, y: 200 }
// Animate target in a circle
useEffect(() => {
const interval = setInterval(() => {
const time = Date.now() / 1000
setTargetPos({
x: 300 + Math.cos(time) * 50,
y: 200 + Math.sin(time) * 50
})
}, 16)
return () => clearInterval(interval)
}, [])
const angle = Math.atan2(
targetPos.y - turretPos.y,
targetPos.x - turretPos.x
)
return (
<div className="relative w-96 h-96 bg-slate-100 rounded-lg">
{/* Turret */}
<div
className="absolute w-16 h-16"
style={{
left: turretPos.x - 32,
top: turretPos.y - 32
}}
>
<div className="w-full h-full bg-gray-700 rounded-full" />
<div
className="absolute w-24 h-4 bg-gray-800 origin-left top-6"
style={{
transform: `rotate(${angle}rad)`
}}
/>
</div>
{/* Target */}
<div
className="absolute w-8 h-8 bg-red-500 rounded-full"
style={{
left: targetPos.x - 16,
top: targetPos.y - 16
}}
/>
</div>
)
}
This demo shows a turret that automatically tracks a moving target. The target moves in a circle, and the turret’s barrel always points towards it using atan2
.
Common Gotchas and Tips
-
Radians vs Degrees:
atan2
returns angles in radians. To convert to degrees, multiply by180/Math.PI
. -
Coordinate Systems: Remember that most computer graphics use a coordinate system where Y increases downward. This might mean you need to negate your Y values or adjust your angles accordingly.
-
Performance: While
atan2
is generally fast enough for most uses, if you’re calculating it for many objects every frame, consider caching the result if the positions haven’t changed.
Practical Examples
Here are some common use cases for atan2
in game development:
// Making an enemy face the player
function updateEnemyRotation(enemy, player) {
enemy.rotation = Math.atan2(
player.y - enemy.y,
player.x - enemy.x
)
}
// Calculating direction for projectile motion
function shootProjectile(source, target, speed) {
const angle = Math.atan2(
target.y - source.y,
target.x - source.x
)
return {
velocityX: Math.cos(angle) * speed,
velocityY: Math.sin(angle) * speed
}
}
// Creating a homing missile
function updateHomingMissile(missile, target, turnSpeed) {
const targetAngle = Math.atan2(
target.y - missile.y,
target.x - missile.x
)
// Gradually rotate towards target
const angleDiff = targetAngle - missile.rotation
missile.rotation += Math.sign(angleDiff) *
Math.min(Math.abs(angleDiff), turnSpeed)
}
Conclusion
atan2
is a powerful tool in game development that solves the common problem of making objects face or move towards other objects. While the math behind it might seem complex, using it is straightforward once you understand the basics.
Remember the simple pattern:
const angle = Math.atan2(targetY - sourceY, targetX - sourceX)
With this knowledge, you can create engaging gameplay mechanics like homing missiles, tracking turrets, or enemies that face the player. The interactive demos above should help you visualize how atan2
works in practice.