# 04 碰撞与互动
本节将学习3个事件API
onVoxelContact()
触碰方块onInteract()
与实体互动onEntityContact()
触碰实体
1.用onVoxelContact触碰方块事件,做一个欢迎灯
相关代码如下:
world.onVoxelContact(({ x, y, z, voxel }) => {
const voxelName = voxels.name(voxel); // 将方块id转换名称
if (voxelName === 'board5'){ // 如果方块名称是 5号木板
voxels.setVoxel(46, 11, 52, 'lantern_02'); // 在门口顶部生成一个灯箱
const meshScale = 1/16 //默认模型方块大小倍数为地图方块的1/16
const man = world.createEntity({
mesh:'mesh/人物.vb',
position:[44, 14, 52],
meshScale:[meshScale,meshScale,meshScale],//xyz放大倍数
fixed:true,//固定
});
man.say('欢迎回家')
world.sound('audio/欢迎回家.mp3')
}
});
2.用onInteract与实体互动事件,做一个电灯开关
相关的代码如下:
const lampSwitch = world.querySelector('#灯开关-1')
// 用查看实体面板获得开关的实体名, 通过实体名查询得到开关实体。注意查询实体名要前置#号
lampSwitch.enableInteract = true // 允许灯开关被玩家触发交互
lampSwitch.interactRadius = 2 // 交互半径
lampSwitch.interactHint = lampSwitch.id // 交互提示文本内容改为实体名字
lampSwitch.interactColor = new Box3RGBColor(0,1,0) // 交互提示文本绿色
lampSwitch.onInteract(()=>{ // 在游戏中走近开关按E键触发
lampSwitch.meshOrientation = lampSwitch.meshOrientation.rotateZ(Math.PI) // 开关实体旋转180度(PI表示180度), 模拟开关上下切换
lampSwitch.sound('audio/开关灯声音.mp3') // 添加开关灯的音效
floor1ToggleLamps() // 反复开关1楼灯光
})
let floor1LampIsOn = true // 1楼灯的开关状态
function floor1ToggleLamps() { // 定义 反复开关1楼灯光 的函数
if(floor1LampIsOn){
// 换成 地砖方块模拟关灯
voxels.setVoxel(37,12,64,'carpet_07')
voxels.setVoxel(37,12,59,'carpet_07')
voxels.setVoxel(28,12,65,'carpet_07')
voxels.setVoxel(28,12,59,'carpet_07')
}else{
// 换成 灯箱方块模拟开灯
voxels.setVoxel(37,12,64,'lantern_01')
voxels.setVoxel(37,12,59,'lantern_01')
voxels.setVoxel(28,12,65,'lantern_01')
voxels.setVoxel(28,12,59,'lantern_01')
}
floor1LampIsOn = !floor1LampIsOn // 反复反转 开关状态
}
world.placeVoxelSound = '' // 关掉方块替换时的默认声音
3.升降电梯
const elevator = world.querySelector('#电梯地板-1') // 获取电梯地板实体
elevator.collides = true // 电梯开启碰撞检测
elevator.fixed = true // 电梯不受外力影响
world.onEntityContact(({entity, other})=>{
// 实时监测整个世界的实体碰撞事件。entity指被碰撞的实体, other则是主动撞过来的实体
if(entity.id=='电梯地板-1' && other.isPlayer){ // 如果 玩家踏上了电梯
if(entity.position.y<14){ // 如果玩家y低于2楼地板, 则判定玩家在1楼
entity.velocity.y = 0.1 // 电梯持续上移
world.say(other.player.name+' 坐电梯上楼')
}
}
})
world.onTick(()=>{ // 实时检测电梯位置, 进行检测是否到达1楼或2楼
if(elevator.position.y>14){ // 如果电梯y坐标高于2楼的地板, 电梯到达2楼
elevator.position.y = 14 // 复位到2楼的准确位置
elevator.velocity.y = 0 // 电梯停止移动
}
})