• No results found

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

The Game Loop

As mentioned above, the actual game loop is usually the focal point of a game application. The game loop is where all of the action takes place. It processes a series of instructions over and over as quickly as possible to produce the on- screen images that reflect the current state of the game. This processing continues with or without user interaction, and is precisely the method by which the real-time event-driven model discussed previously is implemented.

Technically speaking, a game loop is responsible for three things: retrieving input, updating game objects, and rendering a new frame of animation. Of course, there’s a lot more to a game loop than this oversimplified description suggests. What actually occurs in a game loop is very arbitrary and will depend on the needs of the individual game. However, all games perform similar tasks, usually in a similar order. Expanding upon the three tasks listed above, Figure 2-2 illustrates an example game loop that might be found in a simple action arcade game.

Figure 2-2: A simplistic game loop

There are several different techniques by which this game loop architecture could be implemented. In the examples in this book, we will be implementing the primary game loop inside the Application.OnIdle event.

Title

---This technique is used for several reasons. First, the main game loop will automatically be entered whenever the application becomes idle (after initializing everything in the OnCreate or OnActivate form event handlers or the initialization section of the unit). Second, the application object controls when the OnIdle event is called, meaning that any standard Windows events will be processed and the application never needs to call Application.ProcessMessages. Third, it’s simply an easy, Delphi-centric technique for implementing the game loop that should be easy to understand and reproduce.

Alternatively, a while..do or repeat..until loop could be used to implement the game loop. The advantages of this technique are that the developer will have more control over the application, and it will run a little faster than the OnIdle technique. The application could even exit the game loop for some reason, perhaps to display a simple options screen that didn’t need the complex animation capabilities afforded by the game loop. The disadvantages to this method of game loop implementation are that these types of loops are generally a little harder to work with when trying to support general Windows events. Application.ProcessMessages must certainly be called at some point within the loop so that standard Windows messages can be handled. Also, the variable controlling the loop’s execution must be set so that the loop can exit before the application can terminate; simply calling Close or Application.Terminate will not work. Using this technique can result in little issues such as these that interfere with the normal operation of a Windows application. They can usually be handled with minor workarounds, however, so using a loop such as this may be advantageous depending on the type of game being produced. The following listing demonstrates an implementation of the arbitrary game loop using a while..do loop.

Listing 2-1: Arbitrary game loop example

procedure GameLoop;

var

TimeStart: Longint; // used to time the length of one loop iteration begin

{this while..do loop will continue processing the same commands in rapid succession until instructed to exit from the loop}

while GameRunning do begin

{record the current time upon starting the loop}

TimeStart := GetCurrentTime;

{retrieve input from the user by accessing whichever input device the user has chosen}

RetrieveInput;

{perform any enemy artificial intelligence and other logic associated with game elements not controlled by the user}

PerformEnemyAI;

{iterate through all sprites, updating their positions accordingly, taking into account user input and enemy AI calculations}

UpdateSpritePositions;

{check for any collisions between objects that would result in a change in the current game state, such as missiles colliding with a target or the player’s sprite impacting a wall or other object}

CheckForCollisions;

{start any sound effects needed, based on collision detection or other game states}

StartSounds;

{start any music needed, again based on collision detection or other game states}

StartMusic;

{all processing has been completed, so draw the current state of the game to the screen}

DrawFrame;

{determine if the game is still running, based on whether the player has died or some other deciding threshold has been reached}

GameRunning := IsGameOver;

{determine how long this cycle has taken; if it has been too short, pause for the difference so that the game does not run too fast}

If GetCurrentTime-TimeStart<TimingValue then Pause(GetCurrentTime-TimeStart);

{process any Windows messages that are waiting}

Application.ProcessMessages;

end; // repeat this process over and over until the game has ended end;

As a matter of practice, several of these tasks may be combined or performed simultaneously. For example, since an application must iterate through every game object to update its position, it would be practical to draw each object as its position is updated. Also, collisions usually result in an object being destroyed or its course being altered, so appropriate sound effects could be started at the time of the collision detection. The point is that these steps represent an arbitrary game loop, and may be rearranged or combined (or even split apart) as the individual circumstances warrant.

Even with this expanded view of a game loop implementation, many of the details attended to within the loop are not fully exposed. Throughout this book, we will examine many game examples that contain highly varied game loops, containing various functions as required by the individual game type. Later chapters will discuss in depth the tasks performed by an individual game example’s game loop, but for now, let’s examine an overview of what each segment is responsible for within our arbitrary game loop.

Retrieve User Input

Retrieving user input involves reading the input values from whatever device is supported or that the user has chosen, and translating that information into a form relevant to the control of the game. Most Delphi

applications typically handle user input through event handlers, such as OnKeyDown or OnMouseMove. For business applications and even most strategy or turn-based games, this method is fine. However, fast action arcade games typically require more control over the process, and handling user input through events may impede or interfere with the proper execution of the game.

Previous Table of Contents Next [an error occurred while processing this directive]

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.

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

Thus, most games use a polling technique for retrieving user input. Polling involves directly accessing the device at a specific point within the game loop and reading its data. Theoretically, this polling could take place at any time, but it usually occurs at the beginning of the game loop so that the most recent movement can be reflected in the next frame of animation. Direct polling gives the application developer precise control over the processing of input, and can even allow the detection of multiple input events simultaneously (i.e., check if two keys are pressed at the same time).

polling: A method for retrieving input or checking some data value manually (as opposed to letting a separate thread check it automatically), usually repeated often at regular intervals.

The primary drawback to the direct polling technique is that user input events can get lost if the polling happens infrequently. This is generally a symptom of a slow game loop, where a large amount of processing takes place before the input device is again polled.

Figure 2-3: Missing a user input event

One method to remedy this situation is to conduct device polling at several different places throughout the game loop, and then process the sum of the movement data when it is time to update game world objects.

However, another more accurate technique is to buffer user input events. To perform this technique efficiently, a separate thread must be utilized to perform the device polling and event queuing. Fortunately, DirectX provides several methods that make this technique viable, and we’ll examine a demonstration of this in the chapter on input techniques.

Once the input has been retrieved, it is translated into events that are meaningful in the context of the game.

For example, if the joystick button was pressed, the function for starting a missile or a bullet volley would be called. How the input is translated is, of course, dependent on the type of game itself. The result of such user actions will be apparent after the sprite updating segment has been called and the next frame of animation has been drawn to the screen.

Title

---Perform Antagonist AI and Other Game Logic

In this segment, algorithms that control the behavior of enemy units or other non-player units are performed, with the results being used to update the appropriate sprite positions or to execute any other appropriate actions. This may include deciding if an enemy spacecraft pursues the player or flees, but it also includes other, perhaps more mundane, decision making processes that affect other parts of the game. For example, background sprites that are never interacted with during the game may contain a little logic for changing their animation so that it does not appear repetitive.

This segment may run some very complex code depending on the type of game and its objectives. Some games, such as chess, may have a very advanced thinking engine that examines the current configuration of the board and makes a movement decision based upon the prediction of the next move that the opponent may make. Other games, such as real-time strategy war games, may have several smaller decision engines that determine the most direct route a unit may take to its destination. In general, this segment executes the artificial intelligence code that determines how the game objects will react to the actions of the player.

artificial intelligence (AI): The concept of cognitive software that thinks and reacts to situations in a sentient manner. In relation to game programming, this is the section of code responsible for determining the actions and reactions of game protagonists in relation to the actions and reactions of the player.

Artificial intelligence is a specialty area in its own right, and some game companies hire programmers specifically for their AI expertise. Some AI techniques are well documented and are easy to implement, such as chasing or evading the player or converging on a specific position. Others, such as natural speech

generation or pattern recognition, are very difficult to implement and are either closely guarded trade secrets or the province of advanced academic research.

Update Sprite Positions

The positions of all game objects are updated in this segment. Their velocities are added to their current positions, which are then usually checked to make sure that they are still within the boundaries of the game world. This segment is where the results of user input and artificial intelligence logic are realized. A ship is accelerated or turned according to how the user moved the joystick, and enemy soldiers and cannons are advanced forward or animated per the decisions of the artificial intelligence segment.

Since all objects in the game world need to be updated, the game loop typically iterates through each object, one at a time, applying the position translations as required. The game loop itself needs to run as quickly as possible, so other actions that are performed for each game object are typically executed in this segment as well. The most common action performed at the same time as position updating is probably drawing the sprite image into an offscreen buffer. However, other actions may include collision detection, artificial intelligence processing, or other functions. The process of actually drawing the sprite, as well as other sprite specific procedures, will be examined in Chapter 6, Sprite Techniques.

Check for Collisions

The collision detection segment is necessary for determining if two sprites or game objects have collided, and the action that is a result thereof. Most games are driven off of events where two sprites come into contact.

For example, when a bullet that was fired several frames ago finally touches the enemy ship at which it was targeted, something should happen.

There are hundreds of different methods by which to detect if two or more objects have collided. Some games may require that every object be checked against every other object; others may be interested in the collision between only certain types of objects. Whatever the case, collision detection algorithms vary in complexity according to the task they must perform and the number of objects involved. Accuracy is also an area of great variation. Some may detect only a close collision, and may not be very accurate at all. Others may go as far as comparing the pixels of each bitmap at a certain frame of animation and at a certain position within the game world to see if any pixels actually overlap (a highly accurate method indeed). Speed also becomes a very important issue with the collision detection scheme put into production, as the more accurate the collision detection, typically the slower it will run. Collision detection algorithms will be covered in the chapter on sprite techniques.

Previous Table of Contents Next

[an error occurred while processing this directive]

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.

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

Start Sound Effects

Games would tend to get boring without sound effects to accompany the actions of various game objects. The responsibility of this segment is to commence the output of various sound effects as warranted by the actions of both the user and the game controlled objects. Technically speaking, sound effect playback will probably be handled during other segments of the game loop. For example, when the user presses a button to fire a missile the user input retrieval segment will probably call a function that both starts the missile object as well as commences the playback of an appropriate sound effect. Other sound effects, such as idle background chatter or other appropriate noises that would be generated from non-interactive game objects, will probably be started when the artificial intelligence section makes one of these objects perform some action. Any other sound effects not handled by an appropriate segment, such as ambient sounds or user interface activation sounds, may be generated from this segment. We will see techniques for sound effect output in Chapter 9, Sound and Music.

Start Music

As with sound effects, music enhances the gaming experience, and this segment is responsible for starting musical output or changing the tune of the existing output. Again, music playback may be handled by another, more appropriate segment. However, music is commonly used to reflect the overall mood or state of the game. As such, this segment would be responsible for examining the current state as it would reflect from the user’s standpoint, and start or change the music as appropriate. For example, a neutral musical interlude may be output when the user is just flying along to the next waypoint. This could be changed, on the fly, to a more intense, urgent musical number when the user goes into combat. It could be changed to an even more intense score if the player or enemy is heavily damaged, and finally an appropriate tune could be played based on the user’s victory or defeat. This segment would need to perform the necessary actions to determine the current state of the game, playing a specific musical piece as appropriate. The chapter on sound and music contains examples of musical score playback techniques.

Render the Next Frame

This segment is responsible for the most important part of the game loop, that of displaying the current state of the game from the user’s perspective in graphical form. Depending on the complexity of the game, this may simply entail drawing two-dimensional bitmap images to the screen, or rendering a complex, realistic

Title

---view based on the positions of three-dimensional models. Of all the segments in a game loop, this segment has the greatest variety of implementations. Like all game programming topics, some techniques are well documented, such as simple sprite output or even three-dimensional raycasting or rendering techniques. Other techniques, such as true three-dimensional space rendering, are trade secrets and are poorly documented, if at all.

Typically, rendering a frame of animation starts by drawing the background. This may be as simple as a game board or something more complex, like a textured, scaled wall. Sprite images are then drawn over this

background. All of this drawing generally takes place in an offscreen graphical buffer. After all drawing and rendering has been completed, this buffer is then blasted to the screen, at which point it becomes visible as the next frame of animation. As sprite positions are modified, their images drawn to reflect these new positions, and the results displayed to the screen in rapid succession, the illusion of animation is achieved. DirectX provides several methods for performing graphical output, both simplistic and complex.

Check for Game End

At some point, the current state of the game needs to be compared with a known state to see if a state change is in order. For example, if all of the player’s lives have been used up, the game is over. Additionally, when all of the enemy creatures have been eliminated or the exit is found, the current level has ended and it is time to advance to the next level of difficulty.

Advanced games may potentially contain several states that affect how the overall game loop is processed.

Advanced games may potentially contain several states that affect how the overall game loop is processed.