Silverlight 游戏开发:可重用的拖拽控件

2016-08-20 11:09:02来源:http://nowpaper.blog.51cto.com/3893223/712743作者:nowpaper人点击


游戏中有各种各样的拖拽需求,大到窗口,小到图标,在游戏界面操作中,点击和拖拽占据了用户操作的大部分行为,如何做好一个拖拽控件至关重要,做一个可重用的拖拽控件更加重要,我的这些实现方法可能比较另类,但只要有效就行,在这个基础上,你可以扩展很多的做法。


可能有朋友已经写了这方面的文章,但是本篇介绍的方法是一个可以一劳永逸的重用控件,只需要一个基类代码就可以完成所有的需求——图标、窗体、自定义的目标,所以,本片没有放在小技巧里而是游戏开发分类里。


最先,需要了解一下拖拽原理,即当鼠标按下做一个标识,在鼠标移动时实时修改目标坐标信息,鼠标抬起的时候,释放掉鼠标操作,当然了,为了更好的操作坐标,我们一般将父容器改成Canvas。




将围绕这个做后面的工作,请了解之前有关基类和容器的概念,这样后面看起来就容易很多,考虑它的重用性,创建一个基本控件让后面的控件继承,将一些通用逻辑写在这个基类里,让其他的类去继承重用,这也就是游戏引擎的基本做法之一。


那么,在Blend或者Visual Studio里创建一个名为MovableObject的控件,然后将控件xaml修改成下面的样子:




<UserControl 02xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 03xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 04xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 05xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 06mc:Ignorable="d" 07x:Class="DragObject.MovableObject" 08d:DesignWidth="640"d:DesignHeight="480"Width="Auto"Height="Auto"> 09<Gridx:Name="LayoutRoot"> 10<RectangleStroke="Black"RadiusX="5"RadiusY="5"> 11<Rectangle.Fill> 12<LinearGradientBrushEndPoint="0.5,1"StartPoint="0.5,0"> 13<GradientStopColor="Transparent"/> 14<GradientStopColor="Black"Offset="1"/> 15</LinearGradientBrush> 16</Rectangle.Fill> 17</Rectangle> 18<Imagex:Name="ShowImage"Stretch="Fill"/> 19<Rectanglex:Name="Sel_Rectangle"Stroke="White"StrokeThickness="2"Visibility="Collapsed"RadiusX="5"RadiusY="5"/> 20</Grid> 21</UserControl>
即便使用代码实现并不难,但是为了方便理解,就直接使用XAML较为简便,浏览它的结构图就可以看到。



上面的表示方法分别是带了一个底,和一个要显示图像的Image,以及一个当鼠标移入时候需要表示选择标识。


那么下面就是Coding阶段,打开MovableObject类,代码设计如下:



publicpartialclassMovableObject:UserControl 02{ 03//鼠标点的保存,同时还承担是否点击的判定 04Point?mousePoint=null; 05publicMovableObject() 06{ 07InitializeComponent(); 08//选择框隐蔽掉 09Sel_Rectangle.Visibility=System.Windows.Visibility.Collapsed; 10} 11//鼠标移动的方法重载 12protectedoverridevoidOnMouseMove(MouseEventArgse) 13{ 14//判定是否按下鼠标左键 15if(mousePoint!=null) 16{ 17//计算新的位置 18doublenewTop=e.GetPosition(null).Y-mousePoint.Value.Y+Canvas.GetTop(this); 19doublenewLeft=e.GetPosition(null).X-mousePoint.Value.X+Canvas.GetLeft(this); 20Canvas.SetTop(this,newTop); 21Canvas.SetLeft(this,newLeft); 22mousePoint=e.GetPosition(null); 23} 24base.OnMouseMove(e); 25} 26//鼠标抬起的方法重载 27protectedoverridevoidOnMouseLeftButtonUp(MouseButtonEventArgse) 28{ 29mousePoint=null; 30//释放鼠标设备 31this.ReleaseMouseCapture(); 32base.OnMouseLeftButtonDown(e); 33} 34//鼠标按下的方法重载 35protectedoverridevoidOnMouseLeftButtonDown(MouseButtonEventArgse) 36{ 37mousePoint=e.GetPosition(null); 38//捕获鼠标设备 39this.CaptureMouse(); 40//下面三行是用来保证当前控件为最顶层的做法 41varparent=this.ParentasPanel; 42parent.Children.Remove(this); 43parent.Children.Add(this); 44base.OnMouseLeftButtonUp(e); 45} 46//鼠标进入的方法重载 47protectedoverridevoidOnMouseEnter(MouseEventArgse) 48{ 49Sel_Rectangle.Visibility=System.Windows.Visibility.Visible; 50base.OnMouseEnter(e); 51} 52//鼠标移出的方法重载 53protectedoverridevoidOnMouseLeave(MouseEventArgse) 54{ 55Sel_Rectangle.Visibility=System.Windows.Visibility.Collapsed; 56base.OnMouseLeave(e); 57} 58}
我做了一些注释,可以很明确的得知这个基类的作用,现在可以新建类继承于这个类,来实现扩展的目的。

为此,我准备三种不同的目标效果——图标(MyIcon)、大图片(MyFace)、自定义控件(MyCard)


图标和图片只需要用上原有控件的Image即可,而自定义控件则是通过Blend或其他方式设计制作出来的独立控件,那么如何实现这三个效果呢?请往下看:


我们先创建三个类,他们都继承于MovableObject


public class MyIcon : MovableObject


public class MyFace : MovableObject


public class MyCard : MovableObject


下面在各自的构造函数中填入对应的操作逻辑即可,下面给出了完整代码:



publicclassMyIcon:MovableObject 02{ 03publicMyIcon() 04{ 05IconIndex=1; 06} 07privateint_Iconindex=-1; 08publicintIconIndex 09{ 10get{return_Iconindex;} 11set 12{ 13_Iconindex=value; 14varuri=newUri("/DragObject;component/Res/image"+value+".png",UriKind.Relative); 15ShowImage.Source=newSystem.Windows.Media.Imaging.BitmapImage(uri); 16} 17} 18} 19publicclassMyFace:MovableObject 20{ 21publicMyFace() 22{ 23varuri=newUri("/DragObject;component/Res/nowpaper.jpg",UriKind.Relative); 24ShowImage.Source=newSystem.Windows.Media.Imaging.BitmapImage(uri); 01} 02} 03publicclassMyCard:MovableObject 04{ 05publicMyCard() 06{ 07LayoutRoot.Children.Insert(LayoutRoot.Children.IndexOf(ShowImage),newCard()); 08LayoutRoot.Children.Remove(ShowImage); 09} 10}
MyFace是直接修改ShowImage的Source,MyIcon里写了一个索引属性,这样可以在外面控制ShowImage,显示需要显示的图片,而MyCard里new出来一个控件,并替换掉了原有的ShowImage,MyCard使用了前面制作的一个控件。

好了,现在在MainPage的构造函数中编写其他的代码,但是LayoutRoot需要变成Canvas,这样才能更好的控制图像位置。



publicMainPage() 02{ 03InitializeComponent(); 04//添加自定义的拖拽目标 05varicon=newMyIcon(); 06LayoutRoot.Children.Add(icon); 07Canvas.SetLeft(icon,20); 08Canvas.SetTop(icon,50); 09icon=newMyIcon(){IconIndex=3}; 10LayoutRoot.Children.Add(icon); 11Canvas.SetLeft(icon,20); 12Canvas.SetTop(icon,150); 13varface=newMyFace(); 14LayoutRoot.Children.Add(face); 15Canvas.SetLeft(face,100); 16Canvas.SetTop(face,50); 17varcard=newMyCard(); 18LayoutRoot.Children.Add(card); 19Canvas.SetLeft(card,270); 20Canvas.SetTop(card,50); 21}
现在运行看看效果吧,在这个基础上,可以制作窗口或需要拖拽的物体只需要继承修改一下,在下一篇,将会制作一个窗口并使用技巧完成拖入等操作,放心吧绝对不复杂。

本篇工程源代码下载地址如下:点击直接下载


最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台