[GET]ThreeJS + TweenJS模拟微信跳一跳粒子效果

上接翻转移动动画文章。

在下在实现移动动画的基础上,又去尝试了一下使用ThreeJS实现粒子效果,其过程异常头大。

这个是微信里的特效
这里写图片描述

设计思路

  • 生成粒子
  • 设置位置
  • 控制粒子移动

错误示范
这里写图片描述

通过错误示范,可以看到所生成的红色粒子,没有按照预想的状态去移动,而是产生了自己的移动方式。

之所以会出现这种情况,是因为在此之前在下没有考虑坐标系的缘故,将场景中所有方块的坐标系统一认定为世界坐标(粒子绑定在Player身上)。

之后在下在了解了以下坐标系以后,对整个代码进行了修整。

正确示范

首先是创建粒子,创建8个粒子,并且给定初始位置

这里的位置并没有选择用随机,因为考虑最后的实现效果
在下在类外面定义了一个常量数组,用来存储固定的粒子位置

  • this.geometry.vertices 用于存储粒子的位置
  • this.particles 粒子的节点
// 创建粒子
    CreatorParticles() {
        this.geometry = new THREE.Geometry();
        let vertext = null;
        for (let i = 0; i < 8; i++) {
            vertext = new THREE.Vector3(pos[i][0],pos[i][1],pos[i][2]);
            this.geometry.vertices.push(vertext);
        }
        let loader = new THREE.TextureLoader();
        let sprite = loader.load('./img/brick1.jpg');
        let color = [1, 0, 0];
        let size = 1;
        let pointsMaterial = new THREE.PointsMaterial({
            size: size,
            map: sprite,
            depthTest: false,
            transparent: true,
            opacity: 1.0,
            blending: THREE.AdditiveBlending
        });
        pointsMaterial.color.setRGB(color[0], color[1], color[2]);
        this.particles = new THREE.Points(this.geometry, pointsMaterial);
        this.particles.verticesNeedUpdate = true;
        this.play.add(this.particles);
        this.particles.position.set(0, 0, 0)
        this.particles.visible = false;
    }

这里是粒子的固定位置,0~7,最后一位是粒子向上的固定位置

// 粒子固定位置
const pos = [
    [-1,3,0],
    [0,2,0],
    [0,3,0],
    [0,3,-1],
    [1,3,-1],
    [2,2,0],
    [1,2,-2],
    [-1,1,0],
    [0, 0, -1]
]

做好了生成,边去考虑如何移动。
这里我是使用TweenJS去实现所有个粒子的移动

首先是向下的持续粒子效果

  • _obj是接收粒子当前位置
  • _int是指当前粒子在this.geometry.vertices中的下标
// 粒子移动
    ParticlesMove(_obj, _int) {
        let self = this;
        let endP = {
            x: _obj.x,
            y: _obj.y,
            z: _obj.z,
        }
        this.ParticlesTween = new TWEEN.Tween(endP);
        this.ParticlesTween.to({
            x: 0,
            y: 0,
            z: -1,
        },200);

        this.ParticlesTween.start();
        function onUpdate() {
            if(!self.switchTween) {
                self.ParticlesTween.stop();
            } else {
                self.geometry.verticesNeedUpdate = true;
                self.geometry.vertices[_int].x = this.x;
                self.geometry.vertices[_int].y = this.y;
                self.geometry.vertices[_int].z = this.z;
            }
        }
        function onComplete() {
            // self.particles.visible = true;
            if(self.switchTween) {
                self.geometry.verticesNeedUpdate = true;
                self.geometry.vertices[_int].x = pos[_int][0];
                self.geometry.vertices[_int].y = pos[_int][1];
                self.geometry.vertices[_int].z = pos[_int][2];
                self.ParticlesMove(self.geometry.vertices[_int], _int);
            } else {

            }
        }

        this.ParticlesTween.onUpdate(onUpdate);
        this.ParticlesTween.onComplete(onComplete);
    }

在动画播放结束方法onComplete()中,在不满足条件的的前提下持续回粒子移动方法ParticlesMove()

重点注意
这里我在做移动的时候吃了极大的亏
self.geometry.verticesNeedUpdate = true;
请注意这一段,在控制移动时,一定要告诉渲染器,我粒子需要移动,否则,粒子更改了位置信息,但是显示不会发生变化

经过这段移动代码,便实现了这样的效果:
这里写图片描述

GIF可能看不出效果
他是一个持续向下一个点的粒子效果

最后要做的就是实现向上的粒子特效

同样使用TweenJS去做

传入的参数同上

ParticlesMove2(_obj, _int) {
        let self = this;
        let endP = {
            x: _obj.x,
            y: _obj.y,
            z: _obj.z,
        }
        this.ParticlesTween2 = new TWEEN.Tween(endP);

        this.ParticlesTween2.to({
            x: pos[_int][0],
            y: pos[_int][1],
            z: pos[_int][2],
        }, 500);

        this.ParticlesTween2.start();
        function onUpdate() {
            self.geometry.vertices[_int].x = this.x;
            self.geometry.vertices[_int].y = this.y;
            self.geometry.vertices[_int].z = this.z;
            self.geometry.verticesNeedUpdate = true;
        }
        function onComplete() {
            self.particles.visible = false;
        }

        this.ParticlesTween2.onUpdate(onUpdate);
        this.ParticlesTween2.onComplete(onComplete);
    }

向上的效果:
这里写图片描述

只有一瞬间的效果,因此不再需要持续调用

总结
虽然最后实现了这样一个效果,但是与微信的相比还是差距很大(看到的大厂的实力)

对于小游戏或者技术实现玩一玩这个东西还是不错的
= =、

若有错误,欢迎指出。

开源万岁
Mr.YingS

[email protected]

猜你喜欢

转载自blog.csdn.net/ajicom/article/details/82181825
今日推荐