Golang语言情怀--第118期 全栈小游戏开发:第9节:精灵帧资源(SpriteFrame)

2023-11-22 14:01:56 浏览数 (2)

Cocos Creator 的 SpriteFrame 是 UI 渲染基础图形的容器。其本身管理图像的裁剪和九宫格信息,默认持有一个与其同级的 Texture2D 资源引用。

导入精灵帧资源

使用默认的 资源导入 方式将图像资源导入到项目中,然后在 属性检查器 中将图像资源的类型设置为 sprite-frame,并点击右上角的绿色打钩按钮保存:

Creator 便会自动在导入的图像资源下创建一个如下图所示的 spriteFrame 资源:

图像资源在 资源管理器 中会以自身图片的缩略图作为图标。在 资源管理器 中选中图像子资源后,属性检查器 下方会显示该图片的缩略图。

属性

spriteFrame 资源属性如下:

属性

功能说明

Packable

是否参与动态合图,详情请参考下文 Packable 部分的内容

Rotated

只读属性,不可更改。用于查看 Texture Packer 资源中的子资源是否被旋转

Offset X、Y

只读属性,不可更改。用于查看 Texture Packer 资源中矩形框的偏移量

Trim Type

裁剪类型,包括:1. Auto — 自动裁剪(默认),详情请参考 图像资源的自动剪裁2. Custom — 自定义裁剪3. None — 无裁剪,使用原图

Trim Threshold

透明度阈值,默认为 1,取值范围为 0~1,会将透明度在设定值以下的像素裁减掉。当 Trim Type 设置为 Auto 时生效

Trim X、Y、Width、Height

设置裁剪矩形框,当 Trim Type 设置为 Custom 时生效

Border Top、Bottom、Left、Right

设置九宫格图边距,可点击下方的 编辑 按钮进行可视化编辑

Packable

如果引擎开启了 动态合图 功能,动态合图会自动将合适的贴图在开始场景时动态合并到一张大图上来减少 Drawcall。但是将贴图合并到大图中会修改原始贴图的 UV 坐标,如果在自定义 effect 中使用了贴图的 UV 坐标,这时 effect 中的 UV 计算将会出错,需要将贴图的 Packable 属性设置为 false 来避免贴图被打包到动态合图中。

使用 SpriteFrame

使用 texture 渲染

将 SpriteFrame 资源拖拽到 Sprite 组件 的 SpriteFrame 属性框中,即可切换 Sprite 显示的图像。

在运行时,以上图中导入的名为 content 的图片为例,整个资源分为三部分:

  • content:图像源资源 ImageAsset
  • content 的子资源 spriteFrame,即精灵帧资源 SpriteFrame
  • content 的子资源 texture,即贴图资源 Texture2D

当资源存放在 resources 目录下时,我们可直接加载到 spriteFrame 资源,代码示例如下:

代码语言:javascript复制
const url = 'test_assets/test_atlas/content/spriteFrame';
resources.load(url, SpriteFrame, (err: any, spriteFrame) => {
  const sprite = this.getComponent(Sprite);
  sprite.spriteFrame = spriteFrame;
});

但在有些情况下只能加载到图像源资源 ImageAsset,因此我们提供了 createWithImage 方法来帮助用户通过加载到的 ImageAsset 创建一个 SpriteFrame 资源。根据 ImageAsset 的来源不同,有以下两种创建方式:

存放在服务器上的资源只能加载到图像源资源 ImageAsset,加载方法请参考 动态加载资源。创建 SpriteFrame 资源的代码示例如下:

代码语言:javascript复制
 const self = this;
 const url = 'test_assets/test_atlas/content';
 resources.load(url, ImageAsset, (err: any, imageAsset) => {
   const sprite = this.getComponent(Sprite);
   sprite.spriteFrame = SpriteFrame.createWithImage(imageAsset);
 });

或者用户也可以手动填充信息,代码示例如下:

代码语言:javascript复制
 const self = this;
 const url = 'test_assets/test_atlas/content';
 resources.load(url, ImageAsset, (err: any, imageAsset) => {
   const sprite = this.getComponent(Sprite);
   const spriteFrame = new SpriteFrame();
   const tex = new Texture2D();
   tex.image = imageAsset;
   spriteFrame.texture = tex;
   sprite.spriteFrame = spriteFrame;
 });

通过 Canvas 绘制的 ImageAsset 创建,代码示例如下:

代码语言:javascript复制
 const sprite = this.getComponent(Sprite);
 sprite.spriteFrame = SpriteFrame.createWithImage(canvas);

或者用户也可以手动填充信息,代码示例如下:

代码语言:javascript复制
 const sprite = this.getComponent(Sprite);
 const img = new ImageAsset(canvas);
 const tex = new Texture2D();
 tex.image = img;
 const sp = new SpriteFrame();
 sp.texture = tex;
 sprite.spriteFrame = sp;

使用 RenderTexture 渲染

RenderTexture 是一个渲染纹理,它可以将摄像机上的内容直接渲染到一张纹理上而不是屏幕上。SpriteFrame 通过管理 RenderTexture 可以轻松地将 3D 相机内容显示在 UI 上。具体的使用方法及代码示例如下:

代码语言:javascript复制
const cameraComp = this.getComponent(Camera);
const renderTexture = new RenderTexture();
const size = view.getVisibleSize();
renderTexture.reset({
   width: size.width,
   height: size.height,
   colorFormat: RenderTexture.PixelFormat.RGBA8888,
   depthStencilFormat: RenderTexture.DepthStencilFormat.DEPTH_24_STENCIL_8
});

cameraComp.targetTexture = renderTexture;
const spriteFrame = new SpriteFrame();
spriteFrame.texture = renderTexture;
const sprite = this.getComponent(Sprite);
sprite.spriteFrame = spriteFrame;

API 接口文档:SpriteFrame 资源类型。

图像资源的自动剪裁

导入图像资源后生成的 SpriteFrame 默认会进行自动剪裁,去除原始图片周围的透明像素区域。这样我们在使用 SpriteFrame 渲染 Sprite 时,将会获得有效图像更精确的大小。当 SpriteFrame 为自动剪裁时,下图中自动剪裁的相关信息为置灰状态,不可修改:

Sprite 组件剪裁相关设置详解

和图片裁剪相关的 Sprite 组件设置有以下两个:

  • Trim 勾选后将在渲染 Sprite 图像时去除图像周围的透明像素,我们将看到刚好能把图像包裹住的约束框。取消勾选,Sprite 节点的约束框会包括透明像素的部分。
  • Size Mode 用来将节点的尺寸设置为原图或原图裁剪透明像素后的大小,通常用于在序列帧动画中保证图像显示为正确的尺寸。有以下几种选择:
    • TRIMMED 选择该选项,会将节点的尺寸(size)设置为原始图片裁剪掉透明像素后的大小。
    • RAW 选择该选项,会将节点尺寸设置为原始图片包括透明像素的大小。
    • CUSTOM 自定义尺寸,用户在使用 矩形变换工具 拖拽改变节点的尺寸,或通过修改 Size 属性,或在脚本中修改 widthheight 后,都会自动将 Size Mode 设为 CUSTOM。表示用户将自己决定节点的尺寸,而不需要考虑原始图片的大小。

下图中展示了两种常见组合的渲染效果:

自带位置信息的序列帧动画

有很多动画师在绘制序列帧动画时,会使用一张较大的画布,然后将角色在动画中的运动直接通过角色在画布上的位置变化表现出来。在使用这种素材时,我们需要将 Sprite 组件 的 Trim 设为 false,将 Size Mode 设为 RAW。这样动画在播放每个序列帧时,都将使用原始图片的尺寸,并保留图像周围透明像素的信息,这样才能正确显示绘制在动画中的角色位移。

Trim 设为 true,则是在位移完全由角色位置属性控制的动画中,更推荐使用的方式。

TexturePacker 设置

在制作序列帧动画时,我们通常会使用 TexturePacker 这样的工具将序列帧打包成图集,并在导入后通过图集资源下的 SpriteFrame 来使用。在 TexturePacker 中输出图集资源时,Sprites 分类下的 Trim mode 请选择 Trim,一定不要选择 Crop, flush position,否则透明像素剪裁信息会丢失,您在使用图集里的资源时也就无法获得原始图片未剪裁的尺寸和偏移信息了。目前建议使用 TexturePacker 4.x 以上版本进行打包,以防止低版本导出数据不一致造成的导入失败。

本期就到这里,下期再见。

同学们,兴趣是最好的老师;只争朝夕,不负韶华!加油!


参考资料:

Go语言中文文档

http://www.golang.ltd/

0 人点赞