LibGDX. Box2d. Joint rotation or how to make a tank - libgdx

I trying to make a taknk with LibGDX and Box2D. There is a chassis and tower connected through the box2d revolute joint.
Chassis:
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.bullet = true;
PolygonShape shape = new PolygonShape();
shape.setAsBox(sizeM.x / 2, sizeM.y / 2);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = MASS / (sizeM.x * sizeM.y);
Body body = world.createBody(bodyDefComponent.bodyDef);
body.createFixture(fixtureDef).setUserData(this);
body.setLinearDamping(DAMPING);
body.setAngularDamping(DAMPING);
Tower:
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.bullet = true;
bodyDef.angularDamping = 3;
PolygonShape shape = new PolygonShape();
shape.setAsBox(sizeM.x / 2, sizeM.y / 2);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = MASS / (sizeM.x * sizeM.y);
Body body = world.createBody(bodyDefComponent.bodyDef);
body.createFixture(fixtureDef).setUserData(this);
Joint:
RevoluteJointDef jointDef = new RevoluteJointDef();
jointDef.enableMotor = true;
jointDef.maxMotorTorque = 10000;
jointDef.initialize(mChassis, mTower, new Vector2(position.x, position.y));
Joint joint = world.createJoint(jointDef);
Tower rotate method:
body.applyAngularImpulse(-ROTATION_POWER, true);
The chassis rotates in the same way as the tower. When chassis rotates, tower rotates too. It's ok. But if I rotating the tower, chassis rotates too. I also tryed to set infinity mass, bot that doesn't helps. I guess there is something wrong with the joints. Any idea?

Related

Box2d body sticks to side of platforms/walls while applying impulse

Working on a sidescrolling platform type game and running into a weird issue with my character. If he moves into the side of a platform and I continue to hold the movement button he just sticks to it and doesnt fall until I let up the movement key. Here is my movement code:
public void move(float percent){
float desiredVel = speed.x *percent;
float velChange = desiredVel - b2body.getLinearVelocity().x;
float impulse = b2body.getMass() * velChange;
b2body.applyLinearImpulse(new Vector2(impulse,0),b2body.getWorldCenter(),true);
}
This is called given a percent based on a touchpad controller, but basically percent is somewhere between -1 and 1. This is my body/fixture for the character:
BodyDef bdef = new BodyDef();
bdef.position.set(704/ Constants.PPM, 1000/Constants.PPM);
bdef.type = BodyDef.BodyType.DynamicBody;
b2body = world.createBody(bdef);
b2body.setFixedRotation(true);
//Hitbox
FixtureDef fixtureDef = new FixtureDef();
PolygonShape shape = new PolygonShape();
shape.setAsBox(20/Constants.PPM,45/Constants.PPM);
fixtureDef.shape = shape;
//Add in category and mask bits
hitbox = b2body.createFixture(fixtureDef);
hitbox.setUserData("hitbox");
And this is the body/fixture for the platforms:
bdef.type = BodyDef.BodyType.StaticBody;
bdef.position.set((rect.getX() + rect.getWidth() / 2) / Constants.PPM, (rect.getY() + rect.getHeight() / 2) / Constants.PPM);
body = world.createBody(bdef);
shape.set(new Vector2(-rect.getWidth()/2/Constants.PPM, rect.getHeight()/2/Constants.PPM),new Vector2(rect.getWidth()/2/Constants.PPM, rect.getHeight()/2/Constants.PPM));
fdef.shape = shape;
fdef.friction = 0.5f;
fdef.density = 1;
fdef.filter.categoryBits = Constants.GROUND_BIT;
body.createFixture(fdef).setUserData("platform");
This is caused by the friction generated by the player pushing into the platform which overcomes gravity.
A few things you could try:
Reduce the friction of the character or platforms to reduce friction.
Add a sensor to detect when these friction collisions are happening and disable the user input for that direction.
Add friction free bodies on sides of platforms or sides of player

How do I use filters correctly?

Why doesn't the Player collide with the Ground? Did I use the filter wrong?
I store all my constants in a Class called Constants. Here is the code I use :
for (MapObject object : map.getLayers().get(2).getObjects().getByType(RectangleMapObject.class)) {
Rectangle rect = ((RectangleMapObject) object).getRectangle();
bDef.type = BodyDef.BodyType.StaticBody;
bDef.position.set((rect.getX() + rect.getWidth() / 2)
/ Constants.PPM, (rect.getY() + rect.getHeight() / 2)
/ Constants.PPM);
body = world.createBody(bDef);
shape.setAsBox(rect.getWidth() / 2 / Constants.PPM,
rect.getHeight() / 2 / Constants.PPM);
fDef.shape = shape;
body.createFixture(fDef);
fDef.filter.categoryBits = Constants.BRICK_BIT;
fDef.filter.maskBits = Constants.PLAYER1_BIT;
}
Here is how I define my Player. I am if thats a dump question, but I am a complete newbie in LibGDX...
public void defineMainPlayer1() {
BodyDef bDef = new BodyDef();
bDef.position.set(128 / Constants.PPM, 256 / Constants.PPM);
bDef.type = BodyDef.BodyType.DynamicBody;
b2body = world.createBody(bDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox(42 / 2 / Constants.PPM, 94 / 2 / Constants.PPM);
FixtureDef fDef = new FixtureDef();
fDef.shape = shape;
fDef.filter.categoryBits = Constants.PLAYER1_BIT; // Setting the filter
// for my Player
fDef.filter.maskBits = Constants.BRICK_BIT;
b2body.createFixture(fDef).setUserData(this);
EdgeShape head = new EdgeShape();
head.set(new Vector2(-30 / Constants.PPM, 49 / Constants.PPM),
new Vector2(30 / Constants.PPM, 49 / Constants.PPM));
fDef.shape = head;
fDef.isSensor = true;
b2body.createFixture(fDef).setUserData("head");
}
You should change the order of
body.createFixture(fDef);
fDef.filter.categoryBits = Constants.BRICK_BIT;
fDef.filter.maskBits = Constants.PLAYER1_BIT;
to
fDef.filter.categoryBits = Constants.BRICK_BIT;
fDef.filter.maskBits = Constants.PLAYER1_BIT;
body.createFixture(fDef);
I have written an example below, these should give you a clear explanation and ideas.
short CAT_PLAYER = 0x001;
short CAT_ENEMY = 0x002;
short CAT_SENSOR = 0x004;
short CAT_WALL = 0x008;
short MASK_PLAYER = ~CAT_PLAYER; // cannot collide to a player
short MASK_ENEMY = ~CAT_ENEMY; // cannot collide to a enemy
short MASK_SENSOR = CAT_PLAYER; // can only collide to a player
short MASK_WALL = -1; // can collide to all
And a simple filter for the fixture of a player. This means the player can collide to all except itself.
filter.categoryBits = CAT_PLAYER;
filter.maskBits = MASK_PLAYER;

Box2d bodys won't center in screen when using Pixel per meter

I am trying to create a sample circle to test the pixel per meter.
My PPM is set to 100.
Height and width was set to 320 and 480
Do you why It won't center in y axis but it will center in x axis. also when I set the radius to 50 it doens't draw anything. Am I missing something here?
this.world = new World(new Vector2(0.0f, -9.8f), true);
BodyDef bodyDef = new BodyDef();
bodyDef.position.set( App.WIDTH / 2 / PPM, App.HEIGHT / 2 / PPM);
bodyDef.type = BodyDef.BodyType.StaticBody;
Body body = world.createBody(bodyDef);
FixtureDef fixtureDef = new FixtureDef();
CircleShape shape = new CircleShape();
shape.setRadius(100 / PPM);
fixtureDef.shape = shape;
body.createFixture(fixtureDef);
shape.dispose();
player = new Player(body);
box2DDebugRenderer = new Box2DDebugRenderer();
box2dCam = new OrthographicCamera();
box2dCam.setToOrtho(false, App.WIDTH / PPM , App.HEIGHT / PPM );
When Radius is 100, when radius is 50 the screen is just plain black
Nevermind guys.
shape.setRadius((float) 20 / PPM); I had to cast it to float to show all lower than 100
PPM was declared int should be float to avoid casting.
to center it on screen
box2dCam.position.set(App.WIDTH / 2 / PPM, App.HEIGHT / 2 / PPM, 0);

Box2d Body to follow mouse movement

I am trying a box2d body to rotate following the mouse. Here's an image to clarify what I mean.
The red and blue circles are current point of the mouse and the body (of corresponding color) moving/rotating to follow it. Basically the rectangle should rotate with its one end pointed towards where the mouse pointer is.
Here's my code so far,
World world;
Body body, bullet;
Box2DDebugRenderer debugRenderer;
OrthographicCamera camera;
#Override
public void create() {
world = new World(new Vector2(0, 0f), true);
debugRenderer = new Box2DDebugRenderer();
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(10, 10);
body = world.createBody(bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox(2, 5);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 1f;
Fixture fixture = body.createFixture(fixtureDef);
shape.dispose();
Gdx.input.setInputProcessor(this);
camera = new OrthographicCamera(200, 100 * (h / w));
camera.position.set(camera.viewportWidth / 2f, camera.viewportHeight / 2f, 0);
camera.update();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
world.step(Gdx.graphics.getDeltaTime(), 6, 2);
camera.update();
debugRenderer.render(world, camera.combined);
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
int mouseX = screenX;
int mouseY = Gdx.graphics.getHeight() - screenY;
float rotateAngle = MathUtils.radiansToDegrees * MathUtils.atan2((float) mouseY - (float) body.getPosition().y, (float) mouseX - (float) body.getPosition().x);
body.setTransform(body.getPosition(), rotateAngle / 57.2957795f);
return true;
}
And here's a gif of how it appears now.
as you can see the body gets skewed and also doesn't rotate properly. What am I missing?
The skew looks like a problem with aspect correction, try,
camera = OrthographicCamera(200, 100 * (w / h));
or even,
camera = OrthographicCamera(200, 100);
To get the end of the box to follow the mouse as in the picture just redefine the box,
shape.setAsBox(5, 2, Vector2(offset, 0), 0);

box2d vertical edge or wall collision detection

I am experimenting with collision detection using Box2d Between a ball and four walls of a rectangular block which I call the gameBed.
I am using the below code to setup the ball and the LeftEdge(left wall in this case) Bodies. For brevity I am giving the code only for the left wall.
b2World = new World(new Vector2(0, 0), false);
World.setVelocityThreshold(0);
GameBed gameBed = levelManager.retGameBed(); // rectangular block
Vector2 origin = new Vector2();
BodyDef leftWallDef = new BodyDef();
leftWallDef.type = BodyType.StaticBody;
leftWallDef.position.set(gameBed.position); // gameBed.position is the world co-ordinate of the bottom left corner of the rectangular block
Body body = b2World.createBody(leftWallDef);
PolygonShape leftWallShape = new PolygonShape();
origin.x = 0.005f;
origin.y = (float)(gameBed.bounds.getHeight()) / 2;
float widthOfLeftWall = BallsMania_Constants.VIEWPORT_WIDTH/(2 * Gdx.graphics.getWidth());
Gdx.app.log(TAG, "Width of Left Wall is " + widthOfLeftWall);
leftWallShape.setAsBox(.1f,
gameBed.bounds.height/2, origin, 0); // setting the half of width to .1f so that it represents an edge. The height of the edge should be as long as the rectangular edge.
FixtureDef leftWallFixtureDef = new FixtureDef();
leftWallFixtureDef.shape = leftWallShape;
leftWallFixtureDef.restitution = 0.9f;
body.createFixture(leftWallFixtureDef);
leftWallShape.dispose();
// Defining shape and fixture for ball
Ball ball = new Ball();
BodyDef ballBodyDef = new BodyDef();
ballBodyDef.type = BodyType.DynamicBody;
ballBodyDef.position.set(ball.position);
ballBodyDef.linearDamping = 0.4f;
ball.body = b2World.createBody(ballBodyDef);
CircleShape ballShape = new CircleShape();
ballShape.setPosition(new Vector2(0, -1 * (float)(BallsMania_Constants.VIEWPORT_HEIGHT/2.0
- BallsMania_Constants.bottomBaseDelta
+ ball.dimension.x/2)));
ballShape.setRadius(ball.dimension.x/2);
FixtureDef ballBodyFixture = new FixtureDef();
ballBodyFixture.shape = ballShape;
ballBodyFixture.friction = 0.5f;
ballBodyFixture.restitution = 0.5f;
ball.body.createFixture(ballBodyFixture);
ballShape.dispose();
Problem:
The ball doesn't collide with the leftedge; it just permiates through it and doesn't bounce.
Any guidance would be appreciated.