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:
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; 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