精灵表
现在您已了解了基本精灵,是时候讨论创建它们的更好方法了 - Spritesheet 类。
Spritesheet 是一种更高效地下载和渲染精灵的媒体格式。虽然创建和使用起来有些复杂,但它们是优化项目的一个关键工具。
Spritesheet 的解剖
Spritesheet 的基本思想是将一系列图像打包成一张图像,跟踪每张源图像的最终位置,并将该组合图像用作所得精灵的共享基础纹理。
第一步是收集您想要组合的图像。然后,精灵打包器收集图像,并创建一个新的组合图像。
创建此图像时,构建它的工具会跟踪存储每张源图像的矩形的位置。然后,它会写出一个包含该信息的 JSON 文件。
这两个文件结合在一起,可以传入 SpriteSheet 构造函数。然后 SpriteSheet 对象解析 JSON,并为每张源图像创建一系列纹理对象,根据 JSON 数据为每个纹理设置源矩形。每个纹理都使用相同的基础纹理作为其源。
双重高效性
SpriteSheet 有助于您的项目,方法有以下两种。
首先,通过加快加载过程。尽管下载 SpriteSheet 的纹理需要移动相同(甚至略多!)数量的字节,但这些字节会归为一个文件。这意味着用户的浏览器可以请求并下载更少的文件以获得相同数量的 Sprite。文件数量本身是下载速度的一个关键驱动因素,因为每个请求都需要往返 Web 服务器,并且浏览器对可以同时下载的文件数量有限制。将项目从单独的源图像转换为共享精灵表,这可以在不降低质量的情况下将下载时间减少一半。
其次,通过改善批处理渲染。WebGL 渲染速度基本上会随进行的绘制调用的数量而扩展。将多个 Sprite 等分批到单个绘制调用中是 PixiJS 可以如此快地运行的主要秘诀。最大化批处理是一个复杂的话题,但是当多个 Sprite 都共享一个公共 BaseTexture 时,就更有可能将它们一起批处理并以单次调用渲染。
创建 SpriteSheet
你可以使用第三方工具来组装你的精灵表单文件。这里有两个可能适合你的需求
ShoeBox:ShoeBox 是一个免费的、基于 Adobe AIR 的精灵打包实用程序,非常适合小型项目或学习 SpriteSheet 的工作原理。
TexturePacker:TexturePacker 是一款功能更强大的工具,支持高级功能和工作流。它有一个免费版本,该版本具有为 PixiJS 打包精灵表所需的所有必要功能。它非常适用于大型项目和专业游戏开发,或需要更复杂的切片映射功能的项目。
还可以手动或以编程方式创建精灵表单数据,并将其提供给新动画精灵。如果你的精灵已经包含在单个图像中,这可能是一个更简单的选择。
// Create object to store sprite sheet data
const atlasData = {
frames: {
enemy1: {
frame: { x: 0, y:0, w:32, h:32 },
sourceSize: { w: 32, h: 32 },
spriteSourceSize: { x: 0, y: 0, w: 32, h: 32 }
},
enemy2: {
frame: { x: 32, y:0, w:32, h:32 },
sourceSize: { w: 32, h: 32 },
spriteSourceSize: { x: 0, y: 0, w: 32, h: 32 }
},
},
meta: {
image: 'images/spritesheet.png',
format: 'RGBA8888',
size: { w: 128, h: 32 },
scale: 1
},
animations: {
enemy: ['enemy1','enemy2'] //array of frames by name
}
}
// Create the SpriteSheet from data and image
const spritesheet = new Spritesheet(
Texture.from(atlasData.meta.image),
atlasData
);
// Generate all the Textures asynchronously
await spritesheet.parse();
// spritesheet is ready to use!
const anim = new AnimatedSprite(spritesheet.animations.enemy);
// set the animation speed
anim.animationSpeed = 0.1666;
// play the animation on a loop
anim.play();
// add it to the stage to render
app.stage.addChild(anim);