<?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; 游戏</title>
	<atom:link href="http://software.intel.com/zh-cn/blogs/category/gaming/feed/" rel="self" type="application/rss+xml" />
	<link>http://software.intel.com/zh-cn/blogs</link>
	<description></description>
	<lastBuildDate>Sun, 12 Feb 2012 07:12:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Amazed 游戏学习二 坐标的分析</title>
		<link>http://software.intel.com/zh-cn/blogs/2012/01/13/amazed/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2012/01/13/amazed/#comments</comments>
		<pubDate>Fri, 13 Jan 2012 08:33:05 +0000</pubDate>
		<dc:creator>gaomatrix</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2012/01/13/amazed/</guid>
		<description><![CDATA[对于这种和贪吃蛇类似的游戏，坐标的计算在程序中占了很大的比重，只有坐标算对了，才能在正确的时间、正确的地点画出来正确的东西。 下面是Maze迷宫的坐标计算 01.// maze level data 02.private static int[] mMazeData; 这个一维数组存放所有的tile的类型 01.// maze tile size and dimension 02.private final static int TILE_SIZE = 16; 03.private final static int MAZE_COLS = 20; 04.private final static int MAZE_ROWS = 26; 01.// tile types 02.public final static int PATH_TILE = 0; 03.public final static int VOID_TILE = 1;//death [...]]]></description>
			<content:encoded><![CDATA[<p>对于这种和贪吃蛇类似的游戏，坐标的计算在程序中占了很大的比重，只有坐标算对了，才能在正确的时间、正确的地点画出来正确的东西。</p>
<p>下面是Maze迷宫的坐标计算<br />
01.// maze level data<br />
02.private static int[] mMazeData;</p>
<p>这个一维数组存放所有的tile的类型<br />
01.// maze tile size and dimension<br />
02.private final static int TILE_SIZE = 16;<br />
03.private final static int MAZE_COLS = 20;<br />
04.private final static int MAZE_ROWS = 26;</p>
<p>01.// tile types<br />
02.public final static int PATH_TILE = 0;<br />
03.public final static int VOID_TILE = 1;//death area<br />
04.public final static int EXIT_TILE = 2;//the target<br />
而这个坐标的读取是通过从文件读取的，当然也可以通过写几个数组的形式，但是以文件的形式的话就不需要修改代码就可以实现软件的修改是一种比在代码中写几个大的数组要好的形式。</p>
<p>01./**<br />
02. * Load specified maze level.<br />
03. *<br />
04. * @param activity<br />
05. * Activity controlled the maze, we use this load the level data<br />
06. * @param newLevel<br />
07. * Maze level to be loaded.<br />
08. */<br />
09. void load(Activity activity, int newLevel) {<br />
10. // maze data is stored in the assets folder as level1.txt, level2.txt<br />
11. // etc....<br />
12. String mLevel = "level" + newLevel + ".txt";<br />
13.<br />
14. InputStream is = null;<br />
15.<br />
16. try {<br />
17. // construct our maze data array.<br />
18. mMazeData = new int[MAZE_ROWS * MAZE_COLS];<br />
19. // attempt to load maze data.<br />
20. is = activity.getAssets().open(mLevel);<br />
21.<br />
22. // we need to loop through the input stream and load each tile for<br />
23. // the current maze.<br />
24. for (int i = 0; i &lt; mMazeData.length; i++) {<br />
25. // data is stored in unicode so we need to convert it.<br />
26. mMazeData[i] = Character.getNumericValue(is.read());<br />
27.<br />
28. // skip the "," and white space in our human readable file.<br />
29. is.read();<br />
30. is.read();<br />
31. }<br />
32. } catch (Exception e) {<br />
33. Log.i("Maze", "load exception: " + e);<br />
34. } finally {<br />
35. closeStream(is);<br />
36. }<br />
37. }<br />
mMazeData数组存放了每个tile是什么类型的，MAZE_ROWS一共有多少行，MAZE_COLS一共多少列，TILE_SIZE每个tile的宽度，这样就可以在界面上画出来整个界面的布局</p>
<p>01./**<br />
02. * Draw the maze.<br />
03. *<br />
04. * @param canvas<br />
05. * Canvas object to draw too.<br />
06. * @param paint<br />
07. * Paint object used to draw with.<br />
08. */<br />
09. public void draw(Canvas canvas, Paint paint) {<br />
10. // loop through our maze and draw each tile individually.<br />
11. for (int i = 0; i 0)<br />
22. mLocation = mCellRow * MAZE_COLS;<br />
23.<br />
24. // add the column location.<br />
25. mLocation += mCellCol;<br />
26.<br />
27. return mMazeData[mLocation];<br />
28. }<br />
/**<br />
* Determine which cell the marble currently occupies.<br />
*<br />
* @param x<br />
* Current x co-ordinate of marble on the screen.<br />
* @param y<br />
* Current y co-ordinate of marble on the screen.<br />
* @return The actual cell occupied by the marble.<br />
*/<br />
public int getCellType(int x, int y) {<br />
// convert the x,y co-ordinate into row and col values.<br />
int mCellCol = x / TILE_SIZE;<br />
int mCellRow = y / TILE_SIZE;</p>
<p>// location is the row,col coordinate converted so we know where in the<br />
// maze array to look.<br />
int mLocation = 0;</p>
<p>// if we are beyond the 1st row need to multiple by the number of<br />
// columns.<br />
if (mCellRow &gt; 0)<br />
mLocation = mCellRow * MAZE_COLS;</p>
<p>// add the column location.<br />
mLocation += mCellCol;</p>
<p>return mMazeData[mLocation];<br />
}下面是Marble小球的坐标计算</p>
<p>01.// marble attributes<br />
02.// x,y are private because we need boundary checking on any new values to<br />
03.// make sure they are valid.<br />
04.private int mX = 0;<br />
05.private int mY = 0;<br />
06.private int mRadius = 8;<br />
07.private int mColor = Color.WHITE;<br />
08.private int mLives = 5;</p>
<p>在AmazedView中的onDraw()调用gameTick()的时候会更新小球Marble的坐标：</p>
<p>01./**<br />
02. * Called from gameTick(), update marble x,y based on latest values obtained<br />
03. * from the Accelerometer sensor. AccelX and accelY are values received from<br />
04. * the accelerometer, higher values represent the device tilted at a more<br />
05. * acute angle.<br />
06. */<br />
07. public void updateMarble() {<br />
08. // we CAN give ourselves a buffer to stop the marble from rolling even<br />
09. // though we think the device is "flat".<br />
10. if (mAccelX &gt; mSensorBuffer || mAccelX mSensorBuffer || mAccelY 0) {<br />
19. // user still has some lives remaining, restart the level.<br />
20. mMarble.death();<br />
21. mMarble.init();<br />
22. mWarning = true;<br />
23. } else {<br />
24. // user has no more lives left, end of game.<br />
25. mEndTime = System.currentTimeMillis();<br />
26. mTotalTime += mEndTime - mStartTime;<br />
27. switchGameState(GAME_OVER);<br />
28. }<br />
29.<br />
30. } else if (mMaze.getCellType(mMarble.getX(), mMarble.getY()) == mMaze.EXIT_TILE) {<br />
31. // user has reached the exit tiles, prepare the next level.<br />
32. mEndTime = System.currentTimeMillis();<br />
33. mTotalTime += mEndTime - mStartTime;<br />
34. initLevel();<br />
35. }<br />
36. }</p>
<p>在Marble中更新小球坐标：</p>
<p>01./**<br />
02. * Attempt to update the marble with a new x value, boundary checking<br />
03. * enabled to make sure the new co-ordinate is valid.<br />
04. *<br />
05. * @param newX<br />
06. * Incremental value to add onto current x co-ordinate.<br />
07. */<br />
08. public void updateX(float newX) {<br />
09. mX += newX;<br />
10.<br />
11. // boundary checking, don't want the marble rolling off-screen.<br />
12. if (mX + mRadius &gt;= mView.getWidth())<br />
13. mX = mView.getWidth() - mRadius;<br />
14. else if (mX - mRadius &lt; 0)<br />
15. mX = mRadius;<br />
16. }</p>
<p>if-else中是对左右边界的处理，同样的是对上下边界的处理。</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2012/01/13/amazed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>八款开源 Android 游戏引擎 (巨好的资源)</title>
		<link>http://software.intel.com/zh-cn/blogs/2012/01/13/android-4/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2012/01/13/android-4/#comments</comments>
		<pubDate>Fri, 13 Jan 2012 08:30:42 +0000</pubDate>
		<dc:creator>iamsheldon</dc:creator>
				<category><![CDATA[Android 开发]]></category>
		<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2012/01/13/android-4/</guid>
		<description><![CDATA[初学Android游戏开发的朋友，往往会显得有些无所适从，他们常常不知道该从何处入手，每当遇到自己无法解决的难题时，又往往会一边羡慕于 iPhone下有诸如Cocos2d-iphone之类的免费游戏引擎可供使用，一边自暴自弃的抱怨Android平台游戏开发难度太高，又连个像样的游 戏引擎也没有，甚至误以为使用Java语言开发游戏是一件费力不讨好且没有出路的事情。 事实上，这种想法完全是没有必要且不符合实际的，作为能和苹果iOS分庭抗礼的Android（各种意义上），当然也会有相当数量的游戏引擎存在。仅仅因为我们处于这个狭小的天地间，与外界接触不够，所以对它们的存在茫然不知罢了。 下面我就罗列出八款常见的Android游戏引擎，以供有需要者参考（收费，下载量过小，不公布源码，以及鄙人不知道（-_-）的引擎不在此列）。 1、Angle Angle是一款专为Android平台设计的，敏捷且适合快速开发的2D游戏引擎，基于OpenGL ES技术开发。该引擎全部用Java代码编写，并且可以根据自己的需要替换里面的实现，缺陷在于文档不足，而且下载的代码中仅仅包含有少量的示例教程。 最低运行环境要求不详。 项目地址：http://code.google.com/p/angle/ 2、Rokon rokon是一款Android 2D游戏引擎，基于OpenGL ES技术开发，物理引擎为Box2D，因此能够实现一些较为复杂的物理效果，该项目最新版本为 2.0.3 (09/07/10)。总体来说，此引擎最大的优点在于其开发文档相当之完备，并且项目作者对反馈Bug的修正非常之神速，所以该框架的使用在目前也最为 广泛，有人干脆将它称为Cocos2d-iPhone引擎的Android版（业务逻辑和编码风格上也确实很像）。附带一提，国内某个需要注册会员才能下 载的Android游戏框架衍生于此框架，所以大家也不要刻板的认为收费便一定是好的，免费就一定不好。 最低运行环境要求为Android 1.5。 项目地址：http://code.google.com/p/rokon/ 3、LGame LGame是一款国人开发的Java游戏引擎，有Android及PC(J2SE)两个开发版本，目前最高版本同为0.2.6(31/07/10)。其底 层绘图器LGrpaphics封装有J2SE以及J2ME提供的全部Graphics API（PC版采用Graphics2D封装，Android版采用Canvas模拟实现），所以能够将J2SE或J2ME开发经验直接套用其中，两版本 间主要代码能够相互移植。Android版内置有Admob接口，可以不必配置XML直接硬编码Admob广告信息。 该引擎除了基本的音效、图形、物理、精灵等常用组件以外，也内置有Ioc、xml、http等常用Java组件的封装，代价是jar体积较为庞大，PC版 已突破1.2MB，Android版有所简化也在500KB左右。此外，该引擎还内置有按照1:1实现的J2ME精灵类及相关组件，可以将绝大多数 J2ME游戏平移到Android或PC版中。唯一遗憾的是，该项目作者是个极其懒惰的家伙，开发文档从去年说到今年依旧没有提供，只有游戏示例可供下 载。 最低运行环境要求为Android 1.1。 项目地址：http://code.google.com/p/loon-simple/ 4、AndEngine andengine同样是一款基于OpenGL ES技术的Android游戏引擎，物理引擎同样为Box2D（标配&#124;&#124;&#124;）。该框架性能普通，文档缺乏，但示例较为丰富。 下载地址（未直接提供jar下载，源码可通过svn提取）：http://code.google.com/p/andengine/ 最低运行环境要求不详。 项目地址：http://code.google.com/p/rokon/ 5、libgdx libgdx是一款基于OpenGL ES技术开发的Android游戏引擎，支持Android平台下的2D游戏开发，物理引擎采用Box2D实现。单就性能角度来说，堪称是一款非常强大的 Android游戏引擎，但缺陷在于精灵类等相关组件在使用上不够简化，而且文档也较为匮乏。 最低运行环境要求不详。 项目地址：http://code.google.com/p/libgdx/ 6、jPCT jPCT是一款基于OpenGL技术开发的3D图形引擎(PC环境为标准OpenGL，Android为OpenGL ES)， 以Java语言为基础的，拥有功能强大的Java 3D解决方案。该引擎与LGame（此为2D游戏引擎）相类似，目前拥有PC(J2SE)以及Android两个开发版本。 jPCT的最大优势之一，就在于它惊人的向下兼容性。在PC环境中，jPCT甚至可以运行在JVM1.1环境之中，因为jPCT内部提供的图形渲染接口完 全符合所有的Java 1.1规范（就连已经消失的Microsoft VM乃至更古老的Netscape 4 [...]]]></description>
			<content:encoded><![CDATA[<p>初学Android游戏开发的朋友，往往会显得有些无所适从，他们常常不知道该从何处入手，每当遇到自己无法解决的难题时，又往往会一边羡慕于 iPhone下有诸如Cocos2d-iphone之类的免费游戏引擎可供使用，一边自暴自弃的抱怨Android平台游戏开发难度太高，又连个像样的游 戏引擎也没有，甚至误以为使用Java语言开发游戏是一件费力不讨好且没有出路的事情。</p>
<p>事实上，这种想法完全是没有必要且不符合实际的，作为能和苹果iOS分庭抗礼的Android（各种意义上），当然也会有相当数量的游戏引擎存在。仅仅因为我们处于这个狭小的天地间，与外界接触不够，所以对它们的存在茫然不知罢了。</p>
<p>下面我就罗列出八款常见的Android游戏引擎，以供有需要者参考（收费，下载量过小，不公布源码，以及鄙人不知道（-_-）的引擎不在此列）。<br />
1、Angle</p>
<p>Angle是一款专为Android平台设计的，敏捷且适合快速开发的2D游戏引擎，基于OpenGL ES技术开发。该引擎全部用Java代码编写，并且可以根据自己的需要替换里面的实现，缺陷在于文档不足，而且下载的代码中仅仅包含有少量的示例教程。</p>
<p>最低运行环境要求不详。</p>
<p>项目地址：<a href="http://code.google.com/p/angle/">http://code.google.com/p/angle/ </a><br />
2、Rokon</p>
<p>rokon是一款Android 2D游戏引擎，基于OpenGL ES技术开发，物理引擎为Box2D，因此能够实现一些较为复杂的物理效果，该项目最新版本为 2.0.3 (09/07/10)。总体来说，此引擎最大的优点在于其开发文档相当之完备，并且项目作者对反馈Bug的修正非常之神速，所以该框架的使用在目前也最为 广泛，有人干脆将它称为Cocos2d-iPhone引擎的Android版（业务逻辑和编码风格上也确实很像）。附带一提，国内某个需要注册会员才能下 载的Android游戏框架衍生于此框架，所以大家也不要刻板的认为收费便一定是好的，免费就一定不好。</p>
<p>最低运行环境要求为Android 1.5。</p>
<p>项目地址：<a href="http://code.google.com/p/rokon/">http://code.google.com/p/rokon/</a></p>
<p>3、LGame</p>
<p>LGame是一款国人开发的Java游戏引擎，有Android及PC(J2SE)两个开发版本，目前最高版本同为0.2.6(31/07/10)。其底 层绘图器LGrpaphics封装有J2SE以及J2ME提供的全部Graphics API（PC版采用Graphics2D封装，Android版采用Canvas模拟实现），所以能够将J2SE或J2ME开发经验直接套用其中，两版本 间主要代码能够相互移植。Android版内置有Admob接口，可以不必配置XML直接硬编码Admob广告信息。</p>
<p>该引擎除了基本的音效、图形、物理、精灵等常用组件以外，也内置有Ioc、xml、http等常用Java组件的封装，代价是jar体积较为庞大，PC版 已突破1.2MB，Android版有所简化也在500KB左右。此外，该引擎还内置有按照1:1实现的J2ME精灵类及相关组件，可以将绝大多数 J2ME游戏平移到Android或PC版中。唯一遗憾的是，该项目作者是个极其懒惰的家伙，开发文档从去年说到今年依旧没有提供，只有游戏示例可供下 载。</p>
<p>最低运行环境要求为Android 1.1。</p>
<p>项目地址：<a href="http://code.google.com/p/loon-simple/">http://code.google.com/p/loon-simple/</a></p>
<p>4、AndEngine</p>
<p>andengine同样是一款基于OpenGL ES技术的Android游戏引擎，物理引擎同样为Box2D（标配|||）。该框架性能普通，文档缺乏，但示例较为丰富。</p>
<p>下载地址（未直接提供jar下载，源码可通过svn提取）：http://code.google.com/p/andengine/</p>
<p>最低运行环境要求不详。</p>
<p>项目地址：<a href="http://code.google.com/p/rokon/">http://code.google.com/p/rokon/ </a><br />
5、libgdx</p>
<p>libgdx是一款基于OpenGL ES技术开发的Android游戏引擎，支持Android平台下的2D游戏开发，物理引擎采用Box2D实现。单就性能角度来说，堪称是一款非常强大的 Android游戏引擎，但缺陷在于精灵类等相关组件在使用上不够简化，而且文档也较为匮乏。</p>
<p>最低运行环境要求不详。</p>
<p>项目地址：<a href="http://code.google.com/p/libgdx/">http://code.google.com/p/libgdx/ </a><br />
6、jPCT</p>
<p>jPCT是一款基于OpenGL技术开发的3D图形引擎(PC环境为标准OpenGL，Android为OpenGL ES)， 以Java语言为基础的，拥有功能强大的Java 3D解决方案。该引擎与LGame（此为2D游戏引擎）相类似，目前拥有PC(J2SE)以及Android两个开发版本。</p>
<p>jPCT的最大优势之一，就在于它惊人的向下兼容性。在PC环境中，jPCT甚至可以运行在JVM1.1环境之中，因为jPCT内部提供的图形渲染接口完 全符合所有的Java 1.1规范（就连已经消失的Microsoft VM乃至更古老的Netscape 4 VM也不例外）。</p>
<p>最低运行环境要求为Android 1.5。</p>
<p>项目地址：<a href="http://www.jpct.net/jpct-ae/">http://www.jpct.net/jpct-ae/ </a><br />
7、Alien3d</p>
<p>Alien3d是一款体积非常之小的Android 3D游戏引擎，基于OpenGL ES技术开发。为了压缩体积，它根据不同功能采用多jar方式发布（包括alien3d-engine.jar，alien3d- tiled.jar，alien3d-sprites.jar，alien3d-shapes.jar，alien3d- particles2d.jar，），事实上它的核心文件大约只有40KB，所有相关jar的总和也不足150KB。</p>
<p>最低运行环境要求为Android 1.5。</p>
<p>项目地址：<a href="http://code.google.com/p/alien3d/">http://code.google.com/p/alien3d/ </a><br />
8、Catcake</p>
<p>Catcake是一款跨平台的Java 3D图形引擎，目前支持PC(J2SE)及Android环境运行（已有iPhone版规划）。该引擎在易用性和运行性能上皆有出色的表现，支持常见的游戏开发功能，诸如精灵动画，音频处理和视频播放等。</p>
<p>最低运行环境要求为Android 1.6。</p>
<p>项目地址：<a href="http://code.google.com/p/catcake/">http://code.google.com/p/catcake/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2012/01/13/android-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>案例研究:使用英特尔GPA优化《兵王》游戏的性能</title>
		<link>http://software.intel.com/zh-cn/blogs/2012/01/06/gpa-3/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2012/01/06/gpa-3/#comments</comments>
		<pubDate>Fri, 06 Jan 2012 07:59:46 +0000</pubDate>
		<dc:creator>Cage Lu (Intel)</dc:creator>
				<category><![CDATA[图形和视觉计算]]></category>
		<category><![CDATA[游戏]]></category>
		<category><![CDATA[GPA]]></category>
		<category><![CDATA[性能优化]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2012/01/06/gpa-3/</guid>
		<description><![CDATA[作者：英特尔：卢卷彬, Kiefer Kuah 巨人：余娜娜 下载PDF版本：使用英特尔GPA优化《兵王》游戏的性能 1. 介绍 《兵王》是由巨人网络公司旗下，上海巨贤公司耗时两年自主研发的一款未来战争MMORGP。《兵王》使用了优秀的3D引擎技术，在声光特效方面有极其优秀的表现。为了使《兵王》能够流畅的运行在更多玩家的机器上，我们在英特尔 集成显卡上对游戏进行了优化。英特尔集成显卡的出货量非常大，超过了60%（Q3’2011, Jon Peddie Research统计），其性能和特性也日益增强，是游戏开发者应该重点关注的对象。为了帮助游戏开发者在英特尔集成显卡上优化游戏性能，英特尔推出了一款出色的免费的性能分析工具，英特尔图形性能分析器(Graphics Performance Analyzers, 简称GPA)，不用修改游戏的代码，不用安装特殊的驱动版本就能够使用。游戏开发者可以利用这个工具清晰的了解自己的游戏在什么地方耗费了更多的时间，以进行有针对性的优化。GPA是我们在这次优化中使用的主要工具。 2. 优化准备 以下的分析和优化基于Intel HD Graphics 3000硬件平台，代号Sandybridge(简称SNB)，SNB拥有出色的图形性能，完全可以满足绝大多数网络游戏对性能的需求。我们使用的操作系统为Windows 7， 64位版本，GPA版本为4.2。 关于优化场景的选择，《兵王》支持大规模的群体作战，开发者对这种场景下的游戏性能特别关注，所以我们选择的是以下的一个群体战斗场景，其中有~100个玩家，并且有大量的武器和技能特效，游戏的性能在这个时候遇到很大的挑战，只有10fps左右，如图1所示： 图1，性能分析和优化的目标场景，有~100个玩家和坐骑，大量的技能特效，fps为10左右 3. GPA系统分析器HUD GPA HUD可以从平台的角度分析游戏的性能，它提供了超过80个关于CPU，D3D runtime和GPU的性能指标，以及Null Hardware，Disable all draw calls， 1x1 ScissorRect， 2x2 Texture，Simple Pixel Shader等覆盖模式，收集这些性能指标和覆盖模式得到的数据，可以帮助我们分析出游戏的瓶颈所在。使用GPA HUD分析游戏的这个场景后我们得到以下的结果： 游戏在该场景下，FPS只能维持在10左右，此时的Null Hardware 和Null Driver覆盖模式分别只能达到14fps和20fps左右，也就是说显卡无限快的时候，游戏也只能跑到14fps，因此游戏在CPU上的性能消耗非常大。游戏有7800多个draw calls，这个一个非常大的数字。大量的draw calls，会导致游戏程序，D3D runtime以及显卡驱动等这些CPU上的计算量增加，由此导致性能非常的低。所以，游戏在这个场景中的优化重点，应该是合并小的画图操作，减少draw calls和State Changes的数量，这样可以同时减少CPU和GPU上的负担。 4. GPA帧分析器 GPA可以抓取游戏的一帧数据，然后使用帧分析器进行离线的详细分析。帧分析器打开一帧的过程，就相当于是重新发送指令让GPU渲染出这一帧。帧分析器界面主要包含上部分的柱状图(A)，它们代表的是游戏中按照调用顺序排列的Clear， Draw Primitive，StretchRect等，我们统称为ergs，可以通过设置X轴和Y轴来快速的定位最耗时的调用，比如X轴设为GPU [...]]]></description>
			<content:encoded><![CDATA[<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-family: Times New Roman;font-size: small">作者：</span>英特尔：卢卷彬<span style="font-family: Calibri">, Kiefer Kuah </span>巨人：余娜娜<strong> </strong></p>
<p><span style="font-family: Times New Roman;font-size: small">下载PDF版本：<strong><a title="下载" href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/TheKingofSoldier-game-optimize-case-study.pdf">使用英特尔GPA优化《兵王》游戏的性能</a></strong></span></p>
<p><strong><span style="font-family: Calibri;font-size: small"> </span></strong></p>
<h1><strong><span style="font-family: Calibri;font-size: small">1.</span> </strong><span style="font-size: small"><strong>介绍</strong><strong> </strong></span></h1>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">《兵王》是由巨人网络公司旗下，上海巨贤公司耗时两年自主研发的一款未来战争<span style="font-family: Calibri">MMORGP</span>。《兵王》使用了优秀的<span style="font-family: Calibri">3D</span>引擎技术，在声光特效方面有极其优秀的表现。为了使《兵王》能够流畅的运行在更多玩家的机器上，我们在英特尔<span style="font-family: Calibri"> </span>集成显卡上对游戏进行了优化。英特尔集成显卡的出货量非常大，超过了<span style="font-family: Calibri">60%</span>（<span style="font-family: Calibri">Q3’2011, Jon Peddie Research</span>统计），其性能和特性也日益增强，是游戏开发者应该重点关注的对象。为了帮助游戏开发者在英特尔集成显卡上优化游戏性能，英特尔推出了一款出色的免费的性能分析工具，英特尔图形性能分析器<span style="font-family: Calibri">(Graphics Performance Analyzers, </span>简称<span style="font-family: Calibri">GPA)</span>，不用修改游戏的代码，不用安装特殊的驱动版本就能够使用。游戏开发者可以利用这个工具清晰的了解自己的游戏在什么地方耗费了更多的时间，以进行有针对性的优化。<span style="font-family: Calibri">GPA</span>是我们在这次优化中使用的主要工具。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h1><strong><span style="font-family: Calibri;font-size: small">2.</span> </strong><span style="font-size: small"><strong>优化准备</strong><strong> </strong></span></h1>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">以下的分析和优化基于<span style="font-family: Calibri">Intel HD Graphics 3000</span>硬件平台，代号<span style="font-family: Calibri">Sandybridge(</span>简称<span style="font-family: Calibri">SNB)</span>，<span style="font-family: Calibri">SNB</span>拥有出色的图形性能，完全可以满足绝大多数网络游戏对性能的需求。我们使用的操作系统为<span style="font-family: Calibri">Windows 7</span>，<span style="font-family: Calibri"> 64</span>位版本，<span style="font-family: Calibri">GPA</span>版本为<span style="font-family: Calibri">4.2</span>。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">关于优化场景的选择，《兵王》支持大规模的群体作战，开发者对这种场景下的游戏性能特别关注，所以我们选择的是以下的一个群体战斗场景，其中有<span style="font-family: Calibri">~100</span>个玩家，并且有大量的武器和技能特效，游戏的性能在这个时候遇到很大的挑战，只有<span style="font-family: Calibri">10fps</span>左右，如图<span style="font-family: Calibri">1</span>所示：</span></p>
<p><span style="font-size: small"><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw1.png"><img class="alignnone size-full wp-image-400009644" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw1.png" alt="" width="561" height="351" /></a></span><strong><span style="font-size: small"><span style="font-family: Calibri"> </span></span></strong></p>
<h6><strong>图1，性能分析和优化的目标场景，有</strong><strong><span style="font-family: Calibri">~100</span></strong><strong>个玩家和坐骑，大量的技能特效，</strong><strong><span style="font-family: Calibri">fps</span></strong><strong>为</strong><strong><span style="font-family: Calibri">10</span></strong><strong>左右</strong><strong> </strong></h6>
<p><strong><span style="font-family: Calibri;font-size: small"><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw2.png"></a></span></strong></p>
<h1><strong><span style="font-family: Calibri;font-size: small">3.</span> </strong><span style="font-size: small"><strong><span style="font-family: Calibri">GPA</span></strong><strong>系统分析器</strong><strong><span style="font-family: Calibri">HUD</span></strong></span></h1>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><span style="font-family: Calibri">GPA HUD</span>可以从平台的角度分析游戏的性能，它提供了超过<span style="font-family: Calibri">80</span>个关于<span style="font-family: Calibri">CPU</span>，<span style="font-family: Calibri">D3D runtime</span>和<span style="font-family: Calibri">GPU</span>的性能指标，以及<span style="font-family: Calibri">Null Hardware</span>，<span style="font-family: Calibri">Disable all draw calls</span>，<span style="font-family: Calibri"> 1x1 ScissorRect</span>，<span style="font-family: Calibri"> 2x2 Texture</span>，<span style="font-family: Calibri">Simple Pixel Shader</span>等覆盖模式，收集这些性能指标和覆盖模式得到的数据，可以帮助我们分析出游戏的瓶颈所在。使用<span style="font-family: Calibri">GPA HUD</span>分析游戏的这个场景后我们得到以下的结果：</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">游戏在该场景下，<span style="font-family: Calibri">FPS</span>只能维持在<span style="font-family: Calibri">10</span>左右，此时的<span style="font-family: Calibri">Null Hardware </span>和<span style="font-family: Calibri">Null Driver</span>覆盖模式分别只能达到<span style="font-family: Calibri">14fps</span>和<span style="font-family: Calibri">20fps</span>左右，也就是说显卡无限快的时候，游戏也只能跑到<span style="font-family: Calibri">14fps</span>，因此游戏在<span style="font-family: Calibri">CPU</span>上的性能消耗非常大。游戏有<span style="font-family: Calibri">7800</span>多个<span style="font-family: Calibri">draw calls</span>，这个一个非常大的数字。大量的<span style="font-family: Calibri">draw calls</span>，会导致游戏程序，<span style="font-family: Calibri">D3D runtime</span>以及显卡驱动等这些<span style="font-family: Calibri">CPU</span>上的计算量增加，由此导致性能非常的低。所以，游戏在这个场景中的优化重点，应该是合并小的画图操作，减少<span style="font-family: Calibri">draw calls</span>和<span style="font-family: Calibri">State Changes</span>的数量，这样可以同时减少<span style="font-family: Calibri">CPU</span>和<span style="font-family: Calibri">GPU</span>上的负担。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h1><strong><span style="font-family: Calibri;font-size: small">4.</span> </strong><span style="font-size: small"><strong><span style="font-family: Calibri">GPA</span></strong><strong>帧分析器</strong><strong> </strong></span></h1>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><span style="font-family: Calibri">GPA</span>可以抓取游戏的一帧数据，然后使用帧分析器进行离线的详细分析。帧分析器打开一帧的过程，就相当于是重新发送指令让<span style="font-family: Calibri">GPU</span>渲染出这一帧。帧分析器界面主要包含上部分的柱状图<span style="font-family: Calibri">(A)</span>，它们代表的是游戏中按照调用顺序排列的<span style="font-family: Calibri">Clear</span>，<span style="font-family: Calibri"> Draw Primitive</span>，<span style="font-family: Calibri">StretchRect</span>等，我们统称为<span style="font-family: Calibri">ergs</span>，可以通过设置<span style="font-family: Calibri">X</span>轴和<span style="font-family: Calibri">Y</span>轴来快速的定位最耗时的调用，比如<span style="font-family: Calibri">X</span>轴设为<span style="font-family: Calibri">GPU Duration</span>，<span style="font-family: Calibri">Y</span>轴设为<span style="font-family: Calibri">GPU Breakdown</span>。界面左边中间<span style="font-family: Calibri">(B)</span>是所有<span style="font-family: Calibri">ergs</span>的列表，左边下面<span style="font-family: Calibri">(C)</span>是<span style="font-family: Calibri">Render Target</span>，右边下面<span style="font-family: Calibri">(D)</span>是一系列<span style="font-family: Calibri">Tab</span>，包括性能数据，<span style="font-family: Calibri">ergs</span>的纹理，<span style="font-family: Calibri">shader</span>，<span style="font-family: Calibri">state</span>，<span style="font-family: Calibri">API log</span>等等。我们在目标场景中抓取了一帧数据，下图<span style="font-family: Calibri">2</span>是使用帧分析器打开这帧数据的界面：</span><span style="font-size: small"><span style="font-family: Calibri"> </span></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> <span style="font-family: Calibri;font-size: small"><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw2.png"><img class="alignnone size-full wp-image-400009645" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw2.png" alt="" width="672" height="376" /></a></span></span></p>
<h6><strong>图</strong><strong><span style="font-family: Calibri">2</span></strong><strong>，帧分析器打开场景的界面</strong><strong> </strong></h6>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-family: Calibri;font-size: small"> </span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">从图<span style="font-family: Calibri">2</span>所示的帧分析器界面我们可以看出，渲染这一帧<span style="font-family: Calibri">GPU</span>花费的时间为<span style="font-family: Calibri">71ms</span>。游戏的渲染步骤是先生成阴影贴图（<span style="font-family: Calibri">0-1198</span>），然后是正常场景的渲染，最后是后处理以及<span style="font-family: Calibri">UI</span>部分。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">阴影贴图使用了<span style="font-family: Calibri">1198</span>个<span style="font-family: Calibri">draw calls</span>，通过<span style="font-family: Calibri">GPA</span>帧分析器的纹理<span style="font-family: Calibri">tab</span>可以查看这些<span style="font-family: Calibri">draw calls</span>所使用的纹理，我们发现，游戏对某些特效也计算了阴影：</span><span style="font-size: small"><span style="font-family: Calibri"> </span></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> <a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw3.png"><img src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw3.png" alt="" width="634" height="150" /></a></span></p>
<h6><strong>图</strong><strong><span style="font-family: Calibri">3</span></strong><strong>，生成阴影贴图的</strong><strong><span style="font-family: Calibri">draw calls</span></strong><strong>中，发现了特效的纹理，游戏对特效也计算了阴影</strong><strong> </strong></h6>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">如图<span style="font-family: Calibri">3</span>所示，选中的那个纹理，以及相邻的纹理，都是特效相关的，而游戏设计之初并没有要求计算它们的阴影，可以移除掉。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">另外，游戏花费了<span style="font-family: Calibri">5526</span>个<span style="font-family: Calibri">draw calls</span>来渲染场景中的所有物体，占了整个一帧的<span style="font-family: Calibri">72.6%</span>的时间。这<span style="font-family: Calibri">5526</span>个<span style="font-family: Calibri">draw calls</span>中，有超过<span style="font-family: Calibri">4000</span>个是渲染特效部分，它们占用了整个一帧<span style="font-family: Calibri">44.9%</span>的时间，这是优化的重点目标，如图<span style="font-family: Calibri">4</span>所示，在界面的<span style="font-family: Calibri">render target</span>那里可以看到所有的特效：</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><span style="font-family: Calibri"> <a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw4.png"><img src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw4.png" alt="" width="672" height="378" /></a></span></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h6><strong>图</strong><strong><span style="font-family: Calibri">4</span></strong><strong>，渲染特效的</strong><strong><span style="font-family: Calibri">draw calls</span></strong><strong>有</strong><strong><span style="font-family: Calibri">4079</span></strong><strong>个，占用一帧</strong><strong><span style="font-family: Calibri">44.9%</span></strong><strong>的时间</strong><strong> </strong></h6>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">通过查看和分析这些特效，我们发现每一个特效的<span style="font-family: Calibri">draw call</span>所渲染的东西都是非常小的，而且它们所使用纹理，多数都是小纹理，如下所示：</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><span style="font-family: Calibri"> <a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw4.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw5.png"><img src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw5.png" alt="" width="672" height="378" /></a></span></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h6><strong>图</strong><strong><span style="font-family: Calibri">5</span></strong><strong>，特效的</strong><strong><span style="font-family: Calibri">draw call</span></strong><strong>都很小，</strong><strong><span style="font-family: Calibri">10</span></strong><strong>个</strong><strong><span style="font-family: Calibri">draw calls</span></strong><strong>只渲染了一小部分特效</strong><strong> </strong></h6>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">上图<span style="font-family: Calibri">5</span>中，选中的这<span style="font-family: Calibri">10</span>个相邻的<span style="font-family: Calibri">draw calls</span>使用的都是这个<span style="font-family: Calibri">128*128</span>的蓝色纹理，所渲染的东西也是相邻的，我们可以考虑合并这几个<span style="font-family: Calibri">draw calls</span>。同时，考虑到纹理比较小，我们还可以合并相邻的特效纹理，这样可以减少<span style="font-family: Calibri">SETTEXTURE</span>的次数，也减少了<span style="font-family: Calibri">CPU</span>端的消耗。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">坐骑和人物部分的渲染，也划分得很细，头发，脸孔，衣服，武器等都是由单独的<span style="font-family: Calibri">draw call</span>完成。这些也可以进行适当的合并，从而减少<span style="font-family: Calibri">draw calls</span>和<span style="font-family: Calibri">state changes</span>的数量。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h1><span style="font-family: Calibri;font-size: small"> <strong>5. </strong><strong>优化策略和结果</strong></span></h1>
<h2><span style="font-size: small"><strong><span style="font-family: Calibri">5.1 </span></strong><strong>移除特效的阴影计算</strong><strong> </strong></span></h2>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">如前面的图<span style="font-family: Calibri">3</span>所示，游戏中对特效也计算了实时阴影，一般来说，特效是不需要计算阴影的。移除掉这些<span style="font-family: Calibri">draw calls</span>后，生成阴影贴图<span style="font-family: Calibri"> </span>的<span style="font-family: Calibri">draw calls</span>从<span style="font-family: Calibri">1198</span>个减少到了<span style="font-family: Calibri">860</span>个，<span style="font-family: Calibri"> </span>这部分的<span style="font-family: Calibri">GPU</span>时间消耗从<span style="font-family: Calibri">6.5ms</span>减少到了<span style="font-family: Calibri">4.86ms</span>。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h2><span style="font-size: small"><strong><span style="font-family: Calibri">5.2 </span></strong><strong>合并特效</strong><strong><span style="font-family: Calibri">draw calls</span></strong><strong>和纹理</strong><strong> </strong></span></h2>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">由前面的分析我们知道，要优化游戏在该场景下的性能，最重要的就是减少<span style="font-family: Calibri">CPU</span>端的消耗，也就是要减少游戏的<span style="font-family: Calibri">draw calls</span>和<span style="font-family: Calibri">State Changes</span>的数量。场景中特效的<span style="font-family: Calibri">draw calls</span>数量是最多的，而且特效的<span style="font-family: Calibri">draw calls</span>都是非常小的，所以我们首先来合并特效的<span style="font-family: Calibri">draw calls</span>。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><span style="font-family: Calibri"> </span></span><span style="font-size: small"><span style="font-family: Calibri"> <a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw4.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw5.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw6.png"><img src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw6.png" alt="" width="618" height="240" /></a></span></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h6><strong>图</strong><strong><span style="font-family: Calibri">6</span></strong><strong>，优化前，使用了</strong><strong><span style="font-family: Calibri">37</span></strong><strong>个</strong><strong><span style="font-family: Calibri">draw calls</span></strong><strong>来完成右边的特效</strong><strong> </strong></h6>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><span style="font-family: Calibri"> </span></span><span style="font-size: small"><span style="font-family: Calibri"> <a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw4.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw5.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw6.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw7.png"><img src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw7.png" alt="" width="618" height="240" /></a></span></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h6><strong>图</strong><strong><span style="font-family: Calibri">7</span></strong><strong>，优化后，对特效的顶点和纹理都进行了合并，使用一个</strong><strong><span style="font-family: Calibri">draw call</span></strong><strong>就完成了类似的特效</strong><strong> </strong></h6>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">从以上图<span style="font-family: Calibri">6</span>和图<span style="font-family: Calibri">7</span>的对比我们看到，合并优化后，渲染相同的特效，我们减少了<span style="font-family: Calibri">draw calls</span>的数量，从<span style="font-family: Calibri">37</span>减少到<span style="font-family: Calibri">1</span>，纹理也从<span style="font-family: Calibri">4</span>个合并到<span style="font-family: Calibri">1</span>个。整个一帧，特效的<span style="font-family: Calibri">draw calls</span>数量从<span style="font-family: Calibri">4000</span>多次减少到了<span style="font-family: Calibri">700</span>多次，<span style="font-family: Calibri">set texture</span>的次数从<span style="font-family: Calibri">3764</span>减少到<span style="font-family: Calibri">2029</span>次。整个特效部分的<span style="font-family: Calibri">GPU</span>时间从<span style="font-family: Calibri">45ms</span>减少到了<span style="font-family: Calibri">21ms</span>，提升非常明显！下图<span style="font-family: Calibri">8</span>为优化后的结果：</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><span style="font-family: Calibri"> <a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw4.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw5.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw6.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw7.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw8.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw9.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw10.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw11.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw12.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw8.png"><img class="alignnone size-full wp-image-400009651" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw8.png" alt="" width="520" height="315" /></a></span></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h6><strong>图</strong><strong><span style="font-family: Calibri">8</span></strong><strong>，优化后整个特效部分的</strong><strong><span style="font-family: Calibri">draw call</span></strong><strong>数量减少到了</strong><strong><span style="font-family: Calibri">706</span></strong><strong>个左右，特效的</strong><strong><span style="font-family: Calibri">GPU</span></strong><strong>时间从</strong><strong><span style="font-family: Calibri">45ms</span></strong><strong>减少到了</strong><strong><span style="font-family: Calibri">21ms</span></strong></h6>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><strong><span style="font-family: Calibri;font-size: small"> </span></strong></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h2><span style="font-size: small"><strong><span style="font-family: Calibri">5.3 </span></strong><strong>合并人物和坐骑的渲染</strong><strong> </strong></span></h2>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">游戏对人物的渲染区分很细，帽子，头发，衣服，裤子，鞋子，武器等都由独立的<span style="font-family: Calibri">draw calls</span>来完成，对坐骑也是由<span style="font-family: Calibri">3</span>个<span style="font-family: Calibri">draw calls</span>来完成的，虽然他们使用的是同样的纹理。以下以坐骑为例，将优化前需要<span style="font-family: Calibri">3</span>个<span style="font-family: Calibri">draw calls</span>完成的渲染，合并为一个<span style="font-family: Calibri">draw call</span>来完成。</span><span style="font-size: small"><span style="font-family: Calibri"> </span></span><span style="font-size: small"><span style="font-family: Calibri"> </span></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> <a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw8.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw9.png"><img src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw9.png" alt="" width="644" height="296" /></a></span></p>
<h6><strong>图</strong><strong><span style="font-family: Calibri">9</span></strong><strong>，优化前，使用了</strong><strong><span style="font-family: Calibri">3</span></strong><strong>个</strong><strong><span style="font-family: Calibri">draw calls</span></strong><strong>来完成一个坐骑的渲染</strong><strong> </strong></h6>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><span style="font-family: Calibri"> </span></span><span style="font-size: small"><span style="font-family: Calibri"> <a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw8.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw9.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw10.png"><img src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw10.png" alt="" width="644" height="300" /></a></span></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h6><strong>图</strong><strong><span style="font-family: Calibri">10</span></strong><strong>，优化后，合并了坐骑的</strong><strong><span style="font-family: Calibri">IB</span></strong><strong>和</strong><strong><span style="font-family: Calibri">VB</span></strong><strong>，使用一个</strong><strong><span style="font-family: Calibri">draw call</span></strong><strong>就能完成坐骑的渲染</strong><strong> </strong></h6>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">如上图<span style="font-family: Calibri">9</span>和图<span style="font-family: Calibri">10</span>所示，优化前需要用<span style="font-family: Calibri">3</span>个<span style="font-family: Calibri">draw calls</span>来完成一个坐骑的渲染，我们合并了坐骑的<span style="font-family: Calibri">IB</span>和<span style="font-family: Calibri">VB</span>，优化后只需要一个<span style="font-family: Calibri">draw call</span>就完成了这个坐骑的渲染。整个一帧有<span style="font-family: Calibri">~100</span>个坐骑，合并优化后，节省了<span style="font-family: Calibri">~200</span>个<span style="font-family: Calibri">draw calls</span>。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">我们针对人物也进行了类似的合并优化，也节省了<span style="font-family: Calibri">200</span>个左右的<span style="font-family: Calibri">draw calls</span>。<strong> </strong></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h2><span style="font-size: small"><strong><span style="font-family: Calibri">5.4 </span></strong><strong>移除重复的</strong><strong><span style="font-family: Calibri">SETTEXTURE</span></strong></span></h2>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">为了减少<span style="font-family: Calibri">CPU</span>端的消耗，我们还应该尽量减少<span style="font-family: Calibri">state changes</span>的数量，在帧分析器对另外一个场景的分析中，我们发现，每个<span style="font-family: Calibri">draw call</span>都会设置自己所需要的所有纹理，而不管是否和上一个<span style="font-family: Calibri">draw call</span>使用了相同的纹理。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><span style="font-family: Calibri"> <a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw8.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw9.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw10.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw11.png"><img src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw11.png" alt="" width="576" height="324" /></a></span></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h6><strong>图</strong><strong><span style="font-family: Calibri">11</span></strong><strong>，</strong><strong><span style="font-family: Calibri"> </span></strong><strong>相邻的</strong><strong><span style="font-family: Calibri">2</span></strong><strong>个</strong><strong><span style="font-family: Calibri">draw calls</span></strong><strong>，使用一样的纹理，但是他们都重新设置了一次</strong><strong> </strong></h6>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">如图<span style="font-family: Calibri">11</span>所示，柱状图中选中的临近的<span style="font-family: Calibri">2</span>个<span style="font-family: Calibri">draw call</span>，是在画地形部分，即使它们使用的是完全相同的纹理，它们也都重新调用了<span style="font-family: Calibri">5</span>次完整的的<span style="font-family: Calibri">SETTEXTURE API</span>。该场景中整个一帧总共有<span style="font-family: Calibri">1837</span>个<span style="font-family: Calibri">SETTEXTURE API </span>调用。这不是有效率的做法，如果相邻的<span style="font-family: Calibri">draw call</span>使用的是同样的纹理，可以不用调用<span style="font-family: Calibri">SETTEXTURE</span>再次设置，这样可以减少<span style="font-family: Calibri">state changes</span>的数量，提高游戏性能。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">以下是优化后的截图，移除掉了重复的不必要的<span style="font-family: Calibri">SETTEXTURE API</span>调用，如图<span style="font-family: Calibri">12</span>所示，第二个地形<span style="font-family: Calibri">draw call</span>本身已经没有调用<span style="font-family: Calibri">set texture</span>了。经过优化后，整个一帧所调用的<span style="font-family: Calibri">SETTEXTURE API</span>次数从<span style="font-family: Calibri">1837</span>次减少到了<span style="font-family: Calibri">554</span>次。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><span style="font-family: Calibri"> <a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw8.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw9.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw10.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw11.png"></a><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw12.png"><img src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2012/01/bw12.png" alt="" width="605" height="340" /></a></span></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<h6><strong>图</strong><strong><span style="font-family: Calibri">12</span></strong><strong>，优化后，如果纹理没有变化，则不重复设置了</strong><strong> </strong></h6>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small">经过以上几种优化，我们把《兵王》在这个场景下的<span style="font-family: Calibri">draw calls</span>数量从<span style="font-family: Calibri">7839</span>次减少到了<span style="font-family: Calibri">3812</span>次，<span style="font-family: Calibri">SETTEXTURE API</span>调用次数从<span style="font-family: Calibri">3764</span>次减少到了<span style="font-family: Calibri">2029</span>次。游戏帧率从<span style="font-family: Calibri">10fps</span>提升到了<span style="font-family: Calibri">20fps</span>左右，基本能够流畅的运行，达到了游戏开发者的期望。<strong> </strong></span></p>
<h1><span style="font-family: Times New Roman;font-size: small"> </span></h1>
<h1><span style="font-family: Times New Roman;font-size: small">6<strong>. 总结</strong><strong> </strong></span></h1>
<p><span style="font-size: small"> </span></p>
<p><span style="font-size: small">本文介绍了使用<span style="font-family: Calibri">GPA</span>对《兵王》进行性能分析和优化的过程，从中我们可以看出，游戏客户端的性能优化并不难，我们所使用的优化方法也都很常见，但重要的是如何很快的找到这些游戏热点和瓶颈。在《兵王》的性能分析和优化过程中，<span style="font-family: Calibri">GPA</span>发挥了非常重要的作用，通过它我们很容易就发现了游戏的瓶颈，进行针对性的优化，游戏的性能得到了很大的提升。我们将继续使用<span style="font-family: Calibri">GPA</span>进一步优化游戏。<strong> </strong></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><strong> </strong></span></p>
<h2><span style="font-size: small"><strong>作者简介</strong><strong> </strong></span></h2>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><strong>卢卷彬</strong><strong><span style="font-family: Calibri"> </span></strong>英特尔公司的应用工程师，他和国内几家大的游戏公司有着多年的合作，帮助他们在英特尔平台上优化游戏客户端的性能。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><strong>余娜娜</strong><span style="font-family: Calibri"><strong> </strong> </span>巨人前传技术部经理，参与开发过3DRPG《仙剑奇侠传三-问情篇》，3DMMORPG《巨人》、《兵王》。主要致力于3D引擎的研制开发，与Intel的几年合作中，极大提升了自主研发的3D引擎的特性，在效果提升的基础上，同屏人数也大大提升。</span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
<p><span style="font-size: small"><span style="font-family: Calibri"><strong>Kiefer Kuah</strong> </span>英特尔的软件工程师，他主要负责游戏在英特尔平台上的优化工作。<strong> </strong></span></p>
<p><span style="font-family: Times New Roman;font-size: small"> </span></p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2012/01/06/gpa-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTML5之Web Storage</title>
		<link>http://software.intel.com/zh-cn/blogs/2011/12/26/html5web-storage/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2011/12/26/html5web-storage/#comments</comments>
		<pubDate>Mon, 26 Dec 2011 04:00:27 +0000</pubDate>
		<dc:creator>章政</dc:creator>
				<category><![CDATA[Android 开发]]></category>
		<category><![CDATA[Blog Challenge]]></category>
		<category><![CDATA[全国博客大奖赛]]></category>
		<category><![CDATA[全国大学生软件创新大赛专栏]]></category>
		<category><![CDATA[其他]]></category>
		<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[图形和视觉计算]]></category>
		<category><![CDATA[并行计算]]></category>
		<category><![CDATA[开放源代码]]></category>
		<category><![CDATA[服务器]]></category>
		<category><![CDATA[游戏]]></category>
		<category><![CDATA[移动技术]]></category>
		<category><![CDATA[英特尔® 软件网络 2.0]]></category>
		<category><![CDATA[英特尔信息技术峰会]]></category>
		<category><![CDATA[虚拟化技术]]></category>
		<category><![CDATA[软件开发工具]]></category>
		<category><![CDATA[软件技术学习及认证]]></category>
		<category><![CDATA[高校博客大奖赛]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2011/12/26/html5web-storage/</guid>
		<description><![CDATA[WebStorage的出现是为了弥补cookie的不足,cookie一方面是容量小，4k/8k，存几个电子邮件都不够，二来是全局的，容易被误用，盗用。 在HTML5中网络存储按照生命周期分为2种，一种是基于会话(session),这种存储周期只是当前会话，当网页[注1]被关被后，或者被转到其他网站后，存储也就被销毁； sessionStorage.varName = “生成新变量”; sessionStorage.varName = “变量操作”; delete sessionStorage.varName; //删除变量 另外一种是本地存储，当网页下次被打开的时候，你仍然可以访问上次打开该网页时存储的数据，比如本地存储的网站用户名就可以使用这种方式。 用法和基于会话的存储一样，只是前缀名改成了localStorage localStorage.varName = “生成新变量”; localStorage.varName = “变量操作”; delete localStorage.varName; //删除变量 从上面可以看出web storage其实也只是解决了轻量级的数据存储问题，如果是大量的数据查询，比如商品列表，还是得靠数据库,HTML5中有Web Database来支持这一操作，基本操作和SQL一致。 注1：现在的浏览器基本都支持多窗口了，一个窗口对应一个网页 注2：官方参考]]></description>
			<content:encoded><![CDATA[<p>WebStorage的出现是为了弥补cookie的不足,cookie一方面是容量小，4k/8k，存几个电子邮件都不够，二来是全局的，容易被误用，盗用。<br />
在HTML5中网络存储按照生命周期分为2种，一种是基于会话(session),这种存储周期只是当前会话，当网页[注1]被关被后，或者被转到其他网站后，存储也就被销毁；</p>
<pre name="code" class="js">
sessionStorage.varName = “生成新变量”;
sessionStorage.varName = “变量操作”;
delete sessionStorage.varName;  //删除变量
</pre>
<p>另外一种是本地存储，当网页下次被打开的时候，你仍然可以访问上次打开该网页时存储的数据，比如本地存储的网站用户名就可以使用这种方式。<br />
用法和基于会话的存储一样，只是前缀名改成了localStorage</p>
<pre name="code" class="js">
localStorage.varName = “生成新变量”;
localStorage.varName = “变量操作”;
delete localStorage.varName;  //删除变量
</pre>
<p>从上面可以看出web storage其实也只是解决了轻量级的数据存储问题，如果是大量的数据查询，比如商品列表，还是得靠数据库,HTML5中有Web Database来支持这一操作，基本操作和SQL一致。<br />
注1：现在的浏览器基本都支持多窗口了，一个窗口对应一个网页<br />
注2：<a href="http://dev.w3.org/html5/webstorage/">官方参考</a></p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2011/12/26/html5web-storage/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用英特尔GPA优化《轩辕传奇》游戏的性能</title>
		<link>http://software.intel.com/zh-cn/blogs/2011/12/26/gpa-2/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2011/12/26/gpa-2/#comments</comments>
		<pubDate>Mon, 26 Dec 2011 03:57:56 +0000</pubDate>
		<dc:creator>Cage Lu (Intel)</dc:creator>
				<category><![CDATA[图形和视觉计算]]></category>
		<category><![CDATA[游戏]]></category>
		<category><![CDATA[GPA]]></category>
		<category><![CDATA[性能优化]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2011/12/26/gpa-2/</guid>
		<description><![CDATA[ 文章作者：英特尔：卢卷彬 Kiefer Kuah    腾讯：丛越    下载PDF版本：使用英特尔GPA优化《轩辕传奇》游戏的性能    介绍  随着集成显卡功能和性能的日益增强以及移动平台的不断普及，集成显卡已经成了游戏开发者不可忽视的重要对象。    本文介绍了使用GPA在英特尔集成显卡上分析和优化《轩辕传奇》网络游戏的案例。 《轩辕传奇》是由腾讯研发团队打造的一款MMORPG网游，是腾讯的首款史诗战争网游。该游戏在引擎技术、美术、服务器等诸多方面都力求精益求精，达到了国内顶级网游水准。为了满足更多玩家的机器配置，我们特别针对集成显卡进行了测试和优化。    性能分析开始 本文档的分析和优化基于Intel HD Graphics 3000平台，代号SandyBridge(简称SNB)。 SNB是Intel在2011年推出的一款性能非常出色的处理器集成显卡。它的性能可以媲美一些独立显卡。作为一款网络游戏，《轩辕传奇》的开发者希望能够在更多的平台上面流畅运行游戏，所以尽管游戏在SNB上的性能已经很流畅了，我们还是要尽量的对游戏性能进行优化。 以下是我们这次性能分析和优化所选择的目标场景：        图1. 《轩辕传奇》性能分析和优化的目标场景    系统分析   GPA HUD能够实时的显示游戏运行的时候CPU，DX runtime，以及GPU上的性能数据。同时支持多种D3D流水线上的override模式，帮助游戏开发者进一步定位游戏的瓶颈所在。   通过GPA HUD的分析，我们发现：   1. 游戏的大多数计算都是在主线程中完成，多核心利用率比较低。那么在玩家角色多的时候，因为动画计算比较多，CPU将会成为瓶颈。可以考虑使用多线程来消除这种场景下的瓶颈。   2. 游戏中每帧的State Changes数量不算很多，大概每帧6000个，平均每个DP call 7.5次。能够做一些优化减少State Changes数量的话，对性能是很有好处的。   3. 通过Override模式测试，Null Driver, Null Hardware 都可以使游戏的fps达到100左右，100fps是游戏的限帧。所以在该场景下游戏的瓶颈是在GPU上。我们还在玩家角色比较多的场景进行了类似测试，发现Null Hardware对fps提升不大，此时瓶颈在CPU上。     帧分析   [...]]]></description>
			<content:encoded><![CDATA[<div><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan1.png"></a></div>
<div><span style="font-family: Times New Roman; font-size: small;"> 文章作者：英特尔：卢卷彬 Kiefer Kuah    腾讯：丛越</span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span>下载PDF版本：<strong><a title="下载" href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/GPA_XuanYuan_Optimization_case-study.pdf">使用英特尔GPA优化《轩辕传奇》游戏的性能</a></strong><strong> </strong></div>
<h2><strong> </strong></h2>
<h2><strong>介绍</strong><strong> </strong></h2>
<div><span style="font-size: small;"><span style="font-family: Calibri;"> </span>随着集成显卡功能和性能的日益增强以及移动平台的不断普及，集成显卡已经成了游戏开发者不可忽视的重要对象。</span></div>
<div><span style="font-size: small;"><span style="font-family: Calibri;"> </span></span></div>
<div><span style="font-size: small;"><span style="font-family: Calibri;"> </span>本文介绍了使用<span style="font-family: Calibri;">GPA</span>在英特尔集成显卡上分析和优化《轩辕传奇》网络游戏的案例。<span style="font-family: Calibri;"> </span>《轩辕传奇》是由腾讯研发团队打造的一款<span style="font-family: Calibri;">MMORPG</span>网游，是腾讯的首款史诗战争网游。该游戏在引擎技术、美术、服务器等诸多方面都力求精益求精，达到了国内顶级网游水准。为了满足更多玩家的机器配置，我们特别针对集成显卡进行了测试和优化。</span></div>
<div><strong> </strong></div>
<h2><strong> </strong><strong>性能分析开始</strong><strong> </strong></h2>
<div><span style="font-size: small;">本文档的分析和优化基于<span style="font-family: Calibri;">Intel HD Graphics 3000</span>平台，代号<span style="font-family: Calibri;">SandyBridge(</span>简称<span style="font-family: Calibri;">SNB)</span>。<span style="font-family: Calibri;"> SNB</span>是<span style="font-family: Calibri;">Intel</span>在<span style="font-family: Calibri;">2011</span>年推出的一款性能非常出色的处理器集成显卡。它的性能可以媲美一些独立显卡。作为一款网络游戏，《轩辕传奇》的开发者希望能够在更多的平台上面流畅运行游戏，所以尽管游戏在<span style="font-family: Calibri;">SNB</span>上的性能已经很流畅了，我们还是要尽量的对游戏性能进行优化。</span></div>
<div><span style="font-size: small;">以下是我们这次性能分析和优化所选择的目标场景：</span><span style="font-family: Calibri; font-size: small;"> </span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-size: small;"><span style="font-family: Calibri;"> </span></span><span style="font-size: small;"><span style="font-family: Calibri;"> </span></span></div>
<div><strong><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan1.png"><img class="size-large wp-image-400009552 aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan1-1024x640.png" alt="" width="717" height="448" /></a></strong></div>
<div><strong> </strong></div>
<div style="text-align: center;"><strong>图1. 《轩辕传奇》性能分析和优化的目标场景</strong></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<h2><strong> </strong><strong>系统分析</strong></h2>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><span style="font-family: Calibri;">GPA HUD</span>能够实时的显示游戏运行的时候<span style="font-family: Calibri;">CPU</span>，<span style="font-family: Calibri;">DX runtime</span>，以及<span style="font-family: Calibri;">GPU</span>上的性能数据。同时支持多种<span style="font-family: Calibri;">D3D</span>流水线上的<span style="font-family: Calibri;">override</span>模式，帮助游戏开发者进一步定位游戏的瓶颈所在。</span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;">通过<span style="font-family: Calibri;">GPA HUD</span>的分析，我们发现：</span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><span style="font-family: Calibri;">1. </span>游戏的大多数计算都是在主线程中完成，多核心利用率比较低。那么在玩家角色多的时候，因为动画计算比较多，<span style="font-family: Calibri;">CPU</span>将会成为瓶颈。可以考虑使用多线程来消除这种场景下的瓶颈。</span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><span style="font-family: Calibri;">2. </span>游戏中每帧的<span style="font-family: Calibri;">State Changes</span>数量不算很多，大概每帧<span style="font-family: Calibri;">6000</span>个，平均每个<span style="font-family: Calibri;">DP call 7.5</span>次。能够做一些优化减少<span style="font-family: Calibri;">State Changes</span>数量的话，对性能是很有好处的。</span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><span style="font-family: Calibri;">3. </span>通过<span style="font-family: Calibri;">Override</span>模式测试，<span style="font-family: Calibri;">Null Driver, Null Hardware </span>都可以使游戏的<span style="font-family: Calibri;">fps</span>达到<span style="font-family: Calibri;">100</span>左右，<span style="font-family: Calibri;">100fps</span>是游戏的限帧。所以在该场景下游戏的瓶颈是在<span style="font-family: Calibri;">GPU</span>上。我们还在玩家角色比较多的场景进行了类似测试，发现<span style="font-family: Calibri;">Null Hardware</span>对<span style="font-family: Calibri;">fps</span>提升不大，此时瓶颈在<span style="font-family: Calibri;">CPU</span>上。</span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-family: Calibri; font-size: small;"> </span></div>
<h2><strong>帧分析</strong></h2>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><span style="font-family: Calibri;">GPA</span>帧分析器能够详细的分析游戏的一帧的所有<span style="font-family: Calibri;">draw call</span>的性能数据以及它们所使用的纹理，<span style="font-family: Calibri;">d3d</span>状态，<span style="font-family: Calibri;">shader</span>等等。图<span style="font-family: Calibri;">2</span>显示了我们使用<span style="font-family: Calibri;">GPA</span>帧分析器打开我们在目标场景抓取的一帧数据。</span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><span style="font-family: Calibri;"> </span></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><strong><img class="size-large wp-image-400009553 aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan2-1024x429.png" alt="" width="614" height="257" /></strong></span></div>
<div><span style="font-size: small;"><strong> </strong></span></div>
<div style="text-align: center;"><span style="font-size: small;"><strong> </strong></span><span style="font-size: small;"><strong>图<span style="font-family: Calibri;">2. </span></strong><strong>使用<span style="font-family: Calibri;">GPA</span></strong><strong>帧分析器打开抓取的一帧数据</strong></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-family: Calibri; font-size: small;"> </span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-size: small;">通过帧分析器分析，我们得到整个一帧的时间分布为：</span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<ol>
<li><span style="font-size: small;">生成阴影贴图：<span style="font-family: Calibri;">~170 </span>个<span style="font-family: Calibri;"> DP Calls, 15.9% frame time</span>。场景中所有的物体都计算了实时阴影。我们可以使用静态阴影来替代其中的一部分，比如某些距离远的，固定的物体。</span></li>
<li><span style="font-size: small;">天空盒<span style="font-family: Calibri;">: 3</span>个<span style="font-family: Calibri;"> DP Calls</span>，<span style="font-family: Calibri;">4.7% frame time</span>。实际上在该场景中看不到天空，我们可以在渲染天空盒之前进行可见性检测。如果不可见，则不渲染。</span></li>
<li><span style="font-size: small;"><span style="font-family: Calibri;">Terrain</span>：<span style="font-family: Calibri;">50</span>个<span style="font-family: Calibri;"> DP Calls</span>，<span style="font-family: Calibri;">34.9% frame time</span>。和大多数网络游戏一样，地形总是最耗时的部分，是优化的重点。</span></li>
<li><span style="font-size: small;">人物和其他地上物件：<span style="font-family: Calibri;">~240</span>个<span style="font-family: Calibri;">DP Calls</span>，<span style="font-family: Calibri;">22.4% frame time</span>。没有发现明显的可以优化的地方。</span></li>
<li><span style="font-size: small;">后处理：<span style="font-family: Calibri;">8</span>个<span style="font-family: Calibri;">DP Calls</span>，<span style="font-family: Calibri;">8.4% frame time</span>。没有发现明显的可以优化的地方。</span></li>
<li><span style="font-size: small;"><span style="font-family: Calibri;">UI</span>：<span style="font-family: Calibri;">55 DP Calls</span>，<span style="font-family: Calibri;">7.4% frame time</span>。有许多<span style="font-family: Calibri;">UI</span>元素过小，可以合并一下再渲染。<span style="font-family: Calibri;">UI</span>并不是每帧都变化的，可以重复利用上一帧的结果。</span></li>
</ol>
<div><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<h2><strong>优化策略和结果</strong><span style="font-size: small;">：</span></h2>
<p><span style="font-size: small;"> </span></p>
<h3><span style="font-family: Times New Roman; font-size: small;"> </span><strong><span style="font-family: Calibri;">1. </span></strong><strong>阴影贴图生成</strong><strong> </strong></h3>
<div><span style="font-size: small;">游戏花费了花费了<span style="font-family: Calibri;">~170</span>个<span style="font-family: Calibri;">draw calls</span>来生成所有物体的阴影贴图，但实际上，场景中某些固定的物体或者远处的物体，是没有必要使用实时计算的阴影的，使用提前生成的静态阴影即可。这可以节省<span style="font-family: Calibri;">draw calls</span>的数量，提高性能。图<span style="font-family: Calibri;">3</span>是优化前后的对比，右边是优化后的阴影贴图生成，减少了使用实时阴影的物体数量，可以看到<span style="font-family: Calibri;">draw calls</span>数量减少到了<span style="font-family: Calibri;">45</span>个，整个阴影地图生成花费的时间从<span style="font-family: Calibri;">2.97ms</span>减少到了<span style="font-family: Calibri;">1.03ms</span>。</span><span style="font-size: small;"><span style="font-family: Calibri;"> </span></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><strong><img class="aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan3.png" alt="" width="594" height="397" /></strong></span></div>
<div><span style="font-size: small;"><strong> </strong></span></div>
<div style="text-align: center;"><span style="font-size: small;"><strong>图<span style="font-family: Calibri;">3. </span></strong><strong>优化前和优化后的阴影贴图计算</strong></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-family: Calibri; font-size: small;"> </span><span style="font-family: Times New Roman; font-size: small;"> </span><strong><span style="font-family: Calibri;">2. </span></strong><strong>天空盒</strong><strong> </strong></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;">天空盒在这个场景中是不可见的，但是帧分析器显示游戏依然渲染了它。我们可以在渲染之前检测天空盒的可见性，如果不可见，则不渲染。这可以节省<span style="font-family: Calibri;">0.88ms</span>。而且，天空盒最好是放到场景中不透明物体渲染完之后再渲染，因为天空盒的大部分都是被遮挡的。</span><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><strong> </strong></span></div>
<div><span style="font-size: small;"><strong><img class="aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan4.png" alt="" width="525" height="412" /></strong></span></div>
<div><span style="font-size: small;"><strong> </strong></span></div>
<div style="text-align: center;"><span style="font-size: small;"><strong>图<span style="font-family: Calibri;">4. </span></strong><strong>游戏渲染了不可见的天空盒</strong></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span><strong><span style="font-family: Calibri; font-size: small;"> </span></strong><strong><span style="font-family: Calibri;">3. </span></strong><strong>地形</strong><strong> </strong></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-size: small;"> </span></div>
<div><span style="font-size: small;">地形部分的渲染占用了最多的时间，网络游戏一般都是这样。</span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-size: small;">其中一部分主要的地形，占用了<span style="font-family: Calibri;">6.5ms</span>中的<span style="font-family: Calibri;">5.1ms</span>，它们使用的同一段<span style="font-family: Calibri;">Pixel Shader</span>，以下是这部分地形的截屏：</span><span style="font-size: small;"><span style="font-family: Calibri;"> </span></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><strong><img class="size-large wp-image-400009556 aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan5-1024x507.png" alt="" width="717" height="355" /></strong></span></div>
<div><span style="font-size: small;"><strong> </strong></span></div>
<div style="text-align: center;"><span style="font-size: small;"><strong>图<span style="font-family: Calibri;">5. </span></strong><strong>部分地形使用同样的<span style="font-family: Calibri;">Shader</span></strong><strong>，包含<span style="font-family: Calibri;">89</span></strong><strong>个指令，其中<span style="font-family: Calibri;">13</span></strong><strong>个纹理<span style="font-family: Calibri;">load</span></strong><strong>，<span style="font-family: Calibri;">76</span></strong><strong>个算术指令</strong></span></div>
<div style="text-align: left;"><span style="font-size: small;">过帧分析器我们可以看到，这部分地形的渲染，<span style="font-family: Calibri;">PS duration</span>占用了<span style="font-family: Calibri;">90%</span>的时间，在帧分析器中我们可以在<span style="font-family: Calibri;">Shader Tab</span>查看这些渲染所使用的<span style="font-family: Calibri;">shader code</span>，如图<span style="font-family: Calibri;">5</span>所示，这部分地形的<span style="font-family: Calibri;">shader </span>包含了<span style="font-family: Calibri;">89</span>条指令，其中<span style="font-family: Calibri;">13</span>个纹理<span style="font-family: Calibri;">load</span>，<span style="font-family: Calibri;">76</span>个数学计算，比较复杂。</span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;">我们把<span style="font-family: Calibri;">shader</span>做了一定的简化，去掉了高光，<span style="font-family: Calibri;">normal map</span>，<span style="font-family: Calibri;">AO map</span>等。图<span style="font-family: Calibri;">6</span>是修改了<span style="font-family: Calibri;">pixel shader</span>后的截图，修改后<span style="font-family: Calibri;">pixel shader</span>包含<span style="font-family: Calibri;">31</span>条指令，其中<span style="font-family: Calibri;">8</span>个纹理<span style="font-family: Calibri;">load</span>，<span style="font-family: Calibri;">23</span>个算术指令。<span style="font-family: Calibri;"> </span>这部分地形渲染的时间从<span style="font-family: Calibri;">5.1ms</span>减少到了<span style="font-family: Calibri;">3.4ms</span>。</span><span style="font-size: small;"><span style="font-family: Calibri;"> </span></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><strong><img class="aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan6.png" alt="" width="780" height="386" /></strong></span></div>
<div><span style="font-size: small;"><strong> </strong></span></div>
<div style="text-align: center;"><span style="font-size: small;"><strong>图<span style="font-family: Calibri;">6. </span></strong><strong>优化<span style="font-family: Calibri;">shader</span></strong><strong>代码后，这部分地形所花费的时间减少到了<span style="font-family: Calibri;">3.4ms</span></strong></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-family: Calibri; font-size: small;"> </span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-size: small;">我们还为特别低端的平台准备了更加简单的，只需要<span style="font-family: Calibri;">2</span>个纹理的<span style="font-family: Calibri;">shader</span>版本，时间进一步减少到了<span style="font-family: Calibri;">0.93ms</span>，见图<span style="font-family: Calibri;">7</span>所示：</span><span style="font-size: small;"><span style="font-family: Calibri;"> </span></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><strong><span style="font-size: small;"><strong><img class="aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan7.png" alt="" width="773" height="348" /></strong></span></strong></span></div>
<div><span style="font-size: small;"><strong> </strong></span></div>
<div style="text-align: center;"><span style="font-size: small;"><strong>图<span style="font-family: Calibri;">7. </span></strong><strong>在更低端平台上进一步简化地形的<span style="font-family: Calibri;">pixel shader</span></strong></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><strong><span style="font-family: Calibri; font-size: small;"> </span></strong><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-size: small;">当然，使用<span style="font-family: Calibri;">2</span>个纹理后，地形画面质量肯定有所下降。在<span style="font-family: Calibri;">GPA</span>帧分析器我们能够实时的看到修改<span style="font-family: Calibri;">shader code</span>后对画面的影响。</span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<h3><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-family: Calibri;"><strong>4. </strong><strong>UI</strong></span></h3>
<div><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-size: small;"><span style="font-family: Calibri;">UI</span>部分共占用<span style="font-family: Calibri;">7.4%</span>的时间，图<span style="font-family: Calibri;">8</span>是游戏中左上角的人物<span style="font-family: Calibri;">UI</span>截屏。<span style="font-size: small;"><strong><span style="font-size: small;"><strong> </strong></span></strong></span></span><span style="font-size: small;"><span style="font-family: Calibri;"> </span></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><strong><span style="font-size: small;"><strong><span style="font-size: small;"><strong><img class="size-full wp-image-400009559 aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan8.png" alt="" width="644" height="276" /></strong></span></strong></span></strong></span></div>
<div><span style="font-size: small;"><strong> </strong></span></div>
<div style="text-align: center;"><span style="font-size: small;"><strong>图<span style="font-family: Calibri;">8. </span></strong><strong>游戏中左上角的角色<span style="font-family: Calibri;">UI</span></strong></span><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><strong><span style="font-family: Calibri; font-size: small;"> </span></strong></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-size: small;">通过帧分析器，我们发现为了画游戏左上角的人物头像以及血槽等部分，游戏使用了<span style="font-family: Calibri;">9</span>个<span style="font-family: Calibri;">draw calls</span>来完成（图<span style="font-family: Calibri;">9</span>），而且是每一帧都会花费<span style="font-family: Calibri;">9</span>个<span style="font-family: Calibri;">draw calls</span>来做这件事情。但是对网络游戏来说，<span style="font-family: Calibri;">99%</span>的时间，这部分是不会变化的，那么每帧都使用<span style="font-family: Calibri;">9</span>个<span style="font-family: Calibri;">draw call</span>来画这部分，是没有必要的。我们可以把这个头像部分先渲染到一个<span style="font-family: Calibri;">image buffer</span>，然后使用一个<span style="font-family: Calibri;">draw call</span>把这个<span style="font-family: Calibri;">image</span>画到屏幕上，如果下一帧这个头像部分没有更新，则继续使用上次的这个<span style="font-family: Calibri;">image buffer</span>。这样一来，只有在头像部分需要更新的时候，才去重新做这<span style="font-family: Calibri;">9</span>次<span style="font-family: Calibri;">draw calls</span>，其他时候，只需要一个<span style="font-family: Calibri;">draw call</span>就完成了。<strong> </strong></span><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><strong> </strong></span></div>
<div><span style="font-size: small;"><strong><strong><strong><img class="aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan9.png" alt="" width="720" height="371" /></strong></strong></strong></span></div>
<div><span style="font-size: small;"><strong> </strong></span></div>
<div style="text-align: center;"><span style="font-size: small;"><strong>图<span style="font-family: Calibri;">9. </span></strong><strong>游戏使用了<span style="font-family: Calibri;">9</span></strong><strong>个<span style="font-family: Calibri;">draw calls</span></strong><strong>来完成这部分<span style="font-family: Calibri;">UI</span></strong><strong>的渲染</strong></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-family: Calibri; font-size: small;"> </span><span style="font-size: small;">图<span style="font-family: Calibri;">10</span>显示了优化后的截图，这一帧重利用了<span style="font-family: Calibri;">image buffer</span>，只使用了一个<span style="font-family: Calibri;">draw calls</span>就完成了这部分<span style="font-family: Calibri;">UI</span>的渲染。我们对其它的<span style="font-family: Calibri;">UI</span>也进行了类似的优化。优化后，渲染<span style="font-family: Calibri;">UI</span>所花费的时间从<span style="font-family: Calibri;">1.38ms</span>减少到了<span style="font-family: Calibri;">1.17ms</span>。</span><span style="font-size: small;"><span style="font-family: Calibri;"> </span></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><strong><strong><strong><a href="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan10.png"><img class="aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan10.png" alt="" width="706" height="367" /></a></strong></strong></strong></span></div>
<div><span style="font-size: small;"><strong> </strong></span></div>
<div style="text-align: center;"><span style="font-size: small;"><strong>图<span style="font-family: Calibri;">10. </span></strong><strong>使用<span style="font-family: Calibri;">image buffer</span></strong><strong>来存储这部分<span style="font-family: Calibri;">UI</span></strong><strong>以便重复使用</strong></span><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<h3><span style="font-family: Calibri; font-size: small;"> </span><strong><span style="font-family: Calibri;">5. </span></strong><strong>减少</strong><strong><span style="font-family: Calibri;">State Changes</span></strong><strong>数量</strong><strong> </strong></h3>
<div><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-size: small;"><span style="font-family: Calibri;">State Changes</span>过多会导致游戏程序，<span style="font-family: Calibri;">d3d runtime, </span>显卡驱动和显卡硬件的负载增加。减少<span style="font-family: Calibri;">State Changes</span>的数量能够提高游戏性能。通过帧分析器对这一帧的详细分析，我们发现有很多的<span style="font-family: Calibri;">draw calls</span>，都会使用很小的纹理，<span style="font-family: Calibri;">16*16</span>，<span style="font-family: Calibri;">32*32</span>或者<span style="font-family: Calibri;">64*64</span>大小，大量的使用小纹理，不是一种有效率的做法。图<span style="font-family: Calibri;">11</span>显示了两个相邻的<span style="font-family: Calibri;">draw calls</span>使用了非常小的纹理：</span></div>
<div><span style="font-family: Times New Roman; font-size: small;"><strong><strong> </strong></strong></span></div>
<div><span style="font-size: small;"><strong><img class="aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan11.png" alt="" width="575" height="431" /></strong></span></div>
<div><span style="font-size: small;"><strong> </strong></span></div>
<div style="text-align: center;"><span style="font-size: small;"><strong>图<span style="font-family: Calibri;">11. </span></strong><strong>两个相邻的<span style="font-family: Calibri;">draw calls</span></strong><strong>，都使用了非常小的贴图</strong></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><strong><span style="font-family: Calibri; font-size: small;"> </span></strong><span style="font-size: small;">从上面图<span style="font-family: Calibri;">11</span>中我们看到，临近的的<span style="font-family: Calibri;">2</span>个<span style="font-family: Calibri;">draw calls,</span>分别调用了<span style="font-family: Calibri;">3</span>个<span style="font-family: Calibri;">SETTEXTURE API</span>，其中第二和第三个<span style="font-family: Calibri;">texture</span>，都是很小的纹理（见图<span style="font-family: Calibri;">12</span>）。我们可以合并这些小的纹理，然后只需要设置一次合并后的纹理，接下来的几个<span style="font-family: Calibri;">draw calls</span>就可以直接使用，而不用再设置了。这可以减少<span style="font-family: Calibri;">State Changes</span>的数量。当然，使用合并纹理的时候要注意设置正确的<span style="font-family: Calibri;">UV</span>值。</span><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><strong><img class="aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan12.png" alt="" width="575" height="430" /></strong></span></div>
<div><span style="font-size: small;"><strong><strong><strong> </strong></strong></strong></span></div>
<div style="text-align: center;"><span style="font-size: small;"><strong> </strong></span><span style="font-size: small;"><strong>图<span style="font-family: Calibri;">12. </span></strong><strong>这些<span style="font-family: Calibri;">draw calls</span></strong><strong>所使用的小尺寸纹理</strong></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-family: Calibri; font-size: small;"> </span><span style="font-size: small;">图<span style="font-family: Calibri;">13</span>和<span style="font-family: Calibri;">14</span>是优化后的截屏，我们合并了<span style="font-family: Calibri;">3</span>个<span style="font-family: Calibri;">draw calls</span>所使用的小纹理，<span style="font-family: Calibri;">SETTEXTURE API</span>调用的次数从<span style="font-family: Calibri;">9</span>次减少到了<span style="font-family: Calibri;">4</span>次。整个一帧，我们减少了<span style="font-family: Calibri;">~500</span>次<span style="font-family: Calibri;">State Changes</span>。</span><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><strong><img class="aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan13.png" alt="" width="575" height="431" /></strong></span></div>
<div><span style="font-size: small;"><strong><strong><strong><strong> </strong></strong></strong></strong></span><span style="font-size: small;"><strong> </strong></span></div>
<div style="text-align: center;"><span style="font-size: small;"><strong>图<span style="font-family: Calibri;">13. </span></strong><strong>合并纹理后，<span style="font-family: Calibri;">3</span></strong><strong>个<span style="font-family: Calibri;">draw calls</span></strong><strong>所调用的<span style="font-family: Calibri;">SETTEXTURE API</span></strong><strong>从<span style="font-family: Calibri;">9</span></strong><strong>次减少到了<span style="font-family: Calibri;">4</span></strong><strong>次</strong></span><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;"><strong><strong><strong><strong><strong><img class="aligncenter" src="http://software.intel.com/zh-cn/blogs/wordpress/wp-content/uploads/2011/12/xuanyuan14.png" alt="" width="575" height="430" /></strong></strong></strong></strong></strong></span></div>
<div><span style="font-size: small;"><strong> </strong></span></div>
<div style="text-align: center;"><span style="font-size: small;"><strong>图<span style="font-family: Calibri;">14. </span></strong><strong>将小纹理合并后得到的大纹理</strong></span></div>
<div><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-family: Calibri; font-size: small;"> </span><span style="font-family: Times New Roman; font-size: small;"> </span><strong> </strong></div>
<h2><strong>优化总结：</strong><strong> </strong></h2>
<div><span style="font-family: Times New Roman; font-size: small;"> </span></div>
<div><span style="font-size: small;">我们介绍了在英特尔集成显卡平台上通过<span style="font-family: Calibri;">GPA</span>对游戏性能进行分析和优化的成功案例。<span style="font-family: Calibri;">GPA</span>工具帮助我们找到了游戏的瓶颈所在。我们使用它对一帧进行了深入的分析，对<span style="font-family: Calibri;">shader</span>进行了实时修改，并找到了减少<span style="font-family: Calibri;">State changes</span>数量的办法。经过优化，游戏性能得到了很大提升，能让更多玩家流畅体验轩辕传奇这款游戏。其实我们还使用<span style="font-family: Calibri;">GPA</span>对其他不同场景，不同状态（聊天，骑乘，战斗，换装，技能特效等），不同平台（各个厂商的独立显卡，集成显卡以及不同型号的<span style="font-family: Calibri;">CPU</span>），不同系统进行了各种测试，限于篇幅这里只挑出了一个有代表性的例子。</span></div>
<p><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-family: Times New Roman; font-size: small;"> </span><span style="font-family: Times New Roman; font-size: small;"> </span></p>
<div><strong>作者简介</strong><span style="font-size: small;">：</span></div>
<div><span style="font-size: small;"><strong>卢卷彬</strong><strong><span style="font-family: Calibri;"> </span></strong>是英特尔公司的应用工程师，他和国内几家大的游戏公司有着多年的合作，帮助他们在英特尔平台上优化游戏客户端的性能。</span></div>
<div><span style="font-size: small;"><strong>丛越</strong><strong><span style="font-family: Calibri;"> </span></strong>有<span style="font-family: Calibri;">8</span>年以上的游戏开发经验，他参加了中国最早期的<span style="font-family: Calibri;">3D MMORPG</span>的开发，有着非常丰富的经验。丛越现在就职于腾讯，主要负责游戏和引擎的开发。<span style="font-family: Calibri;"> </span></span></div>
<div><span style="font-size: small;"><span style="font-family: Calibri;"><strong>Kiefer Kuah</strong> </span>是英特尔的软件工程师，他主要负责游戏在英特尔平台上的优化工作。</span></div>
<div> </div>
<p> Appendix A:</p>
<p>Platform Configuration:CPU:  Intel Core i7-2720QM @ 2.20GHz, with HD 3000 graphics</p>
<div>Memory: 8GB DDR3 1333Mhz</div>
<div>HD: Intel 160G SSD</div>
<div>OS: Windows 7 Professional, 64bit</div>
<div>Graphics Driver: 8.15.10.2509</div>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2011/12/26/gpa-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《XNA游戏开发》Game1类的方法与字段</title>
		<link>http://software.intel.com/zh-cn/blogs/2011/12/16/xnagame1/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2011/12/16/xnagame1/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 02:41:13 +0000</pubDate>
		<dc:creator>xy8cn</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2011/12/16/xnagame1/</guid>
		<description><![CDATA[  在上一篇内容中，我们了解到建好项目后生成的Game1类是继承自Microsoft.Xna.Framework.Game类型，然后再重写其中的方法，也就是说，我们的游戏主体这个Game1并不一定非要是这样的命名，当然你可以更改一个其他的名字，但是在改类名后，对应的在Program类的Main法中new的对象得相对应的变更为你改过的类型。 一、Game1中的字段： GraphicsDeviceManager graphics; SpriteBatch spriteBatch; 其中GraphicsDeviceManager为绘制界面管理类型。 SpriteBatch 为精灵处理类型（绘制处理类型）。 二、构造方法： 01.public Game1() { 02. graphics = new GraphicsDeviceManager(this); //初始化为界面管理对象 03. Content.RootDirectory = "Content"; //设置内容读取的目录 04.} 构造方法中：将graphics对象先创建出来，并规定Content的目录在Content文件夹之下。 三、Initialize方法： 01.protected override void Initialize() { 02. base.Initialize(); 03.} 作用：改写原父类型的初始方法。 说明：因为Microsoft已经把繁复的初始内写在父类型当中变得相当简化，直接调用base(基底类型)使用即可所以可以让我们专心在游戏重点的初始化。 也就是说，Microsoft为我们提供可更改初如化的机会。 四、LoadContent方法： 01.protected override void LoadContent() { 02. spriteBatch = new SpriteBatch(GraphicsDevice); 03.} 作用：在游戏启动时加载资源，如声音、图片、3D模型、字体等。 说明：方法中根据GraphicsDevice（绘制界面）创建了spriteBatch（绘制处理）对象。同时可以看到，在LoadContent方法中，并没有Base.LoadContent()方法，因为父类为Game基础来，在该类中并不需要去加载游戏资源，只有在我们制作游戏时才需要加载资源。 五、UnloadContent方法： 01.protected [...]]]></description>
			<content:encoded><![CDATA[<p> </p>
<p>在上一篇内容中，我们了解到建好项目后生成的Game1类是继承自Microsoft.Xna.Framework.Game类型，然后再重写其中的方法，也就是说，我们的游戏主体这个Game1并不一定非要是这样的命名，当然你可以更改一个其他的名字，但是在改类名后，对应的在Program类的Main法中new的对象得相对应的变更为你改过的类型。</p>
<p>一、Game1中的字段：</p>
<p>GraphicsDeviceManager graphics;</p>
<p>SpriteBatch spriteBatch;</p>
<p>其中GraphicsDeviceManager为绘制界面管理类型。</p>
<p>SpriteBatch 为精灵处理类型（绘制处理类型）。</p>
<p>二、构造方法：</p>
<p>01.public Game1() {<br />
02. graphics = new GraphicsDeviceManager(this); //初始化为界面管理对象<br />
03. Content.RootDirectory = "Content"; //设置内容读取的目录<br />
04.}<br />
构造方法中：将graphics对象先创建出来，并规定Content的目录在Content文件夹之下。</p>
<p>三、Initialize方法：</p>
<p>01.protected override void Initialize() {<br />
02. base.Initialize();<br />
03.}<br />
作用：改写原父类型的初始方法。</p>
<p>说明：因为Microsoft已经把繁复的初始内写在父类型当中变得相当简化，直接调用base(基底类型)使用即可所以可以让我们专心在游戏重点的初始化。</p>
<p>也就是说，Microsoft为我们提供可更改初如化的机会。</p>
<p>四、LoadContent方法：<br />
01.protected override void LoadContent() {<br />
02. spriteBatch = new SpriteBatch(GraphicsDevice);<br />
03.}<br />
作用：在游戏启动时加载资源，如声音、图片、3D模型、字体等。<br />
说明：方法中根据GraphicsDevice（绘制界面）创建了spriteBatch（绘制处理）对象。同时可以看到，在LoadContent方法中，并没有Base.LoadContent()方法，因为父类为Game基础来，在该类中并不需要去加载游戏资源，只有在我们制作游戏时才需要加载资源。</p>
<p>五、UnloadContent方法：</p>
<p>01.protected override void UnloadContent() { ... }<br />
该重写方法是用来回收内容。在关闭游戏时，需要将游戏资源释放掉可以在该方法中完成。</p>
<p>六、Update方法：</p>
<p>01.protected override void Update(GameTime gameTime) {<br />
02. if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)<br />
03. this.Exit();<br />
04. base.Update(gameTime);<br />
05.}<br />
作用：重写了逻辑更新的方法。</p>
<p>其中：GameTime对象可以取得游戏时间。</p>
<p>GamePad对象可以得知玩家1是否按下了倒退键而退出游戏。</p>
<p>七、Draw方法：</p>
<p>01.protected override void Draw(GameTime gameTime) {<br />
02. GraphicsDevice.Clear(Color.CornflowerBlue);<br />
03. base.Draw(gameTime);<br />
04.}<br />
作用：重写了绘制游戏的部分。</p>
<p>说明：使用GameDevice对象Clear方法，把画面清成淡蓝色，同时也调用父类型进行运作。</p>
<p>八、注意Update与Draw方法：</p>
<p>1.Update跟Draw会连续进行每秒钟60HZ的更新速度来跑动游戏。</p>
<p>2.其他几个方法，分别为游戏启动时或关闭时进行调用。</p>
<p>3.如果我们想控制游戏的速度，可以通过Update中的GameTime定义</p>
<p>通过以上介绍，大概对XNA框架中，一些基本类及方法的作用及说明有了简单的了解。在以后的内容中，我们再详细介绍每个方法中如何编写代码，实现游戏的运行。</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2011/12/16/xnagame1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>《XNA游戏开发》简介</title>
		<link>http://software.intel.com/zh-cn/blogs/2011/12/16/xna/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2011/12/16/xna/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 02:40:21 +0000</pubDate>
		<dc:creator>xy8cn</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2011/12/16/xna/</guid>
		<description><![CDATA[  一、XNA简介 XNA是基于DirectX的游戏开发环境。 以C# 为开发语言 以 .NET Framework 为基础、并加入游戏应用所需之函式库所构成的 XNA Framework 可开发XNA for Windows Phone游戏，Xbox游戏，PC游戏等。 二、XNA Versions XNA Game Studio Express XNA Game Studio 2.0（VS2005） XNA Game Studio 3.0（VS2008） XNA Game Studio 3.1（VS2008） XNA Game Studio 4.0（VS2010） 官方介绍 ：http://msdn.microsoft.com/zh-cn/windowsphone/gg315893 相关工具包： Windows Phone Developer Tools工具包 以上SDK安装包可以在微软网站 三、创建项目 安装好SDK工具包后，可以打开VS来进行项目的创建，我这里使用的版本是VS2010,安装的是XNA Game Studio 4.0。 四、解决方案 创建好项目后，可以在解决方案管理器中看到以下内容。其中Program类中，放着整个游戏程序的入口点。 五、游戏的主函数 01.static void [...]]]></description>
			<content:encoded><![CDATA[<p> </p>
<p>一、XNA简介</p>
<p>XNA是基于DirectX的游戏开发环境。</p>
<p>以C# 为开发语言</p>
<p>以 .NET Framework 为基础、并加入游戏应用所需之函式库所构成的 XNA Framework<br />
可开发XNA for Windows Phone游戏，Xbox游戏，PC游戏等。</p>
<p>二、XNA Versions</p>
<p>XNA Game Studio Express<br />
XNA Game Studio 2.0（VS2005）<br />
XNA Game Studio 3.0（VS2008）<br />
XNA Game Studio 3.1（VS2008）<br />
XNA Game Studio 4.0（VS2010）<br />
官方介绍 ：http://msdn.microsoft.com/zh-cn/windowsphone/gg315893<br />
相关工具包：<br />
Windows Phone Developer Tools工具包<br />
以上SDK安装包可以在微软网站</p>
<p>三、创建项目<br />
安装好SDK工具包后，可以打开VS来进行项目的创建，我这里使用的版本是VS2010,安装的是XNA Game Studio 4.0。<br />
<img src="http://images.csdn.net/20111215/11.jpg" alt="null" /><br />
四、解决方案</p>
<p>创建好项目后，可以在解决方案管理器中看到以下内容。其中Program类中，放着整个游戏程序的入口点。<br />
<img src="http://images.csdn.net/20111215/2.jpg" alt="null" /><br />
五、游戏的主函数</p>
<p>01.static void Main(string[] args) { 02. using (Game1 game = new Game1()) { 03. game.Run(); 04.} 05.}<br />
通常每一个桌面应用程序都有一个Main方法，做为整个应用程序的入口点，其中的参数“args”的作用是在执行.exe文件的时候，可以将命令行参数传进方法中，从而进行对应的操作。 在方法体中，用using创建了Game1类型的对象game，并执行了Run()方法来启动整个游戏。</p>
<p>六、注意Program中的预编译指令<br />
01.#if WINDOWS || XBOX 02. //游戏在 Windows 平台和 XBOX 游戏是否会执行代码 03.#else 04. //游戏在WP7上时执行代码 05.#endif</p>
<p>七、关于Game1类</p>
<p>01.public class Game1 : Microsoft.Xna.Framework.Game { ...... }<br />
可以看到Game1类型，是继承Microsoft.Xna.Framework.Game类型的。另外再看下Game1类中的方法都使用了override关建字。</p>
<p><img src="http://images.csdn.net/20111215/33.jpg" alt="null" /><br />
从以上图可以看出来微软的XNA框架为我们提供的Game类，本身是可以完成游戏的执行的，我们所需要做的就是重写其在游戏执行过程中的一些方法，就可以完成自己游戏的开发。</p>
<p>下篇介绍Game1类中，这些方法及两个字段的作用。</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2011/12/16/xna/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>游戏服务器的架构设计</title>
		<link>http://software.intel.com/zh-cn/blogs/2011/12/16/400009430/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2011/12/16/400009430/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 02:39:29 +0000</pubDate>
		<dc:creator>smarttony</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[服务器]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2011/12/16/400009430/</guid>
		<description><![CDATA[  游戏服务器的设计是一项颇有挑战性的工作，游戏服务器的发展也由以前的单服结构转变为多服机构，甚至出现了bigworld引擎的分布式解决方案，最近了解到Unreal的服务器解决方案atlas也是基于集群的方式。 负载均衡是一个很复杂的课题，这里暂不谈bigworld和atlas的这类服务器的设计，更多的是基于功能和场景划分服务器结构。 首先说一下思路，服务器划分基于以下原则： 1：分离游戏中占用系统资源（cpu，内存，IO等）较多的功能，独立成服务器 2：在同一服务器架构下的不同游戏，应尽可能的复用某些服务器（进程级别的复用） 3：以多线程并发的编程方式适应多核处理器。 4：宁可在服务器之间多复制数据，也要保持清晰的数据流向 5：主要按照场景划分进程，若需按功能划分，必须保持整个逻辑足够的简单，并满足以上1，2点 服务器结构图： 各个服务器的简要说明： Gateway：应用网关，主要用于保持和client的连接，该服务器需要2种IO，对client采用高并发连接，低吞吐量的网络模型，如IOCP等，对服务器采用高吞吐量连接，如阻塞或异步IO。 网关主要有以下用途： 1：分担了网络IO资源 2：同时，也分担了网络消息包的加解密，压缩解压等cpu密集的操作。 3：隔离了client和内部服务器组，对client来说，它只需要知道网关的相关信息即可（ip和port）。 4：client由于一直和网关保持常连接，所以切换场景服务器等操作对client来说是透明的。 5：维护玩家登录状态 World Server 是一个控制中心，它负责把各种计算资源分布到各个服务器 它具有以下职责： 1：管理和维护多个Scene Server 2：管理和维护多个功能服务器，主要是同步数据到功能服务器 3：复杂转发其他服务器和Gateway之间的数据 4：实现其他需要跨场景的功能，如组队，聊天，帮派等 Phys Server 主要用于玩家移动，碰撞等检测 所有玩家的移动类操作都在该服务器上做检查，所以该服务器本身具备所有地图的地形等相关信息。具体检查过程是这样的：首先，Worldserver收到一个移动信息，WorldServer收到后向Phys Server请求检查，Phys Server检查成功后再返回给world Server，然后world server传递给相应的Scene Server. Scene Server 场景服务器，按场景划分，每个服务器负责的场景应该是可以配置的。理想情况下是可以动态调节的。 ItemMgr Server 物品管理服务器，负责所有物品的生产过程。在该服务器上存储一个物品掉落数据库，服务器初始化的时候载入到内存。任何需要产生物品的服务器均与该服务器直接通信 AIServer 又一个功能服务器，负责管理所有NPC的AI。AI服务器通常有2个输入，一个是Scene Server发送过来的玩家相关操作信息，另一个时钟Timer驱动，在这个设计中，对其他服务器来说，AIServer就是一个拥有很多个NPC的客户端。AIserver需要同步所有与AI相关的数据，包括很多玩家数据。由于AIServer的Timer驱动特性，可在很大程度上使用TBB程序库来发挥多核的性能。]]></description>
			<content:encoded><![CDATA[<p> </p>
<p>游戏服务器的设计是一项颇有挑战性的工作，游戏服务器的发展也由以前的单服结构转变为多服机构，甚至出现了bigworld引擎的分布式解决方案，最近了解到Unreal的服务器解决方案atlas也是基于集群的方式。</p>
<p>负载均衡是一个很复杂的课题，这里暂不谈bigworld和atlas的这类服务器的设计，更多的是基于功能和场景划分服务器结构。</p>
<p>首先说一下思路，服务器划分基于以下原则：<br />
1：分离游戏中占用系统资源（cpu，内存，IO等）较多的功能，独立成服务器<br />
2：在同一服务器架构下的不同游戏，应尽可能的复用某些服务器（进程级别的复用）<br />
3：以多线程并发的编程方式适应多核处理器。<br />
4：宁可在服务器之间多复制数据，也要保持清晰的数据流向<br />
5：主要按照场景划分进程，若需按功能划分，必须保持整个逻辑足够的简单，并满足以上1，2点</p>
<p>服务器结构图：</p>
<p><img src="http://images.csdn.net/20111215/1.jpg" alt="null" /><br />
各个服务器的简要说明：</p>
<p>Gateway：应用网关，主要用于保持和client的连接，该服务器需要2种IO，对client采用高并发连接，低吞吐量的网络模型，如IOCP等，对服务器采用高吞吐量连接，如阻塞或异步IO。</p>
<p>网关主要有以下用途：<br />
1：分担了网络IO资源<br />
2：同时，也分担了网络消息包的加解密，压缩解压等cpu密集的操作。<br />
3：隔离了client和内部服务器组，对client来说，它只需要知道网关的相关信息即可（ip和port）。<br />
4：client由于一直和网关保持常连接，所以切换场景服务器等操作对client来说是透明的。<br />
5：维护玩家登录状态</p>
<p>World Server 是一个控制中心，它负责把各种计算资源分布到各个服务器<br />
它具有以下职责：<br />
1：管理和维护多个Scene Server<br />
2：管理和维护多个功能服务器，主要是同步数据到功能服务器<br />
3：复杂转发其他服务器和Gateway之间的数据<br />
4：实现其他需要跨场景的功能，如组队，聊天，帮派等</p>
<p>Phys Server 主要用于玩家移动，碰撞等检测<br />
所有玩家的移动类操作都在该服务器上做检查，所以该服务器本身具备所有地图的地形等相关信息。具体检查过程是这样的：首先，Worldserver收到一个移动信息，WorldServer收到后向Phys Server请求检查，Phys Server检查成功后再返回给world Server，然后world server传递给相应的Scene Server.</p>
<p>Scene Server 场景服务器，按场景划分，每个服务器负责的场景应该是可以配置的。理想情况下是可以动态调节的。</p>
<p>ItemMgr Server 物品管理服务器，负责所有物品的生产过程。在该服务器上存储一个物品掉落数据库，服务器初始化的时候载入到内存。任何需要产生物品的服务器均与该服务器直接通信</p>
<p>AIServer 又一个功能服务器，负责管理所有NPC的AI。AI服务器通常有2个输入，一个是Scene Server发送过来的玩家相关操作信息，另一个时钟Timer驱动，在这个设计中，对其他服务器来说，AIServer就是一个拥有很多个NPC的客户端。AIserver需要同步所有与AI相关的数据，包括很多玩家数据。由于AIServer的Timer驱动特性，可在很大程度上使用TBB程序库来发挥多核的性能。</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2011/12/16/400009430/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android 游戏开发菜鸟之路（一）</title>
		<link>http://software.intel.com/zh-cn/blogs/2011/12/07/android-3/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2011/12/07/android-3/#comments</comments>
		<pubDate>Wed, 07 Dec 2011 09:01:35 +0000</pubDate>
		<dc:creator>whosemario</dc:creator>
				<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2011/12/07/android-3/</guid>
		<description><![CDATA[最近没有更新博客，原因之一就是在读《Pro Android Games》，其中一些样例游戏实在太有意思，忍不住又山寨一番，在Chapter3中介绍了第一个叫做Space Blaster的游戏，游戏规则蛮简单，就是你控制飞船躲过或者打击流星石。下面是一个游戏的截图： 工程总共有三个类，SpaceBlasterActivity、ArcadeGame和SpaceBlasterGame。第一个类是Android的Activity类；第二类继承了LinearLayout类，主要实现了onLayout函数（当View要为所有子对象分配大小和位置时，调用此方法），也就是说可以将游戏的初始化方法和产生周期性线程（模拟周期性的帧）放在这里。第三个SpaceBlasterGame类继承了ArcadeGame类，游戏的所有逻辑都在这里实现，例如各个Sprite之间的碰撞和显示。类的结构图如下： 接下来上一下这三个类之间的UML图吧，已经画了，不用怪可惜（⊙﹏⊙b汗）： 这里不会说明所有的函数，我的代码在这里，《Pro Android Games》一书网上也有它的示例的代码。这里主要说明几点个人觉得比较重要的地方： 1、 构造方法必须有两个参数的那个，否则main.xml无法解析； 2、 Bullets和Meteors都是用数组记录信息的，一开始用ArrayList容器，游戏玩玩就会崩溃； 然后就是细节问题，这个游戏很简单，没有算法，不够建议还是自己去实现一下，在这个过程中会发现很多细节点的！]]></description>
			<content:encoded><![CDATA[<p>最近没有更新博客，原因之一就是在读《Pro Android Games》，其中一些样例游戏实在太有意思，忍不住又山寨一番，在Chapter3中介绍了第一个叫做Space Blaster的游戏，游戏规则蛮简单，就是你控制飞船躲过或者打击流星石。下面是一个游戏的截图：</p>
<p><img src="http://images.csdn.net/20111207/101.jpg" alt="null" /><br />
工程总共有三个类，SpaceBlasterActivity、ArcadeGame和SpaceBlasterGame。第一个类是Android的Activity类；第二类继承了LinearLayout类，主要实现了onLayout函数（当View要为所有子对象分配大小和位置时，调用此方法），也就是说可以将游戏的初始化方法和产生周期性线程（模拟周期性的帧）放在这里。第三个SpaceBlasterGame类继承了ArcadeGame类，游戏的所有逻辑都在这里实现，例如各个Sprite之间的碰撞和显示。类的结构图如下：</p>
<p><img src="http://images.csdn.net/20111207/201.jpg" alt="null" /><br />
接下来上一下这三个类之间的UML图吧，已经画了，不用怪可惜（⊙﹏⊙b汗）：</p>
<p><img src="http://images.csdn.net/20111207/301.jpg" alt="null" /><br />
这里不会说明所有的函数，我的代码在这里，《Pro Android Games》一书网上也有它的示例的代码。这里主要说明几点个人觉得比较重要的地方：</p>
<p>1、 构造方法必须有两个参数的那个，否则main.xml无法解析；</p>
<p>2、 Bullets和Meteors都是用数组记录信息的，一开始用ArrayList容器，游戏玩玩就会崩溃；</p>
<p>然后就是细节问题，这个游戏很简单，没有算法，不够建议还是自己去实现一下，在这个过程中会发现很多细节点的！</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2011/12/07/android-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Android 游戏音效控制</title>
		<link>http://software.intel.com/zh-cn/blogs/2011/12/06/android-2/</link>
		<comments>http://software.intel.com/zh-cn/blogs/2011/12/06/android-2/#comments</comments>
		<pubDate>Tue, 06 Dec 2011 09:43:51 +0000</pubDate>
		<dc:creator>jgl5987</dc:creator>
				<category><![CDATA[Android 开发]]></category>
		<category><![CDATA[博客征文专栏]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://software.intel.com/zh-cn/blogs/2011/12/06/android-2/</guid>
		<description><![CDATA[  游戏音效就是我们在玩游戏时出现的音乐，这个也是每个游戏必备的一部分，但有是你做游戏的背景音乐有间断的感觉的话，我们可以用getCurrentPosition()这个方法来判断一下声音播放的偏移。其实这个也是非常简单的。只要我们在代码当中设置好(初始化声音)和(加载音效资源)就可以了，别的就和音乐播放器的代码差不多，像开始，停止。不多说了，我们还是先来看看代码当中是怎么实现音效的吧： //音效的音量 　　intstreamVolume; 　　 　　//定义SoundPool对象 　　privateSoundPoolsoundPool; 　　 　　//定义HASH表 　　privateHashMapsoundPoolMap; 　　 　　/*************************************************************** 　　*Function:initSounds(); 　　*Parameters:null 　　*Returns:None. 　　*Description:初始化声音系统 　　*Notes:none. 　　***************************************************************/ 　　publicvoidinitSounds(){ 　　//初始化soundPool对象,第一个参数是允许有多少个声音流同时播放,第2个参数是声音类型,第三个参数是声音的品质 　　soundPool=newSoundPool(100,AudioManager.STREAM_MUSIC,100); 　　 　　//初始化HASH表 　　soundPoolMap=newHashMap(); 　　 　　//获得声音设备和设备音量 　　AudioManagermgr=(AudioManager)context.getSystemService(Context.AUDIO_SERVICE); 　　streamVolume=mgr.getStreamVolume(AudioManager.STREAM_MUSIC); 　　} 　　 　　/*************************************************************** 　　*Function:loadSfx(); 　　*Parameters:null 　　*Returns:None. 　　*Description:加载音效资源 　　*Notes:none. 　　***************************************************************/ 　　publicvoidloadSfx(intraw,intID){ 　　//把资源中的音效加载到指定的ID(播放的时候就对应到这个ID播放就行了) 　　soundPoolMap.put(ID,soundPool.load(context,raw,ID)); 　　} 　　 　　/*************************************************************** 　　*Function:play(); 　　*Parameters:sound:要播放的音效的ID,loop:循环次数 　　*Returns:None. 　　*Description:播放声音 　　*Notes:none. 　　***************************************************************/ 　　publicvoidplay(intsound,intuLoop){ 　　soundPool.play(soundPoolMap.get(sound),streamVolume,streamVolume,1,uLoop,1f); 　　}]]></description>
			<content:encoded><![CDATA[<p> </p>
<p>游戏音效就是我们在玩游戏时出现的音乐，这个也是每个游戏必备的一部分，但有是你做游戏的背景音乐有间断的感觉的话，我们可以用getCurrentPosition()这个方法来判断一下声音播放的偏移。其实这个也是非常简单的。只要我们在代码当中设置好(初始化声音)和(加载音效资源)就可以了，别的就和音乐播放器的代码差不多，像开始，停止。不多说了，我们还是先来看看代码当中是怎么实现音效的吧：<br />
//音效的音量<br />
　　intstreamVolume;<br />
　　<br />
　　//定义SoundPool对象<br />
　　privateSoundPoolsoundPool;<br />
　　<br />
　　//定义HASH表<br />
　　privateHashMapsoundPoolMap;<br />
　　<br />
　　/***************************************************************<br />
　　*Function:initSounds();<br />
　　*Parameters:null<br />
　　*Returns:None.<br />
　　*Description:初始化声音系统<br />
　　*Notes:none.<br />
　　***************************************************************/<br />
　　publicvoidinitSounds(){<br />
　　//初始化soundPool对象,第一个参数是允许有多少个声音流同时播放,第2个参数是声音类型,第三个参数是声音的品质<br />
　　soundPool=newSoundPool(100,AudioManager.STREAM_MUSIC,100);<br />
　　<br />
　　//初始化HASH表<br />
　　soundPoolMap=newHashMap();<br />
　　<br />
　　//获得声音设备和设备音量<br />
　　AudioManagermgr=(AudioManager)context.getSystemService(Context.AUDIO_SERVICE);<br />
　　streamVolume=mgr.getStreamVolume(AudioManager.STREAM_MUSIC);<br />
　　}<br />
　　<br />
　　/***************************************************************<br />
　　*Function:loadSfx();<br />
　　*Parameters:null<br />
　　*Returns:None.<br />
　　*Description:加载音效资源<br />
　　*Notes:none.<br />
　　***************************************************************/<br />
　　publicvoidloadSfx(intraw,intID){<br />
　　//把资源中的音效加载到指定的ID(播放的时候就对应到这个ID播放就行了)<br />
　　soundPoolMap.put(ID,soundPool.load(context,raw,ID));<br />
　　}<br />
　　<br />
　　/***************************************************************<br />
　　*Function:play();<br />
　　*Parameters:sound:要播放的音效的ID,loop:循环次数<br />
　　*Returns:None.<br />
　　*Description:播放声音<br />
　　*Notes:none.<br />
　　***************************************************************/<br />
　　publicvoidplay(intsound,intuLoop){<br />
　　soundPool.play(soundPoolMap.get(sound),streamVolume,streamVolume,1,uLoop,1f);<br />
　　}</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/zh-cn/blogs/2011/12/06/android-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

