java - 在 Libgdx Box2d World 上使用每米像素时出现巨大图像

标签 java libgdx box2d

大家好,我正在尝试实现一个 box2d 世界。我读到 box2d 使用米。并且您需要将其从像素转换为米。

我尝试绘制图像,但我是否也必须缩小图像?我认为绘制图像的想法很糟糕,图像非常巨大,无法弄清楚如何使其与每米的 box2d 像素一起工作

public class TestScreen extends ScreenAdapter {

    private final Body body;
    private int V_WIDTH = 320;
    private int V_HEIGHT = 480;
    private int PPM = 100;

    private SpriteBatch batch;
    private OrthographicCamera camera;
    private World world;
    private Sprite sprite;
    Box2DDebugRenderer box2DDebugRenderer;

    public TestScreen(){
        batch = new SpriteBatch();
        camera = new OrthographicCamera();
        camera.setToOrtho(false, V_WIDTH / PPM, V_HEIGHT / PPM);
        camera.position.set(0,0,0);
        world = new World(new Vector2(0,0) , true);

        sprite = new Sprite(new Texture("test/player.png"));
        box2DDebugRenderer = new Box2DDebugRenderer();

        BodyDef bodyDef = new BodyDef();
        bodyDef.type = BodyDef.BodyType.KinematicBody;
        body = world.createBody(bodyDef);
        FixtureDef fixtureDef = new FixtureDef();

        PolygonShape shape = new PolygonShape();
        shape.setAsBox(sprite.getWidth()/2 / PPM, sprite.getHeight()/2 / PPM);
        fixtureDef.shape = shape;
        body.createFixture(fixtureDef);

        sprite.setPosition(body.getPosition().x - sprite.getWidth() /2 ,body.getPosition().y - sprite.getHeight() / 2  );
    }

    @Override
    public void render(float delta) {
        super.render(delta);
        camera.position.set( body.getPosition().x, body.getPosition().y , 0);
        camera.update();
        world.step(1/60.0f, 6, 2);
        batch.setProjectionMatrix(camera.combined);
        batch.begin();
        sprite.draw(batch);
        batch.end();
        box2DDebugRenderer.render(world, camera.combined);
    }
}

with out ppm

with PPm

我应该缩小图像吗?绘制图像的最佳方式是什么

最佳答案

您不需要从像素转换为米。事实上你应该忘记像素。它们仅存在于您的屏幕上,您的游戏逻辑不应该了解有关您的屏幕的任何信息。这就是相机或视口(viewport)的用途,您可以指定要显示的世界范围以及显示是否应该拉伸(stretch)或黑盒化或其他什么。所以没有像素,就这样。他们是邪恶的,会给你错误的想法。

现在,如果您创建自己的游戏,您可以说单个单位代表 1 毫米、34 厘米或几光年。您告诉负责显示游戏的对象要显示多少这些单位。但是您使用的是 Box2D,Box2D 已经为您填写了单位 1 单位 == 1m。可能可以更改此设置,或者至少创建一个包装类,将您的单位转换为 Box2D 单位。

坚持 Box2D 单元很重要的原因如下。如果你把一颗弹珠扔到地上,它的移动速度似乎比天空中的太阳还要快。但请相信我,太阳移动得更快,但由于距离更远,所以看起来移动得很慢。由于 Box2D 是关于移动的,所以你应该忠于单位,否则事情会开始变得奇怪。

现在让我们使用1 unit == 1m,突然之间,通过提出 View 问题,一切都会变得简单得多。

  • 您希望以米为单位显示游戏世界的多少部分?

    float width = 20; // 20 meters
    //You can calculate on your chosen width or height to maintain aspect ratio
    float height = (Gdx.graphics.getHeight() / Gdx.graphics.getWidth()) * width;        
    camera = new OrthographicCamera(width, height);
    //Now the center of the camera is on 0,0 in the game world. It's often more desired and practical to have it's bottom left corner start out on 0,0
    //All we need to do is translate it by half it's width and height since that is the offset from it's center point (and that is currently set to 0,0.
    camera.translate(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
    camera.update();
    
  • 我们的对象有多大?请记住,质量、重量和尺寸是完全不同的东西。

    Sprite mySprite = new Sprite(myTexture);
    //position it somewhere within the bounds of the camera, in the below case the center
    //This sprite also gets a size of 1m by 1m
    mySprite.setBounds(width / 2, height / 2, 1, 1);
    
  • 我们希望 SpriteBatch 如何绘制到屏幕上?

    //We tell the SpriteBatch to use out camera settings to draw
    spriteBatch.setProjectionMatrix(camera.combined);
    //And draw the sprite using this SpriteBatch
    mySprite.draw(spriteBatch);
    

对于 Box2dDebugRenderer 实现来说,计数相同。如果您希望显示形状,则需要再次使用相机中的组合矩阵来绘制它。

    box2DDebugRenderer.render(world, camera.combined);

当然,当物体移动时,您需要相应地更新 Sprite 位置。您可以从 box2d.Body 对象获取此信息。但这超出了您的问题范围。

最后向您展示出了什么问题:

camera.setToOrtho(false, V_WIDTH / PPM, V_HEIGHT / PPM);

您的相机显示游戏世界的 320/100 == 3.2f x 480/100 == 4.8f。您的 Sprite 可能是 64x64 像素。您没有告诉任何地方以什么尺寸绘制 Sprite ,因此它将假设 1 像素 = 1 单位,并且您将相机设置为显示 3.2f 单位的宽度。我们可以而且应该把像素排除在外,只问你想要的物体的大小。然后将 Sprite 设置为该大小。在这里您会看到,以像素为单位的思考只会给您带来问题。

对于以 3 人称视角驾驶 100x20 米飞船的太空游戏,您可能希望相机视口(viewport)非常大。但对于 Ant 游戏来说,你的 Ant 是真实大小的,你需要一个非常小的相机视口(viewport)。请考虑现实生活中的物理问题。伽利略发现物体以相同的速度下落,不考虑阻力。因此,如果那只 Ant 会掉落沙粒,它看起来会掉落得非常快,因为你的屏幕代表的米要少得多。

实现一个下落的足球 look at my answer here 。它创建一个 box2D 主体并向其附加图像。我将球的功能封装在 Ball() 类中。 (免责声明:我刚刚玩了一下 Box2D,我不知道足球的确切物理行为,所以我并不是说这是一个正确的实现,但它确实展示了如何设置场景并获得图像代表您的 Box2D body )。

关于java - 在 Libgdx Box2d World 上使用每米像素时出现巨大图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36492128/

相关文章:

Libgdx 你能设置一个 ScrollPane 的边界吗?

java - 如何让b2box主体和 Sprite 以相同速度旋转?

java - 用 vector 生成二维世界

java - 使用 Swagger 进行身份验证登录

java - Android 游戏的游戏画面概念的可能实现

java - LibGDX - 窗口不是每帧都被清理

java - Box2D 错误的 body 旋转

java - 为什么每个后续日志条目都会重复(使用 java.util.logging)?

java - 创建 jTDS 连接字符串

java - 非常简单的 2D 游戏中的 libgdx 像素碰撞