十四、3D粒子特效

libGDX 3D 粒子特效可以通过 libgdx 中的 GUI 编辑器 Flame 进行编辑。可以在这里下载

粒子特效类型

  • Billboards :始终面向摄像机的精灵Sprite 图标。
  • PointSprites :画一个精灵 Sprite 到一个 3d 点上。
  • ModelInstances :3D 模型实例。这是性能最差的粒子特效类型。

使用3D粒子特效

使用 3D 粒子特效最简单的方法是使用 ParticleSystem 类,该类抽象出各种粒子的细节并方便管理它们。

当您将 ParticleEffect 类导入 IDE 时,请注意不要导入2d ParticleEffect 类。2D和3D的名称是一样的,3D的包为:com.badlogic.gdx.graphics.g3d.particles 里面

第一步:创建 Batches 和 ParticleSystem

ParticleSystem particleSystem = new ParticleSystem();
// 这里使用的粒子效果是 PointSprites,所以我们创建了一个 PointSpriteParticleBatch
PointSpriteParticleBatch pointSpriteBatch = new PointSpriteParticleBatch();
pointSpriteBatch.setCamera(cam);
particleSystem.add(pointSpriteBatch);

第二步:使用 AssetManager 加载特效

AssetManager assets = new AssetManager();
ParticleEffectLoader.ParticleEffectLoadParameter loadParam = new ParticleEffectLoader.ParticleEffectLoadParameter(particleSystem.getBatches());
assets.load("particle/effect.pfx", ParticleEffect.class, loadParam);
assets.finishLoading()

第三步:将 ParticleEffects 添加到 ParticleSystemPermalink

ParticleEffect originalEffect = assets.get("particle/effect.pfx");
// 不能使用原始效果,必须在每次创建新粒子特效时复制一个
ParticleEffect effect = originalEffect.copy();
effect.init();
effect.start();
particleSystem.add(effect);

在一个游戏中,很可能会有很多粒子效果,因此不希望每次创建一个对象或粒子特效时都需要的复制一个出来。相反,应该共享这些特效,以避免新对象的创建。这个可以通过 libGDX Pool 类来实现,示例如下:

private static class PFXPool extends Pool<ParticleEffect> {
	private ParticleEffect sourceEffect;

	public PFXPool(ParticleEffect sourceEffect) {
		this.sourceEffect = sourceEffect;
	}

	@Override
	public void free(ParticleEffect pfx) {
		pfx.reset();
		super.free(pfx);
	}

	@Override
	protected ParticleEffect newObject() {
		return sourceEffect.copy();
	}
}

第四步:使用 ParticleSystem 渲染粒子特效

一个 ParticleSystem 必须更新和绘制自己的组件,然后被传递给一个 ModelBatch 实例以呈现到场景中。

private void renderParticleEffects() {
	particleSystem.update(); // technically not necessary for rendering
	particleSystem.begin();
	particleSystem.draw();
	particleSystem.end();
	modelBatch.render(particleSystem);
}

你也可以像下面代码一样操作粒子特效:

private void renderParticleEffects() {
	targetMatrix.idt();
	targetMatrix.translate(targetPos);
	effect.setTransform(targetMatrix);
	particleSystem.update(); // technically not necessary for rendering
	particleSystem.begin();
	particleSystem.draw();
	particleSystem.end();
	modelBatch.render(particleSystem);
}

或者

private void renderParticleEffects() {
	effect.translate(deltaPos);
	particleSystem.update(); // technically not necessary for rendering
	particleSystem.begin();
	particleSystem.draw();
	particleSystem.end();
	modelBatch.render(particleSystem);
}

停止发射新的粒子,但是现有的粒子也要继续播放

Emitter emitter = pfx.getControllers().first().emitter;
if (emitter instanceof RegularEmitter) {
	RegularEmitter reg = (RegularEmitter) emitter;
	reg.setEmissionMode(RegularEmitter.EmissionMode.EnabledUntilCycleEnd);
}