跳转到内容

GBA 开发/HAM IDE

来自 Wikibooks,开放的书籍,开放的世界
Game Boy Advance 开发
示例绘图应用程序的开发

使用 HAM IDE 和编译器进行 GBA 开发

[编辑 | 编辑源代码]

步骤 1 - 设置

[编辑 | 编辑源代码]

这个项目的第一步是从这些链接下载并安装必要的程序。

打开第一个可执行文件并运行它,当它完成文件解压缩后,会提示你输入 'OK'(所以就输入),还要指定一个安装路径。将安装路径设置为 C:\GBADev 。完成这些步骤后,点击 '安装',它应该能顺利完成。

接下来运行第二个可执行文件,点击 '下一步',然后选择 '我接受协议',再次点击下一步,选择 vham 将要安装到的文件夹(它应该已经被选中,但如果没选,就将其放到 C:\GBADev\vham 下),然后点击 '下一步' -> '下一步' -> '下一步' -> '安装' -> '完成'。如果一切顺利,你应该已经设置好了 Gameboy Advance 开发环境,并且可以开始制作游戏了!

步骤 2 - 开始一个新项目

[编辑 | 编辑源代码]

如果你还没有打开 VHam 环境,请双击桌面的 'VisualHAM' 图标。打开后,我们将创建一个新项目,所以请点击 '文件' >> '新建' >> '新建项目'。我们要创建的项目类型是 '[C++ 空白]' 类型项目,所以选择它,然后输入项目名称和位置。项目名称是什么并不重要,只要你记住它就行,位置可以是硬盘上的任何文件夹。(如果你想不出合适的项目名称或位置,就输入 "etchasketch" 作为项目名称,输入 "c:\projects\etchasketch" 作为位置)。

步骤 3 - 熟悉 main.cpp 文件

[编辑 | 编辑源代码]

项目创建完成后,在左侧窗口中会有两个可以编辑的文件,main.cpp 和 makefile。不要对 makefile 进行任何更改(在这个项目中不需要它),它只在更高级的项目中需要。我们唯一要更改的文件是 main.cpp 文件。基本上,这个文件是游戏运行时执行的代码。请双击左侧窗格中的 'main.cpp'。

这个文件大多是空的,除了几行代码。目前,你的游戏所做的就是显示 HAM 徽标,然后显示一个空白的黑色屏幕。让我解释一下文件中的一些项目及其作用。

#include <mygba.h>

这行代码将大量其他函数和声明包含到程序中,供我们使用。除非你想在机器级别上做所有事情(很不方便),否则这是必需的。

MULTIBOOT

允许你的游戏从连接线启动,而无需游戏卡。在这个项目中不需要,可以删除它。

int main(void)
{}

第一个花括号和最后一个花括号之间的所有内容都是程序的主体。游戏从第一个花括号开始,在最后一个结束花括号处结束。

ham_Init();

程序主体中的第一条语句。初始化所有 HAM 功能。还会导致在游戏开始时显示那个小型的 '用 HAM 创建" 徽标。

while(true)
{}

一个不断运行且永不结束的循环。这基本上会使游戏停滞,导致它永远不会结束(大多数情况下,控制台游戏会由用户关闭电源而结束)。如果游戏运行到最后,它会从头开始重新启动。这个语句只是为了防止游戏结束。

return 0;

这个语句只是告诉你的 main() 函数退出,返回值为 '0'。通常这表示程序已成功结束。当执行这行代码时,游戏将结束,然后重新启动(如果电源仍然打开)。

步骤 4 - 构建并运行你的游戏

[编辑 | 编辑源代码]

这一步应该很容易。在你对 main.cpp 文件进行任何更改后,如果你想查看它们对游戏的影响,只需点击 '文件' >> '全部保存' 保存代码,然后按键盘上的 'F6' 键编译并运行你的游戏。你也可以通过点击红色 ! 符号使用其他选项进行构建。如果一切正常,你应该有一个运行的游戏!恭喜你...... 它现在还不太完善,但很快就会好起来的。

步骤 5 - 向 main.cpp 添加第一个附加函数

[编辑 | 编辑源代码]

现在,我们将开始真正地向这个游戏添加一些有用的代码。我们希望我们的游戏在屏幕上显示一些东西,对吧?让我们添加一个函数,它将一个特定颜色的像素绘制到屏幕上。如果你对像素或函数有疑问,我会在课堂上解释。

在代码行 ham_Init(); 后面,你需要添加以下代码行

ham_SetBgMode(3);

这将使 Game Boy 硬件进入特定的视频模式(模式 3),这将使我们能够以顺序内存数组的形式直接访问视频内存(我会在课堂上解释这个术语)。这样可以方便地在屏幕上放置一个像素。

现在,我们需要向程序添加一个函数。所有函数都将在 main() 函数上方,但位于 #include <mygba.h> 部分下方。任何调用其他函数的函数只能调用声明在其上方的函数。main() 将调用我们所有其他的函数,因此它需要位于最底部。请将以下函数添加到你的 main.cpp 文件中

//Function that draws a single pixel to the screen
void drawPix(int xPos, int yPos, int color)
{
unsigned short* videoBuffer = (unsigned short*)0x6000000;
videoBuffer[(yPos*240) + xPos] = color;
}

现在你有了这个函数,你可以在 main() 函数中的任何位置调用 drawPix()。你需要告诉函数在屏幕右侧多远(xPos)、在屏幕下方多远(yPos)以及像素要是什么颜色(color)。我会在课堂上详细解释。但例如,如果你想在屏幕右侧 50 像素、下方 100 像素的地方绘制一个白色像素,你可以在 main() 函数中调用以下代码行

drawPix(50,100,0xFFFFFF);

你可以测试它,保存你的项目,然后运行你的程序(有关详细信息,请参阅步骤 4)。

步骤 6 - 使用变量保存信息

[编辑 | 编辑源代码]

在我们的 Etch-A-Sketch 程序中,我们需要保存一些关于 Etch-A-Stetch 笔的位置和当前绘制颜色的信息。这将需要 5 个变量。其中 2 个用于保存笔的位置(水平和垂直方向的距离),另外 4 个用于颜色(笔中红色、绿色和蓝色的值,以及总的笔颜色)。

在刚刚声明的函数上方,我们将创建 6 个全局变量。将以下行放在 #include <mygba.h> 部分的下方(但在其他函数之上)。

// Global variables
int curX, curY, curColor;
u8 cR, cG, cB;

我们还需要在 main() 函数中初始化这些变量,以便将它们的值设置为零,而不是一些随机的垃圾值。在语句 ham_SetBgMode(3); 的下方添加以下行

curX = 0;
curY = 0;
cR = 0xFF;
cG = 0xFF;
cB = 0xFF;
curColor = 0xFFFF;

现在,您可以通过检查变量的值或更改变量的值来跟踪绘制笔的状态。我们将在后面从按键获取输入时进行操作。事实上,这直接引出了下一部分。

第 6 步 - 从键盘获取输入

[编辑 | 编辑源代码]

如果不能控制游戏,那它有什么用呢?输入其实很简单。只需要检查某些值是真还是假。基本上,“A”按钮在特定时间要么被按下,要么没有被按下。棘手的是决定每个按键被按下意味着什么。让我们在 drawPix() 函数下方再创建一个函数,从按键获取输入,并根据输入更改变量的值。

//Gets input from the joypad
void query_input()
{

}

请注意花括号之间有一些空白。我们将在其中添加更多代码,这些代码实际上会检查按键。这是通过使用 If() 语句完成的。如果语句为真,则其下方的代码行将被执行,否则将被跳过。假设我们想要在按下向下键时将笔向下移动。我们将使用以下两行代码

if (F_CTRLINPUT_DOWN_PRESSED)
curY++;

如果在执行这段代码时向下键被按下,则变量 curY 将增加 1。variable++ 等同于 varible = variable + 1。将以下代码放入 query_input() 函数中

if (F_CTRLINPUT_UP_PRESSED)
curY--;
if (F_CTRLINPUT_DOWN_PRESSED)
curY++;
if (F_CTRLINPUT_LEFT_PRESSED)
curX--;
if (F_CTRLINPUT_RIGHT_PRESSED)
curX++;
if (F_CTRLINPUT_B_PRESSED)
curColor = RGB(--cR, cG, cB);
if (F_CTRLINPUT_A_PRESSED)
curColor = RGB(cR, --cG, cB);
if (F_CTRLINPUT_L_PRESSED)
curColor = RGB(cR, cG, --cB);
if (F_CTRLINPUT_R_PRESSED)
{
cR = 0xFF;
cG = 0xFF;
cB = 0xFF;
curColor = RGB(cR, cG, cB);
}

这段代码片段有点长而且不好看,我会在课堂上解释更多细节,但它基本上做的事情是检查按键上的向上、向下、向左、向右、B、A、L 和 R 键。当这些键被按下时,它会将变量设置为某些值。

第 7 步 - 制作游戏循环

[编辑 | 编辑源代码]

我们有一个函数用于从用户获取输入,还有一个函数用于在屏幕上放置内容,现在我们只需要将它们组合起来,制作我们的主要游戏循环。我们将在每次屏幕刷新时调用另一个函数,基本上每秒大约 60 次。每次屏幕刷新时,我们将检查输入按键,然后在屏幕上绘制。在 drawPix() 和 query_input() 函数之后,但在 main() 函数之前,您需要创建另一个函数,该函数调用这两个函数。

// Function called every screen refresh
void vbl_func()
{
query_input();
drawPix(curX,curY, curColor);
}

很简单,不是吗?确实是。大部分工作已经在我们创建的其他两个函数中完成了,所以这里没有太多工作要做。我们唯一需要做的就是每 1/60 秒调用一次这个函数。这可以通过在 main() 中的变量初始化之后添加以下代码语句来完成

//Starts running the vbl_func every screen refresh
ham_StartIntHandler(INT_TYPE_VBL,(void*)&vbl_func);

现在它每 1/60 秒检查一次按键,并将您的笔绘制到屏幕上,您的 Etch-A-Sketch 就完成了!保存文件,构建并运行它!您仍然可以添加其他增强功能(例如,防止笔从屏幕边缘掉落,或添加屏幕上的说明来解释如何使用游戏)。您有一个在 Gameboy Advance 系统上运行的交互式,我还要补充说,它非常有趣。

一旦您正确地运行了基本程序,请保存并备份它,然后尝试自己对程序进行其他更改,看看您是否可以使程序更加独特和个性化。也许您可以将笔做得更大或形状不同,而不是只是一个点,或者当您按下开始按钮时让笔旋转,或者其他一百种不同的操作。

结尾说明 & 资源

[编辑 | 编辑源代码]
华夏公益教科书