【问题标题】:LibGDX Tiled: Moving camera causes tiles to stutter/blur/waveLibGDX Tiled:移动相机会导致瓷砖结巴/模糊/波动
【发布时间】:2018-01-22 22:31:19
【问题描述】:

我已经尝试过到处寻找这个问题的解决方案,但没有运气;尽管我尝试了各种建议,但我将在下面详细说明问题。

我创建了一个非常小且简单的示例项目来测试渲染平铺地图并设置具有视口和一些简单输入处理的相机,以便我可以使用 WASD 在地图周围“平移”。问题是当我尝试在地图上平移时,地图会出现奇怪的效果。其中包括:

  • 瓷砖“挥动”。我的意思是当我向上/向下滚动或在屏幕上滚动时会出现“波浪状”
  • 故障/卡顿屏幕。相机有时会显得不流畅。
  • 瓷砖变化,(例如,黄色瓷砖上的黑条在移动相机时将在侧面或顶部有一个不同颜色的黄色像素。这些“额外”像素在哪一侧取决于相机移动)。我认为这称为纹理渗色,但我不确定。

我尝试过的事情:

  • 用相同颜色像素填充所有图块(这消除了地图上的黑色水平线)
  • 将过滤器设置为线性/最近(尝试了所有组合)
  • 玩转视口
  • 改变相机速度

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

确切代码:

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

【问题讨论】:

  • 首先,您应该在设置新位置后致电camera.update()。接下来,尝试使用常量 delta,而不是 libgdx 提供的 delta,这取决于您的计算机能力。

标签: camera libgdx textures rendering tiled


【解决方案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();
}

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

要了解您的增量问题,我建议阅读这篇文章http://gameprogrammingpatterns.com/game-loop.html

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

Libgdx 自带Ashley,你也可以看看Artemis-odb,这也是一个很棒的项目,在我看来比 Ashley 更完整。

【讨论】:

  • 不幸的是,这些东西对问题没有任何影响。
【解决方案2】:

对于任何偶然发现这个问题的人,我已经在谷歌上搜索并尝试了大约一周的时间。我终于修好了,所以我会分享我所做的。

  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

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

    @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. 将代码精简到准系统级别。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-10
    • 2016-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多