Silverlight 遊戲開發:可重用的拖拽控制項

來源:互聯網
上載者:User

遊戲中有各種各樣的拖拽需求,大到視窗,小到表徵圖,在遊戲介面操作中,點擊和拖拽佔據了使用者操作的大部分行為,如何做好一個拖拽控制項至關重要,做一個可重用的拖拽控制項更加重要,我的這些實現方法可能比較另類,但只要有效就行,在這個基礎上,你可以擴充很多的做法。

可能有朋友已經寫了這方面的文章,但是本篇介紹的方法是一個可以一勞永逸的重用控制項,只需要一個基類代碼就可以完成所有的需求——表徵圖、表單、自訂的目標,所以,本片沒有放在小技巧裡而是遊戲開發分類裡。

最先,需要瞭解一下拖拽原理,即當滑鼠按下做一個標識,在滑鼠移動時即時修改目標座標資訊,滑鼠抬起的時候,釋放掉滑鼠操作,當然了,為了更好的操作座標,我們一般將父容器改成Canvas。

將圍繞這個做後面的工作,請瞭解之前有關基類和容器的概念,這樣後面看起來就容易很多,考慮它的重用性,建立一個基本控制項讓後面的控制項繼承,將一些通用邏輯寫在這個基類裡,讓其他的類去繼承重用,這也就是遊戲引擎的基本做法之一。

那麼,在Blend或者Visual Studio裡建立一個名為MovableObject的控制項,然後將控制項xaml修改成下面的樣子:

<UserControlxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"mc:Ignorable="d"x:Class="DragObject.MovableObject"d:DesignWidth="640" d:DesignHeight="480" Width="Auto" Height="Auto"><Grid x:Name="LayoutRoot"><Rectangle Stroke="Black" RadiusX="5" RadiusY="5"><Rectangle.Fill><LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"><GradientStop Color="Transparent"/><GradientStop Color="Black" Offset="1"/></LinearGradientBrush></Rectangle.Fill></Rectangle><Image x:Name="ShowImage" Stretch="Fill"/><Rectangle x:Name="Sel_Rectangle" Stroke="White" StrokeThickness="2" Visibility="Collapsed" RadiusX="5" RadiusY="5"/></Grid></UserControl>

即便使用代碼實現並不難,但是為了方便理解,就直接使用XAML較為簡便,瀏覽它的結構圖就可以看到。

上面的表示方法分別是帶了一個底,和一個要顯示映像的Image,以及一個當滑鼠移入時候需要表示選擇標識。

那麼下面就是Coding階段,開啟MovableObject類,代碼設計如下:

public partial class MovableObject : UserControl{//滑鼠點的儲存,同時還承擔是否點擊的判定Point ? mousePoint = null;public MovableObject(){InitializeComponent();//選擇框隱蔽掉Sel_Rectangle.Visibility = System.Windows.Visibility.Collapsed;}//滑鼠移動的方法重載protected override void OnMouseMove(MouseEventArgs e){//判定是否按下滑鼠左鍵if (mousePoint!=null){//計算新的位置double newTop = e.GetPosition(null).Y - mousePoint.Value.Y + Canvas.GetTop(this);double newLeft = e.GetPosition(null).X - mousePoint.Value.X + Canvas.GetLeft(this);Canvas.SetTop(this, newTop);Canvas.SetLeft(this, newLeft);mousePoint = e.GetPosition(null);}base.OnMouseMove(e);}//滑鼠抬起的方法重載protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e){mousePoint = null;//釋放滑鼠裝置this.ReleaseMouseCapture();base.OnMouseLeftButtonDown(e);}//滑鼠按下的方法重載protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e){mousePoint = e.GetPosition(null);//捕獲滑鼠裝置this.CaptureMouse();//下面三行是用來保證當前控制項為最頂層的做法var parent = this.Parent as Panel;parent.Children.Remove(this);parent.Children.Add(this);base.OnMouseLeftButtonUp(e);}//滑鼠進入的方法重載protected override void OnMouseEnter(MouseEventArgs e){Sel_Rectangle.Visibility = System.Windows.Visibility.Visible;base.OnMouseEnter(e);}//滑鼠移出的方法重載protected override void OnMouseLeave(MouseEventArgs e){Sel_Rectangle.Visibility = System.Windows.Visibility.Collapsed;base.OnMouseLeave(e);}}

我做了一些注釋,可以很明確的得知這個基類的作用,現在可以建立類繼承於這個類,來實現擴充的目的。

為此,我準備三種不同的目標效果——表徵圖(MyIcon)、大圖片(MyFace)、自訂控制項(MyCard)

表徵圖和圖片只需要用上原有控制項的Image即可,而自訂控制項則是通過Blend或其他方式設計製作出來的獨立控制項,那麼如何?這三個效果呢?請往下看:

我們先建立三個類,他們都繼承於MovableObject

public class MyIcon : MovableObject

public class MyFace : MovableObject

public class MyCard : MovableObject

下面在各自的建構函式中填入對應的操作邏輯即可,下面給出了完整代碼:

public class MyIcon : MovableObject{public MyIcon(){IconIndex = 1;}private int _Iconindex = -1;public int IconIndex{get { return _Iconindex; }set{_Iconindex = value;var uri = new Uri("/DragObject;component/Res/image" + value + ".png", UriKind.Relative);ShowImage.Source = new System.Windows.Media.Imaging.BitmapImage(uri);}}}public class MyFace : MovableObject{public MyFace(){var uri = new Uri("/DragObject;component/Res/nowpaper.jpg", UriKind.Relative);ShowImage.Source = new System.Windows.Media.Imaging.BitmapImage(uri);
 }}public class MyCard : MovableObject{public MyCard(){LayoutRoot.Children.Insert(LayoutRoot.Children.IndexOf(ShowImage), new Card());LayoutRoot.Children.Remove(ShowImage);}}

MyFace是直接修改ShowImage的Source,MyIcon裡寫了一個索引屬性,這樣可以在外面控制ShowImage,顯示需要顯示的圖片,而MyCard裡new出來一個控制項,並替換掉了原有的ShowImage,MyCard使用了前面製作的一個控制項。

好了,現在在MainPage的建構函式中編寫其他的代碼,但是LayoutRoot需要變成Canvas,這樣才能更好的控製圖像位置。

public MainPage(){InitializeComponent();//添加自訂的拖拽目標var icon = new MyIcon();LayoutRoot.Children.Add(icon);Canvas.SetLeft(icon, 20);Canvas.SetTop(icon, 50);icon = new MyIcon() { IconIndex = 3 };LayoutRoot.Children.Add(icon);Canvas.SetLeft(icon, 20);Canvas.SetTop(icon, 150);var face = new MyFace();LayoutRoot.Children.Add(face);Canvas.SetLeft(face, 100);Canvas.SetTop(face, 50);var card = new MyCard();LayoutRoot.Children.Add(card);Canvas.SetLeft(card, 270);Canvas.SetTop(card, 50);}

現在運行看看效果吧,在這個基礎上,可以製作視窗或需要拖拽的物體只需要繼承修改一下,在下一篇,將會製作一個視窗並提示完成拖入等操作,放心吧絕對不複雜。

本篇工程原始碼如下:點擊直接下載

本篇文章的作者:Nowpaper

推薦Silverlight遊戲開發部落格:深藍色右手

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.