MFC实现贪吃蛇游戏开发
具体要求:
①实现贪吃蛇游戏基本功能,屏幕上随机出现一个"食物”,称为豆子。上下左右控制"蛇"的移动,吃到“豆子"以后"蛇"的身体加长一点。
②“蛇"碰到边界或蛇头与蛇身相撞,蛇死亡,游戏结束。
③为游戏设计友好的交互界面; 例如欢迎界面,游戏界面,游戏结束界面。
要有开始键、暂停键和停止退出的选项。
④对蛇吃到豆子进行分值计算,可以设置游戏速度,游戏音乐等拓展元素。
具体功能如下所示:
在进行设计时需要注意的是,新豆子的生成规则为:
①不能超出游戏区域
②不能在蛇身上
游戏结束时的检测规则为:
①蛇是否超出游戏区域
②蛇头是否撞到自己身上
开发工具:MFC
设计过程
首先,打开vs创建基于MFC应用的一个新项目。
创建好之后,打开.rc文件夹下的dialog文件夹进行简单的游戏界面布局设计。如下图所示:
此处红框处的ID名可以自己编辑。
然后在打开的界面添加相关的控件,例如button按钮,我用来进行开始和停止操作。还有两个static text控件用来标识speed和score,速度选择框使用combo box,设置了1,2,3,4,5总共5个等级的速度,考虑到一般情况下大家能适应的速度较低,所以蛇的默认速度设为第2个等级。然后再选用一个示例编辑框来显示得分。界面中还需要有我们的游戏区,我使用了pictuer control控件来实现。
接下来就是我们的代码实现部分。首先在头文件中定义相关的变量,声明相关函数。有一部分代码是系统自动生成的,不需要进行修改。
我在头文件中声明的相关函数如下:
public:
afx_msg void OnBnClickedButton2stop(); //停止按钮
afx_msg void OnBnClickedButton1start(); //开始按钮
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnCbnSelchangeCombo1speed(); //速度选择下拉框
CComboBox Box;
CEdit EDIT_Score; //分数展示框
CFont m_showFont1; //对界面上相关字体的设置
CFont m_showFont2;
CFont m_showFont3;
CBrush m_brush[4];
CRect m_map[30][38];
Point pos = { 0, 0 };
CSnake my_snake;
CPen pen1;
int speed = 135; // 设置蛇移动的初始速度为135
int score = 0; //默认分数为0
bool INIT = true;
bool START = false;
bool DEAD = false;
void SnackInit();
bool setBean(); //随机放置豆子的函数
void drawSnake(); //检测发生碰撞
void MvUp(); //控制蛇移动的函数,分别实现上下左右移动的功能
void MvDown();
void MvLeft();
void MvRight();
void eatBean(); //实现蛇头和豆子位于同一坐标框中时吃豆子的功能
bool checkLive(); //判断蛇是否处于存活状态
void gameOver(); //根据相关条件判定结束
//以下的函数为当你点击界面上的控件时会自动生成
afx_msg void OnStnClickedStaticspeed();
afx_msg void OnStnClickedStaticscore();
afx_msg void OnEnChangeEdit1score();
afx_msg void OnStnClickedStaticgame();
afx_msg void OnStnClickedStaticmusic();
afx_msg void OnBnClickedmusic();
接下来就是在源文件中逐个实现这些功能。
蛇的移动功能:(选取向上移动举例)
void CMFCsnackDlg::MvUp()
{
CDC* pdc = GetDlgItem(IDC_STATICgame)->GetWindowDC();
// 将最后一个变为背景色
CBrush* pOldBrs = pdc->SelectObject(&m_brush[3]);
pdc->Rectangle(m_map[my_snake.body[my_snake.len - 1].x][my_snake.body[my_snake.len - 1].y]);
pdc->SelectObject(&pen1);
pdc->Rectangle(m_map[my_snake.body[my_snake.len - 1].x][my_snake.body[my_snake.len - 1].y]);
pdc->SelectObject(pOldBrs);
my_snake.UpMove();
drawSnake();
}
在蛇移动的过程中,我们需要将舍身最后一个放个恢复为背景色,移动玩之后还需要进行一次碰撞检测,是否撞到蛇身或墙壁。
接下来实现吃豆子功能:
void CMFCsnackDlg::eatBean()
{
if (pos.x == my_snake.body[0].x && pos.y == my_snake.body[0].y) {
my_snake.len++;
setBean();
score = score + (abs(pos.x - my_snake.body[0].x) + abs(pos.y - my_snake.body[0].y));
CString str;
str.Format(_T("%d"), score);
EDIT_Score.SetWindowTextW(str);
}
}
当蛇头遇到的豆子坐标位置与蛇头相同时,将蛇身长度加1并且随机放置新的豆子,更新分数。
判断是否出界:
bool CMFCsnackDlg::checkLive()
{
// 判断是否出界
if (my_snake.body[0].x < 0 || my_snake.body[0].x >= 30 || my_snake.body[0].y < 0 || my_snake.body[0].y >= 38) return false;
// 判断是否撞到了自己
for (int i = 1; i < my_snake.len; i++) {
if (my_snake.body[0].x == my_snake.body[i].x && my_snake.body[0].y == my_snake.body[i].y) return false;
}
return true;
}
根据返回的bool值来确定蛇是否存活。
附加
除了得分记录,移动速度的选择功能之外,设计了背景音乐功能。
首先将我们需要添加的背景音乐下载下来,一般情况下,在MFC中插入的音乐格式为wav无损音质,如果没有mav格式的音频,可以将下载的MP3格式利用网上在线工具进行相应转换,比较方便。
具体插入代码如下:
PlaySound(_T("C:\\Users\\M\\Downloads\\g7h4d-ezigc.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
我用橙色框标出的地方为音频的所在路径,这种方法不是很好,因为当你的程序在其他电脑运行时,背景音乐可能无法播放。
另外一种方法时添加资源,在你所在项目下右击选择添加资源,再选择Accelerator进行导入你想要的音频就可以了,利用PlaySound函数同样可以实现播放。
说在最后
蛇头和蛇身以及豆子的图案设计
我利用MFC中的工具自行绘制自己想要的图案,当然也可以导入现有的bitmap格式的图片,具体绘制步骤如下:
点击添加资源,选择导入就是导入你文件夹目录下的bitmap格式图片,选择新建就可以自己进行绘制。
在绘制窗口找到属性,我们可以设置我们需要的一些基本样式,例如宽高等。绘制界面有相应的画笔,铅笔,喷枪等,可根据自己的需要自行选择。绘制好的资源会显示在资源视图的bitmap目录下。
点击就可以看到自己绘制的bitmap图
蛇头
蛇身
豆子
上面是我绘制的比较简陋的图案,大家也可以根据自己的需要绘制自己想要的图案,操作起来还是比较容易的。
实现效果
有5个等级的速度可供选择。
如果不需要音乐,可以点击右下角音乐控件自行关闭。