原文链接:https://gbdev.gg8.se/wiki/articles/GBDK_Sprite_Tutorial
介绍
本教程旨在介绍一种工作流程,能够显示多个精灵和设置动画。为了使它尽可能地易于访问,我假设您不了解 C 语言。如果您不想在开始之前的几个小时内浏览参考文件,这就是为您准备的。
工具
您将需要:GBDK,文本编辑器,Game Boy Tile Designer 和仿真器(建议使用 BGB,它有许多调试功能)以及任何水平的 C 知识。
如果需要,请替换您喜欢的工具,但是本教程假定您具有上面列出的工具。
第一步:创建瓦块
运行 GBTD。单击视图,图块大小,16x16。
绘制图像,将其复制并粘贴到第二个瓦块插槽中,然后进行更改以制作两帧动画。 我们将在这些之间来回切换。
单击文件,导出到,将 Type 更改为 GBDK C 文件(* .c),并将 To 更改为1。我还将文件名和标签更改为“ smile”。 点击确定。
这将创建一个 .c 和 .h 文件。.c 文件应如下所示:
1 | //lots of comments |
可见,GBTE 只是将像素转换为以标签命名的数组。我们将在要编写的代码中包含 .c 文件。
第二步:set_sprite_data
在屏幕上绘制精灵
GBDK 通过 gb.h 中提供的一些函数来处理精灵。
启动您的文本编辑器,并包含必要的文件:
1 |
每个 C 脚本都需要一个主函数,因此请在其中添加以下函数之一:
1 | void main(){ |
这是我们将编写所有代码的地方。
进入 main 函数,输入:
1 | SPRITES_8x16; |
逐行显示:
- 告诉 GBDK 一次加载两个 8x8 精灵,制作一个 8x16 瓦片
- 从零开始,将 8 个 8x8 瓦片从 smile 数组推入运行中的精灵数据
- 将图块 0 设置为精灵数据中编号为 0 的精灵
- 将精灵 0 移动到该坐标
这是到目前为止的完整代码:
1 |
|
将该文件保存为 filename.c,使用 lcc 编译:/path/to/GBDK/bin/lcc -o gamename.gb filename.c
。
运行 BGB 并加载 gamename.gb。
Emmmmmm,这里只有半张脸。好吧,由于 Gameboy 只能处理最大 8x16 的瓦块,我们需要通过把两个 8x16 的瓦块画在一起来构造一个 16x16 的。
首先,让我们看看精灵和图块如何存储在 Gameboy 上。
在 BGB 中,您已编写的 rom 已加载并运行,右键单击,将鼠标悬停在 “其他” 上,单击 “VRAM查看器”。
在这里,您可以看到我们使用 set_sprite_data 设置为 8x8 瓦片的精灵。最左侧的两个数字 0 和 1 亮起,表示它们正在使用中。我们想要的是设置第二个图块,将其用脸的右半部分填充,然后将其与左半部分对齐。
将此添加到代码中:
1 | set_sprite_tile(1, 2); |
在 VRAM 查看器中进行计数时,该面的左上象限是精灵 0,左下角是 1,右上角从 2 开始,并且 SPRITES_8x16 行将使我们设置的图块包含精灵 3,即 所有四个象限。现在,我们在屏幕上激活了两个精灵,分别是 0 号和 1 号 ,而精灵 1 比精灵 0 靠右 8 个像素,这意味着它可以完美排列以显示一个 16x16 的面。
请记住,每次移动此精灵时,都需要将两个部分一起移动。
编译并运行它,然后在 VRAM 查看器中查看。
第三步:动画
我们将定时使用 set_sprite_tile 替换图块。
在 SHOW_SPRITES 之后在主函数中编写一个 while 循环。我们使用 while(1),这样它会永远循环。
1 | while(1){ |
在该循环内,将图块编号 1(脸的右侧)更改为精灵 6(我使用 VRAM 查看器进行计数)。
1 | set_sprite_tile(1, 6); |
将其交换回去并延迟几个时间,以便可以看到更改,我们会得到以下代码:
1 | while(1){ |
这是所有可以用于复制和粘贴的代码:
1 |
|
编译并运行它。成功运行!
在 VRAM 查看器中实时观看图块切换。
一个有趣的注释:由于仅精灵的右侧发生了变化,因此左侧的重复是多余的。将来的迭代可能会删除它以保存数据。此外,只有右上角的四分之一会发生变化,因此,如果我们绘制四个8x8瓦片而不是两个8x16瓦片,我们可以通过仅包含并交换该象限来节省更多空间。
现在,让这个更加复杂一点:加载多个精灵集。
第四步:多个精灵集合
本节在这里展示了跟踪“哪些精灵存储在何处”的重要性。
我为动画制作了第二张脸,并将其导出到 frown.c(带有皱眉标签),并使用上述方法将其包含在代码中。
这是数组:
1 | unsigned char frown[] = |
让我们在主函数中(在循环上方)将其设置为我们的Sprite数据:
1 | set_sprite_data(8, 8, frown); |
这就是本演示的重点:当图块以数字方式进展时(图块 0,图块 1,图块 2 …),set_sprite_data 只是将 8x8 子图插入到数据集中。第一个参数必须指向内存中的第一个自由精灵,并且要记住,我们已经用微笑艺术的 8 个精灵填充了 0-7 。如果我们将第一个参数设置为小于 8 的任何值,它将覆盖部分微笑,对于更大的覆盖范围,并且两张脸之间会有间隙。第二个参数再次是我们在此处插入的 8x8 磁贴的数量,并且我们的心理计数最高跳到 16,这意味着 0-15 被占用。
这样做的复杂之处在于,即使我们有并行的动画周期,我们也必须记住每个图块在内存中的位置。 好处是任何图块都可以从子画面堆栈中的任何位置拉出。
让我们复制微笑代码以便与新的皱眉脸一起使用,同时交换精灵:
1 |
|
我们用第二张脸的左半部分和右半部分填充编号为 2 和 3 的精灵。
当笑脸在精灵数据 2(和 3)和 6(和 7)之间切换时,皱眉在左侧的 8(和 9)和 12(和 13)之间以及在 10(和 11)和 14(和 15)之间循环。 )在右侧,两边同时出现。
编译并在 VRAM 查看器中查看!
结论
希望这可以教您如何使用 GBDK 加载和显示精灵,或者至少以人类可读形式呈现了一个真实示例。