LibGDX-黑白图像将黑色呈现为透明,白色呈现为黑色

时间:2019-09-15 17:01:59

标签: libgdx scene2d

长期阅读者,第一次海报...我正在使用LibGDX和Scene2D将iOS SpriteKit应用程序翻译为Android。我正在慢慢掌握它,但是我遇到了一个奇怪的图像问题,我无法解决问题。我有三个黑白图像,用作游戏板上的瓷砖。在每种情况下,当我将它们添加到舞台上时,它们的黑色部分都是透明的,白色部分是黑色的。这是一个示例:

black and white image become transparent and black image

这是我的自定义课程

public class Tile extends Actor {
private int value;
private Image prime;
private Label label;
private boolean isPrime;
private Rectangle r;

Tile(int number, boolean primeSquare, Rectangle rect, float textSize) {
    value = number;
    r = rect;

    if (primeSquare) {
        isPrime = true;
        prime = new Image(new Texture(Gdx.files.internal("prime_background.png")));
        prime.setBounds(r.x, r.y, r.width, r.height);
    } else {
        isAvailable = true;
    }

    Label.LabelStyle style = new Label.LabelStyle(Fonts.bold(textSize), Color.BLACK);
    label = new Label(Integer.toString(number), style);
    label.setBounds(r.x, r.y, r.width, r.height);
    label.setAlignment(Align.center);
}

@Override
public void draw(Batch batch, float parentAlpha) {
    if (isPrime) {
        prime.draw(batch, parentAlpha);
        label.draw(batch, parentAlpha);
    }

}

我还有另外两个黑白图像,我也在本课程中尝试过,它们也存在相同的问题。我替换了一张全彩色图像,并且可以正确呈现它。

黑白图像是否有某些特殊之处,会导致它们以这种方式渲染?其他可能导致它消失的设置是我所忽略的吗?

所有这些都是通过我的自定义Screen类呈现的,我觉得这是一种非常普通的方式:

@Override
public void render(float delta) {
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    stage.act(Gdx.graphics.getDeltaTime());
    stage.draw();
}

任何帮助将不胜感激。谢谢。

这是我能够找到的最接近的线程:LibGDX: Why my black/white picture gets transparent?

1 个答案:

答案 0 :(得分:0)

灰度PNG文件可能是8位(纯alpha通道)或16位(一种颜色(“亮度”)通道和一个alpha通道)。我不知道您拥有哪个,因为没有清楚地记录纹理加载行为,但是我猜您保存了一个8位图像。 OpenGL会将单个通道视为alpha(透明度),并添加纯黑色的颜色通道。这将产生您在屏幕快照中显示的内容。

假设您要在数字后面绘制此图像,因此它根本不需要透明度,最简单的解决方案是使用纯白色Alpha通道保存源PNG文件,使其成为16位图像。如果这样给您带来麻烦,请将它们另存为全彩32位PNG。

顺便说一下,new Texture不应在Actor文件中使用。 Texture是一个很重的对象,它还使用本机内存,必须对其进行清理以防止内存泄漏。 Java垃圾收集器不会自动清理本机分配的内存。通过在游戏的每个图块中创建新的纹理,您可以无缘无故地将同一图像多次加载到内存中。如果您在引用丢失之前没有在Texture上调用dispose(),则会泄漏内存。

最佳实践是拥有一个中央资产类,您可以在其中加载所有纹理。您可以将对相同纹理的引用传递给每个Tile构造函数。您的资产类应该处理游戏关闭(game.dispose())时加载的所有内容。

事实上,LibGDX已经为此目的内置了AssetManager类。您可以在文档中进行阅读。