项目二:贪吃蛇游戏开发

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个等级的速度可供选择。
在这里插入图片描述
如果不需要音乐,可以点击右下角音乐控件自行关闭。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值