babylonJs webGL 3D babylon.js -- 04 做個簡單的fps
標簽:
JavaScript
有了世界有了颜色有了光,我们要在场景里走起来,这个在每个渲染引擎里都可以实现,不过 babylon 的这个像 fps 一样移动,碰到障碍物会停,实在是比 three.js 简单太多,至少在官方例子中没有一个完备的解决方案
FPS游戏中模拟相机运动: 放在地板上的相机,与地面发生的碰撞,以及可能与场景中的任何物体发生的碰撞,这样让我们感觉和真人在场景上行动一样。
下面我们来实现一下
首先在前面的 TestGeometries 文件中我们创建了很多模型,现在就把这些模型全部都存成一个数组,让外部可以访问到,
self.bodys = [box, sphere, plane, disc, cylinder, torus, knot]
同时加入一个 self 来取代 this,方便以后我们进一步的修改,完整代码如下
'use strict';function TestGeometries (scene) { let self = {} self.bodys = [] // 创建一堆材质 const material1 = new BABYLON.StandardMaterial("texture1", scene); material1.diffuseColor = new BABYLON.Color3(0.0, 0.7, 0.95); //漫射色 const material2 = material1.clone() // material2.emissiveColor = new BABYLON.Color3(.2, .8, .3); //发光色 material2.ambientColor = new BABYLON.Color3(.1, .3, .0); //发光色 material2.bumpTexture = new BABYLON.Texture("img/bump.png", scene); //凹凸贴图 const material3 = material1.clone() material3.specularColor = new BABYLON.Color3(0.8, 0.2, 0.7); //反射色 material3.alpha = 0.6; //调整透明度 const material4 = material1.clone() material4.diffuseTexture = new BABYLON.Texture('http://www.babylonjs-playground.com/textures/tree.png', scene) material4.diffuseTexture.hasAlpha = true; //显示为透明 material4.backFaceCulling = false; //使透明在背面也显示贴图,而不是裁切后显示为空 const material5 = material1.clone() material5.diffuseColor = new BABYLON.Color3(1.0, 0.2, 0.15); //漫射色 material5.reflectionTexture = new BABYLON.Texture("http://www.babylonjs-playground.com/textures/tree.png", scene); // 反射贴图 material5.reflectionTexture.coordinatesMode = BABYLON.Texture.SPHERICAL_MODE; // 反射模式 const materialWireframe = new BABYLON.StandardMaterial("materialWireframe", scene); materialWireframe.wireframe = true // 显示网格 const materialGrass = new BABYLON.StandardMaterial("materialGrass", scene); materialGrass.diffuseTexture = new BABYLON.Texture("http://www.babylonjs-playground.com/textures/grass.jpg", scene); materialGrass.diffuseTexture.uScale = 5.0;//垂直方向重复5次 materialGrass.diffuseTexture.vScale = 5.0;//水平方向重复5次 // 创建一个盒子 //参数为: 名字,盒子大小, 它们将放到场景, 是否可更新?(如果该网格后面必须被更新) 和可选的面朝向(参见下面). 如果你需要默认表现那么最后两个参数可以忽略: BABYLON.Mesh.CreateBox("box", 6.0, scene); const box = BABYLON.Mesh.CreateBox("box", 1.0, scene, false, BABYLON.Mesh.DEFAULTSIDE); // box.position.x = -1; //移动一下它的默认位置,x轴移到-3的位置 //Apply the materials to meshes box.material = material1; // 创建一个球体//参数为: 名字, 细分段数 (高度细节或不需), 大小, 将被放到的场景, 是否可更新?(如果该网格后面必须被更新) 和可选的面朝向(参见下面). 如果你需要默认的表现那么最后两个参数可以忽略: BABYLON.Mesh.CreateSphere("sphere", 10.0, 10.0, scene); const sphere = BABYLON.Mesh.CreateSphere("sphere", 8.0, 1.0, scene, false, BABYLON.Mesh.DEFAULTSIDE); sphere.position.x = -1.5; //移动一下x轴的默认位置 sphere.material = material2 // 创建一个平面 (注意这个面是竖立着的) //参数为: 名字, 大小, 和将被放到的场景, 是否可更新?(如果该网格后面必须被更新) 和可选的面朝向 const plane = BABYLON.Mesh.CreatePlane("plane", 100.0, scene, false, BABYLON.Mesh.DOUBLESIDE); //这里怕看不出来用了双面贴图 // const plane = BABYLON.Mesh.CreatePlane("plane", 10.0, scene); plane.position.y = -1; plane.rotation.x = Math.PI / 2 //转动x轴成平面 plane.material = materialGrass // 创建一个盘片 或着一个规则多边形 这里创建了一个8边型 const disc = BABYLON.Mesh.CreateDisc("disc", 1, 8, scene, false, BABYLON.Mesh.DOUBLESIDE); // 参数为: 名字, 半径, 边数, 场景, 可更新否和可选的朝向(参见下面). 如果你需要默认的表现,那么最后两个参数参数可以忽略: // const disc = BABYLON.Mesh.CreateDisc("disc", 1, 8, scene); disc.position.x = -3; disc.rotation.x = Math.PI / 2 //转动x轴成平面 disc.material = material3 //创建一个圆柱体 // 参数为: 名称, 高度, 顶直径, 底直径, 边数, 高向细分度, 场景, 可更新否和可选的朝向(参见下面). 如果你需要默认表现,那么最后两个参数可以忽略: const cylinder = BABYLON.Mesh.CreateCylinder("cylinder", 3, 1, 1, 6, 1, scene); cylinder.position.x = 1.5; cylinder.material = material4 // 创建一个环体 // var torus = BABYLON.Mesh.CreateTorus("torus", 5, 1, 10, scene, false, BABYLON.Mesh.DEFAULTSIDE); // 参数为: 名称, 直径, 厚度, 边数(高度细节或不是), 场景, 可更新否和可选的朝向(参见下面). 如果你使用默认表现那么最后两个参数可忽略 : const torus = BABYLON.Mesh.CreateTorus("torus", 1, 0.5, 10, scene); torus.position.x = 3; torus.material = material5 // 创建一个结 // const knot = BABYLON.Mesh.CreateTorusKnot("knot", 2, 0.5, 128, 64, 2, 3, scene, false, BABYLON.Mesh.DEFAULTSIDE); // 参数为: 名称, 半径, tube, 半径上分段数, tubularSegments, p, q, 场景, 可更新否和可选的朝向(参见下面). 如果你使用默认的表现那么最后的两个参数可以忽略 : const knot = BABYLON.Mesh.CreateTorusKnot("knot", 1, 0.2, 32, 16, 2, 3, scene); knot.position.x = 5.5; knot.material = materialWireframe // 赋予材质 // 创建线 // 参数为: 名称, [都好分隔的向量数组], 场景. const lines = BABYLON.Mesh.CreateLines("lines", [ new BABYLON.Vector3(-2, 0, 0), new BABYLON.Vector3(2, 0, 0), new BABYLON.Vector3(0, 0, -2), new BABYLON.Vector3(0, 0, 2), new BABYLON.Vector3(-2, 0, 0) ], scene); lines.position.y = 3 //绘制点划线 // 参数为 : 名称, [三元向量数组], 划线大小, 间隙大小, 段划线数, 场景. 作为许多线段, 每条段先都是以三元向量组的方式呈现在空间里. 上面函数设置了这条点划线里线段的数量, 每段都是由两个连续三元向量定义. 划线大小 和 间隙大小 是指点划线里每个划线和之间间隙的相对大小. const dashedlines = BABYLON.Mesh.CreateDashedLines("dashedLines", [ new BABYLON.Vector3(-2, 0, 0), new BABYLON.Vector3(2, 0, 0), new BABYLON.Vector3(0, 0, -2), new BABYLON.Vector3(0, 0, 2) ] , 1, 1, 100, scene); dashedlines.position.x = -4 dashedlines.position.y = 3 self.bodys = [box, sphere, plane, disc, cylinder, torus, knot] return self }
接下来在 scene 文件中要将相机替换成freecamera
// 创建一个 FreeCamera,设置位置到 (x:0, y:5, z:-10) var camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5,-10), scene); // camera.setTarget(BABYLON.Vector3.Zero()); //指向原点 这里会冲突 所以我们先取消 // 原来的围绕相机在这里先取消 // var camera = new BABYLON.ArcRotateCamera("Camera", 1.0, 1.0, 12, BABYLON.Vector3.Zero(), scene);
为了区分这种碰撞和不碰撞的情况,所以我们专门建立一个 Physic 处理需要给相机加入 FPS碰撞效果的情况
const Physic = function (sceneObj) { let self = {} function init() { // 传入整个场景参数 sceneObj.scene.gravity = new BABYLON.Vector3(0, -9.81, 0); sceneObj.camera.applyGravity = true; //Set the ellipsoid around the camera (e.g. your player's size) sceneObj.camera.ellipsoid = new BABYLON.Vector3(1, 1, 1); // Enable Collisions sceneObj.scene.collisionsEnabled = true; sceneObj.camera.checkCollisions = true; } self.addCollision = function (o) { // 将物体加入和相机碰撞 o.checkCollisions = true; } init() return self}
接下来记得在html中引入这个文件
同时main 文件也要作出一点点内容的增加
'use strict';let DB = {} //全局可控内容window.addEventListener('DOMContentLoaded', function() { var canvas = document.getElementById('renderCanvas'); // 获取html的元素 start(canvas) });function start (canvas) { const s = new Scene(canvas) const phy = new Physic(s) DB.engine = s.engine //保存两个内容到全局 DB.scene = s.scene const objs = new TestGeometries(DB.scene) // 创建基本元素 for(let i = 0; i<objs.bodys.length; i++){ phy.addCollision(objs.bodys[i]) } }
哒哒,现在可以像 FPS 游戏一样自由遨游我们创建的场景了
image.png
注意要鼠标点击左键才能切换镜头角度,方向键控制前进后退,这里 WASD 还不起作用
作者:x1911
链接:https://www.jianshu.com/p/5ed0e54c565a
點擊查看更多內容
為 TA 點贊
評論
評論
共同學習,寫下你的評論
評論加載中...
作者其他優質文章
正在加載中
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦