如何在LibGDX中防止瓷砖地图中的纹理渗透。

huangapple go评论82阅读模式
英文:

How to prevent texture bleeding in a tilemap in LibGDX

问题

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

我正在开发一个小型测试项目,使用libGDX,我试图添加一个简单的平铺地图。我使用Tiled创建了这个平铺地图,看起来效果还不错,除了纹理出现了“纹理出血”,导致有时出现黑线(背景颜色)在平铺之间。

我到目前为止尝试过的事情:

我阅读了一些Stack Overflow的问题、教程和论坛帖子,并尝试了几乎所有的解决方案,但似乎无法解决这个问题。大多数答案都说我需要在平铺之间添加填充,但这似乎并没有解决问题。我还尝试了使用不同的参数加载平铺地图(例如,在加载它们时使用最近滤镜)或四舍五入相机的位置以防止四舍五入问题,但这只会让问题变得更糟。

我的当前设置:

您可以在GitHub上找到整个项目。分支名为'tile_map_scaling'

目前,我使用的是由这个平铺图片制作的平铺图集:
如何在LibGDX中防止瓷砖地图中的纹理渗透。

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

我的Tiled平铺图集设置如下:

如何在LibGDX中防止瓷砖地图中的纹理渗透。

我使用了两个像素的边距和间距,试图防止出现纹理出血。

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

如何在LibGDX中防止瓷砖地图中的纹理渗透。

我目前在不带任何参数的情况下将平铺地图加载到资源管理器中:

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

    //...其他方法...

}

问题:

我在平铺地图上使用了填充,还尝试了不同的加载参数和四舍五入相机位置,但我仍然在我的平铺地图上遇到了这个纹理出血问题。我错过了什么?或者我做错了什么?

对此的任何帮助都将是很有帮助的。

英文:

I know there are quite some questions (and answers) on this topic, but they all have different solutions, and none of them seems to be working in my case.

I'm developing a small test project with libGDX, in which I tried to add a simple tilemap. I created the tilemap using Tiled, which seems to be working quite good, except for the texture bleeding, that causes black lines (the background color) to appear between the tiles sometimes.

<hr>

What I've tried so far:

I read several SO-questions, tutorials and forum posts, and tried almost all of the solutions, but I just don't seem to get this working. Most of the answers said that I would need a padding between the tiles, but this doesn't seem to fix it. I also tried loading the tilemap with different parameters (e.g. to use the Nearest filter when loading them) or rounding the camera's position to prevent rounding problems, but this did even make it worse.

<hr>

My current setup:

You can find the whole project on GitHub. The branch is called 'tile_map_scaling'

At the moment I'm using a tileset that is made of this tile-picture:
如何在LibGDX中防止瓷砖地图中的纹理渗透。

It has two pixels of space between every tile, to use as padding and margin.

My Tiled tileset settings look like this:

如何在LibGDX中防止瓷砖地图中的纹理渗透。

I use two pixels of margin and spacing, to (try to) prevent the bleeding here.

Most of the time it is rendered just fine, but still sometimes there are these lines between the tiles like in this picture (sometimes they seem to appear only on a part of the map):

如何在LibGDX中防止瓷砖地图中的纹理渗透。

I'm currently loading the tile map into the asset manager without any parameters:

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

... and use it like this:

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(&quot;map/map.tmx&quot;);
    	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 ...
}

<hr>

The question:

I am using padding on the tilemap and also tried different loading parameters and rounding the camera position, but still I have this texture bleeding problem in my tilemap.
What am I missing? Or what am I doing wrong?

Any help on this would be great.

答案1

得分: 1

你需要在你的瓷砖图中填充瓷砖的边缘。
看起来你已经尝试过这样做,但填充是透明的,它需要与填充的像素颜色相同。

所以,如果你有这样的一幅图像(其中每个字母代表一个像素,瓷砖大小为一个像素):

AB
CB

那么填充它应该看起来像这样:

 A  B 
AAABBB
 A  B
 C  C
CCCCCC
 C  C

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

(我将尝试创建一个带有修复的拉取请求,以用于你的Git仓库。)

英文:

You need to pad the edges of your tiles in you tilesheet.
It looks like you've tried to do this but the padding is transparent, it needs to be of the color of the pixel it is padding.

So if you have an image like this (where each letter is a pixel and the tile size is one):

AB
CB

then padding it should look something like this

 A  B 
AAABBB
 A  B
 C  C
CCCCCC
 C  C

The pixel being padded must be padded with a pixel of the same color.

(I'll try try create a pull request with a fix for your git-repo as well.)

答案2

得分: 0

作为对bornander答案的小补充,我创建了一些Python脚本,可以从没有填充的纹理生成具有正确边缘填充(如bornander在他的答案中解释的)的瓦片集纹理。

以防有人能够使用,它可以在GitHub上找到:
https://github.com/tfassbender/libGdxImageTools

英文:

As a little addition to bornander's answer, I created some python scripts, that do all the work to generate a tileset texture, that has the correct edge padding (that bornander explained in his answer) from a texture, that has no padding yet.

Just in case anyone can make use of it, it can be found on GitHub:
https://github.com/tfassbender/libGdxImageTools

答案3

得分: 0

有一个npm包可以将瓦片拉伸。它是为Phaser JS游戏库构建的,但您仍然可以使用它。链接:https://github.com/sporadic-labs/tile-extruder

英文:

There is also a npm package that can extrude the tiles. It was built for the Phaser JS game library, but you could still use it. https://github.com/sporadic-labs/tile-extruder

huangapple
  • 本文由 发表于 2020年8月8日 19:25:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/63314823.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定