在上一节中,我们实现了地图牵引式移动,同时还遗留着一个小尾巴:主角和障碍物该如何跟随着地图的移动而移动?

    上节中有点到,只要在地图移动的同时,时时根据主角等对象物体的XY坐标进行相对于地图的XY坐标移动即可达到目的。但是由此又引来了新问题:主角为Image控件,障碍物则为矩形控件,它们都没有XY这两个属性,我们该如何对它们的坐标进行记录呢?

    最简单且最直接的方法莫过于将它们的XY坐标通过分隔符连接然后记录进Tag属性中,在调用的时候再将它分离取出。例如我们可以在构建障碍物的时候这样做:

            //构建障碍物(本节只为演示,随便建一个)

            for (int y = 11; y <= 14; y++) {

                for (int x = 31; x <= 40; x++) {

                    //障碍物在矩阵中用0表示

                    Matrix[x, y] = 0;

                    rect = new Rectangle();

                    //目前暂时不新创一个自定义控件,而把坐标储存在Tag属性中

                    rect.Tag = x + "," + y;

                    ……

                }

            }

    其中上图中黄色的代码即为将障碍物的XY坐标记录进它的Tag属性,然后我们可以通过下面的函数在需要的时候对Tag属性进行分离调用:

        //从矩形障碍物的Tag属性中分离出它的坐标Point

        private Point getPointFromTag(object tag) {

            string[] str = tag.ToString().Split(new char[] { ',' });

            return new Point(Convert.ToDouble(str[0]), Convert.ToDouble(str[1]));

        }

    但是,这样做的效率是极其低下的;更主要的是它毫无扩展性可言。障碍物还好对付,如果是主角呢?它不光有XY两个属性,还有名字、门派、血条、蓝条、金木水火土、力量、智慧……、线程参数、方向、装备代号等等等等(晕了。。。列不完的),太多太多的五花八门的属性,难不成全都要记录进这一个Tag属性中?将霸王龙关进笼子里这是件很可怕的事情,装也难,取也难!两个字:恐怖。

    读者声音:老大,那该怎么办?搞不定难道还要上吊呀?

    作者:安啦,急什么?下面才是重点。可要认真看呀,超大一个精华!!!

    如果有做过游戏开发的朋友,或者说有了解过游戏开发相关内容的朋友一定会发现,游戏中除了地图引擎外,最关键的莫过于精灵的创建。精灵是游戏中大家见得最多的对象物体,它可以是主角,可以是其他玩家,可以是NPC,可以是怪物及BOSS,甚至可以是坐骑、障碍物等等。很多初学的朋友往往在为如何使用外国人制作好的通用精灵而发愁(毕竟繁杂的英文专业术语及超量的对象属性及方法是大多数人无法轻易弄通的)。幸运的是,在WPF/Silverlight中我们可以找到强大且使用简单的相关支持,它就是下文中我将详细讲解的传说中的精灵控件

    我们首先来看看如何在WPF/Silverlight中创建一个精灵控件。第一步要做的是在项目中添加一个文件夹(取名Controls)来归类保存它,接下来在该文件夹上点右键添加一个用户控件(取名叫QXSpirit.xaml,嘿嘿,当然其他名字都可啦,高兴就好),如下图。

    准备工作完成啦,第二步就是去丰富这个控件,多多给它加内容,让它强大起来。那么我们双击QXSpirit.xaml,窗口中显示的就是它的界面了,暂时是一片空白的,我们首要添加的当然就是迫不及待想要出世的角色了,所以我们这样写:

<UserControl x:Class="WPFGameCourse.Controls.QXSpirit"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml xmlns:QXControl="clr-namespace:QX.Game.Controls;assembly=QX">

    <Canvas x:Name="Spirit">

        <Image x:Name="Body" Width="150" Height="150"/>

        <StackPanel Name="Description" Width="150" Height="58" Canvas.Top="-21">

            <!--门派-->

            <QXControl:BorderText x:Name="Faction" Fill="Orchid" FontSize="12" Bold="True" Stroke="Black" StrokeThickness="0.1" Text="娥眉大师姐" Height="13" HorizontalAlignment="Center" />

            <!--家族-->

            <QXControl:BorderText x:Name="Clan" Fill="DarkOrange" FontSize="12" Bold="True" Stroke="Black" StrokeThickness="0.1" Text="破天一剑" Height="13" HorizontalAlignment="Center" />

            <!--名字-->

            <QXControl:BorderText x:Name="Name" Fill="SteelBlue" FontSize="12" Bold="True" Stroke="Black" StrokeThickness="0.1" Text="爱在后院前" Height="13" HorizontalAlignment="Center" />

        </StackPanel>

    </Canvas>

</UserControl>

    代码很简单,我先定义一个名为SpiritCanvas主布局控件(为了方便自由定位它内部的其他子控件,所以在选择上我依然使用我钟爱的Canvas。当然,你也可以使用别的布局控件作为主控件)。然后在它的内部建立一个名为BodyImage子控件,它就是精灵的身体啦(也就是我们前面章节中一直使用着的Image Spirit=new Image())。游戏中的精灵不光只有身体部分,还包括关于它的很多附加信息显示在周围:例如名字、帮派、家族等等。在上面代码中,我将这3个描述精灵身份的文字控件放在一个名为Describtion,类型为StackPanel的布局控件(该布局控件特点为可以轻松的排列子控件)中并且稍微调整一下它的位置以便在角色身体上方合适的位置显示(Canvas.Top="-21")。而这3个描述身份的文字控件均为我事先写好的带描边的名为BorderText的控件,该控件同样编译封装在项目源码中的Dll文件夹中的QX.dll中。在WPF/Silverlight中要引用程序集中的控件,必须在xaml开头申明它。因此,我们需要在UserControl中写这样一句申明:xmlns:QXControl="clr-namespace:QX.Game.Controls;assembly=QX",其中QXControl为下文中引用该控件时需要申明的前缀名称,clr-namespaceassembly这两个词应该不用再解释了吧,会编程的人都应该知道。需要特别说明的是:这么几个字,用TextBlockLabel现成的控件不就行了,何必要劳师动众那么夸张自己去写个控件来实现?对WPF/Silverlight中的中文字有一定了解的朋友都知道,在WPF/Silverlight中,文字都是矢量的,它在显示时被处理过(仿佛像是Photoshop中的文字锐利效果),因此显得模糊不清。例如假设我将本例的3个描述身份控件全用TextBlock来替换,那么效果将如下图:

    我们可以很清晰的看到,在位图中12像素的字是不会显示成这样的;但是在WPF/Silverlight中,它的效果看上去是带模糊。而我在QXControl:BorderText控件中添加了一个Stroke属性和一个StrokeThickness属性,它们分别用来设置文字的描边线颜色和描边线粗细。并且StrokeThicknessdouble型,这样我就可以以任意想要的粗细对文字描边进行设置了。在上文代码中,我将之设置为0.1,这样显示出来的效果如下图:

    虽然还无法达到最好的效果,但比起普通无描边的文字来说会美化些。由于文字只有12像素大小,在它上面描边无法很清晰的显示。因为,为了让大家更好理解WPF/SilverlightTextBlockQXControl:BorderText文字效果区别,我分别在这两个控件中输入“深蓝色”3个字,48像素,其中QXControl:BorderText以黑色1.5像素描边(该控件默认字体为“微软雅黑”),得到以下效果比较图:

左边为<TextBlock FontSize="48" FontFamily="微软雅黑" Text="深蓝色" Foreground="Pink" />创建的,

右边为<QXControl:BorderText FontSize="48" Stroke="Black" StrokeThickness="1.5" Text="深蓝色" Fill="Pink" />创建的,不用我说大家都会明白谁更幽雅漂亮了吧?更可贵的是,它提供了另一种WPF/Silverlight中关于中文字体模糊的解决方案。因此,在后面的游戏设计中,我将以QXControl:BorderText作为主要的文字控件使用。

    呼呼,到此终于将我们可爱的精灵控件界面xaml代码写完,剩下的就是在Behind代码中丰富精灵的内部了。在下一节中,我将就精灵控件后台代码及上一节中遗留的问题:在地图移动中,主角(精灵)与障碍物如何跟随移动进行讲解,敬请关注。

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