Physics · Mechanics · core
Projectile Motion
constant sideways speed, steadily changing vertical speed
Launch angle, speed and gravity fully determine a ballistic arc: x moves at constant speed while y accelerates downward.
The orange ball follows the cyan arc and the yellow line is its instantaneous velocity. Change the angle, launch speed and gravity to reshape the arc; the readout shows flight time and range.
What it is
A projectile is any body moving under gravity alone. Split its velocity into components: the horizontal part v0·cos θ never changes (no drag), while the vertical part v0·sin θ loses g metres per second every second.
Because the two axes are independent, the path is a parabola. Flight time, peak height and range all follow from the launch speed, angle and gravity, so you can predict a landing point before the shot happens.
In games this is how grenades, arrows, jump arcs and aim-assist trajectory previews are computed. It is also the reference you check a fixed timestep integrator against.
Key formulas
- Horizontal position
- Vertical position
- Flight time (flat ground)
- Range
Maximum at 45° on flat ground, with no drag.
- Peak height
Rules of thumb
- Complementary angles (30° and 60°) land at the same spot; the steeper one stays in the air longer.
- Earth
g = 9.81 m/s². Many platformers use 2–3× that for snappier jumps. - To hit a target, solve the range equation for θ. Two solutions mean a low and a high lob.
Implementation
import * as THREE from "three"
export function trajectory(v0: number, angle: number, g = 9.81, samples = 64) {
const vx = v0 * Math.cos(angle)
const vy = v0 * Math.sin(angle)
const T = (2 * vy) / g
const points: THREE.Vector3[] = []
for (let i = 0; i <= samples; i++) {
const t = (i / samples) * T
points.push(new THREE.Vector3(vx * t, vy * t - 0.5 * g * t * t, 0))
}
return new THREE.BufferGeometry().setFromPoints(points) // draw with THREE.Line
}Common mistakes
- Mixing degrees and radians:
Math.sin(45)is not sin 45°. - Integrating with explicit Euler at a variable frame rate, which makes the landing point depend on FPS.
- Forgetting launch height: the flat-ground formulas assume the projectile lands at the height it started from.
- Adding drag later and still trusting the analytic range. Once there is drag, simulate numerically.
Prompt
Implement a projectile trajectory preview in TypeScript with Three.js. Given launch speed v0 (m/s), angle θ (radians) and gravity g, compute x(t)=v0·cosθ·t and y(t)=v0·sinθ·t−½gt², sample 64 points until it returns to launch height (T=2v0·sinθ/g), and draw them with THREE.Line. Also return range R=v0²·sin2θ/g and peak height H=(v0·sinθ)²/(2g). Keep angles in radians, make the sampler a pure function, and add a unit test checking that 30° and 60° give the same range.
Related
Further reading
Updated 2026-11-01