Skip to main content

精灵表


现在你已经了解了基本的精灵,是时候讨论创建它们的更好方法了 - 精灵表 类。

英:Now that you understand basic sprites, it's time to talk about a better way to create them - the Spritesheet class.

Spritesheet 是一种用于更有效地下载和渲染 Sprite 的媒体格式。 虽然创建和使用起来有些复杂,但它们是优化项目的关键工具。

英:A Spritesheet is a media format for more efficiently downloading and rendering Sprites. While somewhat more complex to create and use, they are a key tool in optimizing your project.

Spritesheet 剖析

Spritesheet 的基本思想是将一系列图片打包成单个图片,跟踪每个源图片的最终位置,并将该组合图片用作生成的 Sprite 的共享 BaseTexture。

英:The basic idea of a spritesheet is to pack a series of images together into a single image, track where each source image ends up, and use that combined image as a shared BaseTexture for the resulting Sprites.

第一步是收集要组合的图片。 然后,精灵打包器收集图片,并创建新的组合图片。

英:The first step is to collect the images you want to combine. The sprite packer then collects the images, and creates a new combined image.

创建此图片时,构建它的工具会跟踪存储每个源图片的矩形的位置。 然后它会写出包含该信息的 JSON 文件。

英:As this image is being created, the tool building it keeps track of the location of the rectangle where each source image is stored. It then writes out a JSON file with that information.

这两个文件组合起来可以传递到 SpriteSheet 构造函数中。 然后,SpriteSheet 对象解析 JSON,并创建一系列纹理对象,每个对象对应一个源图片,并根据 JSON 数据为每个对象设置源矩形。 每个纹理都使用相同的共享 BaseTexture 作为其源。

英:These two files, in combination, can be passed into a SpriteSheet constructor. The SpriteSheet object then parses the JSON, and creates a series of Texture objects, one for each source image, setting the source rectangle for each based on the JSON data. Each texture uses the same shared BaseTexture as its source.

双倍效率

SpriteSheets 通过两种方式帮助你的项目。

英:SpriteSheets help your project in two ways.

首先,加快加载过程。 虽然下载 SpriteSheet 的纹理需要移动相同(甚至稍微多一点!)的字节数,但它们会被分组到一个文件中。 这意味着对于相同数量的 Sprite,用户的浏览器可以请求和下载更少的文件。 文件数量本身是下载速度的关键驱动因素,因为每个请求都需要往返网络服务器,而浏览器则受到可以同时下载的文件数量的限制。 将项目从单个源图片转换为共享精灵表可以将你的下载时间缩短一半,而不会影响质量。

英:First, by speeding up the loading process. While downloading a SpriteSheet's texture requires moving the same (or even slightly more!) number of bytes, they're grouped into a single file. This means that the user's browser can request and download far fewer files for the same number of Sprites. The number of files itself is a key driver of download speed, because each request requires a round-trip to the webserver, and browsers are limited to how many files they can download simultaneously. Converting a project from individual source images to shared sprite sheets can cut your download time in half, at no cost in quality.

其次,通过改进批量渲染。 WebGL 渲染速度大致与绘制调用的数量成正比。 将多个 Sprite 等批处理到单个绘制调用中是 PixiJS 运行速度如此之快的主要秘密。 最大化批处理是一个复杂的主题,但是当多个 Sprite 都共享一个公共 BaseTexture 时,它们更有可能一起批处理并在一次调用中渲染。

英:Second, by improving batch rendering. WebGL rendering speed scales roughly with the number of draw calls made. Batching multiple Sprites, etc. into a single draw call is the main secret to how PixiJS can run so blazingly fast. Maximizing batching is a complex topic, but when multiple Sprites all share a common BaseTexture, it makes it more likely that they can be batched together and rendered in a single call.

创建 SpriteSheets

你可以使用第三方工具来组装精灵表文件。 这里有两个可能适合你的需求:

英:You can use a 3rd party tool to assemble your sprite sheet files. Here are two that may fit your needs:

ShoeBox: ShoeBox 是一款免费的、基于 Adobe AIR 的精灵打包实用程序,非常适合小型项目或学习 SpriteSheets 的工作原理。

英:ShoeBox: ShoeBox is a free, Adobe AIR-based sprite packing utility that is great for small projects or learning how SpriteSheets work.

TexturePacker: TexturePacker 是一个更加完善的工具,支持高级功能和工作流程。 提供免费版本,其中包含为 PixiJS 打包 spritesheet 所需的所有功能。 它非常适合大型项目和专业游戏开发,或需要更复杂的图块映射功能的项目。

英:TexturePacker: TexturePacker is a more polished tool that supports advanced features and workflows. A free version is available which has all the necessary features for packing spritesheets for PixiJS. It's a good fit for larger projects and professional game development, or projects that need more complex tile mapping features.

Spritesheet 数据也可以手动或以编程方式创建,并提供给新的 AnimatedSprite。 如果你的精灵已包含在单个图片中,这可能是一个更简单的选择。

英:Spritesheet data can also be created manually or programmatically, and supplied to a new AnimatedSprite. This may be an easier option if your sprites are already contained in a single image.

// 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 PIXI.Spritesheet(
PIXI.BaseTexture.from(atlasData.meta.image),
atlasData
);

// Generate all the Textures asynchronously
await spritesheet.parse();

// spritesheet is ready to use!
const anim = new PIXI.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);