2D Graphics Overview
Sprites are 2D bitmaps drawn directly on the screen, as opposed to being drawn in 3D space. Sprites are commonly used to display information such as health bars, number of lives, or text such as scores. Some games, especially older games, are composed entirely of sprites. This topic discusses sprites in detail, covering the following areas.
- Overview
- Sprite Origin
- Sprite Depth
- Sampling Textures
- Sprite Scaling
- Sprite Transformation Matrices
- Sprite Fonts
- Sprite Batching
- Render States
- Point Sprites
Overview
Sprites are positioned on the screen by coordinates. The width and height of the screen is the same as the back buffer. The x-axis represents the screen width and the y-axis represents the screen height. It is important to note that the y-axis is measured from the top of the screen and increases as you move down the screen, and the x-axis is measured from left to right. For example, when the graphics back buffer is 800×600, 0,0 is the upper left of the screen, and 800,600 is the lower right of the screen (see Figure 1).
Figure 1. A sprite's location in screen coordinates (x-axis 400, y-axis 200)
To draw a sprite, you must create a SpriteBatch object, initialize it by calling Begin, and then call Draw for each sprite. The bitmap information for a sprite is taken from a Texture2D object. The texture may contain alpha channel information to make part of the texture transparent or semi-transparent. You can tint, rotate, or scale sprites by using Draw. This method also gives you the option of drawing only part of the texture on-screen. After the sprites are drawn, call End before calling Present.
Sprite Origin
The most important concept when drawing sprites is the sprite origin. The origin is a specific point on the sprite, which is by default the upper-left corner of the sprite, or (0,0). Draw draws the origin of the sprite at the screen location you specify. For example, if you draw a 50×50 pixel sprite at location (400,200) without specifying an origin, the upper left of the sprite will be on pixel (400,200). If you use the center of the 50×50 sprite as the origin (25,25), to draw the sprite in the same position you must add the origin coordinates to the position. In this case, the position is (425,225) and the origin is (25,25), as shown in Figure 2.
Figure 2. The blue dot indicates the center coordinate of the sprite
When rotating a sprite, the method uses the origin as the center of the rotation. In these cases, it is common to use the center of the sprite as the origin when calculating where to draw the sprite on the screen.
Sprite Depth
Sprites also have a concept of depth. When drawing a sprite, you can specify a depth between 0 and 1 as a floating-point number. Sprites drawn at a depth of 0 are at the "front" of the screen, and will cover any sprites drawn at a lower depth. Sprites drawn at a depth of 1 are at the "back" of the screen, and will be covered by any sprites drawn at a depth less than 1.
Sampling Textures
A sprite is based on a Texture2D object—in other words, a bitmap. Draw can draw the entire texture, or a portion of the texture. To draw a portion of the texture, use the sourceRectangle parameter to specify which texels to draw as a sprite. A texel is a pixel in the texture. A 32×32 texture has 1024 texels, specified as x and y values similar to how screen coordinates are specified. Specifying a sourceRectangle of (0, 0, 16, 16) would select the upper-left quadrant of a 32×32 texture.
Sprite Scaling
Draw provides three methods of scaling sprites. Draw accepts either a uniform scaling parameter, a nonuniform scaling parameter, or a source and destination rectangle. The uniform scaling parameter is a floating-point number that multiplies the sprite size through both the x- and y-axes. This will shrink or expand the sprite along each axis equally, maintaining the original ratio between the sprite width and height.
To scale the x- and y-axes independently, Draw accepts a Vector2 value as a scalar. This Vector2 specifies nonuniform scaling: x- and y-axes are scaled independently according to the X and Y fields of the Vector2.
Draw also accepts a source and destination rectangle. The destination rectangle is specified in screen coordinates, while the source rectangle is specified in texels. Draw takes the pixels on the texture specified in sourceRectangle and scales them independently along the x- and y-axes until they fit the screen coordinates specified by destinationRectangle.
Sprite Transformation Matrices
XNA Game Studio Express 1.0 Refresh introduces a new feature for sprite batches - the ability to specify a transformation matrix that the batch can apply to each sprite before drawing. The transformation matrix can be any combination of translation, rotation, or scaling matrices multiplied together into a single matrix. This matrix is combined with the sprite position, rotation, scaling and depth parameters supplied to Draw. Because the matrix also applies to depth, any z-coordinate transformation that makes the sprite depth greater than 1.0 or less than 0.0 will cause the sprite to disappear.
See How to: Rotate a Group of Sprites for an example of matrix rotation, and How to: Scale Sprites Based On Screen Size for an example of matrix scaling.
Sprite Fonts
XNA Game Studio Express 1.0 Refresh introduces the ability to draw text using SpriteBatch. The DrawString method will draw text on screen, with position, color, rotation, origin, and scaling. DrawString also requires a special type of texture encapsulated by the SpriteFont class. A SpriteFont is created by the Content Pipeline when you add a Sprite Font file to your project. The Sprite Font file has information such as the name and point size of the font, and which Unicode characters to include in the SpriteFont texture. At run time, a SpriteFont is loaded with ContentManager.Load just like a Texture2D object.
See How to: Draw Text for an example of how to use SpriteFont to draw text, and Sprite Font XML Schema Reference for a list of Sprite Font tags. You can use the Content Pipeline to determine your character regions automatically. For more information, see How to: Extend the Font Description Processor to Support Additional Characters.
Sprite Batching
In normal drawing, the SpriteBatch object does not change any render states or draw any sprites until you call End. This is known as Deferred mode. In Deferred mode, SpriteBatch saves the information from each Draw call until you call End. When you then call End, SpriteBatch changes the graphics device settings and draws each sprite in the batch. End then resets the device settings, if you specified SaveStateMode.SaveState.
If you call Begin, specifying SpriteSortMode.Immediate, it triggers Immediate mode. In Immediate mode, the SpriteBatch immediately changes the graphics device render states to begin drawing sprites. Thereafter, each call to Draw immediately draws the sprite using the current device settings. Calling End resets the device settings, if you specified SaveStateMode.SaveState.
In Immediate mode, once you call Begin on one SpriteBatch instance, do not call it on any other SpriteBatch instance until you call End for the first SpriteBatch.
Deferred mode is slower than Immediate mode, but it allows multiple instances of SpriteBatch to accept Begin and Draw calls without interfering with each other.
Render States
The SpriteBatch object sets the following render states on the graphics card when drawing sprites.
Render State | Value |
---|---|
GraphicsDevice.RenderState.CullMode | CullMode.CullCounterClockwiseFace |
GraphicsDevice.RenderState.DepthBufferEnable | false |
GraphicsDevice.RenderState.AlphaBlendEnable | true |
GraphicsDevice.RenderState.AlphaBlendOperation | BlendFunction.Add |
GraphicsDevice.RenderState.SourceBlend | Blend.SourceAlpha |
GraphicsDevice.RenderState.DestinationBlend | Blend.InverseSourceAlpha |
GraphicsDevice.RenderState.SeparateAlphaBlendEnabled | false |
GraphicsDevice.RenderState.AlphaTestEnable | true |
GraphicsDevice.RenderState.AlphaFunction | CompareFunction.Greater |
GraphicsDevice.RenderState.ReferenceAlpha | 0 |
GraphicsDevice.SamplerStates[0].AddressU | TextureAddressMode.Clamp |
GraphicsDevice.SamplerStates[0].AddressV | TextureAddressMode.Clamp |
GraphicsDevice.SamplerStates[0].MagFilter | TextureFilter.Linear |
GraphicsDevice.SamplerStates[0].MinFilter | TextureFilter.Linear |
GraphicsDevice.SamplerStates[0].MipFilter | TextureFilter.Linear |
GraphicsDevice.SamplerStates[0].MipMapLevelOfDetailBias | 0.0f |
GraphicsDevice.SamplerStates[0].MaxMipLevel | 0 |
The most important settings changed are DepthBufferEnable (normally true), AlphaBlendEnable (normally false), and AlphaTestEnable (normally false). You may also want to set TextureAddressMode.Wrap for the AddressU and AddressV sampler states.
The SpriteBatch object also sets the Vertices, Indices, VertexDeclaration, VertexShader, and PixelShader properties on the current GraphicsDevice.
In Immediate mode, all of the render states can be changed before Draw is called, and Draw will use the new render states. How to: Apply a Pixel Shader to Sprites takes advantage of this to apply a custom pixel shader to Draw.
Point Sprites
Point sprites are sprites drawn in 3D space. These sprites are specified by a position and a size. When a point sprite is rendered, it always appears the same size on screen (no matter where the point lies in 3D space relative to the camera) and faces the camera. Point sprites are used to render particle systems. How to: Apply a Pixel Shader to Sprites gives an example of how to render point sprites using a simple pixel and vertex shader.
See Also
Tasks
How to: Draw a Sprite
How to: Draw Text
How to: Animate a Sprite
How to: Draw a Masked Sprite over a Background
How to: Make a Scrolling Background
How to: Rotate a Sprite
How to: Rotate a Group of Sprites
How to: Scale a Sprite
How to: Tint a Sprite
How to: Scale Sprites Based On Screen Size
How to: Draw Point Sprites
How to: Apply a Pixel Shader to Sprites