程序设计综合实践报告姓名梁琨学号201301050817班级信息13-1项目名称飞机大战游戏设计与实现实习地点科技园实习时间2015-10-26至2015-11-6 实习成绩指导教师签字数学与系统科学学院2015年11月6日目录1. 概述 (1)2. 相关技术 (1)2.1 数据链表 (1)2.2 双缓冲 (1)3. 总体设计与详细设计 (2)3.1 系统模块划分 (2)3.2 主要功能模块 (2)4. 编码实现 (12)5. 实训中遇到的主要问题及解决方法 (20)6. 实训体会 (20)1. 概述项目:飞机大战主要功能:本款基于MFC平台所制作的游戏,具有极大的休闲娱乐功能。
玩家通过操纵我机,通过发射子弹机会敌机来积分,分数越高说明了玩家坚持的越长。
游戏开始界面向玩家进行了游戏按键的功能说明,游戏中设置暂停按键,可以方便玩家继续游戏。
游戏还自带无敌模式,以及我机大招,极大地提高了游戏的可玩性。
2. 相关技术本程序主要运用了链表和双缓冲的技术。
链表的应用方便了对数据成员的访问和处理,简化了代码,支持插入和移除表中任意位置上的节点;双缓冲主要用于图像的处理,在内存中重新绘图后复制到前台,同时禁止背景刷新,避免因图像刷新过于频繁导致画面出现闪烁现象。
2.1 数据链表链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
使用链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。
由于常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换,因此链表最大的优点是允许插入和移除表上任意位置上的节点。
在程序运行过程中,根据游戏对象的种类划分不同的链表,每个链表单一的存储一类数据,在进行处理、绘图时,通过对链表的遍历,实现对数据的访问,再根据所要实现的功能,对不同的对象做出不同的处理,对数据成员的插入和移除也变得轻松了许多。
2.2 双缓冲在图形图象处理编程过程中,双缓冲是一种基本的技术。
窗体在响应WM_PAINT消息的时候要进行复杂的图形处理,那么窗体在重绘时由于过频的刷新会引起闪烁现象。
解决这一问题的有效方法就是双缓冲技术。
因为窗体在刷新时,总要有一个擦除原来图象的过程OnEraseBkgnd,它利用背景色填充窗体绘图区,然后在调用新的绘图代码进行重绘,这样一擦一写造成了图象颜色的反差。
当WM_PAINT的响应很频繁的时候,这种反差也就越发明显。
于是我们就看到了闪烁现象。
双缓冲我们会很自然的想到,避免背景色的填充是最直接的办法。
但是那样的话,窗体上会变的一团糟。
因为每次绘制图象的时候都没有将原来的图象清除,造成了图象的残留,于是窗体重绘时,画面往往会变的乱七八糟。
所以单纯的禁止背景重绘是不够的。
我们还要进行重新绘图,但要求速度很快,于是我们想到了使用BitBlt函数。
它可以支持图形块的复制,速度很快。
我们可以先在内存中作图,然后用此函数将做好的图复制到前台,同时禁止背景刷新,这样就消除了闪烁。
以上也就是双缓冲绘图的基本的思路。
3. 总体设计与详细设计3.1 系统模块划分3.2 主要功能模块if(nMeMotion==1)m_pMe->SetVerMotion(1);nMeMotion = GetKey(VK_DOWN);if(nMeMotion==1)m_pMe->SetVerMotion(-1);nMeMotion = GetKey(VK_RIGHT);if(nMeMotion==1)m_pMe->SetHorMotion(1);nMeMotion = GetKey(VK_LEFT);if(nMeMotion==1)m_pMe->SetHorMotion(-1);}//随机产生小敌机static int nCreator = rand() % 5 + 10;if (nCreator <= 0){nCreator = rand() % 5 + 10;m_ObjList[enEnemy].AddTail(new CEnemy);}nCreator--;// 产生大敌机if (m_pMe != NULL&&score >= 1000 && Booswait<=0){CGameObject* pObj;//PlaySound((LPCTSTR)IDR_WAVE5, AfxGetInstanceHandle(),SND_RESOURCE | SND_ASYNC);m_ObjList[enBOSS].AddTail(new BOSS);Booswait = rand() % 300+10 ;}Booswait--;//产生战机导弹PlaneGameif(GetKey(VK_SPACE)==1)//按下了空格键{if(m_pMe!=NULL && m_pMe->Fired()){//PlaySound((LPCTSTR)IDR_WAVE3, AfxGetInstanceHandle(), SND_RESOURCE | SND_ASYNC);CPoint pt = m_pMe->GetPoint();m_ObjList[enBomb].AddTail(new CBomb(pt.x , pt.y -10,3));m_ObjList[enBomb].AddTail(new CBomb(pt.x+15,pt.y-10,3));m_ObjList[enBomb].AddTail(new CBomb(pt.x + 22, pt.y -40,0));m_ObjList[enBomb].AddTail(new CBomb(pt.x + 37, pt.y - 40, 0));m_ObjList[enBomb].AddTail(new CBomb(pt.x+45,pt.y-10,-3));m_ObjList[enBomb].AddTail(new CBomb(pt.x + 60, pt.y -10,-3));}}//无敌模式if (GetKey('A') == 1){wd++;}//小敌机发射子弹CPoint PlanePt = m_pMe->GetPoint();for(POSITION ePos=m_ObjList[enEnemy].GetHeadPosition();ePos!=NULL;) {CEnemy* pEnemy = (CEnemy*)m_ObjList[enEnemy].GetNext(ePos);if(!pEnemy->Fired())continue;CPoint ePt = pEnemy->GetPoint();BOOL by=FALSE;//敌机在战机前面if(pEnemy->GetMontion()==1 && ePt.y<PlanePt.y)by= TRUE;//敌机在战机后面if(pEnemy->GetMontion()==-1 && ePt.y>PlanePt.y)by= TRUE;if(by && ePt.x >= PlanePt.x &&ePt.x<PlanePt.x+CMyPlane::PLANE_WIDTH){m_ObjList[enBall].AddTail(newCBall(ePt.x+10,ePt.y+10,pEnemy->GetMontion()));}}//小敌机子弹炸掉战机POSITION bPos1=NULL,bPos2=NULL;CRect mRect = m_pMe->GetRect();for(bPos1=m_ObjList[enBall].GetHeadPosition();( bPos2 = bPos1 ) != NULL;){CBall* pBall = (CBall*)m_ObjList[enBall].GetNext(bPos1);CRect bRect = pBall->GetRect();CRect tmpRect;if(tmpRect.IntersectRect(&bRect,mRect)){if (wd % 2 == 0){life -= 5;}//删除子弹m_ObjList[enBall].RemoveAt(bPos2);delete pBall;//添加爆炸效果m_ObjList[enExplosion].AddTail(new CExplosion(mRect.left, mRect.top));if (life <= 0){//添加爆炸效果m_ObjList[enExplosion].AddTail(new CExplosion(mRect.left, mRect.top));//删除战机delete m_pMe;m_pMe = NULL;break;}}}//我机与小敌机相遇互相摧毁POSITION coPos1 = NULL, coPos2 = NULL;for (coPos1 = m_ObjList[enEnemy].GetHeadPosition(); (coPos2 = coPos1) != NULL;){CEnemy* pEnemy = (CEnemy*)m_ObjList[enEnemy].GetNext(coPos1);CRect eRect = pEnemy->GetRect();CRect tmpRect;if (tmpRect.IntersectRect(&eRect, mRect)){if (wd % 2 == 0){life -= 10;}energy += 5;//添加爆炸效果m_ObjList[enExplosion].AddTail(new CExplosion(eRect.left, eRect.top));//删除敌机m_ObjList[enEnemy].RemoveAt(coPos2);delete pEnemy;PlaySound((LPCTSTR)IDR_WAVE2, AfxGetInstanceHandle(),SND_RESOURCE | SND_ASYNC );if (life <= 0){//添加爆炸效果m_ObjList[enExplosion].AddTail(new CExplosion(mRect.left, mRect.top));//删除战机delete m_pMe;m_pMe = NULL;break;}}}//我机导弹炸掉敌机POSITION mPos1=NULL,mPos2=NULL;for(mPos1=m_ObjList[enBomb].GetHeadPosition();(mPos2=mPos1)!=NULL;) {CBomb* pBomb = (CBomb*)m_ObjList[enBomb].GetNext(mPos1);CRect bRect = pBomb->GetRect();POSITION ePos1=NULL,ePos2=NULL;for(ePos1=m_ObjList[enEnemy].GetHeadPosition();(ePos2=ePos1)!=NULL; ){CEnemy* pEnemy = (CEnemy*)m_ObjList[enEnemy].GetNext(ePos1);CRect eRect = pEnemy->GetRect();CRect tmpRect;if(tmpRect.IntersectRect(&bRect,eRect)){//添加爆炸效果m_ObjList[enExplosion].AddTail(new CExplosion(eRect.left,eRect.top));pEnemy->Setlife(-pBomb->Gethurt());if (pEnemy->Getlife() <= 0){static int a = 0;a++;if (a % 10 == 0)life += 1;if (life>100)life = 100;//删除敌机m_ObjList[enEnemy].RemoveAt(ePos2);score += 10;energy += 5;delete pEnemy;PlaySound((LPCTSTR)IDR_WAVE2, AfxGetInstanceHandle(), SND_RESOURCE | SND_ASYNC);}//删除导弹m_ObjList[enBomb].RemoveAt(mPos2);delete pBomb;break;}}}//== == == = =====添加爆炸效果,大敌机与战机相撞 == == == == == == == POSITION pPos1 = NULL, pPos2 = NULL;for (pPos1 = m_ObjList[enBOSS].GetHeadPosition(); (pPos2 = pPos1) != NULL;){BOSS* pBboss = (BOSS*)m_ObjList[enBOSS].GetNext(pPos1);CRect bRect = pBboss->GetRect();CRect tmpRect;if (tmpRect.IntersectRect(&bRect, mRect)){//添加爆炸效果m_ObjList[enExplosion].AddTail(new CExplosion(mRect.left, mRect.top));if (wd % 2 == 0){life --;}if (pBboss->get_life() != 0) { pBboss->set_life(-1); }//删除大Bossif (pBboss->get_life() == 0){m_ObjList[enExplosion].AddTail(newCExplosion(mRect.left + 30, mRect.top + 30));m_ObjList[enExplosion].AddTail(newCExplosion(mRect.left + 70, mRect.top + 30));m_ObjList[enExplosion].AddTail(newCExplosion(mRect.left + 50, mRect.top + 50));m_ObjList[enExplosion].AddTail(newCExplosion(mRect.left + 30, mRect.top + 70));m_ObjList[enExplosion].AddTail(newCExplosion(mRect.left + 70, mRect.top + 70));//PlaySound((LPCTSTR)IDR_WAVE2,AfxGetInstanceHandle(), SND_RESOURCE | SND_ASYNC);m_ObjList[enBOSS].RemoveAt(pPos2);score += 100;energy += 10;delete pBboss;pBboss = NULL;break;}if (life <= 0)life = 1;}}//==================添加爆炸效果,我机导弹打中大Boss============ mPos1 = NULL;mPos2 = NULL;for (mPos1 = m_ObjList[enBomb].GetHeadPosition(); (mPos2 = mPos1) != NULL;){CBomb* pBomb = (CBomb*)m_ObjList[enBomb].GetNext(mPos1);CRect bRect = pBomb->GetRect();POSITION ePos1 = NULL, ePos2 = NULL;for (ePos1 = m_ObjList[enBOSS].GetHeadPosition(); (ePos2 = ePos1) != NULL;){BOSS* pEnemy = (BOSS*)m_ObjList[enBOSS].GetNext(ePos1);CRect eRect = pEnemy->GetRect();CRect tmpRect;if (tmpRect.IntersectRect(&bRect, eRect)){//添加爆炸效果m_ObjList[enExplosion].AddTail(newCExplosion(eRect.left, eRect.top));if (pEnemy->get_life() != 0) { pEnemy->set_life(-3); }//删除大Bossif (pEnemy->get_life() <= 0){m_ObjList[enExplosion].AddTail(newCExplosion(eRect.left + 30, eRect.top + 30));m_ObjList[enExplosion].AddTail(newCExplosion(eRect.left + 70, eRect.top + 30));m_ObjList[enExplosion].AddTail(newCExplosion(eRect.left + 50, eRect.top + 50));m_ObjList[enExplosion].AddTail(newCExplosion(eRect.left + 30, eRect.top + 70));m_ObjList[enExplosion].AddTail(newCExplosion(eRect.left + 70, eRect.top + 70));//PlaySound((LPCTSTR)IDR_WAVE2, AfxGetInstanceHandle(), SND_RESOURCE | SND_ASYNC);m_ObjList[enBOSS].RemoveAt(ePos2);score += 100;energy += 10;delete pEnemy;pEnemy = NULL;break;}//删除导弹m_ObjList[enBomb].RemoveAt(mPos2);delete pBomb;break;}}}//==================== 大敌机发射子弹============================ for (POSITION bPos = m_ObjList[enBOSS].GetHeadPosition(); bPos != NULL;){BOSS* pBboss = (BOSS*)m_ObjList[enBOSS].GetNext(bPos);if (!pBboss->Fired())continue;CPoint BPt = pBboss->GetPoint();BOOL by = FALSE;//敌机在战机前面if (BPt.y<PlanePt.y)by = TRUE;if (by && BPt.x >= PlanePt.x && BPt.x<PlanePt.x + CMyPlane::PLANE_WIDTH){m_ObjList[enBball].AddTail(new Bball(BPt.x + 40, BPt.y + 40, 1));}}//========================大敌机子弹炸掉战机===================POSITION BbPos1 = NULL, BbPos2 = NULL;for (BbPos1 = m_ObjList[enBball].GetHeadPosition(); (BbPos2 = BbPos1) != NULL;){Bball* pBball = (Bball*)m_ObjList[enBball].GetNext(BbPos1);CRect bRect = pBball->GetRect();CRect tmpRect;if (tmpRect.IntersectRect(&bRect, mRect)){if (wd % 2 == 0){life -= 30;}//删除子弹m_ObjList[enBball].RemoveAt(BbPos2);delete pBball;//添加爆炸效果m_ObjList[enExplosion].AddTail(new CExplosion(mRect.left, mRect.top));if (life <= 0){//添加爆炸效果m_ObjList[enExplosion].AddTail(new CExplosion(mRect.left, mRect.top));//删除战机delete m_pMe;m_pMe = NULL;break;}}if (energy > 100){energy = 100;}//=============================游戏结束弹窗====================== if (m_pMe == NULL){KillTimer(1);CString str;str.Format(_T("游戏结束,您的得分为%d"), score);AfxMessageBox(str);if (AfxMessageBox(L"游戏结束,是否重新开始", MB_YESNO) == 6){//清空敌机m_ObjList[enEnemy].RemoveAll();//清空战机链表//m_ObjList[enpMe].RemoveAll();//清空战机子弹链表m_ObjList[enBall].RemoveAll();//清空敌机炸弹链表m_ObjList[enBomb].RemoveAll();//清空爆炸链表m_ObjList[enExplosion].RemoveAll();//清空大敌机链表m_ObjList[enBOSS].RemoveAll();//清空大敌机子弹链表m_ObjList[enBball].RemoveAll();//添加新的战机对象m_pMe = new CMyPlane;CPen p1(PS_SOLID, 2, RGB(0, 0, 0));//定义一个画笔类对象p1m_pMemDC->SelectObject(&p1);//选定该对象CBrush b1(RGB(255, 0, 0));//选定一个画刷类对象b1m_pMemDC->SelectObject(&b1);//选定该对象m_pMemDC->Rectangle(300, 20, 300 + life * 40, 10);//画一个矩形life = 100;score = 0;energy = 100;SetTimer(1, 30, NULL);SetTimer(2, 300, NULL);SetTimer(3, 500, NULL);}//if4.编码实现(注:红色加粗部分为新加代码)// PlaneGameView.cpp : CPlaneGameView 类的实现#include"stdafx.h"#include"PlaneGame.h"#include"background.h"#include"BOSS.h"#include"PlaneGameDoc.h"#include"PlaneGameView.h"#include"MyPlane.h"#include"Enemy.h"#include"Bomb.h"#include"Ball.h"#include "Bball.h"#include"Explosion.h"#include <atlimage.h>#include"GameObject.h"// 加声音#include<mmsystem.h>#pragma comment(lib, "WINMM.LIB")#include <MMSYSTEM.H>#ifdef_DEBUG#define new DEBUG_NEW#endif#pragma oncestatic int score=0;static int life=100;static int energy = 100;static int p = 1;static int Booswait;static int wd=0;IMPLEMENT_DYNCREATE(CPlaneGameView, CView)BEGIN_MESSAGE_MAP(CPlaneGameView, 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_TIMER()ON_WM_DESTROY()ON_WM_KEYDOWN()END_MESSAGE_MAP()// CPlaneGameView 构造/析构CPlaneGameView::CPlaneGameView():m_pMe(NULL){// TODO: 在此处添加构造代码}CPlaneGameView::~CPlaneGameView(){}BOOL CPlaneGameView::PreCreateWindow(CREATESTRUCT& cs){// TODO: 在此处通过修改// CREATESTRUCT cs 来修改窗口类或样式return CView::PreCreateWindow(cs);}// CPlaneGameView 绘制void CPlaneGameView::OnDraw(CDC* pDC){CPlaneGameDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;// TODO: 在此处为本机数据添加绘制代码}BOOL CPlaneGameView::OnPreparePrinting(CPrintInfo* pInfo){// 默认准备return DoPreparePrinting(pInfo);}void CPlaneGameView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: 添加额外的打印前进行的初始化过程}void CPlaneGameView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) {// TODO: 添加打印后进行的清理过程}#ifdef_DEBUGvoid CPlaneGameView::AssertValid() const{CView::AssertValid();}void CPlaneGameView::Dump(CDumpContext& dc) const{CView::Dump(dc);}CPlaneGameDoc* CPlaneGameView::GetDocument() const// 非调试版本是内联的{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CPlaneGameDoc)));return (CPlaneGameDoc*)m_pDocument;}#endif//_DEBUG// CPlaneGameView 消息处理程序void CPlaneGameView::OnInitialUpdate(){CView::OnInitialUpdate();// TODO: 在此添加专用代码和/或调用基类//初始化游戏InitGame();}void CPlaneGameView::StopGame(){delete m_pMe;delete m_pMemDC;delete m_pDC;delete m_pMemBitmap;}BOOL CPlaneGameView::InitGame(){CRect rc;GetClientRect(rc);//产生随机数种子srand( (unsigned)time( NULL ) );//建立设备DCm_pDC = new CClientDC(this);//建立内存DCm_pMemDC = new CDC;m_pMemDC->CreateCompatibleDC(m_pDC);//建立内存位图m_pMemBitmap = new CBitmap;m_pMemBitmap->CreateCompatibleBitmap(m_pDC,GAME_WIDTH,GAME_HEIGHT);//将位图选入内存DCm_pMemDC->SelectObject(m_pMemBitmap);CMyPlane::LoadImage();CEnemy::LoadImage();CBomb::LoadImage();CBall::LoadImage();Bball::LoadImage();CExplosion::LoadImage();BOSS::LoadImage();//产生主角(战机)m_pMe = new CMyPlane;//启动游戏SetTimer(1,30,NULL);//添加背景音mciSendString(_T("Open res\\bgm1.mp3 alias bgm1"), NULL, 0, NULL);mciSendString(_T("Play bgm1 repeat"), NULL, 0, NULL);return TRUE;}void CPlaneGameView::UpdateFrame(CDC* pMemDC){CPlaneGameDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;//========================绘制=====================================//绘制背景if (pDoc->bg[0].y == -GAME_HEIGHT || pDoc->bg[0].y == GAME_HEIGHT)pDoc->bg[0].y = 0;pDoc->bg[0].draw(pMemDC);pDoc->bg[0].y += 1;pDoc->bg[1].draw(pMemDC);pDoc->bg[1].y += 1;if (pDoc->bg[1].y > 0) { pDoc->bg[1].y += -GAME_HEIGHT; }//绘制我方战机if(m_pMe!=NULL){m_pMe->Draw(m_pMemDC,FALSE);//无敌if (wd % 2 != 0){m_pMemDC->TextOutW(20, 60, L"无敌模式:开启", 7);}else{m_pMemDC->TextOutW(20, 60, L"无敌模式:关闭", 7);}//底色条CBrush brush;brush.CreateSolidBrush(RGB(0, 0, 0));//pMemDC->SelectObject(&brush);// pMemDC->Rectangle(0, 640, 250, 670);brush.DeleteObject();//绘制底色brush.CreateSolidBrush(RGB(0, 0, 0));//设置画刷颜色:黑pMemDC->SelectObject(&brush);pMemDC->Rectangle(GAME_WIDTH / 2 - 150, 20, GAME_WIDTH / 2 + 150, 30); brush.DeleteObject();brush.CreateSolidBrush(RGB(255, 255, 255));//设置画刷颜色:白pMemDC->SelectObject(&brush);pMemDC->Rectangle(GAME_WIDTH / 2 - 150, 40, GAME_WIDTH / 2 + 150, 50);brush.DeleteObject();//分数CString strs, strl, strb;strs.Format(_T("%d"), score);strl.Format(_T("%d"), life);strb.Format(_T("%d"), energy);m_pMemDC->SetTextColor(RGB(255, 0, 0));//文字颜色m_pMemDC->SetBkMode(TRANSPARENT);m_pMemDC->TextOutW(20, 380, L"得分:", 3);m_pMemDC->TextOutW(100, 380, strs);m_pMemDC->TextOutW(GAME_WIDTH / 2 - 220, 16, L"生命值:", 4);m_pMemDC->TextOutW(GAME_WIDTH / 2 - 220, 35, L"能量值:", 4);//能量m_pMemDC->SetTextColor(RGB(0, 0, 255));//颜色m_pMemDC->TextOutW(GAME_WIDTH / 2 - 173, 35, strb);//血条CBrush b1(RGB(255, 0, 0));//选定一个画刷类对象b1m_pMemDC->SelectObject(&b1);//选定该对象m_pMemDC->Rectangle(GAME_WIDTH / 2 - 150, 20, GAME_WIDTH / 2 - 150 + life * 3, 30);//画一个矩形brush.DeleteObject();//能量CBrush b2(RGB(0, 0, 255));//选定一个画刷类对象b1m_pMemDC->SelectObject(&b2);//选定该对象m_pMemDC->Rectangle(GAME_WIDTH / 2 - 150, 40, GAME_WIDTH / 2 - 150 + energy * 3, 50);//画一个矩形m_pMemDC->SetTextColor(RGB(255, 0, 0));//颜色if (life > 40){m_pMemDC->SetTextColor(RGB(0, 255, 0));//文字颜色m_pMemDC->TextOutW(GAME_WIDTH / 2 - 170, 16, strl);}m_pMemDC->TextOutW(GAME_WIDTH / 2 - 170, 16, strl);}//========================绘制导弹、爆炸、敌机1,2、子弹1,2======================= for(int i=0;i<6;i++){POSITION pos1,pos2;for( pos1 = m_ObjList[i].GetHeadPosition(); ( pos2 = pos1 ) != NULL; ){CGameObject* pObj = (CGameObject*)m_ObjList[i].GetNext( pos1 );if(!pObj->Draw(pMemDC,FALSE)){m_ObjList[i].RemoveAt(pos2);delete pObj;}}}//复制内存DC到设备DCm_pDC->BitBlt(0,0,GAME_WIDTH,GAME_HEIGHT,m_pMemDC,0,0,SRCCOPY);}//=========================AI()================================////========================省略=================================//void CPlaneGameView::OnTimer(UINT_PTR nIDEvent){CPlaneGameDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;if (!pDoc->Get_havewel()){//开始界面CRect rc;GetClientRect(rc);//建立设备DCm_pDC = new CClientDC(this);//建立内存DCCDC mDC;mDC.CreateCompatibleDC(NULL);CBitmap bmp;bmp.LoadBitmap(IDB_BITMAP6);//载入开始界面mDC.SelectObject(bmp);m_pDC->TransparentBlt(0, 0, 500, 700, &mDC, 0, 0, 500, 700, RGB(200, 200, 200));//深灰if (GetKey(VK_RETURN))pDoc->Set_havewel(TRUE);}else{UpdateFrame(m_pMemDC);AI();if (GetKey('P'))pDoc->Set_havewel(FALSE);//P暂停游戏画面的刷新}CView::OnTimer(nIDEvent);}void CPlaneGameView::OnDestroy(){CView::OnDestroy();this->StopGame();// TODO: 在此处添加消息处理程序代码}void CPlaneGameView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags){// TODO: 在此添加消息处理程序代码和/或调用默认值switch (nChar){case'X':if (energy == 100){for (int i = 0; i<4; i++){if (m_ObjList[i].IsEmpty()) continue;POSITION pos1, pos2;for (pos1 = m_ObjList[i].GetHeadPosition(); (pos2 = pos1) != NULL;){CGameObject* pObj = (CGameObject*)m_ObjList[i].GetNext(pos1);m_ObjList[enExplosion].AddTail(new CExplosion(pObj->GetPoint().x, pObj->GetPoint().y));//删除m_ObjList[i].RemoveAt(pos2);delete pObj;}}energy = 0;}break;}CView::OnKeyDown(nChar, nRepCnt, nFlags);}5. 实训中遇到的主要问题及解决方法a.游戏开始前的欢迎界面贴图不成功。