JBox2D学习 - 小球碰撞

 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


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值