最近在公司写H5的3D游戏,选择了ThreeJS去做,做的过程中遇到了很多问题,其中最值得思考的问题就是实现翻转及移动这个动作的小问题。
模拟跳一跳游戏的翻转及移动,实现这个动作,首先要考虑到这么几个问题:
这个两个问题其实并不难,稍微用过3D引擎或者做过3D项目的开发都知道这个问题,如果是向左边跳,那么就要基于z轴旋转,x轴移动;反之,如果是向右边跳,就要基于x轴旋转,z轴移动。
若要体现出弧度的效果,就可以在y轴上动动手脚。
解决完这三个问题,就可以直接上手去做。
回忆一下Unity中如何去做这个问题,去定好Player的锚点位置,已锚点为中心去做出动作,OK,很简单。
如果是这么想的,那么可能在 Three+Tween中遇到一个不小的麻烦。
重点注意
Scene中的每一个物体的中心点都是基于世界坐标,也就是说他们只有一个中心点,就是世界坐标,你做出的所有动作都是基于世界坐标去实现的。
那么这里就很产生一个问题,如果按照正常的逻辑思维去做的话(左边为例):
y轴上移,z轴旋转,x轴移动;
这么实现会在场景中制造出一个大风车,样式非常奇怪。
初始化函数(调用的方法均用类封装完成,基础问题不多概述)
Init() {
this._checkUserAgent();
this._addScene();
this._addHelper();
this._setLight();
this._addCube();
this._addCube();
this._addPlayer();
this._setCamera();
this._setRenderer();
this._setListen();
this.update();
}
创建翻转移动动画
playerClickTween(_str) {
let self = this;
let endP = null;
this.play.scale.y = 1;
if(_str === 'left') {
endP = {
r: 0,
y: Math.PI,
x: this.play.position.x,
z: this.play.position.z,
}
} else {
endP = {
r: Math.PI * 2,
y: Math.PI,
x: this.play.position.x,
z: this.play.position.z,
}
}
this.tween1 = new TWEEN.Tween(endP);
if(_str === 'left') {
this.tween1.to({
r: Math.PI * 2,
y: 0,
x: this.play.position.x + this.JumpLength,
z: this.cubes[this.cubes.length - 1].position.z + 1,
}, 750);
} else {
this.tween1.to({
r: 0,
y: 0,
x: this.cubes[this.cubes.length - 1].position.x,
z: this.play.position.z + this.JumpLength,
}, 750);
}
// this.tween2 = new TWEEN.Tween(endP);
this.tween1.start();
function onUpdate() {
if(_str === 'left') {
self.play.rotation.z = this.r;
self.play.position.y = Math.sin(this.y)* 10;
self.play.position.x = this.x;
self.play.position.z = this.z;
} else if(_str === 'right') {
self.play.rotation.x = this.r;
self.play.position.y = Math.sin(this.y)* 10;
self.play.position.z = this.z;
self.play.position.x = this.x;
}
}
this.tween1.onUpdate(onUpdate);
this.tween1.onComplete(onComplete);
// tweenBack.onUpdate(onUpdate);
}
主要在这里,首先Left不考虑移动x,Right不考虑移动z;
翻转依旧是按照之前的方法实现,Left基于z,Right基于x;
移动做了调整,让y基于三角函数sin去呈现弧度的效果,既做到了弧度,又完成了移动,且不受世界坐标的影响。
if(_str === 'left') {
self.play.rotation.z = this.r;
self.play.position.y = Math.sin(this.y)* 10;
self.play.position.x = this.x;
} else if(_str === 'right') {
self.play.rotation.x = this.r;
self.play.position.y = Math.sin(this.y)* 10;
self.play.position.z = this.z;
}
由此,实现了跳一跳中翻转的效果,和官方略有差别,对于细节可以慢慢去微调。
若有错误,欢迎指出。
开源万岁!
Mr.YingS