游戏中有各种各样的拖拽需求,大到窗口,小到图标,在游戏界面 *** 作中,点击和拖拽占据了用户 *** 作的大部分行为,如何做好一个拖拽控件至关重要,做一个可重用的拖拽控件更加重要,我的这些实现方法可能比较另类,但只要有效就行,在这个基础上,你可以扩展很多的做法。
可能有朋友已经写了这方面的文章,但是本篇介绍的方法是一个可以一劳永逸的重用控件,只需要一个基类代码就可以完成所有的需求——图标、窗体、自定义的目标,所以,本片没有放在小技巧里而是游戏开发分类里。
最先,需要了解一下拖拽原理,即当鼠标按下做一个标识,在鼠标移动时实时修改目标坐标信息,鼠标抬起的时候,释放掉鼠标 *** 作,当然了,为了更好的 *** 作坐标,我们一般将父容器改成Canvas。
将围绕这个做后面的工作,请了解之前有关基类和容器的概念,这样后面看起来就容易很多,考虑它的重用性,创建一个基本控件让后面的控件继承,将一些通用逻辑写在这个基类里,让其他的类去继承重用,这也就是游戏引擎的基本做法之一。
那么,在Blend或者Visual Studio里创建一个名为MovableObject的控件,然后将控件xaml修改成下面的样子:
<UserControl 02 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 03 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 04 xmlns:d="http://schemas.microsoft.com/Expression/blend/2008" 05 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 06 mc:Ignorable="d" 07 x:Class="DragObject.MovableObject" 08 d:DesignWIDth="640" d:DesignHeight="480" WIDth="auto" Height="auto"> 09 <GrID x:name="LayoutRoot"> 10 <Rectangle stroke="Black" RadiusX="5" RadiusY="5"> 11 <Rectangle.Fill> 12 <linearGradIEntBrush EndPoint="0.5,1" StartPoint="0.5,0"> 13 <GradIEntStop color="transparent"/> 14 <GradIEntStop color="Black" Offset="1"/> 15 </linearGradIEntBrush> 16 </Rectangle.Fill> 17 </Rectangle> 18 <Image x:name="ShowImage" Stretch="Fill"/> 19 <Rectangle x:name="Sel_Rectangle" stroke="White" strokeThickness="2" Visibility="Collapsed" RadiusX="5" RadiusY="5"/> 20 </GrID> 21 </UserControl>即便使用代码实现并不难,但是为了方便理解,就直接使用XAML较为简便,浏览它的结构图就可以看到。
上面的表示方法分别是带了一个底,和一个要显示图像的Image,以及一个当鼠标移入时候需要表示选择标识。
那么下面就是Coding阶段,打开MovableObject类,代码设计如下:
public partial class MovableObject : UserControl 02 { 03 //鼠标点的保存,同时还承担是否点击的判定 04 Point ? mousePoint = null; 05 public MovableObject() 06 { 07 InitializeComponent(); 08 //选择框隐蔽掉 09 Sel_Rectangle.Visibility = System.windows.Visibility.Collapsed; 10 } 11 //鼠标移动的方法重载 12 protected overrIDe voID OnMouseMove(MouseEventArgs e) 13 { 14 //判定是否按下鼠标左键 15 if (mousePoint!=null) 16 { 17 //计算新的位置 18 double newtop = e.Getposition(null).Y - mousePoint.Value.Y + Canvas.Gettop(this); 19 double newleft = e.Getposition(null).X - mousePoint.Value.X + Canvas.Getleft(this); 20 Canvas.Settop(this, newtop); 21 Canvas.Setleft(this, newleft); 22 mousePoint = e.Getposition(null); 23 } 24 base.OnMouseMove(e); 25 } 26 //鼠标抬起的方法重载 27 protected overrIDe voID OnMouseleftbuttonUp(MousebuttonEventArgs e) 28 { 29 mousePoint = null; 30 //释放鼠标设备 31 this.ReleaseMouseCapture(); 32 base.OnMouseleftbuttonDown(e); 33 } 34 //鼠标按下的方法重载 35 protected overrIDe voID OnMouseleftbuttonDown(MousebuttonEventArgs e) 36 { 37 mousePoint = e.Getposition(null); 38 //捕获鼠标设备 39 this.CaptureMouse(); 40 //下面三行是用来保证当前控件为最顶层的做法 41 var parent = this.Parent as Panel; 42 parent.Children.Remove(this); 43 parent.Children.Add(this); 44 base.OnMouseleftbuttonUp(e); 45 } 46 //鼠标进入的方法重载 47 protected overrIDe voID OnMouseEnter(MouseEventArgs e) 48 { 49 Sel_Rectangle.Visibility = System.windows.Visibility.Visible; 50 base.OnMouseEnter(e); 51 } 52 //鼠标移出的方法重载 53 protected overrIDe voID OnMouseLeave(MouseEventArgs e) 54 { 55 Sel_Rectangle.Visibility = System.windows.Visibility.Collapsed; 56 base.OnMouseLeave(e); 57 } 58 }我做了一些注释,可以很明确的得知这个基类的作用,现在可以新建类继承于这个类,来实现扩展的目的。
为此,我准备三种不同的目标效果——图标(MyIcon)、大图片(MyFace)、自定义控件(MyCard)
图标和图片只需要用上原有控件的Image即可,而自定义控件则是通过Blend或其他方式设计制作出来的独立控件,那么如何实现这三个效果呢?请往下看:
我们先创建三个类,他们都继承于MovableObject
public class MyIcon : MovableObject
public class MyFace : MovableObject
public class MyCard : MovableObject
下面在各自的构造函数中填入对应的 *** 作逻辑即可,下面给出了完整代码:
public class MyIcon : MovableObject 02 { 03 public MyIcon() 04 { 05 IconIndex = 1; 06 } 07 private int _Iconindex = -1; 08 public int IconIndex 09 { 10 get { return _Iconindex; } 11 set 12 { 13 _Iconindex = value; 14 var uri = new Uri("/DragObject;component/Res/image" + value + ".png", UriKind.relative); 15 ShowImage.source = new System.windows.Media.Imaging.BitmAPImage(uri); 16 } 17 } 18 } 19 public class MyFace : MovableObject 20 { 21 public MyFace() 22 { 23 var uri = new Uri("/DragObject;component/Res/Nowpaper.jpg", UriKind.relative); 24 ShowImage.source = new System.windows.Media.Imaging.BitmAPImage(uri); 01 } 02 } 03 public class MyCard : MovableObject 04 { 05 public MyCard() 06 { 07 LayoutRoot.Children.Insert(LayoutRoot.Children.IndexOf(ShowImage), new Card()); 08 LayoutRoot.Children.Remove(ShowImage); 09 } 10 }MyFace是直接修改ShowImage的Source,MyIcon里写了一个索引属性,这样可以在外面控制ShowImage,显示需要显示的图片,而MyCard里new出来一个控件,并替换掉了原有的ShowImage,MyCard使用了前面制作的一个控件。
好了,现在在MainPage的构造函数中编写其他的代码,但是LayoutRoot需要变成Canvas,这样才能更好的控制图像位置。
public MainPage() 02 { 03 InitializeComponent(); 04 //添加自定义的拖拽目标 05 var icon = new MyIcon(); 06 LayoutRoot.Children.Add(icon); 07 Canvas.Setleft(icon, 20); 08 Canvas.Settop(icon, 50); 09 icon = new MyIcon() { IconIndex = 3 }; 10 LayoutRoot.Children.Add(icon); 11 Canvas.Setleft(icon, 20); 12 Canvas.Settop(icon, 150); 13 var face = new MyFace(); 14 LayoutRoot.Children.Add(face); 15 Canvas.Setleft(face, 100); 16 Canvas.Settop(face, 50); 17 var card = new MyCard(); 18 LayoutRoot.Children.Add(card); 19 Canvas.Setleft(card, 270); 20 Canvas.Settop(card, 50); 21 }现在运行看看效果吧,在这个基础上,可以制作窗口或需要拖拽的物体只需要继承修改一下,在下一篇,将会制作一个窗口并使用技巧完成拖入等 *** 作,放心吧绝对不复杂。
本篇工程源代码下载地址如下:点击直接下载
总结以上是内存溢出为你收集整理的Silverlight 游戏开发:可重用的拖拽控件全部内容,希望文章能够帮你解决Silverlight 游戏开发:可重用的拖拽控件所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)