Box2d libgdx, a bit confused about the pixels to meters stuff

浪子不回头ぞ 提交于 2019-12-31 05:33:08

问题


So I understand the concept. The idea is that box2d more or less works in meters, so you need to do a conversion from pixels to it. Makes sense. I was following the tutorial/intro to box2d here. It mentions to do the conversion and gives you some example amounts to use. Now, that's all well and good, but I find when I'm using such techniques, the debugger box doesn't seem to render where they should. The collision does work as expected however.

In my GameScreen class, here's how I initialize the ground:

ground = new BodyDef();
// set the position half way up the ground
ground.position.set(0,16 * GameScreen.WORLD_TO_BOX);
groundBody = world.createBody(ground);
groundShape = new PolygonShape();
// make the height 16px so it doubles to 32
groundShape.setAsBox(Gdx.graphics.getWidth() * GameScreen.WORLD_TO_BOX, 16.0f * GameScreen.WORLD_TO_BOX);
groundBody.createFixture(groundShape, 0.0f);

My render method in that screen is like so:

public void render(float delta) {
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    camera.update();
    stateTime += Gdx.graphics.getDeltaTime();

    batch.begin();
    batch.draw(background, 0, Gdx.graphics.getHeight() - 512, 512, 512);
    batch.draw(trailingBackground, 512, Gdx.graphics.getHeight() - 512);
    int heightToCover = Gdx.graphics.getHeight() - 512;
    int widthToCover = Gdx.graphics.getWidth();
    for(int w = 0; w < widthToCover; w += 32) {
        for(int h = 0; h < heightToCover; h += 32) {
            batch.draw(lightBackgroundTile, w, h, 32, 32);
        }
    }
    player.update();
    player.render(stateTime, batch);
    batch.end();
    levels.get(currentLevel).render(camera);

    // physics updates
    world.step(1/60f, 6, 2);
    debugRenderer.render(world, camera.combined);
}

Here's the constructor of the player class, so you can see how im setting up its collision box2d objects. I also pasted the update method which is called in the above render loop to adjust the sprites position.

public Player(int x, int y, World world) {
    super();
    playerTexture = new Texture(Gdx.files.internal("assets/hero.png"));
    init(x, y, 128, 128, playerTexture, false, world);

    bodyDef = new BodyDef();
    bodyDef.type = BodyType.DynamicBody;
    bodyDef.position.set(x * GameScreen.WORLD_TO_BOX, y * GameScreen.WORLD_TO_BOX);
    body = getWorld().createBody(bodyDef);
    collisionBox = new PolygonShape();
    collisionBox.setAsBox(32 * GameScreen.WORLD_TO_BOX, 64 * GameScreen.WORLD_TO_BOX, new Vector2(64 * GameScreen.WORLD_TO_BOX, 64 * GameScreen.WORLD_TO_BOX), 0.0f);

    FixtureDef fixtureDef = new FixtureDef();
    fixtureDef.shape = collisionBox;
    fixtureDef.density = 10f; 
    fixtureDef.friction = 0.4f;
    fixtureDef.restitution = 0f;

    body.createFixture(fixtureDef);
    collisionBox.dispose();

    addFrame(0, 0, 128, 128);
}

public void update() {
    this.setX((int) ((body.getPosition().x) * GameScreen.BOX_TO_WORLD));
    this.setY((int) ((body.getPosition().y) * GameScreen.BOX_TO_WORLD));
}

Now, when I remove the multiplication of those static floats in the various calculations, sizes, etc, the collision remains correct and the debugger box shows up. However passing the raw pixels to box2d feels wrong. Is there something I'm missing here as to why the debugging boxes don't show up as is?


回答1:


I do like you are doing but might be a little different.

Might be a little overkill but here's my jucl port

jucl/Android - pastebin

Then I just have utility classes ie:

public class Pixel {

    public static float toMeter(float pixels) {
        return (float)LengthConversions.Pixel2SIf(pixels);
    }

    public static Vector2 toMeter(Vector2 vecPixel) {
        return new Vector2(Pixel.toMeter(vecPixel.x), Pixel.toMeter(vecPixel.y));
    }
}

public class Meter {

    public static final float METERS_PER_PIXEL = (float) LengthConversions.SI_PIXEL;

    public static float toPixel(float meter) {
        return (float)LengthConversions.SI2Pixelf(meter);
    }
}

In my initialize:

int graphicsWidth = Gdx.graphics.getWidth();
int graphicsHeight = Gdx.graphics.getHeight();

CAMERA_WIDTH_METERS = Pixel.toMeter(graphicsWidth);
CAMERA_HEIGHT_METERS = Pixel.toMeter(graphicsHeight);

Then in my game classes (like your Player class). In my case it was a pinball game so i have Flipper, Ball, Bumper, etc. I have a @Override render() method where I sync up the sprite with the physics body.

Here's an example file..sry it's messy but might be helpful.

Pinball Engine Class file



来源:https://stackoverflow.com/questions/14208797/box2d-libgdx-a-bit-confused-about-the-pixels-to-meters-stuff

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!