【three.js学习笔记(2)】完成一个3D游戏

本文介绍如何利用three.js实现一个3D游戏,包括加载3D模型与动画、海底滚筒效果、绿色和红色小球的碰撞检测、粒子效果及游戏交互等关键步骤。游戏元素包括海豚和鲨鱼模型,触碰绿色小球得分,触碰红色小球扣分,以及丰富的粒子爆炸动画。
摘要由CSDN通过智能技术生成

本文借鉴了The Aviator的玩法和部分代码,最终效果如下。




1 加载模型和动画

参考学习笔记1中的方法,将海豚和鲨鱼模型及动画加载到three.js中。

// 对象构造器
let playerObj;
const mixers = [];
// 游戏人物
const Player = function () {
  const isExist = playerObj ? true : false;
  const loader = new THREE.FBXLoader();
  loader.load('assets/models/Player' + OPTIONS.player + '.fbx', function (object) {
    object.mixer = new THREE.AnimationMixer(object);
    mixers.push(object.mixer);
    const action = object.mixer.clipAction(object.animations[0]);
    action.play();
    // 侧面面对镜头
    object.rotation.y = 1.57;
    object.position.y = 50;
    object.position.z = 0;
    const scale = OPTIONS.objScale[OPTIONS.player];
    object.scale.set(scale, scale, scale);
    // 加入场景
    if (isExist) {
      scene.remove(playerObj)
      playerObj = object;
      scene.add(object);
    } else {
      playerObj = object;
      scene.add(object);
      // 载入obj后开始第一次动画循环
      loop();
    }
  });
};

因为游戏开始时需要选择使用两个游戏人物中的哪一个,所以isExist用于判断之前是否已载入某个模型。变量scale判断载入的是哪个模型并调节模型大小。载入完毕后开始动画循环。

2 加入海底滚筒

海底加入滚筒并不断向后滚动,模拟主角游动的场景。

// 海底
const Sea = function () {
  // 锥:上底半径,下底半径,高度,圆面划分,高度划分
  const geom = new THREE.CylinderGeometry(OPTIONS.seaRadius, OPTIONS.seaRadius, 200, 40, 10);
  // 滚动
  geom.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI/2));
  geom.mergeVertices();
  // 增加波动
  this.waves = [];
  for (let i=0; i < geom.vertices.length; i++) {
    this.waves.push({
      y: geom.vertices[i].y,
      x: geom.vertices[i].x,
      z: geom.vertices[i].z,
      ang: Math.random() * Math.PI * 2,
      amp: 5 + Math.random() * 15,
      speed: 0.016 + Math.random() * 0.032
    });
  };
  // 材质
  const mat = new THREE.MeshPhongMaterial({
    color: COLORS.sand
  });
  mat.flatShading = true;
  this.mesh = new THREE.Mesh(geom, mat);
  this.mesh.position.y = -600;
  this.mesh.position.z = -100;
  scene.add(this.mesh);
}

Sea.prototype.wave = function () {
  const verts = this.mesh.geometry.vertices;
  for (let i=0; i < verts.length; i++) {
    const vprops = this.waves[i];
    verts[i].x =  vprops.x + Math.cos(vprops.ang) * vprops.amp;
    verts[i].y = vprops.y + Math.sin(vprops.ang) * vprops.amp;
    vprops.ang += vprops.speed;
  }
  this.mesh.geometry.verticesNeedUpdate = true;
  sea.mesh.rotation.z += 0.005;
}

3 引入绿色小球

绿色小球触碰后消失,并增加得分。绿球起始在Math.PI / 3位置处生成,当全部被主角吃掉或运动至-Math.PI / 3处时,上一组绿色小球消失,并重新生成下一组。对每个绿色小球,每一帧除自转公转外,还需判断是否与主角碰撞。若发生碰撞,绿色小球消失,启动爆炸的粒子效果并增加得分。

// 绿色小球
const GreenBalls = function () {
  this.generate();
}

GreenBalls.protot
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值