Before you can compile this code, you need to add the CreateTexture method from Listing 6.10.
Listing 6.10. Creating the Loopy Texture
private void CreateTexture(Device device)
{
if (loopyTexture != null)
{
// Destroy and re-create a new texture
loopyTexture.Dispose();
}
loopyTexture = TextureLoader.FromFile(device,
GetTextureFileFromColor(loopyColor));
}
private static string GetTextureFileFromColor(PlayerColor color)
{
switch(color)
{
case PlayerColor.Blue:
return GameEngine.MediaPath + "LoopyBlue.bmp";
case PlayerColor.Green:
return GameEngine.MediaPath + "LoopyGreen.bmp";
case PlayerColor.Purple:
return GameEngine.MediaPath + "LoopyPurple.bmp";
case PlayerColor.Red:
return GameEngine.MediaPath + "LoopyRed.bmp";
case PlayerColor.Yellow:
return GameEngine.MediaPath + "LoopyYellow.bmp";
case PlayerColor.Gray:
return GameEngine.MediaPath + "LoopyGray.bmp";
default:
throw new ArgumentException("color",
"An invalid color was passed in.");
}
}
Because this method will potentially be called numerous times, you want to ensure that any loaded texture is destroyed before you create a new one. Then you can create the texture, but the enumeration alone doesn't tell you which texture file you need to use. Another helper method translates the color from the enumeration to a string representation of the filename the texture resides in. Next, add the rendering code for this screen. You'll find the implementation in Listing 6.11.
Listing 6.11. Rendering the Selection Screen
///
/// Render the buttons
///
public void Draw(float totalTime)
{
// Render Loopy Should be "Set the world transform"
storedDevice.Transform.View = Matrix.LookAtLH(
CameraPos, CameraTarget, CameraUp);
storedDevice.Transform.World = Matrix.RotationY(totalTime * 2);
storedDevice.SetTexture(0, loopyTexture);
storedDevice.Material = loopyMaterial;
loopyMesh.DrawSubset(0);
// Start rendering sprites
base.BeginSprite();
// Draw the background
base.Draw();
// Now the buttons
leftButton.Draw();
rightButton.Draw();
okButton.Draw();
// You're done rendering sprites
base.EndSprite();
}
The first thing you'll probably notice is that you aren't overriding the Draw method from the base class but are instead defining your own. You want to make sure that Loopy spins around as the selection screen appears, and you need to know the time from the timer. Remember from an earlier chapter, the View transform defines where the camera is located, where it is looking, and what direction "up" is. In this case, you are using constants that you haven't defined yet, so add these to this class now:
private static readonly Vector3 CameraPos = new Vector3(0, 20.0f, -85.0f);
private static readonly Vector3 CameraTarget = new Vector3(0,20,0);
private static readonly Vector3 CameraUp = new Vector3(0, 1.0f, 0);
After you set up the camera, you update the World transform to do the rotation of Loopy. Notice that you simply rotate Loopy on the Y axis based on the current time of the application. Multiplying the value by two increases the rotation speed. Next, you can render Loopy just as you rendered the sky box earlier. Simply set the correct texture on the device and the material and call the DrawSubset method on your mesh. Because there is only one subset in the Loopy mesh, there is no need to do this in a loop; you can simply pass in 0 for the attribute ID.
The rest of the rendering method is pretty much the same as the last user screen you did, so there's no need to go through that once more. You do still need to add the event handlers for the buttons you declared earlier, so use Listing 6.12 to add them to your class now.
Listing 6.12. Handling Button Click Events
///
/// Fired when the left button is clicked
///
private void OnLeftButton(object sender, EventArgs e)
{
loopyColor--;
if (loopyColor < PlayerColor.Min)
loopyColor = PlayerColor.Max;
// Create the loop texture
CreateTexture(storedDevice);
}
///
/// Fired when the right button is clicked
///
private void OnRightButton(object sender, EventArgs e)
{
loopyColor++;
if (loopyColor > PlayerColor.Max)
loopyColor = PlayerColor.Min;
// Create the loop texture
CreateTexture(storedDevice);
}
///
/// Fired when the ok button is clicked
///
private void OnSelectButton(object sender, EventArgs e)
{
if (Selected != null)
Selected(this, e);
}
The code here is relatively straightforward. Pressing the left button decrements the current color, and pressing the right increments it. Each of these operations handles the wrapping if you've gone past the bounds set for that button and then calls the CreateTexture method to ensure that the updated texture is loaded. When you click the Yes button, it means you've selected which version of Loopy you want to use, and the Selected event is fired. Obviously, you need to add the handlers for the mouse and keyboard events for this screen as well, so you find them in Listing 6.13.
Listing 6.13. Handling User Input
public void OnMouseMove(int x, int y)
{
leftButton.OnMouseMove(x, y);
rightButton.OnMouseMove(x, y);
okButton.OnMouseMove(x, y);
}
public void OnMouseClick(int x, int y)
{
leftButton.OnMouseClick(x, y);
rightButton.OnMouseClick(x, y);
okButton.OnMouseClick(x, y);
}
public void OnKeyPress(System.Windows.Forms.Keys key)
{
switch(key)
{
case Keys.Enter:
// Enter is the same as selecting loopy
OnSelectButton(this, EventArgs.Empty);
break;
case Keys.Left:
// Same as pressing the left arrow
OnLeftButton(this, EventArgs.Empty);
break;
case Keys.Right:
// Same as pressing the left arrow
OnRightButton(this, EventArgs.Empty);
break;
}
}
The mouse events behave exactly the same as they did last time, but the keystrokes are slightly different. You still use Enter to go to the next step (in this case, actually playing the game), but there are two new keys as well. Clicking the left and right arrows is the same as pressing the left or right user button. |