How to construct and draw a nice rope with box2d - java

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.

Related

Different Box2D bodies act differently and unexpectedly with same mass

I have a box2d body which is simply a rectangle (the spaceship).
This ship flies around, affected by the gravity of planets (static circle bodies) just fine.
I have tried changing the ship fixture shape to both (1) a triangle fixture and also (2) two rectangular fixtures put together. Both of these body configurations are causing problems.
Given the change in volume, to make up for the difference in mass I calculated the necessary new densities so that these bodies have the same mass as the original rectangle body. However when launching the ship with the same linear impulse as before, the triangular body and multi-rectangular body both act differently than the original body and shoot forward much faster.
I have tried further tweaking the ship density as well as the linear impulse and also the planet gravity to return the ship to a normal pace of movement,
however when doing that the ship starts to act weird and will do things like suddenly switch direction in mid-air even though there's no collision. This collision-looking event does not happen when the density/gravity/linear impulse are all the same as before, however in that situation the ship is moving too fast for my needs.
Basically I don't know why these bodies are acting differently when there is no change in mass or anything besides shape and size. There's no linear damping or collisions happening. I don't know what else could possibly be affecting the ship.
Any help or ideas is greatly appreciated.
Here is the code that I believe is relevant:
public void createShipBody() {
density = 0.05f; //normal rectangle
//density = 0.06666667f; //density for the two rectangles together
restitution = 1.0f;
bodyDef.type = BodyDef.BodyType.DynamicBody;
setBodyDefPosition(bodyDef);
body = GameCore.world.createBody(bodyDef);
setShipShapeAndFixture();
}
// For with the original rectangle
private void setShipShapeAndFixture() {
PolygonShape shape = new PolygonShape();
shape.setAsBox(Utility.pixelsToMeters(bodyWidth / 2), Utility.pixelsToMeters(bodyHeight / 2));
createFixtureDef(shape);
shape.dispose();
}
// For with triangle fixture
private void setShipShapeAndFixture() {
Vector2[] vertices = new Vector2[3];
vertices[0] = new Vector2(0, 0);
vertices[1] = new Vector2(Utility.pixelsToMeters(bodyWidth), 0);
vertices[2] = new Vector2(Utility.pixelsToMeters(bodyWidth/2), Utility.pixelsToMeters(bodyHeight));
shape.set(vertices);
createFixtureDef(shape);
shape.dispose();
}
// For multi-rectangle body
private void setShipShapeAndFixture() {
PolygonShape shape = new PolygonShape();
shape.setAsBox(Utility.pixelsToMeters(bodyWidth / 2), Utility.pixelsToMeters(bodyHeight / 4));
PolygonShape shape2 = new PolygonShape();
shape2.setAsBox(Utility.pixelsToMeters(bodyWidth / 4), Utility.pixelsToMeters(bodyHeight / 4), new Vector2(0, Utility.pixelsToMeters(bodyHeight/2)), 0);
createShipMultiFixtureDef(shape, shape2);
shape.dispose();
shape2.dispose();
}
private void createFixtureDef(PolygonShape shape) {
FixtureDef polygonFixtureDef = new FixtureDef();
polygonFixtureDef.shape = shape;
polygonFixtureDef.density = density;
polygonFixtureDef.restitution = restitution;
body.createFixture(polygonFixtureDef);
}
private void createShipMultiFixtureDef(PolygonShape shape, PolygonShape shape2) {
FixtureDef polygonFixtureDef = new FixtureDef();
polygonFixtureDef.shape = shape;
polygonFixtureDef.density = density;
polygonFixtureDef.restitution = restitution;
FixtureDef polygonFixtureDef2 = new FixtureDef();
polygonFixtureDef2.shape = shape2;
polygonFixtureDef2.density = density;
polygonFixtureDef2.restitution = restitution;
body.createFixture(polygonFixtureDef);
body.createFixture(polygonFixtureDef2);
}
/**
* This is inside the Ship class
* #param x From world center of release
* #param y From world center of release
* #param distance The capped distance of release from shipCenter, to determine force of impulse
*/
protected void applyLinearImpulse(float x, float y, float distance, float maxDistance) {
float deltaX = x - getXinPixels();
float deltaY = y - getYinPixels();
float scale = 0.8f; // Have tried playing around with this with different bodies
float force = scale * (distance/maxDistance);
float angle = (float) Math.atan2(deltaY, deltaX);
bodyWrapper.body.applyLinearImpulse(new Vector2((float) Math.cos(angle) * force,
(float) Math.sin(angle) * force), getWorldCenter(), true);
}
// This is called on each planet every game update
protected void applyGravity() {
for (SpaceObject spaceObject:spaceObjects) {
float scalar = 2.334f;
if(spaceObject instanceof Ship) {
if (gameCore.shipInMotion) {
scalar = 2f; //Have tried playng with this for different bodies
}
else {
continue; //No gravity to ship until it's launched
}
}
Vector2 objectWorldCenter = spaceObject.getWorldCenter();
Vector2 planetWorldCenter = getWorldCenter();
float planetDiameter = Utility.pixelsToMeters(getWidth());
float distance = Utility.distance(planetWorldCenter.x, planetWorldCenter.y, objectWorldCenter.x, objectWorldCenter.y);
float xDistance = planetWorldCenter.x - objectWorldCenter.x;
float yDistance = planetWorldCenter.y - objectWorldCenter.y;
float x = (float) ((xDistance * planetDiameter * scalar) / (distance*distance));
float y = (float) ((yDistance * planetDiameter * scalar) / (distance*distance));
Vector2 gravity = new Vector2(x, y);
spaceObject.bodyWrapper.body.applyForceToCenter(gravity, true);
}
}

PulleyJoint odd behaviour Box2D

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.

How to make camera same speed as player

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");
}
}

Rotating multiple sprites as one ( around same origin )

I have array of sprites forming T shape, and I want to ratate them around the same origin, in my case box2D body origin, like this:
my shape is defined in matrix like this:
int array[][]= {{0,1,1,1,0},
{0,0,1,0,0},
{0,0,1,0,0},
{0,0,0,0,0},
{0,0,0,0,0}};
this is how I create the body:
public void setBody(int[][] blocks){
BodyDef def = new BodyDef();
def.type = BodyType.DynamicBody;
def.position.set(new Vector2(0 * WORLD_TO_BOX, 0 * WORLD_TO_BOX));
Body body = world.createBody(def);
body.setTransform(130*WORLD_TO_BOX, 200*WORLD_TO_BOX, -90*MathUtils.degreesToRadians);
for (int x = 0; x < 5; x++) { // HARDCODED 5
for (int y = 0; y < 5; y++) { // HARDCODED 5
if(blocks[x][y] == 1){
PolygonShape poly = new PolygonShape();
Vector2 v = new Vector2((x*size/BOX_TO_WORLD),(y*size/BOX_TO_WORLD));
poly.setAsBox(size/2 * WORLD_TO_BOX, size/2 * WORLD_TO_BOX, v, 0);
Sprite sprite = new Sprite(new Texture(Gdx.files.internal("data/block.png")));
sprite.setSize(size, size);
sprites.add(sprite);
orig.add(v);
body.createFixture(poly, 1);
poly.dispose();
}
}
}
this.body = body;
}
this is my render method:
public void draw(SpriteBatch batch){
for (int i = 0;i< this.body.getFixtureList().size;i++) {
Vector2 pos = this.body.getFixtureList().get(i).getBody().getPosition();
Sprite sprite = sprites.get(i);
sprite.setOrigin(this.body.getWorldCenter().x,this.body.getWorldCenter().y);
sprite.setPosition(pos.x*BOX_TO_WORLD+orig.get(i).x*32-16, pos.y*BOX_TO_WORLD+orig.get(i).y*32-16);
sprite.setRotation(this.body.getAngle()*MathUtils.radiansToDegrees);
sprite.draw(batch);
}
}
As you can see in your 'right' example in the diagram, the position of the sprites depends on the angle of the body, which you are not accounting for.
b2Vec2 pos = ...; // center of the sprite relative to body (local coords)
float ang = ...; // angle of the sprite relative to body (probably zero)
//need to rotate image local center by body angle
b2Rot rot( body->GetAngle() );
pos = b2Mul(rot, pos) + body->GetPosition();
ang += -body->GetAngle();
sprite.setRotation( ang * RADTODEG ); // RADTODEG = 57.295779513082320876f
sprite.setPosition( PTM * pos.x, PTM * -pos.y);
Prior to that, I have also done:
sf::FloatRect rect = sprite.getLocalBounds();
sprite.setOrigin( 0.5 * rect.width, 0.5 * rect.height );
The easiest way to do this is to create all the fixtures, remembering what their relative position is to the body. Create a sprite for each fixture and update them using the body->GetWorldPosition(fixture center) each time the physics updates. Finally, the rotation of the sprites is the same as the rotation of the body (excepting it is the negative of the angle).
For example, to create the body:
void MainScene::CreateBody()
{
Vec2 position(0,0);
// Create the body.
b2BodyDef bodyDef;
bodyDef.position = position;
bodyDef.type = b2_dynamicBody;
_body = _world->CreateBody(&bodyDef);
assert(_body != NULL);
// Now attach fixtures to the body.
FixtureDef fixtureDef;
PolygonShape polyShape;
vector<Vec2> vertices;
const float32 VERT_SCALE = .5;
fixtureDef.shape = &polyShape;
fixtureDef.density = 1.0;
fixtureDef.friction = 1.0;
fixtureDef.isSensor = false;
// Main Box
vertices.clear();
vertices.push_back(Vec2(1*VERT_SCALE,1*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,1*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,-1*VERT_SCALE));
vertices.push_back(Vec2(1*VERT_SCALE,-1*VERT_SCALE));
polyShape.Set(&vertices[0],vertices.size());
_body->CreateFixture(&fixtureDef);
_fixturePositions.push_back(CalculateAverage(vertices));
// Down one
vertices.clear();
vertices.push_back(Vec2(1*VERT_SCALE,-1*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,-1*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,-3*VERT_SCALE));
vertices.push_back(Vec2(1*VERT_SCALE,-3*VERT_SCALE));
polyShape.Set(&vertices[0],vertices.size());
_body->CreateFixture(&fixtureDef);
_fixturePositions.push_back(CalculateAverage(vertices));
// Up One
vertices.clear();
vertices.push_back(Vec2(1*VERT_SCALE,3*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,3*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,1*VERT_SCALE));
vertices.push_back(Vec2(1*VERT_SCALE,1*VERT_SCALE));
polyShape.Set(&vertices[0],vertices.size());
_body->CreateFixture(&fixtureDef);
_fixturePositions.push_back(CalculateAverage(vertices));
// T Left Top
vertices.clear();
vertices.push_back(Vec2(-1*VERT_SCALE,3*VERT_SCALE));
vertices.push_back(Vec2(-3*VERT_SCALE,3*VERT_SCALE));
vertices.push_back(Vec2(-3*VERT_SCALE,1*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,1*VERT_SCALE));
polyShape.Set(&vertices[0],vertices.size());
_body->CreateFixture(&fixtureDef);
_fixturePositions.push_back(CalculateAverage(vertices));
// T Right Top
vertices.clear();
vertices.push_back(Vec2(3*VERT_SCALE,3*VERT_SCALE));
vertices.push_back(Vec2(1*VERT_SCALE,3*VERT_SCALE));
vertices.push_back(Vec2(1*VERT_SCALE,1*VERT_SCALE));
vertices.push_back(Vec2(3*VERT_SCALE,1*VERT_SCALE));
polyShape.Set(&vertices[0],vertices.size());
_body->CreateFixture(&fixtureDef);
_fixturePositions.push_back(CalculateAverage(vertices));
_body->SetAngularVelocity(M_PI/8);
}
NOTE The CalculateAverage(...) function just finds the average of the vertices. For squares, it will be the center. I could manually set the centers, but I didn't want to make a simple math oopsie so I wrote a quick function to handle it.
Then create the sprites:
void MainScene::CreateSprites()
{
Viewport& vp = Viewport::Instance();
for(int idx = 0; idx < _fixturePositions.size(); idx++)
{
CCSprite* sprite = CCSprite::create("arrow.png");
sprite->setScale(1.0*vp.GetPTMRatio()/128);
_fixtureSprites.push_back(sprite);
addChild(sprite);
}
}
Then update the sprites after each physics update:
void MainScene::UpdateSprites()
{
for(int idx = 0; idx < _fixturePositions.size(); idx++)
{
CCPoint spritePosition = Viewport::Instance().Convert(_body->GetWorldPoint(_fixturePositions[idx]));
_fixtureSprites[idx]->setPosition(spritePosition);
float32 bodyAngle = _body->GetAngle();
bodyAngle = MathUtilities::AdjustAngle(bodyAngle);
_fixtureSprites[idx]->setRotation(-CC_RADIANS_TO_DEGREES(bodyAngle));
}
}
NOTE The viewport has a function Convert(..) that takes a Vec2 and converts it to a pixel position on the screen. AdjustAngle just puts the angle back in the range of [-pi,pi). All the rest should be fairly straightforward, but feel free to ask.
I have posted a solution on git hub here for Cocos2d-x (C++). Check out the code in MainScene.cpp.
And this is what it looks like on my simulator:
(Hopefully) Final Note: The implementation here uses a "Viewport" class to map between the Box2d world (meters) and the screen coordinates (pixels). One very useful consequence of this is that you can automatically adjust the sizes of sprites based on the size you want the bodies to be in meters and the size of the graphic in pixels. This is part of a larger set of components that I often use. You can find more information about them in this post.
Was this helpful?

Drawing using textureRegion

I'm trying to make a movable car in java, using libgdx and box2d;
I made a car, m_car, with position set in middle of the car.
In every step, i take take the current position of the m_car, decrese that values with the cars width/height, so i have the left bottom corner. When is on a straight ground, it shows well, the texture is where is should be, but when the ground have an angle, the texture position its under, or upper the car.
I don't understand how TextureRegion works, i think that when the angle is not 0, i dont take the point of drawing well, and i dont know how to solve it. help me pls :)
Ty.
Edit:
my code is a mess, its not an actual project, its an ideea, and i took pieces, and put them down to see how they work, so when il start the project, i would know what to do, this is my car declaration:
private void car2(){
m_hz = 5.0f;
m_zeta = 0.7f;
m_speed = 50.0f;
BodyDef bd = new BodyDef();
bd.type = BodyType.DynamicBody;
part1(bd);
part2(bd);
part3(bd);
wheels(bd);
m_car.setAwake(true);
}
private void part3(BodyDef bd) {
PolygonShape shape = new PolygonShape();
shape.setAsBox(0.01f, 0.35f,new Vector2(1.01f - 3, 4.85f - 4), 0);
m_car.createFixture(shape, 1.0f);
}
private void part1(BodyDef bd){
PolygonShape chassis = new PolygonShape();
Vector2 vertices[] = new Vector2[6];
vertices[0] = new Vector2(-2, -0.5f);
vertices[1] = new Vector2(-2, 0.5f);
vertices[2] = new Vector2(1.25f, 0.5f);
vertices[3] = new Vector2(2.5f, 0.15f);
vertices[4] = new Vector2(2.5f, -0.5f);
vertices[5] = new Vector2(-2, -0.5f);
chassis.set(vertices);
bd.position.set(new Vector2(3, 4));
m_car = m_world.createBody(bd);
m_car.createFixture(chassis, 1.0f);
}
private void part2(BodyDef bd){
PolygonShape chassis = new PolygonShape();
Vector2 vertices[] = new Vector2[5];
vertices[0] = new Vector2(3, 4.5f);
vertices[1] = new Vector2(3, 5.25f);
vertices[2] = new Vector2(3.80f, 5.25f);
vertices[3] = new Vector2(4.25f, 4.5f);
vertices[4] = new Vector2(3, 4.5f);
for (int i = 0; i < 5; ++ i){
vertices[i].x -= 3;
vertices[i].y -= 4;
}
chassis.set(vertices);
//m_car = m_world.createBody(bd);
m_car.createFixture(chassis, 1.0f);
}
private void wheels(BodyDef bd){
CircleShape circle = new CircleShape();
circle.setRadius(0.4f);
FixtureDef fd = new FixtureDef();
fd.shape = circle;
fd.density = 1.0f;
fd.friction = 0.9f;
bd.position.set(2f, 3.5f);
m_wheel1 = m_world.createBody(bd);
m_wheel1.createFixture(fd);
bd.position.set(4.5f, 3.5f);
m_wheel2 = m_world.createBody(bd);
m_wheel2.createFixture(fd);
WheelJointDef jd = new WheelJointDef();
Vector2 axis = new Vector2(1.0f, 0.5f);
jd.initialize(m_car, m_wheel1, m_wheel1.getPosition(), axis);
jd.motorSpeed = 0.0f;
jd.maxMotorTorque = 20.0f;
jd.enableMotor = true;
jd.frequencyHz = m_hz;
jd.dampingRatio = m_zeta;
m_spring1 = (WheelJoint) m_world.createJoint(jd);
jd.initialize(m_car, m_wheel2, m_wheel2.getPosition(), axis);
jd.motorSpeed = 0.0f;
jd.maxMotorTorque = 10.0f;
jd.enableMotor = false;
jd.frequencyHz = m_hz;
jd.dampingRatio = m_zeta;
m_spring2 = (WheelJoint) m_world.createJoint(jd);
}
some explenation: why i have for for vertices to decreese 3 and 4 ? i didnt know that if i set position to the bodydef, the vertices consider that point to be 0, 0, when i found out, was easyer to me to just decrese (cuz its just for test, to see how it works)
and this is how i draw:
float angle = (float) Math.toDegrees(m_car.getAngle());
batch.draw(textureRegion, x, y, 3f, 4f,
4.5f, 2.75f, 1f, 0.61f, angle);
For a realistic car in Box2D you might find this useful: http://www.iforce2d.net/b2dtut/top-down-car
About your problem with the angle: You need to supply the angle of the car to the spriteBatch. TextureRegion doesn't know ANYTHING about where or how it is supposed to be rendered. You need to tell the spriteBatch about those informations.
You can use a Sprite for that. A Sprite can be manipulated with setRotation(), setPosition() etc and then being draw with Sprite.draw(spriteBatch) instead of `spriteBatch.draw(sprite)
Furthermore, be careful with your PIXEL_TO_METER conversion and remember to update your Cameras properly.

Categories

Resources