回到H5行业后的前几个项目,试着用了下以前一直想用的Phaser3,体验还阔以。本篇简单讲讲一些经验和碰到过的坑。
首先需要提前讲的,比较合适的参考/文档(目前来看)有以下三个:
(最后一个重点推荐,之前有好多东西,我看官方文档看的满头问号,但是看这个文档是真的能看懂~)
好,下面可以开始(suì)正(suì)题(niàn)了。
Phaser3使用起来大概可以分成 3 个部分:
- 加载基础的库文件(废话),这里包括Phaser3库本体(可以自己定制)和一些第三方插件(如果有的话);
- 全局配置,是一个对象,包括渲染方式(Canvas 还是 WebGL)、背景色、Canvas 容器的 CSS 基础样式、缩放适配、事件监听的开/闭,一直到 Scene 配置(后边讲),直接写到里边就成;
- Scene,简单来说有点像游戏里的场景,每个场景里会包含各自独立的精灵、图片之类不同的资源,以及各种数据,甚至插件等。比如切换页面,就可以直接用场景功能来实现。
在代码结构上,我个人比较倾向于每个Scene/页面一个文件,一个Scene重新new个Phaser.Scene
出来就好。然后在首页HTML里把每个Scene文件全加载以后,再上init.js全局配置就行了。当然,一些统计/jQ辅助/wechat分享注册/bgm自动加载之类的代码放前边就好。
下边说一些零零碎碎的经验:
- 首先是Phaser3库文件可以精简,官方有个photonstorm/phaser3-custom-build项目,就是教你怎么自己build库文件的,我自己fork了一下放到了MarsGT/phaser3-custom-build,主要是敲掉一些用不着的东西,精简过后大概600k~800k左右。
this.add.text
如果用自定义字体(比如用Fontmin精简过的),需要在HTML里加个用了这个字体的div,比如<div style='font-family:myfont;position:absolute;visibility:hidden;'>000</div>
,否则字体不会生效;如果就想用默认的字体,直接把fontFamily
设置为sans-serif
就行了。- 骨骼动画目前没法直接用DragonBones的Runtime(我是Demo都跑不出来的那种不能用),但可以使用Spine的,直接到Phaser3主项目的
plugins/spine/dist
目录下就能找到这个插件了,在HTML里加载,然后在全局配置里加上
就能用了。plugins: { scene: [ { key: 'SpineWebGLPlugin', plugin: SpineWebGLPlugin, start: true } ] },
另外在DragonBones输出Spine格式的时候要注意,我个人不推荐用编辑器直出,而更建议用DragonBones Tools这个工具转换已有的DragonBones文件,主要是因为编辑器直出的是3.3版本的(spine)文件,而转换出来的则是3.6。不过转换出来还需要检查下json主配置文件,里边有个deform
字段,其下可能会存在一个空字符串主键导致报错,改成"default"
即可。还有,this.load.spine
之前可以先用this.load.setPath
设置下路径,这样json文件和atlas文件可以不用再写整段路径了,还有png素材也不用去单独指定路径了。
再补充下,如果DragonBones动画里使用了ik,到网页上时ik可能会出现完全失效的情况,会使动画出现“鬼畜”(实际是由于失去了ik的约束,使原有骨骼出现了错位),这是因为 DragonBones导出的Spine JSON文件中,ik
字段数组下的每个成员都缺少了一个order
字段(其实就是排序),加上之后就没问题了。 - 说一下预加载。预加载一般单独放个Scene里,比如可以叫loader,那么loader需要的资源就在
loader.preload
回调里加载,然后整个H5需要用到的资源放到loader.create
回调里加载(实际就是动态加载)。另外注意在create回调里加载资源的时候,最后需要加一句this.load.start()
启动加载。至于progress和complete这俩事件就不多说了。 - 如果不是全站CDN(HTML文件在普通服上,其它静态资源在CDN),可以在HTML文件的
<head>
里加个<base>
标签设置CDN基地址,相对比较方便。 - 对于数量限定的位图字体,比如只在游戏计分出现的字体(只有数字),用RetroFont是最方便的。切图处理时需要注意,要把所有用到的字符单独输出等大的图片,然后横向拼到一张图里,加载时按普通图片加载就行,初始化需要用RetroFont的方式:
然后就可以直接按bitmaptext那样去用了this.cache.bitmapFont.add('my_num', Phaser.GameObjects.RetroFont.Parse(this, { image: 'my_num', width: 52, height: 83, chars: '0123456789', // 指定图里都是什么字符 charsPerRow: 10, // 每行字符数 spacing: { x: 0, y: 0 } // 每字符相隔像素数 }))
this.add.bitmapText(106, 64, 'my_num', '012')
- 全局配置,直接放代码了:
var config = { type: Phaser.AUTO, // 一般用Phaser.AUTO就行,很少有项目需要强行指定Phaser.WEBGL的。Canvas那项我觉得没啥用 // backgroundColor: 0x1b1b1d, // 看项目需要,如果需要背景色时可以直接在这里设置 render: { antialias: true, // 抗锯齿,建议开 transparent: true // Canvas容器背景透明,如果有和DOM有交互时这项可以开,记得把背景色关掉 }, canvasStyle: 'overflow:hidden;', // 在这里设置Canvas容器的行内样式 banner: false, // 把这项关掉,就不会在控制台输出Phaser引擎版本之类自带的调试信息了 scale: { width: 750, // 建议把设计稿尺寸写这里,会按这个尺寸缩放 height: 1206, mode: Phaser.Scale.ENVELOP, // 适配方式,Phaser.Scale.ENVELOP就相当于是cover,而Phaser.Scale.FIT相当于contain autoCenter: Phaser.Scale.CENTER_BOTH, // 居中方式,有CENTER_HORIZONTALLY、CENTER_VERTICALLY和CENTER_BOTH三种可选 max: { // 指定适配后的最大尺寸,这里限制一下,在pc端会美观一点(不会出现尺寸特别大的情况) width: 1080, height: 1920 } }, physics: { default: 'arcade', // 物理引擎,一般不大的需求用arcade就够了 arcade: { debug: false } // arcade设置,打开debug可以看到刚体的定界框 }, input: { mouse: false, // 移动端项目一般关掉mouse,不然会出点透bug activePointers: 1 // 多指触摸限制,不过貌似用处不大 }, disableContextMenu: true, loader: { crossOrigin: 'anonymous' // 避免图片跨域 }, scene: [loader, home, game] // 这里放每一个Scene的变量,初始化完成后默认加载第一个Scene }