<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_马宁的嵌入式开发研究</title><subtitle type="text">Windows Phone, XNA, Windows Embedded, Windows Mobile</subtitle><id>http://feed.cnblogs.com/blog/u/31097/rss</id><updated>2011-10-07T06:16:29Z</updated><author><name>马宁</name><uri>http://www.cnblogs.com/aawolf/</uri></author><generator>CNBlogs BlogServer</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aawolf/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/31097/rss"/><entry><id>http://www.cnblogs.com/aawolf/archive/2011/10/03/2198607.html</id><title type="text">在Windows Phone应用中添加OpenXLive数据分析功能</title><summary type="text">作者：马宁源代码下载地址：http://files.cnblogs.com/aawolf/OpenXLiveAnalytics.zip 在Windows Phone中很多应用需要数据查询功能，来确定每天的用户数和应用使用次数等关键信息。在iOS和Android中已经有非常多的类似应用了，比如Flurry, 友盟等，但是Windows Phone上只有Flurry提供了此类功能。但由于很多开发者来说，没有中文支持的Flurry有些可望而不可即。 其实，在OpenXLive也提供数据分析的支持，只是之前更多是用于游戏数据的统计和查询上。在这篇文章里，我们将介绍，如何将OpenXLive的数据分析.</summary><published>2011-10-03T09:36:00Z</published><updated>2011-10-03T09:36:00Z</updated><author><name>马宁</name><uri>http://www.cnblogs.com/aawolf/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aawolf/archive/2011/10/03/2198607.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aawolf/archive/2011/10/03/2198607.html"/><content type="html">&#xD;
&lt;p&gt;作者：马宁&lt;/p&gt;&lt;p&gt;源代码下载地址：&lt;/p&gt;&lt;p&gt;&lt;a href="http://files.cnblogs.com/aawolf/OpenXLiveAnalytics.zip"&gt;http://files.cnblogs.com/aawolf/OpenXLiveAnalytics.zip&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;在Windows Phone中很多应用需要数据查询功能，来确定每天的用户数和应用使用次数等关键信息。在iOS和Android中已经有非常多的类似应用了，比如Flurry, 友盟等，但是Windows Phone上只有Flurry提供了此类功能。但由于很多开发者来说，没有中文支持的Flurry有些可望而不可即。&lt;/p&gt;  &lt;p&gt;其实，在OpenXLive也提供数据分析的支持，只是之前更多是用于游戏数据的统计和查询上。在这篇文章里，我们将介绍，如何将OpenXLive的数据分析功能应用在Windows Phone的应用程序开发中。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;创建OpenXLive应用&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;因为所有的统计数据都是保存在OpenXLive的云端存储服务器中，所以，我们要在OpenXLive网站上创建一个应用。&lt;/p&gt;  &lt;p&gt;首先，登录OpenXLive网站(&lt;a href="http://www.openxlive.com/"&gt;http://www.openxlive.com/&lt;/a&gt;)，如果没有帐号，我们需要创建一个相应的帐号，通过电子邮件激活帐号之后，我们还需要升级成为开发者。&lt;/p&gt;  &lt;p&gt;在激活邮件地址后，我们重新回到OpenXLive的网站，输入用户名和密码后，我们会进入用户资料编辑界面，在这里，我们可以填写完整的个人信息，使得朋友在网络中更加容易地找到你。用户资料中最后一项为&amp;#8220;Developer Information&amp;#8221;。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031735226475.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; margin-right: auto; margin-left: auto; float: none; display: block;background-image: none;" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/aawolf/201110/20111003173525638.png" width="591" height="417" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;点击&amp;#8220;Developer Information&amp;#8221;，进入开发者申请界面：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201110/20111003173527407.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; margin-right: auto; margin-left: auto; float: none; display: block;background-image: none;" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031735317536.png" width="401" height="447" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;在这个页面，我们要填写开发者类型（个人/公司/学生）、国家、城市、地址、电话、IM等信息。在填写完成后，我们会看到下面的开发者注册成功界面。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201110/20111003173533893.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; margin-right: auto; margin-left: auto; float: none; display: block;background-image: none;" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/aawolf/201110/20111003173536529.png" width="545" height="238" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;在这个界面中，我们可以进入OpenXLive开发者首页，查看开发指南，也可以直接点击&amp;#8220;Create New Game&amp;#8221;，进入开发者后台。&lt;/p&gt;  &lt;p&gt;进入开发者后台界面之后，如果您之前已经创建过游戏，会显示已创建游戏的列表，如上图所示。在用户图标的下方，有Create New Game的按钮，点击，进入创建新游戏的界面。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031735425541.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; margin-right: auto; margin-left: auto; float: none; display: block;background-image: none;" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031735465918.png" width="539" height="548" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;添加OpenXLive引用&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;为了引用OpenXLive的程序集，我们必须首先下载OpenXLive SDK并且完成安装。下载地址是：&lt;a href="http://developer.openxlive.com/sdk/download/"&gt;http://developer.openxlive.com/sdk/download/&lt;/a&gt; 目前的版本是0.9.6.&lt;/p&gt;  &lt;p&gt;创建Windows Phone Silverlight应用后，我们要获取OpenXLive的程序集。在开始菜单中，找到OpenXLive应用，其中OpenXLive目录下包括XNA和Silverlight两个目录。我们从Silverlight目录中取出OpenXLive.dll程序集，拷贝至我们的应用所在的目录。&lt;/p&gt;  &lt;p&gt;然后在Solution Explorer中，右键单击References，选择Add Reference。在对话框中选择Browse页面，然后找到OpenXLive.dll，将其添加到工程中。&lt;/p&gt;  &lt;p&gt;因为我们不需要OpenXLive的界面，所以只需要添加OpenXLive.dll即可。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031735512947.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; margin-right: auto; margin-left: auto; float: none; display: block;background-image: none;" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031735556596.png" width="579" height="471" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;在添加完引用之后，我们就可以添加代码了。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;创建Session&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;接下来，我们要为工程添加OpenXLive的引用代码。打开工程中的App.xaml.cs文件，首先找到Application_Launching方法：&lt;/p&gt;  &lt;pre &gt;&lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Application_Launching(&lt;span &gt;object&lt;/span&gt; sender, LaunchingEventArgs e)&#xD;
{&#xD;
    &lt;span &gt;if&lt;/span&gt; (XLiveGameManager.CurrentSession == &lt;span &gt;null&lt;/span&gt;)&#xD;
    {&#xD;
        GameSession session = XLiveGameManager.CreateSession(&lt;span &gt;"xxxxxxxx"&lt;/span&gt;);&#xD;
        session.CreateSessionCompleted += &lt;span &gt;new&lt;/span&gt; AsyncEventHandler(session_CreateSessionCompleted);&#xD;
        session.Open();&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;我们在这个方法里判断是否已经有Game Session存在，如果没有的话，则调用XLiveGameManager的CreateSession方法来创建一个Game Session，需要传递的参数，是我们在OpenXLive网站上获得的Secret Key。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;然后，我们可以添加一个CreateSessionCompleted事件处理函数，来获取Game Session是否被创建的事件。当然，这个事件处理函数是可选的，我们可以不添加。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;最后，调用Game Session的Open方法，来打开Game Session就可以了。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;然后是关闭这个Game Session，在Application_Closing方法里调用Close方法。&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Application_Closing(&lt;span &gt;object&lt;/span&gt; sender, ClosingEventArgs e)&#xD;
{&#xD;
    &lt;span &gt;if&lt;/span&gt; (XLiveGameManager.CurrentSession != &lt;span &gt;null&lt;/span&gt;)&#xD;
    {&#xD;
        XLiveGameManager.CurrentSession.Close();&#xD;
    }&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;如果我们不显式调用Close方法的话，Game Session在创建24小时后会自动过期，所以也不会造成太大的影响，唯一的问题是游戏时间将失效。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;为了支持墓碑机制，我们还要特意在Application_Activated和Application_Deactivated函数中，添加对于墓碑机制的处理。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Application_Activated(&lt;span &gt;object&lt;/span&gt; sender, ActivatedEventArgs e)&#xD;
{&#xD;
    XLiveGameManager.Activated();&#xD;
}&#xD;
&#xD;
&lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Application_Deactivated(&lt;span &gt;object&lt;/span&gt; sender, DeactivatedEventArgs e)&#xD;
{&#xD;
    XLiveGameManager.Deactivated();&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;好了，到这里我们就大功告成了，够简单吧？&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;查看数据结果&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;当我们的Windows Phone软件发布之后，就可以在OpenXLive网站上查看应用程序的在线数据了。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;首先，我们访问OpenXLive网站&lt;a href="http://www.openxlive.com/"&gt;http://www.openxlive.com/&lt;/a&gt; ，在网页右上角点击Login登录，成功登录之后，我们会在OpenXLive首页右上角的位置看到下面的网页：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031735588840.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; margin-right: auto; margin-left: auto; float: none; display: block;background-image: none;" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031736021758.png" width="391" height="146" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;点击My Game，可以进入游戏后台管理的Dashboard中。如果用户登录后，访问OpenXLive开发者网站(&lt;a href="http://developer.openxlive.com/"&gt;http://developer.openxlive.com/&lt;/a&gt;)，在右侧的Dashboard中选择&amp;#8220;Managed your games&amp;#8221;也可以进入开发者后台管理界面。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031736042607.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; margin-right: auto; margin-left: auto; float: none; display: block;background-image: none;" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031736079245.png" width="607" height="348" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;上图所示，包括我们创建的所有游戏和应用，点击应用图标会进入应用的产业页面，点击应用标题，则进入应用的管理界面。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031736093474.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; margin-right: auto; margin-left: auto; float: none; display: block;background-image: none;" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/aawolf/201110/20111003173613603.png" width="674" height="255" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;点击管理界面中的Statistics按钮，进入数据分析界面。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;在数据分析界面中，我们可以查看一些通用信息，比如创建Session的数量、使用人数等信息。点击View，则进入详细数据分析界面。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031736158453.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; margin-right: auto; margin-left: auto; float: none; display: block;background-image: none;" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031736174252.png" width="690" height="396" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;在详细数据分析界面中，我们可以考到用户数、Session数的时间分布，按照月、周、日来进行显示等。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031736219396.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; margin-right: auto; margin-left: auto; float: none; display: block;background-image: none;" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/aawolf/201110/201110031736241889.png" width="615" height="360" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;写在最后&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;好了，到这里，我们就介绍完OpenXLive目前的数据分析功能。下一步，OpenXLive还会加入自定义事件、地理分布信息等功能。&lt;/p&gt;  &#xD;
&lt;img src="http://www.cnblogs.com/aawolf/aggbug/2198607.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aawolf/archive/2011/10/03/2198607.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aawolf/archive/2011/08/25/2153827.html</id><title type="text">Kinect for Windows SDK开发初体验（四）景深数据</title><summary type="text">作者：马宁 终于可以坐下来继续这个系列了，在微博和博客园里，已经有无数人催过了，实在抱歉，一个人的精力毕竟是有限的，但我会抽出一切可用的时间，尽可能尽快完成。 这一章我们来说说景深数据Depth Data，这是Kinect的Depth Camera为我们提供的全新功能，以往的技术只能够通过图像识别来完成的一些工作，我们可以借助景深来帮我们完成了。比如，前景与背景的分离，以前只能将背景设置为蓝屏或者绿屏，但是现在有了景深数据，我们就可以很容易地将前景物体从背景中分离出来。当然，需要特别说明的是，Depth Camera技术是由以色列公司PrimeSense提供的。 程序布局 在这一章里，我们要完</summary><published>2011-08-25T14:26:00Z</published><updated>2011-08-25T14:26:00Z</updated><author><name>马宁</name><uri>http://www.cnblogs.com/aawolf/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aawolf/archive/2011/08/25/2153827.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aawolf/archive/2011/08/25/2153827.html"/><content type="html">&lt;p&gt;作者：马宁 &lt;p&gt;终于可以坐下来继续这个系列了，在微博和博客园里，已经有无数人催过了，实在抱歉，一个人的精力毕竟是有限的，但我会抽出一切可用的时间，尽可能尽快完成。 &lt;p&gt;这一章我们来说说景深数据Depth Data，这是Kinect的Depth Camera为我们提供的全新功能，以往的技术只能够通过图像识别来完成的一些工作，我们可以借助景深来帮我们完成了。比如，前景与背景的分离，以前只能将背景设置为蓝屏或者绿屏，但是现在有了景深数据，我们就可以很容易地将前景物体从背景中分离出来。当然，需要特别说明的是，Depth Camera技术是由以色列公司PrimeSense提供的。 &lt;p&gt;&lt;strong&gt;程序布局&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;在这一章里，我们要完成的工作非常简单，根据物体距离Kinect的远近，设置成不同的颜色。首先，我们要创建一个新的WPF工程，然后添加一个Image控件：&lt;pre &gt;&lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Image&lt;/span&gt; &lt;span &gt;Height&lt;/span&gt;&lt;span &gt;="240"&lt;/span&gt; &lt;span &gt;HorizontalAlignment&lt;/span&gt;&lt;span &gt;="Left"&lt;/span&gt; &lt;span &gt;Margin&lt;/span&gt;&lt;span &gt;="62,41,0,0"&lt;/span&gt; &lt;span &gt;Name&lt;/span&gt;&lt;span &gt;="image1"&lt;/span&gt; &lt;span &gt;Stretch&lt;/span&gt;&lt;span &gt;="Fill"&lt;/span&gt; &lt;span &gt;VerticalAlignment&lt;/span&gt;&lt;span &gt;="Top"&lt;/span&gt; &lt;span &gt;Width&lt;/span&gt;&lt;span &gt;="320"&lt;/span&gt; &lt;span &gt;/&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;p&gt;然后是MainWindow.xaml.cs中的核心代码，这部分代码与之前的代码大体一致，所以不做过多解释了：&lt;pre &gt;&lt;span &gt;//Kinect RuntimeRuntime &lt;/span&gt;&#xD;
&#xD;
Runtime nui = &lt;span &gt;new&lt;/span&gt; Runtime(); &#xD;
&#xD;
&lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Window_Loaded(&lt;span &gt;object&lt;/span&gt; sender, RoutedEventArgs e)&#xD;
&#xD;
{&#xD;
&#xD;
&lt;span &gt;//UseDepthAndPlayerIndex and UseSkeletalTracking&lt;/span&gt;&#xD;
&#xD;
nui.Initialize(RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseSkeletalTracking);&#xD;
&#xD;
&lt;span &gt;//register for event&lt;/span&gt;&#xD;
&#xD;
nui.DepthFrameReady += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;ImageFrameReadyEventArgs&amp;gt;(nui_DepthFrameReady);&#xD;
&#xD;
&lt;span &gt;//DepthAndPlayerIndex ImageType&lt;/span&gt;&#xD;
&#xD;
nui.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240,&#xD;
&#xD;
ImageType.DepthAndPlayerIndex);&#xD;
&#xD;
}&#xD;
&#xD;
&lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Window_Closed(&lt;span &gt;object&lt;/span&gt; sender, EventArgs e)&#xD;
&#xD;
{&#xD;
&#xD;
nui.Uninitialize();&#xD;
&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;p&gt;唯一需要大家注意的是，我们在初始化函数中传递的参数是RuntimeOptions.UseDepthAndPlayerIndex，这表示景深信息中会包含PlayerIndex的信息。接下来，我们就要花点时间来理解DepthAndPlayerIndex的实际结构。&#xD;
&lt;p&gt;&lt;strong&gt;理解DepthAndPlayerIndex&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;先来看DepthFrameReady事件处理函数，如下：&lt;pre &gt;&lt;span &gt;void&lt;/span&gt; nui_DepthFrameReady(&lt;span &gt;object&lt;/span&gt; sender, ImageFrameReadyEventArgs e)&#xD;
&#xD;
{&#xD;
&#xD;
&lt;span &gt;// Convert depth information for a pixel into color information &lt;/span&gt;&#xD;
&#xD;
&lt;span &gt;byte&lt;/span&gt;[] ColoredBytes = GenerateColoredBytes(e.ImageFrame); &#xD;
&#xD;
&lt;span &gt;// create an image based on the colored bytes &lt;/span&gt;&#xD;
&#xD;
PlanarImage image = e.ImageFrame.Image;&#xD;
&#xD;
image1.Source = BitmapSource.Create( &#xD;
&#xD;
image.Width, image.Height, 96, 96, PixelFormats.Bgr32, &#xD;
&#xD;
&lt;span &gt;null&lt;/span&gt;, ColoredBytes, image.Width * PixelFormats.Bgr32.BitsPerPixel / 8); &#xD;
&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;p&gt;DepthFrameReady事件会返回一个ImageFrame对象，其中会包含一个PlanarImage对象。PlanarImage对象会包含一个byte[]数组，这个数组中包含每个像素的深度信息。这个数组的特点是，从图像左上角开始、从左到右，然后从上到下。&#xD;
&lt;p&gt;该数组中每个像素由两个bytes表示，我们需要通过位运算的办法来获取每个像素的位置信息。&#xD;
&lt;p&gt;如果是Depth Image Type，将第二个bytes左移8位即可。&lt;pre &gt;Distance (0,0) = (&lt;span &gt;int&lt;/span&gt;)(Bits[0] | Bits[1] &amp;lt;&amp;lt; 8 );&lt;/pre&gt;&lt;pre &gt;&lt;/pre&gt;&#xD;
&lt;p&gt;如果是DepthAndPlayerIndex Image Type，第一个bytes右移三位去掉Player Index信息，第二个bytes左移5位。&lt;pre &gt;Distance (0,0) =(&lt;span &gt;int&lt;/span&gt;)(Bits[0] &amp;gt;&amp;gt; 3 | Bits[1] &amp;lt;&amp;lt; 5);&lt;/pre&gt;&lt;pre &gt;&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;DepthAndPlayerIndex image类型的第一个bytes前三位包括Player Index信息。Player Index最多包含六个可能值：&#xD;
&lt;p&gt;0， 没有玩家；1，玩家1；2，玩家2，以此类推。&#xD;
&lt;p&gt;我们可以用下面的方法来获取Player Index信息：&lt;pre &gt;&lt;span &gt;private&lt;/span&gt; &lt;span &gt;static&lt;/span&gt; &lt;span &gt;int&lt;/span&gt; GetPlayerIndex(&lt;span &gt;byte&lt;/span&gt; firstFrame)&#xD;
&#xD;
{&#xD;
&#xD;
&lt;span &gt;//returns 0 = no player, 1 = 1st player, 2 = 2nd player...&lt;/span&gt;&#xD;
&#xD;
&lt;span &gt;return&lt;/span&gt; (&lt;span &gt;int&lt;/span&gt;)firstFrame &amp;amp; 7; &#xD;
&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;p&gt;&lt;strong&gt;设置颜色&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;接下来，我们创建一个bytes数组，用来存储颜色值。&lt;pre &gt;&lt;span &gt;if&lt;/span&gt; (distance &amp;lt;= 900)&#xD;
&#xD;
{&#xD;
&#xD;
&lt;span &gt;//we are very close&lt;/span&gt;&#xD;
&#xD;
colorFrame[index + BlueIndex] = 255;&#xD;
&#xD;
colorFrame[index + GreenIndex] = 0;&#xD;
&#xD;
colorFrame[index + RedIndex] = 0;&#xD;
&#xD;
}&#xD;
&#xD;
&lt;span &gt;if&lt;/span&gt; (GetPlayerIndex(depthData[depthIndex]) &amp;gt; 0)&#xD;
&#xD;
{&#xD;
&#xD;
&lt;span &gt;//we are the farthest&lt;/span&gt;&#xD;
&#xD;
colorFrame[index + BlueIndex] = 0;&#xD;
&#xD;
colorFrame[index + GreenIndex] = 255;&#xD;
&#xD;
colorFrame[index + RedIndex] = 255;&#xD;
&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;当然，我们最好是设置几个边界值，来定义不同距离的不同颜色：&lt;pre &gt;&lt;span &gt;//equal coloring for monochromatic histogram&lt;/span&gt;&#xD;
&#xD;
var intensity = CalculateIntensityFromDepth(distance);&#xD;
&#xD;
colorFrame[index + BlueIndex] = intensity;&#xD;
&#xD;
colorFrame[index + GreenIndex] = intensity;&#xD;
&#xD;
colorFrame[index + RedIndex] = intensity;&#xD;
&#xD;
&lt;span &gt;const&lt;/span&gt; &lt;span &gt;float&lt;/span&gt; MaxDepthDistance = 4000; &lt;span &gt;// max value returned&lt;/span&gt;&#xD;
&#xD;
&lt;span &gt;const&lt;/span&gt; &lt;span &gt;float&lt;/span&gt; MinDepthDistance = 850; &lt;span &gt;// min value returned&lt;/span&gt;&#xD;
&#xD;
&lt;span &gt;const&lt;/span&gt; &lt;span &gt;float&lt;/span&gt; MaxDepthDistanceOffset = MaxDepthDistance - MinDepthDistance;&#xD;
&#xD;
&lt;span &gt;public&lt;/span&gt; &lt;span &gt;static&lt;/span&gt; &lt;span &gt;byte&lt;/span&gt; CalculateIntensityFromDepth(&lt;span &gt;int&lt;/span&gt; distance)&#xD;
&#xD;
{&#xD;
&#xD;
&lt;span &gt;//formula for calculating monochrome intensity for histogram&lt;/span&gt;&#xD;
&#xD;
&lt;span &gt;return&lt;/span&gt; (&lt;span &gt;byte&lt;/span&gt;)(255 - (255 * Math.Max(distance - MinDepthDistance, 0) / (MaxDepthDistanceOffset)));&#xD;
&#xD;
}&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;最后，把所有代码放在一起，我们设定的颜色值为：&#xD;
&lt;p&gt;蓝色，小于900；900到2000，绿色；大于2000，红色&#xD;
&lt;p&gt;代码如下：&lt;pre &gt;&lt;span &gt;private&lt;/span&gt; &lt;span &gt;byte&lt;/span&gt;[] GenerateColoredBytes(ImageFrame imageFrame)&#xD;
        {    &#xD;
            &lt;span &gt;int&lt;/span&gt; height = imageFrame.Image.Height;    &#xD;
            &lt;span &gt;int&lt;/span&gt; width = imageFrame.Image.Width;     &#xD;
            &#xD;
            &lt;span &gt;//Depth data for each pixel    &lt;/span&gt;&#xD;
            Byte[] depthData = imageFrame.Image.Bits;      &#xD;
            &#xD;
            &lt;span &gt;//colorFrame contains color information for all pixels in image    &lt;/span&gt;&#xD;
            &lt;span &gt;//Height x Width x 4 (Red, Green, Blue, empty byte)    &lt;/span&gt;&#xD;
            Byte[] colorFrame = &lt;span &gt;new&lt;/span&gt; &lt;span &gt;byte&lt;/span&gt;[imageFrame.Image.Height * imageFrame.Image.Width * 4];     &#xD;
            &#xD;
            &lt;span &gt;//Bgr32  - Blue, Green, Red, empty byte    &lt;/span&gt;&#xD;
            &lt;span &gt;//Bgra32 - Blue, Green, Red, transparency     &lt;/span&gt;&#xD;
            &lt;span &gt;//You must set transparency for Bgra as .NET defaults a byte to 0 = fully transparent     &lt;/span&gt;&#xD;
            &lt;span &gt;//hardcoded locations to Blue, Green, Red (BGR) index positions           &lt;/span&gt;&#xD;
            &lt;span &gt;const&lt;/span&gt; &lt;span &gt;int&lt;/span&gt; BlueIndex = 0;    &#xD;
            &lt;span &gt;const&lt;/span&gt; &lt;span &gt;int&lt;/span&gt; GreenIndex = 1;    &#xD;
            &lt;span &gt;const&lt;/span&gt; &lt;span &gt;int&lt;/span&gt; RedIndex = 2;     &#xD;
            var depthIndex = 0;    &#xD;
            &#xD;
            &lt;span &gt;for&lt;/span&gt; (var y = 0; y &amp;lt; height; y++)    &#xD;
            {                &#xD;
                var heightOffset = y * width;         &#xD;
                &#xD;
                &lt;span &gt;for&lt;/span&gt; (var x = 0; x &amp;lt; width; x++)        &#xD;
                {            &#xD;
                    var index = ((width - x - 1) + heightOffset) * 4;             &#xD;
                    &#xD;
                    &lt;span &gt;//var distance = GetDistance(depthData[depthIndex], depthData[depthIndex + 1]);            &lt;/span&gt;&#xD;
                    var distance = GetDistanceWithPlayerIndex(depthData[depthIndex], depthData[depthIndex + 1]);             &#xD;
                    &#xD;
                    &lt;span &gt;if&lt;/span&gt; (distance &amp;lt;= 900)            &#xD;
                    {                &#xD;
                        &lt;span &gt;//we are very close                &lt;/span&gt;&#xD;
                        colorFrame[index + BlueIndex] = 255;                &#xD;
                        colorFrame[index + GreenIndex] = 0;                &#xD;
                        colorFrame[index + RedIndex] = 0;                   &#xD;
                    }            &#xD;
                    &lt;span &gt;else&lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (distance &amp;gt; 900 &amp;amp;&amp;amp; distance &amp;lt; 2000)            &#xD;
                    {                &#xD;
                        &lt;span &gt;//we are a bit further away                &lt;/span&gt;&#xD;
                        colorFrame[index + BlueIndex] = 0;                &#xD;
                        colorFrame[index + GreenIndex] = 255;                &#xD;
                        colorFrame[index + RedIndex] = 0;            &#xD;
                    }            &#xD;
                    &lt;span &gt;else&lt;/span&gt; &lt;span &gt;if&lt;/span&gt; (distance &amp;gt; 2000)            &#xD;
                    {                &#xD;
                        &lt;span &gt;//we are the farthest                &lt;/span&gt;&#xD;
                        colorFrame[index + BlueIndex] = 0;                &#xD;
                        colorFrame[index + GreenIndex] = 0;                &#xD;
                        colorFrame[index + RedIndex] = 255;            &#xD;
                    }             &#xD;
                    &#xD;
                    &lt;span &gt;//Color a player            &lt;/span&gt;&#xD;
                    &lt;span &gt;if&lt;/span&gt; (GetPlayerIndex(depthData[depthIndex]) &amp;gt; 0)            &#xD;
                    {                &#xD;
                        &lt;span &gt;//we are the farthest                &lt;/span&gt;&#xD;
                        colorFrame[index + BlueIndex] = 0;                &#xD;
                        colorFrame[index + GreenIndex] = 255;                &#xD;
                        colorFrame[index + RedIndex] = 255;            &#xD;
                    }             &#xD;
                    &#xD;
                    &lt;span &gt;//jump two bytes at a time            &lt;/span&gt;&#xD;
                    depthIndex += 2;        &#xD;
                &#xD;
                }    &#xD;
            }     &#xD;
            &#xD;
            &lt;span &gt;return&lt;/span&gt; colorFrame;&#xD;
        }&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;程序的现实效果如下图：&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108252226245933.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="clip_image001" border="0" alt="clip_image001" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108252226253392.png" width="527" height="353"&gt;&lt;/a&gt;&#xD;
&lt;p&gt;&lt;strong&gt;写到最后&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;到这里，我们就将Kinect SDK中NUI的基本内容介绍完了，接下来，我们要介绍Audio部分，或者借助一些实际的例子，来看一下Kinect SDK的实际应用。&lt;/p&gt; &lt;img src="http://www.cnblogs.com/aawolf/aggbug/2153827.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aawolf/archive/2011/08/25/2153827.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aawolf/archive/2011/08/03/2125692.html</id><title type="text">马宁的Windows Phone 7.1初体验（三）——Tile</title><summary type="text">作者：马宁 前边介绍Push Notification时，其实已经谈到了Tile Notification。在Windows Phone 7.1中，Smart Tile得到了极大的提高。我们不但可以控制Tile的动画显示、内容和背景切换，而且还能够为同一个应用提供两个Tile，比如一个天气预报的应用程序，就可以在手机的首页上显示多个Tile，一个是北京的天气，另一个是上海的天气等。 实现Application Tile MSDN上的文章写的又臭又长，其实挺简单的事情，弄得那么复杂。我试着改写了一下例子，加入到应用的一个Button点击事件里： // Application Tile is al</summary><published>2011-08-02T18:36:00Z</published><updated>2011-08-02T18:36:00Z</updated><author><name>马宁</name><uri>http://www.cnblogs.com/aawolf/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aawolf/archive/2011/08/03/2125692.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aawolf/archive/2011/08/03/2125692.html"/><content type="html">&lt;p&gt;&lt;b&gt;作者：马宁&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;前边介绍Push Notification时，其实已经谈到了Tile Notification。在Windows Phone 7.1中，Smart Tile得到了极大的提高。我们不但可以控制Tile的动画显示、内容和背景切换，而且还能够为同一个应用提供两个Tile，比如一个天气预报的应用程序，就可以在手机的首页上显示多个Tile，一个是北京的天气，另一个是上海的天气等。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;实现Application Tile&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;MSDN上的文章写的又臭又长，其实挺简单的事情，弄得那么复杂。我试着改写了一下例子，加入到应用的一个Button点击事件里：&lt;/p&gt;  &lt;pre &gt;&lt;span &gt;// Application Tile is always the first Tile, even if it is not pinned to Start.&lt;/span&gt;&#xD;
            ShellTile TileToFind = ShellTile.ActiveTiles.First();&#xD;
&#xD;
            &lt;span &gt;// Set the properties to update for the Application Tile.&lt;/span&gt;&#xD;
            &lt;span &gt;// Empty strings for the text values and URIs will result in the property being cleared.&lt;/span&gt;&#xD;
            StandardTileData NewTileData = &lt;span &gt;new&lt;/span&gt; StandardTileData&#xD;
            {&#xD;
                Title = &lt;span &gt;&amp;quot;Title&amp;quot;&lt;/span&gt;,&#xD;
                BackgroundImage = &lt;span &gt;new&lt;/span&gt; Uri(&lt;span &gt;&amp;quot;Background.png&amp;quot;&lt;/span&gt;, UriKind.Relative),&#xD;
                Count = 2,&#xD;
                BackTitle = &lt;span &gt;&amp;quot;Back Tilte&amp;quot;&lt;/span&gt;,&#xD;
                BackBackgroundImage = &lt;span &gt;new&lt;/span&gt; Uri(&lt;span &gt;&amp;quot;Background2.png&amp;quot;&lt;/span&gt;, UriKind.Relative),&#xD;
                BackContent = &lt;span &gt;&amp;quot;This is BackContent&amp;quot;&lt;/span&gt;&#xD;
            };&#xD;
&#xD;
            &lt;span &gt;// Update the Application Tile&lt;/span&gt;&#xD;
            TileToFind.Update(NewTileData);&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;首先，我们要引用Microsoft.Phone.Shell命名空间，然后通过ShellTile.ActiveTiles.First()方法来获取应用最主要的ShellTile.每个应用至少会有一个Tile，所以不用担心该对象为空。然后我们创建一个StandardTileData对象，为其中的属性赋值。属性分为两组，每组都会有背景图片、标题和内容，显示位置如下图所示。如果设置两组Tile属性，则Tile在显示一段时间后会自动切换。最后，我们调用ShellTile对象的Update方法，将StandardTileData对象传递进去，就完成了新Tile的设置。BackgroundImage和BackBackgroundImage指定的是图片的URI，可以是本地的图片，也可以是来自网络的图片。我们使用的两个图片，都是以Content方式加入到工程中的图片。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030235567616.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image002" border="0" alt="clip_image002" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030235574617.jpg" width="527" height="226" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;当我们将程序部署到设备或模拟器上时，首先会在Application List里出现对应的图标。我们长按图标，会出现一个菜单，选择Pin to start，会将应用程序的图标显示到手机首页上。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;运行应用程序，点击Button后，Tile会被更新成新的式样。两张背景和内容会交替显示，显示效果如下图所示：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030235579318.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image004" border="0" alt="clip_image004" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030235576843.jpg" width="269" height="500" /&gt;&lt;/a&gt; &lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030235576319.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image006" border="0" alt="clip_image006" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030235588304.jpg" width="271" height="500" /&gt;&lt;/a&gt; &lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030235587781.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image008" border="0" alt="clip_image008" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030235585306.jpg" width="268" height="499" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;实现 Secondary Tile&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;在完成了Application Tile的显示之后，我们接下来要实现更复杂的Secondary Tile，当然，我们可以添加多个Tile。在实现Secondary Tile时，有两个技术点需要实现，一个是Tile的添加与显示；另一个则是，程序启动时如何区分是由哪个Tile点击启动应用的。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;首先，我们来看如何添加Secondary Tile的代码：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;// Look to see whether the Tile already exists and if so, don't try to create it again.&lt;/span&gt;&#xD;
            ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x =&amp;gt; x.NavigationUri.ToString().Contains(&lt;span &gt;&amp;quot;DefaultTitle=FromTile&amp;quot;&lt;/span&gt;));&#xD;
&#xD;
            &lt;span &gt;// Create the Tile if we didn't find that it already exists.&lt;/span&gt;&#xD;
            &lt;span &gt;if&lt;/span&gt; (TileToFind == &lt;span &gt;null&lt;/span&gt;)&#xD;
            {&#xD;
                &lt;span &gt;// Create the Tile object and set some initial properties for the Tile.&lt;/span&gt;&#xD;
                &lt;span &gt;// The Count value of 12 shows the number 12 on the front of the Tile. Valid values are 1-99.&lt;/span&gt;&#xD;
                &lt;span &gt;// A Count value of 0 indicates that the Count should not be displayed.&lt;/span&gt;&#xD;
                StandardTileData NewTileData = &lt;span &gt;new&lt;/span&gt; StandardTileData&#xD;
                {&#xD;
                    BackgroundImage = &lt;span &gt;new&lt;/span&gt; Uri(&lt;span &gt;&amp;quot;Background.png&amp;quot;&lt;/span&gt;, UriKind.Relative),&#xD;
                    Title = &lt;span &gt;&amp;quot;Secondary Tile&amp;quot;&lt;/span&gt;,&#xD;
                    Count = 12,&#xD;
                    BackTitle = &lt;span &gt;&amp;quot;Back of Tile&amp;quot;&lt;/span&gt;,&#xD;
                    BackContent = &lt;span &gt;&amp;quot;Welcome to the back of the Tile&amp;quot;&lt;/span&gt;,&#xD;
                    BackBackgroundImage = &lt;span &gt;new&lt;/span&gt; Uri(&lt;span &gt;&amp;quot;Background2.png&amp;quot;&lt;/span&gt;, UriKind.Relative)&#xD;
                };&#xD;
&#xD;
                &lt;span &gt;// Create the Tile and pin it to Start. This will cause a navigation to Start and a deactivation of our application.&lt;/span&gt;&#xD;
                ShellTile.Create(&lt;span &gt;new&lt;/span&gt; Uri(&lt;span &gt;&amp;quot;/MainPage.xaml?DefaultTitle=FromTile&amp;quot;&lt;/span&gt;, UriKind.Relative), NewTileData);&#xD;
            }&#xD;
            &lt;span &gt;else&lt;/span&gt;&#xD;
            {&#xD;
                TileToFind.Delete();&#xD;
            }&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;首先调用ShellTile.ActiveTiles.FirstOrDefault方法，获取在NavigationUri属性中包含&amp;#8220;DefaultTitle=FromTile&amp;#8221;字样的ShellTile对象，如果获取到的ShellTile对象为空，则创建Secondary Tile，否则调用ShellTile的Delete方法，删除这个Tile。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;创建Secondary Tile的过程，首先创建StandardTileData对象，将显示的各个参数进行赋值，这一步与Application Tile相同；然后，调用ShellTile的Create方法，第一个参数是URI，即点击该Tile后，调用Page的命令行，可以包含参数，第二个参数是StandardTileData对象，用于指定显示式样。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;需要注意的是，如果Page命令行指定不对，会引起用户点击Tile时，应用直接退出，由于无法调试，第一次接触这个问题时，会找不到具体的原因。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;Secondary Tile显示效果如下：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030235584782.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image010" border="0" alt="clip_image010" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030235592307.jpg" width="253" height="470" /&gt;&lt;/a&gt; &lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030235597008.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image012" border="0" alt="clip_image012" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/20110803023559945.jpg" width="248" height="468" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;接下来，我们就要处理区分不同Tile点击的事件了，需要重载MainForm的OnNavigatedTo方法：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;protected&lt;/span&gt; &lt;span &gt;override&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)&#xD;
        {&#xD;
            &lt;span &gt;string&lt;/span&gt; &lt;span &gt;value&lt;/span&gt; = &lt;span &gt;null&lt;/span&gt;;&#xD;
&#xD;
            &lt;span &gt;if&lt;/span&gt; (&lt;span &gt;this&lt;/span&gt;.NavigationContext.QueryString != &lt;span &gt;null&lt;/span&gt;)&#xD;
            {&#xD;
                &lt;span &gt;this&lt;/span&gt;.NavigationContext.QueryString.TryGetValue(&lt;span &gt;&amp;quot;DefaultTitle&amp;quot;&lt;/span&gt;, &lt;span &gt;out&lt;/span&gt; &lt;span &gt;value&lt;/span&gt;);&#xD;
                &lt;span &gt;if&lt;/span&gt; (&lt;span &gt;value&lt;/span&gt; != &lt;span &gt;null&lt;/span&gt;)&#xD;
                {&#xD;
                    textBoxTitle.Text = &lt;span &gt;value&lt;/span&gt;;&#xD;
                }&#xD;
                &lt;span &gt;else&lt;/span&gt;&#xD;
                {&#xD;
                    textBoxTitle.Text = &lt;span &gt;&amp;quot;FromMain&amp;quot;&lt;/span&gt;;&#xD;
                }&#xD;
            }&#xD;
&#xD;
            &lt;span &gt;base&lt;/span&gt;.OnNavigatedTo(e);&#xD;
        }&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;通过NavigationContext.QueryString的TryGetValue方法来获取DefaultTitle参数的值，如果无法获取到该值，则认为该点击来自第一个Tile，相反则来自第二个Tile。我们将参数显示在主页面的文本框里，当然，实际应用中可以有更加复杂的业务逻辑。界面显示效果如下：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/20110803023559421.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image014" border="0" alt="clip_image014" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030236009582.jpg" width="280" height="526" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;到这里，我们简单介绍了如何添加Tile、修改Tile内容，除此之外，还有如何修改Tile的初始值，指定Tile更新的时间间隔等。在这里，我们就不介绍了，大家可以参考又臭又长的MSDN文档，这部分不长，我可以保证。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;写在最后&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;好了，到这里，我们正式将Windows Phone 7.1中的Tile编程的内容介绍完了。Windows Phone采用的是HUB方式，对于功能进行分类，所以，就要求Tile具备更丰富的显示方式和展现形式。而且，多个应用可以对应于一个Tile，同样一个应用也可以对应多个Tile，这样极大提高了主页与应用之间交互的丰富程度。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;当然，具体的Tile，还要在实际的开发中使用，才能真正了解其优缺点。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;OpenXLive杯Windows Phone游戏开发大赛&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030236003519.jpg"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="clip_image016" border="0" alt="clip_image016" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108030236004632.jpg" width="212" height="225" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;OpenXLive杯Windows Phone游戏开发大赛，是由OpenXLive联合国内知名的开发者社区：DevDiv、智机网、WPMind、Silverlight银光中国和XNA游戏世界，一起举办的针对Windows Phone游戏开发的比赛。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://www.openxlive.net/posts/news/40"&gt;http://www.openxlive.net/posts/news/40&lt;/a&gt;&lt;/p&gt; &lt;img src="http://www.cnblogs.com/aawolf/aggbug/2125692.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aawolf/archive/2011/08/03/2125692.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aawolf/archive/2011/08/02/2124442.html</id><title type="text">马宁的Windows Phone 7.1初体验（二）——Push Notification</title><summary type="text">作者：马宁 Push Notification并不是Windows Phone 7.1的新功能，但是之前的文章里对这部分都缺少详细的分析，所以姑且就把Push Notification放到这部分里吧。 很多iOS开发者都将WP7里的Push Notification说成抄袭iOS的产物，孰不知，微软才是Push Notification技术的先行者，Windows Mobile时代的Push Mail技术可以说是独步天下，连Symbian也要授权使用相关的技术。 Push Notification的技术为什么越来越重要，其实这跟移动设备的特点紧密相关，移动设备网络的不稳定性，决定了以Socke</summary><published>2011-08-01T17:24:00Z</published><updated>2011-08-01T17:24:00Z</updated><author><name>马宁</name><uri>http://www.cnblogs.com/aawolf/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aawolf/archive/2011/08/02/2124442.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aawolf/archive/2011/08/02/2124442.html"/><content type="html">&#xD;
&lt;p&gt;&lt;strong&gt;作者：马宁&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Push Notification并不是Windows Phone 7.1的新功能，但是之前的文章里对这部分都缺少详细的分析，所以姑且就把Push Notification放到这部分里吧。&lt;/p&gt; &lt;p&gt;很多iOS开发者都将WP7里的Push Notification说成抄袭iOS的产物，孰不知，微软才是Push Notification技术的先行者，Windows Mobile时代的Push Mail技术可以说是独步天下，连Symbian也要授权使用相关的技术。&lt;/p&gt; &lt;p&gt;Push Notification的技术为什么越来越重要，其实这跟移动设备的特点紧密相关，移动设备网络的不稳定性，决定了以Socket为代表的强连接方式并不适用，所以大家更多选择HTTP协议作为主要的通讯方式。但是HTTP的特点是，设备找服务器很容易，通过URL就可以了，但服务器找设备就难上加难了，因为设备会随时切换移动网络，IP地址之类的经常性失效。当然设备端轮询的方式可以解决这个问题，但移动设备的电源、网络都是稀缺资源。所以，OS级别的Push Notification技术就变成了一种珍贵的战略资源，而且，在封闭式的操作系统中，只有OS厂商提供的Push Notification才能够获得最好的效率。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Push Notification简介&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;目前，Windows Phone支持三种Push Notification方式：Toast Notifications、Tile Notifications和Raw Notifications，我不想翻译成中文名字了，因为&amp;#8220;吐司&amp;#8221;之类的翻译无法帮助理解。&lt;/p&gt; &lt;p&gt;Toast Notifications，当我们的程序没有运行时，我们希望有一种形式可以通知用户，并且让用户调用对应的应用，就像收到SMS时，调用Messaging程序一样。运行效果如下图，当用户点击Toast时，可以调用对应的程序。&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108020123526989.jpg"&gt;&lt;img style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline;background-image: none;" title="clip_image002" border="0" alt="clip_image002" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108020123538842.jpg" width="340" height="213" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Tile Notifications，用于更新启动界面上的Tile，可以通过Tile Notifications设置Tile的背景图片、Count和Title等属性，各属性显示位置如下图所示。我们可以通过该技术来提示用户，我们的应用有新的事件发生，比如SNS上有多少新的回复等。&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108020123533269.jpg"&gt;&lt;img style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline;background-image: none;" title="clip_image004" border="0" alt="clip_image004" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108020123533792.jpg" width="343" height="148" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Raw Notifications，最简单，当你的应用程序运行时，可以接收Raw Notification信息，如果程序没有运行，则接受不到Raw Notification。&lt;/p&gt; &lt;p&gt;接下来，我们会以Toast Notifications为例详细介绍，Push Notification的原理和使用方法。&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108020123531807.jpg"&gt;&lt;img style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline;background-image: none;" title="clip_image006" border="0" alt="clip_image006" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108020123549822.jpg" width="643" height="422" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;首先，还是引用这张广为流传的图示吧，确实是目前能够找到的最详细的示意图了。下面是步骤叙述：&lt;/p&gt; &lt;p&gt;1-3，应用通过调用HttpNotificationChannel接口，向Microsoft Push Notification Service (MPNS)请求一个URI，这个URI会在服务器端发送Notification消息时，作为验证发送目标的唯一标识；这样做的一个好处是，当同一个设备上有多个应用在监听Notification时，不会相互干扰。&lt;/p&gt; &lt;p&gt;4. 应用会将获得的URI传到自己的服务器上，这个URI会存储在自己的服务器上，用于发送Push Notification时调用。URI的传递和存储方式，由开发者自己决定，不过要保证传输过程的加密，以及存储时的安全性。接下来的实例里，传递和存储URI的方式就很有创意。&lt;/p&gt; &lt;p&gt;5-6. 当服务器端有信息要通知应用时，需要向MPNS发起一个Http请求，而MPNS将请求转发到相应的设备上，设备上的应用接到Push Notification的消息后，进行相应的处理。&lt;/p&gt; &lt;p&gt;其实过程挺简单，被MSDN文档说得神乎其神。接下来，我们挨个看一下各个类型的Notification。偷点懒，不自己写Sample Code了，请大家去下面的链接里下载。不过注意Sample Code的更新，最近有同学因为更新不及时，而影响了开发进度。&lt;/p&gt; &lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ff431744(VS.92).aspx"&gt;http://msdn.microsoft.com/en-us/library/ff431744(VS.92).aspx&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;初始化 Notifications&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;首先是Toast Notifications，这种Notification在实际应用中最为有效，不但可以提示用户有新的消息，而且还让用户选择是否打开当时的应用。不过比起iOS的Notifications来，Toast Notifications能够容纳的信息量实在有限。所以，开发者要适当&amp;#8220;浓缩&amp;#8221;需要推送的消息。&lt;/p&gt; &lt;p&gt;我们按照调用的顺序，依次来分析代码，首先来看客户端部分ToastNotificationClient的代码：&lt;/p&gt;&lt;pre &gt;&lt;span &gt;/// Holds the push channel that is created or found.&lt;/span&gt;&#xD;
            HttpNotificationChannel pushChannel;&#xD;
&#xD;
            &lt;span &gt;// The name of our push channel.&lt;/span&gt;&#xD;
            &lt;span &gt;string&lt;/span&gt; channelName = &lt;span &gt;"ToastSampleChannel"&lt;/span&gt;;&#xD;
&#xD;
            InitializeComponent();&#xD;
&#xD;
            &lt;span &gt;// Try to find the push channel.&lt;/span&gt;&#xD;
            pushChannel = HttpNotificationChannel.Find(channelName);&#xD;
&#xD;
            &lt;span &gt;// If the channel was not found, then create a new connection to the push service.&lt;/span&gt;&#xD;
            &lt;span &gt;if&lt;/span&gt; (pushChannel == &lt;span &gt;null&lt;/span&gt;)&#xD;
            {&#xD;
                pushChannel = &lt;span &gt;new&lt;/span&gt; HttpNotificationChannel(channelName);&#xD;
&#xD;
                &lt;span &gt;// Register for all the events before attempting to open the channel.&lt;/span&gt;&#xD;
                pushChannel.ChannelUriUpdated += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;NotificationChannelUriEventArgs&amp;gt;(PushChannel_ChannelUriUpdated);&#xD;
                pushChannel.ErrorOccurred += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;NotificationChannelErrorEventArgs&amp;gt;(PushChannel_ErrorOccurred);&#xD;
&#xD;
                &lt;span &gt;// Register for this notification only if you need to receive the notifications while your application is running.&lt;/span&gt;&#xD;
                pushChannel.ShellToastNotificationReceived += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;NotificationEventArgs&amp;gt;(PushChannel_ShellToastNotificationReceived);&#xD;
&#xD;
                pushChannel.Open();&#xD;
&#xD;
                &lt;span &gt;// Bind this new channel for toast events.&lt;/span&gt;&#xD;
                pushChannel.BindToShellToast();&#xD;
&#xD;
            }&#xD;
            &lt;span &gt;else&lt;/span&gt;&#xD;
            {&#xD;
                &lt;span &gt;// The channel was already open, so just register for all the events.&lt;/span&gt;&#xD;
                pushChannel.ChannelUriUpdated += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;NotificationChannelUriEventArgs&amp;gt;(PushChannel_ChannelUriUpdated);&#xD;
                pushChannel.ErrorOccurred += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;NotificationChannelErrorEventArgs&amp;gt;(PushChannel_ErrorOccurred);&#xD;
&#xD;
                &lt;span &gt;// Register for this notification only if you need to receive the notifications while your application is running.&lt;/span&gt;&#xD;
                pushChannel.ShellToastNotificationReceived += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;NotificationEventArgs&amp;gt;(PushChannel_ShellToastNotificationReceived);&#xD;
&#xD;
                &lt;span &gt;// Display the URI for testing purposes. Normally, the URI would be passed back to your web service at this point.&lt;/span&gt;&#xD;
                System.Diagnostics.Debug.WriteLine(pushChannel.ChannelUri.ToString());&#xD;
                MessageBox.Show(String.Format(&lt;span &gt;"Channel Uri is {0}"&lt;/span&gt;,&#xD;
                    pushChannel.ChannelUri.ToString()));&#xD;
&#xD;
            }&#xD;
&lt;/pre&gt;&lt;pre &gt;&lt;/pre&gt;&lt;pre &gt;&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&lt;p&gt;代码比较多，我们逐步来看，首先要声明一个HttpNotificationChannel的变量，命名空间为Microsoft.Phone.Notification。接下来，声明该Notification Channel的名称，该名称是Channel的唯一标识名，不能与其他Channel重复。接下来，我们调用HttpNotificationChannel的静态方法Find来查找，当前的Channel是否存在，如果存在则返回HttpNotificationChannel对象实例，不存在则返回空。如果该程序从未在当前设备上运行过，则HttpNotificationChannel对象为空，只要运行过一次，则能够通过Find方法来获取对象实例。&lt;/p&gt;&#xD;
&lt;p&gt;先来说未创建Channel的情况，创建HttpNotificationChannel的对象，并将Channel名称作为参数传递进去。然后处理该对象的两个事件：ChannelUriUpdated和ErrorOccurred。当URI发生变化时，会触发ChannelUriUpdated事件，我们在创建Channel对象时，会触发该事件，另外一个ErrorOccurred事件，则用于错误处理。&lt;/p&gt;&#xD;
&lt;p&gt;当程序已经在运行时，默认是接收不到Toast Notification消息的，所以，我们还需要处理ShellToastNotificationReceived事件，当程序运行时，也可以接收到相应的消息。&lt;/p&gt;&#xD;
&lt;p&gt;然后调用HttpNotificationChannel的Open方法，打开该Channel，最后是BindToShellToast方法，通知Shell，该Notification的Channel已经被创建。&lt;/p&gt;&#xD;
&lt;p&gt;获取Channel后的代码与之大体类似，但我们可以通过HttpNotificationChannel的ChannelUri属性来获取Channel的URI，该URI值就是需要传递给我们自己服务器的唯一值，标记了该设备上的该Channel。&lt;/p&gt;&#xD;
&lt;p&gt;而创建Channel后，我们也可以获取URI的值，不过我们需要在ChannelUriUpdated事件处理函数里获取该URI值：&lt;/p&gt;&lt;pre &gt;&lt;span &gt;void&lt;/span&gt; PushChannel_ChannelUriUpdated(&lt;span &gt;object&lt;/span&gt; sender, NotificationChannelUriEventArgs e)&#xD;
        {&#xD;
&#xD;
            Dispatcher.BeginInvoke(() =&amp;gt;&#xD;
            {&#xD;
                &lt;span &gt;// Display the new URI for testing purposes.   Normally, the URI would be passed back to your web service at this point.&lt;/span&gt;&#xD;
                System.Diagnostics.Debug.WriteLine(e.ChannelUri.ToString());&#xD;
                MessageBox.Show(String.Format(&lt;span &gt;"Channel Uri is {0}"&lt;/span&gt;,&#xD;
                    e.ChannelUri.ToString()));&#xD;
&#xD;
            });&#xD;
        }&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;到此为止，我们已经完成了Notification Channel的创建，并且获得了唯一标识的URI。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;触发Notification&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;接下来，我们来看Server的代码。我们自己的Server与Microsoft Push Notification Server（MPNS）之间是通过Http协议，使用HttpWebRequest来发送请求。理论上来说，我们也可以使用客户端程序向MPNS发送Notification请求。为什么要用ASP.NET来编写，最主要的原因还是在于客户端应用要将URI传递给Server端，显然基于ASP.NET的Web应用在这方面是最容易的。&lt;/p&gt;&#xD;
&lt;p&gt;不过我们的实例中，没有客户端将URI传递给服务器端的代码，而是采用了最简单的办法：由开发者直接将URI拷贝到ASP.NET的Web应用中。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/20110802012354661.jpg"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline;background-image: none;" title="clip_image008" border="0" alt="clip_image008" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/20110802012354628.jpg" width="596" height="379" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;接下来，我们来看Server端的代码：&lt;/p&gt;&lt;pre &gt;&lt;span &gt;try&lt;/span&gt;&#xD;
            {&#xD;
                &lt;span &gt;// Get the Uri that the Microsoft Push Notification Service returns to the Push Client when creating a notification channel.&lt;/span&gt;&#xD;
                &lt;span &gt;// Normally, a web service would listen for Uri's coming from the web client and maintain a list of Uri's to send&lt;/span&gt;&#xD;
                &lt;span &gt;// notifications out to.&lt;/span&gt;&#xD;
                &lt;span &gt;string&lt;/span&gt; subscriptionUri = TextBoxUri.Text.ToString();&#xD;
&#xD;
&#xD;
                HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(subscriptionUri);&#xD;
&#xD;
                &lt;span &gt;// We will create a HTTPWebRequest that posts the toast notification to the Microsoft Push Notification Service.&lt;/span&gt;&#xD;
                &lt;span &gt;// HTTP POST is the only allowed method to send the notification.&lt;/span&gt;&#xD;
                sendNotificationRequest.Method = &lt;span &gt;"POST"&lt;/span&gt;;&#xD;
&#xD;
                &lt;span &gt;// The optional custom header X-MessageID uniquely identifies a notification message. &lt;/span&gt;&#xD;
                &lt;span &gt;// If it is present, the // same value is returned in the notification response. It must be a string that contains a UUID.&lt;/span&gt;&#xD;
                &lt;span &gt;// sendNotificationRequest.Headers.Add("X-MessageID", "&amp;lt;UUID&amp;gt;");&lt;/span&gt;&#xD;
&#xD;
                &lt;span &gt;// Create the toast message.&lt;/span&gt;&#xD;
                &lt;span &gt;string&lt;/span&gt; toastMessage = &lt;span &gt;"&amp;lt;?xml version=\"1.0\" encoding=\"utf-8\"?&amp;gt;"&lt;/span&gt; +&#xD;
                &lt;span &gt;"&amp;lt;wp:Notification xmlns:wp=\"WPNotification\"&amp;gt;"&lt;/span&gt; +&#xD;
                   &lt;span &gt;"&amp;lt;wp:Toast&amp;gt;"&lt;/span&gt; +&#xD;
                        &lt;span &gt;"&amp;lt;wp:Text1&amp;gt;"&lt;/span&gt; + TextBoxTitle.Text.ToString() + &lt;span &gt;"&amp;lt;/wp:Text1&amp;gt;"&lt;/span&gt; +&#xD;
                        &lt;span &gt;"&amp;lt;wp:Text2&amp;gt;"&lt;/span&gt; + TextBoxSubTitle.Text.ToString() + &lt;span &gt;"&amp;lt;/wp:Text2&amp;gt;"&lt;/span&gt; +&#xD;
                        &lt;span &gt;"&amp;lt;wp:Param&amp;gt;/Page2.xaml?NavigatedFrom=Toast Notification"&lt;/span&gt; + TextBoxSubTitle.Text.ToString() + &lt;span &gt;"&amp;lt;/wp:Param&amp;gt;"&lt;/span&gt; +&#xD;
                   &lt;span &gt;"&amp;lt;/wp:Toast&amp;gt; "&lt;/span&gt; +&#xD;
                &lt;span &gt;"&amp;lt;/wp:Notification&amp;gt;"&lt;/span&gt;;&#xD;
&#xD;
                &lt;span &gt;// Sets the notification payload to send.&lt;/span&gt;&#xD;
                &lt;span &gt;byte&lt;/span&gt;[] notificationMessage = Encoding.Default.GetBytes(toastMessage);&#xD;
&#xD;
                &lt;span &gt;// Sets the web request content length.&lt;/span&gt;&#xD;
                sendNotificationRequest.ContentLength = notificationMessage.Length;&#xD;
                sendNotificationRequest.ContentType = &lt;span &gt;"text/xml"&lt;/span&gt;;&#xD;
                sendNotificationRequest.Headers.Add(&lt;span &gt;"X-WindowsPhone-Target"&lt;/span&gt;, &lt;span &gt;"toast"&lt;/span&gt;);&#xD;
                sendNotificationRequest.Headers.Add(&lt;span &gt;"X-NotificationClass"&lt;/span&gt;, &lt;span &gt;"2"&lt;/span&gt;);&#xD;
&#xD;
&#xD;
                &lt;span &gt;using&lt;/span&gt; (Stream requestStream = sendNotificationRequest.GetRequestStream())&#xD;
                {&#xD;
                    requestStream.Write(notificationMessage, 0, notificationMessage.Length);&#xD;
                }&#xD;
&#xD;
                &lt;span &gt;// Send the notification and get the response.&lt;/span&gt;&#xD;
                HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();&#xD;
                &lt;span &gt;string&lt;/span&gt; notificationStatus = response.Headers[&lt;span &gt;"X-NotificationStatus"&lt;/span&gt;];&#xD;
                &lt;span &gt;string&lt;/span&gt; notificationChannelStatus = response.Headers[&lt;span &gt;"X-SubscriptionStatus"&lt;/span&gt;];&#xD;
                &lt;span &gt;string&lt;/span&gt; deviceConnectionStatus = response.Headers[&lt;span &gt;"X-DeviceConnectionStatus"&lt;/span&gt;];&#xD;
&#xD;
                &lt;span &gt;// Display the response from the Microsoft Push Notification Service.  &lt;/span&gt;&#xD;
                &lt;span &gt;// Normally, error handling code would be here.  In the real world, because data connections are not always available,&lt;/span&gt;&#xD;
                &lt;span &gt;// notifications may need to be throttled back if the device cannot be reached.&lt;/span&gt;&#xD;
                TextBoxResponse.Text = notificationStatus + &lt;span &gt;" | "&lt;/span&gt; + deviceConnectionStatus + &lt;span &gt;" | "&lt;/span&gt; + notificationChannelStatus;&#xD;
            }&#xD;
            &lt;span &gt;catch&lt;/span&gt; (Exception ex)&#xD;
            {&#xD;
                TextBoxResponse.Text = &lt;span &gt;"Exception caught sending update: "&lt;/span&gt; + ex.ToString();&#xD;
            }&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;Server端程序的主体是调用HttpWebRequest对象，来实现HTTP POST的方法。发送的消息以XML形式呈现，在上面代码中表现为toastMessage字符串，wp:Toast指定Notification类型，wp:Text1指定标题，wp:Text2指定子标题，wp:Param指定传递的参数。&lt;/p&gt;&#xD;
&lt;p&gt;请大家注意wp:Param，我们可以认为该参数相当于调用了客户端应用中NavigationService的Navigate方法，必须确认客户端有指定的页面可以进行跳转。当用户点击Toast Notification的提示条时，客户端应用会调用wp:Param，从而跳转到指定界面上。&lt;/p&gt;&#xD;
&lt;p&gt;我们可以通过该参数来传递一些参数，比如标识本次Notification是由哪条消息引发的。不过该参数中不应该包括敏感信息、安全信息，因为无法保证这些信息的安全。最好的办法是，传递一个ID值，当客户端访问服务器时，由服务器端判断该ID是否有效。&lt;/p&gt;&#xD;
&lt;p&gt;接下来，我们还要为HTTP 头添加自定义字段，这部分参考Sample Code就可以了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;接收Notification&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;当Server端代码完成后，我们回到客户端，看一下当MPNS找到设备后，如何触发我们的客户端代码。首先是Page2.xaml的OnNavigatedTo方法：&lt;/p&gt;&lt;pre &gt;&lt;span &gt;protected&lt;/span&gt; &lt;span &gt;override&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)&#xD;
        {&#xD;
            &lt;span &gt;base&lt;/span&gt;.OnNavigatedTo(e);&#xD;
&#xD;
            &lt;span &gt;//  If we navigated to this page&lt;/span&gt;&#xD;
            &lt;span &gt;// from the MainPage, the DefaultTitle parameter will be "FromMain".  If we navigated here&lt;/span&gt;&#xD;
            &lt;span &gt;// when the secondary Tile was tapped, the parameter will be "FromTile".&lt;/span&gt;&#xD;
            textBlockFrom.Text = &lt;span &gt;"Navigated here from "&lt;/span&gt; + &lt;span &gt;this&lt;/span&gt;.NavigationContext.QueryString[&lt;span &gt;"NavigatedFrom"&lt;/span&gt;];&#xD;
        }&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;通过NavigationContext.QueryString属性来获取自定义参数，试过传两个参数，后一个收到不到，目前成功的是传递一个参数的情况。&lt;/p&gt;&#xD;
&lt;p&gt;还有一种情况是，当客户端程序运行时，接收到Toast Notification时，该如何处理：&lt;/p&gt;&lt;pre &gt;&lt;span &gt;void&lt;/span&gt; PushChannel_ShellToastNotificationReceived(&lt;span &gt;object&lt;/span&gt; sender, NotificationEventArgs e)&#xD;
        {&#xD;
            StringBuilder message = &lt;span &gt;new&lt;/span&gt; StringBuilder();&#xD;
            &lt;span &gt;string&lt;/span&gt; relativeUri = &lt;span &gt;string&lt;/span&gt;.Empty;&#xD;
&#xD;
            message.AppendFormat(&lt;span &gt;"Received Toast {0}:\n"&lt;/span&gt;, DateTime.Now.ToShortTimeString());&#xD;
&#xD;
            &lt;span &gt;// Parse out the information that was part of the message.&lt;/span&gt;&#xD;
            &lt;span &gt;foreach&lt;/span&gt; (&lt;span &gt;string&lt;/span&gt; key &lt;span &gt;in&lt;/span&gt; e.Collection.Keys)&#xD;
            {&#xD;
                message.AppendFormat(&lt;span &gt;"{0}: {1}\n"&lt;/span&gt;, key, e.Collection[key]);&#xD;
&#xD;
                &lt;span &gt;if&lt;/span&gt; (&lt;span &gt;string&lt;/span&gt;.Compare(&#xD;
                    key,&#xD;
                    &lt;span &gt;"wp:Param"&lt;/span&gt;,&#xD;
                    System.Globalization.CultureInfo.InvariantCulture,&#xD;
                    System.Globalization.CompareOptions.IgnoreCase) == 0)&#xD;
                {&#xD;
                    relativeUri = e.Collection[key];&#xD;
                }&#xD;
            }&#xD;
&#xD;
            &lt;span &gt;// Display a dialog of all the fields in the toast.&lt;/span&gt;&#xD;
            Dispatcher.BeginInvoke(() =&amp;gt; MessageBox.Show(message.ToString()));&#xD;
&#xD;
        }&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;该方法是HttpNotificationChannel的ShellToastNotificationReceived事件处理函数，具体内容不详细解释了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;Tile Notifications&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Tile Notification是另一种Notification，主要用于在Windows Phone的首页上显示Smart Tile。很多内置的WP应用可以显示Tile上的自定义显示，比如Messaging程序里可以显示当前未读的短信有多少。Tile Notification可以帮助我们实现类似的功能，通常的一个用法是，首先发送一条Toast Notification，如果用户不理睬，可以发送一条Tile Notification，在Smart Tile上显示提示，让用户在方便时，再处理该条请求。&lt;/p&gt;&#xD;
&lt;p&gt;Tile Notification的实现代码与Toast Notification类似，所以，我们不在这里列出全部源代码了，只是列出与上面不同的部分代码。&lt;/p&gt;&#xD;
&lt;p&gt;首先来看Server部分的代码：&lt;/p&gt;&lt;pre &gt;&lt;span &gt;// Create the tile message.&lt;/span&gt;&#xD;
                &lt;span &gt;string&lt;/span&gt; tileMessage = &lt;span &gt;"&amp;lt;?xml version=\"1.0\" encoding=\"utf-8\"?&amp;gt;"&lt;/span&gt; +&#xD;
                &lt;span &gt;"&amp;lt;wp:Notification xmlns:wp=\"WPNotification\"&amp;gt;"&lt;/span&gt; +&#xD;
                    &lt;span &gt;"&amp;lt;wp:Tile&amp;gt;"&lt;/span&gt; +&#xD;
                      &lt;span &gt;"&amp;lt;wp:BackgroundImage&amp;gt;"&lt;/span&gt; + TextBoxBackgroundImage.Text + &lt;span &gt;"&amp;lt;/wp:BackgroundImage&amp;gt;"&lt;/span&gt; +&#xD;
                      &lt;span &gt;"&amp;lt;wp:Count&amp;gt;"&lt;/span&gt; + TextBoxCount.Text + &lt;span &gt;"&amp;lt;/wp:Count&amp;gt;"&lt;/span&gt; +&#xD;
                      &lt;span &gt;"&amp;lt;wp:Title&amp;gt;"&lt;/span&gt; + TextBoxTitle.Text + &lt;span &gt;"&amp;lt;/wp:Title&amp;gt;"&lt;/span&gt; +&#xD;
                      &lt;span &gt;"&amp;lt;wp:BackBackgroundImage&amp;gt;"&lt;/span&gt; + TextBoxBackBackgroundImage.Text + &lt;span &gt;"&amp;lt;/wp:BackBackgroundImage&amp;gt;"&lt;/span&gt; +&#xD;
                      &lt;span &gt;"&amp;lt;wp:BackTitle&amp;gt;"&lt;/span&gt; + TextBoxBackTitle.Text + &lt;span &gt;"&amp;lt;/wp:BackTitle&amp;gt;"&lt;/span&gt; +&#xD;
                      &lt;span &gt;"&amp;lt;wp:BackContent&amp;gt;"&lt;/span&gt; + TextBoxBackContent.Text + &lt;span &gt;"&amp;lt;/wp:BackContent&amp;gt;"&lt;/span&gt; +&#xD;
                   &lt;span &gt;"&amp;lt;/wp:Tile&amp;gt; "&lt;/span&gt; +&#xD;
                &lt;span &gt;"&amp;lt;/wp:Notification&amp;gt;"&lt;/span&gt;;&#xD;
&#xD;
                &lt;span &gt;// Sets the notification payload to send.&lt;/span&gt;&#xD;
                &lt;span &gt;byte&lt;/span&gt;[] notificationMessage = Encoding.Default.GetBytes(tileMessage);&#xD;
&#xD;
                &lt;span &gt;// Sets the web request content length.&lt;/span&gt;&#xD;
                sendNotificationRequest.ContentLength = notificationMessage.Length;&#xD;
                sendNotificationRequest.ContentType = &lt;span &gt;"text/xml"&lt;/span&gt;;&#xD;
                sendNotificationRequest.Headers.Add(&lt;span &gt;"X-WindowsPhone-Target"&lt;/span&gt;, &lt;span &gt;"token"&lt;/span&gt;);&#xD;
                sendNotificationRequest.Headers.Add(&lt;span &gt;"X-NotificationClass"&lt;/span&gt;, &lt;span &gt;"1"&lt;/span&gt;);&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;TileMessage与ToastMessage大体类似，标签变为wp:Tile，而其中包括的数据分为两组：BackgroundImage、Title和Content，显示位置可以参考文章前面的示意图。BackgroundImage可以是本地的资源，也可以是远程的图片链接。&lt;/p&gt;&#xD;
&lt;p&gt;接下来是客户端的部分代码：&lt;/p&gt;&lt;pre &gt;pushChannel = &lt;span &gt;new&lt;/span&gt; HttpNotificationChannel(channelName);&#xD;
&#xD;
                &lt;span &gt;// Register for all the events before attempting to open the channel.&lt;/span&gt;&#xD;
                pushChannel.ChannelUriUpdated += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;NotificationChannelUriEventArgs&amp;gt;(PushChannel_ChannelUriUpdated);&#xD;
                pushChannel.ErrorOccurred += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;NotificationChannelErrorEventArgs&amp;gt;(PushChannel_ErrorOccurred);&#xD;
&#xD;
                pushChannel.Open();&#xD;
&#xD;
                &lt;span &gt;// Bind this new channel for Tile events.&lt;/span&gt;&#xD;
                pushChannel.BindToShellTile();&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;Tile Notification无需添加任何额外的代码，在调用HttpNotificationChannel的Open方法后，还需要调用BindToShellTile的方法，通知Shell绑定该Tile Notification。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;Raw Notifications&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;Raw Notification的用法最简单，在程序运行时，收到Raw Notification时，更新应用程序界面上的某些元素。&lt;/p&gt;&#xD;
&lt;p&gt;首先，我们来看Server端的代码：&lt;/p&gt;&lt;pre &gt;&lt;span &gt;// Create the raw message.&lt;/span&gt;&#xD;
                &lt;span &gt;string&lt;/span&gt; rawMessage = &lt;span &gt;"&amp;lt;?xml version=\"1.0\" encoding=\"utf-8\"?&amp;gt;"&lt;/span&gt; +&#xD;
                &lt;span &gt;"&amp;lt;root&amp;gt;"&lt;/span&gt; +&#xD;
                    &lt;span &gt;"&amp;lt;Value1&amp;gt;"&lt;/span&gt; + TextBoxValue1.Text.ToString() + &lt;span &gt;"&amp;lt;Value1&amp;gt;"&lt;/span&gt; +&#xD;
                    &lt;span &gt;"&amp;lt;Value2&amp;gt;"&lt;/span&gt; + TextBoxValue2.Text.ToString() + &lt;span &gt;"&amp;lt;Value2&amp;gt;"&lt;/span&gt; +&#xD;
                &lt;span &gt;"&amp;lt;/root&amp;gt;"&lt;/span&gt;;&#xD;
&#xD;
                &lt;span &gt;// Sets the notification payload to send.&lt;/span&gt;&#xD;
                &lt;span &gt;byte&lt;/span&gt;[] notificationMessage = Encoding.Default.GetBytes(rawMessage);&#xD;
&#xD;
                &lt;span &gt;// Sets the web request content length.&lt;/span&gt;&#xD;
                sendNotificationRequest.ContentLength = notificationMessage.Length;&#xD;
                sendNotificationRequest.ContentType = &lt;span &gt;"text/xml"&lt;/span&gt;;&#xD;
                sendNotificationRequest.Headers.Add(&lt;span &gt;"X-NotificationClass"&lt;/span&gt;, &lt;span &gt;"3"&lt;/span&gt;);&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;RawMessage非常简单，只需要指定Value1, Value2就可以了，这些值是自定义的，然后指定HTTP头的X-NotificationgClass的值为3，代表Raw Notification。&lt;/p&gt;&#xD;
&lt;p&gt;接下来是客户端代码的片段：&lt;/p&gt;&lt;pre &gt;pushChannel = &lt;span &gt;new&lt;/span&gt; HttpNotificationChannel(channelName);&#xD;
pushChannel.HttpNotificationReceived += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;HttpNotificationEventArgs&amp;gt;(PushChannel_HttpNotificationReceived);&#xD;
pushChannel.Open();&#xD;
&#xD;
&#xD;
        &lt;span &gt;void&lt;/span&gt; PushChannel_HttpNotificationReceived(&lt;span &gt;object&lt;/span&gt; sender, HttpNotificationEventArgs e)&#xD;
        {&#xD;
            &lt;span &gt;string&lt;/span&gt; message;&#xD;
&#xD;
            &lt;span &gt;using&lt;/span&gt; (System.IO.StreamReader reader = &lt;span &gt;new&lt;/span&gt; System.IO.StreamReader(e.Notification.Body))&#xD;
            {&#xD;
                message = reader.ReadToEnd();&#xD;
            }&#xD;
&#xD;
&#xD;
            Dispatcher.BeginInvoke(() =&amp;gt;&#xD;
                MessageBox.Show(String.Format(&lt;span &gt;"Received Notification {0}:\n{1}"&lt;/span&gt;,&#xD;
                    DateTime.Now.ToShortTimeString(), message))&#xD;
                    );&#xD;
        }&#xD;
&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&#xD;
&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;HttpNotificationChannel创建完成后，只需要调用Open方法即可，不需要绑定到Shell上。另外，还需要处理HttpNotificationChannel的HttpNotificationReceived事件处理函数，具体的代码不解释了。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;写在最后&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;好了，到这里，我们正式将Windows Phone 7.1中的Push Notification介绍完了。为了增加用户黏性，Push Notification可能是一种非常有效的方式，但是请开发者谨慎使用，如果太多的垃圾信息影响用户体验，那是得不偿失的。另外，我们还需要为Push Notification搭建一个Web服务器，这对于普通开发人员来说，也是一个很难接受的成本。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;strong&gt;OpenXLive杯Windows Phone游戏开发大赛&lt;/strong&gt;&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108020123544740.jpg"&gt;&lt;img style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline;background-image: none;" title="clip_image010" border="0" alt="clip_image010" src="http://images.cnblogs.com/cnblogs_com/aawolf/201108/201108020123557215.jpg" width="212" height="225" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&lt;p&gt;OpenXLive杯Windows Phone游戏开发大赛，是由OpenXLive联合国内知名的开发者社区：DevDiv、智机网、WPMind、Silverlight银光中国和XNA游戏世界，一起举办的针对Windows Phone游戏开发的比赛。&lt;/p&gt;&#xD;
&lt;p&gt;&lt;a href="http://www.openxlive.net/posts/news/40"&gt;http://www.openxlive.net/posts/news/40&lt;/a&gt;&lt;/p&gt; &#xD;
&lt;img src="http://www.cnblogs.com/aawolf/aggbug/2124442.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aawolf/archive/2011/08/02/2124442.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aawolf/archive/2011/06/21/2086139.html</id><title type="text">Kinect for Windows SDK开发初体验（三）骨骼追踪</title><summary type="text">作者：马宁  我们的Kinect SDK开发开始渐入佳境了，Skeleton Tracking（骨骼追踪）是Kinect的核心技术，正因为有了这项技术，很多有趣的功能才得以实现。  首先，我们来看一下骨骼追踪的具体实现。Kinect最多可以追踪20个骨骼点，而且目前只能追踪人体，其他的物体或者动物就无能为力了。下图介绍了Kinect骨骼点的分布情况： 初始化代码  接下来，我们来看一下骨骼追踪的代...</summary><published>2011-06-21T08:16:00Z</published><updated>2011-06-21T08:16:00Z</updated><author><name>马宁</name><uri>http://www.cnblogs.com/aawolf/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aawolf/archive/2011/06/21/2086139.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aawolf/archive/2011/06/21/2086139.html"/><content type="html">&lt;p&gt;作者：马宁&lt;/p&gt;  &lt;p&gt;我们的Kinect SDK开发开始渐入佳境了，Skeleton Tracking（骨骼追踪）是Kinect的核心技术，正因为有了这项技术，很多有趣的功能才得以实现。&lt;/p&gt;  &lt;p&gt;首先，我们来看一下骨骼追踪的具体实现。Kinect最多可以追踪20个骨骼点，而且目前只能追踪人体，其他的物体或者动物就无能为力了。下图介绍了Kinect骨骼点的分布情况：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106211612551171.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="7" border="0" alt="7" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106211614267781.png" width="446" height="444" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;初始化代码&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;接下来，我们来看一下骨骼追踪的代码是如何编写的。首先，我们要创建一个新的Visual C#的工程，叫做&amp;#8220;SkeletonTracking&amp;#8221;，添加Kinect程序集和Coding4Fun程序集的工作，可以参考上一篇&amp;#8220;Kinect for Windows SDK开发初体验（二）操作Camera&amp;#8221;的内容，在这里不再重复。&lt;/p&gt;  &lt;p&gt;首先我们还是创建Runtime对象，在初始化时，指定UseSkeletalTracking的RuntimeOptions，然后在SkeletonFrameReady事件中添加处理函数。&lt;/p&gt;  &lt;pre &gt;Runtime nui; &#xD;
&#xD;
&lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Window_Loaded(&lt;span &gt;object&lt;/span&gt; sender, RoutedEventArgs e)&#xD;
&#xD;
{&#xD;
&#xD;
nui = &lt;span &gt;new&lt;/span&gt; Runtime();&#xD;
&#xD;
nui.Initialize(RuntimeOptions.UseSkeletalTracking); &#xD;
&#xD;
nui.SkeletonFrameReady += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;SkeletonFrameReadyEventArgs&amp;gt;(nui_SkeletonFrameReady);&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;接下来，窗体关闭时的事件处理函数：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Window_Closed(&lt;span &gt;object&lt;/span&gt; sender, EventArgs e)&#xD;
&#xD;
{&#xD;
&#xD;
nui.Uninitialize();&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;如果这个时候，我们在空的nui_SkeletonFrameReady事件处理函数中，添加一个断点：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;void&lt;/span&gt; nui_SkeletonFrameReady(&lt;span &gt;object&lt;/span&gt; sender, SkeletonFrameReadyEventArgs e) &#xD;
&#xD;
{&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;正确连接Kinect设备，并且站在Kinect前，让Kinect能够正确识别人体时，SkeletonFrameReady事件将被触发。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;我们可以通过下图看到返回的事件处理参数，其中比较重要的是SkeletonFrame和Skeletons两个对象。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106211615089556.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image[11]" border="0" alt="image[11]" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106211615479780.png" width="703" height="380" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;添加代码&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;接下来，我们要准备WPF的界面，在界面上添加五个小球，来跟踪头部、双手和膝盖的位置。在MainPage.xaml中，添加下列代码：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Canvas&lt;/span&gt; &lt;span &gt;Name&lt;/span&gt;&lt;span &gt;=&amp;quot;MainCanvas&amp;quot;&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
&lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Ellipse&lt;/span&gt; &lt;span &gt;Canvas&lt;/span&gt;.&lt;span &gt;Left&lt;/span&gt;&lt;span &gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span &gt;Canvas&lt;/span&gt;.&lt;span &gt;Top&lt;/span&gt;&lt;span &gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span &gt;Height&lt;/span&gt;&lt;span &gt;=&amp;quot;50&amp;quot;&lt;/span&gt; &lt;span &gt;Name&lt;/span&gt;&lt;span &gt;=&amp;quot;headEllipse&amp;quot;&lt;/span&gt; &lt;span &gt;Stroke&lt;/span&gt;&lt;span &gt;=&amp;quot;Black&amp;quot;&lt;/span&gt; &lt;span &gt;Width&lt;/span&gt;&lt;span &gt;=&amp;quot;50&amp;quot;&lt;/span&gt; &lt;span &gt;Fill&lt;/span&gt;&lt;span &gt;=&amp;quot;Orange&amp;quot;&lt;/span&gt; &lt;span &gt;/&amp;gt;&lt;/span&gt;&#xD;
&lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Ellipse&lt;/span&gt; &lt;span &gt;Canvas&lt;/span&gt;.&lt;span &gt;Left&lt;/span&gt;&lt;span &gt;=&amp;quot;50&amp;quot;&lt;/span&gt; &lt;span &gt;Canvas&lt;/span&gt;.&lt;span &gt;Top&lt;/span&gt;&lt;span &gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span &gt;Height&lt;/span&gt;&lt;span &gt;=&amp;quot;50&amp;quot;&lt;/span&gt; &lt;span &gt;Name&lt;/span&gt;&lt;span &gt;=&amp;quot;rightEllipse&amp;quot;&lt;/span&gt; &lt;span &gt;Stroke&lt;/span&gt;&lt;span &gt;=&amp;quot;Black&amp;quot;&lt;/span&gt; &lt;span &gt;Width&lt;/span&gt;&lt;span &gt;=&amp;quot;50&amp;quot;&lt;/span&gt; &lt;span &gt;Fill&lt;/span&gt;&lt;span &gt;=&amp;quot;SlateGray&amp;quot;&lt;/span&gt; &lt;span &gt;/&amp;gt;&lt;/span&gt;&#xD;
&lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Ellipse&lt;/span&gt; &lt;span &gt;Canvas&lt;/span&gt;.&lt;span &gt;Left&lt;/span&gt;&lt;span &gt;=&amp;quot;100&amp;quot;&lt;/span&gt; &lt;span &gt;Canvas&lt;/span&gt;.&lt;span &gt;Top&lt;/span&gt;&lt;span &gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span &gt;Fill&lt;/span&gt;&lt;span &gt;=&amp;quot;SpringGreen&amp;quot;&lt;/span&gt; &lt;span &gt;Height&lt;/span&gt;&lt;span &gt;=&amp;quot;50&amp;quot;&lt;/span&gt; &lt;span &gt;Name&lt;/span&gt;&lt;span &gt;=&amp;quot;leftEllipse&amp;quot;&lt;/span&gt; &lt;span &gt;Stroke&lt;/span&gt;&lt;span &gt;=&amp;quot;Black&amp;quot;&lt;/span&gt; &lt;span &gt;Width&lt;/span&gt;&lt;span &gt;=&amp;quot;50&amp;quot;&lt;/span&gt; &lt;span &gt;/&amp;gt;&lt;/span&gt;&#xD;
&lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Ellipse&lt;/span&gt; &lt;span &gt;Canvas&lt;/span&gt;.&lt;span &gt;Left&lt;/span&gt;&lt;span &gt;=&amp;quot;150&amp;quot;&lt;/span&gt; &lt;span &gt;Canvas&lt;/span&gt;.&lt;span &gt;Top&lt;/span&gt;&lt;span &gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span &gt;Height&lt;/span&gt;&lt;span &gt;=&amp;quot;50&amp;quot;&lt;/span&gt; &lt;span &gt;Name&lt;/span&gt;&lt;span &gt;=&amp;quot;KneeRightEllipse&amp;quot;&lt;/span&gt; &lt;span &gt;Stroke&lt;/span&gt;&lt;span &gt;=&amp;quot;Black&amp;quot;&lt;/span&gt; &lt;span &gt;Width&lt;/span&gt;&lt;span &gt;=&amp;quot;50&amp;quot;&lt;/span&gt; &lt;span &gt;Fill&lt;/span&gt;&lt;span &gt;=&amp;quot;Salmon&amp;quot;&lt;/span&gt; &lt;span &gt;/&amp;gt;&lt;/span&gt;&#xD;
&lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Ellipse&lt;/span&gt; &lt;span &gt;Canvas&lt;/span&gt;.&lt;span &gt;Left&lt;/span&gt;&lt;span &gt;=&amp;quot;200&amp;quot;&lt;/span&gt; &lt;span &gt;Canvas&lt;/span&gt;.&lt;span &gt;Top&lt;/span&gt;&lt;span &gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span &gt;Fill&lt;/span&gt;&lt;span &gt;=&amp;quot;Navy&amp;quot;&lt;/span&gt; &lt;span &gt;Height&lt;/span&gt;&lt;span &gt;=&amp;quot;50&amp;quot;&lt;/span&gt; &lt;span &gt;Name&lt;/span&gt;&lt;span &gt;=&amp;quot;KneeLeftEllipse&amp;quot;&lt;/span&gt; &lt;span &gt;Stroke&lt;/span&gt;&lt;span &gt;=&amp;quot;Black&amp;quot;&lt;/span&gt; &lt;span &gt;Width&lt;/span&gt;&lt;span &gt;=&amp;quot;50&amp;quot;&lt;/span&gt; &lt;span &gt;/&amp;gt;&lt;/span&gt;&#xD;
&lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;Canvas&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;然后，我们在SkeletonFrameReady事件处理函数中添加捕捉SkeletonData的方法：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;void&lt;/span&gt; nui_SkeletonFrameReady(&lt;span &gt;object&lt;/span&gt; sender, SkeletonFrameReadyEventArgs e) &#xD;
&#xD;
{&#xD;
&#xD;
SkeletonFrame allSkeletons = e.SkeletonFrame;&#xD;
&#xD;
&lt;span &gt;//get the first tracked skeleton&lt;/span&gt;&#xD;
&#xD;
SkeletonData skeleton = (from s &lt;span &gt;in&lt;/span&gt; allSkeletons.Skeletons&#xD;
&#xD;
&lt;span &gt;where&lt;/span&gt; s.TrackingState == SkeletonTrackingState.Tracked&#xD;
&#xD;
select s).FirstOrDefault();&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;我们使用了LINQ来获取TrackingState等于Tracked的SkeletonData数据。在SkeletonData对象的Joints属性集合中保存了所有骨骼点的信息。每个骨骼点的信息都是一个Joint对象，其中的Position的X、Y、Z表示了三维位置。其中X和Y的范围都是-1到1，而Z是Kinect到识别物体的距离。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;我们可以用下面的代码，将Joint的位置缩放到合适的比例：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;Joint j = skeleton.Joints[JointID.HandRight].ScaleTo(640, 480, .5f, .5f);&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;最后两个参数为原始大小的最大值和最小值，上面的语句相当于将-0.5到0.5的范围扩大为0到640的范围。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;我们封装了一个函数，将获取到的SkeletonData数据，转换为屏幕上的某一个圆圈：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; SetEllipsePosition(FrameworkElement ellipse, Joint joint) &#xD;
&#xD;
{ &#xD;
&#xD;
var scaledJoint = joint.ScaleTo(640, 480, .5f, .5f);&#xD;
&#xD;
Canvas.SetLeft(ellipse, scaledJoint.Position.X);&#xD;
&#xD;
Canvas.SetTop(ellipse, scaledJoint.Position.Y); &#xD;
&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;最后，我们SkeletonFrameReady事件的处理方法会是这样的：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;void&lt;/span&gt; nui_SkeletonFrameReady(&lt;span &gt;object&lt;/span&gt; sender, SkeletonFrameReadyEventArgs e) &#xD;
&#xD;
{&#xD;
&#xD;
SkeletonFrame allSkeletons = e.SkeletonFrame;&#xD;
&#xD;
&lt;span &gt;//get the first tracked skeleton&lt;/span&gt;&#xD;
&#xD;
SkeletonData skeleton = (from s &lt;span &gt;in&lt;/span&gt; allSkeletons.Skeletons&#xD;
&#xD;
&lt;span &gt;where&lt;/span&gt; s.TrackingState == SkeletonTrackingState.Tracked&#xD;
&#xD;
select s).FirstOrDefault();&#xD;
&#xD;
SetEllipsePosition(headEllipse, skeleton.Joints[JointID.Head]); &#xD;
&#xD;
SetEllipsePosition(leftEllipse, skeleton.Joints[JointID.HandLeft]); &#xD;
&#xD;
SetEllipsePosition(rightEllipse, skeleton.Joints[JointID.HandRight]);&#xD;
&#xD;
SetEllipsePosition(KneeLeftEllipse, skeleton.Joints[JointID.KneeLeft]);&#xD;
&#xD;
SetEllipsePosition(KneeRightEllipse, skeleton.Joints[JointID.KneeRight]);&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;最后，程序运行的效果如下，貌似膝盖的识别还是有些问题：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106211616081403.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="30" border="0" alt="30" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106211616185491.png" width="712" height="426" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;程序运行时，我们会发现小球运动时会有跳动的问题，为了减少这种情况，我们要设置SkeletonEngine引擎的TransformSmooth属性为true，并指定TransformSmoothParameters参数，根据应用的具体情况，该参数也应该被适当微调。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;添加代码后的Load函数，代码如下：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Window_Loaded(&lt;span &gt;object&lt;/span&gt; sender, RoutedEventArgs e)&#xD;
&#xD;
{&#xD;
&#xD;
nui = &lt;span &gt;new&lt;/span&gt; Runtime();&#xD;
&#xD;
nui.Initialize(RuntimeOptions.UseSkeletalTracking); &#xD;
&#xD;
&lt;span &gt;//Must set to true and set after call to Initialize&lt;/span&gt;&#xD;
&#xD;
nui.SkeletonEngine.TransformSmooth = &lt;span &gt;true&lt;/span&gt;;&#xD;
&#xD;
&lt;span &gt;//Use to transform and reduce jitter&lt;/span&gt;&#xD;
&#xD;
var parameters = &lt;span &gt;new&lt;/span&gt; TransformSmoothParameters&#xD;
&#xD;
{&#xD;
&#xD;
Smoothing = 0.75f,&#xD;
&#xD;
Correction = 0.0f,&#xD;
&#xD;
Prediction = 0.0f,&#xD;
&#xD;
JitterRadius = 0.05f,&#xD;
&#xD;
MaxDeviationRadius = 0.04f&#xD;
&#xD;
};&#xD;
&#xD;
nui.SkeletonEngine.SmoothParameters = parameters;&#xD;
&#xD;
nui.SkeletonFrameReady += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;SkeletonFrameReadyEventArgs&amp;gt;(nui_SkeletonFrameReady);&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;写到最后&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;到这里， Kinect最精华的部分&amp;#8220;骨骼追踪&amp;#8221;已经介绍给大家了，大家可以去写一些有趣的应用了。接下来，我们会介绍另外一个Kinect的核心功能——Depth Data，景深数据。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;OpenXLive杯Windows Phone游戏开发大赛&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013539658.jpg"&gt;&lt;img title="clip_image019" border="0" alt="clip_image019" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013545231.jpg" width="212" height="225" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;OpenXLive杯Windows Phone游戏开发大赛，是由OpenXLive联合国内知名的开发者社区：DevDiv、智机网、WPMind、Silverlight银光中国和XNA游戏世界，一起举办的针对Windows Phone游戏开发的比赛。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://www.openxlive.net/posts/news/40"&gt;http://www.openxlive.net/posts/news/40&lt;/a&gt;&lt;/p&gt; &lt;img src="http://www.cnblogs.com/aawolf/aggbug/2086139.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aawolf/archive/2011/06/21/2086139.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aawolf/archive/2011/06/18/2084352.html</id><title type="text">Kinect for Windows SDK开发初体验（二）操作Camera</title><summary type="text">   作者：马宁  Kinect SDK出来之后，不到24小时，很多Geek们已经将自己的示例发布到网上去了。可见，好东西肯定会被大家认可的，不好的东西投入再多的宣传也没用。  这一篇我们就要正式进入Kinect的编程世界了，介绍我们如何从Camera获取图像信息。先来介绍一下Kinect的整体结构，省得大家在后边的介绍中被某些名词弄晕。 Kinect一共有三个Camera，其中中间的一个是RGB...</summary><published>2011-06-18T11:05:00Z</published><updated>2011-06-18T11:05:00Z</updated><author><name>马宁</name><uri>http://www.cnblogs.com/aawolf/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aawolf/archive/2011/06/18/2084352.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aawolf/archive/2011/06/18/2084352.html"/><content type="html">&lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;作者：马宁&lt;/p&gt;  &lt;p&gt;Kinect SDK出来之后，不到24小时，很多Geek们已经将自己的示例发布到网上去了。可见，好东西肯定会被大家认可的，不好的东西投入再多的宣传也没用。&lt;/p&gt;  &lt;p&gt;这一篇我们就要正式进入Kinect的编程世界了，介绍我们如何从Camera获取图像信息。先来介绍一下Kinect的整体结构，省得大家在后边的介绍中被某些名词弄晕。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106181530519386.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image_thumb[3]" border="0" alt="image_thumb[3]" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106181534166412.png" width="494" height="324" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Kinect一共有三个Camera，其中中间的一个是RGB Camera，用来获取640x480的彩色图像，每秒钟最多获取30帧图像；两侧是两个景深(3D Depth)传感器，用来检测玩家的相对位置，原理和人眼立体成像是一样的，不过这两个传感器使用的是红外线，所以说奥巴马玩不了Kinect的人一定是居心叵测。Kinect两侧是麦克风，下边还有一个可移动底座，用来调整Kinect的仰角。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Kinect开发环境&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;今天我们主要是操作RGB Camera和Depth Sensor，首先，我们要完成Kinect开发环境的配置：&lt;/p&gt;  &lt;p&gt;第一步，创建WPF工程&lt;/p&gt;  &lt;p&gt;打开Visual Studio 2010，创建一个WPF工程，名叫KinectWpfDemo：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106181534381788.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="21" border="0" alt="21" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106181535031681.png" width="601" height="414" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;当然，由于Kinect SDK中包含基于.NET的程序集，除了WPF外，我们使用.NET WinForm或XNA框架都可以，目前还没有人在Silverlight平台上实验成功。&lt;/p&gt;  &lt;p&gt;第二步，添加Kinect程序集的引用&lt;/p&gt;  &lt;p&gt;在Solution Explorer中，右键单击KinectWpfDemo，在右键菜单中选择&amp;#8220;Add Reference&amp;#8230;&amp;#8221;。在弹出的对话框中，我们在.NET标签页里，选择&amp;#8220;Microsoft.Research.Kinect&amp;#8221;程序集。如下图所示：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106181904196523.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="22" border="0" alt="22" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106181904212752.png" width="542" height="434" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;第三步，添加Coding4Fun Kinect Toolkit&lt;/p&gt;  &lt;p&gt;这是一个可选项，不过为了之后的编程方便，建议大家添加一个。Coding4Fun Kinect Toolkit的下载地址：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://c4fkinect.codeplex.com/"&gt;http://c4fkinect.codeplex.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;解压缩后，一共有五个文件，针对WinForm、WPF平台，还有一个Microsoft.Expression.Drawing.dll。我们通过Add Reference，将Coding4Fun.Kinect.Wpf.dll添加进来。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106181904215850.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="23" border="0" alt="23" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106181904236854.png" width="372" height="515" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;获取RGB Camera数据&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;第四步，添加控件&lt;/p&gt;  &lt;p&gt;双击打开MainWindow.xaml，在设计器中添加两个Image控件，一个用于显示RGB图像，另一个用于显示Depth信息。&lt;/p&gt;  &lt;p&gt;第五步，引用命名空间&lt;/p&gt;  &lt;p&gt;打开MainWindow.xaml.cs文件，在文件头部添加对于Kinect对象的引用：&lt;/p&gt;  &lt;pre &gt;&lt;span &gt;using&lt;/span&gt; Microsoft.Research.Kinect.Nui;&#xD;
&#xD;
&lt;span &gt;using&lt;/span&gt; Microsoft.Research.Kinect.Audio;&#xD;
&#xD;
&lt;span &gt;using&lt;/span&gt; Coding4Fun.Kinect.Wpf;&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;回到MainWindow.xaml的设计器中，在属性窗口中选择Event，找到Loaded和Closed两个方法，分别双击，添加两个事件的处理函数：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106181904234063.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="25" border="0" alt="25" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/20110618190424574.png" width="372" height="455" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;在MainWindow.xaml.cs文件的MainWindow类中，声明Runtime的变量：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;Runtime nui;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;然后，在Loaded事件的处理函数中添加Runtime初始化的代码：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Window_Loaded(&lt;span &gt;object&lt;/span&gt; sender, RoutedEventArgs e)&#xD;
&#xD;
{&#xD;
&#xD;
nui = &lt;span &gt;new&lt;/span&gt; Runtime();&#xD;
&#xD;
nui.Initialize(RuntimeOptions.UseColor| RuntimeOptions.UseDepth | RuntimeOptions.UseDepthAndPlayerIndex | RuntimeOptions.UseSkeletalTracking);&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;接下来是Closed事件中关闭Runtime的代码：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Window_Closed(&lt;span &gt;object&lt;/span&gt; sender, EventArgs e)&#xD;
&#xD;
{&#xD;
&#xD;
nui.Uninitialize();&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;Runtime对象是Kinect SDK中最主要的一个类，所有针对Kinect的操作都由Runtime类进行了封装。Runtime的构造函数没有接受任何参数，但有一个显式的初始化函数Initialize，接受RuntimeOptions参数，指定调用Kinect的哪些功能。其中RuntimeOptions.UseColor表示使用RGB Camera，而RuntimeOptions.UseDepth则表示使用Depth传感器。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;初始化工作完成之后，我们要通过RGB Camera来获取实时的图像数据了。我们首先要声明一个事件处理方法，来接收视频数据的信息：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;nui.VideoFrameReady += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;ImageFrameReadyEventArgs&amp;gt;(nui_VideoFrameReady);&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;然后是事件处理函数：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;void&lt;/span&gt; nui_VideoFrameReady(&lt;span &gt;object&lt;/span&gt; sender, ImageFrameReadyEventArgs e)&#xD;
&#xD;
{&#xD;
&#xD;
PlanarImage imageData = e.ImageFrame.Image;&#xD;
&#xD;
image1.Source = BitmapSource.Create(imageData.Width, imageData.Height, 96, 96,&#xD;
&#xD;
PixelFormats.Bgr32, &lt;span &gt;null&lt;/span&gt;, imageData.Bits, imageData.Width * imageData.BytesPerPixel);&#xD;
&#xD;
&lt;span &gt;//image1.Source = e.ImageFrame.ToBitmapSource();&lt;/span&gt;&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;提示：Getting Started上提供的Sample Code有误，需要将最后一个参数中的data.Width改为imageData.Width才可以正常运行。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;VideoFrameReady事件会传递一个ImageFrameReadyEventArgs参数给事件处理函数，其中的ImageFrame会包含关于图片的各种信息，比如Type变量指定了图像是来自RGB还是Depth，Resolution变量指定了分辨率，而Image中以byte[]数组的方式保存了图像的真实数据。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;然后的工作就是根据PlanarImage中包括的数据来创建一个Bitmap对象，然后将其传递给Image控件，显示到WPF程序的界面上。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;最后，我们还要在构造函数里打开视频流，来获取视频数据：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;nui.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;第一个参数是ImageStreamType，用来指定打开的设备流类型；第二个参数是PoolSize，指定缓冲区的数量，至少为2，保证一个Buffer进行绘制，另一个Buffer进行数据填充；第三个参数指定Camera的分辨率；第四个参数则是获取的图片类型。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;显示效果如下图所示：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106181904253704.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="24 - Copy" border="0" alt="24 - Copy" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106181904267773.png" width="616" height="412" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;上面的示例代码，没有使用Coding4Fun的Helper类，如果使用的话，则代码如下：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;void&lt;/span&gt; nui_VideoFrameReady(&lt;span &gt;object&lt;/span&gt; sender, ImageFrameReadyEventArgs e)&#xD;
&#xD;
{&#xD;
&#xD;
image1.Source = e.ImageFrame.ToBitmapSource();&#xD;
&#xD;
e.ImageFrame.ToBitmapSource().Save(&lt;span &gt;&amp;quot;catpure.jpg&amp;quot;&lt;/span&gt;, ImageFormat.Jpeg);&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;Helper类使用了C#的Extension Methods，为ImageFrame增加了一些转换方法。我们还可以将图像保存为文件，考虑到文件系统存储的效率文件，建议大家不用每张都存。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;获取Depth信息&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;接下来我们要获取Depth信息了，过程与RGB Camera类似。首先要确保Runtime对象被初始化时，已经添加了RuntimeOptions.UseDepth的属性，否则设备无法正常打开。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;然后，添加获取Depth数据的事件处理，并打开Depth的数据流，这次的分辨率是320x240：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;nui.DepthFrameReady += &lt;span &gt;new&lt;/span&gt; EventHandler&amp;lt;ImageFrameReadyEventArgs&amp;gt;(nui_DepthFrameReady);&#xD;
&#xD;
nui.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.Depth);&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;下面是事件处理函数，在另外一个Image函数里，显示Depth图像：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;void&lt;/span&gt; nui_DepthFrameReady(&lt;span &gt;object&lt;/span&gt; sender, ImageFrameReadyEventArgs e)&#xD;
&#xD;
{&#xD;
&#xD;
image2.Source = e.ImageFrame.ToBitmapSource(); &#xD;
&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;偷懒，所以使用了Coding4Fun的Helper类。程序运行的效果如下：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106181904289608.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="24" border="0" alt="24" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106181904308137.png" width="650" height="435" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;写到最后&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;这一篇中，我们完成了Kinect开发环境的配置、添加了Coding4Fun Kinect Toolkit、从RGB Camera和Depth Sensor中获取了图像信息。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;接下来，我们就要进入Kinect动作捕捉部分了。&lt;/p&gt; &lt;img src="http://www.cnblogs.com/aawolf/aggbug/2084352.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aawolf/archive/2011/06/18/2084352.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aawolf/archive/2011/06/17/2083249.html</id><title type="text">Kinect for Windows SDK开发初体验（一）环境配置</title><summary type="text">作者：马宁 万众期待的Kinect for Windows SDK终于在广大开发者的千呼万唤中发布了beta版，作为历史上销售最快的消费电子产品，早就有无数人想将其用于其他领域了。微软虽然在硬件接口上制造了一点小障碍，但并没有对Kinect的输出做任何加密。于是，基于Kinect的各种应用层出不穷，也有开源社区提供了针对Kinect的USB驱动程序，比如OpenKinect等。 微软从谏如流，推出了官方版的Kinect for Windows SDK，终于让广大开发者可以名正言顺地使用Kinect SDK了。我希望能够在第一时间为国内开发者提供Kinect开发相关的介绍，根据微软官方提供的指南</summary><published>2011-06-16T19:25:00Z</published><updated>2011-06-16T19:25:00Z</updated><author><name>马宁</name><uri>http://www.cnblogs.com/aawolf/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aawolf/archive/2011/06/17/2083249.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aawolf/archive/2011/06/17/2083249.html"/><content type="html">&lt;p&gt;作者：马宁&lt;/p&gt;  &lt;p&gt;万众期待的Kinect for Windows SDK终于在广大开发者的千呼万唤中发布了beta版，作为历史上销售最快的消费电子产品，早就有无数人想将其用于其他领域了。微软虽然在硬件接口上制造了一点小障碍，但并没有对Kinect的输出做任何加密。于是，基于Kinect的各种应用层出不穷，也有开源社区提供了针对Kinect的USB驱动程序，比如OpenKinect等。&lt;/p&gt;  &lt;p&gt;微软从谏如流，推出了官方版的Kinect for Windows SDK，终于让广大开发者可以名正言顺地使用Kinect SDK了。我希望能够在第一时间为国内开发者提供Kinect开发相关的介绍，根据微软官方提供的指南，从浅入深，将自己摸索Kinect SDK 的过程记录下来。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170324415321.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="2" border="0" alt="2" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170324427372.png" width="533" height="355" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;安装环境&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;首先来说，Kinect for Windows SDK的下载地址：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/download.aspx"&gt;http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/download.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Kinect SDK目前只支持Windows 7，分为x86和x64两个版本。开发工具方面还需要.NET Framework 4.0和Visual Studio 2010 （最低Express版本）的支持。&lt;/p&gt;  &lt;p&gt;Kinect SDK的视频开发教程：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://channel9.msdn.com/Series/KinectSDKQuickstarts?sort=recent#tab_sortBy_recent"&gt;http://channel9.msdn.com/Series/KinectSDKQuickstarts?sort=recent#tab_sortBy_recent&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Kinect SDK的开发指南：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/guides.aspx"&gt;http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/guides.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Kinect SDK的官方论坛：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://social.msdn.microsoft.com/Forums/en-US/kinectsdk/threads"&gt;http://social.msdn.microsoft.com/Forums/en-US/kinectsdk/threads&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;硬件设备的需求是：Kinect for Xbox 360 sensor和Xbox 360 Kinect AC Adapter/ Power Supply。&lt;/p&gt;  &lt;p&gt;如果您购买的是单独的Kinect，将包含Kinect AC Adapter/ Power Supply。但是如果您购买的是XBOX 360 Slim和Kinect的套装，就需要单独购买Kinect AC Adapter/ Power Supply。下面是亚马逊上的产品链接：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.amazon.com/Xbox-360-Kinect-Adapter-Power-Supply/dp/B004IXRXGY/ref=sr_1_1?ie=UTF8&amp;amp;qid=1308247174&amp;amp;sr=8-1"&gt;http://www.amazon.com/Xbox-360-Kinect-Adapter-Power-Supply/dp/B004IXRXGY/ref=sr_1_1?ie=UTF8&amp;amp;qid=1308247174&amp;amp;sr=8-1&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;安装步骤&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;1. 硬件安装&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;下面的图片是Kinect和AC Adapter/ Power Supply：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170324428834.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="WP_000094" border="0" alt="WP_000094" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170324433916.jpg" width="548" height="412" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;按照接口连接好后，将USB插入到PC上，AC Adapter电源是可以支持220V的，所以不需要转换器直接插到电源上就可以。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;2. Kinect SDK安装&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Kinect SDK的安装过程非常简单，无需任何设置，直接安装即可。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170324446490.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="1" border="0" alt="1" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170324449065.png" width="575" height="451" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;3. 环境测试&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Kinect SDK安装完成后，我们将Kinect转接口的USB接口插入到PC中。PC会发现新硬件，并且自动查找驱动程序安装。下图是安装完成后的示意图：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/20110617032445734.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="evm1" border="0" alt="evm1" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170324458292.png" width="549" height="356" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;4. 测试程序&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;我们打开Kinect SDK中自带的Sample Skeletal Viewer就可以很方便地检测Kinect设备是否与PC已经连接好了。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170324463898.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="evm2" border="0" alt="evm2" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170324466788.png" width="633" height="240" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;为了测试，逼得我不得不闪亮出镜了。以后Kinect调试，说不定还真要请一个人站在那里，实现敏捷开发中的&amp;#8220;双人编程&amp;#8221;&amp;#8230;&amp;#8230;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;写到最后&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;我们今天关于Kinect的介绍就到这里，在Kinect SDK的发布会上展示了很多有意思的DEMO，可见Kinect的应用前景是无限广阔的。下图就是一个Kinect与虚拟增强现实整合的案例：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170324477966.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="4" border="0" alt="4" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170324485001.png" width="558" height="318" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;下一节，我们会深入Kinect真实的开发环境，来编写第一个Kinect的应用程序。&lt;/p&gt; &lt;img src="http://www.cnblogs.com/aawolf/aggbug/2083249.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aawolf/archive/2011/06/17/2083249.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aawolf/archive/2011/06/17/2083222.html</id><title type="text">马宁的Windows Phone 7.1初体验——XNA与Silverlight集成</title><summary type="text">关于Windows Phone Mango真真假假的图片、视频已经在网上流传很久了，微软发布的Windows Phone 7.1 SDK可以让我们看到一部分Mango支持的功能。 普通用户对Mango的关注更多停留在多语言、多任务等方面，但对于开发者来说，Mango还有很多有趣的功能。我会试着将自己感兴趣的一些功能写出来，变成一个系列。 首先，大家要安装Windows Phone 7的SDK和Windows Phone 7.1 SDK的Beta 版，下载地址如下： http://www.microsoft.com/downloads/en/details.aspx?FamilyID=77586</summary><published>2011-06-16T16:14:00Z</published><updated>2011-06-16T16:14:00Z</updated><author><name>马宁</name><uri>http://www.cnblogs.com/aawolf/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aawolf/archive/2011/06/17/2083222.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aawolf/archive/2011/06/17/2083222.html"/><content type="html">&lt;p&gt;关于Windows Phone Mango真真假假的图片、视频已经在网上流传很久了，微软发布的Windows Phone 7.1 SDK可以让我们看到一部分Mango支持的功能。&lt;/p&gt;  &lt;p&gt;普通用户对Mango的关注更多停留在多语言、多任务等方面，但对于开发者来说，Mango还有很多有趣的功能。我会试着将自己感兴趣的一些功能写出来，变成一个系列。&lt;/p&gt;  &lt;p&gt;首先，大家要安装Windows Phone 7的SDK和Windows Phone 7.1 SDK的Beta 版，下载地址如下：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.microsoft.com/downloads/en/details.aspx?FamilyID=77586864-ab15-40e1-bc38-713a95a56a05"&gt;http://www.microsoft.com/downloads/en/details.aspx?FamilyID=77586864-ab15-40e1-bc38-713a95a56a05&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;创建工程&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;关于Windows Phone 7.1的第一个功能是XNA与Silverlight的集成。Windows Phone里有两个Framework，Silverlight是做应用的，而XNA是做游戏开发的。Silverlight有一套非常好用的UI设计工具和控件体系，而XNA对于动画效果的处理又远远超过Silverlight。但是在WP7里，Silverlight和XNA必须是分开的，所以当Silverlight应用需要高性能显示，或者XNA游戏里需要编写UI时，都会碰到很多困难。&lt;/p&gt;  &lt;p&gt;于是，在WP 7.1里，提供了XNA与Silverlight集成的功能。接下来，我们就来看一下，如何创建一个Silverlight和XNA集成的应用。&lt;/p&gt;  &lt;p&gt;打开Visual Studio 2010，选择File-New Project，在Visual C#里找到Silverlight for Windows Phone，然后选择其中的&amp;#8220;Windows Phone 3D Graphics Application&amp;#8221;，这个名字有足够的迷惑性，XNA的2D也是支持的。如下图：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013375466.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="2" border="0" alt="2" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013387757.png" width="710" height="492" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;创建过程没有什么特殊的地方，创建完成后的工程如下图所示：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013392840.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="3" border="0" alt="3" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013406843.png" width="326" height="506" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;说实话，XNA与Silverlight集成的实现并不算优雅，有点叠床架屋的感觉。整个Solution里分为三个Project，其中GraphicsApp1是我们的主程序，主要的逻辑代码都是在这个工程里的，这是一个典型的Silverlight程序，包含了App.xaml和MainPage.xmal，多出来一个GamePage.xaml，这个是XNA的页面。除此之外，还有两个Library，分别叫做GraphicsApp1Library和GraphicsApp1LibraryContent，后边是XNA的Content库，前边一个应该是为了能够让Silverlight加载XNA资源所做的适配库。&lt;/p&gt;  &lt;p&gt;直接运行程序，我们会看到下面的界面，点击HomePage的Play按钮，我们就进入了XNA的GamePage界面：&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013418894.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="4" border="0" alt="4" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013429516.png" width="277" height="517" /&gt;&lt;/a&gt; &lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013437107.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="5" border="0" alt="5" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013437729.png" width="279" height="515" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;GamePage探秘&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;接下来，我们看一下GamePage.xaml的结构，看看这个看似普通的XAML页面里具体做了什么事情。首先是GamePage.xaml，如下：&lt;/p&gt;  &lt;pre &gt;&lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;phone:PhoneApplicationPage&lt;/span&gt; &#xD;
    &lt;span &gt;x:Class&lt;/span&gt;&lt;span &gt;=&amp;quot;GraphicsApp2.GamePage&amp;quot;&lt;/span&gt;&#xD;
    &lt;span &gt;xmlns&lt;/span&gt;&lt;span &gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;&lt;/span&gt;&#xD;
    &lt;span &gt;xmlns:x&lt;/span&gt;&lt;span &gt;=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&lt;/span&gt;&#xD;
    &lt;span &gt;xmlns:phone&lt;/span&gt;&lt;span &gt;=&amp;quot;clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone&amp;quot;&lt;/span&gt;&#xD;
    &lt;span &gt;xmlns:shell&lt;/span&gt;&lt;span &gt;=&amp;quot;clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone&amp;quot;&lt;/span&gt;&#xD;
    &lt;span &gt;xmlns:d&lt;/span&gt;&lt;span &gt;=&amp;quot;http://schemas.microsoft.com/expression/blend/2008&amp;quot;&lt;/span&gt;&#xD;
    &lt;span &gt;xmlns:mc&lt;/span&gt;&lt;span &gt;=&amp;quot;http://schemas.openxmlformats.org/markup-compatibility/2006&amp;quot;&lt;/span&gt;&#xD;
    &lt;span &gt;FontFamily&lt;/span&gt;&lt;span &gt;=&amp;quot;{StaticResource PhoneFontFamilyNormal}&amp;quot;&lt;/span&gt;&#xD;
    &lt;span &gt;FontSize&lt;/span&gt;&lt;span &gt;=&amp;quot;{StaticResource PhoneFontSizeNormal}&amp;quot;&lt;/span&gt;&#xD;
    &lt;span &gt;Foreground&lt;/span&gt;&lt;span &gt;=&amp;quot;{StaticResource PhoneForegroundBrush}&amp;quot;&lt;/span&gt;&#xD;
    &lt;span &gt;SupportedOrientations&lt;/span&gt;&lt;span &gt;=&amp;quot;Portrait&amp;quot;&lt;/span&gt; &lt;span &gt;Orientation&lt;/span&gt;&lt;span &gt;=&amp;quot;Portrait&amp;quot;&lt;/span&gt;&#xD;
    &lt;span &gt;mc:Ignorable&lt;/span&gt;&lt;span &gt;=&amp;quot;d&amp;quot;&lt;/span&gt; &lt;span &gt;d:DesignHeight&lt;/span&gt;&lt;span &gt;=&amp;quot;800&amp;quot;&lt;/span&gt; &lt;span &gt;d:DesignWidth&lt;/span&gt;&lt;span &gt;=&amp;quot;480&amp;quot;&lt;/span&gt;&#xD;
    &lt;span &gt;shell:SystemTray&lt;/span&gt;.&lt;span &gt;IsVisible&lt;/span&gt;&lt;span &gt;=&amp;quot;False&amp;quot;&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
&#xD;
    &lt;span &gt;&amp;lt;!--No XAML content as the page is rendered entirely with XNA--&amp;gt;&lt;/span&gt;&#xD;
    &#xD;
&lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;phone:PhoneApplicationPage&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;什么都没有&amp;#8230;&amp;#8230;所有的显示都是由XNA控制的。接下来，我们去看GamePage.xaml.cs，首先来看引用程序集的部分：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;using&lt;/span&gt; Microsoft.Xna.Framework;&#xD;
&#xD;
&lt;span &gt;using&lt;/span&gt; Microsoft.Xna.Framework.Content;&#xD;
&#xD;
&lt;span &gt;using&lt;/span&gt; Microsoft.Xna.Framework.Graphics;&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;引用了三个XNA的命名空间，接下来是变量声明：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;GameTimer timer;&#xD;
&#xD;
ContentManager content;&#xD;
&#xD;
SpriteBatch spriteBatch;&#xD;
&#xD;
Texture2D texture;&#xD;
&#xD;
Vector2 spritePosition;&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;除了GameTimer是生面孔外，其他几个都是老熟人，GameTimer也好理解，Silverlight是事件驱动的Framework，如果想定时更新的话，必须要加入一个Timer。接下来，是GamePage的构造函数：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;public&lt;/span&gt; GamePage()&#xD;
        {&#xD;
            InitializeComponent();&#xD;
&#xD;
            &lt;span &gt;// Get the application's ContentManager&lt;/span&gt;&#xD;
            content = (Application.Current &lt;span &gt;as&lt;/span&gt; App).Content;&#xD;
&#xD;
            &lt;span &gt;// Create a timer for this page&lt;/span&gt;&#xD;
            timer = &lt;span &gt;new&lt;/span&gt; GameTimer();&#xD;
            timer.UpdateInterval = TimeSpan.FromTicks(333333);&#xD;
            timer.Update += OnUpdate;&#xD;
            timer.Draw += OnDraw;&#xD;
        }&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;ContentManager对象是来自于App的Content属性，我们不会再有一个派生自Microsoft.Xna.Framework.Game的Host类了。然后是GameTimer的初始化工作，指定更新时间间隔，然后为Update和Draw事件添加方法。我不知道理解的是否正确，但有可能是GameTimer类重新实现了XNA Framework的机制。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;然后是两个重载的Navigated函数：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;protected&lt;/span&gt; &lt;span &gt;override&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; OnNavigatedTo(NavigationEventArgs e)&#xD;
        {&#xD;
            &lt;span &gt;// Set the sharing mode of the graphics device to turn on XNA rendering&lt;/span&gt;&#xD;
            SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(&lt;span &gt;true&lt;/span&gt;);&#xD;
&#xD;
            &lt;span &gt;// Create a new SpriteBatch, which can be used to draw textures.&lt;/span&gt;&#xD;
            spriteBatch = &lt;span &gt;new&lt;/span&gt; SpriteBatch(SharedGraphicsDeviceManager.Current.GraphicsDevice);&#xD;
&#xD;
            &lt;span &gt;// TODO: use this.content to load your game content here&lt;/span&gt;&#xD;
&#xD;
            &lt;span &gt;// Start the timer&lt;/span&gt;&#xD;
            timer.Start();&#xD;
&#xD;
            &lt;span &gt;base&lt;/span&gt;.OnNavigatedTo(e);&#xD;
        }&#xD;
&#xD;
        &lt;span &gt;protected&lt;/span&gt; &lt;span &gt;override&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; OnNavigatedFrom(NavigationEventArgs e)&#xD;
        {&#xD;
            &lt;span &gt;// Stop the timer&lt;/span&gt;&#xD;
            timer.Stop();&#xD;
&#xD;
            &lt;span &gt;// Set the sharing mode of the graphics device to turn off XNA rendering&lt;/span&gt;&#xD;
            SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(&lt;span &gt;false&lt;/span&gt;);&#xD;
&#xD;
            &lt;span &gt;base&lt;/span&gt;.OnNavigatedFrom(e);&#xD;
        }&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;OnNavigatedTo函数实现了LoadContent的功能，第一句话值得注意，我们要首先打开GraphicsDevice的SetSharingMode为true，才能够让XNA元素正常的显示出来。这句话也交代了XNA最主要的类GraphicsDeviceManager的去向，被放到一个静态的SharedGraphicsDeviceManager对象里去了。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;创建SpriteBatch和加载资源的过程不再叙述，最后要调用GameTimer的Start方法，来启动XNA的时间驱动机制，与之对应的是OnNavigatedFrom函数中，我们还需要调用GameTimer的Stop方法，来关闭时间驱动机制。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;最后是熟悉的OnUpdate和OnDraw方法，就数这两个函数原汁原味地保留了XNA的特点。&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&#xD;
        &lt;span &gt;/// Allows the page to run logic such as updating the world,&lt;/span&gt;&#xD;
        &lt;span &gt;/// checking for collisions, gathering input, and playing audio.&lt;/span&gt;&#xD;
        &lt;span &gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&#xD;
        &lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; OnUpdate(&lt;span &gt;object&lt;/span&gt; sender, GameTimerEventArgs e)&#xD;
        {&#xD;
            &lt;span &gt;// TODO: Add your update logic here&lt;/span&gt;&#xD;
        }&#xD;
&#xD;
        &lt;span &gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&#xD;
        &lt;span &gt;/// Allows the page to draw itself.&lt;/span&gt;&#xD;
        &lt;span &gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&#xD;
        &lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; OnDraw(&lt;span &gt;object&lt;/span&gt; sender, GameTimerEventArgs e)&#xD;
        {&#xD;
            SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.CornflowerBlue);&#xD;
&#xD;
            &lt;span &gt;// TODO: Add your drawing code here&lt;/span&gt;&#xD;
        }&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;添加Silverlight控件&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;如果只是在Silverlight应用里添加一个XNA的页面，恐怕还没有太大的吸引力。我们还应该让XNA和Silverlight能够在一个页面上显示。首先我们要打开GamePage.xaml文件，找到下面的代码：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;&amp;lt;!--No XAML content as the page is rendered entirely with XNA--&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;将下列代码替换上面的注释：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;&amp;lt;!-- LayoutRoot is the root grid where all page content is placed --&amp;gt;&lt;/span&gt;&#xD;
    &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Grid&lt;/span&gt; &lt;span &gt;x:Name&lt;/span&gt;&lt;span &gt;=&amp;quot;LayoutRoot&amp;quot;&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
        &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Grid.RowDefinitions&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;RowDefinition&lt;/span&gt; &lt;span &gt;Height&lt;/span&gt;&lt;span &gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span &gt;/&amp;gt;&lt;/span&gt;&#xD;
            &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;RowDefinition&lt;/span&gt; &lt;span &gt;Height&lt;/span&gt;&lt;span &gt;=&amp;quot;*&amp;quot;&lt;/span&gt;&lt;span &gt;/&amp;gt;&lt;/span&gt;&#xD;
            &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;RowDefinition&lt;/span&gt; &lt;span &gt;Height&lt;/span&gt;&lt;span &gt;=&amp;quot;Auto&amp;quot;&lt;/span&gt;&lt;span &gt;/&amp;gt;&lt;/span&gt;&#xD;
        &lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;Grid.RowDefinitions&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
&#xD;
        &lt;span &gt;&amp;lt;!-- Toggles the visibility of the ColorPanel --&amp;gt;&lt;/span&gt;&#xD;
        &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Button&lt;/span&gt; &lt;span &gt;Grid&lt;/span&gt;.&lt;span &gt;Row&lt;/span&gt;&lt;span &gt;=&amp;quot;0&amp;quot;&lt;/span&gt; &lt;span &gt;x:Name&lt;/span&gt;&lt;span &gt;=&amp;quot;ColorPanelToggleButton&amp;quot;&lt;/span&gt; &lt;span &gt;Click&lt;/span&gt;&lt;span &gt;=&amp;quot;ColorPanelToggleButton_Click&amp;quot;&lt;/span&gt; &lt;span &gt;Margin&lt;/span&gt;&lt;span &gt;=&amp;quot;1,0,-1,0&amp;quot;&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;Toggle Color Panel&lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;Button&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
&#xD;
        &lt;span &gt;&amp;lt;!-- Arrange buttons in a horizontal line by using StackPanel --&amp;gt;&lt;/span&gt;&#xD;
        &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;StackPanel&lt;/span&gt; &lt;span &gt;x:Name&lt;/span&gt;&lt;span &gt;=&amp;quot;ColorPanel&amp;quot;&lt;/span&gt; &lt;span &gt;Grid&lt;/span&gt;.&lt;span &gt;Row&lt;/span&gt;&lt;span &gt;=&amp;quot;2&amp;quot;&lt;/span&gt;  &lt;span &gt;Height&lt;/span&gt;&lt;span &gt;=&amp;quot;100&amp;quot;&lt;/span&gt; &lt;span &gt;Orientation&lt;/span&gt;&lt;span &gt;=&amp;quot;Horizontal&amp;quot;&lt;/span&gt; &lt;span &gt;HorizontalAlignment&lt;/span&gt;&lt;span &gt;=&amp;quot;Center&amp;quot;&lt;/span&gt; &lt;span &gt;Visibility&lt;/span&gt;&lt;span &gt;=&amp;quot;Visible&amp;quot;&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
            &lt;span &gt;&amp;lt;!-- Buttons to set the rectangle to specific colors --&amp;gt;&lt;/span&gt;&#xD;
            &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Button&lt;/span&gt; &lt;span &gt;Click&lt;/span&gt;&lt;span &gt;=&amp;quot;redButton_Click&amp;quot;&lt;/span&gt; &lt;span &gt;HorizontalAlignment&lt;/span&gt;&lt;span &gt;=&amp;quot;Center&amp;quot;&lt;/span&gt; &lt;span &gt;Height&lt;/span&gt;&lt;span &gt;=&amp;quot;75&amp;quot;&lt;/span&gt; &lt;span &gt;VerticalAlignment&lt;/span&gt;&lt;span &gt;=&amp;quot;Center&amp;quot;&lt;/span&gt; &lt;span &gt;BorderThickness&lt;/span&gt;&lt;span &gt;=&amp;quot;3&amp;quot;&lt;/span&gt; &lt;span &gt;Background&lt;/span&gt;&lt;span &gt;=&amp;quot;Firebrick&amp;quot;&lt;/span&gt; &lt;span &gt;Width&lt;/span&gt;&lt;span &gt;=&amp;quot;75&amp;quot;&lt;/span&gt; &lt;span &gt;/&amp;gt;&lt;/span&gt;&#xD;
            &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Button&lt;/span&gt; &lt;span &gt;Click&lt;/span&gt;&lt;span &gt;=&amp;quot;greenButton_Click&amp;quot;&lt;/span&gt; &lt;span &gt;HorizontalAlignment&lt;/span&gt;&lt;span &gt;=&amp;quot;Center&amp;quot;&lt;/span&gt; &lt;span &gt;Height&lt;/span&gt;&lt;span &gt;=&amp;quot;75&amp;quot;&lt;/span&gt; &lt;span &gt;VerticalAlignment&lt;/span&gt;&lt;span &gt;=&amp;quot;Center&amp;quot;&lt;/span&gt; &lt;span &gt;BorderThickness&lt;/span&gt;&lt;span &gt;=&amp;quot;3&amp;quot;&lt;/span&gt; &lt;span &gt;Background&lt;/span&gt;&lt;span &gt;=&amp;quot;Lime&amp;quot;&lt;/span&gt; &lt;span &gt;Width&lt;/span&gt;&lt;span &gt;=&amp;quot;75&amp;quot;&lt;/span&gt; &lt;span &gt;/&amp;gt;&lt;/span&gt;&#xD;
            &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Button&lt;/span&gt; &lt;span &gt;Click&lt;/span&gt;&lt;span &gt;=&amp;quot;blueButton_Click&amp;quot;&lt;/span&gt; &lt;span &gt;HorizontalAlignment&lt;/span&gt;&lt;span &gt;=&amp;quot;Center&amp;quot;&lt;/span&gt; &lt;span &gt;Height&lt;/span&gt;&lt;span &gt;=&amp;quot;75&amp;quot;&lt;/span&gt; &lt;span &gt;VerticalAlignment&lt;/span&gt;&lt;span &gt;=&amp;quot;Center&amp;quot;&lt;/span&gt; &lt;span &gt;BorderThickness&lt;/span&gt;&lt;span &gt;=&amp;quot;3&amp;quot;&lt;/span&gt; &lt;span &gt;Background&lt;/span&gt;&lt;span &gt;=&amp;quot;Blue&amp;quot;&lt;/span&gt; &lt;span &gt;Width&lt;/span&gt;&lt;span &gt;=&amp;quot;75&amp;quot;&lt;/span&gt; &lt;span &gt;/&amp;gt;&lt;/span&gt;&#xD;
        &lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;StackPanel&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
    &lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;Grid&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;如果编译的话，会提示没有Button对应的事件处理函数。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;添加代码&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;下面部分和MSDN提供的示例代码不同，我试图找到一种更简单的办法来更改颜色。首先，我们在GraphicsApp1LibraryContent工程里找到redRect.jpg，右键单击，选择Open With，然后在列表里选择Paint，用画图打开文件后，将整个图片涂成白色。做完这个工作后，记得一定要重新编译整个工程。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;接下来，我们声明Color变量，并且在构造函数里赋初始值。&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;Color bgColor;&#xD;
&#xD;
&lt;span &gt;public&lt;/span&gt; GamePage()&#xD;
&#xD;
{&#xD;
&#xD;
&lt;span &gt;    // ...&lt;/span&gt;&#xD;
 &#xD;
    bgColor = Color.Red;&#xD;
&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;然后我们增加事件处理函数，首先是控制颜色是否显示的控件：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;// Toggle the visibility of the StackPanel named &amp;quot;ColorPanel&amp;quot;&lt;/span&gt;&#xD;
        &lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; ColorPanelToggleButton_Click(&lt;span &gt;object&lt;/span&gt; sender, RoutedEventArgs e)&#xD;
        {&#xD;
            &lt;span &gt;if&lt;/span&gt; (System.Windows.Visibility.Visible == ColorPanel.Visibility)&#xD;
            {&#xD;
                ColorPanel.Visibility = System.Windows.Visibility.Collapsed;&#xD;
            }&#xD;
            &lt;span &gt;else&lt;/span&gt;&#xD;
            {&#xD;
                ColorPanel.Visibility = System.Windows.Visibility.Visible;&#xD;
            }&#xD;
        }&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;然后是切换颜色的几个Button的处理函数：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;// Switch to the red rectangle&lt;/span&gt;&#xD;
        &lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; redButton_Click(&lt;span &gt;object&lt;/span&gt; sender, RoutedEventArgs e)&#xD;
        {&#xD;
            bgColor = Color.Red;&#xD;
        }&#xD;
&#xD;
        &lt;span &gt;// Switch to the green rectangle&lt;/span&gt;&#xD;
        &lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; greenButton_Click(&lt;span &gt;object&lt;/span&gt; sender, RoutedEventArgs e)&#xD;
        {&#xD;
            bgColor = Color.Green;&#xD;
        }&#xD;
&#xD;
        &lt;span &gt;// Switch to the blue rectangle&lt;/span&gt;&#xD;
        &lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; blueButton_Click(&lt;span &gt;object&lt;/span&gt; sender, RoutedEventArgs e)&#xD;
        {&#xD;
            bgColor = Color.Blue;&#xD;
        }&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;最后，我们在OnDraw函数里，找到下面的代码：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;spriteBatch.Draw(texture, spritePosition, Color.White);&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;换成下面的代码：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;spriteBatch.Draw(texture, spritePosition, bgColor); &lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;这样我们就可以为白色的材质绘制出不同的颜色了。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;现在程序可以编译通过了，但是运行程序后，Silverlight的控件却没办法显示出来。原因是Silverlight控件必须经过特殊的处理，才能够显示出来。首先要声明一个UIElementRenderer变量：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;// For rendering the XAML onto a texture&lt;/span&gt;&#xD;
&#xD;
UIElementRenderer elementRenderer;&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;然后，在GamePage的构造函数里，添加下面的代码：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;// Use the LayoutUpdate event to know when the page layout &lt;/span&gt;&#xD;
&#xD;
&lt;span &gt;// has completed so we can create the UIElementRenderer&lt;/span&gt;&#xD;
&#xD;
LayoutUpdated += &lt;span &gt;new&lt;/span&gt; EventHandler(GamePage_LayoutUpdated);&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;添加GamePage_LayoutUpdated的函数，在函数中创建UIElementRenderer的对象：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;void&lt;/span&gt; GamePage_LayoutUpdated(&lt;span &gt;object&lt;/span&gt; sender, EventArgs e)&#xD;
        {&#xD;
            &lt;span &gt;// Create the UIElementRenderer to draw the XAML page to a texture.&lt;/span&gt;&#xD;
&#xD;
            &lt;span &gt;// Check for 0 because when we navigate away the LayoutUpdate event&lt;/span&gt;&#xD;
            &lt;span &gt;// is raised but ActualWidth and ActualHeight will be 0 in that case.&lt;/span&gt;&#xD;
            &lt;span &gt;if&lt;/span&gt; (ActualWidth &amp;gt; 0 &amp;amp;&amp;amp; ActualHeight &amp;gt; 0 &amp;amp;&amp;amp; elementRenderer == &lt;span &gt;null&lt;/span&gt;)&#xD;
            {&#xD;
                elementRenderer = &lt;span &gt;new&lt;/span&gt; UIElementRenderer(&lt;span &gt;this&lt;/span&gt;, (&lt;span &gt;int&lt;/span&gt;)ActualWidth, (&lt;span &gt;int&lt;/span&gt;)ActualHeight);&#xD;
            }&#xD;
        }&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;最后，在OnDraw函数里，添加下面的代码：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&#xD;
        &lt;span &gt;/// Allows the page to draw itself.&lt;/span&gt;&#xD;
        &lt;span &gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&#xD;
        &lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; OnDraw(&lt;span &gt;object&lt;/span&gt; sender, GameTimerEventArgs e)&#xD;
        {&#xD;
            SharedGraphicsDeviceManager.Current.GraphicsDevice.Clear(Color.Black);&#xD;
&#xD;
            &lt;span &gt;// TODO: Add your drawing code here&lt;/span&gt;&#xD;
            &lt;span &gt;// Render the Silverlight controls using the UIElementRenderer&lt;/span&gt;&#xD;
            elementRenderer.Render();&#xD;
&#xD;
&#xD;
            &lt;span &gt;// Draw the sprite&lt;/span&gt;&#xD;
            spriteBatch.Begin();&#xD;
            spriteBatch.Draw(texture, spritePosition, bgColor); &lt;span &gt;//Color.White);&lt;/span&gt;&#xD;
            spriteBatch.DrawString(StartFont, &lt;span &gt;&amp;quot;Hello, XNA&amp;quot;&lt;/span&gt;, &lt;span &gt;new&lt;/span&gt; Vector2(50), Color.Blue);&#xD;
&#xD;
            &lt;span &gt;// Using the texture from the UIElementRenderer, &lt;/span&gt;&#xD;
            &lt;span &gt;// draw the Silverlight controls to the screen&lt;/span&gt;&#xD;
            spriteBatch.Draw(elementRenderer.Texture, Vector2.Zero, Color.White);&#xD;
&#xD;
&#xD;
            spriteBatch.End();&#xD;
        }&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;再运行程序时，我们就可以看到Silverlight控件了，点击颜色控件，方块会切换成对应的颜色。如下图所示：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013444174.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="6" border="0" alt="6" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013441209.png" width="299" height="562" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;加载XNA资源&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;到这里，我们的体验基本上告一段落了，但是我试了一下是否能够正常加载XNA的字体，所以就写了最后这部分。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;右键点击GraphicsApp1LibraryContent，选择Add &amp;#8211; New Item。在对话框中选择Sprite Font，我们将字体命名为StartFont。在打开的字体文件中，我们将Size改成30，如下面所示：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;&amp;lt;!--&lt;/span&gt;&#xD;
&lt;span &gt;    Size is a float value, measured in points. Modify this value to change&lt;/span&gt;&#xD;
&lt;span &gt;    the size of the font.&lt;/span&gt;&#xD;
&lt;span &gt;    --&amp;gt;&lt;/span&gt;&#xD;
    &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Size&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;30&lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;Size&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;回到GamePage.xaml.cs文件中，我们首先声明SpriteFont变量：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;SpriteFont StartFont;&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;然后，在OnNavigatedTo函数中，添加字体加载的代码：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;protected&lt;/span&gt; &lt;span &gt;override&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; OnNavigatedTo(NavigationEventArgs e)&#xD;
        {&#xD;
&#xD;
            &lt;span &gt;// Set the sharing mode of the graphics device to turn on XNA rendering&lt;/span&gt;&#xD;
            SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(&lt;span &gt;true&lt;/span&gt;);&#xD;
&#xD;
            spriteBatch = &lt;span &gt;new&lt;/span&gt; SpriteBatch(SharedGraphicsDeviceManager.Current.GraphicsDevice);&#xD;
&#xD;
            &lt;span &gt;// TODO: use this.content to load your game content here&lt;/span&gt;&#xD;
            texture = content.Load&amp;lt;Texture2D&amp;gt;(&lt;span &gt;&amp;quot;redRect&amp;quot;&lt;/span&gt;);&#xD;
            StartFont = content.Load&amp;lt;SpriteFont&amp;gt;(&lt;span &gt;&amp;quot;StartFont&amp;quot;&lt;/span&gt;);&lt;/pre&gt;&#xD;
&#xD;
&lt;p&gt;最后，在OnDraw函数里，添加字体的绘制函数：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;spriteBatch.DrawString(StartFont, &lt;span &gt;&amp;quot;Hello, XNA&amp;quot;&lt;/span&gt;, &lt;span &gt;new&lt;/span&gt; Vector2(50), Color.Blue);&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;程序运行的效果如下：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013451831.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="7" border="0" alt="7" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013469422.png" width="323" height="602" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;另一条路&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;除了在Silverlight for Windows Phone创建Windows Phone 3D Graphics Application外，我们还能够通过另一种方式创建XNA与Silverlight整合的应用程序。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;在XNA Game Studio 4.0中，选择Windows Phone Rich Graphics Application：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013478649.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="1" border="0" alt="1" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013483764.png" width="714" height="495" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;通过这个向导创建的程序，与上面创建的程序大同小异，只是界面略有不同。运行界面如下：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&amp;#160;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/20110617001349275.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="8" border="0" alt="8" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013503406.png" width="270" height="503" /&gt;&lt;/a&gt; &lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013528130.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="9" border="0" alt="9" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013536801.png" width="272" height="506" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;写在最后&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;好了，到这里，我们正式将Windows Phone 7.1中的Silverlight与XNA整合应用介绍完了。在XNA游戏中，我们可以使用Silverlight来创建界面；也可以在Silverlight应用中编写高性能的3D界面。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;OpenXLive杯Windows Phone游戏开发大赛&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013539658.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="clip_image019" border="0" alt="clip_image019" src="http://images.cnblogs.com/cnblogs_com/aawolf/201106/201106170013545231.jpg" width="212" height="225" /&gt;&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;OpenXLive杯Windows Phone游戏开发大赛，是由OpenXLive联合国内知名的开发者社区：DevDiv、智机网、WPMind、Silverlight银光中国和XNA游戏世界，一起举办的针对Windows Phone游戏开发的比赛。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://www.openxlive.net/posts/news/40"&gt;http://www.openxlive.net/posts/news/40&lt;/a&gt;&lt;/p&gt; &lt;img src="http://www.cnblogs.com/aawolf/aggbug/2083222.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aawolf/archive/2011/06/17/2083222.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aawolf/archive/2011/04/02/2003381.html</id><title type="text">如何将OpenXLive添加到WP7 Silverlight游戏中</title><summary type="text">OpenXLive beta版发布已经有一个半月的时间了，得到了开发者和玩家的好评，目前已经有五款OpenXLive游戏进入Windows Phone Marketplace，其中的7bomb和Super Hoops都取得了非常骄人的成绩。 当OpenXLive在XNA游戏中大展身手的同时，我们也听到了一些来自Silverlight程序员的抱怨。在Windows Phone 7中虽然提供了XNA的游戏开发平台，但相当一部分的游戏是采用Silverlight开发的。毕竟对于显示性能不高的游戏来说，Silverlight是一个颇具魅力的快速开发工具。 幸好，我们在最初的架构设计上考虑了未来支持Si</summary><published>2011-04-02T07:06:00Z</published><updated>2011-04-02T07:06:00Z</updated><author><name>马宁</name><uri>http://www.cnblogs.com/aawolf/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aawolf/archive/2011/04/02/2003381.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aawolf/archive/2011/04/02/2003381.html"/><content type="html">&lt;p&gt;OpenXLive beta版发布已经有一个半月的时间了，得到了开发者和玩家的好评，目前已经有五款OpenXLive游戏进入Windows Phone Marketplace，其中的7bomb和Super Hoops都取得了非常骄人的成绩。&lt;/p&gt;  &lt;p&gt;当OpenXLive在XNA游戏中大展身手的同时，我们也听到了一些来自Silverlight程序员的抱怨。在Windows Phone 7中虽然提供了XNA的游戏开发平台，但相当一部分的游戏是采用Silverlight开发的。毕竟对于显示性能不高的游戏来说，Silverlight是一个颇具魅力的快速开发工具。&lt;/p&gt;  &lt;p&gt;幸好，我们在最初的架构设计上考虑了未来支持Silverlight的可能性，所以将业务逻辑部分封装到了OpenXLive.dll中，而将XNA上的XLiveForm窗体和控件库封装到了OpenXLive.Forms.dll中。我们只需要在Silverlight中调用OpenXLive中的功能即可。&lt;/p&gt;  &lt;p&gt;在提供了一个OpenXLive on Silverlight的简单示例代码后，我们发现对Silverlight游戏的支持仍旧不够。首先，我们只提供了Leaderboard部分的示例代码，在缺乏文档的情况下，开发其他功能的UI是很困难的；其次，开发者并不希望自己动手写一个Silverlight UI，而只是想简单地在游戏中加入OpenXLive的支持，就像在XNA游戏中那样。&lt;/p&gt;  &lt;p&gt;所以，我们重新定义了OpenXLive Silverlight的功能，实现了OpenXLive中的所有功能，并将其封装到了OpenXLive.Silverlight.dll中。在开发过程中，我们尽力保持XNA和Silverlight框架的一致性，如果您使用过OpenXLive XNA版本，在Silverlight版本中，您会有一种似曾相识的感觉，这正是我们所希望的。&lt;/p&gt;  &lt;p&gt;需要提示的一点是，OpenXLive的Silverlight和XNA版本共同使用了一个逻辑程序集——OpenXLive.dll，所以他们在功能上是一致的。&lt;/p&gt;  &lt;p&gt;未来，我们会将OpenXLive Silverlight加入到OpenXLive SDK中，并提供Visual Studio模板。在某一个时间点上，我们会考虑对OpenXLive Silverlight进行开源，让开发者能够方便的将OpenXLive Silverlight修改成自己想要的样子。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;OpenXLive简介&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;微软为Windows Phone 7上的XNA和Silverlight游戏开发提供了非常好的开发工具和应用程序框架，使得开发者可以更加容易地开发出生动有趣的游戏来。但是随着开发的深入，我们发现，虽然我们开发的游戏品质可以和大公司的产品相媲美，但比起大公司游戏的用户体验还是相差很多。因为，我们必须将很多时间用于周边功能的开发，比如：启动界面(Splash Screen), 积分榜(Leaderboard)和游戏成就(Achievement)等，更不要奢谈为游戏加入SNS功能，比如：查看在线用户(Online Player)、云存储(Cloud Storage)等在线功能了。这些周边功能的开发时间，可能要超过游戏本身的开发时间，那我们该怎么办呢？&lt;/p&gt;  &lt;p&gt;OpenXLive正在想办法帮助个人开发者和小团队开发者，使他们在最短的时间内拥有以上这些只有大公司才可能拥有的游戏功能。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506102878.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="openxlive logo" border="0" alt="openxlive logo" src="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506117305.png" width="367" height="99" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;OpenXLive是一种为Windows Phone 7智能手机游戏开发者提供的云端在线服务。支持开发者为单机游戏增加云端和SNS功能，帮助开发者以最小的工作量将云端服务集成到自己的游戏中。这些云端服务包括：积分榜、游戏成就、在线对战、Social Network和云端存储等功能。与Open XLive类似的服务，还有iOS上的OpenFeint。&lt;/p&gt;  &lt;p&gt;OpenXLive目前支持Windows Phone的XNA与Silverlight开发框架，不需要开发者编写UI代码，即可在游戏中方便地调用OpenXLive的界面及功能。由于XNA和Silverlight是两个不同的应用程序框架，所以，OpenXLive提供了不同的引用方式来支持XNA和Silverlight游戏。&lt;/p&gt;  &lt;p&gt;本文讨论的是如何将OpenXLive加入到Silverlight游戏中，如果您的游戏采用XNA编写，请查看《OpenXLive开发入门》，链接如下：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://wiki.openxlive.net/Getting-Started-with-Open-XLive.ashx"&gt;http://wiki.openxlive.net/Getting-Started-with-Open-XLive.ashx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;添加引用&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;您可以在下面的链接中下载单独的OpenXLive Silverlight SDK:&lt;/p&gt;  &lt;p&gt;&lt;a title="http://resource.openxlive.com/resource/Download/ad686043-d477-4d5a-bc83-f27520a3d600" href="http://resource.openxlive.com/resource/Download/ad686043-d477-4d5a-bc83-f27520a3d600"&gt;http://resource.openxlive.com/resource/Download/ad686043-d477-4d5a-bc83-f27520a3d600&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;首先，我们假设您已经有了基于Silverlight开发的Windows Phone游戏。如果您想从头创建一个OpenXLive Silverlight游戏，您可以参考下一节《OpenXLive Silverlight向导使用》。&lt;/p&gt;  &lt;p&gt;我们采用的示例工程OpenXLiveGameSilverlight，您可以在OpenXLive的资源网站中找到。&lt;/p&gt;  &lt;p&gt;首先，我们在OpenXLive SDK的bin文件夹下找到OpenXLive.dll和OpenXLive.Silverlight.dll，将其拷贝到工程所在的目录中。&lt;/p&gt;  &lt;p&gt;然后，在Visual Studio 2010中，打开OpenXLiveGameSilverlight工程，在Solution Explorer中找到References节点，右键单击啊，选择Add References，在对话框中选择Browse页面，找到工程目录下的OpenXLive.dll和OpenXLive.Silverlight.dll，将两个程序集的引用加入到工程中。&lt;/p&gt;  &lt;p&gt;添加成功后，如下图所示：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506116192.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="SLDemo1" border="0" alt="SLDemo1" src="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506119747.png" width="312" height="401" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;修改初始页面&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;在引用添加完成之后，我们还要修改WMAppMainifest.xml文件，使Silverlight游戏启动时，启动OpenXLive.Silverlight中所包含的Startup页面。&lt;/p&gt;  &lt;p&gt;在工程的Propertes节点下找到WMAppMainifest.xml文件，双击打开，如下图所示：&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506115810.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="SLDemo2" border="0" alt="SLDemo2" src="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506124141.png" width="376" height="376" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;WMAppMainifest.xml文件的结构如下：&lt;/p&gt;  &lt;pre &gt;&lt;span &gt;&amp;lt;?&lt;/span&gt;&lt;span &gt;xml&lt;/span&gt; &lt;span &gt;version&lt;/span&gt;&lt;span &gt;=&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;span &gt;encoding&lt;/span&gt;&lt;span &gt;=&amp;quot;utf-8&amp;quot;&lt;/span&gt;?&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
&#xD;
&lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Deployment&lt;/span&gt; &lt;span &gt;xmlns&lt;/span&gt;&lt;span &gt;=&amp;quot;http://schemas.microsoft.com/windowsphone/2009/deployment&amp;quot;&lt;/span&gt; &lt;span &gt;AppPlatformVersion&lt;/span&gt;&lt;span &gt;=&amp;quot;7.0&amp;quot;&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
  &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;App&lt;/span&gt; &lt;span &gt;xmlns&lt;/span&gt;&lt;span &gt;=&amp;quot;&amp;quot;&lt;/span&gt; &lt;span &gt;ProductID&lt;/span&gt;&lt;span &gt;=&amp;quot;{3cf35939-f7f6-4808-969c-22d520f6a526}&amp;quot;&lt;/span&gt; &lt;span &gt;Title&lt;/span&gt;&lt;span &gt;=&amp;quot;OpenXLiveGameSilverlight&amp;quot;&lt;/span&gt; &lt;span &gt;RuntimeType&lt;/span&gt;&lt;span &gt;=&amp;quot;Silverlight&amp;quot;&lt;/span&gt; &lt;span &gt;Version&lt;/span&gt;&lt;span &gt;=&amp;quot;1.0.0.0&amp;quot;&lt;/span&gt; &lt;span &gt;Genre&lt;/span&gt;&lt;span &gt;=&amp;quot;apps.normal&amp;quot;&lt;/span&gt;  &lt;span &gt;Author&lt;/span&gt;&lt;span &gt;=&amp;quot;OpenXLiveGameSilverlight author&amp;quot;&lt;/span&gt; &lt;span &gt;Description&lt;/span&gt;&lt;span &gt;=&amp;quot;Sample description&amp;quot;&lt;/span&gt; &lt;span &gt;Publisher&lt;/span&gt;&lt;span &gt;=&amp;quot;OpenXLiveGameSilverlight&amp;quot;&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
    &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;IconPath&lt;/span&gt; &lt;span &gt;IsRelative&lt;/span&gt;&lt;span &gt;=&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span &gt;IsResource&lt;/span&gt;&lt;span &gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;ApplicationIcon.png&lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;IconPath&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
    &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Capabilities&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
      &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Capability&lt;/span&gt; &lt;span &gt;Name&lt;/span&gt;&lt;span &gt;=&amp;quot;ID_CAP_GAMERSERVICES&amp;quot;&lt;/span&gt;&lt;span &gt;/&amp;gt;&lt;/span&gt;&#xD;
    &lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;Capabilities&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
    &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Tasks&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
      &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;DefaultTask&lt;/span&gt;  &lt;span &gt;Name&lt;/span&gt; &lt;span &gt;=&amp;quot;_default&amp;quot;&lt;/span&gt; &lt;span &gt;NavigationPage&lt;/span&gt;&lt;span &gt;=&amp;quot;OpenXLive.Silverlight;component/Forms/StartupPage.xaml&amp;quot;&lt;/span&gt;&lt;span &gt;/&amp;gt;&lt;/span&gt;&#xD;
    &lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;Tasks&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
    &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Tokens&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
      &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;PrimaryToken&lt;/span&gt; &lt;span &gt;TokenID&lt;/span&gt;&lt;span &gt;=&amp;quot;OpenXLiveGameSilverlightToken&amp;quot;&lt;/span&gt; &lt;span &gt;TaskName&lt;/span&gt;&lt;span &gt;=&amp;quot;_default&amp;quot;&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
        &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;TemplateType5&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
          &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;BackgroundImageURI&lt;/span&gt; &lt;span &gt;IsRelative&lt;/span&gt;&lt;span &gt;=&amp;quot;true&amp;quot;&lt;/span&gt; &lt;span &gt;IsResource&lt;/span&gt;&lt;span &gt;=&amp;quot;false&amp;quot;&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;Background.png&lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;BackgroundImageURI&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
          &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Count&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;0&lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;Count&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
          &lt;span &gt;&amp;lt;&lt;/span&gt;&lt;span &gt;Title&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;OpenXLiveGameSilverlight&lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;Title&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
        &lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;TemplateType5&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
      &lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;PrimaryToken&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
    &lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;Tokens&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
  &lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;App&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&#xD;
&lt;span &gt;&amp;lt;/&lt;/span&gt;&lt;span &gt;Deployment&lt;/span&gt;&lt;span &gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;在WMAppMainifest.xml文件中找到&lt;b&gt;DefaultTask&lt;/b&gt;节点，并将其中的NavigationPage改为&amp;#8221;OpenXLive.Silverlight;component/Forms/StartupPage.xaml&amp;#8221;。这样能保证Silverlight游戏启动之后，会首先启动OpenXLive的Startup页面。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;接下来，我们还要完成对XLiveSLFormManager对象的初始化工作。打开工程中的App.xaml.cs文件，首先在文件顶部加入对OpenXLive.Silverlight的引用：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;using&lt;/span&gt; OpenXLive.Silverlight;&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;然后，在App类中找到&lt;b&gt;Application_Launching&lt;/b&gt;方法，加入XLiveSLFormManager对象的创建操作：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;// Code to execute when the application is launching (eg, from Start)&lt;/span&gt;&#xD;
        &lt;span &gt;// This code will not execute when the application is reactivated&lt;/span&gt;&#xD;
        &lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Application_Launching(&lt;span &gt;object&lt;/span&gt; sender, LaunchingEventArgs e)&#xD;
        {&#xD;
            XLiveSLFormManager manager = &lt;span &gt;new&lt;/span&gt; XLiveSLFormManager(&lt;span &gt;this&lt;/span&gt;, &lt;span &gt;&amp;quot;xxxxxxxxxxxxxxxx&amp;quot;&lt;/span&gt;);&#xD;
        }&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;其中，第一个参数为App实例的引用，第二个参数为SecretKey，该Key是在OpenXLive网站上创建游戏时，由系统生成的，作为OpenXLive系统识别游戏的唯一标识符，请保证这个SecretKey的安全，以防止其他游戏进行仿冒。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;更多详细情况，请查看《在开发者网站上创建OpenXLive游戏》，链接如下：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://wiki.openxlive.net/Tutorial-4-Create-OpenXLive-Game-in-website.ashx"&gt;http://wiki.openxlive.net/Tutorial-4-Create-OpenXLive-Game-in-website.ashx&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;当然，我们也可以在App类中创建一个static的FormManager属性，用于在程序的其他地方调用XLiveSLFormManager对象，但这一步不是必须的，代码如下：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;public&lt;/span&gt; &lt;span &gt;static&lt;/span&gt; XLiveSLFormManager FromManager { get; &lt;span &gt;internal&lt;/span&gt; set; }&#xD;
&#xD;
        &lt;span &gt;// Code to execute when the application is launching (eg, from Start)&lt;/span&gt;&#xD;
        &lt;span &gt;// This code will not execute when the application is reactivated&lt;/span&gt;&#xD;
        &lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Application_Launching(&lt;span &gt;object&lt;/span&gt; sender, LaunchingEventArgs e)&#xD;
        {&#xD;
            FromManager = &lt;span &gt;new&lt;/span&gt; XLiveSLFormManager(&lt;span &gt;this&lt;/span&gt;, &lt;span &gt;&amp;quot;xxxxxxxxxxxxxxxxxx&amp;quot;&lt;/span&gt;);&#xD;
        }&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;我们运行程序，能够看到下面的界面，是不是有一种似曾相识的感觉？点击Game Center和Leaderboards，我们可以进入相关的界面：&lt;/p&gt;&#xD;
&#xD;
&lt;p align="center"&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506135155.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="SLDemo3" border="0" alt="SLDemo3" src="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506133170.png" width="197" height="365" /&gt;&lt;/a&gt;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506139549.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="SL2" border="0" alt="SL2" src="http://images.cnblogs.com/cnblogs_com/aawolf/201104/20110402150614563.png" width="197" height="365" /&gt;&lt;/a&gt;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506156876.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="SL3" border="0" alt="SL3" src="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506156843.png" width="196" height="364" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;目前OpenXLive Silverlight只支持竖屏（Portrait）显示，未来我们会加入对于横屏（Landscape）的支持。另外，除了Startup界面之外，其他OpenXLive界面都是黑色背景，这样做主要是为了节省系统资源。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;添加背景和事件处理&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;接下来，为了美化启动界面，我们要加入背景图片。添加背景图片的操作非常简单：在Solution Explorer中，选择Project节点，右键单击，选择Add &amp;#8211; Existing Item，在选择一副PNG或JPG的图片，尺寸最好是800x480，这样能够有效保证图片不变形。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;另外请确认一下，我们加入的图片Build Action为Resource，且Copy to Output Directory选择&amp;#8220;Do not copy&amp;#8221;。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;然后，回到App.xaml.cs文件的Application_Launching方法中：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;// Code to execute when the application is launching (eg, from Start)&lt;/span&gt;&#xD;
        &lt;span &gt;// This code will not execute when the application is reactivated&lt;/span&gt;&#xD;
        &lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Application_Launching(&lt;span &gt;object&lt;/span&gt; sender, LaunchingEventArgs e)&#xD;
        {&#xD;
            FromManager = &lt;span &gt;new&lt;/span&gt; XLiveSLFormManager(&lt;span &gt;this&lt;/span&gt;, &lt;span &gt;&amp;quot;xxxxxxxxxxxxxxxxxxx&amp;quot;&lt;/span&gt;);&#xD;
            StartupPage.BackgroundPath = &lt;span &gt;&amp;quot;/OpenXLiveGameSilverlight;component/OpenXLive.Portrait.png&amp;quot;&lt;/span&gt;;&#xD;
        }&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;我们要为StartupPage添加BackgroundPath，示例代码的写法是针对游戏本身的资源，也可以指定一个来自Web的链接，不过出于显示效果的考虑，建议您不要这么做。OpenXLiveGameSilverlight，是资源所在程序集的名称；component/OpenXLive.Portrait.png，是资源的引用路径，如果资源包含在一个文件夹中，写法应该是component/MyFolder/OpenXLive.Portrait.png。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;最后提醒，请大家千万不要忘记字符串前面的&amp;#8220;/&amp;#8221;，没有这个符号，程序将抛出异常。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;接下来，我们要加入Startup页面的事件处理函数，当用户点击某一个按钮时，会触发一个事件操作。我们在下面增加了其中两个按钮的事件处理方法：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;public&lt;/span&gt; &lt;span &gt;static&lt;/span&gt; XLiveSLFormManager FromManager { get; &lt;span &gt;internal&lt;/span&gt; set; }&#xD;
&#xD;
        &lt;span &gt;// Code to execute when the application is launching (eg, from Start)&lt;/span&gt;&#xD;
        &lt;span &gt;// This code will not execute when the application is reactivated&lt;/span&gt;&#xD;
        &lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Application_Launching(&lt;span &gt;object&lt;/span&gt; sender, LaunchingEventArgs e)&#xD;
        {&#xD;
            FromManager = &lt;span &gt;new&lt;/span&gt; XLiveSLFormManager(&lt;span &gt;this&lt;/span&gt;, &lt;span &gt;&amp;quot;xxxxxxxxxxxxxxxxxx&amp;quot;&lt;/span&gt;);&#xD;
            StartupPage.BackgroundPath = &lt;span &gt;&amp;quot;/OpenXLiveGameSilverlight;component/OpenXLive.Portrait.png&amp;quot;&lt;/span&gt;;&#xD;
            StartupPage.NewGameButtonClick += &lt;span &gt;new&lt;/span&gt; EventHandler(StartupPage_NewGameButtonClick);&#xD;
            StartupPage.AboutButtonClick += &lt;span &gt;new&lt;/span&gt; EventHandler(StartupPage_AboutButtonClick);&#xD;
        }&#xD;
&#xD;
        &lt;span &gt;void&lt;/span&gt; StartupPage_AboutButtonClick(&lt;span &gt;object&lt;/span&gt; sender, EventArgs e)&#xD;
        {&#xD;
            MessageBox.Show(&lt;span &gt;&amp;quot;OpenXLive Silverlight Demo 1.0&amp;quot;&lt;/span&gt;);&#xD;
        }&#xD;
&#xD;
        &lt;span &gt;void&lt;/span&gt; StartupPage_NewGameButtonClick(&lt;span &gt;object&lt;/span&gt; sender, EventArgs e)&#xD;
        {&#xD;
            &lt;span &gt;this&lt;/span&gt;.RootFrame.Navigate(&lt;span &gt;new&lt;/span&gt; Uri(&lt;span &gt;&amp;quot;/MainPage.xaml&amp;quot;&lt;/span&gt;, UriKind.Relative));&#xD;
        }&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;AboutButtonClick的处理函数非常简单，只是调用了Message来显示游戏的版本信息。而NewGameButtonClick则是为了调用开发人员自己编写的Silverlight游戏界面，这个界面应该存在于Silverlight游戏的程序集中。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506162283.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="SL1" border="0" alt="SL1" src="http://images.cnblogs.com/cnblogs_com/aawolf/201104/20110402150617199.png" width="237" height="441" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;最后，我们得到的Silverlight启动界面就是上图这样。我们在Silverlight的界面中，没有增加Exit选项，因为Silverlight界面默认不支持退出操作，只能通过按Back键来退出程序。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;使用Wizard创建新游戏&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;接下来，我们要介绍如何使用Visual Studio 2010的Template来创建一个OpenXLive Silverlight游戏。OpenXLive Silverlight的模板会包括在OpenXLive SDK中，如果您安装了OpenXLive SDK，就可以在Visual Studio 2010中创建基于Silverlight的游戏了。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;首先，打开Visual Studio 2010，在File菜单中选择New-Project，在New Project对话框中，选择Visual C#下的Silverlight for Windows Phone中的OpenXLive Silverlight节点，然后选择创建OpenXLiveSilverlightGame。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506186512.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Wizard1" border="0" alt="Wizard1" src="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506196413.png" width="657" height="393" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;OpenXLiveSilverlightGame工程创建完毕后，如果直接编译，会得到下列的错误提示：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506193349.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Wizard2" border="0" alt="Wizard2" src="http://images.cnblogs.com/cnblogs_com/aawolf/201104/201104021506205824.png" width="631" height="148" /&gt;&lt;/a&gt; &lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;这个错误是为了提醒开发者，要在OpenXLive开发者网站上创建自己的游戏，获取游戏对应的Secret Key，才能够正常使用OpenXLive的在线功能。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;获取Secret Key的方法，请参考《在开发者网站上创建OpenXLive游戏》，链接如下：&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://wiki.openxlive.net/Tutorial-4-Create-OpenXLive-Game-in-website.ashx"&gt;http://wiki.openxlive.net/Tutorial-4-Create-OpenXLive-Game-in-website.ashx&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;打开App.xaml.cs文件，找到下面的代码：&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;public&lt;/span&gt; &lt;span &gt;static&lt;/span&gt; XLiveSLFormManager FromManager { get; &lt;span &gt;internal&lt;/span&gt; set; }&#xD;
&#xD;
&lt;span &gt;#error&lt;/span&gt; Please full your game Secret Key &lt;span &gt;in&lt;/span&gt; below code&#xD;
&lt;span &gt;private&lt;/span&gt; &lt;span &gt;string&lt;/span&gt; APISecretKey = &lt;span &gt;&amp;quot;xxxxxxxxxxxxxxxxxxxxxxxxxxxx&amp;quot;&lt;/span&gt;;&#xD;
&#xD;
&lt;span &gt;// Code to execute when the application is launching (eg, from Start)&lt;/span&gt;&#xD;
&lt;span &gt;// This code will not execute when the application is reactivated&lt;/span&gt;&#xD;
&lt;span &gt;private&lt;/span&gt; &lt;span &gt;void&lt;/span&gt; Application_Launching(&lt;span &gt;object&lt;/span&gt; sender, LaunchingEventArgs e)&#xD;
{&#xD;
    FromManager = &lt;span &gt;new&lt;/span&gt; XLiveSLFormManager(&lt;span &gt;this&lt;/span&gt;, APISecretKey);&#xD;
    StartupPage.BackgroundPath = &lt;span &gt;&amp;quot;/OpenXLiveSilverlightGame2;component/OpenXLive.Portrait.png&amp;quot;&lt;/span&gt;;&#xD;
    StartupPage.NewGameButtonClick += &lt;span &gt;new&lt;/span&gt; EventHandler(StartupPage_NewGameButtonClick);&#xD;
    StartupPage.AboutButtonClick += &lt;span &gt;new&lt;/span&gt; EventHandler(StartupPage_AboutButtonClick);&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;开发者将Secret Key加入到高亮显示部分，并且注释掉#error代码，我们的工程就可以正常编译了。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;我们也可以修改New Game Button的事件处理函数，来决定调用哪个Silverlight窗体。&lt;/p&gt;&#xD;
&#xD;
&lt;pre &gt;&lt;span &gt;void&lt;/span&gt; StartupPage_NewGameButtonClick(&lt;span &gt;object&lt;/span&gt; sender, EventArgs e)&#xD;
{&#xD;
    &lt;span &gt;this&lt;/span&gt;.RootFrame.Navigate(&lt;span &gt;new&lt;/span&gt; Uri(&lt;span &gt;&amp;quot;/MainPage.xaml&amp;quot;&lt;/span&gt;, UriKind.Relative));&#xD;
}&lt;/pre&gt;&#xD;
&lt;style type="text/css"&gt;&#xD;
&#xD;
&#xD;
.csharpcode, .csharpcode pre&#xD;
{&#xD;
	font-size: small;&#xD;
	color: black;&#xD;
	font-family: consolas, "Courier New", courier, monospace;&#xD;
	background-color: #ffffff;&#xD;
	/*white-space: pre;*/&#xD;
}&#xD;
.csharpcode pre { margin: 0em; }&#xD;
.csharpcode .rem { color: #008000; }&#xD;
.csharpcode .kwrd { color: #0000ff; }&#xD;
.csharpcode .str { color: #006080; }&#xD;
.csharpcode .op { color: #0000c0; }&#xD;
.csharpcode .preproc { color: #cc6633; }&#xD;
.csharpcode .asp { background-color: #ffff00; }&#xD;
.csharpcode .html { color: #800000; }&#xD;
.csharpcode .attr { color: #ff0000; }&#xD;
.csharpcode .alt &#xD;
{&#xD;
	background-color: #f4f4f4;&#xD;
	width: 100%;&#xD;
	margin: 0em;&#xD;
}&#xD;
.csharpcode .lnum { color: #606060; }&lt;/style&gt;&#xD;
&#xD;
&lt;p&gt;到这里，我们就介绍完了如何通过Visual Studio 2010向导来创建OpenXLive Silverlight游戏的方法。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;写在最后&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;我们用几乎与XNA版本相同的顺序，叙述了如何将OpenXLive Silverlight加入到Windows Phone Silverlight的游戏中去。接下来，我们会介绍，如何提交成绩、提交成就，考虑到Silverlight的界面编程更加容易，我们并不会提供一个标准的成绩提交界面，该界面只会以示例代码的形式出现。&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://wiki.openxlive.net/OpenXLive-Silverlight.ashx"&gt;http://wiki.openxlive.net/OpenXLive-Silverlight.ashx&lt;/a&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;引用&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;OpenXLive&lt;/strong&gt;&lt;strong&gt;官方网站&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://www.openxlive.net/"&gt;http://www.openxlive.net/&lt;/a&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;OpenXLive&lt;/strong&gt;&lt;strong&gt;开发者网站&lt;/strong&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://developer.openxlive.net/"&gt;http://developer.openxlive.net/&lt;/a&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;strong&gt;OpenXLive&lt;/strong&gt;&lt;strong&gt;开发入门&lt;/strong&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&#xD;
&#xD;
&lt;p&gt;&lt;a href="http://wiki.openxlive.net/Getting-Started-with-Open-XLive.ashx"&gt;http://wiki.openxlive.net/Getting-Started-with-Open-XLive.ashx&lt;/a&gt;&lt;/p&gt; &lt;img src="http://www.cnblogs.com/aawolf/aggbug/2003381.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aawolf/archive/2011/04/02/2003381.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/aawolf/archive/2011/03/31/2000973.html</id><title type="text">Game Center，移动游戏社交平台的勘探报告</title><summary type="text">当你读到这封信的时候，我们已经在路上了。南加州发现了金矿，先到那里的人会赢得鲜花、掌声，以及足以笑傲未来十年的资本。是的，我们站在移动互联网的破晓之时，这与淘金时代是多么的相似，每个人都狂热地进入这个领域，宣称自己拥有最先进的设备，足以找到地下深埋的黄金。资本的追捧，也让耐心与沉着离我们而去。</summary><published>2011-03-31T06:13:00Z</published><updated>2011-03-31T06:13:00Z</updated><author><name>马宁</name><uri>http://www.cnblogs.com/aawolf/</uri></author><link rel="alternate" href="http://www.cnblogs.com/aawolf/archive/2011/03/31/2000973.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/aawolf/archive/2011/03/31/2000973.html"/><content type="html">&lt;p&gt;Game Center，移动游戏社交平台的勘探报告&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;作者：马宁&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;缘起&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;亲爱的朋友，&lt;/p&gt;  &lt;p&gt;当你读到这封信的时候，我们已经在路上了。南加州发现了金矿，先到那里的人会赢得鲜花、掌声，以及足以笑傲未来十年的资本。是的，我们站在移动互联网的破晓之时，这与淘金时代是多么的相似，每个人都狂热地进入这个领域，宣称自己拥有最先进的设备，足以找到地下深埋的黄金。资本的追捧，也让耐心与沉着离我们而去。&lt;/p&gt;  &lt;p&gt;作为一个赶上互联网泡沫结尾的程序员，在我的记忆中，如今的互联网巨头都是活过了严冬的幸存者，上一个世纪里那些为怎么花钱发愁的互联网公司已经变成了遥远而古老的回忆，甚至已经无人记起，宛如南加州沙漠里的一颗沙砾。&lt;/p&gt;  &lt;p&gt;无论如何，移动互联网时代的巨人们已经在路上了，虽然在熙熙攘攘的人群里，他们是那么的不起眼，甚至还有一些寒酸。吃苦、技术，外加一点点运气，这是未来的巨人们手里仅有的武器，我们不必指点江山，任何一座山下埋藏的宝藏就足以创造一个时代的王者了，接下来的问题就是如何找到这些宝藏。&lt;/p&gt;  &lt;p&gt;我们都知道，这个移动互联网时代的起源是一家Apple的公司发布一款叫做iPhone的智能手机，但一款手机不足以颠覆PC与互联网时代，吹响安魂曲的是一个叫做App Store的服务。&lt;/p&gt;  &lt;p&gt;一句话概括，App Store让软件分发渠道从少数顶尖软件公司的手里解放出来，让小团队和个人开发者的应用可以直接与最终用户见面。这就像真人秀的节目一样，冠军就在选手之中，可是谁也不知道冠军是谁。每一个参赛者不是为了争取一份养活自己的收入，而是为了获得最后的大奖。于是，无数的创富奇迹被有意或无意地创造出来了。目前，这个有30万参赛者的真人秀节目，已经有了第一季的冠军，是的，它来自北欧，一个因为长夜漫漫而盛产程序员的地方。&lt;/p&gt;  &lt;p&gt;其他的手机厂商也在模仿，所以，我们将App Store称之为一种模式，在另外一些厂家嘴里，叫做Marketplace。&lt;/p&gt;  &lt;p&gt;接下来，我们所谈论的一切，都是建筑在App Store这种新的分销模式之上，App Store将彻底改变整个计算机世界的体系与灵魂。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Service + Client&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;我们来描绘一下移动互联网时代的蓝图吧，尽管已经有无数人对此有了专门的论述，其中颇为著名的就是《长尾理论》。&lt;/p&gt;  &lt;p&gt;当产品展示的成本趋近于零，为用户提供越多的产品，就能够获取越丰厚的利润，因为再小众的产品也有被消费的需求。而App Store几乎就是长尾理论在移动互联网上的完美实现。&lt;/p&gt;  &lt;p&gt;而App Store的另一大贡献是整齐划一的定价原则，大部分应用都以 0.99美金的价格销售，这一点来自于Apple另一个成功的在线服务——iTunes。说到&amp;#8220;微创新&amp;#8221;，Apple才是微创新的大师，Apple在产品创新上极为谨慎，几乎每一个成功的产品总有上一个成功产品的影子。&lt;/p&gt;  &lt;p&gt;所以，App Store上的应用被极度细分，每一个功能都会成为一个单独的应用。而在App Store之前，大的软件公司总是试图在一个产品里塞入更多的功能，这主要是为了解释软件为什么要卖那么贵，于是用户经常为一个功能而购买了一个包含几十项功能的工具包。其实，真正的成本来源于软件分发渠道，消费者50%的价格是支付给零售渠道的（这个情况，在各个国际地区会有很大差距，所以这个结论不包括中关村那些抱孩子的妇女）。&lt;/p&gt;  &lt;p&gt;回过头来看，App Store 3：7的分成比例，其实真的已经非常合理了，当然App Store也没有为店面、物流而增加任何成本，因为&amp;#8230;&amp;#8230;商店开在每个人的手机上。&lt;/p&gt;  &lt;p&gt;反过来看App Store对于开发者的影响，首先是小团队和个人开发者获得了前所未有的机会；其次是应用程序的小品化，每一个功能都可以成为一个软件；然后，客户端应用将在移动设备上的主流，70%的功能会来自客户端应用。也许很多人会寄希望于HTML 5，如果你相信几个心怀鬼胎的宿敌能够为了统一的互联网而努力奋斗，那么我无话可说。悄悄的说，你没发现几个主流智能手机平台间的开发环境是越差越多了吗？注：拍我之前请先拍死《Web已死》。&lt;/p&gt;  &lt;p&gt;接下来是什么？在线公共服务受到热捧。虽然Facebook在互联网上获得了巨大的成功，但我们应该将其视为一家移动互联网公司，因为40%的用户会通过移动设备来访问Facebook。这只是表象，真正的原因是Facebook提供了一套完整的API，允许各种应用（不仅限于移动设备上的应用）接入Facebook的服务之中。&lt;/p&gt;  &lt;p&gt;于是，Facebook不提供任何的应用和功能，只提供一个高达五亿的用户关系图谱，以及相关的图片、信息、身份验证的服务。无数的应用及游戏为了拥有这张关系图谱，而选择接入Facebook的系统，于是Facebook就拥有了无数的游戏和应用，而衍生的广告和支付服务，还可以帮Facebook获取利润。用户是我的，什么都是我的，Facebook如是说。&lt;/p&gt;  &lt;p&gt;而且Facebook已经为进入移动互联网做好了准备，这一点从其开发者网站上，将Mobile App作为单独的分类出现就可以看出来。通过API接入的方式，让Facebook远离了多变的用户需求和难以捉摸的用户体验，让他们关注于自己的核心价值——人与人的关系。当别人还在关注Web端的展现时，Facebook已经在关注以Client为核心的下一代移动互联网了。与此类似的是Twitter，与Facebook关注于人与人之间的关系不同，Twitter更像是一个信息传递的媒体，Twitter本身就是为手机准备的，比如140个字的限制就来源于SMS的技术瓶颈。虽然最近爆出Twitter认为客户端过多的新闻，但相信这只是前进路上的一时迷惘，Twitter很快就会重新回到正确的路上的。&lt;/p&gt;  &lt;p&gt;所有的互联网公司都会捱过冰川世纪，成功地进入下一个时代吗？答案显然是否定的，那么，什么样的公司会成为灭绝的恐龙？先看看恐龙的特征，体形庞大，无所不能，同时消耗大量的资源。看似无可匹敌的庞然大物，在外部环境发生骤然变化时，无法获得足够多的资源而快速灭绝了，反而是那些相对弱小的动物熬过了漫漫长夜。&lt;/p&gt;  &lt;p&gt;生物界的自然法则同样适用于互联网领域，某些公司利用充足的资源在所有领域遏制竞争对手，虽然依赖强大的用户群和充足的现金流，他们可以赢得任何一场战役的胜利。但是，他们缺少创新能力，模仿是唯一的产品发展渠道。当所有创新公司都在计划阶段首先考虑绕开这家公司时，这家公司的创新能力在逐渐萎缩。更可怕的是，当这家公司试图进入所有领域时，他们不在乎单个产品是否赚钱，维护大量的不赚钱产品会消耗大量社会资源。而且这些不赚钱产品缺少正常的淘汰机制，反而会加剧整个公司的机构膨胀和决策缓慢。&lt;/p&gt;  &lt;p&gt;退出桌面，是目前互联网那个巨头转型到移动互联网时代的生死劫。在过去十年中，那个巨头的策略是占领桌面，用户所需要的每一种功能都可以在这家公司的客户端中找到，所以，用户就无法离开这家公司所提供的服务。而到了移动互联网时代，随着智能手机、平板电脑平台越来越多，想要抓住每个最终用户，就必须支持每一个移动平台，开发的难度和资源消耗是以倍数增长的。退出桌面、提供开发式平台，成了唯一的选择，但是上一个十年中种下的恶果，是否会成为下一个十年中的原罪？&lt;/p&gt;  &lt;p&gt;移动互联网的开发者需要掌握用户需求、并作出快速响应，根据市场变化及时调整产品策略。小团队在这方面做得永远比大公司要优秀，他们所缺乏的是强大的后台支持系统。于是，一些大公司会将各种服务以开放平台的形式来提供，比如身份验证、手机支付、LBS、手机广告等。而小团队和个人开发者会调用各种服务，来完成各种充满创意的移动应用。而最终用户是通过这些应用来获取各种移动互联网时代的服务。&lt;/p&gt;  &lt;p&gt;所以，我们用下面三种角色来定义：&lt;/p&gt;  &lt;p&gt;服务提供商（Service Provider）：有一定规模的大公司，提供各种在线服务，定义在线服务标准接口；&lt;/p&gt;  &lt;p&gt;内容提供商（Content Provider）：小团队及个人开发者，调用在线服务，来实现各种移动应用和内容信息，将直接面对最终用户；&lt;/p&gt;  &lt;p&gt;最终用户（End User）：通过应用来访问各种在线服务，并通过购买应用、点击广告的形式来支持整个产业链。&lt;/p&gt;  &lt;p&gt;不过，千万不要以为服务提供商必须是大公司，很多的在线服务会由小公司或个人提供，比如提供自己家周围500米的天气预报服务、提供甲骨文与汉字对照服务。但由于他们无力定义在线服务的标准，并且没有足够资源推广他们的在线服务。通过某种形式，接入到几家有影响力的在线服务提供商的系统中，并通过标准接口为应用程序提供在线服务。目前，这种服务接入架构还没有出现，相信随着云计算平台的完善，这种在线服务接入方式很快会出现。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201103/20110331141313384.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="GameCenter1" border="0" alt="GameCenter1" src="http://images.cnblogs.com/cnblogs_com/aawolf/201103/201103311413133939.png" width="345" height="408" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p align="center"&gt;&lt;b&gt;&amp;lt;&lt;/b&gt;&lt;b&gt;图：Service + Client&lt;/b&gt;&lt;b&gt;结构图&amp;gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;我们用了太多篇幅来勾勒移动互联网的框架，接下来，让我们来看看Game Center在线服务吧。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;移动互联网的第二座金矿&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;如果说App Store是移动互联网时代的第一座金矿，现在我们试着寻找第二座金矿，LBS、手机支付、手机广告，都是第二座金矿的理想选择，我们选择的是一个相对生僻的领域——Game Center。我们姑且将&amp;#8220;移动游戏社交平台&amp;#8221;称之为Game Center吧，这是Apple的叫法，在XBox 360上叫做XBOX LIVE，在PS3上叫做PSN。这也是移动互联网的一大特色，不同平台上的同一个东西会有不同的名字。&lt;/p&gt;  &lt;p&gt;Game Center可以分为两类，一种是由操作系统厂商提供的，比如iPhone的Game Center，Windows Phone 7上的XBOX LIVE；另一种是第三方提供的，比如iPhone、Android上的OpenFeint、ScoreLoop、Plus+，Windows Phone 7上的OpenXLive。&lt;/p&gt;  &lt;p&gt;说到Game Center的起源，也可以分为两类：来自家用游戏机，比如XBOX LIVE和PSN，他们定义了Game Center的基本要素，比如用户ID、头像(或Avatar)、积分榜和游戏成就等；智能手机原生平台，这个就必须谈到大名鼎鼎的OpenFeint了。&lt;/p&gt;  &lt;p&gt;OpenFeint的作者是iPhone游戏的早期开发者之一，开发了一款叫做Aurora Feint的游戏，其中包含了在线积分榜和游戏成就系统。一些iPhone的游戏开发者开始在自己的游戏里使用该系统，以至于Aurora Feint的开发者发现这个积分系统比游戏更加流行，便将积分榜和成就系统拿出来形成单独的产品，于是就形成了著名的OpenFeint。&lt;/p&gt;  &lt;p&gt;可以说，OpenFeint的发展历史也恰好勾勒出Game Center的特点。由于智能手机的游戏开发者都是小团队或个人开发者，开发积分系统虽然没有什么难度，但是服务器的维护、代码的后期管理，这些工作量就已经超过了游戏开发本身。出于经济学的考虑，开发者如果单独维护积分系统，还不如再去开发一个新的游戏。于是，较早起步的开发者会共享自己的服务器资源、积分系统代码，而随着游戏数量的快速攀升，维护积分系统本身的收益，却超越了开发游戏本身。社会分工更加明确，使得移动游戏开发形成了分工更为明晰的生态系统。&lt;/p&gt;  &lt;p&gt;在家用游戏机上，XBOX LIVE和PSN也是最火热和最赚钱的在线服务，但是一直处于从属地位。原因大概与游戏机上的游戏多为大制作，使得玩家更加关注游戏本身，而积分榜、成就系统的界面也会根据游戏进行定制，使得用户不易察觉背后的积分、成就系统。&lt;/p&gt;  &lt;p&gt;真正赋予Game Center实际意义的还是智能手机平台，玩家在家用机平台上更多是扮演一个虚拟的角色，联机对战功能也是由游戏自身提供的。而在手机游戏中，玩家会更接近真实的自己，增加了位置定位功能和SNS交互功能之后，手机游戏会向SNS游戏的方向发展，增加更多真实好友间的互动特性。&lt;/p&gt;  &lt;p&gt;目前Game Center还处于初始阶段，单机游戏仍然是手机游戏的主流。手机游戏同样会经历PC游戏的发展历程，从单机游戏、到局域网对战、再到广域网对战，最后是多人实时在线游戏。当然，由于手机游戏，是在人们零散的时间中消遣娱乐的方式，所以弱连接的交互游戏，会比强连接的多人游戏有更大的发展空间，但从单机到多人的发展趋势是变不了的，因为人类是群体动物，沟通与交流是他们的本能之一。&lt;/p&gt;  &lt;p&gt;从上面的介绍中，我们可以发现，Game Center是一个与游戏数量紧密相关的在线服务。如果没有足够多的游戏，Game Center的服务器开销、维护成本、开发资源的支出，使Game Center处于入不敷出的状态。最可怕的是，如果没有吸引到足够多的用户，就无法吸引更多的开发者使用该服务，会使得用户资源与游戏资源处于逐渐枯竭的状态。只有当游戏数量超过阀值之后，新增的游戏所消耗的服务器资源趋近于零，于是，又一个经典的长尾理论场景出现了，可以提供无数个的在线游戏，再冷门的游戏也会有自己忠实的拥趸。当游戏数量达到一定程度后，热门游戏会逐渐浮出水面，几个热门游戏会为Game Center提供大量的注册用户，而注册用户数量恰好是Game Center服务的最好推手，很多新的游戏形式会随之出现。&lt;/p&gt;  &lt;p&gt;我不知道这个阀值是多少，但是OpenFeint在2010年9月的数据是1000多款游戏、130万用户，平均每个游戏1300个用户。当然，游戏与玩家的分布绝对不是平均的，前几位的游戏肯定贡献了大量的用户。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;未来的两个方向&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;目前Game Center还处于初始阶段，到目前为止，没有任何一家第三方的Game Center盈利，成绩最好的OpenFeint也只是完成了第二轮融资。未来的发展方向是什么，如何盈利，这些问题困扰着每一个在黑暗中前行的创业者。&lt;/p&gt;  &lt;p&gt;XBOX LIVE和PSN采用的是订阅收费的机制，这必须依赖于强大的平台支持，以及这个平台上拥有足够多的专属游戏，很多人成为XBOX LIVE的金会员，是因为XBOX 360上的游戏足够吸引人。&lt;/p&gt;  &lt;p&gt;而在手机游戏的世界中，向最终用户收费的订阅模式显然不合适，无论是原生平台，还是第三方平台，收费就意味着要与游戏开发者达成分成协议，因为Game Center服务是嵌入到游戏中的。手机操作系统提供商对于游戏开发者的控制，显然没有家用游戏机领域那么强势。这就是手机与家用游戏机最大的不同，游戏机靠的是质量，而手机游戏靠的是数量。&lt;/p&gt;  &lt;p&gt;那么，在Game Center上我们是否可以复制App Store的成功呢？还是先来看看各自的优缺点吧。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#183; App Store&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;模式简单，能在较短时间内带来大量收益，必须有操作系统和开发平台的支持，否则验证过程会成为埋葬无数财富与梦想的泥潭，这也是我不看好缺少操作系统支持和支付手段第三方App Store的主要原因。缺点是，一买一卖，缺少用户黏性，无法形成有效的反馈机制。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#183; Game Center&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;能够掌握大量用户的个人信息与好友关系，可以形成有效的信息反馈，与游戏开发者的结合更为紧密，拥有较高的用户黏性，通过推荐游戏方式，有助于用户形成持续的使用习惯。缺点是没有直接的获利模式，短时间内无法形成有效且持续的现金流。&lt;/p&gt;  &lt;p&gt;好了，Game Center如果想成为移动互联网时代的第二座金矿，那么只能扬长避短，利用自己的优势，找到合理的盈利方式，以确定下一步的发展方向。&lt;/p&gt;  &lt;p&gt;目前我们能够看到Game Center的未来发展方向有两种：Marketplace或SNS，需要指出的是，这两者之间不是非此即彼的关系，而是侧重点各有不同而已。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#183; Marketplace：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;我们在这里采用Marketplace的称呼，主要是泛指智能手机平台上的在线应用商店和店中店模式。这也是最明晰的一个发展方向，当你的网站拥有上千个游戏时，网站本身就会变成一个推广渠道。OpenFeint在这个方向上走的最远，OF Channel支持用户在手机上查看、浏览OpenFeint的游戏。店中店的形式可窥一斑，但这样最大的问题在于，需要和官方的Marketplace产生利益冲突，支付、下载等还需要依赖官方的Marketplace。在Android这种对第三方Marketplace控制不严的操作系统上，可能问题不大，换到iPhone上可能就存在一定的问题了。&lt;/p&gt;  &lt;p&gt;&amp;#8220;One Touch iPromote&amp;#8221;兼具了Marketplace和SNS的部分功能，但是目的还是为了推广应用，而非为最终用户提供一个SNS的交互平台。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#183; SNS：&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Game Center是SNS Game吗？不是，Game Center是Game SNS。强调Game Center的SNS特性，也许是第三方Game Center的唯一出路。第三方Game Center大都选择支持多个手机平台，一则是开发者有向多个平台移植游戏的需求，二则，只支持某个手机平台的第三方Game Center，会面临原生Game Center的残酷绞杀。前面曾经讨论过第三方Marketplace一定败给原生Marketplace。同理，原生Game Center在自己的平台上也具有无以复加的优势，但这种优势是相对的，离开自己的平台之后，这种优势反而会变成一种劣势。不过，身边的朋友都使用一种手机的概率是微乎其微的，所以提供跨平台支持，是Game Center的必由之路。这种跨平台是无疆界的，XBOX LIVE支持Windows Phone和XBOX LIVE，这个充其量算是在自己院子里溜达了一圈，如果哪天XBOX LIVE宣布支持iPhone或Android，那才算真正的跨平台。&lt;/p&gt;  &lt;p&gt;OpenFeint和ScoreLoop对此看得非常清楚，在稳定了iPhone的基本盘后，毅然选择了Android作为第二平台，目前的成绩还不错。不过目前的SNS交互，仍然游离于游戏之外。如果让SNS与游戏结合，也许是接下来我们要思考的问题。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;未来的服务&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;接下来，我们试着探讨一下未来Game Center会支持的在线服务有哪些。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;SNS&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;由于目前的手机游戏仍旧以单机版为主，增加其互联互通的特性，应该是下一步的发展重点。但是，人们用手机游戏消磨的主要是零散时间，比如开会前的几分钟，等人的时候等，且地点不固定。所以，手机游戏不会像PC游戏那样，首先演化出局域网游戏来，然后再扩展到广域网上去。所以，对于时间和及时性要求不那么高的SNS游戏会抢得先机。&lt;/p&gt;  &lt;p&gt;SNS游戏也许会成为手机游戏的下一个热点，在这个热潮中，Game Center大有可为。因为从本质上说，Game Center就是一个带积分榜、游戏成就的用户交互系统。建立用户交互系统，是一个手机游戏开发者所不能企及的， 这就需要专业的Game Center提供商为游戏开发者提供完善的用户注册、验证服务。&lt;/p&gt;  &lt;p&gt;目前的Game Center系统仅仅将SNS看作用户登录的接入方式，还没有提供将SNS嵌入到游戏中的接口。如何定义和抽离SNS游戏中的共有元素，使其成为积分榜、游戏成就那样的标准元素，并将接口标准化，将是Game Center下一步发展的重点。&lt;/p&gt;  &lt;p&gt;Facebook是最接近这种架构的在线服务，但是Facebook是将Web SNS游戏的服务器接入到自己的服务中去，并且开放自己的用户登录系统和消息系统。这个架构对于Web SNS游戏来说是足够好的，但是如果直接应用到手机的SNS游戏中，就意味着游戏开发者需要搭建自己的服务器，这样他们对Game Center服务的依赖度就会变低。&lt;/p&gt;  &lt;p&gt;如何抽离共有信息和游戏信息，并将其有效地标准化、接口化，将考验未来每一个打算提供SNS服务的Game Center提供商。&lt;/p&gt;  &lt;p&gt;另一个关键点是Avatar的标准化，XBOX LIVE在这方面走在了前边，提供了一个3D卡通编辑界面，能够设计出与玩家类似的卡通形象。游戏开发者可以通过标准接口来调用这些卡通形象，并将其应用在游戏之中。不过，目前成功嵌入Avatar的XBOX LIVE游戏并不多，可能的原因有以下几点：开发较为复杂，3D形象受到限制，Avatar与游戏的契合度不高（想象一下，在三国游戏中，忽然出现一个戴牛仔帽的人物？）。&lt;/p&gt;  &lt;p&gt;总之，SNS Game Center缺的不是需求，缺的是标准化的接口。OpenFeint的历史教育我们说，当我们不知道怎么做的时候，说明时机还未成熟，也许手机上出现大量SNS游戏时，才是Game Center加入SNS最好时机。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Location Based Game&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;LBG？是的，我们讨论的是在Game Center中加入LBS功能。目前的LBS典型应用是Foursquare，通过Check-in获取徽章、赢得奖励的方式，其实已经在LBS应用中增加了游戏的元素。LBG游戏也随之出现，比如城市追逐类、大富翁类，利用玩家所在的真实位置，来进行虚拟游戏。&lt;/p&gt;  &lt;p&gt;LBG听起来不错，但是和Game Center有什么关系？本来没有，但是放到移动设备的场景下就有关系了。游戏的主题、策划、兴趣点，是需要经常变化的，才能吸引玩家乐此不疲。在这之外，什么是不变的？定位服务、好友关系，现在是不是觉得跟Game Center有那么点关系了？&lt;/p&gt;  &lt;p&gt;我们需要做的事情是将LBS抽离出来，封装成标准化的接口，比如发现游戏玩家的位置信息、查看好友状态、邀请好友加入游戏，然后让游戏开发者通过标准接口进行调用，实现不同题材的游戏。&lt;/p&gt;  &lt;p&gt;似乎LBS提供商和Game Center提供商都可以做这件事，为什么非要让Game Center来做呢？优势有两点：第一，开发者熟悉了Game Center的API调用方式，会更加容易地使用Game Center所提供的API；第二，虽然加入LBS服务对于Game Center来说，也不算容易，但相比起LBS供应商要加入游戏元素来，还是要简单许多。&lt;/p&gt;  &lt;p&gt;还有一点，LBS服务提供商本身也是应用提供商，会和游戏开发者存在竞争关系，而Game Center则和已有的LBS提供商没有任何交集。当然，免费的LBS服务也要活跃起来了，比如Google Location还有MobileMe，哦，MobileMe免费？谁说的？等等看吧。&lt;/p&gt;  &lt;p&gt;LBG得到游戏玩家的接受，恐怕还有一段时间，个人认为，最早获得成功的LBG游戏，应该是城市探索/解谜类的游戏，穿梭在陌生的街巷之中，试图发现青砖黛瓦背后的虚拟真相，我就是名侦探&amp;#8230;&amp;#8230;动画片看多了。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;云游戏平台&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;我们不能将云游戏平台视为一种游戏在线服务，因为它是一种Cloud Computing Hosting。虽然Amazon、Microsoft、Google都提供了完整的云计算解决方案，他们将会统治未来十年的主流云计算领域。&lt;/p&gt;  &lt;p&gt;但是在某些细分领域中，其他的云计算供应商仍有机会。因为通用的云计算平台可能有存在以下问题：&lt;/p&gt;  &lt;p&gt;1， 不适用于某些具体的应用场景；&lt;/p&gt;  &lt;p&gt;2， 供应商会打包卖给你许多用不着的服务；&lt;/p&gt;  &lt;p&gt;3， 为了通用性考虑，而损失了某个领域/功能上的实用性&lt;/p&gt;  &lt;p&gt;归根到底，选择哪种云计算平台，还是开发者说了算。当然，我们在这里讨论的云计算专指PaaS，而并非IaaS。&lt;/p&gt;  &lt;p&gt;提供一个云计算开发平台、提供云计算服务集群，听起来似乎是只有业内的领头羊才可以做的事情，但是如果加上&amp;#8220;细分市场&amp;#8221;这个前提条件，范围一下子就变大了。&lt;/p&gt;  &lt;p&gt;通用领域的云计算市场肯定会由几家巨头公司来把持，但是对于某些细分市场来说，整合他们的共有需求，提供针对专门领域的云计算服务也不是不可能的。某个特定领域是否需要云计算，并不是由某个善于拍脑袋的领导决定的，而来源于这个领域的真实需求。比如，MMORPG肯定不需要云计算，因为服务器是游戏运营公司的核心资产，他们需要开发独有的服务器端应用、维护服务器，云计算减少的维护成本，不足以弥补转型所带来的开发成本上涨。如果将来他们转向云计算，那也一定是IaaS，而肯定不会是PasS。&lt;/p&gt;  &lt;p&gt;那么手机游戏领域是否适合云计算呢？非常适合，原因是手机游戏的主力是小团队或个人开发者开发的&amp;#8230;&amp;#8230;这个理由说了很多遍了。无力维护服务器，单独租用服务器不合算，都会成为手机游戏开发者选择云计算的理由。而通用的云计算服务，也未必适合这些开发者，尤其是当这些开发者还需要接入到公用的用户登录系统、SNS系统、游戏积分系统时，这种通用的云计算服务会让用户的自定义数据游离于整个游戏服务体系之外。&lt;/p&gt;  &lt;p&gt;最佳的选择，就是由Game Center提供商来提供游戏云计算服务，我们可以将其称之为云游戏平台（Cloud Game Platform）。前面所述的游戏通用服务，身份验证、SNS、游戏积分等，由统一的Game Center平台来提供。而某些与游戏逻辑密切相关的逻辑与数据，就需要游戏开发者自己定义数据存储结构、逻辑代码，并将其部署到云游戏平台之中，由云游戏平台来解决负载均衡之类的问题。&lt;/p&gt;  &lt;p&gt;说白了，就是让个人开发者拥有开发网络游戏的能力。而云游戏平台的收费模式，可以是按月租赁的方式，也可以是按游戏收入分成的方式。&lt;/p&gt;  &lt;p&gt;这个构想需要跨越障碍非常之多，比如服务器的稳定性、游戏数据如何定义、开发环境是否符合游戏开发使用习惯、如何保证开发者程序的安全性。&lt;/p&gt;  &lt;p&gt;不过，Game Center在手机网络游戏这个细分市场上，会拥有比通用云计算服务更加突出的优势，因为Game Center提供了大量基于SaaS的通用服务，而基于PaaS的自定义服务只会占用开发者非常少的开发时间，这比起使用通用的云计算服务来说，要先进很多。&lt;/p&gt;  &lt;p&gt;云游戏平台会在三年内完成技术储备，大概五年之后，会成为手机游戏市场上的主流。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;盈利模式&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;在说完Game Center未来的服务模式之后，我们继续下一个敏感话题——Game Center如何盈利？推广分成的模式已经在前边介绍过了，所以我们就不在这里讨论了。&lt;/p&gt;  &lt;p&gt;我们试图按照由早及晚的方式来，排列以下的几种盈利模式：&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;广告&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;广告是最简单的模式，也是最难的模式。这取决于你如何看待广告：如果只是接入到已有的在线广告服务中去，他无疑是最简单的盈利模式，已经有很多游戏证明，通过广告的收入甚至可以和销售软件的收入相媲美。&lt;/p&gt;  &lt;p&gt;而如果你想自己来做一个广告发布平台的话，它又是最复杂的模式。首先要解决用户兴趣与广告之间的匹配问题，屏蔽竞争对手广告，建立广告供应商体系。当然这一切都与最终用户的数量密切相关。&lt;/p&gt;  &lt;p&gt;由于广告嵌入在游戏之中，所以还要和开发者就分成比例达成一致，而开发者还可以选择成熟的广告供应商。由于和Game Center的核心业务缺乏交集，想成为独立的广告供应商，对于Game Center来说是不能承受之轻。&lt;/p&gt;  &lt;p&gt;当用户达到万级规模时，就可以通过嵌入广告的方式来尝试盈利了，但自己成为广告供应商的时机，就不是我能够揣测的了。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;道具&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;还是回到与游戏相关的领域吧，MMORPG已经为我们诠释了完美的收费模式，尤其是中国的网络游戏运营商创造&amp;#8220;免费游戏、收费道具&amp;#8221;的方式。&lt;/p&gt;  &lt;p&gt;收费道具，仍旧是手机游戏中尚未充分开发的一个新领域。在MMOPRG中，收费道具主要是为了与他人PK时成为杀人利器，从而更好的保护自己的虚拟生命及财产，当然收费道具也兼具了显摆的功能。限量版、绝版道具可以买到一个天价，显摆是一个很好的理由。&lt;/p&gt;  &lt;p&gt;可是，我们要考虑手机游戏的现状：单机版为主、SNS游戏初露端倪。在缺少众人围观的网络世界中，道具似乎无法卖到一个天价。但是，工具类道具和成就类道具，仍旧可以占得一席之地。&lt;/p&gt;  &lt;p&gt;&amp;#183; 工具类道具&lt;/p&gt;  &lt;p&gt;指的是能够帮助玩家节省游戏时间、直接通关、避免危险的辅助类道具。那些偏好使用辅助工具的玩家可以先使用虚拟货币购买道具，使之形成使用道具的习惯，通过游戏数值分析，当玩家面临困难挑战时，使用虚拟货币购买的道具不足以帮其完成任务，促使其购买虚拟货币，再使用虚拟货币购买道具。&lt;/p&gt;  &lt;p&gt;&amp;#183; 成就类道具&lt;/p&gt;  &lt;p&gt;指的是资深玩家可以通过某些困难关卡获得的随身携带的道具，比如运动类游戏中的护腕、项链等，还能够显示在玩家的个人信息页面中。成就类道具，可以说是一种可以随身携带的游戏成就。&lt;/p&gt;  &lt;p&gt;资深玩家可以通过卖掉这些道具换取虚拟货币，普通玩家也可以通过购买来获取这些道具。&lt;/p&gt;  &lt;p&gt;也许还有其他形式的道具，慢慢补充吧。这里就涉及到一个关键点了：道具商店。之前游戏的道具商店都是由开发者自己掌控，说白了，就是把游戏里赚到的虚拟金钱转换成虚拟道具，只是游戏的形式之一，并不具有MMORPG中的那种价值体系。&lt;/p&gt;  &lt;p&gt;但是，如果把道具商店抽象出来，变成与积分榜、游戏成就的独立体系行不行呢？开发者通过道具商店来定义道具属性、价格，当玩家购买道具时，支付虚拟货币给道具商店，商店与开发者按一定比例进行分成，然后开发者可以按一定汇率将虚拟货币兑换成真实货币，变成真实的收入。&lt;/p&gt;  &lt;p&gt;呵呵，一切听起来都很完美是不是？道具商店有可能成为下一个Marketplace，但首先要解决一进一出的问题：进，指的是用户的支付，出，指的是道具商店向开发者支付报酬的渠道。还有虚拟货币如何保值的问题，还是留到后边再讨论吧。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;游戏关卡&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;目前在iPhone中已经支持了这种方式，不过也引起了正当性的争议。对于诈骗类的收费方式，我们在这里就不做讨论了，只是想寻找另一种合理的游戏内付费方式，比如关卡。&lt;/p&gt;  &lt;p&gt;网络文学的收费模式通常是这样，由作家先写几十章出来，供用户免费阅读，当用户如痴如醉之时，小说宣布开始收费，为了能够看到最新的章节，很多人开始付费，不愿意付费的人可能要等一段时间。&lt;/p&gt;  &lt;p&gt;这个收费模式同样适用于手机游戏之中，首先提供免费游戏，游戏分为不同的关卡，当用户玩到上瘾时，后边的关卡开始收费。要知道，游戏的吸引力要远远大于小说。这样做的另外一个好处时，开发者会专注于提高游戏品质和可玩性，而不会把心思放到另外一个坑蒙拐骗的方式上去。&lt;/p&gt;  &lt;p&gt;游戏关卡的真正挑战是来自于技术层面，目前，所有封闭式的智能手机系统都不允许应用下载可执行文件，所以，在游戏内下载新关卡的路就被阻塞住了。&lt;/p&gt;  &lt;p&gt;解决方法有下面几种，不过各有局限性：&lt;/p&gt;  &lt;p&gt;&amp;#183; 将不同关卡分成单独的游戏：&lt;/p&gt;  &lt;p&gt;这种方式可以解决新关卡下载的问题，还可以利用内置Marketplace的支付功能。缺点是打断用户的游戏进程，当用户忙完下载和支付之后，可能也没有兴趣玩下一个关卡了。游戏关卡是一种冲动消费，采用游戏内付费的方式，仍旧是最佳选择。&lt;/p&gt;  &lt;p&gt;&amp;#183; 从服务器端获取逻辑：&lt;/p&gt;  &lt;p&gt;我们可以将关卡逻辑放到服务器端，当确定用户付费之后，从服务器端下载新关卡的逻辑。这样做的好处是不打断游戏进程，缺点是必须将所有关卡的资源放置到游戏之中，无法实现真正的实时更新，容易被破解。&lt;/p&gt;  &lt;p&gt;当然，这种收费模式还要依赖于出色的游戏关卡设计，如果设计出的关卡不吸引人，那么也无法获取更多的收益。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;虚拟货币/支付体系&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;虚拟货币不是一种盈利模式，但缺少虚拟货币的话，盈利模式就无从谈起。采用虚拟货币进行支付，已经成为各种游戏的通用方式了。虚拟货币的好处很多，主要的有：&lt;/p&gt;  &lt;p&gt;1， 缩短用户的支付环节：&lt;/p&gt;  &lt;p&gt;当用户处于冲动消费的状态下时，支付环节越长，放弃的可能性就越大，而且无助于提高游戏体验。&lt;/p&gt;  &lt;p&gt;2， 利用币值差异使用户产生错觉：&lt;/p&gt;  &lt;p&gt;我们可以人为制造币值差异，使得用户无法将虚拟货币与真实货币的价值联系起来，让他们产生富可敌国的印象，有助于增加他们的消费。&lt;/p&gt;  &lt;p&gt;3， 使用户忽略购买行为：&lt;/p&gt;  &lt;p&gt;实际上，用户使用真实货币购买虚拟货币是一种购买行为，而用户会认为这是一种兑换行为，他们仍旧持有等价值的虚拟货币。&lt;/p&gt;  &lt;p&gt;如果在Game Center中推行虚拟货币，所面临的挑战也是空前的。即使是MMORPG游戏中，虚拟货币也只能在某个游戏中流通，而Game Center的虚拟货币要在整个虚拟世界中流通，而构成这个世界的基本元素——游戏，是由不同开发者开发的。如何平衡每个开发者之间的利益，使得不会产生&amp;#8220;价格谷地&amp;#8221;，使每个游戏开发者的利益不会受到别人的损害。&lt;/p&gt;  &lt;p&gt;另外，如何保证Game Center中虚拟货币的币值稳定。这些工作加起来，与一个中小国家央行的责任也相差无几了。&lt;/p&gt;  &lt;p&gt;在考虑清楚这些问题之前，我只能送一句话给这些&amp;#8220;虚拟央行&amp;#8221;的行长们——&amp;#8220;像爱惜你的眼睛一样，爱惜你的虚拟货币&amp;#8221;。&lt;/p&gt;  &lt;p&gt;虚拟货币不是一个封闭的体系，有进有出。用户支付实际货币来购买虚拟货币，是虚拟货币的入口；而与开发者的分成、固定资产、人员成本，都可以视为虚拟货币的出口。而虚拟货币的出入口恰好就是支付体系的职责范围。&lt;/p&gt;  &lt;p&gt;支付体系，似乎每一个在线服务都需要这样的一套体系，但是真正能够适合全球、并且让最终用户、开发者都能够舒服使用的支付体系，其实没有多少。iTunes算是最为成功的一个支付体系了，但是在面对全球的税务体系、银行体系时，iTunes仍旧有很多照顾不到的地方。&lt;/p&gt;  &lt;p&gt;所以说，支付体系决定了虚拟货币，虚拟货币决定了以上的盈利模式。如果没有这两点的支撑，一切的盈利模式都是奢谈。&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;写到最后&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;综上所述，游戏基础服务（积分榜、游戏成就）、Social Network、Location-Based Service和虚拟货币/支付/广告系统，构成了Game Center的四大公共服务平台，而云游戏平台，则是Custom Service Hosting，用于满足游戏开发者在云端的一些个性化需求。这一切构成了一个完整的Game Center服务体系。&lt;/p&gt;  &lt;p&gt;游戏开发者通过标准的API来查询、调用各种由Game Center提供的在线服务，而Game Center更像是一个Cloud Service Proxy，除了Game Center本身提供的服务之外，还需要将其他服务进行重新的Mash-up使得开发者可以通过单一的API接口进行调用，当然对于接入的第三方在线服务，Game Center也有必要定义一套相应的接口。&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/aawolf/201103/201103311413135858.png"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="GameCenter2" border="0" alt="GameCenter2" src="http://images.cnblogs.com/cnblogs_com/aawolf/201103/201103311413135825.png" width="771" height="373" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p align="center"&gt;&lt;b&gt;&amp;lt;&lt;/b&gt;&lt;b&gt;图：Game Center Ecosystem&amp;gt;&lt;/b&gt;&lt;/p&gt;  &lt;p&gt;十年之后，当我们回望今天时，也许才能够看清这幅图的全貌。未来十年，也许会有许多的在线服务兴起，有更多在线服务退出市场。但是，云+端的体系，是未来十年的大框架、大趋势，做技术的人不是要创造一个趋势，而是顺应趋势、顺流而下，寻找属于自己的那一片天地。&lt;/p&gt;  &lt;p&gt;好了，我的朋友，以上这些，就是我对移动互联网第二座金矿——Game Center的勘探报告。我无法确定下一座金矿在哪里，只是试图将自己对移动互联网的理解变成现实。几个月以来，我们看了很多、想了很多、做了很多，深切地感触到——知易行难。哪怕是最简单的事情，在旷野中也会变得复杂无比。我们不知道自己能走多远，但我们的尝试却充满意义，哪怕失败，却不愿错过。&lt;/p&gt;  &lt;p&gt;南加州沙漠里的风沙很大，你们这些在玻璃房子里住惯的人要做好准备。&lt;/p&gt;  &lt;p&gt;致四个月前的自己！&lt;/p&gt;  &lt;img src="http://www.cnblogs.com/aawolf/aggbug/2000973.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/aawolf/archive/2011/03/31/2000973.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
