好好学习,天天向上,一流范文网欢迎您!
当前位置:首页 >> 最新范文 内容页

程序设计综合实践报告

程序设计综合实践报告 本文关键词:程序设计,实践,报告,综合

程序设计综合实践报告 本文简介:程序设计综合实践报告姓名梁琨学号201301050817班级信息13-1项目名称飞机大战游戏设计与实现实习地点科技园实习时间2015-10-26至2015-11-6实习成绩指导教师签字数学与系统科学学院2015年11月6日目录1.概述12.相关技术12.1数据链表12.2双缓冲13.总体设计与详细设

程序设计综合实践报告 本文内容:

程序设计综合实践报告

姓名

梁琨

学号

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

系统模块划分

游戏规则子系统

模块名称

功能简述

人工智能

人机对战规则的实现

游戏子系统

模块名称

功能简述

应用程序对象

游戏程序的加载、游戏对象的绘制、游戏规则的调用、玩家的键盘事件获取

游戏对象

各个游戏对象的抽象父类

战机对象

战机类

敌机对象

敌机类、大敌机类

炸弹对象

炸弹1类、炸弹2类

爆炸对象

爆炸类

文字对象

文字类

3.2

主要功能模块

模块名称

人工智能

功能描述

人机对战规则规则

接口与属性

void

AI(

void

);

数据结构

与算法

(注:红色加粗部分为新加代码!)

void

CPlaneGameView::AI()

{

if(m_pMe==NULL)

return;

//检测四个方向键,移动战机

for(int

i=0;iSetVerMotion(0);

m_pMe->SetHorMotion(0);//初始化

nMeMotion

=

GetKey(VK_UP);

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

=

1000

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

if(by

}

}

//小敌机子弹炸掉战机

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(

}

//删除子弹

m_ObjList[enBall].RemoveAt(bPos2);

delete

pBall;

//添加爆炸效果

m_ObjList[enExplosion].AddTail(

new

CExplosion(mRect.left,mRect.top)

);

if

(life

GetRect();

CRect

tmpRect;

if

(tmpRect.IntersectRect(

}

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

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(

pEnemy->Setlife(-pBomb->Gethurt());

if

(pEnemy->Getlife()

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(

if

(wd

%

2

==

0)

{

life

--;

}

if

(pBboss->get_life()

!=

0)

{

pBboss->set_life(-1);

}

//删除

大Boss

if

(pBboss->get_life()

==

0){

m_ObjList[enExplosion].AddTail(new

CExplosion(mRect.left

+

30,mRect.top

+

30));

m_ObjList[enExplosion].AddTail(new

CExplosion(mRect.left

+

70,mRect.top

+

30));

m_ObjList[enExplosion].AddTail(new

CExplosion(mRect.left

+

50,mRect.top

+

50));

m_ObjList[enExplosion].AddTail(new

CExplosion(mRect.left

+

30,mRect.top

+

70));

m_ObjList[enExplosion].AddTail(new

CExplosion(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

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(

if

(pEnemy->get_life()

!=

0)

{

pEnemy->set_life(-3);

}

//删除

大Boss

if

(pEnemy->get_life()

Fired())

continue;

CPoint

BPt

=

pBboss->GetPoint();

BOOL

by

=

FALSE;

//敌机在战机前面

if

(BPt.y=

PlanePt.x

CRect

tmpRect;

if

(tmpRect.IntersectRect(

}

//删除子弹

m_ObjList[enBball].RemoveAt(BbPos2);

delete

pBball;

//添加爆炸效果

m_ObjList[enExplosion].AddTail(

new

CExplosion(mRect.left,mRect.top)

);

if

(life

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));//定义一个画笔类对象p1

m_pMemDC->SelectObject(//选定该对象

CBrush

b1(RGB(255,0,0));//选定一个画刷类对象b1

m_pMemDC->SelectObject(//选定该对象

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);

}//if

else

exit(1);

}

}

补充说明

4.

编码实现

(注:红色加粗部分为新加代码)

//

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

#include

“GameObject.h“//

加声音

#include

#pragma

comment(lib,“WINMM.LIB“)

#include

#ifdef

_DEBUG

#define

new

DEBUG_NEW

#endif

#pragma

once

static

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,}

//

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

_DEBUG

void

CPlaneGameView::AssertValid()

const

{

CView::AssertValid();

}

void

CPlaneGameView::Dump(CDumpContext

}

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

)

);

//建立设备DC

m_pDC

=

new

CClientDC(this);

//建立内存DC

m_pMemDC

=

new

CDC;

m_pMemDC->CreateCompatibleDC(m_pDC);

//建立内存位图

m_pMemBitmap

=

new

CBitmap;

m_pMemBitmap->CreateCompatibleBitmap(m_pDC,GAME_WIDTH,GAME_HEIGHT);

//将位图选入内存DC

m_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(

//

pMemDC->Rectangle(0,640,250,670);

brush.DeleteObject();

//绘制底色

brush.CreateSolidBrush(RGB(0,0,0));//设置画刷颜色:黑

pMemDC->SelectObject(

pMemDC->Rectangle(GAME_WIDTH

/

2

-

150,20,GAME_WIDTH

/

2

+

150,30);

brush.DeleteObject();

brush.CreateSolidBrush(RGB(255,255,255));//设置画刷颜色:白

pMemDC->SelectObject(

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));//选定一个画刷类对象b1

m_pMemDC->SelectObject(//选定该对象

m_pMemDC->Rectangle(GAME_WIDTH

/

2

-

150,20,GAME_WIDTH

/

2

-

150

+

life

3,30);//画一个矩形

brush.DeleteObject();

//能量

CBrush

b2(RGB(0,0,255));//选定一个画刷类对象b1

m_pMemDC->SelectObject(//选定该对象

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;iDraw(pMemDC,FALSE))

{

m_ObjList[i].RemoveAt(pos2);

delete

pObj;

}

}

}

//复制内存DC到设备DC

m_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);

//建立设备DC

m_pDC

=

new

CClientDC(this);

//建立内存DC

CDC

mDC;

mDC.CreateCompatibleDC(NULL);

CBitmap

bmp;

bmp.LoadBitmap(IDB_BITMAP6);//载入开始界面

mDC.SelectObject(bmp);

m_pDC->TransparentBlt(0,0,500,700,//深灰

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;

iGetPoint().x,pObj->GetPoint().y)

);

//删除

m_ObjList[i].RemoveAt(pos2);

delete

pObj;

}

}

energy

=

0;

}

break;

}

CView::OnKeyDown(nChar,nRepCnt,nFlags);

}

5.

实训中遇到的主要问题及解决方法

a.游戏开始前的欢迎界面贴图不成功。这个问题主要是由于忘记将内存DC复制到设备DC,即绘图后忘记添加m_pDC->BitBlt(0,0,GAME_WIDTH,GAME_HEIGHT,m_pMemDC,0,0,SRCCOPY);

b.血量、能量为负值。原因是计算血量时提前删除了子弹,导致访问到的子弹伤害值为一个未知数,应当把计算血量放在删除子弹之前。

c.出现断点。主要原

TAG标签: