接上一篇文章
上一篇游戏功能做到主角的动画以及控制
在进行下一次主角出现之前需要做很多工作。第一步先对主角进行切割
分出在有效范围内和有效范围外的模型
将有效范围内放置到场景内,有效范围外的模型做自由落体
切割主要用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对象 leadBsp
和lastLeadBsp
再进行裁切和模型材质赋值
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值
堆叠几次之后的效果
那么接下来需要做一下无效区域的下落动画(非物理运动)
自由落体单独写吧,挺复杂的,游戏开发接近尾声,剩下记分器,镜头移动等其他功能