Friday, June 26, 2015

How to implement rotating rectangle around circle in libGDX Box2D?


I want to implement rotating rectangle around cicrle in such way, that circle has no rotation, and rectangle has, and I could myself control rotation of this rectangle (I mean set its angular velocity). All object's are Box2D Body objects. Here is picture, what I want to have:


enter image description here



In my case rectangle touches circle, but I think it doesn't matter.


At first I tried to do it with two Fictures for same Body, but there was a problem with rotation: I couldn't have one ficture with rotation and another without.


I think, it should be somehow connected, but I don't know what exactly Joint I should use.


I tried to use DistanceJoint, but there was a problem, that I couldn't control Rectangle: when I even linear velocity of rectangle to 0 in render() method it continued to rotate.


Maybe are there another solutions?


P.S. It's important, that Cicrle should be DynamicBody, not StaticBody.



Answer



You can achieve this using a RevoluteJoint to anchor the "motor" to a point in the world, and a WeldJoint to anchor the rotating box to the "motor".


In my example I've used two static bodies, one for the circle that shouldn't move, and one for a small box inside the circle that will serve as the anchor point in the world.


The dynamic rotator Body is attached to the anchorBody using the RevoluteJoint and then the box (which is also dynamic) is welded to the rotator (which serves as the engine) using a `WeldJoint'.



The result looks like this; Rotating boxes! Sorry about the artifacts, the gif capture seems to be broken.


Full source for the above looks like this;


package com.bornander.androidstudiosandbox;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;

import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.Shape;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef;

import com.badlogic.gdx.physics.box2d.joints.WeldJointDef;

public class MyAndroidStudioSandboxGame extends ApplicationAdapter {
World world;
OrthographicCamera camera;
Box2DDebugRenderer renderer;

@Override
public void create () {
camera = new OrthographicCamera(100, 100);

camera.position.set(0,0,0);

world = new World(Vector2.Zero, true);

renderer = new Box2DDebugRenderer();

Body visibleCircle = createCircle(5, 0, 0);
visibleCircle.setType(BodyDef.BodyType.StaticBody);

Body anchorPoint = createBox(2, 2, 0, 0);

anchorPoint.setType(BodyDef.BodyType.StaticBody);

Body rotator = createBox(4,4,0,0);
rotator.setType(BodyDef.BodyType.DynamicBody);

Body box = createBox(4,4,8,0);
box.setType(BodyDef.BodyType.DynamicBody);


RevoluteJointDef revoluteJointDef = new RevoluteJointDef();

revoluteJointDef.initialize(anchorPoint, rotator, anchorPoint.getWorldCenter());
revoluteJointDef.enableMotor = true;
revoluteJointDef.motorSpeed = 20;
revoluteJointDef.maxMotorTorque = 50;

WeldJointDef weldJointDef = new WeldJointDef();
weldJointDef.initialize(rotator, box, rotator.getWorldCenter());

world.createJoint(revoluteJointDef);
world.createJoint(weldJointDef);


}

private Body createBox(float w, float h, float x, float y) {
BodyDef nodeBodyDefinition = new BodyDef();
nodeBodyDefinition.type = BodyDef.BodyType.DynamicBody;
nodeBodyDefinition.position.set(10, 10);

PolygonShape shape = new PolygonShape();
float density = 1.0f;

shape.setAsBox(w / 2.0f, h / 2.0f);

Body body = world.createBody(nodeBodyDefinition);
body.setUserData(this);
body.setTransform(x, y, 0);
final FixtureDef nodeFixtureDefinition = createFixtureDefinition(shape, density);

body.createFixture(nodeFixtureDefinition);
shape.dispose();


return body;
}

private Body createCircle(float r, float x, float y) {
BodyDef nodeBodyDefinition = new BodyDef();
nodeBodyDefinition.type = BodyDef.BodyType.DynamicBody;
nodeBodyDefinition.position.set(10, 10);

CircleShape shape = new CircleShape();
float density = 1.0f;

shape.setRadius(r);

Body body = world.createBody(nodeBodyDefinition);
body.setUserData(this);
body.setTransform(x, y, 0);
final FixtureDef nodeFixtureDefinition = createFixtureDefinition(shape, density);

body.createFixture(nodeFixtureDefinition);
shape.dispose();


return body;
}

private static FixtureDef createFixtureDefinition(final Shape shape, final float density) {
final FixtureDef nodeFixtureDefinition = new FixtureDef();
nodeFixtureDefinition.shape = shape;
nodeFixtureDefinition.friction = 1;
nodeFixtureDefinition.density = density;
nodeFixtureDefinition.restitution = 0.1f;
return nodeFixtureDefinition;

}



@Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

world.step(Gdx.graphics.getDeltaTime(), 4, 4);

camera.update();

renderer.render(world, camera.combined);
}
}

No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...