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
slf4j-api-1.6.3.jar