Silverlight C# 游戏开发:自定义鼠标(一)

简介:

我们在游戏中经常应用自定义鼠标来提升游戏的画面品质,一个好的游戏怎么能没有好看的鼠标呢,关于Silverlight的各种自定义鼠标的方法很多,而我将为大家带来的是在游戏当中的应用效果,当然了,做法更加游戏化,先看下图:

 

我们期望达到的效果是,鼠标移入不同的对象上显示不同的鼠标效果:

在其他的文章中曾经看到过一些做法,都是习惯将一个控件绑定到MainPage的MouseMove上,我所用做法也是一样,但是较之更加“密封”一些,比如先创建一个CursorBase类(我是喜欢直接写代码,而不是用控件老搞定^_^):


 
 
  1. public class CursorBase : Canvas  
  2. {  
  3. public CursorBase(FrameworkElement parent)  
  4. {  
  5. parent.MouseMove += new MouseEventHandler(parent_MouseMove);  
  6. parent.Cursor = Cursors.None;  
  7. Canvas.SetZIndex(this, 9999);   
  8.  
  9. }  
  10. //将父对象的鼠标移动事件增加到这里  
  11. void parent_MouseMove(object sender, MouseEventArgs e)  
  12. {  
  13. Point pt = e.GetPosition(sender as UIElement);  
  14. X = pt.X;  
  15. Y = pt.Y;  
  16. }  
  17. //一套简单的坐标控制  
  18. public double X  
  19. {  
  20. get { return Canvas.GetLeft(this); }  
  21. set { Canvas.SetLeft(this, value); }  
  22. }  
  23. public double Y  
  24. {  
  25. get { return Canvas.GetTop(this); }  
  26. set { Canvas.SetTop(this, value); }  
  27. }   
  28. }  
  29.    
  30.  
  31. 这是一个自定义鼠标的基本类,特别提一下构造函数添加的FrameworkElement,这是代表MainPage的父对象传入,当然了,也可以传入其他的元素做父对象,就要看你要将自定义鼠标应用在什么地方了。  
  32.  
  33. 但是这只是通过代码写一个控件而已,如果呈现这些图片呢,于是下面再写一个控制类:  
  34.  
  35.    
  36.  
  37. Model控制类   
  38. public class CursorControl : CursorBase  
  39. {  
  40. public CursorControl(FrameworkElement parent)  
  41. : base(parent)  
  42. {  
  43. this.CacheMode = new BitmapCache();  
  44. this.IsHitTestVisible = false;  
  45. }  
  46. //添加一个鼠标模型  
  47. public void AddCursorModel(string name, FrameworkElement model)  
  48. {  
  49. this.Children.Add(model);  
  50. if (this.Children.Count != 1)  
  51. model.Visibility = Visibility.Collapsed;  
  52. else  
  53. model.Visibility = Visibility.Visible;  
  54. model.Name = name;  
  55. }  
  56. //从图片添加鼠标模型  
  57. public void AddCursorModelFromImage(string name, Uri uri)  
  58. {  
  59. AddCursorModel(name, new Image() { Source = new BitmapImage(uri) });  
  60. }  
  61. //正在显示的模型名字  
  62. string ModelName = "默认";  
  63. //获得正在显示的模型名字  
  64. public string GetCursorModel()  
  65. {  
  66. return ModelName;  
  67. }  
  68. //设置要显示的鼠标模型  
  69. public void SetCursorModel(string name)  
  70. {  
  71. foreach (FrameworkElement item in this.Children)  
  72. {  
  73. if (item.Name == name)  
  74. {  
  75. item.Visibility = System.Windows.Visibility.Visible;  
  76. ModelName = name;  
  77. }  
  78. else  
  79. item.Visibility = System.Windows.Visibility.Collapsed;  
  80. }  
  81.  
  82. }  
  83. }  
  84.    
  85.  
这次直接操作Children集合,通过外部添加的方式设置鼠标的不同状态和样式,这个类更多意义是封装了几个方法,以方便我们达到更便捷的操作,通过AddCursorModel增加样式模型,SetCursorModel设置样式模式,在这个基础上,可以使用状态枚举等方式,但是都需要这些方法来操作样式,如果你需要Remove,那么可以简单的自己写一个:)

这里有一个特别需要提到的是关于IsHitTestVisible,是用来阻止自定义鼠标的点击测试。

下一步,将图片添加到工程当中:

现在,我们写一个MyCursor类,构建我们所需要的样式的图片序列。

我的鼠标

  
  
  1. //我的鼠标  
  2. public class MyCursor : CursorControl  
  3. {  
  4. public MyCursor(FrameworkElement parent)  
  5. : base(parent)  
  6. {  
  7. base.AddCursorModelFromImage("默认", new Uri(@"/CustomCursor01;component/Res/Cursor/" + 0 + ".png", UriKind.Relative));  
  8. base.AddCursorModelFromImage("禁止", new Uri(@"/CustomCursor01;component/Res/Cursor/" + 1 + ".png", UriKind.Relative));  
  9. base.AddCursorModelFromImage("攻击", new Uri(@"/CustomCursor01;component/Res/Cursor/" + 2 + ".png", UriKind.Relative));  
  10. base.AddCursorModelFromImage("魔法", new Uri(@"/CustomCursor01;component/Res/Cursor/" + 3 + ".png", UriKind.Relative));  
  11. base.AddCursorModel("等待", new WaitCursor());  
  12. ThisCursor = this;  
  13. }  
  14. public static MyCursor ThisCursor = null;  
  15. }  
  16.    
  17.  
为了更加方便的控制自定义的鼠标,增加了一个ThisCursor用来保存最新的Cursor,我通常认为界面中只有一个鼠标,所以这样做法更加直接明了,除非你使用了全局的控制方法:)

WaitCursor是一个UserControl,里面加入了一些动画和效果,并不是所有的鼠标样式都是图片,而我们的方法中提供了对控件的支持,关于WaitCursor控件请下载源代码自行查看吧。

下一步就是如何控制它们,现在我需要布局元素,然后为他们起上名字分别叫Item01、Item02、Item03、Btn_ShowWait,当鼠标移入的时候就可以直接通过ThisCursor来控制。

但是,我们怎么能够控制这些样式,怎么在正确的调用SetCursorModel呢,难点在鼠标移入到一个元素,而不知道到底是什么应该触发什么鼠标的样式,为了解决这个问题,我们需要借助Tag这个Silverlight特有的属性。下面截选自Silverlight4.0的离线文档。

于是,我们借助了一个小小的属性来完成不可告人之目的,也有更加暴力的方法就是为每个对象都增加一个独立处理的鼠标事件,但是很不好,如果游戏中的对象过多就不好办了,所以,越精简越封装越好。

我只需将MainPage.xaml写成这样:


 
 
  1. <Canvas x:Name="LayoutRoot"> 
  2. <Image x:Name="Item01" Height="90" Canvas.Left="26" Source="Res/Item01.png" Stretch="Fill" Canvas.Top="18" Width="90"/> 
  3. <Image x:Name="Item02" Height="96" Canvas.Left="263" Source="Res/Item02.png" Stretch="Fill" Canvas.Top="12" Width="51"/> 
  4. <Image x:Name="Item03" Height="80" Canvas.Left="407" Source="Res/Item03.png" Stretch="Fill" Canvas.Top="24" Width="100"/> 
  5. <Button x:Name="Btn_ShowWait" Content="动画图标" Height="35" Canvas.Left="40" Canvas.Top="152" Width="148"/> 
  6. </Canvas> 
  7.    
  8.  
在后台的MainPage.cs添加和修改如下代码:
MainPage.cs代码

  
  
  1. public partial class MainPage : UserControl  
  2. {  
  3. public MainPage()  
  4. {  
  5. InitializeComponent();  
  6. InitializeMyPlace();  
  7. this.CacheMode = new BitmapCache();  
  8. LayoutRoot.Children.Insert(0,new Image() { Source = new BitmapImage(new Uri(@"/CustomCursor01;component/Res/map01.jpg", UriKind.Relative)) });  
  9. LayoutRoot.Children.Add(new MyCursor(this));  
  10.  
  11. }  
  12. public void InitializeMyPlace()  
  13. {  
  14. Item01.Tag = "攻击";  
  15. Item02.Tag = "魔法";  
  16. Item03.Tag = "禁止";  
  17. Item01.MouseEnter += new MouseEventHandler(Item_MouseEnter);  
  18. Item02.MouseEnter += new MouseEventHandler(Item_MouseEnter);  
  19. Item03.MouseEnter += new MouseEventHandler(Item_MouseEnter);  
  20. Item01.MouseLeave += new MouseEventHandler(Item_MouseLeave);  
  21. Item02.MouseLeave += new MouseEventHandler(Item_MouseLeave);  
  22. Item03.MouseLeave += new MouseEventHandler(Item_MouseLeave);  
  23.  
  24. Btn_ShowWait.Click += new RoutedEventHandler(Btn_ShowWait_Click);  
  25. }  
  26.  
  27. void Btn_ShowWait_Click(object sender, RoutedEventArgs e)  
  28. {  
  29. if (MyCursor.ThisCursor.GetCursorModel() == "等待")   
  30. MyCursor.ThisCursor.SetCursorModel("默认");  
  31. else  
  32. MyCursor.ThisCursor.SetCursorModel("等待");  
  33. }  
  34. void Item_MouseEnter(object sender, MouseEventArgs e)  
  35. {  
  36. MyCursor.ThisCursor.SetCursorModel((sender as FrameworkElement).Tag as string);  
  37. }  
  38. void Item_MouseLeave(object sender, MouseEventArgs e)  
  39. {  
  40. MyCursor.ThisCursor.SetCursorModel("默认");  
  41. }  
  42. }  
还有一个WaitCursor控件,请直接看源代码吧,源代码下载如下: 点击这里下载

现在运行效果看看怎么样呢,鼠标在上面移动看看: 

到此,我们可以基本上完成了游戏中的自定义鼠标的雏形开发工作,关于Tag可以使用自定义的结构体来带入相关信息,毕竟对象所需要的内容是很多的,在下个关于自定义鼠标的文章中,我们一起研究一下拾取和拖拽的制作方法。



本文转自nowpaper 51CTO博客,原文链接:http://blog.51cto.com/nowpaper/712365

相关文章
|
6月前
|
存储 开发框架 .NET
【C#】C# 基础语法与游戏开发
【1月更文挑战第21天】【C#】C# 基础语法与游戏开发
|
关系型数据库 MySQL C#
C# winform 一个窗体需要调用自定义用户控件的控件名称
给用户控件ucQRCode增加属性: //二维码图片 private PictureBox _pictureBoxFSHLQrCode; public PictureBox PictureBoxFSHLQrCode {   get { return _pictureBoxFSHLQrCode; }   set { this.pictureBoxFSHLQrCode = value; } } 在Form1窗体直接调用即可: ucQRCode uQRCode=new ucQRCode(); ucQRCode.PictureBoxFSHLQrCode.属性= 要复制或传给用户控件上的控件的值
70 0
|
5月前
|
C# C++
C# 自定义时间进度条
本文作者通过参考leslie_xin的一篇文章,成功创建了一个自定义的WinForms控件——时间进度条,该控件带有时间刻度和多种可定制的属性,如颜色、时间间隔等。作者在控件中加入了开始和结束时间,以及自适应的时间刻度间隔。控件能根据设置显示时间标签,并提供了事件处理,如值改变时的触发。代码中包含了计算时间刻度、绘制刻度线和时间标签的逻辑。作者强调了避免循环调用事件、使用OnXXX()形式的事件处理函数以及注意自定义控件中的属性和事件设计。
132 7
|
3月前
|
开发框架 .NET 编译器
总结一下 C# 如何自定义特性 Attribute 并进行应用
总结一下 C# 如何自定义特性 Attribute 并进行应用
|
3月前
|
图形学 C# 开发者
全面掌握Unity游戏开发核心技术:C#脚本编程从入门到精通——详解生命周期方法、事件处理与面向对象设计,助你打造高效稳定的互动娱乐体验
【8月更文挑战第31天】Unity 是一款强大的游戏开发平台,支持多种编程语言,其中 C# 最为常用。本文介绍 C# 在 Unity 中的应用,涵盖脚本生命周期、常用函数、事件处理及面向对象编程等核心概念。通过具体示例,展示如何编写有效的 C# 脚本,包括 Start、Update 和 LateUpdate 等生命周期方法,以及碰撞检测和类继承等高级技巧,帮助开发者掌握 Unity 脚本编程基础,提升游戏开发效率。
78 0
|
编译器 C#
c# 自定义扩展方法
c# 自定义扩展方法
|
6月前
|
移动开发 JavaScript 安全
C# 实现微信自定义分享
C# 实现微信自定义分享
|
6月前
|
C#
C#学习相关系列之自定义遍历器
C#学习相关系列之自定义遍历器
|
6月前
|
存储 开发框架 .NET
【C#】认识C# (为了游戏开发 O(≧口≦)O)
【1月更文挑战第26天】【C#】认识C# (为了游戏开发 O(≧口≦)O)
|
编译器 C#
C#中导入其它自定义的命名空间
c#中怎么导入其它自定义的命名空间首先要确保已经导入了想要导入的自定义的命名空间。如上图这时编译器应该会报错,此时就需要手动去添加引用了,cs文件默认没有添加引用,只是加载了想要导入的命名空间,但是没有添加引用,所以需要自己要手动添加引用。切记!然后会有一个对话框选择你想引用的命名空间,点击确定即可。注意:一般而言,C#中如果没有改变那么一般项目的类名都默认是Program,在引用时需要注...
107 1
C#中导入其它自定义的命名空间