天津理工大学2010届本科毕业设计说明书
4.3.3碰撞算法
图4.3碰撞示意图
碰撞的检测方法是,比较两个sprite的碰撞矩形。比如矩形一得左边在矩形二的左边,而矩形二的左边又在矩形一得左边,此时即可以得出,在水平方向上两个矩形是交叉的。同理在考虑垂直方向。如果矩形一得上边在矩形二的上边又在矩形一得上边的上面,那么则可以得出两个矩形现在是相互重叠的。 m_rcCollision.left =rcTest.right&& rcTest.left<= rcCollision.right&& m_rcCollision.top <= rcTest.bottom && rcTest.top <= m_rcCollision.bottom;
由于坦克的形状是不规则的。所以在计算碰撞矩形的时候,不使用他的位置矩形,而是在图片举行的基础上计算碰撞矩形。计算方法为:矩形的每一条边都向中心移动十二分之一。也就是款缩短了十二分之一,而高也缩短了十二分之一。
当游戏开始后,运行game cycle ,会执行GameEngine::UpdateSprites()此函数会创建一个迭代器来循环每一个子画面,已更新每一个子画面。更新子画面之后会检查他是否与其他的子画面碰撞GameEngine::CheckSpriteCollision,在此函数中会判断是否发生碰撞,如果没有发生碰撞,则返回FALSE,继续game cycle ,如果返回TRUE,也就是发生碰撞,则执行SpriteCollision。
SpriteCollision是执行碰撞后的一系列行为。pSpriteHitter->Kill()会使子画面销毁标记赋值为TRUE,然后会进入game cycle,再一次执行GameEngine::UpdateSprites,此时判断saSpriteAction 是否与 SA_KILL相等如果相等SpriteDying(*siSprite),此函数会创建一个爆炸的子画面。然后回到GameEngine::UpdateSprites执行delete siSprite删除列表中的指针。至此一个碰撞爆破完毕
一下为创建爆炸子画面的代码,比较简单所以单独列出,没有加入流程图。
- 17 -
天津理工大学2010届本科毕业设计说明书
开始 Game cycle() GameEngine::UpdateSprites() saSpriteAction SpriteDying(*siSprite) 创建爆炸画面 GameEngine::UpdateSprites(){delete(siSprite)} GameEngine::CheckSpriteCollision Sprite::TestCollisiSpriteCollision() 结束 图4.4 碰撞系统
- 18 -
天津理工大学2010届本科毕业设计说明书
4.3.4 双缓冲技术
在图形显示程序中,经常会遇到这样的问题:在客户区内动态绘图,或者客户区被其它窗口遮挡而产生无效区域时,会产生闪烁现象。
其原因为:View类是由Wnd类继承而来,也就是说,View类是窗口类,客户区就是一个窗口。在Windows程序中,窗口的的更新是通过处理WM_PAINT消息实现的,在更新之前,程序会先处理WM_ERASEBKGND消息,该消息默认处理函数会使用预定义的画刷刷新窗口,作为背景色,然后WM_PAINT消息处理函数重绘窗口。而MFC程序预定义的用来刷新窗口的画刷是白色(24位色RGB(255,255,255)),所以当动态绘图或重绘窗口时,客户区内是白色和图像交替出现,短时间内出现颜色的反差,由于人眼的视觉暂留作用,速度很快的情况不会看出反差,但是会有闪烁的感觉,这是用户所不能接受的,所以,在这里我们来解决这个问题。
建立另一个缓冲区,并在其中作图。在绘图函数中,定义两个局部变量,其类型为CDC(设备上下文类)和Bitmap(位图类),在程序中,存储器中的图像,一般是存储于位图中,而图像与设备的通信,是在设备上下文对象中完成的,所以,把Bitmap对象调入CDC对象中,就可以在设备上下文中作图了,其实质是在主存储器中作图,还没有写入到显存中。
把主存中的图像拷贝到显存,以显示图像。这步很简单,只要把自定义的设备上下文对像,送给系统预定义的设备上下文对像中即可。
总结其原理,出现闪烁的原因关键问题就是颜色的反差,消除了反差,闪烁自然就消除。但是双缓冲是有缺点的:
1. 由于两次绘图,运行速度比较慢,在某些追速度的应用中,效果不是很理想。 2. 使用了两倍的缓冲区空间,空间占用比较大,在某些大规模计算的应用中,不是理想首选。
- 19 -
天津理工大学2010届本科毕业设计说明书
第五章 系统实现
5.1 系统实现概述
在开发中,通常把编码和测试统称为实现。
所谓编码就是把软件设计结果翻译成为某种程序设计语言书写的程序。作为软件工程过程的一个阶段,编码是对设计的进一步具体化,因此,程序的质量主要取决于软件设计的质量。但是,所选用的程序设计语言的特点及编码风格也将对程序的可靠性、可读性、可测试性和可维护性产生深远的影响。
程序设计语言是人和计算机通信的最基本的工具,它的特点必然会影响人的思维和解题方式,会影响人和计算机通信的方式和质量,也会影响其他人阅读和理解程序的难易程度。因此,编码之前的一项重要工作就是选择一种适当的程序设计语言,这项任务已经在总体设计阶段完成选定。
无论怎样强调软件测试的重要性和它对软件可靠性的影响都不过分。在开发大型软件系统的过程中,面对极其复杂的问题,人的主观认识不可能完全符合客观事实,与工程密切相关的各类人员之间的通信和配合也不可能完美无缺,因此,在软件生命周期的每个阶段都不可避免地会产生差错。在每个阶段结束之前通过严格的技术审查,尽可能早的发现并纠正错误,此外在编码过程还可能引入新的错误。如果在软件投入运行之前,没有发现并纠正软件中的绝大部分差错,则这些差错迟早会在生产过程中暴露出来,那时不仅改正这些错误的代价更高,而且必然会造成更加严重的后果。测试的目的就是在软件投入生产性运行之前,尽可能多地发现软件中的错误。大量资料统计表明,软件测试的工作量往往占软件开发总工作量的40%以上。因此测试在软件开发中的地位极其重要。
5.2 系统具体实现方法
5.2.1游戏任务函数实现
1.game start。
此函数首先初始化随机数种子,随机数虽然简单但是在游戏中却起着举足轻重的作用,
srand(GetTickCount());然后创建显示设备相关环境也就是双缓冲环境。接下来载入全部位图,并调用newgame。
2.玩家坦克的移动方式为环绕型
首先当玩家输入游戏指令后会调用OffsetPosition用于移动坦克poisionRect,随后重新计算坦克碰撞矩形的位置。其中会用到一个WIN API 函数OffsetRect(RECT,X,Y),此函数
- 20 -
天津理工大学2010届本科毕业设计说明书
开始 g_bGameOver = FALSE 初始化游戏全局数据判断演示模式 演示模式添加3个电脑人,演示战斗情况 创建玩家坦克 播放背景音乐 结束 图5.1 newgame 流程图
的功能为移动矩形。X 为水平移动距离,Y为垂直移动距离。
3.实现坦克重生的3秒无敌
定义一个全局游戏变量 g_iStrong,每个游戏循环它增长一,当它大于30后就不再是无敌。为了使他不能无限的增长避免越界,添加一个判断在game cycle 中。让后就是它被初始化为零的条件:创建玩家坦克的时候.当该变量小于30的时候不去计算玩家坦克与其他子画面的碰撞。
4.NewGame
此函数负责每局游戏开始初始化一些游戏变量,如:gameover,玩家所得分数,开火间隔,剩余生命数量,游戏难度等等,然后根据玩家操作是否创建玩家坦克并播放背景音乐。
- 21 -