【问题标题】:How to prevent texture bleeding in a tilemap in LibGDX如何防止 LibGDX 中的瓦片地图中的纹理渗色
【发布时间】:2020-11-28 13:26:45
【问题描述】:

我知道关于这个主题有很多问题(和答案),但它们都有不同的解决方案,而且似乎都不适用于我的情况。

我正在使用libGDX 开发一个小型测试项目,我尝试在其中添加一个简单的平铺地图。我使用Tiled 创建了瓷砖贴图,它似乎工作得很好,除了纹理渗色,有时会导致黑色线条(背景颜色)出现在瓷砖之间。


到目前为止我所做的尝试:

我阅读了几个 SO 问题、教程和论坛帖子,并尝试了几乎所有的解决方案,但我似乎并没有得到这个工作。大多数答案都说我需要在瓷砖之间进行填充,但这似乎并不能解决它。我还尝试使用不同的参数加载瓷砖地图(例如,在加载时使用 Nearest 过滤器)或舍入相机的位置以防止舍入问题,但这确实使情况变得更糟。


我目前的设置:

您可以在GitHub 上找到整个项目。该分支称为“tile_map_scaling”

目前我正在使用一个由这个图块图片组成的图块集:

每个图块之间有两个像素的空间,用作填充和边距。

我的 Tiled tileset 设置如下所示:

我使用两个像素的边距和间距,以(尝试)防止此处流血。

大多数情况下它渲染得很好,但有时瓷砖之间仍然会有这些线条,就像这张图片中一样(有时它们似乎只出现在地图的一部分上):

我目前正在将瓦片地图加载到资产管理器中,没有任何参数:

public void load() {
    AssetManager manager = new AssetManager();
    manager.setLoader(TiledMap.class, new TmxMapLoader(new InternalFileHandleResolver()));
    manager.setErrorListener(this);
    manager.load("map/map.tmx", TiledMap.class, new AssetLoaderParameters());
}

...并像这样使用它:

public class GameScreen {

    public static final float WORLD_TO_SCREEN = 4.0f;
    public static final float SCENE_WIDTH = 1280f;
    public static final float SCENE_HEIGHT = 720f;

    //...

    private Viewport viewport;
    private OrthographicCamera camera;
    
    private TiledMap map;
    private OrthogonalTiledMapRenderer renderer;
    
    public GameScreen() {
        camera = new OrthographicCamera();
        viewport = new FitViewport(SCENE_WIDTH, SCENE_HEIGHT, camera);

        map = assetManager.get("map/map.tmx");
        renderer = new OrthogonalTiledMapRenderer(map);
    }

    @Override
    public void render(float delta) {
        //clear the screen (with a black screen)
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    
        moveCamera(delta);
        renderer.setView(camera);
        renderer.render();
        //... draw the player, some debug graphics, a hud, ...
        moveCameraToPlayer();
    }

    private void moveCamera(float delta) {
        if (Gdx.input.isKeyPressed(Keys.LEFT)) {
            camera.position.x -= CAMERA_SPEED * delta;
        }
        else if (Gdx.input.isKeyPressed(Keys.RIGHT)) {
            camera.position.x += CAMERA_SPEED * delta;
        }
        
        // ...

        //update the camera to re-calculate the matrices
        camera.update();
    }


    private void moveCameraToPlayer() {
        Vector2 dwarfPosition = dwarf.getPosition();
        
        //movement in positive X and Y direction
        float deltaX = camera.position.x - dwarfPosition.x;
        float deltaY = camera.position.y - dwarfPosition.y;
        float movementXPos = deltaX - MOVEMENT_RANGE_X;
        float movementYPos = deltaY - MOVEMENT_RANGE_Y;
        
        //movement in negative X and Y direction
        deltaX = dwarfPosition.x - camera.position.x;
        deltaY = dwarfPosition.y - camera.position.y;
        float movementXNeg = deltaX - MOVEMENT_RANGE_X;
        float movementYNeg = deltaY - MOVEMENT_RANGE_Y;
            
        camera.position.x -= Math.max(movementXPos, 0);
        camera.position.y -= Math.max(movementYPos, 0);
        
        camera.position.x += Math.max(movementXNeg, 0);
        camera.position.y += Math.max(movementYNeg, 0);
        
        camera.update();
    }
    
    // ... some other methods ...
}

问题:

我在 tilemap 上使用了 padding,还尝试了不同的加载参数和四舍五入的相机位置,但我的 tilemap 中仍然存在这个纹理渗出问题。
我错过了什么?还是我做错了什么?

在这方面的任何帮助都会很棒。

【问题讨论】:

  • 如何创建瓷砖纹理图集?您不希望它们之间有间隙,而是要从它们中流出它们的边界像素的副本。 LibGDX TexturePacker 对此有一个设置。但是看起来您的游戏也使用了像素艺术,因此您可能应该使用最近过滤,这首先不容易受到边缘出血问题的影响。
  • 我没有创建任何图集,只是尝试使用我在 itch.io 上找到的纹理。我想我现在明白问题所在了。非常感谢。

标签: java libgdx textures tiled


【解决方案1】:

还有一个可以挤压瓷砖的 npm 包。它是为 Phaser JS 游戏库而构建的,但您仍然可以使用它。 https://github.com/sporadic-labs/tile-extruder

【讨论】:

    【解决方案2】:

    作为对bornander 答案的一点补充,我创建了一些python 脚本,它们完成所有工作来生成一个tileset 纹理,该纹理具有正确的边缘填充(bornander 在他的回答中解释),没有填充还没有。

    以防万一任何人都可以使用它,可以在 GitHub 上找到它: https://github.com/tfassbender/libGdxImageTools

    【讨论】:

      【解决方案3】:

      您需要在图块表中填充图块的边缘。 看起来您已尝试这样做,但填充是透明的,它必须是填充像素的颜色。

      因此,如果您有这样的图像(其中每个字母是一个像素,图块大小是一个):

      AB
      CB
      

      然后填充它应该看起来像这样

       A  B 
      AAABBB
       A  B
       C  C
      CCCCCC
       C  C
      

      被填充的像素必须用相同颜色的像素填充。

      (我会尝试创建一个拉取请求并修复您的 git-repo。)

      【讨论】:

      • 我想现在我明白了:) 我尝试只使用我在 itch.io 上找到的图块集,而没有创建纹理图集或类似的东西,所以边距是透明的,而不是边缘颜色(现在没有任何意义,因为我了解它们的用途)。您能否指出有关如何从我使用的图形创建正确图形的任何教程?已经非常感谢了。这对我有很大帮助:)
      • 我为您的图块集创建了一个拉取请求,它应该可以解决问题。至于执行此操作的工具,libGDX 有一个名为 runnable-texturepacker.jar 的工具,它适用于单独的平铺图像并将它们组合成一个精灵表。所以我只是将您的图像拆分为多个 128x128 图像,然后运行 ​​runnable-texturepacker.jar 并使用为瓷砖填充配置的 pack.json 文件。
      • 我刚刚合并了您的拉取请求,它现在似乎可以正常工作了。非常感谢! :)
      猜你喜欢
      • 1970-01-01
      • 2014-01-03
      • 1970-01-01
      • 2020-06-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-23
      • 1970-01-01
      相关资源
      最近更新 更多