Collision detection in kinematic bodies LIBGDX - java

I managed to use box2d in libgdx. However the example code given here is for dynamic body only. I tried to use it and it works great but when i change the Dynamic to KinematicBody the code does not work. here is my code
#Override
public void create() {
// Create our body definition
BodyDef groundBodyDef =new BodyDef();
groundBodyDef.type = BodyDef.BodyType.StaticBody;
// Set its world position
groundBodyDef.position.set(new Vector2(0, 10));
// Create a body from the defintion and add it to the world
groundBody = world.createBody(groundBodyDef);
// Create a polygon shape
PolygonShape groundBox = new PolygonShape();
// Set the polygon shape as a box which is twice the size of our view port and 20 high
// (setAsBox takes half-width and half-height as arguments)
groundBox.setAsBox(camera.viewportWidth, 10.0f);
// Create a fixture from our polygon shape and add it to our ground body
groundBody.createFixture(groundBox, 0.0f);
// Clean up after ourselves
groundBox.dispose();
//endregion
BodyDef bodyDef = new BodyDef();
// We set our body to dynamic, for something like ground which doesnt move we would set it to StaticBody
bodyDef.type = BodyDef.BodyType.KinematicBody;
// Set our body's starting position in the world
bodyDef.position.set(bolaX, bolaY);
// Create our body in the world using our body definition
body = world.createBody(bodyDef);
// Create a circle shape and set its radius to 6
CircleShape circle = new CircleShape();
circle.setRadius(20f);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = 20;
fixtureDef.friction = 0;
fixtureDef.restitution = 0.6f; // Make it bounce a little bit
// 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();
Gdx.input.setInputProcessor(this);
}
#Override
public void render() {
world.step(1/60f, 6, 2);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
//batch.getProjectionMatrix().set(camera.combined);
batch.begin();
textureBodies = body.getPosition();
float angle = MathUtils.radiansToDegrees * body.getAngle();
//batch.draw(ball,textureBodies.x ,textureBodies.y );
batch.draw(ball, textureBodies.x - (bola.getWidth() / 2) , textureBodies.y - (bola.getHeight()/2) , // the bottom left corner of the box, unrotated
1f, 1f, // the rotation center relative to the bottom left corner of the box
bola.getWidth(), bola.getHeight(), // the width and height of the box
1, 1, // the scale on the x- and y-axis
angle);
batch.end();
debugRenderer.render(world, camera.combined);
if(Gdx.input.isKeyPressed(Input.Keys.DPAD_UP)){
Gdx.app.log("Input Test", "key down: " + "aw ---- x" + body.getPosition().x + " y " + body.getPosition().y);
vel += 1;
//Gdx.app.log("vel","" + vel);
body.setLinearVelocity(0f,vel);
} else{
vel -= 1;
// Gdx.app.log("vel","" + body.getPosition().y);
body.setLinearVelocity(0f,vel);
}
int numContacts = world.getContactCount();
if (numContacts > 0) {
Gdx.app.log("contact", "start of contact list");
for (Contact contact : world.getContactList()) {
Fixture fixtureA = contact.getFixtureA();
Fixture fixtureB = contact.getFixtureB();
Gdx.app.log("contact", "between " + fixtureA.toString() + " and " + fixtureB.toString());
}
Gdx.app.log("contact", "end of contact list");
}
}
And here is the image.. You can see in the left side is the DynamicBody and the right side is the KinematicBody.
Getting the contacts works on Dynamic Body but not on Kinematic Body. Can you tell how to detect the collision in kinematic body?

Kinematic body dont collide with static body.
May be this will help you.

Kinematic Bodies are only influenced by velocities and not by forces
Static bodies have O displacement but are effected by forces i.e. they generate impulse upon collision whereas Dynamic Bodies have both

Related

Libgdx Box2d Player doesnt move

I got a problem on Box2d I'm new on Box2d so couldnt handle it movement of my player.
I want to move my player to the left and right when the user touch left and right buttons in my game.
in my game player already going through the up y axis .
I wanted see cool smooth animation while controlling player.
I just couldnt move my player to the left how can I do that ?
thanks in advance
//EDITED
I created a fixture for testing , I can move fixture but not my player.
how can I attach my player sprite to body ?
and I have to find a proper way to controlling body. it wont stop once you started.
this is my codes
public World world;
public Body bplayer;
public Box2DDebugRenderer b2dr;
public Matrix4 cameraBox2D;
PlayScreen
buttonimage.addListener(new ClickListener() {
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
bplayer.setLinearVelocity(-5*PPM , 0);
return true;
}
});
world = new World(new Vector2(player.getPosition().x , player.getPosition().y) , false);
b2dr = new Box2DDebugRenderer();
bplayer = createPlayer(player.getPosition().x , player.getPosition().y);
show method
buttonimage.setPosition(160,0);
rightbuttonimage.setPosition(320,0);
pauseimage.setPosition(220,-20);
cameraBox2D = camera.combined.cpy();
Render method
Gdx.gl.glClearColor(0, 0, 2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
sb.setProjectionMatrix(camera.combined);
player.position.y += 500 * Gdx.graphics.getDeltaTime();
sb.begin();
sb.draw(bg, 0, camera.position.y - (camera.viewportHeight/2));
sb.draw(player.sprite, player.getPosition().x , player.getPosition().y);
for (Tube tube : tubes) {
sb.draw(tube.getlefttube(), tube.getposlefttube().x, tube.getposlefttube().y);
sb.draw(tube.getrighttube(), tube.getposrighttube().x, tube.getposrighttube().y);
sb.draw(tube.getLight() , tube.getPoslight().x , tube.getPoslight().y);
}
delta*=speed;
sb.end();
update(delta);
b2dr.render(world , cameraBox2D);
stage.draw();
app.batch.begin();
app.font23.draw(app.batch,"Lights collected :" + dropsGathered , 0, 720);
app.batch.end();
cameraUpdate method
Vector3 position = camera.position;
position.x = player.position.x;
position.y = player.position.y;
camera.position.set(position);
createPlayer method
Body pBody;
BodyDef def = new BodyDef();
def.type = BodyDef.BodyType.DynamicBody;
def.position.set(x * PPM, y * PPM );
def.fixedRotation = true;
pBody = world.createBody(def);
return pBody;
update method
world.step(1 / 60f , 6 , 2);
for(int i = 0; i < tubes.size; i++) {
Tube tube = tubes.get(i);
if (camera.position.y - (camera.viewportWidth/2) > tube.getposlefttube().y + tube.getlefttube().getWidth()) {
tube.reposition(tube.getposlefttube().y + ( TUBE_COUNT) );
}
if (tube.collides(player.getBounds())){
app.setScreen(new GameOver(app));
}
if (tube.gathered(player.getBounds())){
dropsGathered++;
}
if (dropsGathered >= 50){
//app.setScreen(new Stage2(app));
}
}
camera.update();
handleInput();
camera.position.y = player.getPosition().y + 300;
player.update(delta);
camera.update();
cameraUpdate(delta);
stage.act(delta);
In your createPlayer method you can do body.setUserData(sprite). Then in your render method, you can do this (similar to how you are rendering tubes):
for (Body body : bodies) {
Sprite playerSprite = (Sprite) body.getUserData();
playerSprite.setPosition(body.getPosition().x, body.getPosition().y);
playerSprite.draw(spriteBatch);
}
This will update the sprite's position with the body's position.

libGDX Box2D Stop Move When Touching Wall

This happen when my Body object touching with wall and I hold right key. So it is stop as long I hold right key.
When I release my right key it dropped. How to fix this problem?
Here my script:
World Definition:
this.world = new World(new Vector2(0, -9.8f), true);
Create ground body from tilemap:
//create body and fixture variables
BodyDef bdef = new BodyDef();
PolygonShape shape = new PolygonShape();
FixtureDef fdef = new FixtureDef();
Body body;
//create ground bodies/fixtures
for(MapObject object : tileMap.getLayers().get(2).getObjects().getByType(RectangleMapObject.class)){
rect = ((RectangleMapObject) object).getRectangle();
x = Static.toMeter(rect.getX() + rect.getWidth() / 2);
y = Static.toMeter(rect.getY() + rect.getHeight() / 2);
bdef.type = BodyDef.BodyType.StaticBody;
bdef.position.set(x, y);
body = world.createBody(bdef);
x = Static.toMeter(rect.getWidth() / 2);
y = Static.toMeter(rect.getHeight() / 2);
shape.setAsBox(x, y);
fdef.shape = shape;
fdef.filter.categoryBits = HookaHookaGame.GROUND_BIT;
body.createFixture(fdef);
}
Player body definition:
BodyDef bodyDef = new BodyDef();
bodyDef.position.set(Static.toMeter(128), Static.toMeter(HookaHookaGame.HEIGHT));
bodyDef.type = BodyDef.BodyType.DynamicBody;
body = world.createBody(bodyDef);
// Define mario shape
PolygonShape shape = new PolygonShape();
shape.setAsBox(Static.toMeter(32) / 2, Static.toMeter(32) / 2);
FixtureDef fixture = new FixtureDef();
fixture.shape = shape;
body.createFixture(fixture);
// Define foot shape
shape = new PolygonShape();
shape.setAsBox(Static.toMeter(32 / 4) / 2, Static.toMeter(32 / 4) / 2, new Vector2(0, Static.toMeter((-32 + 8) / 2)), 0);
fixture = new FixtureDef();
fixture.shape = shape;
// Create filter
fixture.filter.categoryBits = HookaHookaGame.MARIO_BIT;
fixture.filter.maskBits = HookaHookaGame.GROUND_BIT;
body.createFixture(fixture).setUserData(this);
My ContactListener here my beginContact() method:
int cDef;
Fixture a, b;
MySprite spriteA, spriteB;
a = contact.getFixtureA();
b = contact.getFixtureB();
cDef = a.getFilterData().categoryBits | b.getFilterData().categoryBits;
switch (cDef) {
case HookaHookaGame.GROUND_BIT | HookaHookaGame.MARIO_BIT:
System.out.println("Foot with ground");
if(a.getUserData() != null) {
spriteA = (MySprite) a.getUserData();
spriteA.onHit();
}
if(b.getUserData() != null) {
spriteB = (MySprite) b.getUserData();
spriteB.onHit();
}
break;
}
Handling user input:
private void handleInput() {
//control our player using immediate impulses
if (Gdx.input.isKeyPressed(Input.Keys.D))
player.moveRight();
else if (Gdx.input.isKeyPressed(Input.Keys.A))
player.moveLeft();
else
player.stopMove();
if (Gdx.input.isKeyPressed(Input.Keys.SPACE))
player.jump();
}
I read his tutorial and it seem he didn't do anything about it and it works fine. His source code GitHub
The problem is that your linear impulse is to strong.
You can test this with the Mario project, if you increase the impulse you will get stuck at walls, too.
To solve this either lower the impulse, lower the friction (but then you might need code that stops Mario) or instead of applying an linear impulse you could apply a torch and use a circle shape to let the player "roll".
None of these solutions are perfect, but you can try and see which one suits you most.

LibGdx Physics body editor

I am developing a game with LibGdx. I am using scene2d actors in my game.
I have 2 arrows with this body
private void creatBody() {
BodyDef bd = new BodyDef();
bd.position.set(getX(), getY());
bd.type = BodyType.DynamicBody;
FixtureDef fd = new FixtureDef();
fd.density = 15f;
fd.friction = 0.6f;
fd.restitution = 0.02f;
if (body != null)
removeBodySafely(body);
body = world.createBody(bd);
body.setTransform(body.getWorldCenter(), MathUtils.degreesToRadians
* getRotation());
GameScreen.shapeLoader.attachFixture(body, type, fd, 1);
}
public void draw(SpriteBatch batch, float parentAlpha) {
setRotation(MathUtils.radiansToDegrees * body.getAngle());
setPosition(body.getPosition().x, body.getPosition().y);
TextureRegion keyFrame = GameScreen.getAtlas("arrows").findRegion(type);
batch.draw(keyFrame, getX(), getY(), 0, 0, getWidth(), getHeight(),
1, 1, getRotation());
}
Picture of the body
but, when I drop one arrow above another they overlap instead of colliding.
From description of body editor I found that there is a red mark which is the reference point.
How do I make the arrows collide?
I found the answer
GameScreen.shapeLoader.attachFixture(body, type, fd, 90);
where 90 is the width of arrow.

Box2d Edgeshape doesn't rotate

I'm using Libgdx's port of box2d. I'm creating an edge shape, but it does not rotate upon collision with other polygons. Why is this?
Here's my code for setting up the edge shape.
float x = 3;
float y = 10;
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(x, y);
Body body = this.world.createBody(bodyDef);
MassData massdata = new MassData();
massdata.center.set(1,1);
massdata.mass = 10;
body.setMassData(massdata);
FixtureDef fixtureDef = new FixtureDef();
EdgeShape shape = new EdgeShape();
shape.set(0, 0, 2, 2);
fixtureDef.shape= shape;
fixtureDef.friction = 1;
fixtureDef.restitution = .5f;
fixtureDef.density = 10;
body.createFixture(fixtureDef);
That is because an Edge Shape in Box2D is meant to create static scenery. It simply cannot move due to dynamics. I guess kinematic would work. This is logic, because an EdgeShape has no mass, since it has no surface (or volume if you would consider the 2D world as 3D with a fixed depth).
Here is an excerpt taken from the manual, which confirms my initial thoughts:
Edge shapes are line segments. These are provided to assist in making
a free-form static environment for your game. A major limitation of
edge shapes is that they can collide with circles and polygons but not
with themselves. The collision algorithms used by Box2D require that
at least one of two colliding shapes have volume. Edge shapes have no
volume, so edge-edge collision is not possible.
As Martijn said, I calculate and set mass data of the body. To do this, I calculate the center of mass assuming uniform density. I am using LIBGDX and so I needed a way to do this in java. I wrote the routine using Box2D's source. Feel free to use it for whatever you like.
EdgeShapes do not have mass, and so do not behave physically. To cause this kind of behavior, manually calculation was necessary.
public static MassData calculateMassData(List<Vector2> vertices,
float density) {
float k_inv3 = 1.0f / 3.0f;
float area = 0.0f;
float I = 0.0f;
Vector2 center = new Vector2();
Vector2 s = new Vector2();
for (int i = 0, size = vertices.size(); i < size; i++) {
s.add(vertices.get(i));
}
s.div(vertices.size());
for (int i = 0, size = vertices.size(); i < size; ++i) {
// Triangle vertices.
Vector2 e1 = new Vector2(vertices.get(i));
e1.sub(s);
Vector2 e2 = new Vector2(i + 1 < size ? vertices.get(i + 1)
: vertices.get(0));
e2.sub(s);
float D = e1.crs(e2);
float triangleArea = 0.5f * D;
area += triangleArea;
// Area weighted centroid
center.add(e1.cpy().add(e2).mul(k_inv3).mul(triangleArea));
float ex1 = e1.x, ey1 = e1.y;
float ex2 = e2.x, ey2 = e2.y;
float intx2 = ex1 * ex1 + ex2 * ex1 + ex2 * ex2;
float inty2 = ey1 * ey1 + ey2 * ey1 + ey2 * ey2;
I += (0.25f * k_inv3 * D) * (intx2 + inty2);
}
MassData data = new MassData();
// Total mass
data.mass = density * area;
center.mul(1.0f / area);
data.center.set(center.cpy().add(s));
// Inertia tensor relative to the local origin (point s).
data.I = density * I;
// Shift to center of mass then to original body origin.
data.I += data.mass
* (data.center.dot(data.center) - center.dot(center));
data.I = (data.I);
return data;
}
2 limitations of edge shapes:
Edge shapes do not collide with other edge shapes
Edge shapes are not normal polygons. There's no real outside/inside definitions for any polygons built using only edge shapes.
Because of #2, other bodies can wind up inside of polygons built with edge shapes.
Because of #1, I took a different approach and constructed my polygon using a series of narrow rectangles. This is working well, but unfortunately does not solve #2.
I am not wanting to use PolygonShape for fixtures because the polygon I am attempting to model is complex. It can have hundreds of vertices.
I have tried triangulating my polygon and creating fixtures from each of these triangles. Unfortunately often the resulting triangle's area is too small for Box2D, and causes exceptions with box2d.
I am open to other solutions here.
Try: http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/physics/box2d/Body.html#setFixedRotation%28boolean%29
body.setFixedRotation(false)
Also your friction is too high. Try 0.6f

not proper collision in box2d

I am developing a game in which the user have to hit a high speed ball. To hit the ball I have joined a rectangular body with the actor using revolute joint and enabled its motor, to rotate it with a specified speed(motor speed). Now everything is perfect but sometime when ball`s velocity is high , it is bypassing the rectagular body. Using collision listner i found that collision is happening but ball is not getting reflected after collision.
As this is happening only when ball is on a high speed, is it bcoz of density of bodies that are colliding . Or its the motor of revolute joint that is responsible for it ?? Am i missing something here??
Here is the code for both bodies
// method for rectangular body
public Body createRectangleBodyPart(float x, float y, float width,
float height, short groupIndex) {
PolygonShape shape = new PolygonShape();
shape.setAsBox(width*WORLD_TO_BOX, height*WORLD_TO_BOX);
MassData massData = new MassData();
massData.mass = 15;
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.KinematicBody;
bodyDef.position.y = y*WORLD_TO_BOX;
bodyDef.position.x = x*WORLD_TO_BOX;
body = world.createBody(bodyDef);
body.setMassData(massData);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 1;
fixtureDef.friction = 100f;
fixtureDef.restitution = 0.5f;
fixtureDef.filter.groupIndex=groupIndex;
body.createFixture(fixtureDef);
shape.dispose();
return body;
}
// method for ball body
public Body createRoundBodyPart2(float x, float y, float radius,
short groupIndex, float density, int mass) {
CircleShape shape = new CircleShape();
shape.setPosition(new Vector2(0, 0));
shape.setRadius(radius*WORLD_TO_BOX ); // *18
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.y = y*WORLD_TO_BOX;
bodyDef.position.x = x*WORLD_TO_BOX;
MassData massData = new MassData();
massData.mass = 8;
Body body = world.createBody(bodyDef);
body.setMassData(massData);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 0.5f;
fixtureDef.restitution=0.007f;
fixtureDef.filter.groupIndex = groupIndex;
body.createFixture(fixtureDef);
shape.dispose();
return body;
}
Try to use isBullet=true property on your ball body
Have you tried playing around with these properties: density, friction and restitution.
The ball could be moving so fast that on impact with the rectangular body, the force of the ball is to high for the rec body. Which means that the ball cannot be stopped by the rec body, that why it is passing through it.
Just a guess.

Categories