MULTIMEDIA

DirectX 10 : The 2D Resurgence - Sprite Animation

10/10/2012 7:27:38 PM
The preceding version of the sprite structure allowed for the display of the sprites on the screen, but sprites that don’t animate aren’t that exciting. The sprites are constantly displaying the same static image the whole time. Sprites are commonly animated using a technique called frame-based animation. Frame-based animation is equivalent to a movie reel, where the individual images or frames are displayed in rapid succession giving the appearance of movement. Sprite animation uses the same idea, quickly changing the image that the sprite displays to give the illusion of movement.

The first part of sprite animation is updating your sprites to support more than one image.

The Updated GameSprite Structure

Animating a sprite requires that the sprite support the ability to cycle through multiple frames; currently, the GameSprite structure supports only a single frame. Adding animation support is actually quite simple. The sprite needs to be able to track which image it is currently displaying, as well as know how many images it can cycle through.

The GameSprite structure needs to be updated by adding two new variables.

First, an integer called numFrames keeps track of the number of frames the sprite has available.

Second, an integer called curFrame is used to hold the current frame being displayed.

You can see an updated GameSprite structure next; the new variables are shown in bold.

// Sprite structure
typedef struct
{
     // sprite dimensions
     float width;
     float height;
     
     // sprite position
     float posX;
     float posY;
     // sprite movement
     float moveX;
     float moveY;
     
     BOOL visible;
     
     // animation information
     int curFrame;         // the current frame of animation
     int numFrames;        // the number of frames in this animation
} GameSprite;

Now that you have two new variables in the GameSprite structure, you need to set them to their default values when the sprites are initialized. In the following code sample, the current frame is set to 0 and the number of frames for the sprite is set to 4. In most sprite systems, the sprites will be able to handle more than a single series of animations; only a simple example is shown here.

// Loop through and init the active sprites
for (int curSprite = 0; curSprite < MAX_SPRITES; curSprite++)
{
    // Set the width and height of the sprite
    sprites[curSprite].width = 64;
    sprites[curSprite].height = 64;
    
    // Create and set a random x,y position
    sprites[curSprite].posX = (float)(rand()%600);
    sprites[curSprite].posY = (float)(rand()%450);
    
    // This sprite is visible
    sprites[curSprite].visible = TRUE;

    // Set up the animation information
    sprites[curSprite].curFrame = 0;
    sprites[curSprite].numFrames = 4;
}

Updating the Sprite’s Animation

When displaying the previous sprites, special image processing wasn’t necessary. Now that the sprites have multiple frames that need to be managed, an Update Sprites function is needed.

The UpdateSprites function handles the incrementing of the current frame of animation, as well as checking against the number of frames. If the current frame were constantly incremented without comparing against the number of frames, the sprite would quickly run out of images and cause an error in your application. When the current frame reaches the maximum number of frames, the current frame needs to be reset to 0 and the whole process starts over again. This causes the sprite’s animation to loop indefinitely.

The following UpdateSprites function loops through the sprites and updates their animations.

/*******************************************************************
* UpdateSprites
* Updates the sprite's animation information
* Inputs - none
* Outputs - void
*******************************************************************/
void UpdateSprites()
{
    // Loop through the sprites and update the animation info
    for (int i = 0; i < MAX_SPRITES; i++)
    {
        // only update visible sprites
        if (sprites[i].visible)
        {
            // increment the current frame
            sprites[i].curFrame++;
            
            // if the current frame is past the number of frames
            // reset to 0

            if (sprites[i].curFrame >= sprites[i].numFrames)
            {
                sprites[i].curFrame = 0;
            }
        }
    }
}

					  

The UpdateSprites function can be inserted into the main application loop right after the Render function.

// Main message loop
MSG msg = {0};
while (WM_QUIT != msg.message)
{
    // Process Windows messages first
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    
    // update and render the current frame
    UpdateScene();
    Render();
    
    // Update the sprites for the next frame
    UpdateSprites();
}

Displaying the Animated Sprites

At this point the sprites are animating within the GameSprite structure but will still be displayed using only a single image. To remedy this, the UpdateScene function will need to be changed. If you recall, the job of the UpdateScene function is to update the sprites in the sprite pool. Currently, those sprites are constantly pointing to the same frame in their source texture. The texture coordinates associated have to be updated based on the current frame of animation.

When animating sprites, it is common for the all the frames of an animation to appear in the same texture. The frames are laid out horizontally in the texture, as displayed in Figure 1.

Figure 1. Multiple frames for a sprite in a single texture.


When using this type of texture, the texture coordinates in the X direction reference the correct frame. The new X texture coordinate can be calculated in the UpdateScene function by dividing the current frame number by the number of frames in the animation. This will yield a value between 0 and 1.

Also, the texture size should be updated to reflect the current frame. Not all frames are the same size. The texture size is calculated by dividing the current frame width by the width of the whole texture. In the following example, the width of the texture is determined by multiplying the sprite width by the number of frames. This only works because all frames in the sample animation are the same size.

/*******************************************************************
* UpdateScene()
* Updates the scene with the current sprite information
* Inputs - void
* Outputs - void
*******************************************************************/
void UpdateScene()
{
    D3DXMATRIX matScaling;
    D3DXMATRIX matTranslation;
    
    int curPoolIndex = 0;
    
    // Loop through the sprites
    for (int i = 0; i < MAX_SPRITES; i++)
    {
        // only update visible sprites
        if (sprites[i].visible)
        {
           // set the proper scale for the sprite
           D3DXMatrixScaling(&matScaling, sprites[i].width, sprites[i].height,
           1.0f);

            // Move the sprite to spritePosX, spritePosY
            // SpriteWidth and SpriteHeight are divided by 2 to move the
            // translation point to the top-left sprite corner instead of
            // the center of the sprite.
            D3DXMatrixTranslation(&matTranslation,
               (float)sprites[i].posX + (sprites[i].width/2),
               (float)(windowHeight - sprites[i].posY - (sprites[i].height/2)),
               0.1f);
            
            // Update the sprite's position      and scale
            spritePool[curPoolIndex].matWorld = matScaling * matTranslation;
            
            // determine the texture coordinates for the current frame
            spritePool[curPoolIndex].TexCoord.x = (float)(sprites[i].curFrame /
            sprites[i].numFrames);
            
            spritePool[curPoolIndex].TexCoord.y = 0.0f;
            
            // Set the texture size for this frame
            spritePool[curPoolIndex].TexSize.x = (float)(sprites[i].width /
            (sprites[i].width * sprites[i].numFrames));
            
            // Increment the pool index
            curPoolIndex++;
        }
    }
    
    // set the number of active sprites
    numActiveSprites = curPoolIndex;
}	

Other  
 
Most View
Microsoft SharePoint 2010 Web Applications : Presentation Layer Overview - Ribbon (part 1)
The Cyber-athletic Revolution – E-sports’ Era (Part 1)
Windows Server 2003 : Implementing Software Restriction Policies (part 4) - Implementing Software Restriction Policies - Creating a Path Rule, Designating File Types
Sql Server 2012 : Hierarchical Data and the Relational Database - Populating the Hierarchy (part 1)
Two Is Better Than One - WD My Cloud Mirror
Programming ASP.NET 3.5 : Data Source-Based Data Binding (part 3) - List Controls
Windows 8 : Configuring networking (part 5) - Managing network settings - Understanding the dual TCP/IP stack in Windows 8, Configuring name resolution
Nikon Coolpix A – An Appealing Camera For Sharp Images (Part 2)
Canon PowerShot SX240 HS - A Powerful Perfection
LG Intuition Review - Skirts The Line Between Smartphone And Tablet (Part 2)
Popular Tags
Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8 BlackBerry Android Ipad Iphone iOS
Top 10
Review : Acer Aspire R13
Review : Microsoft Lumia 535
Review : Olympus OM-D E-M5 Mark II
TomTom Runner + MultiSport Cardio
Timex Ironman Run Trainer 2.0
Suunto Ambit3 Peak Sapphire HR
Polar M400
Garmin Forerunner 920XT
Sharepoint 2013 : Content Model and Managed Metadata - Publishing, Un-publishing, and Republishing
Sharepoint 2013 : Content Model and Managed Metadata - Content Type Hubs