14.04.2015, 17:58
(
Последний раз редактировалось hotspicytaco; 14.04.2015 в 20:14.
)
Disclaimer
This tutorial was originally written by ****** - I do not take credit for it.
Introduction
I've seen people get confused time and time again so I thought I would write a very quick tutorial on what colours actually are.
Colours are numbers - it's as simple as that. People often try to treat them as strings but they are not:
Right:
Right:
Wrong:
Wrong:
Because they are numbers you can store and compare them. And if you want to use them in CallRemoteFunction or SetTimerEx, you need to use "d" instead of "s".
Representation
Colours are usually represented in "hex" format (that's short for "hexadecimal", which means "base 16", as opposed to "decimal" which means "base 10"). I'm not going to go in to hex in depth, but you should know that they don't HAVE to be stored in this way:
Right:
Colours can be stored and manipulated in the same way as all other numbers:
You can even do maths, though it may not always make sense:
For example blue (0x0000FFAA) times 7 gives a very slightly bluey-green (0x0006FDA6), or times 256 gives an invisible turquoise (0x00FFAA00). Why is that invisible? Because there is no alpha, which will be explained shortly.
Storage
Cells in PAWN are 4 bytes, in colours each one of those bytes represent a different part of the colour - in order red, green, blue and alpha. As with RGB (red-green-blue) monitors, the first three parts determine the exact colour, the alpha is how transparent the thing will be. Note that this is not always used, for example the colours used in SendClientMessage from 0.3c on is just "RGB", not "RGBA". You can convert an "RGBA" colour to an "RGB" by right shifting by 8 (>>>8) - note THREE chevrons.
Pure Red (RGBA):
Pure Green (RGBA):
Pure Blue (RGBA):
Pure Cyan* (RGBA):
Pure Magenta* (RGBA):
Pure Yellow* (RGBA):
Pure Red (RGB):
Pure Green (RGB):
Pure Blue (RGB):
Pure Cyan* (RGB):
Pure Magenta* (RGB):
Pure Yellow* (RGB):
* Red-Green-Blue is known as a "colour space", based on the method used in eyes to detect light, another colour space commonly used in printers is the "Cyan-Magenta-Yellow" (often written "CMYK" where "K" is "Key", meaning black) space.
Comparing the first yellow (0xFFFF00AA) to the second (0xFFFFFF, also written as 0x00FFFFFF) should show how shifting converts them. Note that doing ">>8" instead of ">>>8" would result in "0xFFFFFF00" instead of "0x00FFFF00" because this is actually a negative number and ">>" preserves the sign of numbers. This is a very important result coming from the fact that COLOURS ARE NUMBERS - you may not think that colours can be negative, but any colour with a red value higher than "7F" will be negative (which will cause problems when trying to print it using "%x".
Printing Colours
There is a bug in printf when using "%x" with negative numbers (which colours are) so to properly format all colours do:
That will print two halves of the number next to each other correctly spaced and with a "0x" in front.
Making Colours:
As I said, these are just numbers, so you can construct them quickly and if you use this method the compiler will do it for you:
To create a new colour in this manner you need the values for each slot (RGB in order, with A on the third). These can be found from any graphics editor - even ms paint. To find the values in paint double click on a colour and then click "Define Custom Colours". In the bottom right of the window which appears will be the red, green and blue values for any colour selected in the large window. Ignore "Hue-Sat (Saturation)-Lum(Luminescence)", that's just a different representation of colours not used in SA:MP.
SendClientMessage (String Colour Embedding)
I mentioned above that embedding colours in SendClientMessage uses RGB format, rather than RGBA, furthermore, unlike everything stressed so far, this uses a STRING representation of the colour - NOT a number. Fortunately converting between formats (at least converting TO a string representation) is easy.
There are two start points - the first is that you have colours defined if the standard format (by that I mean defined as people have defined colours in SA:MP since version 0.1, making it a de-facto standard):
This is the format already explained in this post and is in RGBA format. The second option is that you define a whole new set of colours purely for use in SendClientMessage and other SA:MP strings which can have embedded colours:
In the first instance you will need to format your string to include the colour - fortunately this is very simple and already well documented:
There are two important aspects to this. The first is "{%06x}" - that is the exact format specifier required to add a numeric colour into a string. The colours are always 6 characters long, prefixed by zeros when shorter (which is what "06" means), are hexadecimal (which is what "%x" means) and are surrounded by "{}"s. The second part is the "COLOUR >>> 8" - that simply removes the alpha channel from the colour, changing the original RGBA representation to the required RGB representation.
Using the second instance is simpler if you know what they are to be used for from the start. If the original definition is:
Change it to:
This is exactly the same length as a string so no harder to write, but can be used in strings directly:
Alternatively to use this style in format you would use "%s" (as it is now a string):
y_colours
The y_colours library (aka y_colors) is a file recently included with YSI which adds thousands of different colour definitions for all the "X11" colours (list here). Each one available in both the spaced (using an underscore) and unspaced versions, for example "X11_NAVY_BLUE" and "X11_NAVYBLUE". It also includes a function to look up a colour by string name (case and space insensitive):
This tutorial was originally written by ****** - I do not take credit for it.
Introduction
I've seen people get confused time and time again so I thought I would write a very quick tutorial on what colours actually are.
Colours are numbers - it's as simple as that. People often try to treat them as strings but they are not:
Right:
Код:
new iColour = 0x00FF00AA; // Green
Код:
#define COLOUR_GREEN (0x00FF00AA) new iColour = COLOUR_GREEN;
Код:
new szColour[] = "GREEN";
Код:
new szColour[] = "0x00FF00AA"; // Green
Representation
Colours are usually represented in "hex" format (that's short for "hexadecimal", which means "base 16", as opposed to "decimal" which means "base 10"). I'm not going to go in to hex in depth, but you should know that they don't HAVE to be stored in this way:
Right:
Код:
new iColour = 16711850; // Green
Код:
#define COLOUR_BLUE (0x0000FFAA) new gPlayerColour[MAX_PLAYERS] = {COLOUR_BLUE, ...};
Код:
if (gPlayerColour[playerid] == COLOUR_BLUE) { // Do something. }
Код:
gPlayerColour[playerid] *= 7; // Meaningless but valid
Storage
Cells in PAWN are 4 bytes, in colours each one of those bytes represent a different part of the colour - in order red, green, blue and alpha. As with RGB (red-green-blue) monitors, the first three parts determine the exact colour, the alpha is how transparent the thing will be. Note that this is not always used, for example the colours used in SendClientMessage from 0.3c on is just "RGB", not "RGBA". You can convert an "RGBA" colour to an "RGB" by right shifting by 8 (>>>8) - note THREE chevrons.
Pure Red (RGBA):
Код:
#define COLOUR_RED (0xFF0000AA)
Код:
#define COLOUR_GREEN (0x00FF00AA )
Код:
#define COLOUR_BLUE (0x0000FFAA)
Код:
#define COLOUR_CYAN (0x00FFFFAA)
Код:
#define COLOUR_MAGENTA (0xFF00FFAA)
Код:
#define COLOUR_YELLOW (0xFFFF00AA)
Код:
#define COLOUR_RED (0xFF0000)
Код:
#define COLOUR_GREEN (0x00FF00)
Код:
#define COLOUR_BLUE (0x0000FF)
Код:
#define COLOUR_CYAN (0x00FFFF)
Код:
#define COLOUR_MAGENTA (0xFF00FF)
Код:
#define COLOUR_YELLOW (0xFFFF00)
Comparing the first yellow (0xFFFF00AA) to the second (0xFFFFFF, also written as 0x00FFFFFF) should show how shifting converts them. Note that doing ">>8" instead of ">>>8" would result in "0xFFFFFF00" instead of "0x00FFFF00" because this is actually a negative number and ">>" preserves the sign of numbers. This is a very important result coming from the fact that COLOURS ARE NUMBERS - you may not think that colours can be negative, but any colour with a red value higher than "7F" will be negative (which will cause problems when trying to print it using "%x".
Printing Colours
There is a bug in printf when using "%x" with negative numbers (which colours are) so to properly format all colours do:
Код:
printf("0x%04x%04x", colour >>> 16, colour & 0xFFFF);
Making Colours:
As I said, these are just numbers, so you can construct them quickly and if you use this method the compiler will do it for you:
Код:
#define MAKE_COLOUR(%0,%1,%2) ((((%0) & 0xFF) << 16) | (((%1) & 0xFF) << 8) | (((%2) & 0xFF) << 0)) #define MAKE_COLOUR_AA(%0,%1,%2) ((((%0) & 0xFF) << 24) | (((%1) & 0xFF) << 16) | (((%2) & 0xFF) << 8) | 0xAA) #define MAKE_COLOUR_ALPHA(%0,%1,%2,%3) ((((%0) & 0xFF) << 24) | (((%1) & 0xFF) << 16) | (((%2) & 0xFF) << 8) | (((%3) & 0xFF) << 0)) #define COLOUR_RED MAKE_COLOUR(255, 0, 0) #define COLOUR_GREEN MAKE_COLOUR(0, 255, 0) #define COLOUR_BLUE MAKE_COLOUR(0, 0, 255) #define COLOUR_CYAN_AA MAKE_COLOUR_AA(0, 255, 255) #define COLOUR_MAGENTA_AA MAKE_COLOUR_AA(255, 0, 255) #define COLOUR_YELLOW_AA MAKE_COLOUR_AA(255, 255, 0) #define BLACK_ALPHA MAKE_COLOUR_ALPHA(0, 0, 0, 170) // 170 == 0xAA #define WHITE_ALPHA MAKE_COLOUR_ALPHA(255, 255, 255, 255) #define INVISIBLE_BLACK (0)
SendClientMessage (String Colour Embedding)
I mentioned above that embedding colours in SendClientMessage uses RGB format, rather than RGBA, furthermore, unlike everything stressed so far, this uses a STRING representation of the colour - NOT a number. Fortunately converting between formats (at least converting TO a string representation) is easy.
There are two start points - the first is that you have colours defined if the standard format (by that I mean defined as people have defined colours in SA:MP since version 0.1, making it a de-facto standard):
Код:
#define COLOUR_RED (0xFF0000AA)
Код:
#define COLOUR_RED_EMBED (0xFF0000)
Код:
format(string, sizeof (string), "{%06x}Red {%06x}Green {%06x}Blue", COLOUR_RED >>> 8, COLOUR_GREEN >>> 8, COLOUR_BLUE >>> 8);
Using the second instance is simpler if you know what they are to be used for from the start. If the original definition is:
Код:
#define COLOUR_RED_EMBED (0xFF0000)
Код:
#define COLOUR_RED_EMBED "{FF0000}"
Код:
SendClientMessage(playerid, COLOUR_RED, "Red " COLOUR_GREEN_EMBED "Green " COLOUR_BLUE_EMBED "Blue");
Код:
format(string, sizeof (string), "%sRed %sGreen %sBlue", COLOUR_RED_EMBED, COLOUR_GREEN_EMBED, COLOUR_BLUE_EMBED);
The y_colours library (aka y_colors) is a file recently included with YSI which adds thousands of different colour definitions for all the "X11" colours (list here). Each one available in both the spaced (using an underscore) and unspaced versions, for example "X11_NAVY_BLUE" and "X11_NAVYBLUE". It also includes a function to look up a colour by string name (case and space insensitive):
Код:
new cyan = GetColour("cYan");