版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、【文章标题】用面向对象的思想探讨游戏“魔兽争霸”(1)【文章作者】曾健生【作者邮箱】【作者QQ】【作者博客】【编程环境】JDK 1.6.0_01【作者声明】欢迎转载文章,但转载请保留文章的完整性以及注明文章的出处。*前言:面向对象思想是学习java, .net等计算机语言的核心思想,在本人学习的过程中,本人直到最近对面向对象思想有了一个大突破后才发现原来在玩 “魔兽争霸”这个游戏的过程中就已经包含了深刻的面向对象的思想,现在根据自己对面向对象思想的理解结合“魔兽争霸”这个游戏进行相关的阐述(本人知道很多兄弟们对“魔兽争霸”等相关即时战略游戏相当沉迷,用“魔兽争霸”举例说明能减少学习的枯燥性,看
2、完本文后就能发现其实面向对象的思想我们早已熟悉了,只是没发现而已),希望能对各位理解面向对象的思想有所帮助。阅读本文前最好对即时战略游戏有所理解,即时战略游戏指魔兽争霸,星际(当然也包括帝国时代,红色警戒等游戏),有所理解是指起码也要知道游戏是怎么玩的。最后,请原谅由于本人对“魔兽争霸”不太熟悉而在魔兽的专业术语的使用上有所错误,其实本人只是“魔兽争霸”菜鸟(勉强能打赢初级电脑),而且本人也有半年多没玩,很多内容都忘记,阅读本文的“魔兽”玩家请原谅我吧-本人才疏学浅,对于文中出现的各种错误,敬请各位大侠指出!这里也简单阐述一下面向对象的概念(详细的定义读者可参考相关的书籍或文章):面向对象的思
3、想力图使计算机中描述的事物和现实生活中的尽量相近,其中类是指具有相同属性,相同行为的一类事物;实例是指该类事物的具体例子首先开始就文中的一些概念进行约定以减少阅读的困难:(1) 我们玩“魔兽争霸”游戏是在一个地图(是指2D地图)中进行,如果现在有一个人族的农民站在地图上,那么这个农民在地图上有个坐标(坐标的原点是地图左下角),譬如是农民的坐标(200,100),那么在地图上的标识如下(图1),这个坐标概念在下文中经常用到,各位读者必须要理解是怎么一回事(2) 全文中都是假设玩家选的种族是精灵族其实我们在玩魔兽的过程中对类的概念已经耳熟能详了(对于这一点,是本人在前几天对面向对象有了一个更深刻的
4、认识后才发现,各位玩家看了后一定会恍然大悟-)下面就面向对象中的属性,行为,类,实例等概念用游戏的例子说明一下(1) 属性:是说明某个物体的基本特征,通过一系列的属性数据,我们就能得出结论某个物体是什么?譬如一个精灵族的小精灵,它的生命是120,防御是0,看起来像是发红光的物体,知道了小精灵的以上数据,就对小精灵有所了解。如图1 图1(2) 行为:说明某个物体能干什么?譬如小精灵能采矿(),能建造生命之树(),能移动()等,这都是小精灵的能干的事情。如图2 、图2(3) 类:是某一种事物的描述。我们知道在精灵族种小精灵的生命值120,防御力是0,小精灵能采矿(),能建造生命之树(),能移动()
5、,但我们不需要知道具体到底指的是哪个小精灵,反正小精灵这个概率就有以上的内容。所以小精灵就是一个类,它可以存在于抽象层次(知道是什么一回事),但不需要实体。在精灵古树种有个生产小精灵的按钮,我们知道这个按钮能生产小精灵,生产的小精灵除了位置和内部ID号外其他都是一样的。所以这个生产小精灵的按钮就是已经蕴含了面向对象中的“小精灵”类的概念。如图3图3(4) 实例:类只是某一种事物的抽象的概念。就正如“小精灵”类一样,如果不训练一个小精灵去采矿,那么小精灵类永远不会采矿。如果我们需要一个小精灵去采矿,我们就必需点击一下训练小精灵的按钮训练一个小精灵出来点击训练小精灵按钮创造一个小精灵,用面向对象的
6、术语描述就是用小精灵类产生了一个小精灵的实例。训练出来的小精灵就是小精灵类一个实例。图4就是用小精灵类创造的多个实例: 图4经过以上的论述,本人得出了一个结论:每个玩家都已很熟悉面向对象思想。玩魔兽的过程就像是一个面向对象编程的过程:我们玩游戏就是用暴雪公司提供的各种类和方法,思考用那些类(英雄类,小精灵类,战士类等),创造多少个实例(训练多少各精灵,生产多少个弓箭手,需要用哪个英雄),针对各个对象的属性(生命值,资源值,攻击力,防御力)考虑调用哪些方法(小精灵去采矿(),小精灵建造生命之树(),弓箭手攻击()来获取胜利,在这个基础上玩家们创造出不同的战术获取胜利。所以正在学习面向对象的各位玩
7、家,其实我们早已对面向对象的那套思想非常熟悉,只是我们不知道这就是面向对象思想而已。希望阅读完本文的各位玩家能根据本文的内容及时把思维转换过来,更快地迈入面向对象的世界。现在我们开始在程序的角度用“魔兽争霸”游戏阐述面向对象的思想(以下的代码进行了最大程度的简化,只阐述最核心的部分,各位读者要明白,真正的游戏编程没有这么简单-,Let Go!那么现在我们从程序员的角度思考一下,如果现在有这么一个场景:玩家生产了一个弓箭手去攻击对手不死族的食尸鬼。如果你是一个程序员,应该怎么用面向对象编程完成这个场景动作?根据我们玩“魔兽争霸”的经验,第一步是生产一个弓箭手,这个不难,但如果玩家是生产2个,3个
8、,4个,如果每次生产一个弓箭手都要把弓箭手的所有代码重写一遍,那不是把我们写程序的活活累死!不要着急,我们可以分析一下每个弓箭手有什么不同。现在我们再回顾一下类的概念:类是指具有相同属性,相同行为的一类事物。对于弓箭手,就正如我们玩家所熟悉的,每个弓箭手相对于其他弓箭手唯一的不同就是所在的位置(也就是在地图上的坐标)还有一个ID,其它的什么攻击力,防御力,生命值,移动的方法:步行,攻击的方法:用弓箭射击 ,受到攻击的防御行为等都是一样的。那么对于所有的弓箭手来说,除了所在的位置不同外的所有属性(攻击力,防御力,生命值),所有行为(移动的方法:步行,攻击的方法:弓箭射击,受到攻击的行为)是不是一
9、样啊!这不是已经符合了类的定义吗?所以把弓箭手抽象为一个类Bower。类的定义如下:/这是一个弓箭手类class Bower private int posX; /弓箭手在地图上X的坐标private int posY; /弓箭手在地图上Y的坐标private int ID; /弓箭手在地图上Y的坐标private int lifeNum; /弓箭手的生命值private int attackNum; /弓箭手的攻击力private int untenNum; /弓箭手的防御力/构造函数,生产一个弓箭手,传入参数为在地图中的坐标public Bower( int IDNum, int x, i
10、nt y )posX=x;/弓箭手生产出来后在地图上X的坐标posY=y;/弓箭手生产出来后在地图上Y的坐标lifeNum= 245;/弓箭手的默认生命值attackNum=16;/弓箭手的默认攻击力untenNum=0;/弓箭手的默认防御力ID=IDNum;/弓箭手的IDSystem.out.println("弓箭手 "+ID+"生产完毕了");/默认构造函数public Bower( )/*一般来说,生命值,攻击力,防御力等都属于对象的核心数据,对它们的访问必须要严格控制,所以设计出getLifeNum(),getAttackNum(),getUnt
11、enNum()这三个方法*/获取弓箭手的剩余生命值public int getLifeNum()return lifeNum;/获取弓箭手的攻击力public int getAttackNum()return attackNum;/获取弓箭手的防御力public int getUntenNum()return untenNum;/获取弓箭手的ID号public int getID()return ID;/获取弓箭手的X坐标public int getX()return posX;/获取弓箭手的Y坐标public int getY()return posY;/弓箭手移动的行为,就是一般情况下用点
12、击了/一个弓箭手后命令弓箭手移动到某个位置所用的方法/传入参数为要移动到的对象public void moveTo( Ghost gs )posX=gs.getX();posY=gs.getY();System.out.println( "弓箭手"+ID+"移动到地点 "+posX+","+posY );/用弓箭手攻击食尸鬼的方法,传入的参数为攻击的对象/附:本人感觉这个攻击行为抽象的设计非常差,如果有好的方法,/敬请指教public void attackByBow( Ghost gs )gs.getHunt( this );/受到
13、攻击时调用这个方法计算伤害值public void getHunt( Ghost gs )/只有在食尸鬼和弓箭手都没死亡的前提下会攻击if( gs.getLifeNum()>0 && getLifeNum()>0 )/如果受到的攻击值大于自身的生命值表示对象死亡if( (gs.getAttackNum()-getUntenNum()>=lifeNum )lifeNum=0;System.out.print("弓箭手"+getID()+"受到食尸鬼"+gs.getID();System.out.print("的攻
14、击力"+gs.getAttackNum();System.out.println(",弓箭手"+ID+"死亡");else /用生命值减去受到的伤害值lifeNum=lifeNum-(gs.getAttackNum()-getUntenNum();System.out.print("弓箭手"+getID()+"受到食尸鬼"+gs.getID();System.out.print("的攻击力"+gs.getAttackNum();System.out.println(",剩余生
15、命值为"+getLifeNum(); 对于食尸鬼,可以用同样的抽象方法成一个食尸鬼类/这是一个食尸鬼类class Ghostprivate int posX; /食尸鬼在地图上X的坐标private int posY; /食尸鬼在地图上Y的坐标private int ID; /食尸鬼在地图上Y的坐标private int lifeNum; /食尸鬼的生命值private int attackNum; /食尸鬼的攻击力private int untenNum; /食尸鬼的防御力/构造函数,生产一个食尸鬼,传入参数为在地图中的坐标public Ghost( int IDNum,int x
16、, int y )posX=x;/食尸鬼生产出来后在地图上X的坐标posY=y;/食尸鬼生产出来后在地图上Y的坐标lifeNum= 245;/食尸鬼的默认生命值attackNum=12;/食尸鬼的默认攻击力untenNum=0;/食尸鬼的默认防御力ID=IDNum;/食尸鬼的IDSystem.out.println("食尸鬼 "+ID+"生产完毕了");/默认构造函数public Ghost( )/获取食尸鬼的剩余生命值public int getLifeNum()return lifeNum;/获取食尸鬼的攻击力public int getAttack
17、Num()return attackNum;/获取食尸鬼的防御力public int getUntenNum()return untenNum;/获取食尸鬼的ID号public int getID()return ID;/获取食尸鬼的X坐标public int getX()return posX;/获取食尸鬼的Y坐标public int getY()return posY;/食尸鬼移动的行为,就是一般情况下用点击了/一个食尸鬼后命令食尸鬼移动到某个位置所用的方法/传入参数为要移动到的对象public void moveTo( Bower bo )posX=bo.getX();posY=bo.g
18、etY();System.out.println( "食尸鬼"+ID+"移动到地点 "+posX+","+posY );/用食尸鬼攻击弓箭手的方法,传入的参数为攻击的对象/附:本人感觉这个攻击行为抽象的设计非常差,如果有好的方法,/敬请指教public void attackByWater( Bower bo )bo.getHunt( this );/受到攻击时调用这个方法计算伤害值public void getHunt( Bower bo )/只有在食尸鬼和弓箭手都没死亡的前提下会攻击if( bo.getLifeNum()>0
19、 && getLifeNum()>0 )/如果受到的攻击值大于自身的生命值表示对象死亡if( (bo.getAttackNum()-getUntenNum()>=lifeNum )lifeNum=0;System.out.print("食尸鬼"+getID()+"受到弓箭手"+bo.getID();System.out.print("的攻击力"+bo.getAttackNum();System.out.println(",食尸鬼"+ID+"死亡");else /用生命
20、值减去受到的伤害值lifeNum=lifeNum-(bo.getAttackNum()-getUntenNum();System.out.print("食尸鬼"+getID()+"受到弓箭手"+bo.getID();System.out.print("的攻击力"+bo.getAttackNum();System.out.println(",剩余生命值为"+getLifeNum() );那么现在我们根据上面写的类,用一段代码模拟玩家生产了一个弓箭手去攻击对手不死族的食尸鬼这个过程class GameStartpubl
21、ic static void main( String args )/下面一段代码产出了一个食尸鬼Ghost gs= new Ghost( 1, 90, 90 );/下面这两行代码表示玩家创建了两个弓箭手,相当于玩家按了两下生产弓箭手的按钮Bower bo1= new Bower( 1, 180, 180 );Bower bo2= new Bower( 2, 180, 180 );/这里的设计就能体现面向对象的好处:/1.直观,把弓箭手移动到食尸鬼的位置代码为bo1.moveTo( gs ),/ 从字面上就能理解这句代码的含义/2.把程序员从繁琐的移动细节中解放出来,我们只需要调用弓箭手的/
22、方法命令弓箭手移动,至于弓箭手移动时走路的方式如何,是走直线还是/ 曲线,这些都不需要在这里写代码,因为这些内容都是封装在类的内部处理 /下面这两行代码表示玩家指挥两个弓箭手移动到要攻击的食尸鬼的位置,/相当于玩家指挥两个弓箭手走向食尸鬼bo1.moveTo( gs );bo2.moveTo( gs );/这里也同样体现了面向对象编程的好处,我们只需要给弓箭手发出/攻击的命令就行,至于攻击的细节(用手还是用脚,攻击的力度等)都是/封装在类的内部实现,程序员调用这个方法时不需要理会里面的细节/下面的while循环是两个弓箭手开始攻击食尸鬼攻击的过程/为了编写代码的方便性,假设弓箭手和食尸鬼相遇时
23、才互相攻击,/没有远程攻击手段,只站在原地互相攻击,请各位魔兽玩家原谅我吧-/攻击过程抽象如下(有点像回合制的RPG游戏-)/1.弓箭手1攻击食尸鬼后食尸鬼反击弓箭手1/2.弓箭手2攻击食尸鬼后食尸鬼反击弓箭手2/3.如果食尸鬼或两个弓箭手都没死亡就重复1,2的过程while( true )/弓箭手1攻击食尸鬼bo1.attackByBow( gs );/如果食尸鬼没死亡就反击gs.attackByWater( bo1 );/弓箭手2攻击食尸鬼bo2.attackByBow( gs );/如果食尸鬼没死亡就反击gs.attackByWater( bo2 );/攻击结束的条件是以下两个条件之一(当生命值等于0时表示死亡)/1.食尸鬼死亡/2.两个弓箭手死亡if( (gs.getLifeNum()=0) | (bo1.getLifeNum()=0 && bo2.getLifeNum()=0) )break;/根据食尸鬼的生命值是否等于0判断任何if( gs.getLifeNum()>0 )System.out.println("两个弓箭手死亡,任务失败");
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 叉车作业事故处置方案
- 灰缝厚度质量控制要点
- 2026监理工程师交通三控真题及答案
- 基坑拆撑施工方案及技术措施
- 2026全国特种作业操作证高处安装、维护、拆除模拟试题及答案
- 2026年新能源汽车电池回收与回收设备维护培训考试试卷(附答案)
- GBT 32968-2026《钢筋混凝土用涂镀层钢筋》
- 社区老人防跌倒坠床教育试题
- 2026年苏教版八年级下册政治期末地市统考卷(含答案可下载)
- 介入护士介入易错集训卷附答案
- 2026广西南宁市良庆区良庆镇人民政府招聘工作人员21人备考题库及一套完整答案详解
- 健康产业门店运营方案
- 2026上海青浦区白鹤镇基层单位招聘85名笔试模拟试题及答案详解
- 2026年高考新高考I卷语文真题试卷
- 2025年基层法律服务工作者考试题及答案
- 有限空间作业案例分析及应急救援
- 连锁便利店城市合伙人合作协议范本
- 山西路桥集团笔试题目
- 激光熔覆缺陷控制方法
- 农产品销售推广员绩效考核表
- 2024年吉林职工医科大学马克思主义基本原理概论期末考试笔试题库
评论
0/150
提交评论