主题
06 · Phaser 3 + TypeScript 工程脚手架
目标:用 Vite + TypeScript 装好 Phaser 3,跑通
Phaser.Game+ Boot/Game 双场景,并用 Graphics 生成色块纹理(无美术包)。
前置:05 · AABB 与迷你街机
官方:Phaser 3 文档 · Getting Started
1. 为什么换引擎,而不是继续手写 Canvas
阶段一把 Game Loop / 输入 / AABB 跑通了。接下来重复造轮子的成本上升:精灵、物理、Group、定时器、场景切换。
Phaser 用同一套 TS 心智,把这些收成 API——对照前端:从「手写 rAF 列表」换到「带路由的 SPA 框架」。
本系列锁定:Phaser 3.80+、Arcade 物理、色块资源。
2. 建工程
可新建目录(不必覆盖阶段一的 arcade-lab):
bash
pnpm create vite phaser-arcade --template vanilla-ts
cd phaser-arcade
pnpm install
pnpm add phaser
pnpm dev1
2
3
4
5
2
3
4
5
index.html:给 Phaser 一个挂载点(不必手写 <canvas>,引擎会创建):
html
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>Phaser Arcade</title>
<style>
html, body { margin: 0; background: #0b1220; }
#app { display: flex; justify-content: center; padding: 16px; }
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
3. 启动配置
src/main.ts:
ts
import Phaser from 'phaser'
import { BootScene } from './scenes/BootScene'
import { GameScene } from './scenes/GameScene'
const config: Phaser.Types.Core.GameConfig = {
type: Phaser.AUTO,
parent: 'app',
width: 480,
height: 640,
backgroundColor: '#0b1220',
physics: {
default: 'arcade',
arcade: {
gravity: { x: 0, y: 0 }, // 街机射击:不用重力
debug: false,
},
},
scene: [BootScene, GameScene],
}
new Phaser.Game(config)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
对照:parent ≈ 前端根挂载节点;scene 数组 ≈ 路由表(先注册,再 start)。
4. Boot:生成色块纹理
src/scenes/BootScene.ts:
ts
import Phaser from 'phaser'
export class BootScene extends Phaser.Scene {
constructor() {
super('Boot')
}
create() {
this.makeTexture('player', 40, 24, 0xfbbf24)
this.makeTexture('bullet', 6, 12, 0xe2e8f0)
this.makeTexture('enemy', 28, 28, 0xf87171)
this.scene.start('Game')
}
private makeTexture(key: string, w: number, h: number, color: number) {
const g = this.make.graphics({ x: 0, y: 0 })
g.fillStyle(color, 1)
g.fillRect(0, 0, w, h)
g.generateTexture(key, w, h)
g.destroy()
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
src/scenes/GameScene.ts(本篇只占位):
ts
import Phaser from 'phaser'
export class GameScene extends Phaser.Scene {
constructor() {
super('Game')
}
create() {
this.add.image(240, 320, 'player')
this.add.text(12, 12, 'Boot OK — GameScene', {
fontSize: '16px',
color: '#f8fafc',
})
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
应看到深蓝底 + 黄色方块 + 一行字。纹理已进纹理缓存,后面 Scene 用 key 引用即可。
5. 心智对照
| 前端 / 阶段一 | Phaser |
|---|---|
requestAnimationFrame 自管循环 | 引擎内部驱动 Scene.update |
| 多个「页面」 | 多个 Scene,this.scene.start(key) |
自己画 fillRect | 纹理 + Image / Sprite |
手动 dt | Arcade 物理与 update(time, delta)(delta 毫秒) |
常见坑
| 坑 | 处理 |
|---|---|
Cannot find module 'phaser' | 确认 pnpm add phaser;重启 dev server |
| 画面空白 | 查 parent id;看控制台是否 Scene key 写错 |
| 纹理花屏 | generateTexture 的宽高与 fillRect 一致 |
验收清单
- [ ]
pnpm dev能打开游戏画布 480×640 - [ ] Boot 跑完自动进入 Game
- [ ] Game 里能显示用
player纹理画的图 - [ ]
physics.default === 'arcade'已写在 config(下一篇用)
