LibGDX Tiled:移动相机导致瓷砖卡顿/模糊/波动

时间:2017-08-15 01:55:52

标签: camera libgdx textures rendering tiled

我已经尝试过寻找解决这个问题的方法而且没有运气;虽然我已经尝试了各种建议,我将在下面详细介绍这个问题。

我创建了一个非常小而简单的示例项目来测试渲染Tiled地图并设置带有视口和一些简单输入处理的摄像机,这样我就可以用WASD“平移”地图了。问题是,当我尝试在地图上平移时,我会对地图产生奇怪的效果。其中包括:

  • 瓷砖“挥舞着。”我的意思是当我向上/向下滚动或屏幕上方显示“波浪”时
  • Glitchy / Stuttering屏幕。相机有时不会显得平滑。
  • 瓷砖更换,(例如,黄色瓷砖上的黑条会在移动相机时在侧面或顶部有一个不同颜色的黄色像素。这些“额外”像素在哪一侧取决于哪个方向相机移动)。我认为这被称为纹理出血,但我不确定。

我尝试过的事情:

  • 在所有面上填充所有具有相同颜色像素的图块(这样可以消除地图上的黑色水平线)
  • 将过滤器设置为线性/最近(尝试所有组合)
  • 使用视口播放
  • 更改相机速度

是否有人对可能出现的问题有任何想法?我只是想确保我了解如何在继续之前正确渲染地图并正确移动相机而没有任何问题。

确切代码:

public class GameScreen implements Screen {
final Alpha game;

private OrthographicCamera camera;
private FitViewport viewport;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;
private Rectangle player;

public GameScreen(final Alpha game) {
    this.game = game;

    camera = new OrthographicCamera();
    viewport = new FitViewport(800, 480, camera);

    TmxMapLoader.Parameters params = new TmxMapLoader.Parameters();
    params.textureMinFilter = Texture.TextureFilter.Nearest;
    params.textureMagFilter = Texture.TextureFilter.Linear;
    map = new TmxMapLoader().load("simple_padded_same_color.tmx");
    renderer = new OrthogonalTiledMapRenderer(map);

    player = new Rectangle(32,32,32,32);
}

@Override
public void render(float delta) {
    camera.update();
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    // handle input
    if (Gdx.input.isKeyPressed(Input.Keys.A)) {
        player.setX(player.getX() - 200 * delta);
    }
    if (Gdx.input.isKeyPressed(Input.Keys.D)) {
        player.setX(player.getX() + 200 * delta);
    }
    if (Gdx.input.isKeyPressed(Input.Keys.W)) {
        player.setY(player.getY() + 200 * delta);
    }
    if (Gdx.input.isKeyPressed(Input.Keys.S)) {
        player.setY(player.getY() - 200 * delta);
    }

    camera.position.set(player.getX(), player.getY(), 0);

    renderer.setView(camera);
    renderer.render();
}

@Override
public void resize(int width, int height) {
    viewport.update(width, height);
}

@Override
public void show() {
}

@Override
public void hide() {
}

@Override
public void pause() {
}

@Override
public void resume() {
}

@Override
public void dispose() {
    map.dispose();
    renderer.dispose();
}
}

2 个答案:

答案 0 :(得分:1)

这是你的渲染功能应该是什么样的

@Override
public void render(float delta) {

    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    // force a constant delta
    float gameDelta = 0.1f;

    // handle input
    if (Gdx.input.isKeyPressed(Input.Keys.A)) {
        player.setX(player.getX() - 200 * gameDelta);
    }
    if (Gdx.input.isKeyPressed(Input.Keys.D)) {
        player.setX(player.getX() + 200 * gameDelta);
    }
    if (Gdx.input.isKeyPressed(Input.Keys.W)) {
        player.setY(player.getY() + 200 * gameDelta);
    }
    if (Gdx.input.isKeyPressed(Input.Keys.S)) {
        player.setY(player.getY() - 200 * gameDelta);
    }

    // set camera position first
    camera.position.set(player.getX(), player.getY(), 0);
    // update camera
    camera.update();

    // then set the view
    renderer.setView(camera);
    // last render
    renderer.render();
}

首先,您需要在设置新位置后更新相机。然后,尝试使用恒定的delta而不是实际的delta,这将导致奇怪的相机移动,因为libgdx delta表示两帧之间的时间量并且不是常量。这应该消除你在游戏中的波浪效果。

要了解delta问题,建议您阅读本文http://gameprogrammingpatterns.com/game-loop.html

理想情况下,您将使用实体系统框架和特定的PhysicSystem以及MotionSystem来计算您的玩家移动,并将玩家位置计算与渲染循环分离。

Libgdx附带Ashley,您还可以查看Artemis-odb这是一个非常棒的项目,在我看来比Ashley更完整。

答案 1 :(得分:0)

对于任何在这个问题上绊倒的人,我已经使用谷歌搜索并尝试了大约一周的时间。我终于修复了它,所以我会分享我所做的。

  1. 将填充添加到您的图块集和字符中。我还使用了重复填充。
  2. 检查您的插值函数并确保它们不是问题(在一种情况下,我使用的插值方法之一使效果变得更糟)。
  3. 更改正射相机初始化。最初,我将相机设置为绘制 25x19 瓷砖。更改此数字有时会解决问题,但随后地图会失真。这是我使用的:
camera.setToOrtho(false, Gdx.graphics.getWidth() / TILE_SIZE / 2f, Gdx.graphics.getHeight() / TILE_SIZE / 2f);

TILE_SIZE 是您的磁贴(PPU?)。我的图块是 16x16,所以值为 16。我的地图渲染器初始化为 1 / 16.0f

如果您使用的是视口,您也可以在调整大小方法中应用它。

    @Override
    public void resize(int width, int height) {
        viewport.update(width, height, false);
        camera.setToOrtho(false, width / 16f / 2f, height / 16f / 2f);
    }

我为调试问题所做的工作:

  1. 分析,并没有真正显示任何内容。
  2. 确保我没有在渲染/更新循环中创建任何对象。
  3. 多次更改我的时间步长。
  4. 将代码精简到准系统级别。