DIY自己的“贪吃蛇”(4)——用BREW设计游戏高分排行榜

技术与开发

通过前面几期的介绍,“贪吃蛇”游戏已经基本实现啦!不过,是不是还觉得少了什么?猜对了,少了游戏的存储。这期我们设计一个高分排行榜,用来存储游戏得分。

“贪吃蛇”游戏高分排行榜设计思路

将5个最高分存储到文件里(初始化分数全为0),如果游戏结束后得分高于5个最高分中的任何一个,则更新分数并重新存储到文件里。保存的文件名为“save.dat”。显示时按分数高低从上到下排列,整个流程如图1所示。

34-f13-1.jpg
图1

“贪吃蛇”游戏高分排行榜接口的选择

BREW API 里面基本的文件操作接口有两种:

IFileMgr接口:提供基本的文件服务,可以用来创建、删除和重命名文件以及目录,还可以得到已存在的文件或者目录的相关信息。

IFile接口:本身不提供创建、删除文件的功能,一般和IFileMgr接口一起使用,对文件进行读取或者写入操作。

小提示:要使用上面两个接口创建文件和存储内容,我们的应用程序必须要有文件操作权限。用MIF文件编辑器打开“snake.mif”文件,选择Privileges选项,然后勾选左上角的File选项框,再保存MIF文件即可。

“贪吃蛇” 游戏高分排行榜代码是如何编写的

第一步:定义常量与变量

首先引入接口需要使用的头文件:

#include "AEEFile.h" //文件系统

然后定义程序需要使用的常量和变量:

#define SAVE_FILE "save.dat" /* 存储文件名字 */

在结构体snake里加入全局变量:

unsigned int HighScore[5]; /* 最高分记录 */

第二步:设计排行榜功能

修改snake_HandleEvent函数的事件处理代码,实现“最高分数”菜单功能:

case EVT_COMMAND: //处理菜单命令

switch (wParam){

case ITEM_MENU_HIGH_SCORE: //最高分数

DBGPRINTF("---------ITEM_MENU_HIGH_SCORE----------");

pMe->Mode = MODE_HIGH_SCORE; //将程序状态设为显示最高分数

release_Menuctl(pMe);

loadScore(pMe); /* 读取排行榜 */

break;

case EVT_KEY://处理按键

switch(wParam) {

case AVK_SELECT: //确定键

if ((pMe->Mode == MODE_HIGH_SCORE) || (pMe->life == 1 && pMe->Mode == MODE_GAME)){ /*排行榜和游戏失败界面按确定键可以回到菜单画面*/

init_Menuctl(pMe);

pMe->Mode = MODE_MENU;

}

break;

在main_Display函数中保存分数:

case MODE_GAME:

……

for (i = 3; i < pMe->length; i ++){ /*从蛇的第四节开始判断是否撞到自己了*/

if ((pMe->x[i] == pMe->x[0]) && (pMe->y[i] == pMe->y[0])){ /*游戏失败 */

saveScore(pMe); /*保存分数 */

}

}

第三步:保存游戏得分

现在为上面用到的函数编写代码,具体代码如下:

/* loadScore 函数功能:从文件中读取排行榜中的高分记录,如果记录文件不存在,则排行榜分数全初始化为0 */

void loadScore(snake* pMe){

IFileMgr *pIFileMgr = NULL;

IFile *pIFile = NULL;

int i;

for (i = 0; i < 5; i++){ /* 初始化分数全为0 */

pMe->HighScore[i] = 0;

}

/* 创建文件接口实例 */

if (SUCCESS == ISHELL_CreateIn stance(pMe->a.m_pIShell, AEECLSID_ FILEMGR, (void**)&pIFileMgr)){

if (pIFileMgr){

pIFile = IFILEMGR_OpenFile(pIFile Mgr, SAVE_FILE, _OFM_READ); /* 打开记录文件 */

if (pIFile){ /* 排行榜记录文件存在 */

if (IFILE_Read(pIFile, (void*)pMe->HighScore, sizeof(pMe->HighScore)) == sizeof(pMe->HighScore)){/* 从文件中读取排行榜分数 */

}else{

DBGPRINTF("---Load file error!---"); /* 打印信息提示文件读取出错 */

}

IFILE_Release(pIFile);

}

IFILEMGR_Release(pIFileMgr); /* 释放相关文件接口 */

}

}

}

/* saveScore 函数功能:游戏结束后得分如果破记录,则更新排行榜并存储到文件中 */

void saveScore(snake* pMe){

IFileMgr *pIFileMgr = NULL;

IFile *pIFile = NULL;

int ret, i, j;

/* 创建文件接口实例 */

if (SUCCESS == ISHELL_CreateIn stance(pMe->a.m_pIShell, AEECLSID_ FILEMGR, (void**)&pIFileMgr)){

if (pIFileMgr){ /* 创建接口成功 */

ret = IFILEMGR_GetFreeSpace(pI FileMgr, NULL); /*得到剩余的文件空间*/

if(ret < sizeof(pMe->HighScore)){ /* 空间不够则不再进行存储 */

IFILEMGR_Release(pIFileMgr);

return;

}

if (SUCCESS == IFILEMGR_Test(pIFileMgr, SAVE_FILE)){/* 如果已经存在最高分记录文件 */

pIFile = IFILEMGR_OpenFile(pIFile Mgr, SAVE_FILE, _OFM_READWRITE); /* 读写方式打开文件 */

}else{

pIFile = IFILEMGR_OpenFile(pIFile Mgr, SAVE_FILE, _OFM_CREATE); /* 新建文件来存储最高分 */

}

if (pIFile){ /* 文件打开或者新建成功 */

for (i = 0; i < 5; i++){

if (pMe->scores > pMe->HighScore[i]){ /* 如果得分上榜 */

for (j = 4; j > i; j--){/* 重新排列排行榜 */

pMe->HighScore[j] = pMe->High Score[j-1];

}

pMe->HighScore[i] = pMe->scores; /* 新记录上榜 */

break;

}

}

if (IFILE_Write(pIFile, (PACKED const void*)pMe->HighScore,

sizeof(pMe->HighScore)) == sizeof(pMe->HighScore)){ /* 保存排行榜分数到文件 */

}else{

DBGPRINTF("---Save file error!---"); /* 打印信息提示文件存储出错 */

}

IFILE_Release(pIFile);

}

IFILEMGR_Release(pIFileMgr); /* 释放相关文件接口 */

}

}

}

/* show_HighScore 函数功能:排行榜画面显示历史前五名最高得分 */

void show_HighScore(snake* pMe){

AECHAR wstr[100];

char str[100];

int i;

IDISPLAY_SetColor(pMe->a.m_pIDisplay, CLR_USER_TEXT, BLUE); /* 设置标题蓝色 */

IDISPLAY_DrawText(pMe->a.m_pIDisplay, AEE_FONT_BOLD, L"HighScores", -1, 0, 10, NULL, IDF_ ALIGN_CENTER|IDF_TEXT_UNDER LINE|IDF_TEXT_TRANSPARENT); /* 标题加粗、居中并加下划线 */

IDISPLAY_SetColor(pMe->a.m_pIDisplay, CLR_USER_TEXT, WHITE); /* 设置分数白色 */

for(i = 0; i < 5; i ++) {

SPRINTF(str, "%d. %d", i+1, pMe->HighScore[i]); /* 转换分数到字符串 */

STRTOWSTR(str, wstr, sizeof(str)+1); /* 转换成BREW用来显示的宽字节字符串 */

IDISPLAY_DrawText(pMe->a.m_pIDisplay, AEE_FONT_NORMAL, wstr, -1, 20, 40 + i*20, NULL, IDF_TEXT_TRANSPARENT); /* 显示排行榜上各分数*/

}

}

代码添加完成后,编译运行。开始游戏,游戏结束后查看排行榜(图2)。

34-f13-2.jpg
图2

编后

截至本期,BREW系列已经全部结束了。通过前面的介绍,我们已经对用BREW进行开发有了大致的了解。可以看出,在BREW SDK的帮助下,我们完全可以很轻松的在手机上编写程序。只要熟练掌握BREW API,即使是初学者也可以轻松上手。

对于编程来说,如何实现程序的思路,这才是最重要的,在设计“贪吃蛇”的时候,每期我们都列出设计思路。最后,希望大家用BREW设计出更多更好的程序,早日功成名就。

如果你想看该系列的所有文章或者下载相关的代码,请登录《电脑报》的网站,地址是http://bbs.cpcw.com/viewthread.php?tid=1227720