首页 > 其他分享 >斜45度瓦片地图(Staggered Tiled Map)里的简单数学

斜45度瓦片地图(Staggered Tiled Map)里的简单数学

时间:2024-01-23 14:47:33浏览次数:27  
标签:Map Staggered 45 tileCoord 坐标 装饰物 平行四边形 Tiled

转载至:Shuai YUAN

斜45度瓦片地图(Staggered Tiled Map)里的简单数学

前段时间在做游戏的地图编辑功能,我们是在一个斜45度视角的场景上,对地图上的建筑或装饰物进行添加、移动、移除等基本操作,而且位置的改变是以网格作为最小操作单位的。本渣是用Staggered Tiled Map实现的,与垂直视角的Tiled Map不同,斜45度视角处理起来相对麻烦些,这次就聊聊其中一些跟数学相关的有趣问题。

何为Staggered Tiled Map?

不解释,有图有真相XD

‘Orthogonal Tiled Map’

‘Isometric Tiled Map’

‘Hexagonal Tiled Map’

‘Staggered Tiled Map’

判断区域相交

地图编辑的一个基础功能便是判断当前被编辑的建筑或装饰物的位置的合法性。这种合法性检查主要有两方面:一是不能放置在地图上被禁止编辑的区域(例如地图上的河流、山坡),这可以通过在Tiled Map上在相应区域做上标记,判断建筑所在的区域是否有该标记就可以了;二是不能与其他建筑或装饰物重叠,这便是这里主要要讨论的问题了。

在实际做位置判断时,我们并非按照每个建筑或装饰物的图片实际轮廓,而是把它们都对应到Tiled Map上一块以网格线为边的区域上——在斜45度视角下,这样的区域就是一个平行四边形。因此,建筑或装饰物是否重叠的问题便转化为在Tiled Map上的两个平行四边形是否相交的问题。再做进一步简化,我们发现这其实只需要判断任一平行四边形的四个顶点的瓦片(tile)是否落在另一个平行四边形内部就可以了。

看到这里,你也许已经发现:这不就是中学里简单的代数问题吗?判断点是否在平行四边形内,只需要知道平行四边形四条边所在直线的方程和点的坐标,便迎刃而解。没错,Tiled Map里每一块瓦片区域有自己的坐标,我们只需要把一块瓦片的坐标当做点的坐标,直线方程和点的坐标就有了。但斜45度角Staggered Tiled Map的有趣之处在于,即便把瓦片当做点,得到的并不是一个常见的平面直角坐标系。

下面我们还是通过图片来看看Staggered Tiled Map的坐标:

为了方便起见,我们把向下作为y轴正方向,我们可以发现上面的坐标(x, y)有着如下规律:

1
2
3
4
5
6
7
8
-- columnNum表示列数
-- columnNum = 1, 2, 3, ...
x = (columnNum - 1) % 2


-- rowNum表示行数
-- rowNum = 1, 2, 3, ...
y = rowNum - 1

看上去好像不复杂,但要列出直线方程呢?比如以下两种可作为平行四边形瓦片区域的边的直线:

一时半会懵逼了吧?使问题复杂的正是这些公式需要判断奇偶性,能不能把奇偶性判断拿掉呢?当然可以,做坐标转换就可以了,让我们先看一张直观的坐标转换结果图:

这相当于做了如下的坐标转换:

1
2
3
f[(x, y)] = (x * 2, y) if y mod 2 = 0

f[(x, y)] = (x * 2 + 1, y) if y mod 2 = 1

合并成一条公式也就是:

1
f[(x, y)] = (x * 2 + y mod 2, y)

现在是不是简单得多了?上面两条直线方程(因为这样的直线斜率是确定的,只需要知道直线上一点的坐标就可以确定直线方程)分别是:

1
2
3
4
-- linear equation of the row line containing the point of tileCoord
local function rowEquation(tileCoord)
    return tileCoord.x * 2 + tileCoord.y % 2 + tileCoord.y
end
1
2
3
4
-- linear equation of the column line containing the point of tileCoord
local function columnEquation(tileCoord)
    return tileCoord.x * 2 + tileCoord.y % 2 - tileCoord.y
end

这个时候你应该已经发现,我们可以用之前简单的代数问题解法来解决这一问题了:已知点的坐标tileCoord和一个区域region四个顶点的坐标(分别为region.topregion.bottomregion.leftregion.right,事实上只需要知道其中两个点就可以了),判断点是否在区域内,只需要做不等式判断即可:

1
2
3
4
5
local function containsTile(region, tileCoord)
    return (rowEquation(tileCoord) >= rowEquation(region.top))
    and (rowEquation(tileCoord) <= rowEquation(region.bottom))
    and (columnEquation(tileCoord) <= columnEquation(region.top))
    and (columnEquation(tileCoord) >= columnEquation(region.bottom))

你也许会问,为什么不直接定义一套方便计算的坐标系统?为何要用Staggered Tiled Map原有的坐标系统去做变换呢?这是因为前面所提到的做标记的非法编辑区域是采用原有的坐标系统的,采用同一套坐标系统加简单的坐标转换处理比起采用两套坐标系统,在实现上和维护上的成本更低。

遮挡关系

地图编辑的另一个基础需求是要处理好建筑及装饰物之间的遮挡关系。这个问题可以转化为建筑或装饰物的显示层级的排序。但是问题又来了,如何比较任意两个建筑或装饰物的显示先后顺序呢?特别是它们还有可能隔得很远,并没有显示上的重叠区域?

这个问题其实没有固定答案,本渣也只是根据我们系统的实际情况定了一套排序规则。在本渣的规则中,建筑或装饰物的显示层级只与它们对应的平行四边形区域有关。本渣用每一个的平行四边形左侧和右侧瓦片的坐标点得到一条直线,并把平行四边形对角线交点作为基准点。当比较两个建筑或装饰物的显示先后时,先判断二者平行四边形的宽度(两条相邻边的tile数量),短的求基准点,长的求直线。如果点在直线下方,则点所对应的建筑或装饰物在前方;反之则在后方。

当然,本渣这套规则实际能显示正确还有赖于美术大大们提供的建筑或装饰物图片资源的情况哈,如果建筑或装饰物的轮廓宽度超过它们的平行四边形区域,还是可能会出现显示奇怪的地方的。

标签:Map,Staggered,45,tileCoord,坐标,装饰物,平行四边形,Tiled
From: https://www.cnblogs.com/kt007/p/17982420

相关文章

  • PostMappering中consumes与produces属性的作用
     哈喽大家好今天跟大家简单聊一聊PostMappering中consumers与produces两个属性的作用在对接接口中,对方API要求,请求头HTTPHeader中设置Content-Type为application/x-www-form-urlencoded,响应头HTTPHeader中Content-Type为application/json。也就是说一个接口中,接收......
  • P4588 [TJOI2018] 数学计算
    题目描述小豆现在有一个数x,初始值为1。小豆有Q次操作,操作有两种类型:1m:将x变为×*m,并输出xmodM。2pos:将x变为x除以第pos次操作所乘的数(保证第pos次操作一定为类型1,对于每一个类型1的操作至多会被除一次),并输出xmodM。输入格式一共有t组输入。对于每一......
  • CMU15445 Concurrency Control
    LockManagerlock检查事务的隔离级别是否符合锁的要求REPEATABLE_READ:Thetransactionisrequiredtotakealllocks.AlllocksareallowedintheGROWINGstateNolocksareallowedintheSHRINKINGstateREAD_COMMITTED:Thetransactionisrequi......
  • STL-map/unordered_map映射
    STL-map/unordered_map映射目录STL-map/unordered_map映射1.构造初始化2.数据插入3.数据查找4.迭代器遍历5.删除和清空6.成员方法7.multimap8.unordered_map9.unordered_multimap10.底层原理11.总结12.参考资料键值对容器Map映射是一种类似于字典的数据结构。它是(键,值)对的序......
  • Elasticsearch-Mapping篇
    官方文档官网:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html映射是定义文档及其包含的字段如何存储和索引的过程。每个文档都是字段的集合,每个字段都有自己的数据类型。映射数据时,您创建一个映射定义,其中包含与文档相关的字段列表。映射定义......
  • Linux基础45 firewalld防火墙, 参数, 区域配置, 放行策略, 端口转发, 富规则, 防火墙
    firewalld防火墙一、防火墙安全概述在Centos7系统中继承了多款防火墙管理工具,默认启动的是firewalld(动态防火墙管理器)防火墙管理工具,Firewalld支持CLI(命令行)以及(图形)的两种管理方式。对于接触Linux较早的人员对Iptables比较熟悉,但由于Iptables的规则比较的麻烦,并且对网络有......
  • 使用Javamail接收imaps协议的邮件
    网上的消息不能说大多,只能说基本都过时了,连imap和imaps都不分了本文基于apache-james项目搭建的邮件服务器,其他邮件服务器仅供参考首先是依赖,这里需要引入两个依赖,如下<dependency><groupId>javax.mail</groupId><artifactId>javax.mail-api</artifactId>......
  • CF455D Serega and Fun 题解
    题目链接:CF或者洛谷本题是可以用平衡树去做的,具体的为每个\(k\)开一棵平衡树去维护相对位置,而这种移动操作用平衡树维护又是很容易做到的,这种做法是双\(log\)。在\(1e5\)的数据下,我们来说说好写的分块该如何去写。黑色的代表一个块,考虑暴力修改情况,假如原来的数字为\([1......
  • Maptalks内阴影实践
    背景    地图可视化项目中往往有要求进行内阴影的需求,但是对于可视化能力比较弱的giser来说,这个没有现成的方案,一般都会说进行ui切图然后进行贴图就行,但是这样对于动态生成的场景就不太满足,本文基于canvas进行动态绘制内阴影。原理    内阴影的原理主要是用的canvas的......
  • Go语言核心36讲 45 | 使用os包中的API (下)
    你好,我是郝林,今天我们继续分享使用os包中的API。我们在上一篇文章中。从“os.File类型都实现了哪些io包中的接口”这一问题出发,介绍了一系列的相关内容。今天我们继续围绕这一知识点进行扩展。知识扩展问题1:可应用于File值的操作模式都有哪些?针对File值的操作模式主要有只读......