背景
最近在做一个城市旅行打卡养成类的活动需求,其中主场景地图模块是采用PixiJs
渲染的,由于之前也没有接触过H5游戏的开发,对于PixiJs
也是只停留在有所耳闻的阶段,因此这次的开发也是现学现用,前后历时1个月左右的时间,踩了一些坑,也总结了一些个人的开发经验,基于PixiJs
做了一些基础的游戏功能API
的封装。俗话说得好:“工欲善其事,必先利其器。”,在揭晓这些API
的神秘面纱之前,我们一起来学习一下PixiJs
的几个简单概念,为我们后续的深入了解打下基础。
PixiJs
官网对于PixiJs
的定义:它是一个非常快的2D sprite渲染引擎
。渲染引擎就说明它负责关于渲染的一切功能,可以帮助我们显示、动画和管理交互图形。
几个基本概念
Application
const app = new PIXI.Application({
width: 256, // default: 800 宽度
height: 256, // default: 600 高度
antialias: true, // default: false 反锯齿
transparent: false, // default: false 透明度
resolution: 1 // default: 1 分辨率
})
document.body.appendChild(app.view)
pixi通过Application
对象创建一个矩形显示区域。它会自动生成一个HTML的canvas
元素,所有的绘制都是基于这个canvas
画布。Application
也会自动选择使用Canvas或者是WebGL来渲染图形,这个取决于浏览器的支持情况。
Container
Container
-容器对象,它会在应用中创造一个新的图层。可以类比于我们HTML中的div
,作为一个容器,必然是可以装载子元素对象,在实际开发中,我们一般用它来为显示对象
做分组。
Sprite
在pixi中,Sprite(精灵)
是一种特殊的图像对象,这个应该是游戏开发最常用的对象之一了,实际开发中,一般用它来显示游戏图片资源。
Loader
pixi使用WebGL在GPU上渲染图像,因此图像需要被转换为GPU可以处理的对象,这个对象在pixi中被称为texture(纹理)
,为了保证存取的高效,pixi使用text cache(纹理缓存)
来存储和引用精灵需要的所有纹理。那么如何加载图像文件,将它转化为GPU所需要的纹理呢?那就需要Loader(加载器)
对象来出马了,它可以加载任何类型格式的图像。
了解完上面一些基础概念之后,我们就来开始今天第一个API
的揭秘。
封装一个图片预加载API
首先我们要明白为什么需要预加载,上面我们提到如果要创建一个Sprite
精灵对象,就需要取纹理缓存中存储的纹理对象,而纹理对象是通过Loder
加载器加载转化的。也就是我们游戏的loading
过程其实就是通过加载器加载图像资源转化为纹理对象的过程。
Loder的基本使用方式
// pixiv5.0.x版本以后Loader挂载在shared属性下
const Loader = PIXI.Loader.shared
// 一、add加载图像列表
Loader.add([
'assets/fire.png',
'assets/water.png'
])
.load(callback)
// 二、add加载单个图片,为资源分配名称
Loader.add('fire', 'aasets/fire.png').load(callback)
// 三、单个资源加载成功回调,其中的url可以是本地图片地址,也可以是远程cdn图片资源地址
Loader.add([
{ name: 'fire', url: 'assets/fire.png', onComplete: () => {} }
])
.load(callback)
从上面可以看出loader加载器先add
加载图像资源(列表),load
为加载完成的回调,所以基于上述loader
相关api进行封装:
export default function (resource: Array<any[]>): Promise<unknown> {
if (!Array.isArray(resource)) {
console.error(`请传入一个资源列表`)
return
}
let loaderArr = []
if (Array.isArray(resource[0])) {
resource.forEach(item => {
const onComplete = item[2] ? item[2] : null
const loaderItem = {
name: item[0], // 资源的别名
url: item[1], // 资源的地址
onComplete // 资源完成加载时要调用的函数
}
loaderArr.push(loaderItem)
})
} else {
loaderArr = resource
}
return new Promise((resolve, reject) => {
Loader.add(loaderArr)
.load(resolve)
Loader.onError.add(reject)
})
}
使用方式如下:
let count = 0
// 用作计算资源的加载进度
const loadCount = () => {
count++
console.log(`加载资源图片第${count}张, 时间${Date.now()}`)
}
// 预加载
Preloader([
['fire', 'assets/fire.png', loadCount],
['water', 'assets/water.png', loadCount],
['json', 'assets/sprite.json', loadCount]
]).then(() => {
console.log('资源加载成功')
}).catch(() => {
console.log('资源加载失败')
})
Loder
加载器支持加载雪碧图的json
文件。那么基于pixi的雪碧图该如何制作呢,接下来我们聊聊这个话题。
关于如何制作PixiJs雪碧图
在游戏开发领域,资源加载效率是游戏性能的一大瓶颈,为了提升游戏的加载性能,对于多张同类型的资源图片,会通过软件合成的方式把他们合成到一张图片上,这张图片就是雪碧图,减少了网络请求次数。而我们通常用来做雪碧图的工具就是TexturePacker
,字面上的意思就是纹理打包工具
。软件操作界面:
只需要在右侧设置一览的数据格式中选择PixiJS
选项即可,最后生成的文件包含一个.json
和一个.png/.jpg
文件,前者是每张图片在雪碧图上的位置和图片相关信息,后者是合成之后的大尺寸雪碧图,其中的json文件格式:
其中的meta/image
属性替换成你的cdn图片资源地址即可,而鲜肉月饼
则是该图片对应的纹理名称
,然后Preloader
中的json地址替换成你的cdn上的json地址即可,json上包含的所有的图片对象纹理都会被加载到纹理缓存中。
TexturePacker
软件还是很方便的,支持业内几乎全部流行的游戏引擎,包括但不限于Cocos
、Unity
、白鹭Egret
、PixiJs
等,不过专业版对于一台机器只有7天的试用期,免费版不能使用高级算法,合成出来的雪碧图有瑕疵,这个就比较没办法,除非愿意付费支持,目前还没有其他相关的能代替它的工具,如果有小伙伴知道的,可以评论区分享出来哈~
后记
本次主要分享关于PixiJs
的一些基础知识,封装一个简单的资源预加载器,以及TexturePacker
软件用于合成雪碧图的一些基础使用步骤。后续会更新关于帧动画播放
、碰撞检测
以及自适应的应用创建
等相关API
,有问题评论区码字,也欢迎指错勘误!