Appearance
Sprite(精灵)
是什么
Sprite(精灵)是 GBA 上的硬件加速可移动图形对象。GBA 最多支持 128 个同时显示的精灵,每个精灵由一个或多个 8×8 图块(Tile)组合而成。精灵可以独立于背景进行移动、旋转、缩放,并支持翻转、半透明等效果。精灵的属性(位置、大小、图块索引等)存储在 OAM 中。
为什么需要
精灵是 GBA 游戏中最核心的视觉元素之一。在 Pokémon Emerald 中,玩家角色、NPC、野生 Pokémon、对话框箭头、菜单光标等都是通过精灵实现的。理解精灵的工作原理对于在浏览器中正确渲染游戏画面至关重要:
- 角色和物体的渲染:所有在地图上移动的角色和物体都使用精灵。
- 动画实现:精灵通过切换图块索引来实现帧动画。
- 优先级控制:精灵可以设置显示优先级,实现前后遮挡效果。
原理与实现
精灵的组成
一个精灵由以下要素定义:
- 图块数据:存储在 VRAM 的 OBJ 区域(通常 Bank 4-5),包含精灵的像素数据。
- OAM 条目:存储精灵的属性(位置、大小、图块索引等),详见 OAM。
- 调色板:精灵使用 OBJ 调色板(256 色),存储在
0x05000200。
精灵尺寸
GBA 精灵支持以下尺寸(由 OAM 中的 Shape 和 Size 字段组合决定):
| 形状 | 尺寸 0 | 尺寸 1 | 尺寸 2 | 尺寸 3 |
|---|---|---|---|---|
| 正方形 | 8×8 | 16×16 | 32×32 | 64×64 |
| 横向 | 16×8 | 32×8 | 32×16 | 64×32 |
| 纵向 | 8×16 | 8×32 | 16×32 | 32×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 中,精灵的渲染流程为:
- OAM 遍历:JavaScript 渲染代码遍历 Wasm 内存中的 128 个 OAM 条目。
- 属性解析:从每个启用的 OAM 条目中提取位置、大小、图块索引、翻转标志等属性。
- 图块数据读取:根据图块索引从 VRAM 的 OBJ 区域读取图块像素数据。
- 调色板应用:将图块中的颜色索引通过 OBJ 调色板转换为实际颜色。
- 变换处理:如果精灵启用了旋转/缩放,从 Wasm 内存中读取仿射矩阵并应用变换。
- Canvas 绘制:将处理后的精灵像素写入 Canvas 的 ImageData,按优先级顺序绘制以确保正确的遮挡关系。