三、新增功能:

1)新增游戏的音乐及音效对象:

public static MediaElement gameMusic, gameAudio;

2)新增游戏鼠标光标:

//设置游戏鼠标光标

GameCursor.Stretch = Stretch.Fill;

GameCursor.Source = Super.GetImage("/Image/Cursor/0.png");

在鼠标移动事件中根据命中测试进行时时的鼠标光标图片位置更新:

//鼠标移动(悬停)事件

private void Game_MouseMove(object sender, MouseEventArgs e) {

……

Point p = e.GetPosition(Root);

GameCursor.SetValue(Canvas.LeftProperty, p.X); GameCursor.SetValue(Canvas.TopProperty, p.Y);

……

}

此方法实现了鼠标图片跟随光标移动,但是很明显的影响了程序整体性能(CPU消耗会明显增加),如果哪位朋友能提供更好的解决方案,望留言给我。

3)新增点击水滴:

当鼠标在屏幕上左键点击时,只要不点到对象物体上,则在该位置显示出光标水滴,并播放它自身的动画。目前我的Silverlight游戏引擎中只用一个光标水滴:

QXDecoration hitCursor;

/// <summary>

/// 加载光标点击水滴

/// </summary>

private void LoadHitCursor() {

        hitCursor = new QXDecoration() {

           Code = 1,

           EndFrame = 9,

           CenterX = 32,

           CenterY = 32,

         };

         hitCursor.Visibility = Visibility.Collapsed;

         Add(hitCursor);

}

//鼠标左键事件

private void Game_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {

……

        //出现光标水滴

        hitCursor.Visibility = Visibility.Visible;

        hitCursor.FrameCounter = 0;

        hitCursor.Timer.Start();

        hitCursor.Coordinate = p;

……

}

 

如果您想最求更漂亮的点击效果,那么只需每次鼠标左键点击时创建新的水滴即可:

private void Game_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) {

……

//出现光标水滴

QXDecoration hitCursor = new QXDecoration() {

      Code = 1,

      EndFrame = 9,

      CenterX = 32,

      CenterY = 32,

};

Add(hitCursor);

hitCursor.Coordinate = p;

}

四、360度极光类型魔法的制作及使用方法

大家在看Demo演示时,是否会对那个极光魔法充满兴趣与好奇。它不仅仅是动画的,而且可以360度随意旋转,且伤害范围为一个不规则矩形区域,而这所有的一切的原始素材仅为我制作的一张图片而已,下面我将为大家演示它的整个制作流程。

首先我们画出该魔法向X轴正向的图片:

神奇的动画效果就要出现啦,接下来每隔5个色相保存一张图片:

最后保存出8张图片,并按顺序定义好名字:

    素材准备工作完成,下面是逻辑上的实现。该极光魔法同样通过QXMagic来创建实例,当点击鼠标右键时,我们首先获取鼠标右键点击点的坐标,然后根据方法将之延长到攻击距离。再根据公式计算出直角坐标系下实际应该旋转的角度Angle

/// <summary>

/// 根据两点商值计算角度

/// </summary>

/// <param name="y">y2-y1</param>

/// <param name="x">x2-x1</param>

/// <returns>直角坐标系角度</returns>

    public static double GetAngle(double y, double x) {

           return Math.Atan2(y, x) / Math.PI * 180;

}

然后还需要对极光魔法对象进行旋转处理:

magic.RenderTransform = new RotateTransform() {

       CenterX = 0,

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

       Angle = magic.Angle

}

其中CenterY将该魔法发射点及旋转中心定位到施法者中心,即手的部位;施法时以该中心为旋转轴进行旋转。这里还有个小技巧,即在制作激光魔法图片时,我特意在激光头部与图片左边边缘留下一段距离,这样做可以不需要额外的代码即可以实现从手的前端发射出魔法处进行旋转,而不是从身体中心进行旋转发射:

接着确定伤害区域,该区域为一个时时的不规则矩形区域。处理时我将360二维空间划分为斜4象限,即45度到135度和-135度到-45度这两个象限为一个伤害区域、其他角度为另外的伤害区域,那么最后得到的公式如下:

        /// <summary>

        /// 根据45度斜四象限获取矩形四个顶点(直线穿梭魔法用)

        /// </summary>

        /// <param name="angle">旋转角度</param>

        /// <param name="start">矩形中线起点</param>

        /// <param name="end">矩形中线终点</param>

        /// <param name="radius">矩形中线与边距离</param>

        /// <returns>四个顶点</returns>

        public static Point[] GetRectRange(double angle, Point start, Point end, int radius) {

            if ((angle >= 45 && angle <= 135) || (angle >= -135 && angle <= -45)) {

                return new Point[]{

                    new Point(start.X - radius, start.Y),

                    new Point(start.X + radius, start.Y),

                    new Point(end.X + radius, end.Y),

                    new Point(end.X - radius, end.Y),

                };

            } else {

                return new Point[]{

                    new Point(start.X, start.Y - radius),

                    new Point(start.X, start.Y + radius),

                    new Point(end.X, end.Y + radius),

                    new Point(end.X, end.Y - radius),

                };

            }

        }

这样做公式简单,省掉了对每个顶点的获取及旋转变换。

最后通过判断所有在屏幕中的敌对精灵坐标是否处于该矩形区域内进行伤害处理:

        /// <summary>

        /// 判断点是否在多边形内(射线法)

        /// </summary>

        /// <param name="target">目标点</param>

        /// <param name="range">多边形各顶点</param>

        /// <returns></returns>

        public static bool InPolygon(Point target, Point[] range) {

            int n = 0, count = 0;

            for (int i = 0; i < range.Length; i++) {

                n = (i == range.Length - 1) ? 0 : n + 1;

                if ((range[i].Y != range[n].Y) && (((target.Y >= range[i].Y) && (target.Y < range[n].Y)) || ((target.Y >= range[n].Y) && (target.Y < range[i].Y))) && (target.X < (range[n].X - range[i].X) * (target.Y - range[i].Y) / (range[n].Y - range[i].Y) + range[i].X)) {

                    count++;

                }

            }

            return (count % 2 > 0) ? true : false;

        }

    用了两节的时间进行了本教程示例游戏从WPFSilverlight平台的移植的关键点讲解,当然细节的优化还有非常多,源码发布后大家应该都能理解,因此这里也不累述了。后面的教程均将在此Silverlight引擎的基础上进行全新演义,下一节首先讲解的是如何制作游戏中的小地图,敬请关注。

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