How do you use sprite functions from sprites.h with grayscale?

Previous Graphics and Display Next

Q: I would like to know if it is possible to use the sprite functions in sprites.h with grayscale. I have tried using the Sprite16 function with grayscale, and none of the sprites I intended to be in grayscale appeared. I tried to use DrawIcon and the grayscale worked just fine. But DrawIcon is too slow... Can Sprite16 and Sprite32 handle grayscale sprites.
A: Very common question in a recent time. See, you probably tried to use GraySetAMSPlane. Sprite16 have a parameter for drawing plane, so it is not sensitive to GraySetAMSPlane: you need to give the plane as an explicite parameter. In fact, you need to have two different sprite planes and to draw a sprite twice, passing two different planes as a parameter. For example,
static unsigned short light_definition [] = {...};
static unsigned short dark_definition [] = {...};
...
Sprite16 (x, y, height, light_definition, GrayGetPlane (LIGHT_PLANE), A_XOR);
Sprite16 (x, y, height, dark_definition, GrayGetPlane (DARK_PLANE), A_XOR);
In other words, sprite routines can handle grayscale sprites, but not natively, meaning you have to take your grayscale sprite, split it into two layers, and draw each one separately on its own plane - the routine does not handle these by itself. As suggested by Scott Noveck, it is possible to make a function of your own to handle this. Assume that your grayscale sprites follow the "standard" format seen in the most of ASM games, with the dark plane data followed immediately by the light plane data. This routine will call Sprite16 twice - once for each plane:
void GraySprite16 (short x, short y, short h, unsigned short *spr, short mode)
{
  Sprite16 (x, y, h, *spr, GetPlane (LIGHT_PLANE), mode);
  Sprite16 (x, y, h, *spr + h, GetPlane (DARK_PLANE), mode);
}
Don't be afraid about calling GrayGetPlane each time: it is not a waste of time. Its implementation is smart: when the input is a constant, it will simply evaluate to a memory address that contains the pointer; when it is variable, it expands to a simple macro.