前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MFC贪吃蛇

MFC贪吃蛇

作者头像
立羽
发布2023-08-24 13:01:28
1480
发布2023-08-24 13:01:28
举报
文章被收录于专栏:Unity3d程序开发Unity3d程序开发

1多人贪吃蛇项目描述

1.1功能描述

实现多人对战贪吃蛇,具体实现功能:A.可以选择游戏人数,最多设置4人同时游戏;B.显示玩家得到的分数;C.可以设置游戏的速度;D.能实现最高分的记录

1.2所需技术

1.在对话框中创建窗口;2.双缓冲绘图;3.蛇身移动处理;4.碰撞检测;5.Ini文件操作

2多人贪吃蛇运行流程

3多人贪吃蛇详细设计

3.1贪吃蛇个体类设计

把贪吃蛇单独的设为一个类,其中包含成员变量如下

代码语言:javascript
复制
	BOOL m_bAliveFlg; //蛇当前存活标志
	int	m_iDirect;	//当前蛇先进方向
	int m_iScore;	//分数
	CArray<CPoint,CPoint> m_bufBody;	//蛇身向量

3.2最高分对话框类设计

游戏要记录玩家所玩的最高得分和玩家的姓名。使用ini文件进行记录。最高分对话框分为两种情况,一种是显示当前的最高分,另一种是写入当前的最高分,所以用标志位m_bWriteFlg来区分。

对配置文件的操作用GetPrivateProfileString函数和WritePrivateProfileString函数完成。 具体用法如下所示。

代码语言:javascript
复制
GetPrivateProfileString("HERO","NAME","0",bufTmp,MAX_PATH,".\\HERO.ini");WritePrivateProfileString("HERO","SCORE",strScore,".\\HERO.ini");

3.3贪吃蛇游戏类的设计

3.3.1对话框中创建一个窗体

贪吃蛇游戏类是继承自CWnd类,所以主对话框中OnInitDialog初始化消息时创建一个贪吃蛇游戏类的窗体,如下所示。

代码语言:javascript
复制
m_CSnake.CreateEx( WS_EX_CLIENTEDGE, _T("SNAKEMAP"), NULL, WS_VISIBLE| WS_BORDER | WS_CHILD,CRect( 0, 0, 405, 405 ), this, 256 );//新建一个窗口出来

CWinApp这个类有三个virtual成员函数InitApplication、InitInstance和Run。其中InitInstance是为程序创建和显示窗口所设置的。因此在设计程序时,必须在CWinApp类的基础上派生自己的应用程序类,并对函数InitInstance进行重写。所以在应用程序类注册窗口类。

3.3.2双缓冲绘图

绘图可能需要几秒钟甚至更长的时间,而且有时还会出现闪烁现象,为了解决这些问题,可采用双缓冲技术来绘图。双缓冲即在内存中创建一个与屏幕绘图区域一致的对象,先将图形绘制到内存中的这个对象上,再一次性将这个对象上的图形拷贝到屏幕上,这样能大大加快绘图的速度。双缓冲实现过程如下:

1、在内存中创建与画布一致的缓冲区

2、在缓冲区画图

3、将缓冲区位图拷贝到当前画布上

4、释放内存缓冲区

代码语言:javascript
复制
CPaintDC dc( this );
    CDC MemDC;//创建与画布一致的缓冲区
MemDC.CreateCompatibleDC( &dc );
CBitmap bmp;
MemDC.SelectObject( &bmp );// 装载背景
MemDC.Rectangle(
					CRect(ysPoint.y*SNAKE_SIZE,
					ysPoint.x*SNAKE_SIZE,
					(ysPoint.y+1)*SNAKE_SIZE,
					(ysPoint.x+1)*SNAKE_SIZE)
					);//在内存中绘图
dc.BitBlt( 0, 0, MAP_RIGHT, MAP_BUTTON, &MemDC,0, 0, SRCCOPY );//将缓冲区位图拷贝到当前画布上

因为游戏类是基于窗口类的,所以所有的绘图消息都可以在OnPaint消息中处理。在OnPaint中,只需要描绘蛇身和食物,后面的逻辑处理与碰撞检测会使用Invalidate()或局部矩形重绘InvalidateRect来产生重绘消息。

3.3.3游戏碰撞检测

只需要判断蛇头的坐标与待判定的坐标是否重合,重合就发生了碰撞,说明该蛇死亡了。

3.3.4蛇身移动处理

方法一:1.得到蛇身数组第一个点的坐标,即蛇头的坐标;2.使蛇头后面的开始的每一个点的坐标等于上一个点的坐标,例如:蛇头下一个点的坐标等于蛇头的坐标。然后重绘。

这里提供另一种方案二:1.首先获得蛇身向量的第一个点的坐标,这里说明下蛇身向量的坐标是与真实绘图相差10倍的。

代码语言:javascript
复制
CPoint ysPoint=m_CSnakeIndv[iCnt].m_bufBody.GetAt(0);     //获取蛇身的第一个点坐标

2.根据蛇的方向,使这个坐标值发生变动。改变的是蛇头的坐标值。

3.判断ysPoint这个坐标是否发生过界或碰撞,如果蛇死亡。

代码语言:javascript
复制
int iSnakeLen = m_CSnakeIndv[iCnt].m_bufBody.GetUpperBound();
				for ( ; iSnakeLen >= 0; iSnakeLen--)
				{
					CPoint pt=m_CSnakeIndv[iCnt].m_bufBody.GetAt(iSnakeLen);//将最后一个赋给pt
					m_CSnakeIndv[iCnt].m_bufBody.RemoveAt(iSnakeLen);       //将移出最后一个
					ReDrawBody(pt);                                //重新绘制pt这点
				}
				m_CSnakeIndv[iCnt].m_bAliveFlg = FALSE;

说明:重绘整个蛇身,这里是取出蛇身的动态数组的最后一个元素,重绘这个点,并把这个点从蛇身数组中移除,以此类推,直到重绘整个蛇身,使死亡了的蛇不在屏幕中显示出来。

如果这个新点没有发生越界或是碰撞,说明游戏可以继续进行下去。

代码语言:javascript
复制
m_CSnakeIndv[iCnt].m_bufBody.InsertAt(0,ysPoint);    //将新点添加到蛇的身体中
				ReDrawBody(ysPoint);           //重绘蛇的身体

说明:把这个新点添加到蛇身向量中,是插入到第0个位置,原来的蛇身数组里元素每位向后移动一位。

如果新点的位置与食物的位置是重合的。主要进行如下处理。

代码语言:javascript
复制
CPoint pt=m_CSnakeIndv[iCnt].m_bufBody.GetAt(m_CSnakeIndv[iCnt].m_bufBody.GetUpperBound());//将最后一个赋给pt
					m_CSnakeIndv[iCnt].m_bufBody.RemoveAt(m_CSnakeIndv[iCnt].m_bufBody.GetUpperBound());       //将移出最后一个
					ReDrawBody(pt);                                //重新绘制pt这点

说明:得到蛇身数组的最后一个点坐标,把这个点从蛇身数组移除出去,重绘该点。这样,就说明绘图中会移除蛇尾,就是视觉上蛇的移动是蛇头前插入一个元素,蛇尾去除一个元素,这样造成蛇移动的效果。

4.多人贪吃蛇运行结果

源码下载

点击打开链接

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-08-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1多人贪吃蛇项目描述
    • 1.1功能描述
      • 1.2所需技术
      • 2多人贪吃蛇运行流程
      • 3多人贪吃蛇详细设计
        • 3.1贪吃蛇个体类设计
          • 3.2最高分对话框类设计
            • 3.3贪吃蛇游戏类的设计
            • 4.多人贪吃蛇运行结果
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档