《坦克大战》游戏整体设计及框架
1.游戏功能描述
按下空格键后游戏开始,“空格开始”消失,载入地图,并把玩家坦克设置在指挥部左侧。
在游戏进入之前,可选单人对战or双人对战。
在游戏进入之前,可选地图1 or 2 or 3。
游戏时间到,比如30秒,玩家坦克被敌方坦克摧毁,或者玩家指挥部被摧毁,一局游戏结束,游戏回到初始界面,并显示上一局的分数。
游戏区域为下图中最内部的黑色区域,左上角坐标[-26, -22],右下角坐标为[26, 22]。墙为正方形,边长为4,坦克也是正方形,比墙略小一点。
玩家用WASD键控制坦克上、下、左、右运行,按J键开炮。玩家坦克碰到墙就停下来,需要调转方向才能继续前进。玩家坦克开炮,一炮就能摧毁一块墙,或者一辆敌方坦克。玩家没摧毁一辆敌方坦克,加1分。
玩家指挥部被坦克或者炮弹(不管玩家还是敌方)碰上,都会被摧毁。
每隔几秒钟,比如3秒,就会产生一辆敌方坦克。敌方坦克每隔一段时间,比如1秒,就自动开炮。敌方坦克遇到墙就会停下来。停下来的坦克,前方的墙如果被摧毁了,又能继续前进。每隔几秒钟,比如2秒,敌方坦克就会顺时针变换一个方向前进。
在开炮时,有开炮声音。
每隔12s出现一个BUFF,当玩家坦克吃到BUFF的时候,实现敌方坦克全屏清除,得分加10。若在BUFF出现后8s内玩家坦克没有吃到,则BUFF自动消失。
游戏进行中时,P键暂停游戏,O键继续游戏。
2. 游戏流程图
3. 详细设计
主函数模块main()函数模块
主要功能为启动游戏引擎,刷新时间循环,进入游戏主循环,关闭游戏引擎。
List.cpp文件,游戏主循环
- 游戏主循环:
-
// 游戏主循环,此函数将被不停的调用,引擎每刷新一次屏幕,此函数即被调用一次 // 用以处理游戏的开始、进行中、结束等各种状态. // 函数参数fDeltaTime : 上次调用本函数到此次调用本函数的时间间隔,单位:秒 void GameMainLoop( float fDeltaTime ) { dSetWindowTitle("TANKWAR"); // 设置游戏窗口标题 float fTimeDelta = dGetTimeDelta(); switch( g_iGameState ) { // 初始化游戏,清空上一局相关数据 case 1: { GameInit(); g_iGameState = 2; // 初始化之后,将游戏状态设置为进行中 } break; // 游戏进行中,处理各种游戏逻辑 case 2: { // TODO 修改此处游戏循环条件,完成正确游戏逻辑********************* if(g_bStart) { GameRun( fDeltaTime ); } else { // 游戏结束。调用游戏结算函数,并把游戏状态修改为结束状态 g_iGameState = 0; GameEnd(); } } break; // 游戏结束/等待按空格键开始 case 0: default: break; } }
- 游戏开始前初始化
-
// 每局开始前进行初始化,清空上一局相关数据 void GameInit() { CreatePlayer(); CreateSecondPlayer(); Loadmap(); }
- 游戏进行中
-
// 每局游戏进行中 void GameRun( float fDeltaTime ) { if(pause) { g_fGameTime += fDeltaTime; dSetTextValue("time", (int)g_fGameTime); g_BuffTime+=fDeltaTime; if(g_BuffTime>12.f)//12秒出现一个buff { dCloneSprite("boomtime","boomtime0"); dSetSpritePosition("boomtime0",dRandomRange(-25,25),dRandomRange(-21,21)); dSetSpriteCollisionReceive("boomtime0", true); g_BuffTime=0; } if(g_BuffTime>8.f) dDeleteSprite("boomtime0"); // 时间到,生成新一批敌方坦克 g_fCreateTime -= fDeltaTime; if(g_fCreateTime < 0.f) { g_fCreateTime = CREATE_TANK_TIME; CreateEnemyTanks(); g_shuliang++; } // 链表节点指针 Weapon* pNode = g_pHead; int num = GetListSize(); // 当前链表的节点数量 // 遍历当前链表,寻找敌方坦克节点 for(int i=0; i<num; i++) { if(pNode->iType == ENEMYTANK) // 敌方坦克 { // 到敌方坦克调转方向时间 pNode->fRotateTime -= fDeltaTime; if(pNode->fRotateTime < 0.f) { pNode->fRotateTime = ROTATE_TIME; MoveEnemyTank(pNode->szName); } pNode->fFireTime -= fDeltaTime; if(pNode->fFireTime < 0.f) { pNode->fFireTime = FIRE_TIME; OnFire(pNode->szName, ENEMYBULLET); } } pNode = pNode->pNext; } } }
- 游戏结束
-
// 本局游戏结束 //删除地图 void GameEnd() { char szName[128]; for(int i=0; i<g_iWallCount; i++) {sprintf(szName, "wall%d", i);dDeleteSprite(szName);} for(int a=0; a<g_iGrassCount; a++) {sprintf(szName, "grass%d", a);dDeleteSprite(szName);} for(int b=0; b<g_iStockCount; b++) {sprintf(szName, "stock%d", b);dDeleteSprite(szName);} g_iWallCount = 0; bLoad = true; // 设置指挥所不可见 dSetSpriteVisible("goal", false); DeleteList(); dSetSpriteVisible(g_pMyTank->szName, false); dSetSpriteVisible(g_pMyTank2->szName, false); dSetSpritePosition("gameover", 0, 0);dSetSpriteVisible("gameover",true); dSetSpriteVisible("boomtime0", false); g_h_score=g_iScore+g_iScore2; dSetTextValue("historyscore",g_h_score); if(g_highestscore<=g_h_score) { g_highestscore=g_h_score; dSetTextValue("highestscore",g_highestscore); } g_iScore=0; g_iScore2=0; }
- 鼠标移动
-
// 鼠标移动 // 参数 fMouseX, fMouseY:为鼠标当前坐标 void OnMouseMove( const float fMouseX, const float fMouseY ) { if(g_xuanze==2) { if (dIsPointInSprite("single",fMouseX,fMouseY)) dSetSpriteVisible("baitiao2",true); else dSetSpriteVisible("baitiao2",false); if (dIsPointInSprite("double",fMouseX,fMouseY)) dSetSpriteVisible("baitiao1",true); else dSetSpriteVisible("baitiao1",false); } }
- 鼠标点击
-
// 鼠标点击 // 参数 iMouseType:鼠标按键值,见 enum MouseTypes 定义 // 参数 fMouseX, fMouseY:为鼠标当前坐标 void OnMouseClick( const int iMouseType, const float fMouseX, const float