今天郭先生发现大家更喜欢看我发的three.js小作品,今天我就发一个3d版本推箱子的游戏,其实webGL有很多框架,three.js并不合适做游戏引擎,但是可以尝试一些小游戏。在线案例请点击博客原文

要制作一个推箱子游戏,正常要有以下4个步骤

  1. 定义一些数组,要有开始箱子数组、结束箱子数组、地面数组还有墙面数组,有这四个数组就可以组成一个关卡。
  2. 根据数组初始化地面墙面箱子和目标地点标志物。
  3. 使用FirstPersonControls控制器,控制相机移动,根据地面箱子和墙面算出可移动区域。
  4. 根据相机正对箱子时,用鼠标点击箱子,控制箱子移动,并做成功性校验。

下面我们上代码分析代码

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 制作一个三维的推箱子游戏的更多相关文章

  1. 用C写一个简单的推箱子游戏(二)

    下面接着上一篇随笔<用C写一个简单的推箱子游戏(一)>来写 tuidong()函数是用来判断游戏人物前方情况的函数,是推箱子游戏中非常重要的一个函数,下面从它开始继续介绍推箱子的小程序怎么 ...

  2. 用C写一个简单的推箱子游戏(一)

    我现在在读大二,我们有一门课程叫<操作系统>,课程考查要求我们可以写一段程序或者写Windows.iOS.Mac的发展历程.后面我结合网上的资料参考,就想用自己之前简单学过的C写一关的推箱 ...

  3. JavaScript写一个小乌龟推箱子游戏

    推箱子游戏是老游戏了, 网上有各种各样的版本, 说下推箱子游戏的简单实现,以及我找到的一些参考视频和实例: 推箱子游戏的在线DEMO : 打开 如下是效果图: 这个拖箱子游戏做了移动端的适配, 我使用 ...

  4. 用HTML5+原生js实现的推箱子游戏

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  5. 用JS制作一个信息管理平台完整版

      前  言 JRedu 在之前的文章中,介绍了如何用JS制作一个实用的信息管理平台. 但是那样的平台功能过于简陋了,我们今天来继续完善一下. 首先我们回顾一下之前的内容.   1.JSON的基础知识 ...

  6. JavaScript 推箱子游戏

    推箱子游戏的 逻辑非常简单,但是如果不动手的话,还是不太清楚.我在这里讲一下自己的思路. 制作推箱子,首先要有自己的设计素材.如下我也是网上找的素材 第二步,理清游戏的规则. 游戏规则: 1.小人将箱 ...

  7. 如何制作一个类似Tiny Wings的游戏(2) Cocos2d-x 2.1.4

    在第二篇<如何制作一个类似Tiny Wings的游戏>基础上,增加添加主角,并且使用Box2D来模拟主角移动,原文<How To Create A Game Like Tiny Wi ...

  8. C语言实现推箱子游戏完整代码

    C语言实现推箱子游戏完整代码 前言 自己做的,可能有些代码不够工整,或者有些小问题,但游戏的基本操作是可以实现的 代码效果 代码一共分为8个部分,4个控制上下左右移动,2个判断输赢,1个统计归为的个数 ...

  9. 怎样制作一个相似Tiny Wings的游戏 Cocos2d-x 2.1.4

    在第一篇<怎样使用CCRenderTexture创建动态纹理>基础上,添加�创建动态山丘,原文<How To Create A Game Like Tiny Wings with C ...

随机推荐

  1. 循环&&数组&&方法&&面向对象

    day03 数值的默认值 类型 初始化的值 byte,short,int,long 0 float,double  0.0 char 空格 boolean false 引用类型 null JVM的内存 ...

  2. 浅谈并查集&种类并查集&带权并查集

    并查集&种类并查集&带权并查集 前言: 因为是学习记录,所以知识讲解+例题推荐+练习题解都是放在一起的qvq 目录 并查集基础知识 并查集基础题目 种类并查集知识 种类并查集题目 并查 ...

  3. HotSpot的类模型(3)

    上一篇 HotSpot的类模型(2) 介绍了类模型的基础类Klass的重要属性及方法,这一篇介绍一下InstanceKlass及InstanceKlass的子类. 2.InstanceKlass类 每 ...

  4. (一)ansible 安装配置

    CentOS 7.5 一,安装 yum -y install ansible 二,配置hosts文件 /etc/ansible/hosts s1 ansible_ssh_port= ansible_s ...

  5. GitHub 热点速览 Vol.27:程序员的自我救赎——GitHub 摸鱼

    作者:HelloGitHub-小鱼干 摘要:都知道 VSCode 有各种摸鱼小插件,边听云音乐.边在 IDE 斗地主,再来一个 NBA 直播,怎一个美滋滋了得.作为 VSCode 的同门,GitHub ...

  6. 3.Unity3d物体操作常用按键

    新建一个cube物体.在unity3d界面左上角可以看到红色下划线的五个图标(下面用图标1到5数字表示),分别对应不同功能,这些功能操作物体很常用.下面用cube物体的操作来演示这几个功能. 1.按Q ...

  7. Howdoo中文社区AMA总结(10月21日)

    10月21日Howdoo举办了中文社区的首次AMA活动,CEO -David Brierley和CMO -Jason Sibley加入到社群中与大家交流并回答社区成员的相关问题. 以下是精选的问题总结 ...

  8. Docker装的Oracle 11g没有HR用户怎么办?一个脚本解决问题!

    #0x0 问题描述 这个学期有一门Oracle的课,我图省事就直接拉了个docker镜像来做练习,一直倒也没啥问题,但是今天的作业需要用到HR这个模板用户. 然而我执行alter user hr ac ...

  9. 使用Git GUI工具 上传本地仓库到 gitee码云仓库

    前言: 网上关于git的命令操作与使用很多教程和博客,在使用git工具时我发现有一个 git Gui 可视化工具,我觉得十分的亲切,由于我之前一直是使用svn作为版本控制管理工具,都是可视化操作,使用 ...

  10. 数据可视化之powerBI入门(二)体验PowerBI:零基础分分钟生成一份交互报表

    https://zhuanlan.zhihu.com/p/64144595 体验PowerBI:零基础分分钟生成一份交互报表 首先我们准备一份数据,Excel格式 数据是从2006年到2015年10年 ...