I set a contact listener on my world and for some reason it isn't getting called when fixtures collide. I can confirm that the fixtures are indeed colliding with a box2dDebugRenderer. I have a suspicion that the problem "could" be that each frame for the player, I remove the fixture and add a new one (Because there is no way (that I know of) to resize/re-position fixture). I am adding the listener to the correct world, the world is working correctly, act is being called (ofcourse). Thanks for your help!
This is called each frame in the player class :
private void createFixture(boolean remove) {
if (remove) {
body.destroyFixture(fixture);
}
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.KinematicBody;
bodyDef.position.set(0, 0);
body = world.createBody(bodyDef);
FixtureDef fixtureDef = new FixtureDef();
CircleShape circle = new CircleShape();
circle.setRadius(getWidth() / 2);
circle.setPosition(new Vector2(0, getY() + getHeight() / 2));
fixtureDef.shape = circle;
fixture = body.createFixture(fixtureDef);
circle.dispose();
}
You are missing filterdata in your FixtureDef. You have to set category bits and mask bits.
Try this:
fixtureDef.filter.categoryBits = 1;
fixtureDef.filter.maskBits = 1;
Related
I am currently using libgdx and it's box2d extension to make an open world platformer. I wanted to render a world from a tmx tilemap, and add physics from it. The tilemap renders fine (using OrthogonalTiledMapRenderer), but when I tried to add phyiscs using the following code nothing happened.
public void renderPhysicsMap(TiledMap map, World world, int layer, int tileSize) {
TiledMapTileLayer mapLayer = (TiledMapTileLayer) map.getLayers().get(layer);
MapObjects mapObjects = mapLayer.getObjects();
for (MapObject mapObject : mapObjects) {
Rectangle rect = ((RectangleMapObject) mapObject).getRectangle();
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.StaticBody;
Body body = world.createBody(bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox((rect.width/2)/tileSize, (rect.height/2)/tileSize);
Fixture fixture = body.createFixture(shape, 0.0f);
fixture.setFriction(0.1f);
Vector2 center = new Vector2();
rect.getCenter(center);
body.setTransform(center.scl(1/tileSize), 0);
}
}
After some debugging (running mapObjects.getCount()) I found that the size was 0. This is odd, because I know this is a valid tilemap (I can render it just fine). Would anyone know why this is?
I am trying to make ball bouncing between 4 walls using the JBox2D library in Java. The code above is the code I use to create and the ball in the world.
// Creating the Body Definition
BodyDef bodyDef = new BodyDef();
// Set position to Body Definition
bodyDef.position.set(x, y);
// Setting body type to body definition
bodyDef.type = bodyType;
// Creating CircleShape object
CircleShape circleShape = new CircleShape();
// Setting radius to CircleShape
circleShape.m_radius = radius;
/ /Creating Fixture Definition object
FixtureDef fixtureDef = new FixtureDef();
// Setting circleShape as shape of fixture definition
fixtureDef.shape = circleShape;
// This defines the heaviness of the body with respect to its area
fixtureDef.density = density;
// This defines how bodies slide when they come in contact with each other.
// Friction value can be set between 0 and 1. Lower value means more slippery bodies.
fixtureDef.friction = friction;
// This define how bouncy is the body.
// Restitution values can be set between 0 and 1.
// Here higher value means more bouncy body.
fixtureDef.restitution = restitution;
// "Uploading" the ball into the world
Body body = world.createBody(bodyDef);
// Setting fixtureDef as body's fixture
body.createFixture(fixtureDef);
And this is the code I used to make a wall. For example the right wall.
// Creating the Body Definition
BodyDef bodyDef = new BodyDef();
// Set position to Body Definition
bodyDef.position.set(850f, 0f);
// Setting body type as static
bodyDef.type = BodyType.STATIC;
// Creating CircleShape object
PolygonShape polygonShape = new PolygonShape();
// Set polygon shape as a box
polygonShape.setAsBox(1f - 44,1000);
// Creating Fixture Definition object
FixtureDef fixtureDef = new FixtureDef();
// Setting circleShape as shape of fixture definition
fixtureDef.shape = polygonShape;
fixtureDef.friction = 0f;
// "Uploading" the ball into the world
Body body = world.createBody(bodyDef);
// Setting fixtureDef as body's fixture
body.createFixture(fixtureDef);
The ball starts to move vertically or horizontally when it collides with another body. The circle goes fine until it collides with another body. As some other posts said, I tried setting the ball's friction to 0 but that didn't work for me.
These are the values I use for the ball:
tileFixture.density = 1f;
tileFixture.friction = 1f;
tileFixture.restitution = 10000f;
I found my mistake. The problem is in the value of the restitution. The value is a lot so JBox2D makes move horizontally or vertically. I changed the value of restitution to 1f and now it works great.
I've been looking at some other threads, and despite every thing I have tried, the shapes I have created in box2d are not rendering. It is very bizarre, and I hope that you guys can provide a solution.
public class worldRender {
fighterGame game;
PlayScreen renderGame;
private Viewport gamePort = new StretchViewport(1020 / game.PPM,760 / game.PPM);
World world = new World(new Vector2(0,-10), true);
Box2DDebugRenderer b2dr = new Box2DDebugRenderer();
private OrthographicCamera gameCam = new OrthographicCamera();
BodyDef bDef = new BodyDef();
public Body b2body;
FixtureDef fixtureDef = new FixtureDef();
ShapeRenderer shapeRender;
public worldRender() {
gameCam = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
gameCam.position.set(1020/2, 760/2, 0);
}
public worldRender(float dt) {
gameCam.update();
world.step(1/60f, 6, 2);
b2dr.render(world, gameCam.combined);
bodyRender();
}
public void bodyRender() {
BodyDef bdef = new BodyDef();
bdef.position.set(0.0f / game.PPM,4.0f / game.PPM);
bdef.type = BodyDef.BodyType.DynamicBody;
b2body = world.createBody(bdef);
FixtureDef fdef = new FixtureDef();
fdef.friction = 0.25f;
CircleShape shape = new CircleShape();
shape.setRadius(5);
fdef.shape = shape;
fdef.density = 1.0f;
b2body.createFixture(fdef);
}
}
I'm going to list off a few solutions because not everything is clear in the snippet:
Are you sure the worldRender() method is being run
If you are using Game and Screen make sure your game render() method calls super() otherwise your Screen render() method will not be run;
As mentioned before is the value of PPM correct/what is it?
Does this draw:
// First we create a body definition
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.StaticBody;
// Set our body's starting position in the world
bodyDef.position.set(50, 50);
// Create our body in the world using our body definition
Body body = world.createBody(bodyDef);
// Create a circle shape and set its radius to 6
CircleShape circle = new CircleShape();
circle.setRadius(10f);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
// Create our fixture and attach it to the body
Fixture fixture = body.createFixture(fixtureDef);
// Remember to dispose of any shapes after you're done with them!
// BodyDef and FixtureDef don't need disposing, but shapes do.
circle.dispose();
This should draw a circle of radius 10 at x=10,y=10 (make sure those points are in your view port.
I would suggest cleaning up your code a bit, and studying some more tutorials, that will probably solve your problems. But let's give you some hints to get you on the way:
I somehow suspect you are creating a worldRender object every frame. Java is a garbage collected language, doing so will severly impact your performance. Persist as many objects as possible. In my bigger games, i create next to 0 objects each render and game logic tick. Aim for that.
Finally, what will probably solve your problem: the camera you use to render your box2ddebugrenderer ("dbrndr") has screen pixels as units. The dbrndr uses meters as render units. You need to give the dbrndr its own camera in meters. Your current method will draw a 10pixel wide circle at 0 / 4 pixels in the bottom left corner.
Do you create your world with gravity? if yes, the circle instantly falls out of your screen...Yes you do.
You might actually even see your circle for a splitsecond in the lower left corner after starting... given that you render before you do box2d logic.
Please dispose() all objects that you create, otherwise the memory they occupy is not free'd afterwards.
I am using the basic libgdx box2d to manage physics operations of a game. Everything is working properly, except the rotations: even when I set
anyobject.body.setAngularVelocity(someLargeConstant);
the object rotates really slowly(and almost at the same speed) no matter what the 'someLargeConstant' is. Except when I use small numbers for parameter, it can rotate slower. Thus I think I somehow have a maximum angular velocity constant inside my world object, which should be set to some small value.
(I also had a similar issue with linear velocity before and I solved it by adjusting the pixels/meter scale. So its unlikely that the problem is a scaling issue.)
How can I enable the objects to rotate faster?
Here is the code I use:
private static World world = new World(new Vector2(0, 0), true); //Create a world with no gravity
to create an object I call another class
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
}
and here I just try to make it rotate fast:
tempBall.body.setAngularVelocity(20000);
angularvilocity is used to set the direction of the rotation when it comes to use it with an actionListener as like key or mouse lister , here is an example of use :
case KeyEvent.VK_RIGHT:
ball.setAngularVelocity(-20); // Directly set the angular velocity
case KeyEvent.VK_LEFT:
ball.setAngularVelocity(20); // Directly set the angular velocity
like you can see here the code make the ball body rotate to the right in Key_Right pressed and to the left in Key_Left pressed , and i can play aroud with it's argument to increase or lower the rotation speed and it works pretty well for me , here is my body definition try to apply the same values and it must work with no problem :
private Body createObject(Shape shape, BodyType type, Vec2 position, float orientation, Sprite sprite) throws InvalidSpriteNameException {
for(Sprite s:spriteList) {
if(s.getName().equals(sprite.getName())) {
throw new InvalidSpriteNameException(sprite.getName()+" already used.");
}
}
Body body = null;
FixtureDef fixDef = new FixtureDef();
fixDef.shape = shape;
fixDef.density = 0.1f;
fixDef.isSensor = false;
fixDef.restitution = 0.1f;
BodyDef bodyDef = new BodyDef();
bodyDef.type = type;
bodyDef.angularDamping = 0.1f;
bodyDef.linearDamping = 0.1f;
bodyDef.fixedRotation = false;
bodyDef.gravityScale = 1f;
bodyDef.linearVelocity = new Vec2(0,0);
bodyDef.angularVelocity = 0;
bodyDef.position = new Vec2(position);
bodyDef.angle = orientation;
bodyDef.allowSleep = true;
spriteList.add(sprite); // Save the sprite to the list (sprites must be serialiazed in the PhysicalWorld)
bodyDef.userData = sprite; // Link the body and the sprite
do {
body = jBox2DWorld.createBody(bodyDef);
} while(body== null); // Wait until the object is really created
sprite.linkToBody(body); // Link the body to the sprite (this link is not serialiazed)
body.createFixture(fixDef);
return body;
}
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.
This should be a quick question, with hopefully a quick answer. :) I am using box2d for a side scroller project I'm doing. All's going good, thanks for asking. :D Anyways, my character needed to differently sized boxes used for bounding. I thought it would be as simple as adding a new fixture to the body, but it didn't work. It crashes and I get this:
java: ./Box2D/Collision/b2Distance.h:103: const b2Vec2&
b2DistanceProxy::GetVertex(int32) const: Assertion `0 <= index &&
index < m_count' failed.
I have no idea what that means. Here is the code I use to create the body and fixtures:
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(level.character.position);
Body body = b2world.createBody(bodyDef);
level.character.body = body;
PolygonShape polygonShapeHead = new PolygonShape();
origin.x = level.character.circleBoundOrigin.x * 2.0f;
origin.y = level.character.circleBoundOrigin.y * 3.0f;
polygonShapeHead.setAsBox(level.character.circleBoundOrigin.x,
level.character.circleBoundOrigin.y, origin, 0);
FixtureDef fixtureDefHead = new FixtureDef();
fixtureDefHead.shape = polygonShapeHead;
fixtureDefHead.friction = level.character.friction.x;
body.createFixture(fixtureDefHead);
polygonShapeHead.dispose();
PolygonShape polygonShapeBod = new PolygonShape();
origin = level.character.rectBoundOrigin;
polygonShapeHead.setAsBox(level.character.rectBoundOrigin.x,
level.character.rectBoundOrigin.y, origin, 0);
FixtureDef fixtureDefBod = new FixtureDef();
fixtureDefBod.shape = polygonShapeBod;
fixtureDefBod.friction = level.character.friction.x;
body.createFixture(fixtureDefBod);
polygonShapeBod.dispose();
As far as I know, I'm doing everything properly. So why is it not working? Why does it crash? I'm using fixturedef. Could that possibly be the problem. Thanks!
This happens when you add/destroy an obect during world.step(). If you're dynamically adding/destroying objects you need to queue them up and ensure you make your changes before or after you call world.step()
It's discussed in this tutorial series.
http://youtu.be/ACQaU2Vr1ao?t=15m26s