2D地图tile纹理自动拼接算法

2D地图tile纹理自动拼接算法

前言

如果你玩过RPGMaker MZ之类关卡编辑器的,可能对地图纹理的自动拼接印象比较深刻。本文将详细介绍如何实现此类基于tile的地图纹理自动拼接功能。

基本算法

该算法在网上已经有比较详细的介绍,这里再大概讲一下。该算法认为一个块由四个象限组成,每一个块标志着有或者无。我们将对象限做如下编号:
在这里插入图片描述

图1

这样,可以用四个位来对应每个象限做索引,1表示有,0表示没有,共有2^4=16种组合,如下:
在这里插入图片描述

图2

(因为网上的图在画边的时候不严谨,容易导致二义性,所以这里重新画了一张。)
这样排列有个好处,我们完全可以扫描块的每个象限(子块),然后用位或来计算得到图2中对应的索引号,代码大约如下:

//以上16个块的id号
block_id=0;
//i是terrain中单元的行号,j是列号
//terrain[i][j]的取值假设只有0或者1
block_id|=terrain.at(i,j)<<0;		//第0象限
block_id|=terrain.at(i,j+1)<<1;		//第1象限
block_id|=terrain.at(i+1,j)<<2;		//第2象限
block_id|=terrain.at(i+1,j+1)<<3;	//第3象限
算法1

这样通过当前块及相邻的三个块就可以计算得到图2中对应的id了。

RPGMaker MZ中的转换

用过RPGMaker MZ的小伙伴可能看过它的tilesets里的图像,差不多像这个样子:
在这里插入图片描述

图3

根据网上文章的描述,左上角那块是不用于绘制地图的,但是这样带来一个问题,无法平滑的绘制全都没有时的地面。所以这里魔改一下,把这块用起来,就成了这样:
在这里插入图片描述
图4

第一次看到这张图时,在网上查找了许多文章,仅仅只知道绘制时被分成了4x6的子块,但是子块id的计算网上并没有太好的方式,差不多相当于硬算。后来想到,既然RPG Maker MZ地图的绘制结果与图2那种方式的结果一样,那能不能将图4的子块映射到图2那种样子呢?经过一通折腾,终于发现真相了,先把图4划分成这样,并对横纵坐标编号:
在这里插入图片描述
图5

接下来举个例子看看如何通过上面的子块合成图2中的子块。例如,我们要合成图2的子块1(子块从0开始编号):

  1. 以图5中的子块{0,0},{1,0},{0,1},{1,1}为模板,用子块{3,5}替换掉{0,0},就得下图了:
    在这里插入图片描述
    图6

    怎么样,这四个子块合起来就是图2中的块1,也就是说:
    [{3,5},{1,0},{0,1},{1,1}]=1
    这样,我们就建立了图5到图2的映射。针对图2中的其他每个块,同样可以用图5中的4个子块去映射,以下是完整映射:
			{{0,0},{1,0},{0,1},{1,1}},//0
			{{3,5},{1,0},{0,1},{1,1}},//1
			{{0,0},{0,5},{0,1},{1,1}},//2
			{{1,5},{2,5},{0,1},{1,1}},//3
			{{0,0},{1,0},{3,2},{1,1}},//4
			{{3,3},{1,0},{3,4},{1,1}},//5
			{{0,0},{0,5},{3,2},{1,1}},//6
			{{3,1},{2,5},{3,4},{1,1}},//7
			{{0,0},{1,0},{0,1},{0,2}},//8
			{{3,5},{1,0},{0,1},{0,2}},//9
			{{0,0},{0,3},{0,1},{0,4}},//10
			{{1,5},{2,1},{0,1},{0,4}},//11
			{{0,0},{1,0},{1,2},{2,2}},//12
			{{3,3},{1,0},{3,0},{2,2}},//13
			{{0,0},{0,3},{1,2},{2,0}},//14
			{{1,3},{2,3},{1,4},{2,4}},//15
算法2

这样,我们就可以像图2一样轻松的绘制自动拼接的地图了,只不过图2只绘制一个子块,而图5绘制4个子块。以下是效果图:
在这里插入图片描述

图7

这个可能不太明显,我们使用这篇博客的素材来绘制
https://blog.csdn.net/u013412391/article/details/105021909
在这里插入图片描述
图8

结果如下:
在这里插入图片描述

图9

结果与那篇博客的一致,证明我们算法没有问题。
这样,我们就完成了从算法2到算法1的映射。

扩展

其实我们仔细观查图5后会发现,基本的子块只有这6个块:
在这里插入图片描述

图10

其他子块都可以通过这6个子块经过旋转来得到,每个块只要保证边界不变,中间的地方可以通过适当修改来得到可以用于拼接的等效子块。这样地图上显示的拼接画面就不至于出现明显重复的情况。
一点讨论:图2中的块共16个,每个块又有4个子块,这样共有64个子块,而这刚好是2^6次方。可以用6位二进制来指定,这是否意味着比算法1多出来的两个二进制位代表了某些信息,比如旋转方向(四个方向刚好两个二进制位)?

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值