mcbbs原帖链接:https://www.mcbbs.net/thread-939995-1-1.html
仅转载了后半部分,因这个机制比较神奇
大家好,这里是丢人C60。
说起我是怎么接触到坐标原点这个东西的,最先是因为一次偶然发现particle的dx,dy,dz参数可以输入相对坐标,但是用相对坐标输入后基本找不到粒子效果。然后因为一个偶然的因素,我开始怀疑游戏对particle的delta参数的解析是由绝对坐标决定的,如果不是绝对坐标,游戏会自动转化成绝对坐标。于是我tp至坐标原点进行了一系列的实验,大致验证了这个猜想。具体内容会在下面解释。
但是这个发现当时并没有引起我的重视,因为所有东西都局限于坐标原点,使用意义不大。直到我第二次接触坐标原点(也就是前不久,我回答一个问题的时候想到了坐标原点,也因为当时在复习,就偷了个懒)。这个时候我突然意识到,这个东西可能比较有用,但事实证明除了能吸引一下眼球、以及用来偷懒以外,基本没啥用。
但是既然已经研究过了,那就拿来水一帖吧。
首先来了解一下particle的蜜汁解析方式吧。
/particle <颗粒名称> [<pos>] [<delta>] <速度> <数量> [force/normal] [<可见玩家>]
这里解释一下里面的参数。后面的两个参数不需要管,因为用不上。
● 颗粒名称:粒子效果的名称
● pos:粒子生成的坐标,格式为<x y z>
● delta:粒子生成时的分散程度(如果数量不为0)或粒子的移动速度(如果数量为0),格式为<dx dy dz>。一旦填写此参数,后面两个参数变为必填。
● 速度:以某种方式计算粒子的速度。
● 数量:一次生成粒子的数量。如果数量为0,则生成1个粒子,此时粒子具有指定的初速度。
如果要让指定的粒子具有指定的初速度,常规的做法是直接指定delta,然后令数量为0。以火焰粒子为例,/particle flame ~ ~ ~ 2 0 0 1 0
会生成一个沿x轴正方向移动的粒子。
那么,该如何动态指定这个delta呢?还记不记得我之前说过,dx,dy,dz可以由相对坐标指定?我猜不少人想到了/particle flame ~ ~ ~ ~2 ~ ~ 1 0
,但是很抱歉,这个粒子究竟往哪运动,我也说不清,因为命令执行点的坐标会影响到这个粒子的运动方向。
我做出的假设是,游戏在解析坐标时,首先会把所有相对坐标和局部坐标替换成绝对坐标,然后再进行解析。目前看来这个假设基本成立。依据这个原理,假设你的坐标是100 200 300,我们试着分析以上命令。首先,游戏把所有坐标替换为绝对坐标。这时,命令由/particle flame ~ ~ ~ ~2 ~ ~ 1 0
变成了/particle flame 100 200 300 102 200 300 1 0
。这个时候看一下delta,它的值是102 200 300,它的运动方向是向南稍偏东,且明显偏上,速度非常快。
虽然这个过程有点不讨好,但至少找到了一个可以控制粒子速度的接口。如果我指定坐标为原点附近的某个点,是不是就可以做到任意控制粒子的运动方向及速度了呢?以此为依据,我首先做了一个小玩具。
execute positioned 6 5 8 facing entity @e[type=zombie,sort=nearest,limit=1] eyes positioned 0.0 0.0 0.0 run particle minecraft:flame 6 5 8 ^ ^ ^1 0.5 0
这里解释一下,命令中出现的两次 6 5 8 是信标的坐标,这里不能用marker代替,由于positioned 0.0 0.0 0.0
修改了命令基准点,所以particle的pos参数必须手动指定。那么即使我使用marker,最多也就是把第一个positioned的参数改成positioned as <marker>
或at <marker>
,第二个信标的坐标依然需要穷举。那么既然不管用不用marker都需要穷举,那我还不如不用marker,对吧?
好,现在分析一下这个命令的工作方式。首先,确定命令基准点为信标坐标,然后调整朝向,面向最近的僵尸。然后再次调整命令执行基准点为坐标原点。然后手动指定粒子的出现坐标,并使用局部坐标来指定生成粒子的delta参数(游戏会自动转化为绝对坐标),确保粒子的运动方向一定是朝向最近的僵尸。
使用局部坐标是最容易想到的方法,也是最容易理解的,但是有一定的局限,就是虽然粒子的运动方向可控了,但是粒子的运动速度是固定的。解决方法是使用相对坐标。不过使用相对坐标可能较难理解。
execute positioned 6 5 8 as @e[type=zombie,sort=nearest,limit=1] at @s anchored eyes positioned ^ ^ ^ run particle minecraft:flame 6 5 8 ~-6.5 ~-5.5 ~-8.5 0.05 0
这张gif里,可以明显地看到当僵尸靠近信标时,粒子的速度减慢了。
分析一下这个命令。首先调整命令基准点为信标所在位置,然后再通过as、at、anchored、positioned一系列动作调整基准点至最近的僵尸的眼部。然后将基准点的坐标减去信标的坐标,即得到粒子的运动速度,然后调整至合适的倍率即可。
对于一些受重力影响的粒子(如item粒子),在生成时可以适当增加dy的大小,来抵消重力的影响。
execute positioned 6 5 8 as @e[type=zombie,sort=nearest,limit=1] at @s anchored eyes positioned ^ ^ ^ run particle minecraft:item diamond 6 5 8 ~-6.5 ~-2.5 ~-8.5 0.1 0
这条命令和上面的命令大体上相同,不再过多分析。
总结一下吧,使用坐标来动态指定粒子的运动速度是可行的,但是一个无法克服的问题是必须穷举坐标,这也导致粒子只能由方块发出,而不能由实体发出此问题已由SPG等其他玩家解决,在指定粒子运动速度的前提下,可以通过指定一个远大于实体坐标的数字,来使实体坐标对速度的影响可以忽略不计,详见原帖2楼(注:通过局部坐标,指定一个远大于实体坐标的数值,使实体坐标对其的影响可忽略不计,然后再通过<速度>
参数缩小至所需值)。不过,我觉得如果在地图上能看到向玩家发射粒子的方块,也很高级,是吧(滑稽)