专栏文章

MC 实现区域跳字

科技·工程参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miph5ezj
此快照首次捕获于
2025/12/03 11:55
3 个月前
此快照最后确认于
2025/12/03 11:55
3 个月前
查看原文
这里并不打算去研究什么带有曲线的图形,而是只有一个目的:判定一点是否位于某一多边形内,要求只使用整数。
于是主要有两个算法:射线法,转角法。其实大同小异。
然后随便搞搞就可以了。

这里简要讲一讲转角法是如何工作的。
按理说,应当把每个边与玩家连成的三角形的玩家所在角的角度做代数和,很可惜 MC 中仅有整数的加减乘除模,因此转而考虑能否通过纯有理数进行计算。
注意到可以通过叉积和点积来求出 sin\sincos\cos 的值,并使用和差角公式得到角度和的 sin\sincos\cos,但问题在于 002π2\pi 是等同的,因此考虑先用半角公式,这样可以清晰地分辨出 00π\pi
但新的问题出现了:做不了开方。于是考虑保存其平方,但在平方意义下 00π\pi 又是等同的,于是在额外保存一个正负号即可。那么怎么在求半角时保存正负号呢?注意到原始的角度均位于 [π,π][-\pi,\pi] 中,因此半角位于 [π2,π2][-\frac\pi2,\frac\pi2] 中,设原角为 α\alpha,可知满足 sinαsinα20\sin\alpha\sin\frac\alpha2\ge0cosα20\cos\frac\alpha2\ge0,因此即可知道正负号。
综上转角法可以纯有理数计算完成。

纯矩形区域的实现并不是什么难事,指令甚至只有四行。
初始化:
CPP
scoreboard objectives add A dummy
scoreboard objectives add B dummy
保持循环:
CPP
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,那么新建一个与玩家相关联的盔甲架操纵其二分坐标即可。

最后一个问题,单次判定的复杂度。
实际应用中并不只有一个区域,所以需要做到在多区域的情况下能够尽量减少单次判定的复杂度。
理想一点,假设区域几乎都不重叠(这是因为小范围重叠并不碍事),单个记分板项就能记录玩家所在的区域,因此对单个记分板项操作可以节省很多资源。

评论

0 条评论,欢迎与作者交流。

正在加载评论...