每款 MMORPG 都少不了一個主選單,通常固定在視窗底部,作為玩家存取角色屬性、背包、技能、任務、組隊、地圖、公會、門派、商城、系統設定等核心功能的入口。其中也包含快捷自訂選單欄,以及類似《暗黑破壞神》經典的滑鼠左右鍵快捷技能欄。雖然各遊戲細節略有不同,但整體架構大同小異。本節將以《劍俠世界》的主介面為例,示範如何在 Silverlight 中打造一個精美的主選單面板與滑鼠左右鍵快捷技能欄。
首先需要一張主介面的框架素材:
在《劍俠世界》中,該面板從左至右依序為鍵盤快捷選單、滑鼠左右鍵快捷選單與主選單。我們先從右側的主選單著手。介面中已鏤空的區域用於填入對應的選單按鈕。若僅用單一圖片填充,遊戲質感將大打折扣。回想網頁導航列,滑鼠進入時透過 CSS/JS 切換樣式以達突顯美化效果,遊戲同樣可採用此策略:滑鼠進入按鈕時,將按鈕圖片從灰暗切換為明亮。
上述做法需兩張圖片互換,但在 Silverlight 這類依賴素材即時下載的遊戲中,應盡量減少素材數量與容量。因此推薦使用透明高亮遮罩實現按鈕突顯:
滑鼠進入按鈕時,疊加一張圖示遮罩於按鈕圖示上方,同樣能達到高亮效果。更棒的是,遊戲中所有物品與技能圖示尺寸通常統一,僅需一張遮罩即可套用至所有圖示,大幅節省資源空間,一舉兩得。
核心控件為 QXIcon,經改造支援三種模式:
public enum IconTypes {
None = 0, // 普通圖示
Transform = 1, // 圖片切換突顯
Highlights = 2 // 遮罩高亮突顯
}
QXIcon 主要建構邏輯:
public QXIcon(IconTypes iconTypes) {
InitializeComponent();
switch (iconTypes) {
case IconTypes.Transform:
this.MouseEnter += delegate { Container.Background = NewSource; };
this.MouseLeave += delegate { Container.Background = _BodySource; };
break;
case IconTypes.Highlights:
Rectangle mask = new Rectangle() { Visibility = Visibility.Collapsed };
Container.Children.Add(mask);
this.MouseEnter += delegate {
mask.Width = this.Width;
mask.Height = this.Height;
mask.Fill = NewSource;
mask.Visibility = Visibility.Visible;
};
this.MouseLeave += delegate { mask.Visibility = Visibility.Collapsed; };
break;
}
}
Brush _BodySource;
public Brush BodySource {
get { return _BodySource; }
set { Container.Background = _BodySource = value; }
}
public Brush NewSource { get; set; }
NewSource 與 _BodySource 間切換背景。Rectangle 遮罩,填入 NewSource 並顯示/隱藏來實現高亮。同時改造 ToolTip,使其背景依文字長寬自適應,呈現 40% 透明度的黑色圓角矩形:
<ToolTipService.ToolTip>
<ToolTip>
<ToolTip.Template>
<ControlTemplate>
<ContentPresenter Content="{TemplateBinding Content}"/>
</ControlTemplate>
</ToolTip.Template>
<ToolTip.Content>
<Canvas x:Name="Dialog">
<Rectangle x:Name="DialogBack" Fill="Black" RadiusX="7" RadiusY="7" Stroke="Gray" StrokeThickness="2" Opacity="0.4" />
<TextBlock x:Name="Details" Foreground="Snow" TextWrapping="Wrap" Width="150" Canvas.Left="5" Canvas.Top="5" />
</Canvas>
</ToolTip.Content>
</ToolTip>
</ToolTipService.ToolTip>
程式碼後段同步更新背景尺寸:
public string Tip {
get { return Details.Text; }
set {
Details.Text = value;
DialogBack.Width = Details.ActualWidth + 10;
DialogBack.Height = Details.ActualHeight + 10;
}
}
左鍵負責移動、選取目標、物理攻擊;右鍵負責施放魔法。點擊右鍵快捷按鈕時,彈出主角已習得的所有法術供選擇,參考《暗黑破壞神》經典設計。Silverlight 中可使用微軟開源工具包的 WrapPanel 輕鬆實現自動換行排列。
定義魔法資料類別:
public class Magic {
public int Code { get; set; }
public int Level { get; set; }
public string Name { get; set; }
}
初始化主角可用魔法列表:
List<Magic> availableMagic = new List<Magic>();
availableMagic.Clear();
for (int i = 0; i < 6; i++) {
availableMagic.Add(new Magic() {
Code = i,
Level = 9,
Name = string.Format("名稱:{0}\r\n描述:{1}",
Super.GetXElement(Data.Settings["Arguments"], "Magic", "Code", i.ToString()).Attribute("Name").Value,
Super.GetXElement(Data.Settings["Arguments"], "Magic", "Code", i.ToString()).Attribute("Description").Value)
});
}
點擊右鍵圖示時,將魔法以圖示形式加入 WrapPanel(寬 270 像素,每列 10 個圖示),並綁定點擊事件切換預設右鍵魔法:
rightButtonMagicIcon.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e) {
if (rightButtonMagicList == null) {
rightButtonMagicList = new WrapPanel() {
Orientation = Orientation.Horizontal,
Width = 270
};
foreach (Magic magic in availableMagic) {
QXIcon magicIcon = new QXIcon(IconTypes.Highlights) {
BodySource = new ImageBrush() { ImageSource = Super.GetImage(string.Format("/Image/Magic/{0}/0.png", magic.Code)) },
NewSource = new ImageBrush() { ImageSource = Super.GetImage("/Image/Icon/34.png") },
Width = 27, Height = 27,
Tip = magic.Name,
Tag = magic
};
magicIcon.MouseLeftButtonDown += delegate(object ss, MouseButtonEventArgs ee) {
QXIcon icon = ss as QXIcon;
Magic m = icon.Tag as Magic;
rightButtonMagicIcon.BodySource = icon.BodySource;
rightButtonMagicIcon.Tip = m.Name;
Leader.CurrentMagic.Code = m.Code;
Leader.CurrentMagic.Level = m.Level;
rightButtonMagicList.Visibility = Visibility.Collapsed;
ee.Handled = true;
};
rightButtonMagicList.Children.Add(magicIcon);
}
BottomMenu.Children.Add(rightButtonMagicList);
Canvas.SetLeft(rightButtonMagicList, 437);
Canvas.SetTop(rightButtonMagicList, -Math.Ceiling(rightButtonMagicList.Children.Count / (rightButtonMagicList.Width / 27)) * 27);
} else {
if (rightButtonMagicList.Visibility == Visibility.Collapsed) {
rightButtonMagicList.Visibility = Visibility.Visible;
Canvas.SetTop(rightButtonMagicList, -rightButtonMagicList.ActualHeight);
} else {
rightButtonMagicList.Visibility = Visibility.Collapsed;
}
}
e.Handled = true;
};
增加更多魔法測試 WrapPanel 自動換行效果:
主選單面板雛形已成,後續將完善各子面板功能。敬請期待。
原始碼下載:目錄中;線上演示:https://silverfuture.cn