3D堆叠游戏——第三步 切割等功能

1,037 阅读3分钟

上一篇文章

上一篇游戏功能做到主角的动画以及控制

在进行下一次主角出现之前需要做很多工作。第一步先对主角进行切割

分出在有效范围内和有效范围外的模型

将有效范围内放置到场景内,有效范围外的模型做自由落体

切割主要用threebsp

require("../utils/threebsp.js");

源码中将threebsp绑定到windows上,所以可以直接用const ThreeBSP = (window as any).ThreeBSP引用

function ThreeBSP(treeIsh, matrix) {
    this.matrix = matrix;
    this.intersect = __bind(this.intersect, this);
    this.union = __bind(this.union, this);
    this.subtract = __bind(this.subtract, this);
    this.toGeometry = __bind(this.toGeometry, this);
    this.toMesh = __bind(this.toMesh, this);
    this.toTree = __bind(this.toTree, this);
    if (this.matrix == null) {
      this.matrix = new THREE.Matrix4();
    }
    this.tree = this.toTree(treeIsh);
  }

这是源码中对几个方法的封装

intersect 处理结果为相交

union 处理结果为联合

subtract 处理结果为减法,前面的模型减去后面的模型得出的结果

感兴趣的童鞋可以阅读一下源码,主要对顶点信息进行的计算

进行bsp计算之前需要将底板的高度提升和主角的高度一样,不然永远没有相交区域

大概这个意思(灵魂画手表示哭泣)

进行的相交计算

计算的结果大致这样

所以需要进行两次计算 一次相交计算 得到有效区域 一次减法计算 得到无效区域

先处理有效区域

const ThreeBSP = (window as any).ThreeBSP
//生成ThreeBSP对象
var leadBsp = new ThreeBSP(lead);
var lastLeadBsp = new ThreeBSP(lastLead);

这样就得到两个bsp对象 leadBsplastLeadBsp

再进行裁切和模型材质赋值

function handleBsp(firstBSP: any, secondBSP: any, type: string) {
  // 进行相减计算  前面的减去与后面进行交叉计算
  var mesh
  if(type === 'intersect') {
    mesh = firstBSP.intersect(secondBSP);
  }
  if (type === 'subtract') {
    mesh = firstBSP.subtract(secondBSP);
  }

  // 将裁剪的模块转为object
  var intersectResult = mesh.toMesh();

  //更新模型的面和顶点的数据
  intersectResult.geometry.computeFaceNormals();
  intersectResult.geometry.computeVertexNormals();

  // 判断是否存在顶点信息
  if (intersectResult.geometry.vertices.length > 0) {
    //重新赋值一个纹理
    var material = new THREE.MeshNormalMaterial();
    intersectResult.material = material;
    return intersectResult
  }
}

将计算好的结果 返回给initGame方法,再进行处理

const intersectResult = handleBsp(leadBsp, lastLeadBsp, 'intersect')
meshList.push(intersectResult)

得到的结果

透明区域是抬高位置的底板

接下来处理多余的部分(无效区域)

方法是相同的 传不同的参数即可

然后通过有效区域,将下一次的主角定位有效区域的尺寸

接下来就是将此次的有效区域克隆clone一份,作为下一次的主角

this.leadCube = meshArr[0].clone()

之前计算的位置关系再赋值给克隆的主角,

奇数在右侧出现的,修改z值位置,偶数在左侧出现的,修改x值

y值跟第一次创建主角时候使用同一种计算方式

let nextPosition = this.leadCube.position.clone()
// 奇数在右侧出现的,修改z值位置,偶数在左侧出现的,修改x值
if (flag) {
  nextPosition.setX(sx)
} else {
  nextPosition.setZ(sz)
}
nextPosition.setY(y)
this.leadCube.position.copy(nextPosition)

下面需要计算终点位置

同样 如果是奇数 从右侧来,不改变z值 如果是偶数 从左侧来 不改变x值

堆叠几次之后的效果

那么接下来需要做一下无效区域的下落动画(非物理运动)

自由落体单独写吧,挺复杂的,游戏开发接近尾声,剩下记分器,镜头移动等其他功能

3D堆叠游戏——第一步 基础 初始化游戏

3D堆叠游戏——第二步 控制 控制主角移动以及停止