Including the Player


Before you create the player object, do you remember back a few chapters ago when you were first rendering the sky box for the level? Well, the code is probably still there in the OnCreateDevice method of the game engine, but that probably isn't where it should be. You don't need to create the sky box, or the player, or the level until the user selects the character he will be using in the game. You left the event handler for this user interface screen "empty" before, so you should fill it now, using the method in Listing 9.1.

Listing 9.1. Selecting Your Character Event Handler
 private void OnLoopySelected(object sender, EventArgs e) {     SelectLoopyScreen screen = sender as SelectLoopyScreen;     System.Diagnostics.Debug.Assert(screen != null, GameName,         "The selection screen should never be null.");     // Create the graphics items     CreateGraphicObjects(screen);     // And not showing the select screen     isSelectScreenShowing = false;     // Fix the lights     EnableLights(); } 

First, you want to get the SelectLoopyScreen object that fired this event, which you can do from the sender variable. Considering this event should only be fired from this object, it should never return null (thus the Assert here).

You might be wondering what an assert is or why you would ever want to use such a thing. An assert is essentially an evaluation of a condition that should never be true, and if that condition is true, there is a big problem. What the Assert method does is, in debug builds, check whether that condition is TRue. If it isn't, execution proceeds normally; however, if it is true, execution halts and a dialog appears with the message you've included.

Using this functionality can help uncover many common coding mistakes.

The "graphics" items are created next (you will implement this method presently), the select screen should no longer be showing, and the lights should now be enabled for the level. If you remember from earlier, this method keys off the isSelectScreenShowing variable, so with it false, it enables the light for the level.

Now, you should remove the code that creates the sky-box mesh from the InitializeGraphics method and add the method you are missing into your game engine code. You will find this method in Listing 9.2.

Listing 9.2. Creating Graphics Objects
 private void CreateGraphicObjects(SelectLoopyScreen screen) {     // No need to create the level mesh     if (levelMesh == null)     {         // Create the mesh for the level         ExtendedMaterial[] mtrls;         levelMesh = Mesh.FromFile(MediaPath + "level.x", MeshFlags.Managed,                                   device, out mtrls);         // Store the materials for later use, and create the textures         if ((mtrls != null) && (mtrls.Length > 0))         {             levelTextures = new Texture[mtrls.Length];             for (int i = 0; i < mtrls.Length; i++)             {                 // Create the texture                 levelTextures[i] = TextureLoader.FromFile(device, MediaPath +                     mtrls[i].TextureFilename);             }         }     }     // Create our player object     player = new Player(screen.LoopyMesh, screen.LoopyTexture,                         screen.LoopyMaterial); } 

The code to create the sky-box mesh is the same as it was before, but now it is created only once. Because the mesh is never destroyed until the end of the application, creating it more than once is just a waste of time. When the levelMesh member is null, you can assume that the mesh hasn't been created yet and you can create it the first time. After that, the player object is created using the information from the Select Loopy screen to get the graphical content.

Do you remember earlier when the CleanupLoopy method was created in the Select Loopy screen? You did so when the player object wasn't created yet, and you were told that you would add a call to this method when the player object was added to the game engine. Well, now it's time to oblige. In your OnDestroyDevice overload, add the code from Listing 9.3 directly after your user screen cleanup methods.

Listing 9.3. Cleaning Up Players
 // If the player is null, and you are on the select screen, clean up // those meshes as well if ((player == null) && (selectScreen != null)) {     selectScreen.CleanupLoopyMesh(); } // Clean up the player if (player != null) {     player.Dispose(); } 

You've been working on the player for a while now, and you're probably thinking to yourself, "Self, what else do I need to do with the player?" Well, you need to declare it sometime, so how about now?

 // The player's object private Player player = null; 

The only things left are drawing the player and updating the player. The update is simple because you already have a method in the game engine that will be called every frame. Add this section of code to your OnFrameMove method:

 if ((isQuitMenuShowing) || (isMainMenuShowing) || (isSelectScreenShowing)) {     return; // Nothing to do } // Update the player player.Update(elapsedTime, timer.TotalTime); 

Obviously, if one of the user interface screens is showing, you don't need to update the player. If they are not showing, though, you simply call the player's update method. You probably noticed that you haven't declared the isQuitMenuShowing member variable yet, so go ahead and do that now:

 // Is the quit menu showing? private bool isQuitMenuShowing = false; 

You won't actually use this variable until later when you design the user interface screen for quitting, but this code allows you to compile for now. The last thing you need to do with the player is render it onscreen at the appropriate time. You also want to add the code back for rendering the sky box. Go back to the OnFrameRender method in your game engine, and notice that each of the "rendering" methods is encapsulated into a single call depending on the game state; the correct object is rendered depending on which state the game is currently in. Because no single object is used to render the game scene, you want a separate method to render the game scene so that you don't clutter your render method. Add this final else clause to your render method:

 else {     RenderGameScene(); } 

You then need to add the implementation of this method, which you will find in Listing 9.4.

Listing 9.4. Rendering Your Game
 private void RenderGameScene(Device device, double appTime) {     // First render the level mesh, but before that is done, you need     // to turn off the zbuffer. This isn't needed for this drawing     device.RenderState.ZBufferEnable = false;     device.RenderState.ZBufferWriteEnable = false;     device.Transform.World = Matrix.Scaling(15,15,15) *                              Matrix.Translation(0,22,0);     device.RenderState.Lighting = false;     for(int i = 0; i < levelTextures.Length; i++)     {         device.SetTexture(0, levelTextures[i]);         levelMesh.DrawSubset(i);     }     // Turn the zbuffer back on     device.RenderState.ZBufferEnable = true;     device.RenderState.ZBufferWriteEnable = true;     // Now, turn back on our light     device.RenderState.Lighting = true;     // Render the player     player.Draw(device, (float)appTime); } 

The first part of this method is naturally the replacement code for rendering the sky box that you removed earlier this chapter. The only new code here is the addition of the render call to the player.



Beginning 3D Game Programming
Beginning 3D Game Programming
ISBN: 0672326612
EAN: 2147483647
Year: 2003
Pages: 191
Authors: Tom Miller

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