开启辅助访问     
收藏本站

站内搜索

搜索

Minecraft(我的世界)苦力怕论坛

[BE教程] 附加包教程:43.方块(九)

 发表于 2024-1-13 12:52:15 来自手机|显示全部楼层|阅读模式 IP:天津
本帖最后由 Cat_Anchor 于 2024-2-3 08:32 编辑

巧克力门
稀有度常见
创造分类建筑
材料固体
合适挖掘工具
硬度0.8
爆炸抗性2
亮度0
窒息生物
红石导体
光照透明1
可被火破坏
可被熔岩生成火
可再生
最大堆叠64
命名空间IDchocolate_door


前言
对于大部分人,门确实是一个难复刻的东西。它的难度不在于门的方向或者开关之类,而在于它是一个两格高的方块。门的这种性质注定了它需要一番功夫制作,“活板门”和“门”也花了我一天时间来研究。其中,有半天时间都在优化门的两格高带来的极差的体验。
目标
制作一个尽可能与原版一样的门,可以打开/关闭。
分析与解决
今天的任务比之前的门要更难,但也不是无法解决。首先,既然是门,那么它肯定有指定4个方向的状态,还有指定是否打开的状态。
门的4个方向是根据我们放置时的朝向决定的,所以使用minecraft:placement_direction实现。至于开关与否,就单独定义一个方块状态。
不过我们使用了方块特征,就把相关的触发器组件——例如minecraft:on_placed——给占用了,以后我们不能用这些组件了。不过根据我的测试,minecraft:on_player_placing似乎还可以使用,这是以后的关键。
现在我们来定义方块状态和一些基本的组件。
  1. {
  2.   "format_version": "1.20.60", //格式版本
  3.   "minecraft:block": {
  4.     "description": {
  5.       "identifier": "supplementary:chocolate_door", //方块ID
  6.       "menu_category": { //定义菜单分类
  7.         "category": "construction", //在创造模式物品栏的“建材”类里
  8.         "group": "itemGroup.name.door" //在“门”物品组里
  9.       },
  10.       "traits": {
  11.         "minecraft:placement_direction": {
  12.           "enabled_states": [
  13.             "minecraft:cardinal_direction"
  14.           ]
  15.         }
  16.       }, //定义方块特征,启用minecraft:cardinal_direction方块状态
  17.       "states": {
  18.         "supplementary:open_bit": [ //门是否打开
  19.           false,
  20.           true
  21.         ],
  22.         "supplementary:upper_block_bit": [ //门是否为上半部分
  23.           false,
  24.           true
  25.         ], ...
  26.       }
  27.     },
  28.     "components": {
  29.       "tag:door": {}, //门的标签
  30.       "minecraft:selection_box": { //定义判定箱和碰撞箱
  31.         "origin": [
  32.           -8,
  33.           0,
  34.           -8
  35.         ],
  36.         "size": [
  37.           16,
  38.           16,
  39.           3
  40.         ]
  41.       },
  42.       "minecraft:collision_box": {
  43.         "origin": [
  44.           -8,
  45.           0,
  46.           -8
  47.         ],
  48.         "size": [
  49.           16,
  50.           16,
  51.           3
  52.         ]
  53.       },
  54.       "minecraft:destructible_by_mining": { //定义挖掘时间
  55.         "seconds_to_destroy": 0.8
  56.       },
  57.       "minecraft:on_player_placing": {
  58.         "event": "placed"
  59.       }, //定义触发器,当玩家放置时,触发placed事件
  60.       "minecraft:destructible_by_explosion": { //定义爆炸抗性
  61.         "explosion_resistance": 2
  62.       },
  63.       "minecraft:light_dampening": 0 //定义遮光量为0(完全透光)
  64.     }, ...
  65.   }
  66. }
复制代码

为了实现两格高方块的效果,我们放置门时只放置了下半部分,需要一个事件把上半部分也放置出来。
  1. "events": {
  2.       "placed": { //刚才定义的事件
  3.         "set_block_at_pos": { //事件方法:在x y z位置放置方块
  4.           "block_type": "supplementary:chocolate_door", //放置巧克力门
  5.           "block_offset": [ //在上面一格的位置
  6.             0,
  7.             1,
  8.             0
  9.           ]
  10.         }
  11.       }, ...
复制代码

然后定义门旋转和开关相关的方块排列。给每个排列都加上一个标签,方便后续检测。

但现在有个问题,那就是点击门时只会开半扇门,不会开一整扇门。为了实现这个功能,我们要加上一个循环执行的事件,来不停地检测上面下面的门的状态,并将自身的状态与其同步。我们顺便把开门关门的事件写出来。
  1. "set_door_states": { //检测
  2.         "sequence": [
  3.           { //从这个开始,这8个事件方法都将门的方向进行同步
  4.             "condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_south','door_lower')",
  5.             "set_block_state": {
  6.               "supplementary:upper_block_bit": true,
  7.               "minecraft:cardinal_direction": "'north'"
  8.             }
  9.           },
  10.           {
  11.             "condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_north','door_lower')",
  12.             "set_block_state": {
  13.               "supplementary:upper_block_bit": true,
  14.               "minecraft:cardinal_direction": "'south'"
  15.             }
  16.           },
  17.           {
  18.             "condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_east','door_lower')",
  19.             "set_block_state": {
  20.               "supplementary:upper_block_bit": true,
  21.               "minecraft:cardinal_direction": "'west'"
  22.             }
  23.           },
  24.           {
  25.             "condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_west','door_lower')",
  26.             "set_block_state": {
  27.               "supplementary:upper_block_bit": true,
  28.               "minecraft:cardinal_direction": "'east'"
  29.             }
  30.           },
  31.           {
  32.             "condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_south','door_upper')",
  33.             "set_block_state": {
  34.               "supplementary:upper_block_bit": true,
  35.               "minecraft:cardinal_direction": "'north'"
  36.             }
  37.           },
  38.           {
  39.             "condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_north','door_upper')",
  40.             "set_block_state": {
  41.               "supplementary:upper_block_bit": true,
  42.               "minecraft:cardinal_direction": "'south'"
  43.             }
  44.           },
  45.           {
  46.             "condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_east','door_upper')",
  47.             "set_block_state": {
  48.               "supplementary:upper_block_bit": true,
  49.               "minecraft:cardinal_direction": "'west'"
  50.             }
  51.           },
  52.           {
  53.             "condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_west','door_upper')",
  54.             "set_block_state": {
  55.               "supplementary:upper_block_bit": true,
  56.               "minecraft:cardinal_direction": "'east'"
  57.             }
  58.           },
  59.           { //从这个开始,这2个是将门的开关状态进行同步,防止只开半扇门的情况发生
  60.             "condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_open') || q.block_neighbor_has_all_tags(0,1,0,'door_open')",
  61.             "set_block_state": {
  62.               "supplementary:open_bit": true
  63.             }
  64.           },
  65.           {
  66.             "condition": "q.block_neighbor_has_all_tags(0,-1,0,'door_close') || q.block_neighbor_has_all_tags(0,1,0,'door_close')",
  67.             "set_block_state": {
  68.               "supplementary:open_bit": false
  69.             }
  70.           }
  71.         ]
  72.       },
  73.       "door_open": { //开门时...
  74.         "set_block_state": {
  75.           "supplementary:open_bit": "!q.block_state('supplementary:open_bit')" //将门的开关状态设为另一个(开设为关,关设为开)
  76.         },
  77.         "run_command": {
  78.           "command": "playsound open.wooden_door @a[r=6] ~ ~ ~ 0.4 1.0" //发出声音
  79.         }
  80.       },
  81.       "door_close": { //关门时...
  82.         "set_block_state": {
  83.           "supplementary:open_bit": "!q.block_state('supplementary:open_bit')" //将门的开关状态设为另一个(开设为关,关设为开)
  84.         },
  85.         "run_command": {
  86.           "command": "playsound close.wooden_door @a[r=6] ~ ~ ~ 0.4 1.0" //发出声音
  87.         }
  88.       }, ...
复制代码

问题又来了,每次开关门有概率“失败”。具体情况是,我们如果开/关门,那么开门后有可能会被同步回没有开/关门的状态,所以视觉上就是门开了一瞬间又关上了。为了解决这个问题,我们需要定义新方块状态,决定门是否同步,一般是要同步的,点击门后设置为不同步,然后再设置回去。
  1. "supplementary:should_update": [ //门是否同步
  2.           true,
  3.           false
  4.         ]
复制代码
  1. {
  2.         "condition": "q.block_state('supplementary:should_update')==false",
  3.         "components": {
  4.           "minecraft:queued_ticking": {
  5.             "looping": true,
  6.             "interval_range": [
  7.               1,
  8.               1
  9.             ],
  10.             "on_tick": {
  11.               "event": "update",
  12.               "target": "self"
  13.             }
  14.           }
  15.         }
  16.       }, //如果门不同步,那么等待1刻,然后继续同步
  17.       {
  18.         "condition": "q.block_state('supplementary:should_update')==true",
  19.         "components": {
  20.           "minecraft:queued_ticking": {
  21.             "looping": true,
  22.             "interval_range": [
  23.               1,
  24.               1
  25.             ],
  26.             "on_tick": {
  27.               "event": "set_door_states",
  28.               "target": "self"
  29.             }
  30.           }
  31.         }
  32.       } //如果门同步,那么触发同步的事件set_door_states
复制代码
  1. "door_open": {
  2.         "set_block_state": {
  3.           "supplementary:open_bit": "!q.block_state('supplementary:open_bit')",
  4.           "supplementary:should_update": false //开门时,将门设为不同步
  5.         },
  6.         "run_command": {
  7.           "command": "playsound open.wooden_door @a[r=6] ~ ~ ~ 0.4 1.0"
  8.         }
  9.       },
  10.       "door_close": {
  11.         "set_block_state": {
  12.           "supplementary:open_bit": "!q.block_state('supplementary:open_bit')",
  13.           "supplementary:should_update": false //关门时,将门设为不同步
  14.         },
  15.         "run_command": {
  16.           "command": "playsound close.wooden_door @a[r=6] ~ ~ ~ 0.4 1.0"
  17.         }
  18.       }, ...
复制代码
那么门方块就做好了,下面是我的chocolate_door.json中的代码。

以下是模型文件。

但是这时,我发现原版门的物品使用了不同的纹理,不好看,实现起来也比较麻烦。于是,我打算做一个附着物,手持“门”时显示。之前我讲过这个,不再赘述。
首先制作模型。
  1. {"format_version":"1.16.0","minecraft:geometry":[{"description":{"identifier":"geometry.door_render","texture_width":16,"texture_height":16,"visible_bounds_width":3,"visible_bounds_height":3.5,"visible_bounds_offset":[0,1.25,0]},"bones":[{"name":"door_root","binding":"q.item_slot_to_bone_name(c.item_slot)"},{"name":"lower","parent":"door_root","pivot":[0,0,0],"cubes":[{"origin":[-8,-16,-8],"size":[16,16,3],"uv":{"north":{"uv":[0,0],"uv_size":[16,16]},"east":{"uv":[0,0],"uv_size":[3,16]},"south":{"uv":[0,0],"uv_size":[16,16]},"west":{"uv":[0,0],"uv_size":[3,16]},"down":{"uv":[16,3],"uv_size":[-16,-3]}}}]},{"name":"upper","parent":"door_root","pivot":[0,0,0],"texture_meshes":[{"position":[0,0,0],"rotation":[90,0,0],"local_pivot":[8,8,0],"scale":[1,1,1],"texture":"upper"},{"position":[0,0,1],"rotation":[90,0,0],"local_pivot":[8,8,0],"scale":[1,1,1],"texture":"upper"},{"position":[0,0,2],"rotation":[90,0,0],"local_pivot":[8,8,0],"scale":[1,1,1],"texture":"upper"}]}]}]}
复制代码

然后是附着物和动画。
  1. {
  2.   "format_version": "1.10.0",
  3.   "minecraft:attachable": {
  4.     "description": {
  5.       "identifier": "supplementary:chocolate_door",
  6.       "materials": {
  7.         "default": "entity_alphatest",
  8.         "enchanted": "entity_alphatest_glint"
  9.       },
  10.       "textures": {
  11.         "default": "textures/blocks/chocolate_door_bottom",
  12.         "upper": "textures/blocks/chocolate_door_top",
  13.         "lower": "textures/blocks/chocolate_door_bottom",
  14.         "enchanted": "textures/misc/enchanted_item_glint"
  15.       },
  16.       "geometry": {
  17.         "default": "geometry.door_render"
  18.       },
  19.       "animations": {
  20.         "hold_first_person": "animation.door.hold_first_person",
  21.         "hold_third_person": "animation.door.hold_third_person"
  22.       },
  23.       "scripts": {
  24.         "animate": [
  25.           {
  26.             "hold_first_person": "c.is_first_person"
  27.           },
  28.           {
  29.             "hold_third_person": "!c.is_first_person"
  30.           }
  31.         ]
  32.       },
  33.       "render_controllers": [
  34.         "controller.render.item_default"
  35.       ]
  36.     }
  37.   }
  38. }
  39. //以上是附着物,以下是动画。
  40. {
  41.   "format_version": "1.10.0",
  42.   "animations": {
  43.     "animation.door.hold_first_person": {
  44.       "loop": true,
  45.       "bones": {
  46.         "door_root": {
  47.           "rotation": [
  48.             27,
  49.             -39,
  50.             -159
  51.           ],
  52.           "position": [
  53.             0,
  54.             14.5,
  55.             2.4
  56.           ]
  57.         }
  58.       }
  59.     },
  60.     "animation.door.hold_third_person": {
  61.       "loop": true,
  62.       "bones": {
  63.         "door_root": {
  64.           "rotation": [
  65.             -20,
  66.             -32.5,
  67.             0
  68.           ],
  69.           "position": [
  70.             0,
  71.             19,
  72.             -4
  73.           ],
  74.           "scale": 0.65
  75.         }
  76.       }
  77.     }
  78.   }
  79. }
复制代码

最后是纹理和文本。
  1. //blocks.json
  2. "chocolate_door": {
  3.   "sound": "mud_bricks"
  4. }

  5. //terrain_texture.json
  6. "chocolate_door_upper": {
  7.   "textures": "textures/blocks/chocolate_door_top"
  8. },
  9. "chocolate_door_lower": {
  10.   "textures": "textures/blocks/chocolate_door_bottom"
  11. }

  12. //zh_CN.lang
  13. tile.supplementary:chocolate_door.name=巧克力门
复制代码

总结

这一期,我们制作了一个与原版极其相似的门。
最后,我放出我为这个门做的纹理,以及所有的示例文档,可以参考一下。  示例文档和纹理.zip(5.42 KB, 下载次数: 11)


评分

参与人数 1铁粒 +6收起理由
 拒绝*** + 66

查看全部评分

苦力怕论坛,感谢有您~

本版积分规则

本站
关于我们
联系我们
坛史纲要
官方
哔哩哔哩
技术博客
下载
网易版
安卓版
JAVA
反馈
意见建议
教程中心
更多
捐助本站
QQ群
QQ群

QQ群

访问手机版

访问手机版

手机版|小黑屋|系统状态|klpbbs.com

粤公网安备 44200002445329号 | 由 木韩网络 提供支持 | GMT+8, 2024-11-21 20:26

声明:本站与Mojang以及微软公司没有从属关系

Powered by Discuz! X3.4 粤ICP备2023071842号-3