MC 实现区域跳字

· · 科技·工程

这里并不打算去研究什么带有曲线的图形,而是只有一个目的:判定一点是否位于某一多边形内,要求只使用整数。

于是主要有两个算法:射线法,转角法。其实大同小异。

然后随便搞搞就可以了。

这里简要讲一讲转角法是如何工作的。

按理说,应当把每个边与玩家连成的三角形的玩家所在角的角度做代数和,很可惜 MC 中仅有整数的加减乘除模,因此转而考虑能否通过纯有理数进行计算。

注意到可以通过叉积和点积来求出 \sin\cos 的值,并使用和差角公式得到角度和的 \sin\cos,但问题在于 02\pi 是等同的,因此考虑先用半角公式,这样可以清晰地分辨出 0\pi

但新的问题出现了:做不了开方。于是考虑保存其平方,但在平方意义下 0\pi 又是等同的,于是在额外保存一个正负号即可。那么怎么在求半角时保存正负号呢?注意到原始的角度均位于 [-\pi,\pi] 中,因此半角位于 [-\frac\pi2,\frac\pi2] 中,设原角为 \alpha,可知满足 \sin\alpha\sin\frac\alpha2\ge0\cos\frac\alpha2\ge0,因此即可知道正负号。

综上转角法可以纯有理数计算完成。

纯矩形区域的实现并不是什么难事,指令甚至只有四行。

初始化:

scoreboard objectives add A dummy
scoreboard objectives add B dummy

保持循环:

execute as @a run scoreboard players operation @s B = @s A
execute as @a run scoreboard players set @s A 0
execute as @a[x=某值,y=-500,z=某值,dx=某值,dy=1000,dz=某值] run scoreboard players set @s A 1
execute as @a if score @s A > @s B run title @s actionbar "已进入给定区域"

一个问题:如何将玩家的坐标写到计分板上?

而且是纯整数坐标。

这里首先对区域用长方形框起来做一个粗筛,假设这个长方形的长宽均不超过 1000,那么新建一个与玩家相关联的盔甲架操纵其二分坐标即可。

最后一个问题,单次判定的复杂度。

实际应用中并不只有一个区域,所以需要做到在多区域的情况下能够尽量减少单次判定的复杂度。

理想一点,假设区域几乎都不重叠(这是因为小范围重叠并不碍事),单个记分板项就能记录玩家所在的区域,因此对单个记分板项操作可以节省很多资源。