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.
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 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;
I have these box2d bodies. I want to check for touch events on the bodies. To be specific, touch on a certain area of the body. Please see the image below, within the body, how can I check if the user touched on the blue area of the body (upper right corner).
I can get the touch coordinates, convert it to world coordinates and check if they overlap with that of the box, but that will trigger even if the box is touched anywhere inside it.
Maybe its too late but i will answer your question for who needs help.
You should create a fixture for the body which defines body's edges and attributes. Than you need to add fixtures to the body as sensor. Code sample would be seems like this.
// create bodydef
BodyDef bdef = new BodyDef();
bdef.type = BodyType.DynamicBody;
bdef.position.set(60 / PPM, 120 / PPM);
bdef.fixedRotation = true;
bdef.linearVelocity.set(1f, 0f);
// create body from bodydef
Body body = world.createBody(bdef);
// create box shape for player collision box
PolygonShape shape = new PolygonShape();
shape.setAsBox(13 / PPM, 13 / PPM);
// create fixturedef for player collision box
FixtureDef fdef = new FixtureDef();
fdef.shape = shape;
fdef.density = 1;
fdef.friction = 0;
// create player collision box fixture
body.createFixture(fdef);
shape.dispose();
// create box shape SENSOR for player
shape = new PolygonShape();
shape.setAsBox(13 / PPM, 3 / PPM, new Vector2(0, -13 / PPM), 0);
// create fixturedef SENSOR for player
fdef.shape = shape;
fdef.isSensor = true;
// create player SENSOR fixture
body.createFixture(fdef).setUserData("SENSOR");;
Have a nice day.
The Body itself has nothing common with Libgdx Input/Output operations - this is what is important to understand. Libgdx is handling touching and gestures by
Listeners mechanism - for example InputListener
Scene2d built-in framework
Then you cannot bind body instance to the listener however you can do this with whole screen (and then calculate somehow if coordinates are in body bounds - then if yes in which part exactly) or you can do this by creating a Scene2d actor instance.
If I were you I would create an Actor (for example rectangle shape) with size of part of body you want to be "touchable". The actor should has attached ClickListener with method that you want to fire on touch. Then in the actor's act() method I would update actor position due to the body position.
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.