🌑

冰河末日的博客

游戏引擎Phaser使用总结

— 2020年2月27日
  1. 初始化游戏
  2. 移动端适配
  3. 场景的生命周期
    1. 资源的预加载 Preload
    2. 场景创建 create
    3. 画布更新 update
    4. 渲染设置 render
  4. 场景的管理
    1. 场景的切换
    2. 场景的销毁
  5. 常见对象
  6. 文本:Text
    1. 自定义字体
    2. 字体预加载
    3. 字体的行距
    4. 字符的间距
  7. 位图字体:BitmapText
  8. 时间:Time
    1. 定时器:Timer
    2. 定时器事件:TimerEvent
  9. 动画
  10. 事件绑定

Phaser 在渲染方面支持 webGL/canvas,架构方面 Phaser 直接内嵌了 3 个物理引擎(Arcade Physics,Ninja,p2.js)
提供了动画,预加载,设备适配方案,粒子系统等功能。兼容方面移动端优先。这边之介绍我们最常用的一些方法/对象跟自己踩过的一些坑的经验分享。

初始化游戏

new Phaser.Game(width, height, renderer, parent, state, transparent, antialias)

  • width:画布宽度
  • height:画布高度
  • renderer:渲染方式
    • Phaser.AUTO
    • Phaser.CANVAS
    • Phaser.WEBGL
  • parent:游戏 canvas 挂载的 DOM ID 或者 DOM 节点
  • state:游戏场景对象(按执行顺序:init、preload、create、update、render)
  • transparent:是否为透明
  • antialias:贴图是否抗锯齿
let game = new Phaser.Game(
  800,
  600,
  Phaser.AUTO,
  "phaser-container",
  {
    init: init,
    preload: preload,
    create: create,
    update: update,
    render: render,
  },
  false,
  true
);

移动端适配

以 750*1336 设计稿为例。

let game = new Phaser.Game(750, 1336, Phaser.CANVAS, "game", {}, true, true);
// 推荐 SHOW_ALL:
// 比例不变,缩放不变形(通常使用该类型)
game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;

场景的生命周期

可以理解为类型 vue 哪有的生命周期,在一个场景从创建到渲染都会走的几个钩子函数

// 初始化
function init() {}
// 预加载
function preload() {}
// 场景创建
function create() {}
// 画布更新
function update() {}
// 渲染设置
function render() {}

资源的预加载 Preload

写在 preload 函数中

  1. game.load.image(key, url, overwrite)

场景创建 create

画布更新 update

渲染设置 render

场景的管理

场景的切换

场景的销毁

// 销毁整个游戏
game.destroy();

常见对象

Game 对象

  • World 对象
    • 设置游戏世界范围
// 不设默认为canvas画布大小
game.world.setBounds(x, y, width, height);

Stage 对象
Camare 对象
State
Sprite

文本:Text

自定义字体

/* CSS中先设置好字体 */
@font-face {
  font-family: "WEBFONT";
  font-display: swap;
  src: url("../font/webfont.eot"); /* IE9*/
  src: url("../font/webfont.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */
      url("../font/webfont.woff2") format("woff2"),
    url("../font/webfont.woff") format("woff"), /* chrome、firefox */
      url("../font/webfont.ttf") format("truetype"),
    /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
      url("../font/webfont.svg#思源黑体-细") format("svg"); /* iOS 4.1- */
}
// Phaser中添加字体的设置
let style = {
  font: "30px WEBFONT",
};
game.add.text(0, 0, "你好世界", style);

字体预加载

  • 自定义字体常见的坑:
    • 当字体 没有加载完毕 ,Phaser 还是会渲染系统默认当字体
  • 解决方案:
    • 使用第三方库 fontfaceobserver 来做字体的预加载
// 在vue的钩子函数mounted中做预加载
async mounted () {
  // 要加载的字体
  let fontOptions = [
    'HELVETI1-1',
    'WEBFONT'
  ];
  // 加载完成后返回的promise队列
  let fontLoadList = [];
  fontOptions.forEach((item) => {
    let font = new FontFaceObserver(item);
    fontLoadList.push(font.load(null, 5000));
  })
  // 等待所有promise完成
  await Promise.all(fontLoadList).then((resolve) => {
    // 游戏初始化
    init();
  }).catch((reason) => {
    console.log('字体加载失败:', reason);
  });
},

字体的行距

text.lineSpacing = 40;

字符的间距

很遗憾 Phaser 不支持,也不是 Phaser 的问题而是 canvas 对文字排版这块支持比较弱。可以使用一些 hack 手段来实现,但是会比较繁琐,可以看张鑫旭老师的这篇博文介绍:
绘制字符间距。

也可以用通过BitmapText这种图片字体来实现,不过种方式也不太适合中文(文字太多工作量太大)

位图字体:BitmapText

时间:Time

基本时间事件

// Phaser.Timer.SECOND 每秒的毫秒数(1000)
game.time.events.add(Phaser.Timer.SECOND * 4, function () {}, this);

定时器:Timer

定时器事件:TimerEvent

使用Phaser.Timer.add / Phaser.Timer.repeat / Phaser.Timer.loop 方法来新建事件

动画

事件绑定

,

知行合一