Part 2: Camera & Path Systems - Cinematic Control
Master the art of professional camera work and smooth motion paths in Phaser.js
This is Part 2 of a 9-part series. Read Part 1: The Journey
The Cinematographer's Toolkit
The difference between an amateur game and a professional one often comes down to camera work. Players don't consciously notice good camera controls—they just feel right. But bad camera work? That's instantly jarring.
In this deep-dive, we explore 20 patterns (10 camera + 10 path) that separate functional cameras from cinematic experiences.
Camera System: Your Window Into the World
Phaser 3's camera system isn't just about showing what's on screen—it's about storytelling. Each of these 10 patterns serves a specific narrative or gameplay purpose.
1. Camera Fade Effects: Scene Transitions That Don't Break Immersion
this.cameras.main.once('camerafadeincomplete', function (camera) {
camera.fadeOut(6000); // Chain effects
});
this.cameras.main.fadeIn(6000);
Why It's Essential: Hard cuts between scenes feel amateurish. Fades provide breathing room—they signal to the player that something is changing. The event-driven architecture means your game code can wait for the fade to complete before triggering the next sequence.
Real-World Use: Death sequences that fade to black before respawn, level transitions that feel cinematic rather than jarring, cutscene boundaries that don't snap jarringly.
2. Multiple Camera System: Split-Screen & Minimaps
this.cameras.main.setSize(400, 300); // Top-left quadrant
this.cameras.add(400, 0, 400, 300); // Top-right
this.cameras.add(0, 300, 400, 300); // Bottom-left
Why It's Essential: Modern games need multiple viewports. Not just for split-screen multiplayer, but for strategy game minimaps, security camera views, rear-view mirrors in racing games, and debug visualizations during development.
Performance Trick: Use camera.ignore(object) to skip rendering decorative elements in your minimap. A minimap doesn't need particle effects or background parallax—only important gameplay objects.
3. Camera Follow with Deadzone: The Secret to Smooth Platforming
this.cameras.main.startFollow(this.player, true, 0.1, 0.1);
this.cameras.main.setDeadzone(400, 200);
Why It's Essential: This is the pattern that makes Super Mario Bros feel so good. The deadzone creates a "comfort zone" where players can move without the camera bobbing around. When they approach the edge, the camera smoothly starts following. The lerp values (0.1, 0.1) add smoothing—10% interpolation per frame creates that buttery-smooth camera motion.
The Math
- Lerp 1.0 = instant snap (no smoothing, feels mechanical)
- Lerp 0.1 = 10% per frame (smooth, feels natural)
- Lerp 0.05 = 5% per frame (very smooth, can feel sluggish)
4. Camera Pan and Zoom: Cinematic Storytelling
camera.pan(767, 1096, 2000, 'Power2');
camera.zoomTo(4, 3000, 'Elastic');
Why It's Essential: This is how you direct player attention. Boss intro sequences that pan to the boss and zoom in dramatically. Tutorial sequences that focus attention on specific UI elements. Victory screens that zoom out to show the full level conquered.
Easing Makes The Difference
Linear- Constant speed (feels mechanical, use rarely)Power2- Natural acceleration/deceleration (use most often)Elastic- Overshoot and settle (playful, attention-grabbing)Sine.easeInOut- Cinematic smoothness (for cutscenes)
5. Camera Shake: Impact Feedback That Feels Physical
camera.shake(500, 0.05); // 500ms, 5% intensity
Why It's Essential: Shake is how you communicate impact. Explosions, heavy landings, boss stomps—all need shake. But here's the trick: scale intensity with impact magnitude. A gunshot gets 0.01 intensity for 100ms. An explosion gets 0.1 intensity for 800ms.
Accessibility Warning: Some players experience motion sickness from camera shake. Always provide an option to disable it in your settings.
6. Camera Flash: Instant Visual Feedback
camera.flash(200, 255, 0, 0); // Red flash for damage
camera.flash(300, 0, 255, 0); // Green flash for healing
Why It's Essential: Flash provides instant, unmissable feedback. The color tells the story:
- Red: Damage, danger, alert
- Green: Healing, success, checkpoint
- White: Impact, teleportation, lightning
- Yellow: Coin pickup, power-up
Combine flash with shake for maximum impact: camera.flash() + camera.shake() = explosion feedback that feels visceral.
7. Camera Rotation: Disorientation & Unique Perspectives
camera.rotation += 0.01; // Gradual rotation
this.text.setScrollFactor(0); // UI doesn't rotate
Why It's Essential: Rotation is rare but powerful. Use it for:
- Disorientation effects: Slow rotation when player is stunned/dizzy
- Barrel rolls: Full 360° for dramatic flourish
- Isometric perspective: Fixed 45° rotation
- Space games: Free rotation matching ship orientation
Performance Note: Rotation requires recalculating all world positions every frame. It's more expensive than pan/zoom, so use it deliberately.
8. Minimap Camera: The Strategy Player's Best Friend
this.minimap = this.cameras.add(200, 10, 400, 100)
.setZoom(0.2)
.setBackgroundColor(0x002244);
// Only show important objects in minimap
this.minimap.ignore(decorativeObjects);
Why It's Essential: Strategy games, metroidvanias, racing games—all need overview cameras. The key is selective rendering: only show important gameplay objects in the minimap. Background stars, particles, and decorative elements are performance waste.
9. Parallax Scrolling: Creating Depth Perception
farBackground.setScrollFactor(0.2); // Moves at 20% speed
midBackground.setScrollFactor(0.5); // 50% speed
foreground.setScrollFactor(1.0); // 100% (default)
Why It's Essential: Parallax is how you create depth in 2D games. When the camera moves 100px to the right:
- Layer with scrollFactor 0.0 doesn't move (fixed background sky)
- Layer with scrollFactor 0.2 moves 20px (far mountains)
- Layer with scrollFactor 1.0 moves 100px (foreground)
This creates the illusion of 3D depth through motion parallax—exactly how our eyes perceive depth in the real world.
10. Camera Bounds: Never Show Empty Space
this.cameras.main.setBounds(0, 0, 4096, 4096);
Why It's Essential: Without bounds, the camera can scroll beyond your world, showing empty black space. With bounds, the camera stops at world edges, maintaining the illusion of a complete world.
Dynamic Bounds: Metroidvania games expand bounds as players explore. Room-based games shrink bounds to the current room. This prevents players from seeing unloaded areas.
Path System: Mathematically Perfect Motion
While cameras control what the player sees, paths control how things move. These 10 patterns enable smooth, predictable, professional-grade motion.
1. Path Builder API: Readable Motion Composition
const path = new Phaser.Curves.Path(50, 500)
.splineTo([164, 446, 274, 542, 412, 457])
.lineTo(700, 300)
.ellipseTo(200, 100, 0, 360, false, 0)
.cubicBezierTo(222, 119, 308, 107, 208, 368);
Why Fluent Interface: The method chaining creates a natural language for describing motion. You can read the path structure directly from the code without visualizing it first. Each method returns this, enabling the chain.
2. Curve Type Primitives: Choose The Right Tool
| Curve Type | Control Points | Best For | Performance |
|---|---|---|---|
| Line | 0 | Waypoint patrol | Fastest |
| Ellipse | Center + radii | Circular orbits | Fast |
| Spline | N points | Organic paths | Moderate |
| Quadratic Bezier | 1 | Simple arcs | Fast |
| Cubic Bezier | 2 | Complex S-curves | Moderate |
3. Manual Path Following: Maximum Control
const follower = { t: 0, vec: new Phaser.Math.Vector2() };
this.tweens.add({
targets: follower,
t: 1, // Animate t from 0 to 1
ease: 'Linear',
duration: 4000
});
// In update:
path.getPoint(follower.t, follower.vec);
Why Manual: You get complete control over timing and easing. You can drive multiple objects from the same t value. You can pause, resume, and reverse easily. And there's no game object overhead—just pure math.
4. PathFollower Game Objects: Automated Motion
const follower = this.add.follower(path, 0, 0, 'sprite');
follower.startFollow({
duration: 10000,
repeat: -1,
yoyo: true,
rotateToPath: true,
verticalAdjust: true
});
Why PathFollower: Less code for common cases. Built-in rotation management. Event callbacks (pathstart, pathcomplete, pathupdate). Integrates with physics, animations, and other Phaser systems.
Tower Defense Pattern: Every enemy is a PathFollower on the lane path. When they complete the path, you lose health. Simple, predictable, professional.
5. Rotate to Path: Facing Forward
follower.startFollow({
rotateToPath: true, // Auto-rotate to face motion direction
verticalAdjust: true // +90° offset for vertical sprites
});
Why Essential: Sprites facing the wrong direction look broken. rotateToPath automatically calculates the tangent vector at each position and rotates the sprite to match. verticalAdjust adds a 90° offset for sprites that face upward instead of rightward.
6. Path Serialization: Designer-Friendly Workflows
{
"type": "Path",
"x": 50,
"y": 500,
"curves": [
{ "type": "LineCurve", "points": [50, 500, 150, 200] },
{ "type": "CubicBezierCurve", "points": [150, 200, 200, 100, 400, 100, 400, 500] }
]
}
Why JSON: Design paths in visual tools (Tiled, custom editors), export to JSON, load in-game. This enables iteration without code changes. Level designers can tweak paths without touching JavaScript.
7. Spline Curves: Smooth Curves Through Points
const points = [50, 400, 200, 200, 350, 300, 500, 500, 700, 400];
const spline = new Phaser.Curves.Spline(points);
Spline vs Bezier:
- Spline: Curve passes through all control points (interpolating)
- Bezier: Control points don't lie on the curve (approximating)
Use splines when you have specific waypoints the path must pass through (patrol routes). Use Beziers when you need precise control over curve shape (projectile arcs).
8. Tangent Vectors: Physics-Based Following
const tangent = new Phaser.Math.Vector2();
path.getTangent(t, tangent); // Get direction at t
const speed = 200;
tangent.scale(speed);
sprite.setVelocity(tangent.x, tangent.y);
Why Tangents: Instead of forcing a sprite to a position, apply velocity in the direction of the path. This creates physics-based following—the sprite actually moves along the path using forces, enabling realistic acceleration, banking in turns, and interaction with other physics objects.
9. Mass Followers: Wave Patterns
for (let i = 0; i < 20; i++) {
const follower = this.add.follower(path, 0, 0, 'ship');
follower.startFollow({
duration: 5000,
delay: i * 70 // Stagger by 70ms
});
}
Why Stagger: Spawning 20 enemies instantly looks unnatural. Staggering with delay: i * 70 creates a wave effect—enemies flow down the path like a river. This is the foundation of tower defense games.
10. Path Bounds and Visualization: Debug Like A Pro
const bounds = path.getBounds();
graphics.strokeRect(bounds.x, bounds.y, bounds.width, bounds.height);
Why Bounds: Use bounds for culling—only update followers inside the camera bounds. This is how you scale to hundreds of enemies without killing performance.
Visualization Pattern: Draw paths, control points, tangent vectors, and bounds during development. Ship games with this disabled, but keep the code so you can re-enable it for debugging.
Combining Camera & Path: The Power Duo
The real magic happens when you combine these systems:
Cinematic Intro Sequence
// Camera follows path
const cameraPath = new Phaser.Curves.Path()...;
const follower = { t: 0 };
this.tweens.add({
targets: follower,
t: 1,
duration: 8000,
ease: 'Sine.easeInOut'
});
// In update:
const pos = new Phaser.Math.Vector2();
cameraPath.getPoint(follower.t, pos);
this.cameras.main.centerOn(pos.x, pos.y);
This creates camera rail systems—the camera follows a predefined path while the player watches. Perfect for intros, outros, and establishing shots.
Boss Intro
- Camera fades in
- Camera pans to boss along spline path
- Camera zooms in
- Camera shakes (boss roars)
- Camera pans back to player
- Gameplay resumes
This is cinematic game development—using camera and path patterns to create memorable moments.
Real-World Applications
E-Learning Simulations:
- Camera path tours through 3D medical diagrams
- Pan and zoom to highlight key anatomy
- Minimap showing student's position in complex environments
- Flash effects for correct/incorrect feedback
Training Scenarios:
- PathFollowers for NPC behaviors (patrol routes, evacuation paths)
- Camera shake for equipment failure scenarios
- Multi-camera split-screen for team coordination training
- Parallax for depth perception in spatial reasoning tests
Key Takeaways
Camera Patterns Enable:
- Professional polish through smooth transitions
- Strategic gameplay through minimaps and multiple viewports
- Storytelling through cinematic camera movements
- Impact feedback through shake and flash
Path Patterns Enable:
- Predictable, smooth motion without hand-coding
- Reusable movement patterns across levels
- Physics-based movement using tangent vectors
- Wave-based enemy spawning and formations
Together They Create:
- Cutscene systems
- Camera rail sequences
- Cinematic gameplay moments
- Professional game feel
Coming Up
In Part 3, we dive into Animation Mastery with Tweens and Particles—the systems that transform functional games into visually stunning experiences. Learn the 20 patterns that separate "it works" from "wow, that looks amazing."
Patterns documented: 389 total (Camera: 10, Path: 10, Previous: 369)
Part of the Phaser.js Training Series.
📝 Edits & Lessons Learned
No edits yet - this is the initial publication.