斜角地图逻辑原理解析和Isometric地图编辑器设计方案

本文主要是介绍斜角地图逻辑原理解析和Isometric地图编辑器设计方案,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

当我要做的一款游戏,而无法即时地查看地图各图形元件的拼接效果,而导致不得不中止时,当时找过不少公开的地图编辑器,希望能拿来即用,但不是因为拼接效果不满意,就是因为生成的文件不是太满意。无奈之下决心自己动手写一个工具时,才知道有多少困难。

论坛里的相关帖子,基本上都试着各种关键词看了一遍,说实在的,感觉上,除了几个原来做过斜角地图编辑的,其余帖子里基本上是迷茫的
感觉坛子里像wangqiang99x,闪刀浪子,恋水泥人,wxsr等几位应该还是比较熟悉的,但看了一下他们的帖子,还是感觉有些不够,直到看过杜宇欣的文章,才算解决了斜角地图中的各个障碍

在前一篇斜角地图原理解释及斜角图形绘制实例细述已经对斜角地图的原理进行了细致的阐述。这里就不再重复了,只从斜角地图的逻辑原理方面进行解析。

关于地图中的图形元件的拼接原理,请参考这篇文章闪刀浪子的地图编辑器对应的地图解析类及教程的前半部分,或者只看这个图

因为所有的图片都是矩形的,所以拼接时必然要有所叠加,这就是图片的遮挡。

而要处理图片的遮挡关系,才能使所有这些图片构成的地图所呈现的画面显示出立体效果。
而这种遮挡关系就是地图景深的处理,那么景深的处理都会涉及哪些关键点呢,下面请一个个来看。

1、图片之间的遮挡,这是景深呈现的关键

2、图形元件所代表的意义,即处于某个位置的图形元件是山水建筑物,还是路面等,以标识游戏当中的角色是可以通行还是受阻碍的

3、图形元件是否允许与用户的交互,即一个图形元件放到地图上,如果就是代表一棵树,一片小山,而这些又仅仅是表征地图地形的一个障碍物,那么则不会影响用户的键盘鼠标消息

4、如何通过鼠标当前位置(或角色当前位置),来了解所处的是哪里(什么地形,会不会产生事件等)

5、如何通过网格中某个单元格的纵列位置,来获得屏幕坐标。比如角色在某一个位置,而房子在另一个位置,现在角色要走到房子里,这就要获取某个建筑物所在的坐标,以使角色行走到目标位置

6、碰撞处理和寻路等,如果是地国中有运动的角色等类物体,就必须处理这方面的问题,这暂时不属于地图逻辑原理,也不属于地图编辑器的设计,暂不展开讨论

为了表述方便,我专门截图制作了下面的一张图片来进行一些要素的标注
 

从上图可以看出,以等距地图网格对象的顶点top为坐标系原点T(0,0),以汉字撇捺两个方向的纵列为坐标系的两个坐标轴,即Pie轴与top-right方向平行,Na轴与top-left平行。

这样比其他文章里建立的u-v坐标系在使用时更容易理解,也计算时也更便捷。
在接下来的计算中,各单元格也与网格坐标一样,全部以其顶点坐标代表该单元格的位置(屏幕坐标x,y);
而建立的Pie-Na坐标系,仅是通过单元格相对原点T的撇向序号,捺向序号(Pie,Na)数值对来表示该单元格在此网格上的序列位置。

我们通过分析一下网格的两个单元格关系,就可以得出此坐标系下的计算公式。
看图中标注的两个绿色点M(1,2),N(3,1),我们首先看一下,M点相对原点T其屏幕坐标是什么关系
Mx = cellHalfWidth * (Mpie - Mna) = -1 * cellHalfWidth,即相对原点T向左半个单元格宽度
My = cellHalfHeight * (Mpie + Mna) = 3 * cellHalfHeight,即相对原点T向下3倍的半个单元格高度

我们再用此公式来套一下N点,看下是否如实
Nx = cellHalfWidth * (Npie - Nna) = 2 * cellhalfWidth,看下图中,是不是刚好相差一个单元格宽度?
Ny = cellHalfHeight * (Npie + Nna) = 4 * cellHalfHeight,看下图中,也刚好相差2个单元格高度。

好吧,再看点M和N之间又如何呢
Width(M-N) = cellHalfWidth * ((Npie -Mpie) - (Nna-Mna)) = cellHalfWidth * (2 - (-1)) = 3 * cellHalfWidth,再对照一下图中,嗯,刚好是3倍的半个单元格宽度
Height(M-N) = cellHalfHeight * ((Npie - Mpie) + (Nna - Mna)) = cellHalfHeight * (2 + (-1)) = 1 * cellHalfHeight,看下图中,这个也没错!

那么经过一番验证,我们的公式就可以确定没问题了,
即,在上述以网格顶点T为原点的Pie-Na坐标中,任一单元格的屏幕位置Q(x,y)都有如下公式:
Qx = cellHalfWidth * (Qpie - Qna) + Tx
Qy = cellHalfHeight * (Qpie + Qna) + Ty

Width(Q) = cellHalfWidth * (Qpie - Qna)        //含正负,在原点左侧为负,右则为正
Height(Q) = cellHalfHeight * (Qpie + Qna)      //肯定为正

对于任意两点U(ux,uy),V(vx,vy)都有如下公式:
Vx = cellHalfWidth * (Vpie - Vna) + Ux
Vy = cellHalfHeight * (Vpie + Vna) + Uy

V到U的距离为
Width(V-U) = cellHalfWidth * ((Vpie-Upie) - (Vna-Una))        //含正负,V在U点左侧为负,右则为正
Height(V-U) = cellHalfHeight * ((Vpie-Upie) + (Vna-Una))      //肯定为正

看起来,上下两个公式没多大不同,不过在使用时,可以一目了然,还是比较方便,所以不嫌麻烦都列出来了

这解决了上面所说的哪个问题了,通过单元格的序列位置求出其屏幕位置,是不是第5个问题解决了呢。

大海航行靠舵手,在斜角地图的逻辑中,有了这样一个公式的出现,就可以顺次搞定以上的1~5的问题了,下面就不这么罗嗦了。

4、通过任一点屏幕坐标,求所在单元格的序列位置
直接把上面公式一翻转,再根据前一篇(还不知道斜角地图原理和细节的看这里)中所述的单元格的宽=2*单元格的高
可得出如下公式:
参数点Q(x,y)为Cell中任一点,其与网格的顶点坐标的距离在X、Y轴方向长度分别是Width(Q),Height(Q);
Qpie = (2 * Height(Q) + Width(Q)) / (cellHalfWidth * 2)
Qna = (2 * Height(Q) - Width(Q)) / (cellHalfHeight * 2)


3、是否允许用户交互,我们只要给图形元件设置这样一个属性即可

2、图元类型,同理,我们只需标识一下此图元的类型即可

1、遮挡关系,现在再去看下图中的单元格序列坐标,就可以看到,凡是单元格序列坐标小的,必然被单元格序列坐标大的遮挡
再来看稍微复杂点的单元格之间的遮挡关系,比如M,N

如果图片的宽度仅为单元格顶点left-right,则像M,N这样的点,根本不会发生遮挡关系,因为Mright与Nleft相距半个单元格宽度的,但如果其宽度都超出left-right的宽度,并

且都又比较高,这时仍然会发生遮挡关系的,那么该如何处理这个遮挡关系呢,非常快速,加减法而已
(Npie - Mpie) + (Nna - Mna) > 0,则N挡M,小于零,则M挡N。

那么又必然会存在相等的,比如M(1,2)与Q(2,1)看起来是平行的,这时怎么办呢
像这类,根本就是完全平行,即使是在视觉效果上,所以,怎么处理都无所谓了,左挡右,或者右挡左,都非常合理,完全视自己喜好了

但是在代码中,一般是不需要这么进行3次加减法运算,多数都会拦截在对pie,na序列值的if语句处。
当然,如果是循环设置地图上所有的图元遮挡关系,pie,na的两个for循环中更是直接

说到这里,斜角地图的逻辑原理,就已经没什么东西了,再来看地图编辑器该如何来设计

通常,我们会为地图绘制一幅背景图的,然后我们可能在这个背景图上添加一些建筑物等物体(甚至包括地面,NPC等),让整个游戏世界看起来像是真实世界的映射。

我们首先来看一下会有哪些东西要出现在这个地图当中

1、地图背景

2、网格对象

3、放置的物体(建筑、地面、NPC等)

4、角色对象

5、有时也需要一个可通行路径对象

一般来说,地图这个大容器可能会被塞进去很多的对象,当非常多的可视对象,尤其是交互类对象时,会使得相关的一些处理,比如遮挡关系的处理,碰撞检测,寻路等非常耗费系统资源,所以我们在规划时,就要考虑到可能出现的这些问题

对于上述前三类对象,是必须放置到地图这个容器当中去的。

而第3项,放置的物体有可能会包含两类,一类是非交互性物体,一类是交互性物体;
而处理方式,一般也有两种方式,即放置进的物体都是非交互性物体,而交互性物体放置到地图外面的另一专门层里,并且使之与地图容器对象等大,这个层容器里面,全部是响应用户的一些对象,但都是看不到的,当鼠标或角色移动到此类对象范围内时,就表现出交互性的半透明效果叠在地图中同样位置的对象上面,因为可响应用户的对象在地图中远远少于非交互对象。但这样一来,寻路和角色在运动时的遮挡处理也复杂化了,因为既然把交互对象移出了地图容器,那么地图容器一般都会设为完全不响应用户,角色有属于自己的层对象来容纳,而遮挡关系就只能靠贴图算法来实现了,当同屏幕有数量非常多的角色对象时,而主程能力又很给力时,有个优秀的贴图算法,可以实现非常高的效率和承载能力

但是一般较为常用的方法,还是采用非交互性物体和交互性物体都放置在地图容器中,而且角色也同样放置在地图容器中,这种处理方案一般在遇到地图在有大量物体,并且角色数量在3~4位数时,通常会遇到瓶颈,CPU和内存飞速上涨,而且会出现画面卡顿的现象。但是一般的小游戏都可以满足了,只要尽量消减一下地图中的非交互性对象数量即可,但话又说回来,如果采用消减地图中非交互性对象的数量,则一定会采用通行路径的处理办法,因为地图上大量不可通行的位置都在地图背景图片中来表现来的

newscreen348447000.png (42.56 KB, 下载次数: 20)

newscreen348447000.png

这篇关于斜角地图逻辑原理解析和Isometric地图编辑器设计方案的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/719253

相关文章

ShardingProxy读写分离之原理、配置与实践过程

《ShardingProxy读写分离之原理、配置与实践过程》ShardingProxy是ApacheShardingSphere的数据库中间件,通过三层架构实现读写分离,解决高并发场景下数据库性能瓶... 目录一、ShardingProxy技术定位与读写分离核心价值1.1 技术定位1.2 读写分离核心价值二

深度解析Python中递归下降解析器的原理与实现

《深度解析Python中递归下降解析器的原理与实现》在编译器设计、配置文件处理和数据转换领域,递归下降解析器是最常用且最直观的解析技术,本文将详细介绍递归下降解析器的原理与实现,感兴趣的小伙伴可以跟随... 目录引言:解析器的核心价值一、递归下降解析器基础1.1 核心概念解析1.2 基本架构二、简单算术表达

深度解析Java @Serial 注解及常见错误案例

《深度解析Java@Serial注解及常见错误案例》Java14引入@Serial注解,用于编译时校验序列化成员,替代传统方式解决运行时错误,适用于Serializable类的方法/字段,需注意签... 目录Java @Serial 注解深度解析1. 注解本质2. 核心作用(1) 主要用途(2) 适用位置3

深入浅出Spring中的@Autowired自动注入的工作原理及实践应用

《深入浅出Spring中的@Autowired自动注入的工作原理及实践应用》在Spring框架的学习旅程中,@Autowired无疑是一个高频出现却又让初学者头疼的注解,它看似简单,却蕴含着Sprin... 目录深入浅出Spring中的@Autowired:自动注入的奥秘什么是依赖注入?@Autowired

Java MCP 的鉴权深度解析

《JavaMCP的鉴权深度解析》文章介绍JavaMCP鉴权的实现方式,指出客户端可通过queryString、header或env传递鉴权信息,服务器端支持工具单独鉴权、过滤器集中鉴权及启动时鉴权... 目录一、MCP Client 侧(负责传递,比较简单)(1)常见的 mcpServers json 配置

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

Maven中生命周期深度解析与实战指南

《Maven中生命周期深度解析与实战指南》这篇文章主要为大家详细介绍了Maven生命周期实战指南,包含核心概念、阶段详解、SpringBoot特化场景及企业级实践建议,希望对大家有一定的帮助... 目录一、Maven 生命周期哲学二、default生命周期核心阶段详解(高频使用)三、clean生命周期核心阶

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Java Scanner类解析与实战教程

《JavaScanner类解析与实战教程》JavaScanner类(java.util包)是文本输入解析工具,支持基本类型和字符串读取,基于Readable接口与正则分隔符实现,适用于控制台、文件输... 目录一、核心设计与工作原理1.底层依赖2.解析机制A.核心逻辑基于分隔符(delimiter)和模式匹

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装