主题列表:juejin, github, smartblue, cyanosis, channing-cyan, fancy, hydrogen, condensed-night-purple, greenwillow, v-green, vue-pro, healer-readable, mk-cute, jzman, geek-black, awesome-green
贡献主题:https://github.com/xitu/juejin-markdown-themes
theme: juejin
highlight:
上一篇写的是裁切主角分为有效区域和无效区域
有效区域作为底板放置在场景内,无效区域做自由落体下落并删除
镜头跟进
在每放置一块主角的时候镜头随之向上移动
typescript 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) }) }
游戏结束判定
判定游戏结束 首先判定底板和主角没有交集,就是裁切的有效区域的顶点信息为空
typescript intersectResult.geometry.vertices.length > 0
另一种情况是未操作空格进行放置 就是主角运动结束而没有点击的情况
判定游戏结束后,将镜头拉至全景
将场景下所有内容展现出来
记分环节
记分可以按照堆叠高度计算 也可以按照堆叠数量计算 可以按照剩余总面积计算
咱们搞个高难度的,按照搭建表面积计算
每次叠加的有效区域表面积相加得出记分结果
通过box3得到有效区域的尺寸,再将每个有效区域记录在页面
计算有效区域的方法之前封装过getsize
,继续使用这个再次封装一个getarea
typescript export function getArea(mesh):number { const size = new THREE.Vector3() getSize(mesh, size) const area = Math.floor(size.x * size.z) return area }
页面上需要一个dom节点用来呈现分数 typescript fractionDom:HTMLElement = document.querySelector('#fraction')
给dom节点赋值 typescript upDateFraction(){ this.fractionDom.innerText = this.areaCount + '' }
制作开始按钮
开始按钮功能
typescript 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 功能 将变量重置之后,拉近镜头,调整视角,重新绘制主角
typescript 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
然后就不报错啦
也可以直接写本身,看需求呗
其实可以兼容一下移动端,毕竟手游目前比较受欢迎啊