package bwapi; import java.util.HashMap; import java.util.Map; import java.util.Objects; /** * The Color object is used in drawing routines to specify the color to use. *
* Starcraft uses a 256 color palette for rendering. Thus, the colors available are
* limited to this palette.
*/
public final class Color {
/**
* The default color for Player 1.
*/
public final static Color Red = new Color(111);
/**
* The default color for Player 2.
*/
public final static Color Blue = new Color(165);
/**
* The default color for Player 3.
*/
public final static Color Teal = new Color(159);
/**
* The default color for Player 4.
*/
public final static Color Purple = new Color(164);
/**
* The default color for Player 5.
*/
public final static Color Orange = new Color(156);
/**
* The default color for Player 6.
*/
public final static Color Brown = new Color(19);
/**
* A bright white. Note that this is lighter than Player 7's white.
*/
public final static Color White = new Color(255);
/**
* The default color for Player 8.
*/
public final static Color Yellow = new Color(135);
/**
* The alternate color for Player 7 on Ice tilesets.
*/
public final static Color Green = new Color(117);
/**
* The default color for Neutral (Player 12).
*/
public final static Color Cyan = new Color(128);
/**
* The color black.
*/
public final static Color Black = new Color(0);
/**
* The color grey.
*/
public final static Color Grey = new Color(74);
private static Map
* This function computes the distance of the RGB values and may not be accurate.
*
* @param red The amount of red.
* @param green The amount of green.
* @param blue The amount of blue.
*/
public Color(final int red, final int green, final int blue) {
id = getRGBIndex(red, green, blue);
}
/**
* A constructor that uses the color at the specified palette index.
*
* @param id The index of the color in the 256-color palette.
*/
public Color(final int id) {
// The id is set to 255 if the id is invalid, as in the official BWAPI sources:
// https://github.com/bwapi/bwapi/blob/3438abd8e0222f37934ba62b2130c3933b067678/bwapi/include/BWAPI/Color.h#L13
// https://github.com/bwapi/bwapi/blob/3438abd8e0222f37934ba62b2130c3933b067678/bwapi/include/BWAPI/Type.h#L66
this.id = id < 0 || id > 255 ? 255 : id;
}
private static int getBestIdFor(final int red, final int green, final int blue) {
int min_dist = 3 * 256 * 256;
int best_id = 0;
for (int id = 0; id < 255; ++id) {
final RGBQUAD p = defaultPalette[id];
if (p.rgbReserved != 0) {
continue;
}
final int r = red - (p.rgbRed & 0xFF);
final int g = green - (p.rgbGreen & 0xFF);
final int b = blue - (p.rgbBlue & 0xFF);
final int distance = r * r + g * g + b * b;
if (distance < min_dist) {
min_dist = distance;
best_id = id;
if (distance == 0) {
break;
}
}
}
return best_id;
}
private static int getRGBIndex(final int red, final int green, final int blue) {
if (closestColor == null) {
closestColor = new byte[64][64][64];
for (int r = 0; r < 64; ++r) {
for (int g = 0; g < 64; ++g) {
for (int b = 0; b < 64; ++b) {
closestColor[r][g][b] = (byte) getBestIdFor(r << 2, g << 2, b << 2);
}
}
}
}
return closestColor[red >> 2][green >> 2][blue >> 2] & 0xFF;
}
public int red() {
return defaultPalette[id].rgbRed & 0xFF;
}
public int green() {
return defaultPalette[id].rgbGreen & 0xFF;
}
public int blue() {
return defaultPalette[id].rgbBlue & 0xFF;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Color color = (Color) o;
return id == color.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
@Override
public String toString() {
String defaultColor = getDefaultColor(id);
if (defaultColor != null) {
return "Color." + defaultColor;
}
return "Color{" +
"red=" + red() +
", green=" + green() +
", blue=" + blue() + "}";
}
/// BROODWAR COLOR IMPLEMENTATION
private static class RGBQUAD {
final byte rgbRed;
final byte rgbGreen;
final byte rgbBlue;
final byte rgbReserved;
RGBQUAD(int rgbRed, int rgbGreen, int rgbBlue) {
this(rgbRed, rgbGreen, rgbBlue, 0);
}
RGBQUAD(int rgbRed, int rgbGreen, int rgbBlue, int rgbReserved) {
this.rgbRed = (byte)rgbRed;
this.rgbGreen = (byte) rgbGreen;
this.rgbBlue = (byte)rgbBlue;
this.rgbReserved = (byte)rgbReserved;
}
}
private static String getDefaultColor(final int id) {
if (defaultColors == null) {
defaultColors = new HashMap<>();
defaultColors.put(Color.Red.id, "Red");
defaultColors.put(Color.Blue.id, "Blue");
defaultColors.put(Color.Teal.id, "Teal");
defaultColors.put(Color.Purple.id, "Purple");
defaultColors.put(Color.Orange.id, "Orange");
defaultColors.put(Color.Brown.id, "Brown");
defaultColors.put(Color.White.id, "White");
defaultColors.put(Color.Yellow.id, "Yellow");
defaultColors.put(Color.Green.id, "Green");
defaultColors.put(Color.Cyan.id, "Cyan");
defaultColors.put(Color.Black.id, "Black");
defaultColors.put(Color.Grey.id, "Grey");
}
return defaultColors.getOrDefault(id,null);
}
}