上一节,我们实现了6大系魔法的附加属性,并赋予了不同的颜色加以区别;但是在实际的游戏开发中,特别是Q版或追求艺术表现的网络游戏中,为了能够更加突显魔法的绚丽与雍华,设计师们会为魔法增加大量的画面体现:例如被冻结的精灵脚底长出冰刺(或被装进一块冰晶中);灼伤的精灵会周身燃烧;中毒的精灵会不停的冒着毒泡泡;麻痹中的精灵浑身会不停的穿梭着电流等等,这些修饰使得魔法的魅力提升到极至,同时也是游戏幽雅细节的终极体现。

本节我将以冻结魔法为例,向大家讲解如何为魔法增加漂亮的特效装饰。

经过前面的学习,大家是否已总结出一个规律:需要增加额外东西时,首先想到的即是用户控件;那么我们首先创建一个名为QXDecoration的用户控件。接下来就是准备素材了。这里我制作了3张用于装饰的冰刺:

分别命名为4-04-14-2,其命名规则对应上一节中的魔法类型设定,即所有冰冻类魔法均可以用之来装饰。为什么要使用3张呢?其实一张就已足够了,只是效果上每个精灵被冻结后将一模一样;而通过随机从这3张中抽取1张用于装饰冻结效果将大幅度增加画面的生动性,在大量精灵同时被冻结的情况下产生一种宏大的气势感;另外,如果您能通过Blend画出一个类似的冰刺,那么基于矢量的装饰物将可以任意的拉伸及变化,表现出来的效果会更加逼真与贴切。

都准备好后,代码实现起来是很简单的,首先将配置写进Config.xml

      <Decoration Code="4" Num="3" Duration="2" CenterX="40" CenterY="60"></Decoration>

接下来只需在魔法触发伤害帧时将对应的魔法效果装饰附加到被攻击对象的脚底即可:

……

//附加特效装饰

if (magic.DecorationCode != -1 && canvas.FindName(string.Format("Decoration{0}", enemy.Name)) == null) {

    LoadXElement(string.Format("Decoration{0}", magic.DecorationCode.ToString()), GetTreeNode(SystemConfig, "Decoration", "Code", magic.DecorationCode.ToString()));

    XElement DecorationData = GetXElement(string.Format("Decoration{0}", magic.DecorationCode.ToString()));

    Random rm = new Random();

    QXDecoration decoration = new QXDecoration() {

      BodySource = getImage(string.Format("Decoration/{0}-{1}.png", magic.DecorationCode, rm.Next((int)DecorationData.Attribute("Num") - 1))),

      CenterX = (double)DecorationData.Attribute("CenterX"),

      CenterY = (double)DecorationData.Attribute("CenterY"),

      X = enemy.X,

      Y = enemy.Y,

      Duration = (double)DecorationData.Attribute("Duration"),

    };

    canvas.RegisterName(string.Format("Decoration{0}", enemy.Name), decoration);

    canvas.Children.Add(decoration);

}

……

上一节中的冰冻只是减缓对象精灵的各种速度,那么本节为了演示,我将之改为了冻结效果,类似于麻痹。因此该冻结装饰的消失分两种情况:一是在冻结时间归0时被移除;另一种为被冻结精灵死亡后移除,相关逻辑我写在源码中,这里就不罗列了。

来一张效果图吧:

相对于上一节,气势增加了不少呢,对吗?

额外的,通常的网络游戏中,我们都可以通过角色头像面板中的小图标来查看当前监视的精灵对象被附加的DeBuff以及相关信息如持续时间、效果等等,而这个功能在我们的示例游戏中该如何实现呢?

这里我们同样的先添加一个名为QXIcon的图标控件,该控件的界面xaml定义如下:

……

    <Canvas x:Name="Icon">

        <Image x:Name="Body">

            <Image.ToolTip>

                <TextBlock x:Name="Details"/>

            </Image.ToolTip>

        </Image>

    </Canvas>

……

该控件的主体是一张图片,我为之增加了一个ToolTip用于鼠标悬停时显示该图片的描述。

接下来再为通用型角色头像面板增加一个水平排列的StackPanel控件作为这些DeBuff图标的容器:

<StackPanel x:Name="ExtraPanel" Orientation="Horizontal" />

为什么选择StackPanel而不是其他的布局控件呢?一方面为了与Silverlight更好的兼容,另一方面只要设置好它的宽度,动态的子控件添加或移除队列起来均非常的完美,我们需要做的仅仅是AddRemove操作罢了。

最后,在刷新监视对象角色头像面板方法中添加如下逻辑进行DeBuff图标的添加与移除判断:

……

//更新DeBuff附加属性图标及描述
for (int i = 0; i < obj.ExtraTime.Count(); i++) {

      QXIcon icon = ObjectRoleFace.ExtraPanel.FindName(string.Format("Extra{0}", i)) as QXIcon;

      if (obj.ExtraTime[i] > 0) {

      XElement ExtraItem = Super.GetTreeNode(Super.SystemXElement["ExtraItems"], "Item", "Value", i.ToString());

      if (icon == null) {

          icon = new QXIcon() {

          Width = 16,

          Height = 16,

          BodySource = Super.getImage(ExtraItem.Attribute("Src").Value)

          };

          ObjectRoleFace.ExtraPanel.RegisterName(string.Format("Extra{0}", i), icon);

          ObjectRoleFace.ExtraPanel.Children.Add(icon);

      }

      icon.Tip = string.Format("{0}持续:{1}", ExtraItem.Attribute("Name").Value, obj.ExtraTime[i]);

      } else {

      if (icon != null) {

          ObjectRoleFace.ExtraPanel.UnregisterName(string.Format("Extra{0}", i));

          ObjectRoleFace.ExtraPanel.Children.Remove(icon);

          icon = null;

       }

    }

 }

……

运行效果图:

很酷吧~WPF中的ToolTip非常强大,模板化的它无论内容多少或形式如何均能自如显示。不同尺寸的QXIcon不仅仅可以用来显示图标,还可以拓展到技能图标、快捷图标等等;另外,这些DeBuff图标在StackPanel的管理下显得相当智能,前一个图标消失后,后一个图标将自动前置,再新加入的DeBuff图标又会跟进追尾显示,而这些的一切乱序队列均是伟大的StackPanel在默默无闻的处理,我们无须插手任何一句多余的代码:

    角色面板到此为止总算完善了。下一节我将为大家讲解如何为本教程示例游戏制作地图编辑器,初步打算首先实现障碍物设置与地图切片功能,现做现卖,时间会久一点,要关注哦。

WPF/Silverlight
作者:深蓝色右手
出处:http://alamiye010.cnblogs.com/
教程目录及源码下载:点击进入(欢迎加入WPF/Silverlight小组 WPF/Silverlight博客团队)
本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此段声明,且在文章页面显著位置给出原文连接,否则保留追究法律责任的权利。
posted on 2009-09-17 16:21  深蓝色右手  阅读(7019)  评论(30编辑  收藏  举报