Android 交流群 110687406
使用引擎版本:jbox2d-library-2.1.2.jar
封装好的JBOX2D引擎,专门适合android平台使用
注意:下载这个封装好的不需要slfj库支持,效率更高
之前在jbox2d 官网下载的2.1.2一直跑不起来,发现jar包有问题,后来在官网发帖子,jbox2d作者非常耐心的解答了我的问题,终于用上2.1.2的jbox2d了哇,
非常感谢老外的开源精神,做出这么好的物理引擎,完全免费
jbox2d官网:http://code.google.com/p/jbox2d/
现在奉上我学习jbox2d做的demo,这个demo类似与testbed 里的 varying restitution
baseview.java:
package com.tszy.testjbox2d212;
import org.jbox2d.collision.shapes.CircleShape;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.FixtureDef;
import org.jbox2d.dynamics.World;
import org.jbox2d.dynamics.joints.MouseJoint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.view.View;
public class BaseView extends View implements Runnable{
public static final float RATE = 30.0f; //比例尺
public static final int DEF_FPS = 30; //默认刷新频率
private Thread thread;
protected World world;
protected Paint paint;
protected Matrix matrix;
protected BodyDef bd;
protected MouseJoint mouseJoint;
public boolean a = true;
public Body m_groundBody;
public BaseView(Context context) {
super(context);
// TODO Auto-generated constructor stub
bd = new BodyDef();
paint = new Paint(Paint.ANTI_ALIAS_FLAG);// 无锯齿
paint.setStyle(Style.FILL);
matrix = new Matrix();
Vec2 gravity = new Vec2(0, 10f);
world = new World(gravity, true);
BodyDef bodyDef = new BodyDef();
m_groundBody = world.createBody(bodyDef);
thread = new Thread(this);
thread.start();
}
/**
* 创建矩形
* @param world 所在世界
* @param x, y 中心点位置
* @param w, h 尺寸
* @param friction 摩擦力
* @param restitution 恢复力
* @param isStatic 静态否
* @return 对象
*/
public Body createPolygon(float x, float y, float w, float h,
float friction, float restitution,
boolean isStatic) {
//创建多边形皮肤
PolygonShape shape = new PolygonShape();
shape.setAsBox(w/2/RATE, h/2/RATE);
FixtureDef fd = new FixtureDef();
fd.shape = shape;
fd.density = 1.0f; //设置密度
fd.friction = friction; //设置摩擦力
fd.restitution = restitution; //设置多边形的恢复力
//设置刚体初始坐标
bd.type = isStatic? BodyType.STATIC : BodyType.DYNAMIC;
bd.position.set(x/RATE, y/RATE);
//创建物体
Body body = world.createBody(bd); //物理世界创建物体
//此方法改变了
//body.createShape(pDef); //为body添加皮肤
body.createFixture(fd);
return body;
}
public Body createPolygon(float x, float y, float w, float h,
boolean isStatic) {
return createPolygon(x, y, w, h, 0.3f, 0.5f, isStatic);
}
/**
* 创建圆形
* @param world 所在世界
* @param x, y 圆心位置
* @param r 半径
* @param friction 摩擦力
* @param restitution 恢复力
* @param isStatic 静态否
* @return 对象
*/
public Body createCircle(float x, float y, float r,
float friction, float restitution,
boolean isStatic) {
//创建圆形皮肤
CircleShape shape = new CircleShape();
shape.m_radius = r/RATE;
FixtureDef fd = new FixtureDef();
fd.shape = shape;
fd.density = 1.0f;
fd.friction = friction;
fd.restitution = restitution;
//创建刚体
bd.type = isStatic? BodyType.STATIC : BodyType.DYNAMIC;
bd.position.set((x+r)/RATE, (y+r)/RATE);
//创建一个body
Body body = world.createBody(bd);
body.createFixture(fd);
return body;
}
public Vec2 screen2world(Vec2 p) {
p.x /= RATE;
p.y /= RATE;
return p;
}
public Vec2 world2screen(Vec2 p){
p.x *= RATE;
p.y *= RATE;
return p;
}
public Vec2 screen2world2(Vec2 p) {
return new Vec2(p.x/RATE, p.y/RATE);
}
public Vec2 world2screen2(Vec2 p){
return new Vec2(p.x*RATE, p.y*RATE);
}
private void drawFPS(Canvas canvas) {
paint.setColor(0xffffffff);
paint.setAntiAlias(true);
if (USETIME > 0)
canvas.drawText("FPS:" + (USETIME>0? 1000/USETIME : 33), 3,
3 + paint.getTextSize(), paint);
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
drawFPS(canvas);
super.onDraw(canvas);
}
private long USETIME;
@Override
public void run() {
// TODO Auto-generated method stub
long t1, t2;
while (a) {
//模拟世界
//速度模拟频率,位置模拟频率
world.step(1.0f/30.0f, 3, 8);
t1 = System.currentTimeMillis();
postInvalidate();
t2 = System.currentTimeMillis();
USETIME = t2 - t1;
//正常休眠
if (USETIME < 33) {
try {
Thread.sleep(33 - USETIME);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
View.java
package com.tszy.testjbox2d212;
import org.jbox2d.callbacks.QueryCallback;
import org.jbox2d.collision.AABB;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.Fixture;
import org.jbox2d.dynamics.joints.MouseJoint;
import org.jbox2d.dynamics.joints.MouseJointDef;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.MotionEvent;
public class View6 extends BaseView {
private static final float R = 15.0f;
public View6(Context context) {
super(context);
// TODO Auto-generated constructor stub
create();
}
private void create() {
// 地板
Body body = null;
body = createPolygon(10+460/2, 305, 460, 10, true);
// 球
float restitution[] = new float[]{0.0f, 0.1f, 0.3f, 0.5f, 0.75f, 0.9f, 1.0f};
for (int i = 0; i < restitution.length; i++) {
body = createCircle(80 + i * 40, 40, R, 0.3f, restitution[i], false);
}
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
canvas.drawColor(0xff000000);
//地板
paint.setColor(0xff00ff00);
paint.setAntiAlias(false); //消除画笔锯齿
paint.setStyle(Paint.Style.STROKE);
Rect r = new Rect(10, 300, 470, 310);
canvas.drawRect(r, paint);
r = null;
//球
//得到body链表表头
Body body = world.getBodyList();
for(int i=1; i<world.getBodyCount(); i++){
if(body.getType() != BodyType.DYNAMIC){ //不是动态的物体
continue;
}
drawBall(canvas, body);
body = body.m_next;
}
//if(mouseJoint != null)
drawLine(canvas);
super.onDraw(canvas);
}
private void drawLine(Canvas canvas){
if(curBody==null || !isMoving) return;
paint.setAntiAlias(false); //消除画笔锯齿
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
Vec2 d = world2screen2(curBody.getPosition());
Vec2 d2 = world2screen2(p);
canvas.drawLine(d.x, d.y, d2.x, d2.y, paint);
}
private void drawBall(Canvas canvas, Body ball){
//得到的body的质点坐标
Vec2 p = world2screen2(ball.getPosition());
//canvas.save();
//获取球的旋转角度
float degrees = (float) ((ball.getAngle()*180/Math.PI) % 360);
matrix.reset();
canvas.save(); //保存不需要绘制的区域
if (degrees != 0)
matrix.preRotate(degrees, p.x, p.y); //设置矩阵旋转角度
canvas.setMatrix(matrix);
//填充
paint.setColor(0x80ffbbff);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(p.x, p.y, R, paint);
//轮廓
paint.setAntiAlias(true);
paint.setColor(0xffffbbff);
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(p.x, p.y, R, paint);
//paint.setAntiAlias(false);
//角度
paint.setColor(0xff00ff00);
paint.setStyle(Paint.Style.FILL);
canvas.drawLine(p.x, p.y, p.x, p.y-R, paint);
canvas.restore();
}
private boolean isMoving;
private Body curBody;
private Vec2 p;
private final AABB queryAABB = new AABB();
private final TestQueryCallback callback = new TestQueryCallback();
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
p = screen2world(new Vec2(event.getX(), event.getY()));
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN :{
isMoving = true;
if (mouseJoint != null) {
return true;
}
queryAABB.lowerBound.set(p.x - .001f, p.y - .001f);
queryAABB.upperBound.set(p.x + .001f, p.y + .001f);
callback.point.set(p);
callback.fixture = null;
world.queryAABB(callback, queryAABB);
if(callback.fixture != null){
curBody = callback.fixture.getBody();
MouseJointDef def = new MouseJointDef();
def.bodyA = m_groundBody;
def.bodyB = curBody;
def.target.set(p);
def.maxForce = 1000f * curBody.getMass();
mouseJoint = (MouseJoint) world.createJoint(def);
curBody.setAwake(true);
}
}
case MotionEvent.ACTION_MOVE : {
if (mouseJoint != null) {
mouseJoint.setTarget(p);
}
return true;
}
case MotionEvent.ACTION_UP : {
isMoving = false;
if (mouseJoint != null) {
world.destroyJoint(mouseJoint);
mouseJoint = null;
}
return true;
}
}
return super.onTouchEvent(event);
}
class TestQueryCallback implements QueryCallback {
public final Vec2 point;
public Fixture fixture;
public TestQueryCallback() {
point = new Vec2();
fixture = null;
}
/**
* @see org.jbox2d.callbacks.QueryCallback#reportFixture(org.jbox2d.dynamics.Fixture)
*/
public boolean reportFixture(Fixture argFixture) {
Body body = argFixture.getBody();
if (body.getType() == BodyType.DYNAMIC) {
boolean inside = argFixture.testPoint(point);
if (inside) {
fixture = argFixture;
return false;
}
}
return true;
}
}
}
jbox2d库,这两个都需要
jbox2d-library-2.1.2.jar