上一篇写的是裁切主角分为有效区域和无效区域
有效区域作为底板放置在场景内,无效区域做自由落体下落并删除
镜头跟进
在每放置一块主角的时候镜头随之向上移动
moveCamera(){
// 定义控制器target的y值
const oldty = this.controls.target.y
const newty = oldty + 1 // 每一次向上移动1
console.log(oldty, newty)
let tween:any = NumberAnimate(oldty, newty, 100)
tween.onUpdate(()=>{
this.controls.target.setY(tween._object.p)
})
}
游戏结束判定
判定游戏结束 首先判定底板和主角没有交集,就是裁切的有效区域的顶点信息为空
intersectResult.geometry.vertices.length > 0
另一种情况是未操作空格进行放置 就是主角运动结束而没有点击的情况
判定游戏结束后,将镜头拉至全景
将场景下所有内容展现出来
记分环节
记分可以按照堆叠高度计算 也可以按照堆叠数量计算 可以按照剩余总面积计算
咱们搞个高难度的,按照搭建表面积计算
每次叠加的有效区域表面积相加得出记分结果
通过box3得到有效区域的尺寸,再将每个有效区域记录在页面
计算有效区域的方法之前封装过getsize
,继续使用这个再次封装一个getarea
export function getArea(mesh):number {
const size = new THREE.Vector3()
getSize(mesh, size)
const area = Math.floor(size.x * size.z)
return area
}
页面上需要一个dom节点用来呈现分数
fractionDom:HTMLElement = document.querySelector('#fraction')
给dom节点赋值
upDateFraction(){
this.fractionDom.innerText = this.areaCount + ''
}
制作开始按钮
开始按钮功能
const mark: HTMLElement = document.querySelector('#mark')
const startBtn: HTMLElement = document.querySelector('#start-game')
console.log(mark, startBtn)
if (mark && startBtn) {
console.log(startBtn)
startBtn.onclick = function () {
mark.style.display = 'none'
// 缩放镜头
createGame.restart()
}
}
restart 功能 将变量重置之后,拉近镜头,调整视角,重新绘制主角
restart() {
if (this.isOver) {
this.floorGroup.remove(...this.floorGroup.children)
this.leadCount = 0
this.leadCube = null
this.tween = null
this.T = 2000
this.flag = false
this.isOver = false // 是否游戏结束
this.areaCount = 0 // 分数
this.upDateFraction()
this.scene.updateMatrix()
this.initFloor()
}
this.undateCameraZoom(5.5, () => {
// 开始创建第一个主角
this.createlead()
})
}
结束
游戏开发到次就差不多完事了,剩下的就是一些代码的规范了
ts中尽量不要出现any这种类型规范
以接口为例
interface Element {
scene: THREE.Object3D
camera: THREE.OrthographicCamera
controls: OrbitControls
}
constructor(element: Element) {
this.scene = element.scene
this.camera = element.camera
this.controls = element.controls
this.floorGroup = new THREE.Group()
this.scene.add(this.floorGroup)
this.initFloor()
window.addEventListener('keydown', this.leadStop.bind(this))
}
如果要规定一个three元素类型 比如scene 场景,就可以在官网上看scene的基类是哪个
它的基类是object3d 所以可以用THREE.Object3D
对它进行约束
如果你使用的方法在基类中没有 比如scene的autoUpdate
这个方法是在自己本身的
那么就需要将值规范为 THREE.Scene
scene: THREE.Scene
然后就不报错啦
也可以直接写本身,看需求呗
其实可以兼容一下移动端,毕竟手游目前比较受欢迎啊