ThreeJS + TweenJS实现跳一跳翻转移动动画

最近在公司写H5的3D游戏,选择了ThreeJS去做,做的过程中遇到了很多问题,其中最值得思考的问题就是实现翻转及移动这个动作的小问题。

模拟跳一跳游戏的翻转及移动,实现这个动作,首先要考虑到这么几个问题:

  • 基于哪一个轴去做旋转
  • 基于哪一个轴去做移动

这个两个问题其实并不难,稍微用过3D引擎或者做过3D项目的开发都知道这个问题,如果是向左边跳,那么就要基于z轴旋转,x轴移动;反之,如果是向右边跳,就要基于x轴旋转,z轴移动。

若要体现出弧度的效果,就可以在y轴上动动手脚。

解决完这三个问题,就可以直接上手去做。

回忆一下Unity中如何去做这个问题,去定好Player的锚点位置,已锚点为中心去做出动作,OK,很简单。

如果是这么想的,那么可能在 Three+Tween中遇到一个不小的麻烦。

重点注意
Scene中的每一个物体的中心点都是基于世界坐标,也就是说他们只有一个中心点,就是世界坐标,你做出的所有动作都是基于世界坐标去实现的。

那么这里就很产生一个问题,如果按照正常的逻辑思维去做的话(左边为例):
y轴上移,z轴旋转,x轴移动;
这么实现会在场景中制造出一个大风车,样式非常奇怪。

以下是在下的解决方案
这里写图片描述

1、创建Scene、Player、Cubes

初始化函数(调用的方法均用类封装完成,基础问题不多概述)

扫描二维码关注公众号,回复: 2841533 查看本文章
Init() {
        this._checkUserAgent();
        this._addScene();
        this._addHelper();
        this._setLight();
        this._addCube();
        this._addCube();
        this._addPlayer();
        this._setCamera();
        this._setRenderer();
        this._setListen();
        this.update();
    }

1、使用Tween创建动画

创建翻转移动动画

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

邮箱:[email protected]

猜你喜欢

转载自blog.csdn.net/ajicom/article/details/81806286