Building the Fore Program Example


Although the Sprite class is certainly an engineering marvel, only so much gratification can be gained from staring at its code. For this reason, it's important to put together a demonstration program to put the Sprite class through its paces. Because I've been obsessed lately with improving my golf game, I thought a golf program example might be fitting as a means of demonstrating how to create and use sprites . If you've ever had to yell "Fore!" you understand that it is a phrase used to inform someone that you've shanked a golf ball in his general direction. The Fore program example uses a woodsy backdrop and several sprite golf balls to get your feet wet with sprite animation.

The idea behind the Fore program is to create several sprite golf balls and let them zing around the game screen. Because it's not terribly important to factor in real-world physics, I opted to use the golf balls to demonstrate the three bounds actions supported by the Sprite class: Wrap, Bounce, and Stop. So, the program creates three golf balls with each of these bounds actions and then turns them loose on the game screen to see how they react . To make things a little more interesting, you can use the mouse to grab and drag any of the balls around the screen. Let's get started with the code because you're no doubt itching to see this program in action.

Writing the Program Code

As you know by now, every Windows program has a header file that includes other important header files, as well as declares global variables used by the program. Listing 10.5 contains the code for the Fore.h header file.

Listing 10.5 The Fore.h Header File Imports Several Header Files and Declares Global Variables Required for the Golf Ball Sprites
 1: #pragma once  2:  3: //-----------------------------------------------------------------  4: // Include Files  5: //-----------------------------------------------------------------  6: #include <windows.h>  7: #include "Resource.h"  8: #include "GameEngine.h"  9: #include "Bitmap.h" 10: #include "Sprite.h" 11: 12: //----------------------------------------------------------------- 13: // Global Variables 14: //----------------------------------------------------------------- 15: HINSTANCE   _hInstance; 16: GameEngine* _pGame; 17: Bitmap*     _pForestBitmap; 18: Bitmap*     _pGolfBallBitmap; 19: Sprite*     _pGolfBallSprite[3]; 20: BOOL        _bDragging; 21: int         _iDragBall; 

A quick look at this code reveals two bitmaps ”one for the forest background (line 17) and another for the golf balls (line 18). Each ball sprite uses the same bitmap. The golf ball sprites are stored in an array to make it a little easier to access them (line 19). The last two member variables are used to allow you to drag a golf ball around with the mouse. The bDragging variable determines whether a ball is currently being dragged (line 20). If a ball is indeed being dragged, the iDragBall variable keeps track of which ball it is (line 21); this variable is actually an index into the _pGolfBallSprite array.

With the global variables for the Fore program in mind, you can now press on and examine the specific game functions for the program. The GameInitialize() function is virtually identical to the version of it that you've seen in other examples. The only point to make is that it sets the frame rate to 30 frames per second, which is relatively standard for the programs that use sprite animation throughout the book.

The GameStart() and GameEnd() functions are where the interesting things start taking place in the Fore program, as shown in Listing 10.6.

Listing 10.6 The GameStart() Function Creates and Loads the Bitmaps and Sprites, While the GameEnd() Function Cleans Them Up
 1: void GameStart(HWND hWindow)  2: {  3:   // Seed the random number generator  4:   srand(GetTickCount());  5:  6:   // Create and load the bitmaps  7:   HDC hDC = GetDC(hWindow);  8:   _pForestBitmap = new Bitmap(hDC, IDB_FOREST, _hInstance);  9:   _pGolfBallBitmap = new Bitmap(hDC, IDB_GOLFBALL, _hInstance); 10: 11:   // Create the golf ball sprites 12:   RECT rcBounds = { 0, 0, 600, 400 }; 13:   _pGolfBallSprite[0] = new Sprite(_pGolfBallBitmap, rcBounds); 14:   _pGolfBallSprite[1] = new Sprite(_pGolfBallBitmap, rcBounds, BA_WRAP); 15:   _pGolfBallSprite[2] = new Sprite(_pGolfBallBitmap, rcBounds, BA_BOUNCE); 16:   _pGolfBallSprite[0]->SetVelocity(2, 1); 17:   _pGolfBallSprite[1]->SetVelocity(3, -2); 18:   _pGolfBallSprite[2]->SetVelocity(7, 4); 19: 20:   // Set the initial drag info 21:   _bDragging = FALSE; 22:   _iDragBall = -1; 23: } 24: 25: void GameEnd() 26: { 27:   // Cleanup the bitmaps 28:   delete _pForestBitmap; 29:   delete _pGolfBallBitmap; 30: 31:   // Cleanup the sprites 32:   for (int i = 0; i < 3; i++) 33:     delete _pGolfBallSprite[i]; 34: 35:   // Cleanup the game engine 36:   delete _pGame; 37: } 

The GameStart() function does several important things, beginning with the loading of the forest and golf ball bitmaps (lines 8 and 9). A bounding rectangle for the game screen is then created (line 12), which is important because it serves as the bounding rectangle for all the golf ball sprites. The three golf ball sprites are then created and stored in the _pGolfBallSprite array (lines 13 “15), and their velocities are set to differing values (lines 16 “18). The function ends by initializing the global variables that keep track of a sprite being dragged with the mouse (lines 21 and 22). The GameEnd() function simply cleans up the bitmaps and sprites, as well as the game engine itself (lines 25 “37).

The GamePaint() function is next on the agenda, and you might be surprised by its simplicity (Listing 10.7).

Listing 10.7 The GamePaint() Function Draws the Forest Background and the Golf Ball Sprites
 1: void GamePaint(HDC hDC)  2: {  3:   // Draw the background forest  4:   _pForestBitmap->Draw(hDC, 0, 0);  5:  6:   // Draw the golf ball sprites  7:   for (int i = 0; i < 3; i++)  8:     _pGolfBallSprite[i]->Draw(hDC);  9: } 

The GamePaint() function simply draws the forest bitmap (line 4) followed by the three golf ball sprites (lines 7 and 8). The Draw() method in the Sprite class makes drawing the sprites painfully easy (line 8).

Of course, the GamePaint() method alone wouldn't be too helpful in animating the golf ball sprites if the game, screen wasn't told to repaint itself periodically. This is accomplished in the GameCycle() function which also updates the sprites (Listing 10.8).

Listing 10.8 The GameCycle() Function Updates the Golf Ball Sprites and Then Repaints the Game Screen
 1: void GameCycle()  2: {  3:   // Update the golf ball sprites  4:   for (int i = 0; i < 3; i++)  5:     _pGolfBallSprite[i]->Update();  6:  7:   // Force a repaint to redraw the golf balls  8:   InvalidateRect(_pGame->GetWindow(), NULL, FALSE);  9: } 

This function begins by updating the golf ball sprites, which simply involves calling the Update() method on each sprite (lines 4 and 5). After updating the sprites, the game screen is invalidated so that it gets repainted to show the new sprite positions (line 8). If you didn't invalidate the game screen, the GamePaint() method wouldn't get called and you wouldn't see any changes on the screen even though the sprites are being moved behind the scenes. In other words, in addition to changing the position of sprites, you must also make sure that they get repainted so that the changes are visualized.

I mentioned earlier in the hour that the Fore program allows you to click a golf ball sprite with the mouse and drag it around. This functionality is established in the MouseButtonDown() , MouseButtonUp() , and MouseMove() functions, which are shown in Listing 10.9.

Listing 10.9 The MouseButtonDown() , MouseButtonUp() , and MouseMove() Functions Use the Left Mouse Button to Allow You to Click and Drag a Golf Ball Sprite Around on the Game Screen
 1: void MouseButtonDown(int x, int y, BOOL bLeft)  2: {  3:   // See if a ball was clicked with the left mouse button  4:   if (bLeft && !_bDragging)  5:   {  6:     for (int i = 0; i < 3; i++)  7:       if (_pGolfBallSprite[i]->IsPointInside(x, y))  8:       {  9:         // Capture the mouse 10:         SetCapture(_pGame->GetWindow()); 11: 12:         // Set the drag state and the drag ball 13:         _bDragging = TRUE; 14:         _iDragBall = i; 15: 16:         // Simulate a mouse move to get started 17:         MouseMove(x, y); 18: 19:         // Don't check for more balls 20:         break; 21:       } 22:   } 23: } 24: 25: void MouseButtonUp(int x, int y, BOOL bLeft) 26: { 27:   // Release the mouse 28:   ReleaseCapture(); 29: 30:   // Stop dragging 31:   _bDragging = FALSE; 32: } 33: 34: void MouseMove(int x, int y) 35: { 36:   if (_bDragging) 37:   { 38:     // Move the sprite to the mouse cursor position 39:     _pGolfBallSprite[_iDragBall]->SetPosition( 40:       x - (_pGolfBallBitmap->GetWidth() / 2), 41:       y - (_pGolfBallBitmap->GetHeight() / 2)); 42: 43:     // Force a repaint to redraw the golf balls 44:     InvalidateRect(_pGame->GetWindow(), NULL, FALSE); 45:   } 46: } 

The MouseButtonDown() function starts the drag process by first checking to see if the left mouse button is being pressed, while making sure that a drag isn't somehow already in progress (line 4). The next check is to see if the mouse click actually occurred within a sprite. This involves looping through the sprites and seeing if the mouse coordinates lie within a sprite (lines 6 and 7). If so, the mouse is captured so that its input is routed to the Fore program even if it strays outside the game window (line 10). The drag state and ball being dragged are then stored away because the other mouse functions need to know about them (lines 13 and 14). The MouseMove() function is then called to simulate a mouse move so that the sprite is centered on the mouse cursor position (line 17). Finally, the sprite loop is broken out of because you don't want to check for more balls when one has been clicked with the mouse (line 20).

The MouseButtonUp() function ends a sprite drag by releasing the mouse capture (line 28), and then clearing the _bDragging global variable (line 31). This is sufficient to stop the sprite drag, while also allowing the user to initiate another drag by clicking a sprite and starting the process over.

The last of the mouse functions is MouseMove() , which moves a golf ball sprite so that it follows the location of the mouse cursor. The _bDragging global variable is first checked to make sure that a drag is taking place (line 36). If so, the position of the appropriate golf ball sprite is set to correspond to the position of the mouse cursor (lines 39 “41). The program window is then invalidated so that the game screen is repainted (line 44), which is necessary so that the sprite is redrawn in the new position.

Testing the Finished Product

Although it isn't a game, the Fore program example is a quite interesting sample program in the sense that it demonstrates how powerful and straightforward sprite animation can be. After the Sprite class was created, it only took a few lines of code to create a few sprites and get them moving around the game screen. Figure 10.1 shows the golf ball sprites flying around on the forest background in the Fore program example.

Figure 10.1. The golf ball sprites in the Fore program move around thanks to the handy Sprite class that you created in this hour.

graphics/10fig01.gif

If you watch the sprites carefully , you'll notice that each of them responds differently when encountering the edge of the game screen, which happens to serve as their bounding rectangle. One of the balls will wrap around to the other side of the screen, another will bounce off the side of the screen like a game of Pong, whereas the last ball stops at the edge of the screen. The really neat thing about the program is that you can click and drag any of the balls on the screen, including the ones that are moving.

Granted, clicking and dragging a golf ball isn't exactly my idea of an exciting "game," but it does provide a good demonstration of the new Sprite class that you've now added to your game development toolkit.



Sams Teach Yourself Game Programming in 24 Hours
Sams Teach Yourself Game Programming in 24 Hours
ISBN: 067232461X
EAN: 2147483647
Year: 2002
Pages: 271

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