《《面向对象的编程技术》课程设计实验报告详解.doc》由会员分享,可在线阅读,更多相关《《面向对象的编程技术》课程设计实验报告详解.doc(22页珍藏版)》请在三一办公上搜索。
1、面向对象的编程技术课程设计实验报告 系计算机科学与技术 班级计114 姓名石险峰 学号119074122 指导教师胡增涛计算机学院2012年12月一应用程序的名称设计:“坦克大战” (1) 参考(PC游戏编程(窥门篇)谭文洪著)中的“坦克大战”(TankWar工程),并对其进行完善、扩充,程序要能看出专业水平和商业化产品的效果。(2) 要求:修改案例中“子弹可以穿透石头墙”的错误;增加上帝模式(无敌);修改一种敌军坦克,使之威力更大(要求坦克画面采用学生自己的头像)(需要重新编译资源包;之所以“改”而不是“增”,是因为同学们无法修改地图编辑器,另一个办法是在程序运行后动态加入);回答 “坦克大
2、战”指导书.doc(或pdf) 和 TankWar剖析.doc(或pdf)中带有蓝色.?标记的问题。二.应用程序的设计目的面向对象的编程技术课程设计是一门独立开设的实验课程,旨在进一步强化学生对类、封装、继承、多态等面向对象基本概念的理解和OOP(面向对象编程)实际动手能力,并进一步拓展到OOD(面向对象设计)原则、技巧和初步的OOA(面向对象分析)方法。在中国,电子游戏曾一度被大家斥为“电子海洛因”。然而电子游戏在青年学生中大受欢迎却又是一个不争的事实。正如水能载舟,亦能覆舟一样,任何事物都有其两面性。与其千方百计地封堵,还不如让同学们从技术的角度来研究它,这样既可以掌握复杂系统的设计技巧,
3、也可以破除对电子游戏的神秘感。我相信,一个人如果自己能制作游戏,如果能清楚地知道那个绚丽多彩的虚拟世界背后无非就是一些类、变量、函数的话,他就不可能再沉迷于打游戏与一堆对象、内存变量和函数较劲。同时,从技术上讲,游戏程序的开发异常复杂,能充分体现面向对象的拟人化思想和面向对象设计技巧。通过游戏程序的制作,可以帮助学生真正掌握面向对象程序设计的精髓。 三 应用程序简介设计目的:C+电脑游戏开发:侧重利用面向对象的拟人化思想解决复杂问题和OOD技巧;运行环境:1本设计采用Microsoft Visual C+6.0编译,并能够在WIN98,WIN2000下运行2游戏基于Windows Game E
4、ngine(WGE游戏引擎,添翼虎科技)(没提供源程序,不过不用担心,你可以把它看成是利用DirectX快速处理图片、声音、键鼠的类库) ,该引擎需要DirectX7.0 SDK支持(仅有Runtime运行库不够,必须包含开发语言需要的Header&Libs 头文件和库文件)功能介绍:修改案例中“子弹可以穿透石头墙”而且增加了敌军坦克子弹不能穿过箱子:无论是敌军坦克还是玩家坦克的子弹都不能穿过石头,敌军坦克子弹不能透过箱子,一旦它们相碰撞子弹会自动销毁。增加上帝模式(无敌):玩家1通过按F1键变为上帝模式,再按一次,还原,一旦玩家进入上帝模式,敌军坦克的子弹对玩家坦克没任何损伤。修改火坦克的性
5、能,使之威力更大,并且将该敌军坦克改为其他图像,通过更改火坦克的一些属性,使火坦克的子弹射程、威力,坦克的移动速度、硬度(血量),都有了明显的增加。 2、基本内容:坦克大战主要是玩家坦克与敌军坦克之间的斗争,在许多敌军坦克的包围下,玩家坦克通过消灭一部分坦克,打开通完邪恶源的通道,然后摧毁邪恶源获得闯关的胜利。在这个过程中,玩家可以摧毁木箱,在木箱中获得钱、经验、血量,通过这些使得玩家坦克的威力和防御更强,为最终的胜利获得条件。在玩家坦克消灭敌军坦克时,将获得经验,当经验达到一定程度时,玩家坦克的性能将会变得更强,可以从青铜坦克变为白银、黄金坦克,大致情况如下:剧情:“玩家坦克”打掉“邪恶源”
6、即可过关。(共3关,可循环玩)游戏规则:1) 玩家坦克移动:4个方向箭头,和W、S、A、D,“机动力”由升级次数决定型号:“青铜战士”,“白银战士”,“黄金战士”防护:由“经验值(打掉木箱,捡)”决定“最大防护值”,捡恢复物品可提高当前防护值武器:左ctrl和Enter开火,只有“光弹”(匀速),“射程”由型号决定,“破坏力”由“金钱数(捡)”决定2) 敌军坦克总之有3种:双导弹、单导弹、火坦克,性能各有所长。3)“邪恶源” 防护值很大4) 木箱5) 奖励物品恢复、金钱、升级6) 背景地图草地、泥地、白石头、黑石头、白石高地(地形障碍)3、主要技术、WGE游戏引擎的使用坦克大战(TankWar
7、)的实现、C+面向对象技术4、运行环境本设计采用Microsoft Visual C+6.0编译,并能够在WIN98,WIN2000,WINXP,WIN7下运行游戏基于Windows Game Engine(WGE游戏引擎,添翼虎科技)(你可以把它看成是利用DirectX快速处理图片、声音、键鼠的类库) ,该引擎需要DirectX7.0 SDK支持(仅有Runtime运行库不够,必须包含开发语言需要的Header&Libs 头文件和库文件)应用程序的总体设计结构图坦克玩家坦克敌军坦克 奖励(金钱、经验、血) 邪恶源 通往下一关TObjectTBonus TSpriteTObstacleTExp
8、ledo TBulletTEnemyTankTPlayerTankTLinkTLinkNodeTWrold游戏开始进入游戏无敌模式受到火坦克攻击后,上下血量不减爆炸模式敌军全灭。跳关模式直接进入下一关任务完成进入下一关:修改坦克图片,并使其中一种坦克威力增强。换子弹模式:在修改子弹穿墙错误中,我也产生过一些问题,例如:子弹是怎样来实现和改变自己发射的方向的。通过对TEnemyTank类中Move函数的观察,我有了一些认识:敌军坦克的移动和方向的改变和子弹应该是类似的。我对TBullet类中的Move函数进行了修改很增添:/判断是否穿墙/ 、直接对子弹四个方向上的边角修改,使子弹消失。if(g_
9、world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)Dead(); if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)Dead();if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)Dead(); if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGH
10、T)Dead();if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)Dead(); if(g_world.ObstacleMap(rc.right/OBSTACLE_WIDTH,rc.bottom/OBSTACLE_HEIGHT)Dead();if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.top/OBSTACLE_HEIGHT)Dead(); if(g_world.ObstacleMap(rc.left/OBSTACLE_WIDTH,rc.bottom/
11、OBSTACLE_HEIGHT)Dead();这些代码是在TBullet类中的/取得碰撞矩形void TBullet:GetRect(RECT& rc)函数中添加的,在判断子弹能否穿墙与敌军坦克是否碰到障碍物有一点区别,坦克在碰到障碍物时,应该设置不能继续移动的效果,而子弹在碰到物体后得效果不应该是不能继续移动而是立刻消失,所以当有与地形障碍相碰时,全部改为Dead(),在作为判断子弹是否与障碍物碰撞的代码,这样子弹不能穿墙的效果就成功实现了。/增加上帝模式(无敌)。/我是通过增加按钮来改变玩家的模式:我首先在TTank/TPlayerTank/玩家坦克类中定义了一个私有成员private:
12、static int N;根据N%2的值是1还是0来判断玩家是否设置为无敌状态了,我设置了F1为玩家无敌状态的快捷键,在Move里增加以下代码/玩家坦克移动int TPlayerTank:N=0;/给上帝赋初始值void TPlayerTank:Move()if(WGE_Input.Key()DIK_F1) N+;/增加上帝模式在判断子弹与玩家坦克碰撞是否有效里加:/增加无敌模式/if(N%2=1) return TRUE;else if(N%2=0)m_nShield-=pBullet-m_nShield ;return TRUE;但也出现一个问题,在按F1时有时候会发现上帝模式没有出现,有
13、时需要多按几次。/修改图片/这里比较简单,直接自己做一个图片,四个图层,四个方向的,用psd格式,再用PSD2EPG.EXE转换一个epg格式,放入data文件里替换某一种坦克,将图片名字改成相同的,再将工具三个全放入data里,用makeres.bat打包即可/增加爆炸模式,所有坦克全灭/本来想法是想在地图上读取坦克,然后灭了,后来觉得利用坦克链表比较简单就直接使用了。在敌军坦克移动里增加爆炸代码,使敌军所有坦克全灭敌军坦克移动void TEnemyTank:Move() if(WGE_Input.Key()DIK_F2)/增加爆炸模式,所有坦克全灭TLinkNode * pNode=g_w
14、orld.EnemyTankLink().m_pHeader;while(pNode)/还不到链尾pNode =pNode-m_pNext;m_nShield=-1;if(m_nShield m_nExper += 10 + m_nType * 10;/加点爆炸效果g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY,EXPLODE_TANK);/增加正向跳关模式/这个比较简单,只需在障碍物文件加入代码if(WGE_Input.Key()DIK_F3)/跳关模式g_game_status = GAME_STAGECLEAR;/子弹转换/设置F4F5F
15、6F7分别为光弹 火弹 双导弹 单导弹,本来我以为仅仅只需要改变调用时的函数就可以了,后来做的时候发现做这个有点难。这里简略说一下现在玩家坦克里定义,int bullet_type;/自定义玩家子弹类型然后对按键处理if(WGE_Input.Key()DIK_F4)bullet_type=1;if(WGE_Input.Key()DIK_F5)bullet_type=2;if(WGE_Input.Key()DIK_F6)bullet_type=3;if(WGE_Input.Key()DIK_F7)bullet_type=4;enum BULLET_TYPE p=LIGHT;switch(bull
16、et_type)case 1:p=LIGHT;break;case 2: p=FIRE;break;case 3: p=DMISSILE;break;case 4: p=SMISSILE;break;g_world.BulletLink().Add(NEW TBullet(m_nX,m_nY,m_dir,bullet_type,10+m_nMoney/300,100+m_nType*25);上式调用函数为自己改的子弹构造函数TBullet(int x,int y,DIRECTION dir1,int p1,int nShield=10,int nFireRange1=100);构造函数为TBu
17、llet:TBullet(int x,int y,DIRECTION dir1,int p1,int nShield,int nFireRange1):TSprite(x,y,nShield,0,CLASS_TBULLET),bullet_type(p1)p=LIGHT;switch(bullet_type)case 1:p=LIGHT;break;case 2: p=FIRE;nFireRange1=100;break;case 3: p=DMISSILE;nFireRange1=250;break;case 4: p=SMISSILE;nFireRange1=250;break;m_nTy
18、pe=p;SetDelayTimer(50);m_dir = dir1;m_nFireRange = nFireRange1;int valume,pan;/音量和均衡int w,h;/声源与玩家的距离w = x - g_world.Player(0)-GetX();h = y - g_world.Player(0)-GetY();/计算音效的音量及均衡valume = MAX(ABS(w),ABS(h) * (-10000/800);pan = w * (10000/400);/跟据类型设置速度switch(p)case LIGHT:/玩家的子弹,总会听到声音的m_nSpeed = 15;/
19、if(valume-10000)/小于最小音量,没必要播放m_sound2.Play(-1000,pan);break;case FIRE:m_nSpeed = 10; m_sound1.Play(-1000,pan); break;case DMISSILE:m_nSpeed = 0;/导弹开始速度为0,然后利用加速度加速 m_sound0.Play(-1000,pan);m_sound0.Play(valume,pan);break;case SMISSILE:m_nSpeed = 0; m_sound0.Play(-1000,pan); break;上面也改变了子弹音量问题后面对子弹碰撞
20、修改switch(m_nType)case FIRE:/火弹,由火坦克发射的炮弹/计算出当前动画帧m_nCurrentFrame = m_dir*3+(m_nCurrentFrame+1)%3; if(p=FIRE)pNode=g_world.EnemyTankLink().m_pHeader;while(pNode)/还不到链尾/打中了吗?if(pNode-m_pObject-HitBy(this)/Ok,Mission completedDead();/取得下一辆坦克pNode = pNode-m_pNext;pNode = g_world.ObstacleLink().m_pHeader
21、 ;while(pNode)if(pNode-m_pObject-HitBy(this)Dead();pNode = pNode-m_pNext;if(m_nFireRange0)/太远了,没办法Dead(); if(IsDead()g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY,EXPLODE_FIRE); break;/超出射程范围,发出死亡信息if(m_nFireRangeHitBy(this)/击中目标,任务完成Dead();/已经死亡,来个爆炸效果if(IsDead()g_world.ExplodeLink().Add(NEW TEx
22、plode(m_nX,m_nY,EXPLODE_FIRE);break;case DMISSILE:/双导弹,敌军的导弹m_nSpeed +=1;/以加速为1的速度运动m_nCurrentFrame = m_dir;/计算当前动画的帧 if(p=DMISSILE)pNode=g_world.EnemyTankLink().m_pHeader;while(pNode)/还不到链尾/打中了吗?if(pNode-m_pObject-HitBy(this)/Ok,Mission completedDead();/取得下一辆坦克pNode = pNode-m_pNext;pNode = g_world.
23、ObstacleLink().m_pHeader ;while(pNode)if(pNode-m_pObject-HitBy(this)Dead();pNode = pNode-m_pNext;if(m_nFireRange0)/太远了,没办法Dead(); if(IsDead()if(m_dir=DIR_RIGHT|m_dir=DIR_LEFT)g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY+6,EXPLODE_MISSILE);g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY-6,EXPLOD
24、E_MISSILE);elseg_world.ExplodeLink().Add(NEW TExplode(m_nX+6,m_nY,EXPLODE_MISSILE);g_world.ExplodeLink().Add(NEW TExplode(m_nX-6,m_nY,EXPLODE_MISSILE);break;/超出射程范围,发出死亡信息if(m_nFireRangeHitBy(this)Dead();/死了if(IsDead()/双导弹当然是两个爆炸效果if(m_dir=DIR_RIGHT|m_dir=DIR_LEFT)g_world.ExplodeLink().Add(NEW TExpl
25、ode(m_nX,m_nY+6,EXPLODE_MISSILE);g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY-6,EXPLODE_MISSILE);elseg_world.ExplodeLink().Add(NEW TExplode(m_nX+6,m_nY,EXPLODE_MISSILE);g_world.ExplodeLink().Add(NEW TExplode(m_nX-6,m_nY,EXPLODE_MISSILE);break;case SMISSILE:/单导弹,不用注释了吧m_nSpeed +;m_nCurrentFrame =
26、 m_dir; if(p=SMISSILE)pNode=g_world.EnemyTankLink().m_pHeader;while(pNode)/还不到链尾/打中了吗?if(pNode-m_pObject-HitBy(this)/Ok,Mission completedDead();/取得下一辆坦克pNode = pNode-m_pNext;pNode = g_world.ObstacleLink().m_pHeader ;while(pNode)if(pNode-m_pObject-HitBy(this)Dead();pNode = pNode-m_pNext;if(m_nFireRan
27、ge0)/太远了,没办法Dead(); if(IsDead()g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY,EXPLODE_FIRE); break;if(m_nFireRangeHitBy(this)Dead();if(IsDead()g_world.ExplodeLink().Add(NEW TExplode(m_nX,m_nY,EXPLODE_MISSILE);break;case LIGHT:/我们的武器:)m_nCurrentFrame = 0;/计算是否打中在链表中的敌军坦克/取得链表中的第一辆坦克pNode=g_world.En
28、emyTankLink().m_pHeader;while(pNode)/还不到链尾/打中了吗?if(pNode-m_pObject-HitBy(this)/Ok,Mission completedDead();/取得下一辆坦克pNode = pNode-m_pNext;/计算是否打中障碍物pNode = g_world.ObstacleLink().m_pHeader ;while(pNode)if(pNode-m_pObject-HitBy(this)Dead();pNode = pNode-m_pNext;if(m_nFireRangem_nType = LIGHT|pBullet-m_
29、nType = FIRE|pBullet-m_nType =DMISSILE|pBullet-m_nType =SMISSILE)m_nHardiness -= pBullet-m_nShield ;return TRUE;在敌军坦克里对子弹碰撞有效判断if(WGE_Input.Key()DIK_F5)bullet_type=2;if(WGE_Input.Key()DIK_F6)bullet_type=3;if(WGE_Input.Key()DIK_F7)bullet_type=4;if(pBullet-m_nType = LIGHT|(pBullet-m_nType = FIRE&bulle
30、t_type=2)|(pBullet-m_nType = DMISSILE&bullet_type=3)|(pBullet-m_nType =SMISSILE&bullet_type=4)/是光弹,防护减去光弹的力量m_nShield -= pBullet-m_nShield ;return TRUE;上面只是简略讲的,还有不少细节问题没写。在做这这时也遇到了问题,我发现按键处理只能在函数move里,其他地方都会无法处理,所以改了后的敌军坦克也会击中障碍物,但不会击中其他敌军坦克。函数与函数之间数据共享要自己增加数据成员。解答问题static int x; 思考一下静态变量的作用?此处静态变量
31、主要是为了记录坦克移动的水平坐标,储存此时坦克在水平的位置。设为静态变量则其初始值为0,使坦克的初始位置位于水平坐标为0的位置,同时在坦克移动时,背景图片也随着坦克的移动而移动,而且具有全局性,当再次调用时水平坐标不会发生变化,能很好的记录坦克的水平位置;g_world.Move();/不马上返回菜单,而是继续动,去掉此行怎样?g_world是Tworld建立的一个对象,利用g_world调用Tworld类的Move函数,使坦克大战这个世界“活”的精灵进行移动。如果去掉这一行的话,当游戏结束的时候,即玩家坦克死亡时,游戏不会马上停止,里面“活”的精灵还是像刚才一样运动;static DWORD
32、 dwTick ;/定时器用法。静态变量有何作用?此静态变量主要是存储GetTickCount()这个函数所获得的数据,也就是游戏进行到当前消耗的时间。定义为全局变量主要是因为其所在的函数是一个循环过程,当游戏进行的时间没有达到所规定的时间时,函数继续被调用,将避免了多次定义且多次定义后的值将会改变,不能起到记录时间的作用,定义为静态变量很好的避免了这些问题,在初次定义时,初始值为0,且具有全局性,再次被调用是还是原来记录的时间;CLASS_TYPE m_nClassType;/对象类型枚举型,在最顶层父类中记录最底层子类的类型不符合OO设计原则,只是为了便于管理和碰撞检测。如何改进?又会有何
33、麻烦?可以再定义一个对象类,运用类的组合。这需要在每个TObject类派生的对象中用对象类声明一下当前对象的类型,这样的话比较符合面向对象设计规则。但是在检测物体之间碰撞时,需要对每个TObject类派生的对象的类型进行判断,而且在检测碰撞类型时,需要调用每个派生子类的对象类型,再根据判断后得结果,实现相应的变化。如果在抽象类TObject中定义对象的类型,这样避免在每个派生类中的定义,而且在判断碰撞类型时只需要用TObject类声明一个对象指针调用各子类的对象类型CLASS_TYPE,这就是代表各个子对象的类型,只需用一个类的成员函数进行碰撞对象的判断。Virtual void Move()
34、=0;virtual void Draw()=0;virtual void GetRect(RECT& rect)=0;为何要用纯虚函数,在oo设计中有何价值?在TObject类中将Move、Draw、GetRect声明为纯虚函数,主要是因为在Object是个抽象类,没有实际的物体与其相符如果实现上述三个函数没有实际意义。纯虚函数在面向对象设计中有很重要的作用,通过声明虚函数从而实现了多态。对于一些函数,只能根据相应的对象才能实现这些函数的作用,而在抽象类中无法给定有意义的实现,这时就在基类中只说明函数原型用来规定整个类族的统一接口形式,这样派生类中的这几个函数就是对基类相应函数的覆盖,通过基
35、类指针调用这些函数时,派生类的相应函数将被实际调用,避免产生的二义性的问题。BOOL HitTest(TObject* object);/为何又不用虚函数?注意是 几何尺寸上得碰撞检测:比较2矩形是否重合。请结合以上几个虚函数,阐述多态在oo设计原则中的重要作用?将一个函数声明为虚函数主要是为了实现多态,而且这个函数在每个派生类中的实现不用,通过基类指针调用。但是BOOL HitTest(TObject *object)这个函数是判断对象与对象之间是否发生碰撞,而且这个的碰撞的检测是通过比较两个对象的矩形是否重合,因为坦克大战是二维的其所有的对象都是可以看成矩形,这样在检测碰撞时只需要调用基类
36、的HitTest函数。不需要声明为虚函数,再在各个派生类中有不同的实现。多态性是面向对象系统的重要概念之一,它指的是同样的消息能被发送到父类的对象和它的子类的对象,它可以将派生类的对象当做基类对象一样处理的功能,体现了多态的优越性,使程序更容易去管理。int m_nStatus;/精灵状态为何活的东西要有状态?对于每一个活的精灵必须要有其自己的状态,用m_nStatus来记录该精灵的生死,通过Dead()、IsDead()来调用m_nStatus来判断此时精灵的状态,如果m_nStatus为0的话要将该精灵销毁,若m_nStatus为1则要让其运动。Tworld要想使用上述各对象的功能,也可以
37、做它们的子类(多继承),这样做好不好?为什么?如果Tworld作为上述对象的子类的话,那么在Tworld类中将包括上述各类对象的接口,这样使得上述对象存在不安全因素,对类对象起不到保护作用。但是利用类的组合,在Tworld中存在上述类的内嵌对象,Tworld中包括上述对象的全部内容,但不包括上述类对象的接口,对类的数据起到很好的保护作用。设计实践过程中的心得体会通过这次坦克大战的课程设计,使我对面向对象程序设计有了更深层次的了解,更熟练的掌握了多态,继承,组合等等一些面向对象中很重要的概念。坦克大战是C+面向对象程序设计的实际应用,使我更加了解到面向对象的设计思想,怎样处理类和类之间的复杂关系
38、。特别是在类比较多的时候,我们需要通过建立一个抽象类来管理这些类,对于一些比较大规模的程序是很重要的。研究坦克大战的游戏代码,让我以前对游戏的神秘感有所减弱,我明白了游戏就是靠着一些函数、一些对象、一些变量来实现的。我现在觉得面向对象是一门很有趣也非常有用的一门技术,希望通过以后的学习研究,来获得更多的知识。同时我发现当一个人对编程的东西感兴趣的时候,他工作起来就会事半功倍。附录:程序安装1 安装Visual C+6.02 安装DirectX SDK:3. 安装WGE游戏引擎:WgeSetup,建议安装在c:wgesdk4. 设置VC+ 6.0环境,以便找到上述SDK的头文件和库文件:5. 打
39、开TankWar.dsw文件,按F5运行。使用说明坦克大战主要是玩家坦克与敌军坦克之间的斗争,在许多敌军坦克的包围下,玩家坦克通过消灭一部分坦克,打开通完邪恶源的通道,然后摧毁邪恶源获得闯关的胜利。在这个过程中,玩家可以摧毁木箱,在木箱中获得钱、经验、血量,通过这些使得玩家坦克的威力和防御更强,为最终的胜利获得条件。在玩家坦克消灭敌军坦克时,将获得经验,当经验达到一定程度时,玩家坦克的性能将会变得更强,可以从青铜坦克变为白银、黄金坦克,大致情况如下:剧情:“玩家坦克”打掉“邪恶源”即可过关。(共3关,可循环玩)游戏规则:3) 玩家坦克移动:4个方向箭头,和W、S、A、D,“机动力”由升级次数决定型号:“青铜战士”,“白银战士”,“黄金战士”防护:由“经验值(打掉木箱,捡)”决定“最大防护值”,捡恢复物品可提高当前防护值武器:左ctrl和Enter开火,只有“光弹”(匀速),“射程”由型号决定,“破坏力”由“金钱数(捡)”决定4) 敌军坦克总之有3种:双导弹、单导弹、火坦克,性能各有所长。3)“邪恶源” 防护值很大7) 木箱8) 奖励物品恢复、金钱、升级9) 背景地图草地、泥地、白石头、黑石头、白石高地(地形障碍)
链接地址:https://www.31ppt.com/p-4085459.html