攀枝花学院课程设计
题 目:
院 (系):
年级专业:
姓 名:
学 号:
指导教师:
坦克大战程序设计 数学与计算机学院 2015级网络工程 陈波 201510803075 朱正国
二〇一六年七月五日 攀枝花学院教务处制
攀枝花学院本科学生课程设计任务书
题 目 坦克大战程序设计 1、课程设计的目的 通过完成一个完整项目,经历策划、设计、开发、测试、验收各阶段,达到: (1)巩固和实践计算机图形学课程中的理论和算法; (2)培养项目策划、架构设计、软件开发和科研设计的能力; (3)培养认真学习、积极探索的工作态度和良好的团队合作精神。 2、课程设计的内容和要求(包括原始数据、技术要求、工作要求等) 开发工具:TC或Visual C++ 开发人数:1人 实现内容: 设计开发一个坦克大战程序 功能要求: (1)根据需求设计出图形显示界面 (2)根据坦克大战移动攻击的全过程演示。 3、主要参考文献 [1] [美]Watts S Humphrey。软件工程规范[M].苏俊,许青松译.清华大学出版社,2008. [2] [美]Mc.Connell,代码大全(第二版).电子工业出版社[M],2006.3 [3] 刘志峰.软件技术与是件[M].电子工业出版社.2008 [4] 柳朝阳,周晓平.计算机图形学:图形的计算与显示原理. 西安电子科技大学出版社 .2005 [5] 肖永亮,Visual C++游戏编程基础[M],电子工业出版社,2005.5 [6] 陈锦昌,赵明秀.C语言计算机绘图教程.华南理工大学出版社.1998.9 [7] 杨昂岳.微机实用绘图方法与技巧.国防科技大学出版社.1995.12 4、课程设计工作进度计划 1、设计动员,布置任务,选题(1天) 2、查阅资料,分析、讨论与设计(1天) 3、编写程序,进行调试(1天) 4、完成模块联调,进行测试(1天) 5、成果验收,完成设计报告(1天) 指导教师(签字) 教研室意见: 年 月 日 学生(签字): 接受任务时间: 年 月 日 注:任务书由指导教师填写。
日期 年 月 日 课程设计(论文)指导教师成绩评定表
题目名称 评分项目 工作 表现 20% 01 02 03 04 05 06 07 08 学习态度 科学实践、调研 课题工作量 综合运用知识的能力 应用文献的能力 设计(实验)能力,方案的设计能力 计算及计算机应用能力 对计算或实验结果的分析能力(综合分析能力、技术经济分析能力) 插图(或图纸)质量、篇幅、设计(论文)规范化程度 设计说明书(论文)质量 创新 分值 6 7 7 10 5 5 5 10 坦克大战 得分 评价内涵 遵守各项纪律,工作刻苦努力,具有良好的科学工作态度。 通过实验、试验、查阅文献、深入生产实践等渠道获取与课程设计有关的材料。 按期圆满完成规定的任务,工作量饱满。 能运用所学知识和技能去发现与解决实际问题,能正确处理实验数据,能对课题进行理论分析,得出有价值的结论。 能独立查阅相关文献和从事其他调研;能提出并较好地论述课题的实施方案;有收集、加工各种信息及获取新知识的能力。 能正确设计实验方案,独立进行装置安装、调试、操作等实验工作,数据正确、可靠;研究思路清晰、完整。 具有较强的数据运算与处理能力;能运用计算机进行资料搜集、加工、处理和辅助设计等。 具有较强的数据收集、分析、处理、综合的能力。 能力 水平 35% 成果 质量 45% 09 10 11 5 30 10 符合本专业相关规范或规定要求;规范化符合本文件第五条要求。 综述简练完整,有见解;立论正确,论述充分,结论严谨合理;实验正确,分析处理科学。 对前人工作有改进或突破,或有独特见解。 成绩 指导教师评语 指导教师签名: 年 月 日 攀枝花学院学生课程设计论文 摘要
摘 要
坦克大战是一款适用于青少年娱乐放松的游戏,不仅有利于人们放松还能避免对游戏的上瘾。该游戏简单,操作性低,随着现在各种网络游戏的盛行有着一款既不上瘾又能缓解人们的压力,对于当今社会很是重要。
坦克大战利用了计算机图形学进行程序设计,也利用C++语言绘图函数实现坦克大战图形界面演示过程。同时,通过C++语言实现图形学的绘图,程序控制,以及区域填充,并根据坦克大战的移动和攻击全过程演示。
关键词 坦克大战,绘图,程序控制,界面演示。
I
攀枝花学院学生课程设计论文 目录
目 录
摘 要 ............................................................................................................................................ I
1 需求分析 ................................................................................................................................ 3
1.1 需求概述 ............................................................................................................................... 3 1.2 需求环境 ............................................................................................................................... 3 1.3 功能描述 ............................................................................................................................... 3
2 概要设计 ................................................................................................................................. 5
2.1 程序功能模块 ....................................................................................................................... 5 2.2 程序流程图 ........................................................................................................................... 6
3 详细设计 .................................................................................................................................... 7
3.1 游戏开始 ............................................................................................................................... 7 3.1.1代码功能 ........................................................................................................................ 7 3.1.2 功能实现代码 ............................................................................................................... 8 3.2 坦克的移动过程 ................................................................................................................. 10 3.2.1代码功能 ...................................................................................................................... 10 3.2.2 功能实现代码 ............................................................................................................. 11
3.3 坦克开炮和敌方坦克的构造 ..................................................................................... 17
3.3.1代码功能 ...................................................................................................................... 17 3.3.2功能实现代码 .............................................................................................................. 19 3.4地图的加载和创建父类-CWEAPON类 ................................................................................... 23 3.4.1代码功能 ...................................................................................................................... 23 3.4.2 功能实现代码 ............................................................................................................. 25 3.5 子弹链表和显示游戏信息 ................................................................................................. 30 3.5.1代码功能 ...................................................................................................................... 30 3.5.2 功能实现代码 ............................................................................................................. 32
4 测试与运行 ............................................................................................................................. 36 结束语 ........................................................................................................................................... 37 参考文献 ...................................................................................................................................... 38
II
攀枝花学院学生课程设计论文 需求分析
1 需求分析
1.1 需求概述
坦克大战程序设计是计算机图形学中图形变换的内容之一。而图形学中的图形变换的概念是由简单图形生成复杂图形,可用二维图形表示三维形体,甚至可以对静态图形经过快速变换而获得图形的动态显示效果。其任务是研究各点坐标之间的变化规律。而本次课程设计就是利用C++语言以及图形函数实现坦克大战移动的全过程显示。在TC环境中要实现这样的功能,就要牵涉到图形设备接口的知识。Windows图形设备接口是为与设备无关的图形设计的,是Windows系统的重要组成部分,负责系统与用户或绘图程序之间的信息交换,并控制在输出设备上显示图形或文字。应用程序必须通知图形设备接口来加载特定的设备驱动,一旦驱动得以加载,就可以准备应用设备进行相关的操作这些任务都要通过创建和维护设备描述表来完成。在实现坦克大战程序设计时,是利用坐标系统而得到的,而在Windows应用程序中有两种坐标系统:设备坐标系统和逻辑坐标系统。其中设备坐标系统中又有三种相互独立的坐标系统:屏幕坐标系统、窗口坐标系统和用户区坐标系统。这些坐标系统均以像素点来表示度量的单位。屏幕坐标系统使用整个屏幕作为坐标区域,原点为屏幕原点。窗口坐标系统使用了边界在内的应用程序的窗口作为坐标区域。窗口边界的左上角是坐标系统的原点。用户坐标系统是最经常使用的坐标系统。用户区是窗口工作区,不包括窗口边界、菜单条及滚动条等。用户一般只需操作应用程序的用户区,因此用户区坐标系统对大多数应用程序都是适用的。
在计算机机图形学中窗口的定义是指在用户坐标系中定义的确定显示内容的一个矩形区域,只有在这个区域内的图形才能在设备坐标系下输出,而窗口外的部分则被截掉。视区是在设备坐标中定义的一个区域,用于输出窗口中的图形。视区决定了窗口中的图形要显示于屏幕上的位置的大小。
1.2 需求环境
本课程设计需要的设备为硬件要求和软件配置要求具体要求如下: ①硬件要求:一台计算机。 ②软件配置:WINDOWS、C/VC++6.0。
1.3 功能描述
本课程设计是利用图形学的相关知识在TC或Visual C++环境下利用递归
3
攀枝花学院学生课程设计论文 需求分析
算法实现坦克大战的全过程,其基本的功能描述如下: ① 绘制若干坦克。
② 为坦克填充颜色,坦克的颜色代码为栈顶盘子代号加1。 ③ 通过鼠标或者键盘控制坦克移动和发射炮弹。
④ ⑤ ⑥ ⑦ 游戏有一个初始页面,如下图。
按下任意键开始游戏,玩家控制坦克在战场上穿梭,碰到墙时,不能通过。 敌方坦克自由移动,每隔2秒改变一个方向,每隔3秒发射一发子弹。
敌方坦克共有20辆,每隔5秒,从屏幕上方的左、中、右三个位置依次出现。 ⑧ 当玩家被消灭或者我方基地被摧毁时,游戏结束。
4
攀枝花学院学生课程设计论文 概要设计
2 概要设计
2.1 程序功能模块
由需求分析知,本次课程设计分为五大模块游戏开始模块、坦克的移动模块、坦克开炮和敌方坦克的构造模块、地图的加载和父类的创建模块,子弹链表和显示游戏信息模块。
坦克大战 游戏开始 坦克的移动 坦克开炮和敌方坦克的构造 图2.1 模块图
地图的加载和父类的创建 子弹链表和显示游戏信息
5
攀枝花学院学生课程设计论文 概要设计
2.2 程序流程图
图2.2 程序流程图
6
攀枝花学院学生课程设计论文 详细设计
3 详细设计
3.1 游戏开始
3.1.1代码功能
游戏开始
1、 设置游戏标题
2、 按空格键,提示图片消失,游戏进入开始状态. 3、 【实验运行结果】
图3.1 游戏开始前
图3.2 按下空格键后
7
攀枝花学院学生课程设计论文 详细设计
4、 【实验思路】
5、 按下空格键是键盘按下事件,可在CSystem::OnKeyDown函数中编写响应
代码。为了保证程序结构的清晰、一致,更好的办法是在CGameMain类中添加一个相应的键盘按下事件处理函数,然后在CSystem::OnMouseClick函数中进行调用。
6、 g_GameMain是CGameMain类的对象,它是全局变量,在程序运行时最先
被创建
3.1.2 功能实现代码
【游戏开始】
1、 C++程序的执行入口是主函数。FunCode的主函数名称叫WinMain,写在Main.cpp文件中。CSystem::SetWindowTitle是设置程序运行窗口标题的函数,修改如下:
CSystem::SetWindowTitle(\"坦克大战\");
2、 参考CSystem::OnKeyDown函数,为CGameMain类创建一个OnMouseClick函数。CGameMain类的头文件是LessonX.h文件,实现代码写在LessonX.cpp文件中。因此,先在LessonX.h文件对函数进行声明。函数的返回值和参数列表都与CSystem::OnKeyDown函数保持一致。访问权限应该是public。代码如下:
void OnKeyDown( const int iKey, const bool bAltPress, const bool bShiftPress, const bool bCtrlPress ); 3、 接着,在Lesson.cpp文件中对该函数进行定义:
void CGameMain::OnKeyDown( const int iKey, const bool bAltPress, const bool bShiftPress, const bool bCtrlPress ) { } 4、 在
CSystem::OnKeyDown
函数(Main.cpp
文件中)调用
CGameMain::OnKeyDown函数,并将自己的参数传递给该函数。g_GameMain是是CGameMain类的对象,它是全局变量,在程序运行时最先被创建。因此,我们可以用g_GameMain调用自己的成员函数OnKeyDown。 g_GameMain.OnKeyDown(iKey, bAltPress, bShiftPress, bCtrlPress); 5、 FunCode程序运行时,当发生键盘按下事件,程序首先调用并执行CSystem::OnKeyDown函数,然后由CSystem::OnKeyDown函数调用并执行
8
攀枝花学院学生课程设计论文 详细设计
CGameMain::OnKeyDown函数。因此,键盘按下事件的响应代码我们在CGameMain::OnKeyDown函数中编写即可。
6、 我们要处理的两个精灵如下图,它们的名称分别是splash和start。我们需要创建两个CSprite类对象与这两个精灵绑定。
图3.3 开始界面
7、 在CGameMain类中声明两个CSprite*类型的成员变量,根据面向对象的封装性原理,成员变量的访问权限应该是private。代码应该写在哪个文件,请参看前面的实验步骤。
CSprite* CSprite*
m_pSplash; m_pStart;
8、 在CGameMain类的构造函数中,对上面两个指针变量进行初始化。通过调用CSprite的构造函数,将精灵和精力对象绑定在一起。
m_pSplash = new CSprite(\"splash\"); m_pStart
= new CSprite(\"start\");
9、 最后,我们在CGameMain::OnKeyDown函数中处理空格键按下事件。
if(iKey == KEY_SPACE) { }
KEY_SPACE是枚举变量KeyCodes的成员,表示空格键。KeyCodes定义在CommonClass.h文件中。该枚举变量定义了全部的键盘值。调用CSprite类的SetSpriteVisible函数将精灵图片设置为不可见。注意:必须将m_iGameState的值改为1。当GameMainLoop函数再次执行时,根据m_iGameState的值调用并执行GameInit函数,游戏进入开始状态。
10、
在CGameMain类的析构函数中delete本实验创建的指针对象,以释放分配的内存。
m_pSplash->SetSpriteVisible(false); m_pStart->SetSpriteVisible(false); m_iGameState = 1;
9
攀枝花学院学生课程设计论文 详细设计
CGameMain::~CGameMain() { }
delete m_pSplash; delete m_pStart;
3.2 坦克的移动过程
3.2.1代码功能
1、 创建坦克类CTankPlayer;
2、 游戏开始时,将坦克放置于(0,0)的坐标上; 3、 通过按键WSAD控制坦克上下左右运动; 4、 坦克运行到黑色区域边界时不能继续前进。 5、 【运行结果】
图3.4 在区域内运动
10
攀枝花学院学生课程设计论文 详细设计
图3.5 运动到区域边界
【实验思路】
坦克也是精灵,但是它具备一些自己独特的功能,比如通过键盘控制运动、开炮等。因此我们可以创建一个新的类CTankPlayer类,并让它继承CSprite类。
通过WASD键,控制坦克做相应的的上左下右运动。按下某个键,给坦克设置相应方向的运动速度;松开时,将该方向的速度设为0,表示停止运动。
屏幕上最内部的黑色区域为玩家坦克的活动区域,左上角坐标为(-26,-22),右下角坐标为(26,22)。当坦克运动到该区域边界时,坦克不能继续前进。
3.2.2 功能实现代码
【坦克的移动】
1、 通过类向导创建CTankPlayer类,其继承于CSprite类。以VC++ 6.0
为例:
第一步、点击菜单“插入”-〉“新建类”。
图3.6 新建类
第二步、在“New Class”对话框中输入类名和父类名。
11
攀枝花学院学生课程设计论文 详细设计
图3.7 父名类
第三步、点击“Change”按钮,在新对话框中修改CTankPlayer类的头文件和cpp文件的路径。将头文件保存到项目文件夹的\\SourceCode\\Header文件夹中,将cpp文件保存到项目文件夹下的\\SourceCode\\Src文件夹中。
图3.8保存图
2、 为CTankPlayer类添加m_iDir,m_fSpeedX,m_fSpeedY三个成员变量(成员变量、成员函数的声明和定义如何添加,访问权限是什么,可参考实验一,下文不再继续提示),分别表示运动方向、X轴、Y轴速度。本文档的命名采用匈牙利命名法,m_表示类成员变量,i表示整型,f表示float型,sz表示字符指针,g_表示全局变量等。
3、 CTankPlayer的父类是CSprite类(具体声明查看CommonClass.h),构造函数为CSprite( const char *szName )。为CTankPlayer类添加构造函数:CTankPlayer(const char* szName)。
12
攀枝花学院学生课程设计论文 详细设计
CTankPlayer::CTankPlayer(const char* szName):CSprite(szName) { }
子类对象创建时,要先调用父类的构造函数完成父类部分的构造。如果父类没有默认构造函数,子类的构造函数必须显示调用父类的构造函数。CTankPlayer构造函数调用CSprite类构造函数,并将参数szName的值传递给它,从而将名称为szName的精灵图片与CTankPlayer对象绑定起来。
4、 为CTankPlayer类添加Init函数,该函数主要用来完成该类的初始化工
作。这里,先调用父类的SetSpritePosition函数将坦克精灵设置在屏幕中央(0,0)处。
void CTankPlayer::Init() { }
5、 在CGameMain类中增加一个私有成员变量m_pTankplayer,类型为
CTankPlaye*。在CGameMain类的构造函数创建m_pTankplayer对象。 CGameMain::CGameMain() { }
6、 按下空格键后,程序会调用键盘按下事件响应函数,将m_iGameState
的值改为1,游戏进入开始状态(见实验一)。程序再次执行CGameMain::GameMainLoop函数时,根据m_iGameState的值调用并执行CGameMain::GameInit函数。因此,可以在该函数中调用CTankPlayer::Init函数来完成该类对象的初始化工作。 void CGameMain::GameInit() { }
m_pTankPlayer->Init(); m_iGameState = 0;
m_pSplash = new CSprite(\"splash\"); m_pStart = new CSprite(\"start\");
m_pTankPlayer = new CTankPlayer(\"player\");
SetSpritePosition(0,0);
SetSpriteWorldLimit(WORLD_LIMIT_NULL, -26, -22, 26, 22);
13
攀枝花学院学生课程设计论文 详细设计
程序执行完CGameMain::GameInit函数后,执行CGameMain:: SetGameState(2),将m_iGameState的值改为2,游戏进入运行状态。 7、 编译并运行程序,然后按下空格键,看看运行效果。
8、 接下来,我们来实现用键盘操控坦克运动。首先定义两个成员变量
m_fSpeedX、m_fSpeedY和m_iDir,用来表示坦克在X轴和Y轴方向上的速度以及运行的方向,并且在构造函数中初始化为0。这里规定,m_iDir的值为0、1、2、3,分别表示上、右、下、左。
9、 为CTankPlayer类添加OnMove函数,参数iKey、bPress分别表示按下
的是哪个按键和按键是否按下。首先声明该函数,访问权限为public: void OnMove(int iKey, bool bPress); 10、
{
if(bPress)
{
switch (iKey) {
case KEY_W:
m_iDir = 0; m_fSpeedX = 0; m_fSpeedY = -8;
接着,完成OnMove方法。
void CTankPlayer::OnMove(int iKey, bool bPress)
break; case KEY_D:
m_iDir = 1; m_fSpeedX = 8; m_fSpeedY = 0;
break; case KEY_S:
m_iDir = 2; m_fSpeedX = 0; m_fSpeedY = 8;
break; case KEY_A:
m_iDir = 3;
14
攀枝花学院学生课程设计论文 详细设计
}
}
}
m_fSpeedX = -8; m_fSpeedY = 0; break;
SetSpriteRotation(90*m_iDir);
SetSpriteLinearVelocity(m_fSpeedX,m_fSpeedY);
else { }
if(iKey == KEY_W || iKey == KEY_D || iKey == KEY_S || iKey { }
m_fSpeedX = 0; m_fSpeedY = 0;
SetSpriteLinearVelocity(m_fSpeedX,m_fSpeedY);
== KEY_A)
用参数bPress来判断键盘是按下还是弹起。如果bPress为false,表示键盘弹起,且弹起的键是WASD键时,设置坦克的X轴和Y轴移动速度都为0。如果bPress为true,表示键盘按下,根据按下的键,为m_iDir,m_fSpeedX,m_fSpeedY赋予相应的值。SetSpriteRotation和SetSpriteLinearVelocity函数用来设置精灵的角度和线性速度,具体含义参考CommonClass.h文件。 11、
在CGameMain类的OnKeyDown函数中,通过调用CTankPlayer类的OnMove方法,根据按下的键,控制坦克朝指定方向运动。只有游戏进入开始状态,按键才有效。注意:OnMove参数bPress的值为true。 void CGameMain::OnKeyDown( const int iKey, const bool bAltPress, const bool bShiftPress, const bool bCtrlPress ) {
if(iKey == KEY_SPACE) {
m_pSplash->SetSpriteVisible(false); m_pStart->SetSpriteVisible(false);
15
攀枝花学院学生课程设计论文 详细设计
} 12、 13、
}
m_iGameState = 1;
if(m_iGameState == 2) { }
编译并运行程序。按空格键开始,按WASD键,坦克会向规定的方向参考CSystem::OnKeyUp函数,给CGameMain类声明并定义一个
m_pTankPlayer->OnMove(iKey, true);
运动。但是松开按键后,坦克继续前进,不会停止下来。
OnKeyUp函数,用来处理按键弹起事件,然后在CSystem::OnKeyUp函数中调用它。关于这个函数如何声明、定义以及调用参考实验一。 14、
在CGameMain::OnKeyUp函数中调用CTankPlayer的OnMove方法,参数bPress的值为false。
void CGameMain::OnKeyUp(const int iKey) { } 15、 16、
编译并运行程序,按下WASD键,坦克运行;松开按键,坦克停止。首先,在CTankPlayer::Init函数中给坦克精灵设置时间边界的大接下来,我们来实现坦克运行到黑色区域边界停止运动的效果。 小,与世界边界的碰撞模式为WORLD_LIMIT_NULL,表示精灵与世界边界碰撞的响应由代码完成。 void CTankPlayer::Init() { } 17、
参考CSystem::OnSpriteColWorldLimit函数,给CGameMain类声明并定义一个OnSpriteColWorldLimit函数,用来处理精灵与世界边界的碰撞事件,然后在CSystem:: OnSpriteColWorldLimit函数中调用它。
SetSpriteWorldLimit(WORLD_LIMIT_NULL, -26, -22, 26, 22); SetSpritePosition(0,0); if(m_iGameState == 2) {
m_pTankPlayer->OnMove(iKey, false); }
16
攀枝花学院学生课程设计论文 详细设计
关于这个函数如何声明、定义以及调用参考实验一。 18、
当坦克精灵碰到边界时,将精灵的速度都设为0,精灵停止运动。代码如下:
void CGameMain::OnSpriteColWorldLimit( const char *szName, const int iColSide ) { } 19、
在CGameMain类的析构函数中delete本实验创建的指针对象,以释放分配的内存。参考实验一。
m_pTankPlayer->SetSpriteLinearVelocity(0,0);
3.3 坦克开炮和敌方坦克的构造
3.3.1代码功能
坦克开炮
【实验内容】
1、 创建子弹类CBullet;
2、 通过按键J控制坦克开炮;
【实验运行结果】
图3.9 坦克开炮
【实验思路】
创建子弹类,该类应具备子弹的运动方向、起始位置、X轴速度、Y轴速度等属性,其中运动方向和起始位置由坦克的方向和位置决定。
通过按键控制坦克发射子弹,因此在CGameMain类的OnKeyDown方法中实现
17
攀枝花学院学生课程设计论文 详细设计
该需求。此时我们为CTankPlayer类添加发射子弹的方法OnFire。当按下J键后,坦克发射子弹,在OnFire方法中,我们需要告诉子弹的方向和初始位置。而创建子弹我们由CGameMain类来完成。这样减少了类之间的耦合。 敌方坦克 【实验内容】
1、 创建CTankEnemy类;
2、 实现坦克隔2秒,随机改变一个方向。 3、 实现坦克隔5秒发射一发子弹; 4、 当坦克与世界边界碰撞时,改变方向; 5、 创建一个敌方坦克实例。
【实验运行结果】
图3.10 敌方坦克开炮
【实验思路】
同我方坦克一样,敌方坦克运动,也需要有运动方向、X轴Y轴速度三个基本属性。为了实现坦克能自由运动,即坦克运动一段时间后改变方向,需增加一个改变方向的时间间隔。同时为了实现坦克自动发射子弹,需增加一个发射子弹的时间间隔。
然后为敌方坦克增加移动和发射子弹的方法。
最后我们在CGameMain类的GameRun方法中调用敌方坦克移动和发射子弹的方法。
18
攀枝花学院学生课程设计论文 详细设计
3.3.2功能实现代码
【坦克开炮】
1、 通过类向导创建CBullet类,其继承于CSprite类,具体做法参考实验一;
2、 为CBullet类添加m_iDir,m_fSpeedX,m_fSpeedY三个成员,分别表示方向、X轴、Y轴速度;
3、 为CTankPlayer类添加构造函数和析构函数。在构造函数,利用父类方法与指定名称的精灵联系起来。由于地图上只有一个子弹模板,所以我们需要先复制这个模板,然后设置该精灵的世界边界。
4、 为CBullet类添加OnMove方法,参数为iDir表示子弹的运动方向。
5、 完成OnMove方法。根据方向m_iDir,首先设置m_fSpeedX,m_fSpeedY的值,然后设置根据方向设置旋转角度,最后设置子弹的运动速度。
void CBullet::OnMove(int iDir) {
m_iDir = iDir; switch(m_iDir) { case 0:
m_fSpeedX = 0; m_fSpeedY = -10; break;
m_fSpeedX = 10; m_fSpeedY = 0; break; m_fSpeedX = 0; m_fSpeedY = 10; break;
m_fSpeedX = -10;
case 1:
case 2:
case 3:
19
攀枝花学院学生课程设计论文 详细设计
}
}
m_fSpeedY = 0; break;
SetSpriteRotation(90*m_iDir);
SetSpriteLinearVelocity(m_fSpeedX,m_fSpeedY);
6、 在CGameMain类中添加表示子弹数目的变量m_iBulletNum。然后添加AddBullet方法。方法中有iDir、fPosX、fPosY三个参数分别表示子弹方向、子弹初始位置的X轴Y轴坐标。
void CGameMain::AddBullet( int iDir,float fPosX,float fPosY ) {
char*
CBullet bullet(szName); bullet.CloneSprite(\"bullet\");
szName
=
CSystem::MakeSpriteName(\"bullet\
bullet.SetSpriteWorldLimit(WORLD_LIMIT_KILL,GetWorldLeft(),
GetWorldTop(),GetWorldRight(), GetWorldBottom());
}
7、 为CTankPlayer类增加OnFire方法,实现发射子弹的功能。在根据坦克的运动状态,得到子弹的相关属性后,通过AddBullet方法在游戏中增加一发子弹。
void CTankPlayer::OnFire() {
float x,y;
x = GetSpritePositionX(); y = GetSpritePositionY(); switch(m_iDir) { case 0:
bullet.SetSpritePosition(fPosX,fPosY); bullet.OnMove(iDir); m_iBulletNum++;
20
攀枝花学院学生课程设计论文 详细设计
}
}
y=y-GetSpriteHeight()/2-1; break;
x=x+GetSpriteWidth()/2+1; break;
y=y+GetSpriteHeight()/2+1; break;
x=x-GetSpriteWidth()/2-1; break;
case 1:
case 2:
case 3:
g_GameMain.AddBullet(m_iDir,x,y);
【敌方坦克】
1、 通过类向导创建CTankEnemy类;
2、 为类CTankEnemy添加m_iDir,m_fSpeedX,m_fSpeedY三个成员,分别表示方向、X轴、Y轴速度;
3、 参照前面的实验,为CTankEnemy类添加构造函数和析构函数。 4、 为类CTankEnemy添加OnMove方法,实现随机改变方向,设置坦克运动。
5、 完成OnMove方法。根据方向m_iDir,首先设置m_fSpeedX,m_fSpeedY的值,然后设置根据方向设置旋转角度,最后设置子弹的运动速度。与CTankPlayer类的OnMove方法类似,只是方向的设置是随机的。
m_iDir = CSystem::RandomRange(0,3);
6、 为类CTankEnemy添加OnMove方法,参数fDeltaTime,为游戏的时间差,实现隔一段时间随机改变方向。
void CTankEnemy::OnMove(float fDeltaTime) {
m_fChangeDirTime+=fDeltaTime; if(m_fChangeDirTime>2.0f) {
21
攀枝花学院学生课程设计论文 详细设计
}
}
OnMove();
7、 为类CTankEnemy添加OnFire方法,参数也为fDeltaTime,实现隔一段时间自动发射子弹。
void CTankEnemy::OnFire(float fDeltaTime) { }
}
x = GetSpritePositionX(); y = GetSpritePositionY(); switch(m_iDir) { case 0: }
g_GameMain.AddBullet(m_iDir,x,y);
y=y-GetSpriteHeight()/2-1; break;
x=x+GetSpriteWidth()/2+1; break;
y=y+GetSpriteHeight()/2+1; break;
x=x-GetSpriteWidth()/2-1; break;
m_fBulletCreateTime+=fDeltaTime; if(m_fBulletCreateTime>3.0f) {
float x,y;
m_fBulletCreateTime = 0.0f;
case 1:
case 2:
case 3:
22
攀枝花学院学生课程设计论文 详细设计
8、 在CGameMain类中添加CTankEnemy类指针变量m_pTankEnemy,然后在GameInti中初始化,并将敌方坦克设置在(10,0)的位置。
m_pTankEnemy = new CTankEnemy(\"enemy\"); 子弹。
void CGameMain::GameRun( float fDeltaTime ) { } 10、
在CGameMain类的OnSpriteColWorldLimit方法中添加敌方
坦克与世界边界碰撞的检测。
if(m_pTankEnemy&&strcmp(m_pTankEnemy->GetName(),szName)==0)
m_pTankEnemy->SetSpritePosition(10,0);
9、 在CGameMain类的GameRun方法中实现敌方坦克自由移动和发射
if(m_pTankEnemy) { }
m_pTankEnemy->OnMove(fDeltaTime); m_pTankEnemy->OnFire(fDeltaTime);
{ }
m_pTankEnemy->OnMove();
3.4地图的加载和创建父类-CWeapon类
3.4.1代码功能
加载地图
【实验内容】
1、 加载游戏开始页面,并按任意键开始游戏; 2、 加载游戏地图;
3、 当子弹与游戏中的任何东西碰撞时,双方都消失; 4、 当我方坦克与敌方坦克碰撞时,我方坦克静止不动,敌方坦克改变方向; 5、 当我方坦克被消灭或者我方军营被击中时,游戏结束。
23
攀枝花学院学生课程设计论文 详细设计
【实验运行结果】
图3.11 加载地图
【实验思路】
在CGameMain类OnKeyDown方法中控制游戏开始。 在CGameMain类中添加方法LoadMap实现地图加载。地图数据是已知的,数据中的0表示此处为空;1表示的是地图中此处为墙;2表示此处为玩家指挥部。每块墙大小为4*4。
声明一个CTankEnemy类数组对象。
在OnSpriteColSprite方法中添加碰撞检测。
在OnSpriteColWorldLimit中添加与世界边界的碰撞检测。
创建父类-CWeapon类
【实验内容】
1、 添加CWeapon类,使CBullet、CTankPlayer、CTankEnemy类继承与
CWeapon类;
2、 将三个子类OnFire和OnMove方法中相同的功能抽取出来,在父类中创
建相应方法。子类调用父类方法进行改进。 3、 添加三辆敌方坦克;
【实验运行结果】
24
攀枝花学院学生课程设计论文 详细设计
图3.12 创建坦克
【实验思路】
CBullet、CTankPlayer、CTankEnemy类中有许多共同的属性和方法,因此我们添加父类CWeapon。
3.4.2 功能实现代码
【加载地图】
1、 在CGameMain类中添加一个表示游戏开始的变量; bool m_bStart;
2、 在CGameMain类OnKeyDown方法中控制游戏开始。 if( 0 ==GetGameState() )
}
CSprite sprite2(\"start\"); sprite2.SetSpriteVisible(false); {
m_bStart = true; SetGameState(1);
CSprite sprite1(\"splash\"); sprite1.SetSpriteVisible(false);
3、 在CGameMain类中添加LoadMap方法,实现加载地图。在方法中
25
攀枝花学院学生课程设计论文 详细设计
用for循环遍历地图二维数组,当二维数组中的某个值为1时表示该处是一堵墙。
void CGameMain::LoadMap() { }
4、 在OnSpriteColSprite中添加碰撞检测。进行的检测顺序是,首先判断发送碰撞方为谁,然后在判断接受碰撞方为谁。
void CGameMain::OnSpriteColSprite( const char *szSrcName, const char *szTarName )
{
// 如果子弹
for(i=0;i<11;i++) { }
for(j=0;j<13;j++) { }
}
x = -24+4*j; y = -20+4*i;
cWall.SetSpritePosition(x,y); if(g_iMap[i][j]==1) {
szName
CSprite cWall(szName); cWall.CloneSprite(\"wall\");
cWall.SetSpriteCollisionActive(0,1);
=
char* szName; int i,j; float x,y;
CSystem::MakeSpriteName(\"wall\
cWall.SetSpriteCollisionResponse(COL_RESPONSE_CUSTOM);
26
攀枝花学院学生课程设计论文 详细设计
0)
if(memcmp(szSrcName,\"bullet\{
//击中军营
if(strcmp(szTarName,\"aim_nor\")==0) { } //碰上墙
if(memcmp(szTarName,\"wall\{ }
//碰上敌方坦克 else { } else
CBullet bullet(szSrcName); bullet.DeleteSprite(); m_pTankEnemy->DeleteSprite(); delete m_pTankEnemy; m_pTankEnemy = NULL; CBullet bullet(szSrcName); bullet.DeleteSprite();
CSprite cWall(szTarName); cWall.DeleteSprite(); m_bStart = false;
if(m_pTankEnemy&&strcmp(szTarName,m_pTankEnemy->GetName())==0)
if(m_pTankPlayer&&strcmp(szTarName,m_pTankPlayer->GetName())==
{
CBullet bullet(szSrcName); bullet.DeleteSprite();
27
攀枝花学院学生课程设计论文 详细设计
}
}
m_pTankPlayer->DeleteSprite(); delete m_pTankPlayer; m_pTankPlayer = NULL;
m_bStart = false;
else
if(m_pTankPlayer&&strcmp(szSrcName,m_pTankPlayer->GetName())==0) //我方坦克
if(m_pTankEnemy&&strcmp(szTarName,m_pTankEnemy->GetName())==0) //敌人
}
else if(memcmp(szTarName,\"wall\
strcmp(szTarName,\"aim_nor\")==0) {
m_pTankPlayer->SetSpriteLinearVelocity(0,0); m_bStart = false;
CBullet bullet(szTarName); bullet.DeleteSprite();
{ } else {
m_pTankPlayer->DeleteSprite(); delete m_pTankPlayer; m_pTankPlayer = NULL;
m_pTankPlayer->SetSpriteLinearVelocity(0,0); m_pTankEnemy->OnMove();
{
if(memcmp(szTarName,\"bullet\子弹
28
攀枝花学院学生课程设计论文 详细设计
}
}
else
if(m_pTankEnemy&&strcmp(szSrcName,m_pTankEnemy->GetName())==0) //敌方坦克
if(m_pTankPlayer&&strcmp(szTarName,m_pTankPlayer->GetName())==0) //我方
}
5、 在OnSpriteColWorldLimit中添加敌方坦克与世界边界的碰撞检测。当敌方坦克与世界边界碰撞时,敌方坦克改变方向。
void CGameMain::OnSpriteColWorldLimit( const char *szName ) {
}
{ } else { }
else if(memcmp(szTarName,\"wall\
strcmp(szTarName,\"aim_nor\")==0) { }
m_pTankEnemy->OnMove(); m_pTankEnemy->DeleteSprite(); delete m_pTankEnemy; m_pTankEnemy = NULL;
CBullet bullet(szTarName); bullet.DeleteSprite();
m_pTankPlayer->SetSpriteLinearVelocity(0,0); m_pTankEnemy->OnMove();
{
if(memcmp(szTarName,\"bullet\子弹
29
攀枝花学院学生课程设计论文 详细设计
if(m_pTankEnemy&&strcmp(m_pTankEnemy->GetName(),szName)==0)
}
【创建父类】
1、 通过类向导添加CWeapon类,其继承于CSprite类。
2、 根据分析为CWeapon类添加表示方向、X轴Y轴速度三个变量。 int m_iDir; float m_fSpeedX; float m_fSpeedY;
3、 添加虚函数OnMove和OnFire方法: // fSpeedX和fSpeedY是精灵速度的绝对值
virtual void OnMove(int iDir, float fSpeedX, float fSpeedY); virtual void OnFire();
4、 将CBullet、CTankPlayer、CTankEnemy类的父类改为CWeapon。 5、 在CGameMain类中修改关于m_pTankPlayer和m_pTankEnemy的声明。
CTankPlayer* m_pTankPlayer; CTankEnemy*
m_pTankEnemy[3];
{ }
m_pTankEnemy->OnMove();
3.5 子弹链表和显示游戏信息
3.5.1代码功能
实验六 子弹链表 【实验内容】
1、 添加一个子弹链表结构体。 2、 添加子弹链表类CBulletList。
3、 只有当被对方的子弹击中时,坦克才消失。
30
攀枝花学院学生课程设计论文 详细设计
【实验运行结果】
图3.13 子弹发射
【实验思路】
为子弹增加一个表示是谁发射的属性,定义0表示我方,1表示敌方。 将子弹放入子弹链表中,当子弹与坦克碰撞时,首先根据子弹名称从链表从取出子弹的指针,然后或者该子弹是谁发射的属性,在判断碰撞结果。 显示游戏信息 【实验内容】
1、 记录游戏的分数,当分数高于上次的得分时,将此次得分写入文件。 2、 显示游戏的得分等信息。
【实验运行结果】
31
攀枝花学院学生课程设计论文 详细设计
图3.14 显示游戏信息
【实验思路】
在CGameMain类的GameInit方法中,读取游戏的最高分。在游戏结束GameEnd方法中,记录游戏的最高分。
在OnSpriteColSprite碰撞检测中,每消灭一辆地方坦克加5分,同时敌方坦克数量减1。
3.5.2 功能实现代码
【子弹链表】
1、 通过类向导生成子弹链表类CBulletList。 2、 定义一个子弹链表的节点。 struct BulletStruct { };
3、 为CBulletList添加链表头节点和表示链表节点数的变量。 BulletStruct int
*m_pListHeader; m_iListSize;
CBullet
*pBullet;
BulletStruct *pPre; BulletStruct *pNext;
4、 为CBulletList添加增加子弹的方法,参数为子弹的指针。并实
32
攀枝花学院学生课程设计论文 详细设计
现该方法。
void CBulletList::AddSprite(CBullet *pSprite) { }
5、 添加GetSprite方法,实现通过名称获得子弹指针。 CBullet* CBulletList::GetSprite( const char *szName ) { 0 )
return pPtr->pBullet; pPtr = pPtr->pNext;
BulletStruct *pPtr = m_pListHeader; while( NULL != pPtr ) {
if(strcmp( pPtr->pBullet->GetName(), szName ) ==
if( NULL == pSprite ) //
pFish->pBullet pFish->pPre // 插入链表中
if( NULL == m_pListHeader ) { }
m_iListSize++;
BulletStruct *pTemp = m_pListHeader; while( NULL != pTemp->pNext )
pFish->pPre
= pTemp;
pTemp->pNext = pFish;
pTemp = pTemp->pNext; m_pListHeader = pFish; else
= pSprite;
pFish->pNext = NULL;
= NULL;
return;
BulletStruct *pFish = new BulletStruct;
33
攀枝花学院学生课程设计论文 详细设计
}
}
return NULL;
6、 添加DeleteSprite方法,实现根据名称删除链表中的某个节点。 void CBulletList::DeleteSprite( const char *szName ) {
BulletStruct *pFish = NULL;
for( pFish = m_pListHeader; NULL != pFish; pFish pFish->pNext )
{ } }
7、 修改OnSpriteColSprite方法中的代码。当碰撞方或者接受方是
if( strcmp( szName, pFish->pBullet->GetName() ) == 0 ) { }
if( NULL != pFish->pNext ) { } //
if( NULL != pFish->pPre ) { }
if( pFish == m_pListHeader ) { }
pFish->pBullet->DeleteSprite(); delete pFish; return;
m_pListHeader = m_pListHeader->pNext; pFish->pPre->pNext
= pFish->pNext;
pFish->pNext->pPre
= pFish->pPre;
=
34
攀枝花学院学生课程设计论文 详细设计
子弹时,首先从子弹链表中或者子弹的指针,然后获得子弹是哪方发生的。如果是己方发生的,则不进行处理。
【显示游戏信息】
1、 在GameInit方法中打开记录文件,如果文件不存在则创建该文件,如果存在,则 读取数据。并显示在游戏中。
FILE * fp =fopen(\"save.dat\if(fp)
{
fread(&m_iHight,sizeof(int),1,fp); fclose(fp); }
m_pHightText = new CTextSprite(\"hight\"); m_pHightText->SetTextValue(m_iHight);
2、 在GameEnd方法中,当游戏的得分大于最高分时,将游戏的得分写入文件中。
FILE * fp =fopen(\"save.dat\if(m_iScore>m_iHight)
fwrite(&m_iScore,sizeof(int),1,fp);
fclose(fp);
在OnSpriteColSprite函数中,我方子弹与坦克的碰出添加如下
3、 代码。
m_iScore+=5;
m_pScoreText->SetTextValue(m_iScore); m_iEnemy --;
m_pEnemyText->SetTextValue(m_iEnemy);
35
攀枝花学院学生课程设计论文 测试与运行
4 测试与运行
测试运行结果如下:
图4.1 进入游戏时的画面:
图4.1 盘块移动前 图4.2 游戏进行时:
36 攀枝花学院学生课程设计论文 结束语
结束语
在这次课程设计中,我基本上完成了任务,通过每个模块的实现,基本上达到了此次课程设计的要求。但是它的不足也是显而易见的,在坦克移动的过程中用方向键移动时只有上下左右没有弧度转弯,这给玩家带来视觉上的不足,所以这是值得改进的地方,整个程序的功能有待进一步完善,让更多的方法能得以实现。
虽然在这次的课程设计中有很多的不足,但是我也有很多的收获。上网查找资料,找到了一个关于坦克大战设计的毕业论文,于是我也借鉴了他的程序代码设计理念,如何构造坦克,如何实现坦克的移动。再运用这些知识在TC中实现这次课程设计所要完成的任务。这让我不仅对TC开发环境有了更多的认识和了解,对其图形设备接口的知识也有了很好的掌握,而且让我对图形学的知识有了更好的运用,拓展了对图形学的知识了解的视野,让我的理论知识和算法有了更多的实践。作为一个大的项目,我更体会到了团队合作精神的重要性,虽然我的设计是一个人一组的,但我深刻地认识到只有大家一起努力地学习并研究相关的知识,才能提高做事的效率,也才能更好更快地完成任务。所以这将在我以后的学习和生活中有很在的引导作用。在以后的学习中,我也将加倍地学习图形学的有关知识,以同样的方法学习其他的知识,不断地丰富自己,充实自己,提高自己的能力。
37
攀枝花学院学生课程设计论文 参考文献
参考文献
[1] [美]Watts S Humphrey。软件工程规范[M].苏俊,许青松译.清华大学出版社,2008. [2] [美]Mc.Connell,代码大全(第二版).电子工业出版社[M],2006.3 [3] 刘志峰.软件技术与是件[M].电子工业出版社.2008
[4] 柳朝阳,周晓平.计算机图形学:图形的计算与显示原理. 西安电子科技大学出版
社 .2005
[5] 肖永亮,Visual C++游戏编程基础[M],电子工业出版社,2005.5 [6] 陈锦昌,赵明秀.C语言计算机绘图教程.华南理工大学出版社.1998.9 [7] 杨昂岳.微机实用绘图方法与技巧.国防科技大学出版社.1995.12
因篇幅问题不能全部显示,请点此查看更多更全内容