ThreeJS之东拼西凑闯迷宫(一)

本系列适合初学者,当然老鸟们能给一些指导就更好了,欢迎大家在底部评论留言。

迷宫指的是充满复杂通道,很难找到从其内部到达入口或从入口到达中心的道路,道路复杂难辨,人进去不容易出来的建筑物。

先来一张效果图。

先说下这个系列的一些设想,用户以第一视角的的方式通过迷宫,为了增加整个闯过的趣味性,准备加入一些冒险的玩法,比如答题提示、怪物攻击、不同形状的迷宫等。

迷宫利用深度优先+递归+回溯的方式生成。迷宫类包含生成和解法的方法。

代码注释已经很详细了,不在赘述。

只有一个出口,一个入口;解有且只有一个,行与列均为奇数;路径连续。

源码地址:【https://github.com/webxing/algorithm/tree/master/%E8%BF%B7%E5%AE%AB%E9%97%AE%E9%A2%98/%E8%87%AA%E5%8A%A8%E7%94%9F%E6%88%90

 1 // 初始化迷宫数据
 2  65                 initData(maze) {
 3  66                     for (let i = 0; i < this.row; i++) {
 4  67                         maze[i] = new Array(this.col).fill(this.wall) //  初始化二维数组
 5  68                         this.visited[i] = new Array(this.col).fill(false) // 初始化访问状态为false
 6  69                         this.findPathVisited[i] = new Array(this.col).fill(false) // 初始化访问状态为false
 7  70 
 8  71                         for (let j = 0; j < this.col; j++) {
 9  72                             // 横纵坐标均为奇数 则是路
10  73                             if (i % 2 === 1 && j % 2 === 1) {
11  74                                 maze[i][j] = this.road
12  75                             }
13  76                         }
14  77                     }
15  78                     // 入口及出口 则是路
16  79                     maze[this.entryX][this.entryY] = this.road
17  80                     maze[this.outX][this.outY] = this.road
18  81 
19  82                     return maze
20  83                 }

调用迷宫类生成迷宫。这里为防止卡顿,生成13行13列的迷宫地图。

 1 let mazeClass = new Maze(13,13, 10, 400, 400)
 2 mazeClass.paintMaze();
 3 
 4 var geometry = new THREE.BoxGeometry(300, 200, 300);
 5                     var material = new THREE.MeshBasicMaterial({
 6                         map: new THREE.TextureLoader().load("images/alien-carving.png")
 7                     });
 8                 for (var i = 0; i < mazeClass.maze.length; i++) {
 9                     for (var j = 0; j < mazeClass.maze[i].length; j++) {
10                         if (mazeClass.maze[i][j] === 1) {                            
11                                 var plane = new THREE.Mesh(geometry, material);
12                                 plane.position.set(300 * j, 0, 300 * i);
13                                 walls.push(plane);
14                                 scene.add(plane);
15                         }
16                     }
17                 }

ThreeJS操作借鉴了FPS游戏的第一视角的方式进行探索,其中用到了天空盒、地面、物理等相关技术。

天空盒盒地面脚本:

 1 // SKYBOX/FOG
 2                 var imagePrefix = "images/autumn-";
 3                 var directions = ["xpos", "xneg", "ypos", "yneg", "zpos", "zneg"];
 4                 var imageSuffix = ".png";
 5                 var skyGeometry = new THREE.BoxGeometry(10000, 10000, 10000);
 6 
 7                 var materialArray = [];
 8                 for (var i = 0; i < 6; i++)
 9                     materialArray.push(new THREE.MeshBasicMaterial({
10                         map: new THREE.TextureLoader().load(imagePrefix + directions[i] + imageSuffix),
11                         side: THREE.BackSide
12                     }));
13                 var skyBox = new THREE.Mesh(skyGeometry, materialArray);
14                 scene.add(skyBox);
15 
16                 var floorT = new THREE.TextureLoader().load('images/rocky-ground.jpg');
17                 floorT.wrapS = floorT.wrapT = THREE.RepeatWrapping;
18                 floorT.repeat.set(10, 10);
19                 var floor = new THREE.Mesh(new THREE.BoxGeometry(50000, 50, 50000),
20                     new THREE.MeshBasicMaterial({
21                         map: floorT
22                     })
23                 );
24                 floor.position.set(0, -100, 0);
25                 walls.push(floor);
26                 scene.add(floor);

用户的第一视角脚本。第一视角用一个空的对象代替,用鼠标和键盘控制对象的移动。

 1 person = new THREE.Object3D();
 2                 person.add(camera);
 3                 camera.position.set(0, 35, 10); // first-person view
 4                 person.position.set(-600, 50, 500);
 5                 person.rotation.y = -Math.PI / 5.0;
 6 
 7                 boundingG = new THREE.BoxGeometry(40, 80, 40);
 8                 // radiusAtTop, radiusAtBottom, height, segmentsAroundRadius, segmentsAlongHeight,
 9                 // boundingG = new THREE.CylinderGeometry(20,20,80,8,2);
10                 // better collision but FPS drops too much
11 
12                 boundingG.computeBoundingSphere();
13                 boundingM = new THREE.MeshBasicMaterial({
14                     color: 0xff0000,
15                     transparent: true,
16                     wireframe: true
17                 });
18                 bounding = new THREE.Mesh(boundingG, boundingM);
19                 bounding.visible = false;
20                 person.add(bounding);
21 
22                 person.velocity = new THREE.Vector3(0, 0, 0);
23 
24                 scene.add(person);

体验地址:【http://www.yingbaiyou.cn/upload/maze/maze.html】

欢迎拍砖和不吝赐教,我这也是ThreeJS新手一枚。

猜你喜欢

转载自www.cnblogs.com/wyang/p/12932841.html