2
\$\begingroup\$

I have two box2d bodies like below, enter image description here

What I need is to create another body that kind of bridges this two bodies. I am not looking for a box2d joint, but a body that will be like a bridge touching the rightmost point of the first body and the leftmost point in the second body, like in this image (excuse my paint skills). enter image description here

Problem is, looks like I am not getting the co-ordinates and angles on how to create the third (bridge) body. Here's my code below,

  Body body1, body2, bridge;

BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.StaticBody;
bodyDef.position.set(350 / Constants.PIXELS_TO_METERS, 0 / Constants.PIXELS_TO_METERS);

body1 = world.createBody(bodyDef);

PolygonShape shape = new PolygonShape();
shape.setAsBox(300 / Constants.PIXELS_TO_METERS, 300 / Constants.PIXELS_TO_METERS);

FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 1f;
body1.createFixture(fixtureDef);

BodyDef bodyDef2 = new BodyDef();
bodyDef2.type = BodyDef.BodyType.StaticBody;
bodyDef2.position.set(1600 / Constants.PIXELS_TO_METERS, 0 / Constants.PIXELS_TO_METERS);

body2 = world.createBody(bodyDef2);

PolygonShape shape2 = new PolygonShape();
shape2.setAsBox(300 / Constants.PIXELS_TO_METERS, 500 / Constants.PIXELS_TO_METERS);

FixtureDef fixtureDef2 = new FixtureDef();
fixtureDef2.shape = shape2;
fixtureDef2.density = 1f;
body2.createFixture(fixtureDef2);

BodyDef bodyDef3 = new BodyDef();
bodyDef3.type = BodyDef.BodyType.StaticBody;

Vector2 a = new Vector2(body1.getPosition().x + 300 / Constants.PIXELS_TO_METERS, body1.getPosition().y + (300 + 50 / 2) / Constants.PIXELS_TO_METERS);
Vector2 b = new Vector2(body2.getPosition().x - 300 / Constants.PIXELS_TO_METERS, body2.getPosition().y + (300 + 50 / 2) / Constants.PIXELS_TO_METERS);


float distance = a.dst(b);
Vector2 bridgePos = new Vector2(a.x + distance / 2, a.y + 50 / 2 / Constants.PIXELS_TO_METERS);

bodyDef3.position.set(bridgePos);

float angle = (float) Math.atan2(a.y + 50 / Constants.PIXELS_TO_METERS, b.x);
bridge = world.createBody(bodyDef3);

PolygonShape shape3 = new PolygonShape();
shape3.setAsBox(distance / 2, 50 / Constants.PIXELS_TO_METERS);

FixtureDef fixtureDef3 = new FixtureDef();
fixtureDef3.shape = shape3;
fixtureDef3.density = 1f;
bridge.createFixture(fixtureDef3);
bridge.setTransform(bridgePos, angle);

This doesn't give the correct position or angle for the bridge, as it works for some body sizes and sometimes don't (yes, I have accounted for the hardcoded values for every change). I am not exactly sure what I am doing wrong. Any help?

\$\endgroup\$
1
\$\begingroup\$

One way to approach this would be to represent the definition of the first bodies as Rectangles, then the problem of figuring out the position and rotation of the bridges goes aways as the bridge is always made up as a polygon touching the top corners of the Rectangle.

enter image description here

The above image was generated using this approach, full source code below. It uses setAsBox for the boxes, but uses an array of Vector2s to describe the polygon that is the bridge between boxes.

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.math.Rectangle;
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.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.Shape;
import com.badlogic.gdx.physics.box2d.World;

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

    @Override
    public void create () {
        camera = new OrthographicCamera(24, 24);
        camera.position.set(0, 0, 0);

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

        renderer = new Box2DDebugRenderer();

        Body box1 = createBox(new Rectangle(-10, 0, 1, 4));
        Body box2 = createBox(new Rectangle(-8, 0, 1, 4));
        Body box3 = createBox(new Rectangle(-6, 1, 4, 2));
        Body box4 = createBox(new Rectangle(2, -1, 2, 2));
        Body box5 = createBox(new Rectangle(6, -3, 2, 2));

        buildBridge(box1, box2, 0.5f);
        buildBridge(box2, box3, 0.5f);
        buildBridge(box3, box4, 0.5f);
        buildBridge(box4, box5, 0.5f);
    }

    // This will only work for bodies where the userData has been set to a rectangle
    // describing the body
    private Body buildBridge(Body leftBox, Body rightBox, float thickness) {
        Rectangle lr = (Rectangle)leftBox.getUserData();
        Rectangle rr = (Rectangle)rightBox.getUserData();

        Vector2 v1 = new Vector2(lr.x + lr.width, lr.y + lr.height);
        Vector2 v2 = new Vector2(rr.x, rr.y + rr.height);
        Vector2 v3 = new Vector2(rr.x, rr.y + rr.height - thickness);
        Vector2 v4 = new Vector2(lr.x + lr.width, lr.y + lr.height - thickness);

        BodyDef nodeBodyDefinition = new BodyDef();
        nodeBodyDefinition.type = BodyDef.BodyType.DynamicBody;

        //nodeBodyDefinition.position.set(temp.x, temp.y);

        PolygonShape shape = new PolygonShape();
        float density = 1.0f;
        shape.set(new Vector2[]{v1, v2, v3, v4});

        Body body = world.createBody(nodeBodyDefinition);
        final FixtureDef nodeFixtureDefinition = createFixtureDefinition(shape, density);

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

        return body;
    }

    private Body createBox(Rectangle rect) {
        Vector2 temp = new Vector2();
        BodyDef nodeBodyDefinition = new BodyDef();
        nodeBodyDefinition.type = BodyDef.BodyType.DynamicBody;

        rect.getCenter(temp);
        nodeBodyDefinition.position.set(temp.x, temp.y);

        PolygonShape shape = new PolygonShape();
        float density = 1.0f;
        shape.setAsBox(rect.getWidth() / 2.0f, rect.getHeight() / 2.0f);

        Body body = world.createBody(nodeBodyDefinition);
        body.setUserData(rect);
        body.setTransform(temp.x, temp.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);
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.