今天郭先生发现大家更喜欢看我发的three.js小作品,今天我就发一个3d版本推箱子的游戏,其实webGL有很多框架,three.js并不合适做游戏引擎,但是可以尝试一些小游戏。在线案例请点击
要制作一个推箱子游戏,正常要有以下4个步骤
- 定义一些数组,要有开始箱子数组、结束箱子数组、地面数组还有墙面数组,有这四个数组就可以组成一个关卡。
- 根据数组初始化地面墙面箱子和目标地点标志物。
- 使用FirstPersonControls控制器,控制相机移动,根据地面箱子和墙面算出可移动区域。
- 根据相机正对箱子时,用鼠标点击箱子,控制箱子移动,并做成功性校验。
下面我们上代码分析代码
1. 定义数组
这四个数组分别是墙的数组、地面的数组、箱子初始位置数组和目标数组。
wallArr = [[0, 0], [1, 0], [2, 0], [3, 0], [3, 1], [4, 1], [4, 2], [4, 3], [5, 3], [5, 4], [5, 5], [5, 6], [4, 6], [3, 6], [2, 6], [1, 6], [0, 6], [0, 5], [0, 4], [0, 3], [0, 2], [0, 1]] scopeArr = [[1, 1], [2, 1], [1, 2], [2, 2], [3, 2], [1, 3], [2, 3], [1, 4], [4, 4], [1, 5], [2, 5], [3, 5], [4, 5]]; boxArr = [[3, 3], [2, 4], [3, 4]]; targetArr = [[2, 2], [1, 3], [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, 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 制作推箱子游戏的资料请关注其它相关文章!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 凤飞飞《我们的主题曲》飞跃制作[正版原抓WAV+CUE]
- 刘嘉亮《亮情歌2》[WAV+CUE][1G]
- 红馆40·谭咏麟《歌者恋歌浓情30年演唱会》3CD[低速原抓WAV+CUE][1.8G]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[320K/MP3][193.25MB]
- 【轻音乐】曼托凡尼乐团《精选辑》2CD.1998[FLAC+CUE整轨]
- 邝美云《心中有爱》1989年香港DMIJP版1MTO东芝首版[WAV+CUE]
- 群星《情叹-发烧女声DSD》天籁女声发烧碟[WAV+CUE]
- 刘纬武《睡眠宝宝竖琴童谣 吉卜力工作室 白噪音安抚》[FLAC/分轨][748.03MB]
- 理想混蛋《Origin Sessions》[320K/MP3][37.47MB]
- 公馆青少年《我其实一点都不酷》[320K/MP3][78.78MB]
- 群星《情叹-发烧男声DSD》最值得珍藏的完美男声[WAV+CUE]
- 群星《国韵飘香·贵妃醉酒HQCD黑胶王》2CD[WAV]
- 卫兰《DAUGHTER》【低速原抓WAV+CUE】
- 公馆青少年《我其实一点都不酷》[FLAC/分轨][398.22MB]
- ZWEI《迟暮的花 (Explicit)》[320K/MP3][57.16MB]