目前游戏的开发进度已经基本实现了精灵对象之间的普通交互,接下来我们需要朝着实现战斗系统的目标前行。而实现它的前提是必须完善精灵控件的基本属性,如添加生命值、魔法值、活力值、经验值等基本属性并通过窗体界面进行完美体现,本节我将为大家讲解上述内容的具体实现。
既然是为精灵添加属性,大家首先想到的当然是为精灵控件加入属性值索引器:
/// <summary>
/// 生命值,[0]-当前值,[1]-当前最大值
/// </summary>
public double[] VLife { get ; set ; }
/// <summary>
/// 魔法值,[0]-当前值,[1]-当前最大值
/// </summary>
public double[] VMagic { get ; set ; }
/// <summary>
/// 活力值,[0]-当前值,[1]-当前最大值
/// </summary>
public double[] VEnergy { get ; set ; }
/// <summary>
/// 等级
/// </summary>
public double VLevel { get ; set ; }
/// <summary>
/// 经验值
/// </summary>
public double VExperience { get ; set ; }
/// <summary>
/// 头像代号
/// </summary>
public int FaceSign { get ; set ; }
/// <summary>
/// PK模式
/// </summary>
public PKMode PKmode { get ; set ; }
以上这些我称之为精灵的基本值属性,也是界面上最常需要表现出来的属性(精灵控件的属性还有很多,在后面的章节中我会根据需要进行逐步的补充)。注释已经写得很清楚了,至于PKMode为精灵PK状态的枚举,目前暂时定义如下:
public enum PKModes {
/// <summary>
/// 和平模式
/// </summary>
Peace = 0,
/// <summary>
/// 全体模式
/// </summary>
Whole = 1,
/// <summary>
/// 善恶模式
/// </summary>
GoodAndEvil = 2,
/// <summary>
/// 门派模式
/// </summary>
Faction = 3,
/// <summary>
/// 家族模式
/// </summary>
Clan = 4,
}
在主角与精灵对象进行交互时我们需要通过它们之间的PK状态分析出是否与对象精灵为敌对状态,如果是则鼠标样式变为攻击光标且此时可以向敌对精灵发起攻击,否则反之。
基本数值定义完后,剩下的就是在游戏窗体界面中将之体现出来。
通常的游戏中,精灵头顶上除了身份描述外,还会存在一个血条,实现该血条其实是很简单的,我们只需为精灵控件的xaml增加如下代码:
<Border x:Name="LifeBorder" Width="45" Height="5" BorderBrush="Black" BorderThickness="0.6" HorizontalAlignment="Left">
<Rectangle x:Name="Life" Width="45" Height="5" HorizontalAlignment="Left"></Rectangle>
</Border>
该血条实际为一个类型为Border的黑色边框包裹着一个Rectangle矩形控件组成,位置数据微调后运行效果如下图:
很漂亮对吧,呵呵,至此我们的精灵控件界面元素算补齐完美了。
接下来是在游戏窗体中进行相关的显示设置;传统的MMORPG游戏界面中角色头像面板分为三种,布局基本如下图:
左上角的面板我称之为主角头像面板,该面板通常包含主角的头像、名字、等级、PK状态、生命值、魔法值、活力值等;在游戏窗体正中顶部的面板我称之为监视对象头像面板,当我们鼠标点击其它精灵如其他玩家、怪物、NPC等时该面板才会显示出来,此面板一般相对于主角头像面板来说构造会简单许多,只有头像、等级、PK状态、名字、生命值等,其中头像及值条尺寸均相对于主角头像面板来说偏小;在游戏窗体最左边的一竖列多个面板为队伍头像面板,该类型面板内容介于主角头像面板与监视对象头像面板之间,并且它的内容尺寸是最小的。
通过上述的分析大家不难看出,其实3个面板以主角头像面板最为齐全;队伍头像面板相当于主角头像面板的缩小版且布局稍微变动些;监视对象头像面板内容最少,相当于主角头像面板的反向且稍微缩小。
基于这些大致概念,我们只需要制作一个以主角头像面板为蓝本的面板控件即可以通过不同的参数配置出另外的两种头像面板。这也是控件封装给我们带来的另一大好处:通用型角色头像面板。
OK,让我们从原理转向实际制作阶段,这里我仅以制作主角头像面板与监视对象头像面板为例进行讲解,组队头像面板因为暂时用不上,实现起来其实是一样的。
首先任务当然是将面板的图片制作出来,同样的,它们需要背景透明:
这两图为我自己手动扣出来的,所以稍微有些锯齿请大家见谅,实际开发中请以美工制作为主,那个才叫个性与优美。
接下来是完成PK图标及人物头像图片。
PK图标我暂时只放置2个,
它们的命名是与PKMode枚举的数值一一对应的。
而人物头像图片在主角及组队头像面板中是朝右的,但在监视对象面板中是朝左的(头像的缩小很容易实现,而水平反向在Silverlight我暂时没有找到1图的解决方案),因此每个角色的头像都由2张图片组成:x_0代表右朝向头像,x_1代表左朝向头像(其中的x为头像代号FaceSign):
然后我们按照第五节的方法将这些图片分类添加进Interface中的相应的文件夹中,到此素材准备阶段算完成了。
下面我们创建一个名为QXRoleFace的通用型面板控件,创建方法具体见第十四节。有了前面那么多章节关于控件的讲解,我们可以很轻松的将头像、PK图标、以及其他基本参数值镶嵌进QXRoleFace控件中(如下图):
添加完后,剩下的是本节的一个难点:如何根据面板中值条(生命值、魔法值、活力值)槽尺寸创建相应的方块值条进行填充?我们首先分析,这3条值应该用什么控件来实现?大家结合本文的第一张图不难看出,它们均为渐变的圆角矩形(为了简单起见,我对其左右两边进行了对称处理而非三角形,至于如何实现不规则矩形,大家可以参考图片蒙版,后面的章节我也会讲到);在WPF/Silverlight中,创建渐变必须用到彩虹笔刷,我根据这3值的传统颜色,如下定义这3把彩虹笔刷:
LinearGradientBrush[] rainbowBrush = new LinearGradientBrush[3];
/// <summary>
/// 初始化彩虹笔刷
/// </summary>
private void InitializeRainbowBrush() {
//血值笔刷
CreateRainbowBrush(ref rainbowBrush[0], 201, 238, 206, 60, 224, 70, 106, 234, 130);
//魔值笔刷
CreateRainbowBrush(ref rainbowBrush[1], 192, 195, 238, 86, 104, 226, 100, 104, 233);
//活值笔刷
CreateRainbowBrush(ref rainbowBrush[2], 254, 209, 172, 255, 142, 40, 255, 177, 74);
}
/// <summary>
/// 创建彩虹笔刷
/// </summary>
private void CreateRainbowBrush(ref LinearGradientBrush brush ,
byte r0, byte g0, byte b0, byte r1,byte g1,byte b1, byte r2, byte g2, byte b2) {
brush = new LinearGradientBrush();
brush.StartPoint = new Point(0, 0);
brush.EndPoint = new Point(0, 1);
brush.GradientStops.Add(new GradientStop(Color.FromRgb(r0, g0, b0), 0));
brush.GradientStops.Add(new GradientStop(Color.FromRgb(r1, g1, b1), 0.70));
brush.GradientStops.Add(new GradientStop(Color.FromRgb(r2, g2, b2), 1));
brush.Freeze();
}
然后通过RadiusX及RadiusY设置矩形值条的圆角边,并添加对应的数字。最后将这3条矩形相应的嵌入到主角头像面板中,这样就完成了主角头像面板的创建:
有了主角头像面板,我们还需要在此基础上改造出监视对象头像面板;前文中我曾有提到,既然是通用型控件,我们只需进行参数的修改即可实现不同的界面表现形式。因此首先需要定义一个名为RoleFaceTypes的枚举进行区分:
/// 角色头像值面板类型
public enum RoleFaceTypes {
/// 主角头像面板
Leader = 0,
/// 监视对象头像面板
Object = 1,
/// 队伍头像面板
Team = 2,
}
如上,我们只需在游戏窗体中以RoleFaceTypes为参数创建QXRoleFace控件,即可以创建出对应的头像面板,例如我们通过如下方式创建监视对象头像面板:
QXRoleFace ObjectRoleFace = new QXRoleFace(RoleFaceTypes.Object);
当然,主角与监视对象头像面板之间是存在方向、尺寸上的差异的,且后者少了2个值条;因此,在构建QXRoleFace控件的时候,我们根据RoleFaceTypes的类型进行相应的子控件位置布局及隐藏,具体调整在源码中,这里就不一一列举了。终于完成了,让我们看看效果:
上图右边即为主角监视自身的头像面板,呵呵,稍微粗糙了些呢,我相信大家能做得更好!
最后就是关于监视对象面板的显示场合及显示方式;在本节例子中,我暂时使用如下模式:当鼠标悬停于精灵对象上时即显示其头像面板,离开时该面板隐藏。具体的实现代码只需在上一节命中测试方法中的鼠标进入精灵有效区域及离开时进行相关简单处理即可。
其他的界面微调代码虽然很繁多,但是只要大家是跟着本系列教程一节节学下来的,肯定打下了WPF/Silverlight方面很扎实的基础,这些代码对于大家来说再简单不过了,同样不再一一列举。
最后国际惯例,让我们一同欣赏下劳动成果吧:
界面的内容讲解似乎有种只便意会,不易言传的感觉;不同类型的游戏拥有不同的界面风格,大家在开发的时候只需统一美工的绘画风格,制作出来的游戏界面肯定都是much much个顶个的漂亮;我希望同过本节的简单讲解,能给予大家一些界面制作方面的启发与思维,让我们携手为提升未来的游戏视觉品质共同努力吧!
下一节仿佛将进入战斗阶段了,是不是太快了些。您准备好了吗?