This series of tutorials covers a number of Half-Life graphics topics. This first one covers printing 2D sprites on the screen. These functions are used in the SDK e.g. for displaying the weapons list, ammo, health indicators etc.
2D Sprites are 2D images, and are drawn directly on the screen. Dont confuse this with "3d sprites", which are drawn at a position in the world, and specified at a 3d location (in which case the engine calculates the correct position on the screen). The effect of drawing a 2D sprite is just to add a flat image to the players screen. No matter what direction the player looks, the image will still appear at the same place on the screen. All 2D sprite drawing is done from client.dll.
The process of drawing a 2D sprite on the screen is:
The following code will load a sprite and display it at a coordinate on the screen.
HSPRITE m_hRadarSpr;
// Declare the
variable as a HSPRITE type (int)
m_hRadarSpr = LoadSprite("sprites/radar1.spr"); // Load
the sprite into memory from disk
SPR_Set( m_hRadarSpr, 255, 255, 255);
// Set the sprite ready to display when SPR_Draw* is called
SPR_DrawHoles( 0, x, y, NULL);
// Draw the current "SPR_Set" sprite at position x,y on
the screen
LoadSprite() calls SPR_Load() to load the sprite into memory. It returns a HSPRITE, which is an integer index into the global sprite array. This is the LoadSprite() sourcecode in util.cpp:
HSPRITE LoadSprite(const char *pszName)
{
// Declare variables
int i;
char sz[256];
if (ScreenWidth < 640)
i = 320;
else
i = 640;
sprintf(sz, pszName, i);
return SPR_Load(sz); // Do the actual loading of the
sprite into memory
}
SPR_Set() sets the selected sprite ready for display. It takes r/g/b parameters for shading the sprites (you can use this to make the sprites lighter/darker).
All the SPR_Draw() functions take the same parameters, but they have slightly different behaviour. The last parameter is a wrect_t which defines the area of the sprite to be displayed. This is used for small sprites, where it is more memory efficient to pack multiple sprites together in a single sprite. If you leave it as NULL, the whole sprite is used.
This is a fast way to draw rectangular opaque sprites. In practise, it's never used, since most sprites are non-rectangular.
This draws translucent sprites on the screen. Any black pixels on the sprite will be completely transparent.
This draws sprites with and pixels that use the 255th pallete colour treated as completely transparent.
Most of the code in the client.dll doesnt do its own LoadSprite() call. Instead, it gets it's sprites from the HUD.TXT file. The CHud class has a number of methods for reading and cacheing all the sprites from this file, and we can use the global gHUD object to access them:
This is called on startup, opens the hud.txt file, and loads all the sprites into memory. You shouldnt need to change anything in this code - providing you add your new sprite to hud.txt, it should just get picked up with all the others.
void CHud :: VidInit( void )
{
...
// we need to load the hud.txt, and all sprites
within.
// This just reads a list of all the sprite definitions. It doesnt load the
sprites into memory.
m_pSpriteList = SPR_GetList("sprites/hud.txt",
&m_iSpriteCountAllRes);
...
// Then, for
each sprite, call SPR_Load to load it into memory.
char sz[256];
sprintf(sz, "sprites/%s.spr", p->szSprite);
m_rghSprites[index] = SPR_Load(sz); // Our old friend
...
}
Returns the CHud sprite index for the relevant sprite.
e.g. m_HUD_number_0 = gHUD.GetSpriteIndex( "number_0" );
Translates the CHud sprite index into the global HSPRITE for the relevant sprite.
e.g. HSPRITE hsprNumber0 = gHUD.GetSprite(m_HUD_number_0);
This gets the displayable area for the relevant sprite.
e.g. wrect_t recNumber0 = gHUD.GetSpriteRect(m_HUD_number_0);
So, to display the sprite from the basic code at the top of the tutorial sprite, we do:
int m_hRadarSpr;
// This is the
integer index of the sprite in gHud
m_hRadarSpr = gHUD.GetSpriteIndex( "radar1");
// Get the sprite index from gHud
SPR_Set( gHud.GetSprite( m_hRadarSpr ), 255, 255, 255);
// Set the sprite ready to display when SPR_Draw* is
called
SPR_DrawHoles( 0, x, y, &gHUD.GetSpriteRect(m_hRadarSpr);
// Draw the current "SPR_Set" sprite at position x,y on
the screen
In the next tutorial we'll cover the EFX API, including 3D sprites, beam entities etc.
steve