??xml version="1.0" encoding="utf-8" standalone="yes"?>国产av无码专区亚洲av桃花庵,亚洲av片不卡无码久久,亚洲午夜国产精品http://m.tkk7.com/yangsail/archive/2005/07/24/8318.html蓝色雪焰蓝色雪焰Sat, 23 Jul 2005 16:19:00 GMThttp://m.tkk7.com/yangsail/archive/2005/07/24/8318.htmlhttp://m.tkk7.com/yangsail/comments/8318.htmlhttp://m.tkk7.com/yangsail/archive/2005/07/24/8318.html#Feedback0http://m.tkk7.com/yangsail/comments/commentRss/8318.htmlhttp://m.tkk7.com/yangsail/services/trackbacks/8318.html如何~写用TCP/IP的通讯E序

   最q在|上不断的看到有人问如何用BCB的TServerSocket和TClientSocketq行~程的问题,所以决定把我的一些编E经验告诉给大家,让大家能够尽快的掌握他们的用法?BR>
首先要讲一下他们的一些设|(属性)Q?BR>TServerSocket 的几个属?BR>Active       
    是否是工作状态,可以把它讄为ture或false来启动和停止侦听?BR>Port
    本机侦听的端口,可以讄Z大于1024的数Q?BR>ServerType   
    服务端的工作方式Q有两个选择Q一个是stNonBlocking 非阻塞方式,一个是stThreadBlockingU程d方式Q默认是非阻塞方式。用非阻塞方式编E比较简单(我个为)Q用d方式Ҏ个连接必自qU程来控制收发?BR>ThreadCacheSize  
    ~冲的线E个?当ServerType是stThreadBlocking时有效?BR>TClientSocket 的几个属?BR>Active      
    是否是工作状态,可以把它讄为ture或false来同服务端徏立或断开q接?BR>Host    
    服务器(ServerSocketQ的计算机名Q是一个字W串
Address
服务器(ServerSocketQ的IP地址
ClientType
   客户端的工作方式一U是ctNonBlocking非阻塞方式,一U是ctBlockingd方式Q默认是非阻塞方?BR>Port
同服务端(ServerSocket)q接的端口,q个端口是ServerSocket的侦?nbsp;             端口
在设|ClientSocket的(HostQ主机名和设|(AddressQIP地址是等效的Q但设主机名需要网l具有DNSQ域名解析服务)服务器,而且设主机名要比设主机的IP地址q接的速度慢一些。徏议用Address来同ServerSocketq行q接?BR>
讄好所有的属性后QServerSocket控g可以通过它的Active属性置为true来进行侦听了。ClientSocket可以通过讄它的Active属性来同ServerSocketq行q接。连接成功就可以q行通讯了。在q个q程中会产生一些事Ӟ下面说说他们各自的事件?BR>
TServerSocket的几个事?BR>OnAccept
    当一个客户同服务端连接成功后产生q个事gQ生这个事件后q个q接可用了Q可以对q个客户q行发送和接收数据?BR>OnClientConnect  
当一个客h在同服务端徏立连接的时候生此事gQ在q里你可以决定是否接受这个连接?BR>OnClientDisconnect
当一个客户同服务端的q接断开的时候生此事gQ你需要在q里q行一些处理,如从q接列表中清除次q接释放内存{?BR>OnClientError
当客户同服务端出现错误时产生此事Ӟ在此事g中你可以通过讄ErrorCode Q?0来屏蔽系l的错误提示。这样就可以避免讨厌的英文错误了。根据ErrorEvent的不同的值来得知发生了什么错误,它有一下几中错误类?BR>eeGeneral   未知错误
eeSend    发送数据出现错?BR>eeReceive   接收数据出现错误
eeConnect   客户hq接时出现错?BR>eeDisconnect 客户断开q接时出现错?BR>eeAccept     接受一个客h发生错误
    一般来Ԍ当发生错误的时候这个客Lq接已l不可用了,要对q个客户q行q接p|处理?BR>OnClientRead
当服务端收到客户端发来的数据的时候生此事g。接收客L的数据都在这里进行?BR>OnClientWrite
当服务端发送数据的时候生此事g?BR>
TClientSocket的几个事?BR>
OnConnect
同服务端QServerSocketQ连接成功后生此事gQ生此事g后才说明q个q接可用了,q时才可以向ServerSocket发送数据?BR>OnConnecting
正在同服务端q行q接是生此事g?BR>OnDisconnect
同服务端的连接断开后生此事gQ生此事g后ClientSocket的Active属性就为false了,q时q个q接׃可用了,必须重新q行q接才能向服务器发送数据?BR>onError
当Socket发生错误时生此事gQ这个事件的意义和ServerSocket的Error事g完全一P只是它没有eeAccept错误?BR>OnRead
当接收到服务端发来的数据后生此事g?BR>OnWrite
当向服务端发送数据的时候生此事g?BR>
上面介绍了一下这两个控g的基本属性和事gQ在掌握一些方法就可以用这两个控gq行~写通讯E序了,今天写的有写累了Q改天在写它的方法ƈ具体使用q两个控件编写一个通讯E序Q有两个选择Q一个是局域网的聊天程序,一个是局域网内的控制E序Q大家喜Ƣ那一个呢Q给点徏议吧.



蓝色雪焰 2005-07-24 00:19 发表评论
]]>
游戏完成q性的技?/title><link>http://m.tkk7.com/yangsail/archive/2005/07/24/8317.html</link><dc:creator>蓝色雪焰</dc:creator><author>蓝色雪焰</author><pubDate>Sat, 23 Jul 2005 16:16:00 GMT</pubDate><guid>http://m.tkk7.com/yangsail/archive/2005/07/24/8317.html</guid><wfw:comment>http://m.tkk7.com/yangsail/comments/8317.html</wfw:comment><comments>http://m.tkk7.com/yangsail/archive/2005/07/24/8317.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/yangsail/comments/commentRss/8317.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/yangsail/services/trackbacks/8317.html</trackback:ping><description><![CDATA[<H3 style="CURSOR: hand" onclick=switchDisplay(408)>游戏完成q性的技?/H3> <div class="9hp9f99" id=excerpt_408>概要Q关于游戏^衡性技巧的资料q不普及。这文章有意通过描述游戏q和不q的性质Q以及如何达到游戏^衡的q方法这两个斚w来填补这个信息空白。这个方法非怾赖于现有的系l工E技能以及公认的游戏设计理论。大量的案例学习及小故事被采用来帮助方法和具体的设计结合v来?BR></DIV> <div class="ljzdzzh" id=content_408 style="DISPLAY: block"> <P>译Q张三丰 语嫣<BR>作者:Tom Cadwell<BR><BR> 一个伟大的设计和一个杰出的游戏之间往往只有一个缺乏游戏^衡性的区别。多数游戏策划要通过反复试验才学会游戏^衡的基本原理。如果他们幸q的话,也许可以得到同事传授的一两个窍门。精通游戏^衡的人往往警惕C守着自己的秘密,或者无心与人分享。结果是虽然有关游戏q性的信息实存在Q但是可得到的却很少。这文章试NqC个获得游戏^衡性的Ҏ?BR><BR>什么是游戏qQ?BR><BR>  Sid Meier 曄说过Q“一个游戏是很多有趣的选择的集合。”因此得出的是如果游戏失d^衡,׃减少q些选择而媄响游戏性。一个理想的游戏应该l过一pd的选择Q最后以胜利或其它完成的条gl束。有时一些选择明显成ؓ唯一的选择Q或明显是无效的。如果在某一阶段Q游戏出C有唯一的选择Q而游戏却没有l束Q就说明游戏的^衡性有了问题?BR><BR>  几乎所有通常所谓的不^衡都来自选择权的减少。例如,在一个策略游戏里Q如果某一U部队的作用和费用相比过于划,׃造成其它的部队几乎或完全没有作用。这U情况不仅只留给玩家一个选择Q无从选择Q,而且使玩家受到很多不相关的干扰。这些干扰实际上让游戏变得比较迷乱,减损了游戏性,而且让玩家感到灰心?BR><BR>  游戏大富?Monopoly)中就有很好的游戏不^衡性的例子。在游戏的后期,玩家们L量拖长呆在监狱里的旉。显然地Q玩家在游戏后期的最好的{略是q监p且不付钱出来,希望别hq入自己的领土而破产。在玩大富翁的最后阶D,无需再作选择Q游戏基本结束了。没有h再选择是否购买财Q也很少有机会再Ҏ游戏规则新的财Q因为房子已l被用完Q,而且因ؓ资已经被几个h集中Q所以也不再有交易可<BR>做。一旦生这U情形,游戏变成每个玩家有一定的机率莯而基本上l束了。此时玩家可以做的很,除非靠运气得胜。这情景与游戏前期及中期大相径庭Q那时玩家往往忙于大施战术、y妙夺取利益、陷宛_手或谨慎购买“重量”黄艌Ӏ绿色或p色的C?BR><BR>  q只是一个不q性的举例说明。在游戏中存在许多不同种cȝ不^衡性。所有的不^衡性都与没有选择性或~Z选择性有兟?BR><BR>?太昂贵却用处不大和便宜而且有效Q游戏选择通常与游戏代L联系Q不是牺牲其它的选择、游戏金钱或其它的商品。当一个选择太昂贵以致用处不大,或者太便宜而成为明昄选择Ӟ游戏的不q性就出现了,因ؓ有一些游戏选择无效了。虽然此cMq性最为普遍,但是通常l过单地调整q些选择的h格或者是效果可以纠正过来?BR><BR>?玩家旉的不qQ大多数游戏q性对比的基础是以玩家Z个选择而必L弃其它的各种不同选择的代h衡量。我们很Ҏ忽视玩家必须消耗时间执行每一个选择。在一个即时游戏里Q玩家在游戏里没有无限的旉Q所以时间不仅是一个资源,而且是一个有限的资源。在一个非x游戏里,游戏旉不受限制Q但是玩家的旉是受限制的。这U不q性基本上是另一U太昂贵或太廉h不^衡性的表现Q只是这里这些游戏的代h不是有Ş的。游戏星际争?Starcraft)里的虫族(Zerg)是一个很好的q种不^衡的例子。虽然虫族从h上与其它族类是^衡的Q但是就玩家的时间而言他们很容易被刉及使用。主要由于这个特点,虫族在游戏星际争霸发行之后大U长?个月中,在联赛与竞赛中一直是最受欢q的U族?BR><BR>?技术水q的不^衡性:随着玩家的游戏技能不断提高,不同的游戏选择的相Ҏ效性也会改变。如果一U选择Ҏ操作Q而另一U极难操作,则结论是一个资q家和一个新玩家的对q两U选择的相Ҏ效性的判断是完全不同的。这是游戏开发者的一个常见的陷阱Q因Z们一般比较接q“高U玩家”的水^Q所以经常看不见新玩家所要面对的问题。但是从另一斚w看,随着操作水^的提高,而游戏性也同时“进化”,通常被认为是一件好事。所以注意到q种q性很重要Q但是也要认识到上面说的现象也很普遍?BR><BR>?强制的劣势或优势Q在一个对战的游戏里,一些操作的l合使得某一Ҏh优越性。这样不仅是典型的不q性(因ؓ有一个选择明显最好)Q这U状况还是不公^的。在一个多人游戏中Q最好避免不公^的情况出玎ͼq也是保证游戏^衡的重要一招?BR> <P>  所有的不^衡性最l归lؓ没有选择性。只要记住这个原则,容易区分可校正的不q性及Ҏ的不q性?BR><BR>如何辑ֈ可^衡?BR><BR>  游戏q性通常被认为是alpha或beta试的事情,但事实上像M工程Q好的准备工作是实现良好游戏q的关键。优U的游戏设计具有极大的可^衡性,也就是指游戏pȝ可以较容易地调整到^衡的状态。如果系l没有可q性,费尽周折也不可能游戏调整到q?BR><BR>  一个游戏是一个系l,在设计初期应用良好的pȝ设计方式带来较好的可^衡性。好的系l设计方式可以分成三个重要步骤:游戏要素的模块性,q诏的设计宗旨及对复杂性的控制与调节。在设计的早期就采用q些Ҏؓ设计师在游戏试的alpha和beta阶段节省大量的时间?BR><BR>游戏要素的模块?BR><BR>  游戏要素的模块性归l于每个游戏要素只ؓ了一个特别目的存在,如果可能的话Q尽量做到只有一个单一的目的。只要诏彻这个原则,调整一个游戏要素只会改变游戏的某个斚w而不是许多方面?BR><BR>  有一个很好的例子Q说明游戏要素缺乏模块性会造成游戏开发h不必要的ȝ。在星际争霸的beta试中,暴雪QBlizzardQ星际争霸的开发hQ有一套相当清晰的伤害pȝQ其中每一늧各有三种伤害方式Q爆炸性的Q标准型的或冲击性的。每U伤x式都有一个根据外型大而不同的伤害pL——爆炸性伤宛_大型目标最有效Q冲L伤宛_型目标最有效Q而标准型伤害可用于Q何目标。其中一个兵U——飞龙(MutaliskQ,不断l^衡性带来问题,因ؓ功能性上看,不可以被分ؓ大、中或小型中的一U。如果将飞龙设ؓ中型늧Q则它对于爆炸性武器类型的늧来说抉|力太强;如将其设为大型,则其相对爆炸性武器类型的늧Q这U兵U一般是飞龙的天敌)又过于脆弱。暴雪(BlizzardQ不能仅仅修改爆炸性相对于大型늧或爆炸性相对于中型늧的伤害系敎ͼ因ؓq样做的话就会媄响一大批其它늧的设|。也无法修改爆炸性武器兵U的d|因ؓq样会媄响其它的很多的设|?BR><BR>  更让人困惑的是飞龙有两个重要角色——防I军与防步兵Q陆战兵U没有空中攻击能力)Qƈh相同的基本伤宛_Q而其他类似的兵团Q侦察机QScout、幽灉|机-WraithQ却有不同的武器pȝQ可以根据具体角色进行调整?BR><BR>  因ؓ在伤害系l和飞龙的设计上~Z模块性的原因Q暴雪直到游戏上市后五个月才佉K龙兵U达到^衡。这q不是因Z正是不可能做刎ͼ而是因ؓ~Zpȝ模块性而修正非常困难。飞龙在星际争霸里具有一定独特的用途,如果暴雪它的^衡参C其它不相关的늧分开设计Q^衡将大ؓҎ。最单的Ҏ是为飞龙(及其它类似兵团)d一个独立的cdQƈl予它一个针对各U伤害的自己的防御系数。如果设计师飞<BR>龙的I军与地面攻d分开来,调节q也会变得单?BR><BR>  当然Q星际争霸的多数设计都有相当E度的模块性。施法者(SpellcasterQ兵U具有清晰的用途和相对Ҏ的角色就是一个很好的例子。事实上许多法QSpellsQ,包括寄生虫(BroodlingQ和EMP振荡波(EMP BlastQ,h非常Ҏ的作用,使调整这些兵U的q性就Ҏ得多?BR><BR>  良好的系l模块性不仅是游戏q性的前提Q它q是朝着解决的方向走q一步。有一个良好的模块性可以设计师针对各U特D问题轻松进行调_而不会媄响到其它pȝ?BR><BR>q诏的设计宗?BR><BR>  q诏的设计宗旨可能是在初始设计阶D要遵守的最重要的原则,但是往往Ҏ因ؓ政策问题、疏忽大意或~Z良好沟通而被忽视。连贯设计宗旨的定义是如果游戏要素没有根据游戏的大局q行同步设计Q最好的l果是它会玩家偏移主要的游戏感觉,最坏的可能性是它会损害主要的游戏感觉。这U情况存在于~Z中心控制或开发时间很长的游戏中?BR><BR>  较有名的多用Ll游戏(MUDQDurisQLand of BloodlustQ是Everquest—“无的d”的原型Sojourn的姐妹版Q就因此带来太多问题。其中一个例子是Q某个程序设计h自行~入一个他自己感兴的角色cd。虽然这个角色类型本w很有意思,但是它其它几个cd变得无用或大失威力。这个角色类型拥有了其它U族专有的技能,而正是这些技能的专有性才使得q些U族实用而且好玩。这个程序员q带来很多类似的?BR>戏^衡性问题。他的主要目的是创造一个他感兴的cd。这与多用户|络游戏开发h惌创造有、独创的角色q与整个pȝ相吻合的愿望相冲H。他的类型非但不独特Q因为是从其它各cd中各取一部分特点)Q还与游戏的其它部分格格不入?BR><BR></P> <div class="3tfjpf3" id=content_409 style="DISPLAY: block"> <P>复杂性控?BR><BR>  复杂性控制应概括为:“保持简单、易懂”。过于复杂的游戏pȝ让h费解Q因此,也更隑ց到^衡。一个过于复杂的pȝ通常是因为最初的设计太糟p和无休止的d补丁Q理Zq些补丁是合理,但实际上是不q诏的一团糟Q,或者是太常见的“太多厨师呆在一个厨戉K”的现象Q这通常也说明缺乏设计宗旨一致性的问题。复杂性控制的另外一个优点就是它避免了一些潜在的游戏性的问题。尤其是Q正如复杂的游戏pȝ让h费解也因此不好^衡,也更难让玩家理解Q甚至从某一E度开始玩家很隑ֆ享受游戏。一个很常见的设计错误是Z游戏复杂化而牺牲游戏深度,那将Ҏ戏^衡调整造成极大的困难,q成Ҏ戏性的困惑和费解?BR><BR>基本游戏qq程<BR><BR>  除了基本的规则和技巧之外,q程是非帔R要的。游戏的qq程有几个步骤,每个步骤都有各种各样的技巧?BR><BR>  首先要考虑的是让游戏进入一个有及可玩的境界,q就需要宏观调控,或者说让游戏中的大部分要素臛_辑ֈ基本上^衡,而且不存在Q何要素过分地不^衡。只要达到这个状态,可以l细调游戏要素的具体部分Q如RTS游戏里的U族或派pR?BR><BR>  当然在游戏alpha试阶段之前通常应已q行了宏观调_所以可能随着新功能的增加要重新进行调整。家园(HomeworldQ的ȝ划Erin Daly提出Q应相关的功能在同一旉加入Q然后做一个宏观调控,基本上这是在整个开发过E中保持游戏可玩性的最有效的方法?BR><BR>  一旦实现最后的宏观调整Q最好在alpha试阶段的后期,可以对游戏q行微观调控1使游戏^衡达到完的E度?BR><BR>宏观调控<BR><BR>  提供一个可q的游戏系l显然只是达到游戏^衡的W一个步骤。即便是最完美的设计也需要变成现实,而在实施的过E中错误׃出现Q在初期设计中就l常会出现小错误。许多游戏h值在整个游戏实现之后才能被清楚认识到。在q些情况下,设计者必dalpha试阶段之前及测试期间运用宏观调控技巧校正^衡倹{?BR><BR>  宏观调控应在微观调开始之前结束;如果游戏的基q在不断改变Ӟ较小的^衡性的改变变得没有效果而无用。在q行宏观调时Q目的是“找到”在设计案中描述的游戏性目标。当Ӟ在你q不清楚如何表明核心游戏性时是不可能q行游戏l节的调整?BR><BR>  Z瞄准核心游戏性,明确地说明核心游戏性及其如何体现是很重要的。只要做到这一步,可以徏立一定的基线Q也是Ensemble Studios1所谓的“定锚”。D例说明,你也许设立游戏速度的基Uؓ“大U?0分钟长的游戏”,或者设立角色韧性的基线为“被一个危险怪兽d3ơ是致命的”。一旦你为每个游戏因素(一个地图、一个角色类型,一D对话等{)都找到满意的基线Q就可以利用q些游戏要素基线为根据扩展游戏?BR><BR>q性数?BR><BR>  一旦完成某一特定要素的宏观调控,在有些情况下可应用^衡性数学将l果复制到类似的要素中去。虽然用q性数学改善系l的功效q不定Q原因是很难计算一些微妙的l节Q但是它对确定不同游戏要素中的基U还是有效的。公认的、几乎对每一个游戏都有帮助的一个公式是成本效率方程式?BR><BR>成本效率公式说明Q针对一个成分来_<BR>游戏威力×耐久?效力<BR><BR>而且Q?BR>qx根(游戏威力×耐力÷成本的^方)=成本效力<BR><BR>  游戏威力有可能是火力Q伤x×发速度Q或Ҏ。耐力可以是用次数或被击Ҏ。成本代表游戏资源,通常是金子、钱币或回合Q如赛中走一步的真正成本是一个回合)。另一个有用的方程式主要适用于策略游戏和其它“战斗”场景的是分解式方程式。“分解式”反应了战斗场景中众多小体ȝ有效性虽然与几个大群体的战斗力相{,但效力却不相同的特点。众多小体通常效力,当然q是假设不存在其它微妙的因素Q如大团体攻d늧Ӟ杀伤力太大而造成费Q。这是因为群体在个体逐渐d之后逐渐丧失威力Q而一个大늧可以支撑较长旉Q所以不会因逐渐损失而失L力。据此,相对有效性的公式被定为:<BR>有效性的减损Q相对于较小的个体)=<BR>0.5+0.5×[较大个体的数量ï个体的数量Q相同的hQ]<BR><BR>所得到数字的倒数则是较大个体有效性的增加?BR><BR>  q些公式和其它“^衡性数学”对于初步的q性特别有用。最好避免从数学上实现完的q性,除非是相当简单的游戏pȝ。比如说Q因为游戏规则简单,q游戏Riskq不是特别困难,且玩家的选择可以作到相当的量化。^衡游戏大富翁QMonopolyQ是可能的,但是会比游戏Risk困难Q因为随机因素(如滚骰子Q相对于Risk来说可造成更普遍的影响Q而且也因为大富翁有更多数量的特别游戏因素Q运气牌、抵D则,监狱<BR>{等Q。譬如在一个现代的RTS中,能够在这h多复杂性的情况下得到完的数学q性,q当于完成了博士论文?BR> <DIV></DIV> <P> 一旦游戏已受宏观调控,游戏的^衡必要q入l节调校。如果游戏至达到有点乐可aQ且不存在明昄问题Q则已基本上完成宏观调控q可开始{向微细节。微观调控是游戏{划Zq一步完^衡性而实施的手术。一个小手术一般被定义为:变化值相对于一个“全球”数|影响许多其它的游戏要素)要少?0%Q相对于一个“地Ҏ”数|一个单一游戏要素Q则应少?0-40%?BR><BR>  微观调控最大的挑战是找到问题。一旦找到问题,可以开始稍微调整数|但要注意不要因此再生出新的问题。良好的要素模块和预先计划在q一阶段很有效果——没有它们,可能做不到在一个合理时间范围内完成游戏的^衡?BR><BR>辨识较小的不q?BR><BR>  {划有几个技巧可辨识较小的不q性。其中最明显的做法是大量地测试游戏,L一贯受惠或占优势的ҎQ或L从不被用的Ҏ。另一个常用方法是与一个试验h或另一个策划讨论假讄情景或与其对战,扑ֈ一个一致认Z产生的结果,然后在游戏中试是否会发生同Ll果?BR><BR>  如果{划用第一U方法,只是L占优势(或从不被使用Q的ҎQ确定这U情况生的实际原因是很重要的,q确认事情是否应该这样发展。对不^衡性进行分c,q尝试将其归cd典型的不q性中Q有助于理解问题。基本上是了解不^衡性的cd及特征就能够调整它?BR><BR>  q年来,愈加行的方法是U密记录Q不告诉玩家Q游戏成果及l计数据。游戏世U帝国(Age of EmpiresQ,雪乐山(SierraQ发表的几款游戏及斗争阴影(StrifeshadowQ都受益于这个技巧。有时这些统计数据具开导性,有时也极兯导性?BR><BR>  Ҏ有的数据都应有所保留。有时一个不成熟的测试h会带来很不正确的结果,只因Z们不熟悉游戏Q而且没有Z全面试Q或只是试最Ҏ的部分)。同LQ一个过于成熟的试人群也有可能忽视其它{略的潜力,或被困在一个很高却较模糊的不q点,而这些不q与其它更明显的不q点相比显得不那么紧迫。Ethermoon׃公司在游戏斗争阴影里应用的一个极为有效的技巧就是夸大在beta阶段的补丁中的游<BR>戏^衡性变化,来怂恿玩家试新的战略Q而不再l“抵抗”新的变化?BR><BR>  发现不^衡性的W二个方法有时被UCؓ“追逐不q性”,也就是一个假定的情景被定义后Q而由此生的各种可能的行动及l果都应是符合设计的。例如,一个坦克部队的冲锋应该被认为打败一个轻型R队的q攻Q但同时也应该受到轻度伤宻I而面寚w坦克步兵团的反攻则应受到重创。如果在实际的游戏中Q一个坦克部队的冲锋可完全歼灭一个轻型R队ƈ可以与防坦克步兵团不分胜负,此时坦克部队的过于强大就造成了不q<BR>性。追逐不q性是十分重要的,如果严格地执行,很容易就可以发现75%以上的较不q性问题。游戏往往不按照策划所愿望的某U特别方式发展,特别是在一个对抗型的多人游戏中Q一个“地区性”^衡h值的微小变化可以造成游戏的^衡与不^衡?BR><BR>  要紧记的一条是无论何时q行不^衡性的搜烦Q在游戏早期所讄的游戏要素,往往比后期的游戏要素要敏感得多。仅仅因Z个早期游戏要素的不^衡性会影响在它之后讄的所有东西,而后期游戏要素能够制造麻烦的旉有限。正如有必要在做微观调控之前先做好游戏的宏观调控Q也有必要先q早期的游戏因素?BR><BR>修整较小的不q?BR><BR>  一旦L识ƈ证明了不q性,是否Ҏq行修正呢?是的Q如果游戏已被设计ؓҎ调整Q?一个非常可调的游戏具备的素质能让设计师在不间接影响其它游戏因素的情况下Q专门对付某一不^衡性?BR><BR>  校正的重要一Ҏ保持l调的水准(往的斚w惻IQ尤其是升游戏的时候。一个过于强大的游戏要素Ҏ使其它要素失L力,而一个过于无力的游戏要素则会被忽略而毫无效果?BR><BR>  q很重要的一Ҏl调时不要媄响到其它的游戏数|譬如Q在角色扮演游戏里考虑一个叫做“火球”的W咒Q它是火pȝ咒的一U。如果火球威力过大,{划可做的就是全面降低火p魔法的威力Q或火球降U。很明显你应该做的是选择“地Ҏ”的解决ҎQ在l调全面火系法之前火球降U。这是一个很单的例子Q在大多情况下,游戏要素之间都存在一定程度的互相依赖。}慎地考虑一个改变将会带来的冲击力,试<BR>使用专门解决问题而不影响其它游戏要素的方法?BR><BR>  最后,避免“过度解决”不q性。当{划在同一旉q用多重不同的细调方法来解决一个特定问题时׃产生“过度解决”的情Ş。这样就很难军_变化所带来的效果,因ؓ你应用了多重独立的可变性来影响一个不独立的可变性。“过度解决”也有可能因意外地媄响其他游戏要素而带来麻烦?BR> <DIV></DIV> <P>ȝ<BR><BR>  开发游戏过E当中,在面对许多细节所带来的庞大冲L很容易偶忽视最l目标。保持真实地对待所惛_到的游戏性,从根本上贯彻游戏q的原则是很辛苦的Q但只有q样才可以保证高质量的游戏^衡,q且避免beta试拖得太久。多人游戏日渐受到青睐,游戏q应尽可能地做到最好。太多充满希望的多h游戏都因为^庸的游戏q而黯然失艌Ӏ? <DIV></DIV></DIV></DIV><img src ="http://m.tkk7.com/yangsail/aggbug/8317.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/yangsail/" target="_blank">蓝色雪焰</a> 2005-07-24 00:16 <a href="http://m.tkk7.com/yangsail/archive/2005/07/24/8317.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java2基础 ?amp;{(一Q?/title><link>http://m.tkk7.com/yangsail/archive/2005/04/09/3046.html</link><dc:creator>蓝色雪焰</dc:creator><author>蓝色雪焰</author><pubDate>Sat, 09 Apr 2005 12:05:00 GMT</pubDate><guid>http://m.tkk7.com/yangsail/archive/2005/04/09/3046.html</guid><wfw:comment>http://m.tkk7.com/yangsail/comments/3046.html</wfw:comment><comments>http://m.tkk7.com/yangsail/archive/2005/04/09/3046.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://m.tkk7.com/yangsail/comments/commentRss/3046.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/yangsail/services/trackbacks/3046.html</trackback:ping><description><![CDATA[1.什么是字节码?它对Java的InternetE序设计Z十分重要Q?BR>字节码是一U高度优化的指o集,由Javaq行时解释器执行Q可以帮助Java获得可移植性和安全性?BR><BR>2.面向对象E序设计?个重要原则是什么?<BR>装、多态性和l承?BR><BR>3.什么是变量Q?BR>变量是一U命名的内存地址Q变量的内容可以在程序运行时修改?BR><BR>4.什么样的变量名无效Q?BR>变量名只可以?字母QA/aQ、下划线Q_Q及圆W号Q?Q开_数字做开头的变量无效?BR><BR>5.如何创徏单行注释与多行注释?<BR>单行注释以?/开始”,在行束。多行注释以?*”开始,以?/”结束?BR><BR>6.语句在一行中的放|位|有限制吗?<BR>没有限制。Java是一UŞ式自q语言?BR><BR>7.JavaZ么要严格指定其简单类型的取D围和行ؓQ?BR>Java严格指定其简单类型的取D围和行ؓ是ؓ了确保跨q_的可UL性?BR><BR>8.Java的字W类型是什么?它与其他大多数程序设计语a的字W类型的不同之处是什么?<BR>Java的字W类型是char。Java字符采用Unicode~码格式而不是ASCII格式Q后者是大多数其他计机语言采用的格式?BR><BR>9.因ؓM?值都为trueQ所以boolean值可以取M你想要的|对吗Q?BR>不对Qboolean值只能是true或者false?BR><BR>10.解释自增q算W的前缀形式与后~形式的不同?<BR>当自增运符在其操作C前,Java会先执行对应的操作Q然后获得操作数的值用语表辑ּ的其他部分。如果运符位于操作C后,Java 会在自增之前获得操作数的倹{?BR><BR>11.在表辑ּ中,byte和short升Z么类型?<BR>在表辑ּ中,byte和short升?int cd?BR><BR>12.总述什么时候需要强制{换?<BR>当在不兼容的cd之间转换Ӟ或者窄域{换发生时Q需要用强制{换?img src ="http://m.tkk7.com/yangsail/aggbug/3046.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/yangsail/" target="_blank">蓝色雪焰</a> 2005-04-09 20:05 <a href="http://m.tkk7.com/yangsail/archive/2005/04/09/3046.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>漂亮的游戏开始画?/title><link>http://m.tkk7.com/yangsail/archive/2005/04/08/3006.html</link><dc:creator>蓝色雪焰</dc:creator><author>蓝色雪焰</author><pubDate>Fri, 08 Apr 2005 11:01:00 GMT</pubDate><guid>http://m.tkk7.com/yangsail/archive/2005/04/08/3006.html</guid><wfw:comment>http://m.tkk7.com/yangsail/comments/3006.html</wfw:comment><comments>http://m.tkk7.com/yangsail/archive/2005/04/08/3006.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/yangsail/comments/commentRss/3006.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/yangsail/services/trackbacks/3006.html</trackback:ping><description><![CDATA[<STRONG>漂亮的游戏开始画?BR></STRONG> <P>介绍一个游戏开始的画面?BR>先徏两个c?MenuScreen.java  SimpleCustomMenuWithBGFont.java用于试</P><BR> <P>首先说下SimpleCustomMenuWithBGFont.java</P><BR> <P>import javax.microedition.midlet.*;<BR>import javax.microedition.lcdui.*;<BR>//import java.util.*;</P><BR> <P>public class SimpleCustomMenuWithBGFont extends MIDlet implements CommandListener {</P><BR> <P>  Display display;<BR>  Display pauseDisplay;<BR>  boolean isSplash = true;<BR>  MenuScreen menuScreen;</P><BR> <P>  public SimpleCustomMenuWithBGFont() {<BR>    MenuScreen menuScreen = new MenuScreen();<BR>    display = Display.getDisplay(this);<BR>    display.setCurrent(menuScreen);<BR>  }</P><BR> <P>  protected void startApp() throws MIDletStateChangeException   {<BR>  }</P><BR> <P>  protected void pauseApp() {  }<BR>  protected void destroyApp (boolean flag) throws MIDletStateChangeException {}</P><BR> <P>  public void commandAction (Command cmd, Displayable dis) {</P><BR> <P>  }<BR>}<BR>q个cd?是作ؓ了测试用的?/P><BR> <P>主要来介l一下MenuScreen.java</P><BR> <P><BR>import javax.microedition.lcdui.*;</P><BR> <P>public class MenuScreen extends Canvas implements Runnable {</P><BR> <P>  // 讄字体<BR>  static final Font lowFont  = Font.getFont (Font.FACE_MONOSPACE, Font.STYLE_PLAIN, Font.SIZE_SMALL);<BR>  static final Font highFont = Font.getFont (Font.FACE_MONOSPACE, Font.STYLE_BOLD, Font.SIZE_MEDIUM);<BR>  static final int NEW_GAME = 0;<BR>    static final int HIGH_SCORE = 1;<BR>    static final int SETTINGS = 2;<BR>    static final int HELP = 3;<BR>    static final int ABOUT = 4;<BR>    static final int MENU_ITEM_COUNT = 5;</P><BR> <P>  // 讄颜色<BR>  static final int lowColor  = 0x0000FF00;    // Not Highlighted<BR>  static final int highColor = 0x000000FF;    // Highlighted<BR>  static final int highBGColor = 0x00CCCCCC;  // Highlighted Background</P><BR> <P><BR>  static int width;   //屏幕?BR>  static int height;  // 屏幕?/P><BR> <P>  static int startHeight;  // 菜单开始的高度</P><BR> <P>  static final int spacing = highFont.getHeight()/2;  // 菜单w的距?BR>  // 菜单?BR>  static final String[] mainMenu = {"New Game","High Score","Settings","Help","About"};<BR>  // 当前高亮昄的烦引号<BR>  static int menuIdx;<BR>  Thread thread;<BR>  // 背景?BR>  Image bgImage;<BR>  //构?BR>  public MenuScreen() {<BR>    width = getWidth();<BR>    height = getHeight();<BR>    // 计算菜单开始的高度<BR>    startHeight = (highFont.getHeight() * mainMenu.length) + ((mainMenu.length-1) * spacing);<BR>    startHeight = (height - startHeight) / 2;<BR>    // 默认所选ؓ菜单的第一?BR>    menuIdx = 0;<BR>    try {<BR>      bgImage = Image.createImage("/res/bg.png");<BR>    } catch (Exception e) {}</P><BR> <P>    thread = new Thread(this);<BR>    thread.start();<BR>  }<BR>  public void run() {<BR>    while(true) {<BR>      repaint();<BR>    }<BR>  }<BR>public void paint(Graphics g) {<BR>//清屏<BR>    g.setColor(0x00000000);<BR>    g.fillRect(0,0,width,height);<BR>// 背景<BR>    g.drawImage(bgImage,(width - bgImage.getWidth()) / 2, (height - bgImage.getHeight())/2,20);<BR>    for (int i=0; i<mainMenu.length; i++) {<BR>      if (i==menuIdx) {<BR>       //g.setColor(highBGColor);<BR>       //g.fillRect(0,startHeight + (i*highFont.getHeight()) + spacing,width,highFont.getHeight());<BR>        g.setFont(highFont);<BR>        g.setColor(highColor);<BR>        g.drawString(mainMenu,<BR>                     (width - highFont.stringWidth(mainMenu)) / 2,<BR>                      startHeight + (i*highFont.getHeight()) + spacing,<BR>                      20<BR>                     );</P><BR> <P><BR>      } else {<BR>        g.setFont(lowFont);<BR>        g.setColor(lowColor);<BR>        g.drawString(mainMenu,<BR>                     (width - lowFont.stringWidth(mainMenu)   ) / 2,<BR>                     startHeight + (i*highFont.getHeight()) + spacing,<BR>                     20<BR>                    );<BR>      }<BR>    }<BR>  }</P><BR> <P><BR>  protected void keyPressed (int code) {<BR>    if (getGameAction(code) == Canvas.UP && menuIdx - 1 >= 0) {<BR>      menuIdx--;<BR>    } else if (getGameAction(code) == Canvas.DOWN && menuIdx + 1 < mainMenu.length) {<BR>      menuIdx++;<BR>    }else if (getGameAction(code) == Canvas.FIRE)<BR>    switch(menuIdx) {<BR>         case NEW_GAME:   System.out.println("Start New Game"); break;<BR>         case HIGH_SCORE: System.out.println("Display High Score"); break;<BR>         case SETTINGS:   System.out.println("Display Settings"); break;<BR>         case HELP:       System.out.println("Display Help"); break;<BR>         case ABOUT:      System.out.println("Display About Info."); break;<BR>       }</P><BR> <P>  }<BR>}</P><BR> <P>Zq里介绍一下J2ME中的字体:<BR>字体的属性由Q字体类型,风格和字体大构成,h意颜色ƈ不是字体的属性。字?BR>cd由FormcM的静态常量进行定义,可能的取?<BR>FACE_MONOSPACE: {宽字体<BR>FACE_PROPORTIONAL: 比例字体Q非常宽<BR>FACE_SYSTEM: pȝ字体</P><BR> <P>字体风格由Font cM的静态常量进行定义,字体风格是可以多选的Q可能的取gؓQ?BR>STYLE_BOLD : 加粗<BR>STYLE_ITALIC Q斜?BR>STYLE_PLAIN Q常?BR>STYLE_UNDERLINEDQ带下划U字?/P><BR> <P>字体由Font cM的静态常量进行定义,可能的取gؓQ?BR>SIZE_LARGE: 大号字体<BR>SIZE_MEDIUM: 中号字体<BR>SIZE_SMALL: 号字体</P><BR> <P>创徏字体时ƈ不是通过Font cȝ构造方法来创徏Q而是利用Fontcȝ静态方?BR>static Font getFont(int face,int style,int size)来创建字体。或者利?BR>static font getDefauleFont()来创建系l默认字体?BR>在MIDP v2.0中,为Fontcd加了新的一个方法用于创建字体,?static Font<BR>getFont(int fontSpecifier),参数fontSpecifier的取D围被定义为Fontc?<BR>的静态常量,目前只能׃U取|<BR>FONT_STATIC_TEXT:静态文本字?定义了屏q显C时讑֤采用的字?BR>FONT_INPUT_TEXT:输入文体,定义了在用户输入时设备采用的字体<BR>在显C文字时,如果文字q长而超q当前屏q的宽度,那么多余的部分将无法昄,<BR>所以ؓ了有效地昄文字可以用检字W或者字W串的宽度的Ҏ,q序判断每<BR>行输出的字符?来达到更好的昄效果.</P><img src ="http://m.tkk7.com/yangsail/aggbug/3006.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/yangsail/" target="_blank">蓝色雪焰</a> 2005-04-08 19:01 <a href="http://m.tkk7.com/yangsail/archive/2005/04/08/3006.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>J2ME游戏中的囄处理[转脓]http://m.tkk7.com/yangsail/archive/2005/04/08/3005.html蓝色雪焰蓝色雪焰Fri, 08 Apr 2005 10:58:00 GMThttp://m.tkk7.com/yangsail/archive/2005/04/08/3005.htmlhttp://m.tkk7.com/yangsail/comments/3005.htmlhttp://m.tkk7.com/yangsail/archive/2005/04/08/3005.html#Feedback0http://m.tkk7.com/yangsail/comments/commentRss/3005.htmlhttp://m.tkk7.com/yangsail/services/trackbacks/3005.htmlJ2ME游戏中的囄处理

 

         囄资源乃是游戏的外,直接影响一个游戏是否看上去很美。在J2ME游戏开发中Q由于受到容量和内存的两重限Ӟ囄使用受到极大的限制。在q种环境中,处理好图片的使用问题显得更加重要?BR> 本文从容量和内存两个斚w谈谈J2ME游戏囄处理的基本方法?/P>

一 减少囄定w

Ҏ1Q将多张png囄集成C张图片上?BR> q是最基本也是最有效的减png囄定w的办法了。比如你?0张png囄Q每?0×15Q现在你可以把它集成C?00×15或?0×150或者X×X的图片上厅R这张大png囄的容量比10张png囄的d量小很多。这是因为省M9张图片的文g_文gl束数据块等{,而且合ƈ了调色板Q如?0张图片的调色板恰好相同,则省M9张图片的调色板所占的定wQ这是个不小的数字)

Ҏ2Q减图片的颜色?BR> 减少颜色也算是一个方法?我想说的是什么时候减Q谁d。如果游戏完成后发现定w出Q此时在用优化工具减颜Ԍ虽然能降低图片容量,但图片效果可能就不让你满意了。所以,在美工作图时p定使用的颜色数Q手机游戏用的是象素图Q即一个象素一个象素点出来的图像,所以预先规定调色板颜色数量是可以办到的。不q,最l用优化工具也是有用的Q有时候相差一两种颜色Q但效果差别q不大,定w却可以变一些。呵呵,减少颜色实可以是一U方法?/P>

Ҏ3Q尽可能使用旋{和翻?BR> q点不用解释?nbsp;

Ҏ4Q用换调色板技术和自定义图片格?BR> 如果前两U方法还不能满你对定w的要求,而你的游戏中恰好使用了很多仅颜色不同的怪物Q那么可以试试换调色板技术。J2ME规范中规定手可以支持png格式的图片,每张png都带有调色板数据Q如果两张图片除了颜色不同而其他(包括颜色敎ͼ完全相同Q则只要保存一张图片和其他囄的调色板Q这相对于保存多张图片来说节省了不少定w。不q这个方法挺ȝQ你得了解png文g格式Q然后做一个工h取出调色板数据和调色板数据块在png文g中的偏移。内存中保存囑փ仍用Image,如果要换调色板,则将png文gdC个字节数l中Q根据调色板数据块在png中的偏移Q用新的调色板代替原来的调色板数据,然后用这个字节数l创建出换色后的Image。也怽觉得保存一张png和n份调色板数据的方法有Ҏ贏V至多保存?份调色板数据啊!如果直接图像数据提取出来,在加上n份调色板数据Q岂不是更节省容量。但是用上面的ҎQ我们还可以用drawImage渲染。如果这栯定义了图片格式,那只有自己写个渲染函CQ这倒还可以Q只不过put pixel的速度在某些机器上非常慢。或者自己构造png格式数据,再用Image.如果你真得决定这么做Q我q有个小Q不要对囑փ数据q行压羃Qzip压羃大多数时候比你写得压~算法好(参见J2ME Game开发笔讎ͼ压羃q是不压~?。论坛上有位朋友提过使用bmp格式代替png格式Qjar中图片容量更,也是一个道理?/P>

?减少囄所占内?/P>

1 囄所占内存的计算
 png囄所占用的内存ƈ不对应于囄定w。图片占用的内存的计ؓQwidth*height*bpp。bpp即ؓpȝ内置的颜色位数。以Nokia 6600ZQ象素格式ؓ565?6位。所以一?00*100的图片占?00*100*(16/8)=20000字节Q约?9.5k的内存。象素格式是固定的无法改变,所以只有减图片的宽和高才能降低其消耗的内存?/P>

2 减少Image对象数量可节U大量内?BR> 减少Image对象数量不等于减图片数量。我的意思是_一张集成图保存在一个Image对象中,通过setClip的方法从q个Iamge对象中选取你需要的囑փ渲染。不q这个方法牺牲了一炚w度Q每帧都从集成图Image中减切图像的速度比无减切的渲染慢。但对于数目不多的渲染,比如_Q用这个方法没问题。这个方法还有一个问题就是不能释N成图中不需要的囄Q这p看你集成的程度了。从囄定w和内存管理的角度l合考虑Q我一般用二ơ集成的Ҏ。比如有n个精?先将各精灉|有的囄集成C张集成图中,得到n张集成图Q然后将qn张集成图再次集成C张更大的集成图中。这样在jar中只存在一张集成图。用时Q先大集成囑ֈ割蝲入到n个Image对象中即可。这样各个精늚囄可以单独理了?/P>

3 使用旋{和翻?BR> 只保存一个原始的Image,需要时再旋转或{


 



蓝色雪焰 2005-04-08 18:58 发表评论
]]>
新手{划如何快速的提高自己的水q?http://m.tkk7.com/yangsail/archive/2005/03/25/2455.html蓝色雪焰蓝色雪焰Fri, 25 Mar 2005 15:02:00 GMThttp://m.tkk7.com/yangsail/archive/2005/03/25/2455.htmlhttp://m.tkk7.com/yangsail/comments/2455.htmlhttp://m.tkk7.com/yangsail/archive/2005/03/25/2455.html#Feedback0http://m.tkk7.com/yangsail/comments/commentRss/2455.htmlhttp://m.tkk7.com/yangsail/services/trackbacks/2455.html
另外是多看看一些其他h的心得,而且心得q个东西是随着自己水^的提高,感受也在不断提高的。所以暂时看C你不以为然的文章不要先忙着否定Q也写下自己Z么不认同他的原因Q如果有可能最好是能和其他Z下,说服别h的同时你也在考证着自己的理论!

最后:能够q速提高自q水^的还是参加实늚工作Q但是已l参加工作的要注意,不要把自己每天都陷入q琐的事情中,半个或者一个月的时候应该ȝ一下自己,qx注意写开发日讎ͼ主要是记录当时自q心得Q等目做完之后Q用市场的反应再回头来对照自q开发心得,我想您的q步肯定是阶D|的Q也是说你的水q会有一个非常大的进步!


蓝色雪焰 2005-03-25 23:02 发表评论
]]>
关于q连看寻路算法的思\[转蝲CSDN]http://m.tkk7.com/yangsail/archive/2005/03/25/2450.html蓝色雪焰蓝色雪焰Fri, 25 Mar 2005 13:19:00 GMThttp://m.tkk7.com/yangsail/archive/2005/03/25/2450.htmlhttp://m.tkk7.com/yangsail/comments/2450.htmlhttp://m.tkk7.com/yangsail/archive/2005/03/25/2450.html#Feedback0http://m.tkk7.com/yangsail/comments/commentRss/2450.htmlhttp://m.tkk7.com/yangsail/services/trackbacks/2450.html图-Q?BR>0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 8, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 9, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0


  q是一张连q看的地图,假设??的部分是两张相同的牌?BR>  在数l矩阵中Q?表示没有牌,大于1表示有牌。至于是什么牌Q那是随机的了?BR>不要告诉我,你说的“布局法”是指怎么把牌刚刚好放上去Q那个无所谓什?BR>法Q你只要首先在地图数l中准备好偶C1Q在布牌时保证每U牌是偶C
Q不同种cȝ牌用大于1的数来表C)Q相应地攑օ每个1的位|上可以了?/FONT>

一、计地图上q两张牌能不能连?当然能了Q哈哈)?/FONT>

q是q连看寻路算法的W一步?BR>先定义一下两张牌能连的充分条Ӟ
1.两张牌是同一U?BR>2.两张牌之间有一条全?的\可以q通?BR>3.q一条\不能有两个以上的拐角(corner)
满q三个条Ӟ可以认两张牌是可以q的?/FONT>

首先Q我们依据前两个条g来完成一个基本的寻\法?BR>我们的目的是??扑և一条可以连通的路来?BR>那么很明显从8?的第一步一其有四个方向可以选择Q分别是东,南,西,?BR>Qe, s, w, n以中国地图方向ؓ标准Q四个方向,在第一步中我们首先假设?BR>个方面没有Q何优劣,那么我可以Q意选择一个方向移动,那就是东面吧?BR>图二Q?BR>0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 8, Q?, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 9, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
我从8向东Ud了一步,所以到达了-8的位|,我之所以可以移?8位置Q很明显Q?BR>是因?8的位|上原来是一?Q表C没有牌L?BR>那么现在寻\的问题就变成了,如何从-8找连?的\了!
说到q里应该明白了吧Q好多费话,有点像娘们在说话?/FONT>

所以目前的寻\法归结Z个递归法的基本问题?BR>先从8到找C一个结点-8Q再用同L规则Q从Q?扑ֈ下一个结点,比如Q?8。。?BR>图三Q?BR>0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 8, Q?, Q?8, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0
0, 0, 0, 0, 0, 0, 0, 0 , 9, 0
0, 0, 0, 0, 0, 0, 0, 0 , 0, 0

如果一直都能OKQ没有阻的话,最后找C9Q就成功以Q如要有一步不能走下去了,
再退回上个结点,向别的方向发展,都不行,再退回上U结点,再向别的方向发展Q?BR>q里的逻辑是递归的思想了?/FONT>

用这LҎ写出来的法已经能在最优的情Ş下用了,比如?Q到Q?8Q哈哈?BR>但在E微复杂的情况下Q会产生奇多的递归l点。P4Z跑不动啊。我试过Q哈哈?/FONT>

那么W二步就是ؓQe,s,w,nQ四个方向加权,也就是让它们之间有一个优先权Q说白了?BR>是先试哪一条\。决定的法则应该有好几个吧,比如?L位置来看Q它处于8L东南面,
那试路时当然应当优先选择东面和南面,再比?号如果牌8L正东面,那当然是选择正东了?BR>再比如,当走刎ͼ8的位|时Q明昑֏能再C个方向,因ؓ它是不能回头的?/FONT>

l过q样的处理,递归法生成的结Ҏ会明昑֏,会更快的扑ֈ成功的\。但性能在最坏情?BR>下没有本质改变?/FONT>

接下来,W三步,我们把第三个充分条g加进来,来解x本问题?BR>3.q一条\不能有两个以上的拐角(corner)

按照面向对象的思想Q很自然的,我给每个在递归法中生成的位置l点加上了个corner的属性,
来记录这条\到目前ؓ止拐了几个角?BR>q样一下子好办了啊。如果发现这个结点已l拐了两个弯Ӟ如果要再拐弯Q或者到?之前注定
要再增加cornorӞ果断overQ返回上U结炏V?/FONT>

注意Q要把二、三两步的条件综合v来详l规划一个个可能性,可能提早让不可能的l点OVERQ?BR>q就是提高性能的关键吧。算法预见性越强,性能p高吧?/FONT>

我们的算法在赛扬500Q?56M的机器上Q?0万次q_l果是一ơ运花时不过0.1毫秒,得q不
_Q速度实很快Q因为在很坏的情形下Q生的最大结Ҏ?90几个Q这样必然会很快?BR>Q详l的数据已经C清了?/FONT>


说了q么多了Q应当明白第一步连通算法的思\了吧Q我所知道的,都已l尽可能的讲出来了?BR>q个法完全是自己按照连q看的特点,度n定做的。因为是一步步test出来的,所以我个h
觉得是很自然的,没有M高深的地方,完成后,性能也很好,q才觉得是如此的单。相信大?BR>仔细看看p写出自己的算法来的吧?/FONT>


二、整个地图有没有解?Q?可以q通的ȝ敎ͼ
  q是一个问题?BR>  解决q个问题之前Q我们先来解xC功?hintQ就是ؓ玩家提供提示Q哪一对牌可以q?BR>通?BR>  我的做法是,先把整个地图中相同牌归到一P用数l也好,链表也好?BR>  像这P
 4,4,4,4
 5,5,5,5
 6,6,6,6
 ......
    然后计算比如4?之间有哪两对可以q,至于如何判断能不能连Q第一步算法已l实C吧,哈哈?BR>  一发现有可以连的牌退出来Q告诉玩家这两张牌可以连啊!
  q就OK了?BR>  q完全是建立在第一步算法的基础上实现的?/FONT>

  好的Qhint功能可以了,
  那么Q整个地图没有解的算法是不是出来了?
  是的Q如果找不到可以hint的牌Q那当然是没有解了Q?BR>  把所有可以hint的对数记下来Q就是ȝ可以q通数了?/FONT>

  xQ与q连看所有算法有关的问题解决完毕?BR>W二步算法的实现Q明昑ּ销要大很多Q最坏情况应当会是单ơ连通算法计量的大U?0倍以?BR>Q与牌的L量和摆的位置有关Q还好在一般的服务器上单次q通计花的时间实在太了Q?BR>实际q行中完全可以很畅。以上数据都是我估计的理论|因ؓ实际试时一直没有问题,
我也懒得计算出真正比较可靠的均g?BR>  
  q一部分也是我认为可以有所改进的部分,公开出来Q也希望大家能提供一些更好,更y?BR>的方法,我觉得我计算q通数和有无解的方法是比较W的ҎQ几乎是仗着基本的算法快Q一
个一个算出来的。有没有更好的方法呢Q期待中...



蓝色雪焰 2005-03-25 21:19 发表评论
]]>
J2ME学习W记整理http://m.tkk7.com/yangsail/archive/2005/03/13/1979.html蓝色雪焰蓝色雪焰Sun, 13 Mar 2005 03:01:00 GMThttp://m.tkk7.com/yangsail/archive/2005/03/13/1979.htmlhttp://m.tkk7.com/yangsail/comments/1979.htmlhttp://m.tkk7.com/yangsail/archive/2005/03/13/1979.html#Feedback0http://m.tkk7.com/yangsail/comments/commentRss/1979.htmlhttp://m.tkk7.com/yangsail/services/trackbacks/1979.htmlJ2ME学习W记整理Q一Q?/strong>
http://www.j2medev.com/Article_Show.asp?ArticleID=249

一直想写点东西为我学习J2ME做个ȝQ自从上ơ笔记本在寝室莫名其妙弄丢后Q就再没写过J2ME的学习笔讎ͼ今天l于股v勇气再动W,同时也ؓ准备学习J2ME的兄弟姐妹v个抛砖引玉的作用Q呵呵,希望不让大家失望?/span>

J2ME学习W记整理Q二Q?br> http://www.j2medev.com/Article_Show.asp?ArticleID=250

接下来我们来介绍一下LCDUIq个包及其相兛_容,大家都知道,在J2SE里面我们用AWT或者SWING来开发用L面,但是在J2ME里面Q开发用L面ƈ非上q的AWT或者SWINGQ我们用的是全新的针对Ud讑֤设计的LCDUI包(即Limited Configuration Device User InterfaceQ?br>

蓝色雪焰 2005-03-13 11:01 发表评论
]]>3D效果的Applet游?/title><link>http://m.tkk7.com/yangsail/archive/2005/03/10/1927.html</link><dc:creator>蓝色雪焰</dc:creator><author>蓝色雪焰</author><pubDate>Thu, 10 Mar 2005 13:38:00 GMT</pubDate><guid>http://m.tkk7.com/yangsail/archive/2005/03/10/1927.html</guid><wfw:comment>http://m.tkk7.com/yangsail/comments/1927.html</wfw:comment><comments>http://m.tkk7.com/yangsail/archive/2005/03/10/1927.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/yangsail/comments/commentRss/1927.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/yangsail/services/trackbacks/1927.html</trackback:ping><description><![CDATA[<P><FONT size=2><FONT face=Arial><STRONG>3D效果的Applet游?/STRONG> <BR><A >http://www.javaresearch.org/code/thread.jsp?thread=21723</A><BR><BR>有代?/FONT></FONT></P><img src ="http://m.tkk7.com/yangsail/aggbug/1927.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/yangsail/" target="_blank">蓝色雪焰</a> 2005-03-10 21:38 <a href="http://m.tkk7.com/yangsail/archive/2005/03/10/1927.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ZNokia S60的游戏开?/title><link>http://m.tkk7.com/yangsail/archive/2005/03/03/1629.html</link><dc:creator>蓝色雪焰</dc:creator><author>蓝色雪焰</author><pubDate>Thu, 03 Mar 2005 01:57:00 GMT</pubDate><guid>http://m.tkk7.com/yangsail/archive/2005/03/03/1629.html</guid><wfw:comment>http://m.tkk7.com/yangsail/comments/1629.html</wfw:comment><comments>http://m.tkk7.com/yangsail/archive/2005/03/03/1629.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/yangsail/comments/commentRss/1629.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/yangsail/services/trackbacks/1629.html</trackback:ping><description><![CDATA[<span id="l9tr9fd" class=f14><FONT size=2><STRONG>本文是基于Nokia Series 60和Symbian OS技术,指导开发者在现在的Series 60Ud电话l端上开发高U的Ud游戏?/STRONG><BR><BR>  注意Q本文档中讨论的技术\UK是以Symbian OS GT 6.1作ؓSeries 60q_的基本操作系l。这适用于Series 60q_v1.x。Series 60q_v2.0ZSymbian OS GT 7.0s。本文主要适用于Series 60 v1.x版,所以可能会有部分不兼容Series 60 v2.0版?<BR><BR>  Symbian操作pȝ?BR><BR>  Symbian操作pȝ是所有Symbian OS电话׃n的应用编E接? API)技术的公共核心?q个核心被命名ؓ"通用技?Qgeneric technologyQ简UCؓGTQ,它被分成不同的版本?GT包括一个多d核心、通讯、数据管理和图表中间Ӟ低囑Ş用户界面框架和应用程序引擎?<BR><BR>  象智能电话这L型手持讑֤Q通常是资源非常紧张的讑֤?q种讑֤的尺寸和刉费用限制了可用的存储器Q处理速度和电池寿命?管以上q些资源~ZQ但是这些设备还是需要能够稳定运行相当长的一D|_甚至C月?一旦出现资源溢出的错误Q对于系l来说重要的事情是q回到前一个稳定的状态,而不失去M重要的数据?q得完全地捕捉和处理每个运行错误对于系l和应用E序来说是非帔R要的?<BR><BR>  ׃资源溢出而出现的错误Q和所有的q行期错误一栯UCؓ异常?在标准的C++中,q些异常是用try-catch-throw机制处理的,但是因ؓ它造成了代码长度的负面影响Q所以Symbian OS提供了它自己的称为trap harness的机制?BR><BR>  Symbian开发他们自q异常处理E序的另一个原因是开发Symbian OS的时候,try - catch - throw机制q不是C++标准的一部分。trap- harness的概忉|使用一个TRAP宏把可能引发异常的函数封装v来。这个宏可用于捕获多个函敎ͼq且q些函数可以嵌套。万一出现一个异常,D异常的函数的执行׃通过User::Leave函数l止Q相当于标准的C++异常处理中的throw。这被称Z个leaveQ离开Q,它将q回E序执行到结束的TRAP宏,在那里相应的恢复动作可以被执行?BR><BR>  Symbian OSq提供一个工P以便清除异常。一个cleanupstack被用于引用只被一个自动变量引用,q且如果出现一个leave的时候需要被释放的对象。TRAP宏将销毁cleanupstack中自动变量分配的内存?BR><BR>  Symbian OS提供一个用于在单一U程之内非抢先式多Q务处理技术的pȝ。这个包括活动对象和zd调度E序的系l的设计目标是降低运行时间成本和解决与优先计划线E冲H的同步问题。Symbian OS中的每个应用E序׃个活动调度程序和一个或多个zd对象l成。这个调度程序封装一个需要异步的服务和依照它们的优先权安排活动对象的{待循环。活动对象封装实际的异步服务?<BR></FONT></SPAN><img src ="http://m.tkk7.com/yangsail/aggbug/1629.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/yangsail/" target="_blank">蓝色雪焰</a> 2005-03-03 09:57 <a href="http://m.tkk7.com/yangsail/archive/2005/03/03/1629.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>学习J2ME~程需要掌握的几种技?/title><link>http://m.tkk7.com/yangsail/archive/2005/02/25/1506.html</link><dc:creator>蓝色雪焰</dc:creator><author>蓝色雪焰</author><pubDate>Fri, 25 Feb 2005 06:39:00 GMT</pubDate><guid>http://m.tkk7.com/yangsail/archive/2005/02/25/1506.html</guid><wfw:comment>http://m.tkk7.com/yangsail/comments/1506.html</wfw:comment><comments>http://m.tkk7.com/yangsail/archive/2005/02/25/1506.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/yangsail/comments/commentRss/1506.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/yangsail/services/trackbacks/1506.html</trackback:ping><description><![CDATA[<P>    J2ME~程是Java在智能家电领域的应用Q主要包含以下技术:</P> <P> <SCRIPT id=ad_text_pcjob src="http://www.pconline.com.cn/script/ad_text_pcjob.js" defer></SCRIPT>      <B><SPAN style="COLOR: #cc0000">1?nbsp; 高用户界面</SPAN></B></P>高用户界面是指J2ME~程中用到的Form(H体)、TextBox(文本?、List(列表?和Alert(提示信息?{的使用Q以及其中的一些控件的使用Q当然也包括相应的事件处理。应用在一般的如登陆窗体、关于窗体和提示{? <P></P> <P>    <B><SPAN style="COLOR: #cc0000"> 2?nbsp; 低用户界面</SPAN></B></P> <P>     低用户界面指CanvascdGraphicscȝ的用,以及相应的事件处理,应用与游戏编E以及特D界面的l制{?/P> <P>     <B><SPAN style="COLOR: #cc0000">3?nbsp; 记录存储pȝ</SPAN></B></P> <P>     记录存储pȝ是手Z支持的用于数据永久保存的技术。因为手Z没有数据文g的概念,所以一般需要保存的数据只能以记录的形式保存?/P> <P>     <B><SPAN style="COLOR: #cc0000">4?nbsp; 声音处理pȝ</SPAN></B></P> <P>     MIDP1.0不支持声韛_理,但是很多手机厂商如Nokia、Siemens{都支持Q所以播攑֣音也是一w要掌握的技术。该技术用的API多和手机厂商相关。但是MIDP2.0提供了通用的支持?/P> <P>     <B><SPAN style="COLOR: #cc0000">5?nbsp; |络~程</SPAN></B></P> <P>     |络~程指在手机中通过GPRS或者CDMA|络以HTTP协议或者SOCKET的Ş式连接网l。现在的手机支持HTTP|络~程的占大多敎ͼ支持SOCKET的相对很。所以网l编E暂时也是使用HTTP协议q行~程?/P> <P>    <B><SPAN style="COLOR: #cc0000"> 6?nbsp; 多线E?/SPAN></B></P> <P>     多线E是J2ME应用中比较核心的技术之一Q因行网l编E和低用户界面~程是ؓ了响应迅速,都需要处理成多线E。所以也必须熟练掌握?/P> <P>     <B><SPAN style="COLOR: #cc0000">7?nbsp; 短信息编E?/SPAN></B></P> <P>     很多手机都提供了用于发送短信息的APIQ如NOKIA、SIEMENS、SAMSUNG{,所以在J2ME中发送短信息也是一个比较常用的技术?/P> <P>     <B><SPAN style="COLOR: #cc0000">8?nbsp; 其他</SPAN></B></P> <P>     当然Ҏ厂商的不同还提供了其他的一些技术,如Siemens的API中支持文ӞNokia的API支持dpȝ通讯录等{?/P><img src ="http://m.tkk7.com/yangsail/aggbug/1506.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/yangsail/" target="_blank">蓝色雪焰</a> 2005-02-25 14:39 <a href="http://m.tkk7.com/yangsail/archive/2005/02/25/1506.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转蝲]优化J2MEE序大小http://m.tkk7.com/yangsail/archive/2005/02/20/1374.html蓝色雪焰蓝色雪焰Sun, 20 Feb 2005 10:21:00 GMThttp://m.tkk7.com/yangsail/archive/2005/02/20/1374.htmlhttp://m.tkk7.com/yangsail/comments/1374.htmlhttp://m.tkk7.com/yangsail/archive/2005/02/20/1374.html#Feedback0http://m.tkk7.com/yangsail/comments/commentRss/1374.htmlhttp://m.tkk7.com/yangsail/services/trackbacks/1374.html要把J2MEE序与J2SEE序区分开来,其依据就是J2MEq行所处的受限环境。多数J2MEpȝ的主要受限条件就是可以存储和q行E序所需内存的大。例如,许多MIDP讑֤限制应用E序的尺怸大于50KQ这q远不及Server端J2SEq行环境下那些成兆的E序。实际应用中Q程序会很容易超些限制条件。通过本篇您将学到一些减程序尺寸大的技巧,q在下面的例子中实践q些技术。这个例子MIDlet仅仅昄一个文本框q在其内Ҏ变时发声?

package com.j2medeveloper.techtips; 
import javax.microedition.lcdui.*; 
public class BeforeSizeOptimization extends 
                                      BasicMIDlet { 
 public static final Command exitCommand = 
                      new Command( "Exit", 
                                 Command.EXIT, 1 ); 
 public BeforeSizeOptimization(){ 
 } 
 protected void initMIDlet(){ 
     getDisplay().setCurrent( new Mainform() ); 
 } 
 public class Mainform extends form { 
     public Mainform(){ 
         super( "Mainform" ); 
         addCommand( exitCommand ); 
         append( textf ); 
         setCommandListener( new CommandListener(){ 
             public void commandAction( Command c, 
                                    Displayable d ){ 
                 if( c == exitCommand ){ 
                     exitMIDlet(); 
                 } 
             } 
           } 
         ); 
         setItemStateListener( 
                           new ItemStateListener() { 
             public void itemStateChanged( 
                                        Item item ){ 
                 if( item == textf ){ 
                     AlertType.INFO.playSound( 
                                     getDisplay() ); 
                 } 
             } 
           } 
         ); 
     } 

     private TextField textf = 
               new TextField( "Type anything", null, 
                              20, 0 ); 
 } 
}


虽然q个MIDlet在此仅作Z个例子,但用的寸优化技巧可以适用于Q一J2ME的profile上?/FONT>


注意Q上面的MIDletc需要下面的辅助c:

package com.j2medeveloper.techtips; 
import javax.microedition.lcdui.*; 
import javax.microedition.midlet.*; 
public abstract class BasicMIDlet extends MIDlet { 
 private Display display; 
 public BasicMIDlet(){ 
 } 
 protected void destroyApp( boolean unconditional ) 
                 throws MIDletStateChangeException { 
     exitMIDlet(); 
 } 
 public void exitMIDlet(){ 
     notifyDestroyed(); 
 } 
 public Display getDisplay(){ return display; } 
 protected abstract void initMIDlet(); 
 protected void pauseApp(){ 
 } 
 protected void startApp() 
                 throws MIDletStateChangeException { 
     if( display == null ){ 
         display = Display.getDisplay( this ); 
         initMIDlet(); 
     } 
 } 
}


用J2ME WTK打包Ӟ本例子MIDlet占用4KI间?


减小寸的首要步骤就是通过修正E序的功能实现来L多余的类。程序的所有功能确实必都实现吗?用户可以不需要这些“附属功能”吗Q要设计可能小的程序,q里的MIDlet例子已经相当了?

W二步就是深入考察E序定义的内部类Q特别是匿名cR记住,每个cL仉有一定量的与之相关的pȝ开销。即便最普通的cM有系l开销?

public class foo { 
     // nothing here 
 }


~译上边的类Q生成的cL件大U?00byte大小。比如实C个事件监听器Q就是对匿名cȝ常见使用。在例子MIDlet中就定义了两个此cȝ监听器。接下来q行的最单的优化是Q让主MIDletcd现CommandListener和ItemStateListener接口Qƈ把监听器代码U至此处。记住,多个对象可以使用同样的监听器。必要时Q可以用传递至commandAction和itemStateChangedҎ的参变量来区分它们?

内部cM可代码q大Q因为编译器必须生成Ҏ的变量和ҎQ以便内部类可以讉K包含它们的类的私有内宏V请参考内部类的规范以获取更多信息?

W三步,量使用现有的类。例如,ZCLDC的profile没有构造集合类Q所以我们可以用内徏的Hashtable和VectorcL实现之。构造MIDPE序时也可采用此法。例子MIDlet中定义了一个form字类来生成主表,可以Ҏ的如下直接生成:

mainform = new form( "Mainform" ); 
 mainform.addCommand( okCommand ); 
 mainform.setCommandListener( listener );


q里没有正确或者错误的{案Q只是要推敲?

W四步就是破坏程序的l承关系。你也许把相关的代码攑ֈ一个或多个抽象cMQ这是OOD中ؓ提高E序间代码重用的推荐做法。虽然破坏承关pM你所学知识相q背Q但化的l承关系更有意义。特别的Q当你的的抽象类――可能来自其他项目――仅仅被l承一ơ时Q破坏承关pȝl果不言而喻。例如,例子MIDletl承了BasicMIDletc,但两者合qؓ一个类?

W五步就是要~短名字长度Q如包名、类名、方法名和数据元素名。看h有些蠢,但一个类文g实包含太多的符号信息。羃短各量的名字可以~小生成的类文g寸。这U节省不会特别明显,但多个类中进行d的结果还是可观的。包名对减小寸来讲特别合适。MIDPE序是完全自我包容的Q完全可以不使用包名Q因为在手持讑֤上包名根本不可能与其他类名冲H。例子MIDlet中,可以把com.j2medeveloper.tchtips包名L?

注意Q一般来Ԍ~短名字不需要手工去做,要用一个“؜淆器”去做。“؜淆器”的主要功能是“隐藏”程序代码,使之不能通过反编译读出。它的副作用是减了E序的尺寸。因为隐藏过E主要通过更改Ҏ和数据成员的名字来完成。有一个开源的h器称为RetroGuardQ可以免费从http://www.retrologic.com得到。也有一些商业包可用?当ؓZCLDC的profilehӞ记得在预校验之前hQ否则؜淆器ɾcL件中的预校验数据失效?

最后,深入数组的初始化?例子MIDlet没有做数l初始化Q但对程序来说初始化是重要的一? 在编译时Q一个数l初始化声明如下所C:

int arr[] = { 0, 1, 2, 3 }; 
而实际生成代码的q程如下所C: 
<ccid_nobr>
<table width="400" border="1" cellspacing="0" cellpadding="2" 
 bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center">
<tr>
    <td bgcolor="e6e6e6" class="code" style="font-size:9pt">
    <pre><ccid_code> arr[0] = 0; 
 arr[1] = 1; 
 arr[2] = 2; 
 arr[3] = 3;


q个q程可以通过使用Java 2 SDK中附带的javap工具把二q制代码反编译成cL件去?使用-c选项)。也怽会诧异于看到的内容,特别当你希望看到的是一排排二进制常数时。有两种Ҏ可以让你看不到反~译的程序代码,(1)把数据编码ؓ字符Ԍq行时解码之Q或?2)把数据存Zq制文gq与E序打包Q用c装载器的getResourceAsStreamҎ在运行时存取之?

以上只是一些指导性的ҎQ对每个J2MEE序而言Q这里没有具体到步骤。但是多数方法可以应用的本例。优化后的MIDlet如下所C:

import javax.microedition.lcdui.*; 
import javax.microedition.midlet.*; 
public class ASO extends MIDlet 
              implements CommandListener, 
                         ItemStateListener { 
 private Display   display; 
 private form      mainform; 
 private TextField mainformTF = 
               new TextField( "Type anything", null, 
                              20, 0 ); 
 public static final Command exitCommand = 
                      new Command( "Exit", 
                                  Command.EXIT, 1 ); 
 public ASO(){ 
 } 
 public void commandAction( Command c, 
                            Displayable d ){ 
     if( c == exitCommand ){ 
         exitMIDlet(); 
     } 
 } 
 protected void destroyApp( boolean unconditional ) 
                 throws MIDletStateChangeException { 
     exitMIDlet(); 
 } 
 public void exitMIDlet(){ 
     notifyDestroyed(); 
 } 
 public Display getDisplay(){ return display; } 
 protected void initMIDlet(){ 
     mainform = new form( "Mainform" ); 
     mainform.addCommand( exitCommand ); 
     mainform.setCommandListener( this ); 
     mainform.setItemStateListener( this ); 
     mainform.append( mainformTF ); 
     getDisplay().setCurrent( mainform ); 
 } 
 public void itemStateChanged( Item item ){ 
     if( item == mainformTF ){ 
         AlertType.INFO.playSound( getDisplay() ); 
     } 
 } 
 protected void pauseApp(){ 
 } 
 protected void startApp() 
                 throws MIDletStateChangeException { 
     if( display == null ){ 
         display = Display.getDisplay( this ); 
         initMIDlet(); 
     } 
 } 
}


关于作者:Eric Giguere是来自Sybase下属iAnywhere Solutions的Y件开发h员。他致力于手持设备和无线计算领域的Java技术。他是滑铁卢大学的数学学士和数学士Q写了很多有兌的文章?



蓝色雪焰 2005-02-20 18:21 发表评论
]]>
d手机游戏产业的三张底?/title><link>http://m.tkk7.com/yangsail/archive/2005/02/20/1373.html</link><dc:creator>蓝色雪焰</dc:creator><author>蓝色雪焰</author><pubDate>Sun, 20 Feb 2005 10:15:00 GMT</pubDate><guid>http://m.tkk7.com/yangsail/archive/2005/02/20/1373.html</guid><wfw:comment>http://m.tkk7.com/yangsail/comments/1373.html</wfw:comment><comments>http://m.tkk7.com/yangsail/archive/2005/02/20/1373.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/yangsail/comments/commentRss/1373.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/yangsail/services/trackbacks/1373.html</trackback:ping><description><![CDATA[<FONT size=2>  手机游戏产业价值几何?对于包括Udq营、内容和服务提供在内的整条移动应用业链而言Q在所谓手机游戏业的宏观概念下到底潜藏着一个多大规模的市场Q可以挖掘到哪些市场亮点和创新的应用U类Q又有多亦明亦暗的产业障碍q亟待跨? <BR><BR>  表面看来Q手机游戏正在成营商q速创收的新渠道,q且g卛_成ؓ语音呼叫和短信息之外存在的又一个潜力巨大的Ud服务市场。运营商通过收取游戏下蝲费用来增加ARPU值ƈ同时拉动数据服务消费量实现增ѝ服务和内容提供?SP和CP)们则通过出卖游戏下蝲版权和提供下载服务^台赚取更多的利润提成?<BR><BR>  事实上,手机游戏产业早在上世U?0q代后期已l初具雏形。当ӞGSM手机基本都内嵌了一些简单的黑白游戏Q比如经怸衰的“贪吃蛇”和“俄|斯方块”。在当时Q是否内|有q些游戏已经成ؓ一Ƅ销手机的必备要素。紧接着Q短信息(SMS)服务所取得的巨大成?世界各地每个月在SMS服务上花费近300亿美?使得q营商们看到了移动数据服务市含的庞大潜力Qƈ且萌生了手机游戏培LUd数据服务的下一代杀手应用的冲动?<BR><BR>  现在p我们来揭开q位“杀手”的秘底牌吧?<BR><BR></FONT><STRONG> <CENTER><FONT size=2>底牌一Q到底有多少游戏形式可供挖掘Q?/FONT></CENTER></STRONG><BR><BR><FONT size=2>  q今为止Q业界所能挖掘到的手机游戏种cd致有五种cd(q里不包含N-GAGEq种Ua是游戏机和手机的融合产物)Q不同的游戏cd在开发难度和市场定w斚w存在着较大差别?<BR><BR>  <STRONG>嵌入式游?/STRONG> <BR><BR>  手机出厂时固化的嵌入式游戏无疑是所有手机游戏的h。Nokia是始作俑者之一Q当时它的开发h员向其经典的6100pd手机d了“贪吃蛇”游戏。与短消息非常相|“贪吃蛇”游戏自然而然地流行v来:没有d的营销Q只是凭借口的传诵可以流行v来,?100?310pd手机也间接受益成Z当时的畅销手机?<BR><BR>  对于q一意外的成?Nokia认ؓ大约每周会有100万手机用户在l常玩这ƾ游?Q让许多q营商开始相信手机游戏的拥有强劲的发展潜力。唯一的不_于这些游戏无法更斎ͼ因此很容易被时尚的潮所厌倦和抛弃。手机厂商们必须不断地开发和销售更多的新游戏来取代它们……就q样Q手机游戏市场终于诞生了?<BR><BR>  <STRONG>SMS游戏和MMS游戏</STRONG> <BR><BR>  从易用性、吸引力{角度看来,短信?SMS)完全不适合被作ZU游戏类型。但是,SMS却适用于那些早期的文字MUD(|游的前w?游戏Q游戏的玩家怺发送简短的文本消息Q用以控制其游戏角色的行为。此外,对于一些吸引力颇高的“投式游戏”以及其他智力测验类游戏QSMS也是相当适用的游戏手Dc?<BR><BR>  我们可以看到Q尽SMSq理想的游戏媒介,但它是让手机游戏用户和潜在用户习惯于使用手机q行游戏׃的绝妙方式?<BR><BR>  另一斚wQ我们看到多媒体消息服务(MMS)已经成ؓSMS发展的下一阶段Q它为用L单的文本体验增加了图形、照片乃臌频片D늭新内容元素?<BR><BR>  但是从玩游戏的观点看QMMS在功能本质上相比SMSq没有实现根本性的提升。业界认为MMS仍可以被用作实现某些比较初的互动游戏,但M而言Q移动游戏业q不看好MMSq_Q相反注意到更有效和更具zd的Java/J2ME技术已l日成熟,而手机游戏的发展为此也即登上新的高峰?<BR><BR>  <STRONG>Java/J2MEQ手机游戏的未来Q?/STRONG> <BR><BR>  Java/J2ME技术是推动手机游戏向更高层ơ进一步发展的关键动力?<BR><BR>  q些技术是Udq营商、手机制造商和应用开发商q军手机游戏领域时一直期待的基础元素。通过Java/J2ME实现拥有动画和声音的可下载游戏,q就是手机游戏应用下一阶段的发展方向?<BR><BR>  由Java/J2ME技术构建的可下载游戏不仅手机游戏可以更ؓL地吸引到用户的兴,同时也有利于创造更为多样化的计费Ş式。例如对于一些售价低廉的游戏Q可以参照类D机游戏的业务模型q行销售。用户可以先付费Q然后一直玩q款游戏直到他们的预付费或游戏时间用完ؓ止。对于另外一些手机游戏,q营商可以允许用户一ơ花Ҏ多的p获得无限制的游戏时_用户甚至q可以购买某一游戏Q然后依照版权规定的相关协议此ƾ游戏{让给其他玩家?<BR><BR>  当前Q具有Java应用下蝲功能的手机已l在市场上逐渐行hQ甚臛_能从2004qv被作ؓ新型手机的标准配|。另一斚wQ随着功能更ؓ强大的手片、更多容量的内存以及正在大规模开发中的Java游戏的出玎ͼ未来的手机无疑将成ؓ一个真正的游戏q_?<BR><BR>  <STRONG>FlashQ甚xJava更好Q?/STRONG> <BR><BR>  当然Qƈ不是所有h都把Java(特别是移动版的J2ME)看作手机游戏发展的真正方向。反Ҏ的意见认为,Java游戏目前的性能表现很难Ȁh戏玩家的真正兴趣。同Ӟ我们看到如今在互联网上几乎所有的Web游戏已经开始被Flash游戏所l治QJava游戏的辉煌正在逐渐褪去。所以Flash的支持者们怿Q同L情Ş必将在手机游戏n上重演?<BR><BR>  除了J2MEE序处理周期长,对于手机芯片的运能力要求较高以及运行过E相当耗电{缺点之外,在游戏方面J2ME的最大缺点的让人难以想象—竟然是玩家在游戏中无法同时按下两个功能键。无论是游戏老手q是~Zl验的新手,q都是玩家所厌恶的一个致命缺陗所qFlash不仅克服了这一~点Q而且对于更ؓ复杂的图形与声音处理也应付自如。有专业咨询师认为,在目前Java当道的情形下Q敢于将Flash嵌入到手机和手机游戏中的厂商q寥寥无几,但是不可否认Flash最l将成ؓ所有手机游戏应用的标准操作环境?<BR><BR></FONT><STRONG> <CENTER><FONT size=2>底牌二:手机游戏市场I竟有多大?</FONT></CENTER></STRONG><BR><BR><FONT size=2>  我们首先手机游戏分Zc,然后再分析各自的市场定w。第一cL包括智力验、文本问{等在内的基于短信息(SMS或MMS服务)的游戏。第二类是“复杂的可下载游戏”,q其中包括了l大多数未来的游戏应用?<BR><BR>  <STRONG>Z短信息的游戏</STRONG> <BR><BR>  Z短信息的游戏往往定h也偏低,因此q类游戏的收入潜力可能不如h们最初想像的那般乐观。但是考虑C用短信息的庞大用L是q种游戏的潜在市场,因此我们仍将最l得C个巨大的市场定w模型?<BR><BR>  在全球部分发辑֜区,Z短信息的手机游戏服务已经开始赢利。特别是在欧zԌ已经初步形成了一个规模达数十亿美元的行业市场。然而反观北市场的规模Q目前则只有令h失望?亿美元而已Q在2008q_北美市场规模预期超?0亿美元大兟?<BR><BR>  <STRONG>复杂的可下蝲游戏</STRONG> <BR><BR>  未来几年中,可下载的手机游戏市场预计出现跨国和跨地域的发展势。在一些地区,如果2.5G?G手机以及相关|络的渗透率较高Q那么可下蝲的手机游戏市Z额也会相应出现明昄增幅。当Ӟ我们不能忽视短信息游戏所蕴含的市量,其中许多的游戏很可能得到用Lq泛接受甚至成ؓC会文化的一部分。这些积极因素都ؓW三Ҏ戏提供商和提供游戏下载的Udq营商带来丰厚的利润?<BR><BR>  管今后几年中手机游戏下载的h呈整体下降的趋势,但这一市场的赢利前景仍焉怹观。据Juniper Resource的研I显C,目前全球范围内可下蝲的手机游戏已lŞ成了一个h?0亿美元的巨大市场。今后几q中Q随着市场领域的不断扩大以及中高端手机h的相应下降,其市模将实现ȝQ向60亿美元迅速靠q。这的确是一ơ真正的商机Q?<BR><BR>  当然QJuniper Resource表示Q若惌q一切预成为现实,那么必须满两方面的前提条gQ始l有关键的市场推动因素以及有益于市场规模化的q营制和计费基?<BR><BR></FONT><STRONG> <CENTER><FONT size=2>底牌三:有多业障亟待解除?</FONT></CENTER></STRONG><BR><BR><FONT size=2>  <STRONG>手机外Ş因素</STRONG> <BR><BR>  所有移动娱乐服务的明显~点是屏q尺寸过和分L率太低。直C久前Q手Z不是专门为玩游戏而设计的。彩屏技术的出现增加了对使用者的吸引力,事实上,彩屏也是目前新手机销售的最大推动因素。但是,生适合于彩色屏q性能的手机游戏完全取决于游戏生商。嵌入式游戏和某些复古游戏最适合于基本的Ud电话屏幕Q因为它们的黑白屏幕分L率不高而且W合用户ҎU传l体验的期待心理。但对于其他大部分手机游戏而言Q则需要更高分辨率的屏q?<BR><BR>  <STRONG>手机内存制约因素</STRONG> <BR><BR>  有限的手机内存可满今天大多数普通游戏和其他׃应用的需要,但是在新一代游戏上则成为最大的障碍。例如,一般手?甚至是某些市面上更先q的手机)一ơ也只能保存4个游戏。这意味着玩家的游戏体验已l受到限制。他们必d出选择Q要么保留喜q游戏q有效地保存它们Q要么在他们希望试新游戏时必须攑ּ他们以前喜爱的游戏?<BR><BR>  <STRONG>新型手机的普?/STRONG> <BR><BR>  目前的一些游戏在设计上几乎可以适合大部分手机。但是,如果游戏市场x有一个持l繁荣的未来Q那么能够处理彩色图像、复合音色ƈ最l可处理Java下蝲的手机数量必d大增加和普及。也许,只有2.5G?G手机hq种可能性,q引发新一波互动游戏的潮?<BR><BR>  <STRONG>|络技?/STRONG> <BR><BR>  目前Q多数用h有基?G的手机,它们一般适合于通过SMS提供单的智力竞赛cȝ游戏和服务。ؓ了获得更丰富的游戏体验,用户需要WAP?G乃至3G手机Q但距离规模应用仍有很长的\要走。此外,在消费者心目中QWAP在许多方面的形象不佳Q性能不可靠,速度又慢得o人难以忍受。但是WAP可能是早期提供手机游戏的首选^台。当Ӟq必L一U新的、改q的WAP版本Q当?.5G?G|络上用时Q它的性能与WAP 1.0早期q告承诺的“无UInternet”非常像。当Ӟ考虑到它的Ş像缺损,未来的市场推q应量避免提到“WAP因素”?/FONT><img src ="http://m.tkk7.com/yangsail/aggbug/1373.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/yangsail/" target="_blank">蓝色雪焰</a> 2005-02-20 18:15 <a href="http://m.tkk7.com/yangsail/archive/2005/02/20/1373.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用J2ME在移动设备上实现动画http://m.tkk7.com/yangsail/archive/2005/02/17/1286.html蓝色雪焰蓝色雪焰Thu, 17 Feb 2005 12:04:00 GMThttp://m.tkk7.com/yangsail/archive/2005/02/17/1286.htmlhttp://m.tkk7.com/yangsail/comments/1286.htmlhttp://m.tkk7.com/yangsail/archive/2005/02/17/1286.html#Feedback0http://m.tkk7.com/yangsail/comments/commentRss/1286.htmlhttp://m.tkk7.com/yangsail/services/trackbacks/1286.html使用MIDP(Mobile Information Device Profile)的开发h员经怼抱怨用些什么办法才可以在一个MIDlet上显C动甅RMIDP 1.0 没有直接提供对动ȝ支持(正在开发中的MIDP 2.0支持)Q但真要是自己去实现Q其实也q是一件很隄事?

M动画的最基本的前提,是要在够快的时间内昄和更换一张张的图片,让h的眼睛看到动的画面效果。图片必L照顺序画出来。从一张图片到下一张图片之间的变化小Q效果会好?

首先要做的,是用你的图片处理YӞ比如ps或者fireworkQ创Zpd相同大小的图片来l成动画。每张图片代表动M帧?BR>

你需要制作一定数量的-Q越多的帧会让你的动ȝ上去^滑。制作好的图片一定要保存成PNG(Portable Network Graphics) 格式QMIDP唯一支持的图片格式;Q有两个办法让你刚做好的囄在MIDlet上变成动甅R第一Q把囄都放C个web服务器上Q让MIDlet下蝲他们QMIDP内置的HTTP支持。第二个办法更简单,把图片用MIDlet打包成jar文g。如果你使用的是J2ME开发工P把PNG文g攑֜你的目文g里面可以了?

动画的过E其实更像帐本记录:昄当前帧,然后适当地更换到下一帧。那么用一个类来完成这个工作应该是很恰当的Q那好,我们先定义一个AnimatedImagec:

import java.util.*;
import javax.microedition.lcdui.*;
// 定义了一个动画,该动d实只是一pd相同大小的图?
// 轮流昄Q然后模拟出的动?
public class AnimatedImage extends TimerTask {;
private Canvas canvas;
private Image[] images;
private int[][] clipList;
private int current;
private int x;
private int y;
private int w;
private int h;

// Construct an animation with no canvas.

public AnimatedImage( Image[] images ){;
this( null, images, null );
};

// Construct an animation with a null clip list.

public AnimatedImage( Canvas canvas, Image[]
images ){; this( canvas, images, null );
};

// Construct an animation. The canvas can be null,
// but if not null then a repaint will be triggered
// on it each time the image changes due to a timer
// event. If a clip list is specified, the image is
// drawn multiple times, each time with a different
// clip rectangle, to simulate transparent parts.

public AnimatedImage( Canvas canvas, Image[] images,
int[][] clipList ){;
this.canvas = canvas;
this.images = images;
this.clipList = clipList;

if( images != null && clipList != null ){;
if( clipList.length < images.length ){;
throw new IllegalArgumentException();
};
};

if( images != null && images.length > 0 ){;
w = images[0].getWidth();
h = images[0].getHeight();
};
};

// Move to the next frame, wrapping if necessary.

public void advance( boolean repaint ){;
if( ++current >= images.length ){;
current = 0;
};

if( repaint && canvas != null && canvas.isShown()
){;
canvas.repaint( x, y, w, h );
canvas.serviceRepaints();
};
};

// Draw the current image in the animation. If
// no clip list, just a simple copy, otherwise
// set the clipping rectangle accordingly and
// draw the image multiple times.

public void draw( Graphics g ){;
if( w == 0 || h == 0 ) return;

int which = current;

if( clipList == null || clipList[which] == null
){;
g.drawImage( images[which], x, y,
g.TOP | g.LEFT );
}; else {;
int cx = g.getClipX();
int cy = g.getClipY();
int cw = g.getClipWidth();
int ch = g.getClipHeight();

int[] list = clipList[which];

for( int i = 0; i + 3 <= list.length; i +=
4 ){;
g.setClip( x + list[0], y + list[1],
list[2], list[3] );
g.drawImage( images[which], x, y,
g.TOP | g.LEFT );
};

g.setClip( cx, cy, cw, ch );
};
};

// Moves the animation's top left corner.

public void move( int x, int y ){;
this.x = x;
this.y = y;
};

// Invoked by the timer. Advances to the next frame
// and causes a repaint if a canvas is specified.

public void run(){;
if( w == 0 || h == 0 ) return;

advance( true );
};
};



蓝色雪焰 2005-02-17 20:04 发表评论
]]>囑֝象素化的边缘抗锯齿处?/title><link>http://m.tkk7.com/yangsail/archive/2005/02/17/1283.html</link><dc:creator>蓝色雪焰</dc:creator><author>蓝色雪焰</author><pubDate>Thu, 17 Feb 2005 10:59:00 GMT</pubDate><guid>http://m.tkk7.com/yangsail/archive/2005/02/17/1283.html</guid><wfw:comment>http://m.tkk7.com/yangsail/comments/1283.html</wfw:comment><comments>http://m.tkk7.com/yangsail/archive/2005/02/17/1283.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/yangsail/comments/commentRss/1283.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/yangsail/services/trackbacks/1283.html</trackback:ping><description><![CDATA[<P><FONT size=2><STRONG><FONT size=3>囑֝象素化的边缘抗锯齿处?BR></FONT></STRONG>׃通常用作游戏画面的h物肖像、背景等需要做扣图处理的图片在处理前底色都是白Ԍ如果直接q样的话Q很可能做出来的象素化后的图片(?56色的环境下,整个囑֝颜色于40Ԍ会有明显的边~锯ѝ?BR>克服锯或者减弱锯齿效应以前用的Ҏ是修边,即用pQ例如纯黑,把图块的周围描绘一遍,q样做可以很好的减少锯q能提高象素的味道,但是~点有:对于极细的线条的处理Q例如一条线只有1个象素宽Q那么描边过后就?象素宽,q在某些场合是不可取的,很可能会破坏原由画面的味道。而对于手Z的图象处理,q样的结果肯定不行?BR>那么Q就只好q行没有描边的处理方式?BR>查看了日本最新格斗游戏kof2003的图片内容,kofpd的h物从来都是不描边的,卛_全用色块来表现角艌Ӏ这对于32*32寸以内的小囄来说Q直接在Ҏ内照原画用象素画法画一遍就可以了,但是如果寸是大?2*32的或者战局大半个手机屏q的一q图呢?例如人物的特写,rpg中会用到的头像?q个时候如果还用象素的方式来描l很可能会跟原画有相当大的出入,而且修改h也很ȝ?BR>因此Q可以利用原Lq行加工Q?BR>把底色设|ؓ蓝色Q?,0,255Q然后羃图片尺寸,q样囑֝的周围一圈就很好的和兰色融合在了一P然后通过反复的在索引色及rgb色之间的转换减少原色Q同时对一些相邻色q行删减Q把盔R的颜色用灌桶填成同一U颜Ԍ例如121,34,133?21Q?4Q?44可以合成ؓ一个颜Ԍ。这hl做出来的图片就是以兰色为底色的颜色很少但失真ƈ不严重的囄Q把加工的图块扣取出来,攑ֈ背景里面Q发现融合程度很好,边缘锯弱化很多?BR></FONT><A target=_blank><FONT size=2><IMG alt="" src="http://www.move2008.com/bbs/UploadFile/200421313425417831.gif" onload="javascript:if(this.width>screen.width-333)this.width=screen.width-333" border=0 dypop="按此在新H口览囄"></FONT></A><FONT size=2> </FONT></P> <P><FONT size=2><B>q是以白色ؓq布做出来的囄----</B>锯非常明显?BR></FONT><A target=_blank><FONT size=2><IMG alt="" src="http://www.move2008.com/bbs/UploadFile/200421313495885142.gif" onload="javascript:if(this.width>screen.width-333)this.width=screen.width-333" border=0 dypop="按此在新H口览囄"></FONT></A></P> <P><FONT size=2><STRONG>完成的原画背静改ؓ兰色------</STRONG>是这h子滴Q?BR></FONT><A target=_blank><FONT size=2><IMG alt="" src="http://www.move2008.com/bbs/UploadFile/200421313504382357.gif" onload="javascript:if(this.width>screen.width-333)this.width=screen.width-333" border=0 dypop="按此在新H口览囄"></FONT></A></P> <P><FONT size=2><STRONG>上囑և尺寸过?-----</STRONG>是q个样子_<BR></FONT><A target=_blank><FONT size=2><IMG alt="" src="http://www.move2008.com/bbs/UploadFile/200421313513283131.gif" onload="javascript:if(this.width>screen.width-333)this.width=screen.width-333" border=0 dypop="按此在新H口览囄"></FONT></A></P> <P><FONT size=2>此时再用你所能想到的MҎQ在不明昑֤真的前提下进行颜色压~,最后把兰色LQ就得到成品啦。哈哈啊?/FONT></P> <P><FONT size=2><STRONG>用另外一个女生的囄做的?BR></STRONG>同样的方法,可以取得同样良好的结果?BR></FONT><A target=_blank><FONT size=2><IMG alt="" src="http://www.move2008.com/bbs/UploadFile/20042131401036261.gif" onload="javascript:if(this.width>screen.width-333)this.width=screen.width-333" border=0 dypop="按此在新H口览囄"></FONT></A></P> <P><FONT size=2><STRONG>反复q行不同背静的测试,<BR></STRONG>发现锯问题解决得很好,兰色的背静幕布在抠图q后能与其他颜色很好的融合?BR></FONT><A target=_blank><FONT size=2><IMG alt="" src="http://www.move2008.com/bbs/UploadFile/20042131414772402.gif" onload="javascript:if(this.width>screen.width-333)this.width=screen.width-333" border=0 dypop="按此在新H口览囄"></FONT></A></P><A target=_blank></A><img src ="http://m.tkk7.com/yangsail/aggbug/1283.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/yangsail/" target="_blank">蓝色雪焰</a> 2005-02-17 18:59 <a href="http://m.tkk7.com/yangsail/archive/2005/02/17/1283.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>~程技巧在动画斚whttp://m.tkk7.com/yangsail/archive/2005/02/17/1281.html蓝色雪焰蓝色雪焰Thu, 17 Feb 2005 10:07:00 GMThttp://m.tkk7.com/yangsail/archive/2005/02/17/1281.htmlhttp://m.tkk7.com/yangsail/comments/1281.htmlhttp://m.tkk7.com/yangsail/archive/2005/02/17/1281.html#Feedback0http://m.tkk7.com/yangsail/comments/commentRss/1281.htmlhttp://m.tkk7.com/yangsail/services/trackbacks/1281.html动画斚w.

前面的朋友说了动ȝ制作,一个动L由很多l在?,您说的方法把一帧的动d成一q幅的图?再一q幅地蝲?q样做的效率不高.应该把各q员的动L在一?做成一q大的图,加蝲一q大图比加蝲多幅图效率要高,一q大图也比多q小囑֮易管理得?那么怎样做呢?


做法和前面朋友说的差不多,关键是这个方?
drawImage(Image img,dx1,dy1,dx2,dy2,sx1,sy1,sx1,sy1,this)
其中Image img是来源图?
    dx1是目的区域的===左上===点?==X====坐标;

    dy1是目的区域的===左上===点?==Y====坐标;

    dx2是目的区域的===右下===点?==X====坐标;

    dy2是目的区域的===右下===点?==Y====坐标;

    sx1是来源区域的===左上===点?==X====坐标;

    sy1是来源区域的===左上===点?==Y====坐标;

    sx2是来源区域的===右下===点?==X====坐标;

    sy2是来源区域的===右下===点?==Y====坐标.
================================================================
下面是一个动ȝE序代码.
import java.awt.*;
import java.applet.*;
public class Seriallmage4 extends Applet implements Runnable
{
  int SPF;                       //用来表示U程暂停的时?BR>  int sx,sy;
/******************************************************************
sx,sy用来表示来源区域的左上顶?因ؓ每一帧我们都做成了长?0?7的图,再把它们攑֜一起做成一q大的图,
所以来源区域的右下点的坐标等于左上顶点坐标加上长和高.
式子?sx+80;sy+87
******************************************************************/                     
  Image Animation;              //来源图象
  MediaTracker MT;              //囑փq踪?用来查图像是否完全加?BR>  Thread newThread;             //新的U程.
  Image OffScreen;              //后台囑փ;
  Graphics drawOffScreen;       //l制后台囑փ的实?实例).
//======================init()函数===========================
  public void init()
  {
     SPF=100;                   //U程暂停的时间是100豪秒,
     MT=new MediaTracker(this); //实体化图像追t器.
     Animation=getImage(getDocumentBase(),"lunisEx.gif");//加蝲囑փ.
//======================//q踪囑փ=============================
     MT.addImage(Animation,0);  
     try
     {
       showStatus("图象加蝲?...");   //在状态栏中显CZ?BR>       MT.waitForAll();                //{待加蝲
     }
     catch(InterruptedException E){}
//============================================================
     OffScreen=createImage(300,300);  //建立后台画面的实?BR>     drawOffScreen=OffScreen.getGraphics();  //取得后台画面的绘制类
  }
//===========================================================
  public void start()                //start函数
  {
     newThread=new Thread(this);     //建立U程
     newThread.start();              //启动U程
  }
  public void stop()                 //stop函数
  {
     newThread=null;                 //U程设ؓnull
  }
//==========================================================
  public void paint(Graphics g)
  {
     drawOffScreen.setColor(Color.green);    //讄后台画面的背景色,
     drawOffScreen.fillRect(0,0,300,300);    //Mơ背?作用是清除后台画?如果背景是一q画
//则要用这q图来画.
     drawOffScreen.drawImage(Animation,20,20,250,250,sx,sy,sx+80,sy+87,this);//在后台画面绘?BR>//的图?
     g.drawImage(OffScreen,0,0,300,300,this);//把后台画面画到前台画?BR>  }
  public void update(Graphics g)
  {
     paint(g);                              
  }
//====================新动d@环在?=======================50
   public void run()                       
   {
      while(newThread !=null)               //如果U程不等于null
      {
        repaint();                         // 重画一?
        try
        {
           Thread.sleep(SPF);              //让线E暂?BR>           sx+=80;                         //M一ơ后,改变来源区域,使其C一?
           if(sx==800)                     //我的囑փ是一q?00*170?有两?每行十,如果sx走到?BR>//800p明播攑֮W一行了,
           {
              sy+=85;                      //播放完第一行后,改变来源区域的左上顶点其跑到第二行.
              sx=0;
              if(sy==170)                  //如果播放完第二行?又让它回到第一?
              {
                 sy=0;
              }
           }
        }
        catch(InterruptedException E){}
      }
    }

}
动画每秒播放多少帧好?
电媄的是每秒24?q样的速度不仅能生视觉停?而且让h感觉到画面非常流?那么是不是我们做游戏也要用这个速度?{案是否定的,实际上每U播?0帧就_产生视觉停留,如果讄高了会消耗更多的资源.臛_的是,有一些手每秒10帖都做不?



蓝色雪焰 2005-02-17 18:07 发表评论
]]>
J2ME游戏开发实例讲?/title><link>http://m.tkk7.com/yangsail/archive/2005/02/17/1263.html</link><dc:creator>蓝色雪焰</dc:creator><author>蓝色雪焰</author><pubDate>Wed, 16 Feb 2005 17:02:00 GMT</pubDate><guid>http://m.tkk7.com/yangsail/archive/2005/02/17/1263.html</guid><wfw:comment>http://m.tkk7.com/yangsail/comments/1263.html</wfw:comment><comments>http://m.tkk7.com/yangsail/archive/2005/02/17/1263.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/yangsail/comments/commentRss/1263.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/yangsail/services/trackbacks/1263.html</trackback:ping><description><![CDATA[<P><span id="lzzn3rz" class=f14><STRONG><FONT size=2>本文通过使用J2ME开发华定w游戏Q介l了J2ME游戏开发的基本模式....</FONT></STRONG></SPAN></P> <P><span id="tvh3d99" class=f14><FONT size=2><STRONG>一、序a<BR><BR></STRONG>  昨天在网上闲逛,发现一讲解用delphi实现华容道游戏的文章Q颇受启发.于是Q生了华定w游戏UL到手Zȝ冲动Q现在手机游戏琳琅满目,不一而Q华定w的实现版本也很多Q正巧不久前W者对J2ME下了一番功夫,正想借这个机会小试牛刀。选用J2ME的原因还有一个就是目前Java开发大行其刎ͼ无线增殖业务q猛发展QJ2ME的应用日渐活跃v来,也希望我的这文章能够ؓJ2ME知识的普及和开发团队的壮大推L助澜。由于长期受ISO规范的媄响,q次试牛刀我也打算늅软g工程的要求,q取瀑布式的开发模式来规划目Q也希望借此Z向各位没有机会参与正式项目开发的读者介l一下Y件开发的程?/FONT></SPAN></P> <P><span id="lj3vrp1" class=f14><FONT size=2>  q里我们先定义项目组的h员体?其实只有我一个h)Q技术调研、需求分析、概要设计、详l设计、编码、测试均有笔者一人担任;工q里我找了个捷径Q盗用网上现成的囄Q然后用ACDSee把它由BMP转换成PNG格式(我出于讲座的目的Q未做商业应用,应该不算侉|?Q至于发布工作,׃~少OTA服务器,此项工作不做(但是我会介绍q步如何??BR><BR>  接下来,我们规划一下项目实现的旉表,以我个hl验Q设惛_下:技术调研用2?q部分解决项目的可行性和重大技术问题,旉会长一?Q需求分析用半天(毕竟有现成的东东可以参照Q只要理清思\p了,况且q有很多以前用过的设计模式和写好的代?Q概要设计再用半?有了需求,概要只不够是照方抓药)Q详l设计要??q一步要把所有的问题x楚,q要可能的准确描述出来)Q编码用2?其实1天就够了Q技术已l不是问题,多计划出一天来应付H发事g)Q测试用2?试应该臛_占全部项目的四分之一Q不q这个项目只是一个DemoQ也太简单了)Q发布也要用上半?管我们不去实际发布它,但是q要q旉搞清楚应该如何做)Q最后就是项目ȝ和开庆功?旉待定)?BR><BR>  <B>?利其?/B><BR><BR>  “公Ʋ善其事Q必先利其器”,做项目之前第一步是前期调研Q我们要做的华容道这个东东随处可见,我们要调研的是两个方面:<BR><BR>  1、游戏的内容Q游戏本w很单,是有几个格子,Ҏ占据其中一个较大的格子Q然后被几个格子包围Q这些格子Ş状不一定相同,但是挡住了曹操移动的方向Q游戏者需要挪动这些格子最l把ҎUdC个指定的位置才算是过养I更具体的分析我们攑֜后面需求分析和概要设计中讨论?BR><BR>  2、技术储备:谈到技术,q里单介l一下J2ME.Java有三个版本,分别是J2MEQ微型版Q?J2SEQ标准版Q?J2EEQ企业版Q.J2ME是一个标准,采用Q层l构设计Q最低层是配|层QConfigurationQ也是讑֤层,其上是简表层QProfileQ?再上是应用层QApplicationQ?MIDP是Ud信息讑֤表,目前L手机支持MIDP1.0Q最新的是MIDP2.0,它比前一个版本增加了Ҏ戏的支持Q在javax.microedition.lcdui.game包中提供了一些类来处理游戏中的技术,比如我们后面会用到的Spritec,它是用来{囄?权衡再三Q笔者决定用MIDP2.0来做开发.首先需要安装一个J2ME的模拟器Q我们就用Sun公司的WTK2.0Q我觉得Sun的东西最权威Q当然你也可以用Nokia.Siemens或是Motolora{其他模拟器Q但是他们的JDK不尽相同Q写出来的程序移植是比较ȝ的.Sun公司的WTK2.0可以刎ͼA href="http://here/?Qhttp://here/下</AQ蝲Q当然要x功下载的前提是你要先注册成ؓSun的会员(其实q样对你是有好处的)Q当下来之后是按照提示一步一步的安装Q安装好了之后,我们用一?Hello World"E序开始你的J2ME之旅Q我们启动WTK2.0工具集中的KToolBarQ然后点击New Project按钮Q在弹出的输入框中输入Project Name为HelloWorld,MIDlet Class Name为Hello,然后点击Create ProjectQ开始生成项目,工具会弹出MIDP配置表,q里接受生成的默认|以后q可以修改)点击OKQ工hC我们把写好的Java源程序放到[WTK_HOME]\apps\HelloWorld\src目录之下Q我们编辑如下代码,q保存在上述目录之下Q文件名为Hello.java?BR><BR></FONT></P> <P> <TABLE width="100%" bgColor=#ffffff> <TBODY> <TR> <TD><FONT color=#0000ff size=2>import javax.microedition.midlet.*;<BR>import javax.microedition.lcdui.*;<BR>public class Hello extends MIDlet<BR>{<BR>private Display display;<BR>public Hello(){<BR>display =Display.getDisplay(this);<BR>}<BR>public void startApp(){<BR>TextBox t = new TextBox("Hello","Hello",256,0);<BR>display.setCurrent(t);<BR>}<BR>public void pauseApp(){<BR>}<BR>public void destroyApp(boolean unconditional){<BR>}<BR>}</FONT></TD></TR></TBODY></TABLE></P> <P><BR><FONT size=2>  保存好了之后Q点击Build按钮Q工具会Z~译E序Q如无意外再点击Run按钮Q会弹出一个手机界面,剩下的就不用我教了吧Q用鼠标Ҏ机按键一狂点)。呵呵,你的W一个J2MEE序已经OK?什么?你还一炚w没懂呢(真是厉害Q不懂都能写出J2MEE序来,果然是高手)Q我q里主要是介lWTK2.0工具的用,E序q不是目的,不懂的话后面q会有详l的解说Q这里只是带你上路.什么?你不懂JavaQ那也没有关p,后面我再讲得l一炏V?BR><BR>  跌J2MEQ我们先来讲Ҏ戏的理论Q具体到华容道这个游戏,主要有三个方面,贴图Q游戏操作.逻辑判断Q这里讲讲脓图,其他两方面放在概要设计和详细设计里讲Q所谓的贴图Q其实就是画图,是在要昄囑Ş的位|上输出一副图片,Q要是牵扯到动画pȝ一些,可以使用TimerTask.Thread或Rannable之类的技?Q这副图片可以是事先准备好的也可以是临时处理的.在J2ME中有一个Imagec?专门用于理囄Q它有createImage()ҎQ可以直接读取图片文ӞJ2ME只支持PNG格式的图片)Q也可以截取已有的图片的一部分Q这h们可以把很多囄攑֜一P然后一张一张的截下来,好处是节省存储空间和文gd旉Q对于手两者都是性能的瓶颈)QJ2MEq有一个Graphicsc,专门用于l图Q它有drawImage()ҎQ可以把一副图片在指定的位|上昄出来Q它q有drawRect()Ҏ和setColor()ҎQ这两个Ҏ在后面我们进行游戏操作时׃用到Q这里先交代一下.有了囄和绘囄ҎQ还需要知道把囄到谁w上QJ2ME提供了一个Canvasc,字面意思就是画布,它有一个paint()Ҏ用于h面Q还有一个repaint()Ҏ用于调用paint()ҎQ听着有些p涂是吧Q不要紧Q我来结合具体程序讲解一下.Z今后~程的方便,我们创徏两个cImages和Draw,Images用于保存一些常量值和囄QDraw主要是用于画图,q两个类的源代码如下?BR><BR>  Imagescȝ源代码如下:<BR><BR></FONT> <TABLE width="100%" bgColor=#ffffff> <TBODY> <TR> <TD><FONT color=#0000ff size=2>package huarongroad; </FONT> <P><FONT color=#0000ff size=2>import javax.microedition.lcdui.*;<BR>import javax.microedition.lcdui.game.*;</FONT></P> <P><FONT color=#0000ff size=2>public class Images {//保存帔R<BR>//l图位置帔R<BR>public static final int UNIT = 32;//方块的单位长?BR>public static final int LEFT = 10;//d的左边界点<BR>public static final int TOP = 9;//d的上边界点<BR>//地图位置帔R<BR>public static final int WIDTH = 4;//地图的宽?BR>public static final int HEIGHT = 5;//地图的高?BR>//地图标记帔R<BR>public static final byte CAOCAO = (byte) 'a'; QA href="file://?Qfile://曹</AQ操的地图标?BR>public static final byte MACHAO = (byte) 'b';//马超的地图标?BR>public static final byte HUANGZHONG = (byte) 'c';//黄忠的地图标?BR>public static final byte GUANYU = (byte) 'd';//关羽的地图标?BR>public static final byte ZHANGFEI = (byte) 'e';//张飞的地图标?BR>public static final byte ZHAOYUN = (byte) 'f';//赵云的地图标?BR>public static final byte ZU = (byte) 'g';//卒的地图标记<BR>public static final byte BLANK = (byte) 'h';//I白的地图标?BR>public static final byte CURSOR = (byte) 'i';//光标的地图标?BR>//地图l合标记帔R<BR>public static final byte DLEFT = (byte) '1'; QA href="file://l?Qfile://l</AQ合囑Ş左边标记<BR>public static final byte DUP = (byte) '2'; QA href="file://l?Qfile://l</AQ合囑Ş上边标记<BR>public static final byte DLEFTUP = (byte) '3'; QA href="file://l?Qfile://l</AQ合囑Ş左上标记<BR>//囄帔R<BR>public static Image image_base;//基本囄<BR>public static Image image_Zhaoyun;//赵云的图?BR>public static Image image_Caocao;//Ҏ的图?BR>public static Image image_Huangzhong;//黄忠的图?BR>public static Image image_Machao;//马超的图?BR>public static Image image_Guanyu;//关羽的图?BR>public static Image image_Zhangfei;//张飞的图?BR>public static Image image_Zu;//卒的囄<BR>public static Image image_Blank;//I白的图?BR>public static Image image_Frame;//游戏框架的图?/FONT></P> <P><FONT color=#0000ff size=2>public Images() {//构造函?BR>}</FONT></P> <P><FONT color=#0000ff size=2>public static boolean init() {//初始化游戏中用到的图?BR>try {<BR>image_base = Image.createImage("/huarongroad/BITBACK.png");<BR>image_Frame = Image.createImage(image_base, 126, 0, 145, 177,<BR>Sprite.TRANS_NONE);<BR>//SpritecL用来{囄的,是MIDP2.0新新增加的支持游戏的Ҏ?BR>image_Zhaoyun = Image.createImage(image_base, 0, 0, UNIT, 2 * UNIT,<BR>Sprite.TRANS_NONE);<BR>image_Caocao = Image.createImage(image_base, UNIT, 0, 2 * UNIT,<BR>2 * UNIT, Sprite.TRANS_NONE);<BR>image_Huangzhong = Image.createImage(image_base, 3 * UNIT, 0, UNIT,<BR>2 * UNIT,<BR>Sprite.TRANS_NONE);<BR>image_Machao = Image.createImage(image_base, 0, 2 * UNIT, UNIT,<BR>2 * UNIT,<BR>Sprite.TRANS_NONE);<BR>image_Guanyu = Image.createImage(image_base, UNIT, 2 * UNIT,<BR>2 * UNIT, UNIT,<BR>Sprite.TRANS_NONE);<BR>image_Zhangfei = Image.createImage(image_base, 3 * UNIT, 2 * UNIT,<BR>UNIT, 2 * UNIT,<BR>Sprite.TRANS_NONE);<BR>image_Zu = Image.createImage(image_base, 0, 4 * UNIT, UNIT, UNIT,<BR>Sprite.TRANS_NONE);<BR>image_Blank = Image.createImage(image_base, 1 * UNIT, 4 * UNIT,UNIT,<BR>UNIT,<BR>Sprite.TRANS_NONE);</FONT></P> <P><FONT color=#0000ff size=2>return true;<BR>}catch (Exception ex) {<BR>return false;<BR>}<BR>}<BR>}</FONT></P></TD></TR></TBODY></TABLE></P> <P><FONT size=2>  Drawcȝ源代码如下:<BR></FONT></P> <P> <TABLE width="100%" bgColor=#ffffff> <TBODY> <TR> <TD> <P><FONT color=#0000ff size=2>package huarongroad;</FONT></P> <P><FONT color=#0000ff size=2>import javax.microedition.lcdui.*;</FONT></P> <P><FONT color=#0000ff size=2>public class Draw {<BR>//l制游戏中的囄<BR>public Draw(Canvas canvas) {//构造函?BR>}</FONT></P> <P><FONT color=#0000ff size=2>public static boolean paint(Graphics g, byte img, int x, int y) {<BR>//在地囄x,y点绘制img指定的图?BR>try {<BR>paint(g, img, x, y, Images.UNIT);//把地图x,y点{化成d的绝对坐标,l图<BR>return true;<BR>}<BR>catch (Exception ex) {<BR>return false;<BR>}<BR>}</FONT></P> <P><FONT color=#0000ff size=2>public static boolean paint(Graphics g, byte img, int x, int y, int unit) {<BR>try {<BR>switch (img) {<BR>case Images.CAOCAO://L?BR>//变成l对坐标Qƈ做调?BR>g.drawImage(Images.image_Caocao, Images.LEFT + x * unit,<BR>Images.TOP + y * unit,<BR>Graphics.TOP | Graphics.LEFT);<BR>break;<BR>case Images.GUANYU://d?BR>g.drawImage(Images.image_Guanyu, Images.LEFT + x * unit,<BR>Images.TOP + y * unit,<BR>Graphics.TOP | Graphics.LEFT);<BR>break;<BR>case Images.HUANGZHONG://画黄?BR>g.drawImage(Images.image_Huangzhong, Images.LEFT + x * unit,<BR>Images.TOP + y * unit,<BR>Graphics.TOP | Graphics.LEFT);<BR>break;<BR>case Images.MACHAO://画马?BR>g.drawImage(Images.image_Machao, Images.LEFT + x * unit,<BR>Images.TOP + y * unit,<BR>Graphics.TOP | Graphics.LEFT);<BR>break;<BR>case Images.ZHANGFEI://d?BR>g.drawImage(Images.image_Zhangfei, Images.LEFT + x * unit,<BR>Images.TOP + y * unit,<BR>Graphics.TOP | Graphics.LEFT);<BR>break;<BR>case Images.ZHAOYUN://画n?BR>g.drawImage(Images.image_Zhaoyun, Images.LEFT + x * unit,<BR>Images.TOP + y * unit,<BR>Graphics.TOP | Graphics.LEFT);<BR>break;<BR>case Images.ZU://d<BR>g.drawImage(Images.image_Zu, Images.LEFT + x * unit,<BR>Images.TOP + y * unit,<BR>Graphics.TOP | Graphics.LEFT);<BR>break;<BR>case Images.BLANK://ȝ?BR>g.drawImage(Images.image_Blank, Images.LEFT + x * unit,<BR>Images.TOP + y * unit,<BR>Graphics.TOP | Graphics.LEFT);<BR>break;<BR>case Images.CURSOR://d?BR>g.drawRect(Images.LEFT + x * unit,<BR>Images.TOP + y * unit,Images.UNIT,Images.UNIT);<BR>break;<BR>}<BR>return true;<BR>}catch (Exception ex) {<BR>return false;<BR>}<BR>}<BR>} </FONT></P></TD></TR></TBODY></TABLE></P> <P><FONT size=2>  其中Imagescd的是l图位置帔RQ也是在画图时每个格子的长度和相对坐标原点位置要进行的调整Q、地图位|常量(地图的长、宽Q,地图标记帔RQh物对应的记号Q,地图l合标记帔RQ后面会l说Q,囄帔RQ存放h物的囄Q;DrawcM要负责在制定的位|画Zh物图片。下面我来说说ImagescM的地图标记常量和地图l合标记帔R。ؓ了能够灵zȝ安排各个关面的布局Q我们决定把游戏布局的信息存储在外部文g中,然后E序启动后把它读q来。这h们制定了一套存储图片的代码Q这是地图标记帔RQ如上面ImagescM定义的Caocao(Ҏ)用a字符来表C,当程序读到a字符时就能将它{化成Ҏ对应的图片,q在da字符的位|上q行昄。但是从实际观察中我们发现所有的囄q不是统一大小的,有的?个格子,有的?个格子,q有的占1个格子,而且即便同是占两个格子的囄q有横、竖之分。有鉴于此,我们引入了地囄合标记常量,是说在遇到占有多个格子的时候,?(也就是Images.LEFT)表示它的左边是一个真正的地图标记Q?(也就是Images.UP)表示它的上边是一个真正的地图标记Q?(也就是Images.LEFTUP)表示它的左上Ҏ一个真正的地图标记。地囄合标记常量其实就是用来占位置的,与实际显C无养I当后面我们将到移动时q会再来分析l合标记的用?BR><BR>  DrawcM要是用来在画布上d囑ŞQ它有两个paintҎQ这是很常见的函数重载。但是程序中实际上只用到?个参数的paintҎQ它直接获得要画囄的相对坐标位|信息,然后调用5个参数的paintҎ?个参数的paintҎ相对坐标位|信息{换成l对位置Qƈ实际调用Graphics.drawImage()ҎQ将Images中的囄M出来。这U实现方法的好处是灵zd便于扩展Q但你需要画囄位置q不能够对应到格子中的相对坐标位|时Q你可以直接调?个参数的paintҎQ而不必再M改这各类Q但你添加新的图片时Q只要在Images中增加对应的帔RQ然后向Draw?个参数的paintҎd一条处理就可以了?BR>写到q里Q两天的旉刚好用完?BR><BR></FONT><span id="d9d9npr" class=f14><FONT size=2>  <B>三、需求分?/B><BR><BR>  q部分叫做需求分析,听v来挺吓h的,其实是搞清楚我们要做什么,做成什么样Q那些不做。下面我引领着大家共同来完成这一步骤。首先,我们要做一个华定w的游戏,华容道的故事q里不再赘述了,但其中的人物在这里限定一下,如上面Imagesc里的定义,我们q个版本只提供曹?Caocao)、关?Guanyu)、张?Zhangfei)、n?Zhaoyun)、黄?Huangzhong)、马?Machao)和卒(Zu)。我们这里也限定一下游戏的操作ҎQ首先要通过方向键选择一个要Ud的区?是一张图?Q被选择的区域用黑色Ҏ框住Q选好后按Fire?是定?这块区域选中Q被选中的区域用l色Ҏ框住Q然后选择要移动到的区域,此时用红色方框框住被选择的区域;选好要移动到的区域之后按Fire键将要移动的区域(囄)Ud要移动到的区域,q去掉绿色和U色的方框。这里需要强调的概念有选择的区域、选中的区域、要Ud的区域和要移动到的区域,q四个概念请读者注意区分,当然也应当把q一部分记入数据字典之中。ؓ了文章的重点突?介绍如何制作一个J2ME的收集游?Q我们这里限定一些与本主题无关的内容暂不d玎ͼq关之后的动?实现时要用到TimerTask或Threadc,后箋的系列文章中我会详细介绍动画斚w的知?、关面之间的切换(其实很简单,当完成Q务之后重新再做一?、暂停和保存{操?q部分的内容介绍的资料很多,我也写不Z么新的东东来Q难免抄袭,故此免掉)?BR><BR>  需求分析基本完成,M午还有一D|_马上动手用ACDSee把从|上找来的BMP文gQ调整其大小?71*177(我的q个囄是两个部分合在一P所以比手机实际屏幕大了)Q另存ؓPNG格式。半天时间刚刚好Q不但搞清楚了要做的东东Q还把要用的囄准备好了?BR><BR>  <B>四、概要设?/B><BR><BR>  概要设计是从需求分析过渡到详细设计的桥梁和U带Q这一部分中我们确定项目的实现Ҏ和模块的划分。我们决定将整个目分成五个部分Q分别是前面介绍的Images、DrawQ还有Map和Displayable1和MIDlet1。Images和Drawcd能简单、结构固定,因此很多目我们都用这两各c,q里直接拿来Ҏp用了Q前面已l介l过q里不再赘述。MapcL用来从外部文件读入地图,然后保存在一个数l之中,q部分的内容是我们在本阶D讨论的重点。Displayable1是一个承了CanvascȝdQ它用来处理E序的主要控刉辑和一部分控制逻辑所需的辅助函敎ͼ主要函数应该包括用来l图的paint()函数、用来控制操作的keyPressed()函数、用来控刉择区域的setRange()函数、用来控刉择要移动到区域的setMoveRange()函数、用来移动选中区域的Move()函数和判断是否完成Q务的win()函数Q更具体的分析,我们攑ֈ详细设计中去l化。MIDlet1实际上就是一个控制整个J2ME应用的控制程序,其实也没有什么可特别的,它和我们前面介绍?Hello World"E序大同异Q这里就不展开来说了,后面会脓出它的全部代码?BR><BR>  MapcM要应该有一个Grid[][]的二l数l,用来存放华容道的地图Q还应该有一个read_map()函数用来从外部文件读取地囑ֆ容填充Grid数据l构Q再是要有一个draw_map()函数用来把Grid数据l构中的地图内容转换成图片显C出?当然要调用DrawcȝpaintҎ)。说到读取外部文ӞW者知道有两种ҎQ一U是传统的定义一个InputStream对象Q然后用getClass().getResourceAsStream()Ҏ取得输入,然后再从输入中取得外部文g的内容,例如<BR></FONT></P> <P><FONT size=2></FONT></P> <P> <TABLE width="100%" bgColor=#ffffff> <TBODY> <TR> <TD><FONT color=#0000ff size=2>InputStream is = getClass().getResourceAsStream("/filename");<BR>if (is != null) {<BR>byte a = (byte) is.read();<BR>}</FONT></TD></TR></TBODY></TABLE></P> <P><FONT color=#0000ff size=2>  q里h意文件名中的根\径是相对于便以后的class文g攄的位|,而不是源文g(java)。第二种Ҏ是用onnector.openInputStreamҎQ然后打开的协议是ResourceQ但是这U方法笔者反复尝试都没能调通,报告的错误是~少Resource协议Q估计第二种Ҏ用到J2ME的某些扩展类包,此处不再q。由于以前已l做q一些类似华定wq样的地图,q里直接l出Mapcȝ代码Q后面就不再详细解释MapcMQ以便于我们可以集中_֊处理Displayable1中的逻辑。Mapcȝ代码如下Q?BR></FONT></P> <P> <TABLE width="100%" bgColor=#ffffff> <TBODY> <TR> <TD> <P><FONT color=#0000ff size=2>package huarongroad;</FONT></P> <P><FONT color=#0000ff size=2>import java.io.InputStream;<BR>import javax.microedition.lcdui.*;</FONT></P> <P><FONT color=#0000ff size=2>public class Map {<BR>//处理游戏的地图,负责从外部文件加载地图数据,存放地图数据Qƈ按照地图数据l制地图</FONT></P> <P><FONT color=#0000ff size=2>public byte Grid[][];//存放地图数据</FONT></P> <P><FONT color=#0000ff size=2>public Map() {//构造函敎ͼ负责初始化地图数据的存储l构<BR>this.Grid = new byte[Images.HEIGHT][Images.WIDTH];<BR>//用二l数l存攑֜图数据,注意W一l是竖直坐标Q第二维是水q_?BR>}</FONT></P> <P><FONT color=#0000ff size=2>public int[] read_map(int i) {<BR>QA href="file://?Qfile://从</AQ外部文件加载地图数据,q存攑֜存储l构中,q回值是光标点的位置<BR>//参数是加载地图文件的{<BR>int[] a = new int[2];//光标点的位置Q?是水q位|,1是竖直位|?BR>try {<BR>InputStream is = getClass().getResourceAsStream(<BR>"/huarongroad/level".concat(String.valueOf(i)));<BR>if (is != null) {<BR>for (int k = 0; k Q?Images.HEIGHT; k++) {<BR>for (int j = 0; j Q?Images.WIDTH; j++) {<BR>this.Grid[k][j] = (byte) is.read();<BR>if ( this.Grid[k][j] == Images.CURSOR ) {<BR>//判断出光标所在位|?BR>a[0] = j;//光标水^位置<BR>a[1] = k;//光标竖直位置<BR>this.Grid[k][j] = Images.BLANK;//光标位|设成空白背?BR>}<BR>}<BR>is.read();//d回RQ?3Q?忽略?BR>is.read();//d换行Q?0Q?忽略?BR>}<BR>is.close();<BR>}else {<BR>//d文gp|<BR>a[0] = -1;<BR>a[1] = -1;<BR>}<BR>}catch (Exception ex) {<BR>//打开文gp|<BR>a[0] = -1;<BR>a[1] = -1;<BR>}<BR>return a;<BR>}</FONT></P> <P><FONT color=#0000ff size=2>public boolean draw_map(Graphics g) {<BR>//调用Drawcȝ静态方法,l制地图<BR>try {<BR>for (int i = 0; i Q?Images.HEIGHT; i++) {<BR>for (int j = 0; j Q?Images.WIDTH; j++) {<BR>Draw.paint(g, this.Grid[i][j], j, i);//l制地图<BR>}<BR>}<BR>return true;<BR>}catch (Exception ex) {<BR>return false;<BR>}<BR>}<BR>}</FONT></P></TD></TR></TBODY></TABLE></P> <P><FONT size=2>  对于像华定wq样的小型地囑֏以直接用手工来绘制地囄内容Q比如:<BR><BR>fa1c<BR>2232<BR>bd1e<BR>2gg2<BR>gihg<BR><BR>  但是Q如果遇到像坦克大战或超U玛莉那L地图Q就必须另外开发一个地囄辑器?我会在后l的文章中介l用vb来开发一个地囄辑器)?/FONT></P> <P><span id="1hbfh9n" class=f14><FONT size=2>  <B>五、详l设?/B><BR><BR>  详细设计是程序开发过E中臛_重要的一个环节,好在我们在前面的各个阶段中已l搭建好了项目所需的一些工P现在q个阶段中我们只需集中_֊设计好Displayable1中的逻辑?两天的时间当然不只干q点z,q要把其他几个类的设计修改一?<BR><BR>  Displayable1q个c负责处理程序的控制逻辑。首先,它需要有表示当前关面的变量level、表C当前光标位|的变量loc、表CUd区域的变量SelectArea、表CUd到的区域的变量MoveArea、表C是否已有区域被选中而准备移动的变量Selected和Mapcȝ实例MyMap。然后,我们Ҏ用户按不同的键来处理不同的消息,我们要实现keyPressed()函数Q在函数中我们处理按键的上下左右和选中(Fire)Q这里的处理需要我展开来讲一Ԍ后面我很快会把这一部分详细展开?BR><BR>  接下来,是实现paint()函数Q我们打在q一部分中反复的重画背景、地囑֒选择区域Q这个函数必d理好区域被选中之后的画W颜色的切换Q具体讲是在没有选中M区域时要用黑色画W,当选重要移动的区域时用绿色画W,当选择要移动到的区域时改用U色ȝ(当然附加一张流E图是必不可的)?BR><BR>  再下面要实现的setRange()函数和setMoveRange()函数Q这两个函数用来讄要移动的区域和要Ud到的区域Q我的思\是利用前面在ImagescM介绍q的地图l合标记帔RQ当Ud到地囄合标记常量时Q根据该点地图中的值做逆向变换扑ֈ相应的地图标记常量,然后讄相应的loc、SelectArea和MoveArea,其中setMoveRange()函数q用C一个辅助函数isInRange(),isInRange()函数是用来判断给定的Ҏ否在已选中的要Ud的区域之?如果isInRange()的返回值是假ƈ且该点处的g是空白就表明要移动到的区域R犯了其他以被占用的区域。有了setRange()和setMoveRange()函数QMove()函数水到渠成了,Move()函数要Ud的区域移动到要移动到的区?在移动过E中分ؓ三步q行:<BR><BR>  W一.复制要移动的区域Q?BR><BR>  W二.复制出的要Ud区域复制到要Ud到的区域(q两步分开q行的目的是防止在复制过E中覆盖掉要Ud的区?Q?BR><BR>  W三.用isInRange2()判断l定的点是否在要Ud到的区域?不在要Ud到的区域内的点设|成I白?BR><BR>  下面我们详细的分析一下keyPressed()函数的实现方?首先,keyPressed()函数要处理按键的上下左右和选中(Fire),在处理时需要用CanvascȝgetGameAction函数来将按键的键D{换成游戏的方?q样可以提高游戏的兼Ҏ?因ؓ不同的J2ME实现,其方向键的键g一定是相同??BR><BR>  接下?分别处理四个方向和选中.当按下向上时,先判断是否已l选定了要Ud的区?即this.selected是否为真),如果没有选中要移动区域则让光标向上移动一?然后调用setRange()函数讄选择要移动的区域,再调用repaint()函数h屏幕,否则如果已经选中了要Ud的区?p光标向上Ud一?然后调用setMoveRange()函数判断是否能够向上Ud已选中的区?如果能移动就调用repaint()函数h屏幕,如果不能Udp光标向下退回到原来的位|?BR><BR>  当按下向下时,先判断是否已l选定了要Ud的区?如果没有选中要移动的区域则判断当前所处的区域是否Z个格?如果是两个格高则向下Ud两格,如果是一个格高则向下Ud一?接着再调用setRange()函数讄选择要移动的区域,而后调用repaint()函数h屏幕,否则如果已经选中了要Ud的区?p光标向下Ud一?然后调用setMoveRange()函数判断是否能够向下Ud已选中的区?如果能移动就调用repaint()函数h屏幕,如果不能Udp光标向上退回到原来的位|?按下向左时情况完全类似向上的情况,按下向右时情况完全类似向下的情况,因此q里不再赘述,详细情况请参见程序的源代码?BR><BR>  当按下选中键时,先判断是否已l选中了要Ud的区?如果已经选中了要Ud的区域就调用Move()函数完成pUd的区域到要移动到的区域的Udq程,接着调用repaint()函数h屏幕,然后已选择标记|成false,l箋调用win()函数判断是否完成了Q?否则如果q没有选定要移动的区域则再判断当前选中区域是否为空?如果不是I白将选中标记|成true,然后h屏幕.q里介绍一个技?在开发程序遇到复杂的逻辑的时?可以构造一格打印函数来所兛_的数据结构打印出来以利调?q里我们构造一个PrintGrid()函数,q个函数Ua是ؓ了调试之?效果q得不错.x我们完成了编码前的全部工作?/FONT></SPAN></P> <P><span id="lfrbnhr" class=f14><span id="pzlfzxn" class=f14><FONT size=2>  <B>?~码</B><BR><BR>  整个目共有五个c?有四个类的代码前面已l介l过?而且是在其他目中用过的相Ҏ熟的代码.现在只需全力d现Displayable1c?Displayable1cȝ代码如下:<BR></FONT></P> <P><FONT size=2></FONT></P> <P> <TABLE width="100%" bgColor=#ffffff> <TBODY> <TR> <TD> <P><FONT color=#0000ff size=2>package huarongroad;</FONT></P> <P><FONT color=#0000ff size=2>import javax.microedition.lcdui.*;</FONT></P> <P><FONT color=#0000ff size=2>public class Displayable1 extends Canvas implements CommandListener {</FONT></P> <P><FONT color=#0000ff size=2>private int[] loc = new int[2]; QA href="file://?Qfile://光</AQ标的当前位|,0是水q位|,1是竖直位|?BR>private int[] SelectArea = new int[4];//被选定的区域,卌Ud的区?BR>private int[] MoveArea = new int[4];//要移动到的区?BR>private Map MyMap = new Map();//地图c?BR>private boolean selected;//是否已经选中要移动区域的标志<BR>private int level;//但前的关?BR>public Displayable1() {//构造函?BR>try {<BR>jbInit();//JBuilder定义的初始化函数<BR>}catch (Exception e) {<BR>e.printStackTrace();<BR>}<BR>}<BR>private void Init_game(){<BR>//初始化游戏,d地图Q设|选择区域Q清IUd到的区域<BR>this.loc = MyMap.read_map(this.level);//d地图文gQƈq回光标的初始位|?BR>//0为水q位|,1为竖直位|?BR>this.SelectArea[0] = this.loc[0];//初始化选中的区?BR>this.SelectArea[1] = this.loc[1];<BR>this.SelectArea[2] = 1;<BR>this.SelectArea[3] = 1;<BR>this.MoveArea[0] = -1;//初始化要Ud到的区域<BR>this.MoveArea[1] = -1;<BR>this.MoveArea[2] = 0;<BR>this.MoveArea[3] = 0;<BR>}<BR>private void jbInit() throws Exception {//JBuilder定义的初始化函数<BR>QA href="file://?Qfile://初</AQ始化实例变?BR>this.selected = false;//讄没有被选中的要Ud区域<BR>this.level = 1;<BR>Images.init();//初始化图片常?BR>Init_game();//初始化游戏,d地图Q设|选择区域Q清IUd到的区域<BR>setCommandListener(this);//d命o监听Q这是Displayable的实例方?BR>addCommand(new Command("Exit", Command.EXIT, 1));//d“退出”按?BR>}</FONT></P> <P><FONT color=#0000ff size=2>public void commandAction(Command command, Displayable displayable) {<BR>//命o处理函数<BR>if (command.getCommandType() == Command.EXIT) {//处理“退出?BR>MIDlet1.quitApp();<BR>}<BR>}</FONT></P> <P><FONT color=#0000ff size=2>protected void paint(Graphics g) {<BR>//d函数Q用于绘制用L面,xC图片,勄选中区域和要Ud到的区域<BR>try {<BR>g.drawImage(Images.image_Frame, 0, 0,<BR>Graphics.TOP | Graphics.LEFT);//画背?BR>MyMap.draw_map(g);//按照地图内容d<BR>if ( this.selected )<BR>g.setColor(0,255,0);//如果被选中Q改用绿色画选中的区?BR>g.drawRect(this.SelectArea[0] * Images.UNIT + Images.LEFT,<BR>this.SelectArea[1] * Images.UNIT + Images.TOP,<BR>this.SelectArea[2] * Images.UNIT,<BR>this.SelectArea[3] * Images.UNIT);//d选择区域Q?BR>QA href="file://?Qfile://如</AQ果被选中Q就用绿?BR>QA href="file://?Qfile://否</AQ则Q用黑?BR>g.setColor(255,255,255);//恢复ȝ颜色<BR>if (this.selected) {//已经选中了要Ud的区?BR>g.setColor(255, 0, 255);//改用U色<BR>g.drawRect(this.MoveArea[0] * Images.UNIT + Images.LEFT,<BR>this.MoveArea[1] * Images.UNIT + Images.TOP,<BR>this.MoveArea[2] * Images.UNIT,<BR>this.MoveArea[3] * Images.UNIT);//d要移动到的区?BR>g.setColor(255, 255, 255);//恢复ȝ颜色<BR>}<BR>}catch (Exception ex) {<BR>}<BR>System.out.println(Runtime.getRuntime().freeMemory());<BR>System.out.println(Runtime.getRuntime().totalMemory());<BR>}</FONT></P> <P><FONT color=#0000ff size=2>private void setRange() {<BR>//讄Ud后能够选中的区?BR>//调整当前光标位置到地囄M|,卌录h物信息的位置<BR>if (this.MyMap.Grid[this.loc[1]][this.loc[0]] == Images.DLEFT) {<BR>this.loc[0] -= 1;//向左?BR>}else if (this.MyMap.Grid[this.loc[1]][this.loc[0]] == Images.DUP) {<BR>this.loc[1] -= 1;//向上?BR>}else if (this.MyMap.Grid[this.loc[1]][this.loc[0]] == Images.DLEFTUP) {<BR>this.loc[0] -= 1;//向左?BR>this.loc[1] -= 1;//向上?BR>}<BR>this.SelectArea[0] = this.loc[0];//讄光标的水q位|?BR>this.SelectArea[1] = this.loc[1];//讄光标的竖直位|?BR>//讄光标的宽?BR>if (this.loc[0] + 1 Q?Images.WIDTH) {<BR>this.SelectArea[2] = this.MyMap.Grid[this.loc[1]][this.loc[0] + 1] != (byte) '1' ?<BR>1 : 2;<BR>}else {<BR>this.SelectArea[2] = 1;<BR>}<BR>//讄光标的高?BR>if (this.loc[1] + 1 Q?Images.HEIGHT) {<BR>this.SelectArea[3] = this.MyMap.Grid[this.loc[1] + 1][this.loc[0]] != (byte) '2' ?<BR>1 : 2;<BR>}else {<BR>this.SelectArea[3] = 1;<BR>}<BR>}</FONT></P> <P><FONT color=#0000ff size=2>private boolean setMoveRange() {<BR>//讄要移动到的区域,能够Udq回true,否则q回false<BR>for (int i = 0; i Q?this.SelectArea[2]; i++) {<BR>for (int j = 0; j Q?this.SelectArea[3]; j++) {<BR>if (this.loc[1] + j Q? Images.HEIGHT ||<BR>this.loc[0] + i Q? Images.WIDTH ||<BR>(!isInRange(this.loc[0] + i, this.loc[1] + j) &&<BR>this.MyMap.Grid[this.loc[1] + j][this.loc[0] + i] !=<BR>Images.BLANK)) {<BR>return false;<BR>}<BR>}<BR>}<BR>this.MoveArea[0] = this.loc[0];<BR>this.MoveArea[1] = this.loc[1];<BR>this.MoveArea[2] = this.SelectArea[2];<BR>this.MoveArea[3] = this.SelectArea[3];<BR>return true;<BR>}</FONT></P> <P><FONT color=#0000ff size=2>private boolean isInRange(int x, int y) {<BR>//判断l定的(xQyQ点是否在选定区域之内Qx是水q_标,y是竖直坐?BR>if (x Q? this.SelectArea[0] &&<BR>x Q?this.SelectArea[0] + this.SelectArea[2] &&<BR>y Q? this.SelectArea[1] &&<BR>y Q?this.SelectArea[1] + this.SelectArea[3]) {<BR>return true;<BR>}else {<BR>return false;<BR>}<BR>}</FONT></P> <P><FONT color=#0000ff size=2>private boolean isInRange2(int x, int y) {<BR>//判断l定的(xQyQ点是否在要Ud到的区域之内Qx是水q_标,y是竖直坐?BR>if (x Q? this.MoveArea[0] &&<BR>x Q?this.MoveArea[0] + this.MoveArea[2] &&<BR>y Q? this.MoveArea[1] &&<BR>y Q?this.MoveArea[1] + this.MoveArea[3]) {<BR>return true;<BR>}else {<BR>return false;<BR>}<BR>}</FONT></P> <P><FONT color=#0000ff size=2>protected void keyPressed(int keyCode) {<BR>//处理按下键盘的事Ӟq是Canvas的实例方?BR>switch (getGameAction(keyCode)) {//按键的D{化成方向帔R<BR>case Canvas.UP://向上<BR>if (!this.selected) {//q没有选定要移动的区域<BR>if (this.loc[1] - 1 Q? 0) {//向上q有UdI间<BR>this.loc[1]--;//向上Ud一?BR>setRange();//讄光标Ud的区域,该函数能光标移动到地图M|?BR>repaint();//重新l图<BR>}<BR>}else {//已经选定了要Ud的区?BR>if (this.loc[1] - 1 Q? 0) {//向上q有UdI间<BR>this.loc[1]--;//向上Ud一?BR>if (setMoveRange()) {//能够UdQ该函数能够讄要移动到的区?BR>repaint();//重新l图<BR>}else {//不能Ud<BR>this.loc[1]++;//退回来<BR>}<BR>}<BR>}<BR>break;<BR>case Canvas.DOWN://向下<BR>if (!this.selected) {//q没有选定要移动的区域<BR>if (this.loc[1] + 1 Q?Images.HEIGHT) {//向下q有UdI间<BR>if (this.MyMap.Grid[this.loc[1] + 1][this.loc[0]] ==<BR>Images.DUP){//该图片有两个格高<BR>this.loc[1]++;//向下Ud一?BR>if (this.loc[1] + 1 Q?Images.HEIGHT) {//向下q有<BR>QA href="file://U?Qfile://U</AQ动I间<BR>this.loc[1]++;//向下Ud一?BR>setRange();//讄光标Ud的区域,<BR>QA href="file://?Qfile://该</AQ函数能光标移动到地图M|?BR>repaint();//重新l图<BR>}else {//向下没有UdI间<BR>this.loc[1]--;//退回来<BR>}<BR>}else {//该图片只有一个格?BR>this.loc[1]++;//向下Ud一?BR>setRange();//讄光标Ud的区域,<BR>QA href="file://?Qfile://该</AQ函数能光标移动到地图M|?BR>repaint();//重新l图<BR>}<BR>}else {<BR>}<BR>}else {//已经选定了要Ud的区?BR>if (this.loc[1] + 1 Q?Images.HEIGHT) {//向下q有UdI间<BR>this.loc[1]++;//向下Ud一?BR>if (setMoveRange()) {//能够UdQ该函数能够讄要移动到的区?BR>repaint();//重新l图<BR>}else {//不能Ud<BR>this.loc[1]--;//退回来<BR>}<BR>}<BR>}<BR>break;<BR>case Canvas.LEFT://向左<BR>if (!this.selected) {//q没有选定要移动的区域<BR>if (this.loc[0] - 1 Q? 0) {//向左q有UdI间<BR>this.loc[0]--;//向左Ud一?BR>setRange();//讄光标Ud的区域,该函数能光标移动到地图M|?BR>repaint();//重新l图<BR>}<BR>}else {//已经选定了要Ud的区?BR>if (this.loc[0] - 1 Q? 0) {//向左q有UdI间<BR>this.loc[0]--;//向左Ud一?BR>if (setMoveRange()) {//能够UdQ该函数能够讄要移动到的区?BR>repaint();//重新l图<BR>}else {//不能Ud<BR>this.loc[0]++;//退回来<BR>}<BR>}<BR>}<BR>break;<BR>case Canvas.RIGHT://向右<BR>if (!this.selected) {//q没有选定要移动的区域<BR>if (this.loc[0] + 1 Q?Images.WIDTH) {//向右q有UdI间<BR>if (this.MyMap.Grid[this.loc[1]][this.loc[0] + 1] ==<BR>Images.DLEFT) {//该图片有两个格宽<BR>this.loc[0]++;//向右Ud一?BR>if (this.loc[0] + 1 Q?Images.WIDTH) {//向右q有<BR>QA href="file://U?Qfile://U</AQ动I间<BR>this.loc[0]++;//向右Ud一?BR>setRange();//讄光标Ud的区域,<BR>QA href="file://?Qfile://该</AQ函数能光标移动到地图M|?BR>repaint();//重新l图<BR>}else {//向右没有UdI间<BR>this.loc[0]--;//退回来<BR>}<BR>}else {//该图片只有一个格?BR>this.loc[0]++;//向右Ud一?BR>setRange();//讄光标Ud的区域,<BR>QA href="file://?Qfile://该</AQ函数能光标移动到地图M|?BR>repaint();//重新l图<BR>}<BR>}else {<BR>}<BR>}else {//已经选定了要Ud的区?BR>if (this.loc[0] + 1 Q?Images.WIDTH) {//向右q有UdI间<BR>this.loc[0]++;//向右Ud一?BR>if (setMoveRange()) {//能够UdQ该函数能够讄要移动到的区?BR>repaint();//重新l图<BR>}else {//不能Ud<BR>this.loc[0]--;//退回来<BR>}<BR>}<BR>}<BR>break;<BR>case Canvas.FIRE:<BR>if (this.selected) {//已经选定了要Ud的区?BR>Move();//要Ud的区域移动到刚选中的区?BR>repaint();//重新l图<BR>this.selected = false;//清除已选定要移动区域的标志<BR>if ( win()) {<BR>System.out.println("win");<BR>}<BR>}else {//q没有选定要移动的区域<BR>if (this.MyMap.Grid[this.loc[1]][this.loc[0]] ==<BR>Images.BLANK) {//要移到的位置是一个空?BR>}else {//要移到的位置不是I白<BR>this.selected = true;//讄已选定要移动区域的标志<BR>}<BR>repaint();//重新l图<BR>}<BR>break;<BR>}<BR>}</FONT></P> <P><FONT color=#0000ff size=2>private boolean win(){<BR>QA href="file://?Qfile://判</AQ断是否已经救出了曹?BR>if ( this.MyMap.Grid[Images.HEIGHT - 2 ][Images.WIDTH - 3 ] == Images.CAOCAO )<BR>return true;<BR>else<BR>return false;<BR>}</FONT></P> <P><FONT color=#0000ff size=2>private void PrintGrid(String a) {<BR>QA href="file://?Qfile://打</AQ印当前地图的内容,用于调试<BR>System.out.println(a);<BR>for (int i = 0; i Q?Images.HEIGHT; i++) {<BR>for (int j = 0; j Q?Images.WIDTH; j++) {<BR>System.out.print( (char)this.MyMap.Grid[i][j]);<BR>}<BR>System.out.println("");<BR>}<BR>}</FONT></P> <P><FONT color=#0000ff size=2>private void Move() {<BR>QA href="file://?Qfile://</AQ要Ud的区域移动到刚选中的区?BR>if (this.MoveArea[0] == -1 || this.MoveArea[1] == -1 ||<BR>this.SelectArea[0] == -1 || this.SelectArea[1] == -1) {//没有选中区域<BR>}else {//已经选中了要Ud的区域和要移动到的区?BR>byte[][] temp = new byte[this.SelectArea[3]][this.SelectArea[2]];<BR>QA href="file://?Qfile://复</AQ制要移动的区域Q因块区域可能会被覆盖掉<BR>for (int i = 0; i Q?this.SelectArea[2]; i++) {<BR>for (int j = 0; j Q?this.SelectArea[3]; j++) {<BR>temp[j][i] =<BR>this.MyMap.Grid[this.SelectArea[1] +j]<BR>[this.SelectArea[0] + i];<BR>}<BR>}<BR>QA href="file://PrintGrid"Qfile://PrintGridQ?AQ?"1"); // 调试信息<BR>QA href="file://?Qfile://</AQ要Ud的区域移动到刚选中的区域(卌Ud到的区域Q?BR>for (int i = 0; i Q?this.SelectArea[2]; i++) {<BR>for (int j = 0; j Q?this.SelectArea[3]; j++) {<BR>this.MyMap.Grid[this.MoveArea[1] + j]<BR>[this.MoveArea[0] + i] = temp[j][i];<BR>}<BR>}<BR>QA href="file://PrintGrid"Qfile://PrintGridQ?AQ?"2");// 调试信息<BR>QA href="file://?Qfile://</AQ要Ud的区域中无用内容|成I白<BR>for (int i = 0; i Q?this.SelectArea[3]; i++) {<BR>for (int j = 0; j Q?this.SelectArea[2]; j++) {<BR>if (!isInRange2(this.SelectArea[0] + j,<BR>this.SelectArea[1] + i)) {//该点是不在要Ud?BR>QA href="file://?Qfile://的</AQ区域之内,需|空<BR>this.MyMap.Grid[this.SelectArea[1] + i]<BR>[this.SelectArea[0] + j] = Images.BLANK;<BR>}else {<BR>}<BR>}<BR>}<BR>QA href="file://PrintGrid"Qfile://PrintGridQ?AQ?"3");// 调试信息<BR>this.SelectArea[0] = this.MoveArea[0];//重置选中位置的水q_?BR>this.SelectArea[1] = this.MoveArea[1];//重置选中位置的竖直坐?BR>this.MoveArea[0] = -1;//清空要移动到的位|?BR>this.MoveArea[1] = -1;//清空要移动到的位|?BR>this.MoveArea[2] = 0;//清空要移动到的位|?BR>this.MoveArea[3] = 0;//清空要移动到的位|?BR>}<BR>}<BR>}</FONT></P></TD></TR></TBODY></TABLE></P> <P><FONT size=2>  代码的相兛_?在详l设计阶D已l讲q?代码中有比较相近的注?误者自行研d?全部的代码写好,用wtk2.0自带的Ktoolbar工具建立一个工E?接下来把M源文件放到正位|下,然后点击build,再点run,完成了E序的编?当然如果有错误还要修改和调试.<BR><BR></FONT><span id="dxt39j9" class=f14><FONT size=2>  </FONT><FONT size=2><B>七、测?BR></B><BR>  作ؓ一个真正的产品要经q单体测试、结合测试和pȝ试。由于项目本w简?而且大部分代码已l是相对成熟?我们跌单体试Q又׃W者的实际环境所?无法搞到Java手机,无法架设OTA服务?因此我们也只能放弃系l测试。那么就让我们开始结合测试吧。测试之前要先出一个测试式样书,也就是测试的计划。我们将它简化一?只测试如下几U情?W一、对各种形状的区域的选择和移?W二、͘q边界区域的选择和移?W三、同一区域的反复选择和反复移?W四、非法选择和非法移动。有了测试的目标,接下来的工作是用wtk2.0自带的Run MIDP Application工具q行试。打开q个工具,加蝲huarongRoad的jad文g,E序׃自动q行,选择launch上MIDlet1q个E序,华容道游戏就会跃然屏q之?接下来的工作是左三?右三?拇指扭扭,来做试。测试过E中发现M的问?立刻发一个bug给自己,然后又是痛苦的调试和修正bug,如此如此?BR><BR>  <B>?发布</B><BR><BR>  谈到发布,其实是个关键,再好的品不能很好的发布出去也只是个产品而已,变不成商品也得不到回报.׃W者的条g所?q里只能是纸上谈?不过q是希望能够使读者对q一q程有所了解(|上的资料也很多)?BR><BR>  J2ME的程序发布一般都是通过OTA(Over The Air),你只需要一台有公网IP的主机和一个普通的web Server可以了(管要求很低,但笔者还是没?Q这里我们以apacheZ介绍一下OTA服务的配|,首先是安装好了apache服务器,然后在conf目录下找到mime.types文gQ在该文件中加入如下两行<BR><BR>application/java-archive jar <BR>text/vnd.sun.j2me.app-descriptor jad <BR><BR>  然后重vapache服务器就可以了。接下来的工作就是修改jad文g中MIDlet-Jar-URL:后面的参敎ͼ它改ؓURL的绝对\径,卻IA href="http://***/"Qhttp://***/Q?AQhuarongroad.jar(其中***是你的域名或IP地址)。在下面是用java手机下蝲jad文gQ它会自动部|相应的jar文gq加载它。剩下的工作和在模拟器上操作是一L了?BR><BR>  <B>九、项目ȝ</B> </FONT></P> <P><FONT size=2></FONT></P> <P><FONT size=2>  xQ我们已l完成了一个J2ME游戏的全部开发过E,E序中涉及到了调研、分析、设计、编码、测试和发布{方面的问题Q其实在实际的工作中q有很多更ؓ具体的问题,毕竟技术只在Y件开发过E中占据很有限的一部分Q这里限于篇q的限制无法一一具体展开。今后,W者计划再写一用J2ME开发手机屏保的文章Q借此Z向读者展CJ2ME动画技术;然后再写一J2ME|络应用的文章,做一个类似开心辞兔RL知识问答游戏Q以便向读者展CJ2ME的网l技术;待这两方面的技术交待清楚之后,我将引领读者制作一个稍大一些的游戏?/FONT></P></SPAN></SPAN></SPAN></SPAN></SPAN><img src ="http://m.tkk7.com/yangsail/aggbug/1263.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/yangsail/" target="_blank">蓝色雪焰</a> 2005-02-17 01:02 <a href="http://m.tkk7.com/yangsail/archive/2005/02/17/1263.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>韩国pMMORPG和EverQuest在怪物上的单对?/title><link>http://m.tkk7.com/yangsail/archive/2005/02/16/1239.html</link><dc:creator>蓝色雪焰</dc:creator><author>蓝色雪焰</author><pubDate>Tue, 15 Feb 2005 16:00:00 GMT</pubDate><guid>http://m.tkk7.com/yangsail/archive/2005/02/16/1239.html</guid><wfw:comment>http://m.tkk7.com/yangsail/comments/1239.html</wfw:comment><comments>http://m.tkk7.com/yangsail/archive/2005/02/16/1239.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/yangsail/comments/commentRss/1239.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/yangsail/services/trackbacks/1239.html</trackback:ping><description><![CDATA[<H3 style="CURSOR: hand" onclick=switchDisplay(93)><FONT size=2>韩国pMMORPG和EverQuest在怪物上的单对?/FONT></H3> <div class="pjxrjzp" id=excerpt_93><FONT size=2></FONT></DIV> <div class="tf3tnlj" id=content_93 style="DISPLAY: block"> <DIV> <P><FONT size=2>现在Q让我们假设怽正在设计一ƾMMO ARPG中的怪物行动模式?/FONT></P> <P><FONT size=2>在主的韩国pMMO ARPG中,q些问题一般被如下处理Q?BR>1. 敌h是否会主动攻ȝ家h物?如何判断Q?BR>分ؓdd和被动攻MU类型。前者当玩家人物q入自n周围一定范围之后激发攻击行为。后者当自n被攻dȀ发攻击行为?/FONT></P> <P><FONT size=2>2. 当怪物面对多个玩家的时候,如何选择自己的攻d象?<BR>L的处理方式是dW一个攻击自q玩家?/FONT></P> <P><FONT size=2>3. 战斗q程中,怪物能够改变自己的攻ȝ标吗Q如何判断?<BR>基本上不改变?/FONT></P> <P><FONT size=2>4. 当处于不利的情况下,怪物会作Z么行动?<BR>L到底Q有些游戏中有逃跑的设定?/FONT></P> <P><FONT size=2>5. 怪物之间能否协作Q?BR>一拥而上?/FONT></P> <P><FONT size=2>在欧经典MMORPG EverQuest中,是这样处理的Q?BR>1. 敌h是否会主动攻ȝ家h物?如何判断Q?BR>通过一个关p表来决定,如果玩家和自w阵营关pL劣,那么dd。否则是被动d。(q个关系表是动态的Q会Ҏ玩家的行改变)</FONT></P> <P><FONT size=2>2. 当怪物面对多个玩家的时候,如何选择自己的攻d象?<BR>d首先q入自己视野或者攻击自q玩家?/FONT></P> <P><FONT size=2>3. 战斗q程中,怪物能够改变自己的攻ȝ标吗Q如何判断?<BR>战斗中,怪物有一个隐藏的仇恨列表。怪物会攻d于自׃恨列表顶端的玩家Q而玩家会增加仇恨的动作包括攻凅R挑衅、医疗同伴、施N法……等{。换a之,如果一个法师疯狂的施放d法术Q那么一定会被怪物首先料理。同LQ如果牧师频J的ȝ同伴Q也会被怪物Ҏ照顾。(正确的战斗方式是让肉盄角色保证自己永远处于仇恨列表最端Q当然这很困难,但是却很有必要,也很有趣Q?/FONT></P> <P><FONT size=2>4. 当处于不利的情况下,怪物会作Z么行动?<BR>逃跑Q而且速度相当快。鉴于怪物之间能够呼唤Q所以让怪物成功跑掉往往比较可怕。有一些法师系的敌Z用施放传送门的方式逃跑?/FONT></P> <P><FONT size=2>5. 怪物之间能否协作Q?BR>怪物之间的仇恨可以传递。如果两个怪物距离很近Q那么很可能一个发现到了你而两个都冲过来。法师系的怪物也会l同伴加血和一些防御性法术?/FONT></P> <P><BR><FONT size=2>单的_EQ在“h工智能”的范畴上ƈ没有走多q,但是在游戏上却做的很。特别是“仇恨列表”,q不复杂的规则衍生出了很多的变化Q堪U天才的设计。当你体会到因ؓq个限制而衍生出的精彩刺Ȁ的游戏过E,便能理解到玩家想要的其实q不仅仅是经验D已?/FONT></P> <P><FONT size=2>试试看将“仇恨列表”导入你的游戏,你觉得会发生什么? </FONT></P></DIV></DIV><img src ="http://m.tkk7.com/yangsail/aggbug/1239.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/yangsail/" target="_blank">蓝色雪焰</a> 2005-02-16 00:00 <a href="http://m.tkk7.com/yangsail/archive/2005/02/16/1239.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>j2me游戏引擎E序l构http://m.tkk7.com/yangsail/archive/2005/02/13/1115.html蓝色雪焰蓝色雪焰Sun, 13 Feb 2005 03:47:00 GMThttp://m.tkk7.com/yangsail/archive/2005/02/13/1115.htmlhttp://m.tkk7.com/yangsail/comments/1115.htmlhttp://m.tkk7.com/yangsail/archive/2005/02/13/1115.html#Feedback0http://m.tkk7.com/yangsail/comments/commentRss/1115.htmlhttp://m.tkk7.com/yangsail/services/trackbacks/1115.html        游戏引擎的结构很多,不过基本上都是在一个游戏主循环内实现。程序里面的d@环包含了E序框架的最主要的结构体?/SPAN>J2me的程序一般都包含两个class文gQ一个是MIDlet,一个是Displayable。一般我都是把游戏的主要代码攑֜Displayableq个c里面。这个类是基于事仉动的E序Q有三个主要相应函数void paint(Graphics g),void keyPressed(int keyCode),void keyReleased(int keyCode)?/SPAN>

 

1.         使用Runnable和创建线E的d@?/SPAN>

一般主体的做法是?/SPAN>Displayableq个cd?/SPAN>Runnableq个接口Q然后在其构造函C创徏一个线E,启动?/SPAN>run()函数,?/SPAN>run函数里面包含了游戏的主循环。下面是我在仙剑里面的片断代码?/SPAN>

 

public class GameMIDlet extends MIDlet {

  static GameMIDlet instance;

  Display display;

  GameDisplayable displayable = null;

 

  public GameMIDlet() {

    instance = this;

    display =  Display.getDisplay(this);

    displayable = new GameDisplayable();

  }

 

  public void startApp() {

    display.setCurrent(displayable);

  }

 

  public void pauseApp() {

  }

 

  public void destroyApp(boolean unconditional) {

    displayable.running = false;

  }

 

  public static void quitApp() {

    instance.destroyApp(true);

    instance.notifyDestroyed();

    instance = null;

  }

}

 

public class GameDisplayable extends FullCanvas implements Runnable {

  /** L制线E?/SPAN> */

  Thread MainThread = null;

  /** 游戏旉间隔 毫秒为单?/SPAN> */

  public static long timeinterval = 20;

  public static boolean Isstable = true;

 

  /* 用于游戏旉的变?/SPAN> */

  public static long timeold = 0;

  public static long timenow = 0;

  public long interval = 0;

  public static long frames_per_second = 0;

  int count = 0;

  long second = 0;

  public static boolean running = true;

public GameDisplayable() {

      // 开始主U程

    Thread MainThread = new Thread(this);

    MainThread.start();

  }

public void run() {

    while (running) {

      timenow = System.currentTimeMillis();

      interval = timenow - timeold;

 

      if (interval >= timeinterval) {

        timeold = timenow;

        Game_Process();

        if (second != (System.currentTimeMillis() / 1000)) {

          second = System.currentTimeMillis() / 1000;

          frames_per_second = count;

          count = 1;

        }

        else

          count++;

      }

      lib.sleep(30);

    }

 

 }

 

其中关于控制d@环速度的代码可以不要,但是lib.sleep(30)必须保留Q因为在Nokia 60的手ZQ如果去除了sleep(30),那么游戏无法切换回来。同Ӟ在游戏中M一个内部@环中Q也必须加入sleep(30)q个{待Q才能让游戏可以切换回来Q至于ؓ什么这样做Q我暂时q不清楚?/SPAN>30ms是我试q没有问题的数|可能?/SPAN>30msq小的g是没有问题的?/SPAN>

 

同时Q在MOTO的手ZQ必d游戏的主循环攑֜一个线E中Q游戏才能切换回来,不过可以不加上面说的sleep(30)延时?/SPAN>

 

2.         不用线E的d@环办?/SPAN>

q个办法只能?/SPAN>Nokia的^C实现Q而我只徏议在Nokia 40的^C做,q样不需要线E,道理上来说节U了一些内存,如果不是内存很紧张的机型Q那么最好还是用上一U办法?/SPAN>

 

游戏的主循环攑֜MIDlet?/SPAN>class里面Q具体做法如下:

public class GameMIDlet extends MIDlet {

  GameDisplayable displayable = null;

 

  /** 游戏旉间隔 毫秒为单?/SPAN> */

  public static long  timeinterval = 0;

  //用于游戏旉的变?/SPAN>

  public static long timeold = 0;

  public static long timenow = 0;

  public long interval = 0;

  public static long frames_per_second=0;

  int count=0;

  long second =0;

  public static boolean running = false;

  static boolean exitApp =false;

 

  public GameMIDlet() {

    displayable = new GameDisplayable();

    running =true;

  }

 

  public void startApp() {

    running =true;

    Display.getDisplay(this).setCurrent(displayable);

    while(running) {

      timenow = System.currentTimeMillis();

      interval = timenow - timeold;

      if (interval >= timeinterval) {

        timeold = timenow;

        displayable.Game_Process();

        if(second != (System.currentTimeMillis() /1000)){

            second = System.currentTimeMillis()/1000;

            frames_per_second = count;

            count = 1;

          }else

            count ++;

      }

    }

    if(exitApp) {

      destroyApp(true);

      notifyDestroyed();

    }

 

  }

 

  public void pauseApp() {

    running =false;

  }

 

  public void destroyApp(boolean unconditional) {

    running = false;

  }

 

  public static void quitApp() {

    running =false;

    exitApp =true;

  }

 

}



蓝色雪焰 2005-02-13 11:47 发表评论
]]>角色扮演游戏引擎的设计原?/title><link>http://m.tkk7.com/yangsail/archive/2005/02/10/1067.html</link><dc:creator>蓝色雪焰</dc:creator><author>蓝色雪焰</author><pubDate>Thu, 10 Feb 2005 13:43:00 GMT</pubDate><guid>http://m.tkk7.com/yangsail/archive/2005/02/10/1067.html</guid><wfw:comment>http://m.tkk7.com/yangsail/comments/1067.html</wfw:comment><comments>http://m.tkk7.com/yangsail/archive/2005/02/10/1067.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/yangsail/comments/commentRss/1067.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/yangsail/services/trackbacks/1067.html</trackback:ping><description><![CDATA[<P><FONT size=2>角色扮演游戏引擎的设计原?/FONT></P> <P><FONT size=2>  角色扮演游戏(RPG)是深受广大游戏迷们喜q一U游? 它以独特的互动性和故事性吸引了无数的玩家。它向h们提供了出现实生活的广阔的虚拟世界QZ能够试扮演不同的角Ԍȝ历和体验各种不同的h生旅E或奇l历。这些体验都是在现实生活中无法实现的。在玩过许多游戏后,许多玩家都不再仅仅满于一个游戏玩家的w䆾Q而会思考游戏是如何制作的,q且打算制作一个自q游戏Q网上的各种游戏制作组更是如雨后春W般涌现。下面我q大家介绍一下角色扮演游戏引擎的原理与制作,希望能对游戏制作爱好者有所帮助?</FONT></P> <P></P> <P><FONT size=2>一 游戏引擎的原?/FONT></P> <P><FONT size=2>  说到引擎Q游戏迷们都很熟悉。游戏引擎是一个ؓq行某一cL戏的机器设计的能够被机器识别的代码(指oQ集合。它象一个发动机Q控制着游戏的运行。一个游戏作品可以分为游戏引擎和游戏资源两大部分。游戏资源包括图象,声音Q动ȝ部分Q列一个公式就是:游戏=引擎Q程序代码)+资源Q图象,声音Q动ȝQ。游戏引擎则是按游戏设计的要求顺序的调用q些资源?/FONT></P> <P><FONT size=2>?nbsp;角色扮演游戏的制?/FONT></P> <P><FONT size=2>  一个完整的角色扮演游戏的制作从大的分工来说可以分ؓQ策划,E序设计Q美工,音乐制作以及目理Q后期的试{?BR>  {划主要d是设计游戏的剧情Q类型以及模式等Qƈ分析游戏的复杂性有多大Q内Ҏ多少Q策划的q度要多快等因素?BR>  E序设计的Q务是用某U编E语a来完成游戏的设计Qƈ与策划配合,辑ֈ预期的目的?BR>  工主要是根据游戏的时代背景与主题设计游戏的场景及各U角色的图象?BR>  音乐制作是根据游戏的剧情和背景制作游戏的音乐与音效?BR>  目理主要是控制游戏制作的q程Q充分利用现有的资源Qh员,资金Q设备等Q,以达到用量的资金实现最大的收益?BR>  后期的测试也是非帔R要的一个环节,对于一个几十hp几个月甚x几年旉制作的游戏,试往往能找到许多问题,只有改进E序才能保游戏的安全发行?BR>  ׃文章主要是讲解游戏程序的制作的,所以策划,工Q音乐制作等斚w误者参考其它文章,下面我就讲讲游戏E序的设计?/FONT></P> <P><FONT size=2>(一) 开发工具与主要技?/FONT></P> <P><FONT size=2>1Qg开发工?/FONT></P> <P><FONT size=2>  游戏E序开发工h很多Q在不同游戏q_上有不同的开发工兗在个h计算ZQ可以用目前性的软g开发工P比如QCQC++QVC++QDelphiQC++ Builder{。由于Windows操作pȝ的普及和其强大的多媒体功能,来多的游戏支持Windows操作pȝ。由于VC是微软的产品Q用它来~写WindowsE序有强大的E序接口和丰富的开发资源的支持Q加之VC严}的内存管理,在堆栈上良好的分配处理,生成代码的体U小Q稳定性高的优点,所以VC++成为目前游戏的L开发工兗?/FONT></P> <P><FONT size=2>2QDirectXlg的知?/FONT></P> <P><FONT size=2>  谈到Windowspȝ下的游戏开发,我们p说一下微软的DirectX SDK?BR>  Windowspȝ有一个主要优Ҏ应用E序和设备之间的独立性。然而应用程序的讑֤无关性是通过牺牲部分速度和效率的到的QWindows在硬件和软g间添加了中间抽象层,通过q些中间层我们的应用E序才能在不同的g上游刃有余。但是,我们因此而不能完全利用硬件的特征来获取最大限度的q算和显C速度。这一点在~写Windows游戏时是致命的,DirectX便是册个问题而设计的。DirectX由快速的底层库组成ƈ且没有给游戏设计dq多的约束。微软的DirectX软g开发工具包QSDKQ提供了一套优U的应用程序编E接口(APIsQ,q个~程接口可以提供l你开发高质量、实时的应用E序所需要的各种资源?BR>  DirectX?个组件分别是Q?BR>    DirectDrawQ?nbsp;使用面切换的方法实现动画,它不仅可以访问系l内存,q可以访问显C内存?BR>    Direct3DQ?nbsp;提供?Dg接口?BR>    DirectSoundQ?nbsp;立体声和3D声音效果Q同时管理声卡的内存?BR>    DirectPlayQ?nbsp;支持开发多人网l游戏,q能处理游戏中网l之间的通信问题?BR>    DirectInputQ?nbsp;为大量的讑֤提供输入支持?BR>    DirectSetupQ?nbsp;自动安装DirectX驱动E序?BR>  随着DirectX版本的提高,q增加了音乐播放的DirectMusic?/FONT></P> <P><FONT size=2>3QAlphaBlend 技?/FONT></P> <P><FONT size=2>  现在许多游戏Z辑ֈ光媄或图象的透明效果都会采用AlphaBlend 技术。所谓AlphaBlend技术,其实是按照"Alpha"混合向量的值来混合源像素和目标像素Q一般用来处理半透明效果。在计算Z的图象可以用R(U色)QG(l色)QB(蓝色)三原色来表示。假设一q图象是AQ另一q透明的图象是BQ那么透过BȝAQ看上去的图象C是B和A的؜合图象,设B图象的透明度ؓalpha(取gؓ0-1Q?为完全透明Q?为完全不透明)QAlpha混合公式如下Q?BR>    R(C)=alpha*R(B)+(1-alpha)*R(A)<BR>    G(C)=alpha*G(B)+(1-alpha)*G(A)<BR>    B(C)=alpha*B(B)+(1-alpha)*B(A)<BR>  R(x)、G(x)、B(x)分别指颜色x的RGB分量原色倹{从上面的公式可以知道,Alpha其实是一个决定؜合透明度的数倹{应用Alpha混合技术,可以实现游戏中的许多ҎQ比如火光、烟雾、阴影、动态光源等半透明效果?/FONT></P> <P><FONT size=2>4QA*法</FONT></P> <P><FONT size=2>  在许多游戏中要用鼠标控制人物q动Q而且让h物从目前的位|走到目标位|应该走最短的路径。这p用到最短\径搜索算法即A*法了?BR>  A*法实际是一U启发式搜烦Q所谓启发式搜烦Q就是利用一个估价函数评估每ơ的的决{的价|军_先尝试哪一U方案。如果一个估价函数可以找出最短的路径Q我们称之ؓ可采Ux。A*法是一个可采纳的最好优先算法。A*法的估价函数可表示为:<BR>    f(n) = g(n) + h(n)<BR>  q里Qf(n)是节点n的估价函敎ͼg(n)是v点到l点的最短\径|h(n)是n到目标的最断\l的启发倹{由于A*法比较复杂Q限于篇q,在此单介l一下,具体理论朋友们可以看人工斚w的书c了解详l的情况?/FONT></P> <P><FONT size=2>  其它技术还有粒子系l,音频与视频的调用Q图象文件的格式与信息存储等Q大家可以在学好DirectX的基上逐渐学习更多的技术?/FONT></P> <P><FONT size=2>Q二Q游戏的具体制作</FONT></P> <P><FONT size=2>1Q地囄辑器的制?/FONT></P> <P><FONT size=2>  RPG游戏往往要有大量的场景,场景中根据需要可以有草地Q湖泊,树木Q房屋,家具{道俱,׃一个游戏需要很多场景且地图来大Qؓ了节省空_提高图象文g的可重用性,RPG游戏的画面采用很多重复的单元Q可以叫做“图块”)所构成的,q就要用到地囄辑器了。我们在制作游戏引擎前,要完成地囄辑器的制作。在 RPG游戏里,场景的构成,是图块排列顺序的记录。首先制定一个场景构成文件的格式Q在q个文g里记录构成场景所需要的囑֝的排列顺序,因ؓ我们已经为每个图块徏立了索引Q所以只需要记录这些烦引就可以了。一个场景的构成Q是分成几层来完成的Q地面,建筑和植物,家具摆设Q和在场景中zd的h物或者物体(比如飘扬的旗帜)Q按照一定的序把它们依ơ显C到屏幕上,Ş成了一个丰富多采的场景。我们可以用数组来表C地囑֜景的生成q程?/FONT></P> <P><FONT size=2>MapData[X][Y]Q?nbsp;//地图数据QX表示地图宽度QY表示地图高度<BR>Picture[num]Q?nbsp;//道具的图片,num表示道具的L<BR>void MakeBackGround() //生成场景函数<BR>{<BR> int n;<BR> for( int i=0; i<Y; i++) //共Y?BR> for( int j=0; j<X; j++) //共X?BR> {<BR>  n=MapData[ i ][ j ]; //取得该位|的道具~号<BR>  Draw( j*32, i*32, Picture[n]); //在此位置(j*32,i*32)画道?BR> }<BR>}</FONT></P> <P><FONT size=2>2Q游戏的模块的划?/FONT></P> <P><FONT size=2>  游戏按功能分为:消息处理pȝ、场景显C及行走pȝ、打斗系l三大主要部分。其中又以消息处理系lؓ核心模块Q其余部分紧紧围l它q行?/FONT></P> <P><FONT size=2>一Q消息处理系l?/FONT></P> <P><FONT size=2>  消息处理pȝ是游戏的核心部分。游戏用到的消息处理pȝ先等待消息,然后Ҏ收到的消息{到相应的函数q行处理。比如:主角到敌h后,我们pE序产生‘打斗消息’,消息处理pȝ收到q个消息后就会马上{到打斗模块中厅R消息处理的大体框架如下Q?/FONT></P> <P><FONT size=2>//定义E序中要用到的变?BR>DWORD Message; //消息变量<BR>WinMain() //q入E序<BR>{<BR> 初始化主H口;<BR> 初始化DirectDraw环境Qƈ调入E序需要的囑Ş、地图数据;<BR> while( 1 ) //消息循环<BR> {<BR>  switch( Message )<BR>  {<BR>   case 行走消息: 行走模块();<BR>   case 打斗消息Q?nbsp;打斗模块();<BR>   case 事g消息Q?nbsp;事g模块();<BR>  }<BR> }<BR>}</FONT></P> <P><FONT size=2>二:场景昄及行走系l?/FONT></P> <P><FONT size=2>  作ؓRPG游戏Q其所有事件的发生几乎都是和场景有养I例如Q不同的地方会碰C同的敌h、与不同的h对话得知不同的事情等。鉴于这部分的重要性,我们可再它划分为:背景昄、行?nbsp;?nbsp;事g发生 三个子模块,分别处理各自的功能。下面进行具体分析?/FONT></P> <P><FONT size=2>Q一Q背景显C?BR>  E序q行后,先读取前面地囄辑器制作的场景所需要的囑֝的排列顺序,按照排列序图象拼成一个完整的场景Q一般做法是Q在内存中开辟一C个屏q缓存区Q事先把卛_昄的图象数据准备在~存区内Q然后一ơ性搬Ӟ把它们传送到真正的屏q缓冲区内?BR>  游戏用到的图片则事先制作好ƈ存于另外的图形文件中。地囄辑器制作的场景文件仅仅是对应的数据,而不是真正的囄。在游戏中生成场景就是地囄辑的逆过E,一个是Ҏ场景生成数据Q而另一个是Ҏ数据生成场景?/FONT></P> <P><FONT size=2>Q二Q行?BR>  要让主角在场景中行走Q至要有上、下、左、右四个行走方向Q每个方?q图Q站立、迈左腿、迈双、迈左腿Q,如图Q游戏中一定要图片的背景设ؓ透明Q这样在Mh物的时候就不会覆盖上背景色了(q一技术DirectDraw中只要用SetColorKeyQ)函数原囄背景色过滤掉p了)。我们让主角位置不动Q而场景UdQ即采用滚屏技术来实现角色在场景上Ud。这栯色一直保持在屏幕的正中间Q需要做的工作只是根据行走方向和步伐不停变换囄而已。行走时的障物判断也是每一个场景中必定要有的,有一些道具如树木、房屋等是不可跨的。对此我主要用一个二l数l来对应一个场景,每一个数lg表场景的一格(见图3)。有障碍的地方,该数l的对应gؓ1Q可通过的地方的gؓ0?/FONT></P> <P><FONT size=2>Q三Q事件发?BR>  事g发生原理是把相应事件的序号存储在地囄某些格子中,当主角一t入q个格子׃触发对应事g。例如:在游戏开始时Q主角是在他的家里。他要是惛_ȝ话,需要执行场景切换这个处理函数。我们假定该事g的编号ؓ001Q那么在地图上把安外\口处的格子D?01。这样主角走到\口时Q编号ؓ001的场景切换函数就会被触发Q于是主角便C下一个场景中。程序具体如下:</FONT></P> <P><FONT size=2>void MessageLoop( int Msg ) //消息循环<BR>{<BR> switch( Msg )<BR> {<BR>  char AddressName[16]; //数组AddressName[16]用来存储主角所在地点的名称<BR>  case ADDRESS == 001: // 由ADDRESS的值决定场景|出门Q?BR>  ScreenX=12; ScreenY=0; //初始化游戏背景位|?BR>  Hero.x=360; Hero.y=80;//主角坐标<BR>  Move();//主角Ud函数<BR>  //以下E序用来昄主角所在地?BR>  sprintf(AddressName,"下一q游戏场景的名称");<BR>  PrintText(lpDDSPrimary, 280, 330,AddressName , RGB(255,255,255));//在屏q上昄出场景的名称<BR>  break;<BR> }<BR>}</FONT></P> <P><FONT size=2>三:打斗pȝ</FONT></P> <P><FONT size=2>  l大多数的RPG都是有战斗存在的Q因此,打斗pȝ成为RPGpȝ中很重要的一环。有不少RPG游戏采用回合制打斗方式,因ؓ实现h较ؓ单。和打斗紧密相关的是升Q通常在一场战斗结束后Q主角的l验值都会增加。而当l验值到达一定程度时Q角色就升了?BR>  上面我简要的介绍了角色扮演游戏的制作Q由于写q篇文章的目的是让读者对角色扮演游戏的制作有一个基本的了解Q所以读者朋友们可以研究相关资料?/FONT></P><img src ="http://m.tkk7.com/yangsail/aggbug/1067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/yangsail/" target="_blank">蓝色雪焰</a> 2005-02-10 21:43 <a href="http://m.tkk7.com/yangsail/archive/2005/02/10/1067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://m.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://mhysf.com" target="_blank">һƵվ</a>| <a href="http://by6215.com" target="_blank">պƷһAVۿ </a>| <a href="http://ztsf6688.com" target="_blank">Ƶѹۿ</a>| <a href="http://3344by.com" target="_blank">Ʒһ</a>| <a href="http://91se01.com" target="_blank">Ļɫ</a>| <a href="http://kmrghj.com" target="_blank">޹Ƶ߹ۿ</a>| <a href="http://xx16xx.com" target="_blank">ŷഺɫУ԰С˵</a>| <a href="http://mtspvip.com" target="_blank">ҹһ</a>| <a href="http://nn227.com" target="_blank">þ޾Ʒϵַ </a>| <a href="http://k67m.com" target="_blank">鶹avŮһ</a>| <a href="http://ttooyuyu.com" target="_blank">ۺ޹</a>| <a href="http://qiyupu.com" target="_blank">޳AVƬþ</a>| <a href="http://8fue.com" target="_blank">޵һӰԺ</a>| <a href="http://2xpp.com" target="_blank">պһ</a>| <a href="http://bjsunic.com" target="_blank">AVһδ</a>| <a href="http://199291.com" target="_blank">ѾƷԲ߹ۿ</a>| <a href="http://tvnxl.com" target="_blank">Ҹ</a>| <a href="http://www998xe.com" target="_blank">߹ۿƵ</a>| <a href="http://6878vip.com" target="_blank">91Ƶѹۿ</a>| <a href="http://33sse.com" target="_blank">պavһ</a>| <a href="http://wo93xyz.com" target="_blank">ѻɫƬվ</a>| <a href="http://bjmyhfc.com" target="_blank">Ů߲</a>| <a href="http://www-456446.com" target="_blank">޹ƷƬþ</a>| <a href="http://tqdrhj.com" target="_blank">޸Ƶ</a>| <a href="http://c4665.com" target="_blank">91|</a>| <a href="http://33303339.com" target="_blank">˾þþƷС˵</a>| <a href="http://blcvs.com" target="_blank">žѾþоƷ23</a>| <a href="http://js-jiarui.com" target="_blank">182tvƵ߹ۿ</a>| <a href="http://8654123.com" target="_blank">Ƶѹۿ</a>| <a href="http://a8g8.com" target="_blank">ձ˳ɻҳۿƵ</a>| <a href="http://anhuish.com" target="_blank">޹Ʒyw</a>| <a href="http://fense1.com" target="_blank">޾ƷƬþ</a>| <a href="http://gz-shunan.com" target="_blank">޻ɫѹۿ</a>| <a href="http://ahzlgj.com" target="_blank">MM1313޾Ʒþ</a>| <a href="http://ghiearning.com" target="_blank">ëƬ100ѹۿ</a>| <a href="http://www96008.com" target="_blank">Ļ</a>| <a href="http://dazhe777.com" target="_blank">ôӲˬƵ</a>| <a href="http://ztsf6688.com" target="_blank">ɫɫwww˿</a>| <a href="http://luyifeile.com" target="_blank">޾Ʒ˾þ</a>| <a href="http://992fanli.com" target="_blank">޾Ʒһۺ</a>| <a href="http://www5xsq.com" target="_blank">鶹ƷѹƬ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>