logo资料库

10 C语言课程设计_太空战机.doc

第1页 / 共26页
第2页 / 共26页
第3页 / 共26页
第4页 / 共26页
第5页 / 共26页
第6页 / 共26页
第7页 / 共26页
第8页 / 共26页
资料共26页,剩余部分请下载后查看
课程设计三 太空战机
一、游戏介绍
二、实验目的
三、实验内容
四、实验指南
实验二 游戏需要的实物及分析
实验三 对游戏中的精灵进行链表管理
实验四 游戏开始和控制我方战机移动
实验五 添加子弹类,实现战机开炮
实验六 敌方战机
实验七 添加碰撞检测
实验六 读写游戏记录
课程设计三 太空战机 一、游戏介绍 太空战机是玩家用键盘控制战机移动并发射子弹,消灭敌方的战机。敌方战机从右到左 移动,同时上下浮动。同时隔一定的时间发射子弹,我方战机在受到敌方战机子弹攻击时, 战机的颜色会发生变化,生命值也在减少,当我方战机的生命值减少到 0 时,我方战机消失, 同时产生一架我方的新的战机,游戏重新开始。 二、实验目的 综合应用 C 语言的知识开发一款小游戏。 三、实验内容 在外星球上,玩家通过键盘 WSAD 键控制己方战机,消灭外星球的邪恶战机。 要求如下: 1、 游戏运行时,初始界面如下图。 2、 按下空格键,游戏开始,玩家通过 WSAD 键控制己方战机移动;己方战机不能超出 世界边界。 3、 玩家战机每隔 0.3 秒发射一发子弹; 4、 添加敌方战机,每隔 2 秒创建一架敌方战机; 5、 敌方战机每隔 0.3 秒发射一发子弹; 6、 记录游戏的最高分。 游戏初始界面
上海锐格软件有限公司 四、实验指南 实验一 游戏框架的搭建 【实验内容】 1、由于本实验比较复杂,所以我们使用多文件实现 2、添加文件 3、搭建游戏平台 4、还没有用到的函数可以先声明,在定义,函数体为空 【实验思路】 为了让游戏的代码更加清晰,我们使用多文件,一般的代码编写都是一个源程序文件对 应一个头文件,所以我们增加一个源文件程序,一个头文件程序。在本实验中,主程序 Main.cpp 主要是来显示游戏的大体框架,我们将在 LessonX.cpp 中去具体实现不同的函数, 由主程序调用。 【实验指导】 1、 导入模板“AirPlane”,将太空战机的地图初始化; 2、 由于我们这个游戏稍稍有些复杂,所以我们采用多文件的形式,那么我们先添加一 个 LessonX.cpp 和 LessonX.h 文件: 首先在 VC6.0 当中,点击新建按钮,如图红色区域 然后会出现一个空白文件,然后再空白文件中点击一下,选中空白文件,使用快捷 方式 Ctrl+s,或者使用 File 菜单栏下的 Save 选项,如下图 这样会弹出一个对话框,如下图 之后点击红色区域,返回到上一个目录: 1
选中 Src 目录,双击进入 Src 并将 Text2.txt 命名为 LessonX.cpp 点击保存即可。 同样的方式建立 LessonX.h 文件,在保存的时候放在 Hearder 目录下,并将**.txt 文 件更名为 LessonX.h; 3、 下面我们将新建的两个文件添加到我们的工程当中, 首先在 VC 中右击 Source Files,并且选中 Add Files to Folder 选项,如下图 然后弹出对话框,如下图 点击返回上一目录,得到如下对话框 双击 Src 进入到目录里面,选中 LessonX.cpp 文件,点击 OK 即可; 4、 添加 LessonX.h 文件的步骤,右击 Header Files,然后找到 Header 文件夹,双击进 入并选中 LessonX.h 文件,左击 OK 即可; 5、 我 们 来 搭 建 游 戏 的 框 架 , 我 们 在 主 函 数 中 的 while 循 环 的 最 后 添 加 一 个 函 数 GameMainLoop(fDeltaTime)的调用,该函数是游戏的中心部分,游戏就是通过它不 断的刷新数据; 6、 现在我们在 LessonX.cpp 中来实现这个 GameMainLoop 函数,游戏主循环,此函数 2
将被不停的调用,引擎每刷新一次屏幕,此函数即被调用一次用以处理游戏的开始、 进行中、结束等各种状态. 函数参数 fDeltaTime : 上次调用本函数到此次调用本函 数的时间间隔,单位:秒 上海锐格软件有限公司 fDeltaTime ) void GameMainLoop( float { switch( g_iGameState ) { // 初始化游戏,清空上一局相关数据 case 1: { g_iGameState = 2; // 初始化之后,将游戏状态设置为进行中 GameInit(); } break; // 游戏进行中,处理各种游戏逻辑 case 2: { // 判断输赢 if( true) { //游戏结束。调用游戏结算函数,并把游戏状态修改为结束状态 g_iGameState = 0; GameEnd(); } else // 游戏未结束,继续游戏 { GameRun( fDeltaTime ); } } break; // 游戏结束/等待按空格键开始 case 0: default: break; }; } 7、 以上游戏框架中 GameInit、GameRun、GameEnd 函数我们还没有定义,那么我们就 在 LessonX.cpp 中定义这三个函数; // 注意<>和“”的区别 #include #include “LessonX.h” // 游戏状态的定义 g_iGameState = 0; // 函数声明 void GameInit(); 3
void GameRun(float); void GameEnd(); // 函数定义 Void GameInit() { } Void GameRun(float fDeltaTime) { } Void GameEnd() { } 这样我们的游戏框架就搭建好了,编译一下就可以运行了,虽然有什么效果。 实验二 游戏需要的实物及分析 【实验内容】 1、分析游戏中需要的对实物 2、分析这些实物需要的变量 3、这些变量进行初始化 【实验思路】 对于本游戏,我们至少需要以下几个实物,我方战机、敌方战机、我方战机发射的子弹、 敌方战机发射的子弹、当前分数、最高分数等,关于战机我们还需要考虑到生命值、发射子 弹的时间、敌机上下浮动等变量,关于子弹我们需要考虑子弹的生命值、对敌方或者是我方 的伤害值、是由谁发射的等问题。 【实验指导】 1、为了便于对战机和子弹的管理,我们使用结构体来将战机和子弹的变量存放在一起。 战机和子弹的管理我们都放在链表中进行管理, 我们首先增加 ListX.cpp 和 List.h 这两 个文件,并且将这两个文件添加到工程当中; 2、在 LessonX.h 中添加防止头文件包含的语句: #ifndef _LESSONX_H_ #define _LESSONX_H_ ... ... #endif 我们将代码写入到#define 和#endif 的中间 //_LESSONX_H_ 3、然后我们加入头文件#include “CommonAPI.h” 4、接着我们用宏定义定义一些极限值 #define MAX_NAME_LEN 128 // 名字的最大长度 #define CONTROL_MAX_HP 1000 #define BULLET_DAMAGE_1 100 #define VER_MIN_CREATE #define VER_MAX_CREATE 1 6 // 我方战机的最大生命值是 1000 // 子弹 1 的伤害值是 100 5、之后我们用枚举类型列出本游戏需要用的三种类型: enum ESpriteType { 4
SPRITE_CONTROL, SPRITE_VER, SPRITE_BULLET1 // 我们控制的战机 // 敌方战机 // 朝前方发射的子弹,且可以被销毁 上海锐格软件有限公司 }; 6、再接下来就是我们的结构体了 struct SGameSprite { char szName[MAX_NAME_LEN]; int iHp; int iScore; int iDamage; ESpriteType eSpriteType; int iBulletType; float fFireAffterCreate; float fBulletTime; float fFloatTime; bool bFloatUp; // 精灵的名字 // Health Point 生命值 // 击毁本精灵可以获得的分数值 // 自身碰到敌方可以给敌方造成的伤害 // 精灵的类型 // 该子弹类型,通过该类型判断是不是受到伤害 // 精灵被创建多长时间可以发射子弹 // 子弹 1 被发射的时间间隔 // 上下浮动的时间 // 是否上下浮动 }; 这样我们的 LessonX.h 文件就已经初始化好了,接下来使用就比较方便了; 实验三 对游戏中的精灵进行链表管理 【实验内容】 1、精灵是个体,将这些个体联系在一起便于管理 2、我们要根据链表由名字获得精灵,遍历精灵链表,添加精灵到链表,根据名字删除 链表,删除所有精灵 【实验思路】 如果通过个体去处理问题,在不断有其他精灵创建的前提下,是相当麻烦的,比如战机 撞到世界边界的问题,如果不用链表遍历操作的话,通过 if-else 判断是无法想象的工作量, 其实也是无法完成的,因为你不知道到底会有多少架战机被创造出来,所以为了便于对这些 个体进行管理和操作,我们有必要为这些精灵个体建立一个链表,这样对于精灵的遍历、插 入、删除等操作就非常遍历了。 【实验指导】 //__LISTX_H_ 1、在 List.h 文件中,首先要防止头文件重复包含: #ifndef _LISTX_H_ #define _LISTX_H_ ... ... #endif 以后所有代码都写在#define 和#endif 之间; 2、接着要将头文件包含进来 #include #include “CommonAPI.h” #include “LessonX.h” 3、建立一个结构体的结构体 5
SpriteStruct struct { SGameSprite SpriteStruct SpriteStruct *pSprite; *pNext; *pPrev; GList_GetListSize(); *GList_GetSpriteByIndex( const int iIndex ); *GList_GetSpriteByName( const char *szName ); }; 4、之后就是声明一下操作链表的函数,具体用到的函数如下 extern int // 根据名字获取 Sprite extern SGameSprite // 根据索引获取 Sprite,如果要遍历链表并删除其中的某个元素,请从后面往前面遍历 (即索引初始化为链表大小然后递减),否则必然出错 extern SGameSprite // 添加一个 Sprite 到链表里 extern SpriteStruct *GList_AddSprite( SGameSprite *pSprite ); // 根据名字删除 Sprite. bDeleteImage : 是否删除该 Sprite 在地图上的图片显示 extern void GList_DeleteSprite( const char *szName, bool bDeleteImage = true ); // 根据指针删除 Sprite. bDeleteImage : 是否删除该 Sprite 在地图上的图片显示 extern void GList_DeleteSprite( SGameSprite *pSprite, bool bDeleteImage = true ); // 删除所有 Sprite. bDeleteImage : 是否删除该 Sprite 在地图上的图片显示 extern void 5、有了上面的函数声明,我们在 ListX.cpp 中给出函数的实现,在函数实现中都有注释, 我们就不在做详解,并且这部分比较难,同学可以直接抄在文件当中,之后做一下分析 就可以了 SpriteStruct int g_iListSize = 0; // 链表元素个数 ///////////////////////////////////////////////////////////////////////////////// int GList_GetListSize() { GList_DeleteAllSprite( bool bDeleteImage = true ); *g_pListHeader = NULL; return g_iListSize; } //========================================================================= // 根据名字获取 Sprite SGameSprite* GList_GetSpriteByName( const char *szName ) { SpriteStruct *pPtr while( NULL != pPtr ) { = g_pListHeader; if( strcmp( pPtr->pSprite->szName, szName ) == 0 ) return pPtr->pSprite; pPtr = pPtr->pNext; } return NULL; 6
上海锐格软件有限公司 } //========================================================================= // 任务:根据索引获取 Sprite // 提示:参考“根据名字获取 Sprite” // 提示:如果要遍历链表并删除其中的某个元素,请从后面往前面遍历(即索引初始化 为链表大小然后递减),否则必然出错 SGameSprite *GList_GetSpriteByIndex( const int iIndex ) { // 通过循环从链表头开始查找,当循环次数达到 iIndex 次时,得到该索引对应的元素 0; = iLoop int SpriteStruct *pPtr while( NULL != pPtr ) { = g_pListHeader; if( iLoop == iIndex ) return pPtr->pSprite; iLoop++; pPtr = } return NULL; pPtr->pNext; } //========================================================================= // 添加一个 Sprite 到链表里 SpriteStruct *GList_AddSprite( SGameSprite *pSprite ) { if( NULL == pSprite ) return NULL; = (SpriteStruct*)malloc( sizeof(SpriteStruct) ); *pPtr SpriteStruct pPtr->pSprite = pPtr->pNext pPtr->pPrev // 插入链表表尾 if( NULL == g_pListHeader ) pSprite; = = NULL; NULL; g_pListHeader = pPtr; else { SpriteStruct while( NULL != pTemp->pNext ) *pTemp = g_pListHeader; pTemp = pTemp->pNext; pPtr->pPrev pTemp->pNext= = pPtr; pTemp; } g_iListSize++; 7
分享到:
收藏