Animating Your Sprites

Most applications that render 2D sprites will not simply render a static image continuously. The majority of times, they will render a series of consecutive images that form what appears to be animation. Since the basic principle of this rendering is the same as the static image written earlier, that code will be used as the starting point. Go ahead and make a copy of that code for this new application.

The major differences between this application and the last will be in the helper class being used to render the sprites. The initialization will be mostly the same, although the filename that the source code included with the CD uses has been changed to sprites.tga to emphasize the fact that there are multiple sprites stored in this one file.

First, since these will be small animated sprites flying around the screen, rather than the large static one, it makes more sense to have the position of these sprites initialized randomly. Update the constructor for the sprite class as follows:

 public GraphicsSprite() {     position = new Vector3(rnd.Next(Form1.ScreenWidth-SpriteSize),         rnd.Next(Form1.ScreenHeight-SpriteSize), 1);     xUpdate += (float)rnd.NextDouble();     yUpdate += (float)rnd.NextDouble();     column = rnd.Next(NumberSpritesCol);     row = rnd.Next(NumberSpritesRow);     if ((column % 3) == 0)         xUpdate *= -1;     if ((row % 2) == 0)         yUpdate *= -1; } 

The position of the sprite onscreen is determined by taking the width and height of the screen, subtracting the size of the sprite, and getting a random integer between zero and that value. However, the sprite size hasn't been defined yet. For the sprite that is stored on the included CD, the size of each frame of animation is 50x45. Define these constants now:

 private const int SpriteSizeWidth = 50; private const int SpriteSizeHeight = 45; 

Once the position has been determined, the velocity is set to a random value between zero and one. You could multiply this value by two to simulate "quicker" sprites if need be. The sprites in this example are formed by a series of 50x45 images, each located in the file sequentially. The file is composed of five of these sprites per column, and a total of six rows. Store this information using constants:

 private const int NumberSpritesRow = 6; private const int NumberSpritesCol = 5; 

You will also need to declare the variables that will be used to store the current animation frame:

 private int column = 0; private int row = 0; 

Since the code is randomly picking the position, it may as well randomly pick a starting point for the animation as well. Once that is done, you don't want every sprite to be moving in the same direction (at random speeds), so some of the sprites' initial velocity will be reversed.

Now that the constructor for your sprite class has been changed, the code should no longer compile. You will need to replace the end of the initialization where the sprites were added with this:

 // Add a few sprites for(int i = 0; i < 100; i++)     ar.Add(new GraphicsSprite()); 

This makes it much easier to add sprites to your application. Feel free to modify the number of sprites added at any time.

The update method will need to be modified next. Since you already know the size of each sprite, having the texture size as a parameter to this function is pointless. Also, you will need to update the animation frame being rendered anyway. Replace your method with the method found in Listing 16.4.

Listing 16.4 Updating Your Animated Sprites
 public void Update() {     // Update the current position     position.X += xUpdate;     position.Y += yUpdate;     // See if we've gone beyond the screen     if (position.X > (Form1.ScreenWidth - SpriteSizeWidth))     {         xUpdate *= -1;     }     if (position.Y > (Form1.ScreenHeight - SpriteSizeHeight))     {         yUpdate *= -1;     }     // See if we're too high or too the left     if (position.X < 0)     {         xUpdate *= -1;     }     if (position.Y < 0)     {         yUpdate *= -1;     }     // Now update the column     column++;     if (column >= NumberSpritesCol)     {         row++;         column = 0;     }     if (row >= NumberSpritesRow)     {         row = 0;     } } 

The beginning of this method is very similar to the last version, only it uses the sprite size instead of the passed-in texture size. However, at the end, the animation frame needs to be updated. Since the frame is stored simply as the column and row that should be rendered, the method simply increments the column. If you've reached the end of one column of sprites, move to the next row. If you've reached the end of the rows of sprites, move back to the beginning.

Again, with the method signature for the update code having been changed, the application will no longer compile. You can simply remove the parameter from your calls into update:

 foreach(GraphicsSprite gs in ar)     gs.Update(); 

The last thing that you should need to do for this application is to modify the Draw method and the call to this method. First, replace your Draw method with the following:

 public void Draw(Sprite sprite, Texture t) {     sprite.Draw(t, new Rectangle(column * SpriteSizeWidth, row * SpriteSizeHeight,         SpriteSizeWidth, SpriteSizeHeight), Center, position, Color.White); } 

As you can see here, the size has been removed from the parameter list. Instead, the source rectangle of the sprite is calculated using the animation frame data we have stored. Now you can update your OnPaint override to call this updated method:

 foreach(GraphicsSprite gs in ar)     gs.Draw(sprite, spriteTexture); 

Running the application now, you should see some animated sprites flying around your screen. See Figure 16.2.

Figure 16.2. Animated sprites.

graphics/16fig02.jpg



Managed DirectX 9 Graphics and Game Programming, Kick Start
Managed DirectX 9 Kick Start: Graphics and Game Programming
ISBN: B003D7JUW6
EAN: N/A
Year: 2002
Pages: 180
Authors: Tom Miller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net