Android实现粒子烟花爆炸效果

龙旋

共 6748字,需浏览 14分钟

 ·

2021-05-09 10:09

实现效果:


当手指在屏幕上按下,会生成随机颜色的粒子,然后向上移动,在高处爆炸,看上去就像放烟花一样,还挺好看。。。。。

现在开始说一下实现流程:

一、每一个粒子都是一个实体,有自己的属性,所以需要定义一个实体类:
/** * 上升粒子 */public class ParticalBean {    //画笔    private Paint paint;    //x位置    private int x;    //y位置    private int y;    //速率    private int speed;    //移动距离    private int distance;    //是否爆炸    private boolean isBoom;    //爆炸后粒子数据    private List<BoomParicalBean> boomParicalBeans;
public ParticalBean(Paint paint, int x, int y, int speed, int distance) { this.paint = paint; this.x = x; this.y = y; this.speed = speed; this.distance = distance; }
public Paint getPaint() { return paint; }
public void setPaint(Paint paint) { this.paint = paint; }
public int getDistance() { return distance; }
public void setDistance(int distance) { this.distance = distance; }
public int getX() { return x; }
public void setX(int x) { this.x = x; }
public int getY() { return y; }
public void setY(int y) { this.y = y; }
public int getSpeed() { return speed; }
public void setSpeed(int speed) { this.speed = speed; }
public boolean isBoom() { return isBoom; }
public void setBoom(boolean boom) { isBoom = boom; }
public List<BoomParicalBean> getBoomParicalBeans() { return boomParicalBeans; }
public void setBoomParicalBeans(List<BoomParicalBean> boomParicalBeans) { this.boomParicalBeans = boomParicalBeans; }
}

这个实体类就是上升粒子的实体类,详细属性有写。

二、每一个爆炸粒子也是一个实体,所以也要定义一个实体类:
/** * 爆炸粒子 */public class BoomParicalBean {    //x位置    private int x;    //y位置    private int y;    //速率    private int speed;    //移动距离    private int distance;    //粒子半径    private int raduis;
public BoomParicalBean(int x, int y, int raduis, int speed, int distance) { this.x = x; this.y = y; this.raduis = raduis; this.speed = speed; this.distance = distance; }
public int getX() { return x; }
public void setX(int x) { this.x = x; }
public int getY() { return y; }
public void setY(int y) { this.y = y; }
public int getRaduis() { return raduis; }
public void setRaduis(int raduis) { this.raduis = raduis; }
public int getSpeed() { return speed; }
public void setSpeed(int speed) { this.speed = speed; }
public int getDistance() { return distance; }
public void setDistance(int distance) { this.distance = distance; }}

三、生成实体粒子与爆炸粒子,需要一个制造它们的工厂:
/** * 粒子工厂 */class ParticalFactory {
/** 生成上升粒子 * @param paint * @param x * @param y * @param speed * @param distance * @return */ static ParticalBean createPartical(Paint paint, int x, int y, int speed, int distance){ return new ParticalBean(paint, x, y, speed, distance); }
/** 生成爆炸粒子 * @param x * @param y * @param raduis * @param speed * @param distance * @return */ static BoomParicalBean createBoomPartical(int x, int y, int raduis, int speed, int distance){ return new BoomParicalBean(x, y, speed, raduis, distance); }}

四、有了这些基本元素之后,开始绘制逻辑:

1、当手指按下新增一个粒子,将粒子添加到集合,并刷新画布。
 gestureDetector = new GestureDetector(getContext(), new GestureDetector.SimpleOnGestureListener(){            @Override            public boolean onDown(MotionEvent e) {                ViewCompat.postInvalidateOnAnimation(ParticalView.this);                list.add(ParticalFactory.createPartical(cratePaint(), (int) e.getX(), (int)e.getY(), (int) (Math.random() * (15-5)+5), (int) (Math.random() * 1000)));                return true;            }        });

2、在onDraw()方法绘制圆形粒子,当粒子移动到设定的位置(范围内随机)时,设置为爆炸粒子。
for (ParticalBean particalBean : list) {                if(!particalBean.isBoom()){                    canvas.drawCircle(particalBean.getX(), particalBean.getY(), 50, particalBean.getPaint());                    particalBean.setY(particalBean.getY() - particalBean.getSpeed());                }            }            for (int i=0; i<list.size(); i++){                ParticalBean particalBean = list.get(i);                if(!particalBean.isBoom()){                    if (particalBean.getY() <= particalBean.getDistance()){                        //碎片个数                        int fragments = (int) (Math.random() * (100 - 60) + 60);                        List<BoomParicalBean> boomParicalBeans = new ArrayList<>();                        for (int j=0; j < fragments ;j++){                            double angle = (j * 2 * Math.PI) / fragments;                            int raduis = (int) (Math.random() * fragmentsRaduis);                            int x = (int) (Math.cos(angle) * raduis) + particalBean.getX();                            int y = (int) (Math.sin(angle) * raduis) + particalBean.getY();                            BoomParicalBean boomPartical = ParticalFactory.createBoomPartical(x, y, boomParicalSpeed, (int) (Math.random() * particalRaduis), y + boomParticalMoveY);                            boomParicalBeans.add(boomPartical);                        }                        particalBean.setBoomParicalBeans(boomParicalBeans);                        particalBean.setBoom(true);                    }                }            }

3、根据上升粒子的位置,计算爆炸粒子的位置(范围内随机),爆炸粒子数量(范围内随机),爆炸粒子下落距离(预设),开始绘制爆炸粒子。
 //爆炸粒子            for (int p=0; p< list.size(); p++){                ParticalBean particalBean = list.get(p);                if(particalBean.isBoom()){                    List<BoomParicalBean> boomParicalBeans = particalBean.getBoomParicalBeans();                    for (int i=0; i<boomParicalBeans.size() ;i++){                        BoomParicalBean boomParicalBean = boomParicalBeans.get(i);                        canvas.drawCircle(boomParicalBean.getX(), boomParicalBean.getY(), boomParicalBean.getRaduis(), particalBean.getPaint());                        boomParicalBean.setY(boomParicalBean.getY() + boomParicalBean.getSpeed());
if(boomParicalBean.getY() >= boomParicalBean.getDistance()){ boomParicalBeans.remove(boomParicalBean); }
if(boomParicalBeans.isEmpty()){ list.remove(particalBean); ViewCompat.postInvalidateOnAnimation(ParticalView.this); } } } }

4、当爆炸粒子下落完设定距离后,清除集合中的粒子,画布停止刷新。

Github地址:
https://github.com/amggg/ParticalDemo

到这里就结束啦。
浏览 125
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报