如何使用three.js 製作一個三維的推箱子游戲
阿新 • • 發佈:2020-07-30
今天郭先生髮現大家更喜歡看我發的three.js小作品,今天我就發一個3d版本推箱子的遊戲,其實webGL有很多框架,three.js並不合適做遊戲引擎,但是可以嘗試一些小遊戲。線上案例請點選
要製作一個推箱子游戲,正常要有以下4個步驟
- 定義一些陣列,要有開始箱子陣列、結束箱子陣列、地面陣列還有牆面陣列,有這四個陣列就可以組成一個關卡。
- 根據陣列初始化地面牆面箱子和目標地點標誌物。
- 使用FirstPersonControls控制器,控制相機移動,根據地面箱子和牆面算出可移動區域。
- 根據相機正對箱子時,用滑鼠點選箱子,控制箱子移動,並做成功性校驗。
下面我們上程式碼分析程式碼
1. 定義陣列
這四個陣列分別是牆的陣列、地面的陣列、箱子初始位置陣列和目標陣列。
wallArr = [[0,0],[1,[2,[3,1],[4,2],3],[5,4],5],6],[0,1]] scopeArr = [[1,5]]; boxArr = [[3,4]]; targetArr = [[2,3]];
2. 根據箱子初始位置陣列初始化箱子
initBox() { var textureBox = new THREE.TextureLoader().load("/static/images/base/crate.png"); if (boxGroup) { scene.remove(boxGroup) } boxGroup = new THREE.Group(); boxGroup.name = 'box_group' boxArr.forEach(d => { var boxGeom = new THREE.BoxGeometry(40,40,40); var boxMate = []; boxGeom.faces.forEach(d => boxMate.push(new THREE.MeshBasicMaterial({ map: textureBox }))) var boxMesh = new THREE.Mesh(boxGeom,boxMate); boxMesh.position.set(d[0] * 40 - 20,20,d[1] * 40 - 20); boxMesh.name = 'box'; boxGroup.add(boxMesh); }) scene.add(boxGroup); //判斷是否贏得比賽 this.isWinner(boxArr,targetArr) }
3. 根據地面數組初始化地面
initGround() { var textureGround = new THREE.TextureLoader().load("/static/images/wall/plaster.jpg",() => {this.loaded_num --}); var textureGroundNormal = new THREE.TextureLoader().load("/static/images/wall/plaster-normal.jpg",() => {this.loaded_num --}); var textureGroundSpecular = new THREE.TextureLoader().load("/static/images/wall/plaster-diffuse.jpg",() => {this.loaded_num --}); textureGround.wrapS = textureGround.wrapT = THREE.RepeatWrapping; textureGround.repeat.set(50,50); textureGroundNormal.wrapS = textureGroundNormal.wrapT = THREE.RepeatWrapping; textureGroundNormal.repeat.set(50,50); var materialGround = new THREE.MeshPhongMaterial({ map: textureGround }) materialGround.normalMap = textureGroundNormal; materialGround.specularMap = textureGroundSpecular; var ground = new THREE.Mesh(new THREE.PlaneGeometry(1000,1000,1,1),materialGround); ground.rotation.x = - Math.PI / 2; scene.add(ground); }
4. 根據牆陣列初始化地面
initWall() { var normal = new THREE.TextureLoader().load("/static/images/wall/stone.jpg",() => {this.loaded_num --}); var bump = new THREE.TextureLoader().load("/static/images/wall/stone-bump.jpg",() => {this.loaded_num --}); wallArr.forEach(d => { var wallBox = new THREE.BoxGeometry(40,40); var material = new THREE.MeshPhongMaterial({ map: normal,bumpMap: bump,bumpScale: 1 }) var wall = new THREE.Mesh(wallBox,material); wall.position.x = d[0] * 40 - 20; wall.position.y = 20; wall.position.z = d[1] * 40 - 20; scene.add(wall); }) }
5. 根據目標陣列初始化目標物
initTarget() { let objLoader = new OBJLoader(); objLoader.setPath("/static/images/texture/hongqi/"); objLoader.load('hongqi.obj',(object) => { this.loaded_num --; let hongqi = object.children[0]; targetArr.forEach(d => { hongqi.position.set(d[0] * 40 - 20,-50,d[1] * 40 - 20) hongqi.scale.set(0.12,0.12,0.12) hongqi.material = new THREE.MeshNormalMaterial({ side: THREE.DoubleSide }); scene.add(hongqi.clone()) }) }) }
6. 監聽箱子的點選事件
每次點選的時候執行computeMove方法,判斷如果是否可移動。
initEventListener() { raycaster = new THREE.Raycaster(); document.addEventListener('mousemove',function (event) { event.preventDefault(); mouse.x = (event.clientX / window.innerWidth) * 2 - 1; mouse.y = - (event.clientY / window.innerHeight) * 2 + 1; },false) document.addEventListener('click',() => { if (scene.children && scene.getObjectByName('box')) { raycaster.setFromCamera(mouse,camera); let intersects = raycaster.intersectObjects(scene.getObjectByName('box_group').children); if (intersects[0] && intersects[0].object.name == 'box') { this.computeMove(intersects[0].object,camera.position); } } }) }
7. 監聽遊戲成功
如果成功了,那麼簡單的彈出提示。
isWinner(arr1,arr2) { let boo = true; //true為贏 arr1.forEach(d => { let res = arr2.some(dd => { return d[0] == dd[0] && d[1] == dd[1] }) if(!res) { boo = false; } }) if(boo) { setTimeout(() => { alert('恭喜你贏了!') },100) } }
由於當時做這個小案例時還是菜鳥,所以很少用一些three.js的輔助方法,見笑了。
以上就是如何使用three.js 製作一個三維的推箱子游戲的詳細內容,更多關於three.js 製作推箱子游戲的資料請關注我們其它相關文章!