Phaser 基础概念 #

游戏实例 #

创建游戏 #

Phaser 游戏的核心是 Phaser.Game 实例:

javascript
const config = {
  type: Phaser.AUTO,
  width: 800,
  height: 600,
  scene: GameScene
};

const game = new Phaser.Game(config);

游戏实例属性 #

javascript
game.canvas           // Canvas 元素
game.renderer         // 渲染器实例
game.scene            // 场景管理器
game.loop             // 游戏循环
game.scale            // 缩放管理器
game.input            // 输入管理器
game.sound            // 音频管理器
game.textures         // 纹理管理器
game.cache            // 缓存管理器

游戏循环 #

text
┌─────────────────────────────────────────────────────────────┐
│                    游戏循环                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────────────────────────────────────────┐      │
│   │                                                 │      │
│   │    ┌──────────┐                                │      │
│   │    │  开始帧   │                                │      │
│   │    └────┬─────┘                                │      │
│   │         │                                      │      │
│   │         ▼                                      │      │
│   │    ┌──────────┐                                │      │
│   │    │ 处理输入  │                                │      │
│   │    └────┬─────┘                                │      │
│   │         │                                      │      │
│   │         ▼                                      │      │
│   │    ┌──────────┐                                │      │
│   │    │ 更新逻辑  │ ◄─── scene.update()           │      │
│   │    └────┬─────┘                                │      │
│   │         │                                      │      │
│   │         ▼                                      │      │
│   │    ┌──────────┐                                │      │
│   │    │ 渲染画面  │                                │      │
│   │    └────┬─────┘                                │      │
│   │         │                                      │      │
│   │         ▼                                      │      │
│   │    ┌──────────┐                                │      │
│   │    │  结束帧   │                                │      │
│   │    └────┬─────┘                                │      │
│   │         │                                      │      │
│   │         └──────────────┐                       │      │
│   │                        │                       │      │
│   └────────────────────────┼───────────────────────┘      │
│                            │                               │
│                            └─────► 下一帧                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

场景系统 #

场景生命周期 #

javascript
class GameScene extends Phaser.Scene {
  constructor() {
    super({ key: 'GameScene' });
  }

  init(data) {
    // 1. 初始化
    // 接收场景启动时传递的数据
    console.log('Received data:', data);
    this.score = data.score || 0;
  }

  preload() {
    // 2. 加载资源
    // 在 create 之前完成所有资源加载
    this.load.image('sky', 'assets/sky.png');
    this.load.image('ground', 'assets/platform.png');
    this.load.image('star', 'assets/star.png');
  }

  create() {
    // 3. 创建游戏对象
    // 资源加载完成后调用
    this.add.image(400, 300, 'sky');
    this.player = this.physics.add.sprite(100, 450, 'dude');
  }

  update(time, delta) {
    // 4. 游戏循环
    // 每帧调用,处理游戏逻辑
    if (this.cursors.left.isDown) {
      this.player.setVelocityX(-160);
    }
  }

  shutdown() {
    // 5. 场景关闭
    // 清理资源、事件监听器
    this.events.off('customEvent');
  }
}

场景配置 #

javascript
const sceneConfig = {
  key: 'GameScene',           // 场景唯一标识
  active: false,              // 是否立即激活
  visible: true,              // 是否可见
  pack: {                     // 预加载资源
    files: [
      { type: 'image', key: 'loading', url: 'loading.png' }
    ]
  },
  mapAdd: {                   // 注入场景的属性
    score: 0
  },
  map: {                      // 映射插件
    game: 'game'
  }
};

class GameScene extends Phaser.Scene {
  constructor() {
    super(sceneConfig);
  }
}

场景管理 #

javascript
// 启动场景
this.scene.start('GameScene', { level: 1 });

// 暂停场景
this.scene.pause('GameScene');

// 恢复场景
this.scene.resume('GameScene');

// 停止场景
this.scene.stop('GameScene');

// 休眠场景(暂停但不销毁)
this.scene.sleep('GameScene');

// 唤醒场景
this.scene.wake('GameScene');

// 切换场景
this.scene.switch('MenuScene');

// 并行运行场景
this.scene.launch('UIScene');

// 移除场景
this.scene.remove('GameScene');

// 获取场景实例
const gameScene = this.scene.get('GameScene');

多场景协作 #

javascript
const config = {
  type: Phaser.AUTO,
  width: 800,
  height: 600,
  scene: [BootScene, PreloadScene, MenuScene, GameScene, UIScene]
};

// BootScene.js
class BootScene extends Phaser.Scene {
  preload() {
    this.load.image('logo', 'assets/logo.png');
  }
  
  create() {
    this.scene.start('PreloadScene');
  }
}

// GameScene.js - 游戏主场景
class GameScene extends Phaser.Scene {
  create() {
    // 启动 UI 场景
    this.scene.launch('UIScene');
    
    // 与 UI 场景通信
    this.events.emit('scoreUpdate', this.score);
  }
}

// UIScene.js - UI 覆盖层
class UIScene extends Phaser.Scene {
  create() {
    // 监听游戏场景事件
    const gameScene = this.scene.get('GameScene');
    gameScene.events.on('scoreUpdate', (score) => {
      this.scoreText.setText('Score: ' + score);
    });
  }
}

游戏对象 #

常见游戏对象类型 #

text
┌─────────────────────────────────────────────────────────────┐
│                    游戏对象类型                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  基础对象:                                                 │
│  ├── Image          - 静态图像                              │
│  ├── Sprite         - 动画精灵                              │
│  ├── Text           - 文本                                  │
│  ├── TileSprite     - 平铺精灵                              │
│  └── RenderTexture  - 渲染纹理                              │
│                                                             │
│  图形对象:                                                 │
│  ├── Graphics       - 矢量图形                              │
│  ├── Rectangle      - 矩形                                  │
│  ├── Circle         - 圆形                                  │
│  ├── Ellipse        - 椭圆                                  │
│  ├── Triangle       - 三角形                                │
│  ├── Line           - 线条                                  │
│  └── Polygon        - 多边形                                │
│                                                             │
│  容器对象:                                                 │
│  ├── Container      - 容器                                  │
│  ├── Group          - 分组                                  │
│  └── Layer          - 图层                                  │
│                                                             │
│  特殊对象:                                                 │
│  ├── ParticleEmitter - 粒子发射器                           │
│  ├── Light          - 光源                                  │
│  ├── Zone           - 区域                                  │
│  └── BitmapText     - 位图文本                              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

创建游戏对象 #

javascript
// 图像
const image = this.add.image(400, 300, 'sky');

// 精灵
const sprite = this.add.sprite(100, 100, 'player');

// 文本
const text = this.add.text(400, 300, 'Hello', {
  fontSize: '32px',
  fill: '#fff'
});

// 矩形
const rect = this.add.rectangle(400, 300, 200, 100, 0xff0000);

// 圆形
const circle = this.add.circle(400, 300, 50, 0x00ff00);

// 容器
const container = this.add.container(400, 300);
container.add([image, text]);

游戏对象属性 #

javascript
// 位置
sprite.x = 100;
sprite.y = 200;
sprite.setPosition(100, 200);

// 大小
sprite.width = 64;
sprite.height = 64;
sprite.setSize(64, 64);
sprite.setScale(2, 2);      // 缩放
sprite.scaleX = 2;
sprite.scaleY = 2;

// 旋转
sprite.rotation = Math.PI / 4;  // 弧度
sprite.angle = 45;              // 角度

// 原点
sprite.setOrigin(0.5, 0.5);  // 中心
sprite.setOrigin(0, 0);      // 左上角
sprite.setOrigin(1, 1);      // 右下角

// 透明度
sprite.alpha = 0.5;
sprite.setAlpha(0.5);

// 可见性
sprite.visible = true;
sprite.setVisible(true);

// 深度(层级)
sprite.depth = 10;
sprite.setDepth(10);

// 翻转
sprite.setFlipX(true);
sprite.setFlipY(true);

// 混合模式
sprite.setBlendMode(Phaser.BlendModes.ADD);

// 着色
sprite.setTint(0xff0000);
sprite.clearTint();

游戏对象方法 #

javascript
// 销毁
sprite.destroy();

// 复制
const clone = Phaser.Utils.Objects.Clone(sprite);

// 获取边界
const bounds = sprite.getBounds();

// 获取中心点
const center = sprite.getCenter();

// 获取顶部
const top = sprite.getTopCenter();

// 世界坐标转换
const worldPoint = sprite.getWorldTransformMatrix();

// 检查点是否在对象内
const isInside = sprite.getBounds().contains(x, y);

资源加载 #

加载器基础 #

javascript
preload() {
  // 加载图像
  this.load.image('sky', 'assets/sky.png');
  
  // 加载精灵表
  this.load.spritesheet('dude', 'assets/dude.png', {
    frameWidth: 32,
    frameHeight: 48
  });
  
  // 加载音频
  this.load.audio('bgm', 'assets/bgm.mp3');
  
  // 加载 JSON
  this.load.json('data', 'assets/data.json');
  
  // 加载文本
  this.load.text('dialog', 'assets/dialog.txt');
  
  // 加载 XML
  this.load.xml('data', 'assets/data.xml');
  
  // 加载 SVG
  this.load.svg('icon', 'assets/icon.svg');
}

加载事件 #

javascript
preload() {
  // 加载进度
  this.load.on('progress', (value) => {
    console.log('Loading: ' + Math.round(value * 100) + '%');
    progressBar.setScale(value, 1);
  });
  
  // 加载完成
  this.load.on('complete', () => {
    console.log('All assets loaded!');
    this.scene.start('MenuScene');
  });
  
  // 单个文件加载完成
  this.load.on('filecomplete', (key, type, data) => {
    console.log('Loaded:', key);
  });
  
  // 加载错误
  this.load.on('loaderror', (file) => {
    console.error('Error loading:', file.key);
  });
  
  // 开始加载
  this.load.on('start', () => {
    console.log('Loading started');
  });
}

制作加载界面 #

javascript
class PreloadScene extends Phaser.Scene {
  constructor() {
    super({ key: 'PreloadScene' });
  }
  
  preload() {
    // 创建加载界面
    this.createLoadingUI();
    
    // 加载资源
    this.load.image('sky', 'assets/sky.png');
    this.load.image('ground', 'assets/platform.png');
    this.load.spritesheet('dude', 'assets/dude.png', {
      frameWidth: 32,
      frameHeight: 48
    });
  }
  
  createLoadingUI() {
    const width = this.cameras.main.width;
    const height = this.cameras.main.height;
    
    // 进度条背景
    const progressBox = this.add.graphics();
    progressBox.fillStyle(0x222222, 0.8);
    progressBox.fillRect(width / 2 - 160, height / 2 - 25, 320, 50);
    
    // 进度条
    const progressBar = this.add.graphics();
    
    // 加载文字
    const loadingText = this.add.text(width / 2, height / 2 - 50, 'Loading...', {
      fontSize: '20px',
      fill: '#fff'
    }).setOrigin(0.5);
    
    // 百分比文字
    const percentText = this.add.text(width / 2, height / 2, '0%', {
      fontSize: '18px',
      fill: '#fff'
    }).setOrigin(0.5);
    
    // 监听加载进度
    this.load.on('progress', (value) => {
      percentText.setText(Math.round(value * 100) + '%');
      progressBar.clear();
      progressBar.fillStyle(0x00ff00, 1);
      progressBar.fillRect(width / 2 - 150, height / 2 - 15, 300 * value, 30);
    });
    
    this.load.on('complete', () => {
      progressBar.destroy();
      progressBox.destroy();
      loadingText.destroy();
      percentText.destroy();
    });
  }
  
  create() {
    this.scene.start('MenuScene');
  }
}

加载多文件 #

javascript
// 批量加载图像
this.load.image([
  { key: 'sky', url: 'assets/sky.png' },
  { key: 'ground', url: 'assets/platform.png' },
  { key: 'star', url: 'assets/star.png' },
  { key: 'bomb', url: 'assets/bomb.png' }
]);

// 使用 atlas
this.load.atlas('game', 'assets/game.png', 'assets/game.json');

// 加载瓦片地图
this.load.tilemapTiledJSON('map', 'assets/map.json');

资源缓存 #

javascript
// 获取缓存资源
const texture = this.textures.get('player');
const json = this.cache.json.get('data');
const audio = this.cache.audio.get('bgm');

// 检查资源是否存在
if (this.textures.exists('player')) {
  // 资源存在
}

// 移除缓存
this.textures.remove('player');
this.cache.json.remove('data');

坐标系统 #

世界坐标与屏幕坐标 #

text
┌─────────────────────────────────────────────────────────────┐
│                    坐标系统                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  屏幕坐标 (0, 0)                                            │
│      │                                                      │
│      │    ┌─────────────────────┐                          │
│      │    │                     │                          │
│      │    │   世界坐标          │                          │
│      │    │   (相机偏移)        │                          │
│      │    │                     │                          │
│      │    │      ● (100, 100)   │                          │
│      │    │                     │                          │
│      │    └─────────────────────┘                          │
│      │                                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

坐标转换 #

javascript
// 世界坐标转屏幕坐标
const screenPoint = this.cameras.main.worldView.contains(x, y);

// 屏幕坐标转世界坐标
const worldPoint = this.cameras.main.getWorldPoint(pointer.x, pointer.y);

// 相机滚动
this.cameras.main.scrollX = 100;
this.cameras.main.scrollY = 50;

原点与锚点 #

text
┌─────────────────────────────────────────────────────────────┐
│                    原点位置                                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  setOrigin(0, 0)      setOrigin(0.5, 0.5)    setOrigin(1, 1)│
│                                                             │
│  ┌─────────┐              ┌─────────┐        ┌─────────┐   │
│  │●        │              │         │        │        ●│   │
│  │         │              │    ●    │        │         │   │
│  │         │              │         │        │         │   │
│  └─────────┘              └─────────┘        └─────────┘   │
│  左上角                    中心               右下角        │
│                                                             │
└─────────────────────────────────────────────────────────────┘
javascript
// 设置原点
sprite.setOrigin(0, 0);     // 左上角
sprite.setOrigin(0.5, 0.5); // 中心(默认)
sprite.setOrigin(1, 1);     // 右下角
sprite.setOrigin(0.5, 1);   // 底部中心

// 设置原点并更新位置
sprite.setOrigin(0.5, 0.5);

时间与计时器 #

游戏时间 #

javascript
// 获取游戏时间
const time = this.time.now;           // 游戏开始后的毫秒数
const delta = this.game.loop.delta;   // 帧间隔(毫秒)

// update 方法中的时间
update(time, delta) {
  // time: 当前时间戳
  // delta: 距离上一帧的时间
}

计时器 #

javascript
// 延迟执行
this.time.delayedCall(1000, () => {
  console.log('1秒后执行');
});

// 带参数的延迟执行
this.time.delayedCall(1000, (message) => {
  console.log(message);
}, ['Hello!']);

// 重复执行
this.time.addEvent({
  delay: 1000,
  callback: () => {
    console.log('每秒执行一次');
  },
  loop: true
});

// 有限次数重复
this.time.addEvent({
  delay: 1000,
  callback: () => {
    console.log('执行');
  },
  repeat: 4  // 执行5次(初始1次 + 重复4次)
});

// 保存计时器引用以便清除
const timer = this.time.addEvent({
  delay: 1000,
  callback: updateScore,
  loop: true
});

// 清除计时器
timer.remove();

// 暂停/恢复计时器
timer.paused = true;
timer.paused = false;

计时器事件 #

javascript
const timerEvent = this.time.addEvent({
  delay: 2000,
  callback: onEvent,
  callbackScope: this,
  loop: true
});

// 获取计时器信息
console.log(timerEvent.elapsed);     // 已过时间
console.log(timerEvent.progress);    // 进度 (0-1)
console.log(timerEvent.repeatCount); // 剩余重复次数

// 手动触发
timerEvent.dispatch();

下一步 #

现在你已经掌握了 Phaser 的基础概念,接下来学习 场景系统,深入了解场景的管理与通信!

最后更新:2026-03-29