上一段时间一直在阅读“深蓝色”的游戏制作教程,其中第十二讲提到了地图副本,即如下:(引自蓝色的博客)
代码下载地址,https://files.cnblogs.com/wangweixznu/WpfGameStudy.rar
具体详细内容讲解可以参考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>
对应后台代码:
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(1, 1);//模拟人物起始点
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(0, 0, 600, 600)));
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(0, 0, 600, 600)));
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/2, 1, 1);
179 crop = new CroppedBitmap(map as BitmapSource, rect);//取每个方块终点位置的颜色
180 pixels = new byte[4];
181 crop.CopyPixels(pixels, 4, 0);
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*算法还是深蓝的,在此声明;感谢深蓝写了这么好的教程