一、实现效果
Android使用LiquidFun物理引擎实现果冻碰撞效果
二、Android代码
// 加载liquidfun动态库
static {
System.loadLibrary("liquidfun");
System.loadLibrary("liquidfun_jni");
}
class ParticleData {
long id;
ParticleSystem particleSystem;
float particleRadius;
int textureId;
ArrayList<ArrayList<Integer>> row;
public ParticleData(long id, ParticleSystem ps, float particleRadius, ArrayList<ArrayList<Integer>> row, int textureId) {
this.id = id;
this.particleSystem = ps;
this.textureId = textureId;
this.particleRadius = particleRadius;
this.row = row;
}
public long getId() {
return this.id;
}
public ParticleSystem getParticleSystem() {
return this.particleSystem;
}
public int getTextureId() { return this.textureId;}
public float getParticleRadius() { return this.particleRadius;}
public ArrayList<ArrayList<Integer>> getRow() { return this.row;}
}
class BodyData {
long id;
Body body;
FloatBuffer vertexBuffer;
FloatBuffer uvBuffer;
int vertexLen;
int drawMode;
int textureId;
public BodyData(long id, Body body, float[] buffer, float[] uv, int drawMode, int textureId) {
this.id = id;
this.body = body;
this.vertexBuffer = makeFloatBuffer(buffer);
this.uvBuffer = makeFloatBuffer(uv);
this.vertexLen = buffer.length / 2;
this.drawMode = drawMode;
this.textureId = textureId;
}
public long getId() {
return this.id;
}
public Body getBody() {
return this.body;
}
public FloatBuffer getVertexBuffer() {
return this.vertexBuffer;
}
public FloatBuffer getUvBuffer() { return this.uvBuffer;}
public int getDrawMode() { return this.drawMode;}
public int getVertexLen() { return this.vertexLen;}
public int getTextureId() { return this.textureId;}
}
public MainRenderer(MainGlView view) {
this.view = view;
world = new World(0, -10);
//this.addBox(1, 1, 0, 10, 0, BodyType.dynamicBody, 0);
}
private void addBodyData(Body body, float[] buffer, float[] uv, int drawMode, int textureId) {
long id = nextBodyDataId++;
BodyData data = new BodyData(id, body, buffer, uv, drawMode, textureId);
this.mapBodyData.put(id, data);
}
private void addParticleData(ParticleSystem ps, float particleRadius, ArrayList<ArrayList<Integer>> row, int textureId) {
long id = nextBodyDataId++;
ParticleData data = new ParticleData(id, ps, particleRadius, row, textureId);
this.mapParticleData.put(id, data);
}
public void addCircle(GL10 gl,float r, float x, float y, float angle, BodyType type, float density, int resId) {
// Box2d用
BodyDef bodyDef = new BodyDef();
bodyDef.setType(type);
bodyDef.setPosition(x, y);
bodyDef.setAngle(angle);
Body body = world.createBody(bodyDef);
CircleShape shape = new CircleShape();
shape.setRadius(r);
body.createFixture(shape, density);
// OpenGL用
float vertices[] = new float[32*2];
float uv[] = new float[32*2];
for(int i = 0; i < 32; ++i){
float a = ((float)Math.PI * 2.0f * i)/32;
vertices[i*2] = r * (float)Math.sin(a);
vertices[i*2+1] = r * (float)Math.cos(a);
uv[i*2] = ((float)Math.sin(a) + 1.0f)/2f;
uv[i*2+1] = (-1 * (float)Math.cos(a) + 1.0f)/2f;
}
int textureId=makeTexture(gl, resId);
this.addBodyData(body, vertices, uv, GL10.GL_TRIANGLE_FAN, textureId);
}
public void addBox(GL10 gl,float hx, float hy, float x, float y, float angle, BodyType type, float density, int resId) {
// Box2d用
BodyDef bodyDef = new BodyDef();
bodyDef.setType(type);
bodyDef.setPosition(x, y);
Body body = world.createBody(bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox(hx, hy, 0, 0, angle);
body.createFixture(shape, density);
// OpenGL用
float vertices[] = {
- hx, + hy,
- hx, - hy,
+ hx, + hy,
+ hx, - hy,
};
FloatBuffer buffer = this.makeFloatBuffer(vertices);
float[] uv={
0.0f,0.0f,//左上
0.0f,1.0f,//左下
1.0f,0.0f,//右上
1.0f,1.0f,//右下
};
FloatBuffer uvBuffer = this.makeFloatBuffer(uv);
int textureId=makeTexture(gl, resId);
this.addBodyData(body, vertices, uv, GL10.GL_TRIANGLE_STRIP, textureId);
}
public void addSoftBody(GL10 gl,float hx, float hy, float cx, float cy, float particleRadius, int resId) {
ParticleSystemDef psd = new ParticleSystemDef();
psd.setRadius(particleRadius);
ParticleSystem ps = world.createParticleSystem(psd);
PolygonShape shape = new PolygonShape();
shape.setAsBox(hx, hy, 0, 0, 0);
ParticleGroupDef pgd = new ParticleGroupDef();
pgd.setFlags(ParticleFlag.elasticParticle);
pgd.setGroupFlags(ParticleGroupFlag.solidParticleGroup);
pgd.setShape(shape);
pgd.setPosition(cx, cy);
ParticleGroup pg = ps.createParticleGroup(pgd);
float py = 0;
ArrayList<ArrayList<Integer>> row = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> line = new ArrayList<Integer>();
for (int i = pg.getBufferIndex(); i < pg.getParticleCount() - pg.getBufferIndex(); ++i) {
float y = ps.getParticlePositionY(i);
if (i==0) {
py = y;
}
if ((float)Math.abs(py - y) > 0.01f) {
row.add(line);
line = new ArrayList<Integer>();
}
line.add(i);
py = y;
}
row.add(line);
int textureId=makeTexture(gl, resId);
this.addParticleData(ps, particleRadius, row, textureId);
}
三、完整源码下载:LiquidFunTest源码: https://url83.ctfile.com/d/45573183-68059777-a5f411?p=7526 (访问密码: 7526)