In front of my question, my english is very adventurous...
In my libgdx application, I have implemented Box2D. So I created a World and add them 2 Bodys. The first Body is a PolygonShape set as box which is static and rotate in the middle of my world. The second body is just a circle, which is dynamic and falling on top of the first body. When the falling Circle is collide with the Box, I create a WeldJoint and expect, that the circle is now rotate with the box too...
But after approx 20 degrees, the circle is stop his rotation within the box and don't move any more...
Here is a picture:
another one:
My code:
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.StaticBody;
bodyDef.position.set(10, 8);
mainBox = world.createBody(bodyDef);
PolygonShape polygonShape = new PolygonShape();
polygonShape.setAsBox(1, .5F);
mainBox.createFixture(polygonShape, 1);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = polygonShape;
fixtureDef.density = .1F;
fixtureDef.friction = .5F;
fixtureDef.restitution = .2F;
Fixture f = mainBox.createFixture(fixtureDef);
f.setUserData("mainbox");
mainBox.setUserData("mainbox");
/* ------------------------------------------------------------------------------------------ */
bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(10, 20);
shootBall = world.createBody(bodyDef);
shootBall.setUserData("shootball");
CircleShape circleShape = new CircleShape();
circleShape.setRadius(.2F);
fixtureDef = new FixtureDef();
fixtureDef.shape = circleShape;
fixtureDef.density = .5F;
fixtureDef.friction = .5F;
fixtureDef.restitution = .3F;
f = shootBall.createFixture(fixtureDef);
f.setUserData("shootball");
circleShape.dispose();
world.setContactListener(new ContactListener(){
#Override
public void beginContact(Contact contact) {
if(contact.getFixtureA().getBody().getUserData().equals("mainbox") && contact.getFixtureB().getBody().getUserData().equals("shootball")){
contact.getFixtureA().getBody().setUserData("createjoint");
System.out.println("contact!");
}
}
And in my render-loop:
if(mainBox.getUserData().equals("createjoint")){
WeldJointDef jointDef = new WeldJointDef();
jointDef.bodyA = mainBox;
jointDef.bodyB = shootBall;
jointDef.initialize(mainBox, shootBall, mainBox.getPosition());
world.createJoint(jointDef);
mainBox.setUserData("mainbox");
}
Ignore bad code, its just for testing...
thanks :)
Related
I wanted to try out Box2d and wrote similar code to one that is in tutorial, everything renders properly, but nothing updates and there are no exceptions. Please help me i think i am going insane.
#Override
public void create () {
world = new World(new Vector2(0, -10f), true);
r = new Box2DDebugRenderer();
camera = new OrthographicCamera(100, 100);
camera.translate(50, 50, 0);
BodyDef bd = new BodyDef();
bd.type = BodyType.DynamicBody;
bd.position.set(50, 50);
Body body = world.createBody(bd);
CircleShape cs = new CircleShape();
cs.setRadius(1);
FixtureDef fd = new FixtureDef();
fd.shape = cs;
body.createFixture(fd);
cs.dispose();
BodyDef b = new BodyDef();
b.type = BodyType.StaticBody;
b.position.set(30, 30);
Body bo = world.createBody(b);
PolygonShape ps = new PolygonShape();
ps.setAsBox(10, 3);
FixtureDef f = new FixtureDef();
f.shape = ps;
bo.createFixture(f);
ps.dispose();
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
r.render(world, camera.combined);
camera.update();
world.step(1/60, 6, 2);
}
of course box2D still work with Libgdx
your problem is this line
world.step(1/60, 6, 2);
try do this
world.step(1/60f, 6, 2);
your time step was considerer 0 cause 1/60 interger is 0
I have testedd your code it will work !
Good luck
I'm currently creating an 2d infinite runner game. In my game, I have Two actors , the Hero and a Coins, both of their body's are set to dynamic, but everytime the Hero hits/collides the coins, the hero moved to left(the hero's get affected by the coins).
Here's my code, i dont know if whats wrong in my settings, Any help, will be appreciated.
public static Body createRunner(World world) {
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(new Vector2(Constants.RUNNER_X, Constants.RUNNER_Y));
PolygonShape shape = new PolygonShape();
shape.setAsBox(Constants.RUNNER_WIDTH / 2, Constants.RUNNER_HEIGHT / 2);
Body body = world.createBody(bodyDef);
body.setGravityScale(Constants.RUNNER_GRAVITY_SCALE);
body.setUserData(new RunnerUserData());
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 0.0f;
fixtureDef.friction = 0.0f;
fixtureDef.restitution = 0.0f;
body.createFixture(fixtureDef);
body.resetMassData();
body.setUserData(new RunnerUserData(Constants.RUNNER_WIDTH, Constants.RUNNER_HEIGHT));
shape.dispose();
return body;
}
public static Body createCoins(World world) {
EnemyType enemyType = RandomUtils.getRandomEnemyType();
BodyDef bodyDef = new BodyDef();
//bodyDef used to set the enemy to make it not be affected when the runner hit
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(new Vector2(enemyType.getX(), enemyType.getY()));
PolygonShape shape = new PolygonShape();
shape.setAsBox(enemyType.getWidth() / 2, enemyType.getHeight() / 2);
Body body = world.createBody(bodyDef);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = -100.0f;
fixtureDef.friction = 0.0f;
fixtureDef.restitution = -50.0f;
body.createFixture(fixtureDef);
body.resetMassData();
EnemyUserData userData = new EnemyUserData(enemyType.getWidth(), enemyType.getHeight(), enemyType.getRegions());
body.setUserData(userData);
shape.dispose();
return body;
}
Thanks
I'd set the ContactFilter to your world instance via world.setContactFilter
This will give you a callback whenever you fixtures collide. Should you return false from this callback it should prevent Box2D from resolving your collision, which is likely what's pushing your hero left.
ContactListener listener = new ContactListneer(){
public boolean shouldCollide(Fixture fixtureA,
Fixture fixtureB){
Body bodyA = fixtureA.getBody();
Body bodyB = fixtureB.getBody();
/* !!! You'll need to implement this next part !!!*/
//figure out which body is hero, which body is coin
//if this is a collision between a hero and coin....
{
world.destroyBody(coinBody);
return false;
}
//else
return true;
}
};
world.setContactFilter(contactFilter);
I am trying to build a lever in an android game using box2d and libgdx. When the game starts, the 2 platforms of the lever are balancing perfectly and when I move a box on one platform of the lever, it goes down as expected but when I move the body out, the 2 platforms doesn't balance again as before.
I am using this code to create the 2 platforms:
private Body setupShape(World world, float cx, float cy, float cw, float ch){
Body ptf;
PolygonShape shape = new PolygonShape();
shape.setAsBox(cw / 2, ch / 2);
FixtureDef fdef = new FixtureDef();
fdef.shape = shape;
fdef.density = 1.0f;
fdef.friction = 1.0f;
fdef.restitution = 0.0f;
BodyDef bd = new BodyDef();
//bd.allowSleep = false;
bd.position.set(cx, cy);
bd.fixedRotation = true;
ptf = world.createBody(bd);
//lever.setGravityScale(10);
ptf.createFixture(fdef);
ptf.setType(BodyDef.BodyType.DynamicBody);
ptf.setUserData("Lever");
shape.dispose();
return ptf;
}
And this code for creating the lever using "PulleyJoint":
PulleyJointDef pulleyDef = new PulleyJointDef();
Vector2 bodyoneanchor = new Vector2(Constants.Pixel2SIf(360), Constants.Pixel2SIf(400));
Vector2 bodytwoanchor = new Vector2(Constants.Pixel2SIf(660), Constants.Pixel2SIf(400));
pulleyDef.initialize(bodyA, bodyB, bodyoneanchor, bodytwoanchor, bodyA.getWorldCenter(), bodyB.getWorldCenter(), 1);
world.createJoint(pulleyDef);
I would like to know what's wrong with my code and how to make the lever re-balance again after moving out objects from it.
Here's a drawing to demonstrate my problem more clearly:
http://costheta.net/quest.png
It will be very much appreciated if you could help me fixing that problem.
Best regards!
UPDATE:
Here's my new code after adding Prismatic joints:
PulleyJointDef pulleyDef = new PulleyJointDef();
Vector2 bodyoneanchor = new Vector2(Constants.Pixel2SIf(360), Constants.Pixel2SIf(400));
Vector2 bodytwoanchor = new Vector2(Constants.Pixel2SIf(660), Constants.Pixel2SIf(400));
pulleyDef.initialize(bodyA, bodyB, bodyoneanchor, bodytwoanchor, bodyA.getWorldCenter(), bodyB.getWorldCenter(), 1);
world.createJoint(pulleyDef);
BodyDef bd0 = new BodyDef();
bd0.position.set(bodyoneanchor.x, bodyoneanchor.y);
Body ptf0 = world.createBody(bd0);
PrismaticJointDef pjd0 = new PrismaticJointDef();
pjd0.initialize(ptf0, bodyA, ptf0.getWorldCenter(), new Vector2(0, 1));
pjd0.motorSpeed = 200f;
pjd0.maxMotorForce = 30.0f;
pjd0.enableMotor = true;
pjd0.lowerTranslation = -Math.abs(bodyA.getWorldCenter().y - bodyoneanchor.y);
pjd0.upperTranslation = 0;//Math.abs(bodyA.getWorldCenter().y - bodyoneanchor.y);
pjd0.enableLimit = true;
world.createJoint(pjd0);
BodyDef bd1 = new BodyDef();
bd1.position.set(bodytwoanchor.x, bodytwoanchor.y);
Body ptf1 = world.createBody(bd1);
PrismaticJointDef pjd1 = new PrismaticJointDef();
pjd1.initialize(ptf1, bodyB, ptf1.getWorldCenter(), new Vector2(0, 1));
pjd1.motorSpeed = 200f;
pjd1.maxMotorForce = 30.0f;
pjd1.enableMotor = true;
pjd1.lowerTranslation = -Math.abs(bodyB.getWorldCenter().y - bodytwoanchor.y);
pjd1.upperTranslation = 0;//Math.abs(bodyB.getWorldCenter().y - bodytwoanchor.y);
pjd1.enableLimit = true;
world.createJoint(pjd1);
They shouldn't re-balance because the weight of each side is the same and the tensions cancel each other out, resulting in no movement (get some string and build the setup in real life).
If you want it to re-balance, add a spring on each platform with a length of zero placed on the initial position and center of the box.
I'm making an endless runner on LibGDX with Box2d. I want to make the camera and player move at the same speed so while everything's fine, the player is in the center of the screen. I don't want it to just always make the player the center though, since I want the player to be left behind by the camera if the player gets stuck (ex. behind a crate). With that, I was thinking that I could translate the camera with the same default velocity that the player has. Doesn't work though. Help?
render() (with the camera update):
dx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//stage.getCamera().translate(Constants.DEFAULT_VELOCITY / Constants.PIXELS_TO_BOX, 0, 0);
//the commented function call above was what I was thinking; doesnt work
stage.getCamera().position.x = player.getX();
batcher.begin();
batcher.draw(AssetLoader.background, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batcher.end();
stage.draw();
batcher.begin();
debugRenderer.render(gameWorld.getWorld(), debugMatrix);
batcher.end();
part of Player:
public Player(Texture texture, float x, float y, World world) {
this.texture = texture;
setWidth(texture.getWidth()); //pixels
setHeight(texture.getHeight()); //pixels
setPosition((x + getWidth()/2), y + (getHeight()/2)); //pixels
setName("player");
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(x / Constants.PIXELS_TO_BOX, y / Constants.PIXELS_TO_BOX); //meters
body = world.createBody(bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox(texture.getWidth()/2 / Constants.PIXELS_TO_BOX , texture.getHeight()/2 / Constants.PIXELS_TO_BOX); //meters
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.0f;
fixtureDef.restitution = 0.0f;
body.createFixture(fixtureDef);
body.setFixedRotation(true);
shape.dispose();
body.setUserData(this);
}
#Override
public void act(float delta) {
body.setLinearVelocity(new Vector2(Constants.DEFAULT_VELOCITY, body.getLinearVelocity().y));
//what I use to set velocity
if (hasJumped) {
jump();
hasJumped = false;
Gdx.app.log("player", "jumped");
}
}
I created a rope in box2d with RevoluteJoint and a RopeJoint but I have several problems with it:
From time to time, the last segment rotates and it looks like it was disconnected from the rope.
How to draw this thing? I create a texture with the size of each link. If the rope isn't moving it looks good, but as soon as the rope moves and the different links start to rotate slightly, you see gaps between the links.
Code:
private void createChain(World world, Body anchorBody) {
Body previousBody = anchorBody;
FixtureDef fixtureDef = new FixtureDef();
PolygonShape robeLinkShape = new PolygonShape();
robeLinkShape.setAsBox(4 / PPM, 8 / PPM);
fixtureDef.shape = robeLinkShape;
fixtureDef.density = 0.1f;
// fixtureDef.friction = 1.0f;
fixtureDef.restitution = 0.1f;
fixtureDef.filter.maskBits = Box2DConst.BIT_PLAYER;
fixtureDef.filter.categoryBits = Box2DConst.BIT_GROUND;
float mapX = anchorBody.getPosition().x * PPM;
float mapY = anchorBody.getPosition().y * PPM;
BodyDef bodyDef = new BodyDef();
bodyDef.angularDamping = 1.0f;
bodyDef.linearDamping = 1.0f;
//create rope
for (int i = 0; i < 10; i++) {
Float robeX = mapX / PPM;
Float robeY = (mapY - (i * 16)) / PPM;
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(robeX, robeY);
final Body link = world.createBody(bodyDef);
link.createFixture(fixtureDef);
RevoluteJointDef jointDef = new RevoluteJointDef();
jointDef.initialize(previousBody, link, new Vector2(robeX, robeY));
//don't need the rope to collide itself
jointDef.collideConnected = false;
jointDef.enableLimit = false;
// because we don't collide with other bodies in the rope, limit rotation to keep the rope bodies from rotating too much.
jointDef.lowerAngle = -5.0f * MathUtils.degreesToRadians;
jointDef.upperAngle = 5.0f * MathUtils.degreesToRadians;
world.createJoint(jointDef);
links.add(link);
previousBody = link;
}
RopeJointDef ropeJointDef = new RopeJointDef();
ropeJointDef.localAnchorB.set(0, 0);
ropeJointDef.maxLength = 90.0f;
ropeJointDef.bodyB = previousBody;
ropeJointDef.bodyA = links.get(0);
ropeJointDef.collideConnected = false;
world.createJoint(ropeJointDef);
}
public void draw(final SpriteBatch batch) {
Texture texture = FipiGame.res.get("rope");
batch.begin();
for (Body link : links) {
float x = (link.getPosition().x * PPM) - 4;
float y = (link.getPosition().y * PPM) - 8;
float angleDeg = MathUtils.radiansToDegrees * link.getAngle();
batch.draw(texture, x, y, 0, 0, texture.getWidth(), texture.getHeight(), 1f, 1f, angleDeg, 0, 0,
texture.getWidth(), texture.getHeight(), false, false);
}
batch.end();
}
Instead of drawing based on body positions and rotations: Create a set of points by looping through the revolute joint positions (midpoint of anchorA and anchorB in world space). Then draw your sprites so they connect those positions. This will be somewhat inaccurate in that it won't perfectly line up with the positions of the rigid bodies, but it should look all right.