求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
android 游戏开发之粒子系统应用
 

作者:jj120522,发布于2012-1-7,来源:CSDN

 

上一节说的是android 游戏开发之物理小球的应用,而这节介绍的是粒子系统,从名字上就可以得出数量之极多.简单说:粒子系统就是有好多好多小球在一起欲动,那么这就叫做粒子系统,考虑的是整体感觉,而不是单个小球的轨迹.这让我联想到了墨迹和新浪推出的天气动态背景,是不是也是这样实现的呢.总而言之,如下雨,下雨,瀑布等都可以做到,但是做起来很复杂,估计我想远跑偏了,肯定有更好的办法实现动态背景.

我们还是先看一个案例,实现起来和前面讲解小球一样.

首先粒子对象Particle.java

package com.jj.partical;
/***
 * 粒子对象
 * 
 * @author zhangjia
 * 
 */
public class Particle {
	int color; // 颜色
	int r;// 半径
	double vertical_v;// 垂直速度
	double horizontal_v;// 水平速度
	int startX;
	int startY;
	int x;
	int y;
	double startTime;// 起始时间

	public Particle(int color, int r, double vertical_v, double horizontal_v,
			int x, int y, double startTime) {
		super();
		this.color = color;
		this.r = r;
		this.vertical_v = vertical_v;
		this.horizontal_v = horizontal_v;
		this.startX = x;
		this.startY = y;
		this.x = x;
		this.y = y;
		this.startTime = startTime;
	}

} 

就是一些属性,下面我们创建一个存放粒子的几个ParticleSet.java其实二者可以整个一个里面,总而言之,达到效果就OK.

package com.jj.partical;
import java.util.ArrayList;
import android.graphics.Color;
/***
 * 存放粒子对象集合
 * 
 * @author zhangjia
 * 
 */
public class ParticleSet {
	ArrayList<Particle> particals;

	public ParticleSet() {
		super();
		particals = new ArrayList<Particle>();
	}

	/***
	 * 获取相关颜色
	 * 
	 * @return
	 */
	public int getColor(int i) {
		int color = Color.RED;
		switch (i % 4) {
		case 0:
			color = Color.RED;
			break;
		case 1:
			color = Color.GREEN;
			break;
		case 2:
			color = Color.YELLOW;
			break;
		case 3:
			color = Color.WHITE;
			break;
		default:
			break;
		}
		return color;
	}

	/***
	 * 添加粒子
	 * 
	 * @param count
	 *            个数
	 * @param startTime
	 *            起始时间
	 */
	public void addPartical(int count, double startTime, int window_Width) {
		for (int i = 0; i < count; i++) {
			int color = getColor(i);
			int r = 1;
			double vertical_v = -30 + 10 * (Math.random());// 垂直速度
			double horizontal_v = 10 - 20 * (Math.random());// 水平速度
			int startX = window_Width / 2;
			int startY = 100;

			Particle partical = new Particle(color, r, vertical_v,
					horizontal_v, startX, startY, startTime);
			particals.add(partical);
		}

	}
} 

接下来介绍:粒子物理引擎ParticleThread.java

package com.jj.partical;

import java.util.ArrayList;

/***
 * 粒子物理引擎
 * 
 * @author zhangjia
 * 
 */
public class ParticleThread extends Thread {
	boolean flag;// 线程标识
	ParticleView particalView;
	int sleepSpan = 80;
	double time = 0;
	double span = 0.15;
	private int window_Width;

	public ParticleThread(ParticleView particleView, int window_Width) {
		this.particalView = particleView;
		this.flag = true; // 设置线程执行标志位为true
		this.window_Width = window_Width;
	}

	@Override
	public void run() {
		while (flag) {
			particalView.particleSet.addPartical(5, time, window_Width);// 每次添加5粒
			ArrayList<Particle> particals = particalView.particleSet.particals;// 获取粒子集合
			int count = particals.size();
			for (int i = 0; i < count; i++) {
				Particle partical = particals.get(i);
				double timeSpan = time - partical.startTime;// 计算程序开始到现在的时间差
				int tempX = (int) (partical.startX + partical.horizontal_v
						* timeSpan);// 计算此时粒子的X值
				// 4.9 * timeSpan * timeSpan=1/2*g*t*t;//物理公式,g=9.8m/s;
				int tempY = (int) (partical.startY + 4.9 * timeSpan * timeSpan);// 计算此时粒子的Y值
				if (tempY > ParticleView.DIE_OUT_LINE) {
					particals.remove(partical);// 删除该粒子
					count = particals.size();// 重新获取个数
				}
				partical.x = tempX;
				partical.y = tempY;
			}
			time += span;
			try {
				Thread.sleep(sleepSpan);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
} 

ParticleView.java

package com.jj.partical;

import java.util.ArrayList;

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;

//继承自SurfaceView并实现SurfaceHolder.Callback接口的类
public class ParticleView extends SurfaceView implements SurfaceHolder.Callback {
	public static int DIE_OUT_LINE = 420;// 粒子的Y坐标超过该值会从粒子集合移除
	DrawThread drawThread; // 后台刷新屏幕线程
	ParticleSet particleSet; // ParticleSet对象引用
	ParticleThread particleThread; // ParticleThread对象引用
	String fps = "FPS:N/A"; // 声明帧速率字符串

	// 构造器,初始化主要成员变量
	public ParticleView(Context context, int window_Width, int window_Height) {
		super(context); // 调用父类构造器
		DIE_OUT_LINE = window_Height;
		this.getHolder().addCallback(this); // 添加Callback接口
		drawThread = new DrawThread(this, getHolder()); // 创建DrawThread对象
		particleSet = new ParticleSet(); // 创建ParticleSet对象
		particleThread = new ParticleThread(this, window_Width); // 创建ParticleThread对象
	}

	// 方法:绘制屏幕
	public void doDraw(Canvas canvas) {
		canvas.drawColor(Color.BLACK); // 清屏
		ArrayList<Particle> particleSet = this.particleSet.particals; // 获得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; // 获得粒子X坐标
			int tempY = p.y; // 获得粒子Y坐标
			int tempRadius = p.r; // 获得粒子半径
			RectF oval = new RectF(tempX, tempY, tempX + 2 * tempRadius, tempY
					+ 2 * tempRadius);
			// canvas.drawOval(oval, paint); // 绘制椭圆粒子
			canvas.drawCircle(tempX, tempY, tempRadius, paint);
		}
		paint.setColor(Color.WHITE); // 设置画笔颜色
		paint.setTextSize(18); // 设置文字大小
		paint.setAntiAlias(true); // 设置抗锯齿
		canvas.drawText(fps, 15, 15, paint);// 画出帧速率字符串
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {// 重写surfaceChanged方法
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {// 从写surfaceCreated方法
		if (!drawThread.isAlive()) { // 如果DrawThread没有启动,就启动这个线程
			drawThread.start();
		}
		if (!particleThread.isAlive()) { // 如果ParticleThread没有启动,就启动这个线程
			particleThread.start();
		}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {// 重写surfaceDestroyed方法
		drawThread.flag = false; // 停止线程的执行
		drawThread = null; // 将dt指向的对象声明为垃圾
	}
} 

用于重绘屏幕和计算帧率DrawThread.java

package com.jj.partical;

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

/***
 * 用于重绘屏幕和计算帧率
 * 
 * @author zhangjia
 * 
 */
public class DrawThread extends Thread {
	ParticleView particalView;// 自定义View
	SurfaceHolder surfaceHolder;
	boolean flag = false;// 线程标识
	int sleepSpan = 15;// 线程休眠
	long start = System.nanoTime();// 其实时间,用于计算帧速率
	int count = 0;// 计算帧率

	public DrawThread(ParticleView particalView, SurfaceHolder surfaceHolder) {
		super();
		this.particalView = particalView;
		this.surfaceHolder = surfaceHolder;
		this.flag = true;
	}

	@Override
	public void run() {
		Canvas canvas = null;
		while (flag) {
			try {
				canvas = surfaceHolder.lockCanvas();// 获取canvas.
				synchronized (surfaceHolder) {
					particalView.doDraw(canvas);// 进行绘制ballView.

				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (canvas != null) {
					surfaceHolder.unlockCanvasAndPost(canvas);// 解锁
				}
			}
			this.count++;
			if (count == 20) { // 如果计满20帧
				count = 0; // 清空计数器
				long tempStamp = System.nanoTime();// 获取当前时间
				long span = tempStamp - start; // 获取时间间隔
				start = tempStamp; // 为start重新赋值
				double fps = Math.round(100000000000.0 / span * 20) / 100.0;// 计算帧速率
				particalView.fps = "FPS:" + fps;// 将计算出的帧速率设置到BallView的相应字符串对象中
			}
			try {
				Thread.sleep(sleepSpan); // 线程休眠一段时间
			} catch (Exception e) {
				e.printStackTrace(); // 捕获并打印异常
			}
		}
	}

} 

接下来调用展示View,就不写了,相信大家都明白如何操作,

现在我简单讲解一下原理:首先我们创建DrawThread线程,目的是相隔sleepSpan进行绘制doDraw方法.其实就好比就是刷屏操作.而我们的ParticleThread物理引擎则每隔sleepSpan都要添加5个粒子进去.然后在通过DrawThread线程进行不停的更新UI从而实现粒子系统.

烟火粒子示例:

  

其实我们稍微整理下逻辑就可以变为瀑布效果.

	// double horizontal_v = 10 - 20 * (Math.random());// 水平速度(火焰效果)
			double horizontal_v = 10 + 20 * (Math.random());// 水平速度(瀑布效果)

瀑布效果图:

关于粒子系统就说到这里,有不足的地方,请指示.

这个相比物理小球运动简单一点,不涉及太多的逻辑判断.总而言之:这套实现的步骤和方案值得参考.


 
分享到
 
 


android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   


Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合


领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...