我知道你们都很忙,所以我要保持简短和重点。
我目前正在开发一款有趣的小游戏。游戏中有敌人。为简单起见,将它们视为彩色方块。我想最小化任何HUD,所以我决定通过它们的颜色平滑地显示生物的生命值 (绿色为健康,黄色为受损,红色为近乎死亡)。
然而,我真的很难想出一个将(int)hp值转换为RGB颜色的高效方法。映射到0-255的单个int根本不会成为问题 - 这是一个完全相同的示例函数:public int mapHpToGreyscale(int input) {
//input = current hp
double minHealth = 0;
double maxHealth = hpmax;
double minColValue = 0;
double maxColValue = 255;
int output = (int) ((input - minHealth) / (maxHealth - minHealth) * (maxColValue - minColValue) + minColValue);
return output;
}
有没有快速简便的方法来实现我想做的事情?我很感激任何意见。
答案 0 :(得分:5)
首先,我的回答是这个的改编版本:Calculate color values from green to red。我决定创建 JavaScript 解决方案的 Java 版本。代码,您可以直接插入代码而无需自己转移所有内容。
我们的想法是使用 HSL (hue, saturation, lightness)颜色空间而不是 RGB (红色,绿色,蓝色)。红色由色调值0°
表示,绿色由120°
表示,黄色介于60°
之间,其中<em>平滑过渡的色调:
我们会确定100%
的饱和度和50%
的亮度,但如果您愿意,可以使用这些值。
以下是在代码中使用它的方法:
// A value between 1.0 (green) to 0.0 (red)
double percentage = ...
// Get the color (120° is green, 0° is red)
Color color = transitionOfHueRange(percentage, 120, 0);
这就是结果范围:
这是transitionOfHueRange
方法。它接受percentage
和0.0
之间的1.0
值以及hue
和0
之间的360
范围:
public static Color transitionOfHueRange(double percentage, int startHue, int endHue) {
// From 'startHue' 'percentage'-many to 'endHue'
// Finally map from [0°, 360°] -> [0, 1.0] by dividing
double hue = ((percentage * (endHue - startHue)) + startHue) / 360;
double saturation = 1.0;
double lightness = 0.5;
// Get the color
return hslColorToRgb(hue, saturation, lightness);
}
这是hslColorToRgb
函数。它接受从0.0
到1.0
的 HSL 值:
public static Color hslColorToRgb(double hue, double saturation, double lightness) {
if (saturation == 0.0) {
// The color is achromatic (has no color)
// Thus use its lightness for a grey-scale color
int grey = percToColor(lightness);
return new Color(grey, grey, grey);
}
double q;
if (lightness < 0.5) {
q = lightness * (1 + saturation);
} else {
q = lightness + saturation - lightness * saturation;
}
double p = 2 * lightness - q;
double oneThird = 1.0 / 3;
double red = percToColor(hueToRgb(p, q, hue + oneThird));
double green = percToColor(hueToRgb(p, q, hue));
double blue = percToColor(hueToRgb(p, q, hue - oneThird));
return new Color(red, green, blue);
}
hueToRgb
方法:
public static double hueToRgb(double p, double q, double t) {
if (t < 0) {
t += 1;
}
if (t > 1) {
t -= 1;
}
if (t < 1.0 / 6) {
return p + (q - p) * 6 * t;
}
if (t < 1.0 / 2) {
return q;
}
if (t < 2.0 / 3) {
return p + (q - p) * (2.0 / 3 - t) * 6;
}
return p;
}
最后是小实用程序方法percToColor
:
public static int percToColor(double percentage) {
return Math.round(percentage * 255);
}
答案 1 :(得分:3)
此答案基于某人在评论中提到的Algorithm: How do I fade from Red to Green via Yellow using RGB values?的答案之一的算法。
请注意,此示例中未使用minHealth
和minColValue
,但实现起来应该不会太难。
import java.awt.Color;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class HealthColors {
static double minHealth = 0;// unused here
static double maxHealth = 100;
static double minColValue = 0;// unused here
static double maxColValue = 255;
public static void main(final String[] args) {
JFrame frame = new JFrame();
JPanel content = new JPanel();
content.setLayout(new GridLayout(10, 10, 2, 2));
for (int i = 0; i < maxHealth; i++) {
int value = (int) (Math.random() * maxHealth + 1);
JLabel label = new JLabel("" + value, SwingConstants.CENTER);
label.setOpaque(true);
label.setBackground(mapHpToColor(value));
content.add(label);
}
frame.setContentPane(content);
frame.pack();
frame.setVisible(true);
}
public static Color mapHpToColor(final int input) {
//input = current hp
double redValue = (input > maxHealth / 2 ? 1 - 2 * (input - maxHealth / 2) / maxHealth : 1.0) * maxColValue;
double greenValue = (input > maxHealth / 2 ? 1.0 : 2 * input / maxHealth) * maxColValue;
double blueValue = 0;
Color hpColor = new Color((int) redValue, (int) greenValue, (int) blueValue);
return hpColor;
}
}
答案 2 :(得分:2)
有没有快速简便的方法来实现我想要做的事情?
是的,有,你甚至可以重用你自己的代码,只是那些常量应该是参数:
public int mapHpToComponent(int input,
double minHealth, double maxHealth,
double minComponentValue, double maxComponentValue) {
int output = (int) ((input - minHealth) / (maxHealth - minHealth) *
(maxComponentValue - minComponentValue) + minComponentValue);
return output;
}
然后将其应用于调色板片段。有两个,一个从HP = 0 ... 50开始,G = 0 ... 255,然后第二个段是HP = 50 ... 100和R = 255 ... 0:
public int mapHpToColor(int input){
if(input<50){ // first segment
int R=255;
int G=mapHpToComponent(input,0,50,0,255);
int B=0;
return (R<<16)+(G<<8)+B;
} else {
int R=mapHpToComponent(input,50,100,255,0);
int G=255;
int B=0;
return (R<<16)+(G<<8)+B;
}
}
(是的,min / maxComponentValue可能更像是开始/结束,因为这就是它们的真实含义。)
答案 3 :(得分:1)
import java.lang.Math;
public class Color {
public int r;
public int g;
public int b;
public Color() {
r = 0;
g = 0;
b = 0;
}
};
public static Color hpToColor(float hp, float maxhp) {
Color color = new Color();
float alpha = hp / maxhp;
if (alpha <= 0.5) {
color.r = 255;
color.g = Math.round((alpha * 2) * 255);
color.b = 0;
} else {
color.r = Math.round(((1 - alpha) * 2) * 255);
color.g = 255;
color.b = 0;
}
return color;
}