LibGDX 如何防止 tilemap 中的纹理渗色
How to prevent texture bleeding in a tilemap in LibGDX
我知道有很多关于这个主题的问题(和答案),但它们都有不同的解决方案,其中 none 似乎适用于我的情况。
我正在用 libGDX, in which I tried to add a simple tilemap. I created the tilemap using Tiled 开发一个小型测试项目,它似乎工作得很好,除了纹理渗色,有时会导致瓷砖之间出现黑线(背景色)。
目前我尝试过的:
我阅读了几个 SO 问题、教程和论坛帖子,并尝试了几乎所有的解决方案,但我似乎无法正常工作。大多数答案都说我需要在图块之间进行填充,但这似乎并不能解决问题。我还尝试使用不同的参数加载 tilemap(例如,在加载它们时使用 Nearest 过滤器)或舍入相机的位置以防止舍入问题,但这甚至使情况变得更糟。
我目前的设置:
您可以在 GitHub 上找到整个项目。该分支称为 'tile_map_scaling'
目前我正在使用由这张图块图片组成的图块集:
每个图块之间有两个 space 像素,用作填充和边距。
我的 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 上使用填充,也尝试了不同的加载参数和四舍五入相机位置,但我的 tilemap 中仍然存在纹理渗色问题。
我错过了什么?或者我做错了什么?
任何帮助都将非常有用。
您需要在图块表中填充图块的边缘。
看起来您已尝试这样做,但填充是透明的,它需要具有填充像素的颜色。
因此,如果您有这样的图像(其中每个字母是一个像素,图块大小是一个):
AB
CB
然后填充它应该看起来像这样
A B
AAABBB
A B
C C
CCCCCC
C C
被填充的像素必须用相同颜色的像素填充。
(我会尝试为您的 git-repo 创建一个包含修复的拉取请求。)
作为 bornander 回答的一点补充,我创建了一些 python 脚本,它们完成所有工作以生成一个 tileset 纹理,它具有正确的边缘填充(bornander 在他的回答中解释)来自纹理,还没有填充。
以防万一有人可以使用它,可以在 GitHub 上找到它:
https://github.com/tfassbender/libGdxImageTools
还有一个可以挤出瓷砖的npm包。它是为 Phaser JS 游戏库构建的,但您仍然可以使用它。 https://github.com/sporadic-labs/tile-extruder
我知道有很多关于这个主题的问题(和答案),但它们都有不同的解决方案,其中 none 似乎适用于我的情况。
我正在用 libGDX, in which I tried to add a simple tilemap. I created the tilemap using Tiled 开发一个小型测试项目,它似乎工作得很好,除了纹理渗色,有时会导致瓷砖之间出现黑线(背景色)。
目前我尝试过的:
我阅读了几个 SO 问题、教程和论坛帖子,并尝试了几乎所有的解决方案,但我似乎无法正常工作。大多数答案都说我需要在图块之间进行填充,但这似乎并不能解决问题。我还尝试使用不同的参数加载 tilemap(例如,在加载它们时使用 Nearest 过滤器)或舍入相机的位置以防止舍入问题,但这甚至使情况变得更糟。
我目前的设置:
您可以在 GitHub 上找到整个项目。该分支称为 'tile_map_scaling'
目前我正在使用由这张图块图片组成的图块集:
每个图块之间有两个 space 像素,用作填充和边距。
我的 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 上使用填充,也尝试了不同的加载参数和四舍五入相机位置,但我的 tilemap 中仍然存在纹理渗色问题。
我错过了什么?或者我做错了什么?
任何帮助都将非常有用。
您需要在图块表中填充图块的边缘。 看起来您已尝试这样做,但填充是透明的,它需要具有填充像素的颜色。
因此,如果您有这样的图像(其中每个字母是一个像素,图块大小是一个):
AB
CB
然后填充它应该看起来像这样
A B
AAABBB
A B
C C
CCCCCC
C C
被填充的像素必须用相同颜色的像素填充。
(我会尝试为您的 git-repo 创建一个包含修复的拉取请求。)
作为 bornander 回答的一点补充,我创建了一些 python 脚本,它们完成所有工作以生成一个 tileset 纹理,它具有正确的边缘填充(bornander 在他的回答中解释)来自纹理,还没有填充。
以防万一有人可以使用它,可以在 GitHub 上找到它: https://github.com/tfassbender/libGdxImageTools
还有一个可以挤出瓷砖的npm包。它是为 Phaser JS 游戏库构建的,但您仍然可以使用它。 https://github.com/sporadic-labs/tile-extruder