libgdx游戏引擎(三)之粒子系统

      一个游戏引擎要做出精美的游戏出来,有两个类是必不可少的,一个是精灵类,一个是粒子系统。粒子系统可以做出各种精妙的效果,如水流,火焰,烟雾等等,制作精美的粒子系统甚至可以以假乱真,制作出令人惊叹的效果。

      libgdx也提供了粒子系统的支持,而且令人兴奋的是,libgdx提供了一个可视化的粒子系统编辑器,我们可以采取边编辑边预览的方式,“所见即所得”,很快就能做出不错的粒子系统效果。

    

     先Save一下,将得到的一个文件,我们将它保存为particle.p,这个可以留下来等会用。这里还需要一个用来形成单个粒子的图片(图片的宽高必须为2的次幂),一般用一个很小的白色小圆即可。

      官方网站上对软件中的各个参数的解释如下:

      Delay:当粒子系统开始后,发射器等待多少时间开始发射

      Duration:发射器生存跨度,也就是粒子效果持续的时间,注意这个时间和粒子生存时间不同

      Count:顾名思义,同一时间可出现的粒子个数,有一个上限和一个下限

      Emission:每秒钟发射多少个粒子,这个参数带了一张图表,图表中间写着Duration,代表图X轴表示发射器生存时间,该图表控制各个时间点粒子每秒钟发射多少个,左边的上下两个文本框用于控制生成初始值的范围,左边的‘>’字符用于输入另外一个数值,发射器会在这两个值中间选择一个随机值作为上限值,Relative,如果选中,表示图表中的值是相对值,相对于初始值。否则是个绝对值。

Life:一个粒子的生存时间。

Life Offset:决定粒子在显示之前已经用掉它生命多少值,这样可以实现让一个粒子在它生命50%时再显现

X Offset and Y Offset:粒子出现在位置相对中心位置的像素偏移

Spawn:用于产生粒子的发射器的形状

Spawn Width and Spawn Height:发射器的形状的宽,高

Size:粒子的大小

Velocity:

Angle:

Rotation:

这几个值用于控制粒子的运动轨迹

Wind and Gravity:粒子在生存时间内在X轴和Y轴上每秒钟的像素偏移值

Tint:粒子的颜色,可以在粒子生存期内变化任意多个颜色

Transparency:粒子的透明度

下面的代码要实现的是粒子模拟出触摸轨迹的一个功能:

package com.lichunan.libgdx.game;

import java.util.ArrayList;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
import com.badlogic.gdx.graphics.g2d.ParticleEffectPool;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class FirstGame implements ApplicationListener {
    
    private SpriteBatch spriteBatch;
    private BitmapFont bf;
    
    private ParticleEffect particle;//粒子实例
    private ParticleEffect tem;//临时变量
    private ParticleEffectPool particlepool;//粒子系统的统一管理的类,负责管理粒子系统的产生和回收
    private ArrayList<ParticleEffect> particlelist;
    
    @Override
    public void create() {
        spriteBatch = new SpriteBatch();
        bf = new BitmapFont();
        particle = new ParticleEffect();//初始化粒子变量
        particle.load(Gdx.files.internal("particle.p"), Gdx.files.internal(""));
        particlepool = new ParticleEffectPool(particle, 5, 10);
    }
    
    @Override
    public void render() {
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        Gdx.gl.glClearColor(0f, 0f, 0f, 0f);
        
        spriteBatch.begin();
        bf.draw(spriteBatch, "Hello World", Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2);
        spriteBatch.end();
    }
    
    @Override
    public void dispose() {
        /**
         * 释放内存
         */
        spriteBatch.dispose();
        bf.dispose();
        particle.dispose();
        if(tem != null){
            tem.dispose();
        }
        particlepool.clear();
    }

    @Override
    public void pause() {
        // TODO Auto-generated method stub

    }

    @Override
    public void resize(int arg0, int arg1) {
        // TODO Auto-generated method stub

    }

    @Override
    public void resume() {
        // TODO Auto-generated method stub

    }

}

    Gdx.files.internal()的位置是在项目的asset根目录下,同理在asset下的data文件夹的话,格式应该为Gdx.files.internal("data/particle.p").

    libgdx中很多资源需要手动回收,

    ParticleEffect,particleEffetctPool两个类都实现了Disposeable接口,一定要记得手动回收资源。

    particle.load(Gdx.files.internal("particle.p"), Gdx.files.internal("particle.png"));

    第一个参数是Particle Editor生成的编辑文件(注意后缀也是自己取的,读取的时候记得对应),第二个参数是形成单个粒子的图片文件。

    particlepool = new ParticleEffectPool(particle, 5, 10);

    第一个参数是刚刚初始化完成的粒子,第二个参数是制定该粒子池里以第一个参数为模板生成多少个粒子可以供系统随时调用,第三个参数是粒子池中最大的粒子数目。

    下面我们实现粒子模拟触摸轨迹的功能,首先我们需要捕捉到触摸事件。而且我们面临一个很现实的问题:我们在哪里捕捉触摸事件?要知道libgdx和API可不一样,我们没有办法使用API在libgdx中获取触摸事件。对此Gdx包中的input部分提供了Gdx.input.isTouched()方法,判断当前屏幕是否被触摸,是则返回true。我们将这一语句放在render()方法中,就达到了随时检测的目的。修改后的代码如下:

package com.lichunan.libgdx.game;

import java.util.ArrayList;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.ParticleEffect;
import com.badlogic.gdx.graphics.g2d.ParticleEffectPool;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

public class FirstGame implements ApplicationListener {
    
    private SpriteBatch spriteBatch;
    private BitmapFont bf;
    
    private ParticleEffect particle;//粒子实例
    private ParticleEffect tem;//临时变量
    private ParticleEffectPool particlepool;//粒子系统的统一管理的类,负责管理粒子系统的产生和回收
    private ArrayList<ParticleEffect> particlelist;
    
    @Override
    public void create() {
        spriteBatch = new SpriteBatch();
        bf = new BitmapFont();
        particle = new ParticleEffect();//初始化粒子变量
        particle.load(Gdx.files.internal("particle.p"), Gdx.files.internal(""));
        particlepool = new ParticleEffectPool(particle, 5, 10);

        particlelist = new ArrayList<ParticleEffect>();

   }
    
    @Override
    public void render() {
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        Gdx.gl.glClearColor(0f, 0f, 0f, 0f);
        
        spriteBatch.begin();
        bf.draw(spriteBatch, "Hello World", Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2);
        spriteBatch.end();
        
        if(true){
            if(Gdx.input.isTouched()){
                //当此触摸点与上一触摸点距离大于一定值的时候触发新的粒子系统,由此减小系统负担
                tem = particlepool.obtain();
                tem.setPosition(Gdx.input.getX(), Gdx.graphics.getHeight()-Gdx.input.getY());
                particlelist.add(tem);
            }
            
            spriteBatch.begin();
            for(int i=0; i<particlelist.size(); i++){
                particlelist.get(i).draw(spriteBatch, Gdx.graphics.getDeltaTime());
            }
            spriteBatch.end();
            
            //清除已经播放完成的粒子系统
            ParticleEffect temparticle;
            for(int i=0; i<particlelist.size(); i++){
                temparticle = particlelist.get(i);
                if(temparticle.isComplete()){
                    particlelist.remove(i);
                }
            }
            
        }
    }
    
    @Override
    public void dispose() {
        /**
         * 释放内存
         */
        spriteBatch.dispose();
        bf.dispose();
        particle.dispose();
        if(tem != null){
            tem.dispose();
        }
        particlepool.clear();
    }

    @Override
    public void pause() {
        // TODO Auto-generated method stub

    }

    @Override
    public void resize(int arg0, int arg1) {
        // TODO Auto-generated method stub

    }

    @Override
    public void resume() {
        // TODO Auto-generated method stub

    }

}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值