Java 如何在LibGDX的tilemap中防止纹理出血

Java 如何在LibGDX的tilemap中防止纹理出血,java,libgdx,textures,tiled,Java,Libgdx,Textures,Tiled,我知道在这个话题上有很多问题(和答案),但它们都有不同的解决方案,而且没有一个在我的情况下有效 我正在开发一个小的测试项目,其中我尝试添加一个简单的tilemap。我使用创建了tilemap,它似乎工作得很好,除了纹理出血,有时会导致瓷砖之间出现黑线(背景色) 到目前为止我所尝试的: 我读了一些关于SO的问题、教程和论坛帖子,并尝试了几乎所有的解决方案,但我似乎无法实现这一点。大多数答案都说我需要在瓷砖之间垫上一层垫子,但这似乎无法解决问题。我还尝试加载具有不同参数的tilemap(例如,加载

我知道在这个话题上有很多问题(和答案),但它们都有不同的解决方案,而且没有一个在我的情况下有效

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


到目前为止我所尝试的:

我读了一些关于SO的问题、教程和论坛帖子,并尝试了几乎所有的解决方案,但我似乎无法实现这一点。大多数答案都说我需要在瓷砖之间垫上一层垫子,但这似乎无法解决问题。我还尝试加载具有不同参数的tilemap(例如,加载时使用最近的过滤器)或舍入相机位置以防止舍入问题,但这甚至使情况变得更糟


我的当前设置:

你可以在网上找到整个项目。该分支称为“平铺贴图缩放”

目前,我使用的瓷砖集由以下瓷砖图片组成:

它在每个瓷砖之间有两个像素的空间,用作填充和边距

我的平铺平铺集设置如下所示:

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 ...
}

我用了两个像素的边距和间距来防止出血

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

我当前正在将平铺贴图加载到资产管理器中,没有任何参数:

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上使用填充,还尝试了不同的加载参数和取整摄影机位置,但我的tilemap中仍然存在纹理出血问题。
我错过了什么?或者我做错了什么


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

您需要将瓷砖边缘填充到瓷砖表中。 看起来您已经尝试过这样做,但是填充是透明的,它需要具有填充的像素的颜色

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

那么它应该是这样的

 A  B 
AAABBB
 A  B
 C  C
CCCCCC
 C  C
要填充的像素必须用相同颜色的像素填充


(我将尝试创建一个pull请求,并对您的git回购进行修复。)

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

如果任何人都可以使用它,可以在GitHub上找到:

如何创建瓷砖纹理图谱?您不希望在它们之间有间隙,而是希望从它们中流出边界像素的副本。LibGDX TexturePack对此有一个设置。但看起来你的游戏也使用了像素艺术,所以你可能应该使用最近的过滤,这在一开始就不会受到边缘出血问题的影响。我没有创建任何图集,只是尝试使用我在itch.io上找到的纹理。我想我现在明白问题所在了。非常感谢。我想现在我明白了:)我试着只使用一个tileset,我在itch.io上找到的,没有创建纹理图集或类似的东西,所以边距是透明的,而不是边缘颜色(这在我理解它们的用途时已经没有任何意义了)。你能指出一些关于如何从我正在使用的图形中创建正确图形的教程吗?已经非常感谢你了。这对我帮助很大:)我为你的tileset创建了一个pull请求,它应该可以解决这个问题。至于实现这一点的工具,libGDX有一个名为runnable-texturepacker.jar的工具,它可以处理单独的平铺图像,并将它们组合到一个sprite表中。因此,我只是将您的图像分割为多个128x128图像,然后运行runnable-texturepacker.jar,并将pack.json文件配置为平铺填充。非常感谢!:)