游戏中会使用大量的菜单面板,而这些面板往往都带有选项卡。如果用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://blog.csdn.net/alamiye010/
教程目录及源码下载:点击进入
本文版权归作者和CSDN共有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面显著位置给出原文连接,否则保留追究法律责任的权利。

C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(四十四)制作主角属性面板及加点器相关推荐

  1. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(十四) 精灵控件横空出世!①

    在上一节中,我们实现了地图牵引式移动,同时还遗留着一个小尾巴:主角和障碍物该如何跟随着地图的移动而移动? 上节中有点到,只要在地图移动的同时,时时根据主角等对象物体的X,Y坐标进行相对于地图的X,Y坐 ...

  2. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(十八) 完美精灵之八面玲珑(WPF Only)②...

    紧接着上一节,首先得解释一下为什么需要将这272张图片合成为一张大图.因为如果游戏中还有装备.坐骑等其他设置,那么我们就需要对图片源进行时时的合成:同时对272张甚至更多的图片进行合成效率高还是对2张 ...

  3. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(十)斜度α地图的构造及算法...

    在当前的网络游戏中,地图基本都是采取一定斜度的拼装地图,这其中存在两种斜度地图的构造方式: 第一种我称之为伪斜度地图:该类型地图表现层图片为斜度的,但地图基底障碍物等的构造则实为正方形,如下图: 其实 ...

  4. C#开发WPF/Silverlight动画及游戏系列教程(Game Course):(十四) 精灵控件横空出世!①

    在上一节中,我们实现了地图牵引式移动,同时还遗留着一个小尾巴:主角和障碍物该如何跟随着地图的移动而移动? 上节中有点到,只要在地图移动的同时,时时根据主角等对象物体的X,Y坐标进行相对于地图的X,Y坐 ...

  5. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):目录

    本系列教程的示例代码下载(感谢 银光中国 提供资源分流): 第一部分源码:WPFGameTutorial_PartI(1-20节) 第二部分源码:WPFGameTutorial_PartII(21-2 ...

  6. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(二)让物体动起来②

    第二种方法,CompositionTarget动画,官方描述为:CompositionTarget对象可以根据每个帧回调来创建自定义动画.其实直接点,CompositionTarget创建的动画是基于 ...

  7. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(一)让物体动起来①

    序:自从QXGame(WPF GAME ENGINE)游戏引擎公布以来,受到很多朋友的热切关注,于是乎有了写教程的想法.那么从今天开始,我将带领大家一步一步的学会如何使用纯C#开发WPF/Silver ...

  8. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(二十六)通用型角色头像面板...

    目前游戏的开发进度已经基本实现了精灵对象之间的普通交互,接下来我们需要朝着实现战斗系统的目标前行.而实现它的前提是必须完善精灵控件的基本属性,如添加生命值.魔法值.活力值.经验值等基本属性并通过窗体界 ...

  9. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(二十五)完美捕捉精灵之神器 -- HitTest...

    怪物们都出现了,如何选中自己心仪的怪是主角目前首要做的事. 为了进行鼠标状态区别,我首先对鼠标变化规则进行约束:当鼠标在屏幕上空旷地图区域移动时,鼠标光标形态表现为默认光标 (0号光标图片),当鼠标经 ...

最新文章

  1. 判别模型和生成模型的区别
  2. 基于TCP的应用层协议、与基于UDP的应用层协议分别有哪些?
  3. SpaceX再发射58颗星链卫星 总数达到538颗
  4. 集合框架知识系列05 HashMap的源码分析和使用示例
  5. C/S与B/S架构比较
  6. JMETER分布式部署注意事项
  7. 用DataAdapter对象填充DataSet数据集。
  8. Tensorflow2.0数据和部署(四)——Tensorflow高级模型部署
  9. 【物理】概念的理解 —— Phase(相位)
  10. StringUtils测试
  11. 基于K均值聚类算法的图像分割(Matlab)
  12. 循环冗余校验码(CRC)详解
  13. [推荐]15款非常好用的新浪,腾讯短链接生成器,一次生成永不失效,巨好用!
  14. 对一款国家级内容过滤系统Dos安全缺陷分析
  15. 如果微软狠心鸿蒙系统,微软强制用户升级华为鸿蒙系统出来你会放弃windows使用鸿蒙吗...
  16. Loadrunner11.00破解方法
  17. 快速刷新页面ajax出现404,react使用BrowserRouter打包后,刷新页面出现404
  18. P1265 公路修建
  19. php影视网站主页不显示列表,七星修改米酷影视6.2.8完整版–PHP7.0及以上,修复页面不显示和不能播放等...
  20. 【bug】mysql tinyint boolean 插入无效问题

热门文章

  1. php统计 柱状图,PHP动态柱状图
  2. 基于javaweb的宠物医院管理系统设计和实现(java+springboot+ssm+mysql+jsp)
  3. numpy.array的二维数组拼接做法
  4. Oracle12C EMCC部署安装
  5. 论文阅读|node2vec: Scalable Feature Learning for Networks
  6. java gcm_Java实现AES-GCM解密,JS实现AES-GCM加密。
  7. java gcm_JAVA中的AES GCM加密和解密
  8. ssm+jsp计算机毕业设计艾儿影楼管理系统18llj(程序+LW+源码+远程部署)
  9. ckplayer播放器控制播放/暂停
  10. Java版贪食蛇游戏的设计与实现毕业设计