
Phaser4 Gamedev
- 4 installs
- 143 repo stars
- Updated April 15, 2026
- chongdashu/vibejam-starter-pack
Build 2D browser games with Phaser 4's WebGL-first renderer, filters, shaders, GPU layers, and tilemaps, or migrate from Phaser 3.
About
Covers Phaser 4 game development with its WebGL-first renderer, updated rendering APIs, GPU layers, and Phaser 3-to-4 migration. Used when a developer builds or ports a game to Phaser 4.
- WebGL-first renderer and GPU layer guidance
- Phaser 3-to-4 migration as selective redesign
Phaser4 Gamedev by the numbers
- 4 all-time installs (skills.sh)
- Ranked #210 of 247 Game Development skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/chongdashu/vibejam-starter-pack --skill phaser4-gamedevAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 4 |
|---|---|
| repo stars | ★ 143 |
| Last updated | April 15, 2026 |
| Repository | chongdashu/vibejam-starter-pack ↗ |
What it does
Build 2D browser games with Phaser 4's WebGL-first renderer, filters, shaders, GPU layers, and tilemaps, or migrate from Phaser 3.
Files
Phaser 4 Game Development
Build 2D browser games using Phaser 4's WebGL-first renderer, scene model, and updated rendering APIs.
Philosophy: Renderer-Aware, Asset-Exact
Phaser 4 is not Phaser 3 with a few renamed methods. The renderer, filter model, shader assumptions, texture orientation, and batching behavior changed. Good Phaser 4 work starts by choosing the right rendering path and measuring assets before code is written.
Before coding, ask:
- Is this a new Phaser 4 feature or a Phaser 3 migration?
- Does this feature stay on standard game object APIs, or does it depend on filters, shaders, lighting, or custom rendering?
- What is the asset source of truth: exact frame size, spacing, margin, atlas bounds, and texture orientation?
- Is the bottleneck CPU object churn, GPU fill rate, or batch breaking?
- Would
SpriteGPULayer,TilemapGPULayer,RenderTexture, or a plainSpritesolve this more cleanly?
Core principles: 1. WebGL-first, not Canvas-first: Phaser 4 is designed around WebGL. Treat Canvas as legacy compatibility, not the default target. 2. Measure assets before loader config: Sprite and tile bugs often start as incorrect frame metadata, not rendering bugs. 3. Prefer the simplest rendering path: Use standard game objects until scale or effect requirements justify filters, GPU layers, or shader work. 4. Treat rendering features as architectural choices: Filters, lighting, shaders, and render textures affect coordinate systems, batching, and debugging. 5. Migration is selective redesign: Basic scene code may port cleanly, but masks, FX, custom pipelines, shaders, and texture workflows usually need real updates.
STOP: Before Loading Any Spritesheet or Atlas
Read references/spritesheets-and-textures.md first.
Spritesheet loading is still fragile. A few pixels off in frame size, spacing, or margin can create silent corruption that looks like animation or rendering bugs later.
NEVER guess frame dimensions. DO NOT assume texture orientation details are irrelevant if compressed textures or custom shaders are involved.
STOP: Before Porting Phaser 3 Code
Read references/migration-hotspots.md first.
Search for the Phaser 3 APIs that changed meaning or disappeared. These are where most migration time goes:
setTintFillBitmapMaskpreFX/postFXPhaser.Geom.PointMath.TAU/Math.PI2setPipeline('Light2D')DynamicTexture/RenderTexture- custom pipelines
- custom shader code
TileSpritecropping
Reference Files
Read these before working on the relevant feature:
| When working on... | Read first |
|---|---|
| Migrating Phaser 3 code | references/migration-hotspots.md |
| Loading spritesheets, atlases, compressed textures, or TileSprite | references/spritesheets-and-textures.md |
| Performance issues, GPU layers, filters, lighting, or batching | references/rendering-and-performance.md |
Architecture Decisions (Make Early)
Rendering Path Choice
| Path | Use when |
|---|---|
| Standard game objects | Most gameplay, UI, and ordinary animation |
SpriteGPULayer | Very large numbers of mostly simple quads or particle-like members |
TilemapGPULayer | Very large orthographic tile layers using one tileset |
RenderTexture / DynamicTexture | You need capture, compositing, stamping, or texture reuse |
| Filters / Shader | The effect is genuinely image-space or shader-driven |
Physics System Choice
| System | Use when |
|---|---|
| Arcade | Platformers, shooters, most 2D action games |
| Matter | Physics puzzles, compound bodies, more realistic collisions |
| None | Menu scenes, card games, visual novels, strategy UIs |
Scene Structure
scenes/
├── BootScene.ts # Asset loading, progress bar, shader/texture setup
├── MenuScene.ts # Title screen and options
├── GameScene.ts # Main gameplay
├── UIScene.ts # HUD overlay (launched in parallel)
└── GameOverScene.ts # End screen and restart flowScene Transitions
this.scene.start('GameScene', { level: 1 }); // Stop current, start new
this.scene.launch('UIScene'); // Run in parallel
this.scene.pause('GameScene'); // Pause
this.scene.stop('UIScene'); // StopCore Patterns
Game Configuration
Prefer explicit WebGL unless there is a concrete reason not to.
const config: Phaser.Types.Core.GameConfig = {
type: Phaser.WEBGL,
width: 800,
height: 600,
roundPixels: false,
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH
},
physics: {
default: 'arcade',
arcade: { gravity: { y: 300 }, debug: false }
},
scene: [BootScene, MenuScene, GameScene]
};Scene Lifecycle
class GameScene extends Phaser.Scene {
init(data: unknown) {} // Receive data from previous scene
preload() {} // Load assets before create
create() {} // Set up game objects, physics, input
update(time: number, delta: number) {} // Use delta for frame-rate independence
}Frame-Rate Independent Movement
// Correct: scales with frame rate
this.player.x += this.speed * (delta / 1000);
// Wrong: varies with frame rate
this.player.x += this.speed;Phaser 4 Migration Replacements
// Phaser 3
sprite.setTintFill(0xff0000);
// Phaser 4
sprite.setTint(0xff0000).setTintMode(Phaser.TintModes.FILL);// Phaser 3
sprite.setPipeline('Light2D');
// Phaser 4
sprite.setLighting(true);// Phaser 3
const mask = new Phaser.Display.Masks.BitmapMask(scene, maskObject);
sprite.setMask(mask);
// Phaser 4
sprite.filters.internal.addMask(maskObject);RenderTexture and DynamicTexture
Phaser 4 buffers drawing commands. If you queue drawing work into a DynamicTexture or RenderTexture, execute it deliberately.
const rt = this.add.renderTexture(0, 0, 256, 256);
rt.draw(sprite, 0, 0);
rt.render();Use preserve() or render modes only when they solve a concrete problem. Extra indirection complicates debugging quickly.
Pixel Rounding
Do not assume old roundPixels behavior. Phaser 4 defaults it to false, and per-object control is more explicit.
sprite.vertexRoundMode = 'safe';Use rounding intentionally for pixel art. Leave it off for rotated, scaled, or camera-heavy scenes unless you want the visual tradeoff.
Anti-Patterns to Avoid
| Anti-pattern | Why it hurts | Better |
|---|---|---|
| Treating Phaser 4 as a drop-in Phaser 3 upgrade | You miss renderer, filter, shader, and texture changes | Audit migration hotspots first, then port intentionally |
| Starting new work on Canvas-first assumptions | Many Phaser 4 features are WebGL-centric or unavailable in Canvas | Design for WebGL and treat Canvas as fallback only if required |
| Guessing spritesheet or atlas metadata | Visual corruption appears far away from the actual mistake | Measure frames, spacing, margin, and bounds before loading |
| Using filters or shaders for every visual effect | More complexity, more batch breaks, harder debugging | Use plain sprites, textures, and tint where possible |
| Applying lighting or filters everywhere | Shader changes break batches and can tank performance | Reserve them for objects that benefit visually |
Forgetting render() on DynamicTexture or RenderTexture | Queued work never lands on the texture | Make render execution explicit in the workflow |
Using SpriteGPULayer for frequently mutated gameplay entities | Its strength is scale, not arbitrary object behavior | Keep complex interactive entities on normal game objects |
Assuming TilemapGPULayer is a universal tilemap replacement | It is orthographic-only and more constrained | Use it when the layer size and rendering profile justify it |
Making raw gl calls outside supported integration points | You can desync Phaser's renderer state | Use Extern or higher-level Phaser APIs |
Common pitfall: "the port compiles, so the migration is done." Rendering, shader, and texture bugs often survive the first compile.
Variation Guidance
Avoid converging on a single Phaser 4 setup. Choose based on context:
- Rendering path: standard objects vs GPU layers vs textures vs shader/filter pipelines
- Physics: Arcade vs Matter vs none
- Content: tilemaps vs pure sprites vs hybrid
- Pixel art handling:
roundPixelsoff, safe per-object rounding, or deliberate full rounding - Assets: spritesheets vs atlases vs single textures
- Scene layout: separate
UIScenevs in-scene HUD
What should vary is the architecture, not the rigor. Measure assets, check batching costs, and adapt the solution to the game's real constraints.
Remember
Phaser 4 gives you a more capable renderer and more explicit rendering tools, but it expects better architectural choices in return.
Before coding: what rendering path are you choosing, what assets define the truth, and what batch-breaking features are actually worth their cost?
Codex can do strong Phaser 4 work when the problem is framed precisely: scene boundaries, asset dimensions, rendering constraints, performance targets, and migration scope. These guidelines illuminate the path; they do not replace engineering judgment.
Phaser 3 to 4 Migration Hotspots
Use this reference before touching a Phaser 3 codebase. The first pass is not implementation; it is search, classification, and scope control.
Migration Philosophy
Do not treat migration as a flat rename exercise.
Split findings into three buckets:
1. Usually mechanical: straightforward API updates 2. Behavioral review required: code may compile but behave differently 3. Architectural rewrite: the underlying renderer or feature model changed
This prevents wasting time hand-editing easy cases while missing the renderer-level risks.
First Search Pass
Run searches for these symbols early:
setTintFilltintFillBitmapMaskGeometryMaskpreFXpostFXColorMatrixPhaser.Geom.PointPoint.Math.TAUMath.PI2setPipeline('Light2D')setPipeline("Light2D")DynamicTextureRenderTextureTileSpriteShadergl.PipelineWebGLRenderer
Mechanical Replacements
| Phaser 3 | Phaser 4 |
|---|---|
setTintFill(color) | setTint(color).setTintMode(Phaser.TintModes.FILL) |
Math.PI2 | Math.TAU |
setPipeline('Light2D') | setLighting(true) |
Phaser.Struct.Set | native Set |
Phaser.Struct.Map | native Map |
These are good codemod candidates, but still review call sites for behavior assumptions.
Behavioral Review Required
Math.TAU
In Phaser 3, Math.TAU effectively matched PI / 2. In Phaser 4, Math.TAU is actual tau: PI * 2.
If old code used TAU for quarter turns, replace it with Math.PI_OVER_2.
ColorMatrix
Color methods moved under the colorMatrix property.
// old
colorMatrix.sepia();
// new
colorMatrix.colorMatrix.sepia();DynamicTexture and RenderTexture
Buffered drawing now requires explicit render() execution. If a ported effect appears blank or stale, check whether the commands are queued but never rendered.
TileSprite
Texture cropping support is gone. If the old implementation depended on cropped repetition, redesign it instead of trying to force the old pattern back in.
Camera Internals
Standard camera properties usually port cleanly. Direct matrix work does not. Any code that reads or mutates camera matrices needs a focused review.
Architectural Rewrite Areas
FX and Masks
Phaser 4 unifies FX and masks into filters.
BitmapMaskis removed in WebGL paths.preFXandpostFXassumptions no longer apply.- Some old FX are now actions or new game objects.
If a scene relies on layered masking, post-processing, or filter order, plan dedicated time for it.
Custom Pipelines and Renderer Internals
Phaser 4 replaces the v3 pipeline model with render nodes. If the project touched custom pipelines, internal renderer buffers, or direct WebGL state, expect redesign work rather than patching.
Shaders and Texture Orientation
Phaser 4 uses GL-style texture orientation. Custom shader work must be re-checked with that assumption. Compressed textures may need to be regenerated with the correct Y-axis orientation.
Recommended Migration Order
1. Update package version and type surfaces. 2. Fix obvious compile errors from removed APIs. 3. Audit renderer, filter, shader, lighting, and texture workflows. 4. Re-test visuals before optimizing performance. 5. Only then consider GPU-layer upgrades or visual enhancements.
What Not to Do
- Do not rewrite everything before classifying the migration risks.
- Do not assume passing TypeScript means rendering is correct.
- Do not debug masks, shaders, and compressed textures as if Phaser 3 internals still apply.
Phaser 4 Rendering and Performance
Phaser 4 performance work starts with one question: what is actually expensive here?
The answer is usually one of these:
- too many independent objects and CPU-side updates
- too many shader or filter changes breaking batches
- too much fill-rate from large filtered or lit surfaces
- incorrect asset choices causing unnecessary work
Choose the Right Rendering Path
Standard Game Objects
Use standard sprites, images, text, and tilemaps by default.
They are the right choice when:
- entities are interactive
- state changes frequently
- gameplay logic is per-object
- debugging clarity matters more than raw maximum counts
Do not move to a more specialized path just because it sounds faster.
SpriteGPULayer
Use SpriteGPULayer when you need huge numbers of mostly simple quads with predictable animation behavior.
Good fit:
- starfields
- animated backgrounds
- particle-like swarms
- dense decorative motion
Bad fit:
- ordinary enemies with unique gameplay logic
- objects that need constant structural edits
- scenes where per-member mutation is more important than raw count
The layer is fast because it avoids ordinary per-object CPU work. The tradeoff is flexibility.
TilemapGPULayer
Use TilemapGPULayer when:
- the map is orthographic
- one tileset is sufficient
- very large visible tile counts matter
- smooth filtering without seams matters
Do not use it as a reflex upgrade over TilemapLayer. Its constraints are real.
After editing layer data, regenerate the layer data texture so the GPU representation stays correct.
RenderTexture and DynamicTexture
Use these when you need:
- texture capture
- compositing
- reuse of generated visuals
- staged multi-pass effects
Remember that queued work is not the same as executed work. Call render() when the texture must update.
Batch Breakers
These features are valuable, but they are not free:
- filters
- lighting
- shader changes
- unusual blend behavior
- render target switches
Use them where the effect is visible and justified. A subtle glow on one hero object may be worth it; the same glow on every prop usually is not.
Pixel Art Guidance
Phaser 4 no longer defaults to old roundPixels behavior.
For pixel art:
- start with
roundPixels: false - enable per-object rounding only where needed
- test camera movement, scaling, and rotation before committing
If the scene has transforms everywhere, forcing full rounding can trade shimmer for wobble. That is a stylistic choice, not a default.
Debugging Order
When performance is poor:
1. Count object types and churn. 2. Check whether filters or lighting are everywhere. 3. Identify whether a GPU layer would simplify the scene. 4. Verify textures and tile data are not causing avoidable redraws. 5. Profile before rewriting architecture.
Anti-Patterns
- Using shader/filter solutions for problems that tint, texture, or art direction could solve
- Moving gameplay entities into
SpriteGPULayertoo early - Assuming the most GPU-heavy path is the fastest path
- Optimizing before validating correctness
Phaser 4 Spritesheets and Textures
Most "rendering bugs" in 2D games are still asset metadata bugs.
Measure first.
Before Loading
Confirm these values from the source asset:
- full image width and height
- frame width and height
- spacing
- margin
- atlas frame bounds
- whether the asset is pixel art or smooth art
- whether the texture is compressed
Do not infer any of these from appearance alone.
Spritesheets
For spritesheets:
- compute the frame grid from exact dimensions
- verify spacing and margin numerically
- confirm whether frames are square or rectangular
- test the final frame index and row count, not just the first frame
One wrong measurement can look like a timing, animation, or rendering issue later.
Atlases
For atlases:
- trust the atlas data, not visual intuition
- confirm the frame names the code expects actually exist
- inspect trimmed frames carefully when using tight collision or origin assumptions
Texture Orientation
Phaser 4 uses GL-style texture orientation internally.
This matters most when:
- writing custom shaders
- using framebuffer outputs
- loading compressed textures
For ordinary PNG or JPG loading, Phaser handles the common cases for you.
For compressed textures, verify the Y-axis orientation during asset generation. If the old asset pipeline targeted Phaser 3 assumptions, it may need regeneration.
TileSprite
Phaser 4 TileSprite is more capable, but it is not the old object internally.
Key implications:
- texture cropping support is gone
- repeating atlas or spritesheet frames is now viable
tileRotationis available
If the old implementation relied on crop-based repetition tricks, redesign the approach instead of forcing the old behavior.
Shader-Adjacent Texture Checks
If a shader effect looks upside down, mirrored, or vertically offset:
1. verify the shader's UV assumptions 2. verify the source texture orientation 3. verify whether the source came from a framebuffer or compressed texture path
Do not immediately blame the math if the asset pipeline may be wrong.
Anti-Patterns
- Eyeballing frame dimensions
- Assuming all texture sources share the same orientation rules
- Debugging animation timing before verifying frame metadata
- Treating compressed textures like ordinary PNGs during migration