Box2d libgdx,对像素到米的东西有点困惑

2022-01-12 00:00:00 box2d java libgdx

所以我理解这个概念.这个想法是 box2d 或多或少以米为单位,所以你需要从像素到它的转换.说得通.我正在关注 box2d 这里的教程/介绍.它提到了进行转换,并为您提供了一些示例金额以供使用.现在,这一切都很好,但是我发现当我使用这些技术时,调试器框似乎没有呈现它们应该呈现的位置.然而,碰撞确实按预期工作.

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.

在我的 GameScreen 类中,我是这样初始化地面的:

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

这是播放器类的构造函数,因此您可以看到我是如何设置它的碰撞 box2d 对象的.我还粘贴了上面渲染循环中调用的更新方法来调整精灵的位置.

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

现在,当我在各种计算、大小等中删除这些静态浮点数的乘法时,碰撞仍然正确并且调试器框出现.然而,将原始像素传递给 box2d 感觉不对.关于为什么调试框没有按原样显示,我在这里有什么遗漏吗?

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?

推荐答案

我确实喜欢你正在做的事情,但可能会有所不同.

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

可能有点矫枉过正,但这是我的 jucl 端口

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

在我的初始化中:

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

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

然后在我的游戏类中(比如你的 Player 类).在我的例子中,这是一个弹球游戏,所以我有 Flipper、Ball、Bumper 等.我有一个 @Override render() 方法,用于将精灵与物理体同步.

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.

这是一个示例文件..sry 它很乱但可能会有所帮助.

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

弹球引擎类文件

相关文章