【问题标题】:Libgdx change color of Texture at runtimeLibgdx 在运行时更改纹理的颜色
【发布时间】:2023-03-11 20:56:01
【问题描述】:

在使用 libgdx 制作的游戏中,我有一个 TextureAtlas,其中存储了我的 Animations 和 Player 的所有 TextureRegions。 Player 默认情况下有一件蓝色 T 恤(例如)。现在我希望能够拥有不止一个Player,并且每个都应该有另一种 T 恤颜色。所以基本上,我想用红色替换第二个Player 的蓝色和第三个Player 的绿色等等。我确信我可以用PixMap 做到这一点,但不会。因为那样我就失去了TextureAtlas(?) 的优势。 还有另一种方法可以做到这一点吗?或者我是否需要在TextureAtlas 中将每个“颜色版本”都作为TextureRegion

另一个小问题:
使用 Gimp(可能还有一些其他程序),您可以为“.gif”文件使用颜色索引。通过为文件中的每种颜色保存一个索引,然后使用该索引来描述像素,这可以减小所有 Textures 的大小。因此,对于每个红色像素,您将有一个“1”而不是“#FF0000”,并且在文件中的某处您有一个“1=#FF0000”。如果我们随后将带有颜色索引的“.gif”文件打包到 TextureAtlas 中,那么索引会丢失并恢复默认的 RGB 颜色还是会产生问题?

非常感谢!

【问题讨论】:

  • 只需将 T-Shirt 纹理设为白色,然后在渲染红色播放器之前使用 spriteBatch.setColor(1, 0, 0, 1) 即可。
  • 我总是用一些 SpriteSprite#setColor(Color tint) 来做这件事 :)
  • @noone 但如果我这样做,整个TextureRegion 都会受到影响还是我错了?会不会只影响白色部分?
  • @Nizil 这将与spriteBatch.setColor(1, 0, 0, 1) 相同,但仅适用于Sprites,我有TextureRegions。无论如何谢谢(:

标签: java colors libgdx textures


【解决方案1】:

我在使用相同纹理生成具有随机颜色的武器时遇到了同样的问题。

所以我写了这个。
基本上,我会为您要编辑的纹理制作像素图。

然后你迭代所有的像素,在迭代的同时我检查某些颜色,这些颜色是纹理的特定部分。 (我建议使用不同的灰度,因为 RGB 是相同的)

然后,当它位于需要更改颜色的像素上时,我使用颜色选择器方法为这些像素组获取颜色,该方法基本上是随机的,从预制颜色数组中获取颜色,
然后将该特定像素更改为新颜色。

/**
 * Requires a asset's textureName, and requires gray scale colors of the
 * parts
 * 
 * @param texturename
 * @param colorBlade
 * @param colorEdge
 * @param colorAffinity
 * @param colorGrip
 * @return
 */
private static Texture genTexture(String texturename, int colorBlade,
        int colorEdge, int colorAffinity, int colorGrip, int colorExtra) {
    Texture tex = Game.res.getTexture(texturename);

    TextureData textureData = tex.getTextureData();
    textureData.prepare();

    Color tintBlade = chooseColor(mainColors);
    Color tintEdge = new Color(tintBlade.r + 0.1f, tintBlade.g + 0.1f,
            tintBlade.b + 0.1f, 1);

    Color tintAffinity = chooseColor(affinityColors);
    Color tintGrip;
    Color tintExtra = chooseColor(extraColors);

    boolean colorsAreSet = false;

    do {
        tintGrip = chooseColor(mainColors);

        if (tintAffinity != tintBlade && tintAffinity != tintGrip
                && tintGrip != tintBlade) {
            colorsAreSet = true;
        }
    } while (!colorsAreSet);

    Pixmap pixmap = tex.getTextureData().consumePixmap();

    for (int y = 0; y < pixmap.getHeight(); y++) {
        for (int x = 0; x < pixmap.getWidth(); x++) {

            Color color = new Color();
            Color.rgba8888ToColor(color, pixmap.getPixel(x, y));
            int colorInt[] = getColorFromHex(color);

            if (colorInt[0] == colorBlade && colorInt[1] == colorBlade
                    && colorInt[2] == colorBlade) {
                pixmap.setColor(tintBlade);
                pixmap.fillRectangle(x, y, 1, 1);
            } else if (colorInt[0] == colorEdge && colorInt[1] == colorEdge
                    && colorInt[2] == colorEdge) {
                pixmap.setColor(tintEdge);
                pixmap.fillRectangle(x, y, 1, 1);
            } else if (colorInt[0] == colorAffinity
                    && colorInt[1] == colorAffinity
                    && colorInt[2] == colorAffinity) {
                pixmap.setColor(tintAffinity);
                pixmap.fillRectangle(x, y, 1, 1);
            } else if (colorInt[0] == colorGrip && colorInt[1] == colorGrip
                    && colorInt[2] == colorGrip) {
                pixmap.setColor(tintGrip);
                pixmap.fillRectangle(x, y, 1, 1);
            }
            else if (colorInt[0] == colorExtra && colorInt[1] == colorExtra
                && colorInt[2] == colorExtra) {
            pixmap.setColor(tintExtra);
            pixmap.fillRectangle(x, y, 1, 1);
            }
        }
    }

    tex = new Texture(pixmap);
    textureData.disposePixmap();
    pixmap.dispose();

    return tex;
}

我希望这会有所帮助。
请不要只是复制粘贴,尝试重新构建它以满足您的需求,否则您将学不到任何东西。

【讨论】:

  • 您好 Rose Blax,感谢您提供此解决方案。这基本上是我想做的。但这里的问题是:当您创建一个新的Texture 时,这是否消除了TextureAtlas 的优势,还是仍然采用TextureAtlas
  • 我会说试着弄清楚,我没试过所以我不知道。
  • 我建议只在两个 for 循环之外调用 new Color() 一次,然后在该位置设置 rgba 值。创建实例的计算成本很高,因此在不必要时避免这样做。
【解决方案2】:

一种方法就是设置最大玩家数量,为每个人制作T恤,用纹理图集打包,添加到一个TextureRegion数组中。

现在您只需在索引之间切换。

另一种方法是使用 batch.setColor

void    setColor(Color tint)
void    setColor(float color) 
void    setColor(float r, float g, float b, float a) 

只需为您绘制的每件 T 恤设置精灵批次的颜色,在您绘制完所有 T 恤后,再次将精灵批次颜色设置为白色。

您也可以使用带有 setColor 函数的 Sprite 类来做到这一点。

如果您的 T 恤尺寸不是很大,并且您的最大玩家人数很小,我会推荐第一种方法。

【讨论】:

  • 你是怎么得出数字 15 的?为什么更喜欢第一种方法?对我来说似乎是更糟糕的选择。改变颜色基本上会产生无数种不同的衬衫,你只需要保持一件的质感。
  • 这只是我的看法,一个游戏可能不会超过 15 名玩家,反正我已经编辑过了。我会使用这种方法,因为这是最简单的方法,而且对于小 T 恤和球员编号,正如我所说,很容易为每个球员分配一个索引。..
  • 感谢您的回答。没有问题,如果每种颜色只有 1 件 T 恤,但玩家的Animation 会包含更多的Textures,所以这不是一个真正的选择,或者至少是最后一个我想使用的... setColor() 很有趣,但它不会影响整个Texture 吗?
  • 它会影响整个纹理,但黑色会保持黑色,白色会变成批次的颜色。您不应该使用任何其他颜色,因为它们会混合在一起并且看起来很奇怪。
  • @noone 但最终结果应该是Player(想想一个人)和一件彩色 T 恤。那么setColor 方法不可能做到这一点?
【解决方案3】:

Rose Blax 确实做得很好。但是,如果您想通过使用 SpriteBatch 或有相同问题但不想使用 Pixmap 的人来做到这一点...

当然,我真的很喜欢使用 Pixmap,但我已经看到“spritebatch/sprite.setcolor(r,g,b,a)”的使用带来了一些挑战,因为更改所有纹理颜色而不是仅更改 T 恤。 .. 这就是我来这里的原因,是的,可以使用这种方式只更换 T 恤。你准备好了吗? :D

1 - 使零件想要绘制灰度或白色 2 - 拆分零件将在纹理包中绘制或不同的纹理:如果是 T 恤,您需要一个包,其中 T 恤不在您的字符中......是的,将是一个有头、手臂和只有腿。 t-short 可能在同一个包中,也可能不在。但是在这之间留一个洞,以便将来穿上 T 恤。

看起来像这样:

Check out this asset

不必害怕。我知道这张图片已经分割了整个角色,但如果你只想更换 T 恤,那么你只会将它与身体的其他部分分开。

3 - 您将同时绘制它们,但不是相同的 TextureRegion,您的代码将如下所示:

public void draw(SpriteBatch batch){
        //First we draw the player with a hole in his body
        batch.draw(playerA,0,0,75,100);
        //Here we set the color of next texture to be drawn as RED.
        batch.setColor(Color.RED);
        //Now we draw the t-shirt of the player in same x and half y.
        //That t-short has to be drawn in right position. That's why calc it.
        batch.draw(tshirtA, 0,50,50);
        //For don't affect others textures then make it white back.
        batch.setColor(Color.WHITE);
    }

【讨论】:

    猜你喜欢
    • 2022-12-14
    • 1970-01-01
    • 2017-12-31
    • 2019-05-30
    • 2015-11-01
    • 1970-01-01
    • 2021-09-18
    • 2020-05-04
    • 1970-01-01
    相关资源
    最近更新 更多