Search Tips Advanced Search |
| Delphi Graphics and Game Programming Exposed with DirectX 7.0 by John Ayres Wordware Publishing, Inc. ISBN: 1556226373 Pub Date: 12/01/99
Search this book:
Previous | Table of Contents | Next
Baseline Differences While the baseline application with mouse support was functional, we needed to make some minor modifications. Specifically, we want to show a mouse cursor during the idle state, but we want to suppress the display of the mouse cursor during any other state. Therefore, we ripped all of the mouse cursor display code out of the mouse input thread and added a variable to control mouse cursor display. If the mouse cursor is to be hidden, only the horizontal position of the mouse cursor is updated, and it is clipped according to the dimensions of the paddle graphic. #### Sound and Music Any game can be improved by using sound effects, and this game is certainly no different. We decided to use a few simple sounds to indicate when a ball hits a block, hits the side of the screen, hits the paddle, or falls off of the bottom and dies. There’s not much opportunity for sounds to overlap, so we could have used regular Windows multimedia function calls to output the sound. However, we went with DirectSound in case we wanted to expand the sound functionality at a later date. DirectSound programming is relatively easy anyway, and this architecture certainly would support advanced sound functionality if we needed it. We also wanted to have some music playing in the background, so the application uses MCI commands to continuously play a MIDI file while the application is active. We could have easily used DirectSound to stream a large WAV file to the sound card, which would have given us better sound quality, but this example shows how Windows multimedia functions and DirectSound can be used simultaneously. #### Graphics The graphical requirements for this application are not very stringent, and were thus very easy to implement. This is a 2-D sprite game that doesn’t feature very much animation, so all of the graphics easily fit into one file. We load this bitmap into an offscreen surface, letting DirectDraw determine its location; if there is enough video memory available, the surface will be located on the video card itself. Since we use nothing but simple blits, available hardware acceleration will dramatically improve the performance of the game. The game images are arranged in the single bitmap like so: Figure 13-2: Delphi Blocks game graphics The largest part of the graphic file is the background screen. The images for the block sprites are located below the background, including the image of the ball and paddle. We also see the button images as well as the cursor sprite image. Sprites This game features a large amount of sprites in the form of the blocks and the ball. We could easily extend the block grid to be larger or smaller, and the game is already set up to support more than one active ball. In order to encapsulate this functionality, we will use an object to manage all of the block sprites, and another object to manage all of the ball sprites. The block manager itself is pretty simplistic. It contains an array property that holds a 10×15 grid of TBlock objects, with each TBlock object representing one block sprite on the screen. The manager contains functions for initializing the entire block grid as well as drawing all of the blocks or deleting one specific block from the grid. This encapsulation allows us to deal with the large quantity of block sprites using one simple class. It is defined as:
      {defines the manager that will track all of the blocks}

      TBlockMgr = class

        {this static grid can be modified to increase or decrease the overall

         block area and size}

        BlockGrid: array[0..14, 0..9] of TBlock;

        NumBlocks: Integer;

        destructor Destroy; override;

        procedure Draw;

        procedure InitializeBlocks;

        procedure KillBlock(Row, Col: Integer);

      end;
The ball manager object is very similar in functionality and design. It contains a list object that tracks several TBall objects. This allows us to add any number of active balls to the screen and track them all simultaneously. Additional methods move and draw all of the active balls, clear the entire list of balls, or delete a specific ball sprite. It is defined as:
      {defines the manager that will track all of the ball sprites. note that

       this gives us the ability to add and track several active balls at once}

      TBallMgr = class

        BallList: TList;

        VelCoefficient: Integer;

        FTotalBalls: Integer;

        function GetActiveBalls: Integer;

        constructor Create;

        destructor Destroy; override;

        procedure AddBall(XPos, YPos, XVel, YVel: Real; DecBalls: Boolean);

        procedure KillBall(Idx: Integer);

        procedure MoveBalls;

        procedure DrawBalls;

        procedure Clear;

        property TotalBalls: Integer read FTotalBalls write FTotalBalls;

        property ActiveBalls: Integer read GetActiveBalls;

      end;
Collision Detection Collision detection really is the heart of this game. The entire idea is to make a ball collide with a block, and the balls must bounce off the walls and the paddle in a predictable manner. Bouncing off the walls is a relatively simple behavior to implement. We simply check the horizontal and vertical coordinates of a ball after it has been moved, and if it has collided with the sides or top of the screen, its horizontal or vertical velocity is reversed as appropriate. A collision with the bottom of the screen results in a lost ball. Collision with the paddle is a little more involved. To simplify matters, we use the bounding box collision detection technique covered in Chapter 6. To review, each ball has a bounding rectangle, as does the paddle. When these two rectangles intersect, a collision has occurred. The paddle is rectangular, and the ball is almost rectangular, so this collision detection technique is accurate enough for our purposes. However, we would like to give the user some control over the ball so he or she can influence its direction. Therefore, the angle of deflection that the ball takes is dependent on the position at which the ball collides with the paddle. Towards the center of the paddle, the ball tends to deflect at a 90-degree angle to the paddle itself, or straight upward. As the ball collides nearer and nearer to the edge of the paddle, the deflection angle becomes more and more acute, as the following illustration shows: Figure 13-3: Ball deflection angle Collisions with the blocks are where things get kind of hairy. We first perform a bounding box collision test to see if they collided. However, we need to know if the ball hit the top, sides, or bottom of the block in order to determine which velocity to reverse. Unfortunately, it is impossible to determine this from a simple bounding box collision, as illustrated below: Figure 13-4: Which side was hit—the top or the left? Therefore, we need a more accurate method of collision detection that can determine which side of the box was hit. This can be accomplished by using a general line segment intersection algorithm. The specific algorithm used in the example is covered on page 199 of Graphics Gems III by David Kirk. The algorithm was deduced by Franklin Antonio. The math behind this algorithm is complex, and although it is documented thoroughly in the example code, please consult Graphics Gems III for a detailed explanation of this algorithm.
Previous | Table of Contents | Next

Products | Contact Us | About Us | Privacy | Ad Info | Home Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.