坦克大战课程设计 - 图文

更新时间:2023-12-24 09:28:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

《面向对象的编程技术》课程设计实验报告

学院:计算机学院

班级:软件工程114

学号:119074258

姓名:黄芳恺

指导老师:胡增涛

2012.12.10

[程序设计名称]:疯狂坦克;

[程序设计主题]:一款娱乐游戏,玩家通过运行操作坦克消灭坦克最后打掉“邪恶

源获得胜利;

[程序设计目的]:《面向对象的编程技术》课程设计是一门独立开设的实验课程,旨

在进一步强化学生对类、封装、继承、多态等面向对象基本概念的理解和OOP(面向对象编程)实际动手能力,并进一步拓展到OOD(面向对象设计)原则、技巧和初步的OOA(面向对象分析)方法。

[程序设计简介]:

一、设计目的:C++电脑游戏开发:侧重利用面向对象的拟人化思想解决复杂问题和

OOD技巧;同时让学生 掌握基本面向对象C++程序设计方法,熟悉C++程序设计的步骤; 通过进行可视化程序设计,进一步熟悉可视化C++开发工具的使用和开发,提高动手能力,提高分析问题和解决问题的能力;

二、功能介绍:这是一款小游戏,主要通过玩家的相关操作游戏中坦克做出相关的动作达到相应的效果,使玩家能够获得小乐趣;

三、基本内容:模拟敌我各种坦克、各种炮弹的运动,模拟地形和各种障碍 物,设计上述对象之间的交互。处理坦克的各种功能与操作。 四、主要技术:C++程序编程以及相关软件的运用;

五、运行环境:本设计采用Microsoft Visual C++6.0编译,并能够在WIN98,WIN2000

下运行游戏基于Windows Game Engine(WGE游戏引擎,添翼虎科技)(没提供源程序,不过不用担心,你可以把它看成是利用DirectX快速处理图片、声音、键鼠的类库) ,该引擎需要DirectX7.0 SDK支持

[应用程序的总体设计结构图]:

TObject 、 TObstacle TEnemyTank TPlayerTank TBullet TSprite TExplode TBonus TWord TLink TLinkNode [应用程序类层次图]:

[主要运行界面的介绍]:

程序主要运行界面如下图,首先是3个选择项目,开始游戏,游戏介绍和退出游戏。通过选择不同的功能进入相应的功能页。开始游戏则是进入相应的游戏程序。游戏介绍则是进入相关介绍。

[应用程序创新和难点]:

[子弹不穿墙修改]:

修改:主要是通过是否碰撞效果来改变子弹是否穿墙,以下是其中之一,其他与之相同方法修改;

RECT rc;/////////////////////////////////////////////////////////子弹不穿墙、、、、、、、、、、、、、、 GetRect(rc);

if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) Dead(); else

if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) Dead(); else

if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) Dead(); else

if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) Dead(); else

if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) Dead(); else

if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT))

Dead(); else

if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) Dead(); //超出射程范围,发出死亡信息 if(m_nFireRange<0) { Dead(); } //击中玩家了吗?(即使死了也不让你好过) if(g_world.Player(0)->HitBy(this)) { //击中目标,任务完成 Dead(); } //已经死亡,来个爆炸效果 if(IsDead()) g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY,EXPLODE_FIRE)); break; case DMISSILE: //双导弹,敌军的导弹 m_nSpeed +=1; //以加速为1的速度运动 m_nCurrentFrame = m_dir; //计算当前动画的帧

[增加自己坦克修改]:

修改:先通过选择一幅自己喜欢的图片,然后用PS将其格式改为PSD,在通过相应软件将其改变为游戏中需要的格式,再对DATA中的进行写入结束运行就可以使用了。

[增加GOD模式修改]:

修改:首先了解坦克变化的相应处理,增加GOD模式即修改这些内容m_nType = MIN((m_nExper/1000),2);第1000点升一级通过升级改变坦克子弹威力;m_nMaxShield =999999999; 调整到最大防护;m_dwDelayTimer -= m_dwDelayTimer*90/100;通过该百分率变速度;结束后还要修改回来;

////////////////////////////////上帝模式、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、 if(WGE_Input.Key()[DIK_G]) {

m_nShield=1000000; m_nMoney=10000000; m_nExper=2000;

m_nType = MIN((m_nExper/1000),2); //第1000点升一级

m_nMaxShield =999999999; //调整最大防护 m_dwDelayTimer -= m_dwDelayTimer*90/100;////// 变速度 }

if(WGE_Input.Key()[DIK_S]) {

m_nShield=100; m_nMaxShield=100; m_nMoney=0; m_nType = 0;

SetDelayTimer(40);////////////////速度恢复 }

[按键后可以穿墙修改]:

修改:首先定义一个整型int wall=0来完成修改,定义开始wall==0时坦克是不可以穿墙的。修改是否穿墙即修改相应的碰撞是否产生即可。按键后调用wall,如果wall==0则坦克不可以进入墙中。如果wall=1则坦克可以进入墙中;

按键设置:

if(WGE_Input.Key()[DIK_Z]) { wall=1; }

if(WGE_Input.Key()[DIK_X]) { wall=0; }

Wall的处理:

BOOL canMove=TRUE; //假设有效先 RECT rc; if(wall==0) { GetRect(rc); //是否碰撞地形障碍?方法和敌人坦克一样 if(m_dir==DIR_UP){ if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) canMove = FALSE; else

if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) canMove = FALSE; }else if(m_dir==DIR_DOWN){ if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) canMove = FALSE; else

if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) canMove = FALSE; }else if(m_dir==DIR_RIGHT){ if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) canMove = FALSE; else

if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) canMove = FALSE; }else if(m_dir==DIR_LEFT){ if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)) canMove = FALSE; else

if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)) canMove = FALSE; } } //碰到了敌人的坦克没有? if(g_world.EnemyTankLink().HitTestAll(this)) canMove = FALSE; //是否碰到了障碍物(木箱或邪恶源) if(g_world.ObstacleLink().HitTestAll(this)) canMove = FALSE; //移动无效,恢复原坐标 if(canMove==FALSE) m_nX = x,m_nY=y; //计算当前动画帧 m_nCurrentFrame=m_dir; //按左CTRL键开火,不过每100ms才能开一次,加弹总要花点时间吧:) static DWORD dwFireTick=GetTickCount(); if(GetTickCount()-dwFireTick>100) { if(WGE_Input.Key()[DIK_LCONTROL]){ g_world.BulletLink().Add(NEW

TBullet(m_nX,m_nY,m_dir,LIGHT,10+m_nMoney/300,100+m_nType*25)); } dwFireTick=GetTickCount(); }

[增加一种子弹修改]:

修改:首先定义一个新子弹NEWBULLET,然后要在子弹类TBullet中增加一个新类并进行相关修改。

定义:enum BULLET_TYPE { SMISSILE,DMISSILE,FIRE,LIGHT,NEWBULLET }; 增加类:static EPG m_epg[5]; 新子弹按键处理:

//按左A键开火,不过每200ms才能开一次,加弹总要花点时间吧:) static DWORD dwFireTick1=GetTickCount(); if(GetTickCount()-dwFireTick1>200) { if(WGE_Input.Key()[DIK_A]){ g_world.BulletLink().Add(NEW

TBullet(m_nX,m_nY,m_dir,NEWBULLET,150,100+m_nType*25)); } dwFireTick1=GetTickCount(); 将火弹定义给玩家坦克: 画子弹

void TBullet::Draw() { static int isload=0; if(isload==0) m_epg[4]=m_epg[2];//将火弹给新弹 POINT p; p.x = m_nX;

} }

p.y = m_nY;

g_world.LPToDP(p); //把世界逻辑坐标转换到设备坐标 WGE_Surface.Blt(m_epg[m_nType], m_nCurrentFrame, p.x,p.y );

}

//让玩家坦克处于可视区的中央 g_world.GetViewportRect(rc);

int height= rc.bottom - rc.top - OBSTACLE_HEIGHT; int width= rc.right - rc.left - OBSTACLE_WIDTH; g_world.SetViewport(m_nX-width/2,m_nY-height/2);

[课程设计中目前存在的问题]:游戏在运行过程中偶尔会出现错误,出现几率

很小,但不知道原因所在。在修改代码是再次编译有时会出现无法运行,错误显示stdafx.h错误。后来知道删除Debug文件夹就行了。

[课程设计中相关问题解决]:

1.static int x;//静态变量有何作用?

答:静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化;静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0;它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束;即此处是一个计时器,在一段时间内GameLoop()被执行了很多次,如果不是一个静态变量每次出函数就被销毁,每次进函数又会被重新定义,重新初始化,这样就无法起到计时器的作用了。

2.g_word.Move();//不马上返回菜单,而是继续动,去掉此行怎样?

答:去掉此行后敌方坦克和子弹都将会停止运动,几秒后就会回到主菜单;

3.CLASS_TYPEm_nClassType;//设计枚举型,在最顶层父类中记录最底层子类的类型不符合OO设计原则,只是为了便于管理和碰撞检测。如何改进?又会有何麻烦?

答:如果这样处理的话刻意为子类分类导致不满足多态;改进:首先取消分类,再用父类指针直接调用子类,让程序判断对象的类型。麻烦:子类对象的链表不易于管理,如果只有父类指针,子类对象不论类型都将只能混合在一个链表里,增加了指针寻找对象的时间。

4.virtual void Move()=0;virtual void Draw()=0;virtual void GetRect(RECT&rect)=0;//

为何要用纯虚函数,在OO设计中有何价值?

答:保证所有TObject的派生类都实现这三个函数,可以方便的用父类的指针去使用这些函数,这样便于程序的管理从而实现程序的多态。

5.5.BOLL HitTest(TObject*object);//为何又不用虚函数?注意是几何尺寸上的碰撞检

测:比较2矩形是否重合。请结合以上几个虚函数,阐述多态在OO设计中的重要作用?

答:对同一类族的对象进行统一处理,抽象程度更高。

6.int m_nStatus;//精灵状态,为何活的东西会有状态?

答:活的东西会有各种状态需要用不同状态加以区分。

7.TWorld要想使用上述各对象的功能,也可以做它们的子类(多继承),这样做好不好?为什么?

答:不好。TWord类型的对象包括各类全部数据,但本身不包括其他各类接口,这样接口只能被TWord类所用更安全。

[设计实践过程中的心得体会]:

通过这次对《面向对象的编程技术》课程设计的学习,在实验与实践过程中我学到了很多。首先通过实践我掌握面向对象编程的基本思路和方法,我学会了如何根据相关要求进行上机调试,在不断实验中掌握了很多开发工具的运用。总的来说,这次学习让我获益良多。首先,我学会了在每次编程过程中必须要有个谨慎的心理。对待每个问题必须认真对待,从问题的本质出发,先想应该怎么处理从哪里入手。在初步了解问题本质后,再开始分析一步一步的处理直至问题解决。另外,在这次实验中,我对面向对象的编程有了新的认识,面向对象程序设计中的概念主要包括:对象、类、数据抽象、继承、动态绑定、数据封装、多态性、消息传递。通过这次实验我对这些概念有了更深层次的认识。通过这次修改与创新,我建立了新的认识,提高了我的系统性的认知能力,掌握从上而下的问题分析能力,既能理解各个类中方法的细节,又能站在项目总体的角度从宏观上认识程序,然后将程序很好地分解为不同功能的类。我了解了面向对象设计方法以对象为基础,利用特定的软件工具直接完成从对象客体的描述到软件结构之间的转换。我学到了面向对象的编程范式即首先决定你要的类,再给每个类提供完整的一组操作,明确地使用继承来表现共同点。另外,这次设计还巩固了我的C++知识。在不断的测试运行中我不仅对基础语法的应用更加熟悉,在能力培养和技术训练,分析问题和解决问题的能力、表达能力有了更好的提升。总体说来这次《面向对象的编程技术》课程设计让我学会了很多,增强我们对未来的适应能力和解决问题的能力,更好地将理论联系实际。

[附录]:

1. 安装Visual C++6.0 2. 安装DirectX SDK:

思路:Runtime与Header&Libs必须配套,且高于7.0版本。由于DirectX不太容易卸载,所以建议安装高于当前系统Runtime的DirectX(升级当前DirectX Runtime,并补上Header&Libs)

1) 检查当前DirectX版本:windows下“开始” | “运行” |dxdiag

2) 如果版本低于9.0c安装,安装(90C OK) directx_9c_Jun05sdk_redist.exe以升级运行

库;安装适合c++的SDK:dx9sdkcp.exe(运行类型:Retail速度快;Debug便于调

试),建议装在c:\\dxsdk。

3) 检查DirectX SDK安装是否正确:运行dxdiag | “显示” |“测试DirectX Draw”,

确保2D显示正确。(以后若用到3D,至少要保证DirectX3D 7正确。)

3. 安装WGE游戏引擎:WgeSetup,建议安装在c:\\wgesdk

4. 设置VC++ 6.0环境,以便找到上述SDK的头文件和库文件:

VC++ 6.0 | “Tools” | “Option”,选Directors(路径)(缺省的 “Show Directories for”列表为 “Include files”),加入DirectX SDK和WGE游戏引擎的头文件路径:c:\\dxsdk\\include(注意要移到首行,以便优先于VC自带的旧文件), c:\\wgesdk\\include,从“Show Directories for”列表选 “Library files”,加入c:\\dxsdk\\lib ,c:\\wgesdk\\lib\\. 5. 测试所有软件安装是否正确:

1)VC | File | New | Project |Windows Game Engine SDK AppWizard工程向导,输入工程名Test和路径 | OK;

2)输入屏幕宽(必须偶数)、高为400,300,游戏名Test,显示模式GDI_MODE(窗口模式,当前显示设置不应少于16bit)

4) finish完成。编译:VC | “Build” | “Build Test.exe” ,运行:“Build” | “Execute

Test.exe”,看到如下界面表示上述安装正确(ESC退出):

本文来源:https://www.bwwdw.com/article/hh35.html

Top