上一段时间一直在阅读“深蓝色”的游戏制作教程,其中第十二讲提到了地图副本,即如下:(引自蓝色的博客)
代码下载地址,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>
对应后台代码:
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Windows;
6
using System.Windows.Controls;
7
using System.Windows.Data;
8
using System.Windows.Documents;
9
using System.Windows.Input;
10
using System.Windows.Media;
11
using System.Windows.Media.Imaging;
12
using System.Windows.Shapes;
13
using System.Windows.Media.Animation;
14
using System.IO;
15![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
16
using QX.Game.PathFinder;
17
namespace WpfGameStudy
18![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
19![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
20
/// 演示A*和自动构建地图路径算法
21
/// </summary>
22
public partial class AStarMapDemo : Window
23![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
34
35
InitializeComponent();
36
InitMap();
37
}
38![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
39
/// 初始化地图
40
/// </summary>
41
void InitMap()
42![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
43![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
//提供供用户选择的地图#region//提供供用户选择的地图
44
cboMap = new ComboBox();
45
DirectoryInfo info = new DirectoryInfo("CopyMap\\");
46
FileInfo[] files = info.GetFiles("*.*");
47
for (int i = 0; i < files.Length; i++)
48![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
49
cboMap.Items.Add(files[i].Name);
50
}
51
cboMap.SelectedIndex = 0;
52
cboMap.SetValue(Canvas.ZIndexProperty, 100);
53
Canvas.SetLeft(cboMap,20);
54
Canvas.SetTop(cboMap,570);
55
canvas.Children.Add(cboMap);
56
cboMap.SelectionChanged += new SelectionChangedEventHandler(cboMap_SelectionChanged);
57
#endregion
58
stratPoint = new System.Drawing.Point(1, 1);//模拟人物起始点
59![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
79
80
}
81![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
82
void cboMap_SelectionChanged(object sender, SelectionChangedEventArgs e)
83![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
87![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
//测试地图是否跟图像一样,不需要删掉#region //测试地图是否跟图像一样,不需要删掉
88
string mapstr = "测试地图是否跟图像一样:"+System.Environment.NewLine;;
89
for (int i = 0; i < Matric.GetUpperBound(1); i++)
90![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
91
for (int j = 0; j < Matric.GetUpperBound(0); j++)
92![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
93
mapstr+= Matric[j, i] .ToString();
94
}
95
mapstr += System.Environment.NewLine;
96
}
97
MessageBox.Show(mapstr);
98
#endregion
99
}
100![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
101
private void canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
102![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
103
stratPoint = new System.Drawing.Point((int)Canvas.GetLeft(person) / gridSize, (int)Canvas.GetTop(person) / gridSize);//记录先当前新起始点
104![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
105
Point point = e.GetPosition(canvas);
106
endPoint = new System.Drawing.Point((int)point.X / gridSize, (int)point.Y / gridSize);//记录当期终点
107![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
114
if (path == null)
115
MessageBox.Show("没有路径通过");
116
else
117![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
118
Point[] pathPoint = new Point[path.Count];
119
for (int i = 0; i < path.Count; i++)
120![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
147
}
148
action.Children.Add(animX);
149
action.Children.Add(animY);
150
//添加进资源
151
if (!Resources.Contains("action"))
152![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
153
Resources.Add("action", action);
154
}
155
action.Begin();
156![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
157
}
158![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
159
}
160![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <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![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
176
for (int i = 0; i < yLength; i++)
177![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
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![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
184
grid[i, j] = 1;//为白色区域为可行路径否则为不可行路径
185
}
186
else
187
grid[i, j] = 0;
188
}
189
}
190
return grid;
191
}
192
}
193
}
只是简单写了一下,细节上的大家可以自己完善,根据这个原来创建地图真实太Easy了,哈哈
注:里面用的A*算法还是深蓝的,在此声明;感谢深蓝写了这么好的教程