To follow the same pattern that was used in the previous chapter, you should now make a copy of this code so that it can be updated to show some animated sprites.
The major changes will once again happen in the sprite class. The same constants that were used before can be used now: private const int NumberSpritesRow = 6; private const int NumberSpritesCol = 5; private const int SpriteSizeWidth = 50; private const int SpriteSizeHeight = 45; The source code included on the CD uses the file sprites.bmp for the sprites to be rendered, which is the same file used in the previous chapter, just with different dimensions and no alpha channel. You will need to store the animation frame as well, which is a combination of a row and column. Add those variables to your sprite class: private int column = 0; private int row = 0; Now, you will need to update the constructor, to randomly place the sprite somewhere on the screen, with a random animation frame: public GraphicsSprite() { xPosition = rnd.Next(Form1.ScreenWidth-SpriteSizeWidth); yPosition = rnd.Next(Form1.ScreenHeight-SpriteSizeHeight); 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 Draw method will also need updating: public void Draw(Surface backBuffer, Surface spriteSurface) { backBuffer.DrawFast(xPosition, yPosition, spriteSurface, new Rectangle(column * SpriteSizeWidth, row * SpriteSizeHeight, SpriteSizeWidth, SpriteSizeHeight), DrawFastFlags.DoNotWait | DrawFastFlags.SourceColorKey); } As you see, we calculate the source rectangle based on the animation frame and the sprite size. Once again, the sprite is drawn using the source color key transparency. Finally, you will need to make the Update method handle the animation as well. See Listing 17.3: Listing 17.3 Updating Your Animated Spritespublic void Update() { // Update the current position xPosition += (int)xUpdate; yPosition += (int)yUpdate; // See if we've gone beyond the screen if (xPosition > (Form1.ScreenWidth - SpriteSizeWidth)) { xUpdate *= -1; } if (yPosition > (Form1.ScreenHeight - SpriteSizeHeight)) { yUpdate *= -1; } // See if we're too high or too the left if (xPosition < 0) { xUpdate *= -1; } if (yPosition < 0) { yUpdate *= -1; } // Now update the column column++; if (column >= NumberSpritesCol) { row++; column = 0; } if (row >= NumberSpritesRow) { row = 0; } } With the sprite class finally updated, your main class should have a few compilation errors now. First, replace your sprite creation code: // Add a few sprites for(int i = 0; i < 100; i++) ar.Add(new GraphicsSprite()); The last two items that need updating are both in the rendering code, but are removing the size parameter that is passed into the sprite methods. You can replace this method with the following: protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) { DirectXException.IgnoreExceptions(); foreach(GraphicsSprite gs in ar) gs.Update(); backBuffer.ColorFill(0); foreach(GraphicsSprite gs in ar) gs.Draw(backBuffer, sprite); primary.Flip(backBuffer, FlipFlags.DoNotWait); this.Invalidate(); } As you can see, the differences between Direct3D and DirectDraw aren't as all-encompassing as some people seem to think. While it's true that porting a fully 3D application to DirectDraw is next to impossible, it would be relatively simple to port any 2D application from one to the other. |