跳跃动画实现
- objects/bottle.js
import gameConf from '../../confs/game-conf'
constructor () {
//物体跳跃参数
this.status = 'stop'
this.velocity = {
vx: 0, // 水平方向速度
vy: 0 //竖直方向速度
}
this.flyingTime = 0
this.direction = 0
this.scale = 1
}
update() {//实时刷新
if (this.status == 'shrink') {//点击时收缩
this._shrink()
} else if (this.status == 'jump') {//点击释放时跳跃
//计算释放时间与点击时间差值
const tickTime = Date.now() - this.lastFrameTime
this._jump(tickTime)
}
this.head.rotation.y += 0.06
this.lastFrameTime = Date.now()//上帧时间
}
shrink () {//改变物体状态(静止或收缩或跳跃)
this.status = 'shrink'
}
_shrink () {//具体如何收缩实现
const DELTA_SCALE = 0.005//每帧收缩幅度
const HORIZON_DELTA_SCALE = 0.007
const HEAD_DELTA = 0.03
const MIN_SCALE = 0.55
this.scale -= DELTA_SCALE
this.scale = Math.max(MIN_SCALE, this.scale)
if (this.scale <= MIN_SCALE) {//最小值限制
return
}
this.body.scale.y = this.scale
this.body.scale.x += HORIZON_DELTA_SCALE
this.body.scale.z += HORIZON_DELTA_SCALE
this.head.position.y -= HEAD_DELTA
const bottleDeltaY = HEAD_DELTA / 2
const deltaY = blockConf.height * DELTA_SCALE / 2
this.obj.position.y -= (bottleDeltaY + deltaY * 2)
}
jump (duration) {//改变物体状态(静止或收缩或跳跃)
this.status = 'jump'
}
_jump(tickTime) {//具体跳跃实现(传参:点击与释放的间隔时间)添加game-conf
const t = tickTime / 1000
this.flyingTime = this.flyingTime + t//
const translateH = this.velocity.vx * t
const translateY = this.velocity.vy * t - 0.5 * gameConf.gravity * t * t - gameConf.gravity * this.flyingTime * t
this.obj.translateY(translateY)
this.obj.translateOnAxis(this.axis, translateH)
// console.log('跳跃完成')
}
stop () {//停止跳跃
this.status = 'stop'
this.velocity = {
vx: 0, // 水平方向速度
vy: 0 //竖直方向速度
}
this.flyingTime = 0
this.scale = 1
}
setDirection (direction, axis) {//设置跳跃方向
this.direction = direction
this.axis = axis
}
rotate () {//物体旋转点击释放时调用
const scale = 1.4
this.human.rotation.z = this.human.rotation.x = 0
if (this.direction == 0) { // x
customAnimation.to(this.human.rotation, 0.14, { z: this.human.rotation.z - Math.PI })
customAnimation.to(this.human.rotation, 0.18, { z: this.human.rotation.z - 2 * Math.PI, delay: 0.14 })
customAnimation.to(this.head.position, 0.1, { y: this.head.position.y + 0.9 * scale, x: this.head.position.x + 0.45 * scale })
customAnimation.to(this.head.position, 0.1, { y: this.head.position.y - 0.9 * scale, x: this.head.position.x - 0.45 * scale, delay: 0.1 })
customAnimation.to(this.head.position, 0.15, { y: 7.56, x: 0, delay: 0.25 })
customAnimation.to(this.body.scale, 0.1, { y: Math.max(scale, 1), x: Math.max(Math.min(1 / scale, 1), 0.7), z: Math.max(Math.min(1 / scale, 1), 0.7) })
customAnimation.to(this.body.scale, 0.1, { y: Math.min(0.9 / scale, 0.7), x: Math.max(scale, 1.2), z: Math.max(scale, 1.2), delay: 0.1 })
customAnimation.to(this.body.scale, 0.3, { y: 1, x: 1, z: 1, delay: 0.2 })
} else if (this.direction == 1) { // z
customAnimation.to(this.human.rotation, 0.14, { x: this.human.rotation.x - Math.PI })
customAnimation.to(this.human.rotation, 0.18, { x: this.human.rotation.x - 2 * Math.PI, delay: 0.14 })
customAnimation.to(this.head.position, 0.1, { y: this.head.position.y + 0.9 * scale, z: this.head.position.z - 0.45 * scale })
customAnimation.to(this.head.position, 0.1, { z: this.head.position.z + 0.45 * scale, y: this.head.position.y - 0.9 * scale, delay: 0.1 })
customAnimation.to(this.head.position, 0.15, { y: 7.56, z: 0, delay: 0.25 })
customAnimation.to(this.body.scale, 0.05, { y: Math.max(scale, 1), x: Math.max(Math.min(1 / scale, 1), 0.7), z: Math.max(Math.min(1 / scale, 1), 0.7) })
customAnimation.to(this.body.scale, 0.05, { y: Math.min(0.9 / scale, 0.7), x: Math.max(scale, 1.2), z: Math.max(scale, 1.2), delay: 0.1 })
customAnimation.to(this.body.scale, 0.2, { y: 1, x: 1, z: 1, delay: 0.2 })
}
}
- pages/game.js
bindTouchEvent(){//绑定监听事件
canvas.addEventListener('touchstart',this.touchStartCallback)
canvas.addEventListener('touchend',this.touchEndCallback)
}
removeTouchEvent () {//解除监听事件
console.log('remove touch event')
canvas.removeEventListener('touchstart', this.touchStartCallback)
canvas.removeEventListener('touchend', this.touchEndCallback)
}
touchStartCallback = (e) => {//用箭头函数确保this指向正确
this.touchStartTime = Date.now()
this.state = 'prepare'
this.bottle.shrink()
}
touchEndCallback = (e) => {
this.touchEndTime = Date.now()
const duration = this.touchEndTime - this.touchStartTime
this.bottle.velocity.vx = Math.min(duration / 6, 400)
this.bottle.velocity.vx = +this.bottle.velocity.vx.toFixed(2)
this.bottle.velocity.vy = Math.min(150 + duration / 20, 400)
this.bottle.velocity.vy = +this.bottle.velocity.vy.toFixed(2)
this.state = 'jump'//开启跳跃
this.bottle.rotate()//开启旋转
this.bottle.jump(duration)
// this.updateNextBlock()
}
setDirection (direction) {//设置跳跃方向,在Blockinit中加载
const currentPosition = {
x: this.bottle.obj.position.x,
z: this.bottle.obj.position.z
}
this.axis = new THREE.Vector3(this.targetPosition.x - currentPosition.x, 0, this.targetPosition.z - currentPosition.z)
this.axis.normalize()
this.bottle.setDirection(direction, this.axis)
}
在addInitBlock中
//设置跳跃方向
const initDirection = 0
this.targetPosition = {
x: 23,
y: 0,
z: 0
}
this.setDirection(initDirection)