Java Libgdx 在运行时更改纹理的颜色

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24034352/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 09:50:09  来源:igfitidea点击:

Libgdx change color of Texture at runtime

javacolorslibgdxtextures

提问by Springrbua

In a game made with libgdx I have a TextureAtlasin which I have stored all the TextureRegions for my Animations of the Player. The Playerby default has a blue T-Shirt (for example). Now I would like to be able to have more then one Playerand each should have another T-Shirt color. So basically, I want to replace the blue with red for the second Playerand with green for the 3rd Playerand so on. I am sure I can do this with PixMapbut wouldn't. Because then I lose the advantage of the TextureAtlas(?). Is there another way to do this? Or do I need to have every "color version" as a TextureRegionin the TextureAtlas?

在与libgdx做了一个游戏我有一个TextureAtlas在我所存储的所有的TextureRegion,是为我Animation的S- Player。在Player默认情况下,具有蓝色T恤(例如)。现在我希望能够拥有不止一件,Player并且每件都应该有另一种 T 恤颜色。所以基本上,我想在第二个用红色替换蓝色,Player在第三个用绿色替换蓝色Player,依此类推。我确信我可以做到这一点,PixMap但不会。因为那样我就失去了TextureAtlas(?)的优势。有没有另一种方法可以做到这一点?或者,我需要有充分的“色版”作为一个TextureRegionTextureAtlas

Another little question:
With Gimp (and maybe a few other programs) you can use color indexes for ".gif" files. This reduces the size of all your Textures by saving an index for every color in the file and then using this index to describe the pixels. So for every red pixel you would have a "1" instead of "#FF0000" and somewhere in the file you have a "1=#FF0000". If we then pack the ".gif" files with the color indexes inside a TextureAtlas, is the index then lost and it restores the default RGB colors or will that make problems?

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

Thanks a lot!

非常感谢!

采纳答案by Rose Blax

I faced the same Issue for generating weapon with random colors using the same texture.

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

So I wrote this.
Basically I make a pixmap of the texture you want to edit.

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

Then you iterate over all of the pixels, while iterating I check for certain colors which are a part specific part of the texture. (I suggest using different shades of gray since the RGB is the same)

Then when it is on a pixel where the color needs to be changed I grab a color for those pixel groups using a color picker method which is basically random which gets a color from a prefabbed color array,
and then changes that specific pixel to the new color.

然后迭代所有像素,同时迭代我检查某些颜色,这些颜色是纹理的特定部分。(我建议使用不同的灰色阴影,因为 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;
}

I hope this helps.
Please don't just copy paste, try to rebuild this to suit your needs or you won't learn anything.

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

回答by Boldijar Paul

A way of making this is just setting a maximum number of players, and make T-shirts for everyone, and pack them with texture atlas and add them into one TextureRegion array.

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

Now you would only have to switch between indexes.

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

Another way to do it is with batch.setColor

另一种方法是使用 batch.setColor

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

And just set the color of the sprite batch for every T-Shirt you draw, and after you drawn all of them, put the spritebatch color to white again.

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

You can also do this with the Sprite class with the setColor function.

您也可以使用带有 setColor 函数的 Sprite 类来执行此操作。

If your T-Shirts doesn't have a very big size, and your maximum player number is a small one, I would recommend the first method.

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

回答by Play Marques

Rose Blax did really a good work. But if you want a way to do that by using SpriteBatch or for someone who has same issue but does not want to use Pixmap...

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

For sure I really like to use Pixmap, but I have seen the usage of "spritebatch/sprite.setcolor(r,g,b,a)" gave some challenges as change all texture color instead only the t-shirt... That's why I came here and yes, it's possible to change only the t-shirt using this way. Are you ready? :D

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

1 - Make the part want to paint grey scale or white 2 - Split the parts would paint in the texturepack or a different texture: in case of a t-shirt, you need a pack where the t-shirt is out of your char... Yes, will be someone with head, arms and legs only. The t-short may be in the same pack or not. But keep a hole between then to put the t-shirt in the future.

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

it will look like that:

它看起来像这样:

Check out this asset

看看这个资产

Do not need to be scared. I know that image has splited whole characther, but If you want to change only the t-shirt then you will split only it from rest of body.

不需要害怕。我知道图像已经分裂了整个角色,但是如果你只想改变 T 恤,那么你只会将它与身体的其余部分分开。

3 - You will draw they both, but not same TextureRegion, your code will look like that:

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