Tricks of the Windows Game Programming Gurus:Putting It All Together: You God Game!

All ITKnowledge Source Code Search Tips Advanced Search |

| Tricks of the Windows Game Programming Gurus by Andre LaMothe Sams, Macmillan Computer Publishing ISBN: 0672313618 Pub Date: 09/27/99

Search this book:

Previous | Table of Contents | Next

### The Game Universe: Scrolling in Space

I already covered how to implement scrolling, so I’m not going to cover it again. However, there are a couple of interesting details about the scrolling in Outpost. First, the player is always at the center of the screen. This makes things a bit easier, but more importantly it gives the player the biggest game area possible to react in. If you allowed the player’s character to get near the edges of the screen in a scrolling game, it’s possible that an enemy could pop up and hit the player before he even had a few milliseconds to react. By keeping the player in the center of the screen, you give him good visibility of what’s around him at all times.

As for the size of the game universe, I chose 16000×16000, as shown here:

    // size of universe

    #define UNIVERSE_MIN_X   (-8000)

    #define UNIVERSE_MAX_X   (8000)

    #define UNIVERSE_MIN_Y   (-8000)

    #define UNIVERSE_MAX_Y   (8000)

Universe size is always a hard thing to decide, but my standard technique is the following: Estimate how many frames per second the game is going to run at, estimate the max speed the player can move, and then, based on that, decide how long you want the player to take to get from one end of the universe to the other:

    universe_size = player_velocity*fps*desired_time

Hence, if the player moves at a max of 32 pixel/frames per second, and you want to run at 30 fps with a time of 10 seconds from one end to another, you have a universe size of

    universe_size = 32 pixels/frame * 30 fps * 10

                  = 9600 units

Here, each unit is a pixel. This is basically how I came up with the 16,000. Of course, the final values in the game were slightly different, but this is how I came up with the ballpark figures.

The other issue to consider when you’re making a scrolling space game is the sparseness. You may think that a space of 10×10 seconds or 16000×16000 pixels isn’t that big, but to populate it, you will need hundreds if not thousands of asteroids. Otherwise, the player will be flying around forever looking for stuff to shoot! My friend Jarrod Davis learned this when writing Astro3D, which you can find on the CD.

As for the scrolling algorithm, there’s not much to it. The player’s position is used as the center of a window to render from, as shown in Figure 14.3.

Figure 14.3 The scrolling window algorithm for Outpost.

The algorithm works by taking the player’s position, and then translating the player to the origin (the screen center) and translating the objects to the player. The objects that are within the window are rendered, and the others are not. The only objects that aren’t drawn this way are the stars, which are basically pixels that wrap around as they move off the edges of the screen. Hence, if you look carefully, you can see the same stars in the same positions if you move slowly in the x- or y-axis.

### The Player’s Ship: “The Wraith”

The player’s ship was hand-drawn. I was going to render it, but it had so much detail that I decided to just draw it and then use Paint Shop Pro to light it and make it look real. In addition, I only drew the Wraith facing north and then used PSP’s built-in bitmap rotation to rotate the ship in 16 different angles. The artwork is shown in Figure 14.4.

Figure 14.4 The artwork for the Wraith.

The Wraith doesn’t do much except fly around and shoot, but the friction algorithm is interesting. I wanted the Wraith to look like it was flying under gravity, so I wanted some form of friction when it turned. I implemented this with the standard techniques that you learned in previous chapters.

The Wraith has a velocity vector that is modified when the player thrusts in any particular direction. The nice thing about this approach is that you don’t have to worry about things like, “If the ship is going east at this speed and the player thrusts north, what should the ship do?” Instead, I let the vector math do it.

Here’s a portion of the control code for the Wraith:

    // test if player is moving

    if (keyboard_state[DIK_RIGHT])

        {

        // rotate player to right

        if (++wraith.varsI[WRAITH_INDEX_DIR] > 15)

            wraith.varsI[WRAITH_INDEX_DIR] = 0;

        } // end if

    else

    if (keyboard_state[DIK_LEFT])

        {

        // rotate player to left

        if (-wraith.varsI[WRAITH_INDEX_DIR] <  0)

             wraith.varsI[WRAITH_INDEX_DIR] = 15;

        } // end if

    // vertical/speed motion

    if (keyboard_state[DIK_UP])

        {

        // move player forward

        xv = cos_look16[wraith.varsI[WRAITH_INDEX_DIR]];

        yv = sin_look16[wraith.varsI[WRAITH_INDEX_DIR]];

        // test to turn on engines

        if (!engines_on)

           DSound_Play(engines_id,DSBPLAY_LOOPING);

        // set engines to on

        engines_on = 1;

        Start_Particle(PARTICLE_TYPE_FADE, PARTICLE_COLOR_GREEN, 3,

                       player_x+RAND_RANGE(-2,2),

                       player_y+RAND_RANGE(-2,2),

                      (-int(player_xv)>>3), (-int(player_yv)>>3));

        } // end if

    else

    if (engines_on)

       {

       // reset the engine on flag and turn off sound

       engines_on = 0;

       // turn off the sound

       DSound_Stop_Sound(engines_id);

       } // end if

    // add velocity change to player’s velocity

    player_xv+=xv;

    player_yv+=yv;

    // test for maximum velocity

    vel = Fast_Distance_2D(player_xv, player_yv);

    if (vel >= MAX_PLAYER_SPEED)

       {

       // recompute velocity vector by normalizing then rescaling

       player_xv = (MAX_PLAYER_SPEED-1)*player_xv/vel;

       player_yv = (MAX_PLAYER_SPEED-1)*player_yv/vel;

       } // end if

    // move player, note that these are in world coords

    player_x+=player_xv;

    player_y+=player_yv;

> Tip: About the name Wraith. A long time ago I saw a movie called The Wraith with Charlie Sheen. In the film, Charlie ended up in the trunk of his car, falling off a cliff at 32 ft/sec2. He died and came back as a wraith, which is an evil ghost that takes revenge on its killers. Anyway, he had this cool car, a prototype Dodge Interceptor, and the movie is where I got the name. I thought you should know. (Plus, guess who has the Dodge Interceptor?)

Studying the code, you’ll notice there is some code to keep the Wraith from going too fast. Basically, I continually check the length of the velocity vector against a MAX length. If it’s too long, I shrink it. Another approach could have been to use a unit direction vector and a speed scalar, and then translate the ship each frame an amount equal to the unit vector scaled by the speed. Either way is about the same.

Previous | Table of Contents | Next

Copyright © Macmillan Computer Publishing, Inc.

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 in whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.