在書上看到的粒子系統的示例分享給大家參考,希望可以幫助大家學習安卓!
首先是MyRenderer.java
package com.boring.ParticleActivity;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.Random;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLUtils;
public class MyRenderer implements Renderer{
private int[] textures = new int[1];
// 随機數
private Random random = new Random();
// 定義最大的粒子數
private static final int MAX_PARTICLES = 1000;
// 減速粒子
private float slowdown = 0.5f;
// X方向的速度
private float xspeed = 80;
// Y方向的速度
private float yspeed = 80;
// 沿Z軸縮放
private float zoom = -30.0f;
// 循環變量
private int loop;
// 建立一個名為Particle的數組,存儲MAX_PARTICLES個元素
private Particle particles[] = new Particle[MAX_PARTICLES];
// 存儲12種不同顔色
private float colors[][] = { { 1.0f, 0.75f, 0.5f }, { 1.0f, 0.75f, 0.5f },
{ 1.0f, 1.0f, 0.5f }, { 0.75f, 1.0f, 0.5f }, { 0.5f, 1.0f, 0.5f },
{ 0.5f, 1.0f, 0.75f }, { 0.5f, 1.0f, 1.0f }, { 0.5f, 0.75f, 1.0f },
{ 0.5f, 0.5f, 1.0f }, { 0.75f, 0.5f, 1.0f }, { 1.0f, 0.5f, 1.0f },
{ 1.0f, 0.5f, 0.75f } };
// vertexBuffer
private FloatBuffer vertexBuffer;
// texCoordBuffer
private FloatBuffer texCoordBuffer;
// vertex
private float[] vertex = new float[12];
// texCoord
private float[] texCoord = new float[8];
// LoadBuffer
public void LoadBuffer(GL10 gl) {
ByteBuffer vertexByteBuffer = ByteBuffer
.allocateDirect(vertex.length * 4);
vertexByteBuffer.order(ByteOrder.nativeOrder());
vertexBuffer = vertexByteBuffer.asFloatBuffer();
vertexBuffer.put(vertex);
vertexBuffer.position(0);
ByteBuffer texCoordByteBuffer = ByteBuffer
.allocateDirect(texCoord.length * 4);
texCoordByteBuffer.order(ByteOrder.nativeOrder());
texCoordBuffer = texCoordByteBuffer.asFloatBuffer();
texCoordBuffer.put(texCoord);
texCoordBuffer.position(0);
}
public void onDrawFrame(GL10 gl) {
// LoadBuffer
LoadBuffer(gl);
// 清除螢幕和顔色緩存
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
// 重置模型變換矩陣
gl.glLoadIdentity();
// 開啟頂點紋理狀态
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texCoordBuffer);
// 循環所有的粒子
for (loop = 0; loop < MAX_PARTICLES; loop++) {
// 如果粒子為激活的
if (particles[loop].active) {
// 傳回X軸的位置
float x = particles[loop].x;
// 傳回Y軸的位置
float y = particles[loop].y;
// 傳回Z軸的位置
float z = particles[loop].z + zoom;
// 設定粒子顔色
gl.glColor4f(particles[loop].r, particles[loop].g,
particles[loop].b, particles[loop].life);
// 開始準備繪制"三角地帶"
texCoordBuffer.clear();
vertexBuffer.clear();
texCoordBuffer.put(1.0f);
texCoordBuffer.put(1.0f);
vertexBuffer.put(x + 0.5f);
vertexBuffer.put(y + 0.5f);
vertexBuffer.put(z);
texCoordBuffer.put(1.0f);
texCoordBuffer.put(0.0f);
vertexBuffer.put(x + 0.5f);
vertexBuffer.put(y);
vertexBuffer.put(z);
texCoordBuffer.put(0.0f);
texCoordBuffer.put(1.0f);
vertexBuffer.put(x);
vertexBuffer.put(y + 0.5f);
vertexBuffer.put(z);
texCoordBuffer.put(0.0f);
texCoordBuffer.put(0.0f);
vertexBuffer.put(x);
vertexBuffer.put(y);
vertexBuffer.put(z);
// 繪制
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
// 更新X坐标的位置
particles[loop].x += particles[loop].xi / (slowdown * 1000);
// 更新Y坐标的位置
particles[loop].y += particles[loop].yi / (slowdown * 1000);
// 更新Z坐标的位置
particles[loop].z += particles[loop].zi / (slowdown * 1000);
// 更新X軸方向速度大小
particles[loop].xi += particles[loop].xg;
// 更新Y軸方向速度大小
particles[loop].yi += particles[loop].yg;
// 更新Z軸方向速度大小
particles[loop].zi += particles[loop].zg;
// 減少粒子的生命值
particles[loop].life -= particles[loop].fade;
// 如果粒子生命小于0
if (particles[loop].life < 0.0f) {
float xi, yi, zi;
xi = xspeed + (float) ((rand() % 60) - 32.0f);
yi = yspeed + (float) ((rand() % 60) - 30.0f);
zi = (float) ((rand() % 60) - 30.0f);
initParticle(loop, random.nextInt(12), xi, yi, zi);
}
}
}
// 關閉頂點紋理狀态
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glFinish();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
// ratio
float ratio;
if (height == 0) {
height = 1;
}
ratio = (float) width / (float) height;
gl.glViewport(0, 0, (int) width, (int) height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
gl.glFrustumf(-ratio, ratio, -1, 1, 1.0f, 200.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
// 重置模型矩陣
gl.glLoadIdentity();
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig arg1) {
// 黑色背景
gl.glClearColor(0, 0, 0, 0);
// 關閉深度測試
gl.glDisable(GL10.GL_DEPTH_TEST);
// 陰影平滑
gl.glShadeModel(GL10.GL_SMOOTH);
// 啟用混合
gl.glEnable(GL10.GL_BLEND);
// 精細修正
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
// 啟用紋理
gl.glEnable(GL10.GL_TEXTURE_2D);
// 建立紋理
gl.glGenTextures(1, textures, 0);
// 綁定紋理
gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
// 生成紋理
// GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, LoadImage.bitmap, 0);
// 線性濾波
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
GL10.GL_LINEAR);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
GL10.GL_LINEAR);
for (loop = 0; loop < MAX_PARTICLES; loop++) {
float xi, yi, zi;
xi = (float) ((rand() % 50) - 26.0f) * 10.0f;
yi = zi = (float) ((rand() % 50) - 25.0f) * 10.0f;
// 初始化粒子
initParticle(loop, random.nextInt(12), xi, yi, zi);
}
}
public int rand() {
return Math.abs(random.nextInt(1000));
}
// initParticle初始化粒子
public void initParticle(int num, int color, float xDir, float yDir,
float zDir) {
Particle par = new Particle();
// 使所有粒子為激活狀态
par.active = true;
// 所有粒子生命值為最大
par.life = 1.0f;
// 随機生成衰率(0~99)/1000+0.003f
par.fade = rand() % 100 / 1000.0f + 0.003f;
// 賦予粒子顔色分量r,g,b
// r
par.r = colors[color][0];
// g
par.g = colors[color][1];
// b
par.b = colors[color][2];
// 設定粒子方向xi,yi,zi
// xi
par.xi = xDir;
// yi
par.yi = yDir;
// zi
par.zi = zDir;
// x,y,z方向加速度
// xg
par.xg = 0.0f;
// yg
par.yg = -0.5f;
// zg
par.zg = 0.0f;
particles[loop] = par;
}
}
接下來是Particle.java
package com.boring.ParticleActivity;
public class Particle {
boolean active; // 是否激活
float life; // 粒子生命
float fade; // 衰減速度
float r; // 紅色值
float g; // 綠色值
float b; // 藍色值
float x; // X位置
float y; // Y位置
float z; // Z位置
float xi; // X方向
float yi; // Y方向
float zi; // Z方向
float xg; // X 方向重力加速度
float yg; // Y 方向重力加速度
float zg; // Z 方向重力加速度
}
接下來是ParticleActivity.java
package com.boring.ParticleActivity;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
public class ParticleActivity extends Activity {
/** Called when the activity is first created. */
private GLSurfaceView glSurfaceView;
private MyRenderer myRenderer;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LoadImage.load(getResources());
myRenderer = new MyRenderer();
glSurfaceView = new GLSurfaceView(this);
glSurfaceView.setRenderer(myRenderer);
setContentView(glSurfaceView);
}
}
class LoadImage {
public static Bitmap bitmap;
public static void load(Resources res) {
bitmap = BitmapFactory.decodeResource(res, R.drawable.mm);
}
}
AndroidManifest.xml配置
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.boring.ParticleActivity"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".ParticleActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>