【原创】《矩阵的史诗级玩法》连载四:45度地图砖块所蕴含的矩阵基础知识(上)

        写理论的东西,最容易被吐槽的,莫过于没有应用领域了。但很幸运地,我找到了很热门的应用领域,就是45度视角游戏的地图铺设。我在三维家讲完这节课以后,负责技术面试的小伙伴们就拿去当面试题来用了,然而竟招来一波吐槽。究其原因,是大部分所谓的45度地图并非真的按照砖块的方向进行裁剪,其网格形状仍然为正方形。因此铺贴和点击等操作的逻辑都变得非常简单,视角完全是美术的事情,程序根本不用关心。在如今这个浮躁的社会,解决问题的方法越简单,就越受到大家的追捧。至于能否学到东西,提升个人的技术水平,他们并不在乎,反正事情早点做完,能拿到工资就万事大吉。


        抛开45度游戏,我们公司的项目反倒有用到这篇文章里的知识,而且老总在大会上明确指出,前端要招够170人。所以大家可以放一万个心,我的矩阵系列教程在工作中绝对有用得上的地方。说用不上的,那只是你缘分未到而已。


        45度地图最原始的做法是对平面直角坐标系做一个叫“等角投影”的操作。这个概念我不打算给出解释,直接上图就是了。


        坐标轴从原来的水平和垂直变成了有一定角度的倾斜。而我们平时常用的坐标系都基于直角。为了计算出图上每个砖块在直角坐标系中的位置,我们需要把斜坐标转换到直角坐标上。反过来,假如要在这个地图上实现鼠标选取,那么,系统底层会给出直角坐标系下的鼠标位置,然后我们需要把这个直角坐标转换到斜坐标上,从而确定当前位置是选中了哪个砖块。

        

        说白了,要实现的无非是直角坐标和斜坐标的相互转换。方法有很多,但看我以前装逼的套路,相信大家都能猜出来,我用的是类似于椭圆拉伸或者矩形旋转的变换。

        


        从直角坐标转换到斜坐标,以及从斜坐标变换回直角坐标,它们之间为互逆关系。我们可以选取其中一种变换进行推导,那么,它的逆变换自然就能反推出来了。


        不知道大家更喜欢选取哪种,此处我们就用后者吧,喜欢前者的朋友可以自行类推。首先,45度地图砖块的宽高比(两对角线的长度比)为2:1(严格来说,2:1并不能得到45度,但这个比例方便美术人员进行尺寸的调整,所以业界一般都按照2:1进行设计)

        



        所以,45度地图砖块是一个菱形。它的4条边相等,但是4个角都不等于90度。这时候,如果横向压缩到原来的一半,或者纵向拉长到原来的两倍,那么它就变成一个正方形了。

        


        这是一个带了旋转的正方形,按照上一篇文章的做法,只要旋转45度,就可以完全转换成直角坐标系了。





        放到上面的7*7砖块地图上,这个转换的过程如下图所示。(这里放不了演示动画啊,纠结)


        第一步:缩放


        第二步:旋转

        

        

         这样的话,整个变换的过程就确定下来了,就是先横向压缩50%,然后负旋转45度。

          

         PS:数学老师喜欢用顺逆时针来指定旋转方向。然而受3D左右手坐标系等概念的影响,在不同的场合,y轴的方向可能向上也可能向下,这时候用顺逆时针就不好确定角度的正负了。所以CSDN博客上有位算法大神提出了正旋转这样一个术语。

        

        传送门:正旋转的定义


        现假设平面上有一点,其直角坐标为(x, y),其斜坐标为(x', y'),那么,根据上面的讨论,想要根据(x, y)推导出(x', y'),第一步就是缩放:

        

        

        

        而第二步则在第一步的基础上旋转-45度,旋转的计算方法在上一篇文章中已经说到,这里直接给出结果。

        

        

        为什么我还写x2,y2而不直接写x',y'呢?这是因为在这过程中,还有一个地方被遗漏了,就是两个坐标系的单位长度(1所表示的长度)不一样。


        前面提到,菱形砖块的对角线长度为2:1,因此可以假定下图中蓝线所示的矩形宽度为2,高度为1。


        



           现在我们开始进行上面的变换,第一步如下图所示。






            第二步是旋转,但是在这个过程中形状不再发生变化,并且蓝色网格和灰色网格都已经是正方形了。所以在这一步就可以确定长度的比例。蓝网格的边长为灰网格的根号2倍,所以旋转完之后,灰色网格需要缩放到原来的根号2倍,才能确保两坐标系的单位长度一致。


        



        总结一下,就是这样的过程


                  


        然后就是各种代入。


        


        这下总算推导完成了。


        



        以上的推导过程实现的是计算直角坐标系上的点在斜坐标系下的x,y值,它可以让您在鼠标移动或者屏幕触摸的时候算出当前触碰到的点具体在哪个砖块上。反过来,已知某砖块在斜坐标系下的x,y值,求出它在直角坐标系下的位置也同样重要,因为铺贴的时候就需要把这个转换结果给算出来。


         不过有了上面的推导经验之后,反过来就很简单了。直角转斜的步骤为:


        横向缩小50%->负旋转45度->等比缩放根号2倍


        反过来的步骤自然就是:


        等比缩放根号2/2倍->正旋转45度->横向拉伸2倍


        演算过程如下:


        


        虽然思路清晰,但是演算过程却繁琐的一逼。而且跟前面的转换仅仅是方向之差,但我们却要因为顺序和变换方向的不同而重新算一遍,如果变换稍复杂一点的话,那这样从0开始推导就感觉做了很多重复而无意义的体力劳动。


        是时候轮到矩阵登场了!有了它,一切都将简单起来。此刻我想起了一句名言:“把简单的事情变复杂很容易,把复杂的事情变简单则很困难”。由此可见,矩阵把很困难的事情给解决掉了,史诗级的称号当之无愧!


        哎呦,到现在都还没看到矩阵的影子呢!抱歉,我食言了,上篇文章就说这次开始讲矩阵,然而我还是太啰嗦了。估计已经有很多人看不下去。那我还是先让大家休息一下,下篇真的真的会开讲矩阵了,嘿嘿!

猜你喜欢

转载自blog.csdn.net/iloveas2014/article/details/79265735
今日推荐