0
\$\begingroup\$

I think I'm doing something completely wrong but I just can't seem to wrap my head around the box2d pixels per meter conversion. Currently I have a Tiled map with an object layer I want to use as my collision boxes. I have one class to take the object layer and turn them into shapes and another to convert the units to meters. The problem I'm having is I can only get the boxes to be the correct size on my map if the pixels per meter is set to 1:1.

In the constructor for my level class I have this to create all the box2d objects:

world = new World(new Vector2(0f,-9.8f), true);
        MapObjects objects = map.getLayers().get("Collisions").getObjects();
        for (MapObject object : objects) {
            if (object instanceof TextureMapObject) {
                continue;
            }

            Shape shape;

            if (object instanceof RectangleMapObject) {
                shape = ShapeFactory.getRectangle((RectangleMapObject) object);
            } else if (object instanceof PolygonMapObject) {
                shape = ShapeFactory.getPolygon((PolygonMapObject) object);
            } else if (object instanceof PolylineMapObject) {
                shape = ShapeFactory.getPolyline((PolylineMapObject) object);
            } else if (object instanceof CircleMapObject) {
                shape = ShapeFactory.getCircle((CircleMapObject) object);
            } else {
                continue;
            }

            BodyDef bodyDef = new BodyDef();
            bodyDef.type = BodyDef.BodyType.StaticBody;
            Body body = world.createBody(bodyDef);
            body.createFixture(shape, 1);

            shape.dispose();
        }
        BodyDef bodyDef = new BodyDef();
        bodyDef.type = BodyDef.BodyType.DynamicBody;
        bodyDef.position.set(x,y);
        Body body = world.createBody(bodyDef);

        FixtureDef fdef = new FixtureDef();
        PolygonShape shape = new PolygonShape();
        shape.setAsBox(16,16);
        fdef.shape = shape;
        fdef.density = 1.0f;
        fdef.friction = 0.3f;
        fdef.restitution = 0.6f;
        body.createFixture(fdef);


        debugRenderer = new Box2DDebugRenderer();

This calls methods in my shapeFactory class that converts the mapobjects to shapes.

package Utils;

import com.badlogic.gdx.maps.objects.CircleMapObject;
import com.badlogic.gdx.maps.objects.PolygonMapObject;
import com.badlogic.gdx.maps.objects.PolylineMapObject;
import com.badlogic.gdx.maps.objects.RectangleMapObject;
import com.badlogic.gdx.math.Circle;
import com.badlogic.gdx.math.Polygon;
import com.badlogic.gdx.math.Polyline;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.ChainShape;
import com.badlogic.gdx.physics.box2d.CircleShape;
import com.badlogic.gdx.physics.box2d.PolygonShape;

public final class ShapeFactory {

    private ShapeFactory() {}

    public static PolygonShape getRectangle(RectangleMapObject rectangleObject) {
        return getRectangle(rectangleObject.getRectangle());
    }

    public static PolygonShape getRectangle(Rectangle rectangle) {
        PolygonShape polygon = new PolygonShape();

        Vector2 size = new Vector2(
                Physics.toUnits(rectangle.x + rectangle.width * 0.5f),
                Physics.toUnits(rectangle.y + rectangle.height * 0.5f)
        );

        polygon.setAsBox(
                Physics.toUnits(rectangle.width * 0.5f),
                Physics.toUnits(rectangle.height * 0.5f),
                size,
                0.0f
        );

        return polygon;
    }

    public static CircleShape getCircle(CircleMapObject circleObject) {
        return getCircle(circleObject.getCircle());
    }

    public static CircleShape getCircle(Circle circle) {
        CircleShape circleShape = new CircleShape();
        circleShape.setRadius(Physics.toUnits(circle.radius));
        circleShape.setPosition(new Vector2(Physics.toUnits(circle.x), Physics.toUnits(circle.y)));

        return circleShape;
    }

    public static PolygonShape getPolygon(PolygonMapObject polygonObject) {
        return getPolygon(polygonObject.getPolygon());
    }

    public static PolygonShape getPolygon(Polygon polygon) {
        PolygonShape polygonShape = new PolygonShape();

        float[] vertices = polygon.getTransformedVertices();
        float[] worldVertices = new float[vertices.length];

        for (int i = 0; i < vertices.length; ++i) {
            worldVertices[i] = Physics.toUnits(vertices[i]);
        }

        polygonShape.set(worldVertices);

        return polygonShape;
    }

    public static ChainShape getPolyline(PolylineMapObject polylineObject) {
        return getPolyline(polylineObject.getPolyline());
    }

    public static ChainShape getPolyline(Polyline polyline) {
        ChainShape chain = new ChainShape();

        float[] vertices = polyline.getTransformedVertices();
        Vector2[] worldVertices = new Vector2[vertices.length / 2];

        for (int i = 0; i < vertices.length / 2; ++i) {
            worldVertices[i] = new Vector2();
            worldVertices[i].x = Physics.toUnits(vertices[i * 2]);
            worldVertices[i].y = Physics.toUnits(vertices[i * 2 + 1]);
        }

        chain.createChain(worldVertices);

        return chain;
    }
}

Which also calls methods in my physics class that converts from units to pixels:

package Utils;


import com.badlogic.gdx.math.Vector;
import com.badlogic.gdx.math.Vector2;

public final class Physics {

    public static final float PIXELS_PER_UNIT = 32f;

    private Physics() {}

    public static float toUnits(float pixels) {
        return pixels / PIXELS_PER_UNIT;
    }

    public static Vector toUnits(Vector2 pixels) {
        return new Vector2(toUnits(pixels.x), toUnits(pixels.y));
    }

    public static float toPixels(float units) {
        return units * PIXELS_PER_UNIT;
    }

    public static Vector2 toPixels(Vector2 units) {
        return new Vector2(toPixels(units.x), toPixels(units.y));
    }
}

When My Pixels Per Unit is 1 it lines up perfectly but the physics acts as if everything is huge.

enter image description here

But when My Pixels Per Unit is 32 how I want it, it is way too small. enter image description here

\$\endgroup\$
  • \$\begingroup\$ It looks like you are using the box2d debug renderer which may be using the default projection matrix. Try setting the projection matrix to the same as the graphics rendering camera. \$\endgroup\$ – dfour Apr 17 '19 at 10:34

Your Answer

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

Browse other questions tagged or ask your own question.