1、c+实训报告实 训 报 告飞机大战游戏设计与开发 孙业栋 专业名称:软件工程 班 级:2010级04班 学 号:201001050819信息科学与工程学院二零一一年十一月目 录1. 概述 32. 相关技术 3 2.1 透明贴图.32.2 MFC基础类库 33. 总体设计与详细设计 33.1 系统模块划分 43.2 主要功能模块 43.3主要类图 54. 编码实现 55. 实训中遇到的主要问题及解决方法 216. 实训体会 .211. 概述这是一款休闲小游戏。本游戏是我方战机打敌机的游戏,主要为得分。战机初始生命数是100,可发射导弹;敌机随机无限产生,可发射敌机子弹。当敌方战机发射子弹击中战机
2、时,生命数就减1;当敌机与战机碰撞时,会爆炸,战机生命数减1,敌被击中便死。每隔一段时间,敌方的boss机会出现并发射子弹,击落它会会得到很多分。2. 相关技术 2.1 透明贴图绘制透明位图的关键就是创建一个“掩码”位图(mask bitmap),这个“掩码”位图是一个单色位图,它是位图中图像的一个单色剪影。 在MFC中,绘图需要使用设备描述表,透明贴图时需要创建两个内存设备描述表,一个是用于存放位图的设备描述表(imgDC),一个是用于存放“掩码”位图的设备描述表(maskDC)。在“掩码”位图设备描述表中制作“掩码”位图的方法是先创建一个单色的bitmap,放入掩码设备描述表(maskDC
3、)中,然后使用拷贝粘贴的方式将存放有位图的设备描述表(imgDC)绘制到掩码设备描述表上,这样,掩码设备描述表显示的位图即是“掩码”位图。 在详细介绍实现过程之前先介绍下所使用的画图函数以及函数参数所代表的功能; 整个绘制过程需要使用到BitBlt()函数,关于这个函数,MSDN上的说明是这样的:这个函数的功能是把源设备上下文中的一个矩形区域中所有像素的颜色比特信息输 。2.2 MFC基础类库用到的主要MFC函数及消息 OnDraw 绘制函数OnTimer 定时刷新函数OnInitialUpdate 初始化OnDestroy 销毁OnEraseBkgnd 禁用屏幕刷新,使用双缓冲SetTime
4、r 设置定时器 KillTimer 销毁定时器3. 总体设计与详细设计3.1 系统模块划分 有两个主要的部分组成,分别是规则子系统、游戏对象子系统。系统的总体结构图如下:3.2 主要功能模块 3.2.1 规则子系统该子系统主要是实现飞机大战各项游戏规则。实现了需求中的游戏规则。组成结构如下图所示:这个系统包含1个重要的模块,人工智能,它实现了敌机对战机的攻击以及游戏对象碰撞监测规则,其实实现的是代表计算机方玉玩家进行对战。 攻击规则 敌机在战机上方或下方时发射炸弹,炸弹从下至上或从上至下射向战机 碰撞规则 导弹或炸弹本身的矩形区域和敌机或战机的矩形区域相交时,表示导弹或炸弹射中了战机或敌机 战
5、机生命值为零,游戏结束。 敌机被击中,战机得分;敌机与战机相撞,两者爆炸,战机不得分。 每得一百分,或者BOSS机死亡,或者游戏结束,会有文字提示。3.2.2 游戏对象子系统 该子系统包含了各个游戏对象的实现,它实现了需求中的部分规则以及游戏特效。本子系统的组织结构图如下: 应用程序对象 游戏程序的加载 游戏对象的绘制 游戏规则的调用 玩家的键盘事件获取(用GetKeyState函数) 游戏对象 敌机图像加载 敌机贴图 位置存储3.3 主要类图游戏规则子系统模块名称功能简述人工智能人机对战规则的实现游戏子系统模块名称功能简述应用程序对象游戏程序的加载、游戏对象的绘制、游戏规则的调用、玩家的键盘
6、事件获取战机对象 战机类(Cpalne)敌机对象 敌机类 (enemy)派生出两个敌机类(enup 、endown)导弹对象 导弹类(bomb)炸弹对象炸弹类 (Zidan)爆炸对象爆炸类 (explosion) 4. 编码实现/ planeView.cpp : CplaneView 类的实现/#include stdafx.h#include plane.h#include planeDoc.h#include planeView.h#include Cplane.h#include ZiDan.h#include explosion.h#include enemy.h#include Se
7、tUp.h#include enemydown.h#include enemyup.h#include bomb.h#include boss.h#pragma comment(lib,winmm.lib)#include mmsystem.h#ifdef _DEBUG#define new DEBUG_NEW#endif / CplaneViewint j,z;int ENUM=0;int p=400;int count=0,count1=0;int Ran=rand()%2;IMPLEMENT_DYNCREATE(CplaneView, CView)BEGIN_MESSAGE_MAP(Cp
8、laneView, CView) / 标准打印命令 ON_COMMAND(ID_FILE_PRINT, &CView:OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView:OnFilePrint) ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView:OnFilePrintPreview) ON_WM_LBUTTONDOWN() ON_WM_KEYDOWN() ON_WM_TIMER() ON_WM_DESTROY() ON_COMMAND(ID_32771, &CplaneView:Onchangspeed) O
9、N_WM_CREATE()END_MESSAGE_MAP()/ CplaneView 构造/析构CplaneView:CplaneView(): ZNUM(0), BNUM(0), Pause(true) /m_pMemDC=new CDC(); /m_pMemBitmap=new CBitmap(); / TODO: 在此处添加构造代码int NUM=100;CplaneView:CplaneView() /delete m_pMemBitmap; /delete m_pMemDC;BOOL CplaneView:PreCreateWindow(CREATESTRUCT& cs) / TOD
10、O: 在此处通过修改 / CREATESTRUCT cs 来修改窗口类或样式 return CView:PreCreateWindow(cs);/ CplaneView 绘制void CplaneView:OnDraw(CDC* pDC) CplaneDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; /pDoc-e1.Drawexplosion(pDC); / TODO: 在此处为本机数据添加绘制代码/ CplaneView 打印BOOL CplaneView:OnPreparePrinting(CPrintIn
11、fo* pInfo) / 默认准备 return DoPreparePrinting(pInfo);void CplaneView:OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) / TODO: 添加额外的打印前进行的初始化过程void CplaneView:OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) / TODO: 添加打印后进行的清理过程/ CplaneView 诊断#ifdef _DEBUGvoid CplaneView:AssertValid() const CView:
12、AssertValid();void CplaneView:Dump(CDumpContext& dc) const CView:Dump(dc);CplaneDoc* CplaneView:GetDocument() const / 非调试版本是内联的 ASSERT(m_pDocument-IsKindOf(RUNTIME_CLASS(CplaneDoc); return (CplaneDoc*)m_pDocument;#endif /_DEBUG/ CplaneView 消息处理程序void CplaneView:OnLButtonDown(UINT nFlags, CPoint poin
13、t) / TODO: 在此添加消息处理程序代码和/或调用默认值 CplaneDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; pDoc-p1.x=point.x; pDoc-p1.y=point.y; /this-Invalidate(); CView:OnLButtonDown(nFlags, point);void CplaneView:OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) / TODO: 在此添加消息处理程序代码和/或调用默认值 CplaneDoc
14、* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; switch(nChar) case VK_CONTROL:/暂停 Pause=!Pause; if(Pause)/假 SetTimer(1,20,NULL); SetTimer(2,800,NULL); SetTimer(3,500,NULL); else/真 KillTimer(1); KillTimer(2); KillTimer(3); break; /this-Invalidate(); CView:OnKeyDown(nChar, nRepCnt, nFla
15、gs);void CplaneView:OnInitialUpdate() CplaneDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; pdc = new CClientDC(this); SetTimer(1,15,0); /方向键、子弹、碰撞 SetTimer(2,800,0); SetTimer(3,500,0); /敌机生成 SetTimer(4,40000,0); pDoc-e1.loadimage(); PlaySound (TEXT (kanong.wav), NULL, SND_FILENAME
16、 | SND_ASYNC); CView:OnInitialUpdate(); / TODO: 在此添加专用代码和/或调用基类*/void CplaneView:OnTimer(UINT_PTR nIDEvent) / TODO: 在此添加消息处理程序代码和/或调用默认值 CplaneDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); if (!pDoc) return; wchar_t Shu100; CDC MemDC; CRect rect; CFont font; GetClientRect(&rect); /定义一个位图对象 CBitmap
17、MemBitmap; /建立与屏幕设备描述表(前端缓冲区)兼容的内存设备描述表句柄(后备缓冲区) MemDC.CreateCompatibleDC(pdc); /这时还不能绘图,因为没有位图的设备描述表是不能绘图的 /下面建立一个与屏幕设备描述表(或者内存设备描述表)兼容的位图 /MemBitmap.CreateCompatibleBitmap(pdc,rect.Width(),rect.Height(); /将位图选入到内存设备描述表 /只有选入了位图的设备描述表才有地方绘图,画到指定的位图上 MemBitmap.LoadBitmapW(IDB_BITMAP6); CBitmap *pOld
18、Bit=MemDC.SelectObject(&MemBitmap); /MemDC.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(0,0,255); /绘图 if(pp1.score); MemDC.TextOutW(10,10,Shu,6); wsprintf(Shu ,L生命值:%.3d,pDoc-p1.death); MemDC.TextOutW(10,40,Shu,7); wsprintf(Shu ,LBOSS生命值:%.4d,pDoc-boss1.life); MemDC.TextOutW(10,70,Shu,12); if(pD
19、oc-p1.score%100=0&pDoc-p1.score0) MemDC.TextOutW(300,300,L身手不错啊!,7); if(pDoc-p1.score=0) MemDC.TextOutW(300,300,LAre You Ready? GO!,18); if(pDoc-p1.death=0) pDoc-p1.DrawSelf(&MemDC); /画战机 else pDoc-p1.x=200; pDoc-p1.y=1500; for(z=0;zzdownz.DrawZiDan(&MemDC); pDoc-zupz.DrawZiDan(&MemDC); for(z=0;zz1z
20、.DrawZiDan(&MemDC); pDoc-z2z.DrawZiDan(&MemDC); pDoc-z3z.DrawZiDan(&MemDC); for(z=0;zbm1z.drawbomb(&MemDC); pDoc-bm2z.drawbomb(&MemDC); /画敌机 for(j=0;jenupj.y-=pDoc-mspeed; pDoc-endownj.y+=pDoc-mspeed; pDoc-endownj.Drawenemy(&MemDC); pDoc-enupj.Drawenemy1(&MemDC); /画BOSS pDoc-boss1.drawboss(&MemDC);
21、if( count1 %80 = 0 & count11) pDoc-boss1.life=100; count=1; /定时器 switch (nIDEvent) case 1: if(GetKeyState(VK_UP)p1.yrect.top)pDoc-p1.y-=15; if(GetKeyState(VK_DOWN)p1.yp1.y+=15; if(GetKeyState(VK_LEFT)p1.xrect.left)pDoc-p1.x-=15; if(GetKeyState(VK_RIGHT)p1.xp1.x+=15; /战机导弹 if(GetKeyState(70)bm1BNUM.x
22、=pDoc-p1.x+10;pDoc-bm1BNUM.y=pDoc-p1.y; pDoc-bm2BNUM.x=pDoc-p1.x+30;pDoc-bm2BNUM.y=pDoc-p1.y; BNUM+; if(BNUM=99) BNUM=0; /战机导弹发射 for(z=0;zbm1z.y rect.top-20 & pDoc-bm2z.yrect.top-20) pDoc-bm1z.y-=35; pDoc-bm2z.y-=35; else pDoc-bm1z.x=3000; pDoc-bm2z.x=3000; for(j=0;jENUM;j+) for(int t=0;tendownj.x-1
23、0 bm1t.x) & (pDoc-endownj.y+35 pDoc-bm1t.y)&(pDoc-endownj.x+35 pDoc-bm1t.x)&(pDoc-endownj.y-20 bm1t.y) &(pDoc-endownj.x-10 bm2t.x) &(pDoc-endownj.y+35 pDoc-bm2t.y)&(pDoc-endownj.x+35 pDoc-bm2t.x)&(pDoc-endownj.y-20 bm2t.y) pDoc-e1.x=pDoc-endownj.x; pDoc-e1.y=pDoc-endownj.y; pDoc-e1.Drawexplosion(&Me
24、mDC); pDoc-endownj.x=rand()%2500; pDoc-endownj.y=rect.top-40; pDoc-bm1t.x=3000; pDoc-bm1t.y=400; pDoc-bm2t.x=3000; pDoc-bm2t.y=400; pDoc-p1.score+=1; if(pDoc-enupj.x-10 bm1t.x) & (pDoc-enupj.y+35 pDoc-bm1t.y)&(pDoc-enupj.x+35 pDoc-bm1t.x)&(pDoc-enupj.y-20 bm1t.y) &(pDoc-enupj.x-10 bm2t.x) &(pDoc-enu
25、pj.y+35 pDoc-bm2t.y)&(pDoc-enupj.x+35 pDoc-bm2t.x)&(pDoc-enupj.y-20 bm2t.y) pDoc-e1.x=pDoc-enupj.x; pDoc-e1.y=pDoc-enupj.y; pDoc-e1.Drawexplosion(&MemDC); pDoc-enupj.x=rand()%2500; pDoc-enupj.y=rect.bottom+40; pDoc-bm1t.x=3000; pDoc-bm1t.y=400; pDoc-bm2t.x=3000; pDoc-bm2t.y=400; pDoc-p1.score+=1; /战机导弹击中敌机子弹 if(pDoc-zdownj.x-10 bm1t.x) & (pDoc-zdownj.y+8 pDoc-bm1t.y)&(pDoc-zdownj.x+8 pDoc-bm1t.x)&(pDoc-zdownj.y-20 bm1t.y) |(pDoc-zdownj.x-10 bm2t.x) &(pDoc-zdownj.y+8 pDoc-bm2t.y)&(pDoc-zdow
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2