Generate colors between red and green for a power

2020-01-25 12:19发布

I'm writing a Java game and I want to implement a power meter for how hard you are going to shoot something.

I need to write a function that takes a int between 0 - 100, and based on how high that number is, it will return a color between Green (0 on the power scale) and Red (100 on the power scale).

Similar to how volume controls work:
volume control

What operation do I need to do on the Red, Green, and Blue components of a color to generate the colors between Green and Red?

So, I could run say, getColor(80) and it will return an orangish color (its values in R, G, B) or getColor(10) which will return a more Green/Yellow RGB value.

I know I need to increase components of the R, G, B values for a new color, but I don't know specifically what goes up or down as the colors shift from Green-Red.


Progress:

I ended up using HSV/HSB color space because I liked the gradiant better (no dark browns in the middle).

The function I used was:

public Color getColor(double power)
{
    double H = power * 0.4; // Hue (note 0.4 = Green, see huge chart below)
    double S = 0.9; // Saturation
    double B = 0.9; // Brightness

    return Color.getHSBColor((float)H, (float)S, (float)B);
}

Where "power" is a number between 0.0 and 1.0. 0.0 will return a bright red, 1.0 will return a bright green.

Java Hue Chart:
Java Hue Chart

19条回答
太酷不给撩
2楼-- · 2020-01-25 12:32

Short Copy'n'Paste answer...

On Java Std:

int getTrafficlightColor(double value){
    return java.awt.Color.HSBtoRGB((float)value/3f, 1f, 1f);
}

On Android:

int getTrafficlightColor(double value){
    return android.graphics.Color.HSVToColor(new float[]{(float)value*120f,1f,1f});
}

note: value is a number between 0 and 1 indicating the red-to-green condition.

查看更多
3楼-- · 2020-01-25 12:33

I made a small function wich gives you the rgb integer value for a percentage value:

private int getGreenToRedGradientByValue(int currentValue, int maxValue)
{
    int r = ( (255 * currentValue) / maxValue );
    int g = ( 255 * (maxValue-currentValue) ) / maxValue;
    int b = 0;
    return ((r&0x0ff)<<16)|((g&0x0ff)<<8)|(b&0x0ff);
}

So if your currentValue is 50 and your maxValue is 100, this function will return the color that you need, so if you loop this function with a percentage value, your color value will go from green to red. Sorry for the bad explanation

查看更多
混吃等死
4楼-- · 2020-01-25 12:36

I'd say you want something in between a line segment in the HSV space (which has a slightly-too-bright yellow in the centre) and a line segment in the RGB space (which has an ugly brown in the centre). I would use this, where power = 0 will give green, power = 50 will give a slightly dull yellow, and power = 100 will give red.

blue = 0;
green = 255 * sqrt( cos ( power * PI / 200 ));
red = 255 * sqrt( sin ( power * PI / 200 )); 
查看更多
淡お忘
5楼-- · 2020-01-25 12:37

The accepted answer didn't even really answer the question...

C++

Here's a simple C++ code segment from my engine that linearly and efficiently interpolates between three arbitrary colors:

const MATH::FLOAT4 color1(0.0f, 1.0f, 0.0f, 1.0f);  // Green
const MATH::FLOAT4 color2(1.0f, 1.0f, 0.0f, 1.0f);  // Yellow
const MATH::FLOAT4 color3(1.0f, 0.0f, 0.0f, 1.0f);  // Red

MATH::FLOAT4 get_interpolated_color(float interpolation_factor)
{
    const float factor_color1 = std::max(interpolation_factor - 0.5f, 0.0f);
    const float factor_color2 = 0.5f - fabs(0.5f - interpolation_factor);
    const float factor_color3 = std::max(0.5f - interpolation_factor, 0.0f);

    MATH::FLOAT4 color;

    color.x = (color1.x * factor_color1 +
               color2.x * factor_color2 +
               color3.x * factor_color3) * 2.0f;

    color.y = (color1.y * factor_color1 +
               color2.y * factor_color2 +
               color3.y * factor_color3) * 2.0f;

    color.z = (color1.z * factor_color1 +
               color2.z * factor_color2 +
               color3.z * factor_color3) * 2.0f;

    color.w = 1.0f;

    return(color);
}

The interpolation_factor is assumed to be in the range of 0.0 ... 1.0.
The colors are assumed to be in the range of 0.0 ... 1.0 (e.g. for OpenGL).

C#

Here's the same function written in C#:

private readonly Color mColor1 = Color.FromArgb(255, 0, 255, 0);
private readonly Color mColor2 = Color.FromArgb(255, 255, 255, 0);
private readonly Color mColor3 = Color.FromArgb(255, 255, 0, 0);

private Color GetInterpolatedColor(double interpolationFactor)
{
    double interpolationFactor1 = Math.Max(interpolationFactor - 0.5, 0.0);
    double interpolationFactor2 = 0.5 - Math.Abs(0.5 - interpolationFactor);
    double interpolationFactor3 = Math.Max(0.5 - interpolationFactor, 0.0);

    return (Color.FromArgb(255,
                (byte)((mColor1.R * interpolationFactor1 +
                        mColor2.R * interpolationFactor2 +
                        mColor3.R * interpolationFactor3) * 2.0),

                (byte)((mColor1.G * interpolationFactor1 +
                        mColor2.G * interpolationFactor2 +
                        mColor3.G * interpolationFactor3) * 2.0),

                (byte)((mColor1.B * interpolationFactor1 +
                        mColor2.B * interpolationFactor2 +
                        mColor3.B * interpolationFactor3) * 2.0)));
}

The interpolationFactor is assumed to be in the range of 0.0 ... 1.0.
The colors are assumed to be in the range of 0 ... 255.

查看更多
不美不萌又怎样
6楼-- · 2020-01-25 12:37

You need to linearly interpolate (LERP) the color components. Here's how it's done in general, given a start value v0, an end value v1 and the required ratio (a normalized float between 0.0 and 1.0):

v = v0 + ratio * (v1 - v0)

This gives v0 when ratio is 0.0, v1 when ratio is 1.0, and everything between in the other cases.

You can do this either on the RGB components, or using some other color scheme, like HSV or HLS. The latter two will be more visually pleasing, since they work on hue and brightness compoments that map better to our color perception.

查看更多
Rolldiameter
7楼-- · 2020-01-25 12:38

This will vary from Red to Yellow and then to Green
value varies from 0 - 100

-(UIColor*) redToGreenColorWithPosition:(int) value {

    double R, G;
    if (value > 50) {
        R = (255 * (100 - value)/ 50) ;
        G = 255;
    }else {
        R = 255;
        G = (255 * (value*2)) / 100;
    }

    return [UIColor colorWithRed:R/255.0f green:G/255.0f blue:0.0f alpha:1.0f];
}
查看更多
登录 后发表回答