Turn vector operations into gameplay: move toward a target, compute distances cheaply, reflect a ball off a wall, and steer smoothly. The everyday vector recipes you reach for constantly.
The most common vector recipe: get the direction from A to B by subtracting and normalizing, then move along it at a speed scaled by delta time. Multiplying by delta time makes movement frame-rate independent — the same real-world speed whether the game runs at 30 or 144 fps. This pattern drives chasing enemies, projectiles, and homing behavior.
def sub(a, b): return (a[0]-b[0], a[1]-b[1])
def move_toward(pos, target, speed, dt):
to_target = sub(target, pos) # direction + distance
dir = normalize(to_target)
# move at 'speed' units/second, scaled by frame time -> fps-independent
return (pos[0] + dir[0] * speed * dt,
pos[1] + dir[1] * speed * dt)
enemy = (0, 0)
player = (10, 0)
enemy = move_toward(enemy, player, speed=5, dt=1/60) # steps toward player
# ALWAYS multiply movement by dt so speed is the same at any frame rate.Distance between two points is the length of the vector between them. But square roots are relatively expensive, and for comparisons — "is the enemy within attack range?" — you do not need the actual distance. Compare squared distances instead and skip the sqrt entirely. This "use distance-squared for comparisons" trick is a pervasive game-performance habit.
def distance_sq(a, b):
dx, dy = a[0]-b[0], a[1]-b[1]
return dx*dx + dy*dy # NO square root
def in_range(a, b, radius):
# compare squared distance to squared radius -> avoids a sqrt
return distance_sq(a, b) <= radius * radius
print(in_range((0,0), (3,4), 5)) # True (distance 5)
print(in_range((0,0), (3,4), 4)) # False
# only take the real sqrt when you need the actual distance (e.g. to display).
# for range checks, sorting by nearness, etc. -> distance_sq is faster + exact.Bouncing a ball off a wall is vector reflection: given the incoming direction and the wall’s normal, the reflected direction is d − 2(d·n)n. The dot product finds how much of the motion is into the surface, and you subtract twice that component. This one formula handles ball-and-paddle games, ricochets, and mirror-like bounces.
def reflect(d, n):
# reflect direction d off a surface with unit normal n
# formula: r = d - 2 * (d . n) * n
dn = dot(d, n)
return (d[0] - 2 * dn * n[0],
d[1] - 2 * dn * n[1])
# a ball moving down-right hits a floor (normal points up):
velocity = (1, -1)
floor_normal = (0, 1)
bounced = reflect(velocity, floor_normal) # (1, 1) -> now moving up-right
print(bounced)
# n must be a UNIT vector. This drives ball bounces, ricochets, mirrors.Lerp blends between two values by a factor t from 0 to 1, giving a straight-line transition. Applied to vectors it smoothly moves a value toward a target — a camera easing to follow the player, a health bar animating, a color fading. Lerp is one of the most-used tools in all of game programming; you will reach for it every day.
def lerp(a, b, t): # scalar lerp: a at t=0, b at t=1
return a + (b - a) * t
def lerp_vec(a, b, t):
return (lerp(a[0], b[0], t), lerp(a[1], b[1], t))
print(lerp(0, 100, 0.25)) # 25.0
# smooth "follow" — ease the camera toward a target each frame:
camera = (0, 0)
target = (10, 5)
camera = lerp_vec(camera, target, 0.1) # moves 10% of the way, every frame
# repeated lerp-toward-target = smooth exponential easing. Everywhere in games.