winston 发表于 2012-1-19 20:10:22

魔兽争霸自动地图元件的绘制原理

魔兽争霸自动地图元件的绘制原理序:本文主要介绍一种简单高效的自动地图元件的绘制方法,基本的原理是基于CodeProject的作者为Colin Vella的一篇文章:http://www.codeproject.com/KB/game/Autotiles_Algorithm.aspx#_comments 该文章介绍的方法非常简单,而且很高效。本文会先讲述此方法,然后在此方法的基础上,介绍魔兽争霸的自动地图元件的绘制原理,因为其实这2者的原理是一样的,但方法稍有不同。1.基本原理对于自动地图元件,我们可以这样理解,它实际上是一种地形分割器,例如岸边 -- 水和陆地的分割;墙壁 -- 室内和室外的分割。http://hi.csdn.net/attachment/201201/17/0_13267847546rNr.gif图1那么我们就可以用0和1分别来代表两种地形了,我们将一个tile分成4个角,每个角都可能是两种地形的其中一种(即可以是0,也可以是1)。这样我们用一个4位的数字b3b2b1b0表示一个tile,其中每一位表示一个角的地形,如下图http://hi.csdn.net/attachment/201201/17/0_1326784757xGgo.gif
图2这样4个角总共有16种情况,分别是以下16种,如下图,我们将蓝色部分想象成水,黄色部分想象成陆地,而两者间的黑线想象成岸边http://hi.csdn.net/attachment/201201/17/0_1326784760ypd7.gif
图3在实际绘制过程中,我们就是用这16种情况类拼接地图的。2.自动地图元件的规格上面图3就是此方法使用的地图元件的规格,注意此方法使用的自动地图元件的规则与RMXP的规格并不一样,在某种意义上说,RMXP的地图元件的精度要高一点,这点会在后续文章中给出分析。在图3中,我们故意将原件按其对应数字的大小来排序,也就是说0000排在第一,0001排在第二,1111排在最后。这样就可以很方便地根据tile的数值对应到其实际贴图了,用如下方法
view plaincopy



[*]int tileNumber = tileMap;
[*]Rect srcRect(tileNumber * tileWidth, 0, tileWidth, tileHeight);


3.绘制算法绘制的算法非常简单,反而是原文讲得比较绕口。如下图,我们打算在位置4绘制地图元件,此时我们只需将位置4以及它周围共16个小格填为1即可。如下图:http://hi.csdn.net/attachment/201201/17/0_13267847639mRK.gif
图4注意一点,我们只是将上图红色方框内的16个小格填为1而已,并不改动方框外的格的内容。例如左上角,我们假设其当前值是0110,那么改动后变成1110。算法要注意的地方是,在地图的边缘时,要考虑绘制位置的旁边是否有tile,例如在(0,0)位置绘制时,0,1,2,3,6格子都是不存在的。绘制的代码如下:r,c分别代表要绘制的行和列号,easyMap是二维数组,保存了所有tile。MAPROW和MAPCOL分别是地图的行数和列数。 view plaincopy



[*]// 将中心点周围的16个小格填为1
[*]
[*]if (r > 0)
[*]{
[*]    if (c > 0) easyMap |= 0x8;    // 1000
[*]    easyMap |= 0xC;   // 1100
[*]    if (c < MAPCOL - 1) easyMap |= 0x4;   // 0100
[*]}
[*]
[*]if (c > 0) easyMap |= 0xA;    // 1010
[*]easyMap |= 0xF;   // 1111
[*]if (c < MAPCOL - 1) easyMap |= 0x5;   // 0101
[*]
[*]if (r < MAPROW - 1)
[*]{
[*]    if (c > 0) easyMap |= 0x2;    // 0010
[*]    easyMap |= 0x3;   // 0011
[*]    if (c < MAPCOL - 1) easyMap |= 0x1;   // 0001
[*]}



消除的过程是绘制的反过程,也就是将填为1的16个小格填为0即可 view plaincopy



[*]// 将中心点周围的16个小格填为0
[*]
[*]if (r > 0)
[*]{
[*]    if (c > 0) easyMap &= ~0x8;   // 0111
[*]    easyMap &= ~0xC;// 0011
[*]    if (c < MAPCOL - 1) easyMap &= ~0x4;// 1011
[*]}
[*]
[*]if (c > 0) easyMap &= ~0xA;   // 0101
[*]easyMap &= ~0xF;// 0000
[*]if (c < MAPCOL - 1) easyMap &= ~0x5;   // 1010
[*]
[*]if (r < MAPROW - 1)
[*]{
[*]    if (c > 0) easyMap &= ~0x2;   // 1101
[*]    easyMap &= ~0x3;// 1100
[*]    if (c < MAPCOL - 1) easyMap &= ~0x1;   // 1110
[*]}


4.魔兽争霸的自动地图绘制如果你没用过魔兽争霸的地图编辑器,那么你可以在魔兽争霸的游戏目录下找到它,World Editor.exe打开它默认出现的就是编辑地形的模式,可以看到它的地形编辑与RMXP的不同是,它是以顶点来定位的,而不是RMXP的以tile来定位的。如下图http://hi.csdn.net/attachment/201201/17/0_1326784772q025.gif
图5要绘制出魔兽争霸的地图编辑器的效果,用上面的算法即可,不过需稍作修改。如下图,我们打算在中心顶点位置绘制地图元件,此时我们只需将该顶点附近4个小格填为1即可,也就是将下图红色方框内的小格填为1。http://hi.csdn.net/attachment/201201/17/0_1326784774aJmu.gif
图65.共性我们将魔兽争霸地图编辑器的绘制形状改为正方形,尺寸改为2,如下图http://hi.csdn.net/attachment/201201/17/0_1326784777o3bn.gif
图7这图是不是有点时曾相识呢,就是跟上述填16格的算法的区域基本一样。此时我们可以得知,此算法对绘制区域有一个隐性要求,就是绘制区域不能设定为刚好是整数个方格。试想一下,参考图4,如果在绘制时,我们仅将中心的4个小格填为1会出现什么情况?情况就是我们只能绘制出0000和1111两种地形了,魔兽争霸的地图编辑器也一样,你可以改一下绘制区域的尺寸,不管是什么尺寸,都不会出现上面所说的情况。6.实现具体的实现代码可以从下面地方下载,是用的HGE引擎编写的。如果你没用过,可以在这里下载HGE并学习:http://hge.relishgames.com/ 下面是程序的截图http://hi.csdn.net/attachment/201201/17/0_1326784766QY84.gif
代码下载地址:http://download.csdn.net/detail/gouki04/4025467 项目使用VS2008写的,打开后直接生成解决方案即可。里面包含2个项目,分别是上面所说的2种方法,生成成功后可直接运行,操作为鼠标左键绘制,右键清除。
页: [1]
查看完整版本: 魔兽争霸自动地图元件的绘制原理