1. 纹理与纹理动画
让我们重新再来审视这个模型:
{
"parent": "item/generated",
"textures": {
"layer0": "example_mod:item/example_item_texture"
}
}
它用到了位于 assets/example_mod/textures/item/
目录下的 example_item_texture.png
这张纹理。
这张纹理是可以有动画效果的,如此一来这个“模型”就会动起来(虽然,实际上在动的是纹理)。
1.1. 逐帧动画与 .mcmeta 文件
要使用原版的纹理动画机制,首先这张纹理必须包括整个动画效果中所有的帧,且每一帧都必须按先后顺序从上到下排列好。
换言之,这张纹理此时类似于胶卷,而使用这张纹理的那个面便是“荧屏”。因此:
- 带动画效果的纹理的高度(height)一定是宽度(width)的整数倍。
- 带动画效果的纹理的高度可以等分成 N 个正方形,正方形的边长即为最终纹理的宽,正方形边长乘以 N 即为最终纹理的高。
- N 即是总帧数。
原版中使用这个机制的纹理的典型代表是静止的水方块的纹理,位于 assets/minecraft/textures/block/water_flow.png
,它是一张由 32 个正方形纹理摞在一起组成的 32 * 1024 像素的巨大纹理。
如果你在 forgeSrc JAR 中找到了这张纹理,你会注意到这个纹理文件下面有一个叫 water_flow.png.mcmeta
的文件。这个文件便是 Minecraft 判断该纹理是否存在动画的依据:如果 Minecraft 在纹理的相同目录下找到了以纹理文件全名并在结尾加上 .mcmeta
命名的文件,它会默认该纹理带动画效果,并尝试解析这个 .mcmeta
文件中对动画的定义。water_flow.png.mcmeta
长这样:
{
"animation": {
"frametime": 2
}
}
是的,动画的定义是通过 JSON 来描述的。animation
这个键下包含了所有对这个动画效果的描述。静止水方块的动画效果并不复杂,"framtetime": 2
定义了它是每隔 2 游戏刻(通常为 0.1 秒)切换下一帧的逐帧动画。
若没有指明 frametime
的值,则默认为 1,即每隔 1 游戏刻(通常为 0.05 秒)切换下一帧。
1.1.1. 对帧的精确控制
默认的动画播放顺序是从上到下,然后回到开头循环往复的,但你仍然可以手动指定具体的播放顺序:
{
"animation": {
"frametime": 2,
"frames": [
3, 1, 4, 1, 5, 9, 2, 6,
5, 3, 5, 8, 9, 7, 9, 3, 2,
3, 8, 4, 6, 2, 6, 4, 3, 3,
8, 3, 2, 7, 9, 5, 0, 2, 8
]
}
}
纹理最顶部的那一块正方形是第 0 帧。在上面这个 mcmeta
文件中,我们定义了动画的播放顺序是从第 3 帧开始,然后是第 1 帧、第 4 帧、第 1 帧、第 5 帧、……
1.1.2. 覆盖默认帧持续时间
还可以手动指定某一帧的停留时间,此时这一帧的停留时间会无视 frametime
的设定,而是使用你设定的值。
{
"animation": {
"frametime": 2,
"frames": [
3,
1,
{ "index": 4, "time": 666 },
1,
5,
9
]
}
}
注意第三个要播放的帧是原本的第 4 帧,但持续时间被定义为了 666 游戏刻。
1.1.3. 插值
Minecraft 可以帮你对动画进行(线性?)插值,使得每一帧之间的切换更为平滑。只需声明 "interpolate": true
即可:
{
"animation": {
"interpolate": true,
"frametime": 2
}
}
1.1.4. 非传统的尺寸纹理
虽然不是很常见,但如果你的纹理形成的动画并不是正方形的,你可以手动指定纹理的总宽度和总高度。
{
"animation": {
"width": 233,
"height": 466
}
}
值得注意的是,Minecraft 本身只是读取并保存了这两个值,但并没有在任何地方用到这两个值。所以即便是像上面这样写了也没什么用,除非你自己手动去调用:
AnimationMetadataSection.getFrameWidth()
(func_110474_b
)AnimationMetadataSection.getFrameHeight()
(func_110471_a
)