[GET]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

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

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

邮箱:aji@fristd.com

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
是的,three.jstween.js可以一起使用,实现复杂的动画效果,包括飞线动画。以下是一个简单的例子,演示了如何使用three.jstween.js创建一条飞线动画: ```javascript // 创建three.js场景 var scene = new THREE.Scene(); // 创建相机 var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); camera.position.z = 5; // 创建渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // 创建飞线路径 var curve = new THREE.CatmullRomCurve3([ new THREE.Vector3(-10, 0, 0), new THREE.Vector3(-5, 5, 0), new THREE.Vector3(0, 0, 0), new THREE.Vector3(5, -5, 0), new THREE.Vector3(10, 0, 0) ]); // 创建飞线材质 var material = new THREE.LineBasicMaterial({ color: 0xffffff }); // 将飞线路径转换为几何体 var geometry = new THREE.Geometry(); geometry.vertices = curve.getPoints(50); // 创建飞线网格 var line = new THREE.Line(geometry, material); scene.add(line); // 创建飞线动画 var tween = new TWEEN.Tween({t:0}) .to({t:1}, 5000) // 5秒钟 .onUpdate(function() { // 根据tween的进度计算飞线的位置 var position = curve.getPoint(this.t); // 更新飞线网格的位置 line.position.copy(position); }) .start(); // 渲染场景 function render() { requestAnimationFrame(render); TWEEN.update(); // 更新tween动画 renderer.render(scene, camera); } render(); ``` 在这段代码中,我们首先创建了一个three.js场景、相机和渲染器。然后,我们创建了一个CatmullRomCurve3曲线,用于定义飞线路径,并将其转换为three.js几何体。接下来,我们创建了一个TWEEN.Tween对象,将其起始值设置为0,结束值设置为1,表示飞线动画的进度。在Tween对象的 onUpdate 回调函数中,我们根据飞线路径计算当前进度对应的位置,并将飞线网格的位置更新为该位置。最后,我们创建了一个渲染函数,用于在每帧更新Tween动画和渲染场景。 希望这个例子可以帮助你了解如何使用three.jstween.js创建飞线动画
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值