3D迷宫(二)babylon.js
生活随笔
收集整理的這篇文章主要介紹了
3D迷宫(二)babylon.js
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
3D迷宮(二)babylon.js
續上一篇的文章。
前面說到迷宮的算法,地圖生成路線的代碼如下:
// 繪制 地圖 數據this.__proto__.MapDrawData = function(){this.mapDrawData = [];for(let x = 0; x <= mapSize; x++){for(let y = 0; y <= mapSize; y++){if(this.map[x][y] == mapInit){this.mapDrawData.push([[x,y],this.MapDataXY(x,y)]);}}}}//地圖 數據 x y軸的走向this.__proto__.MapDataXY = function(x,y,n = -1){var list = [];this.map[x][y] = mapWall;if(n === -1){++y;n = 0;if(y < mapSize){list = this.JudgeGrid([[x,y]]);}if(list.length <= 0){n = 1;++x;--y;if(x > mapSize){--x;return [x,y];}list = this.JudgeGrid([[x,y]]);if(list.length <= 0){--x;return [x,y];}}}else{n === 0 ? ++y : ++x;if(x > mapSize){--x;return [x,y];}if(y > mapSize){--y;return [x,y];}list = this.JudgeGrid([[x,y]]);if(list.length <= 0){n === 0 ? --y : --x;return [x,y];}}list = this.MapDataXY(x,y,n);return list;}突然感覺還可以用更簡單的方式來做,大學白上了。
3D迷宮代碼,如下:
<!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="utf-8"><title>3D 迷宮游戲 -- 3D MazeGame</title><script src="./js/babylon.js"></script><script src="./js/mazeMapData.js"></script><script src="./js/babylon.gui.js"></script><style>html, body {overflow: hidden;width: 100%;height: 100%;margin: 0;padding: 0;}#renderCanvas {width: 100%;height: 100%;touch-action: none;}</style> </head> <body><canvas id="renderCanvas"></canvas><script type="text/javascript">window.addEventListener('DOMContentLoaded',function(){//**********************************let publicMethod = function(name,data){this[name] = this[name] || data;}publicMethod.prototype = {// 隨機random: function(mix,max){return Math.floor(Math.random()*(mix - max) + max);}}//**********************************// 燈光let createLightClass = function (){this.light = this.light || [];}createLightClass.prototype = {// 定向光directional: function(scene,name){let light = new BABYLON.PointLight(name, new BABYLON.Vector3(100,50, 50), scene);light.intensity = 0.5;this.light[name] = light;},// 半球光hemispheric: function(scene,name){let light = new BABYLON.HemisphericLight(name, new BABYLON.Vector3(0, 100, 50),scene);light.diffuse = new BABYLON.Color3(0.97, 0.92, 0.45);light.specular = new BABYLON.Color3(1, 0.15, 0, 0.71);light.intensity = 0.4;this.light[name] = light;}}//**********************************// 相機let createCameraClass = function(wallSize){this.camera = this.camera || [];this.wallSize = wallSize;}createCameraClass.prototype = {// 第一人稱firstPerspective: function(scene,name,canvas){let camera;camera = new BABYLON.DeviceOrientationCamera(name,new BABYLON.Vector3(this.wallSize / 2 + this.wallSize,100, this.wallSize + this.wallSize / 2),scene);// 地圖區域camera.viewport = new BABYLON.Viewport(0, 0, 1, 1);// 設置相機移動按鍵camera.keysDown = [83,40];camera.keysLeft = [65,37];camera.keysRight = [68,39];camera.keysUp = [87,38];// 相機應用重力camera.applyGravity = true;// 相機碰撞camera.checkCollisions = true;// 相機碰撞 半徑camera.collisionRadius = new BABYLON.Vector3(0.5, 0.5, 0.5)// 相機橢圓體camera.ellipsoid = new BABYLON.Vector3(3, 3, 3);// // 解決掉落不移動 則停止掉落camera.needMoveForGravity = true;camera.attachControl(canvas,true);scene.activeCameras.push(camera);this.camera[name] = camera;},// 小地圖minimap: function(scene,name,canvas){let camera;camera = new BABYLON.ArcRotateCamera(name, 0, 100, 0, new BABYLON.Vector3(0, 0, 0), scene);// 小地圖區域camera.viewport = new BABYLON.Viewport(0, 0, 0.3,0.3);camera.attachControl(canvas,true);scene.activeCameras.push(camera);this.camera[name] = camera;},// 固定場景 - 固定相機fixed: function(scene,name,canvas){let camera;camera = new BABYLON.DeviceOrientationCamera(name, new BABYLON.Vector3(0, 0, 0),scene);// 清除相機的輸入 -- 就是不能操控了camera.inputs.clear();// 添加鼠標操作camera.inputs.addMouse();camera.attachControl(canvas, true);this.camera[name] = camera;},// 控件相機controlsCamera: function(scene,name,layerMask){let camera = new BABYLON.ArcRotateCamera(name, 0, 0.8, 100, BABYLON.Vector3.Zero(), scene);camera.layerMask = layerMask;this.camera[name] = camera;}}//**********************************// 物料let createMaterialsClass = function(wallSize){this.wallSize = wallSize;this.materials = this.materials || {status: 1,now: '',data: [],dataImg: [{name:'woodgrain',path:'./img/Woodgrain.jpg'},{name:'brick2',path:'./img/brick2.jpg'},]};}createMaterialsClass.prototype = {// 地圖gound: function(scene,MazeMapData,name){let materials;materials = BABYLON.Mesh.CreatePlane(name, MazeMapData.map.length * this.wallSize, scene);// 旋轉值 x弧度旋轉值materials.rotation = new BABYLON.Vector3(Math.PI / 2, 0, 0);materials.position = new BABYLON.Vector3(MazeMapData.map.length * this.wallSize / 2,0,MazeMapData.map.length * this.wallSize / 2);// 地面 碰撞materials.checkCollisions = true;// 材料materials.material = this.materialInit(scene,name);this.materials.data[name] = materials;},// 迷宮maze: function(scene,MazeMapData,name){// 加快添加網格scene.blockfreeActiveMeshesAndRenderingGroups = true;// 墻體大小let obj = {height: this.wallSize, width: this.wallSize, depth: this.wallSize};let boxObj = '',x,y = this.wallSize >> 1,z;//材料let myMaterial = this.materialInit(scene,name);let materials = [];for(let i = 0; i < MazeMapData.mapDrawData.length; i++){boxObj = Object.assign({},obj);boxObj.depth = (MazeMapData.mapDrawData[i][1][0] - MazeMapData.mapDrawData[i][0][0] + 1) * boxObj.depth;boxObj.width = (MazeMapData.mapDrawData[i][1][1] - MazeMapData.mapDrawData[i][0][1] + 1) * boxObj.width;materials[i] = BABYLON.MeshBuilder.CreateBox(name+i, boxObj, scene);x = boxObj.width / 2 + MazeMapData.mapDrawData[i][0][1] * obj.width;z = boxObj.depth / 2 + MazeMapData.mapDrawData[i][0][0] * obj.depth;materials[i].position = new BABYLON.Vector3(x,y,z);materials[i].checkCollisions = true;materials[i].material = myMaterial;}// 設置回來scene.blockfreeActiveMeshesAndRenderingGroups = false;this.materials.data[name] = materials;},// 游戲角色gameRole: function(scene,name){let materials;materials = BABYLON.MeshBuilder.CreateSphere(name, {diameter: 10}, scene);materials.position = new BABYLON.Vector3(0,1.5,0);let materialsMat = new BABYLON.StandardMaterial(name, scene);materialsMat.emissiveColor = new BABYLON.Color3(1, 0, 0);materials.material = materialsMat;this.materials.data[name] = materials;},// 終點end: function(scene,z,x,name){let materials,y = (this.wallSize >> 1) / 2;let faceColors = new Array(6).fill(new BABYLON.Color3(1, 0, 0));let obj = {height: this.wallSize / 2, width: this.wallSize, depth: this.wallSize,faceColors: faceColors};materials = BABYLON.MeshBuilder.CreateBox(name, obj, scene);x = obj.width / 2 + x * obj.width;z = obj.depth / 2 + z * obj.depth;materials.position = new BABYLON.Vector3(x,y,z);let materialsMat = new BABYLON.StandardMaterial(name, scene);materialsMat.emissiveColor = new BABYLON.Color3(1, 0, 0);// 透明值materialsMat.alpha = 0.7;// 開啟碰撞materials.checkCollisions = true;materials.material = materialsMat;this.materials.data[name] = materials;},// 起點outset: function(scene,z,x,name){let materials,y = (this.wallSize >> 1) / 2;let faceColors = new Array(6).fill(new BABYLON.Color3(0, 0, 255));let obj = {height: this.wallSize / 2, width: this.wallSize, depth: this.wallSize,faceColors: faceColors};materials = BABYLON.MeshBuilder.CreateBox(name, obj, scene);x = obj.width / 2 + x * obj.width;z = obj.depth / 2 + z * obj.depth;materials.position = new BABYLON.Vector3(x,y,z);let materialsMat = new BABYLON.StandardMaterial(name, scene);materialsMat.emissiveColor = new BABYLON.Color3(0, 0, 255);// 透明值materialsMat.alpha = 0.7;// 開啟碰撞materials.checkCollisions = true;materials.material = materialsMat;this.materials.data[name] = materials;},// 材料materialInit: function(scene,name){if(this.materials.dataImg.length > 1){let random = this.random(0,this.materials.dataImg.length);return this.material(scene,name,random);}else if(this.materials.dataImg.length == 1){return this.material(scene,name,0);}},// 材料material: function(scene,name,i = 0){let myMaterial = new BABYLON.StandardMaterial(name, scene);myMaterial.bumpTexture = new BABYLON.Texture(this.materials.dataImg[i].path, scene);myMaterial.invertNormalMapX = true;myMaterial.invertNormalMapY = true;return myMaterial;}}Object.assign(createMaterialsClass.prototype,publicMethod.prototype);createMaterialsClass.prototype.constructor = createMaterialsClass;//**********************************// 天氣let createWeatherClass = function(){this.weather = this.weather || {status: 1,now: null,data: ['sunnyDay','fog','sunnyDay','sunnyDay']};}createWeatherClass.prototype = {createWeatherInit: function(scene,type = 0){if(type == 0){let random;if(this.weather.data.length > 1){if(this.weather.now === null){random = this.random(0,this.weather.data.length);}else{if(this.weather.now == 0){random = this.random(1,this.weather.data.length);}else{let list = [this.random(0,this.weather.now - 1),this.random(this.weather.now + 1,this.weather.data.length)];random = this.random(0,list.length);}}}else if(this.weather.data.length == 1){random = 0;}this.weather.now = random;this[this.weather.data[random]](scene);}else{this[this.weather.data[this.weather.now]](scene);}},// 天氣 霧fog: function(scene){// this.weather.now = 'fog';scene.fogMode = BABYLON.Scene.FOGMODE_EXP2;// BABYLON.Scene.FOGMODE_NONE;// BABYLON.Scene.FOGMODE_EXP;// BABYLON.Scene.FOGMODE_EXP2;// BABYLON.Scene.FOGMODE_LINEAR;// scene.fogStart = 0;// scene.fogEnd = 100;scene.fogColor = new BABYLON.Color3(0.62, 0.62, 0.62);scene.fogDensity = 0.05;},// 天氣 晴天sunnyDay: function(scene){// 停用霧scene.fogMode = BABYLON.Scene.FOGMODE_NONE;// this.weather.now = 'sunnyDay';}}Object.assign(createWeatherClass.prototype,publicMethod.prototype);createWeatherClass.prototype.constructor = createWeatherClass;//**********************************// 天空let createSkyClass = function(){this.sky = this.sky || {status: 1,now: null,data:[{name:'sunnyDay',path:'./img/skybox/1/skybox'},{name:'nightSky',path:'./img/skybox/2/skybox'},{name:'3',path:'./img/skybox/3/skybox'},{name:'4',path:'./img/skybox/4/skybox'},{name:'5',path:'./img/skybox/5/skybox'},{name:'6',path:'./img/skybox/6/skybox'},{name:'7',path:'./img/skybox/7/skybox'},{name:'8',path:'./img/skybox/8/skybox'},{name:'9',path:'./img/skybox/9/skybox'},{name:'10',path:'./img/skybox/10/skybox'},{name:'11',path:'./img/skybox/11/skybox'},],box: ''}}createSkyClass.prototype = {createSkyInit: function(scene,name){if(this.sky.box === ''){this.sky.box = BABYLON.Mesh.CreateBox(name, 500.0, scene);// 天空盒跟隨我們相機的位置this.sky.box.infiniteDistance = true;}if(this.sky.data.length > 1){let random;if(this.sky.now === null){random = this.random(0,this.sky.data.length);}else{if(this.sky.now == 0){random = this.random(1,this.sky.data.length);}else{let list = [this.random(0,this.sky.now - 1),this.random(this.sky.now + 1,this.sky.data.length)];random = this.random(0,list.length);}}this.createSkyBox(scene,random);}else if(this.sky.data.length == 1){this.createSkyBox(scene,0);}},// 白天 - 晴天createSkyBox: function(scene,i){this.sky.now = i;let skyboxMaterial = new BABYLON.StandardMaterial(this.sky.data[i], scene);// 背景色剔除skyboxMaterial.backFaceCulling = false;// 刪除盒子上的所有光反射skyboxMaterial.disableLighting = true;// 天空紋理skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture(this.sky.data[i].path,scene);skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;skyboxMaterial.diffuseColor = new BABYLON.Color3(1, 0, 0);skyboxMaterial.specularColor = new BABYLON.Color3(1, 0, 0);this.sky.box.material = skyboxMaterial;}}Object.assign(createSkyClass.prototype,publicMethod.prototype);createSkyClass.prototype.constructor = createSkyClass;//**********************************// 創建迷宮let CreateMazeClass = function(name,MazeMapData){// 清除關卡數據 -- 刷新重零開始sessionStorage.clear();this.createLightClass = new createLightClass();this.createCameraClass = new createCameraClass(20);this.createMaterialsClass = new createMaterialsClass(20);this.createWeatherClass = new createWeatherClass();this.createSkyClass = new createSkyClass();// 關卡this.checkpoint();// // 獲取canvas 對象this.canvas = this.getHtmlObj(name);// // 加載巴比倫引擎this.engine = new BABYLON.Engine(this.canvas, true);// 多個場景this.scenes = [];this.fixedScene = [];// 場景數this.scenesNum = 0;// 當前使用的場景 下標this.scenesNow = 0;// 創建場景this.createMazeClassInit(this.scenesNum);// 創建固定場景 - 天空this.createFixedScene();// // 循環 渲染this.runRenderLoop();// // 預備場景this.qerScenes();}CreateMazeClass.prototype = {createMazeClassInit: function(scenesNum,num = 5){MazeMapData.Init(num);// 墻壁 大小this.wallSize = 20;// // 創建場景this.scenes[scenesNum] = this.createScene();// // 燈光 -- 定向光this.createLightClass.directional(this.scenes[scenesNum],'directional');// // 燈光 -- 半球光this.createLightClass.hemispheric(this.scenes[scenesNum],'hemispheric');// // 相機 - 第一視角this.createCameraClass.firstPerspective(this.scenes[scenesNum],'firstPerspective',this.canvas);// 相機 - 小視角 - 小地圖 (相機的執行順序,會影響視圖的層級關系)this.createCameraClass.minimap(this.scenes[scenesNum],'minimap',this.canvas);// 地面this.createMaterialsClass.gound(this.scenes[scenesNum],MazeMapData,'gound');// 游戲角色this.createMaterialsClass.gameRole(this.scenes[scenesNum],'gameRole');// 迷宮this.createMaterialsClass.maze(this.scenes[scenesNum],MazeMapData,'maze');// 天氣this.createWeatherClass.createWeatherInit(this.scenes[scenesNum]);// 起點 - 終點this.outsetEnd(scenesNum);// 剩余一些參數 配置this.over();// 熏染this.render();},// 創建 固定場景createFixedScene: function(){this.fixedScene = new BABYLON.Scene(this.engine);// 相機this.createCameraClass.fixed(this.fixedScene,'fixed',this.canvas);// 天空this.createSkyClass.createSkyInit(this.fixedScene,'fixed_skybox');// 天氣this.createWeatherClass.createWeatherInit(this.fixedScene,1);// 創建控件this.createControls(this.fixedScene);},// 創建控件createControls: function(scene){// 創建控件相機this.createCameraClass.controlsCamera(scene,'controlsCamera',2);this.controls = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("myUI");// 背景控件this.controls.isForeground = true;this.controls.layerMask = 2;let panel = new BABYLON.GUI.StackPanel();this.controls.addControl(panel);panel.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_RIGHT;panel.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_TOP;let inputText = new BABYLON.GUI.InputText();inputText.width = 0.2;inputText.height = "40px";inputText.color = "Orange";inputText.thickness = 1;inputText.placeholderText = '輸入關卡 1 - 30';inputText.focusedBackground = BABYLON.Color4(1,1,1,1);inputText.background = BABYLON.Color4(0.83, 0.62, 0.62, 0);inputText.text = 5;let button = BABYLON.GUI.Button.CreateSimpleButton("run", "run");button.width = "100px";button.height = "40px";button.color = "white";button.focusedBackground = BABYLON.Color4(1,1,1,1);button.background = "Orange";let _this = this;button.onPointerClickObservable.add(function(){let checkpointNum = parseInt(inputText.text);if(checkpointNum <= 0){checkpointNum = 1;}if(checkpointNum > 30){checkpointNum = 30;}_this.createMazeClassInit(_this.scenesNum, (checkpointNum - 1) * 2 + 5);});panel.addControl(inputText);panel.addControl(button);},// 預備 場景qerScenes: function(){this.scenesNum = this.scenesNum === 1 ? 0 : 1;this.createMazeClassInit(this.scenesNum,this.checkpointNum);this.scenesNum = this.scenesNum === 1 ? 0 : 1;},// 場景 切換scenesSwitch: function(){this.scenesNum = this.scenesNum === 1 ? 0 : 1;this.scenesNow = this.scenesNum;// 切換 - 天空this.createSkyClass.createSkyInit(this.fixedScene,'fixed_skybox');// 切換 - 天氣this.createWeatherClass.createWeatherInit(this.fixedScene,1);//切換 場景this.qerScenes();},// 關卡checkpoint: function(num = 5){this.checkpointNum = this.checkpointNum || num;if(sessionStorage.checkpointNum){num += 2;}// 判斷奇數if((num & 1) === 0){num++;}sessionStorage.checkpointNum = (num - 5) / 2 + 1;this.checkpointNum = num;if(num > 5){this.scenesSwitch();}},// 終點outsetEnd: function(scenesNum){this.createMaterialsClass.outset(this.scenes[scenesNum],MazeMapData.exportEntrance[0][0],MazeMapData.exportEntrance[0][1],'ouset');this.createMaterialsClass.end(this.scenes[scenesNum],MazeMapData.exportEntrance[1][0],MazeMapData.exportEntrance[1][1],'end');},// 每次渲染 都會執行render: function(){// let _this = this; // this.scene.registerAfterRender(function () {// });},// 獲取 html 對象getHtmlObj: function(name,type = 'Id'){if(type == 'Id'){return document.getElementById(name);}},// 創建場景createScene: function(){// 場景let scene = new BABYLON.Scene(this.engine);// 場景重力scene.gravity = new BABYLON.Vector3(0, -9, 0);// 場景顏色// scene.clearColor = new BABYLON.Color3(0.17, 0.16, 0.16);// 場景碰撞scene.collisionsEnabled = true;// 場景重疊scene.autoClear = false;return scene;},// 剩余的一些配置over: function(){// 游戲角色 與 相機綁定this.createMaterialsClass.materials.data['gameRole'].position = this.createCameraClass.camera['firstPerspective'].position;// 小地圖 位置this.createCameraClass.camera['minimap'].position = new BABYLON.Vector3(0,this.wallSize * 10,0);// 相機鎖定this.createCameraClass.camera['minimap'].lockedTarget = this.createMaterialsClass.materials.data['ground'];// 過關事件let _this = this;this.createCameraClass.camera['firstPerspective'].onCollide = function(mesh){if(mesh.id == 'end'){mesh.checkCollisions = false;_this.checkpoint(_this.checkpointNum);}}},// 渲染runRenderLoop: function(){let _this = this;this.engine.runRenderLoop(function(){_this.fixedScene.render();_this.scenes[_this.scenesNow].render();});}}//**********************************// 生成地圖數據// MazeMapData.Init(5);let maze = new CreateMazeClass('renderCanvas',MazeMapData);// 窗口重新調整大小事件window.addEventListener('resize', function(){maze.engine.resize();});});</script> </body> </html>終于告一段落了。
歷史,先是了解到three.js 后面發現 webGl 再發現 babylon.js
本來是用three.js做的,但是不知道看了誰的文檔,說webGl是遠古時期的投石索,three.js 是AK47,babylon.js 絕地武士的光劍。
然后我就用babylon.js了。
找工作咯,不然沒飯吃了
總結
以上是生活随笔為你收集整理的3D迷宫(二)babylon.js的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大家来扎绵羊啊。
- 下一篇: 用Python写了个websocket即