最近項目上線完樟遣,正好有空搞點新花樣而叼,記得有個粒子爆炸效果,一直沒弄過豹悬,現(xiàn)在正好擼一下葵陵。。瞻佛。
下面先看一下實現(xiàn)效果:
20200527203126.gif
當(dāng)手指在屏幕上按下脱篙,會生成隨機顏色的粒子,然后向上移動伤柄,在高處爆炸绊困,看上去就像放煙花一樣,還挺好看适刀。秤朗。。笔喉。取视。
現(xiàn)在開始說一下實現(xiàn)流程:
一.每一個粒子都是一個實體,有自己的屬性常挚,所以需要定義一個實體類:
/**
* 上升粒子
*/
public class ParticalBean {
//畫筆
private Paint paint;
//x位置
private int x;
//y位置
private int y;
//速率
private int speed;
//移動距離
private int distance;
//是否爆炸
private boolean isBoom;
//爆炸后粒子數(shù)據(jù)
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.當(dāng)手指按下新增一個粒子,將粒子添加到集合怨酝,并刷新畫布傀缩。
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()方法繪制圓形粒子,當(dāng)粒子移動到設(shè)定的位置(范圍內(nèi)隨機)時农猬,設(shè)置為爆炸粒子赡艰。
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()){
//碎片個數(shù)
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.根據(jù)上升粒子的位置,計算爆炸粒子的位置(范圍內(nèi)隨機)斤葱,爆炸粒子數(shù)量(范圍內(nèi)隨機)慷垮,爆炸粒子下落距離(預(yù)設(shè)),開始繪制爆炸粒子揍堕。
//爆炸粒子
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.當(dāng)爆炸粒子下落完設(shè)定距離后料身,清除集合中的粒子,畫布停止刷新衩茸。
有點意思
完芹血、、楞慈、幔烛。
完整代碼:
github: