信息科学与工程学院
2014 年 10 月 15 日
1. 实习目的
1.1使学生全面了解软件项目实施的过程,理解软件企业对于程序员的基本素质和技术能力要求。
1.2使学生掌握C++及Window程序设计的基本技术,能够运用MFC技术及其开发环境进行小型项目的开发。
1.3重点培养学生的独立创新精神和查阅资料能力,提高其口头和书面的沟通能力。
1.4使学生掌握快速学习新知识、新技术方法,培养良好的分析问题和解决问题的能力
1.5重点提高学生的编程能力,使学生建立正确的编程理念,养成规范的编程习惯。
2. 实习计划
一、9.20-9.21
1、认识MFC的基本功能,实现在windows窗体上的贴图功能;
2、初步利用brush绘制背景的颜色,进而掌握添加背景图片的技术;
3、设置定时器进行刷屏;
二、9.22-9.25
1、把握游戏的整体架构,了解各个类之间的继承与多态关系,对父类进行编码;
2、对游戏对象进行透明贴图,并实现具体的功能;
三.9.26-9.28
1、建立各个游戏对象的链表,并定义对象;
2、实现用键盘控制战机的移动,实现战机与战机导弹的链接;
3、实现其他游戏对象的移动与速度的设定;
4、实现战机导弹与敌机、子弹与战机矩形区域的重合的功能,并清除链表中需要清除的对象;
5、释放定时器和内存;
四、9.29-9.30
1、与游戏的功能与界面进行完善,添加文字显示和生命条等;
2、对游戏进行调试与改进。
3.实习过程
4.1 技术准备
(1)、透明贴图函数
LoadImage(CImageList& imageList,UINT bmpID,COLORREF crMask,int cx,int cy,int nInitial)
//可用于从 BMP 文件加载位图,主要用于将图片放入图像链表imageList中。
m_Images.Draw(pDC,0,m_ptPos,ILD_TRANSPARENT)
//此函数主要是将链表中的图像显示在pDC这个句柄中。
(2)、CObList链表
CObList list_ball;
//主要是定义一个CObList类的一个链表对象用于存储所有的此种相关对象,易于后续的添加删除和提取数据。
POSITION posball=NULL; //定义指针
posBall=list_ball.GetHeadPosition();//指针读取头结点
pBall=(CBall *)list_ball.GetNext(posBall);//指针读取下一个结点
(3)、设置定时器
定时器告诉WINDOWS一个时间间隔,然后WINDOWS以此时间间隔周期性触发程序。本程序中使用多个定时器,分别控制不同的功能。使用SetTimer()函数设置定时器,设置系统间隔时间,在OnTimer()函数中实现响应定时器的程序。
(4)、双缓冲技术
关于双缓冲技术主要就是利用缓存的原理进行将所有的东西都先存在一个缓冲得虚拟的区域,然后再一次性的将所有的虚拟缓存中的东西都放入实在的存储器中。
(5)、内存释放技术
在此次实训项目中有太多的对象的生成和运用,造成了内存的极度的紧张,当游戏进行到一定的程度的时候就会出现内存溢出现象。内存释放技术的实现主要是通过释放各个满足一定条件的对象和链表来实现的,list_bomb.RemoveAt(B2);//RemoveAt从列表中删除指定位置的元素 delete pBomb;//删除敌机
(6)、获取矩形区域函数
CRect rc; //定义
GetClientRect(&rc); //获取其矩形区域
获取结果为:rc.Width() //矩形区域的宽度rc.Height() //矩形区域的高度
CRect tmpRect;
tmpRect.IntersectRect(&bRect,eRect))//判断两个矩形是否有交接
4.2 项目实施
4.2.1 功能需求
1、战机数量为1,战机的位置可通过键盘进行控制。可通过空格键控制战机进行发导弹,导弹具有一定的速度。
1、2、敌机出现的时间和位置均为随机,敌机的速度也是随机的,敌机发射子弹的时间也是随机的,子弹的发射具有延时性,子弹的速度具有随机性。
1、3、导弹和子弹及敌机碰撞爆炸同时销毁碰撞的物体,战机和子弹及敌机碰撞爆炸同时销毁碰撞的子弹及敌机,战机则判断生命,为0时销毁否则不销毁。与此同时进行分数和生命的变化同时进行文本的显示提示。
1、4、背景图片的添加。为游戏提供相关背景。
5、主要的攻击规则如下:
敌机可在战机的上方或者下方进行将子弹进行射向战机,同时战机也可根据玩家的指示进行向上或者向下进行发射导弹进行反攻。
6、主要的碰撞规则如下:
1)、导弹和敌机的矩形区域或子弹和敌机的矩形区域相交时,表示其相互发生碰撞表示其相互爆炸,销毁游戏对象。
2)、战机生命为0,战机被炸,战机被销毁,游戏结束。
3)、敌机被炸毁,将其进行销毁同时进行分数的相应的增加,并且出现文字提示。
7、实现对战机的生命的增减,战机基本生命值为5,战机射击增加生命值,当其被击中后其生命就-1,每销毁一架敌机加10分,销毁累计10架敌机,战机的生命值加一,生命为0时游戏结束。
8、实现控制战机速度的功能主要是用于在键盘控制战机位置时。
9、实现双缓冲技术进行解决刷屏时屏闪的问题。
4.2.2 总体设计
飞机大战游戏主要模块可以说是有几个重要的类组成的。首先是老师给出的CGameObject类,以及在其派生下的BOMB,BALL,ENEMY,MYPLANE等等。如图:
2、主要功能模块
主要功能是在飞机大战View类中,OnTimer函数中实现,将各个类调用,随机产生敌机,子弹的输出,爆炸的实现等等。它的实现图可以如下实现:
4.2.3 详细设计与编码
#include "stdafx.h"
#include "飞机大战.h"
#include "飞机大战Doc.h"
#include "飞机大战View.h"
#include"MyPlane.h"
#include"explosion.h"
#include"ball.h"
#include"enemy.h"
#include"bomb.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
void CMyView::OnDraw(CDC* pDC)
{
CMyDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
}
void CMyView::OnTimer(UINT nIDEvent)
{
CDC* pDC=GetDC();
CRect rc;
GetClientRect(&rc);
//双缓存
CDC memDC;//定义一个显示设备对象
CBitmap bmp;//定义一个位图对象
memDC.CreateCompatibleDC(NULL);//建立与屏幕显示兼容的内存显示设备
bmp.CreateCompatibleBitmap(pDC,rc.Width(),rc.Height());
CBitmap*oldBit=memDC.SelectObject(&bmp);
//设置背景图
CBitmap bitmap;
CBrush brush;
bitmap.LoadBitmap(beijing);
brush.CreatePatternBrush(&bitmap);
CClientDC dc(this);
memDC.FillRect(&rc,&brush);
CRect rect;
GetClientRect(&rect);
//------------------------------
static int life=5;
static int score=0;
/****画战机******************************************/
if(pMyPlane!=NULL)
{
pMyPlane->Draw(&memDC,0,rc);
memDC.SetBkMode(TRANSPARENT);//透明
memDC.SetTextColor(RGB(255,255,20));//文字颜色
memDC.TextOut(20,150,"分数:");
memDC.TextOut(100,150,itoa(score,new char,10));//itoa:把int转为char字符串
memDC.TextOut(20,180,"剩余生命:");
memDC.TextOut(150,180,itoa(life,new char,10));
//显示生命线
CBrush brush1;
brush1.CreateSolidBrush(RGB(255,0,0));
//创建画刷
memDC.SelectObject(brush1);
//选择画刷
memDC.Rectangle(rect.Width()/2-100,10, rect.Width()/2+life*60-100,
30);
}
else
{
memDC.SetBkMode(TRANSPARENT);
memDC.SetTextColor(RGB(255,255,20));
memDC.TextOut(300,300,"GAME OVER");
}
/*******************添加战机导弹************************/
POSITION posBomb=NULL;
posBomb=list_bomb.GetHeadPosition();
while(posBomb!=NULL)
{
pBomb= (CBomb *)list_bomb.GetNext(posBomb);
pBomb->Draw(&memDC,0,rc);
}
/******************添加敌机*********************/
static int n=0;
if(n<=0)
{
n=rand()%40;
list_enemy.AddTail(new CEnemy);
}
n--;
POSITION pEnemy1=NULL,pEnemy2=NULL;
pEnemy1=list_enemy.GetHeadPosition();//GetHeadPosition 返回列表中首元素的位置
while((pEnemy2=pEnemy1)!=NULL)
{
pEnemy=(CEnemy*)list_enemy.GetNext(pEnemy1);
if(!pEnemy->Draw(&memDC,0,rc))
{
list_enemy.RemoveAt(pEnemy2);
delete pEnemy;
}
int x=rand()%40;
if(x==1)
{
list_ball.AddTail(newCBall(pEnemy->GetPoint().x+12,pEnemy->GetPoint().y+25,pEnemy->GetMontion()));
}
}
/************************添加敌机子弹*******************************/
POSITION posBall=NULL;
posBall=list_ball.GetHeadPosition();
while(posBall!=NULL)
{
pBall=(CBall *)list_ball.GetNext(posBall);
pBall->Draw(&memDC,0,rc);
}
/****************添加爆炸效果**************************/
POSITION posExplosion=NULL;
for(posExplosion=list_explosion.GetHeadPosition();posExplosion!=NULL;)//GetHeadPosition返回列表中首元素的位置
{
pExplosion=(CExplosion*)list_explosion.GetNext(posExplosion);
//GetNext获取循环遍历中的下一个元素
pExplosion->Draw(&memDC,0,rc);
}
/*****************战机子弹炸掉敌机***********************/
if(pMyPlane!=NULL)
{
POSITION B1=NULL,B2=NULL;
B1=list_bomb.GetHeadPosition();
while((B2=B1)!=NULL)
//GetHeadPosition 返回列表中首元素的位置
{
pBomb= (CBomb*)list_bomb.GetNext(B1);
//GetNext获取循环遍历中的下一个元素
CRect bRect = pBomb->GetRect();//获得导弹区域
POSITION E1=NULL,E2=NULL;
E1=list_enemy.GetHeadPosition();
while((E2=E1)!=NULL)
{
pEnemy=(CEnemy*)list_enemy.GetNext(E1);
CRect eRect=pEnemy->GetRect();//获得敌机区域
CRect enRect;
//定义一个区域,该区域作用为获得导弹和敌机区域的交集。
if(enRect.IntersectRect(&bRect,eRect))
//若导弹和敌机有交集,删除导弹和敌机,添加爆炸效果
{
score+=10;
//添加炸弹效果
list_explosion.AddTail(new CExplosion(eRect.left, eRect.top));
//删除导弹
list_bomb.RemoveAt(B2);//RemoveAt从列表中删除指定位置的元素
delete pBomb;
//删除敌机
list_enemy.RemoveAt(E2);
delete pEnemy;
//生命值与分数换算
static int a;
a++;
if(a%10==0)
{
life+=1;//每击破10架敌机生命数加1
}
}
}
}
}
/**********************敌机子弹炸掉战机********************/
if(pMyPlane!=NULL)
{
POSITION bPos1=NULL,bPos2=NULL;
CRect mRect = pMyPlane->GetRect();//获得战机区域
bPos1=list_ball.GetHeadPosition();
while(( bPos2 = bPos1 ) != NULL)
{
pBall = (CBall*)list_ball.GetNext(bPos1);
CRect bRect = pBall->GetRect();//获得子弹区域
CRect tmpRect;
if(tmpRect.IntersectRect(&bRect,mRect))
//子弹区域与战机区域相交
{
life-=1;
//添加炸弹效果
list_explosion.AddTail(new CExplosion(mRect.left,mRect.top));
//删除子弹
list_ball.RemoveAt(bPos2);
delete pBall;
//删除战机
if(life==0)
{
delete pMyPlane;
pMyPlane=NULL;
break;
}
}
}
}
/*****************敌机与战机相撞****************************/
if(pMyPlane!=NULL)
{
POSITION bPos1=NULL,bPos2=NULL;
CRect mRect = pMyPlane->GetRect();//获得战机区域
bPos1=list_enemy.GetHeadPosition();
while(( bPos2 = bPos1 ) != NULL)
{
pEnemy = (CEnemy*)list_enemy.GetNext(bPos1);
CRect eRect=pEnemy->GetRect();//获得敌机区域
CRect tmpRect;
if(tmpRect.IntersectRect(&eRect,mRect))
//敌机区域与战机区域相交
{
score+=10;
life-=1;
//添加炸弹效果
list_explosion.AddTail(new CExplosion(mRect.left,mRect.top));
//删除敌机
list_enemy.RemoveAt(bPos2);
delete pEnemy;
//删除战机
if(life==0)
{
delete pMyPlane;
pMyPlane=NULL;
break;
}
}
}
}
//双缓存释放
pDC->BitBlt(0,0,rc.Width(),rc.Height(),&memDC,0,0,SRCCOPY);
memDC.SelectObject(oldBit);
memDC.DeleteDC();
bmp.DeleteObject();
CView::OnTimer(nIDEvent);
}
void CMyView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if(pMyPlane!=NULL)
{
if(nChar==VK_RIGHT)
{
pMyPlane->SetHorMotion(1);
}
if(nChar==VK_LEFT)
{
pMyPlane->SetHorMotion(-1);
}
if(nChar==VK_UP)
{
pMyPlane->SetVerMotion(1);
}
if(nChar==VK_DOWN)
{
pMyPlane->SetVerMotion(-1);
}
}
//战机添加导弹
if(pMyPlane!=NULL)
{
int m;
m=GetKey(VK_SPACE);
if(m==1)
{
{
list_bomb.AddTail(newCBomb(pMyPlane->GetPoint().x,pMyPlane->GetPoint().y+20));
list_bomb.AddTail(newCBomb(pMyPlane->GetPoint().x+20,pMyPlane->GetPoint().y));
list_bomb.AddTail(newCBomb(pMyPlane->GetPoint().x+40,pMyPlane->GetPoint().y+20));
}
}
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
int flag = 0;
void CMyView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)//释放
{
if(pMyPlane!=NULL)
{
if(nChar==VK_RIGHT)
{
pMyPlane->SetHorMotion(0);
}
if(nChar==VK_LEFT)
{
pMyPlane->SetHorMotion(0);
}
if(nChar==VK_UP)
{
pMyPlane->SetVerMotion(0);
}
if(nChar==VK_DOWN)
{
pMyPlane->SetVerMotion(0);
}
}
CView::OnKeyUp(nChar, nRepCnt, nFlags);
}
int CMyView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
//安装定时器
SetTimer(1,30,NULL);
//1是定时器的标示符,30ms的间隔,NULL表示让窗体接受消息,不是函数
pMyPlane=new CMyPlane; //显示飞机
CMyPlane::LoadImage();
CBomb::LoadImage();
CEnemy::LoadImage();
CBall::LoadImage();
CExplosion::LoadImage();
return 0;
}
void CMyView::OnDestroy()
{
//释放定时器
KillTimer(1);
delete pDC;
CView::OnDestroy();
}
4.2.4 测试
游戏界面:
4.总结与建议
通过这次飞机大战的实训,一方面我深刻的意识到了自己所掌握的C++知识还远远不够,基本的语法都记不牢还需要进行查书,致使实训进行的非常缓慢;另一方面,自己对于C++面向对象的思想没有把握好,并且对于封装之类的以及多态的思想也不是真正的理解。通过实训,我还意识到光记住书本的理论知识是远远不够的,要不断的进行实践,只有在不断的敲代码、改错误的反复过程中才能使自己的编程能力得到真正的提升。
在此次实训中,自己的程序只是实现了基本的功能,还可以有其他的扩展功能可进行增加,主要有:
1、给游戏进行增加boss,通过boss的添加进行游戏的关卡和难度的更加进一步的提升。
主要思路是:再增加一个类让它继承敌机类,然后再敌机类的基础上进行增加其生命值和被打死后的得分。当战机得分到达一定的值以后boss出现并进行和敌机一个队伍发射另类的子弹进行攻击战机。
2、给游戏进行增加另类的子弹供boss向战机进行攻击,此类继承敌机的子弹类。
3、进行增加存盘处理,用于暂停功能。通过存盘使玩家可以进行暂停或者人为结束时的继续进行玩。主要思路是:在玩家进行选择暂停或者结束时,系统将当前各个类的对象信息存储在文件中,当玩家选择继续时,系统从文件中读取各个对象的相应信息进行继续进行游戏。
IE生产实习报告院系管理工程学院姓名方宗炼专业工业工程班级081班学号3080502101指导老师费志敏曹邦平梁艳叶逊王志国刘从虎…
生产实践实习实习报告学科专业武器系统与工程弹药方向学生姓名张洪铭学号1101510340实习日期20xx年3月实习地点豫西工业集团…
生产实习报告学院专业年级姓名学号一概述实习目的生产实习是高等工科院校教学计划中的一个重要的实践性教学环节为了响应课本知识与实践相结…
姓名:吴彦民院系:广东机电职业技术学院机械工程系专业:数控技术一、实习目的............................…
生产实习报告实习地点东风汽车公司湖北十堰实习时间学生姓名班级学号一生产实习内容每天的实习内容字数不应少于1000字要求字迹工整11…
在一个有效的组织中,必定拥有杰出的一线人才。软件设计也是一样的,一线人才的素质决定了软件的质量。从敏捷的观点来看,代码是检验软件过…
JAVA软件开发专业实习报告一、实习的时间:20##年4月5日20##年6月20日二、实习的地点:软帝有限公司三、实习的目的:进一…
xxxx学院毕业实习报告系别:年级班级:学号:姓名:指导教师:实习类型:实习单位:实习时段:集中实习关于在XX公司从事软件开发的实…
不知不觉,在大庆实习的日子快过去半个月了,记得刚来大庆的头几天,感觉非常不适应。首先是环境:这里吃的东西很贵,而且这里的物价很高。…
实训总结实训目的:实训单位和工作岗位:实训的内容:从事工作情况实训的心得体会:“天下英雄皆我辈,一入江湖立马催。”从学校到社会的大…
实习报告西安文理学院软件学院10级软件工程一班张兴华学号141xxxxxxxx实习报告一、实习目的根据所学课程的理论知识,结合企业…