﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-游戏人生-随笔分类-人生</title><link>http://www.cppblog.com/Fox/category/5794.html</link><description>游戏人生 != ( 人生 == 游戏 )</description><language>zh-cn</language><lastBuildDate>Fri, 21 Dec 2007 13:27:00 GMT</lastBuildDate><pubDate>Fri, 21 Dec 2007 13:27:00 GMT</pubDate><ttl>60</ttl><item><title>也说说级数求和(1+2+3...N)和其他</title><link>http://www.cppblog.com/Fox/archive/2007/12/21/simple_series_sum.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Fri, 21 Dec 2007 02:19:00 GMT</pubDate><guid>http://www.cppblog.com/Fox/archive/2007/12/21/simple_series_sum.html</guid><wfw:comment>http://www.cppblog.com/Fox/comments/39190.html</wfw:comment><comments>http://www.cppblog.com/Fox/archive/2007/12/21/simple_series_sum.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/Fox/comments/commentRss/39190.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Fox/services/trackbacks/39190.html</trackback:ping><description><![CDATA[
		<p>Author: Fox(<a href="mailto:yulefox@126.com">yulefox@126.com</a>)</p>
		<p>对于(1+2+...+N) 的求和，最早就是看高斯的故事，而且说实话，我是没有这样的智商的：</p>
		<p>                sum(1+2+...+N) = N*(N+1)/2</p>
		<p>刚看了一篇<a href="/azhisoft/archive/2007/12/19/436.html" target="_blank">研究该级数求和的文章</a>，虽为调侃，但实在感觉文中纰漏太多，不禁在此多言。</p>
		<p>文中的第一种方法自称标准，而且还能使“全班2/3的同学都用俺的标准应付老师和试卷”，我大为惊诧：</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font face="Courier New">
						<font size="4">
								<span style="COLOR: #008080">1</span> <span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> i, sum </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span></font>
				</font>
				<font face="Courier New">
						<font size="4">
								<span style="COLOR: #000000">;<br /></span>
								<span style="COLOR: #008080">2</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(i </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;i </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> N;i </span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">)sum </span><span style="COLOR: #000000">+=</span></font>
				</font>
				<font face="Courier New">
						<font size="4">
								<span style="COLOR: #000000"> i;<br /></span>
								<span style="COLOR: #008080">3</span> <span style="COLOR: #000000">printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1-N的级数和是: %i</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,sum);</span></font>
				</font>
		</div>
		<p>
				<br />显然，printf的结果是N-1个数的和，此处，我更愿意相信是文中的笔误而已。</p>
		<p>第二种和第三种方法让人觉得奇怪：</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font face="Courier New">
						<font size="4">
								<span style="COLOR: #008080">1</span> <span style="COLOR: #0000ff">float</span></font>
				</font>
				<font face="Courier New">
						<font size="4">
								<span style="COLOR: #000000"> sum;<br /></span>
								<span style="COLOR: #008080">2</span> <span style="COLOR: #000000">sum </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (N </span><span style="COLOR: #000000">^</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">) </span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">2</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> N </span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">2</span></font>
				</font>
				<font face="Courier New">
						<font size="4">
								<span style="COLOR: #000000">;<br /></span>
								<span style="COLOR: #008080">3</span> <span style="COLOR: #000000">printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1-N的级数和是: %i</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,(</span><span style="COLOR: #0000ff">int</span></font>
				</font>
				<font face="Courier New">
						<font size="4">
								<span style="COLOR: #000000">)sum);<br /></span>
								<span style="COLOR: #008080">4</span> </font>
				</font>
				<span style="COLOR: #000000">
						<br />
				</span>
				<font face="Courier New">
						<font size="4">
								<span style="COLOR: #008080">5</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">float</span></font>
				</font>
				<font face="Courier New">
						<font size="4">
								<span style="COLOR: #000000"> sum;<br /></span>
								<span style="COLOR: #008080">6</span> <span style="COLOR: #000000">sum </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> N </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> (N </span><span style="COLOR: #000000">/</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">2</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0.5</span></font>
				</font>
				<font face="Courier New">
						<font size="4">
								<span style="COLOR: #000000">);<br /></span>
								<span style="COLOR: #008080">7</span> <span style="COLOR: #000000">printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1-N的级数和是: %i</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000">)sum);</span></font>
				</font>
		</div>
		<p>
				<br />前面的写法纯属恶搞，^在C/C++中是异或位操作，相信接触过位运算的人都知道这一点，而且当N为奇数时，sum的结果将比真实值少1。后面的写法更是荒唐，当N为奇数时，sum的结果将比真实值相去更远（有兴趣的可以仔细看看）。</p>
		<p>对于后面两种写法，我想说的重点不是这些明显的错误，因为这样的错误只可博众君一笑。但文中定义sum使用float的做法，让我百思不得其解。对于计算机的运算，浮点运算的耗时和整型运算的耗时，那不是一个数量级的。对于该级数运算，我们完全可以避免浮点运算，而且方法在文章一开始，就已经给出了：</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #008080">1</span> <span style="COLOR: #0000ff">int</span></font>
				</font>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #000000"> sum;<br /></span>
								<span style="COLOR: #008080">2</span> <span style="COLOR: #000000">sum </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> N</span><span style="COLOR: #000000">*</span><span style="COLOR: #000000">(N</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">2</span></font>
				</font>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #000000">;<br /></span>
								<span style="COLOR: #008080">3</span> <span style="COLOR: #000000">printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">1-N的级数和是: %i</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">, sum);</span></font>
				</font>
		</div>
		<p>
				<br />无论N为奇数还是偶数，N*(N+1)一定是偶数，因此，上述方法不存在浮点运算，而且系统会自动将/2的操作优化为右移1位。</p>
		<p>不知怎么，忽然就想到了递归，想到了Fibonacci数列。讲递归的教材都会拿上面的级数求和和Fibonacci数列做例子。其实，我个人感觉这是不恰当的，但想想为了让学生掌握递归算法，也只能举类似的简单的例子。我们也知道，递归计算对于堆栈调用是非常频繁而耗时的，对于求Hanoi塔这样的复杂问题，我不知道不用递归有没有更好的方法，但如果计算Fibonacci数列还是使用递归，在初学递归时是可以原谅的。简单点的方法可以是这样：</p>
		<p>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #008080"> 1</span> <span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> fib_odd </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">, fib_even </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span></font>
				</font>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #000000"> ;<br /></span>
								<span style="COLOR: #008080"> 2</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> n </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (N+1)</span><span style="COLOR: #000000">/</span><span style="COLOR: #000000">2</span></font>
				</font>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #000000">;<br /></span>
								<span style="COLOR: #008080"> 3</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000">(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> i</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">; i</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">n; i</span><span style="COLOR: #000000">++</span></font>
				</font>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #000000"> )<br /></span>
								<span style="COLOR: #008080"> 4</span> </font>
				</font>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #000000">{<br /></span>
								<span style="COLOR: #008080"> 5</span> <span style="COLOR: #000000">  fib_odd </span><span style="COLOR: #000000">+=</span></font>
				</font>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #000000">  fib_even;<br /></span>
								<span style="COLOR: #008080"> 6</span> <span style="COLOR: #000000">  fib_even </span><span style="COLOR: #000000">+=</span></font>
				</font>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #000000">  fib_odd;<br /></span>
								<span style="COLOR: #008080"> 7</span> </font>
				</font>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #000000">}<br /></span>
								<span style="COLOR: #008080"> 8</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> nFib </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span></font>
				</font>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #000000">;<br /></span>
								<span style="COLOR: #008080"> 9</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000">( N </span><span style="COLOR: #000000">%</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">2</span></font>
				</font>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #000000"> )<br /></span>
								<span style="COLOR: #008080">10</span> <span style="COLOR: #000000">  nFib </span><span style="COLOR: #000000">=</span></font>
				</font>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #000000"> fib_odd;<br /></span>
								<span style="COLOR: #008080">11</span> <span style="COLOR: #000000"></span><span style="COLOR: #0000ff">else</span></font>
				</font>
				<span style="COLOR: #000000">
						<br />
				</span>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #008080">12</span> <span style="COLOR: #000000">  nFib </span><span style="COLOR: #000000">=</span></font>
				</font>
				<font size="4">
						<font face="Courier New">
								<span style="COLOR: #000000"> fib_even;<br /></span>
								<span style="COLOR: #008080">13</span> <span style="COLOR: #000000">printf(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Fibonacci数列前N项和是: %i</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">,nFib); </span></font>
				</font>
		</div>
		<p>
				<br />上面的两段代码中sum和nFib的值不能太大:)。</p>
		<p>常言道，言过必失。但自私一点讲，把自己的错误暴露给别人，可以让自己更好的进步:)，因此，我写下来，提醒自己也提醒大家，更欢迎大家多批评指正。</p>
<img src ="http://www.cppblog.com/Fox/aggbug/39190.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Fox/" target="_blank">Fox</a> 2007-12-21 10:19 <a href="http://www.cppblog.com/Fox/archive/2007/12/21/simple_series_sum.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>反外挂的一点牢骚</title><link>http://www.cppblog.com/Fox/archive/2007/12/20/anti_credit.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Wed, 19 Dec 2007 18:08:00 GMT</pubDate><guid>http://www.cppblog.com/Fox/archive/2007/12/20/anti_credit.html</guid><wfw:comment>http://www.cppblog.com/Fox/comments/39081.html</wfw:comment><comments>http://www.cppblog.com/Fox/archive/2007/12/20/anti_credit.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/Fox/comments/commentRss/39081.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Fox/services/trackbacks/39081.html</trackback:ping><description><![CDATA[
		<p>Author: Fox(<a href="mailto:yulefox@126.com">yulefox@126.com</a>)</p>
		<p>俗话说，道高一尺，魔高一丈。</p>
		<p>今天在一个群里，有人提到某某算法（3DES）可以杜绝外挂。我当时心里苦笑一声：哥们儿，太逗了。这年头，中国人已经被忽悠怕了。我信鬼信魔，就是不信佛……</p>
		<p>不过想想，如果能在一定程度上打击外挂，也不错，可是讨论了半天，愣是没有给出具体的方案，最后还是不了了之。</p>
		<p>不过，有时间把思路整理整理，提一个稍微好一点的方法也好。</p>
		<p>王城里面，一排排的外挂小号像阅兵一样，嚣张成马了，完全不把我们放在眼里。</p>
		<p>话说回来，连个脱机外挂都防不住，别人还确实没必要把你放在眼里。</p>
		<p>这边Login Server搞了两三个月的验证码，感觉不错，因为不使用外挂的玩家每次都要折腾半天，我们自己人员输入验证码输的都烦，结果没出半个月外挂又开始横行了，感觉比以前还嚣张。</p>
		<p>我是外挂，我得意的笑，我得意的笑……</p>
		<p>敢情是防贼没防住，把贼扔屋里，自己被锁在外面了！</p>
		<p>
				<font color="#008000">/*****************************************************************************<br />  晚上本来想自己写个内挂，可以偷偷懒，可惜对这东西实在是从来没有过研究。<br />  折腾了一晚上，郁郁而终。<br />  技不如人啊！想来都觉得可笑……<br />*****************************************************************************/</font>
				<font color="#000000">
				</font>
		</p>
<img src ="http://www.cppblog.com/Fox/aggbug/39081.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Fox/" target="_blank">Fox</a> 2007-12-20 02:08 <a href="http://www.cppblog.com/Fox/archive/2007/12/20/anti_credit.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>游戏脚本变量存取优化</title><link>http://www.cppblog.com/Fox/archive/2007/12/17/script_variable_optimize.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Mon, 17 Dec 2007 11:55:00 GMT</pubDate><guid>http://www.cppblog.com/Fox/archive/2007/12/17/script_variable_optimize.html</guid><wfw:comment>http://www.cppblog.com/Fox/comments/38779.html</wfw:comment><comments>http://www.cppblog.com/Fox/archive/2007/12/17/script_variable_optimize.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/Fox/comments/commentRss/38779.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Fox/services/trackbacks/38779.html</trackback:ping><description><![CDATA[
		<p>Author: Fox(<a href="mailto:yulefox@126.com">yulefox@126.com</a>)</p>
		<p>在MMORPG中，存在大量的数据文件和脚本文件，这些文件涉及很多变量，当玩家信息需要存取时（上线、下线、保存、服务器交互），即伴随着大量的读写操作。随着游戏中游戏任务的增加，每一个玩家对应的需要数据库存取的脚本变量的数据量也随之线性增长，随着玩家数量的增加，在服务器保存玩家角色信息的时候，通信量的大小是相当可观的，使用多线程读写，可以使服务器的处理能力大幅增强，但网络和数据库承受的压力也会大幅增加。</p>
		<p>当然现在有很多的脚本语言为我们设计任务系统提供了便利，像Lua、Python、Ruby这些动态语言的功能越来越强，而且可以肯定的是，会有越来越多的产品采用这些优秀的语言。但我今天要谈的不是如何使用动态语言，也不是讨论动态语言孰优孰劣的问题，而是对于大量的脚本变量的存取优化。说白了，这对于使用自定义脚本语言的游戏开发人员才更有参考价值。而且我要说的问题很小，小到我只是讲一点点内容，只是我今天下午的一点活，总结下来更多只是为了让自己记住，并不是教育别人。</p>
		<p>假设在整个脚本系统中，存在500个与玩家相关而且需要数据库存取的脚本变量，如果一个游戏世界中拥有3000个在线玩家，平均每个玩家的脚本变量大小为10KB，如果服务器同时保存这3000个玩家的数据（那可不仅仅是脚本变量，当然脚本变量所占的分量比较大就是了），3000×10KB，哦……与此同时，服务器还要进行其实正常的网络通信和逻辑处理（虽然不可能是同一个线程），但服务器承受的压力已经不小了吧，为了减少这种压力，脚本变量成为了一种稀缺资源。<br />为了对脚本变量的存取进行优化，我想到了一个最容易实现的方法。通过对数据库的观察（其实想也想也想得到:)），我发现玩家数据中大量的脚本变量的值都是0或者空字符串，这就为优化提供了很大的一个空间。</p>
		<p>服务器一般都保存有一个脚本变量的配置文件，在这个文件中列出了所有的脚本变量及其默认值。当玩家登录时，服务器将为其依据这个文件为其建立一份拷贝，并从数据库读取这些变量的真实值填充之。因为大量的变量值都是默认值，所以在往数据库保存的时候，是没有必要全部保存的，而只需保存那些不同于默认值的变量名和变量值以及该变量对应的下标即可。下一次从数据库读入的时候根据下标确定哪些变量值需要从数据库中读取就可以了。</p>
		<p>很简单的一个操作，虽然做到了这一点优化，但是对于500个变量的线性读取和其他操作，依然不是一个好的处理方法。</p>
		<p>几点改进的方向，目前只是有个想法：</p>
		<p>1、将玩家与其脚本变量解耦</p>
		<p>并不是所有的玩家都需要500个脚本变量的，不同等级的玩家可以参与的任务和活动是完全不同的，我们显然没有必要为每一个玩家从生到死都保持这500个变量。这样考虑下来，估计一个玩家的脚本变量数可以减少300-400个，从而实现了“垃圾”回收再利用。OMG！</p>
		<p>想法是非常具有诱惑力的，但这一优化同时涉及到脚本策划和程序，而且稍有不慎（对某一变量重复使用），全盘皆输，在“稳定压倒一切”的大方针下，这样的优化需要给出一个系统的策略，玩家等级、职业因素的影响都要考虑进去。</p>
		<p>2、对玩家脚本变量实现压缩存储</p>
		<p>未经压缩的脚本变量，每个大概有几十Bytes，如果采用一个好的压缩算法，能不能减少到10Bytes呢？什么又是一个好的压缩算法呢？压缩解压缩的成本和直接存取成本比起来哪个更高呢？想想这些的确也都是问题呢。</p>
		<p>
				<font color="#008000">/*****************************************************************************<br />  这只是我工作中的一个总结，问题很简单，也很琐碎，正如我前面所提的，仅仅是提供一个参考。<br />*****************************************************************************/</font>
		</p>
<img src ="http://www.cppblog.com/Fox/aggbug/38779.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Fox/" target="_blank">Fox</a> 2007-12-17 19:55 <a href="http://www.cppblog.com/Fox/archive/2007/12/17/script_variable_optimize.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MMORPG中游戏世界的构建</title><link>http://www.cppblog.com/Fox/archive/2007/12/16/game_world_architecture.html</link><dc:creator>Fox</dc:creator><author>Fox</author><pubDate>Sat, 15 Dec 2007 21:24:00 GMT</pubDate><guid>http://www.cppblog.com/Fox/archive/2007/12/16/game_world_architecture.html</guid><wfw:comment>http://www.cppblog.com/Fox/comments/38600.html</wfw:comment><comments>http://www.cppblog.com/Fox/archive/2007/12/16/game_world_architecture.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/Fox/comments/commentRss/38600.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Fox/services/trackbacks/38600.html</trackback:ping><description><![CDATA[
		<p>Author: Fox(<a href="mailto:yulefox@126.com">yulefox@126.com</a>)<br /><span><br />一个</span><span>MMORPG</span><span>（</span><span>Massively Multiplayer Online Role Playing Game</span><span>）的架构包含客户端和服务器两部分。客户端主要涉及计算机图形学、物理学、多媒体技术等，服务器主要涉及网络通信技术、数据库技术，而人工智能、操作系统等计算机基础学科知识的应用体现在</span><span>MMORPG</span><span>开发过程中的方方面面。</span></p>
		<p>
				<span>一、游戏世界的划分</span>
		</p>
		<p>
				<span>理想状态的游戏世界仅由一个完整的场景组成，在《魔兽争霸</span>
				<span>III</span>
				<span>》、《</span>
				<span>CS</span>
				<span>》这样的单机游戏中，所有玩家位于该场景中，在理论上，位于该场景中的任意玩家都可以看到游戏中所有玩家并与之交互，出于公平性和游戏性（而不是技术上）的考虑，游戏中并不会这样做。</span>
		</p>
		<p>
				<span>然而，目前的</span>
				<span>MMORPG</span>
				<span>中，几乎没有任何一款可以做到整个游戏世界只包含一个场景，因为在一款</span>
				<span>MMORPG</span>
				<span>中，同时在线的玩家数量成百上千，甚至是数万人同时在一个游戏世界中交互。以现在的网络技术和计算机系统，还无法为这么多玩家的交互提供即时处理。因此，</span>
				<span>MMORPG</span>
				<span>的游戏世界被划分为大小不等、数量众多的场景，游戏服务器对于这些场景的处理分为分区和无缝两种。</span>
		</p>
		<p>
				<span>在分区式服务器中，一个场景中的玩家无法看到另一个场景中的玩家，当玩家从一个场景到另外一个场景跨越时，都有一个数据转移和加载的过程（尤其是从一个分区服务器跨越到另外一个服务器时），玩家都有一个等待的时间，在这段时间内，服务器的主要工作是实现跨越玩家数据的转移和加载以及后一个场景中玩家、</span>
				<span>NPC</span>
				<span>等数据的传输，客户端的主要工作是实现新场景资源的加载和服务器通信。主要时间的长短主要取决于后一个场景中资源数据的大小。分区式服务器的优点主要是各分区服务器保持相对独立，缺点是游戏空间不够大，而且，一旦某个分区服务器中止服务，位于该服务器上的所有玩家将失去连接。</span>
		</p>
		<p>
				<span>所谓无缝服务器，玩家几乎察觉不到场景之间的这种切换，在场景间没有物理上的屏障，对于玩家而言，众多场景构成了一个巨大的游戏世界。场景之间，甚至服务器之间“没有了”明确的界线。因此，无缝服务器为玩家提供了更大的游戏空间和更友好的交互，实现了动态边界的无缝服务器甚至可以在某个服务器中止服务时，按一定策略将负载动态分散到其他服务器。因此，无缝服务器在技术上要比分区服务器更加复杂。</span>
		</p>
		<p>
				<span>目前国内上市的</span>
				<span>MMORPG</span>
				<span>，大多采用分区式服务器，做到无缝世界的主要有《完美世界》和《天下贰》等，国外的</span>
				<span>MMORPG</span>
				<span>中，像《魔兽世界》、《</span>
				<span>EVE</span>
				<span>》等，都实现了无缝世界。</span>
		</p>
		<p>
				<span>无缝服务器与分区式服务器在技术上的主要区别是，当位于场景</span>
				<span>S1</span>
				<span>中的玩家</span>
				<span>P1</span>
				<span>处于两个（甚至更多）场景</span>
				<span>S1</span>
				<span>、</span>
				<span>S2</span>
				<span>的边界区域内时，要保证</span>
				<span>P1</span>
				<span>能够看到场景</span>
				<span>S2</span>
				<span>中建筑、玩家、</span>
				<span>NPC</span>
				<span>等可感知对象。而且边界区域的大小要大于等于</span>
				<span>P1</span>
				<span>可感知的范围，否则就可能发生</span>
				<span>S2</span>
				<span>中的可感知对象突然闪现在</span>
				<span>P1</span>
				<span>视野中的异常。</span>
		</p>
		<p>
				<span>无疑，无缝世界为玩家提供了更人性化和更具魅力的用户体验。</span>
		</p>
		<p>
				<span>二、无缝世界游戏服务器的整体架构</span>
		</p>
		<p>
				<span>MMORPG</span>
				<span>的服务器架构从功能上主要划分为三种：</span>
		</p>
		<p>
				<span>
						<span>1、</span>
				</span>
				<span>登录服务器（</span>
				<span>Login Server</span>
				<span>）</span>
		</p>
		<p>
				<span>登录服务器用于玩家验证登录，并根据系统记录玩家信息得到其所在节点服务器，并通过世界服务器为登录玩家和对应节点服务器建立连接。</span>
		</p>
		<p>
				<span>
						<span>2、</span>
				</span>
				<span>世界服务器（</span>
				<span>World Server</span>
				<span>）</span>
		</p>
		<p>
				<span>世界服务器将整个游戏世界划分成不同场景，将所有场景按一定策略分配给节点服务器，并对节点服务器进行管理。世界服务器的另一功能是与登录服务器交互。因此，世界服务器是登录服务器、节点服务器的沟通桥梁，当然，一旦玩家登录成功，世界服务器将主要处理节点服务器间的通信。因此，世界服务器对于玩家是透明的。</span>
		</p>
		<p>
				<span>
						<span>3、</span>
				</span>
				<span>节点服务器（</span>
				<span>Node Server</span>
				<span>）</span>
		</p>
		<p>
				<span>节点服务器负责管理位于该节点的所有玩家、</span>
				<span>NPC</span>
				<span>的所有交互，在无缝世界游戏中，由于边界区域的存在，一个节点服务器甚至要处理相邻节点上位于边界区域的玩家和</span>
				<span>NPC</span>
				<span>的信息。</span>
		</p>
		<p>
				<span>在具体实现上，不同的</span>
				<span>MMORPG</span>
				<span>为了便于管理，可能还会具有</span>
				<span>AI</span>
				<span>服务器、日志服务器、数据库缓存服务器、代理服务器等。</span>
		</p>
		<p>
				<span>
						<span>三、</span>
				</span>
				<span>无缝世界游戏服务器的主要技术需求</span>
		</p>
		<p>
				<span>
						<span>1、</span>
				</span>
				<span>编程语言（</span>
				<span>C/C++</span>
				<span>、</span>
				<span>SQL</span>
				<span>、</span>
				<span>Lua</span>
				<span>、</span>
				<span>Python</span>
				<span>）</span>
		</p>
		<p>
				<span>
						<span>2、</span>
				</span>
				<span>图形库（</span>
				<span>Direct 3D</span>
				<span>、</span>
				<span>OpenGL</span>
				<span>）</span>
		</p>
		<p>
				<span>
						<span>3、</span>
				</span>
				<span>网络通信（</span>
				<span>WinSock</span>
				<span>、</span>
				<span>BSD Socket</span>
				<span>，或者</span>
				<span>ACE</span>
				<span>）</span>
		</p>
		<p>
				<span>
						<span>4、</span>
				</span>
				<span>消息、事件、多线程、</span>
				<span>GUI</span>
		</p>
		<p>
				<span>
						<span>5、</span>
				</span>
				<span>OS</span>
		</p>
		<p>
				<span>三、无缝世界游戏服务器需要解决的主要问题</span>
		</p>
		<p>
				<span>
						<span>1、</span>
				</span>
				<span>资源管理</span>
		</p>
		<p>
				<span>无论是服务器还是客户端，都涉及到大量资源：玩家数据、</span>
				<span>NPC</span>
				<span>数据、战斗公式、模型资源、通信资源等。当这些资源达到一定规模，其管理的难度不可忽视。而且，资源管理的好坏，直接关系到游戏的安全和生命。</span>
		</p>
		<p>
				<span>
						<span>2、</span>
				</span>
				<span>网络安全</span>
		</p>
		<p>
				<span>安全永远是第一位的，我们无法指望所有的玩家及其所持的客户端永远是友好的。事实上，威胁到游戏的公平性和安全性的大多数问题，归根结底，都是由于网络通信中存在的欺骗和攻击造成的，这些问题包含但不限于交易欺骗、物品复制。</span>
		</p>
		<p>
				<span>
						<span>3、</span>
				</span>
				<span>逻辑安全</span>
		</p>
		<p>
				<span>逻辑安全按理说应该是游戏中最基本的考虑，覆盖的范围也最广最杂。随机数系统是一个非常值得重视的问题，随机数不仅仅用于玩家可见的一些任务系统、战斗公式、人工智能、物品得失等，还可用于网络报文加密等。因此，随机数系统本身的安全不容忽视。另外一个常见的逻辑安全是玩家的移动，最主要的就是防止加速齿轮这样的变态操作。</span>
		</p>
		<p>
				<span>
						<span>4、</span>
				</span>
				<span>负载均衡</span>
		</p>
		<p>
				<span>MMORPG</span>
				<span>中的负载均衡包括客户端及服务器资源管理和逻辑处理的负载均衡，其中最难预知的是网络通信的负载均衡，正常情况下的网络通信数量是可以在游戏设计时做出评估的，但因恶意攻击造成的网络负载是无法预测的。因此，负载均衡所要处理的主要是实时动态负载均衡和灾难恢复。负载均衡需要解决的问题包括负载监控、负载分析、负载分发和灾难恢复。</span>
		</p>
		<p>
				<span>
						<span>5、</span>
				</span>
				<span>录像系统</span>
		</p>
		<p>
				<span>录像系统的构建，主要用于重现关键数据的输入输出，如玩家交易、玩家充值，或者当</span>
				<span>bug</span>
				<span>出现后，为逻辑服务器（泛指上文提到的所有类型服务器，主要是节点服务器）相应部分启动录像系统。待收集到足够数据后，通过录像系统重现</span>
				<span>bug</span>
				<span>。为了使逻辑服务器不受自身时间（如中断调试等）的影响，还可以专门设计心跳服务器来控制数据传输。</span>
		</p>
		<p>
				<span>四、总结</span>
		</p>
		<p>
				<span>在</span>
				<span>MMORPG</span>
				<span>中，真正的</span>
				<span>bug</span>
				<span>永远存在于将来。从这一点出发，关于</span>
				<span>MMORPG</span>
				<span>中游戏世界的构建，怎样苛刻的思考都不为过。<br /><br />参考资料：</span>
		</p>
		<p>
				<span>1、 [美] Kim Pallister编, 孟宪武 等译. 游戏编程精粹5, P467-474, P516. 人民邮电出版社, 2007年9月. 北京.<br />2、 [美] Thor Alexander编, 史晓明 译. 大型多人在线游戏开发, P174-185. 人民邮电出版社, 2006年12月. 北京.<br />3、 [美] Dante Treglia编, 张磊 译. 游戏编程精粹3, P117-122. 人民邮电出版社, 2003年7月. 北京.<br />4、 [美] Mark DeLoura编, 王淑礼 等译. 游戏编程精粹1, P90-93. 人民邮电出版社, 2004年10月. 北京.<br />5、 [美] Douglas 等著, 於春景 译. C++网络编程 卷1. 中国电力出版社, 2004年11月. 北京.<br />6、 [美] Stephen D. Huston 等著, 马维达 译. ACE程序员指南. 中国电力出版社, 2004年11月. 北京.<br />7、 [美] Erich Gamma等著, 李英军 等译. 设计模式. 机械工业出版社, 2000年6月. 北京.<br />8、 游戏引擎全剖析. <a href="http://bbs.gameres.com/showthread.asp?threadid=101293">http://bbs.gameres.com/showthread.asp?threadid=101293</a>.<br />9、 服务器结构探讨：登录服的负载均衡. <a href="http://gamedev.csdn.net/page/351491d0-05ad-48a4-85e1-77870bc1eef3">http://gamedev.csdn.net/page/351491d0-05ad-48a4-85e1-77870bc1eef3</a>.<br />10、服务器结构探讨：最终的结构. <a href="http://gamedev.csdn.net/page/28695655-974c-4291-8ac4-2589c4e770d3">http://gamedev.csdn.net/page/28695655-974c-4291-8ac4-2589c4e770d3</a>.<br />11、谈谈网络游戏服务器解决方案. <a href="http://www.beareyes.com.cn/2/lib/200411/08/20041108102.htm">http://www.beareyes.com.cn/2/lib/200411/08/20041108102.htm</a>.<br />12、负载均衡——大型在线系统实现的关键(下篇)（服务器集群架构的设计与选择）. <a href="http://blog.csdn.net/sodme/archive/2005/06/15/394576.aspx">http://blog.csdn.net/sodme/archive/2005/06/15/394576.aspx</a>.<br />13、云风的BLOG. <a href="http://blog.codingnow.com/">http://blog.codingnow.com/</a><br /></span>
		</p>
		<span style="COLOR: #008000">/*****************************************************************************<br />  从0:00到5:00，在写这篇随笔的过程中，我翻找、点击着上面的这些资料，其实还有更<br />  多的资料，没有记在上面，算是为开题做的准备。现在依然是睡意全无。越写越觉得<br />  不够，越想越觉得还有更多东西写不出来……<br />  PS：这些资料大都不是第一次翻，以前看这些资料大多只是单纯的看，现在有目的的<br />  看，才觉得都写得很有味道。不管是不是同意所有观点，都不是本文讨论的重点。<br />*****************************************************************************/</span>
<img src ="http://www.cppblog.com/Fox/aggbug/38600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Fox/" target="_blank">Fox</a> 2007-12-16 05:24 <a href="http://www.cppblog.com/Fox/archive/2007/12/16/game_world_architecture.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>