开发Silverlight游戏教程
- 格式:doc
- 大小:466.50 KB
- 文档页数:23
一步一步学Silverlight 2系列(14):数据与通信之WCF概述Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, Ironpython,对JSON、Web Service、WCF 以及Sockets的支持等一系列新的特性。
《一步一步学Silverlight 2系列》文章将从Silverlight 2基础知识、数据与通信、自定义控件、动画、图形图像等几个方面带您快速进入Silverlight 2开发。
本文将简单介绍在Silverlight 2中如何与WCF进行通信。
简单示例在本示例中,我们将通过WCF来获取一个最新随笔的列表,在Silverlight中显示出来,最终完后效果如下所示。
先定义一个数据契约:在Web项目中添加一个WCF Service文件,命名为Blog.svc 定义服务契约:实现服务,这里可以是从数据库或者其他数据源读取,为了演示方便,我们直接初始化一个集合:修改Web.config中的服务配置,这里使用basicHttpBinding绑定,并且开启httpGetEnabled,以便后面我们可以在浏览器中查看服务:设置一下Web应用程序的端口号为固定端口52424,在浏览器中输入http://localhost:52424/ Blog.svc,看看服务是否正常:好了,现在服务端我们就实现完成了。
现在编写界面展示部分,XAML如下:在Silverlight项目中添加服务引用,输入地址http://localhost:52424/Blog.svc,输入命名空间BlogService。
添加完成后,我们可以在对象浏览器中浏览一下生成的客户端对象:当然大家也可以手工去编写客户端的代码,请参考WCF的相关内容,这里不再赘述。
下面编写调用服务并获取数据,这里仍然是采用异步模式,由于在WCF服务的配置中我们采取了BasicHttpBinding,客户端也要采用BasicHttpBinding。
最后还剩下游戏入口部分,Silverlight是客户端插件,因此首选WCF作为它与服务器端数据库的桥接。
撇去UI方面华丽的动态角色创建与选择不再多说,本节的重点便是在教程Demo的基础上整合进基于WCF的注册与登陆等操作,使之最终成为一款相对完整而五脏俱全的RPG作品。
依旧钟情于LINQ,因此LINQ to SQL成为我操作数据库的首选。
强烈建议大家首先参考这篇文章:数据库LINQ TO SQL在Silverlight中的应用(WCF),其中的所有细节都已阐述得相当详细。
如果你的电脑中存有之前的Demo源码,那么接下来你可以按照下面的步骤跟着我一步步从零开始搭建游戏的登陆部分,真真切切的体会WCF技术在Silverlight中的常规应用。
第一步:依照游戏中角色注册、创建、相关信息及登录等需求设计数据库,并编写好相应可能会用到的增删改查等存储过程(本节Demo源码中附带了名为FS3.sql的数据库文件,表和存储过程都在其中)。
第二步:在Silverlight的寄主Web项目中右键->添加新项目->LINQ to SQL映射类,这里我取名为L2S.dbml:第三步:打开VS视图中的服务器资源管理器,右键添加SQL连接到FS3(SQL版本最好2005以上)后将其中的表和存储过程等均拖到L2S.dbml的设计窗口中形成大家再熟悉不过的映射:第四步:此时便可编写WCF操作类了,在Silverlight的寄主Web 项目中右键->添加WCF服务,取名为WCFService.svc:需要特别注意的是带返回类型的存储过程需要修改其相应属性为表实体,否则后面的逻辑查找不到:第五步:编写具体操作逻辑,搞过WCF开发的朋友此处可完全忽略,超级简单;没搞过的也很容易看懂,具体就不多说啦,直接列代码:[ServiceContract(Namespace = "")][AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityR equirementsMode.Allowed)][ServiceBehavior(IncludeExceptionDetailInFaults = true)]public class WCFService {[OperationContract]public void DoWork() { }///<summary>///添加新用户(添加过程中字符型超出限制长度则自动截取)///</summary>///<returns>新用户的ID,0则表示失败</returns>[OperationContract]public long InsertUser(string userName, string password, string real Name, string idCard, string eMail, string address) {using (L2SDataContext dc = new L2SDataContext()) {return Convert.ToInt64(dc.p_InsertUser(userName, password, r ealName, idCard, eMail, address, "", "").ReturnValue);}}///<summary>///用户资料验证///</summary>///<param name="userName">用户名</param>///<returns>0表示不存在</returns>[OperationContract]public int CheckUserExist(string userName) {using (L2SDataContext dc = new L2SDataContext()) {return dc.p_CheckUserExist(userName);}}///<summary>///用户登陆验证///</summary>///<param name="userName">用户名</param>///<param name="password">密码</param>///<returns>0表示不匹配</returns>[OperationContract]public int UserLogonValidate(string userName, string password) { using (L2SDataContext dc = new L2SDataContext()) {return dc.p_CheckUserLogon(userName, password);}}///<summary>///检查角色是否已存在///</summary>///<param name="name">角色名</param>///<returns>0表示不存在</returns>[OperationContract]public int CheckRoleExist(string name) {using (L2SDataContext dc = new L2SDataContext()) {return dc.p_CheckRoleExist(name);}}///<summary>///检查用户创建的角色数量///</summary>///<param name="userName">用户名</param>///<returns>角色数</returns>[OperationContract]public int GetUserRoleNum(string userName) {using (L2SDataContext dc = new L2SDataContext()) {return dc.p_GetUserRoleNum(userName);}}///<summary>///添加新角色///</summary>///<returns>新角色的ID,0则表示失败</returns>[OperationContract]public long InsertRole(string userName, string name, byte avatar, by te sex, byte occupation, byte roleLevel, long experience, long mapID, strin g lastIP, string remarks) {using (L2SDataContext dc = new L2SDataContext()) {return Convert.ToInt64(dc.p_InsertRole(userName, name, avata r, sex, occupation, roleLevel, experience, mapID, lastIP, "").ReturnValue); }}///<summary>///根据用户名获取该用户的所有角色///</summary>///<param name="userName">用户名</param>///<returns>创建的所有角色</returns>[OperationContract]public List<Role> GetRoleByUserName(string userName) {using (L2SDataContext dc = new L2SDataContext()) {return dc.p_GetRoleByUserName(userName).ToList<Role>();}}///<summary>///删除角色记录///</summary>///<param name="roleName">角色名</param>///<returns>失败0,成功1</returns>[OperationContract]public int DeleteRole(string roleName) {using (L2SDataContext dc = new L2SDataContext()) {return dc.p_DeleteRole(roleName);}}}复制代码第六步:也是最后一步,在RPGEffectsDemo项目中右键添加服务引用(Service References),然后检索到WCFService.svc完成即可。
创建您的第一个应用程序我们需要做的第一件事情是启动Visual Studio并创建一个新的项目。
在您启动Visual Studio,选择“新建项目”菜单中选择:文件- >新建- >项目这将打开“新建项目”对话框中。
在左侧的“模板”列表中,选择Visual C#中(Visual Basic中也可),然后Silverlight的。
然后选择“项目类型的Silverlight应用。
现在的名字你的项目的HelloWorld,然后选择确定。
接下来打开的对话框中询问您是否要创建一个新的网站,或简单地用一个测试页。
对于本示例中,取消选择“在一个新的网站主机的Silverlight应用程序”。
我们将使用“测试页”选项。
开发Silverlight应用程序时,在使用“网站”选项有一些好处,但这个例子中,测试页就足够了。
这是有创造一个新的Silverlight项目。
下一步我们将添加一些功能的应用程序。
如果您没有看到解决方案资源管理器(通常在右侧窗口),您可以从“查看” - >“解决方案资源管理器。
在解决方案资源管理器中,有一些项目文件。
我们将在此QuickStart中使用的文件MainPage.xaml 中和MainPage.xaml.cs 。
如果您不熟悉使用XAML,XAML是一种基于XML的声明性语言,用于创建和布局的UI元素。
请参阅XAML快速入门上的XAML的更多信息。
cs文件是在C#代码隐藏文件。
通过局部类代码隐藏文件是同一个XAML文件。
代码隐藏和局部类的更多信息,请参见代码隐藏和分部类MSDN文章。
从代码中分离的用户界面,允许您创建声明XAML标记可见的用户界面元素,然后使用一个单独的代码隐藏文件,以响应事件和操作您在XAML中声明的对象。
这种分离使得它很容易为设计人员和开发人员一起工作,有效地在同一项目。
双击上MainPage.xaml中。
这将在主编辑器窗口中打开MainPage.xaml文件。
在这个例程里,我们将选择还要添加一个 Web Application项目到解决方案里去,并将它命名为“DiggSample_WebServer”。
在点击OK之后,Visual Studio会为我们创建一个解决方案,里面包含一个Silverlight客户端应用和一个 web服务器端应用:如果我们做一次编译的话,Visual Studio会自动把编译好的Silverlight应用拷贝到我们的web服务器项目中去,不需要手工的步骤或配置。
VS为我们创建的默认的web 服务器项目包含一个网页和一个静态的HTML网页,我们可以用来运行和测试其中的Silverlight应用。
我们将开始改变网格的背景颜色,在其中声明一个Button控件。
我们将给按钮一个"x:Name"属性,设置其值为“MyButton“,这会允许我们在后台代码类中用编程的方法引用它。
我们还将设置它的Content,Width和Height属性:当我们运行应用时,我们的按钮将会在网页的中间出现,内含”Push Me“内容文字,象下面这样:要给我们的按钮加行为的话,我们可以给它加一个"Click"事件处理函数。
我们可以在源码视图中通过输入事件的名称来做:然后就会提示我们在我们的后台代码类中该使用的事件处理函数:然后我们可以输入一个要用的新事件处理方法的名称,或者只要点击回车键,使用默认的命名约定来命名事件处理方法:然后VS就会自动地在我们的后台代码类文件中创建一个占位的事件处理函数实现。
我们可以使用这个事件处理函数在按钮被点击时,用新的消息更新它的内容:在做完上面的改动后,我们可以重新运行应用,再次点击按钮,现在它的内容就会被更新为“Pushed!”的消息:StackPanel常用于安排页面上的一个很小的UI部分。
例如,我们可以用下面的XAML标签在页面上垂直的排布3个按钮:在运行时刻,StackPanel会自动在一个垂直地堆叠(stack)中排列我们的按钮(【译注:这也是为什么叫StackPanel的原因】),如下所示:同样,我们还可以把Orientation属性设置为Horizontal而不是Vertical(默认值):以上代码会按下图方式排布按钮:除了支持绝对尺寸定义(如:Height="60"),Grid的RowDefinition和ColumnDefinition控件还支持自动改变大小的模式(Height="Auto"),这样会根据其中内容的尺寸自动改变Grid或Row的尺寸(你也可以指定最大或最小尺寸限制)。
Silverlight入门教程--基于运行环境示例郑健2008-3-9(一).概述 (3)(二). 代码示例 (3)1).基础知识示例 (3)1. 对象的定位 (3)2. 使用SilverLight插件 (8)3. SilverLight元素的鼠标事件 (10)4. SilverLight元素的键盘事件 (16)5.方法createFromXaml使用示例 (17)6.访问和修改Silverlight元素以及属性 (19)7. Silverlight中的字体使用 (21)8.全屏支持功能 (24)9. Silverlight Downloader 对象使用 (26)10.定时器功能 (29)11.错误处理支持 (31)12.把xaml段内置在aspx或html页面中 (34)2).制作图形示例 (36)13.基本图形形状示例 (36)14.画刷对象的使用 (38)15.视频刷对象的使用 (41)16.Path元素使用 (43)17.变换效果(Transform) (44)3).多媒体功能 (46)18.在线电影播放 (46)4).制作动画效果示例 (51)19.一个动画示例 (51)20.动画的交互控制 (53)21.动画关键帧示例 (55)(一).概述Silverlight是一个跨浏览器的、跨操作系统平台的插件,为Web带来下一代媒体体验和丰富的交互式应用程序体验. 使用JS实现Ajax技术可以使网站具有很好的用户体验, 但它也会使网站过于庞大和臃肿. 业余时间学习了一下微软的Silverlight官方教程, 在学习时顺便根据学习示例整理了一个教程. 此教程包括一些精简的小例子, 主要针对开发使用场景展开示例, 在实际开发中也可以作为查找手册使用. 运行环境为VS 2005, 这些示例比较简单很容易看懂, 因此示例没有太多注释.(二). 代码示例1).基础知识示例1. 对象的定位通过呈现几个Silverlight元素来示例对象之间的定位, 以及在一个页面中创建装载多个Silverlight对象.2. 使用SilverLight插件3. SilverLight元素的鼠标事件I.鼠标滑入和滑出事件II.鼠标点击(按下/弹起)和移动事件4. SilverLight元素的键盘事件5.方法createFromXaml使用示例6.访问和修改Silverlight元素以及属性7. Silverlight中的字体使用8.全屏支持功能9. Silverlight Downloader 对象使用10.定时器功能11.错误处理支持12.把xaml段内置在aspx或html页面中这样的话就不用单独的 *.xaml 文件来承载SilverLight对象控件元素内容.2).制作图形示例13.基本图形形状示例14.画刷对象的使用15.视频刷对象的使用16.Path元素使用17.变换效果(Transform)3).多媒体功能18.在线电影播放。
这是8个系列教程的第2部分,这个系列示范如何使用 Silverlight 2 的 Beta1 版本来创建一个简单的 Digg 客户端应用。
这些教程请依次阅读,将有助于您理解 Silverlight 的一些核心编程概念。
理解布局管理Silverlight 和 WPF 都支持一种灵活的布局管理系统,能让开发者和设计师轻松的定位 UI 上的控件。
该布局系统对显式指定坐标的控件支持固定的定位模型;除此之外,还支持一种更为动态的定位模型,控件和布局能随着浏览器的大小改变而自动改变其大小和方位。
在 Silverlight 和 WPF 中,开发者可以用布局面板来协调包含在其中的控件的位置和大小。
Silverlight Beta1 中内建的布局面板包括在 WPF 中最常用的3种:∙Canvas∙StackPanel∙GridCanvas面板Canvas 面板是一种很基础的布局面板,它支持对其中的控件采用绝对坐标定位。
你可以通过一种 XAML 特性--- "附加属性” 对 Canvas 中的元素进行定位。
用附加属性,你可以指定控件相对于其直接父 Canvas 控件的上、下、左、右坐标的位置。
附加属性很有用,因为它让父面板可以扩展其中包含的控件的属性集。
Canvas 通过定义扩展属性 Top 和Left, 就能定义其中 Button (或其他任何 UI 元素)的 Left, Top,而不需要真正向Button 类中添加这个属性,或修改 Button 类。
我们可以向 Canvas 容器中添加两个按钮,指定其距离 Canvas 左侧的距离为 50 像素,离上边的距离则分别为50 像素和150 像素。
使用如下XAML 语法即可完成(其中Canvas.Top 和 Canvas.Left 都是附加属性的例子):这些代码绘制的界面效果如下:Canvas 适用于其中包含的 UI 元素比较固定的情形,但是如果你想向其中添加更多的控件,或者 UI 需要改变大小或能够移动,Canvas 显得不太灵活。
目录第一章什么是Silverlight? (1)第二章Silverlight 1和Silverlight 2之间的区别 (1)第三章Silverlight和WPF之间的不同 (1)第四章开发Silverlight应用程序需要的工具 (2)Silverlight SDK (2)如何选择Expression Studio 或 Visual Studio (2)第五章Silverlight 运行时和Silverlight SDK之间的不同 (3)第六章什么是XAML? (3)第七章什么是.xap文件? (4)第八章“Hello World”Silverlight应用程序 (4)第九章Visual Studio默认创建的文件 (6)第十章生成并运行“Hello World”Silverlight应用程序 (6)第十一章什么是app.xaml? (8)第十二章Page.xaml文件 (8)第十三章从XAML标签开始 (9)第十四章如何在Web页面放置Silverlight控件? (10)第十五章如何在Silverlight控件中设置默认.xaml页面? (11)第十六章如何从其他的XAML页面打开XAML页面? (11)第十七章从Silverlight控件打开特定的xaml页 (12)第十八章在Silverlight布局控件 (13)Silverlight中的布局面板控件 - Canvas (14)Silverlight中的布局面板控件 - StackPanel (15)Silverlight中的布局面板控件– Grid (16)第十九章如何在Silverlight控件中显示图像? (17)Image.Source属性 (17)Image.stretch属性 (19)Width和Height属性 (20)Image.Clip属性 (20)第二十章在Silverlight中如何拖动或移动图像或对象? (21)第二十一章如何从页面传递参数到Silverlight控件? (23)InitParameters (23)如何设置InitParameters (23)从App.xaml传递参数到其他页面 (24)在XAML页面使用IDictionary参数 (24)第二十二章如何从Silverlight控件调用WCF方法? (25)Silverlight入门Silverlight中使用WCF (25)第二十三章Silverlight中使用WCF示例 (27)第二十四章从Silverlight控件访问Session变量 (29)第二十五章创建WCF访问检索Session数据示例 (30)第二十六章如何从Silverlight代码调用Javascript函数? (33)第二十七章如何在Silverlight页面上弹出层? (34)第二十八章为Silverlight控件添加工具提示 (35)简单的文本提示 (36)显示富UI元素提示 (36)编程方式设置工具提示 (37)第二十九章如何在Silverlight播放音频或声音文件? (38)第三十章在Silverlight中如何显示右键菜单? (39)第三十一章介绍Silverlight绑定数据 (40)第三十二章Silverlight数据绑定示例:BindingMode枚举 (44)第三十三章如何为Siverlight控件设置背景图片 (45)第三十四章Javascript检测是否安装了Silverlight (47)在这套Silverlight学习系列中将学习Silverlight基础并使用Silverlight编写web应用程序。
Silverlight 5 轻松开启绚丽的网页 3D 世界2 —使用Toolkit 开发3D Web 应用前文 已经提到通过 Silverlight T oolkit (December 2011) for Silverlight 5 ,可以开发出基于XNA 的3D Web 应用。
但很多开发人员还是遇到了很多问题, 现在我就一步步带大家看如何进行基于 Silverlight T oolkit 3D App的开发。
1.搭建Silverlight 5 开发环境,确保你的 VS 是2010 SP1以上版本,如果是中文版, 可以参照 此文进行Silverlight 5 T ools 的安装。
2. 安装 Silverlight T oolkit (December 2011) for Silverlight 5 ,你可以在 这里下载。
3.如果你的VS 是中文版,在新建Silverlight 项目时,是看不见以下三个项目模板。
原因是Silverlight T oolkit 将项目模板安装到了英文语言目录下 ,这时需要我们自 己将项目模板从英文语言目录拷贝到中文语言目录下,然后重建VS 环境,具体做法如下:1) 进入 VS 安装目录(默认路径为: C:\Program Files'Microsoft Visual StudioSSlNl)!£nvef1ighiT«tiDAprE-jec^.Sflveriighl3dLiblSivefiigHt.宜用丽Skfdighi 却.SivrdigH ―血用也爭Siveffighl 业寻宜用注孚 W£F FIA £曲“叫亜亡vfsiMic*ViSuaJ t*讪t csVisual C"讷仙M 匚址St V^futl C*Sihnerlight test appicadon 4nr Fn-bg ・f 訶 MiM IfftiftgVisual C*"3TvwfigR: ID Appkaftion C»sivfwiijh wo 血学c*耳忸Ifl 饭脱li已安雷的根區 工 Vhualu#Windows-WetOffke OhudRe port? ng "Silwpr 甲rt WCF Worldl^wXNA 创r*i 會 5>hjdf« 4-0 連遵鼻如目垃川ETFe 肋於al・:如■ ■]Siwlight Link Ttsl AppJkatkxi10.0\Common7\IDE ),进入 \ProjectT emplates\CSharp\Silverlight 目录,然后找到英乂语言目录 1033,在这个目录下有 Silverlight Unit T est Project.zip 、Silverlight3dApp.zip 、Silverlight3dLib.zip 三个项目模板文件。
这是8个系列教程的第七部分,这系列示范如何使用Silverlight 2的Beta1版本建造一个简单的Digg客户端应用。
这些教程旨在按顺序阅读,帮着解释Silverlight的一些核心编程概念。
如何定制控件的观感(Look and Feel)WPF和Silverlight编程模型中一个强大无比的功能,就是能够完全定制所使用的控件的观感(Look and Feel )。
这允许开发人员和设计师对控件的界面以微妙和戏剧性的方式进行精雕细琢,促成无比的灵活性以创建出恰如所愿的用户体验。
在这篇教程里,我们将看一下你可以定制控件的几种方式,然后在结尾使用这些技术对我们的Digg应用的用户界面润色一下。
定制控件的内容在这个系列的第一部分里,我们在页面上加了一个简单的按钮控件,示范了如何把它的内容设成一个自定义的“Push Me!”文字字符串。
然后我们连接了一个Click事件处理函数,在它被点击时执行一些代码:这导致按钮在浏览器里象下面这么显示:关于按钮控件,也许会让你感到惊奇的一件事情是,它的Content属性,不必是象“Push Me!”这样简单的字符串。
实际上,我们可以把Content属性设成我们想要的任何形状或控件序列:譬如,我们可以嵌入一个StackPanel,内含<Image> 和<TextBlock> 控件:这会导致我们的按钮在运行时看上去会象下面这样。
注意,它依然保留同样的功能行为(按它的话,按钮会陷下去,点击事件处理函数也会象以前一样触发):我们也可以使用形状控件(象下面这样的Ellipse控件)来在按钮里面创建自定义的矢量图像:注意上面我是怎么使用一个偏移RadialGradientBrush来加一个非常好看的反射式光泽来填充Ellipse控件的:我们甚至可以搞些古怪,在按钮内嵌入可交互的象日历这样的控件:在上面的例子中,日历控件是完全可以交互的,意味着终端用户可以前后翻月历,在日历里选择一个日期,然后按其中的按钮,触发Click事件处理函数:(注:我不清楚这是否会是一个好的用户体验,但它确实展示了你所能做之灵活性!)我上面概述的这些类型的内容定制场景不仅对按钮控件有效,同样地对其他继承自ContentControl基类的其他控件也工作。
(一)让物体动起来来源:作者:佚名时间:2009-7-17序:自从QXGame(WPF GAME ENGINE)游戏引擎公布以来,受到很多朋友的热切关注,于是乎有了写教程的想法。
那么从今天开始,我将带领大家一步一步的学会如何使用纯C#开发WPF/Silverlight游戏引擎,过程中我会尽量的开源,并对相关小技巧进行解释和介绍,比较复杂的算法原理我会给大家一条绝对可行的思路,至于如何处理这些复杂的算法,那是仁者见仁,智者见智了,或许您写的算法比我的更好呢。
多余的话不多说了,最后来句发自肺腑的话吧:本系列教程的书写编辑花费作者很多心血,没有功劳也有苦劳哇,所以请需要转载的朋友们用突出的字体或颜色标明在您的文章开头,您的大力支持是鼓励我不断写下去的动力。
前言:WPF/Silverlight矢量动画的描述我就不多说了,关于WPF/Silverlight与Flash的比较网上也是一堆一堆的,这里只想客观的告诉读者下面两点:一、WPF开发的是桌面应用程序,自包括Vista在内以后的Windows系列操作系统均大量以之为主流图形工具,即将全面取代Winform,并且Windows 7将集成。
NET3.5+框架,在当今Windows系列操作系统占据90%同类市场的现状下,这意味着什么呢?二、Silverlight基于一个约4M左右的MINI型。
NET框架,目前版本2.0,3.0的beta 英文版,从发展趋势看是绝对有与Flash抗衡并且在未来超越它的可能性。
Silverlight的优势更表现在它可以用一切。
NET语言例如C#,,C++.NET等开发,拓展度与可以参与开发的人群远远高于只能用AS开发的FLASH.转入正题,网上已经有很多关于如何创建WPF/Silverlight动画的教程,但是均为使用Blend工具制作,或直接写在xaml代码内的动画,这样往往造成很多朋友误以为其实WPF/Silverlight不就是MS的Flash?诚然,如果您真的像那些教程里说的去开发WPF /Silverlight程序,我个人觉得一点意义都没有。
这样开发出来的东西根本就超越不了Flash,那何苦还要投入如此多的精力来学习它?所以本系列教程将全方位的以纯C#程序语言进行动态创建一切可视化对象,从而构建出一个如QXGame(WPF GAME ENGINE)游戏引擎,这才是我本系列教程希望达到的目的。
(注:本教程使用的开发工具为Visual studio 2008 版本sp1)好了,那么我首先介绍第一种动态创建动画的方法,这也是官方推荐的Storyboard动画。
该类型动画您可以在网络上查阅相关资料进行了解,这里不累述了,那么我们直接进入主题:首先我们新建一个WPF项目,接下来打开Window1.xaml进入视图代码编辑器,这里我们这样写:<Window x:Class="WpfApplication1.Window1"xmlns="/winfx/2006/xaml/presentation"xmlns:x="/winfx/2006/xaml" Title="WPFGame"><Canvas x:Name="Carrier" Width="800" Height="600" Background="Silver" MouseLeftButtonDown="Carrier_MouseLeftButtonDown" /></Window>这段代码我创建了一个名叫Carrier的Canvas(画布)容器布局控件,并设置它的尺寸为800*600,背景银色,最后注册一个鼠标在它上面点击的事件。
那么为什么要选择Canvas 作为容器呢?因为Canvas可以实现它内部的控件任意的绝对定位,可以很方便的处理物体的移动。
界面容器元素布局好了,那么接下来就动态创建物体对象了:Rectangle rect;//创建一个方块作为演示对象public Window1() {InitializeComponent();rect = new Rectangle();rect.Fill = new SolidColorBrush(Colors.Red);rect.Width = 50;rect.Height = 50;rect.RadiusX = 5;rect.RadiusY = 5;Carrier.Children.Add(rect);Canvas.SetLeft(rect, 0);Canvas.SetTop(rect, 0);}这里我创建了一个50*50象素,圆角5*5红色的方块对象,并且将它作为子控件添加进Carrier 中,并且初始化它在Carrier中的位置:Canvas.SetLeft(rect,0);Canvas.SetTop(rect,0);对象准备好了,那么接下来就是实现动画了。
我们要实现的是鼠标点哪它就移动到哪:private void Carrier_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {//创建移动动画Point p = e.GetPosition(Carrier);Storyboard storyboard = new Storyboard();//创建X轴方向动画DoubleAnimation doubleAnimation = new DoubleAnimation(Canvas.GetLeft(rect),p.X,new Duration(TimeSpan.FromMilliseconds(500))Storyboard.SetTarget(doubleAnimation, rect);Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Canvas.Left)")); storyboard.Children.Add(doubleAnimation);//创建Y轴方向动画doubleAnimation = new DoubleAnimation(Canvas.GetTop(rect),p.Y,new Duration(TimeSpan.FromMilliseconds(500)));Storyboard.SetTarget(doubleAnimation, rect);Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Canvas.Top)")); storyboard.Children.Add(doubleAnimation);//将动画动态加载进资源内if (!Resources.Contains("rectAnimation")) {Resources.Add("rectAnimation", storyboard);}//动画播放storyboard.Begin();}从上面代码我们可以看到,首先获取鼠标点击点相对于Carrier中的坐标位置p,然后创建故事板storyboard和Double类型动画doubleAnimation,doubleAnimation有3个参数,分别代表开始值,结束值,动画经历时间,接着通过Storyboard.SetTarget()和Storyboard.SetTargetProperty()分别设置动画的目标及要修改的动画目标属性,再下来将doubleAnimation添加进storyboard中,这样重复两次分别实现X轴和Y轴方向的动画。
当这些处理完后,最后还需要将storyboard添加进Resources资源内,这样程序才能识别(将它去掉也同样可以通过编译,后面章节中才会用到它,这里只是提前做个说明)。
一切就绪后,通过代码storyboard.Begin()来开始动画。
第二种方法,CompositionTarget动画,官方描述为:CompositionTarget对象可以根据每个帧回调来创建自定义动画。
其实直接点,CompositionTarget创建的动画是基于每次界面刷新后触发的,与窗体刷新率保持一致,所以频率是固定的,很难人工介入控制。
那么如何使用它?xaml的界面代码还是和上一篇中描述的一样,这里不累述了。
那么接下来就是创建对象并注册事件,全部代码如下:Rectangle rect; //创建一个方块作为演示对象double speed = 1; //设置移动速度Point moveTo; //设置移动目标public Window1() {InitializeComponent();rect = new Rectangle();rect.Fill = new SolidColorBrush(Colors.Red);rect.Width = 50;rect.Height = 50;rect.RadiusX = 5;rect.RadiusY = 5;Carrier.Children.Add(rect);Canvas.SetLeft(rect, 0);Canvas.SetTop(rect, 0);//注册界面刷新事件CompositionTarget.Rendering += new EventHandler(Timer_Tick);}private void Carrier_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {moveTo = e.GetPosition(Carrier);}CompositionTarget的注册事件方法为:CompositionTarget.Rendering += new EventHandler(Timer_Tick);因为我们要实现的是鼠标点哪方块就移动到哪,所以我用一个变量moveTo保存鼠标点击点的Point。
并在鼠标左键事件中赋值:moveTo = e.GetPosition(Carrier);同时设置方块X,Y 方向的速度均为speed。
接下来就是实现Timer_Tick了,它是基于窗体的时时刷新事件。
我们这样写:private void Timer_Tick(object sender, EventArgs e) {double rect_X = Canvas.GetLeft(rect);double rect_Y = Canvas.GetTop(rect);Canvas.SetLeft(rect, rect_X + (rect_X < moveTo.X ? speed : -speed));Canvas.SetTop(rect, rect_Y + (rect_Y < moveTo.Y ? speed : -speed));}首先获取方块的X,Y位置,接下让方块的X,Y与moveTo的X,Y进行比较而判断是+speed还是-speed,这里的逻辑需要朋友们自行领会了。