Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Libgdx change color of Texture at runtime

In a game made with libgdx I have a TextureAtlas in which I have stored all the TextureRegions for my Animations of the Player. The Player by default has a blue T-Shirt (for example). Now I would like to be able to have more then one Player and each should have another T-Shirt color. So basically, I want to replace the blue with red for the second Player and with green for the 3rd Player and so on. I am sure I can do this with PixMap but 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 TextureRegion in the TextureAtlas?

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?

Thanks a lot!

like image 526
Robert P Avatar asked Jun 04 '14 09:06

Robert P


2 Answers

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.

/**
 * 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.

like image 145
Maarten Avatar answered Oct 24 '22 16:10

Maarten


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.

Now you would only have to switch between indexes.

Another way to do it is with 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.

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

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.

like image 38
Boldijar Paul Avatar answered Oct 24 '22 16:10

Boldijar Paul