Libgdx Box2D to meter converter?

While trying to program a game with Box2D, I got a problem with Box2D. I filled in the pixel numbers for the texture and sprite lengths to create a rectangle around it. Everything was in the right place, but somehow everything went very slowly. After looking online, I found that if you didn't convert pixels to meters, box2d could handle the shapes as very large objects. it seemed the logical reason for everything that moved slowly.

I found similar questions on this site, but the answers didn't really help. in most cases the solution was to make methods to convert pixel numbers to counters using a scaling factor. I tried this but everything became out of place and was not sized correctly. it seemed logical to me, as numbers that changed but had the same meaning.

I was wondering if there is a way to make the pixels smaller than meters, so everything that should be in one place with the same (pixel) size, but means less than meters. If you have another way that you think might help, I'd love to hear it as well.

Here is the code I am using to create the camera

        width = Gdx.graphics.getWidth() / 5;
        height = Gdx.graphics.getHeight() / 5;

        camera = new OrthographicCamera(width, height);
        camera.setToOrtho(false, 1628, 440);
        camera.update();

      

This is the method I am using to create the object:

public void Create(float X, float Y, float Width, float Height, float density, float  friction, float restitution, World world){ 
    //Method to create an item
    width = Width;
    height = Height;

    polygonDef = new BodyDef();
    polygonDef.type = BodyType.DynamicBody;
    polygonDef.position.set(X + (Width / 2f), Y + (Height / 2f));

    polygonBody = world.createBody(polygonDef);

    polygonShape = new PolygonShape();
    polygonShape.setAsBox(Width / 2f, Height / 2f);

    polygonFixture = new FixtureDef();
    polygonFixture.shape = polygonShape;
    polygonFixture.density = density;
    polygonFixture.friction = friction;
    polygonFixture.restitution = restitution;

    polygonBody.createFixture(polygonFixture);
}

      

To create an element, in this case a table, I use the following:

    Table = new Item();
    Table.Create(372f, 60f, 152f, 96f, 1.0f, 0.2f, 0.2f, world);

      

Sprites are drawn on an element using the following method:

public void drawSprite(Sprite sprite){
    polygonBody.setUserData(sprite);
    Utils.batch.begin();
    if(polygonBody.getUserData() instanceof Sprite){
        Sprite Sprite = (Sprite) polygonBody.getUserData();
        Sprite.setPosition(polygonBody.getPosition().x - Sprite.getWidth() / 2, polygonBody.getPosition().y - Sprite.getHeight() / 2);
        Sprite.setRotation(polygonBody.getAngle() * MathUtils.radiansToDegrees);
        Sprite.draw(Utils.batch);
    }
    Utils.batch.end();
}

      

Sprites also have pixel dimensions.

Using these techniques, it displays images in the right places, but everything moves slowly. I was wondering how or if I would have to change this so that the objects move correctly and / or less. Thanks in advance.

+3


source to share


1 answer


Box2D is completely independent of the graphics library used. It has no concept of sprites and textures. What you read online is correct, you will have to convert pixels to meters as Box2D works with meters (the building block for distance).

For example, if you drew a sprite that is 100x100 pixels, the size of the sprite you want to see on screen. In the real world, the size of the object should be in meters, not pixels, so if you say 1px = 1m, then this will map the sprite to a giant object of 100x100 meters. In Box2D, large objects in the world slow down computation. So, you need to map 100 pixels to fewer meters, say 1 meter, so a 100x100px sprite will be represented in the Box2D world by a 1x1 meter object.

Box2D does not work well with very small numbers and very large numbers. So keep it in between, say 0.5 to 100, to have good performance.

EDIT: OK. Now I am wondering. Don't code pixels. It is so simple. I know it will take a while to figure this out (it took for me). But once you get it, straight ahead. Use a device instead of pixels, let's say you call it a meter. Therefore we decide that our viewport should be specified as 6mx5m.

So initialization

Constants.VIEWPORT_WIDTH = 6;
Constants.VIEWPORT_HEIGHT = 5;
...

void init() {
    camera = new OrthographicCamera(Constants.VIEWPORT_WIDTH, Constants.VIEWPORT_HEIGHT);
    camera.position.set(Constants.VIEWPORT_WIDTH/2, Constants.VIEWPORT_HEIGHT/2, 0);
    camera.update();
}

      

Once you know the actual width and height, you call the following function to maintain the aspect ratio:



public void resize(int width, int height) {
        camera.viewportHeight = (Constants.VIEWPORT_WIDTH / width) * height;
        camera.update();
}

      

resize()

can be called at any time when the screen is resized (for example: when the screen orientation is changed). resize()

takes an actual width and height (320x480, etc.), which is the pixel value.

Now you specify the size of the sprites, their positions, etc. in this new 6x5 world. You can forget pixels. The minimum size for a sprite to fill the screen is 6x5.

Now you can use the same block with Box2D. Since the new sizes will be smaller, this will not be a problem for Box2D. If I remember correctly, Box2D doesn't have any unit. We just call it the meter for convenience.

Now you may ask where to specify the window dimensions. It depends on the platform. The following code shows a 320x480 board game:

public class Main {
    public static void main(String[] args) {
        LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
        cfg.title = "my-game";
        cfg.useGL20 = false;
        cfg.width = 480;
        cfg.height = 320;

        new LwjglApplication(new MyGame(), cfg);
    }
}

      

Our camera will intelligently display a 6x5 viewport to 480x320.

+7


source







All Articles