引言
本文出自 “游戏古登堡计划”。
原文由 craft 翻译自 yellowafterlife 博客,简单的介绍了实现等轴网格的算法。
indienova 之前曾介绍过 Amit Patel 撰写的有关六角网格的实现教程,可以作为参考内容。
等轴网格
等轴网格相关的算法并非什么罕见的技巧。
实际上,考虑到其简单朴素的本质,这个问题的解决可能会比你们想象的还要更加普通。
为此,我特意撰写本文,来澄清下面两点问题:
- 将局部的等轴网格坐标转换为全局的屏幕空间坐标;
- 将全局的屏幕空间坐标转换为局部的等轴网格坐标。
等轴网格坐标到屏幕坐标
我们先来研究将屏幕坐标转换为等轴网格坐标的方法。
人们总是倾向于将这个问题过于复杂化。基本上,假如你仔细观察等轴坐标系:
当等轴网格坐标 X 增加时,屏幕坐标 X 和 Y 也会增加;当等轴网格坐标 Y 增加时,屏幕坐标 Y 会增加,但屏幕坐标 X 会随之减少。因此,可以总结成下组简单的公式:
GlobalX = IsoX + (LocalX - LocalY) * IsoW; GlobalY = IsoY + (LocalX + LocalY) * IsoH;
公式中的 IsoX
和 IsoY
为等轴网格坐标位于原点 (0, 0)
时的屏幕坐标,而 IsoW
与 IsoH
则决定网格的大小及倾斜度(标准 2:1 比例分别使用 2 和 1)。
屏幕坐标到等轴网格坐标
从屏幕坐标获取等轴网格坐标需要一点点不算太困难的技巧(你需要逆转之前用到的将等轴网格坐标转换为屏幕坐标的公式)。最终可以总结下面这组公式出来:
LocalX = ((GlobalY - IsoY) / IsoH + (GlobalX - IsoX) / IsoW) / 2; LocalY = ((GlobalY - IsoY) / IsoH - (GlobalX - IsoX) / IsoW) / 2;
小演示 demo
融会贯通上述知识点,已经足够我们做出下面这个小 demo 来实现简单的等轴网格系统(将等轴网格位置转换到屏幕坐标并绘制单元)和鼠标交互功能(需要将屏幕坐标转换为等轴网格坐标,再转换回来):
深度排序
另一个值得探讨的话题是:深度排序(亦即绘制顺序问题)。
比较直观的解决方案是基于他们的垂直方向坐标来决定绘制顺序。
但对等轴网格也能沿着一些比较奇怪的路径来绘制网格(沿着编号的线路),可能并不是你优先想要选择的方案。
但使用一组嵌套的 for 循环(其中一个用于遍历轴,顺序不重要)来绘制:
for (x = 0; x < 8; x += 1) { for (y = 0; y < 8; y += 1) { DrawIsoTile(x, y) } }
也能达成正确和期望的效果。
先绘制地板,再绘制其上的物品。如果有多个物品出现在同以网格的不同位置,则深度顺序依据垂直方向坐标来决定。
下载地址
注意下载需要科学上网!
- GameMaker 版: .GMZ · 网页 demo
也可以查看这个标准的demo (how to find) - JavaScript 版: gist · 网页 demo
祝玩得开心!
刚好需要这个,谢谢~
好文章,收藏,多谢!
多蟹
也可以这样理解: 从一个直角坐标系转换到这样的一个等轴坐标系是一个切变变换, 以这篇文章为例, 变换矩阵为
|√3/2 1/2|
|-√3/2 1/2|
相应的, 从等轴坐标系到直角坐标系为
|√3/3 -√3/3|
|1 1 | (M)
从屏幕坐标系得到等轴坐标系的位置可以这样计算: ((GlobalX - IsoX)/W, (GlobalY - IsoY)/W) * M
W是直角坐标系中格子的大小
干货文章总是那么浓缩
赞
想问一下GMZ中path路径没有用path_start是怎么做到小车沿路径运动的?一脸懵逼中
汗先入为主了,creator游戏开发左下角为(0,0),看“网格x增加,平面xy也增加”一时没反应过来。