本帖最后由 乾.坤 于 2016-10-21 17:15 编辑

Hey!这里是TheMinecraftLover命令方块小组的好久不见的萌萌的可爱的好好吃的乾坤,先给各位拜个早年了!
今天带来的是Bilibili Minecraft大赛的参赛作品3D方块动画生成器,可将范围内的任何建筑(必须是支持的方块,不支持也可以很方便的自己添加)转化成动画——先将3D建筑转化成2D平面,然后弹射升空,场景震撼!另外Bilibili视频片尾的2D动画生成器(把平面建筑转化成掉落沙动画)也是本组组员:
Rain_Effect所做的。
Billbili视频地址(怪物娘录制):
http://www.bilibili.com/video/av3718219/ (求评分!求弹幕!求被硬币砸死!)[bili=3718219]1[/bili]
优酷视频地址(没劲的卡拉帕西录制):
http://v.youku.com/v_show/id_XMTQ2MTI5OTc2MA==.html
http://v.youku.com/v_show/id_XMTQ2MTI5OTc2MA==.html
演示GIF(乾坤录制)
http://pan.baidu.com/s/1mhvlVYS
小组内部测试视频摘录(Zqk_China录制)
http://pan.baidu.com/s/1hqL2mSO(第三段)
http://pan.baidu.com/s/1sk45qQ5(第二段)
http://pan.baidu.com/s/1bogBtJh(第一段)
Minecraft吧发布链接:
tieba.baidu.com/p/4334475645




下页原理讲解






那么在介绍3D之前,我们先来认识一下2D动画机(即B站片尾感谢名单中的动画机,由组员Rain_Effect制作)的原理,希望对理解3D动画机能起到帮助作用。


这便是2D动画机的所有命令了,是不是很简洁?
第一列和第三列的命令都是额外内容,我们来看一下核心的二列内容来分析:
一开始的几个RCB:
  1. execute @e[type=ArmorStand,name=Check] ~ ~ ~ detect ~ ~ ~-1 minecraft:gold_block 0 execute @e[type=ArmorStand,name=Summon] ~ ~ ~ summon FallingSand ~ ~-2 ~ {Time:1,Tile:41}

  2. execute @e[type=ArmorStand,name=Check] ~ ~ ~ detect ~ ~ ~-1 minecraft:sea_lantern 0 execute @e[type=ArmorStand,name=Summon] ~ ~ ~ summon FallingSand ~ ~-2 ~ {Time:1,Tile:169}

  3. execute @e[type=ArmorStand,name=Check] ~ ~ ~ detect ~ ~ ~-1 redstone_block 0 execute @e[type=ArmorStand,name=Summon] ~ ~ ~ summon FallingSand ~ ~-2 ~ {Time:1,Tile:152}

  4. execute @e[type=ArmorStand,name=Check] ~ ~ ~ detect ~ ~ ~-1 quartz_block 0 execute @e[type=ArmorStand,name=Summon] ~ ~ ~ summon FallingSand ~ ~-2 ~ {Time:1,Tile:155}
复制代码
一上来先是探测Check(检测建筑方块的AS)执行探测,从而在Summon(刷出掉落沙的AS)的地方刷出对应的掉落沙,石英块,红石块所对应的掉落沙等

  1. execute @e[type=ArmorStand,name=Check] ~ ~ ~ detect ~ ~ ~-1 air 0 execute @e[type=ArmorStand,name=Summon] ~ ~ ~ summon FallingSand ~ ~-2 ~ {Time:1,Tile:166}
复制代码
可以看到,这条命令是让空气对应生成成屏障方块(166号方块是屏障方块),这就是精髓所在了,看图就知道:




由于掉落沙是实体,又要让方块位于画布的对应位置不变,那就需要在刷出的时候空气用屏障代替做铺垫(刷出完成后由于掉落沙变成方块,就可以将屏障去掉),3D动画的刷出部分也是类似的原理。
  1. tp @e[type=ArmorStand,name=Summon] ~1 ~ ~
复制代码
  1. scoreboard players add @e[type=ArmorStand,name=Check] locationZ 1
复制代码
  1. execute @e[type=ArmorStand,name=Check,score_locationZ_min=21] ~ ~ ~ scoreboard players add @e[type=ArmorStand,name=Check] locationX 1
复制代码
  1. execute @e[type=ArmorStand,name=Check,score_locationZ_min=21] ~ ~ ~ tp @e[type=ArmorStand,name=Check] ~21 ~1 ~
复制代码
  1. execute @e[type=ArmorStand,name=Check,score_locationZ_min=21] ~ ~ ~ tp @e[type=ArmorStand,name=Summon] ~-21 ~ ~
复制代码
  1. execute @e[type=ArmorStand,name=Check,score_locationZ_min=21] ~ ~ ~ scoreboard players set @e[type=ArmorStand,name=Check] locationZ 0
复制代码
前面的内容就是通过X,Z的控制,使Check和Summon同步移位,用计分板的好处是可以自定义画布和显示屏的长宽高,这点在3D中依旧适用。
  1. execute @e[type=ArmorStand,name=Check,score_locationX_min=10] ~ ~ ~ setblock 1870 63 -238 redstone_block
复制代码
若Check的X,Z值都满(探测完成),则触发关闭线路,核心系统完成。
<<<<<<<<<<下页为3D动画机原理讲解>>>>>>>>>>>>>




那么我们再来看看3D动画机的原理吧。


系统命令一览。

首先我们看主探测进程(你可以理解为扫描系统的AI,控制AS的扫描,刷出和进程):

  1. /blockdata 10 4 -3 {auto:1b}
  2. /blockdata 9 4 -3 {auto:0b}
  3. /blockdata 8 4 -3 {auto:0b}
  4. /testfor @e[type=ArmorStand,name=testfor,score_Y_min=9]
  5. /blockdata 10 4 -3 {auto:0b}
  6. /blockdata 9 4 -3 {auto:1b}
  7. /testfor @e[type=ArmorStand,name=testfor,score_X_min=10]
  8. /blockdata 9 4 -3 {auto:0b}
  9. /blockdata 8 4 -3 {auto:1b}
  10. /testfor @e[type=ArmorStand,name=testfor,score_Z_min=10]
  11. /blockdata 8 4 -3 {auto:0b}
  12. /blockdata 23 4 1 {auto:1b}
  13. /blockdata 23 4 -2 {auto:1b}
  14. /blockdata 23 4 -1 {auto:1b}
  15. /blockdata 23 4 0 {auto:1b}
复制代码
这是一个三层的逻辑嵌套,我一个贴子里也用到了类似的逻辑,大家也可去看看:

[工机巧艺] [15w45a|TML|乾坤]模拟自然生成球类建筑

至于作用,就是以探测AS的位置变化分配给他不同的任务,首先如果探测AS连这竖列的方块都没探测完的话,那么调用到以下模块:
  1. /blockdata 23 4 -5 {auto:1b}
复制代码
然后这个模块再调用到另一个模块(方块-FS库),即一种方块对应一种掉落沙,空气也是屏障,就比如:

  1. /execute @e[type=ArmorStand,name=testfor] ~ ~ ~ detect ~ ~ ~ minecraft:redstone_block 0 execute @e[type=ArmorStand,name=summon] ~ ~ ~ summon FallingSand ~ ~0.405 ~ {Time:1,Tile:152}

  2. /execute @e[type=ArmorStand,name=testfor] ~ ~ ~ detect ~ ~ ~ minecraft:air 0 execute @e[type=ArmorStand,name=summon] ~ ~ ~ summon FallingSand ~ ~0.405 ~ {Time:1,Tile:166}
复制代码

所以如果要添加一种方块,你只需要在方块-FS库中添加一个和上面格式一样的命令,模板如下:
  1. /execute @e[type=ArmorStand,name=testfor] ~ ~ ~ detect ~ ~ ~ minecraft:你自定义的方块ID(英文) 该方块的数据值 execute @e[type=ArmorStand,name=summon] ~ ~ ~ summon FallingSand ~ ~0.405 ~ {Time:1,Tile:该方块的ID(数字),Data:该方块的数据值}
复制代码

就可以添加你想要而没有预设的方块了。

那么方块-FS库的最后要调用回去
  1. /blockdata 20 4 -2 {auto:1b}
复制代码

然后运行这些内容

  1. /scoreboard players add @e[type=FallingSand] release 0
复制代码
  1. /scoreboard players operation @e[type=FallingSand,score_release_min=0,score_release=0] release = @e[type=ArmorStand,name=testfor] Y
复制代码
上面这些内容是为了生成完毕以后一层层的释放FS,所以每一层都有一个对应的释放值,好让最后释放的时候不至于次序混乱
  1. /tp @e[type=ArmorStand,name=testfor] ~ ~1 ~
复制代码
  1. /scoreboard players add @e[type=ArmorStand,name=testfor] Y 1
复制代码

加上对应的Y值让系统识别
  1. /blockdata 23 4 -3 {auto:1b}
复制代码
最后返回主进程


接下来就是Y这列满了,X却未满的处理:
  1. /tp @e[type=ArmorStand,name=testfor] ~1 4 ~
复制代码
  1. /tp @e[type=ArmorStand,name=summon] ~1 ~ ~
复制代码
  1. /scoreboard players set @e[type=ArmorStand,name=testfor] Y 1
复制代码
  1. /scoreboard players add @e[type=ArmorStand,name=testfor] X 1
复制代码
上面依旧是普通的增加分数
  1. /scoreboard players set @e[type=ArmorStand,name=testfor] skip 0
复制代码
  1. /execute @e[type=ArmorStand,name=testfor] ~ ~ ~ /fill ~ ~ ~ ~ 11 ~ barrier 0 replace air
复制代码
  1. /execute @e[type=ArmorStand,name=testfor] ~ ~ ~ /fill ~ ~ ~ ~ 11 ~ air 0 replace barrier
复制代码
之前的testfor的方块与skip计分板通过stats绑定过:
  1. /stats entity @e[type=ArmorStand,name=testfor] set AffectedBlocks @e[type=ArmorStand,name=testfor] skip
复制代码
所以上面那些命令就可以探测到testfor的这竖列是否没有方块
  1. /blockdata 10 4 -1 {auto:1b}
复制代码
  1. /testfor @e[type=ArmorStand,name=testfor,score_skip_min=8,score_skip=8]
复制代码
  1. /blockdata 10 4 -1 {auto:0b}
复制代码
  1. /scoreboard players set @e[type=ArmorStand,name=testfor] Y 9
复制代码
  1. /blockdata 23 4 -3 {auto:1b}
复制代码
又是一系列的逻辑判断和处理,如果AS所在的这列没有方块,则跳过这列(加速处理,后来实践证明加速处理起到了很大的优化作用),如果有方块,那么就交给主AI,让它分配给前面的Y去处理吧。XD
  1. /blockdata 23 4 -3 {auto:1b}
复制代码
最后还是交给我们的苦力AI-主探测进程

然后还剩的就是Y,X都满了,但是Z未满的情况,要做的就是换行了。由于和刚刚的X处理方式类似,故不再赘述。



那么就只有最后一种情况了,XYZ都满,探测完成。
  1. /tp @e[type=ArmorStand,name=summon] 13 4 10
复制代码
  1. /tp @e[type=ArmorStand,name=testfor] 1 4 10
复制代码
  1. /scoreboard players set @e[type=ArmorStand,name=testfor] X 1
复制代码
  1. /scoreboard players set @e[type=ArmorStand,name=testfor] Y 1
复制代码
  1. /scoreboard players set @e[type=ArmorStand,name=testfor] Z 1
复制代码
上面就是将系统全部初始化,锅抛给动画系统。
  1. /setblock 16 5 1 minecraft:redstone_block
复制代码
启动动画系统


  1. /scoreboard players operation @e[type=FallingSand,score_release_min=1] release -= @e[type=ArmorStand,name=testfor] Y
复制代码
  1. /entitydata @e[type=FallingSand,score_release=0,score_release_min=0] {Motion:[0.0,3.0d,0.0]
复制代码
  1. /scoreboard players set @e[score_release_min=0,score_release=0] release -1
复制代码
上面的三个命令就是动画系统了,重复执行就可以实现一层层抛出的效果(其实就像一层层解码的感觉233)


至此,主命令全部完成,不过如果你细心的话会发现,视频里的落在地上的方块总是一跳一跳,或许你已经猜出来了
落在地上的,是掉落沙实体 ,那我们知道
实体存在的时间(刻)。如果为0, 实体就只会出现1刻。如果方块所在位置有一个与实体的方块ID不同的ID那么方块就会消失。当Time为0~1刻时如果在实体位置上的方块有和实体相同的方块ID,方块会被删除,而实体则会继续下落,覆盖方块。 当Time大于600,或当Time大于100同时y<0时,实体会被删除。

上面是掉落沙Time这个NBT的解释,那么又该如何做到让很多掉落沙实体稳定在某个位置一段时间而不变成方块(锁住掉落沙)或消失呢?


  1. /entitydata @e[type=FallingSand,score_release_min=1] {FallDistance:0.0f,Motion:[0.0,0.0399999989999d,0.0],Time:1b}
复制代码

其实只需要一个命令,高频执行,就能让掉落沙实体稳定在一个位置很长一段时间,不过呢,视觉上掉落沙仍然会掉落到方块上面,但是还是实体,就是这个小型的不算黑科技的黑科技让我们实现了锁住很多掉落沙在一个方块里而不会互相冲突,变成方块。也可以说是这个动画的灵魂。而之前的0.405就能让掉落沙实体稳定一些,看起来更像一个方块,而且这个数值只是测试了几次就得到的,大家可以多使用几次,那么就能得到让掉落沙更稳定的数据值了。

(图中可以清晰地看到,落在地上的是掉落沙实体)

下页为感谢名单作品下载与小组




感谢名单:
地图测试:
Zqk_China(及内测视频录制)
Mojedes
Iron_Knot
Sao_N
GXTT
1041159637
Gold_Jo
1041159637
算法讨论:
Arnor_Dorian
Sugar_cane

特别感谢:
Miaoa8(视频录制)
Potter_Lee(算法支持)
Rain_Effect(2D方块动画生成器制作)
Qian_Kun(策划,3D方块动画生成器制作)
Pa_Xi(特邀好友,视频录制)



来自
The Minecraft Lover 小组



附:
[TML 16w05b]3D动画生成器:http://pan.baidu.com/s/1kUje7xt  
[TML 16w05b]2D动画生成器:http://pan.baidu.com/s/1mhrjYHy


来自群组:The Minecraft Lover