Skip to content

Sprite(精灵)

是什么

Sprite(精灵)是 GBA 上的硬件加速可移动图形对象。GBA 最多支持 128 个同时显示的精灵,每个精灵由一个或多个 8×8 图块(Tile)组合而成。精灵可以独立于背景进行移动、旋转、缩放,并支持翻转、半透明等效果。精灵的属性(位置、大小、图块索引等)存储在 OAM 中。

为什么需要

精灵是 GBA 游戏中最核心的视觉元素之一。在 Pokémon Emerald 中,玩家角色、NPC、野生 Pokémon、对话框箭头、菜单光标等都是通过精灵实现的。理解精灵的工作原理对于在浏览器中正确渲染游戏画面至关重要:

  • 角色和物体的渲染:所有在地图上移动的角色和物体都使用精灵。
  • 动画实现:精灵通过切换图块索引来实现帧动画。
  • 优先级控制:精灵可以设置显示优先级,实现前后遮挡效果。

原理与实现

精灵的组成

一个精灵由以下要素定义:

  1. 图块数据:存储在 VRAM 的 OBJ 区域(通常 Bank 4-5),包含精灵的像素数据。
  2. OAM 条目:存储精灵的属性(位置、大小、图块索引等),详见 OAM
  3. 调色板:精灵使用 OBJ 调色板(256 色),存储在 0x05000200

精灵尺寸

GBA 精灵支持以下尺寸(由 OAM 中的 Shape 和 Size 字段组合决定):

形状尺寸 0尺寸 1尺寸 2尺寸 3
正方形8×816×1632×3264×64
横向16×832×832×1664×32
纵向8×168×3216×3232×64

仿射变换(旋转/缩放)

GBA 支持最多 32 组仿射变换参数(Affine Matrix),每个参数集由 4 个固定小数组成(Pa, Pb, Pc, Pd)。启用旋转/缩放的精灵通过 ATTR1 中的参数索引引用一组变换矩阵。

变换矩阵计算公式:

ScreenX = Pa × (SpriteX - CenterX) + Pb × (SpriteY - CenterY) + CenterX
ScreenY = Pc × (SpriteX - CenterX) + Pd × (SpriteY - CenterY) + CenterY

显示优先级

精灵有 4 个优先级(0-3),优先级 0 最先绘制(可能被遮挡),优先级 3 最后绘制(在最上层)。精灵优先级与背景优先级交互,共同决定最终的显示层次。

半透明混合

精灵可以设置为半透明模式(OBJ Mode = 1),此时精灵颜色与下方像素按固定比例(如 50%/50%)进行 Alpha 混合。

在 pokeemerald-wasm 中的实现

在 pokeemerald-wasm 中,精灵的渲染流程为:

  1. OAM 遍历:JavaScript 渲染代码遍历 Wasm 内存中的 128 个 OAM 条目。
  2. 属性解析:从每个启用的 OAM 条目中提取位置、大小、图块索引、翻转标志等属性。
  3. 图块数据读取:根据图块索引从 VRAM 的 OBJ 区域读取图块像素数据。
  4. 调色板应用:将图块中的颜色索引通过 OBJ 调色板转换为实际颜色。
  5. 变换处理:如果精灵启用了旋转/缩放,从 Wasm 内存中读取仿射矩阵并应用变换。
  6. Canvas 绘制:将处理后的精灵像素写入 Canvas 的 ImageData,按优先级顺序绘制以确保正确的遮挡关系。

相关概念

  • OAM — 存储精灵属性信息的 1KB 内存
  • Tile — 构成精灵的 8×8 像素基本图形单元
  • VRAM — 存储精灵图块数据的显存