课程设计说明书NO.1**大学超级玛丽游戏系统1.课程设计的目的随着科学技术的发展,人们的生活水平的提高,然而也越来越繁忙。在充满竞争的社会条件,压力往往带给人们很多烦恼。为了给大家提供一个合理的解压平台,在本次课程设计中为大家开发了一款适合休闲解压的小游戏,超级玛丽。本次设计加深对面向对象程序设计中基础理论和基本知识的理解,培养学生的实践能力,促进理论与实践的结合。通过课程设计,能够熟练运用C++进行面向对象编程,建立对象模型,降低软件的复杂性,改善软件的重用性和维护性,提高软件的生产效率,全面掌握面向对象编程技术。2.设计方案论证2.1设计思路游戏基本功能:1.玩家起初只能用普通子弹或踩踏杀死敌人,但是踩踏无法杀死特殊敌人,无法顶碎砖块。被敌人碰到将失去一条生命。2.在玩家吃旋风炮弹之后,攻击能力变强,可以轻松杀死普通敌人和特殊敌人。3.玩家一共有三条命的机会去闯关超级玛丽游戏,玩家要在一定时间内,通过游戏。如果三条生命都丢掉,将输掉整个游戏。本游戏的用例模型如图1所示。图1用例模型课程设计说明书NO.2**大学2.2开发工具选择代码编写调试使用VisualC++6.0。美术工具,Windows自带的画图(开始-程序-附件-画图),Photoshop,记事本或UltraEdit等文本编辑工具。3.设计结果与分析一个好的游戏一定要有完整的功能,漂亮的界面,为了设计出美观完善的超级马力游戏码分两部分,图像部分,逻辑部分。图像分两种,矩形图片和不规则图片。矩形图片有:地面、砖块、水管、血条、血条背景。不规则图片有:蘑菇(玩家,敌人1,敌人2),子弹、旋风、爆炸效果、金币、撞击金币后的得分、攻击武器(那个从魂斗罗里抠来的东东)、火圈1、火圈2、箭头(用于开始菜单选择)、树木、河流、WIN标志、背景图片(游戏背景和菜单背景)。3.1类结构图像层类如表1所示:表1图像层功能类名称与继承关系图像基类MYBITMAP游戏背景MYBKSKYMYBITMAP游戏图片MYANIOBJMYBITMAP魔法攻击MYANIMAGICMYBITMAP结构和表相关类如表2所示:表2结构和表功能类名称精灵结构ROLE物品结构MapObject地图信息表MAPINFO课程设计说明书NO.3**大学逻辑层类如表3所示:表3逻辑层功能类名称与继承关系游戏逻辑GAMEMAP时钟处理MYCLOCK字体处理MYFONT跟踪打印FILEREPORT玩家控制MYROLEMYBITMAP3.2类的实现3.2.1图片基类MYBITMAP图片基类MYBITMAP把代码写成一个容易扩展、容易维护、功能全面的“框架”,需要什么功能,就从这个框架中取出相应功能,如果是一个新的功能,比如新的图像显示、新的运动控制,也能方便地实现。所以,这个游戏的代码,是在前几个游戏的基础上扩充起来的。部分函数,部分变量在这款游戏中,根本不用,但要保留,要为下一款游戏作准备。只要理解了各个类,就理解了整个框架。简单的介绍几个成员函数。功能:根据一个位图文件,初始化图像入参:应用程序实例句柄资源ID横向位图个数纵向位图个数voidInit(HINSTANCEhInstance,intiResource,introw,intcol);功能:设置环境信息入参:目的DC(要绘制图像的DC),临时DC,要绘制区域的宽高voidSetDevice(HDChdest,HDChsrc,intwwin,inthwin);功能:设置图片位置入参:设置方法横纵坐标voidSetPos(intistyle,intx,inty);课程设计说明书NO.4**大学功能:图片显示入参:图片显示方式voidDraw(DWORDdwRop);功能:图片缩放显示入参:横纵方向缩放比例voidStretch(intx,inty);功能:图片缩放显示入参:横纵方向缩放比例缩放图像ID(纵向第几个)基类的函数实现上,很简单,主要是以下几点:1.图片初始化根据程序实例句柄,由位图文件的资源ID,导入该位图,得到位图句柄。hBm=LoadBitmap(hInstance,MAKEINTRESOURCE(iResource));获取该位图文件的相关信息。GetObject(hBm,sizeof(BITMAP),&bm);根据横纵方向的图片个数,计算出每个图片的宽高(对于超级玛丽,宽高信息由派生类处理)。width=bm.bmWidth/inum;height=bm.bmHeight/jnum;2.图片显示各个图片的显示函数基本大同小异,都要先选入一个临时DC,再bitblt到要绘制的dc上。矩形图片可以直接用SRCCOPY的方式绘制。不规则图片,需要先用黑白图与目的区域相“与”(SRCAND),再用“或”的方法显示图像(SRCPAINT),这是一种简单的“去背”方法。3.图片缩放用StretchBlt的方法实现。voidMYBITMAP::Stretch(intx,inty,intid){课程设计说明书NO.5**大学SelectObject(hdcsrc,hBm);StretchBlt(hdcdest,xpos,ypos,width*x,height*y,hdcsrc,0,id*height,width,height,SRCCOPY);}3.2.2游戏背景类MYBKSKY这是一个专门处理游戏背景的类。在横版游戏或射击游戏中,都有一个背景画面如图2所示,如山、天空、云、星空等等。这些图片一般只有1到2倍屏幕宽度,然后像一个卷轴一样循环移动,连成一片,感觉上像一张很长的图片。这个类就是专门处理这个背景的。在超级玛丽增强版中,主要关卡是3关,各有一张背景图片;从水管进去,有两关,都用一张全黑图片。共四张图。这四张图大小一致,纵向排列在一个位图文件中。MYBKSKY这个类,派生于MYBITMAP。由于背景图片只需要完成循环移动的效果,只需要实现一个功能,而无需关心其他任何问题(例如句柄、dc)。图2背景图技术原理:一张图片像卷轴一样不停移动。假设有一条垂直分割线,把图片分成左右两部分。先显示右边部分,再把左边部分接到图片末尾。不停移动向右移动分割线,图片就会循环地显示。课程设计说明书NO.6**大学成员函数功能列表:classMYBKSKY:publicMYBITMAP{public:MYBKSKY();~MYBKSKY();//show//功能显示一个背景.//入参无voidDrawRoll();//循环补空//功能显示一个背景,并缩放图片//入参横纵方向缩放比例voidDrawRollStretch(intx,inty);//功能指定显示某一个背景,并缩放图片,游戏中用的就是这个函数//入参横纵方向缩放比例背景图片ID(纵向第几个)voidDrawRollStretch(intx,inty,intid);//功能设置图片位置//入参新的横纵坐标voidMoveTo(intx,inty);//功能循环移动分割线//入参分割线移动的距离voidMoveRoll(intx);//data//分割线横坐标intxseparate;};函数具体实现代码如下:课程设计说明书NO.7**大学voidMYBKSKY::DrawRollStretch(intx,inty,intid){//选入句柄SelectObject(hdcsrc,hBm);//将分割线右边部分显示在当前位置StretchBlt(hdcdest,xpos,ypos,//当前位置(width-xseparate)*x,height*y,//缩放比例hdcsrc,xseparate,id*height,//右边部分的坐标width-xseparate,height,//右边部分的宽高SRCCOPY);//将分割线左边部分接在图片末尾StretchBlt(hdcdest,xpos+(width-xseparate)*x,ypos,xseparate*x,height*y,hdcsrc,0,id*height,xseparate,height,SRCCOPY);}3.2.3跟踪打印类FILEREPORT前面介绍了图片显示、时钟控制、字体管理几项基本技术。这是所有游戏都通用的基本技术。剩下的问题就是游戏逻辑,例如益智类、运动类、射击类、格斗类等等。函数具体实现很简单,只是简单的文件写入。要说明的是两部分。第一部分:计数功能,有时要统计某个事情发生多少次,所以用一个整数数组,通过putnum让指定数字累加。第二部分:显示功能,让跟踪信息,立刻显示在屏幕上。具体的代码实现见附件。课程设计说明书NO.8**大学3.3精灵结构structROLE逻辑层:structROLE。这个结构用来存储两种精灵:敌人(各种小怪)和子弹(攻击方式)。敌人包括两种蘑菇兵和两种火圈。子弹包括火球和旋风。精灵的结构实现需要定义精灵的横纵坐标,精灵的运动左右界限,运动速度,生命值等等。游戏中的子弹处理,包括存储、生成、销毁。子弹的存储:所有的子弹存储在一个数组中,如下。structROLEFireArray[MAX_MAP_OBJECT];所有的动态元素都有从生成到销毁的过程。首先,玩家按下z键:发出子弹,调用函数:intGAMEMAP::KeyProc(intiKey)。如果正在发子弹,代码结束。否则,设置iBeginFire为1,表示开始发子弹。连续两个子弹要间隔一定时间。至此,游戏中已经生成了一个子弹.由图像层,通过子弹的id,坐标在屏幕上绘制出来.子弹已经显示在屏幕上,接下来,就是让它移动,碰撞,销毁。如图3所示子弹发射图。图3子弹发射图3.4子弹的显示和帧的刷新上次讲所有的子弹存储到一个数组里。用一个游标(数组下标)表示新生产的子弹存储的位置。设数组为a,长度为n。游戏开始,一个子弹存储在a0,然后是a1,a2,...,a(n-1).课程设计说明书NO.9**大学然后游标又回到0,继续从a0位置存储.数组长度30,保存屏幕上所有的子弹足够了。子弹的显示功能由图像层完成。如同图像处理中讲的。显示一个子弹(所有图片都是如此),只需要子弹坐标,子弹图片id,图片帧。函数:voidGAMEMAP::ShowAniObj(MYANIOBJ&bmobj)用一个函数不停地检测所有子弹,,如果某个子弹碰到了小怪,小怪消失,子弹消失。实现由函数:intGAMEMAP::CheckAni(intitimeclip)至此,玩家按下攻击键然后子弹生成,显示运动,碰到小怪,子弹消失,小怪消失。这些功能全部完成。如果只做成这样,不算本事.攻击方式分两种:子弹和旋风。小怪包括:两种蘑菇兵、两种火圈。同时火圈能产生两种蘑菇兵。而旋风的攻击效果明显高于普通子弹。3.5旋风攻击,小怪运动,火圈作为魔法攻击方式的旋风,和子弹大同小异。旋风的存储与子弹同存储在一个数组中即:structROLEFireArray[MAX_MAP_OBJECT];旋风生成函数:intGAMEMAP::CheckAni(intitimeclip)这和子弹生成的处理相同。唯一区别是旋风不移动,所以movex属性最后设置为0。在幕上的绘制和子弹相同,函数voidGAMEMAP::ShowAniObj(MYANIOBJ&bmobj)。代码部分和子弹相同。但是旋风的帧刷新有些特殊处理,函数是:voidGAMEMAP::ChangeFrame(intitimeclip)至此,旋风将会显示,动画播放结束后消失。旋风不涉及运动。碰撞检测的处理和子弹相同,唯一区别是:当旋风和小怪碰撞,旋风不消失,如图4旋风与小怪的碰撞。课程设计说明书NO.10**大学图4旋风与小怪的碰撞小怪可以分为:蘑菇兵和火圈两种。存储是我问题.和攻击方式处理相同,用数组加游标的方法.蘑菇兵和火圈存储在同一数组中,如下:structROLEMapEnemyArray[MAX_MAP_OBJECT];intiMapEnemyCursor;小怪是由地图文件设定好的。比生成子弹要复杂一些,尤其是火圈。火圈要不停地生成