在用指令做系统的时候,可能会需要求取两点之间的距离。在之前,人们大多数使用 √x^2+y^2+z^2 来获得距离。然而这个方法需要开平方,在MC中,利用指令开方是一个十分耗费时间的操作。那么,有没有办法不开平方,而只用四则运算获得两点之间的距离呢?

如图,P为要求距离的点,x'为其x坐标(以下将直线x=x'与x轴交点称为X')。黑色的块状物体(雾,以下简称点N)为在原点(以下简称O)到P的直线(以下简称OP)上长度为1的位置,x为其x坐标(以下将直线x=x与x轴交点称为X)。∵△ONX∽△OPX
∴OP/1=x'/x,即OP=x'/x
至此,我们已经得到了用除法得到长度的方法。在游戏中,只要facing目标点,并且使用本地坐标^ ^ ^1来获取N的位置即可
进阶,三维空间!前面我们已经讲述了如何在平面空间内用除法得到距离。但是游戏内接触的大多是立体空间,所以我们需要考虑如何在立体空间内更简便地得到距离。事实上也并不比平面复杂多少,如法炮制而已。看图

有点乱……
图中,P为求距离的点,蓝色的线(以下简称OP')为线段OP在xz平面上的正投影,P'为P在xz平面的正投影,N'为N在xz平面的正投影。OP'上的黑点为从原点出发在蓝线上长度为1的位置,其x坐标为x''。其他都和二维的情况相同。
为了得到OP,我们可以将二维求距离法应用到△OPP',但是我们缺少ON'的长度和OP'的长度。所以我们先在△OX'P'上使用二维距离法得到OP'=x'/x'',在△ON'X内得到ON'=x/x''。得到△OPP'中,OP=OP'/ON'=(x'/x'')/(x/x'')=x'/x
所以三维内的距离求法依然是x'/x,即目标x坐标除以到目标直线上单位长度点的x坐标
在这里给出计算玩家眼睛和最近的具有target标签的实体距离的函数记分板:
- #距离
- scoreboard objectives add dist dummy
- #x y z
- scoreboard objectives add x dummy
- scoreboard objectives add y dummy
- scoreboard objectives add z dummy
- #x' y' z'
- scoreboard objectives add xd dummy
- scoreboard objectives add yd dummy
- scoreboard objectives add zd dummy
- #玩家坐标
- scoreboard objectives add xp dummy
- scoreboard objectives add yp dummy
- scoreboard objectives add zp dummy
- #|x|+|y|+|z|
- scoreboard objectives add bsum dummy
- #-1
- scoreboard players set minus dist -1
- scoreboard players set @s dist 0
- scoreboard players set @s bsum 0
- execute as @e[tag=target,limit=1,sort=nearest] store result score @s xd run data get entity @s Pos[0] 10000
- execute as @e[tag=target,limit=1,sort=nearest] store result score @s yd run data get entity @s Pos[1] 10000
- execute as @e[tag=target,limit=1,sort=nearest] store result score @s zd run data get entity @s Pos[2] 10000
- execute store result score @s xp run data get entity @s Pos[0] 10000
- execute store result score @s yp run data get entity @s Pos[1] 10000
- execute store result score @s zp run data get entity @s Pos[2] 10000
- scoreboard players operation @e[tag=target,limit=1,sort=nearest] xd -= @s xp
- scoreboard players operation @e[tag=target,limit=1,sort=nearest] yd -= @s yp
- scoreboard players operation @e[tag=target,limit=1,sort=nearest] zd -= @s zp
- execute facing entity @e[tag=target,limit=1,sort=nearest] eyes run summon minecraft:area_effect_cloud ^ ^ ^1 {"Tags":["marker"]}
- execute as @e[tag=marker,limit=1,sort=nearest] store result score @s x run data get entity @s Pos[0] 10000
- execute as @e[tag=marker,limit=1,sort=nearest] store result score @s y run data get entity @s Pos[1] 10000
- execute as @e[tag=marker,limit=1,sort=nearest] store result score @s z run data get entity @s Pos[2] 10000
- execute as @e[tag=target,limit=1,sort=nearest] if score @s xd matches ..-1 run scoreboard players operation @s xd *= minus dist
- execute as @e[tag=target,limit=1,sort=nearest] if score @s yd matches ..-1 run scoreboard players operation @s yd *= minus dist
- execute as @e[tag=target,limit=1,sort=nearest] if score @s zd matches ..-1 run scoreboard players operation @s zd *= minus dist
- execute as @e[tag=marker,limit=1,sort=nearest] if score @s x matches ..-1 run scoreboard players operation @s x *= minus dist
- execute as @e[tag=marker,limit=1,sort=nearest] if score @s y matches ..-1 run scoreboard players operation @s y *= minus dist
- execute as @e[tag=marker,limit=1,sort=nearest] if score @s z matches ..-1 run scoreboard players operation @s z *= minus dist
- scoreboard players operation @s dist += @e[tag=target,limit=1,sort=nearest] xd
- scoreboard players operation @s dist += @e[tag=target,limit=1,sort=nearest] yd
- scoreboard players operation @s dist += @e[tag=target,limit=1,sort=nearest] zd
- scoreboard players operation @s bsum += @s x
- scoreboard players operation @s bsum += @s y
- scoreboard players operation @s bsum += @s z
- scoreboard players operation @s dist /= @s bsum
[groupid=546]Command Block Logic[/groupid]
