首页 > 系统 > Android > 正文

Android游戏开发学习②焰火绽放效果实现方法

2019-10-24 20:35:57
字体:
来源:转载
供稿:网友

这篇文章主要介绍了Android游戏开发学习②焰火绽放效果实现方法,以实例形式详细分析了Android中粒子对象类Particle类和粒子集合类ParticleSet类及物理引擎ParticleThread类 的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下

本文实例讲述了Android游戏开发学习②焰火绽放效果实现方法。分享给大家供大家参考。具体如下:

本节介绍在游戏开发中常用到的数学物理应用——粒子系统。粒子系统与上一节的小球有类似的地方,都是通过数学方法和物理公式模拟客观世界中的物体的运动轨迹。不同的是小球更强调个体运动,而焰火粒子等粒子系统更注重整体感觉。

一、焰火粒子效果

1.粒子对象类Particle类和粒子集合类ParticleSet类

每个粒子都为一个Particle类的对象,程序中产生的所有Particle对象都由一个ParticleSet对象来管理。

Particle类:

 

 
  1. package com.particle;  
  2. public class Particle {  
  3. int color; // 粒子颜色  
  4. int r; // 粒子半径  
  5. double vertical_v; // 垂直速度  
  6. double horizontal_v; // 水平速度  
  7. int startX; // 初始X坐标  
  8. int startY; // 初始Y坐标  
  9. int x; // 实时X坐标  
  10. int y; // 实时Y坐标  
  11. double startTime; // 起始时间  
  12. public Particle(int color, int r, double vertical_v, double horizontal_v, int x, int y, double startTime) {  
  13. super();  
  14. this.color = color;  
  15. this.r = r;  
  16. this.vertical_v = vertical_v;  
  17. this.horizontal_v = horizontal_v;  
  18. this.startX = x;  
  19. this.startY = y;  
  20. this.x = x;  
  21. this.y = y;  
  22. this.startTime = startTime;  
  23. }  

ParticleSet类:

 

 
  1. package com.particle;  
  2. import java.util.ArrayList;  
  3. import android.graphics.Color;  
  4. public class ParticleSet {  
  5. ArrayList<Particle> particleSet;  
  6. public ParticleSet() {  
  7. particleSet = new ArrayList<Particle>();  
  8. }  
  9. /**  
  10. * 向粒子集合中添加指定数量的粒子对象  
  11. */ 
  12. public void add(int count, double startTime) {  
  13. for (int i = 0; i < count; i++) {  
  14. int tempColor = this.getColor(i);  
  15. int tempR = 1; // 粒子半径  
  16. double tempv_v = -30 + 10 * (Math.random()); // 随机产生粒子竖直方向的速度 
  17. double tempv_h = 10 - 20 * (Math.random()); // 随机产生粒子水平方向的速度 
  18. int tempX = 160;  
  19. int tempY = (int) (100 - 10 * (Math.random())); // 随机产生粒子Y坐标,90到100之间  
  20. Particle particle = new Particle(tempColor, tempR, tempv_v, 
  21. tempv_h, tempX, tempY, startTime);  
  22. particleSet.add(particle);  
  23. }  
  24. }  
  25. /**  
  26. * 获取指定索引的颜色  
  27. */ 
  28. public int getColor(int i) {  
  29. int color = Color.RED;  
  30. switch (i%4) {  
  31. case 0:  
  32. color = Color.RED;  
  33. break;  
  34. case 1:  
  35. color = Color.GREEN;  
  36. break;  
  37. case 2:  
  38. color = Color.YELLOW;  
  39. break;  
  40. case 3:  
  41. color = Color.GRAY;  
  42. break;  
  43. }  
  44. return color;  
  45. }  

产生的粒子竖直初速度为-30至-20,方向向上;水平初速度为-10至10,方向向左或向右。

2.物理引擎ParticleThread类

 

 
  1. package com.particle;  
  2. import java.util.ArrayList;  
  3. public class ParticleThread extends Thread {  
  4. boolean flag;  
  5. ParticleView father;  
  6. int sleepSpan = 80;  
  7. double time = 0; // 物理引擎的时间轴  
  8. double span = 0.15; // 每次计算粒子位移时采用的时间间隔  
  9. public ParticleThread(ParticleView father) {  
  10. this.father = father;  
  11. this.flag = true;  
  12. }  
  13. @Override 
  14. public void run() {  
  15. while (flag) {  
  16. father.ps.add(5, time); // 每次添加5个粒子  
  17. ArrayList<Particle> tempSet = father.ps.particleSet; // 获取粒子集合  
  18. for (int i = tempSet.size() - 1; i >= 0; i--) {  
  19. Particle particle = tempSet.get(i);  
  20. double timeSpan = time - particle.startTime; // 计算从程序开始到现在经过的时间  
  21. int tempX = (int) (particle.startX + particle.horizontal_v * timeSpan);  
  22. int tempY = (int) (particle.startY + 4.9 * timeSpan * timeSpan + particle.vertical_v * timeSpan);  
  23. if (tempY > ParticleView.DIE_OUT_LINE) { // 如果粒子超过屏幕下边沿  
  24. tempSet.remove(particle);  
  25. }  
  26. particle.x = tempX;  
  27. particle.y = tempY;  
  28. }  
  29. time += span;  
  30. try {  
  31. Thread.sleep(sleepSpan);  
  32. catch (Exception e) {  
  33. e.printStackTrace();  
  34. }  
  35. }  
  36. }  

本例中的物理引擎没有采用获取系统时间的方式,而是自己定义了一个时间轴(成员变量time)。这样可以自己确定时间轴行进的快慢程度(通过改变成员变量span的值),而不必依赖于系统的时间。

3.视图类ParticleView类

 

 
  1. package com.particle;  
  2. import java.util.ArrayList;  
  3. import android.content.Context;  
  4. import android.graphics.Canvas;  
  5. import android.graphics.Color;  
  6. import android.graphics.Paint;  
  7. import android.graphics.RectF;  
  8. import android.view.SurfaceHolder;  
  9. import android.view.SurfaceHolder.Callback;  
  10. import android.view.SurfaceView;  
  11. public class ParticleView extends SurfaceView implements Callback {  
  12. public static final int DIE_OUT_LINE = 300;  
  13. DrawThread dt;  
  14. ParticleSet ps;  
  15. ParticleThread pt;  
  16. String fps = "FPS:N/A";  
  17. public ParticleView(Context context) {  
  18. super(context);  
  19. this.getHolder().addCallback(this);  
  20. dt = new DrawThread(this, getHolder());  
  21. ps = new ParticleSet();  
  22. pt = new ParticleThread(this);  
  23. }  
  24. public void doDraw(Canvas canvas) {  
  25. canvas.drawColor(Color.BLACK); // 清屏  
  26. ArrayList<Particle> particleSet = ps.particleSet;  
  27. Paint paint = new Paint();  
  28. for (int i = 0; i < particleSet.size(); i++) {  
  29. Particle p = particleSet.get(i);  
  30. paint.setColor(p.color);  
  31. int tempX = p.x;  
  32. int tempY = p.y;  
  33. int tempRadius = p.r;  
  34. RectF oval = new RectF(tempX, tempY, tempX + 2 * tempRadius, tempY  
  35. + 2 * tempRadius);  
  36. canvas.drawOval(oval, paint); // 绘制椭圆粒子  
  37. }  
  38. paint.setColor(Color.WHITE);  
  39. paint.setTextSize(18);  
  40. paint.setAntiAlias(true);  
  41. canvas.drawText(fps, 15, 15, paint);  
  42. }  
  43. @Override 
  44. public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {  
  45. }  
  46. @Override 
  47. public void surfaceCreated(SurfaceHolder arg0) {  
  48. if (!dt.isAlive()) {  
  49. dt.start();  
  50. }  
  51. if (!pt.isAlive()) {  
  52. pt.start();  
  53. }  
  54. }  
  55. @Override 
  56. public void surfaceDestroyed(SurfaceHolder arg0) {  
  57. dt.flag = false;  
  58. dt = null;  
  59. pt.flag = false;  
  60. pt = null;  
  61. }  

4.绘图类DrawThread及Activity类

基本与上节相同

DrawThread类:

 

 
  1. package com.particle;  
  2. import android.graphics.Canvas;  
  3. import android.view.SurfaceHolder;  
  4. public class DrawThread extends Thread {  
  5. ParticleView pv;  
  6. SurfaceHolder surfaceHolder;  
  7. boolean flag=false;  
  8. int sleepSpan=30;  
  9. long start =System.nanoTime(); //记录起始时间,该变量用于计算帧速率 
  10. int count=0 ; //记录帧数  
  11. public DrawThread(ParticleView pv,SurfaceHolder surfaceHolder) {  
  12. this.pv=pv;  
  13. this.surfaceHolder=surfaceHolder;  
  14. this.flag=true;  
  15. }  
  16. public void run() {  
  17. Canvas canvas=null;  
  18. while(flag) {  
  19. try {  
  20. canvas=surfaceHolder.lockCanvas(null); //获取BallView的画布  
  21. synchronized (surfaceHolder) {  
  22. pv.doDraw(canvas);  
  23. }  
  24. catch (Exception e) {  
  25. e.printStackTrace();  
  26. finally {  
  27. if(canvas!=null) {  
  28. surfaceHolder.unlockCanvasAndPost(canvas); // surfaceHolder解锁,并将画布传回  
  29. }  
  30. }  
  31. this.count++;  
  32. if(count==20) { //计满20帧时计算一次帧速率  
  33. count=0;  
  34. long tempStamp=System.nanoTime();  
  35. long span=tempStamp-start;  
  36. start=tempStamp;  
  37. double fps=Math.round(100000000000.0/span*20)/100.0;  
  38. pv.fps="FPS:"+fps;  
  39. }  
  40. try {  
  41. Thread.sleep(sleepSpan);  
  42. catch (InterruptedException e) {  
  43. e.printStackTrace();  
  44. }  
  45. }  
  46. }  

MainActivity类:

 

 
  1. package com.particle;  
  2. import android.app.Activity;  
  3. import android.os.Bundle;  
  4. import android.view.Window;  
  5. import android.view.WindowManager;  
  6. public class MainActivity extends Activity {  
  7. ParticleView pv;  
  8. @Override 
  9. public void onCreate(Bundle savedInstanceState) {  
  10. super.onCreate(savedInstanceState);  
  11. requestWindowFeature(Window.FEATURE_NO_TITLE); //设置不显示标题  
  12. getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //设置全屏  
  13. pv=new ParticleView(this);  
  14. setContentView(pv);  
  15. }  

效果图:

Android游戏开发学习②焰火绽放效果实现方法

Android游戏开发学习②焰火绽放效果实现方法

二、瀑布粒子效果

瀑布粒子和焰火粒子十分类似,二者的运动都是带有初速度的下落运动。所不同的是焰火粒子水平方向和竖直方向的速度均不为零,而瀑布粒子只有水平方向初速度,竖直方向初速度为零。只需在焰火粒子的生成部分ParticleSet类中修改即可。

ParticleSet类add方法修改如下:

 

 
  1. /**  
  2. * 向粒子集合中添加指定数量的粒子对象(瀑布粒子效果)  
  3. */ 
  4. public void add2(int count, double startTime) {  
  5. for (int i = 0; i < count; i++) {  
  6. int tempColor = this.getColor(i);  
  7. int tempR = 1; // 粒子半径  
  8. double tempv_v = 0; // 粒子竖直方向的速度为0  
  9. double tempv_h = 10 + 20 * (Math.random()); // 随机产生粒子水平方向的速度  
  10. int tempX = 50;  
  11. int tempY = (int) (50 - 10 * (Math.random())); // 随机产生粒子Y坐标,90到100之间  
  12. Particle particle = new Particle(tempColor, tempR, tempv_v, 
  13. tempv_h, tempX, tempY, startTime);  
  14. particleSet.add(particle);  
  15. }  

效果图:

Android游戏开发学习②焰火绽放效果实现方法

Android游戏开发学习②焰火绽放效果实现方法

希望本文所述对大家的Android程序设计有所帮助。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表