• WFP制作游戏地图构建障碍物的方法改进


    上一段时间一直在阅读“深蓝色”的游戏制作教程,其中第十二讲提到了地图副本,即如下:(引自蓝色的博客)

        代码下载地址,https://files.cnblogs.com/wangweixznu/WpfGameStudy.rar  

    引自深蓝色的博客地址为:

    http://www.cnblogs.com/alamiye010/archive/2009/06/17/1505342.htmlhttp://www.cnblogs.com/alamiye010/archive/2009/06/17/1505342.html

    前面几节详细的讲解了游戏地图的完整构造,比较有难度的是关于地图内层如障碍物的实现。A*算法往往能让众多的初学者望而止步,斜度α地图则更需要一定的几何知识及抽象思维。很多朋友就问了:什么年代了,都在说面向对象、提高开发效率,难道就没有大众化可以让各层次能力的朋友们都能轻松制作地图引擎的方法吗?大家是否还记得上一节中遗留的一个小悬念,杀手涧就是它了:神奇的副本地图。

          大家先看上图,左边的是地图表现层,它的尺寸为800*600。右边的则是我通过Photoshop在原图基础上勾勒出来的该地图的副本,同样它的尺寸也为800*600。这里特别要提的是该副本是由简单纯色调组成的,因此能够压缩到极小的容量,几乎忽略不计,这是它能作为我们得力工具的前提,也是Silverlight制作基于网页游戏的必要条件。好了,接下来我们详细介绍一下此副本:大家对照原图很容易会发现它上面的黑色其实代表的就是地图中的障碍物,那大片的白色区域呢?其实就是我们可以任意通行的区域了。至于黄色,聪明的朋友应该也不难猜到,它代表的是地图中的传送点。当然,您还可以在此副本中增加例如红色代表陷阱,绿色代表特殊NPC等等。是否觉得像画画一样的?嘿嘿,这就是我主张的面向对象的游戏编程创新思想了。到此地图副本制作完成了,那么该如何利用它呢?

    具体详细内容讲解可以参考http://www.cnblogs.com/alamiye010/archive/2009/06/17/1505342.html

    但是感觉有一个问题就是对于一旦用到A*算法就要涉及用二维矩阵来构建地图的障碍物,然而大家都知道,一款游戏的地图是很复杂的,障碍物也很复杂,如果纯粹靠编程的方式来精确定位障碍物难免有些麻烦,必须在在图像处理工具上标出每个障碍物的具体位置,然后在一一构建障碍物矩阵,利用深蓝色这篇文章中的道理,我想了一个方法,如果我们在加载地图的时候就能够自动创建障碍物矩阵,岂不是更好,那才是真正面向对象编程,地图由你怎么换,你只要给我提供一副黑白图片即可以了,加载地图的时候会根据黑白地图即地图副本自动创建障碍物矩阵

    具体代码如下:页面代码

     

    <Window x:Class="WpfGameStudy.AStarMapDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="AStarMapDemo"  Width="650"  Height="650">
        <Canvas Name="canvas" Width="600"  Height="600" Background="Gray" MouseLeftButtonDown="canvas_MouseLeftButtonDown"></Canvas>

    </Window>

    对应后台代码:

      1using System;
      2using System.Collections.Generic;
      3using System.Linq;
      4using System.Text;
      5using System.Windows;
      6using System.Windows.Controls;
      7using System.Windows.Data;
      8using System.Windows.Documents;
      9using System.Windows.Input;
     10using System.Windows.Media;
     11using System.Windows.Media.Imaging;
     12using System.Windows.Shapes;
     13using System.Windows.Media.Animation;
     14using System.IO;
     15
     16using QX.Game.PathFinder;
     17namespace WpfGameStudy
     18{
     19    /// <summary>
     20    /// 演示A*和自动构建地图路径算法
     21    /// </summary>

     22    public partial class AStarMapDemo : Window
     23    
     24           Rectangle person; //模拟任务的方块
     25             byte[,] Matric = null;
     26            System.Drawing.Point stratPoint;//起始点坐标
     27            System.Drawing.Point endPoint;//终点坐标
     28            Image map = null;//地图
     29            ComboBox cboMap;//供选择的地图
     30            IPathFinder pathFinder;
     31            int gridSize = 20;
     32        public AStarMapDemo()
     33        {
     34           
     35            InitializeComponent();
     36            InitMap();
     37        }

     38        /// <summary>
     39        /// 初始化地图
     40        /// </summary>

     41        void InitMap()
     42        {
     43            //提供供用户选择的地图
     58            stratPoint = new System.Drawing.Point(11);//模拟人物起始点
     59
     60            Matric = PathGrid("CopyMap\\" + cboMap.SelectedItem.ToString(), gridSize);//生成障碍物路径
     61            map = new Image();
     62            map.Source = (ImageSource)(new CroppedBitmap(BitmapFrame.Create(new Uri("CopyMap\\" + cboMap.SelectedItem.ToString(), UriKind.Relative)), new Int32Rect(00600600)));
     63           
     64            map.Width = 600;
     65             map.Height = 600;
     66            Canvas.SetTop(map,0);
     67            Canvas.SetLeft(map, 0);
     68  
     69            canvas.Children.Add(map);
     70            //创建人物,用一个红色小方块表示
     71            person = new Rectangle();
     72            person.Width = gridSize;
     73            person.Height = gridSize;
     74            person.Fill = new SolidColorBrush(Colors.Red);
     75            canvas.Children.Add(person);
     76            Canvas.SetTop(person, stratPoint.X * gridSize);
     77            Canvas.SetLeft(person, stratPoint.Y * gridSize);
     78
     79         
     80          }

     81
     82        void cboMap_SelectionChanged(object sender, SelectionChangedEventArgs e)
     83        {
     84            Matric = PathGrid("CopyMap\\" + cboMap.SelectedItem.ToString(), gridSize);//生成障碍物路径
     85             map.Source = (ImageSource)(new CroppedBitmap(BitmapFrame.Create(new Uri("CopyMap\\" + cboMap.SelectedItem.ToString(), UriKind.Relative)), new Int32Rect(00600600)));
     86
     87             //测试地图是否跟图像一样,不需要删掉
     99        }

    100
    101        private void canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    102        {
    103            stratPoint = new System.Drawing.Point((int)Canvas.GetLeft(person) / gridSize, (int)Canvas.GetTop(person) / gridSize);//记录先当前新起始点
    104
    105            Point point = e.GetPosition(canvas);
    106            endPoint = new System.Drawing.Point((int)point.X / gridSize, (int)point.Y / gridSize);//记录当期终点
    107
    108            pathFinder = new PathFinder(Matric);
    109            pathFinder.SearchLimit = 200000;
    110            pathFinder.Formula = HeuristicFormula.Manhattan;
    111            pathFinder.HeavyDiagonals = true;//对角线移动
    112            List<PathFinderNode> path = pathFinder.FindPath(stratPoint, endPoint);
    113
    114            if (path == null)
    115                MessageBox.Show("没有路径通过");
    116            else
    117            {
    118                Point[] pathPoint = new Point[path.Count];
    119                for (int i = 0; i < path.Count; i++)
    120                {
    121                    pathPoint[i] = new Point((int)path[i].X * gridSize, (int)path[i].Y * gridSize);
    122                }

    123                Storyboard action = new Storyboard();
    124                int time = 100;
    125                //创建X轴上动画
    126                DoubleAnimationUsingKeyFrames animX = new DoubleAnimationUsingKeyFrames();
    127                animX.Duration = TimeSpan.FromMilliseconds(path.Count * 100);
    128                Storyboard.SetTarget(animX, person);
    129                Storyboard.SetTargetProperty(animX, new PropertyPath("(Canvas.Left)"));
    130                //创建Y轴上动画
    131                DoubleAnimationUsingKeyFrames animY = new DoubleAnimationUsingKeyFrames();
    132                animY.Duration = TimeSpan.FromMilliseconds(path.Count * 100);
    133                Storyboard.SetTarget(animY, person);
    134                Storyboard.SetTargetProperty(animY, new PropertyPath("(Canvas.Top)"));
    135                for (int i = 0; i < path.Count; i++)
    136                {
    137                    LinearDoubleKeyFrame keyFrame = new LinearDoubleKeyFrame();
    138                    keyFrame.Value = i == 0 ? Canvas.GetLeft(person) : pathPoint[i].X;
    139                    keyFrame.KeyTime = TimeSpan.FromMilliseconds(time * i);
    140                    animX.KeyFrames.Add(keyFrame);
    141
    142                    keyFrame = new LinearDoubleKeyFrame();
    143                    keyFrame.Value = i == 0 ? Canvas.GetTop(person) : pathPoint[i].Y;
    144                    keyFrame.KeyTime = TimeSpan.FromMilliseconds(time * i);
    145                    animY.KeyFrames.Add(keyFrame);
    146
    147                }

    148                action.Children.Add(animX);
    149                action.Children.Add(animY);
    150                //添加进资源
    151                if (!Resources.Contains("action"))
    152                {
    153                    Resources.Add("action", action);
    154                }

    155                action.Begin();
    156
    157            }

    158
    159        }

    160        /// <summary>
    161        /// 根据图片自动生成障碍物矩阵
    162        /// </summary>
    163        /// <param name="mapPaht">图片路径</param>
    164        /// <param name="gridSize">网格宽度</param>
    165        /// <returns></returns>

    166        private byte[,] PathGrid(string mapPaht, int gridSize)
    167        {
    168            BitmapSource map = new BitmapImage(new Uri(mapPaht, UriKind.Relative));
    169            int xLenght = (int)(map.PixelWidth / gridSize);//矩阵宽
    170            int yLength = (int)(map.PixelHeight / gridSize);//矩阵高
    171            byte[,] grid = new byte[xLenght, yLength];
    172            byte[] pixels = null;
    173            CroppedBitmap crop = null;
    174             for (int j = 0; j < xLenght; j++)
    175            {
    176                for (int i = 0; i < yLength; i++)
    177                {
    178                    Int32Rect rect = new Int32Rect(i * gridSize+gridSize/2, j * gridSize+gridSize/211);
    179                    crop = new CroppedBitmap(map as BitmapSource, rect);//取每个方块终点位置的颜色
    180                    pixels = new byte[4];
    181                    crop.CopyPixels(pixels, 40);
    182                    if (Colors.White == Color.FromArgb(pixels[3], pixels[2], pixels[1], pixels[0]))
    183                    {
    184                        grid[i, j] = 1;//为白色区域为可行路径否则为不可行路径
    185                    }

    186                    else
    187                        grid[i, j] = 0;
    188                 }

    189             }

    190             return grid;
    191         }

    192    }

    193}

    只是简单写了一下,细节上的大家可以自己完善,根据这个原来创建地图真实太Easy了,哈哈

    注:里面用的A*算法还是深蓝的,在此声明;感谢深蓝写了这么好的教程

  • 相关阅读:
    程序界真正的高帅富团体:Valve
    How Unreal Engine 4 Will Change The Next Games You Play【纯搬运】
    互联网“百年老店”是彻头彻尾的扯淡!
    如何关闭VS10中的IntelliSense
    发人深省周鸿祎:少功利多学习 做力所能及的事情
    FlashCS4 快捷键大全
    《1万小时成功定律——解构成功》
    通过AutoExpand调试Unreal内置数据类型
    14 Ways to Motivate Yourself
    关于C++ 动态定义数组
  • 原文地址:https://www.cnblogs.com/wangweixznu/p/1601519.html
Copyright © 2020-2023  润新知