Direct3D Sprites

A Sprite is the term used to describe a 2D graphics with a number of related functions. In the past hardware acceleration existed on consoles and old computers as sprites were the foundation for all 2D games. E.g. a sprite could be the player character, enemies, power ups etc.

A sprite is simply a 2D texture that can be positioned and rotated on the screen.

Creating a Sprite

D3DX provides a set of sprite functions that we can use to easily render 2D sprites to our screen. The sprite interfaces are just a mechanism for drawing a sprite, we still need to load a texture to represent what the sprite looks like and use that in our draw call - see below.

Note: to use the D3DX functions you must include the header d3dx9.h and link with d3dx9d.lib (in debug build) or d3dx9.lib (in release mode).

As usual we start by declaring a pointer and then we call a function that will create an instance of our sprite and set our pointer to point to that instance.

HRESULT D3DXCreateSprite(LPDIRECT3DDEVICE9 pDevice, LPD3DXSPRITE *ppSprite);

  • pDevice - our device pointer
  • ppSprite - the address of our sprite pointer

e.g.

LPD3DXSPRITE sprite=NULL;

If (SUCCEEDED(D3DXCreateSprite(device,&sprite))
{
     // created OK
}

As always remember to check the return result to make sure no error has occurred.

To render our sprite we must draw it in our render loop between the scene begin and end calls. To display the sprite we call the following three sprite interfaces:

sprite->Begin(...)
sprite->Draw(...)
sprite->End()

Drawing a sprite

Firstly we have to tell the sprite that we are about to start drawing. We can also set some flags at this stage. The interface is:

HRESULT Begin(DWORD flags)

flags - we can specify flags that determine how subsequent sprites will be rendered. A common flag here is to say that our sprites are going to be rendered with alpha blending available D3DXSPRITE_ALPHABLEND. There are other flags available, please check the DirectX help for a full list.

sprite->Begin(D3DXSPRITE_ALPHABLEND);

We can now go ahead and draw our sprite. The call is:

HRESULT Draw(LPDIRECT3DTEXTURE9 pSrcTexture, CONST RECT *pSrcRect, D3DXVECTOR3 *center, CONST D3DVECTOR3 *pTranslation,  D3DCOLOR Color );

  • pSrcTexture - a pointer to the texture to be used, see textures
  • pSrcRect - pointer to a rectangle defining the area of the texture to use or NULL for the whole texture
  • pCenter- pointer to a 3D vector specifying the position in the sprite around which it can be rotated or NULL for top left
  • pTranslation - pointer to a 3D vector defining the screen position of the sprite. Note: in Direct3D 0,0 is the top left of the screen.
  • Color - colour value that can be used to modulate the texture colours. A value of 0xFFFFFFFF maintains the colour from the texture. Note: you can use the D3DCOLOR_COLORVALUE macro to create a D3DCOLOR from RGB values.

So a simple example might be:

D3DXVECTOR3 pos;

pos.x=10.0f;
pos.y=20.0f;
pos.z=0.0f;

sprite->Begin(D3DXSPRITE_ALPHABLEND);
sprite->Draw(texture,NULL,NULL,&pos,0xFFFFFFFF);
sprite->End();

This will draw an alpha blended sprite at screen position 10,20. Remember to release the sprite before your application closes.

Note: if you are drawing many sprites it is best to still use just one sprite interface and do all your drawing between the begin and end calls. This allows Direct3D to speed up the rendering of multiple sprites

Advanced Notes

To scale or rotate our sprites we need to use a matrix. The sprite provides a call SetTransform that allows us to specify the matrix to use. There are a number of D3DX functions we can use to build a matrix, in the example below I use D3DXMatrixTransformation2D which takes a scale, rotation and position and fills a matrix to do the required 2D transformation. In this example I scale the sprite by 2 in each dimension and make it continuously rotate:

m_sprite->Begin(D3DXSPRITE_ALPHABLEND);

// Texture being used is 64 by 64:
D3DXVECTOR2 spriteCentre=D3DXVECTOR2(32.0f,32.0f);

// Screen position of the sprite
D3DXVECTOR2 trans=D3DXVECTOR2(50.0f,80.0f);

// Rotate based on the time passed
float rotation=timeGetTime()/500.0f;

// Build our matrix to rotate, scale and position our sprite
D3DXMATRIX mat;

D3DXVECTOR2 scaling(2.0f,2.0f);

// out, scaling centre, scaling rotation, scaling, rotation centre, rotation, translation
D3DXMatrixTransformation2D(&mat,NULL,0.0,&scaling,&spriteCentre,rotation,&trans);

// Tell the sprite about the matrix
m_sprite->SetTransform(&mat);

// Draw the sprite
m_sprite->Draw(m_texture,NULL,NULL,NULL,0xFFFFFFFF));

// Thats it
m_sprite->End();

Animation

To animate our sprites we load a texture which has our object defined in different states. We can then use the source RECT parameter when drawing our sprite to change which frame of animation will be displayed. For more details see the 2D game techniques section on animating sprites: 2D Animation

Further Reading

Read about how to drawn text to the screen here: Text. For some 2D game programming techniques take a look at the section here: 2D Techniques



© 2004-2016 Keith Ditchburn