LibGDX Tiled:移动相机会导致图块抖动/模糊/波动。

3
我已经尝试在各处寻找解决此问题的方法,但没有任何进展;虽然我已经尝试了一些建议,下面我将详细介绍这些建议以及问题所在。
我创建了一个非常小而简单的示例项目,用于测试呈现Tiled地图并设置具有视口和一些简单输入处理的相机,以便我可以使用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 值。 - Alexandre GUIDET
2个回答

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更完整,我个人认为。

很遗憾,这些东西对问题没有任何影响。 - Hasen

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的值。

如果你正在使用视口,你也可以在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. 将代码剥离到最基本的水平。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接