Game Programming · June 30, 2026
Tweening and Easing for Enemy Movement Choreography in Shmups
Enemies that move at constant linear speed in straight lines read as placeholder content. They are mechanically correct — predictable, avoidable, clear — but they communicate nothing about what the enemy is, what it intends to do, or how dangerous it is. Easing functions solve this without adding behaviour complexity: the same linear path, given an ease-in-out curve, suddenly looks like a creature that accelerates into position and decelerates to a stop. That difference in feel is larger than its implementation cost.
Published June 30, 2026
The easing vocabulary
Easing functions map a linear progress value (0.0 to 1.0) to a curved output. The output is applied to position, scale, rotation, or any other property. The names describe the curve shape:
- Ease-in: Starts slow, ends fast. Good for enemies charging at the player, objects falling into frame, or acceleration to attack speed.
- Ease-out: Starts fast, ends slow. Good for enemies gliding into formation position, decelerating to a hover, or retreat movements.
- Ease-in-out: Slow at both ends, fast through the middle. Good for smooth formation flight and repositioning between attack phases.
- Back: Overshoots the target, then settles. Good for enemies that snap into place with a slight bounce — reads as weight and momentum.
- Elastic: Oscillates around the target before settling. Use sparingly — it reads as bouncy and playful, which may not suit a threatening enemy.
- Bounce: Simulates gravity-based bounce. Appropriate for projectiles that ricochet or special objects, rarely for main enemies.
Entry choreography: the most important moment
The entry movement is when the player first sees an enemy. It establishes personality before the enemy has fired a single shot. Three entry patterns cover most shmup enemy types:
Sweep and stop: Enemy enters from the edge, moves to a mid-screen position, decelerates with ease-out over 0.4–0.6 seconds, and holds position. The deceleration is the key moment. Without it, the enemy appears to hit an invisible wall. With ease-out, it glides to a stop and reads as intentional. This is the correct entry for turret-type enemies that attack from a fixed position.
Pass-through: Enemy enters from one side and exits the opposite without stopping. Ease-in-out on the full path gives it a patrol feel. Pairing pass-throughs with staggered timing (each ship slightly delayed) creates a formation sweep that looks coordinated and is readable from below.
Dive and retreat: Enemy dives toward the player position with ease-in (accelerating), fires at the dive endpoint, then retreats with ease-out (decelerating). The direction change between dive and retreat should be abrupt — no smooth arc — because the sharp direction change is what reads as an attack.
Chained tween sequences
Complex enemy movement is built from sequences of simple tweens chained together. Each tween moves the enemy along one segment of the full path, and the next tween fires when the previous completes. A boss that circles the arena, pauses at cardinal positions to fire, then repositions diagonally is four tweens in a loop, not complex movement code.
The callback between position tweens is where patterns fire, sub-spawns trigger, or phase changes activate. This makes the movement script function as a readable choreography score rather than an update loop full of timer checks.
Spline paths for organic movement
For enemies that need curved flight paths — figure-8s, spirals, interweaving formation loops — spline paths are more natural than tweens. The enemy follows a Bezier or Catmull-Rom curve at a configurable speed, optionally with speed variation along the curve to create moments of acceleration and coast.
Spline paths are best authored in an in-engine path editor rather than defined in code. Most 2D engines provide a Path2D or equivalent node type. Once the paths are authored as assets, enemy spawning code references them by ID. This separates movement path design from code and allows iterating on formations without touching the behaviour layer.
Rotation follows movement direction
Enemies that bank, tilt, or orient toward their movement direction feel physical. The simplest implementation rotates the sprite toward the velocity vector each frame, with a maximum rotation speed that produces a smooth banking lag rather than instant snapping:
The lerp factor (0.12 here) controls the lag. Higher values snap faster. For formation enemies, a tighter lag (0.2–0.3) reads as alert; for slow heavies, a loose lag (0.06–0.1) reads as lumbering weight.
The overuse trap
When every enemy in the game uses complex easing sequences and spline paths, the screen becomes a continuous visual noise of movement that the player cannot parse. Easing is most effective as a contrast: simple enemies move plainly, and the use of a slow ease-out or a back-easing snap calls visual attention to the enemy using it as more significant or dangerous.
Design formation enemies to use consistent, simple movement — their predictability is what makes them navigable. Reserve elaborate tween choreography for boss phases and named sub-bosses where the spectacle and the added readability time both serve a purpose. The moment when a boss decelerates from a charge and hovers, breathing slightly through a scale tween, communicates more about the game's production quality than a hundred identically-moving formations ever could.