Android小程序--模拟焰火粒子和瀑布粒子

[size=medium][color=gray] 需要注意的是,粒子系统和前面开发的物理小球之间有类似的地方,其都是通过数学方法和物理公式模拟客观世界中物体的运动轨迹。不同的是物理小球更强调个体运动,而焰火粒子系统更注重整体感觉,这点区别在代码中也能体现。
1、开发粒子对象Particle类:[/color][/size]
package xiao.fuyan.particle;

/**
* Created by xiao on 2017/2/10.
*/
public class Particle {
//粒子半径
int r;
//粒子颜色
int color;
//垂直速度
double v_v;
//水平速度
double h_v;
//初始坐标
int startX;
int startY;
//实时坐标
int x, y;
//起始时间
double startTime;

//构造器
public Particle(int color, int r, double v_v, double h_v, int x, int y, double startTime){
//初始化各个变量
this.color = color;
this.r = r;
this.v_v = v_v;
this.h_v = h_v;
this.startX = x;
this.startY = y;
this.x = x;
this.y = y;
this.startTime = startTime;
}
}
[size=medium][color=gray] 2、开发粒子集合ParticleSet类:[/color][/size]
package xiao.fuyan.particle;

import android.graphics.Color;

import java.util.ArrayList;

/**
* Created by xiao on 2017/2/10.
*/
public class ParticleSet {
//用于存放Particle对象的集合
ArrayList particleSet;
//构造器,
public ParticleSet(){
particleSet = new ArrayList();
}

//向粒子集合中添加指定个数的粒子对象
public void add(int count, double startTime){
for(int i =0; i < count; i++){

//该段代码是开发焰火粒子
//获取粒子对象的颜色
int tempColor = this.getColor(i);
//设置粒子半径
int tempR = 3;
//随机产生粒子竖直方向上的速度
double tempv_v = -30 + 10 * (Math.random());
//同上获取水平方向上的速度
double temph_v = 10 - 20 * (Math.random());

//粒子的X坐标是固定的
int tempX = 160;
//随机产生Y坐标,90 - 100之间
int tempY = (int) (100 - 10 * (Math.random()));

Particle particle = new Particle(tempColor, tempR, tempv_v, temph_v, tempX, tempY, startTime);
//将创建好的Particle对象添加到列表中
particleSet.add(particle);

//下面代码是将焰火粒子变为瀑布粒子
// int tempColor = this.getColor(i);
// //粒子半径
// int tempR = 3;
// //竖直方向速度为零
// double tempv_v = 0;
// double temph_v = 20 + 10 * (Math.random());
//
// int tempX = 50;
// int tempY = (int) (50 - 10 * (Math.random()));
//
// //创建Particle对象
// Particle particle = new Particle(tempColor, tempR, tempv_v, temph_v, tempX, tempY, startTime);
// //将创建好的Particle对象加入列表
// particleSet.add(particle);
}
}

//获取指定索引的颜色
public int getColor(int i){
int color = Color.RED;
switch (i % 8){
case 0:
color = Color.RED;
break;
case 1:
color = Color.BLUE;
break;
case 2:
color = Color.GRAY;
break;
case 3:
color = Color.GREEN;
break;
case 4:
color = Color.CYAN;
break;
case 5:
color = Color.YELLOW;
break;
case 6:
color = Color.MAGENTA;
break;
case 7:
color = Color.LTGRAY;
break;
}
return color;
}
}
[size=medium][color=gray] 3、开发物理引擎ParticleThread类:[/color][/size]
package xiao.fuyan.particle;

import java.util.ArrayList;

/**
* Created by xiao on 2017/2/10.
*/
public class ParticleThread extends Thread {

//线程执行标志位
boolean flag;
//ParticleView对象的引用
ParticleView father;
//线程休眠的时间
int sleepSpan = 80;
//物理引擎的时间轴
double time = 0;
//每次计算粒子的位移时采用的时间间隔
double span = 0.15;

//构造器
public ParticleThread(ParticleView father){
this.father = father;
this.flag = true;
}

//线程执行的方法
@Override
public void run() {
while(flag){
//每次添加五个粒子
father.ps.add(15, time);
//获取粒子集合
ArrayList tempSet = father.ps.particleSet;
//记录粒子集合的大小
int count = tempSet.size();
for(int i = 0; i < count; i++){ //遍历粒子集合,修改其轨迹
Particle particle = tempSet.get(i);
//计算从程序开始到现在的时间
double timeSpan = time - particle.startTime;
//计算出粒子的X坐标
int tempX = (int) (particle.startX + particle.h_v * timeSpan);
//计算Y坐标
int tempY = (int) (particle.startY + 4.9 * timeSpan * timeSpan + particle.v_v * timeSpan);

//如果粒子超出屏幕下边沿
if(tempY > 1920){
tempSet.remove(particle);
//重新设置粒子的个数
count = tempSet.size();
}

//修改粒子的坐标
particle.x = tempX;
particle.y = tempY;
}

//将时间延长
time += span;
try{
Thread.sleep(sleepSpan);//休眠一段时间
}catch (Exception e){
e.printStackTrace();
}
}
}
}
[size=medium][color=gray] 4、开发视图ParticleView类:[/color][/size]
package xiao.fuyan.particle;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.util.ArrayList;

/**
* Created by xiao on 2017/2/10.
*/
public class ParticleView extends SurfaceView implements SurfaceHolder.Callback {
//粒子的Y坐标超过该值就会从粒子集合中移出
public static final int DIE_OUT_LINE = 1920;
//后台刷新屏幕的线程
DrawThread dt = null;
//ParticleSet对象的引用
ParticleSet ps;
//ParticleThread对象的引用
ParticleThread pt;
//声明帧速率字符串
String fps = "FPS:N/A";

//构造器
public ParticleView(Context context){
super(context);
//添加callback接口
this.getHolder().addCallback(this);
//创建DrawThread对象
dt = new DrawThread(this, getHolder());
//创建ParticleSet对象
ps = new ParticleSet();
//创建ParticleThread对象
pt = new ParticleThread(this);
}

//绘制屏幕
public void doDraw(Canvas canvas){
//清除屏幕
canvas.drawColor(Color.BLACK);
//获取ParticleSet对象中的粒子
ArrayList particleSet = ps.particleSet;

Paint paint = new Paint();
for(int i = 0; i < particleSet.size(); i++){
Particle p = particleSet.get(i);
paint.setColor(p.color);
//获取粒子坐标和半径
int tempX = p.x;
int tempY = p.y;
int tempR = p.r;
//绘制该粒子
RectF oval = new RectF(tempX, tempY, tempX + 2 * tempR, tempY + 2 * tempR);
canvas.drawOval(oval, paint);
}

//设置画笔颜色
paint.setColor(Color.WHITE);
paint.setTextSize(60);
paint.setAntiAlias(true);
//画出帧速率字符串
canvas.drawText(fps, 900, 80, paint);
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
//启动线程
if(!dt.isAlive()){
dt.start();
}
if(!pt.isAlive()){
pt.start();
}
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//停止线程
dt.flag = false;
dt = null;
pt.flag = false;
pt = null;
}
}
[size=medium][color=gray] 5、开发DrawThread类:[/color][/size]
package xiao.fuyan.particle;

import android.graphics.Canvas;
import android.view.SurfaceHolder;

/**
* Created by xiao on 2017/2/10.
*/
public class DrawThread extends Thread {
//ParticleView对象
ParticleView particleView;
//SurfaceHolder对象的引用
SurfaceHolder surfaceHolder;
//线程执行的标志位
boolean flag = false;
//休眠时间
int sleepSpan = 30;
//记录起始时间,用于计算帧速率
long start = System.nanoTime();
//记录帧数,
int count = 0;

//构造器
public DrawThread(ParticleView particleView, SurfaceHolder surfaceHolder){
this.particleView = particleView;
this.surfaceHolder = surfaceHolder;
this.flag = true;
}

@Override
//线程执行的方法,用于重绘屏幕和计算帧速率
public void run() {
Canvas canvas = null;
while(flag){
try{
//获取ParticleView的画布
canvas = surfaceHolder.lockCanvas(null);
//加锁并且绘制
synchronized (surfaceHolder){
particleView.doDraw(canvas);
}
}catch (Exception e){
e.printStackTrace();
}finally {
if(canvas != null){ //如果canvas不为空
//surfaceHolder解锁,并将画布对象传回
surfaceHolder.unlockCanvasAndPost(canvas);
}
}

//如果计满20帧,计算帧速率
this.count++;
if(count == 20){
count = 0;
//获取当前时间
long tempStamp = System.nanoTime();
//获取时间间隔
long span = tempStamp - start;;
//为start重新赋值
start = tempStamp;
//计算帧速率
double fps = Math.round(10000000000.0 / span * 20) / 100.0;
//设置实时帧速率
particleView.fps = "FPS" + fps;
}
}

try{
Thread.sleep(sleepSpan);
}catch (Exception e){
e.printStackTrace();
}
}
}
[size=medium][color=gray] 6、开发程序MainActivity类:[/color][/size]
package xiao.fuyan.particle;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;


public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设置不显示标题
requestWindowFeature(Window.FEATURE_NO_TITLE);
//设置全屏显示模式
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);

//创建一个ParticleView对象
ParticleView particleView = new ParticleView(this);
setContentView(particleView);

}
}

你可能感兴趣的:(Android,android,多线程)