等轴网格的简单实现

作者:gutenberg
2016-08-22
9 32 6

引言

本文出自 “游戏古登堡计划”。

原文由 craft 翻译自 yellowafterlife 博客,简单的介绍了实现等轴网格的算法。

indienova 之前曾介绍过 Amit Patel 撰写的有关六角网格的实现教程,可以作为参考内容。

等轴网格

iso-demo

GIF 动图演示,可交互的 demo 见后文

等轴网格相关的算法并非什么罕见的技巧。
实际上,考虑到其简单朴素的本质,这个问题的解决可能会比你们想象的还要更加普通。

为此,我特意撰写本文,来澄清下面两点问题:

  1. 将局部的等轴网格坐标转换为全局的屏幕空间坐标;
  2. 将全局的屏幕空间坐标转换为局部的等轴网格坐标。

等轴网格坐标到屏幕坐标

我们先来研究将屏幕坐标转换为等轴网格坐标的方法。

人们总是倾向于将这个问题过于复杂化。基本上,假如你仔细观察等轴坐标系:

iso

当等轴网格坐标 X 增加时,屏幕坐标 X 和 Y 也会增加;当等轴网格坐标 Y 增加时,屏幕坐标 Y 会增加,但屏幕坐标 X 会随之减少。因此,可以总结成下组简单的公式:

  GlobalX = IsoX + (LocalX - LocalY) * IsoW;
  GlobalY = IsoY + (LocalX + LocalY) * IsoH;

公式中的 IsoXIsoY 为等轴网格坐标位于原点 (0, 0) 时的屏幕坐标,而 IsoWIsoH 则决定网格的大小及倾斜度(标准 2:1 比例分别使用 2 和 1)。

屏幕坐标到等轴网格坐标

从屏幕坐标获取等轴网格坐标需要一点点不算太困难的技巧(你需要逆转之前用到的将等轴网格坐标转换为屏幕坐标的公式)。最终可以总结下面这组公式出来:

  LocalX = ((GlobalY - IsoY) / IsoH + (GlobalX - IsoX) / IsoW) / 2;
  LocalY = ((GlobalY - IsoY) / IsoH - (GlobalX - IsoX) / IsoW) / 2;

小演示 demo

融会贯通上述知识点,已经足够我们做出下面这个小 demo 来实现简单的等轴网格系统(将等轴网格位置转换到屏幕坐标并绘制单元)和鼠标交互功能(需要将屏幕坐标转换为等轴网格坐标,再转换回来):


不支持 canvas 的浏览器多无趣呀。

鼠标悬停交互

深度排序

另一个值得探讨的话题是:深度排序(亦即绘制顺序问题)。

比较直观的解决方案是基于他们的垂直方向坐标来决定绘制顺序。

但对等轴网格也能沿着一些比较奇怪的路径来绘制网格(沿着编号的线路),可能并不是你优先想要选择的方案。

但使用一组嵌套的 for 循环(其中一个用于遍历轴,顺序不重要)来绘制:

for (x = 0; x < 8; x += 1) {
    for (y = 0; y < 8; y += 1) {
        DrawIsoTile(x, y)
    }
}

也能达成正确和期望的效果。


不支持 canvas 的浏览器多无趣呀。

鼠标悬停交互

先绘制地板,再绘制其上的物品。如果有多个物品出现在同以网格的不同位置,则深度顺序依据垂直方向坐标来决定。

下载地址

注意下载需要科学上网!

祝玩得开心!

近期点赞的会员

 分享这篇文章

您可能还会对这些文章感兴趣

参与此文章的讨论

  1. UMKing 2016-08-22

    刚好需要这个,谢谢~

  2. ChristianTam 2016-08-22

    好文章,收藏,多谢!

  3. ginger 2016-08-23

    多蟹

  4. ylsywkd 2016-08-23

    也可以这样理解: 从一个直角坐标系转换到这样的一个等轴坐标系是一个切变变换, 以这篇文章为例, 变换矩阵为
    |√3/2 1/2|
    |-√3/2 1/2|
    相应的, 从等轴坐标系到直角坐标系为
    |√3/3 -√3/3|
    |1 1 | (M)
    从屏幕坐标系得到等轴坐标系的位置可以这样计算: ((GlobalX - IsoX)/W, (GlobalY - IsoY)/W) * M
    W是直角坐标系中格子的大小

  5. Oncle 2016-08-23

    干货文章总是那么浓缩

  6. rekcul 2016-08-23

您需要登录或者注册后才能发表评论

登录/注册