在上一篇文章中制作了游戏的第一步创建基础 这一篇将制作游戏第二步,控制主角
主角移动主要使用TWEEN
作为动画引擎
因为不是介绍tweenjs所以这里不提基础用法,如果有需要可以留言,专门研究一下
这个是封装好的动画
const TWEEN = require("@tweenjs/tween.js");
export class Animate {
tween
constructor(mesh:any, e:any, t:number) {
this.tween = new TWEEN.Tween(mesh.position)
this.tween.to(e, t)
this.tween.start()
}
}
很简单,从起始vector3向量到结束vector3向量
调用动画还需要在render
方法中对动画进行更新
// 渲染
render(): void {
this.animate()
this.renderer.render(this.scene, this.camera);
this.controls.update();
TWEEN.update();
}
控制主角动画
参数为起始点为主角position
终点为计算后结果,运动时间 T:number = 5000 // 主角运动时间,随着高度增加而衰减
// 控制主角
leadHandle() {
// 控制移动
const lead = this.leadCube
// 动画起始点
const start = lead.position
let ex = lead.position.x
let ez = lead.position.z
ex = ex === this.size / 2 ? this.size / 2 : (Math.abs(ex) + this.offset)
ez = ez === this.size / 2 ? this.size / 2 : (Math.abs(ez) + this.offset)
// 动画结束点
const end = new THREE.Vector3(ex, start.y, ez)
console.log(start, end)
// 开启主角动画
// 每增加一层减100毫秒 难度增加
const t = Math.max(this.T - this.leadCount * 100, 1000)
this.tween = new Animate(this.leadCube, end, t)
}
操作控制
游戏使用空格控制主角暂停和其他操作
监听一下keydown
事件
window.addEventListener('keydown', this.leadStop.bind(this))
主角停止事件
// 主角停止
leadStop(event) {
// 判断是否点击空格
if (event.keyCode === 32) {
if (this.tween) {
// 暂停动画
this.tween.tween.stop()
this.tween = null
// 生成下一个主角
this.createlead()
}
}
}
目前游戏效果是这样的
目前生成下一个角色只有在点击空格之后,所以还需要一个是主角运动结束 再生成下一个主角
this.tween.tween.onComplete(this.leadOperation.bind(this))
leadOperation方法
// 对主角进行处理,包括生成新的主角,裁切主角,重绘底板等
leadOperation(){
// 生成下一个主角
this.createlead()
}
之后的文章会写到裁切功能,自由落体,游戏结束等
initGame目前完整代码
const THREE = require("three");
import { createCube } from '../utils/tools'
import { getSize, getPosition } from '../utils/getBox'
// 引入封装好的动画
import { Animate } from '../utils/animate'
class CreateGame {
scene: any
floorCube: any // 初始底板
floorGroup: any // 底板组
size: number = 30 // 主角宽度和长度
leadY: number = 5 // 主角高度
leadCount: number = 0 // 计数器
startPoint: number = 60 // 主角起始位置 x或z
leadInterval: any = null // 循环
leadCube: any = null // 主角
tween: any = null // 动画
offset: number = 40 // 主角起始位置和终点位置偏移量
T:number = 500 // 主角运动时间,随着高度增加而衰减
constructor(element: any) {
this.scene = element.scene
this.floorGroup = new THREE.Group()
this.scene.add(this.floorGroup)
this.initFloor()
window.addEventListener('keydown', this.leadStop.bind(this))
}
initFloor() {
const w: number = this.size
const h: number = 50
const l: number = this.size
const floorParams = {
w: w,
h: h,
l: l,
x: w / 2,
y: h / 2,
z: l / 2
}
this.floorCube = createCube(floorParams)
this.floorGroup.add(this.floorCube)
this.floorGroup.updateMatrix()
}
createlead() {
const size = new THREE.Vector3()
const mesh = this.floorGroup
// 获取尺寸
getSize(mesh, size)
const position = new THREE.Vector3()
// 获取底板的位置 默认应该都是0
getPosition(mesh, position)
const gy = position.y // 底板的Y值
const y = size.y + gy + this.leadY / 2 // 主角的Y值
// 设定第奇数个主角从z轴的负方向来,第偶数个主角从X轴方向来
// 需要一个主角计数器,同样可以用来计算分数
// 起始点距离底板30
// 主角初始位置
const flag: boolean = this.leadCount % 2 === 0 // 是否是偶数主角
// x 起始点
let sx: number = (flag ? -this.startPoint - this.offset : 0) + this.size / 2
// z 起始点
let sz: number = (flag ? 0 : -this.startPoint - this.offset) + this.size / 2
// 创建一个主角
const leadParam = {
w: this.size,
h: this.leadY,
l: this.size,
x: sx,
y,
z: sz
}
this.leadCube = createCube(leadParam)
this.floorGroup.add(this.leadCube)
// 创建角色后计数器自增1
this.leadCount++
// 开始控制主角
// const startVector3 = new THREE.Vector3(sx,y,sz)
this.leadHandle()
}
// 控制主角
leadHandle():void {
// 控制移动
const lead = this.leadCube
// 动画起始点
const start = lead.position
let ex = lead.position.x
let ez = lead.position.z
ex = ex === this.size / 2 ? this.size / 2 : (Math.abs(ex) + this.offset)
ez = ez === this.size / 2 ? this.size / 2 : (Math.abs(ez) + this.offset)
// 动画结束点
const end = new THREE.Vector3(ex, start.y, ez)
console.log(start, end)
// 开启主角动画
// 每增加一层减100毫秒 难度增加
const t = Math.max(this.T - this.leadCount * 100, 1000)
this.tween = new Animate(this.leadCube, end, t)
if(this.tween) {
console.log(this.tween.tween)
this.tween.tween.onComplete(this.leadOperation.bind(this))
}
}
// 主角停止
leadStop(event):void {
// 判断是否点击空格
if (event.keyCode === 32) {
if (this.tween) {
// 暂停动画
this.tween.tween.stop()
this.tween = null
this.leadOperation()
}
}
}
// 对主角进行处理,包括生成新的主角,裁切主角,重绘底板等
leadOperation(){
// 生成下一个主角
this.createlead()
}
}
export { CreateGame }
代码可能有点粗糙,还望指正