前言
本篇文章是我开发思论启迪(gitee,github)数据包时,为了提高自定义方块放置的精度而研究的内容,在此撰写文章作为研究记录。同时也为MC生态圈贡献一篇技术性资料。
利用实体视线模拟的方法[1],可以十分简单的得到指向方块的坐标,然而这种做法至少有两个弊端:
- 精度不高。在视线模拟算法中,辅助实体会一步步把自己朝着玩家朝向的方向传送过去,为了提高精度,不遗漏方块,每次传送的距离要尽可能小。然而,传送距离越小,所要递归(MC中没有循环语句)的次数就越多。如果每次传送 0.1 0.1 0.1 个方块距离,那么要获取 100 100 100 格外的方块坐标,至少需要递归 1000 1000 1000 次;
- 在获取角落的方块坐标时,由于精度问题,会直接穿过去,获得角落后面的方块的坐标。这在视线模拟算法中,只能通过提高精度的办法降低这种情况发生的可能性。要想完全避免这种情况,编程起来十分繁琐。
为了解决以上问题,本文提出“层穿透法”,旨在用数学方法解决上面的两个弊端。
为了增大受众,本文尽可能避免专业的数学词汇,只要求读者了解空间直角坐标系与向量。
全文共三个章节:
- 在第一章中,将复述问题,以便后文中更好的阅读;
- 在第二章中,提出一种基于空间几何的层穿透法指向方块求解算法;
- 在第三章中,实践第二章中提出的算法,给出在二维情况下,具体的实现代码与其相关逻辑的解释。
一、分析
玩家准星的起点和玩家的坐标是不同的。前者大概从玩家脚底出往上 1.35 1.35 1.35 格高(该数据并未经过精确验证,实际编程时可做调整)的地方,后者是玩家的脚底。因此在实际计算时要特别区分。
指向方块和选中方块是不同的,在MC Java版中,玩家只能选中五格以内(调研确定一下)的方块,而指向方块是比五格更远的。
为了获得玩家选中方块的坐标,主要需要两个参数:玩家的朝向向量与视线初始点。
有了这两个参数以后,就可以确定视线所在的直线了,此时就可以开始计算玩家的选中方块的坐标。
二、数学原理
2.1 二维平面下的方块世界
在进一步分析之前, 首先需要对MC建立模型。MC中的方块坐标全部都是整点,并且从连续的坐标系上看,方块坐标对应的位置都在方块的某个角上。
因此,可以建立如下二维模型:
虽然方块的坐标全都是整点,但是,玩家的坐标却是一个小数,并且玩家的坐标和玩家的视线起点也是不相同的,因此在实际计算时还有进行对应的转换。在下文中,我们如下的符号约定:
符号 | 意义 |
---|---|
l l l | 表示玩家的视线,本质是一条射线 |
P P P 或 ( a , b ) (a,b) (a,b) 或 ( a , b , c ) (a,b,c) (a,b,c) | 表示玩家视线的起点坐标 |
s ⃗ \vec{s} s 或 ( m , n ) (m,n) (m,n) 或 ( m , n , u ) (m,n,u) (m,n,u) | 表示玩家视线的方向向量,并且还是一个单位向量 |
k k k | 表示玩家视线的斜率 |
如何从数学的角度上理解视线经过了方块?从前面的定义我们,可以得到:
2.2 层穿透法
有了前文中的建模以后,接下来开始讨论层穿透法的核心内容。
“层穿透法”是根据算法的行为起名的——视线的路径穿透一层层墙面,每一层都有被穿过的方块。在层穿透法中,将原本二维的计算简化为一维中的计算。这里的“层”可以是水平层,也可以是竖直层。在本文中采用竖直层算法。
令 x 0 = ⌊ a ⌋ , x i = x 0 + i x_0 = \lfloor a \rfloor, x_i = x_0 + i x0=⌊a⌋,xi