<?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>9STG.COM 游手好学 &#187; 游戏心得</title>
	<atom:link href="http://www.9STG.com/category/game_idea/feed" rel="self" type="application/rss+xml" />
	<link>http://www.9STG.com</link>
	<description>学游戏，玩游戏</description>
	<lastBuildDate>Tue, 07 Jun 2011 07:59:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>FLASH游戏开发内存优化13条</title>
		<link>http://www.9STG.com/archives/1791.html</link>
		<comments>http://www.9STG.com/archives/1791.html#comments</comments>
		<pubDate>Tue, 09 Nov 2010 15:38:26 +0000</pubDate>
		<dc:creator>yong</dc:creator>
				<category><![CDATA[小游戏开发]]></category>
		<category><![CDATA[技术碎片]]></category>
		<category><![CDATA[游戏心得]]></category>
		<category><![CDATA[AS3]]></category>

		<guid isPermaLink="false">http://www.9STG.com/?p=1791</guid>
		<description><![CDATA[这篇算是读书笔记吧，边读边记，一来用简练语句分享，二来加深学习印象！关于内存优化总结了13条，欢迎交流指正！也欢迎常来9stg.com，关注游戏那些事儿！
1. 使用合适的显示对象，对于非交互的简单形状用Shape对象，对于不需要时间轴的交互式对象用Sprite,对于使用时间轴的动画用MovieClip,他们的内存使用量分别是236,412,440,可见shape很省内存
2. Number原始存储内存占8个字节，int,uint,Boolean,String均占4个字节, 关于赋值后作占内存，取决值赋的值
3. 对象的重复利用, 在FOR循环内new对象要小心，每次new都会增大内存。
4. 通过重复使用 BitmapData 对象可以节省更多的内存,即不同的bitmap公用一个bitmapdata
5. 重复使用相同对象的时候，可以考虑下对象池的应用
6. 垃圾回收运行时会不断检测出处于非活动状态的对象，大型项目中此进程会占用大量CPU，所以尽量重使用对象，不用的对象设置为NULL
7. 内存释放方面，为了确保被垃圾回收，首先保证该对象没有其他引用，然后移除监听，在然后设置为NULL。关于bitmapdata, 先用dispose 在设置为null
8. 在 Flash Player 10.1 中，对所有bitmapdata实例采用同一版本的bitmapdata, 大大节省了内存, 当bitmapdata数据发生变化的时候，内存中会建立一个新的bitmapdata实例
9. 尽量避免使用滤镜，当对显示对象使用滤镜的时候，内存中将创建两个位图，每个位图的大小都与显示对象相同。一个是显示对象的栅格化版本，一个是用于滤镜的位图
10. 当修改滤镜的属性的时候，内存中两个位图都将更新创建新的位图，会消耗一些CPU，并且会占用大量内存。
11. Flash Player 10.1 在所有平台上引入了一种新的过滤行为。如果滤镜在 30 秒内没有进行修改，或者将其隐藏或置于屏幕之外，将释放未过滤的位图占用的内存。该方式成为动态位图卸载。
12. 使用滤镜时仍要谨慎小心；在对它们进行修改时，仍要求大量 CPU 或 GPU 处理。
13. 如果想要滤镜效果，最好用PHOTOSHOP来做一个
]]></description>
			<content:encoded><![CDATA[<p>这篇算是读书笔记吧，边读边记，一来用简练语句分享，二来加深学习印象！关于内存优化总结了13条，欢迎交流指正！也欢迎常来9stg.com，关注游戏那些事儿！</p>
<p>1. 使用合适的显示对象，对于非交互的简单形状用Shape对象，对于不需要时间轴的交互式对象用Sprite,对于使用时间轴的动画用MovieClip,他们的内存使用量分别是236,412,440,可见shape很省内存</p>
<p>2. Number原始存储内存占8个字节，int,uint,Boolean,String均占4个字节, 关于赋值后作占内存，取决值赋的值</p>
<p>3. 对象的重复利用, 在FOR循环内new对象要小心，每次new都会增大内存。</p>
<p>4. 通过重复使用 BitmapData 对象可以节省更多的内存,即不同的bitmap公用一个bitmapdata</p>
<p>5. 重复使用相同对象的时候，可以考虑下对象池的应用</p>
<p>6. 垃圾回收运行时会不断检测出处于非活动状态的对象，大型项目中此进程会占用大量CPU，所以尽量重使用对象，不用的对象设置为NULL</p>
<p>7. 内存释放方面，为了确保被垃圾回收，首先保证该对象没有其他引用，然后移除监听，在然后设置为NULL。关于bitmapdata, 先用dispose 在设置为null</p>
<p>8. 在 Flash Player 10.1 中，对所有bitmapdata实例采用同一版本的bitmapdata, 大大节省了内存, 当bitmapdata数据发生变化的时候，内存中会建立一个新的bitmapdata实例</p>
<p>9. 尽量避免使用滤镜，当对显示对象使用滤镜的时候，内存中将创建两个位图，每个位图的大小都与显示对象相同。一个是显示对象的栅格化版本，一个是用于滤镜的位图</p>
<p>10. 当修改滤镜的属性的时候，内存中两个位图都将更新创建新的位图，会消耗一些CPU，并且会占用大量内存。</p>
<p>11. Flash Player 10.1 在所有平台上引入了一种新的过滤行为。如果滤镜在 30 秒内没有进行修改，或者将其隐藏或置于屏幕之外，将释放未过滤的位图占用的内存。该方式成为动态位图卸载。</p>
<p>12. 使用滤镜时仍要谨慎小心；在对它们进行修改时，仍要求大量 CPU 或 GPU 处理。</p>
<p>13. 如果想要滤镜效果，最好用PHOTOSHOP来做一个</p>
]]></content:encoded>
			<wfw:commentRss>http://www.9STG.com/archives/1791.html/feed</wfw:commentRss>
		<slash:comments>45</slash:comments>
		</item>
		<item>
		<title>多个swf文件共享AS3 ShareObject</title>
		<link>http://www.9STG.com/archives/687.html</link>
		<comments>http://www.9STG.com/archives/687.html#comments</comments>
		<pubDate>Tue, 02 Feb 2010 15:15:42 +0000</pubDate>
		<dc:creator>yong</dc:creator>
				<category><![CDATA[游戏心得]]></category>

		<guid isPermaLink="false">http://www.8ria.com/?p=687</guid>
		<description><![CDATA[今天不推荐游戏，写写关于AS3 ShareObject的事情，要对得起网站的名字，游手也要好学。

1. ShareObject  可以说是FLASH Cookie，帮助手册原话是：ShareObject 类用于在用户计算机或服务器上读取和存储有限的数据量。 使用共享对象，可在永久贮存在本地计算机或远程服务器上的多个客户端 SWF 文件和对象之间实现实时数据共享。 本地共享对象类似于浏览器 Cookie，远程共享对象类似于实时数据传输设备。 若要使用远程共享对象，则需要一个服务器
2. ShareObject将共享文件存储到本地的存储规则是值得注意的，存储路径在 C:\Documents and Settings\Administrator\Application Data\Macromedia\Flash Player\#SharedObjects下边，在这个文件夹下有类似命名为7HMY2T3Z的文件夹，点进去才是ShareObject真正生成的文件目录。这个文件目录的生成规则值得注意，域 + swf所在根目录下的文件路径 + 以swf文件名命名的文件夹，这下边的.sol文件就是ShareObject共享文件。
比如 \www.8ria.com\flash\game.swf\riaSO.sol
www.8ria.com是域，后边就是根据swf存放在服务器上的路径生成的。
确切的说创建共享文件的swf文件路径是&#8221; www.8ria.com/flash/game.swf&#8221;。
game.swf所作的事情是 var so:SharedObject = SharedObject.getLocal(&#8220;riaSO.sol&#8221;);
然后你在对应一下swf和本地共享文件目录的关系，就很容易明白了，如下：
\www.8ria.com\flash\game.swf\riaSO.sol
与
www.8ria.com/flash/game.swf
3. ShareObject 实现多个swf文件共享的方法是：首先你不能灵活的设定ShareObject的读取路径，也不能灵活的设定ShareObject的写入路径，这些几乎是定死的，完全与你swf的存储位置有关。要想实现共享还必须在同一个域才可以。由于这些问题的存在实现多个swf文件共享一个ShareObject共享文件便的有点棘手。方法我目前想出了两个。
第一方法是设定getLocal的第2个参数为“/”，var so:SharedObject = SharedObject.getLocal(&#8220;riaSO.sol&#8221;,&#8221;/&#8221;); 这样生成的共享文件都在根目录下，所以只要在同一个域的swf都可以共享这个共享文件的数据，只是这样做共享文件就不能肆无忌惮的取名字，要考虑到命名重复的问题，如果第2个参数不设置话，共享文件就会按照目录规则保存在各自的文件夹下，就不用担心重命名问题，这点与as3包路径设置的道理有点类似。
第二个方式是单独做一个swf文件专门负责创建共享文件，然后所有其他的swf文件都可以通过读取这个swf来获得共享数据。
自己对ShareObject了解不是很深，可能存在更多，更好的方法。知道的达人欢迎更正指点。
]]></description>
			<content:encoded><![CDATA[<p>今天不推荐游戏，写写关于AS3 ShareObject的事情，要对得起网站的名字，游手也要好学。</p>
<p><span id="more-687"></span></p>
<p>1. ShareObject  可以说是FLASH Cookie，帮助手册原话是：ShareObject 类用于在用户计算机或服务器上读取和存储有限的数据量。 使用共享对象，可在永久贮存在本地计算机或远程服务器上的多个客户端 SWF 文件和对象之间实现实时数据共享。 本地共享对象类似于浏览器 Cookie，远程共享对象类似于实时数据传输设备。 若要使用远程共享对象，则需要一个服务器</p>
<p>2. ShareObject将共享文件存储到本地的存储规则是值得注意的，存储路径在 C:\Documents and Settings\Administrator\Application Data\Macromedia\Flash Player\#SharedObjects下边，在这个文件夹下有类似命名为7HMY2T3Z的文件夹，点进去才是ShareObject真正生成的文件目录。这个文件目录的生成规则值得注意，域 + swf所在根目录下的文件路径 + 以swf文件名命名的文件夹，这下边的.sol文件就是ShareObject共享文件。</p>
<p>比如 \www.8ria.com\flash\game.swf\riaSO.sol</p>
<p><a href="http://www.8ria.com">www.8ria.com</a>是域，后边就是根据swf存放在服务器上的路径生成的。</p>
<p>确切的说创建共享文件的swf文件路径是&#8221; www.8ria.com/flash/game.swf&#8221;。</p>
<p>game.swf所作的事情是 var so:SharedObject = SharedObject.getLocal(&#8220;riaSO.sol&#8221;);</p>
<p>然后你在对应一下swf和本地共享文件目录的关系，就很容易明白了，如下：</p>
<p>\www.8ria.com\flash\game.swf\riaSO.sol</p>
<p>与</p>
<p>www.8ria.com/flash/game.swf</p>
<p>3. ShareObject 实现多个swf文件共享的方法是：首先你不能灵活的设定ShareObject的读取路径，也不能灵活的设定ShareObject的写入路径，这些几乎是定死的，完全与你swf的存储位置有关。要想实现共享还必须在同一个域才可以。由于这些问题的存在实现多个swf文件共享一个ShareObject共享文件便的有点棘手。方法我目前想出了两个。</p>
<p>第一方法是设定getLocal的第2个参数为“/”，var so:SharedObject = SharedObject.getLocal(&#8220;riaSO.sol&#8221;,&#8221;/&#8221;); 这样生成的共享文件都在根目录下，所以只要在同一个域的swf都可以共享这个共享文件的数据，只是这样做共享文件就不能肆无忌惮的取名字，要考虑到命名重复的问题，如果第2个参数不设置话，共享文件就会按照目录规则保存在各自的文件夹下，就不用担心重命名问题，这点与as3包路径设置的道理有点类似。</p>
<p>第二个方式是单独做一个swf文件专门负责创建共享文件，然后所有其他的swf文件都可以通过读取这个swf来获得共享数据。</p>
<p>自己对ShareObject了解不是很深，可能存在更多，更好的方法。知道的达人欢迎更正指点。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.9STG.com/archives/687.html/feed</wfw:commentRss>
		<slash:comments>63</slash:comments>
		</item>
		<item>
		<title>AS3 优化 之 FOR内循环</title>
		<link>http://www.9STG.com/archives/682.html</link>
		<comments>http://www.9STG.com/archives/682.html#comments</comments>
		<pubDate>Sun, 31 Jan 2010 16:54:29 +0000</pubDate>
		<dc:creator>yong</dc:creator>
				<category><![CDATA[游戏心得]]></category>
		<category><![CDATA[AS3优化]]></category>

		<guid isPermaLink="false">http://www.8ria.com/?p=682</guid>
		<description><![CDATA[写游戏只要有思路，就能实现，但这也只是从功能角度出发，能不能有好的效率，才是关键，于是想积累一些关于优化方面的知识。
关于AS3 FOR内循环的优化

当我们遍历一个数组的时候 ，你可能会这样写
private function testFor() : void
{
 var tmpVar:int;
 for(var i:Number=0; i&#60;testArray.length; i++)
 {
  tmpVar = testArray[i];
 }
}
执行这个函数50次，所用的时间是53.34毫秒。
如果我们将number类型改成int类型，如下
for(var i:int=0; i&#60;testArray.length; i++)
这样所执行的时间是35.58毫秒。
如果先把数组的长度计算出来，速度会更快
var l:int = testArray.length;
for(var i:int=0; i&#60;l; i++)
这个仅仅用了21.6毫秒
所以在for循环上int比number快，将length在循环外事先定义出来比直接写在for条件语句里面要快。
再看两段代码
var tmpVar:int;
for(var i:Number=0; i&#60;100000; i++)
{
 tmpVar = SomeClass.SOME_CONSTANT;
}
和
var tmpVar:int;
var myConstant:int = SomeClass.SOME_CONSTANT;
for(var i:Number=0; i&#60;100000; i++)
{
 tmpVar = myConstant;
}
前者的运行速度是34.08毫秒，后者的速度是 15.8毫秒
所以说 在FOR循环外先取到类属性，比拿到FOR循环内再去取类的属性的速度要快
变量在FOR内的定义
for(var i:int=0; i&#60;100000; i++)
{
 var v1:Number=10;
 var v2:Number=10;
 var v3:Number=10;
 var v4:Number=10;
 var v5:Number=10;
}
这个FOR需要用46.52毫秒，如果你用一个 var 去定义所有，将这些变量写成一行，像这样
for(var i:int=0; i&#60;100000; i++)
{
 var v1:Number=10, v2:Number=10, v3:Number=10, [...]]]></description>
			<content:encoded><![CDATA[<p>写游戏只要有思路，就能实现，但这也只是从功能角度出发，能不能有好的效率，才是关键，于是想积累一些关于优化方面的知识。</p>
<p>关于AS3 FOR内循环的优化</p>
<p><span id="more-682"></span></p>
<p>当我们遍历一个数组的时候 ，你可能会这样写</p>
<p>private function testFor() : void<br />
{<br />
 var tmpVar:int;</p>
<p> for(var i:Number=0; i&lt;testArray.length; i++)<br />
 {<br />
  tmpVar = testArray[i];<br />
 }<br />
}</p>
<p>执行这个函数50次，所用的时间是53.34毫秒。</p>
<p>如果我们将number类型改成int类型，如下</p>
<p>for(var i:int=0; i&lt;testArray.length; i++)</p>
<p>这样所执行的时间是35.58毫秒。</p>
<p>如果先把数组的长度计算出来，速度会更快</p>
<p>var l:int = testArray.length;</p>
<p>for(var i:int=0; i&lt;l; i++)</p>
<p>这个仅仅用了21.6毫秒</p>
<p><strong>所以在for循环上int比number快，将length在循环外事先定义出来比直接写在for条件语句里面要快。</strong></p>
<p>再看两段代码</p>
<p>var tmpVar:int;</p>
<p>for(var i:Number=0; i&lt;100000; i++)<br />
{<br />
 tmpVar = SomeClass.SOME_CONSTANT;<br />
}</p>
<p>和</p>
<p>var tmpVar:int;<br />
var myConstant:int = SomeClass.SOME_CONSTANT;</p>
<p>for(var i:Number=0; i&lt;100000; i++)<br />
{<br />
 tmpVar = myConstant;<br />
}</p>
<p>前者的运行速度是34.08毫秒，后者的速度是 15.8毫秒</p>
<p><strong>所以说 在FOR循环外先取到类属性，比拿到FOR循环内再去取类的属性的速度要快</strong></p>
<p>变量在FOR内的定义<br />
for(var i:int=0; i&lt;100000; i++)<br />
{<br />
 var v1:Number=10;<br />
 var v2:Number=10;<br />
 var v3:Number=10;<br />
 var v4:Number=10;<br />
 var v5:Number=10;<br />
}<br />
这个FOR需要用46.52毫秒，如果你用一个 var 去定义所有，将这些变量写成一行，像这样</p>
<p>for(var i:int=0; i&lt;100000; i++)<br />
{<br />
 var v1:Number=10, v2:Number=10, v3:Number=10, v4:Number=10, v5:Number=10;<br />
}</p>
<p>执行之间缩短到 19.74</p>
<p><strong>所以 在FOR循环内 尽量减少var这个关键字出现的次数，会提高效率</strong></p>
<p>逻辑运算符的适当运用也会提高效率的</p>
<p>for(var i:int=0; i&lt;100000; i++)<br />
{<br />
 var val1:int = 4 * 2;<br />
 var val2:int = 4 * 4;<br />
 var val3:int = 4 / 2;<br />
 var val4:int = 4 / 4;<br />
}</p>
<p>这段执行时间为 49.12 毫秒， 如果换成下面的代码，将会降到 35.56 毫秒</p>
<p>for(var i:int=0; i&lt;100000; i++)<br />
{<br />
 var val1:int = 4 &lt;&lt; 1;<br />
 var val2:int = 4 &lt;&lt; 2;<br />
 var val3:int = 4 &gt;&gt; 1;<br />
 var val4:int = 4 &gt;&gt; 2;<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>http://www.9STG.com/archives/682.html/feed</wfw:commentRss>
		<slash:comments>48</slash:comments>
		</item>
		<item>
		<title>Vincent对webgame开发的整体理解</title>
		<link>http://www.9STG.com/archives/33.html</link>
		<comments>http://www.9STG.com/archives/33.html#comments</comments>
		<pubDate>Tue, 13 Oct 2009 08:19:26 +0000</pubDate>
		<dc:creator>yong</dc:creator>
				<category><![CDATA[游戏心得]]></category>
		<category><![CDATA[webgame]]></category>

		<guid isPermaLink="false">http://www.madud.com/?p=33</guid>
		<description><![CDATA[Vincent先整体理解下webgame。
1.webgame优势：打开既玩，开发成本低。
2.webgame缺点：基于浏览器，基于flash player的效率比较低
3.webgame开发：总体分为前端和后端（B/S结构）
4.前端：美术设计，交互设计。webgame是基于浏览器开发的一种多人在线游戏，前端要做很好交互体验, 采用FLASH实现是最好不过的了，同时ActionScript3.0 是FLASH脚本语言的革新，我们完全可以很好的组织代码，利用OOP的思想去组织大的项目。
5.后端：服务器端开发。我们需要两种方式去实现webgame的运作，一种是实现游戏的实时性，一种是实现游戏的数据保存。第一，采用Socket连接去实现游戏的实时机制，实现同一个房间的信息，人物的移动同步，人物公聊与私聊等。目前有些现成的Socket Server, 比如SFS, FMS, RED5等等。第二，一些数据的存储与处理，比如打怪的时候你打到了一个装备，客户端与服务器端是一种一问一答的请求模式，可以采用HTTP通信方式，用AMFPHP去建立FLASH与数据库之间的关联。
总结：技术层，as3 + JAVA Socket + AMFPHP + MySql；理论层，按需加载，用户可以尽快体验。做好数据层与表现层的分离，做好类的组织，降低耦合度。
]]></description>
			<content:encoded><![CDATA[<p>Vincent先整体理解下webgame。</p>
<p>1.webgame优势：打开既玩，开发成本低。</p>
<p>2.webgame缺点：基于浏览器，基于flash player的效率比较低</p>
<p>3.webgame开发：总体分为前端和后端（B/S结构）</p>
<p>4.前端：美术设计，交互设计。webgame是基于浏览器开发的一种多人在线游戏，前端要做很好交互体验, 采用FLASH实现是最好不过的了，同时ActionScript3.0 是FLASH脚本语言的革新，我们完全可以很好的组织代码，利用OOP的思想去组织大的项目。</p>
<p>5.后端：服务器端开发。我们需要两种方式去实现webgame的运作，一种是实现游戏的实时性，一种是实现游戏的数据保存。第一，采用Socket连接去实现游戏的实时机制，实现同一个房间的信息，人物的移动同步，人物公聊与私聊等。目前有些现成的Socket Server, 比如SFS, FMS, RED5等等。第二，一些数据的存储与处理，比如打怪的时候你打到了一个装备，客户端与服务器端是一种一问一答的请求模式，可以采用HTTP通信方式，用AMFPHP去建立FLASH与数据库之间的关联。</p>
<p>总结：技术层，as3 + JAVA Socket + AMFPHP + MySql；理论层，按需加载，用户可以尽快体验。做好数据层与表现层的分离，做好类的组织，降低耦合度。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.9STG.com/archives/33.html/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Madud对SmartFoxServer的学习:登录，建立虚拟形象以及聊天</title>
		<link>http://www.9STG.com/archives/15.html</link>
		<comments>http://www.9STG.com/archives/15.html#comments</comments>
		<pubDate>Thu, 01 Oct 2009 07:34:24 +0000</pubDate>
		<dc:creator>yong</dc:creator>
				<category><![CDATA[游戏心得]]></category>
		<category><![CDATA[SmartFoxServer]]></category>

		<guid isPermaLink="false">http://www.madud.com/?p=15</guid>
		<description><![CDATA[用SmartFoxServer构建FLASH社区游戏应该是一件容易的事情, Madud最近有想做类DNF网游的冲动，所以先学习下SFS吧，关于SFS基本的东西，链接登录，虚拟形象的思路总结如下。
1.连接SFS
2.如果连接（触发 onConnection）成功就登陆
3.如果登陆（触发onLogin）成功，接着会自动获取房间列表（触发onRoomListUpdate），如果成功，自动或者手动加入一个房间(joinRoom方法)。
4.成功加入房间（触发onJoinRoom），获取下房间名字以及该房间的用户列表, 并加载房间, 初始化自己的虚拟形象，将该形象需要客户端共享的变量传给服务器端（setUserVariables）初始化其他的虚拟形象，getVariables返回所有用户的变量列表，通过这些从服务器端获取的变量，设置其它人此时的状态
 5.此时，已经完成 连接，登陆，加入场景，初始化自己的虚拟形象和其他虚拟形象，下面需要做的是移动，为了实时看见其它虚拟形象的移动（动作，颜色等需要其它玩家实时看见的），需要用setUserVariables 传变量给服务器端，无论什么时候只要用户变量初始化或者更新都会触发onUserVariables, 然后再触发函数里面通过getVariable()从服务器端获取此时虚拟形象的状态（坐标，颜色，服装等），从而进行控制。这样就形成了多人在线社区的实时功能
 6. 用户进入或离开房间，当用joinRoom方法成功进入到另一个房间时，也意味着成功离开了当前房间（除了第一次进入社区的情况外），这个时候会触发onUserEnterRoom和onUserLeaveRoom事件，当用户离开的时候，需要获得离开房间的用户对象，然后便利删除该对象，同样进入房间的时候把该用户加入用户列表
 7.公用聊天，用sendPublicMessage() 发送公共消息, 触发onPublicMessage 事件处理该消息
]]></description>
			<content:encoded><![CDATA[<p>用SmartFoxServer构建FLASH社区游戏应该是一件容易的事情, Madud最近有想做类DNF网游的冲动，所以先学习下SFS吧，关于SFS基本的东西，链接登录，虚拟形象的思路总结如下。</p>
<p>1.连接SFS</p>
<p>2.如果<strong>连接</strong>（触发 onConnection）成功就登陆</p>
<p>3.如果<strong>登陆</strong>（触发onLogin）成功，接着会自动获取房间列表（触发onRoomListUpdate），如果成功，自动或者手动加入一个房间(joinRoom方法)。</p>
<p>4.成功<strong>加入</strong>房间（触发onJoinRoom），获取下房间名字以及该房间的用户列表, 并加载房间, 初始化自己的虚拟形象，将该形象需要客户端共享的变量传给服务器端（setUserVariables）初始化其他的虚拟形象，getVariables返回所有用户的变量列表，通过这些从服务器端获取的变量，设置其它人此时的状态</p>
<p> 5.此时，已经完成 连接，登陆，加入场景，初始化自己的虚拟形象和其他虚拟形象，下面需要做的是移动，为了实时看见其它虚拟形象的移动（动作，颜色等需要其它玩家实时看见的），需要用setUserVariables 传变量给服务器端，无论什么时候只要<strong>用户变量初始化</strong>或者<strong>更新</strong>都会触发onUserVariables, 然后再触发函数里面通过getVariable()从服务器端获取此时虚拟形象的状态（坐标，颜色，服装等），从而进行控制。这样就形成了多人在线社区的实时功能</p>
<p> 6. 用户进入或离开房间，当用joinRoom方法成功进入到另一个房间时，也意味着成功离开了当前房间（除了第一次进入社区的情况外），这个时候会触发onUserEnterRoom和onUserLeaveRoom事件，当用户离开的时候，需要获得离开房间的用户对象，然后便利删除该对象，同样进入房间的时候把该用户加入用户列表</p>
<p> 7.公用聊天，用sendPublicMessage() 发送公共消息, 触发onPublicMessage 事件处理该消息</p>
]]></content:encoded>
			<wfw:commentRss>http://www.9STG.com/archives/15.html/feed</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>多人画板的实现 “哥发的不是画面，哥发的是字符串”</title>
		<link>http://www.9STG.com/archives/9.html</link>
		<comments>http://www.9STG.com/archives/9.html#comments</comments>
		<pubDate>Thu, 01 Oct 2009 05:38:27 +0000</pubDate>
		<dc:creator>yong</dc:creator>
				<category><![CDATA[游戏心得]]></category>

		<guid isPermaLink="false">http://www.madud.com/?p=9</guid>
		<description><![CDATA[祖国60岁的今天，正好是Madud第一个多人游戏告一段落的时候，写点总结，希望与大家一起交流进步！
1.要达到的目的是：所有客户端实时共享画板
2.前后端结构：客户端FLASH ， 服务器端SFS，mySQL
3.单机与多人：单机就是自己和电脑玩，多人游戏就是人和人玩
4.多人共享数据：要实现人和人玩，就意味着你的行为要让大家知道，这就需要你告诉大家你做了什么，所以与单机不同的是你需要用服务器去实时共享你的行为给大家！
5. 画板制作：画板分两层，上层是Sprite,下层是bitmap, 他们的关系是将sprite绘制出来的画面存到bitmap的bitmapdata中，在Sprite中，用MOUSE_MOVE事件函数里面用Sprite的graphics.moveTo, lineTo实现任意画线，然后鼠标抬起的时候，将你在Sprite上所画的保存到bitmapdata中，然后清空Sprite
6.奇淫巧计：橡皮差与清除画板的实现，同事的点子，既然画板背景色是白色，橡皮差就用白色的线条绘制就可以了，同样道理，清除画板只需要用一次遍历，将bitmapdata所有像素点的颜色变成白色就可以了
7.共享画板：为了实现共享，我需要把“画面”发送给服务器，然后服务器在把这个“画面”发送给其他客户端，这样就实现了共享. 但主意的一点是“哥发的不是画面，哥发的是字符串！”，就是说服务器要接收能接收的东西，意思是你不能发送Sprite给他，所以我们就需要借助bitmapdata，并进一步将bitmapdata进行Base64编码转换成字符串发送给服务器端，然后服务器端将字符串发送给客户端，客户端将字符串反编回bitmapdata并绘制！
8.何时发送：当你正在画线，鼠标并没有抬起的时候，大家看不到你所画的，当鼠标抬起的时候大家才能看见，就是说我鼠标抬起的时候我才告诉服务器去广播我所做的事情！不想频繁的发送，MOUSE_UP的时候再通知SFS JAVA扩展，应该算一种得当的方式吧！
9.遇到的问题：服务器对字符串接收有长度限制，处理的方法是将字符串分段发送
10.用到的两个类BitmapByte和Base64

package{  
  
    import flash.display.BitmapData;  
    import flash.geom.Rectangle;  
    import flash.utils.ByteArray;  
    public class BitmapBytes {  
          
        public static function encodeByteArray(data:BitmapData):ByteArray{  
            if(data == null){  
                throw new Error(&#8220;data参数不能为空!&#8221;);  
            }  
            var bytes:ByteArray = data.getPixels(data.rect);  
            bytes.writeShort(data.width);  
            bytes.writeShort(data.height);  
            bytes.writeBoolean(data.transparent);  
            bytes.compress();  
            return bytes;  
        }  
        public static function encodeBase64(data:BitmapData):String{  
            return Base64.encodeByteArray(encodeByteArray(data));  
        }  
          
        public static function decodeByteArray(bytes:ByteArray):BitmapData{  
            if(bytes == null){  
                throw [...]]]></description>
			<content:encoded><![CDATA[<p>祖国60岁的今天，正好是Madud第一个多人游戏告一段落的时候，写点总结，希望与大家一起交流进步！</p>
<p>1.要达到的目的是：所有客户端实时共享画板</p>
<p>2.前后端结构：客户端FLASH ， 服务器端SFS，mySQL</p>
<p>3.单机与多人：单机就是自己和电脑玩，多人游戏就是人和人玩</p>
<p>4.多人共享数据：要实现人和人玩，就意味着你的行为要让大家知道，这就需要你告诉大家你做了什么，所以与单机不同的是你需要用服务器去实时共享你的行为给大家！</p>
<p>5. 画板制作：画板分两层，上层是Sprite,下层是bitmap, 他们的关系是将sprite绘制出来的画面存到bitmap的bitmapdata中，在Sprite中，用MOUSE_MOVE事件函数里面用Sprite的graphics.moveTo, lineTo实现任意画线，然后鼠标抬起的时候，将你在Sprite上所画的保存到bitmapdata中，然后清空Sprite</p>
<p>6.奇淫巧计：橡皮差与清除画板的实现，同事的点子，既然画板背景色是白色，橡皮差就用白色的线条绘制就可以了，同样道理，清除画板只需要用一次遍历，将bitmapdata所有像素点的颜色变成白色就可以了</p>
<p>7.共享画板：为了实现共享，我需要把“画面”发送给服务器，然后服务器在把这个“画面”发送给其他客户端，这样就实现了共享. 但主意的一点是“哥发的不是画面，哥发的是字符串！”，就是说服务器要接收能接收的东西，意思是你不能发送Sprite给他，所以我们就需要借助bitmapdata，并进一步将bitmapdata进行Base64编码转换成字符串发送给服务器端，然后服务器端将字符串发送给客户端，客户端将字符串反编回bitmapdata并绘制！</p>
<p>8.何时发送：当你正在画线，鼠标并没有抬起的时候，大家看不到你所画的，当鼠标抬起的时候大家才能看见，就是说我鼠标抬起的时候我才告诉服务器去广播我所做的事情！不想频繁的发送，MOUSE_UP的时候再通知SFS JAVA扩展，应该算一种得当的方式吧！</p>
<p>9.遇到的问题：服务器对字符串接收有长度限制，处理的方法是将字符串分段发送</p>
<p>10.用到的两个类BitmapByte和Base64</p>
<p><span id="more-9"></span></p>
<p>package{  <br />
  <br />
    import flash.display.BitmapData;  <br />
    import flash.geom.Rectangle;  <br />
    import flash.utils.ByteArray;  </p>
<p>    public class BitmapBytes {  <br />
          <br />
        public static function encodeByteArray(data:BitmapData):ByteArray{  <br />
            if(data == null){  <br />
                throw new Error(&#8220;data参数不能为空!&#8221;);  <br />
            }  <br />
            var bytes:ByteArray = data.getPixels(data.rect);  <br />
            bytes.writeShort(data.width);  <br />
            bytes.writeShort(data.height);  <br />
            bytes.writeBoolean(data.transparent);  <br />
            bytes.compress();  <br />
            return bytes;  <br />
        }  <br />
        public static function encodeBase64(data:BitmapData):String{  <br />
            return Base64.encodeByteArray(encodeByteArray(data));  <br />
        }  <br />
          <br />
        public static function decodeByteArray(bytes:ByteArray):BitmapData{  <br />
            if(bytes == null){  <br />
                throw new Error(&#8220;bytes参数不能为空!&#8221;);  <br />
            }  <br />
            bytes.uncompress();  <br />
            if(bytes.length &lt;  6){  <br />
                throw new Error(&#8220;bytes参数为无效值!&#8221;);  <br />
            }             <br />
            bytes.position = bytes.length &#8211; 1;  <br />
            var transparent:Boolean = bytes.readBoolean();  <br />
            bytes.position = bytes.length &#8211; 3;  <br />
            var height:int = bytes.readShort();  <br />
            bytes.position = bytes.length &#8211; 5;  <br />
            var width:int = bytes.readShort();  <br />
            bytes.position = 0;  <br />
            var datas:ByteArray = new ByteArray();            <br />
            bytes.readBytes(datas,0,bytes.length &#8211; 5);  <br />
            var bmp:BitmapData = new BitmapData(width,height,transparent,0);  <br />
            bmp.setPixels(new Rectangle(0,0,width,height),datas);  <br />
            return bmp;  <br />
        }  <br />
          <br />
        public static function decodeBase64(data:String):BitmapData{              <br />
            return decodeByteArray(Base64.decodeToByteArray(data));  <br />
        }         <br />
          <br />
        public function BitmapBytes() {  <br />
            throw new Error(&#8220;BitmapBytes类只是一个静态类!&#8221;);  <br />
        }  <br />
          <br />
    }  <br />
      <br />
}</p>
<p> </p>
<p>/*<br />
Base64 &#8211; 1.1.0</p>
<p>Copyright (c) 2006 Steve Webster</p>
<p>Permission is hereby granted, free of charge, to any person obtaining a copy of<br />
this software and associated documentation files (the &#8220;Software&#8221;), to deal in<br />
the Software without restriction, including without limitation the rights to<br />
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of<br />
the Software, and to permit persons to whom the Software is furnished to do so,<br />
subject to the following conditions:</p>
<p>The above copyright notice and this permission notice shall be included in all<br />
copies or substantial portions of the Software.</p>
<p>THE SOFTWARE IS PROVIDED &#8220;AS IS&#8221;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br />
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS<br />
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR<br />
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER<br />
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN<br />
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<br />
*/</p>
<p>package {</p>
<p>        import flash.utils.ByteArray;<br />
       <br />
        public class Base64 {<br />
               <br />
                private static const BASE64_CHARS:String = &#8220;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=&#8221;;</p>
<p>                public static const version:String = &#8220;1.0.0&#8243;;</p>
<p>                public static function encode(data:String):String {<br />
                        // Convert string to ByteArray<br />
                        var bytes:ByteArray = new ByteArray();<br />
                        bytes.writeUTFBytes(data);<br />
                       <br />
                        // Return encoded ByteArray<br />
                        return encodeByteArray(bytes);<br />
                }<br />
               <br />
                public static function encodeByteArray(data:ByteArray):String {<br />
                        // Initialise output<br />
                        var output:String = &#8220;&#8221;;<br />
                       <br />
                        // Create data and output buffers<br />
                        var dataBuffer:Array;<br />
                        var outputBuffer:Array = new Array(4);<br />
                       <br />
                        // Rewind ByteArray<br />
                        data.position = 0;<br />
                       <br />
                        // while there are still bytes to be processed<br />
                        while (data.bytesAvailable &gt; 0) {<br />
                                // Create new data buffer and populate next 3 bytes from data<br />
                                dataBuffer = new Array();<br />
                                for (var i:uint = 0; i &lt; 3 &amp;&amp; data.bytesAvailable &gt; 0; i++) {<br />
                                        dataBuffer[i] = data.readUnsignedByte();<br />
                                }<br />
                               <br />
                                // Convert to data buffer Base64 character positions and<br />
                                // store in output buffer<br />
                                outputBuffer[0] = (dataBuffer[0] &amp; 0xfc) &gt;&gt; 2;<br />
                                outputBuffer[1] = ((dataBuffer[0] &amp; 0&#215;03) &lt;&lt; 4) | ((dataBuffer[1]) &gt;&gt; 4);<br />
                                outputBuffer[2] = ((dataBuffer[1] &amp; 0&#215;0f) &lt;&lt; 2) | ((dataBuffer[2]) &gt;&gt; 6);<br />
                                outputBuffer[3] = dataBuffer[2] &amp; 0&#215;3f;<br />
                               <br />
                                // If data buffer was short (i.e not 3 characters) then set<br />
                                // end character indexes in data buffer to index of &#8216;=&#8217; symbol.<br />
                                // This is necessary because Base64 data is always a multiple of<br />
                                // 4 bytes and is basses with &#8216;=&#8217; symbols.<br />
                                for (var j:uint = dataBuffer.length; j &lt; 3; j++) {<br />
                                        outputBuffer[j + 1] = 64;<br />
                                }<br />
                               <br />
                                // Loop through output buffer and add Base64 characters to<br />
                                // encoded data string for each character.<br />
                                for (var k:uint = 0; k &lt; outputBuffer.length; k++) {<br />
                                        output += BASE64_CHARS.charAt(outputBuffer[k]);<br />
                                }<br />
                        }<br />
                       <br />
                        // Return encoded data<br />
                        return output;<br />
                }<br />
               <br />
                public static function decode(data:String):String {<br />
                        // Decode data to ByteArray<br />
                        var bytes:ByteArray = decodeToByteArray(data);<br />
                       <br />
                        // Convert to string and return<br />
                        return bytes.readUTFBytes(bytes.length);<br />
                }<br />
               <br />
                public static function decodeToByteArray(data:String):ByteArray {<br />
                        // Initialise output ByteArray for decoded data<br />
                        var output:ByteArray = new ByteArray();<br />
                       <br />
                        // Create data and output buffers<br />
                        var dataBuffer:Array = new Array(4);<br />
                        var outputBuffer:Array = new Array(3);</p>
<p>                        // While there are data bytes left to be processed<br />
                        for (var i:uint = 0; i &lt; data.length; i += 4) {<br />
                                // Populate data buffer with position of Base64 characters for<br />
                                // next 4 bytes from encoded data<br />
                                for (var j:uint = 0; j &lt; 4 &amp;&amp; i + j &lt; data.length; j++) {<br />
                                        dataBuffer[j] = BASE64_CHARS.indexOf(data.charAt(i + j));<br />
                                }<br />
                             <br />
                              // Decode data buffer back into bytes<br />
                                outputBuffer[0] = (dataBuffer[0] &lt;&lt; 2) + ((dataBuffer[1] &amp; 0&#215;30) &gt;&gt; 4);<br />
                                outputBuffer[1] = ((dataBuffer[1] &amp; 0&#215;0f) &lt;&lt; 4) + ((dataBuffer[2] &amp; 0&#215;3c) &gt;&gt; 2);               <br />
                                outputBuffer[2] = ((dataBuffer[2] &amp; 0&#215;03) &lt;&lt; 6) + dataBuffer[3];<br />
                               <br />
                                // Add all non-padded bytes in output buffer to decoded data<br />
                                for (var k:uint = 0; k &lt; outputBuffer.length; k++) {<br />
                                        if (dataBuffer[k+1] == 64) break;<br />
                                        output.writeByte(outputBuffer[k]);<br />
                                }<br />
                        }<br />
                       <br />
                        // Rewind decoded data ByteArray<br />
                        output.position = 0;<br />
                       <br />
                        // Return decoded data<br />
                        return output;<br />
                }<br />
               <br />
                public function Base64() {<br />
                        throw new Error(&#8220;Base64 class is static container only&#8221;);<br />
                }<br />
        }<br />
}</p>
]]></content:encoded>
			<wfw:commentRss>http://www.9STG.com/archives/9.html/feed</wfw:commentRss>
		<slash:comments>80</slash:comments>
		</item>
	</channel>
</rss>

