LibGDX - B/W 图像将黑色渲染为透明,将白色渲染为黑色

LibGDX - B/W images render black as transparent and white as black

长期 reader,第一次张贴...我正在使用 LibGDX 和 Scene2D 将我的 iOS SpriteKit 应用程序翻译成 Android。我正在慢慢掌握它,但我遇到了一个奇怪的图像问题,我无法解决这个问题。我有三张黑白图像,用作游戏板上的图块。在每种情况下,当我将它们添加到舞台时,它们都会以黑色部分透明、白色部分黑色呈现。这是一个例子:

这是我的习惯class

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

}

我还有另外两张 b/w 图片,我也在这个 class 中尝试过,它们也有同样的问题。我替换了一张全彩色图像,它正确地渲染了没有问题。

b/w 图像有什么特别之处会导致它们以这种方式呈现吗?任何其他可能导致它以我忽略的方式出现的设置?

这一切都是通过我的自定义屏幕呈现的class,我觉得这是一种非常普通的方式:

@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?

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

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

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

最佳做法是拥有一个中央资产 class,您可以在其中加载所有纹理。您可以将对同一纹理的引用传递给每个 Tile 构造函数。你的资产 class 应该在你的游戏关闭时处理它加载的所有东西 (game.dispose())。

事实上,LibGDX 已经有一个用于此目的的内置 AssetManager class。您可以在文档中阅读它。