libgdx 2D 粒子效果

先贴几个文档链接:

https://github.com/libgdx/libgdx/wiki/2d-particle-effects

https://github.com/libgdx/libgdx/wiki/2D-Particle-Editor

http://www.java-gaming.org/topics/particle-effects-in-libgdx/29484/view.html

 

先贴个官网GitHub上的测试代码,代码和资源都可以去下。这里不能传附件??

  1 public class ParticleEmitterTest extends GdxTest {

  2     private SpriteBatch spriteBatch;

  3     ParticleEffect effect;

  4     int emitterIndex;

  5     Array<ParticleEmitter> emitters;

  6     int particleCount = 10;

  7     float fpsCounter;

  8     InputProcessor inputProcessor;

  9 

 10     @Override

 11     public void create () {

 12         spriteBatch = new SpriteBatch();

 13 

 14         effect = new ParticleEffect();

 15         effect.load(Gdx.files.internal("data/test.p"), Gdx.files.internal("data"));//第一个参数是粒子效果文件,第二个参数是图片basepath

 16         effect.setPosition(Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() / 2);

 17         // Of course, a ParticleEffect is normally just used, without messing around with its emitters.

 18         emitters = new Array(effect.getEmitters());//原笔者把多个效果都放在一个文件里了,为了显示需要,这里特殊处理了,如果注释掉这三行,可以看出,几个效果一起显示了

 19         effect.getEmitters().clear();

 20         effect.getEmitters().add(emitters.get(0));

 21 

 22         inputProcessor = new InputProcessor() {

 23             public boolean touchUp (int x, int y, int pointer, int button) {

 24                 return false;

 25             }

 26 

 27             public boolean touchDragged (int x, int y, int pointer) {

 28                 effect.setPosition(x, Gdx.graphics.getHeight() - y);

 29                 return false;

 30             }

 31 

 32             public boolean touchDown (int x, int y, int pointer, int newParam) {//改变粒子的个数,重新显示

 33                 // effect.setPosition(x, Gdx.graphics.getHeight() - y);

 34                 ParticleEmitter emitter = emitters.get(emitterIndex);

 35                 particleCount += 100;

 36                 System.out.println(particleCount);

 37                 particleCount = Math.max(0, particleCount);

 38                 if (particleCount > emitter.getMaxParticleCount()) emitter.setMaxParticleCount(particleCount * 2);

 39                 emitter.getEmission().setHigh(particleCount / emitter.getLife().getHighMax() * 1000);

 40                 effect.getEmitters().clear();

 41                 effect.getEmitters().add(emitter);

 42                 return false;

 43             }

 44 

 45             public boolean keyUp (int keycode) {

 46                 return false;

 47             }

 48 

 49             public boolean keyTyped (char character) {

 50                 return false;

 51             }

 52 

 53             public boolean keyDown (int keycode) {

 54                 ParticleEmitter emitter = emitters.get(emitterIndex);

 55                 if (keycode == Input.Keys.W)//我没找到原始的键,我改成W

 56                     particleCount += 5;

 57                 else if (keycode == Input.Keys.S)////我没找到原始的键,我改成S

 58                     particleCount -= 5;

 59                 else if (keycode == Input.Keys.SPACE) {

 60                     emitterIndex = (emitterIndex + 1) % emitters.size;

 61                     emitter = emitters.get(emitterIndex);

 62 

 63                     // if we've previously stopped the emitter reset it

 64                     if (emitter.isComplete()) emitter.reset();

 65                     particleCount = (int)(emitter.getEmission().getHighMax() * emitter.getLife().getHighMax() / 1000f);

 66                 } else if (keycode == Input.Keys.ENTER) {

 67                     emitter = emitters.get(emitterIndex);

 68                     if (emitter.isComplete())

 69                         emitter.reset();

 70                     else

 71                         emitter.allowCompletion();

 72                 } else

 73                     return false;

 74                 particleCount = Math.max(0, particleCount);

 75                 if (particleCount > emitter.getMaxParticleCount()) emitter.setMaxParticleCount(particleCount * 2);

 76                 emitter.getEmission().setHigh(particleCount / emitter.getLife().getHighMax() * 1000);

 77                 effect.getEmitters().clear();

 78                 effect.getEmitters().add(emitter);

 79                 return false;

 80             }

 81 

 82             @Override

 83             public boolean mouseMoved (int x, int y) {

 84                 return false;

 85             }

 86 

 87             @Override

 88             public boolean scrolled (int amount) {

 89                 return false;

 90             }

 91         };

 92 

 93         Gdx.input.setInputProcessor(inputProcessor);

 94     }

 95 

 96     @Override

 97     public void dispose () {

 98         spriteBatch.dispose();

 99         effect.dispose();//注意

100     }

101 

102     public void render () {

103         spriteBatch.getProjectionMatrix().setToOrtho2D(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());

104         float delta = Gdx.graphics.getDeltaTime();

105         Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

106         spriteBatch.begin();

107         effect.draw(spriteBatch, delta);//这里绘制粒子效果

108         spriteBatch.end();

109         fpsCounter += delta;

110         if (fpsCounter > 3) {

111             fpsCounter = 0;

112             int activeCount = emitters.get(emitterIndex).getActiveCount();

113             Gdx.app.log("libgdx", activeCount + "/" + particleCount + " particles, FPS: " + Gdx.graphics.getFramesPerSecond());

114         }

115     }

116 

117     public boolean needsGL20 () {

118         return false;

119     }

120 }

这只是测试代码,我们平时在使用的时候,几乎不这么用。

1. 大多数情况下我们都是用stage/actor结构的,不会在Screen里专门去draw粒子效果,或者说是很少情况下。

2. 效果文件在使用的时候大多数都是调好了的,不需要我们代码去调节那些参数。

3. ParticleEffectPool我还没看呢....

 

好,我们先在stage中尝试绘制一个粒子效果

其实只是自定义包装一个Actor类,在draw的时候,draw里面的effect就好了。

见代码:

 1 public class ParticleEffectActor extends Actor {

 2     ParticleEffect particleEffect;

 3     Vector2 acc = new Vector2();

 4     private static final Logger LOGGER = new Logger(ParticleEffectActor.class.getName(), Application.LOG_DEBUG);

 5     public ParticleEffectActor(ParticleEffect particleEffect) {

 6         super();

 7         this.particleEffect = particleEffect;

 8     }

 9 

10     @Override

11     public void draw(Batch batch, float parentAlpha) {

12         particleEffect.draw(batch);

13         //LOGGER.debug("draw");

14     }

15 

16     @Override

17     public void act(float delta) {

18         super.act(delta);

19         acc.set(getWidth() / 2, getHeight() / 2);

20         localToStageCoordinates(acc);

21         //LOGGER.debug(acc.toString());

22         particleEffect.setPosition(acc.x, acc.y);

23         particleEffect.update(delta);

24 

25     }

26 

27     public void start(){

28         particleEffect.start();

29     }

30 }

 

 

 1 public class ParticleTest extends ApplicationAdapter implements InputProcessor {

 2     private Stage stage;

 3     private ParticleEffect effect;

 4     private static final Logger LOGGER = new Logger(ParticleTest.class.getName(),Application.LOG_DEBUG);

 5     

 6     @Override

 7     public void create () {

 8         Gdx.app.setLogLevel(Application.LOG_DEBUG);

 9         stage = new Stage();

10         Gdx.input.setInputProcessor(this);

11         effect = new ParticleEffect();

12         effect.load(Gdx.files.internal("data/abc.p"), Gdx.files.internal("data"));//第一个参数是粒子效果文件,第二个参数是图片basepath(这里应该有一个默认的particle.png别忘了)

13 

14     }

15 

16     @Override

17     public void render () {

18         Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1);

19         Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

20         stage.act();

21         stage.draw();

22     }

23 

24     @Override

25     public void dispose() {

26         effect.dispose();

27         stage.dispose();

28         super.dispose();

29     }

30 

31     @Override

32     public void resize(int width, int height) {

33         stage.getViewport().update(width,height);

34         super.resize(width, height);

35     }

36 

37     private void addEffect(){

38         final ParticleEffectActor actor = new ParticleEffectActor(effect);

39 

40         actor.setPosition(0,0);

41 

42         MoveToAction action = Actions.moveTo(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), 4.0f);

43 

44         RunnableAction run = Actions.run(new Runnable() {

45             @Override

46             public void run() {

47                 stage.getActors().removeValue(actor, true);

48             }

49         });

50         actor.addAction(Actions.sequence(action,run));

51         actor.start();

52         stage.addActor(actor);

53     }

54 

55     @Override

56     public boolean keyDown(int keycode) {

57         if(keycode == Input.Keys.J){

58             addEffect();

59         }

60         return false;

61     }

62 

63     @Override

64     public boolean keyUp(int keycode) {

65         return false;

66     }

67 

68     @Override

69     public boolean keyTyped(char character) {

70         return false;

71     }

72 

73     @Override

74     public boolean touchDown(int screenX, int screenY, int pointer, int button) {

75         return false;

76     }

77 

78     @Override

79     public boolean touchUp(int screenX, int screenY, int pointer, int button) {

80         return false;

81     }

82 

83     @Override

84     public boolean touchDragged(int screenX, int screenY, int pointer) {

85         return false;

86     }

87 

88     @Override

89     public boolean mouseMoved(int screenX, int screenY) {

90         return false;

91     }

92 

93     @Override

94     public boolean scrolled(int amount) {

95         return false;

96     }

97 }

 

以上代码中,我们在按下J键的时候,在stage中添加一个粒子效果actor,这个actor从左下角开始向右上角移动,4秒。

注意actor的start方法,官方粒子的素材不需要就可以显示,如果是粒子编辑器默认例子没改过,则需要这个。可能跟life什么的设置有关吧。

至于快速连续按下J键看到的情况,还有待研究,可能是共用同一个effect的缘故,particleEffect的update每个都调用了。

那倒不如把particleEffect直接放到actor中去构造,释放也放在里面,待研究吧。

 

你可能感兴趣的:(libgdx)