上节实现了人遇到障碍物会停:

这节继续实现按空格跳跃的功能。
在地面上,移动速度是 10,但是跳起来以后,速度应该减小,比如往前跳,肯定速度不如走的快。
单独设置一个跳的时候的速度:
首先监听空格按下状态:

const keyPressed = {
w: false,
a: false,
s: false,
d: false,
space: false
};
window.addEventListener('keydown', (e) => {
const key = e.key.toLowerCase();
if (key === ' ') {
keyPressed.space = true;
} else if (key in keyPressed) {
keyPressed[key] = true;
}
});
window.addEventListener('keyup', (e) => {
const key = e.key.toLowerCase();
if (key === ' ') {
keyPressed.space = false;
} else if (key in keyPressed) {
keyPressed[key] = false;
}
});
定义下空中的移动速度,以及往上跳的力。

加一下是否在地面的检测,用数值方向的速度判断就行。
const airControlSpeed = 1.5;
const jumpForce = 1000;
// 检测是否在地面或物体上
const physicsVelocity = playerBody.velocity;
const velocityY = Math.abs(physicsVelocity.y);
const isOnGround = velocityY < 1.0;
然后后面移动的时候,根据是否在地面来计算不同的速度:

地面上的移动速度快,空中慢一点。
if (isMoving) {
moveDirection.normalize();
if (isOnGround) {
// 地面上
playerBody.velocity.x = moveDirection.x * moveSpeed;
playerBody.velocity.z = moveDirection.z * moveSpeed;
} else {
// 空中
playerBody.velocity.x = moveDirection.x * airControlSpeed;
playerBody.velocity.z = moveDirection.z * airControlSpeed;
}
} else if (isOnGround) {
playerBody.velocity.x = 0;
playerBody.velocity.z = 0;
}
并且按住空格的时候,如果是在地面,就给物体加一个向上跳的力:
if (keyPressed.space) {
const physicsVelocity = playerBody.velocity;
const velocityY = Math.abs(physicsVelocity.y);
if (velocityY < 1.0) {
playerBody.applyImpulse(new CANNON.Vec3(0, jumpForce, 0), playerBody.position);
}
}
试下效果:

可以看到,能跳跃,并且能跳到立方体上。
然后从立方体上走下来:

这样,跳跃功能就完成了。
我们走到灰色的墙边看一下:

没问题,同样也无法穿墙。
案例代码上传了小册仓库
总结
这节我们加上了跳跃功能,人物可以跳跃,跳到平台上,然后走下来。
跳跃的时候我们单独处理了下空中的移动速度。
当然,如果模型有跳跃的动画更好,会显得更真实。
下节,我们在这个开放世界中加入更多内容。