<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>肉包子的摇滚生活 &#187; webgame</title>
	<atom:link href="http://www.fangyuqiang.com/archives/tag/webgame/feed" rel="self" type="application/rss+xml" />
	<link>http://www.fangyuqiang.com</link>
	<description>前端开发，交互设计，用户体验</description>
	<lastBuildDate>Wed, 01 Sep 2010 09:06:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>玩玩webgame开发（4）：游戏数据结构设计</title>
		<link>http://www.fangyuqiang.com/archives/200</link>
		<comments>http://www.fangyuqiang.com/archives/200#comments</comments>
		<pubDate>Wed, 10 Dec 2008 14:59:23 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[webgame]]></category>

		<guid isPermaLink="false">http://playfish.javaeye.com/blog/290379</guid>
		<description><![CDATA[很久没做更新了。最近比较忙碌，手头的webgame也都放下。最近很想念我的小webgame了，回来继续写。 上篇玩玩webgame开发（3）：自动战斗实现以及一些游戏细节（下）http://playfish.javaeye.com/blog/267275 在高峰期时候发表的，结果被火速沉底了。。。汗 好了，不小心有说了好多废话，言归正传。 ============= 数据结构设计是门高深的学问，而游戏的数据结构设计，那显然，也是一门很高深的学问（ &#124;&#124;好废话。。），数据结构应该是整个游戏的骨架所在，而游戏数据平衡，（另一门高深的学问。。）跟这游戏的数据结构息息相关。本文只是从自己做的一个小游戏出发，简要的介绍一下我的一个简单的游戏的数据结构设计思路。 一个游戏几个基本的要素： 地图 游戏角色 怪物 物品 建筑 先从地图说起 游戏都在地图上进行的。地图的基本要素包括：地图元素（即每一个地图坐标格子上的元素），不可进入的位置等。其他的还包括一些基本信息。我的地图数据结构设计如下： 这是个很简单的地图结构，包括的几个信息：地图名称，地图等级，地图元素，不可移动的位置。最后生成的展示效果如下（实际界面大很多，这里只是部分）： 关于地图生成以及战争迷雾的部分，可以参看这个系列文章的前2篇。至于在地图上出现的物品，角色，怪物，建筑，并没有放在地图的数据里面，因为我觉得这是属于不同角色的数据，是应该分开的。这样的数据结构可以满足这样的需求：地图按照数据显示，对于指定的地图元素，角色不能进入。 接下来是游戏角色 pos指角色在地图上的坐标，其它的就是一些常见的数据了，包括名称，金钱，满血hp，当前的hp，等级，经验，攻击，防御，速度，幸运，视野，其它的类型，文件，img属于我自己定义的一些结构，用于获得特定状态下的包子的图片。 设计一个这样的数据结构并不难，自己爱怎么设定就怎么设定，呵呵。不过关键的问题在于数据平衡，设置得很bt的数据可以开始玩的时候很爽，但是一结束玩家马上就会失去兴趣，所以，合适的数值以及成长曲线才会保证耐玩度。我个人是喜欢很小的数据，这样玩家自己计算的时候简单，而且数据平衡比较好做。我平时很经常玩一些war3的rpg，只要进去里面的人物或者是物品设定数字都是按百的，alt+q。顺便废话一下我喜欢的元素魔法之战这个。 怪物的数据设计 和游戏角色的数据结构不同，它有额外添加1个id以及一个items数组，id表示怪物类型，因为怪物会在地图上出现很多不同种类的怪物，通过id来区分不同的怪物。items数组，表示这个怪物身上有多大的概率会掉那种类型物品。items数组内的id表示物品的id。 一个怪物需要分布在地图上的各个位置，我目前觉得最简单的方式就是： 哪个位置上哪个怪物，简单明了。 ====未完待续，明晚继续]]></description>
			<content:encoded><![CDATA[<p>很久没做更新了。最近比较忙碌，手头的webgame也都放下。最近很想念我的小webgame了，回来继续写。<span id="more-200"></span></p>
<p>上篇玩玩webgame开发（3）：自动战斗实现以及一些游戏细节（下）<a href="/blog/267275" target="_blank">http://playfish.javaeye.com/blog/267275</a></p>
<p>在高峰期时候发表的，结果被火速沉底了。。。汗</p>
<p>好了，不小心有说了好多废话，言归正传。</p>
<p>=============</p>
<p>数据结构设计是门高深的学问，而游戏的数据结构设计，那显然，也是一门很高深的学问（ ||好废话。。），数据结构应该是整个游戏的骨架所在，而游戏数据平衡，（另一门高深的学问。。）跟这游戏的数据结构息息相关。本文只是从自己做的一个小游戏出发，简要的介绍一下我的一个简单的游戏的数据结构设计思路。</p>
<p>一个游戏几个基本的要素：</p>
<ul>
<li>地图</li>
<li>游戏角色</li>
<li>怪物</li>
<li>物品</li>
<li>建筑</li>
</ul>
<h3>先从地图说起</h3>
<p>游戏都在地图上进行的。地图的基本要素包括：地图元素（即每一个地图坐标格子上的元素），不可进入的位置等。其他的还包括一些基本信息。我的地图数据结构设计如下：</p>
<pre class="js"><!--mce:0--></pre>
<p>这是个很简单的地图结构，包括的几个信息：地图名称，地图等级，地图元素，不可移动的位置。最后生成的展示效果如下（实际界面大很多，这里只是部分）：</p>
<p><img src="/upload/attachment/58556/fd3be481-1163-35e2-83b5-c5279c9b2748.jpg" alt="" /></p>
<p>关于地图生成以及战争迷雾的部分，可以参看这个系列文章的前2篇。至于在地图上出现的物品，角色，怪物，建筑，并没有放在地图的数据里面，因为我觉得这是属于不同角色的数据，是应该分开的。这样的数据结构可以满足这样的需求：地图按照数据显示，对于指定的地图元素，角色不能进入。</p>
<h3>接下来是游戏角色</h3>
<pre class="js"><!--mce:1--></pre>
<p>pos指角色在地图上的坐标，其它的就是一些常见的数据了，包括名称，金钱，满血hp，当前的hp，等级，经验，攻击，防御，速度，幸运，视野，其它的类型，文件，img属于我自己定义的一些结构，用于获得特定状态下的包子的图片。</p>
<p><img src="/upload/attachment/58558/f2f03c78-49e5-3cae-b7bc-b77a5dd9ef58.jpg" alt="" /></p>
<p>设计一个这样的数据结构并不难，自己爱怎么设定就怎么设定，呵呵。不过关键的问题在于数据平衡，设置得很bt的数据可以开始玩的时候很爽，但是一结束玩家马上就会失去兴趣，所以，合适的数值以及成长曲线才会保证耐玩度。我个人是喜欢很小的数据，这样玩家自己计算的时候简单，而且数据平衡比较好做。我平时很经常玩一些war3的rpg，只要进去里面的人物或者是物品设定数字都是按百的，alt+q。顺便废话一下我喜欢的元素魔法之战这个。</p>
<h3>怪物的数据设计</h3>
<pre class="js"><!--mce:2--></pre>
<p>和游戏角色的数据结构不同，它有额外添加1个id以及一个items数组，id表示怪物类型，因为怪物会在地图上出现很多不同种类的怪物，通过id来区分不同的怪物。items数组，表示这个怪物身上有多大的概率会掉那种类型物品。items数组内的id表示物品的id。</p>
<p>一个怪物需要分布在地图上的各个位置，我目前觉得最简单的方式就是：</p>
<pre class="js"><!--mce:3--></pre>
<p>哪个位置上哪个怪物，简单明了。</p>
<p>====未完待续，明晚继续</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/200/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>玩玩webgame开发（3）：自动战斗实现以及一些游戏细节（下）</title>
		<link>http://www.fangyuqiang.com/archives/204</link>
		<comments>http://www.fangyuqiang.com/archives/204#comments</comments>
		<pubDate>Fri, 14 Nov 2008 14:12:30 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[webgame]]></category>

		<guid isPermaLink="false">http://playfish.javaeye.com/blog/267275</guid>
		<description><![CDATA[战斗过程图示意： [img]/upload/attachment/50153/d795065a-57e8-343c-9b37-8d1f27bfe3c8.jpg&#8221; alt=&#8221;[/img] 在《自动战斗实现以及一些游戏细节》的上一篇里面介绍了游戏人物战斗属性的设计以及战斗的触发，本章节是一个重点，主要介绍战斗过程的一系列函数与算法的实现。 本作的一个基本的思路很简单： 伤害 = 攻击-防御 速度决定攻击的间隔，其值为最大速度-速度，比如最大速度设置为12，那攻击间隔就是12-3 =9.也就是9秒发动一次攻击。 幸运决定了暴击跟躲闪，如果躲闪，伤害为0，如果暴击，伤害为攻击*2-防御 双方有任何一方HP小于0，则认为战斗结束，如果双方HP都不小于0结束战斗，即战斗中断，则判断人物逃跑，扣除一次攻击的hp。来看看在上篇就给出的代码： 这段代码前面主要是拼凑一个时间戳，类似[00:00]的格式。值得注意的地方在于下面的动作进度条，这个进度条是每秒推进一次，可以很直观的让用户感觉到战斗的过程。实现算是一个小小的技巧： 2个div都设置成绿色的背景，初始的css设置宽度为0。宝宝需要9秒进度条才会满，怪物需要7秒，满之前显示的就是进度的百分比。比如战斗进行了4秒，宝宝显示的进度的长度应该是4/9，而怪物是4/7。据此，temp是战斗时间对宝宝速度的求余操作，每次过9秒宽度就要从0开始。注意的是到9秒的时候进度是满的，求余结果是0，所以要进行一个判断。 接下来是一个核心部分，双方发动攻击的代码： 我这里用的是setInterval(function(){},boboSpeed*1000)这样的方式，就是按照宝宝的速度定时发动攻击。注意setInterval在没有进行clear之前是一直执行的。因为设计的初衷是给自家MM玩，战斗过程不要人操作，遇到怪物就直接开打一直到结束。如果你要要进行攻击设定，可能用setTimeout程序控制战斗过程更合适。 战斗逻辑部分的处理是这样的：根据对方的幸运判断对方躲闪，没有躲闪的话，根据自己幸运判断自己是否出现暴击。这里有个隐藏的bug陷阱，由于伤害是简单的攻击-防御来计算的，如果不加判断，遇到敌人的防御大于攻击的情况，那每次攻击没伤害还会让敌人的hp增加。所以damage的计算要有这个考虑。另外，hp是不能小于0的，这个也有考虑到。 战斗结束后一定要记得清除所有的定时任务，否则会在后台不断运行。这个是宝宝对怪物进行攻击的实现。怪物对宝宝进行攻击基本相同，不再赘述。 接下来看看战斗结束部分。战斗的结束主要要进行的一些动作包括：对一些临时的数据进行清除，判断战斗结果，数据重置等。战斗的结束分为2种，一种是中断逃跑，一种是完全结束，一方阵亡。对于中断逃跑的情况： 注释部分基本做了流程的概括。需要注意的一点是，如果战斗是中断的，那么宝宝跟怪兽都要回到原来的格子上面，所以战斗前要保存宝宝原来的位置的值。而如果战斗进行到底的话，肯定会有一方阵亡。宝宝赢了就占据当前格，输了则直接被移除，就不存在这个问题。 完全结束，一方阵亡的情况基本是相同的流程，只是少了逃跑惩罚以及位置回复。 战斗部分完整的代码在上一篇的最后有给出，可以点击这里查看http://playfish.javaeye.com/blog/265264 本章的最后介绍一下在上面代码里面出现的一些很重要的函数， 这个函数的作用就是拼凑出战斗信息字符串，如开头的示意图所示。函数的最后使用了$(&#8220;#battleInfo&#8221;)[0].scrollTop = 10000;来使得滚动条保持在最底部，现实的效果就是战斗信息会自动往下滚，不然战斗信息多了以后还要手动的下拉滚动条。 在整个程序中大量的用到了jquery的attr函数，稍微做一下介绍，attr支持对dom的属性进行获取跟设置，本代码里面大部分应用都是用来修改宝宝与怪物在各种情况下的表情，例如战斗最后结束，胜利的一方会摆出胜利的表情，而失败会摆出郁闷的表情。 宝宝攻击被躲闪的表情： 另外一个重要的函数是战斗结果的函数，目前还不完整，还缺少了获得战利品跟经验等级的实现。 战斗部分就暂时介绍到这里。以后再下去的部分会介绍物品的设计实现，以及对之前的介绍过的地图设计实现做一些补充，增加了地图障碍实现等。]]></description>
			<content:encoded><![CDATA[<p>战斗过程图示意：</p>
<p>[img]/upload/attachment/50153/d795065a-57e8-343c-9b37-8d1f27bfe3c8.jpg&#8221; alt=&#8221;[/img]</p>
<p>在《自动战斗实现以及一些游戏细节》的上一篇里面介绍了游戏人物战斗属性的设计以及战斗的触发，本章节是一个重点，主要介绍战斗过程的一系列函数与算法的实现。<br />
<span id="more-204"></span><br />
本作的一个基本的思路很简单：</p>
<p>伤害 = 攻击-防御</p>
<p>速度决定攻击的间隔，其值为最大速度-速度，比如最大速度设置为12，那攻击间隔就是12-3 =9.也就是9秒发动一次攻击。</p>
<p>幸运决定了暴击跟躲闪，如果躲闪，伤害为0，如果暴击，伤害为攻击*2-防御</p>
<p>双方有任何一方HP小于0，则认为战斗结束，如果双方HP都不小于0结束战斗，即战斗中断，则判断人物逃跑，扣除一次攻击的hp。来看看在上篇就给出的代码：</p>
<pre class="java"><!--mce:0--></pre>
<p>这段代码前面主要是拼凑一个时间戳，类似[00:00]的格式。值得注意的地方在于下面的动作进度条，这个进度条是每秒推进一次，可以很直观的让用户感觉到战斗的过程。实现算是一个小小的技巧：</p>
<p>2个div都设置成绿色的背景，初始的css设置宽度为0。宝宝需要9秒进度条才会满，怪物需要7秒，满之前显示的就是进度的百分比。比如战斗进行了4秒，宝宝显示的进度的长度应该是4/9，而怪物是4/7。据此，temp是战斗时间对宝宝速度的求余操作，每次过9秒宽度就要从0开始。注意的是到9秒的时候进度是满的，求余结果是0，所以要进行一个判断。</p>
<p>接下来是一个核心部分，双方发动攻击的代码：</p>
<pre class="javascript"><!--mce:1--></pre>
<p>我这里用的是setInterval(function(){},boboSpeed*1000)这样的方式，就是按照宝宝的速度定时发动攻击。注意setInterval在没有进行clear之前是一直执行的。因为设计的初衷是给自家MM玩，战斗过程不要人操作，遇到怪物就直接开打一直到结束。如果你要要进行攻击设定，可能用setTimeout程序控制战斗过程更合适。</p>
<p>战斗逻辑部分的处理是这样的：根据对方的幸运判断对方躲闪，没有躲闪的话，根据自己幸运判断自己是否出现暴击。这里有个隐藏的bug陷阱，由于伤害是简单的攻击-防御来计算的，如果不加判断，遇到敌人的防御大于攻击的情况，那每次攻击没伤害还会让敌人的hp增加。所以damage的计算要有这个考虑。另外，hp是不能小于0的，这个也有考虑到。</p>
<p>战斗结束后一定要记得清除所有的定时任务，否则会在后台不断运行。这个是宝宝对怪物进行攻击的实现。怪物对宝宝进行攻击基本相同，不再赘述。</p>
<p>接下来看看战斗结束部分。战斗的结束主要要进行的一些动作包括：对一些临时的数据进行清除，判断战斗结果，数据重置等。战斗的结束分为2种，一种是中断逃跑，一种是完全结束，一方阵亡。对于中断逃跑的情况：</p>
<pre class="javascript"><!--mce:2--></pre>
<p>注释部分基本做了流程的概括。需要注意的一点是，如果战斗是中断的，那么宝宝跟怪兽都要回到原来的格子上面，所以战斗前要保存宝宝原来的位置的值。而如果战斗进行到底的话，肯定会有一方阵亡。宝宝赢了就占据当前格，输了则直接被移除，就不存在这个问题。</p>
<p>完全结束，一方阵亡的情况基本是相同的流程，只是少了逃跑惩罚以及位置回复。</p>
<p>战斗部分完整的代码在上一篇的最后有给出，可以点击这里查看<a href="http://playfish.javaeye.com/blog/265264" target="_blank">http://playfish.javaeye.com/blog/265264</a></p>
<p>本章的最后介绍一下在上面代码里面出现的一些很重要的函数，</p>
<pre class="javascript"><!--mce:3--></pre>
<p>这个函数的作用就是拼凑出战斗信息字符串，如开头的示意图所示。函数的最后使用了$(&#8220;#battleInfo&#8221;)[0].scrollTop = 10000;来使得滚动条保持在最底部，现实的效果就是战斗信息会自动往下滚，不然战斗信息多了以后还要手动的下拉滚动条。</p>
<p>在整个程序中大量的用到了jquery的attr函数，稍微做一下介绍，attr支持对dom的属性进行获取跟设置，本代码里面大部分应用都是用来修改宝宝与怪物在各种情况下的表情，例如战斗最后结束，胜利的一方会摆出胜利的表情，而失败会摆出郁闷的表情。</p>
<p>宝宝攻击被躲闪的表情：</p>
<p><img src="/upload/attachment/50171/962ee186-9b9f-3624-8ed6-4cc149e543a0.jpg" alt="" /></p>
<p>另外一个重要的函数是战斗结果的函数，目前还不完整，还缺少了获得战利品跟经验等级的实现。</p>
<pre class="javascript"><!--mce:4--></pre>
<p>战斗部分就暂时介绍到这里。以后再下去的部分会介绍物品的设计实现，以及对之前的介绍过的地图设计实现做一些补充，增加了地图障碍实现等。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/204/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>玩玩webgame开发（3）：自动战斗实现以及一些游戏细节（上）</title>
		<link>http://www.fangyuqiang.com/archives/206</link>
		<comments>http://www.fangyuqiang.com/archives/206#comments</comments>
		<pubDate>Mon, 10 Nov 2008 15:14:43 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[webgame]]></category>

		<guid isPermaLink="false">http://playfish.javaeye.com/blog/265264</guid>
		<description><![CDATA[国际惯例，先上个效果图： 战斗部分的实现应该是游戏里最复杂的部分，具体实现我的小游戏还没做完整，这里只是给出一些我的思路和做法。 战斗部分很复杂，全文大概分成以下几点： 战斗属性设置 战斗触发 战斗过程（重点） 战斗结束 由于游戏初衷是给我家MM玩的，所以过程都设置得很简单，宝宝跟怪物遇上，就自动开打，战斗过程全部自动，根据双方的速度定时发动攻击。 宝宝的战斗属性我的设置如下 var bobo = { pos : {X:1, Y:1}, //地图上的坐标位置 name : '辛德瑞拉 杰克罗琳', //宝宝的名字，GF喜欢个这么拉风的。。。 hp : 100, //full hp curHp : 100, //current hp level : 0, //等级 exp : 0, //经验 ap : 15, //攻击力attack power def : 1, //防御力defence speed : 3, //速度 luck [...]]]></description>
			<content:encoded><![CDATA[<p>国际惯例，先上个效果图：</p>
<div id="attachment_470" class="wp-caption alignnone" style="width: 633px"><img class="size-full wp-image-470" title="webgame自动战斗实现" src="http://www.fangyuqiang.com/wp-content/uploads/2008/11/f8f832f4-057e-3493-9871-9aaa69b038a1.jpg" alt="webgame自动战斗实现" width="623" height="371" /><p class="wp-caption-text">webgame自动战斗实现</p></div>
<p>战斗部分的实现应该是游戏里最复杂的部分，具体实现我的小游戏还没做完整，这里只是给出一些我的思路和做法。<span id="more-206"></span></p>
<p>战斗部分很复杂，全文大概分成以下几点：</p>
<ul>
<li>战斗属性设置</li>
<li>战斗触发</li>
<li>战斗过程（重点）</li>
<li>战斗结束</li>
</ul>
<p>由于游戏初衷是给我家MM玩的，所以过程都设置得很简单，宝宝跟怪物遇上，就自动开打，战斗过程全部自动，根据双方的速度定时发动攻击。</p>
<p>宝宝的战斗属性我的设置如下</p>
<pre class="js" title="code">var bobo = {
	pos		:	{X:1,	Y:1},        //地图上的坐标位置
	name	:	'辛德瑞拉 杰克罗琳',    //宝宝的名字，GF喜欢个这么拉风的。。。
	hp		:	100,	                       //full hp
	curHp	:	100,	                       //current hp
	level	:	0,			               //等级
	exp		:	0,                           //经验
	ap		:	15,		              //攻击力attack power
	def		:	1,		              //防御力defence
	speed	:	3,		              //速度
	luck	:	15,                                 //幸运
	eyeshot	:	2,		              //视野
	type	:	'bobo',                           //类型，用于区分怪兽，宝宝，NPC
	file	:	'baozi'                            //文件名称
};</pre>
<p>怪物的属性基本跟这个类似。但是不同的是，一个地图上可能有多种多样的怪物，所以怪物我使用对象数组来保存：</p>
<pre class="javascript" title="code">var monsters = [
		{
			pos:{	X:1,	Y:8	},
			name:'青蛙',	hp:30, curHp:30, level:0,
			exp:0,	ap:10,	def:0,	speed:5,
			luck:15,	type:'monster',	file:'qingwa'
		},
		{
			pos:{	X:5,	Y:6	},
			name:'青蛙',	hp:30,	curHp:30,	level:0,
			exp:0,	ap:20,	def:0,	speed:5,
			luck:15,	type:'monster',	file:'qingwa'
		},
		{
			pos:{	X:4,	Y:5	},
			name:'青蛙',	hp:130,	curHp:30,	level:0,
			exp:0,	ap:5,	def:0,	speed:5,
			luck:15,	type:'monster',	file:'qingwa'
		},
		{
			pos:{	X:10,	Y:9	},
			name:'青蛙',	hp:50,	curHp:30,	level:0,
			exp:0,	ap:20,	def:0,	speed:5,
			luck:15,	type:'monster',	file:'qingwa'
		}
];</pre>
<p>当然，如果以后做成了多人互动，也可以将宝宝改成使用对象数组来保存。</p>
<p>有了这样的数据结构后，还需要将这样的数据结构转化为页面上的表现形式。比如宝宝要变成页面上的一个图片，怪物要变成在各个地点散落出现的图片。这就需要一个将数组转化为html元素的过程。这个过程我是采用jquery的map函数实现的。</p>
<pre class="javascript" title="code">//将所有怪物对象转换为jQuery的img对象
var monstersFace = $.map(monsters,function(i){
	return $('<img class="monster" title="'+i.name+'" src="images/'+i.type+'/'+i.file+'/lv'+i.level+'/common.gif" alt="" />');
});</pre>
<p>map的作用，就是将一个数组映射为另一个数组返回。这里就省却了我们自己不少功夫。关于jquery的map具体说明可以参看<a href="http://docs.jquery.com/Utilities/jQuery.map#arraycallback" target="_blank">http://docs.jquery.com/Utilities/jQuery.map#arraycallback</a></p>
<p>在开发篇的2已经提到了如果将这些对象插入到地图中，这里不再重复。接下来介绍下战斗如何触发以及如何进行。</p>
<p>战斗的触发设定我的实现是：每次宝宝移动，都判断当前坐标上面的图片数目，如果图片为2，即宝宝跟怪物在同一个格子上面，那么触发战斗。用jquery的方式实现就很简单了</p>
<pre class="javascript" title="code">	var curPosObj = $("#"+"X"+curPos.X+"Y"+curPos.Y); //当前坐标对象

	if($(curPosObj).find('img').length &gt; 1 ){              //如果有2张图片
		var obj = $(curPosObj).find('img').get(0);   //获得第一张
		switch(obj.className){                             //使用classname来区分图片是怪物还是物品，物品功能将在以后介绍
			case "monster": //与怪物战斗
				battle(curPos,prePos);
				break;
			case "item":	  //获得物品
				getItem(curPos);
				break;
		}
	}</pre>
<p>触发了战斗后，开打。开篇的效果图就是开打后的效果，相信大家对thickbox的效果都很熟悉了，不过这个使用jquery的另一个插件blockUI实现的，因为觉得这个界面的定制性更强一些。关于jquery的blockUI插件：<a href="http://malsup.com/jquery/block/#overview" target="_blank">http://malsup.com/jquery/block/#overview</a></p>
<p>进入战斗：</p>
<pre class="js" title="code">	var curPosObj = $("#"+"X"+curPos.X+"Y"+curPos.Y);   //当前战斗坐标
	var prePosObj = $("#"+"X"+prePos.X+"Y"+prePos.Y); //战斗前宝宝的位置

	var boboFace = $(curPosObj).find('img').get(1);
	var monsterFace = $(curPosObj).find('img').get(0);
	$('#boboFace').append(boboFace);          //将宝宝的头像设置到战斗画面中
	$('#monsterFace').append(monsterFace);//怪物的头像设置

	var monster = getObjByPos(curPos.X,curPos.Y,'monster');

	setBattleValue('monster', monster); //将宝宝的战斗信息设置到战斗画面中
	setBattleValue('bobo', bobo);           //怪物的战斗信息设置

	//利用blockUI显示战斗画面
	$.blockUI({
		message	: 	$('#battle') ,
		css		: 	{
						top		:	'15%',
						width 	:	'60%',
						left	:	'20%',
						cursor	:	'default'
					}
	});</pre>
<p>战斗部分应该说是一个大难点，篇幅也比较长，时间关系，所以本篇分成了上下2篇，我有时间就继续往下写。等不及的同志可以先玩味下代码，下篇我就继续介绍的战斗实现的一些细节。主要是战斗过程以及战斗结束的处理。</p>
<pre class="javascript" title="code">	//开始战斗，当前双方hp都大于0
	if(bobo.curHp &gt;0 || monster.curHp &gt; 0 ){

		var boboWin = true;
		var timer = 0;				//战斗计时
		var timerStr = '[00:00]';	//显示时间字符串

		sysBattleMessage('战斗开始');

		var boboSpeed = maxSpeed-bobo.speed;		//宝宝速度计算
		var monsterSpeed = maxSpeed-monster.speed;	//怪物速度计算

		var battleTimer=setInterval(function(){		//计时，定时显示信息
			var s = timer%60;
			var m = Math.floor(timer/60);
			if (s&lt;10) {
				s = "0" + s;
			}
			if(m&lt;10){
				m = "0" + m;
			}
			timerStr = '['+m+':'+s+']';

			//显示宝宝动作进度条
			var temp = (timer+1)%boboSpeed == 0  ? boboSpeed : (timer+1)%boboSpeed;
			$('#boboAction').width(temp/boboSpeed*100+'%');
			//显示怪物动作进度条
			temp = (timer+1)%monsterSpeed == 0 ? monsterSpeed : (timer+1)%monsterSpeed;
			$('#monsterAction').width(temp/monsterSpeed*100+'%');
			//计时增加
			timer++;
		},1000);

		//宝宝定时发动攻击
		var attackMonsterT = setInterval(function(){

			//战斗模式，先判断对方躲闪，如果躲闪，此次攻击无效
			var dodge =  Math.floor(Math.random()*100) &lt; monster.luck;	//躲闪

			if(dodge){
				battleMessage(bobo,monster,'dodge',0,timerStr,monster.curHp);
			}
			else{
				var crit = Math.floor(Math.random()*100) &lt; bobo.luck;	//暴击判断，返回bool值 				 				var damage = bobo.ap*(Number(crit)+1) - monster.def &gt; 0 ? bobo.ap*(Number(crit)+1) - monster.def : 0;

				monster.curHp -= damage;

				if(monster.curHp &lt; 0 ){
					monster.curHp = 0;
				}

				//显示战斗信息
				battleMessage(bobo,monster,crit?'crit':'common',damage,timerStr,monster.curHp);

				//战斗结束，清除所有定时任务
				if(monster.curHp &lt;=0){
					clearInterval(attackMonsterT);
					clearInterval(attackBoboT);
					clearInterval(battleTimer);
					battleOver(boboWin,monster);
				}
			}
		},boboSpeed*1000);

		//怪物定时发动攻击
		var attackBoboT = setInterval(function(){

			var dodge =  Math.floor(Math.random()*100) &lt; bobo.luck;	//躲闪

			if(dodge){
				battleMessage(monster,bobo,'dodge',0,timerStr,bobo.curHp);
			}
			else{
				var crit = Math.floor(Math.random()*100) &lt; monster.luck;	//暴击 				 				var damage = monster.ap*(Number(crit)+1) - bobo.def &gt; 0 ? monster.ap*(Number(crit)+1) - bobo.def : 0;

				bobo.curHp -= damage;

				if(bobo.curHp &lt; 0){
					bobo.curHp = 0;
				}

				battleMessage(monster,bobo,crit?'crit':'common',damage,timerStr,bobo.curHp);

				if(bobo.curHp &lt;=0){ 					clearInterval(attackMonsterT); 					clearInterval(attackBoboT); 					clearInterval(battleTimer); 					boboWin = false; 					battleOver(boboWin,monster); 				} 			} 		},monsterSpeed*1000); 	} 	 	$('#battleCloseIcon').click(function(){ 		if(bobo.curHp&gt;0
		&amp;&amp; monster.curHp&gt;0
		&amp;&amp; confirm('战斗还未结束，逃跑将被怪兽追击，确定宝宝要逃跑吗？')){		//战斗未结束
			$.unblockUI({
                onUnblock: function(){
						bobo.curHp = bobo.curHp - monster.ap &gt;0?bobo.curHp - monster.ap : 1;
						clearInterval(attackMonsterT);
						clearInterval(attackBoboT);
						clearInterval(battleTimer);
						$('#battleInfo').html('');	//清空战斗信息
						$('#monsterFace').empty();	//清空头像

						$('#boboAction').width('0%');	//重置战斗计时
						$('#monsterAction').width('0%');

						//将图片改为普通图片，占据位置
						$(boboFace).attr({
							src:'images/'+bobo.type+'/'+bobo.file+'/'+'lv'+bobo.level+'/common.gif'
						});
						$(prePosObj).append(boboFace);
						//设置坐标
						bobo.pos.X = prePos.X;
						bobo.pos.Y = prePos.Y;
						//怪兽图片
						$(monsterFace).attr({
							src:'images/'+monster.type+'/'+monster.file+'/'+'lv'+monster.level+'/common.gif'
						});
						$(curPosObj).append(monsterFace);
						$("#battleCloseIcon").unbind( "click" );
					}
				});
			}
			else{
			$.unblockUI({
                onUnblock: function(){
					clearInterval(attackMonsterT);
					clearInterval(attackBoboT);
					clearInterval(battleTimer);
					$('#battleInfo,#monsterFace').empty();	//清空战斗信息

					$('#boboAction').width('0%');	//重置战斗计时
					$('#monsterAction').width('0%');

					//将图片改为普通图片，占据位置
					if(boboWin){
						$(boboFace).attr({
							src:'images/'+bobo.type+'/'+bobo.file+'/'+'lv'+bobo.level+'/common.gif'
						});
						$(curPosObj).append(boboFace);
					}
					else{
						$(monsterFace).attr({
							src:'images/'+monster.type+'/'+monster.file+'/'+'lv'+monster.level+'/common.gif'
						});
						$(curPosObj).append(monsterFace);
					}
				}
            });
			}
		});</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/206/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>玩玩webgame开发（2）：人物移动与战争迷雾实现</title>
		<link>http://www.fangyuqiang.com/archives/207</link>
		<comments>http://www.fangyuqiang.com/archives/207#comments</comments>
		<pubDate>Tue, 04 Nov 2008 15:28:04 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[webgame]]></category>

		<guid isPermaLink="false">http://playfish.javaeye.com/blog/262481</guid>
		<description><![CDATA[惯例，先上下效果图片： 在上一篇玩玩webgame开发（1）大概给出了jquery方式的地图实现，最近又做了一些改进，加进了更多元素。代码全部改成jquery插件的方式。有机会做专门的介绍。 这次的主题主要是地图上面人物的移动以及战争迷雾的实现。 人物的移动其实比较简单，就是监听键盘上下左右按键事件。 $(document).keydown(function(event){ $.boboMove(event); }); 后台boboMove函数的写法： switch(event.keyCode){ case 37: if(bobo.pos.X &#62; minX){ //判断地图边缘 bobo.pos.X -= 1; //坐标变化 $("#"+"X"+bobo.pos.X+"Y"+bobo.pos.Y).append(boboFace);//将人物移动到这个位置上，实际做法就是将人物的图片放在这个div上面 } break; case 38: if(bobo.pos.Y &#60; maxY){ bobo.pos.Y += 1; $("#"+"X"+bobo.pos.X+"Y"+bobo.pos.Y).append(boboFace); } break; case 39: if(bobo.pos.X &#60; maxX){ bobo.pos.X += 1; $("#"+"X"+bobo.pos.X+"Y"+bobo.pos.Y).append(boboFace); } break; case 40: if(bobo.pos.Y &#62; minY){ bobo.pos.Y -= 1; $("#"+"X"+bobo.pos.X+"Y"+bobo.pos.Y).append(boboFace); } break; [...]]]></description>
			<content:encoded><![CDATA[<p>惯例，先上下效果图片：</p>
<div id="attachment_401" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium wp-image-401" title="webgame地图效果" src="http://www.fangyuqiang.com/wp-content/uploads/2008/11/3b8e0d31-b9cc-3272-abbb-0941300a68ef-300x171.png" alt="webgame地图效果" width="300" height="171" /><p class="wp-caption-text">webgame地图效果</p></div>
<p>在上一篇玩玩webgame开发（1）大概给出了jquery方式的地图实现，最近又做了一些改进，加进了更多元素。代码全部改成jquery插件的方式。有机会做专门的介绍。</p>
<p>这次的主题主要是地图上面人物的移动以及战争迷雾的实现。<span id="more-207"></span></p>
<p>人物的移动其实比较简单，就是监听键盘上下左右按键事件。</p>
<pre class="javascript" title="code">$(document).keydown(function(event){
			$.boboMove(event);
});</pre>
<p>后台boboMove函数的写法：</p>
<pre class="javascript" title="code">	switch(event.keyCode){
		case 37:
			if(bobo.pos.X &gt; minX){ //判断地图边缘
				bobo.pos.X -= 1; //坐标变化
				$("#"+"X"+bobo.pos.X+"Y"+bobo.pos.Y).append(boboFace);//将人物移动到这个位置上，实际做法就是将人物的图片放在这个div上面
			}
			break;
		case 38:
			if(bobo.pos.Y &lt; maxY){
				bobo.pos.Y += 1;
				$("#"+"X"+bobo.pos.X+"Y"+bobo.pos.Y).append(boboFace);
			}
			break;
		case 39:
			if(bobo.pos.X &lt; maxX){ 				bobo.pos.X += 1; 				$("#"+"X"+bobo.pos.X+"Y"+bobo.pos.Y).append(boboFace); 			} 		break; 		case 40: 			if(bobo.pos.Y &gt; minY){
				bobo.pos.Y -= 1;
				$("#"+"X"+bobo.pos.X+"Y"+bobo.pos.Y).append(boboFace);
			}
		break;
	}
	cleanBattleFog(); //清除战争迷雾</pre>
<p>我写的这个webgame打算做个战争迷雾的效果，玩过魔兽争霸或者英雄无敌的人应该对这个概念很清楚，就是在没有探索之前，地图上面的区域都是迷雾覆盖无法看到的。</p>
<p>迷雾覆盖效果实现其实很简单，对于我所做的系统来说，迷雾就是所有的区域div都加上一个battleFog的css。</p>
<p>移除战争迷雾的算法是这样的：在人物的视野内的格子div移除battleFog这个css类。例如人物视野为1，人物坐标3，3。那么视野内的(2,3),(3,3),(3,4),(4,3),(3,2)。显示出来就是一个十字形，如果视野是2，那么显示出来就类似一个星形。</p>
<p>在正式给出代码之前，各位看客可以自己考虑一下这个算法的实现。可能大家都觉得这个很简单。。但是今天在写这个的时候才发觉这个看似简单的问题要写好不那么好想，可能很久没动脑筋了吧，这里卖个小关子，大家动动脑筋想想，给出人物当前的坐标，以及人物的视野，得出当前人物所有可以看到的坐标。<br />
=================思考十分钟分割线=================<br />
呵呵，最后给出我的战争迷雾移除算法： </p>
<pre class="js" title="code">
function cleanBattleFog(){
	var fogToBeClean = []; //将被移除迷雾的区域数组，保存所有将被移除迷雾的div的id
//bobo.pos.X 人物X坐标，
//bobo.pos.Y 人物Y坐标
//bobo.eyeshot 人物视野
	for(var m =bobo.pos.X-bobo.eyeshot;m<=bobo.pos.X+bobo.eyeshot; m++ ){
		for(var n=bobo.pos.Y-bobo.eyeshot;n<=bobo.pos.Y+bobo.eyeshot;n++){
			var xdiff = m - bobo.pos.X;
			var ydiff = n - bobo.pos.Y;
			if(xdiff*xdiff + ydiff*ydiff <= bobo.eyeshot*bobo.eyeshot
				 &#038;&#038; m>=1 &#038;&#038; n>=1 &#038;&#038; m <= map.maxY &#038;&#038; n <= map.maxX
			){
				fogToBeClean.push('#X'+m+'Y'+n);
			}
		}
	}
	$(fogToBeClean.join(',')).removeClass('battleFog');
}
</pre>
<p>其实算法不难，就是2点间坐标距离要小于视野。并且要注意考虑地图的边界，不然可能得到不在地图内的坐标。<br />
每得到一个坐标，用数组的push方法保存到数组中。jquery支持用逗号分割的表达式获得多个对象，所以最后直接一个join搞定。 </p>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/207/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>玩玩webgame开发（1）：用jquery生成地图</title>
		<link>http://www.fangyuqiang.com/archives/208</link>
		<comments>http://www.fangyuqiang.com/archives/208#comments</comments>
		<pubDate>Wed, 29 Oct 2008 16:46:03 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[cakephp]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[webgame]]></category>

		<guid isPermaLink="false">http://playfish.javaeye.com/blog/259876</guid>
		<description><![CDATA[先上个效果图： 选型：jquery,php,mysql。我喜欢jquery，灵活，强大的选择器，还算够用的ajax功能，还有丰富的plugin，以及effects，这些对于做webgame都是很有用的。php打算用框架来做，不过我php也是半吊子，现在在cakephp跟国产的fleaphp中犹豫不决。mysql，无条件选用 =正文= 由于我很想做一个战斗系统来玩，类似war3里面迷雾探索的，所以不管3721，js直接从战斗系统开始写。晚上写了一会，大概整出这样的代码。 var battle = { //can accect a random map createMap:function(map){ var defaultMap = [       //定义默认地图，字母分别对应css的类名 ['g','r','f','f','f','r','f','w'], ['w','g','f','f','f','r','g','f'], ['w','r','g','f','f','g','f','r'], ['f','r','f','f','f','r','f','f'], ]; //函数传递进来的参数判断 if(boboUtil.isUndefined(map) &#124;&#124; map.length == 0){ map = defaultMap; } //将2维数组转化为1维数组 var mapSequence =  new Array(); for(var i=0;i&#60;map.length;i++){ mapSequence = mapSequence.concat(map[i]); } //计算地图的宽，即横向总共几个格子 var fieldWidth = map[0].length; //设置地图的总宽度 $("#battleField").width(fieldWidth*50); //为每个格子设置对应的css类，即渲染地图 $("#battleField [...]]]></description>
			<content:encoded><![CDATA[<p><strong>先上个效果图：</strong></p>
<p><strong> </strong></p>
<div id="attachment_399" class="wp-caption aligncenter" style="width: 418px"><strong><strong><img class="size-full wp-image-399 " title="jquery生成webgame的地图" src="http://www.fangyuqiang.com/wp-content/uploads/2008/10/048232e5-7cf2-332d-8337-f76822751a47.jpg" alt="jquery生成webgame的地图" width="408" height="212" /></strong></strong><p class="wp-caption-text">jquery生成webgame的地图</p></div>
<p><strong> </strong></p>
<p>选型：jquery,php,mysql。我喜欢jquery，灵活，强大的选择器，还算够用的ajax功能，还有丰富的plugin，以及effects，这些对于做webgame都是很有用的。php打算用框架来做，不过我php也是半吊子，现在在cakephp跟国产的fleaphp中犹豫不决。mysql，无条件选用<span id="more-208"></span></p>
<p>=正文=</p>
<p>由于我很想做一个战斗系统来玩，类似war3里面迷雾探索的，所以不管3721，js直接从战斗系统开始写。晚上写了一会，大概整出这样的代码。</p>
<pre class="js" title="code">var battle = {
 //can accect a random map
 createMap:function(map){
 var defaultMap = [       //定义默认地图，字母分别对应css的类名
 ['g','r','f','f','f','r','f','w'],
 ['w','g','f','f','f','r','g','f'],
 ['w','r','g','f','f','g','f','r'],
 ['f','r','f','f','f','r','f','f'],
 ];
//函数传递进来的参数判断
 if(boboUtil.isUndefined(map) || map.length == 0){
 map = defaultMap;
 }
//将2维数组转化为1维数组
 var mapSequence =  new Array();
 for(var i=0;i&lt;map.length;i++){
 mapSequence = mapSequence.concat(map[i]);
 }
//计算地图的宽，即横向总共几个格子
 var fieldWidth = map[0].length;
//设置地图的总宽度
 $("#battleField").width(fieldWidth*50);
//为每个格子设置对应的css类，即渲染地图
 $("#battleField div").each(function(i){
 //create map
 if(i &gt; mapSequence.length )
 return false;
 $(this).addClass(mapSequence[i]);
//设置格子的坐标
 //set x,y index
 var x = i % fieldWidth +1;
 var y = Math.floor(i / fieldWidth +1);
 $(this).attr("id",""+x+y);
 });
 }
};</pre>
<pre class="javascript"><!--mce:0--></pre>
<p><strong>实现原理：</strong></p>
<ul>
<li>页面上先添加适当数目的空div，我觉得用js添加div可能存在性能问题，所以直接html里面放置一些空的div，作为地图元素。</li>
<li>定义一系列的css，为不同格子地图设置好宽高与背景色，实际运用时候这些背景可以换成图片什么的。</li>
<li>定义一个map的数组，这个数组保存地图的信息，即地图每个格子的css类名，通过js，将这些css类名添加到每个div中</li>
</ul>
<p>最近业余时间想找点事情做，看我家MM似乎回家都比较无聊，就一个劲看片，就想给她写个webgame玩吧，至于为什么不做其他的游戏啥的，好吧，我承认我只会web。也想练练自己的JavaScript，提高下js水平，虽然对js很有兴致，但是工作方面都是做java，再下去就荒废了。</p>
<p>最后顺便附上一个简单的时间测试代码，使用console.log，请在firefox用firebug查看，当然，如果是IE，可以把这句换成alert。用法简单，在页面上写：</p>
<pre class="js" title="code">var executeTimeTest=function(func){
	var start = 0;
	var end = 0;
	start = new Date().getTime()
	for(i = 0; i &lt; 10000000; i++) {
		func;
	}
	end = new Date().getTime();
	console.log((end - start) / 1000+'s');

};</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/208/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
