DIY自己的“贪吃蛇”(2)——用BREW设计游戏画面
技术与开发
上期我们用BREW设计了手机游戏“贪吃蛇”的主菜单,很有成就感吧!好戏还在后头,下面我们就来设计实现“贪吃蛇”游戏的画面,让小蛇动起来。在本期,你还可以DIY自己喜欢的特定画面。
“贪吃蛇”画面设计思路
首先,把整个手机屏幕渲染成黑色作为背景,屏幕四边显示蓝色边框作为边界墙壁。然后,在屏幕中央绘制贪吃蛇,贪吃蛇由三节大小是8 * 8像素的矩形组成。接着,在屏幕上随机显示一份食物,也是一个8 * 8像素的矩形,用户通过按键控制贪吃蛇移动到食物上吃掉它。
随后,贪吃蛇的身体就会长一节,并且再显示一份食物,但是如果蛇头撞到自己的身体则表示失败,游戏结束。整个流程如图1所示:

“贪吃蛇”画面接口有哪些
游戏中,会用到下面四种显示接口:
●IDisplay :用来显示字符串、常用图形、图像等,是最基本也是最常用的接口。
●IGraphics:专门用来提供二维图形显示。包括基本的几何图形的绘制、颜色设置、裁剪区域控制等等。
●IBitmap:专门显示和处理BMP格式的图片。
●IImage :可以用来显示位图和动画,支持的图片格式比较多,有BMP、PNG、JPEG、BCI等等。
例如可以使用IDisplay显示矩形,使用IBitmap和 IImage显示游戏失败画面 以及用IGraphics来显示一个红色的椭圆(图2)。

“贪吃蛇” 画面代码是如何编写的
第一步 定义常量
首先引入所有接口需要使用的头文件。
#include “AEEGraphics.h”
#include “AEEBitmap.h”
#include “AEEImage.h”
然后在结构体snake上方加入代码,定义程序需要使用的常量,比如颜色和方向。
#define SNAKE_MAX_LENGTH 1024 //蛇最大长度(节数)
#define LIVE 1 //蛇活着,移动中
#define DEAD 0 //蛇死亡,游戏失败
#define BLACK MAKE_RGB(0, 0, 0) //黑色
#define WHITE MAKE_RGB(255, 255, 255) //白色
#define RED MAKE_RGB(255, 0, 0) //红色
#define GREEN MAKE_RGB(0, 255, 0) //绿色
#define BLUE MAKE_RGB(0, 0, 255) //蓝色
enum move_direction{ //蛇移动方向
RIGHT = 1, //1 向右
LEFT, //2 向左
UP, //3 向上
DOWN, //4 向下
};
第二步 绘制游戏主画面
在上期的文章中说过,程序是调用main_Display函数根据程序状态来显示画面的,现在我们在这里加入游戏主画面显示代码:
int i;
AEERect rc[SNAKE_MAX_LENGTH+1];/* 设置局部变量保存蛇的身体,最后一位“+1”是用来保存食物的 */
case MODE_GAME://游戏状态
if (pMe->life==1){//失败
draw_Lost(pMe);
return;
}
IDISPLAY_DrawRect(pMe->a.m_pIDisplay, &(pMe->ScreenRect), BLUE, BLACK, IDF_RECT_FILL|IDF_RECT_FRAME);/* 绘制背景和墙壁 */
if (pMe->yes == 1){ /* 须出现新食物 */
new_Food(pMe); /* 生成新的食物 */
pMe->yes = 0; /* 新食物已经出现 */
}
for (i = pMe->length; i > 0; i--){ /* 蛇身体向前移动 */
pMe->x[i] = pMe->x[i-1];
pMe->y[i] = pMe->y[i-1];
}
switch (pMe->direction){ /* 蛇头移动 */
case RIGHT: pMe->x[0] += 8; break;
case LEFT: pMe->x[0] -= 8; break;
case UP: pMe->y[0] -= 8; break;
case DOWN: pMe->y[0] += 8; break;
}
/*设置蛇可穿墙 */
if (pMe->x[0] > pMe->DeviceInfo.cxScreen - 8) pMe->x[0] = 0;
if (pMe->x[0] < 0) pMe->x[0] = pMe->DeviceInfo.cxScreen - 8;
if (pMe->y[0]> pMe->DeviceInfo.cyScreen - 8) pMe->y[0] = 0;
if (pMe->y[0] <0) pMe->y[0] = pMe->DeviceInfo.cyScreen - 8;
if (pMe->yes == 0){ /* 显示已有的食物 */
SETAEERECT(&rc[SNAKE_MAX_LENGTH],pMe->foodx,pMe->foody, 8, 8);
IDISPLAY_DrawRect(pMe->a.m_pIDisplay,&rc[SNAKE_MAX_LENGTH], BLUE, RED, IDF_RECT_FILL|IDF_RECT_FRAME);
}
if ((pMe->x[0] == pMe->foodx) && (pMe->y[0] == pMe->foody)){ /* 吃到食物*/
pMe->length++; /* 蛇身长一节 */
pMe->yes = 1; /* 画面上须出现新的食物 */
pMe->scores += 10;/* 更新得分 */
}
for (i = 0; i< pMe->length; i++)
SETAEERECT(&rc[i],pMe->x[i],pMe->y[i],8,8);
for (i = 0; i < pMe->length; i++)
IDISPLAY_DrawRect(pMe->a.m_pIDisplay,&rc[i], BLUE, GREEN, IDF_RECT_FRAME|IDF_RECT_FILL);//绘制矩形,蛇的身体
for (i = 3; i< pMe->length; i ++){ /* 从蛇的第四节开始判断是否撞到自己了 */
if ((pMe->x[i] == pMe->x[0]) && (pMe->y[i] == pMe->y[0])){
pMe->life = 1; /* 设置蛇的生命,游戏失败 */
}
}
break;
第三步 绘制失败画面
游戏失败后,需要绘制失败画面。为了演示不同显示接口的使用方法,我们调用了两张不同格式的图片来显示,代码如下:
/*显示失败画面 */
void draw_Lost(snake* pMe){
load_Draw_PNG(pMe); //显示55.png
draw_Ellipse(pMe); //画椭圆
load_Draw_BMP(pMe); //椭圆里面显示lost.bmp
}
/* load_Draw_PNG 函数功能:载入并显示PNG图片 */
void load_Draw_PNG(snake* pMe){
IImage* pimg = NULL; //PNG图片指针
AEEImageInfo imginfo; //PNG图片信息
pimg = ISHELL_LoadImage(pMe->a.m_pIShell, “55.png”); /* 载入PNG图片文件 */
if (pimg){ //如果图片载入成功
IIMAGE_GetInfo(pimg, &imginfo); /* 得到图片大小等信息 */
IIMAGE_Draw(pimg, (pMe->DeviceInfo.cxScreen - imginfo.cx)/2, pMe->DeviceInfo.cyScreen - imginfo.cy); /* 图片画在手机屏幕的底部中央 */
IIMAGE_Release(pimg); /* 用完释放图片 */
}
}
/* draw_Ellipse 函数功能:创建IGraphics接口实例并且描绘矩形 */
void draw_Ellipse(snake* pMe){
IGraphics* pgraphic = NULL;
AEEEllipse pellipse;
pellipse.cx = pMe->DeviceInfo.cxScreen/2; /* 椭圆中心点X, Y坐标 */
pellipse.cy = 30;
pellipse.wx = 40; /* 椭圆X,Y方向半轴长度 */
pellipse.wy = 20;
if(SUCCESS == ISHELL_CreateInstance(pMe->a.m_pIShell, AEECLSID_GRAPHICS, (void **)&pgraphic)){
IGRAPHICS_SetFillColor(pgraphic, 255, 0, 0, NULL); /* 设置填充红色 */
IGRAPHICS_SetFillMode(pgraphic, TRUE); /* 设置填充模式 */
IGRAPHICS_DrawEllipse(pgraphic, &pellipse); /* 根据前面的设置描绘椭圆*/
IGRAPHICS_Release(pgraphic); /* 释放接口 */
}
}
/* load_Draw_BMP 函数功能:载入并显示BMP图片 */
void load_Draw_BMP(snake* pMe){
IBitmap* pbmp = NULL; //BMP图片指针
AEEBitmapInfo bmpinfo; //BMP图片信息
pbmp = ISHELL_LoadBitmap(pMe->a.m_pIShell, “lost.bmp”); /* 载入BMP图片文件 */
if (pbmp){ //如果图片载入成功
IBITMAP_GetInfo(pbmp, &bmpinfo, sizeof(AEEBitmapInfo)); /* 得到图片大小等信息 */
IDISPLAY_BitBlt ( pMe->a.m_pIDisplay, (pMe->DeviceInfo.cxScreen - bmpinfo.cx)/2, 20, bmpinfo.cx, bmpinfo.cy, (const void*) pbmp, 0, 0, NULL,);
IBITMAP_Release(pbmp); /* 用完释放图片 */
}
}
小提示:“55.png”和“lost.bmg”这两张图片是用Windows自带的画图板画的,在“C:\Program Files\BREW 3.1.5\sdk\examples\snake”目录下。大家可以自己随便DIY这两张图片,只要图片名称不变即可。
代码全部添加完,编译运行后,就可以看到如图3所示的画面。

网站上有之前文章和相关下载
下期我们将进行“贪吃蛇”游戏的音效设计