地图贴片自动拼接原理研究

1- RPG MAKER的自动砖块拼接

在目前比较流行的游戏制作工具RPG MAKER里面,做地图编辑的时候,有一种特殊的砖块,不需要手动拼接,而直接用鼠标绘制,就自动帮你拼好地块。
如下图所示


 

而这一切是使用下面这张图片来拼接而成的。RPG MAKER把它保存在RGSS/Standard/Graphics/Autotiles里面。



RPG MAKER本身砖块是使用32*32的规格来进行组合的,这张AUTOTILE资源,是3*4排列的32*32的图片。


经过观察发现,上面的图片是使用下面这个图片中的元素按照16*16的大小分割来拼接而成的。
为了验证这个想法,我做了下面这个图片,替换掉RPG MAKER原来这张图片。


再用RPG MAKER察看刚才的地图,变成了这样



从中可以看出,RPG MAKER果然是用16*16的小块来进行分割和拼接。



2- 实现方法

决定一个32*32的图块由哪4个16*16的小图块拼接的关键,是这个图块的周围的同类块的位置和数量。下面介绍一个拼接调色板的方法。

步骤1- 把图块周围的邻接块位置编号,如下图



图中标记了8个BIT,每个BIT表示这个位置上是否有同类块,有就是1,没有就是0。这样,我们就得到了一个0-255的索引。

步骤2- 建立图块拼接调色板

我们针对这个索引,建立一个256元素的表。
在这个256元素的表里面,把每个索引对应的目标块的样子描述一下。
描述一个目标块,需要4个16*16的小块。而表示这个小块,可以使用他们在AUTOTILE图片中的索引。

做完这一步,我们得到了256个4元组。

因为AUTOTILE的图片规格都是一样的,所以,这个调色板可以用在每一种自动拼接的砖块上。

这两个简单的步骤结束后,我们就能够正确的绘制每一个自动拼接的图块了。因为它索引的数据是拼接方法,所以叫它是拼接调色板。

 

1- 分析



通过对照观察,我们会发现,在这个自动拼接元素上,小元素可以分为以下几种:

   A-   向内转角(也就是0,1,6,7,以及12, 17, 42, 47,这里只取一组即可 )(FIXED:这里选择12,17,42,47这组,因为部分特殊元素这四个才是真实的向内转角)
   B-   向外转角(4,5,10,11)
   C-   上下连接(24,29,30,35)
   D-   左右连接(14,15,44,45)
   E-   填充物(26,27,32,33)

通过观察组合图块,我们会发现下面的几条规律


   A- 斜方向的同类块对目标块的影响当且仅当斜方向相邻的两个垂直方向上都有同类块的时候才会出现。也就是将目标块的对应小图块变成填充物。

   B- 当两个相邻的垂直方向上都有同类块,且他们之间的斜方向上没有同类块的时候,目标快对应的小图块变成向外转角

   C- 当某个垂直方向上有同类块,且相邻的一个垂直方向上没有同类块,无论相邻的斜方向上有没有同类块,目标块对应的小图块变成连接(向上下或者向左右连接)

   D- 当某个垂直方向上没有同类块,且相邻的垂直方向上也没有同类块,无论相邻的斜方向上有没有同类块,目标块对应的小图块变成向内转角



2- 生成算法(C#代码)


  1              //   填充物    26 27 32 33
  2              //   向外转角  4 5 10 11
  3              //   上下连接  24 29 30 35
  4              //   左右连接   14 15 44 45
  5              //   向内转角    12 17 42 47
  6  
  7              //   各方向比特   1 2 4 8 16 32 64 128
  8  
  9              //   4 个小图块对应的索引
 10              //   0 1         小图块在大图块里
 11              //  2 3         按照这种顺序排列
 12              byte[] mTile = new byte[4 ];
 13              //  调色板数组,每个元素是一个包含4个索引的DWORD
 14              UInt32[] mAutoTilePal = new UInt32[256 ];
 15  
 16              for (uint nIndex = 0; nIndex < 256; nIndex++ )
 17               {
 18                  //  初始化成向内转角
 19                  mTile[0= 12 ;
 20                  mTile[1= 17 ;
 21                  mTile[2= 42 ;
 22                  mTile[3= 47 ;
 23                  //  如果上方有同类块
 24                  if ((nIndex & 2> 0 )
 25                   {
 26                      //  如果左方有同类块
 27                      if ((nIndex & 128> 0 )
 28                       {
 29                          //  如果左上方有同类块
 30                          if ((nIndex & 1> 0 )
 31                           {
 32                              //  目标块左上为填充物
 33                              mTile[0= 26 ;
 34                           }
 35                          else
 36                           {
 37                              //  目标块左上为向外转角
 38                              mTile[0= 4 ;
 39                           }
 40                       }
 41                      else
 42                       {
 43                          //  目标块左上为向上连接
 44                          mTile[0= 24 ;
 45                       }
 46  
 47                      //  如果右方有同类块
 48                      if ((nIndex & 8> 0 )
 49                       {
 50                          //  如果右上方有同类块
 51                          if ((nIndex & 4> 0 )
 52                           {
 53                              //  目标块右上为填充物
 54                              mTile[1= 27 ;
 55                           }
 56                          else
 57                           {
 58                              //  目标块右上为向外转角
 59                              mTile[1= 5 ;
 60                           }
 61                       }
 62                      else
 63                       {
 64                          //  目标块右上为向上连接
 65                          mTile[1= 29 ;
 66                       }
 67                   }
 68                  else
 69                   {
 70                      //  如果左方有同类块
 71                      if ((nIndex & 128> 0 )
 72                       {
 73                          //  目标左上为向左连接
 74                          mTile[0= 14 ;
 75                       }
 76                      //  如果右方有同类块
 77                      if ((nIndex & 8> 0 )
 78                       {
 79                          //  目标右上为向右连接
 80                          mTile[1= 15 ;
 81                       }
 82                   }
 83  
 84                  //  如果下方有同类块
 85                  if ((nIndex & 32> 0 )
 86                   {
 87                      //  如果左方有同类块
 88                      if ((nIndex & 128> 0 )
 89                       {
 90                          //  如果左下方有同类块
 91                          if ((nIndex & 64> 0 )
 92                           {
 93                              //  目标块左下为填充物
 94                              mTile[2= 32 ;
 95                           }
 96                          else
 97                           {
 98                              //  目标块左下为向外转角
 99                              mTile[2= 10 ;
100                           }
101                       }
102                      else
103                       {
104                          //  目标块左下为向下连接
105                          mTile[2= 30 ;
106                       }
107  
108                      //  如果右方有同类块
109                      if ((nIndex & 8> 0 )
110                       {
111                          //  如果右下方有同类块
112                          if ((nIndex & 16> 0 )
113                           {
114                              //  目标块右下为填充物
115                              mTile[3= 33 ;
116                           }
117                          else
118                           {
119                              //  目标块右下为向外转角
120                              mTile[3= 11 ;
121                           }
122                       }
123                      else
124                       {
125                          //  目标块右下为向下连接
126                          mTile[3= 35 ;
127                       }
128                   }
129                  else
130                   {
131                      //  如果左方有同类块
132                      if ((nIndex & 128> 0 )
133                       {
134                          //  目标块左下为向左连接
135                          mTile[2= 44 ;
136                       }
137                      //  如果右方有同类块
138                      if ((nIndex & 8> 0 )
139                       {
140                          //  目标块右下为向右连接
141                          mTile[3= 45 ;
142                       }
143                   }
144  
145                  mAutoTilePal[nIndex] = (UInt32)mTile[0 ];
146                  mAutoTilePal[nIndex] |= ((UInt32)mTile[1]) << 8 ;
147                  mAutoTilePal[nIndex] |= ((UInt32)mTile[2]) << 16 ;
148                  mAutoTilePal[nIndex] |= ((UInt32)mTile[3]) << 24 ;
149              }

 

================================================================================================== 电子地图一把抓V1.0 Google Earth非完美版及无损压缩版 解决了电子地图一把抓原版的下列问题: ● 抓Google Earth卫图时导致地球旋转,无法正确抓图的问题 ● 抓非卫图地图时,在道路边界及文字附近出现噪点问题。去除噪点后,可以制作出更清晰、也更小的最终文件 GE非完美版的非完美性表现在: 抓Google Earth带KML/KMZ地标显示的卫图时,在某次自动移动地球时,若GE抓手下方恰好有图标,在目前最新的 GE V4.3beta版中测试的结果看,抓手会“滑”一小段,导致错位。 但实测无图标显示的KML/KMZ或关闭其图标,显示道路及面状物时,未测出问题(未进行大量测试)。因此电子地 图一把抓GE非完美版可以制作GE卫图底图+不带图标的KML/KMZ的地图。有图标时,需仔细检查,有问题可稍微改 变一下起点位置或抓图区域大小重抓试验。 可执行文件说明: MapCap.exe 原版本 MapCap_LZW.exe 24位模拟式下将TIF文件从有损JPEG压缩改为无损LZW压缩,解决图像出现噪点的问题。 推荐用于抓取非卫图的地图MapCap_GE.exe 用于Google Earth,非完美(屏幕上图标较密集时有可能导致错位)。存储的结果TIF 文件24位模式下与原版一样,采用有损JPEG压缩。 MapCap_GE_LZW.exe 同MapCap_GE.exe,但24位模拟式下采用无损LZW压缩。 推荐用于抓取Google Earth卫图,特别是带KML显示时,但有图标显示时需仔细检查结果 是否有错位的现象。 注:电子地图一把抓的所有权利完全归原作者Kenchang所有。感谢Kenchang编写这么实用又有生命力的软件。 2009.1.2 ================================================================================================== kenchang对原版的说明: 1、软硬件要求 2、安装卸载说明 3、已知问题 4、版权声明 1、软硬件要求 可运行在Windows98/ME/2000/XP之上,CPU为奔腾133以上,内存32M以上。抓取大图时会需要大量内存, 建议内存为512M以上。 2、安装卸载说明 本软件为绿色软件,将所有文件复制到同一目录中,运行mapcap.exe即可。删除时将该目录下的所有文件删除。 3、已知问题 本软件未经广泛测试,谬误在所难免 4、版权声明 本软件为免费软件,不提供任何形式的技术支持。本软件仅供学习交流用途, 不得用于任何形式的商业目的或其他非法目的,在抓图之前应先取得原版权所有者的同意, 使用本软件造成的任何后果均与本软件作者无关。 kenchang
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值