[Tutorial] Colours
#1

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:

Код:
new
	iColour = 0x00FF00AA; // Green
Right:

Код:
#define COLOUR_GREEN (0x00FF00AA)

new
	iColour = COLOUR_GREEN;
Wrong:

Код:
new
	szColour[] = "GREEN";
Wrong:

Код:
new
	szColour[] = "0x00FF00AA"; // Green
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:

Код:
new
	iColour = 16711850; // Green
Colours can be stored and manipulated in the same way as all other numbers:

Код:
#define COLOUR_BLUE (0x0000FFAA)


new
	gPlayerColour[MAX_PLAYERS] = {COLOUR_BLUE, ...};
Код:
if (gPlayerColour[playerid] == COLOUR_BLUE)
{
	// Do something.
}
You can even do maths, though it may not always make sense:

Код:
gPlayerColour[playerid] *= 7; // Meaningless but valid
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):

Код:
#define COLOUR_RED     (0xFF0000AA)
Pure Green (RGBA):

Код:
#define COLOUR_GREEN   (0x00FF00AA
)
Pure Blue (RGBA):

Код:
#define COLOUR_BLUE    (0x0000FFAA)
Pure Cyan* (RGBA):

Код:
#define COLOUR_CYAN    (0x00FFFFAA)
Pure Magenta* (RGBA):

Код:
#define COLOUR_MAGENTA (0xFF00FFAA)
Pure Yellow* (RGBA):

Код:
#define COLOUR_YELLOW  (0xFFFF00AA)
Pure Red (RGB):

Код:
#define COLOUR_RED     (0xFF0000)
Pure Green (RGB):

Код:
#define COLOUR_GREEN   (0x00FF00)
Pure Blue (RGB):

Код:
#define COLOUR_BLUE    (0x0000FF)
Pure Cyan* (RGB):

Код:
#define COLOUR_CYAN    (0x00FFFF)
Pure Magenta* (RGB):

Код:
#define COLOUR_MAGENTA (0xFF00FF)
Pure Yellow* (RGB):

Код:
#define COLOUR_YELLOW  (0xFFFF00)
* 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:

Код:
printf("0x%04x%04x", colour >>> 16, colour & 0xFFFF);
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:

Код:
#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)
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):

Код:
#define COLOUR_RED (0xFF0000AA)
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:

Код:
#define COLOUR_RED_EMBED (0xFF0000)
In the first instance you will need to format your string to include the colour - fortunately this is very simple and already well documented:

Код:
format(string, sizeof (string), "{%06x}Red {%06x}Green {%06x}Blue", COLOUR_RED >>> 8, COLOUR_GREEN >>> 8, COLOUR_BLUE >>> 8);
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:

Код:
#define COLOUR_RED_EMBED (0xFF0000)
Change it to:

Код:
#define COLOUR_RED_EMBED "{FF0000}"
This is exactly the same length as a string so no harder to write, but can be used in strings directly:

Код:
SendClientMessage(playerid, COLOUR_RED, "Red " COLOUR_GREEN_EMBED "Green " COLOUR_BLUE_EMBED "Blue");
Alternatively to use this style in format you would use "%s" (as it is now a string):

Код:
format(string, sizeof (string), "%sRed %sGreen %sBlue", COLOUR_RED_EMBED, COLOUR_GREEN_EMBED, COLOUR_BLUE_EMBED);
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):

Код:
new
	cyan = GetColour("cYan");
Reply
#2

no need to post twice becoz there is already a topic
Reply
#3

Sorry, I don't see it anywhere - the original one was deleted.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)