jBox2d android 绘制动态物体
我从这里开始学习教程添加了视图的绘图代码(覆盖整个屏幕)。尽管我正在调用 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);
}
}
I started off with the tutorial here and added drawing code for a view (covering the entire screen). The scene appears static and not dynamic even though I'm calling world.step(,). How does one make the scene dynamic and is my drawing the right implementation or is there a better way (using jBox2d functions)?
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);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的代码存在很多问题......但是这个答案可能已经太晚了,无论如何都无法提供任何帮助。
首先,world.createBody() 似乎已被弃用。现在您必须在我拥有的最新版本的 Android Box2D jar 中显式调用 world.createDynamicBody() 。
无论如何......我的版本是这样的......并不完美,但至少它是动态的。
There are a number of issues with your code....but this answer is probably way too late to be of any help anyways.
Firstly, world.createBody() seems to have been deprecated. Now you have to explicitly call world.createDynamicBody() in the latest version of the Android Box2D jar that I have.
Anyways...my version goes something like this...not perfect but at least its dynamic.
回答您问题的这一部分:
“我的绘图是正确的实现还是有更好的方法”
这是来自 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/常见问题解答
In response to this part of your question:
"is my drawing the right implementation or is there a better way"
This is from the Box2D website:
Box2D is tuned for meters-kilograms-seconds (MKS). Your moving objects should be between 0.1 - 10 meters. Do not use pixels as units! You will get a jittery simulation.
Suppose you have a sprite for a character that is 100x100 pixels. You decide to use a scaling factor that is 0.01. This will make the character physics box 1m x 1m. So go make a physics box that is 1x1. Now suppose the character starts out at pixel coordinate (345,679). So position the physics box at (3.45,6.79). Now simulate the physics world. Suppose the character physics box moves to (2.31,4.98), so move your character sprite to pixel coordinates (231,498). Now the only tricky part is choosing a scaling factor. This really depends on your game. You should try to get your moving objects in the range 0.1 - 10 meters, with 1 meter being the sweet spot.
...
Using pixels for length instead of meters.
...
Source: http://code.google.com/p/box2d/wiki/FAQ