程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C#開發WPF/Silverlight動畫及游戲系列教程(Game Tutorial):(四十四)

C#開發WPF/Silverlight動畫及游戲系列教程(Game Tutorial):(四十四)

編輯:關於C#

C#開發WPF/Silverlight動畫及游戲系列教程(Game Tutorial):(四十四)制作主角屬性面板及加點器

游戲中會使用大量的菜單面板,而這些面板往往都帶有選項卡。如果用Silverlight工具中的TabControl,則需要通過復雜的xaml重寫模板來實現自定義樣式,這一點時常讓開發者頭疼,畢竟界面的東西應該屬於美工的范疇,這也是我所發現在目前Silverlight中唯一一處只能通過xaml而無法用代碼實現的地方。當然,如果您對此特別感興趣,同樣可以到http://www.codeplex.com/Silverlight中下載最新的開源工具源碼,其中的示例項目中有非常詳細的模板重寫案例。本節,我將通過創建用戶控件的方式來創建自定義的TabControl和RepeatButton,實現主角屬性面板及其中的屬性加點器。

首先,我創建一個QXTabControl用戶控件,該控件界面可以很簡單,只需要包含一個頭和一個身體即可:

<UserControl x:Class="QXGameEngine.Control.QXTabControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 <Canvas>
   <StackPanel x:Name="Head"/>
   <ContentPresenter x:Name="Body"/>
 </Canvas>
</UserControl>

Head 用做TabItem的容器,作為StackPanel類型控件,它可以對內部控件進行橫排或豎排,從而基本滿足大多數情況需要;而Body是ContentPresenter類型,在第四十二節中我曾提及過它,相當於一個萬用變身控件,將它作為選項卡的身體部分再合適不過了。當我們點擊不同的選項卡時,將不同的面板控件作為值賦予給Body,輕松實現高度自由的選項內容變換。

那麼用什麼控件來替代TabItem呢?在《劍俠世界》中,選項卡做得別具特色,不光在默認情況下鼠標進入與離開會呈現不同的圖片;當被點中後,同樣實現另外的兩張圖片間的切換。這樣的效果相當精致,而我們又該如何將它實現呢?此時,不得不想到我們可愛的QXIcon控件,我為它添加了新的類型:IconTypes.HitModes,定義很簡單,根據該控件是否被點擊從而對4張圖片進行相應切換:

case IconTypes.HitModes:
 this.MouseEnter += (s, e) => { Container.Background = Hit ? HitNewBodySource : NewSource; };
 this.MouseLeave += (s, e) => { Container.Background = Hit ? HitBodySource : _BodySource; };
 this.MouseLeftButtonDown += (s, e) => { Hit = Hit ? false : true; };
break;

實現後的效果如下圖:

在QXTabControl中包含一個List<QXIcon> tabItemList = new List<QXIcon>();用於管理現有的所有選項卡;我還模仿TabControl在QXTabControl中創建SelectionChanged事件:

public delegate void SelectionChangedEventHandler(object sender, QXIcon tabItem);
public event SelectionChangedEventHandler SelectionChanged;

當某個選項卡被點擊時,觸發該事件:

……
tabItem.MouseLeftButtonDown += (sender, e) => {
 foreach (QXIcon icon in tabItemList) {
  if (icon == sender) {
   icon.Hit = true;
   icon.Container.Background = icon.HitNewBodySource;
  } else {
   icon.Hit = false;
   icon.Container.Background = icon.BodySource;
  }
 }
 SelectionChanged(this, sender as QXIcon);
 e.Handled = true;
};
……

這樣我們就可以在游戲窗口中對已創建的選項卡控件注冊SelectionChanged事件了:

//主角屬性選項卡內容
QXTabControl tc = new QXTabControl() {
 TabItemOrientation = Orientation.Horizontal,
 TabItemHeight = 28,
 BodyLeft = -4,
 BodyTop = 27
};
//添加4個選項卡
tc.AddItem(63, 28, 1, "/Image/Icon/39.png", "/Image/Icon/40.png", "/Image/Icon/41.png", "/Image/Icon/42.png", "屬  性");
tc.AddItem(63, 28, 1, "/Image/Icon/39.png", "/Image/Icon/40.png", "/Image/Icon/41.png", "/Image/Icon/42.png", "聲  望");
tc.AddItem(63, 28, 1, "/Image/Icon/39.png", "/Image/Icon/40.png", "/Image/Icon/41.png", "/Image/Icon/42.png", "稱  號");
tc.AddItem(63, 28, 1, "/Image/Icon/39.png", "/Image/Icon/40.png", "/Image/Icon/41.png", "/Image/Icon/42.png", "榮  譽");
……
tc.SelectionChanged += (sender, item) => {
 QXTabControl tabControl = sender as QXTabControl;
 switch (item.Text) {
  case "屬  性":
    tabControl.SetBody(leaderAttributePart);
  break;
  case "聲  望":
    tabControl.SetBody(new Canvas() {
    Background = new ImageBrush() { ImageSource = Super.GetImage("/Image/Plate/RoleAttributeBack1.png") },
    Width = 350,
    Height = 389,
    });
  break;
  case "稱  號":
    tabControl.SetBody(new Canvas() {
                       Background = new ImageBrush() { ImageSource = Super.GetImage("/Image/Plate/RoleAttributeBack2.png") },
     Width = 350,
     Height = 389,
    });
  break;
  default:
     tabControl.SetBody(null);
  break;
 };
};

運行時效果:

很棒吧?嘿嘿。在角色屬性面板裡除了顯示角色的屬性值等個人資料外,還有裝備管理及屬性加點器兩個重要部分。關於裝備,後面的章節再細說。下面我向大家講講如何制作這個屬性加點器。

如果不論樣式,我們直接可以使用官方提供的NumericUpDown控件即可,該控件非常強大,看了它的源碼,其本身為一個組合控件,由4大部分組成:文本(TextBlock)、文本容器(ContentPresenter)、加按鈕(RepeatButton)及減按鈕(RepeatButton),且模式很多,你能想到的基本都有。當然同樣的,要重寫它的樣式實在是麻煩之事,其實該控件的重點就就在RepeatButton上,如何實現這個Repeat動作又是關鍵中的關鍵。我們不妨從它的原理出發,當鼠標在此按鈕上按下時開始計時,如果鼠標一直未放開,則當到達預先設定的Delay時間間隔後即觸發後面的連續重復動作,且這些動作以Interval為間隔不斷重復下去直到鼠標左鍵被放開或鼠標離開該控件。此時,我又想到了美麗的QXIcon,再次為它添加一種新模式:IconTypes.RepeatButton:

case IconTypes.RepeatButton:
DispatcherTimer timer = new DispatcherTimer();
  timer.Tick += (s, e) => { timer.Interval = TimeSpan.FromMilliseconds(Interval); RepeatClick(this, e); };
  this.MouseEnter += (s, e) => { Container.Background = NewSource; };
  this.MouseLeave += (s, e) => { Container.Background = _BodySource; timer.Stop(); };
  this.MouseLeftButtonDown += (s, e) => { timer.Interval = TimeSpan.FromMilliseconds(Delay); timer.Start(); };
  this.MouseLeftButtonUp += (s, e) => { timer.Stop(); e.Handled = true; };
break;

根據前面對RepeatButton工作原理的描述,在這種模式下,我通過創建一個DispatcherTimer,當它Tick時觸發public event EventHandler RepeatClick;事件。其中配合控件自身的 MouseLeftButtonDown、MouseLeftButtonUp及MouseLeave來開停Timer及設置它的間隔。

接著,我們就可以將此控件應用到主角屬性面板中制作屬性加點器了。配合上相應邏輯,當屬性點數加完並提交後,主角的新屬性值會立即更新反映到界面中。按照第二十八節的屬性設置,主角擁有5大基本屬性,當修改這些屬性時會分別影響相關的值數據。例如,默認情況下主角的智慧為30,魔法攻擊基本傷害范圍為460-615(不包括魔法自身的攻擊力),此時用激光魔法攻擊敵人可造成約600左右傷血:

而當我將智慧加到200並點擊確定後,魔法攻擊到了3010-4015,此時攻擊敵人可以造成3500左右的傷害,很酷吧。嘿嘿:

本教程示例游戲中,我為主角賦予了1000點的潛能點,大家可以自由分配到不同的屬性上,例如增加力量屬性可以增加物理攻擊力,增加體格可以提升血上限及防御等,增加敏捷可以加快移動及施法速度等,增加幸運可以提高暴擊率等等,測試起來還是相當有趣的呢~

不過目前的屬性加點器還不能通用,畢竟不同的游戲中加點器的實現都有差異。例如有些只有加沒有減,每次點擊都會直接提交,這種處理最簡單;而有的每次加點都會直接反應到界面上,且中途如果不滿意取消後又會恢復原樣,這種模式做起來相對復雜些,需要一些臨時字段來存儲數據,只有提交後才更新到服務器。本節功能上我選擇了折中的處理方式。

游戲中的面板基本上大同小異,前面章節中的對象監視面板、雷達地圖面板、尋路地圖面板、主角屬性面板的制作基本上含蓋了大多數情況,後面的章節我將不再圍繞面板這個羅嗦的話題了,打算將重心放到裝備、物品、技能存放與拖動的實現方面,敬請關注。

本節源碼請到目錄中下載,在線演示地址:http://silverfuture.cn

出處:http://alamiye010.cnblogs.com/

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved