How the AI Director maintains perfect pacing in a 100-level campaign across vertical space combat.
Infinite Voyager is a vertical scrolling space shooter with 100 levels spanning 4 phases — a campaign of significant length. The core challenge: how do you maintain perfect difficulty pacing across such a journey without feeling scripted or railroad-like?
The answer lies in the AI Director — a system inspired by the AI Director pattern popularized in survival games that dynamically adjusts enemy spawning, accuracy, and encounters based on real-time player performance. It doesn't control the narrative; it controls tension. When you're dominating, it escalates. When you're struggling, it breathes. The game feels alive because it's responding to you.
This is the vision of Infinite Voyager: a polished arcade space shooter where intelligent adaptive systems create emergent difficulty curves, not handcrafted ones.
Player controls ship position by following finger with smooth lerp interpolation. No directional buttons — pure spatial awareness. Solar sail physics scale thrust by inverse-square distance from obstacles.
Scout (weaving, HP:1), Drone (tracking + projectiles, HP:2), Mothership (spawns scouts, HP:5), Phantom (cloaking, HP:3). Each requires different tactical responses.
Every 45–90 seconds: Wormhole (teleport), Distress Signal (protect ship), Solar Flare (double thrust), Alien Market (shop). Encounters inject variety without feeling forced.
Void Sentinel (level 10, lasers + gravity wells), The Architect (level 25, control reversal + clones), Leviathan (level 50, tentacles + shockwaves). Each has unique behavioral patterns and requires skill progression.
The magic happens in the AI Director — a real-time system that updates every 5 seconds, evaluating your performance and adjusting challenge accordingly.
Director monitors: dodge rate (obstacles dodged vs encountered), coin efficiency (coins collected vs available), and recent deaths. These form a performance vector that drives all difficulty decisions.
If dodge rate > 0.8 (dominating), spawn rate increases. If < 0.3 (struggling), it decreases. Formula: baseSpawnInterval = 6.0 / diffMultiplier / directorMultiplier. Smooth transitions maintain flow.
Scales between 0.5x (easier) to 1.0x (normal). Combined with spawn adjustments, this creates exponential difficulty curves. Players feel challenged, not cheaply punished.
After 3 deaths in 60 seconds, Stealth Assist triggers: alien accuracy drops 50% for 30s. When survival time falls below 15s, power-up spawn rate jumps 1.4x. The director reads desperation.
For the technically curious, here's how the Infinite Voyager AI Director maintains perfect pacing across 100 levels.
The Director runs a tight evaluation cycle, reading player state and adjusting difficulty multipliers:
function updateDirector(playerState, gameState) {
const dodgeRate = playerState.obstaclesDodged / playerState.obstaclesEncountered;
const coinEfficiency = playerState.coinsCollected / playerState.coinsAvailable;
const recentDeaths = playerState.deathsInLast60s;
// Spawn rate adjustment
let spawnMultiplier = 1.0;
if (dodgeRate > 0.8) spawnMultiplier += 0.3; // Dominating
else if (dodgeRate < 0.3) spawnMultiplier -= 0.3; // Struggling
// Accuracy adjustment
let accuracyMultiplier = 1.0;
if (dodgeRate > 0.8) accuracyMultiplier = 1.0; // Full difficulty
else if (dodgeRate < 0.3) accuracyMultiplier = 0.5; // Half difficulty
// Stealth Assist: after 3 deaths in 60s
if (recentDeaths >= 3) {
accuracyMultiplier *= 0.5;
stealthAssistActive = true;
stealthAssistTimer = 30;
}
// Power-up Boost when survival < 15s
let powerUpMultiplier = 1.0;
if (playerState.survivalTime < 15) {
powerUpMultiplier = 1.4;
}
return {spawnMultiplier, accuracyMultiplier, powerUpMultiplier};
}
This creates a feedback loop: performance → difficulty → challenge → motivation. Players always face the "right" difficulty.
Each of the 4 enemy types has distinct behavioral logic:
// Scout: Weaving side-to-side
function moveScout(scout, time) {
scout.x += Math.sin(time * 2) * 120 * deltaTime;
}
// Drone: Tracks player, fires every 3s
function moveDrone(drone, playerX) {
drone.x = lerp(drone.x, playerX, 0.1);
if ((gameTime % 3000) < 100) spawnBolt(drone);
}
// Mothership: Spawns scouts every 8s (max 12)
function moveMotherShip(ship) {
if ((gameTime % 8000) < 100 && ship.scouts.length < 12) {
ship.scouts.push(new Scout());
}
}
// Phantom: Mirrors player X, cloaks 2s every 4s
function movePhantom(phantom, playerX, time) {
phantom.x = playerX;
phantom.cloaked = (Math.floor(time / 4) % 2 === 1);
}
Behavior variety forces tactical adaptation. Players can't use the same strategy for all enemies.
The background uses positional seeding (not Perlin noise) for deterministic star placement:
Each screen position generates the same stars consistently. Multiple depth layers with different scroll speeds create parallax depth. Velocity-based speed lines enhance the sense of forward motion.
Encounters spawn every 45–90 seconds with four types:
Encounter selection is probabilistic but weighted by level phase. Campaign phases naturally introduce encounters that suit progression.
Three unique boss types at campaign milestones:
Each boss teaches a lesson: learn attack patterns, adapt to role reversals, manage clones. Boss fights act as skill gates for progression.
The ultimate spawn interval combines base level difficulty with real-time Director adjustments:
diffMultiplier increases with campaign level (harder late-game). directorMultiplier adjusts based on performance. Result: enemies spawn more frequently and accurately as you prove competence, creating smooth progression curves without artificial walls.
Campaign progress, leaderboard scores, and achievement tracking sync through Convex. Players can resume campaigns mid-level. Session logging enables post-mortem analytics: which encounters killed players most? Which boss has the highest skip rate? Data drives balance updates.
Infinite Voyager: A vertical space shooter where the AI Director ensures every run feels perfectly tuned to your skill level.
Back to ExaFabs