??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品无码久久久久sm,久久精品国产2020,色婷婷综合久久久久中文一区二区 http://www.shnenglu.com/flashboy/category/6691.html------3D游戏研发zh-cnMon, 14 Sep 2009 15:14:01 GMTMon, 14 Sep 2009 15:14:01 GMT60游戏Entity设计不完全整??http://www.shnenglu.com/flashboy/archive/2009/08/18/93684.htmlRedLightRedLightTue, 18 Aug 2009 03:11:00 GMThttp://www.shnenglu.com/flashboy/archive/2009/08/18/93684.htmlhttp://www.shnenglu.com/flashboy/comments/93684.htmlhttp://www.shnenglu.com/flashboy/archive/2009/08/18/93684.html#Feedback0http://www.shnenglu.com/flashboy/comments/commentRss/93684.htmlhttp://www.shnenglu.com/flashboy/services/trackbacks/93684.html

在游戏引擎中Q?/span>Entity通常被翻译成实体Q也常用诸如GameObject?/span>Actor?/span>SimulationObject?/span>Unit?/span>Character{名字。相比于对图像声韛_擎的热情Q?/span>Entity层多q来一直备受冷遇,但最q几q随着大型游戏的发展,Entity层设计的重要性已l达到和囑փ声音的同{水qI而且已经出现了多U通用?/span>Entity架构。当Ӟq里伴随着争议和分歧?/span>

直接模式Q?/span>The C ApproachQ?/span>

q是最早、最单、也是Q何h都能直接惛_的模式。这U方式下一?/span>Entity是一个简单的struct:

struct Mob
{
int level, hp, mp, attack, …;
};

q种情况下往往需要对不同cd?/span>Entity定义不同?/span>structQ比?/span>Player?/span>Mob?/span>Item?/span>Doodad{?/span>Entity的数据库可以直接使用现成的数据库pȝ或者从数据文gdQ比?/span>csv文g。一般会选择Excel~辑数据库,然后导出csv?/span>Excel的强大表格和l计计算功能是调节游戏数据^衡的得力工具。以致这U最古老而简单的Entity模式以强大的生命力一直活到现在?/span>

那么Z?/span>Developers会要L索其他方式呢Q最大的问题是这U方式下各种Entity完全不同质。比?/span>Player?/span>Mob?/span>Doodad都有位置Q都要做撞,但他们却是不同的cdQ不能用同一份代码;Player?/span>Mob都有hp?/span>mpQ也有基本相同的处理逻辑……当然Q这个可以用hack的方法解冻I只要各个struct前若q个成员cd和顺序完全相同,可以将指针cast成统一的一?/span>Entitycd来处理。不q,M人都能想到更好的办法Q用c!

l承模式Q?/span>InheritageQ?/span>

q也?/span>Entity?/span>GameObject{这些名字的由来Q他们就是基cR于是我们可以得C颗承关pLQ例如:

Entity

       Character

              Player

              Mob

       Missile

              Laser

              GuidedMissile

       Item

      

Entity对象的逻辑大多也是直接包含在类里的。但也有人采用了数据对象和逻辑对象的分,其好处是对相同的数据可以替换不同的逻辑。不q,个h比较怀疑这U分L否值得Q因为类的派生本w就是可以拥有不同的逻辑?/span>

另外Q?/span>Entity间的交互除了用标准的直接讉K方式外,l常使用消息模式。消息模式和Windows的消息模式类|Entity间通过消息交互。虽说窗口编E画了多q时间才摆脱了当q肥大的switch的消息处理模式,?/span>Entity层用消息模式还是有意义的,因ؓ消息很容易广播且可以直接在网l上发送。执着?/span>OO的h会将消息写成Command对象Q但原理仍然是一L?/span>

同时Q联|游戏出玎ͼ指针不能在不同的机器上标识对象,我们必须用稳定的ID来标识对象,于是我们有了EntityManager来分?/span>ID和管理对象集合,或者叫GameObjectManager?/span>ObjectManager{。这在一D|期内几乎成了完美的方案?/span>

随着游戏内容的丰富性的q速膨胀Q传l的q序员来实现游戏逻辑功能的模式也来力不从心。脚本语a的集成将大部分创意性工作从E序员的担子上拿了下来,交还l游戏设计h员。ؓ了给脚本提供_的控制权Q?/span>Entityl构上必L充分的灵zL?/span>

数据驱动Q?/span>Data-DrivenQ?/span>

现在有句很流行的话,“唯一不变的是变化。(The only constant is change.Q?#8221;数据驱动使得变化对引擎的影响最化。数据驱动不能算是一U独立的Entity模式Q不如说它是一U设计思想Q其目的是内容制作和游戏引擎的制作分d来。与上面所说的填充Entity属性数据库的不同之处在于,它还要能通过数据来设计游戏逻辑?/span>

游戏设计人员需要的一Ҏ基本功能是自定义h物属性,所以与其在c里写死属性成员,不如使用属性表Q?/span>Attributes/PropertiesQ。通常使用一个哈希表Q?/span>HashtableQ,或?/span>std::mapQ或?/span>DictionaryQ或者就是个数组Q随个h喜好Q其实就是要一?/span>key-value的映表。然后ؓ脚本和编辑器提供对属性表的操作?/span>

动态的逻辑主要靠脚本了,必须本提供够的事g和方法。个人推荐用Lua脚本Q因为它是在游戏领域内用得最多的通用脚本语言Q其引擎很小、速度很快、易于集成,管语法q于松散。不要迷信宣传去用庞大、极慢、难于集成的Python。ؓ脚本提供事gQ其实也是调用脚本里的函数Q这里如果用了前面所q的消息模式Q那么就只要调用一个脚本方法,传递不同的消息参数p了。当然也有h觉得q样很丑陋而更愿意Z同的事g注册不同的函数?/span>

当有了数据驱动后Q?/span>Entity的承树基本失L义了Q因Z?/span>Entity是什么已l不是程序里军_的了Q而是通过数据和脚本设计出来的。但数据和脚本又不是全部Q一?/span>Entity的核心内容和需要高效处理的部分Q如撞,q是要程序来完成。于是我们需要重新设?/span>Entityc,困难的局面也q此开始?/span>

一个直观的x是一个统一且唯一?/span>Entityc,它包含了所有的基本功能Q如昄、碰撞检、运动、背包等Q然后由数据军_哪些lg被启用。比如一个玩家角色可能会启用l大部分lgQ而一颗树只启用显C和撞组件。但也伴随着~点Q一、这个类太大了;二、对于树木等一些简单的Entity也要费其他lg的私有数据所占的内存。那么一个简单的折中是部分用ѝ部分用数据定制。例?/span>Entity只提供最基本的组Ӟ再派生出CharactorEntity提供_人物角色使用的组件?/span>

lg模式Q?/span>Component-Based EntityQ?/span>

提到lgQ那么很自然的就q渡到组件模式,是把显C、运动、攻凅R背包、队伍、声音等基本功能都做成独立的lgQ由数据来决定向Entity里添加哪些组件。由此可以得到另外一个扩展,是既然可以有引擎内|的lgQ那׃可以有脚本制作的lgQ实现脚本模块的复用。这U模式在GDC2002正式提出Q到现在L的引擎都有这U设计?/span>

q种模式在理Z很完,但实践上q是有不疑问。最常见的问题就是组仉的依赖关pR理x况下Q各个组件是完全独立的,但实践中必然有所依赖。比如运动速度、攻d度等和角色的基本属性有养Iq动lg需要角色的包围盒来试是否撞Q?/span>AIlg需要分析角色当前状态和发出q动、攻d令,角色动作状态变化时改变昄lg属性,dlg需要访问队伍信息组件以止d队友{等。处理这U依赖关pM要要解决两个问题Q?/span>

<!--[if !supportLists]-->一?span>              <!--[endif]-->谁依赖谁。比如是敏捷属性改变而去修改Ud速度Q还是运动组件读取敏捷属性来计算Ud速度。如果要游戏设计人员自由定义基本属性的话,p选择前者,因ؓ基本属性组件会是脚本组件?/span>

<!--[if !supportLists]-->二?span>              <!--[endif]-->如何取得另一lg的指?/span>/引用。常见的Ҏ是给每个lgcd一个唯一IDQ然后用?/span>ID?/span>Entity上查询注册了的组Ӟ如果扑ֈq回其指?/span>/引用Q否则返?/span>null。当Ӟ每次讉K都做q个查询会很费CPUQ如?/span>Entity的组件不会在q行时动态添加删除的话(除非在编辑器里,否则很少有h会这么做Q,可以?/span>Entity初始化后让每个组件缓存它所要用的其他组件指针。那么当所依赖的组件不存在怎么办,一般情况下都是无声地忽略?/span>

?/span>Entity由很多组件组成后Q交互的消息需要发l每一个组件。这里又一ơ体现出消息机制的优势,你不需要在Entity里ؓ每一个事件函数写一?/span>loop来调用组件的相应事g函数。但q里也出C一个问题,消息到达各个lg的顺序。很多时候这个顺序不会有什么媄响,但个别时候不同的序会导致完全不同的逻辑发展方向?/span>

此外Q?/span>Entity的序列化存储也变得比较复杂,l典?/span>Excel导出csv的模式难以奏效,因ؓq里需要结构化的存储,所以需要结构化的数据文件如XML来存储,或者完全用脚本来包含所有数据和构?/span>Entity?/span>

据个人经验,使用数据驱动的承模式时很是向往lg模式Q感觉上它一个非常自然的扩展方向Q但ֿ其引入的额外的复杂性,其是需要游戏设计h员具有一定的~程能力Q所以一直不敢全盘接q用。但退一步,在引擎里仍然使用lg思想Q但Entity的组件构成在~译时固定,可以辑ֈ某种妥协Q这和采用承与数据驱动的折中类伹{?/span>

混入模式Q?/span>Mix-inQ?/span>

q是又一U常见的折中模式Q即使用C++的多重承,各个组件类混入一?/span>EntitycR如Q?/span>

class Mob: public GameObject, public Renderable, public Movable, public Attackable
{

}

q种Ҏ因其单而且非常W合多重l承设计思想而被很多引擎采用。当然缺点也是只能在支持多重l承的语a里用,而且当组件很丰富Ӟdynamic_cast变成一个代价高昂的操作?/span>

功能性与复杂性(Functionality vs ComplexityQ?/span>

~程领域最古老的原则之一是?#8220;单快?#8221;。但随着问题的复杂化Q程序也随之变得来复杂。好的方法应该能有效的降低或隐藏复杂性。但是,没有不带副作用的药(No silver bullet.Q,在取得更强大的功能的同时M带来额外的复杂性。我们需要做出权衡,在必要时牺牲一些功能,也就是要估算性h比?/span>

一般游戏内容制作h员不会或不太会编E,~程人员也不善于游戏的内容创造和数值^衡,q于复杂的系l会D需要两面兼儡人才Q会大大增加做出一ƾ游戏的隑ֺ?/span>



RedLight 2009-08-18 11:11 发表评论
]]>
游戏对象的实?/title><link>http://www.shnenglu.com/flashboy/archive/2009/07/29/91635.html</link><dc:creator>RedLight</dc:creator><author>RedLight</author><pubDate>Wed, 29 Jul 2009 14:04:00 GMT</pubDate><guid>http://www.shnenglu.com/flashboy/archive/2009/07/29/91635.html</guid><wfw:comment>http://www.shnenglu.com/flashboy/comments/91635.html</wfw:comment><comments>http://www.shnenglu.com/flashboy/archive/2009/07/29/91635.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/flashboy/comments/commentRss/91635.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/flashboy/services/trackbacks/91635.html</trackback:ping><description><![CDATA[<div id="dgrplqy" class=intro>狭义的游戏对象是指游戏世界中所能看到及可交互的对象Q如玩家、怪物、物品等Q我们这里也主要讨论q类对象在服务器上的l织及实现?/div> <div id="zdqczlt" class=content>   <p>  在大部分的MMOG中,游戏对象的类型都大同异Q主要有物品、生物、玩家等。比如在wow中,通过服务器发下来的GUID我们可以了解刎ͼ游戏中有9大类对象Q包括物?Item)、背?Container)、生?Unit)、玩?Player)、游戏对?GameObject)、动态对?DynamicObject)、尸?Corpse){?/p> <p>  在mangos的实CQ对象用类l承的方式,由Object基类定义游戏对象的公有接口及属性,包括GUID的生成及理、构造及更新UpdateData数据的虚接口、设|及获取对象属性集的方法等。然后分Z两类z对象Q一是ItemQ另一是WorldObject。Item即物品对象,WorldObject֐思义Qؓ世界对象Q即可添加到游戏世界场景中的对象Q该对象cd定义了纯虚接口,也就是不可被实例化,主要是在Object对象的基上又d了坐标设|或获取的相x口?/p> <p>  Itemcd又派兵出了一cBag对象Q这是一U特D的物品对象Q其本nh物品的所有属性及ҎQ但又可作ؓ新的容器cdQƈh自己Ҏ的属性和ҎQ所以实C采用了派生。mangos在实现时对Bag的类型定义做了点技巧,Item的类型ؓ2QBag的类型ؓ6Q这样在通过位的方式来表C类型时QBagcd也就同时属于Itemcd了。虽然只是很的一个技巧,但在很多地方却带来了极大的便利?/p> <p>  从WorldObjectz出的cd有好几U了QUnit、GameObject、DynamicObject和Corpse。Unit为所有生物类型的基类Q同WorldObject一P也不可被实例化。它定义了生物类型的公有属性,如种族、职业、性别、生命、魔法等Q另外还提供了相关的一些操作接口。游戏中实际的生物对象类型ؓCreatureQ从UnitzQ另外还有一cL生对象Player为玩家对象。Player与Creature在实C最大的区别是玩家的操作由客L发来的消息驱动,而Creature的控制是p己定义的AI对象来驱动,另外Player内部q包括了很多的逻辑pȝ实现?/p> <p>  另外q有两类Ҏ的CreatureQPet和TotemQ其对象cd仍然q是生物c,只是实现上与会有些特D的东西需要处理,所以在mangos中将其作为独立的zc,只是实现上的一点处理。另外在GameObject中也实现有派生对象,最l的l承关系图比较简单,׃ȝ地去d了?/p> <p>  从我所了解的早期游戏实现来看,大部分的游戏对象l构都是采用的类DU方式。可能与早期寚w向对象的理解有关Q当面向对象的概念刚出来Ӟ大家认ؓl承是面向对象的全部,所以处处皆对象Q处处皆l承?/p> <p>  cd现的是一U封装,虽然从云风那里出来的弃C++而{投C的声韛_能会影响一部分人,但是Q用什么语a本n是个h喜好及团队整体情况决定的。我们所要的也是最l的实现l果Q至于中间的步骤Q完全看个h。还是用云风的话_q只是一U信仰问题,我依焉用我所熟悉的C++Q下面的描述也是如此?/p> <p>  随着面向对象技术的深入Q以及泛型等概念的相l提出,软gE序l构斚w的趋势也有了很大改变。C++大师们常说的话中有一句是q样说的Q尽是采用组合而不是ѝ游戏对象的实现也有cM的{变,向于以l合的方式来实现游戏对象cdQ也是实现一个通用的entitycdQ然后以脚本定义的方式组合出不同的实际游戏对象类型?/p> <p>  描述的有些抽象,具体实现下一来仔细探讨下?br><br><br>在游戏编E精_四有三文章讲C实体以及实体理的实现方案,其中一文章说C实体理pȝ的四大要素:定义实体怎样沟通的实体消息Q实C实体cM码和数据的实体代码,l护已经注册在案的实体类列表Q和用来创徏、管理、发送消息的实体理器?/p> <p>  关于实体消息的内容之前讨Z件机制的时候做q一点说明,其实q也是按接口调用和按消息驱动的区别Q现在mangos的做法是完全的接口调用,所以引擎内部就没有M的实体消息。实体代码实现和实体理器是我们重点要讨论的内容?/p> <p>  另有一文章也提到了用类l箋的方式实现游戏对象的两大问题Q一是它要求pȝ中的所有对象都必须从一个v点衍生而成Q也是说所有对象类在编译的时候已l确定,q可能是一个不受欢q的限制Q如果开发者决定添加新的对象类Q则必须要对基类有所了解Q方能支持新cR另一个问题在于所有的对象c都必须实现同样的一些底层函数?/p> <p>  对于W二个问题,可以通过接口l承的方式来避免基类的方法太多。在mangos的实C采用了cM的方法,从Object虚基cL生的Unit和WorldObject仍然q是不可实例化的c,q两U对象定义了不同的属性和ҎQ分来实C同类型的对象。在游戏内部可以Ҏ对象的实际类型来Object指针向下转型为Unit或WorldObjectQ以调用需要的接口。方法虽然不够OOQ也q能解决问题。但是第一个问题是始终无法避免的?/p> <p>  所以我们便有了通用实体q么一个概念,其主要方法是原来基cȝ接口q行分类Q分C个个不同的子cMQ然后以对象l合的方式来生成我们所需要的实际游戏对象cd。这个组合的q程可以通过脚本定义的方式,q样便可以在q行时生成ؓ同的对象cdQ也p决了上面提到的第一个问题?/p> <p>  通用实体的实现方法在目前的游戏引擎及开源代码中也可以看到媄子。一个是BigWorldQ从提供的资料来看,其引擎只提供了一个entity游戏对象Q然后由游戏内容实现者通过xml和python脚本来自由定义不同类型的entitycdQ每U类型可有不同的property和不同的Ҏ。这样原来由基类定义的接口完全{Ud脚本定义Q具有非常强的灵zL?/p> <p>  另外q有一个是CEL中的entity实现。按照CEL的描qͼentity可以是游戏中的Q意对象,包括玩家可交互的对象Q如钥匙、武器等Q也可以包括不能直接交互的对象,如游戏世界,甚至d链中的一部分{。entity本nq没有Q何特性,具体的功能实现需要靠附加property来完成。简单来_property才定义了entity可以做什么,至于该怎么做,那又是依靠behavior来定义。所以,最l在CEL中一个游戏对象其实是由entityl合了多个property及多个behavior而生成的?/p> <p>  但是CEL中的property与BigWorld中的property意义不大一P在CEL中可定义的property其实是引擎内部要先提供的Q比如其CZ中所丄pcobject.mesh、pcmove.linear、pctools.inventory{,而BigWorld中的property是完全的自由定制。从q个角度来讲Q其实可以把CEL中的property看作是游戏的逻辑pȝQ也是我们上面所描述的,接口分类后所定义的子cR?/p> <p>  由引擎内部提供可选择的property与BigWorld所采用的完全自由定制property其实本质上是相同的。在用BigWorld实现的游戏中Q也不可能ؓ每种游戏对象cd都完全从头定义propertyQ基于代码利用的原则Q也会先定义一些小c,然后在entitycd定义时以自定义property的方式来包含q些类。当Ӟ我没有用过BigWorldQ上面的描述也只是基于游戏实现的大原则所做出来的?/p> <p>  描述的依然有些抽象,我们可以用wow及mangos代码来说明一下。mangos中ؓobject定义了一个属性集合,Ҏ对象cd的不同,q个属性集的大及保存数据也会有差异,另外游戏对象内部含有处理不同游戏逻辑的系l,如RestSystem、FloodFilterSystem、VariousSystem{等Q在player.h中以接口l的方式q行定义?/p> <p>  如果要将q种l构改ؓ我们描述的通用entitypȝQ可以让object只提供property注册和删除的接口Q这里的property定义与CEL中的相同Q放在mangos中也是上面说的RestSystem、FloodFilterSystem、VariousSystemq些。然后也通过xml文g的方式定义我们所需要的游戏对象cdQ如player,creature,item{,不同的对象类型可以选择加蝲不同的propertyQ加载的原则是需要哪些功能就加蝲哪些property?/p> <p>  对象的定义按上面的方法完成后Q对象的实现也需要做一些修攏V以前客L的消息是直接交由player来处理,AI也是直接调用creature的接口来完成一些功能,现在通用的entity内部已经没有M可用的方法,所有的实现都{Cproperty中,所以需要由各个property实现自己来注册感兴趣的事件及消息Qentity实现一个消息的转发Q{l对此感兴趣的property来处理。其余的实现没有什么不同了?/p> <p>  当然Q我们再做一Ҏ展,让property不光由引擎来提供Q用脚本本n也能定义propertyQƈ且可以通过xml来注册这些propertyQ这样便实现了与BigWorld一L完全自由Ҏ。这其实也就是将很多用C++实现的功能{Ud了python中,q种做法可作为参考,但不一定对所有h合适,臛_在我看来Q这L实现也基本只能由E序员来做,所以让E序员选择自己最擅长的语a可能会更易于开发和调试?/p> <p>有关游戏对象实现的描qͼ前面两篇文章中说的不甚清楚,主要是一直都要引用网上能够找到的资料来进行描qͼ以避免与公司引v不必要的ȝ。所以语a有些拼凑的感觉,丄例子也很不恰当,今天正好看到了游戏编E精_五和六上的两篇文章Q内定w差不多,<<Zlg的对象管?gt;>?lt;<Zlg的游戏对象系l?gt;>Q说的也是我上两文章想要描q的内容Q所以再补一,引用其中的部分文字进行明的说明?/p> <p> </p> <p>  传统的游戏对象管理系l采用承的方式来实玎ͼ例如Q所有的子类都从CObjectz。大多数情况下,直接z的也是抽象类Q其中带一些功能而另一些子cd不带q些功能Q比如可控制/不可控制Q可动画/不可动画{。mangos的实C基本是q种情况Q从Object直接z的Unit和WorldObject都是不可直接实例化的cR?/p> <p>  传统Ҏ的问题在于无法应寚w求的变化Q如要求武器也有动画效果时就无法处理了。如果硬要是q样做,那随着需求的啬,很多的方法会被放到基cMQ最l的l果是承树变得来头重脚轻,q样的类会失它的内聚性,因ؓ它们试图为所有对象完成所有的事?/p> <p>  是说到最后,基类会有一个很长的接口列表Q而很多的游戏对象cdҎ不需要实现其中的一些甚臛_部分接口Q但是按照这U结构却又必d实现。以至于于实C个非常庞大的对象Q而且惌修改一点功能会Dpȝ的大调整?/p> <p>  我们希望的系l是可以现有的功能l合到新的对象中Qƈ且在新的功能添加到现有的对象中时不需要重构大量的代码和调整承树的结构?/p> <p>  实现的方法就是从lg来创Z个对象。组件是一个包含所有相x据成员和Ҏ的类Q它完成某个特定的Q务。把几个lgl合在一起就可以创徏一个新的对象。如把Entitylg、Renderlg和Collectablelgl合在一L成了一个Spoon对象。Entitylg让我们可以把对象攑ֈ游戏世界中,Renderlg让我们可以ؓ对象指定一个模型进行渲染,而Collectablelg让我们可以拾取这个对象?/p> <p>  关于lg的实玎ͼ所有的lg都从一个基lg接口zQ可U其为IComponent。每个组件也有自q接口定义Qƈ且这个接口也需要从IComponentzQ类gq样QIComponent -- ICmpRender -- CCmpRender</p> <p>  q里的每个组件也是我在上一中所说的由引擎提供的属性,或者说在BigWorld中自己实现然后定义的属性,或者用mangos中的定义Q就是一个个的SystemQ虽然mangosq没有将其完全做成组Ӟ但是通过其代码注释可以看刎ͼ接口也是按功能组q行了分c,如果要拆分成lg也是比较方便的?/p> <p>  lg之间的通信有两U方法,一是用lgID查询到组件接口指针,然后调用接口ҎQ二是用消息的方式Q向对象中所有组件发消息。在初始化的时候,每一个组件类型都会告诉对象管理器应该接收什么样的消息?/p> <p>  查询接口的方法也是直接的方法调用,只不q接口不是全部在基类中,所以必d查询到指定的lg然后才能调用其接口。消息的使用前面已经说过多次Q其实现Ҏ也有q说明?/p> <p>  最后是关于游戏对象功能的扩展和游戏对象的定义。需要扩展功能也是需要实C个新的组Ӟ或者修改现在组件。在大多数情况下Q扩展都不会引vl构的很大调_受媄响的最多只是用到该组件的部分代码?/p> <p>  游戏对象定义可采用完全数据驱动的方式Q用xml或者脚本语a来定义对象类型,以及每个cd需要加载的lg。对象类型注册到对象理器后Q由理器提供创建指定类型的对象的方法。数据驱动的方式能够让策划自由定义游戏对象类型,q且随时可自由创建新的对象类型?/p> <p><br></p> </div> <img src ="http://www.shnenglu.com/flashboy/aggbug/91635.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/flashboy/" target="_blank">RedLight</a> 2009-07-29 22:04 <a href="http://www.shnenglu.com/flashboy/archive/2009/07/29/91635.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WoW API中的Luahttp://www.shnenglu.com/flashboy/archive/2009/01/12/71770.htmlRedLightRedLightSun, 11 Jan 2009 16:28:00 GMThttp://www.shnenglu.com/flashboy/archive/2009/01/12/71770.htmlhttp://www.shnenglu.com/flashboy/comments/71770.htmlhttp://www.shnenglu.com/flashboy/archive/2009/01/12/71770.html#Feedback0http://www.shnenglu.com/flashboy/comments/commentRss/71770.htmlhttp://www.shnenglu.com/flashboy/services/trackbacks/71770.html阅读全文

RedLight 2009-01-12 00:28 发表评论
]]>
LUA和C之间的函数调?/title><link>http://www.shnenglu.com/flashboy/archive/2009/01/04/71167.html</link><dc:creator>RedLight</dc:creator><author>RedLight</author><pubDate>Sun, 04 Jan 2009 13:43:00 GMT</pubDate><guid>http://www.shnenglu.com/flashboy/archive/2009/01/04/71167.html</guid><wfw:comment>http://www.shnenglu.com/flashboy/comments/71167.html</wfw:comment><comments>http://www.shnenglu.com/flashboy/archive/2009/01/04/71167.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/flashboy/comments/commentRss/71167.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/flashboy/services/trackbacks/71167.html</trackback:ping><description><![CDATA[     摘要:   <a href='http://www.shnenglu.com/flashboy/archive/2009/01/04/71167.html'>阅读全文</a><img src ="http://www.shnenglu.com/flashboy/aggbug/71167.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/flashboy/" target="_blank">RedLight</a> 2009-01-04 21:43 <a href="http://www.shnenglu.com/flashboy/archive/2009/01/04/71167.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lua脚本语法说明Q修订) http://www.shnenglu.com/flashboy/archive/2008/09/12/61701.htmlRedLightRedLightFri, 12 Sep 2008 10:03:00 GMThttp://www.shnenglu.com/flashboy/archive/2008/09/12/61701.htmlhttp://www.shnenglu.com/flashboy/comments/61701.htmlhttp://www.shnenglu.com/flashboy/archive/2008/09/12/61701.html#Feedback0http://www.shnenglu.com/flashboy/comments/commentRss/61701.htmlhttp://www.shnenglu.com/flashboy/services/trackbacks/61701.html
  Lua 的语法比较简单,学习h也比较省力,但功能却q不弱?br>  所以,我只单的归纳一下Lua的一些语法规则,使用h方便好查可以了。估计看完了Q就懂得怎么写LuaE序了?br>
  在Lua中,一切都是变量,除了关键字?br>
I.  首先是注?br>  写一个程序,L不了注释的?br>  在Lua中,你可以用单行注释和多行注释?br>  单行注释中,q箋两个减号"--"表示注释的开始,一直gl到行末为止。相当于C++语言中的"http://"?br>  多行注释中,?--[["表示注释开始,q且一直gl到"]]"为止。这U注释相当于C语言中的"/*...*/"。在注释当中Q?[["?]]"是可以嵌套的Q?span style="COLOR: red">在lua5.1中,中括号中间是可以加若q个"="LQ如 [==[ ... ]==]Q,见下面的字符串表C明?br>
II.  Lua~程
  l典?Hello world"的程序L被用来开始介l一U语a。在Lua中,写一个这LE序很简单:
  print("Hello world")
  在Lua中,语句之间可以用分?Q?隔开Q也可以用空白隔开。一般来_如果多个语句写在同一行的话,L用分号隔开?br>  Lua 有好几种E序控制语句Q如Q?br>
控制语句 格式 CZ
If if 条g then ... elseif 条g then ... else ... end
if 1+1=2 then print("true")
elseif 1+2~=3 then print("true")
else print("false"end

While while 条g do ... end
while 1+1~=2 do print("true"end

Repeat repeat ... until 条g
repeat print("Hello"until 1+1~=2

For for 变量=初? l点? 步进 do ... end
for i = 1102 do print(i) end

For for 变量1, 变量2, ... 变量n in 表或枚D函数 do ... end
for a,b in mylist do print(a, b) end


  注意一下,for的@环变量L只作用于for的局部变量;当省略步q值时Qfor循环会?作ؓ步进倹{?br>  使用break可以用来中止一个@环?br>  相对C语言来说QLua有几个地Ҏ明显不同的,所以面要特别注意一下:

  Q?strong>语句?/strong>
    语句块在C中是?{"?}"括v来的Q在Lua中,它是用do ?end 括v来的。比如:
    do print("Hello") end
    可以?函数 中和 语句?/strong> 中定局部变量?br>
  Q?strong>赋D?/strong>
    赋D句在Lua被强化了。它可以同时l多个变量赋倹{?br>    例如Q?br>    a,b,c,d=1,2,3,4
    甚至是:
    a,b=b,a  -- 多么方便的交换变量功能啊?br>    在默认情况下Q变量L认ؓ是全局的。假如需要定义局部变量,则在W一ơ赋值的时候,需要用local说明。比如:
    local a,b,c = 1,2,3  -- a,b,c都是局部变?br>
  Q?strong>数D?/strong>
    和C语言一P支持 +, -, *, /。但Luaq多了一?^"。这表示指数乘方q算。比?^3 l果?, 2^4l果?6?br>    q接两个字符Ԍ可以?.."q处W。如Q?br>    "This a " .. "string." -- {于 "this a string"

  Q?strong>比较q算
比较W号 < > <= >= == ~=
含义 大于 于或等?/td> 大于或等?/td> 相等 不相{?/td>

    所有这些操作符Lq回true或false?br>    对于TableQFunction和Userdatacd的数据,只有 == ?~=可以用。相{表CZ个变量引用的是同一个数据。比如:
    a={1,2}
    b
=a
    
print(a==b, a~=b)  --输出 true, false
    a={1,2}
    b
={1,2}
    
print(a==b, a~=b)  --输出 false, true


  Q逻辑q算
    and, or, not
    其中Qand ?or 与C语言区别特别大?br>    在这里,请先CQ在Lua中,只有false和nil才计ؓfalseQ其它Q何数据都计算为trueQ?也是trueQ?br>    and ?or的运结果不是true和falseQ而是和它的两个操作数相关?br>    a and bQ如果a为falseQ则q回aQ否则返回b
    a or bQ如?a 为trueQ则q回aQ否则返回b

    丑և个例子:
     print(4 and 5--输出 5
     print(nil and 13--输出 nil
     print(false and 13--输出 false
     print(4 or 5--输出 4
     print(false or 5--输出 5

    在Lua中这是很有用的特性,也是比较令hh的特性?br>    我们可以模拟C语言中的语句Qx = a? b : cQ在Lua中,可以写成Qx = a and b or c?br>    最有用的语句是Q?x = x or vQ它相当于:if not x then x = v end ?br>
  Q运符优先U,从低到高序如下Q?br>
     or
     and
     <     >     <=    >=    ~=    ==
     .. (字符串连?
     +     -
     *     /     %
     not   #(lua5.1 取长度运?/span>)     - (一元运?
     ^
和C语言一P括号可以改变优先U?br>
III.  关键?br>  关键字是不能做ؓ变量的。Lua的关键字不多Q就以下几个Q?br>    
and break do else elseif
end false for function if
in local nil not or
repeat return then true until while

IV.  变量cd
  怎么定一个变量是什么类型的呢?大家可以用type()函数来检查。Lua支持的类型有以下几种Q?br>
Nil I|所有没有用过的变量,都是nil。nil既是|又是cd?/td>
Boolean 布尔|只有两个有效|true和false
Number 数|在Lua里,数值相当于C语言的double
String 字符Ԍ如果你愿意的话,字符串是可以包含"\0"字符的(q和C语言L?\0"l尾是不一LQ?/td>
Table 关系表类型,q个cd功能比较强大Q请参考后面的内容?/td>
Function 函数cdQ不要怀疑,函数也是一U类型,也就是说Q所有的函数Q它本n是一个变量?/td>
Userdata 嗯,q个cd专门用来和Lua的宿L交道的。宿主通常是用C和C++来编写的Q在q种情况下,Userdata可以是宿ȝL数据cdQ常用的有Struct和指针?/td>
Thread U程cdQ在Lua中没有真正的U程。Lua中可以将一个函数分成几部䆾q行?/span>如果感兴的话,可以ȝ看Lua的文档?br>现在回过头来看看Q倒觉得不是线E类型。反而象是用来做遍历的,象是Iterator函数?br>如:
function range(n)
  local
= 0
  
while(i < n) do
    coroutine.yield( i )
    i = i + 1
  
end
end
可惜的是要l运行,需要coroutine.resume函数Q有炚w肋。请指教?br>

V.  变量的定?br>  所有的语言Q都要用到变量。在Lua中,不管在什么地方用变量,都不需要声明,q且所有的q些变量L全局变量Q除非我们在前面加上"local"。这一点要特别注意Q因为我们可能想在函数里使用局部变量,却忘了用local来说明?br>  至于变量名字Q它是大写相关的。也是_A和a是两个不同的变量?br>  定义一个变量的Ҏ是赋倹{?Q?操作是用来赋值的
  我们一h定义几种常用cd的变量吧?br>  A.  Nil
    正如前面所说的Q没有用过的变量的|都是Nil。有时候我们也需要将一个变量清除,q时候,我们可以直接l变量赋以nil倹{如Q?br>
    var1=nil  -- h?nbsp;nil 一定要写

  B.  Boolean
    布尔值通常是用在进行条件判断的时候。布值有两种Qtrue ?false。在Lua中,只有false和nil才被计算为falseQ而所有Q何其它类型的|都是true。比?Q空串等{,都是true。不要被 C语言的习惯所误导Q?在Lua中的的确是true。你也可以直接给一个变量赋以Booleancd的|如:
    theBoolean = true

  C.  Number
    在Lua中,是没有整数类型的Q也不需要。一般情况下Q只要数g是很大(比如不超q?00,000,000,000,000Q,是不会生舍入误差的。在WindowsXP能跑的当今主PC上,实数的运ƈ不比整数慢?br>    实数的表C方法,同C语言cMQ如Q?br>    4 0.4 4.57e-3 0.3e12 5e+20

  D.  String
    字符ԌL一U非常常用的高cd。在Lua中,我们可以非常方便的定义很长很长的字符丌Ӏ?br>    字符串在Lua中有几种Ҏ来表C,最通用的方法,是用双引h单引h括v一个字W串的,如:
    "That's go!"
    ?br>    'Hello world!'

    和C语言相同的,它支持一些{义字W,列表如下Q?br>    \a  bell
    \b  back space
    \f  form feed
    \n  newline
    \r  carriage return
    \t  horizontal tab
    \v  vertical tab
    \\  backslash
    \"  double quote
    \"  single quote
    \[  left square bracket
    \]  right square bracket

    ׃q种字符串只能写在一行中Q因此,不可避免的要用到转义字符。加入了转义字符的串Q看h实在是不敢恭l_比如Q?br>    "one line\nnext line\n\"in quotes\", "in quotes""
    一大堆?\"W号让h看v来很倒胃口。如果你与我有同感,那么Q我们在Lua中,可以用另一U表C方法:?[["?]]"多行的字符串括h。(lua5.1: 中括号中间可以加入若q个"="P?[==[ ... ]==]Q详见下面示?/span>Q?br>    CZQ下面的语句所表示的是完全相同的字W串Q?br>
= 'alo\n123"'
= "alo\n123\""
= '\97lo\10\04923"'
= [[alo
123"
]]
= [==[
alo
123"
]==]

    值得注意的是Q在q种字符串中Q如果含有单独用的"[["?]]"׃然得?\["?\]"来避免歧义。当Ӟq种情况是极会发生的?br>
  E.  Table
    关系表类型,q是一个很强大的类型。我们可以把q个cd看作是一个数l。只是C语言的数l,只能用正整数来作索引Q在Lua中,你可以用Lcd来作数组的烦引,除了nil。同P在C语言中,数组的内容只允许一U类型;在Lua中,你也可以用Q意类型的值来作数l的内容Q除了nil?br>    Table的定义很单,它的主要特征是用"{"?}"来括起一pd数据元素的。比如:
    T1 = {}  -- 定义一个空?/span>
    T1[1]=10  -- 然后我们可以象C语言一h使用它了?/span>

    T1["John"]={Age=27, Gender="Male"}
    q一句相当于Q?br>    T1
["John"]={}  -- 必须先定义成一个表Q还记得未定义的变量是nilcd?/span>
    T1["John"]["Age"]=27
    T1
["John"]["Gender"]="Male"
    当表的烦引是字符串的时候,我们可以写成Q?br>    T1.John
={}
    T1.John.Age
=27
    T1.John.Gender
="Male"
    ?br>    T1.John{Age
=27, Gender="Male"}
q是一个很强的Ҏ?br>
    在定义表的时候,我们可以把所有的数据内容一起写?{"?}"之间Q这样子是非常方便,而且很好看。比如,前面的T1的定义,我们可以q么写:
    T1=
    {
      
10,  -- 相当?nbsp;[1] = 10
      [100] = 40,
      John
=  -- 如果你原意,你还可以写成Q["John"] =
      {
        Age
=27,   -- 如果你原意,你还可以写成Q["Age"] =27
        Gender=Male   -- 如果你原意,你还可以写成Q["Gender"] =Male
      },
      
20  -- 相当?nbsp;[2] = 20
    }

    看v来很漂亮Q不是吗Q我们在写的时候,需要注意三点:
    W一Q所有元素之_L用逗号"Q?隔开Q?br>    W二Q所有烦引值都需要用"["?]"括v来;如果是字W串Q还可以L引号和中括号Q?br>    W三Q如果不写烦引,则烦引就会被认ؓ是数字,q按序自动?往后编Q?br>
    表类型的构造是如此的方便,以致于常常被人用来代曉K|文件。是的,不用怀疑,它比ini文g要漂亮,q且强大的多?br>
  F.  Function
    函数Q在Lua中,函数的定义也很简单。典型的定义如下Q?br>
    function add(a,b)  -- add 是函数名字,a和b是参数名?/span>
     return a+b  -- return 用来q回函数的运行结?/span>
    end

    h意,return语言一定要写在end之前。假如我们非要在中间放上一句returnQ那么就应该要写成:do return end?br>    q记得前面说q,函数也是变量cd吗?上面的函数定义,其实相当于:
    add = function (a,b) return a+end
当重新给add赋值时Q它׃再表C个函C。我们甚臛_以赋laddL数据Q包括nil Q这P赋gؓnilQ将会把该变量清除)。Function是不是很象C语言的函数指针呢Q?br>
    和C语言一PLua的函数可以接受可变参C敎ͼ它同h?..."来定义的Q比如:
    function sum (a,b,)
如果惛_?..所代表的参敎ͼ可以在函C讉Karg局部变量(表类型)得到 (lua5.1: 取消argQƈ直接?..."来代表可变参CQ本质还是arg)?br>    ?sum(1,2,3,4)
    则,在函CQa = 1, b = 2, arg = {3, 4}  (lua5.1:  a = 1, b = 2, ... = {3, 4})
    更可늚是,它可以同时返回多个结果,比如Q?br>
    function s()
      
return 1,2,3,4
    
end
    a,b,c,d 
= s()  -- 此时Qa = 1, b = 2, c = 3, d = 4

    前面说过Q表cd可以拥有Lcd的|包括函数Q因此,有一个很强大的特性是Q拥有函数的表,哦,我想更恰当的应该说是对象吧。Lua可以使用面向对象~程了。不信?举例如下Q?br>
    t =
    {
     Age 
= 27
     
add = function(self, n) self.Age = self.Age+end
    }
    
print(t.Age)  -- 27
    t.add(t, 10)
    
print(t.Age)  -- 37

    不过Qt.add(t,10) q一句实在是有点土对吧?没关p,在Lua中,我们可以写成Q?br>
    t:add(10)    -- 相当?nbsp;t.add(t,10)

  G.  Userdata ?Thread
    q两个类型的话题Q超Z本文的内容,׃打算l说了?br>
VI.  l束?br>  p么结束了吗?当然不是Q接下来Q我们需要用Lua解释器,来帮助理解和实践了。相信这样会更快的对Lua上手了?br>  pC语言一PLua提供了相当多的标准函数来增强语言的功能。用这些标准函敎ͼ可以很方便的操作各种数据cdQƈ处理输入输出。有兌斚w的信息,我们可以参考《Programming in Lua 》一书,也可以在|络上直接观看电子版Q网址为:http://www.lua.org/pil/index.html
  
备注Q本文的部䆾内容摘、译自lua随机文档?br>相关链接Q?br>1. Lua 官方|站Q?http://www.lua.org
2. Lua Wiki|站Q你可以在这里找到很多相关的资料Q如文档、教E、扩展,以及C/C++的包装等Q?http://lua-users.org/wiki/
3. Lua 打包下蝲Q包括各U^台和~译器的工程文g如vs2003,vs2005Q:http://luabinaries.luaforge.net/download.html


RedLight 2008-09-12 18:03 发表评论
]]>
Ʒþþþþר| þõӰһ| ŷСþþþþþ| ŷ龫Ʒþþþ| Ʒþþþ㽶| ɫۺϾþþþۺһ| ҹƷþþþþ˳| ݺݾƷþþĻ | ҹƵþþþһ | þֻоƷ18| ŷպƷþþþ| ޹˾þһþ| þþþƷ| þþƷ| þˬˬƬAV| þþþƷ޳18վ| þrоƷƵ| ޹Ʒþþþվ| ҹƷþþþþþС˵| ۺۺϾþ69| þˬˬAVƬ| þרƷ| vaþþþúݺ | 91Ʒ91þ| Ʒþùһ㽶| þþƷ99þþ㽶| Ƭѹۿþ| һɫþ88Ʒۺ| Ʒ԰״̼þþ| Ʒ18þþ⺾| þþƷɫ鶹| þˬˬƬAV鷳 | ޹Ʒþþþվ | Ʒһþ| þþ뾫Ʒҹ| ԭƷ99þþƷ66 | þþþ?V| 69ƷþþþAPP | ŷСþþþþþ | þþƷŮAV| þþþþŮ|