I'm trying to understand the amount of force i need to move my object. This is how my world is setup and the physics step is done
private void setupWorld() {
mWorld = new World(new Vector2(0f, -9.8f), true);
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(x, y);
body = world.createBody(bodyDef);
PolygonShape box=new PolygonShape();
box.setAsBox(1,1);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = box;
fixtureDef.density = 1f;
fixtureDef.friction = 0.0f;
fixtureDef.restitution = 0.0f;
Fixture fixture = body.createFixture(fixtureDef);
box.dispose();
}
private void doPhysicsStep(float deltaTime) {
float frameTime = Math.min(deltaTime, 0.25f);
accumulator += frameTime;
while (accumulator >= TIME_STEP) {
body.applyForceToCenter(new Vector2(0, 10f), true);
world.step(TIME_STEP, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
accumulator -= (TIME_STEP);
}
}
So i've got a 1x1 box with a density 1. Gravity is set at -9.8 and i'm expecting that when I apply an amount of force to my box that is greater than the gravity (in this example i've set it to 10) that the box should start moving up.
But the box doesn't move. I have to set the force to about 80 (i.e. body.applyForceToCenter(new Vector2(0, 80f), true);) before it starts to move the box.
I've considered that this is due to my time step (which i've currently set to 1/60f), but if anything taking that into account would reduce the force I'm applying in each step.
Can someone explain what i'm miscalculating here?
Your box has a mass of 4, not 1, because in method setAsBox(float hx, float hy) hx means half of desired width, and hy means half of desired height. So if you want to have a box 1 x 1 you will call setAsBox(0.5F, 0.5F).
But this doesn't explain why you need a force of 80 to move it, because force of 50 should be enough to make a difference.
Fg = m * g = 9.8 * 4 = 39.2
On my test project on object of mass 4 even the force of 40 is noticeable when applied programmatically (the delay of application start and pressing the button is significant so I avoid it).
Related
I have been recently trying to get back into LibGDX's version of Box2D, and I looked back at a demo I created a few months back, and my code looks fine, and from my Google search results, my code is fine, but for the life of me, I cannot get the Fixture to render.
Here is my (Minimalist example) code, and for the life of me, I cannot get it to work Note: I built a wrapper around the LibGDX Game class, should be self-explanatory:
public class TestBox2D extends EGGame {
int width;
int height;
static final Vector2 ZERO_GRAVITY = new Vector2(0f, 0f);
OrthographicCamera camera;
World world;
Body body;
Box2DDebugRenderer box2dDebugRenderer;
RayHandler rayHandler;
... // Removed Constructor, nothing special here.
#Override
protected void init() {
width = Gdx.graphics.getWidth() / 2;
height = Gdx.graphics.getHeight() / 2;
camera = new OrthographicCamera(width, height);
camera.position.set(width / 2, height / 2, 0);
camera.update();
world = new World(ZERO_GRAVITY, true);
box2dDebugRenderer = new Box2DDebugRenderer();
rayHandler = new RayHandler(world);
rayHandler.setCombinedMatrix(camera.combined);
// creating Body
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.StaticBody;
bodyDef.position.set(width/2, height/2);
body = world.createBody(bodyDef);
CircleShape shape = new CircleShape();
shape.setRadius(1f);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
body.createFixture(fixtureDef);
}
#Override
protected void updateGame() {
world.step(1f / 30f, 6, 2);
rayHandler.update();
}
#Override
protected void renderGame() {
box2dDebugRenderer.render(world, camera.combined);
rayHandler.render();
}
#Override
public void dispose() {
world.dispose();
}
... // Removed main method, nothing special here.
}
Note that world.getBodyCount(); and world.getFixtureCount(); both return 1.
Probable causes of problem.
Check if you have called render on fixtures in either RayHandler class or Box2DDebugRenderer class.
You have not set the position of the circle shape. It might be lying on the edge and remain out of camera bounds.
Check your units. Radius of circle might be relatively so small that it would be invisible, or it might be so large that it might be covering entire screen.
Hope this helps.
You can try the following, one of the things mention Tanmay Patil, it resizes body:
Example:
Varible Class:
long time = 0;
float testSize = 0;
Call in your render method:
time += System.nanoTime();
if (time >= 100000000){
time = 0;
testSize += (0.1f);
body.getFixtureList().first().getShape().setRadius(testSize);
}
if not notice any change, try the opposite:
time += System.nanoTime();
if (time >= 100000000){
time = 0;
testSize -= (0.1f);
body.getFixtureList().first().getShape().setRadius(testSize);
}
Edit:
On the other hand, this does not affect the question, but you can call dispose here if you want:
.////////////
CircleShape shape = new CircleShape();
shape.setRadius(1f);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
body.createFixture(fixtureDef);
shape.dispose();
}
Fixed.
The issue was that I was attempting to call RayHandler#render() after Box2DDebugRenderer.render(...) while the RayHandler didn't have any Light objects (Adding a PointLight allowed it to render), but whatever the reason for it is, it's weird, but calling the RayHandler#render() first allows it to work. This might be a bug in LibGDX that I will report.
I am using Box2d for a game, and although I use large constants to set angular velocity, the fastest speed I can get is 1 revolution at 3.86 seconds.
I had checked my source code in the following thread and everything is the same with what I have been suggested from both users in here and in tutorials:
setAngularVelocity rotates really slowly
However than I noticed the following unresolved thread:
http://www.reddit.com/r/libgdx/comments/1qr2m3/the_strangest_libgdxbox2d_behaviour/
and noticed that might actually be the problem. Here is my dispose method
public void dispose() {
//Get Rid of Everything!
Assets.Clear();
GameEngine.Clear();
BallMap.clear();
PlayerMap.clear();
shapeRenderer.dispose();
debugRenderer.dispose();
world.dispose();
batch.dispose();
font.dispose();
}
They are all reinitialized on the beginning as follows:
this.game = game;
this.cameraWidth = cameraWidth*pixelRatio;
this.cameraHeight = cameraHeight*pixelRatio;
batch = new SpriteBatch();
shapeRenderer = new ShapeRenderer();
stateTime = 0F;
Scores = new Integer[]{0, 0};
debugRenderer = new Box2DDebugRenderer();
world = new World(new Vector2(0, 0), true); //Create a world with no gravity
GameEngine.setContactListener(world);
I navigate through screens with the following code:
public void create () {
scene_menu = new MainMenuScreen(this, cameraWidth, cameraHeight);
setScreen(scene_menu);
}
public void swtogame(){
scene_menu.dispose();
scene_game = new MatchScreen(this, cameraWidth, cameraHeight);
setScreen(scene_game);
}
public void swtomenu(){
scene_game.dispose();
scene_menu = new MainMenuScreen(this, cameraWidth, cameraHeight);
setScreen(scene_menu);
}
the way i initialize objects:
public Object(World world, short category, short mask, float x, float y, float radius, Sprite image,
float maxSpeed, float frictionStrength, float linearDamping, float angularDamping, boolean movable,
float elasticity, float mass){
this.world = world;
this.category = category;
this.mask = mask;
// We set our body type
this.bodyDef = new BodyDef();
if(movable==true){bodyDef.type = BodyType.DynamicBody;}else{bodyDef.type = BodyType.StaticBody;}
// Set body's starting position in the world
bodyDef.position.set(x, y);
bodyDef.linearDamping = linearDamping;
bodyDef.angularDamping = angularDamping;
// Create our body in the world using our body definition
this.body = world.createBody(bodyDef);
// Create a circle shape and set its radius
CircleShape circle = new CircleShape();
circle.setRadius(radius);
// Create a fixture definition to apply our shape to
fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = (float) (mass/(Math.PI*radius*radius));
fixtureDef.friction = frictionStrength;
fixtureDef.restitution = elasticity;
fixtureDef.filter.categoryBits = category;
fixtureDef.filter.maskBits = mask;
// Create our fixture and attach it to the body
this.fixture = body.createFixture(fixtureDef);
// BodyDef and FixtureDef don't need disposing, but shapes do.
circle.dispose();
... unrelated functions after that
}
Am I disposing correctly? Is this a bug? Is there any way to get around it and use the setAngularVelocity properly?
Because you haven't shown much code, I can I'm not 100% sure that I'm right, but I think that you are hitting the built in maximum movement limit of 2.0 units per time step. This means that at a typical framerate of 60Hz a body covering 2 units per timestep is moving at 120 m/s or 432 km/h (270 mph). Unfortunately it seems that there is no direct way to change this limit in Java, because this limit seems to be defined in the native C++ librarys.
But I think that the real problem is that you have a wrong scale. Box2D uses MKS (meters, kilograms, and seconds). And you may have used pixels instead of meters. The FAQ of Box2D suggests to use
objects [that are] between 0.1 - 10 meters
otherwise you can get strange situations.
See http://www.iforce2d.net/b2dtut/gotchas#speedlimit
and https://code.google.com/p/box2d/wiki/FAQ
I just found the problem, and it was pretty simple. Im just going to post this here for future googlers:
Object was actually rotating properly, the problem was in my drawing method, I didn't use conversion between radians to degrees in my batch.draw, and it interpreted everything in radians. I know such an amateur mistake! Thanks a lot for your time.
I want to know how to prevent an object in crossing another. I have a ball and a square which I can move whith my mouse. When my ball is on my square I move it (in top for example) if I go very slowly the ball remains on the square if not it crosses it.
if both of your 2 object have a fixture defined they will not be able to crossing one another this is an exmple of how a dynamic object who will be affected by physics in the BOX2D world must be created , and also this object can't tunneling through a sensor :
public Ball (World world){
this.world = world;
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DYNAMIC;
bodyDef.position.set(0.0f/RATE, 0.0f/RATE);
Ballbody = world.createBody(bodyDef);
CircleShape circle = new CircleShape();
radius = (int) (Math.random()*30+15); // you can set a non randum raduis
circle.m_radius = radius/RATE;
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.restitution = 0.8f;
fixtureDef.density = 2.0f;
fixtureDef.friction = 0.3f;
fixtureDef.filter.groupIndex = -1;
Ballbody.createFixture(fixtureDef);
Ballbody.getFixtureList().setUserData("Ballounaton"); // optional
Vec2 ballVec = new Vec2((float) (Math.random()*8+2),0.0f);
Ballbody.setLinearVelocity(ballVec);
}
make sure to define a fixture to your box2d dynamic or static object to avoid tunneling through a sensor like in this exmple :
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.restitution = 0.8f;
fixtureDef.density = 2.0f;
fixtureDef.friction = 0.3f;
fixtureDef.filter.groupIndex = -1;
Ballbody.createFixture(fixtureDef);
according to BOX2D official documentation :
Recall that shapes don’t know about bodies and may be used
independently of the physics simulation. Therefore Box2D provides the
b2Fixture class to attach shapes to bodies. Fixtures hold the
following:
a single shape
broad-phase proxies
density, friction, and restitution
collision filtering flags
back pointer to the parent body
user data
sensor flag
Edit 2: http://youtu.be/KiCzUZ69gpA - as you can see in this video, the shaking effect is amplified when I also render some text for each body. Observe how the ground body (blue) shakes violently when each body has some text rendered near it, and how it does not when text rendering is commented out. This has to be connected!
Edit: I've made two important additions to the original question: I've added my rendering functions, and the camera (translation) methods, and I think that the error is actually there, not in JBox2D.
I'm trying to simulate and render a lot of random bodies (2-20) connected with RevoluteJoints. One body can be connected to multiple others, and there are no separate constructions, i.e. all the bodies are interconnected.
However, when watching the live rendering, it is very shaky and unstable. By that I mean that bodies' positions (or maybe angles) seem to be randomly fluctuating for no apparent reason, making the simulation look unstable.
Here's a video of what I'm observing:
http://youtu.be/xql-ypso1ZU
Notice the middle square and the rotating rectangle. The middle square is shifting its position back and forth slightly at seemingly random intervals, and the rotating rectangle is very jittery (take a look at the point it is rotating about).
What could this effect be due? Is it some known issue with (J)Box2D, or is it an issue with my rendering system? I think that I have somehow misconfigured the physics engine, but also some floating point math in the rendering system could be the culprit.
Here's how I'm creating the bodies and the joints:
private Body setPart(Part part) {
// body definition
BodyDef bd = new BodyDef();
bd.position.set(0f, -10f);
bd.angle = 0f;
bd.type = BodyType.DYNAMIC;
// define shape of the body.
PolygonShape Shape = new PolygonShape();
Shape.setAsBox(part.width / 2, part.height / 2);
// define fixture of the body.
FixtureDef fd = new FixtureDef();
Filter filter = new Filter();
filter.groupIndex = -1;
fd.filter = filter;
fd.shape = Shape;
fd.density = 0.5f;
fd.friction = 0.3f;
fd.restitution = 0.5f;
// create the body and add fixture to it
Body body = world.createBody(bd);
body.createFixture(fd);
body.setUserData(new PartUserData());
return body;
}
private void setJoint(PartJoint partJoint) {
Body bodyOne = partToBody.get(partJoint.partOne);
Body bodyTwo = partToBody.get(partJoint.partTwo);
RevoluteJointDef jointDef = new RevoluteJointDef();
jointDef.bodyA = bodyOne;
jointDef.bodyB = bodyTwo;
jointDef.localAnchorA = partJoint.partOne
.getAnchor(partJoint.percentOne);
jointDef.localAnchorB = partJoint.partTwo
.getAnchor(partJoint.percentTwo);
// rotation
jointDef.lowerAngle = GeomUtil.circle(partJoint.rotateFrom);
jointDef.upperAngle = GeomUtil.circle(partJoint.rotateTo);
jointDef.enableLimit = true;
jointDef.maxMotorTorque = 10.0f; // TODO limit maximum torque
jointDef.motorSpeed = GeomUtil.circle(partJoint.angularVelocity);
jointDef.enableMotor = true;
world.createJoint(jointDef);
}
The time step is 0.01f.
Here is how I draw bodies:
private void drawBody(Body body) {
// setup the transforms
Vector position = camera.translate(body.getPosition());
currentGraphics.translate(position.x, position.y);
currentGraphics.rotate(body.getAngle());
// do the actual rendering
for (Fixture fixture = body.getFixtureList(); fixture != null; fixture = fixture
.getNext()) {
PolygonShape shape = (PolygonShape) fixture.getShape();
if (body.getUserData() instanceof PartUserData) {
fillShape(shape, partFillColor);
currentGraphics.setStroke(partOutlineStroke);
outlineShape(shape, partOutlineColor);
} else {
fillShape(shape, groundFillColor);
outlineShape(shape, groundOutlineColor);
}
}
// clean up
currentGraphics.rotate(-body.getAngle());
currentGraphics.translate(-position.x, -position.y);
currentGraphics.setColor(defaultColor);
currentGraphics.setStroke(defaultStroke);
}
I think that the issue might be the way I'm handling rendering of all the bodies.
This is the algorithm for each body:
1. Translate the Graphics2D object to its position
2. Rotate it by body.getAngle()
3. Render the body
4. Rotate the graphics back
5. Translate the graphics back
Could it be that amongst all these transforms something goes wrong?
When I removed the calls to camera's methods, the effect seems to have been reduced. These are the relevant camera methods:
public Vector translate(Vec2 worldPosition) {
Vector point = new Vector();
point.x = (int) (worldPosition.x * pixelsPerMeter) - position.x;
point.y = (int) (worldPosition.y * pixelsPerMeter) - position.y;
point.x = (int) (point.x * zoom);
point.y = (int) (point.y * zoom);
point.x += renderer.getWidth() / 2;
point.y += renderer.getHeight() / 2;
return point;
}
public Vector translateRelative(Vec2 worldPosition) {
Vector point = new Vector();
point.x = (int) (worldPosition.x * pixelsPerMeter);
point.y = (int) (worldPosition.y * pixelsPerMeter);
point.x = (int) (point.x * zoom);
point.y = (int) (point.y * zoom);
return point;
}
But what part of them would cause an issue?
tl;dr: I've found a solution, but haven't identified the exact problem. Quite sure it's with my translation methods.
It seems that I have identified the scope of the problem and the solution, but I am still not sure what exactly is causing this behavior.
In those translation formulas I posted in the question, all JBox2D vectors are multiplied by a scale called pixelsPerMeter. When I set this scale to a low value, the shaking effect occurs (it's also important to note that there is another factor as well, called zoom, which is usually greater for a lower pixelsPerMeter).
So, it could be that when multiplying by a relatively low pixelsPerMeter, I have to multiply with a higher zoom factor, and since I'm converting to ints in both steps, there could be some errors in the floating point math or something. Please see the translation methods I've posted in the question.
Here's a video that demonstrates this: (to be uploaded)
Notice that when I set the pixelsPerMeter to 250, shaking seems to be gone, while when I set it to 25, it's quite visible.
Your solution was the correct one. You are not supposed to use pixel units for the Box2D physics engine :)
http://box2d.org/2011/12/pixels/
and
https://code.google.com/p/box2d/wiki/FAQ#How_do_I_convert_pixels_to_meters?
I have a rectangle that I would like to move fast but for what ever reason the faster velocity I use still seems slow. What am I doing wrong? I have also dropped a circle from above onto a surface and even tough I play with gravity it comes down like a ballon...
Some declarations
float velocity = 10000000f;
static final float BOX_STEP=1/60f;
static final int BOX_VELOCITY_ITERATIONS=6;
static final int BOX_POSITION_ITERATIONS=2;
Gravity, tried everything and they all seem to suck
world = new World(new Vector2(0, -50), true);
The ground my object is moving onto
//ground
BodyDef groundBodyDef =new BodyDef();
groundBodyDef.position.set(new Vector2(0, camera.viewportHeight * .08f));
Body groundBody = world.createBody(groundBodyDef);
PolygonShape groundBox = new PolygonShape();
groundBox.setAsBox((camera.viewportWidth) * 2, camera.viewportHeight * .08f);
groundBody.createFixture(groundBox, 0.0f);
And then here are my objects:
//ball
bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(new Vector2(camera.viewportWidth * .2f, camera.viewportHeight * .75f));
body = world.createBody(bodyDef);
CircleShape dynamicCircle = new CircleShape();
dynamicCircle.setRadius(camera.viewportWidth * .035f);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = dynamicCircle;
fixtureDef.density = 0.5f;
fixtureDef.friction = 0.5f;
fixtureDef.restitution = 0.8f;
body.createFixture(fixtureDef);
body.setLinearVelocity(0,-100);
//slime boy
BodyDef bodyBoxDef = new BodyDef();
bodyBoxDef.type = BodyType.DynamicBody;
bodyBoxDef.position.set(new Vector2(camera.viewportWidth * .08f,camera.viewportHeight * .191f));
bodyBox = world.createBody(bodyBoxDef);
PolygonShape slimeBox = new PolygonShape();
slimeBox.setAsBox(camera.viewportWidth * .04f, camera.viewportHeight * .03f);
FixtureDef fixtureSlimeDef = new FixtureDef();
fixtureSlimeDef.shape = slimeBox;
fixtureSlimeDef.density = 1.0f;
fixtureSlimeDef.friction = 0.0f;
fixtureSlimeDef.restitution = 0.0f;
bodyBox.createFixture(fixtureSlimeDef);
debugRenderer = new Box2DDebugRenderer();
body.applyTorque(1000000000);
bodyBox.setFixedRotation(true);
bodyBox.setBullet(true);
Any one have suggestions to speed up all movement in this?
I have been using a screen 1280 by 720 but I saw from other sources smaller is better so I scaled down to 640 by 260 but still not the preformance I want. How small should I really go?
From the Box2d Manual (Section 2.2):
Box2D is tuned for meters, kilograms, and seconds. So you can consider
the extents to be in meters. Box2D generally works best when objects
are the size of typical real world objects. For example, a barrel is
about 1 meter tall. Due to the limitations of floating point
arithmetic, using Box2D to model the movement of glaciers or dust
particles is not a good idea.
See https://stackoverflow.com/a/4556714/960524