$npx -y skills add Yakoub-ai/phaser4-gamedev --skill phaser-migrateThis skill should be used when the user asks to "migrate from Phaser 3", "upgrade to Phaser 4", "convert my v3 game", "Phaser 3 to 4 migration", "update Phaser version", "my Phaser 3 game broke after upgrading", "behavior changed after RC upgrade", "RC6 to RC7 migration", or has
| 1 | # Phaser 3 → Phaser 4 Migration |
| 2 | |
| 3 | Migrating from Phaser 3 to Phaser 4 is mostly straightforward. The core public API is preserved. This skill covers every breaking change and how to fix it — AND also covers RC-to-RC behavioral drift within Phaser 4 (e.g., RC6 → RC7) where APIs silently changed semantics between RC releases. |
| 4 | |
| 5 | ## Step 1 — Update the Package |
| 6 | |
| 7 | ```bash |
| 8 | npm uninstall phaser |
| 9 | npm install phaser@beta |
| 10 | ``` |
| 11 | |
| 12 | Verify installed version: |
| 13 | ```bash |
| 14 | node -e "const p = require('phaser'); console.log(p.VERSION)" |
| 15 | ``` |
| 16 | |
| 17 | Should print `4.0.0-rc.7` (or later RC). |
| 18 | |
| 19 | ## Step 2 — Scan for Breaking Changes |
| 20 | |
| 21 | Run these grep searches to find every issue in your `src/` directory: |
| 22 | |
| 23 | ```bash |
| 24 | # 1. Point → Vector2 |
| 25 | grep -rn "Geom\.Point\|new Phaser\.Geom\.Point\|Geom\.Point\." src/ |
| 26 | |
| 27 | # 2. Math.PI2 → Math.TAU |
| 28 | grep -rn "Math\.PI2\b" src/ |
| 29 | |
| 30 | # 3. Phaser.Structs |
| 31 | grep -rn "Phaser\.Structs\." src/ |
| 32 | |
| 33 | # 4. DynamicTexture / RenderTexture (check for missing .render()) |
| 34 | grep -rn "DynamicTexture\|RenderTexture\|addDynamicTexture\|addRenderTexture" src/ |
| 35 | |
| 36 | # 5. Removed plugins |
| 37 | grep -rn "Camera3D\|Layer3D\|FacebookInstant\|SpinePlugin\|SpineFile" src/ |
| 38 | |
| 39 | # 6. TileSprite crop (setCrop on TileSprite — no longer supported) |
| 40 | grep -rn "tileSprite.*setCrop\|setCrop.*tileSprite" src/ |
| 41 | |
| 42 | # 7. Create.GenerateTexture (removed) |
| 43 | grep -rn "Create\.GenerateTexture\|Phaser\.Create\." src/ |
| 44 | |
| 45 | # 8. Spine (use official Esoteric plugin instead) |
| 46 | grep -rn "spine\|Spine" src/ -i |
| 47 | |
| 48 | # 9. phaser-ie9 entry point |
| 49 | grep -rn "phaser-ie9" . |
| 50 | |
| 51 | # 10. WebGL geometry masks (stencil-based masks changed in Phaser 4 — use scissor/viewport instead) |
| 52 | grep -rn "createGeometryMask\|setBitmapMask\|setMask\b\|clearMask" src/ |
| 53 | ``` |
| 54 | |
| 55 | ## Step 3 — Apply Fixes |
| 56 | |
| 57 | ### Fix 1: Geom.Point → Vector2 |
| 58 | |
| 59 | `Phaser.Geom.Point` is completely removed. Use `Phaser.Math.Vector2`. |
| 60 | |
| 61 | ```typescript |
| 62 | // BEFORE (Phaser 3) |
| 63 | const point = new Phaser.Geom.Point(x, y); |
| 64 | point.x = 100; |
| 65 | const distance = Phaser.Geom.Point.GetMagnitude(point); |
| 66 | const clone = Phaser.Geom.Point.Clone(point); |
| 67 | Phaser.Geom.Point.SetMagnitude(point, 50); |
| 68 | |
| 69 | // AFTER (Phaser 4) |
| 70 | const point = new Phaser.Math.Vector2(x, y); |
| 71 | point.x = 100; |
| 72 | const distance = point.length(); |
| 73 | const clone = point.clone(); |
| 74 | point.setLength(50); |
| 75 | ``` |
| 76 | |
| 77 | **Full Point → Vector2 method mapping:** |
| 78 | | Phaser 3 (static) | Phaser 4 (instance) | |
| 79 | |---|---| |
| 80 | | `Point.GetMagnitude(pt)` | `pt.length()` | |
| 81 | | `Point.Clone(pt)` | `pt.clone()` | |
| 82 | | `Point.SetMagnitude(pt, n)` | `pt.setLength(n)` | |
| 83 | | `Point.Ceil(pt)` | `pt.ceil()` | |
| 84 | | `Point.Floor(pt)` | `pt.floor()` | |
| 85 | | `Point.Invert(pt)` | `pt.invert()` | |
| 86 | | `Point.Negative(pt)` | `pt.negate()` | |
| 87 | | `Point.Project(pt, target, out)` | `pt.project(target)` | |
| 88 | | `Point.GetCentroid(points)` | `Phaser.Math.GetCentroid(points)` | |
| 89 | | `Point.GetRectangleFromPoints(pts)` | `Phaser.Math.GetVec2Bounds(pts)` | |
| 90 | |
| 91 | All Geometry classes (`Circle`, `Ellipse`, `Line`, `Rectangle`, `Triangle`, `Polygon`) now return `Vector2` instead of `Point` for point-related results. |
| 92 | |
| 93 | ### Fix 2: Math.PI2 → Math.TAU |
| 94 | |
| 95 | ```typescript |
| 96 | // BEFORE (Phaser 3) — NOTE: Math.PI2 was INCORRECTLY π in v3 |
| 97 | const fullRotation = Math.PI2; // was wrong! |
| 98 | |
| 99 | // AFTER (Phaser 4) |
| 100 | const fullRotation = Math.TAU; // Correct π×2 |
| 101 | const halfRotation = Math.PI_OVER_2; // π/2 (new constant) |
| 102 | ``` |
| 103 | |
| 104 | ### Fix 3: Phaser.Structs → Native JS |
| 105 | |
| 106 | ```typescript |
| 107 | // BEFORE (Phaser 3) |
| 108 | const myMap = new Phaser.Structs.Map([]); |
| 109 | myMap.set('key', value); |
| 110 | myMap.get('key'); |
| 111 | myMap.delete('key'); |
| 112 | myMap.getArray(); |
| 113 | |
| 114 | const mySet = new Phaser.Structs.Set(); |
| 115 | mySet.set(value); |
| 116 | mySet.delete(value); |
| 117 | mySet.contains(value); |
| 118 | |
| 119 | // AFTER (Phaser 4) |
| 120 | const myMap = new Map<string, any>(); |
| 121 | myMap.set('key', value); |
| 122 | myMap.get('key'); |
| 123 | myMap.delete('key'); |
| 124 | [...myMap.values()]; |
| 125 | |
| 126 | const mySet = new Set<any>(); |
| 127 | mySet.add(value); |
| 128 | mySet.delete(value); |
| 129 | mySet.has(value); |
| 130 | ``` |
| 131 | |
| 132 | ### Fix 4: DynamicTexture / RenderTexture — Add render() |
| 133 | |
| 134 | ```typescript |
| 135 | // BEFORE (Phaser 3) — drawing happened immediately |
| 136 | const dynTex = this.textures.addDynamicTexture('key', 200, 200); |
| 137 | dynTex.draw('sprite', 0, 0); |
| 138 | // visible immediately |
| 139 | |
| 140 | // AFTER (Phaser 4) — must call render() to commit drawing |
| 141 | const dynTex = this.textures.addDynamicTexture('key', 200, 200); |
| 142 | dynTex.draw('sprite', 0, 0); |
| 143 | dynTex.render(); // ← REQUIRED in v4 |
| 144 | ``` |
| 145 | |
| 146 | ### Fix 5: Removed Plugins |
| 147 | |
| 148 | **Camera3D** — no replacement. Phaser 4 is 2D only. If 3D is needed, use Three.js alongside Phaser. |
| 149 | |
| 150 | **Layer3D** — no replacement. Removed with Camera3D. |
| 151 | |
| 152 | **Facebook Instant Games** — removed. Facebook no longer supports this platform. |
| 153 | |
| 154 | **Spine Plugin** (official v3/v4 Spine support) — use the official [Esoteric S |