欢迎光临散文网 会员登陆 & 注册

关于绘制障碍物边缘的处理

2023-07-31 20:12 作者:虹色的祝福  | 我要投稿

       

        --首先感恩鸣谢@小明童鞋提出的问题和美术资源,思考问题的过程很有趣。

        --其次感谢@寒冰童鞋还没做完的校对工作。

        设想一种情景,我们需要设计一些在有限方格内随机生成的障碍物策略,那么首先我们需要把地图网格化,比如长这样:

空白地块网格

        对于随机格子产生障碍物来说,这里有很多种策略,因为我们主要是讨论障碍物边缘的处理,这里就手动选定一些格子来代表产生的障碍物。

随便画的障碍物地块

        这样的障碍物看上去太单调啦,作为逻辑图导入程序处理肯定是没问题,但是我们希望他的美术效果要好一点,比如rimworld那样

Rimwold的边缘处理

        虽然是2D资源,但是加上这些边缘处理之后,整个墙体的感觉出来了,再辅以阴影光照之类的效果,可以做到欺骗玩家的眼睛了,相比于逻辑图来说,这样会极大加强玩家的体验感。但我们要怎么做才能让边缘处理真实合理呢?

        聪明的你可能已经想到了,把所有的预设方块都画出来,然后根据位置信息来选择使用具体哪一个方块,就像很多俯视角2D游戏正在做的那样

SRPG Studio中的绘制区域

        如果我们要做的是一个随机生成的地图,那么就需要将所有的预设情况罗列出来,那么问题就变成了我们需要多少种预设呢?

        要计算这个问题,不妨尝试一下穷举。首先是最基本的单独方块,他在表现上会是这样:

单区域块

        顺便我们引入逻辑图,这里用0和1来表示格子内的障碍物情况,0为空1则为实;而红色部分表示我们需要做处理的格子(实际上每格都需要处理,这里只是单元化方便后续遍历操作)。

逻辑图:空

        周围的8格分别会在不同的情况下,对中心格造成影响,从而影响其形状,下面会举例说明。比如观察这个逻辑图,他所产生的形状会是怎样的呢?

观察这个

        对于红色区域来说,他在表现上应当是这样:

是这样

        同理对于位于红色区域上面的“1”格来说,他也会受到相应的影响,从而在表现上为:

同理这样

        由于九宫格在四方向上的对称性,所以当“1”的位置改变到↑→↓←四个方向时,会产生四种变化。那么更深一步地考虑这个问题,当我们的逻辑图由现在的情况变化为下图的时候,相应的红色区域会发生变化吗?

会发生变化吗?

        我们直接把表现画出来:

画出来是这样

        可以看到,虽然在上方“1”的位置产生了Inner(内陷角)的图案,但红色区域并没有因此产生变化,也就是没有受到九宫格外部四个拐角的状态影响。那是否外部拐角本身便不会对红色区域产生影响呢?

        答案显然是否定的,我们简单对比两种情况就可以发现不同。

不同吧

        他们所产生的表现应当是这样的:

应该是这样啦

        可以看到,第二张图的部分依旧产生了Inner部分,而第一张图的对应部分为Fill(填充)模式。

--这里有个需要澄清说明的点,可以看到在笔者的实例图在边缘处理方面,实际美术视角看上去会比较低,Inner部分已经只体现在顶部pattern和几像素点的差别。因此在某些项目中,会简单粗糙地将其处理为一种情况,这里为了方便说明原理,还是从数学原理上将所有的可能性罗列出来。这也反映了,根据不同的实际项目需求,处理方式上也会有天差地别,但是需要了解原理,之后采取何种方式去适应就变得得心应手了。

        我们继续对边角的情况分析,将目光聚焦到某个拐角也就是这个2*2的区域,还是由于对称性的原因:

对称性

        这两种情况对于红色区域来说,其拐角状态并不会影响到红色区域的状态。那么我们便可以得出结论:

        --只有当与当前格子和对角格子均相邻的格子状态铺满时,对角格子的状态才会对当前格产生影响,且影响范围为2种--

        这句话可能看上去比较难理解,讲人话就是只有当蓝色部分的值都为1时,白色格子里的值才会对红色格子产生影响,且由于白色格子有两种取值方式,所以对应的红色格子会有两种状态。

这里的0对于红色部分有两种状态的影响

        当我们得出来这个基本原理之后,我们对于九宫格便会把它分成两种情况来考虑,蓝色区域只要变动则一定会对红色区域产生影响,白色区域只有在特定情况下才会产生影响。

分开考虑(分色)

我们要计算其所有种类的话,其实只要分步思考即可。

① 情况0:蓝色区域中没有“1”

        共计种类数:0C4 = 1

不知道怎么打公式,这里发一下组合数,后面不发了

② 情况1:蓝色区域中有且只有一个"1"

        共计种类数:1C4 = 4

再发一次

③ 情况2:蓝色区域中有且只有两个“1”

        注意,此种情况下,总数应为2C4 = 6种

        但其中包含了4种相邻情况和2种对角情况,示意图如下

<相邻情况>和<对角情况>

        在相邻情况下,对应的一个拐角状态会影响到红色区域的状态所以需要*2

        在对角情况下,拐角的状态并不会造成影响,所以不需要*2

        分别对应的情况数为:4种和2C4-4 = 2种

--这里稍微提一句这个4是怎么来的,因为看起来我们好像只是完成了一次穷举来把4种可能的情况列出,但实际上我们可以将蓝色区域看成一个圆环上的四个点,就像是手链上的四个珠子,由于数据的顺序读取,我们按照不同的顺序去读则种类为4--

        再将它们分别乘以拐角造成的影响值,分别为:

                4*2^1 = 8种

                (2C4-4)*2^0 = 2种

④ 情况3:蓝色区域中有且只有3个“1”

        共计种类数:3C4 = 4

        注意这种情况下,不论怎么组合,一定会有两个拐角影响程度,所以需要*2^2也就是*4

        那么共计种类数为:3C4*2^2 = 16种

⑤ 情况4:四个蓝色区域全部为“1”

        在这种情况下,红色区域仅会受到拐角状态的影响,所以需要*2^4也就是*16

        而蓝色区域情况为4C4 = 1

        所以共计为:4C4*2^4 = 16种


        至此,我们将所有的种类想加,得到总计数量为sum = 1+4+8+2+16+16 = 47种

        但实际上应该是48种啦,因为我们还要考虑如果红色区域本身没有值会怎样,那当然是一片空白啦。这与我们穷举出来的情况吻合:

穷举无语了

        本文写到这里,实际上你已经可以拿一套资源去unity里面练练手了,比如使用RuleTile功能将这些模块全绑上去。

绑TM的

        但实际上我会觉得这种做法非常的麻烦(其实主要是对于出美术资源的@小明同学来说非常的麻烦,我打不过他所以只能考虑下别的解决方案)

        我们仔细观察或者思考就会发现,其实在很多种变化里,红色区域的格子只有四个角的某个会发生变化,那我们何不将他们拆开来,然后分别赋予呢?

拆成小格子分别赋予

        比如对于此图来说,红色阴影区域的状态只会受到左上,上和左3个格子的状态影响,因此我们只需要统计到一个待处理区域的九宫格,原理上我们根据其周围的状态便可将四个小区域分别给出。这里需要用到一个sprite混合的方法,具体大家可以去看前人铺路的文章。

        比如这篇:https://blog.csdn.net/mkr67n/article/details/117030977

        我们的原理便是,基于一张逻辑图,将所有格子的信息记录下来,然后根据其周围信息来动态生成格子状态,我们只需要给其提供1*1的构成图即可,而构成图一共几种呢?13种!

13种欸,美术福报

        虽然我觉得网上应该也有相关的理论例子可以看,但并不妨碍我们给它起个炫酷的名字,不如就叫《炫酷的CBIF边缘处理方法吧》。

        哦对了,有生之年我应该会把Unity的sample整理好发上来,做成一个懒人工具的样式方便大家取用。

        能看到这里的都是真爱了吧,那无以为报留下一个思考题吧:

        上述内容都是基于四边形地块而言的,如果我们需要做3D或者是六边形格子地块的边缘处理呢?

关于绘制障碍物边缘的处理的评论 (共 条)

分享到微博请遵守国家法律