您的位置:首页 > 其它

JBox2D学习 - 小球碰撞

2011-10-27 22:02 656 查看
 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息