Phaser
开源 HTML5 2D 游戏框架 —— 快速、免费、有趣的 Web 游戏引擎
官网:https://phaser.io | 文档:https://docs.phaser.io | GitHub:https://github.com/phaserjs/phaser | 示例:https://phaser.io/examples
发展历史
Phaser 由 Richard Davey 于 2013 年创立,是 Web 游戏开发领域最成熟的框架之一:
| 时期 | 版本 | 时间 | 里程碑 |
|---|---|---|---|
| 诞生 | Phaser 1.0 | 2013 | 基于 Flixel 的 HTML5 游戏框架,支持 Canvas 和 WebGL |
| 2.x 时代 | Phaser 2.x | 2014–2016 | 社区迅速扩大,成为最流行的 HTML5 游戏框架 |
| 全面重写 | Phaser 3.0 | 2018 | 完全重写,引入自定义渲染器、场景管理器、Matter 物理 |
| 成熟稳定 | Phaser 3.60 | 2023 | 大量性能优化,WebGL 渲染升级,ESM 模块支持 |
| 持续发展 | Phaser 3.80+ | 2024 | 树摇优化、压缩纹理支持、特效系统(Bloom/Glow) |
| 未来 | Phaser 3.86+ | 2025 | 2025 路线图规划了 3D 支持,持续改进开发体验 |
核心特性
| 特性 | 说明 |
|---|---|
| 双渲染引擎 | 同时支持 WebGL 和 Canvas,自动回退,高性能自定义渲染器 |
| 物理系统 | 内置 Arcade(轻量街机)和 Matter(完整物理)两种物理引擎 |
| 场景管理器 | 将游戏分为多个场景(菜单、关卡、商店等),轻松切换和管理 |
| 资源加载器 | 支持 30+ 文件格式(图片、音频、视频、SVG、图集、瓦片地图等) |
| 游戏对象 | 30+ 种内置对象(Sprite、Text、Container、粒子、Video 等) |
| 动画系统 | 基于纹理帧的动画 + 补间动画(Tween),支持 30+ 缓动效果 |
| 输入系统 | 统一管理键盘、鼠标、触摸、游戏手柄,支持拖放和像素级点击检测 |
| 音频系统 | 支持 HTML5 Audio 和 Web Audio,控制音量、声像、空间音频 |
| 瓦片地图 | 内置 Tiled Map 编辑器支持,CSV/JSON 格式,物理碰撞 |
| 粒子系统 | 丰富的粒子发射器配置,支持各种视觉效果 |
| 相机系统 | 多摄像头支持,抖动、闪光、淡入淡出、滚动、缩放效果 |
| TypeScript | 完整类型定义,官方模板支持 TS/JS 双语言 |
| 树摇优化 | v3.60+ 支持 ESM 按需导入,大幅减小打包体积 |
应用场景
| 场景 | 说明 | 典型案例 |
|---|---|---|
| 网页小游戏 | 休闲游戏、益智游戏、HTML5 广告 | 消灭星星、找你妹类 |
| 社交平台游戏 | Discord Activities、微信小游戏、Twitch Overlays | 互动直播游戏 |
| 移动端游戏 | 通过第三方工具(CocoonJS、Capacitor)打包为 App | 跑酷、射击、RPG |
| 教育互动 | 互动教学、编程学习、知识问答 | CodeCombat 类 |
| 品牌营销 | H5 营销活动、互动广告 | 品牌定制小游戏 |
| 原型开发 | 快速验证游戏玩法和机制 | Game Jam 作品 |
快速开始
方式一:Create Phaser Game(推荐)
最快捷的启动方式:
bash
npm create @phaserjs/game@latest
# 或
npx @phaserjs/create-game@latest
# 或
yarn create @phaserjs/game交互式命令行会引导选择模板和配置。
方式二:NPM 安装
bash
npm install phaser然后在项目中引入:
javascript
import Phaser from 'phaser'
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
scene: {
preload: preload,
create: create,
update: update
}
}
const game = new Phaser.Game(config)
function preload() {
// 加载资源
this.load.image('logo', 'assets/logo.png')
}
function create() {
// 创建游戏对象
const logo = this.add.image(400, 300, 'logo')
this.tweens.add({
targets: logo,
y: 200,
duration: 2000,
ease: 'Sine.easeInOut',
yoyo: true,
repeat: -1
})
}
function update() {
// 游戏循环更新逻辑
}方式三:CDN 引入
html
<script src="//cdn.jsdelivr.net/npm/phaser@3.86.0/dist/phaser.min.js"></script>
<script>
const game = new Phaser.Game({ type: Phaser.AUTO, width: 800, height: 600 })
</script>方式四:HTML 完整示例
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Phaser 入门</title>
</head>
<body>
<script src="//cdn.jsdelivr.net/npm/phaser@3.86.0/dist/phaser.min.js"></script>
<script>
class MainScene extends Phaser.Scene {
constructor() {
super({ key: 'MainScene' })
this.score = 0
}
preload() {
// 生成一个圆形纹理作为玩家
const g = this.add.graphics()
g.fillStyle(0x00ff00, 1)
g.fillCircle(16, 16, 16)
g.generateTexture('player', 32, 32)
g.destroy()
}
create() {
// 创建玩家
this.player = this.add.image(400, 300, 'player')
this.player.setScale(2)
// 键盘输入
this.cursors = this.input.keyboard.createCursorKeys()
// 创建敌人
this.enemies = this.physics.add.group()
this.time.addEvent({
delay: 1000,
callback: () => {
const x = Phaser.Math.Between(0, 800)
const enemy = this.enemies.create(x, -20, 'player')
enemy.setTint(0xff0000)
enemy.setScale(1)
},
loop: true
})
// 得分文本
this.scoreText = this.add.text(16, 16, '得分: 0', {
fontSize: '24px',
fill: '#ffffff'
})
}
update() {
// 移动玩家
const speed = 300
if (this.cursors.left.isDown) {
this.player.x -= speed * this.game.loop.delta / 1000
}
if (this.cursors.right.isDown) {
this.player.x += speed * this.game.loop.delta / 1000
}
// 检测碰撞
this.enemies.children.each(enemy => {
const dist = Phaser.Math.Distance.Between(
this.player.x, this.player.y, enemy.x, enemy.y
)
if (dist < 32) {
enemy.destroy()
this.score += 10
this.scoreText.setText('得分: ' + this.score)
}
if (enemy.y > 620) {
enemy.destroy()
}
})
}
}
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
backgroundColor: '#1a1a2e',
physics: {
default: 'arcade',
arcade: { gravity: { y: 100 }, debug: false }
},
scene: MainScene
}
const game = new Phaser.Game(config)
</script>
</body>
</html>项目模板
Phaser 官方支持所有主流前端框架和打包工具:
| 框架 | 打包工具 |
|---|---|
| Vue.js | Vite |
| React | Rollup |
| Angular | Parcel |
| Next.js | Webpack |
| SolidJS | ESBuild |
| Svelte | Import Map |
| Remix | Bun |
大部分模板同时提供 JavaScript 和 TypeScript 版本。
核心概念
场景(Scene)
场景是 Phaser 游戏的基本单元,每个场景有 3 个生命周期方法:
javascript
class GameScene extends Phaser.Scene {
constructor() {
super({ key: 'GameScene' })
}
// 1. 加载资源(只执行一次)
preload() {
this.load.image('bg', 'assets/background.png')
this.load.spritesheet('player', 'assets/player.png',
{ frameWidth: 32, frameHeight: 48 }
)
}
// 2. 创建游戏对象(只执行一次)
create() {
this.add.image(400, 300, 'bg')
// 创建动画
this.anims.create({
key: 'run',
frames: this.anims.generateFrameNumbers('player', { start: 0, end: 3 }),
frameRate: 10,
repeat: -1
})
}
// 3. 游戏循环(每帧执行)
update(time, delta) {
// 更新逻辑
}
}
// 场景切换
this.scene.start('NextScene')
this.scene.launch('OverlayScene') // 并行运行游戏对象(Game Object)
javascript
// Sprite 精灵
const sprite = this.add.sprite(100, 100, 'texture')
// Image 图片
const image = this.add.image(200, 200, 'logo')
// Text 文本
const text = this.add.text(400, 300, 'Hello Phaser', {
fontSize: '32px',
color: '#ffffff',
fontFamily: 'Arial',
stroke: '#000000',
strokeThickness: 4
})
// Graphics 图形
const graphics = this.add.graphics()
graphics.fillStyle(0xff0000, 1)
graphics.fillRect(50, 50, 100, 100)
// Container 容器
const container = this.add.container(0, 0)
container.add([sprite, text])
// Particle 粒子
const emitter = this.add.particles(400, 300, 'particle', {
speed: { min: -100, max: 100 },
lifespan: 2000,
quantity: 2,
scale: { start: 1, end: 0 },
emitting: true
})物理系统
Arcade Physics(轻量物理)
适合街机风格游戏,性能极好:
javascript
// 开启物理
this.physics.add.existing(this.player)
this.physics.add.existing(this.platform, true) // true = 静态物体
// 碰撞检测
this.physics.add.collider(this.player, this.platforms)
this.physics.add.overlap(this.player, this.coins, collectCoin, null, this)
// 重力
this.physics.add.gravity.y = 300
// 速度
this.player.setVelocityX(200)
this.player.setBounce(0.2)Matter Physics(完整物理)
支持复杂形状、关节、约束:
javascript
// 创建 Matter 物体
const rect = this.matter.add.rectangle(400, 300, 64, 64, {
restitution: 0.8, // 弹性
friction: 0.1, // 摩擦力
density: 0.01 // 密度
})
// 鼠标拖动
this.matter.add.mouseSpring()输入系统
javascript
// 键盘
const cursors = this.input.keyboard.createCursorKeys()
const wasd = this.input.keyboard.addKeys('W,A,S,D')
const space = this.input.keyboard.addKey(Phaser.Input.Keyboard.KeyCodes.SPACE)
// 鼠标/触摸
this.input.on('pointerdown', (pointer) => {
console.log('点击位置:', pointer.x, pointer.y)
})
// 拖放
this.input.setDraggable(this.sprite)
this.input.on('drag', (pointer, gameObject, dragX, dragY) => {
gameObject.x = dragX
gameObject.y = dragY
})高级纹理与渲染
javascript
// 动态纹理(实时绘制)
const dt = this.add.dynamicTexture(200, 200)
dt.fill(0x0000ff, 1)
dt.text('Drawn', 50, 50, { font: '20px Arial', color: 'white' })
// 九宫格切片(可伸缩 UI)
const btn = this.add.nineslice(400, 300, 'button', 0, 200, 50)
btn.setSize(200, 60)
// 压缩纹理(减少内存占用)
this.load.setBaseURL('assets/compressed/')
this.load.texture('bg', 'background.ktx2')
// 特效
this.cameras.main.postFX.addBloom(0.5, 0.5, 0.2)
this.cameras.main.postFX.addGlow(0xff0000, 0.5)音频
javascript
// 加载音频
this.load.audio('bgm', 'assets/background.mp3')
this.load.audio('sfx', 'assets/jump.wav')
// 播放
const music = this.sound.add('bgm', { volume: 0.5, loop: true })
music.play()
// 音效
this.sound.play('sfx', { volume: 0.8 })
// 空间音频
this.sound.play('explosion', {
source: { x: player.x, y: player.y },
pan: 0.5,
volume: 0.4
})打包与发布
Phaser 游戏支持多种发布渠道:
| 渠道 | 方式 | 说明 |
|---|---|---|
| Web 浏览器 | 直接部署静态文件 | 部署到 Nginx、Vercel、Netlify 等 |
| 微信小游戏 | 使用 weapp-adapter | 需要适配微信小游戏 API |
| 移动应用 | Capacitor / Cordova | 打包为 iOS / Android App |
| 桌面应用 | Electron | 打包为 Windows / macOS / Linux 应用 |
| Discord | Discord Activities | 通过 Embedded App SDK 发布 |
| 可玩广告 | HTML5 打包 | 用于 Google Ads、Unity Ads 等平台 |