11. FPS游戏必备-相机、物体碰撞、重力

本教程翻译自官方教程Cameras, Mesh Collisions and Gravity,各位也可以进入本站镜像站点查看

本文目录

  1. 相机、物体碰撞、重力
    1. 我该怎么做?
      1. 定义和应用重力
      2. 定义一个椭圆碰撞边界
      3. 应用碰撞
      4. 物体与物体碰撞
    2. 弧形旋转相机ArcRotateCamera
    3. 下一步
  2. 延伸阅读
  3. 贡献者

相机、物体碰撞、重力

    你玩过FPS(第一人称射击游戏,类似穿越火线,吃鸡)游戏吗?在本章教程中,我们将用相机模拟这个第一人称视角:相机放置在地上,不但与地面接触产生碰撞,并且可能与场景中的任何物体产生碰撞。

我该怎么做?

    要实现这个第一人称视角的相机移动,我们需要按照以下3个步骤执行:

1 - 定义和应用重力

    首先要做的是定义我们的重力向量,也就是万有引力。在模拟地球这样的典型世界场景中,重力的方向是沿着Y轴朝下,大概是(0, -9.81, 0),这个重力值是可以随意修改的。

scene.gravity = new BABYLON.Vector3(0, -9.81, 0);

    重力能够应用到你之前定义的任何类型相机上:

camera.applyGravity = true;

2 - 定义一个椭圆碰撞边界

    接下来的重要步骤就是定义一个椭圆形,让它围绕在我们的相机周围。这个椭圆代表一个玩家的尺寸大小,也就是定义一个碰撞的边界:当一个物体与这个椭圆接触,就会引发一个碰撞事件,从而防止我们的相机离这个物体太近,也就是我们的视角不会穿过这个物体。
1-ellipsoid

    Babylon.js相机的椭圆属性默认设置为大小为(0.5,1,0.5),而修改这个向量值会让碰撞边界更高、更大、更小或更瘦,设置的大小会按照指定的轴心进行缩放。在下面的例子中,我们将把相机椭圆边界设置得比默认稍微大一些:

//设置围绕相机的椭圆 (例如玩家的体积)
camera.ellipsoid = new BABYLON.Vector3(1, 1, 1);

    请注意,相机相对于椭圆有一个偏移量,导致相机的视点总是位于椭圆的顶部。我们能够使用 camera.ellipsoidOffset 属性来控制这个视点的位置,该属性也是一个三维向量Vector3。最终碰撞位置对的计算方式如下所示:

最终碰撞位置finalPosition = 碰撞位置position - vec3(ellipsoid.x, ellipsoid.y, ellipsoid.z) + ellipsoidOffset

3 - 应用碰撞

    一旦我们完成了上述的设置,最后步骤就是要开启碰撞检测、并且设置需要碰撞的物体。

// 开启碰撞检测
scene.collisionsEnabled = true;
camera.checkCollisions = true;

    声明哪些物体可以和我们的相机产生碰撞:

ground.checkCollisions = true;
box.checkCollisions = true;

    就是这么简单

    你能体验一下刚才教程中的这个例子,Playground 相机碰撞示例

    现在你的相机将因为重力而掉落到地面上,可以通过方向键来移动是相机的位置(需要点击一下canvas,键盘事件才能生效),当相机靠近立方体时,它们会产生一个碰撞,从而阻止你的继续前进。

4 - 物体与物体碰撞

    相机可以做第一人称射击游戏,但是比如贪食蛇、赛车等第三人称视角的游戏,怎么办?别担心,Babylon.js可以在物体上实现与相机一样的椭圆碰撞功能,只需要设置 mesh.ellipsoid属性和 **mesh.moveWithCollisions(velocity)**函数即可,此功能将根据给定的速度移动物体,并检查当前物体与激活checkCollisions的所有其他物体之间是否发生碰撞。

    当然,你也能使用 mesh.ellipsoidOffset 来移动物体的椭圆碰撞范围的中心(默认情况下,椭圆是在物体的中心)

var speedCharacter = 8;
var gravity = 0.15;
var character = Your mesh;

character.ellipsoid = new BABYLON.Vector3(0.5, 1.0, 0.5);
character.ellipsoidOffset = new BABYLON.Vector3(0, 1.0, 0);

var forwards = new BABYLON.Vector3(parseFloat(Math.sin(character.rotation.y)) / speedCharacter, gravity, parseFloat(Math.cos(character.rotation.y)) / speedCharacter);
forwards.negate();
character.moveWithCollisions(forwards);
// or
var backwards = new BABYLON.Vector3(parseFloat(Math.sin(character.rotation.y)) / speedCharacter, -gravity, parseFloat(Math.cos(character.rotation.y)) / speedCharacter);
character.moveWithCollisions(backwards);

弧形旋转相机ArcRotateCamera

    各位可能已经注意了,之前开启碰撞的是通用相机或自由相机,但其实弧形旋转相机也可以检查碰撞,只是发生碰撞的时候,弧形旋转相机不能沿着障碍物进行移动。

    要激活碰撞,只需调用camera.checkCollisions = true。 也可以使用以下代码定义碰撞半径:

camera.collisionRadius = new BABYLON.Vector3(0.5, 0.5, 0.5)

下一步

    很好 咱们已经可以开发一款实时FPS游戏了!但你是不是想更加深入一下物体之间的碰撞呢?没错,这就是下一章的内容 ,请阅读12. 碰撞检测-让物体之间产生联系

延伸阅读

相机概述

贡献者

翻译/校对: Cow&Sheep
Playground: 天才
技术支持: Dushusir github

参与贡献? 联系alexads@foxmail.com