我从教程here开始,添加了视图的绘图代码(覆盖整个屏幕)。即使我正在调用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);
}
}
答案 0 :(得分: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);
}
}
}
答案 1 :(得分:0)
回答你的这部分问题:
“我的绘图是正确的实现,还是有更好的方法”
这是来自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米是最佳点。
...
使用像素作为长度而不是米。
...
答案 2 :(得分: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);
}
}