如何让 Pixi 粒子在设置为脊柱动画内的插槽的 child 时正常运行
How to get Pixi Particles to behave properly when set as a child of a slot inside of a spine animation
protected createParticleAnimation ( data: IAnticipationParticle ): particles.Emitter {
let particleResource = PIXI.loader.resources[ data.name ].data;
let particleImages: Array<Texture> = new Array<Texture>();
let container = new particles.ParticleContainer();
container.scale.set( 1, -1 );
let spineAnim = this.anticipationAnimations[ 0 ] as spine.Spine;
spineAnim.slotContainers.forEach( ( slotContainer: Container ) => {
if ( slotContainer.name == 'CoinParticles' ) {
container.position.set( slotContainer.children[ 0 ].x * 2, slotContainer.children[ 0 ].y * 2 );
slotContainer.addChild( container );
return;
}
} );
data.images.forEach( ( image: string ) => {
particleImages.push( PIXI.Texture.fromImage( image ) );
} );
let animation = new PIXI.particles.Emitter(
container,
particleImages,
particleResource
);
animation.emit = false;
animation.autoUpdate = true;
return animation;
}
因此,我在另一个函数中创建了脊椎动画,然后创建了如上所示的粒子效果,并将其附加到脊椎动画内的 slotContainer。但是当我的脊椎动画播放时,粒子总是跟随 parents 位置并且不保持它们的世界坐标。
我认为这是因为脊椎问题,但有人知道如何解决这个问题吗?
例如,当发射器移动时,已经生成的粒子会跟随发射器的 x 位置
所以我最终需要覆盖 pixi 容器的 updateTransform 方法。
我将发射器传递给容器,以便它可以更新其变换。
当我这样做时,我需要计算精灵的原始点。
这需要在创建发射器后调用,因为容器需要传递到发射器的创建中。
然后您需要将容器变换移回原来的位置,以便子项(粒子)可以正常运行。然后将发射器的生成位置与父项一起移动。
import { particles, Point } from 'pixi.js';
/**
* A container to be used when attaching a particle emitter to a spine animation
*/
export class SpineParticleContainer extends particles.ParticleContainer {
/**The emitter that is drawning to the container */
protected emitter: particles.Emitter;
/**The original position of the sprite when the emitter is set */
protected origin: Point;
constructor () {
super();
}
/**
* Sets the containers emittter so it can update the emitters position
* @param emiter The particle emitter to pass in, this should be the particle emitter assigned to this container already
*/
public setEmitter ( emiter: particles.Emitter ): void {
this.emitter = emiter;
this.origin = new Point( this.parent.worldTransform.tx, this.parent.worldTransform.ty );
}
/**Override update transform to reposition the container at its origin position and move the emitter along with the animation */
public updateTransform () {
this._boundsID++;
this.worldAlpha = this.alpha * this.parent.worldAlpha;
let position = new Point( this.parent.worldTransform.tx, this.parent.worldTransform.ty );
let newPosition = new Point( this.origin.x - position.x, this.origin.y - position.y );
this.position.set( newPosition.x, newPosition.y );
this.transform.updateTransform( this.parent.transform );
for ( let i = 0, j = this.children.length; i < j; i++ ) {
const child = this.children[ i ];
if ( child.visible ) {
child.updateTransform();
}
}
this.emitter.spawnPos.set( this.parent.worldTransform.tx, this.parent.worldTransform.ty );
}
}
protected createParticleAnimation ( data: IAnticipationParticle ): particles.Emitter {
let particleResource = PIXI.loader.resources[ data.name ].data;
let particleImages: Array<Texture> = new Array<Texture>();
let container = new particles.ParticleContainer();
container.scale.set( 1, -1 );
let spineAnim = this.anticipationAnimations[ 0 ] as spine.Spine;
spineAnim.slotContainers.forEach( ( slotContainer: Container ) => {
if ( slotContainer.name == 'CoinParticles' ) {
container.position.set( slotContainer.children[ 0 ].x * 2, slotContainer.children[ 0 ].y * 2 );
slotContainer.addChild( container );
return;
}
} );
data.images.forEach( ( image: string ) => {
particleImages.push( PIXI.Texture.fromImage( image ) );
} );
let animation = new PIXI.particles.Emitter(
container,
particleImages,
particleResource
);
animation.emit = false;
animation.autoUpdate = true;
return animation;
}
因此,我在另一个函数中创建了脊椎动画,然后创建了如上所示的粒子效果,并将其附加到脊椎动画内的 slotContainer。但是当我的脊椎动画播放时,粒子总是跟随 parents 位置并且不保持它们的世界坐标。
我认为这是因为脊椎问题,但有人知道如何解决这个问题吗?
例如,当发射器移动时,已经生成的粒子会跟随发射器的 x 位置
所以我最终需要覆盖 pixi 容器的 updateTransform 方法。
我将发射器传递给容器,以便它可以更新其变换。 当我这样做时,我需要计算精灵的原始点。 这需要在创建发射器后调用,因为容器需要传递到发射器的创建中。
然后您需要将容器变换移回原来的位置,以便子项(粒子)可以正常运行。然后将发射器的生成位置与父项一起移动。
import { particles, Point } from 'pixi.js';
/**
* A container to be used when attaching a particle emitter to a spine animation
*/
export class SpineParticleContainer extends particles.ParticleContainer {
/**The emitter that is drawning to the container */
protected emitter: particles.Emitter;
/**The original position of the sprite when the emitter is set */
protected origin: Point;
constructor () {
super();
}
/**
* Sets the containers emittter so it can update the emitters position
* @param emiter The particle emitter to pass in, this should be the particle emitter assigned to this container already
*/
public setEmitter ( emiter: particles.Emitter ): void {
this.emitter = emiter;
this.origin = new Point( this.parent.worldTransform.tx, this.parent.worldTransform.ty );
}
/**Override update transform to reposition the container at its origin position and move the emitter along with the animation */
public updateTransform () {
this._boundsID++;
this.worldAlpha = this.alpha * this.parent.worldAlpha;
let position = new Point( this.parent.worldTransform.tx, this.parent.worldTransform.ty );
let newPosition = new Point( this.origin.x - position.x, this.origin.y - position.y );
this.position.set( newPosition.x, newPosition.y );
this.transform.updateTransform( this.parent.transform );
for ( let i = 0, j = this.children.length; i < j; i++ ) {
const child = this.children[ i ];
if ( child.visible ) {
child.updateTransform();
}
}
this.emitter.spawnPos.set( this.parent.worldTransform.tx, this.parent.worldTransform.ty );
}
}