GBA 开发/HAM IDE
这个项目的第一步是从这些链接下载并安装必要的程序。
打开第一个可执行文件并运行它,当它完成文件解压缩后,会提示你输入 'OK'(所以就输入),还要指定一个安装路径。将安装路径设置为 C:\GBADev 。完成这些步骤后,点击 '安装',它应该能顺利完成。
接下来运行第二个可执行文件,点击 '下一步',然后选择 '我接受协议',再次点击下一步,选择 vham 将要安装到的文件夹(它应该已经被选中,但如果没选,就将其放到 C:\GBADev\vham 下),然后点击 '下一步' -> '下一步' -> '下一步' -> '安装' -> '完成'。如果一切顺利,你应该已经设置好了 Gameboy Advance 开发环境,并且可以开始制作游戏了!
如果你还没有打开 VHam 环境,请双击桌面的 'VisualHAM' 图标。打开后,我们将创建一个新项目,所以请点击 '文件' >> '新建' >> '新建项目'。我们要创建的项目类型是 '[C++ 空白]' 类型项目,所以选择它,然后输入项目名称和位置。项目名称是什么并不重要,只要你记住它就行,位置可以是硬盘上的任何文件夹。(如果你想不出合适的项目名称或位置,就输入 "etchasketch" 作为项目名称,输入 "c:\projects\etchasketch" 作为位置)。
项目创建完成后,在左侧窗口中会有两个可以编辑的文件,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'。通常这表示程序已成功结束。当执行这行代码时,游戏将结束,然后重新启动(如果电源仍然打开)。
这一步应该很容易。在你对 main.cpp 文件进行任何更改后,如果你想查看它们对游戏的影响,只需点击 '文件' >> '全部保存' 保存代码,然后按键盘上的 'F6' 键编译并运行你的游戏。你也可以通过点击红色 ! 符号使用其他选项进行构建。如果一切正常,你应该有一个运行的游戏!恭喜你...... 它现在还不太完善,但很快就会好起来的。
现在,我们将开始真正地向这个游戏添加一些有用的代码。我们希望我们的游戏在屏幕上显示一些东西,对吧?让我们添加一个函数,它将一个特定颜色的像素绘制到屏幕上。如果你对像素或函数有疑问,我会在课堂上解释。
在代码行 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)。
在我们的 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;
现在,您可以通过检查变量的值或更改变量的值来跟踪绘制笔的状态。我们将在后面从按键获取输入时进行操作。事实上,这直接引出了下一部分。
如果不能控制游戏,那它有什么用呢?输入其实很简单。只需要检查某些值是真还是假。基本上,“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 键。当这些键被按下时,它会将变量设置为某些值。
我们有一个函数用于从用户获取输入,还有一个函数用于在屏幕上放置内容,现在我们只需要将它们组合起来,制作我们的主要游戏循环。我们将在每次屏幕刷新时调用另一个函数,基本上每秒大约 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 系统上运行的交互式,我还要补充说,它非常有趣。
一旦您正确地运行了基本程序,请保存并备份它,然后尝试自己对程序进行其他更改,看看您是否可以使程序更加独特和个性化。也许您可以将笔做得更大或形状不同,而不是只是一个点,或者当您按下开始按钮时让笔旋转,或者其他一百种不同的操作。