2

我从这里的教程开始,并为视图添加了绘图代码(覆盖整个屏幕)。即使我调用 world.step(,),场景看起来是静态的而不是动态的。如何使场景动态化,我的绘图是正确的实现还是有更好的方法(使用 jBox2d 函数)?

private class PhysicsView extends View {

        Paint mPaint;

        public PhysicsView(Context context) {
            super(context);
            mPaint = new Paint();
            mPaint.setColor(Color.BLUE);
            mPaint.setStyle(Style.FILL_AND_STROKE);
        }

        @Override
        public void onDraw(Canvas canvas) {
            super.onDraw(canvas);

            synchronized (canvas) {
                Body[] b = mWorld.bodies;
                for (int i = 0; i < b.length; i++) {
                    if (b[i] != null) {

                        Float mass = b[i].getMass();
                        Vec2 v = b[i].getPosition();
                        canvas.drawCircle(v.x, v.y, 15, mPaint);
                    }
                }
                Paint p2 = new Paint(mPaint);
                p2.setColor(Color.GREEN);
                Vec2 base = mWorld.groundBody.getPosition();
                canvas.drawRect(new RectF((float) base.x - 25.0f,
                        (float) base.y - 10.0f, (float) base.x + 25.0f,
                        (float) base.y + 10.0f), p2);

                canvas.drawLine(0.0f, 0.0f,
                        mWorld.world.getWorldAABB().upperBound.x, mWorld.world
                                .getWorldAABB().upperBound.y, p2);
            }
        }
    }


public class PhysicsWorld {

    public int targetFPS = 40;
    public int timeStep = (1000 / targetFPS);
    public int iterations = 5;

    public Body[] bodies = new Body[50];
    public Body groundBody;
    private int count = 0;

    private AABB worldAABB;
    public World world;
    private BodyDef groundBodyDef;
    private PolygonDef groundShapeDef;

    private Vec2 screenDimensions;

    public void create(Vec2 dimens) {

        screenDimensions = dimens;

        worldAABB = new AABB();
        worldAABB.lowerBound.set(new Vec2((float) -1*dimens.x, (float) -1*dimens.y));
        worldAABB.upperBound.set(new Vec2((float) dimens.x, (float) dimens.y));

        Vec2 gravity = new Vec2((float) 0.0, (float) 0.0);
        boolean doSleep = true;
        world = new World(worldAABB, gravity, doSleep);

        groundBodyDef = new BodyDef();
        groundBodyDef.position.set(new Vec2((float) dimens.x/2, (float) dimens.y - 10.0f));
        groundBody = world.createBody(groundBodyDef);
        groundBody.m_mass = 200.0f;

        groundShapeDef = new PolygonDef();
        groundShapeDef.setAsBox((float) 50.0, (float) 10.0);
        groundShapeDef.density = 1.0f;
        groundShapeDef.friction = 0.3f;
        groundBody.createShape(groundShapeDef);

    }

    public void addBall() {

        float x = (float) Math.random() * screenDimensions.x;
        float y = (float) Math.random() * screenDimensions.y;

        BodyDef bodyDef = new BodyDef();
        bodyDef.position.set(new Vec2((float) x, (float) y));
        bodyDef.massData.mass = 20.0f;
        bodies[count] = world.createBody(bodyDef);
        bodies[count].m_type = Body.e_dynamicType;
        bodies[count].m_linearVelocity = new Vec2(1.0f, 2.0f);

        CircleDef circle = new CircleDef();
        circle.radius = (float) 1.8;
        circle.density = (float) 1.0;
        circle.type = ShapeType.CIRCLE_SHAPE;

        bodies[count].createShape(circle);

        count++;
    }

    public void update() {
        world.step(timeStep, iterations);

    }

    public void changeGravity(Vec2 gravity) {
        world.setGravity(gravity);
    }
}
4

3 回答 3

2

您的代码存在许多问题....但是这个答案可能为时已晚,无论如何都无法提供任何帮助。

首先, world.createBody() 似乎已被弃用。现在您必须在我拥有的最新版本的 Android Box2D jar 中显式调用 world.createDynamicBody() 。

无论如何......我的版本是这样的......不是完美的,但至少它是动态的。

package com.box2D;

import java.util.ArrayList;

import org.jbox2d.collision.AABB;
import org.jbox2d.collision.CircleDef;
import org.jbox2d.collision.PolygonDef;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.World;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;

public class PhysicsWorld 
{
    public float timeStep = 1;
    public int iterations = 1;

    private ArrayList<Body> bodies;
    private int count = 0;

    private AABB worldAABB;
    private World world;
    private BodyDef groundBodyDef;
    private PolygonDef boxShapeDef;

    //a paint
    private Paint paint;

    public void create() 
    {
        //create the paint
        paint           = new Paint();
        paint.setColor(0xFFFFFF);

        // Step 1: Create Physics World Boundaries
        worldAABB       = new AABB();
        worldAABB.lowerBound.set(new Vec2((float) -100.0, (float) -100.0));
        worldAABB.upperBound.set(new Vec2((float) 100.0, (float) 300.0));

        // Step 2: Create Physics World with Gravity
        Vec2 gravity    = new Vec2((float) 0.0, (float)10.0);
        boolean doSleep = true;
        world           = new World(worldAABB, gravity, doSleep);
        bodies          = new ArrayList<Body>();

        // Step 3: Create Ground Box
        groundBodyDef   = new BodyDef();
        groundBodyDef.position.set(new Vec2((float) 0.0, (float) 300.0));
        Body groundBody = world.createDynamicBody(groundBodyDef);
        boxShapeDef  = new PolygonDef();
        boxShapeDef.setAsBox((float) 50.0, (float) 10.0);
        groundBody.createShape(boxShapeDef);
    }

    public void addBall() 
    {
        // Create Dynamic Body
        BodyDef bodyDef  = new BodyDef();
        bodyDef.position.set((float)16.0+(count * 10), (float)24.0);        
        Body newBody     = world.createDynamicBody(bodyDef);        

        // Create Shape with Properties
        CircleDef circle = new CircleDef();
        circle.radius    = (float)5;
        circle.density   = (float)1.0;

        // Assign shape to Body
        newBody.createShape(circle);
        newBody.setMassFromShapes();  
        newBody.m_userData = "Circle";
        bodies.add(newBody);

        // Increase Counter
        count += 1;
    }    

    public void addBox() 
    {
        // Create Dynamic Body
        BodyDef bodyDef  = new BodyDef();
        bodyDef.position.set((float)36.0+(count * 10), (float)24.0);
        Body newBody     = world.createDynamicBody(bodyDef);        

        // Create Shape with Properties
        boxShapeDef  = new PolygonDef();
        boxShapeDef.setAsBox((float) 50.0, (float) 10.0);

        // Assign shape to Body
        newBody.createShape(boxShapeDef);
        newBody.setMassFromShapes();  
        newBody.m_userData = "Box";
        bodies.add(newBody);

        // Increase Counter
        count += 1;
    }

    /*
     * 
     * 
     * Physics Update
     */

    private Vec2 position;
    private float angle;

    public void Update(Canvas canvas) 
    {
        // Update Physics World
        world.step(timeStep/5, 1);

        // Print info of latest body
        for (Body i : bodies) 
        {
            position = i.getPosition();
            angle    = i.getAngle(); 

            if(i.m_userData == "Circle")
            canvas.drawCircle(position.x, position.y, 5,paint );

            if(i.m_userData == "Box")
            canvas.drawRect((float)(position.x -5), (float)(position.y - 5), (float)(position.x + 5), (float)(position.y + 5), paint );

            Log.v("Physics Test", "Pos: (" + position.x + ", " + position.y + "), Angle: " + angle);
        }
    }
}
于 2010-12-17T07:40:09.190 回答
0

针对您问题的这一部分:

“我的画是正确的实现还是有更好的方法”

这是来自 Box2D 网站:

  • Box2D 使用什么单位?

Box2D 针对米-千克-秒 (MKS) 进行了调整。您的移动物体应在 0.1 - 10 米之间。不要以像素为单位!你会得到一个抖动的模拟。

  • 如何将像素转换为米?

假设您有一个 100x100 像素的角色精灵。您决定使用 0.01 的比例因子。这将使角色物理框为 1m x 1m。所以去做一个1x1的物理盒子。现在假设字符从像素坐标 (345,679) 开始。所以将物理框定位在 (3.45,6.79)。现在模拟物理世界。假设角色物理框移动到 (2.31,4.98),那么将角色精灵移动到像素坐标 (231,498)。现在唯一棘手的部分是选择比例因子。这真的取决于你的游戏。你应该尽量让你的移动物体在 0.1 - 10 米的范围内,1 米是最佳位置。

...

  • 新用户犯的最大错误是什么?

使用像素作为长度而不是米。

...

来源:http ://code.google.com/p/box2d/wiki/FAQ

于 2011-12-25T15:17:56.097 回答
0
public class PhysicsWorld extends View{


protected static final int GUIUPDATEIDENTIFIER = 0x231;

public int targetFPS = 40;
public float timeStep = 10.0f / targetFPS;
public int iterations = 5;

private Body[] bodies;
private int count = 0;

private AABB worldAABB;
public World world;
private PolygonDef groundShapeDef;

public int World_W,World_H;

private Paint paint;

private float radius=10;


public PhysicsWorld(Context context,int W,int H) {
    super(context);
    World_W=W;
    World_H=H;
    // Step 1: Create Physics World Boundaries
    worldAABB = new AABB();

    Vec2 min = new Vec2(-50, -50);
    Vec2 max = new Vec2(World_W + 50, World_H + 50);

    worldAABB.lowerBound.set(min);
    worldAABB.upperBound.set(max);

    // Step 2: Create Physics World with Gravity
    Vec2 gravity = new Vec2((float) 0.0, (float) -10.0);
    boolean doSleep = true;
    world = new World(worldAABB, gravity, doSleep);


    // Step 3: 
    //Create Ground Box :
    BodyDef bodyDef = new BodyDef();
    bodyDef.position.set(new Vec2((float) 0.0, (float) -10.0));
    Body groundBody = world.createBody(bodyDef);
    groundShapeDef = new PolygonDef();
    groundShapeDef.setAsBox((float) World_W, (float) 10);
    groundBody.createShape(groundShapeDef); 
    // up :
    bodyDef = new BodyDef();
    bodyDef.position.set(new Vec2((float) 0.0, (float) (World_H+10.0) ));
    groundBody = world.createBody(bodyDef);
    groundShapeDef = new PolygonDef();
    groundShapeDef.setAsBox((float) World_W, (float) 10);
    groundBody.createShape(groundShapeDef); 
    // left :
    bodyDef = new BodyDef();
    bodyDef.position.set(new Vec2((float) -10, (float) 0.0 ));
    groundBody = world.createBody(bodyDef);
    groundShapeDef = new PolygonDef();
    groundShapeDef.setAsBox((float)10, (float) World_H);
    groundBody.createShape(groundShapeDef); 
    // right :
    bodyDef = new BodyDef();
    bodyDef.position.set(new Vec2((float) World_W+10, (float) 0.0 ));
    groundBody = world.createBody(bodyDef);
    groundShapeDef = new PolygonDef();
    groundShapeDef.setAsBox((float)10, (float) World_H);
    groundBody.createShape(groundShapeDef); 
    //

    // step 4: initialize 
    bodies=new Body[50];

    // 
    paint=new Paint();
    paint.setStyle(Style.FILL_AND_STROKE);

    paint.setColor(Color.CYAN);
}

public void addBall() {

    // Create Dynamic Body
    BodyDef bodyDef = new BodyDef();
    Random rnd = new Random();
    bodyDef.position.set((float) radius*2+rnd.nextInt( (int)(World_W-radius*4) ), (float)2*radius+ rnd.nextInt( (int)(World_H-radius*4) ));
    bodies[count] = world.createBody(bodyDef);

    // Create Shape with Properties
    CircleDef circle = new CircleDef();
    circle.radius = (float) radius;
    circle.density = (float) 1.0;
    circle.friction = 0.1f; 
    circle.restitution=0.5f;

    // Assign shape to Body
    bodies[count].createShape(circle);
    bodies[count].setMassFromShapes();






    // Increase Counter
    count += 1;        
}
public void addBox() {
    BodyDef bodyDef  = new BodyDef();
    Random rnd = new Random();
    bodyDef.position.set((float)2*count+rnd.nextInt( (int)(World_W-4*count) ), (float)2*count+rnd.nextInt( (int)(World_H-count*4) ));
    bodies[count]     = world.createBody(bodyDef);        

    // Create Shape with Properties
    PolygonDef boxShapeDef  = new PolygonDef();
    boxShapeDef.setAsBox((float) 10.0, (float) 10.0);
    boxShapeDef.density = 1.0f;     // A density of 0 will create a fixed Body that doesn't move
    boxShapeDef.friction = 0.1f;    // How much friction
    boxShapeDef.restitution = 0.5f; // How bouncy is this Shape?

    // Assign shape to Body
    bodies[count].createShape(boxShapeDef);
    bodies[count].setMassFromShapes();  
    bodies[count].m_userData = "Box";

    count += 1;
}


public void update() {  
world.step(timeStep/5, 1);
    postInvalidate(); 
 }  
protected void onDraw(Canvas canvas) {
    for(int j = 0;j<count;j++)
    {
        canvas.drawRect((float)(bodies[j].getPosition().x -10), (float)(bodies[j].getPosition().y - 10), (float)(bodies[j].getPosition().x+ 10), (float)(bodies[j].getPosition().y + 10), paint );
        canvas.drawCircle(bodies[j].getPosition().x,World_H- bodies[j].getPosition().y, radius, paint);
    }
}
于 2012-02-07T12:08:46.283 回答