zoukankan      html  css  js  c++  java
  • 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中去构造,释放也放在里面,待研究吧。

  • 相关阅读:
    DQL2.3.开始使用Dgraph基本类型和操作
    DQL2.7.开始使用Dgraph模糊搜索
    启动时查看配置文件application.yml
    从源码角度,带你研究什么是三级缓存
    Spring Boot 在启动时进行配置文件加解密
    论Redis分布式锁的正确使用姿势
    SpringBoot中整合Redis、Ehcache使用配置切换 并且整合到Shiro中
    在项目中,如何保证幂等性
    给你的SpringBoot做埋点监控JVM应用度量框架Micrometer
    从源码层面带你实现一个自动注入注解
  • 原文地址:https://www.cnblogs.com/hanhongmin/p/3960948.html
Copyright © 2011-2022 走看看