game engine. Although the game engine is a flexible piece of software, you will likely find yourself adding new features in the future to accommodate the special needs of new games. This is a good thing because you get to reuse those features in any game that you create from then on. Adding One Last Sprite Feature to the Game Engine The missing feature in the game engine critical to the Space Out game is the capability for a sprite to automatically create another sprite. This might seem like a strange requirement, but think about an alien that is firing a missile at the car in the Space Out game. The missile must be created so that it appears to come from the alien, which means that the missile must know about the alien’s position. Not only that, but the missile must be unique to the alien that fired it because each alien fires a different kind of missile. This presents a significant challenge to the current design of the game engine because there isn’t a good way to automatically create a new sprite based on the properties of another sprite. A good solution to this problem involves allowing a sprite to create another sprite whenever it needs to. For example, you can allow the alien sprites to create missile sprites themselves, which makes it very easy to position the missile based on the alien’s position not to mention creating the appropriate missile for each different type of alien. The problem with this approach is that it is impossible to add this functionality to the Sprite class in a generic fashion. In other words, the specifics regarding what kind of sprite needs to be created are unique to each game, and therefore can’t be carried out in the Sprite class. However, the Sprite class can establish the interface that makes it possible. An important part of this new “add sprite” feature is a new sprite action called SA_ADDSPRITE. The following code shows how the SA_ADDSPRITE sprite action has been added to the existing sprite actions: typedef WORD SPRITEACTION; const SPRITEACTION SA_NONE = 0×0000L, SA_KILL = 0×0001L, SA_ADDSPRITE = 0×0002L; If you recall, sprite actions are used to signal to the game engine that some particular action must be taken in regard to a sprite. The SA_ADDSPRITE sprite action simply results in a special method being called on the Sprite object to which the action applies. This method is called AddSprite(), and looks like this: virtual Sprite* AddSprite(); The idea behind the AddSprite() method is that it gets called to allow a sprite to add a new sprite to the game engine. The specifics of the new sprite are entirely dependent on each individual game. In fact, the version of the AddSprite() method in the Sprite class doesn’t do anything, as the following code reveals: Sprite* Sprite::AddSprite() { return NULL; } This code shows how the base Sprite::AddSprite() method doesn’t do anything other than return a NULL sprite pointer, which reveals that the task of adding a sprite via the AddSprite() method is left up to derived sprite classes. So, in order to take advantage of this method, you must derive a sprite class for a particular kind of sprite, and then override the AddSprite() method with a version that actually creates a sprite. The SA_ADDSPRITE action and AddSprite() method enter the picture in the game engine in the GameEngine::UpdateSprites() method, which must check for the presence of the SA_ADDSPRITE sprite action, and then call the AddSprite() method on the sprite if the action is set. The return value of the sprite’s AddSprite() method is passed along to the game engine’s AddSprite() function, which handles inserting the sprite into the sprite list. This is all that is required of the game engine to support adding a sprite from within another sprite.
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost Cheap Web Hosting services
Building the Game The construction of the Space Out game is similar to that of the other games you’ve developed throughout the book. However, Space Out is slightly more involved simply because it is a more complete game. The next few sections guide you through the development of the game’s code and resources. Writing the Game Code Although the development of all the previous games in the book began with the header file for the game, Space Out is a little different in that it relies on a custom sprite class. For this reason, the code for the Space Out game begins with the header for this custom sprite class, AlienSprite, which is shown in Listing 21.1. Listing 21.1 The AlienSprite.h Header File Declares the AlienSprite Class, Which Is Derived from Sprite 1: #pragma once 2: 3: //—————————————————————-4: // Include Files 5: //—————————————————————-6: #include 7: #include “Sprite.h” 8: 9: //—————————————————————-10: // AlienSprite Class 11: //—————————————————————-12: class AlienSprite : public Sprite 13: { 14: public: 15: // Constructor(s)/Destructor 16: AlienSprite(Bitmap* pBitmap, RECT& rcBounds, 17: BOUNDSACTION baBoundsAction = BA_STOP); 18: virtual ~AlienSprite(); 19: 20: // General Methods 21: virtual SPRITEACTION Update(); 22: virtual Sprite* AddSprite(); 23: }; The AlienSprite class is not very complex at all, as the listing hopefully reveals. It’s important to notice that AlienSprite derives from Sprite (line 12), and declares a constructor and destructor (lines 16 18). More importantly, however, are the two methods in the Sprite class that AlienSprite overrides, Update() and AddSprite() (lines 21 and 22). These two methods are critical to providing the AlienSprite class with its own unique functionality separate from the Sprite class. In case you’re wondering exactly what this functionality is, let me explain. If you recall from earlier in the hour, one of the problems in the game engine was that it didn’t allow a sprite to create another sprite on its own. You added code to the game engine, including a method called AddSprite() in the Sprite class, to allow for this task to be carried out by sprites. However, the version of the AddSprite() method in the Sprite class doesn’t do anything it’s up to derived Sprite classes to create their own sprites. The AlienSprite class is an example of one of these derived classes that overrides the AddSprite() method to do something useful. Before you get to the AlienSprite::AddSprite() method, however, let’s take a quick look at some external global variables that are required of the AlienSprite class: extern Bitmap* _pBlobboBitmap; extern Bitmap* _pBMissileBitmap; extern Bitmap* _pJellyBitmap; extern Bitmap* _pJMissileBitmap; extern Bitmap* _pTimmyBitmap; extern Bitmap* _pTMissileBitmap; extern int _iDifficulty;
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost Cheap Web Hosting services
perspective. In this hour, you’ll learn: About the basic premise behind the Space Out game How to design the Space Out game About the nuts and bolts of programming the Space Out game Why testing is still the most fun part of testing a new game How Does the Game Play? One of the most classic genres of video games has always been the vertical space shoot-em-up. Space Invaders started it all back in 1978, but many games followed and added their own unique contributions to the genre. One of the most enduring vertical space shooters is Galaga, which you learned about back in the introduction to Hour 9, “A Crash Course in Game Animation.” In Galaga, a relentless sequence of invading aliens fly down from the top of the game screen and attack your ship, which is free to move horizontally across the bottom of the screen. The Space Out game that you develop in this hour is similar in some ways to Galaga, although the theme for the game is a little more whimsical. In Space Out, you are the driver of a small green car on a trek across the desert. Whether you believe in UFOs, it’s hard to argue that quite a few sightings seem to have occurred in remote desert places such as Roswell, New Mexico. For this reason, your traveler in the game can’t seem to get away from a constant onslaught of alien visitors from above. Unfortunately, the aliens in Space Out are bent on putting an end to our traveler’s trip. The cast of alien characters in the Space Out game are somewhat comical, and add a degree of whimsy to the game. Following are the three kinds of aliens that appear throughout the game: Blobbo the Galactic Ooze Jellybiafra (Jelly for short) Timmy the Space Worm Granted, these probably aren’t very realistic aliens when it comes to what you might imagine truly encountering in an extra-terrestrial sighting, but this game isn’t about reality. Each of the aliens has its own style of attack, and they each fire different missiles. The idea here isn’t to simulate a realistic alien invasion, but to have some fun with outlandish characters in the context of a vertical shoot-em-up. The characters and concept for the Space Out game were created by Rebecca Rose, a computer artist and game designer who has collaborated with me in the past on other game projects. Designing the Game Now that you understand the basic idea behind the game, let’s focus on a few details regarding the design of the game. The player’s car can move horizontally across the game screen, which means that its position is confined to the x axis. The player can shoot up vertically with his Twinkie missiles terminating at the top of the screen, similar to the missiles in the Meteor Defense game from Hour 19, “Example Game: Meteor Defense.” The aliens in Space Out can move around in any direction and at different velocities. The Blobbo and Jelly aliens bounce off of the edges of the screen, while Timmy is allowed to wrap around and appear on the other side. This is because Timmy has a tendency to fly horizontally across the screen, whereas the others move around a little more randomly. All the aliens fire missiles down toward the player’s car with the missiles terminating when they strike the car or the ground. The aliens are immune from their own missiles, so they can’t hit each other. This is a good thing for the aliens because they aren’t very careful in terms of how they aim.
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost Cheap Web Hosting services
Space Out has no discrete levels and no real goal other than surviving. However, the difficulty level of the game does gradually increase as the player progresses through the game. The difficulty of the game increases by adding new aliens at a faster pace. Eventually the player will have his hands full trying to contend with a never-ending army of aliens. That’s the whole fun of shoot-em-ups! To help you get a feel for how the Space Out game is laid out, take a look at Figure 21.1. Figure 21.1. The Space Out game consists of a starry background, a ground desert image, a car, aliens, and missiles that are fired between the car and aliens. The figure shows the background image of the desert, which serves as a backdrop for the car to drive around on. The starry background still appears in the majority of the screen, whereas the background image shows the desert where the car drives around. The background image actually includes a horizontal band of sky that helps blend the desert landscape into the starry background. The car sprite moves around on top of the desert background image. The aliens appear in the sky and move around trying to hit the car by firing various missiles. Of course, the car also fires missiles back at the aliens. The score for the game is displayed in the upper right corner of the game screen, along with the number of remaining lives (cars). Now that you understand the basics of the game, it’s important to examine the sprites that it requires. Following is a list of the sprites that go into the Space Out game: Car sprite Alien sprites Missile sprites (from the aliens and the car) Explosion sprites The only type of sprite in this list that I haven’t mentioned is the explosion sprite, which is used to show an alien being destroyed by a missile, as well as the car being destroyed by an alien missile. Two different sizes of explosions are actually used in the Space Out game. The larger explosion is used to show an alien or the car being destroyed, whereas the smaller explosion is used to show a missile exploding. This distinction is important because it shows how missiles cause a smaller explosion when they simply crash into the desert, as opposed to hitting the car. In addition to the sprites, the Space Out game requires several bitmaps. Following are the bitmap images required of the game: Background desert image Car image Missile image (fired by car) Alien images (Blobbo, Jelly, and Timmy; animated) Missile images (fired by each of the three aliens) Explosion images (animated; small and large) Small car image Game over image These images flow directly from the design of the game that you’ve covered thus far, so there hopefully shouldn’t be any big surprises here. Perhaps the main thing to point out is that the aliens all rely on animated images to provide them with a more interesting appearance as they move around on the game screen. The only other animated images in the game are the explosion images, which go with the explosion sprites. The score needs to be maintained throughout the game, as well as the number of remaining lives (cars); the game ends when all three of your cars have been destroyed. The difficulty level of the game is stored away in a global variable, and gradually increases as the player racks up points and progresses through the game. Another important piece of information is the familiar Boolean variable that keeps track of whether the game is over. The last global game variable required of Space Out is an input delay variable that helps add some restraint to the player’s ability to fire missiles rapidly. Without this input delay variable, it would be too easy to wipe out the aliens by holding down the fire key (Spacebar) and raining missiles on the aliens with little effort. By slowing down the number of missiles that can be fired, the player is forced to be more accurate and evade aliens when they miss. Establishing the appropriate delay is somewhat of a trial-and-error process, and you might decide that the game is more fun with a slightly different value than I used. To recap, the design of the Space Out game has led us to the following pieces of information that must be managed by the game: The number of lives (cars) remaining The score The difficulty level A Boolean game over variable A delay variable for firing input Before diving into the code for the Space Out game, you need to add a new feature to the
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost Cheap Web Hosting services
Q&A Q1: Everyone acts like computers are so smart, but you’ve made it sound like they’re dumb. What gives? A1: Computers, in fact, are very “dumb” when it comes to what we humans refer to as thought. However, computers are very “smart” when it comes to mathematical calculations and algorithms. The trick with AI is to model the subtleties of human thought in such a way that the computer can do what it’s good at, executing mathematical calculations and algorithms. The point is that thoughts we take for granted are often very difficult for computers simply because human thought takes into account an incredibly large number of subtle variables when arriving at even the simplest decision. Q2: If my game is designed to have only human players, do I even need to worry with AI? A2: Even though games with all human players might appear to not require any AI at first, it is often useful to control many of the background aspects of the game using simple AI. For example, consider a two player head-to-head space battle game. Even though you might not have any plans for computer ships, consider adding some AI to determine how the environment responds to the players’ actions. For example, add a black hole near the more aggressive player from time to time, providing that player with more hassles than the other player. Although the intelligence required of a black hole is pretty weak by most AI standards, it could still use a simple chase algorithm to follow the player around. Workshop The Workshop is designed to help you anticipate possible questions, review what you’ve learned, and begin learning how to put your knowledge into practice. The answers to the quiz can be found in Appendix A, “Quiz Answers.” Quiz 1: What are the three types of roaming AI? 2: How does behavioral AI work? 3: In regard to strategic AI, what do the terms look-ahead and weighting mean? Exercises 1. Play some video games with computer opponents and see whether you can tell which type of AI approach is being used. 2. Tinker with the AI code in the Roids 2 program example to see how changes to the minimum collision distance affect the movement of the flying saucer. Hour 21. Example Game: Space Out This hour embarks yet again on the development of another complete game. The game is called Space Out, and it represents a culmination of everything you’ve learned about game programming throughout the book. Although this isn’t the last hour of the book, this is the last complete game you’ll be creating. The remaining hours focus on improving the Space Out game with some interesting features. This hour, however, explores the design and development of the basic Space Out game, which is a vertical space shoot-em-up. The closest arcade comparison I can make to Space Out is Galaga, but the aliens in Space Out don’t move with as intricate of patterns as those in Galaga. Nevertheless, I think you’ll find Space Out to be a fun and entertaining game, both from a programming and a playability
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost Cheap Web Hosting services
you don’t want the saucer to jerk and immediately start moving away from the asteroid. Instead, you gradually alter its velocity so that it appears to steer away from the asteroid. This is a subtle difference, but the effect is dramatic because it looks as if the saucer is truly steering through the asteroid field. The first step in the UpdateSaucer() function is to obtain the position of the flying saucer (line 5). You can then loop through the asteroids and find out the minimum X and Y collision distance (lines 8 and 9), which is the closest distance between an asteroid and the saucer. Inside the loop, the asteroid position is first obtained (line 12), which is critical for determining the collision distance. The minimum XY collision distance is then calculated (lines 15 22) and used as the basis for determining if this asteroid is currently the closest one to the saucer. This is where the function gets a little tricky because you must add the X and Y components of the collision distance to see which asteroid is closer to the saucer (lines 23 30). This technique isn’t flawless, but it helps to eliminate “false alarm” situations in which an asteroid is close to the saucer horizontally but far away vertically. When the asteroid loop is exited, you have two pieces of important information to work with: the X collision distance and the Y collision distance. It’s now possible to check and see if these distances are below a certain minimum distance that is required in order for the saucer to be in danger of colliding with an asteroid. My own trial-and-error testing led to a value of 60, but you might decide on a slightly different value in your own testing. In order to steer the saucer to safety horizontally, the X collision distance is checked to see if it is below the minimum distance of 60; in which case, the saucer’s velocity is adjusted (lines 36 43). The same process is then repeated for the saucer’s Y collision distance (lines 44 51). Finally, the new velocity of the saucer is set by calling the SetVelocity() method on the saucer sprite (line 54). Testing the Finished Product The premise behind the Roids 2 program is to show how a certain degree of AI can be injected into a sprite object so that it can avoid other sprite objects. In this context, the evading sprite object is a flying saucer that is desperately trying to keep from colliding with asteroids in an asteroid field. Although you have to actually run the program yourself to see the flying saucer evade the asteroids, Figure 20.3 shows the saucer in the process of steering away from a close call. Figure 20.3. The flying saucer in the Roids 2 program does its best to dodge the asteroids that are floating around the game screen. This is one of those rare program examples that is actually fun to just sit back and watch because the program appears to have a mind of its own. In other words, you’ve created the logic for the flying saucer, and now you get to see how it responds in different situations. This is the part of the process of developing AI in games that is often frustrating because objects can do strange things that are quite unexpected at times. Even so, the flying saucer does a pretty good job of avoiding asteroids in the Roids 2 program. Summary If you find artificial intelligence to be a fascinating area of computer research, you hopefully enjoyed this hour. You learned about the three fundamental types of game AI (roaming, behavioral, and strategic), along with how they are used in typical gaming scenarios. As a game programmer with at least a passing interest in AI, your AI knowledge will likely grow a great deal as you encounter situations in which you can apply AI techniques. After you get comfortable with implementing the basics, you can move on to more advanced AI solutions based upon prior experience and research on the Web. I hope this hour at least provided you with a roadmap to begin your journey into the world of the computer mind. The next hour applies your newfound AI knowledge to the most ambitious game in the book. The game is called Space Out, and it’s a space shoot-em-up with a quirky cast of characters.
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost Cheap Web Hosting services
The _pSaucerBitmap is a bitmap for the flying saucer image. The _pAsteroids and _pSaucer variables both store sprite pointers. These pointers are necessary so that you can compare the positions of the saucer and asteroids and alter the saucer’s velocity; this is how you add “intelligence” to the flying saucer. The Roids 2 program also includes a new helper function named UpdateSaucer(), which is responsible for updating the saucer sprite. Of course, the saucer sprite is already being updated in terms of its position and velocity in the game engine. However, in this case an additional update is taking place that alters the saucer’s velocity based on its proximity to nearby asteroids. You learn exactly how this facet of the program works a little later in the hour. The GameStart() function is similar to the previous version, except that it now contains code to initialize the flying saucer. Listing 20.1 shows the code for this function. Listing 20.1 The GameStart() Function Initializes the Flying Saucer Bitmap and Sprite 1: void GameStart(HWND hWindow) 2: { 3: // Seed the random number generator 4: srand(GetTickCount()); 5: 6: // Create the offscreen device context and bitmap 7: _hOffscreenDC = CreateCompatibleDC(GetDC(hWindow)); 8: _hOffscreenBitmap = CreateCompatibleBitmap(GetDC(hWindow), 9: _pGame->GetWidth(), _pGame->GetHeight()); 10: SelectObject(_hOffscreenDC, _hOffscreenBitmap); 11: 12: // Create and load the asteroid and saucer bitmaps 13: HDC hDC = GetDC(hWindow); 14: _pAsteroidBitmap = new Bitmap(hDC, IDB_ASTEROID, _hInstance); 15: _pSaucerBitmap = new Bitmap(hDC, IDB_SAUCER, _hInstance); 16: 17: // Create the starry background 18: _pBackground = new StarryBackground(500, 400); 19: 20: // Create the asteroid sprites 21: RECT rcBounds = { 0, 0, 500, 400 }; 22: _pAsteroids[0] = new Sprite(_pAsteroidBitmap, rcBounds, BA_WRAP); 23: _pAsteroids[0]->SetNumFrames(14); 24: _pAsteroids[0]->SetFrameDelay(1); 25: _pAsteroids[0]->SetPosition(250, 200); 26: _pAsteroids[0]->SetVelocity(-3, 1); 27: _pGame->AddSprite(_pAsteroids[0]); 28: _pAsteroids[1] = new Sprite(_pAsteroidBitmap, rcBounds, BA_WRAP); 29: _pAsteroids[1]->SetNumFrames(14); 30: _pAsteroids[1]->SetFrameDelay(2); 31: _pAsteroids[1]->SetPosition(250, 200); 32: _pAsteroids[1]->SetVelocity(3, -2); 33: _pGame->AddSprite(_pAsteroids[1]); 34: _pAsteroids[2] = new Sprite(_pAsteroidBitmap, rcBounds, BA_WRAP); 35: _pAsteroids[2]->SetNumFrames(14); 36: _pAsteroids[2]->SetFrameDelay(3); 37: _pAsteroids[2]->SetPosition(250, 200); 38: _pAsteroids[2]->SetVelocity(-2, -4); 39: _pGame->AddSprite(_pAsteroids[2]); 40: 41: // Create the saucer sprite 42: _pSaucer = new Sprite(_pSaucerBitmap, rcBounds, BA_WRAP); 43: _pSaucer->SetPosition(0, 0); 44: _pSaucer->SetVelocity(3, 1); 45: _pGame->AddSprite(_pSaucer); 46: } The changes to the GameStart() function primarily involve the addition of the flying saucer sprite. The saucer bitmap is first loaded (line 15), and then the saucer sprite is created and added to the game engine (lines 42 45). It’s also worth pointing out that the asteroid sprite pointers are now being stored in the _pAsteroids array (lines 22, 28, and 34) because you need to reference them later when helping the saucer avoid hitting the asteroids. The GameCycle() function in Roids 2 requires a slight modification to ensure that the
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost Clan Web Hosting services
flying saucer sprite is updated properly. This change involves the addition of a call to the UpdateSaucer() function, which is responsible for updating the velocity of the flying saucer sprite to help it dodge the asteroids. Speaking of the UpdateSaucer() function, its code is shown in Listing 20.2. Listing 20.2 The UpdateSaucer() Function Updates the Flying Saucer’s Velocity to Help It Dodge Asteroids 1: void UpdateSaucer() 2: { 3: // Obtain the saucer’s position 4: RECT rcSaucer, rcRoid; 5: rcSaucer = _pSaucer->GetPosition(); 6: 7: // Find out which asteroid is closest to the saucer 8: int iXCollision = 500, iYCollision = 400, iXYCollision = 900; 9: for (int i = 0; i < 3; i++) 10: { 11: // Get the asteroid position 12: rcRoid = _pAsteroids[i]->GetPosition(); 13: 14: // Calculate the minimum XY collision distance 15: int iXCollisionDist = (rcSaucer.left + 16: (rcSaucer.right - rcSaucer.left) / 2) 17: (rcRoid.left + 18: (rcRoid.right - rcRoid.left) / 2); 19: int iYCollisionDist = (rcSaucer.top + 20: (rcSaucer.bottom - rcSaucer.top) / 2) 21: (rcRoid.top + 22: (rcRoid.bottom - rcRoid.top) / 2); 23: if ((abs(iXCollisionDist) < abs(iXCollision)) || 24: (abs(iYCollisionDist) < abs(iYCollision))) 25: if ((abs(iXCollisionDist) + abs(iYCollisionDist)) < iXYCollision) 26: { 27: iXYCollision = abs(iXCollision) + abs(iYCollision); 28: iXCollision = iXCollisionDist; 29: iYCollision = iYCollisionDist; 30: } 31: } 32: 33: // Move to dodge the asteroids, if necessary 34: POINT ptVelocity; 35: ptVelocity = _pSaucer->GetVelocity(); 36: if (abs(iXCollision) < 60) 37: { 38: // Adjust the X velocity 39: if (iXCollision < 0) 40: ptVelocity.x = max(ptVelocity.x - 1, -8); 41: else 42: ptVelocity.x = min(ptVelocity.x + 1, 8); 43: } 44: if (abs(iYCollision) < 60) 45: { 46: // Adjust the Y velocity 47: if (iYCollision < 0) 48: ptVelocity.y = max(ptVelocity.y - 1, -8); 49: else 50: ptVelocity.y = min(ptVelocity.y + 1, 8); 51: } 52: 53: // Update the saucer to the new position 54: _pSaucer->SetVelocity(ptVelocity); 55: } I realize that this function contains a lot of code, but if you take it a section at a time, it’s really not too complex. First of all, let’s understand how the UpdateSaucer() function is helping the flying saucer to dodge the asteroids. The idea is to check for the closest asteroid in relation to the saucer, and then alter the saucer’s velocity so that it has a tendency to move in the opposite direction of the asteroid. I say “tendency” because
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost Clan Web Hosting services
Developing an AI Strategy Now that you understand the basic concepts behind AI in games, you can start thinking about an AI strategy for your own specific games. When deciding how to implement AI in a game, you need to do some preliminary work to assess exactly what type and level of AI you think is warranted. You need to determine what level of computer response suits your needs, abilities, resources, and project time frame. If your main concern is developing a game that keeps human players entertained and challenged, go with the simplest AI possible. Actually, try to go with the simplest AI regardless of your goals because you can always enhance it in phases. If you think your game needs a type of AI that doesn’t quite fit into any I’ve described, do some research and see whether something out there is closer to what you need. Most importantly, budget plenty of time for implementing AI because 90% of the time, it will take longer than you ever anticipated to get it all working at a level you are happy with. What is the best way to get started? Start in small steps, of course. Many programmers like to write code as they design, and although that approach might work in some cases, I recommend at least some degree of preliminary design on paper. Furthermore, try to keep this design limited to a subset of the game’s AI, such as a single computer opponent. Start with a small, simple map or grid and simple movement rules. Write the code to get a single opponent from point A to point B. Then add complications piece by piece, building onto a complete algorithm at each step. If you are careful to make each piece of the AI general and open enough to connect to other pieces, your final algorithms should be general enough to handle any conditions your game might encounter. Getting back to more basic terms, a good way to build AI experience is to write a computer opponent for a simple board game, such as tic-tac-toe or checkers. Detailed AI solutions exist for many popular games, so you should be able to find them if you search around a little on the Web. Another good way to get some experience with AI is to modify an existing game in an attempt to make its computer-controlled characters a little smarter. For example, you could modify the Henway game so that the cars speed up and slow down deliberately to make it tougher on the chicken. You could also change the speed of the moving guys in the Battle Office game so that they speed up when you get close to shooting them. Building the Roids 2 Program Example Rather than modify an existing game to demonstrate AI programming, I decided that it would be better to demonstrate AI within the context of a program example that doesn’t involve an objective. In other words, I wanted to create a program that you could tinker with without worrying about messing up the outcome of a game. The program I’m talking about is called Roids 2, and it’s a revamped version of the Roids program from Hour 18. If you recall, the original Roids program displayed an animated asteroid field. You’re now going to add a flying saucer to the program that is intelligent enough to dodge the asteroids, or at least do its best to dodge the asteroids. The Roids 2 program example is very similar to the original Roids program, except for the addition of the flying saucer sprite. The remainder of the hour focuses on the development of this program, and how AI influences the flying saucer sprite. Writing the Program Code The Roids 2 program begins with the Roids.h header file, which declares global variables that are important to the program. More specifically, a flying saucer bitmap has been declared, along with sprites for the asteroids and the flying saucer: Bitmap* _pSaucerBitmap; Sprite* _pAsteroids[3]; Sprite* _pSaucer;
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost Cheap Web Hosting services
behavioral aggressive alien would look like this: int iBehavior = abs(rand() % 100); if (iBehavior < 50) // chase else if (iBehavior < 60) // evade else if (iBehavior < 90) // fly in a pattern else // fly randomly As you can see, creating and assigning behaviors is open to a wide range of creativity. One of the best sources of ideas for creating game object behaviors is the primal responses common in the animal world (and unfortunately all too often in the human world, too). As a matter of fact, a simple fight or flight behavioral system can work wonders when applied intelligently to a variety of game objects. Basically, just use your imagination as a guide and create as many unique behaviors as you can dream up. Strategic AI The final fundamental type of game AI I want to mention is strategic AI, which is basically any AI designed to play a game with a fixed set of well-defined rules. For example, a computer-controlled chess player would use strategic AI to determine each move based on trying to improve the chances of winning the game. Strategic AI tends to vary more based on the nature of the game simply because it is so tightly linked to the rules of the game. Even so, there are established and successful approaches to applying strategic AI to many general types of games, such as games played on a rectangular board with pieces. Checkers and chess immediately come to mind as fitting into this group, and likewise have a rich history of AI research devoted to them. Strategic AI, especially for board games, typically involves some form of look-ahead approach to determining the best move to make. The look-ahead is usually used in conjunction with a fixed table of predetermined moves. For a look-ahead to make sense, however, there must be a method of looking at the board at any state and calculating a score. This is known as weighting, and is often the most difficult part of implementing strategic AI in a board game. As an example of how difficult weighting can be, watch a game of chess or checkers and try to figure out who is winning after every single move. Then go a step further and think about trying to calculate a numeric score for each player at each point in the game. Obviously, near the end of the game it gets easier, but early on it is very difficult to tell who is winning simply because there are so many different things that can happen. Attempting to quantify the state of the game in a numeric score is even more difficult. Nevertheless, there are ways to successfully calculate a weighted score for strategic games. Using a look-head approach with scoring, a strategic AI algorithm can test, for every possible move for each player, multiple moves into the future and determine which move is the best. This move is often referred to as the "least worst" move rather than the best because the goal typically is to make the move that helps the other player the least rather than the other way around. Of course, the end result is basically the same, but it is an interesting way to look at a game, nevertheless. Even though look-ahead approaches to implementing strategic AI are useful in many cases, they can require a fair amount of processing if very much depth is required (in other words, if the computer player needs to be very smart). To better understand strategic AI, consider the case of a computer Backgammon player. The computer player has to choose two or four moves from possibly several dozen, as well as decide whether to double or resign. A practical Backgammon program might assign weights to different combinations of positions and calculate the value of each position reachable from the current position and dice roll. A scoring system would then be used to evaluate the worth of each potential position, which gets back to the often difficult proposition of scoring, even in a game such as Backgammon, with simple rules. Now apply this scenario to a hundred-unit war game with every unit having unique characteristics, and the terrain and random factors complicating the issue still further. The optimal system of scoring simply cannot be determined in a reasonable amount of time, especially with the limited computing power of a workstation or PC. The solution in these cases is to settle for a "good enough" move, rather than the "best" move. One of the best ways to develop the algorithm for finding the "good enough" move is to set up the computer to play both sides in a game, using a lot of variation between the algorithms and weights playing each side. Then sit back and let the two computer players battle it out and see which one wins the most. This approach typically involves a lot of tinkering and trial-and-error with the AI code, but it can result in very good computer players.
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost Cheap Web Hosting services