🏃 移动(Move)#
#bs.move:help
Move entities along a velocity vector, with collision handling.
唯有变化才是永恒。
—赫拉克利特(Heraclitus)
观看演示
🔧 函数#
你可以在下方找到此模块中的所有可用函数。
应用速度#
- #bs.move:apply_vel {scale:<scaling>,with:{}}
在处理碰撞的同时,根据实体的速度分数进行传送。λ 分数仅在回调执行期间可用(
on_*)。- 输入:
执行
as <实体>:要移动的实体。分数
@s bs.vel.[x,y,z]:标准速度向量。函数宏:
参数
scale: 输出的缩放系数。
with: 碰撞设置。
blocks:实体是否应与方块碰撞(默认:true)。 可以是碰撞箱提供器(例如
function #bs.hitbox:callback/get_block_collision)。entities:实体是否应与其他实体碰撞(默认:false)。 可以是选择器标签(通常通过
/tag分配),出于性能考虑推荐使用。ignored_blocks: 要忽略的方块(默认:
#bs.hitbox:can_pass_through)。ignored_entities:要忽略的实体类型(默认:
#bs.hitbox:intangible)。 不适用于具有自定义碰撞箱的实体。on_collision:碰撞发生时运行的命令。 用于解决碰撞(默认:
function #bs.move:callback/bounce)。
- Lambda 表达式:
分数
$move.hit_face bs.lambda:被击中的边界盒的面:5 是东,4 是西,3 是南,2 是北,1 是顶,0 是底。分数
$move.hit_flag bs.lambda:相交边界盒的标志,-1表示实体。分数
$move.vel.[x,y,z] bs.lambda:碰撞调整后规范坐标中的剩余速度。- 输出:
状态:实体根据其速度分数被传送。
- #bs.move:apply_local_vel {scale:<scaling>,with:{}}
实验性
始终优先使用标准版本。基数之间的持续转换可能导致精度损失,有时会造成不可预测的行为。
如果需要向某个方向「发射」实体,仍可将速度设置为局部向量,并在使用
#bs.move:apply_vel之前运行#bs.move:local_to_canonical。使用局部坐标系,根据实体的速度分数进行传送,同时处理碰撞。λ 分数仅在回调执行期间可用(
on_*)。- 输入:
执行
as <实体>:要移动的实体。分数
@s bs.vel.[x,y,z]:局部速度向量。函数宏:
参数
scale: 输出的缩放系数。
with: 碰撞设置。
blocks:实体是否应与方块碰撞(默认:true)。 可以是碰撞箱提供器(例如
function #bs.hitbox:callback/get_block_collision)。entities:实体是否应与其他实体碰撞(默认:false)。 可以是选择器标签(通常通过
/tag分配),出于性能考虑推荐使用。ignored_blocks: 要忽略的方块(默认:
#bs.hitbox:can_pass_through)。ignored_entities:要忽略的实体类型(默认:
#bs.hitbox:intangible)。 不适用于具有自定义碰撞箱的实体。on_collision: 当碰撞时运行的命令,用来解决碰撞问题(默认:
function #bs.move:callback/bounce)。
- Lambda 表达式:
分数
$move.hit_face bs.lambda:被击中的边界盒的面。分数
$move.hit_flag bs.lambda:相交边界盒的标志,-1表示实体。分数
$move.vel.[x,y,z] bs.lambda:碰撞调整后规范坐标中的剩余速度。- 输出:
状态:实体根据其局部速度分数被传送。
什么是边界盒?
边界框是一个简单的矩形框,环绕物体(或物体的一部分),帮助游戏确定其位置和接触对象。例如,Minecraft 中的一组楼梯使用两个边界框:一个用于下台阶,一个用于上台阶。
自定义碰撞箱
Bookshelf 支持多种 hitbox 类型,以实现精准控制。方块可使用自定义 hitbox 提供器。实体支持三种类型:dynamic、baked 和 custom。
示例:根据速度分数移动立方体(block_display)(使用交互实体作为碰撞箱):
# Once
summon minecraft:block_display ~ ~ ~ {block_state:{Name:"stone"},teleport_duration:3,transformation:[1f,0f,0f,-0.5f,0f,1f,0f,0f,0f,0f,1f,-0.5f,0f,0f,0f,1f],Passengers:[{id:"minecraft:interaction",width:1f,height:1f}]}
scoreboard players set @e[type=minecraft:block_display] bs.vel.x 100
scoreboard players set @e[type=minecraft:block_display] bs.vel.y 20
scoreboard players set @e[type=minecraft:block_display] bs.vel.z 50
# In a loop
execute as @e[type=minecraft:block_display] run function #bs.move:apply_vel {scale:0.001,with:{}}
# Choose between multiple collision behaviors
execute as @e[type=minecraft:block_display] run function #bs.move:apply_vel {scale:0.001,with:{on_collision:"function #bs.move:callback/bounce"}}
execute as @e[type=minecraft:block_display] run function #bs.move:apply_vel {scale:0.001,with:{on_collision:"function #bs.move:callback/damped_bounce"}}
execute as @e[type=minecraft:block_display] run function #bs.move:apply_vel {scale:0.001,with:{on_collision:"function #bs.move:callback/slide"}}
execute as @e[type=minecraft:block_display] run function #bs.move:apply_vel {scale:0.001,with:{on_collision:"function #bs.move:callback/stick"}}
性能提示
虽然此系统没有设置具体限制,但需要注意性能受实体的速度和大小的影响。
贡献者:Aksiome
标准转局部#
- #bs.move:canonical_to_local
将标准速度(使用相对坐标系)转换为局部速度(使用局部坐标系)。
- 输入:
执行
rotated as <entity>或rotated <h> <v>:用于转换的旋转。分数
@s bs.vel.[x,y,z]:要转换的速度。- 输出:
分数
@s bs.vel.[x,y,z]:转换后的速度。
什么是局部速度?
与相对速度(标准)不同,此参考系考虑实体的旋转。因此,当父实体旋转时,子实体围绕它旋转。对熟悉 Minecraft 命令的人来说,局部坐标可通过 ^ 符号使用。
贡献者:Aksiome
局部转标准#
- #bs.move:local_to_canonical
将局部速度(使用局部坐标系)转换为标准速度(使用相对坐标系)。
- 输入:
执行
rotated as <entity>或rotated <h> <v>:用于转换的旋转。分数
@s bs.vel.[x,y,z]:要转换的速度。- 输出:
分数
@s bs.vel.[x,y,z]:转换后的速度。
什么是局部速度?
与相对速度(标准)不同,此参考系考虑实体的旋转。因此,当父实体旋转时,子实体围绕它旋转。对熟悉 Minecraft 命令的人来说,局部坐标可通过 ^ 符号使用。
贡献者:Aksiome
设置运动#
- #bs.move:set_motion {scale:<scaling>}
使用速度分数设置实体的运动(Motion)NBT。
- 输入:
执行
as <实体>:要移动的实体。分数
@s bs.vel.[x,y,z]:速度向量。函数宏:
参数
scale: 输出的缩放系数。
- 输出:
状态:运动被应用到给定实体。
示例:根据速度分数移动猪:
# Once
summon minecraft:pig ~ ~ ~
scoreboard players set @e[type=minecraft:pig] bs.vel.x 50
scoreboard players set @e[type=minecraft:pig] bs.vel.y 25
scoreboard players set @e[type=minecraft:pig] bs.vel.z 0
# In a loop
execute as @e[type=minecraft:pig] run function #bs.move:set_motion {scale:0.001}
贡献者:Aksiome
👁️ 谓词#
你可以在下方找到此模块中的所有可用谓词。
有速度?#
bs.move:has_vel
确定实体是否有非零速度分数。
贡献者:Aksiome
🎓 自定义碰撞#
此模块允许你根据特定需求自定义碰撞行为。
通过修改 on_collision 输入参数,你可以自由指定碰撞时触发的函数。不过,自行处理碰撞比较复杂,因此 Bookshelf 提供了多个预定义函数:
|
实体将在碰撞表面反弹。 |
|
实体速度在每次反弹时减少2。 |
|
实体将粘附并沿碰撞表面滑动。 |
|
实体将停止并粘附在碰撞表面上。 |
工作原理#
当发生碰撞时,系统使用速度和该边界框的标志来追踪被击中的边界框。你可以修改:
@s bs.vel.[x,y,z]:将在下一个游戏刻应用的速度。$move.vel.[x,y,z] bs.lambda:回退到碰撞时刻后剩余的速度。
创建自定义行为时无需直接处理局部速度;向量会在碰撞处理前后自动转换。
速度缩放
剩余速度值以缩放整数的形式存储,但缩放系数可随时变更,并且这不破坏兼容性。
为了确保稳定性,请保持计算操作和缩放系数无关。
最简单的碰撞处理是停止移动。
#bs.move:callback/stick
# set all components to 0 to cancel the movement
execute store result score $move.vel.x bs.lambda run scoreboard players set @s bs.vel.x 0
execute store result score $move.vel.y bs.lambda run scoreboard players set @s bs.vel.y 0
execute store result score $move.vel.z bs.lambda run scoreboard players set @s bs.vel.z 0
对于滑动,我们需要取消被阻挡的轴上的速度,并继续行进剩余距离。
#bs.move:callback/slide
# set a component to 0 depending on the surface that was hit.
execute if score $move.hit_face bs.lambda matches 4..5 store result score $move.vel.x bs.lambda run scoreboard players set @s bs.vel.x 0
execute if score $move.hit_face bs.lambda matches 0..1 store result score $move.vel.y bs.lambda run scoreboard players set @s bs.vel.y 0
execute if score $move.hit_face bs.lambda matches 2..3 store result score $move.vel.z bs.lambda run scoreboard players set @s bs.vel.z 0