上接翻转移动动画文章。
在下在实现移动动画的基础上,又去尝试了一下使用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