标题: 【命令方块教程】自动寻路!非调用游戏模块寻找路径
本帖最后由 Sunny_KyLe 于 2016-11-11 10:41 编辑
你好,我是TML小组的晴路卡。
我知道于路径寻找,当下最流行的方式应该是调用游戏模块,就像僵尸追踪或者生物仇恨,但是我仍然想把我的方法做出来,也许是因为调用游戏模块适应不了所有情况(如爬梯),
也许是我的作品里确实需要这种方法,也许是我吃饱了没事干233
[bili=6780799]1[/bili]


正如所见,这份存档差不多就是在你设置好起点和终点之后(15x15的白色羊毛范围内),再非常温柔高雅华丽地按下按钮,就能生成一条从起点到目标点的最短路径。
但是我是怎么做的呢?主要是利用了广度优先算法,然后让我们看一下百科:
(也许dalao们全都看明白了23333)
OK可能这样讲不够透彻,那我们先把minecraft关掉,画几张图来说明问题:
首先,我随手画了一张迷宫:
黑色的单位我们视作障碍,灰色的单位视作可走的单位,黄色的点我们视作起点,红叉我们视作目标。
迷宫搞好了,但别急着走233
我们不妨引入一条规矩:对于每一个箭头标志,在它的周围空白的可走单位都会进一步生成朝向该箭头的箭头,就像这张图:
(中间的箭头是第一步生成的,周围四个是第二步生成的,边角上的箭头是第三步生成的)
妈妈从小就教我:迷宫要倒着走。所以,我们在目标点周围可走的单位先生成一个朝向它的箭头标志。
然后我们把这一规则引入刚才所画的迷宫。
第一步是这样:
继续按照刚才的规则一步一步地扩散箭头,直到在起点出息箭头标志为止。
我们再从起点开始沿着箭头标志走,路径就奇迹般地出现了。
为了清晰一点,我们把没被走过的路径上的标志去掉,其实不去掉也无所谓
这里做一些特殊的说明。
1.关于箭头重叠:因为我们的路径是一步一步扩散生成的,也许在某个单位会在同一步生里成多个重叠的箭头,对于这种情况,我们可以在执行时随机选择其中一个箭头的方向延伸,也可以将该单位里的标志部分清除只剩下一个方向的箭头
2.关于多条路径:对于一个目标可能会有多条路径,但多条路径的开端只会存在于起点,所以同样在起点开始执行时选择其中一个箭头的方向延伸就行了。
3.关于最短路径:这是怎么做的呢?箭头是一步一步延伸开来的,但之前有说过,一旦起点位置出现箭头标志,整个路径延伸就停止运行,转为从起点开始按照箭头方向走一遍(也就是生成路径了)
实现
OK,讲了那么多,实现才是最后要做的事。
但是思路我都说了,所以实现我不会讲太多。
其实不用对我的命令照抄照搬(会爆炸的233333),实现的大体思路也就是aec和scb相结合,而我这一懒鬼在很大程度上用的是aec,所以很明显这优化不够好,所以大家能自己去思考当然是最好的了233
总结如下:
1. 使用area_effect_cloud(药水云)来代表单位
2. 使用scoreboard来代表单位的方向,执行状态。当然你也可以用多个aec来代表方向(存档爆炸大法好)。
3. execute探测单位周围是否可走并进行扩散
4. 在探测到起点单位有方向后停止方向的扩散延伸,并且开始从起点重新按照各个单位的方向走一遍前往目标点的路径。
5. 如果你想让实体按照路径移动而不是仅仅像我一样用粒子效果表示出路径的话,使用execute aec ~ ~ ~ entitydata entity [dx=0,dy=0,dz=0]{Motion:[x,x,x]}
存档内的命令(仅供参考)
(1)目标点生成初始箭头标志:
- execute @e[type=area_effect_cloud,name=Purpose] ~ ~ ~ detect ~1 ~ ~ air -1 summon area_effect_cloud ~1 ~ ~ {CustomName:"a1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=Purpose] ~ ~ ~ detect ~-1 ~ ~ air -1 summon area_effect_cloud ~-1 ~ ~ {CustomName:"b1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=Purpose] ~ ~ ~ detect ~ ~ ~1 air -1 summon area_effect_cloud ~ ~ ~1 {CustomName:"c1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=Purpose] ~ ~ ~ detect ~ ~ ~-1 air -1 summon area_effect_cloud ~ ~ ~-1 {CustomName:"d1",Duration:2100000000}
- /setblock -7 5 3 minecraft:redstone_block 0
- /setblock -7 5 5 minecraft:air 0</font>
复制代码 (2)箭头标志的延伸:
- entitydata @e[type=area_effect_cloud,name=a1] {CustomName:"a2"}
- /entitydata @e[type=area_effect_cloud,name=b1] {CustomName:"b2"}
- /entitydata @e[type=area_effect_cloud,name=c1] {CustomName:"c2"}
- /entitydata @e[type=area_effect_cloud,name=d1] {CustomName:"d2"}
- execute @e[type=area_effect_cloud,name=a2] ~1 ~ ~ detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"a1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=a2] ~-1 ~ ~ detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"b1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=a2] ~ ~ ~1 detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"c1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=a2] ~ ~ ~-1 detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"d1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=b2] ~1 ~ ~ detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"a1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=b2] ~-1 ~ ~ detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"b1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=b2] ~ ~ ~1 detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"c1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=b2] ~ ~ ~-1 detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"d1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=c2] ~1 ~ ~ detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"a1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=c2] ~-1 ~ ~ detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"b1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=c2] ~ ~ ~1 detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"c1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=c2] ~ ~ ~-1 detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"d1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=d2] ~1 ~ ~ detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"a1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=d2] ~-1 ~ ~ detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"b1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=d2] ~ ~ ~1 detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"c1",Duration:2100000000}
- execute @e[type=area_effect_cloud,name=d2] ~ ~ ~-1 detect ~ ~ ~ air -1 execute @e[type=area_effect_cloud,name=Place,r=0] ~ ~ ~ summon area_effect_cloud ~ ~ ~ {CustomName:"d1",Duration:2100000000}
- /entitydata @e[type=area_effect_cloud,name=a2] {CustomName:"a3"}
- /entitydata @e[type=area_effect_cloud,name=b2] {CustomName:"b3"}
- /entitydata @e[type=area_effect_cloud,name=c2] {CustomName:"c3"}
- /entitydata @e[type=area_effect_cloud,name=d2] {CustomName:"d3"}
- execute @e[type=area_effect_cloud,name=a3] ~ ~ ~ entitydata @e[type=area_effect_cloud,name=Place,r=0] {CustomName:"OFF"}
- execute @e[type=area_effect_cloud,name=b3] ~ ~ ~ entitydata @e[type=area_effect_cloud,name=Place,r=0] {CustomName:"OFF"}
- execute @e[type=area_effect_cloud,name=c3] ~ ~ ~ entitydata @e[type=area_effect_cloud,name=Place,r=0] {CustomName:"OFF"}
- execute @e[type=area_effect_cloud,name=d3] ~ ~ ~ entitydata @e[type=area_effect_cloud,name=Place,r=0] {CustomName:"OFF"}
- execute @e[type=area_effect_cloud,name=Begin] ~ ~ ~ execute @e[type=area_effect_cloud,name=a1,r=0] ~ ~ ~ setblock -7 5 -1 redstone_block 0
- execute @e[type=area_effect_cloud,name=Begin] ~ ~ ~ execute @e[type=area_effect_cloud,name=b1,r=0] ~ ~ ~ setblock -7 5 -1 redstone_block 0
- execute @e[type=area_effect_cloud,name=Begin] ~ ~ ~ execute @e[type=area_effect_cloud,name=c1,r=0] ~ ~ ~ setblock -7 5 -1 redstone_block 0
- execute @e[type=area_effect_cloud,name=Begin] ~ ~ ~ execute @e[type=area_effect_cloud,name=d1,r=0] ~ ~ ~ setblock -7 5 -1 redstone_block 0
- execute @e[type=area_effect_cloud,name=Begin] ~ ~ ~ execute @e[type=area_effect_cloud,name=a1,r=0] ~ ~ ~ setblock -7 5 3 air 0
- execute @e[type=area_effect_cloud,name=Begin] ~ ~ ~ execute @e[type=area_effect_cloud,name=b1,r=0] ~ ~ ~ setblock -7 5 3 air 0
- execute @e[type=area_effect_cloud,name=Begin] ~ ~ ~ execute @e[type=area_effect_cloud,name=c1,r=0] ~ ~ ~ setblock -7 5 3 air 0
- execute @e[type=area_effect_cloud,name=Begin] ~ ~ ~ execute @e[type=area_effect_cloud,name=d1,r=0] ~ ~ ~ setblock -7 5 3 air 0
复制代码(3)清除重叠的箭头:
- /scoreboard players set @e[type=area_effect_cloud,name=a3] is 1
- /scoreboard players set @e[type=area_effect_cloud,name=b3] is 1
- /scoreboard players set @e[type=area_effect_cloud,name=c3] is 1
- /scoreboard players set @e[type=area_effect_cloud,name=d3] is 1
- execute @e[score_is_min=1] ~ ~ ~ scoreboard players add @e[type=area_effect_cloud,name=OFF,r=0] count 1
- /execute @e[score_count_min=2,score_count=2] ~ ~ ~ /kill @r[score_is_min=1,c=1,r=0,type=area_effect_cloud]
- /execute @e[score_count_min=3,score_count=3] ~ ~ ~ /kill @r[score_is_min=1,c=2,r=0,type=area_effect_cloud]
- /execute @e[score_count_min=4,score_count=4] ~ ~ ~ /kill @r[score_is_min=1,c=3,r=0,type=area_effect_cloud]
- /scoreboard players set @e[score_is_min=1] of 0
- /execute @e[type=area_effect_cloud,name=Begin] ~ ~ ~ scoreboard players set @r[type=area_effect_cloud,score_is_min=1,r=1] of 2
- /setblock -7 5 -3 minecraft:redstone_block 0
- /setblock -7 5 -1 minecraft:air 0
复制代码(4)从起点开始按照箭头方向走:
- /scoreboard players set @e[score_of_min=2,score_of=2] of 3
- execute @e[type=area_effect_cloud,name=a3,score_of_min=3] ~-1 ~ ~ scoreboard players set @r[type=area_effect_cloud,score_is_min=1,r=0] of 2
- execute @e[type=area_effect_cloud,name=b3,score_of_min=3] ~1 ~ ~ scoreboard players set @r[type=area_effect_cloud,score_is_min=1,r=0] of 2
- execute @e[type=area_effect_cloud,name=c3,score_of_min=3] ~ ~ ~-1 scoreboard players set @r[type=area_effect_cloud,score_is_min=1,r=0] of 2
- execute @e[type=area_effect_cloud,name=d3,score_of_min=3] ~ ~ ~1 scoreboard players set @r[type=area_effect_cloud,score_is_min=1,r=0] of 2
- /scoreboard players set @e[score_of_min=3] of 1
- execute @e[type=area_effect_cloud,name=Purpose] ~ ~ ~ execute @e[score_of_min=1,r=0] ~ ~ ~ /setblock -7 5 -3 minecraft:air 0
复制代码(5)其他的一些效果:
- /execute @e[name=a3,score_of_min=1] ~ ~ ~ particle reddust ~ ~ ~ 0.25 0 0 0.01 5 force
- /execute @e[name=b3,score_of_min=1] ~ ~ ~ particle reddust ~ ~ ~ 0.25 0 0 0.01 5 force
- /execute @e[name=c3,score_of_min=1] ~ ~ ~ particle reddust ~ ~ ~ 0 0 0.25 0.01 5 force
- /execute @e[name=d3,score_of_min=1] ~ ~ ~ particle reddust ~ ~ ~ 0 0 0.25 0.01 5 force
- /execute @e[name=Begin] ~ ~ ~ particle angryVillager ~ ~-0.5 ~ 0.1 0.1 0.1 0.01 5 force
- /execute @e[name=Purpose] ~ ~ ~ particle barrier ~ ~ ~ 0 0 0 0.01 1 force
- /execute @e[type=bat,name=0] ~ ~ ~ summon area_effect_cloud ~ ~0.5 ~ {CustomName:"Begin",Duration:2100000000}
- /execute @e[type=bat,name=1] ~ ~ ~ summon area_effect_cloud ~ ~0.5 ~ {CustomName:"Purpose",Duration:2100000000}
- /kill @e[type=bat,name=0]
- /kill @e[type=bat,name=1]
复制代码
最后,希望这份不怎么样的教程对大家有帮助2333