Phaser 高级主题 #
项目架构 #
目录结构 #
text
my-phaser-game/
├── src/
│ ├── main.js # 游戏入口
│ ├── config.js # 游戏配置
│ ├── scenes/ # 场景目录
│ │ ├── BootScene.js
│ │ ├── PreloadScene.js
│ │ ├── MenuScene.js
│ │ ├── GameScene.js
│ │ └── UIScene.js
│ ├── objects/ # 游戏对象
│ │ ├── Player.js
│ │ ├── Enemy.js
│ │ └── Item.js
│ ├── components/ # UI 组件
│ │ ├── Button.js
│ │ ├── HealthBar.js
│ │ └── ScoreDisplay.js
│ ├── managers/ # 管理器
│ │ ├── AudioManager.js
│ │ ├── DataManager.js
│ │ └── InputManager.js
│ ├── plugins/ # 插件
│ │ └── CustomPlugin.js
│ ├── utils/ # 工具函数
│ │ ├── math.js
│ │ └── storage.js
│ └── constants/ # 常量
│ └── game.js
├── assets/
│ ├── images/
│ ├── sprites/
│ ├── audio/
│ └── fonts/
├── public/
├── index.html
├── package.json
└── vite.config.js
配置管理 #
javascript
const config = {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'game-container',
backgroundColor: '#2d2d2d',
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH
},
physics: {
default: 'arcade',
arcade: {
gravity: { y: 300 },
debug: false
}
},
render: {
pixelArt: true,
antialias: false
},
scene: [BootScene, PreloadScene, MenuScene, GameScene, UIScene]
};
export default config;
游戏入口 #
javascript
import Phaser from 'phaser';
import config from './config';
class Game extends Phaser.Game {
constructor() {
super(config);
}
}
window.addEventListener('load', () => {
new Game();
});
设计模式 #
单例模式 #
javascript
class GameManager {
static instance = null;
constructor() {
if (GameManager.instance) {
return GameManager.instance;
}
this.score = 0;
this.level = 1;
this.lives = 3;
GameManager.instance = this;
}
static getInstance() {
if (!GameManager.instance) {
GameManager.instance = new GameManager();
}
return GameManager.instance;
}
reset() {
this.score = 0;
this.level = 1;
this.lives = 3;
}
}
const gameManager = GameManager.getInstance();
工厂模式 #
javascript
class GameObjectFactory {
constructor(scene) {
this.scene = scene;
}
create(type, x, y, config = {}) {
switch (type) {
case 'player':
return new Player(this.scene, x, y, config);
case 'enemy':
return new Enemy(this.scene, x, y, config);
case 'item':
return new Item(this.scene, x, y, config);
default:
throw new Error(`Unknown object type: ${type}`);
}
}
}
class GameScene extends Phaser.Scene {
create() {
this.factory = new GameObjectFactory(this);
this.player = this.factory.create('player', 100, 100);
this.enemy = this.factory.create('enemy', 300, 100, { speed: 150 });
}
}
观察者模式 #
javascript
class EventEmitter {
constructor() {
this.events = {};
}
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
return () => this.off(event, callback);
}
off(event, callback) {
if (!this.events[event]) return;
this.events[event] = this.events[event].filter(cb => cb !== callback);
}
emit(event, ...args) {
if (!this.events[event]) return;
this.events[event].forEach(callback => callback(...args));
}
}
class GameEvents extends EventEmitter {
static SCORE_UPDATE = 'scoreUpdate';
static GAME_OVER = 'gameOver';
static LEVEL_COMPLETE = 'levelComplete';
}
const gameEvents = new GameEvents();
gameEvents.on(GameEvents.SCORE_UPDATE, (score) => {
console.log('Score:', score);
});
gameEvents.emit(GameEvents.SCORE_UPDATE, 100);
状态模式 #
javascript
class PlayerState {
constructor(player) {
this.player = player;
}
enter() {}
exit() {}
update() {}
}
class IdleState extends PlayerState {
enter() {
this.player.setVelocity(0, 0);
this.player.anims.play('idle');
}
update(cursors) {
if (cursors.left.isDown || cursors.right.isDown) {
this.player.setState('walk');
}
if (cursors.up.isDown && this.player.body.blocked.down) {
this.player.setState('jump');
}
}
}
class WalkState extends PlayerState {
enter() {
this.player.anims.play('walk');
}
update(cursors) {
if (cursors.left.isDown) {
this.player.setVelocityX(-160);
this.player.setFlipX(true);
} else if (cursors.right.isDown) {
this.player.setVelocityX(160);
this.player.setFlipX(false);
} else {
this.player.setState('idle');
}
if (cursors.up.isDown && this.player.body.blocked.down) {
this.player.setState('jump');
}
}
}
class JumpState extends PlayerState {
enter() {
this.player.setVelocityY(-330);
this.player.anims.play('jump');
}
update(cursors) {
if (cursors.left.isDown) {
this.player.setVelocityX(-160);
} else if (cursors.right.isDown) {
this.player.setVelocityX(160);
}
if (this.player.body.blocked.down) {
this.player.setState('idle');
}
}
}
class Player extends Phaser.Physics.Arcade.Sprite {
constructor(scene, x, y) {
super(scene, x, y, 'player');
scene.add.existing(this);
scene.physics.add.existing(this);
this.states = {
idle: new IdleState(this),
walk: new WalkState(this),
jump: new JumpState(this)
};
this.currentState = this.states.idle;
this.currentState.enter();
}
setState(stateName) {
this.currentState.exit();
this.currentState = this.states[stateName];
this.currentState.enter();
}
update(cursors) {
this.currentState.update(cursors);
}
}
数据管理 #
本地存储 #
javascript
class StorageManager {
constructor(prefix = 'game_') {
this.prefix = prefix;
}
save(key, value) {
try {
localStorage.setItem(this.prefix + key, JSON.stringify(value));
return true;
} catch (e) {
console.error('Failed to save:', e);
return false;
}
}
load(key, defaultValue = null) {
try {
const value = localStorage.getItem(this.prefix + key);
return value ? JSON.parse(value) : defaultValue;
} catch (e) {
console.error('Failed to load:', e);
return defaultValue;
}
}
remove(key) {
localStorage.removeItem(this.prefix + key);
}
clear() {
Object.keys(localStorage)
.filter(key => key.startsWith(this.prefix))
.forEach(key => localStorage.removeItem(key));
}
}
const storage = new StorageManager();
storage.save('highScore', 1000);
const highScore = storage.load('highScore', 0);
游戏存档 #
javascript
class SaveManager {
constructor() {
this.storage = new StorageManager('save_');
}
saveGame(state) {
const saveData = {
timestamp: Date.now(),
player: {
x: state.player.x,
y: state.player.y,
health: state.player.health,
score: state.player.score
},
level: state.level,
inventory: state.inventory
};
return this.storage.save('gameState', saveData);
}
loadGame() {
return this.storage.load('gameState');
}
hasSave() {
return this.storage.load('gameState') !== null;
}
deleteSave() {
this.storage.remove('gameState');
}
}
发布部署 #
构建配置 #
javascript
import { defineConfig } from 'vite';
export default defineConfig({
base: './',
build: {
outDir: 'dist',
assetsDir: 'assets',
minify: 'terser',
terserOptions: {
compress: {
drop_console: true
}
},
rollupOptions: {
output: {
assetFileNames: 'assets/[name].[ext]',
chunkFileNames: 'js/[name].[hash].js',
entryFileNames: 'js/[name].[hash].js'
}
}
},
server: {
open: true,
port: 3000
}
});
打包命令 #
json
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
}
部署到 Web 服务器 #
bash
npm run build
scp -r dist/* user@server:/var/www/game/
部署到 CDN #
javascript
const config = {
loader: {
baseURL: 'https://cdn.example.com/game/'
}
};
调试技巧 #
开发模式检测 #
javascript
const isDev = import.meta.env.DEV;
if (isDev) {
this.physics.world.createDebugGraphic();
}
错误处理 #
javascript
window.onerror = function(message, source, lineno, colno, error) {
console.error('Error:', message, source, lineno, colno, error);
return false;
};
window.addEventListener('unhandledrejection', function(event) {
console.error('Unhandled rejection:', event.reason);
});
日志系统 #
javascript
class Logger {
constructor(enabled = true) {
this.enabled = enabled;
}
log(...args) {
if (this.enabled) console.log('[LOG]', ...args);
}
warn(...args) {
if (this.enabled) console.warn('[WARN]', ...args);
}
error(...args) {
console.error('[ERROR]', ...args);
}
time(label) {
if (this.enabled) console.time(label);
}
timeEnd(label) {
if (this.enabled) console.timeEnd(label);
}
}
const logger = new Logger(import.meta.env.DEV);
完整示例 #
游戏管理器 #
javascript
class Game {
constructor() {
this.config = this.createConfig();
this.game = new Phaser.Game(this.config);
this.setupGlobalEvents();
}
createConfig() {
return {
type: Phaser.AUTO,
width: 800,
height: 600,
parent: 'game-container',
backgroundColor: '#2d2d2d',
scale: {
mode: Phaser.Scale.FIT,
autoCenter: Phaser.Scale.CENTER_BOTH
},
physics: {
default: 'arcade',
arcade: {
gravity: { y: 300 },
debug: false
}
},
scene: [BootScene, PreloadScene, MenuScene, GameScene, UIScene]
};
}
setupGlobalEvents() {
this.game.events.on('ready', () => {
console.log('Game ready');
});
}
}
window.addEventListener('load', () => {
new Game();
});
总结 #
恭喜你完成了 Phaser 完全指南的学习!你现在应该已经掌握了:
- Phaser 的基本概念和安装配置
- 场景系统和游戏对象
- 精灵系统和动画
- 输入处理和物理引擎
- 瓦片地图和音频系统
- 补间动画和粒子效果
- 游戏组和插件系统
- 着色器和性能优化
- 项目架构和最佳实践
继续实践,创建你自己的游戏!
最后更新:2026-03-29