Updating the Game Engine with This New Screen
Updating the Game Engine with This New Screen
Now you're ready to update the main game engine to use this new screen. As before, you want a Boolean variable to determine whether this screen is being shown, as well as an instance of the screen declared with your game engine variables:
// The Selection screen for choosing loopy private SelectLoopyScreen selectScreen = null; // Is the selection screen currently being shown private bool isSelectScreenShowing = false; // Textures that will be shared throughout UI screens private Texture buttonTexture = null;
Naturally, you need to create this object as well. Notice that you've also declared the texture that contains the shared texture for the buttons. Find the spot where you created the main screen in the OnCreateDevice method earlier and add this code directly after that:
// Create the textures for the UI screens buttonTexture = TextureLoader.FromFile(device, GameEngine.MediaPath + "buttons.png"); // Create the screen for selecting loopy selectScreen = new SelectLoopyScreen(device, buttonTexture, screenWidth, screenHeight); selectScreen.Selected +=new EventHandler(OnLoopySelected);
After you create the shared texture, you use that to create the new UI screen. Because you've now created two new resources, you must not forget to clean them up, so add this code to your game engine's OnDestroyDevice method directly after the cleanup of the first user screen:
if (selectScreen != null) { selectScreen.Dispose(); } // Clean up the textures used for the UI Screens if (buttonTexture != null) { buttonTexture.Dispose(); }
As with the main menu screen, you need to update the render method to ensure that this screen gets rendered as well. Because you already have an if statement for the first screen in that method, you can add this code to the else statement:
else if (isSelectScreenShowing) { selectScreen.Draw(timer.TotalTime); }
else if (isSelectScreenShowing) { selectScreen.OnMouseMove(x, y); } As well as the when it is: else if (isSelectScreenShowing) { selectScreen.OnMouseClick(x, y); } And naturally the OnKeyEvent method as well: else if (isSelectScreenShowing) { selectScreen.OnKeyDown(key); }
Before you add the event handler for the Selected event, remember from earlier that you had to set up a material for Loopy because he is going to be lit during the scene. To this point, you haven't added any lights to your scene yet, so you want to do this now. You use what is called a directional light. Think of a directional light as something like the sun in the sky. It is a never-ending light source that shines in a certain direction. Although most modern cards support directional lights, and at least eight in hardware, it's entirely possible that your device might not. The IsDeviceAcceptable method is checked for at least a single directional light so you can be sure that any device created has this support. Lights are lost when a device is reset, so the best place to actually define the lights is in the OnResetDevice method you've already declared. Add the code in Listing 6.14 to this method now.
Listing 6.14. Setting Up Lights
// Set up the light // Light 0 will be the level light localDevice.Lights[0].DiffuseColor = new ColorValue(1.0f, 1.0f, 1.0f, 1.0f); localDevice.Lights[0].Direction = LevelLight; localDevice.Lights[0].Type = LightType.Directional; // Light 1 will be the select loopy light localDevice.Lights[1].DiffuseColor = new ColorValue(1.0f, 1.0f, 1.0f, 1.0f); localDevice.Lights[1].Direction = SelectLoopyLight; localDevice.Lights[1].Type = LightType.Directional; EnableLights();
As you see here, if directional lights are available, you actually set two different lights, one with a direction of LevelLight, the other with the direction SelectLoopyLight. You haven't declared these constants yet but can do so now:
// Light constants private static readonly Vector3 SelectLoopyLight = new Vector3(0, 0.0f, 1.0f); private static readonly Vector3 LevelLight = new Vector3(0, -0.6f, 0.4f);
You actually have two separate lights for the game, one that is shown when the selection screen is showing and the other during the course of the main game. You might not have the game being rendered yet, but because you're setting up the lights anyway, you might as well do both. As you see, each light has a color of pure white, much like the sprite's color, with only the direction changing between the two. The selection light points directly at Loopy on the z axis. The "main" light points at an angle down. If directional lights aren't available, the ambient color is set to white. Ambient light ensures that everything is the correct "color," but there will be no shading of the objects. Everything is rendered the same color. Ambient color is by far the most unrealistic-looking type of light.
Notice that after the lights are set up, you make a call to EnableLights. Only one of the lights needs to be in use at any given time, so any time the lights are updated, you use this method to turn on the correct light. See Listing 6.15 for the code.
Listing 6.15. Enabling the Correct Light
private void EnableLights() { // Turn on the correct light, turn off the other light if (isSelectScreenShowing) { device.Lights[1].Enabled = true; device.Lights[0].Enabled = false; } else { device.Lights[0].Enabled = true; device.Lights[1].Enabled = false; } }
If there isn't any support for directional lights, there is naturally nothing more you can do for this method, so you can just return. Otherwise, you turn on the light at index 1 if the select screen is showing and turn off the light at index 0. If the select screen is showing, you simply reverse which light is currently on. Pretty simple stuff.
You can now fix your initial event handler for creating a new game. Replace the blank method with this one:
private void OnNewGame(object sender, EventArgs e) { // Show the select screen isMainMenuShowing = false; isSelectScreenShowing = true; // Fix the lights EnableLights(); }
After you click the New button, it turns off the main menu by switching to the selection screen and calls the EnableLights method to ensure that the correct light is turned on. You can go ahead and add a blank event handler for the Loopy selection now. You won't actually respond to the event until a later chapter, but you will want to compile your application and see your new screen:
private void OnLoopySelected(object sender, EventArgs e) { }
Comments