Space Camera


The SpaceCamera class is a lot more complex than the SimpleCamera class, and even the ChaseCamera class for the racing game looks simpler. The main reason for the complex code of the SpaceCamera class is the fact that it was the first space camera class I ever wrote and getting the Quaternion math is not that easy. The camera class also supports three modes for the menu camera, for the in-game camera, and a free camera mode for unit tests. The SpaceCamera of Rocket Commander XNA is a little bit simpler because the Quaternion math was removed and the controlling of the rocket is a little bit simplified by just allowing pitch and yaw rotations. The roll rotation around the z axis of the rocket is now handled by the engine automatically, which makes it easier to fly around and not get disoriented. The main reason for this change is to allow the player to control the rocket nicely with the Xbox 360 controller, which is harder than in the original Rocket Commander game that also supports the Xbox 360 controller.

Take a quick look at the most important method in SpaceCamera that handles all the player input and updates the camera position each frame:

  /// <summary> /// Handle player input for the game. /// This is where all the input happens in the game. /// </summary> private void HandlePlayerInput() {   if (Player.lifeTimeMs < Player.LifeTimeZoomAndAccelerateMs)   {     float speedPercentage =       Player.lifeTimeMs / (float)Player.LifeTimeZoomAndAccelerateMs;     // Use quadradric product for better speed up effect     Player.SetStartingSpeed(speedPercentage * speedPercentage);     // Always move forward     Translate(Player.Speed * BaseGame.MoveFactorPerSecond *       Player.MovementSpeedPerSecond, MoveDirections.Z);     if (Player.gameTimeMs < 100)     {       yawRotation = 0;       pitchRotation = 0;       pos = Vector3.Zero;     } // if   } // if 

The preceding code increases the speed of the rocket in Rocket Commander and it also resets the rotation and position values if the game just started. Next you do some checking if the game is over and handle the special case to allow moving. Then the mouse and keyboard input is handled. This is pretty much the original code from the very first version I implemented for the SpaceCamera class; all the other code was added later to add more input devices:

  #region Mouse/keyboard support if (Input.MouseXMovement != 0.0f ||   Input.MouseYMovement != 0.0f) {   float xMovement = Input.MouseXMovement;   float yMovement = Input.MouseYMovement;   Rotate(RotationAxis.Yaw, -xMovement * rotationFactor);   Rotate(RotationAxis.Pitch, -yMovement * rotationFactor); } // if (Mouse.left.Pressed) // Use asdw (qwerty keyboard), aoew (dvorak keyboard) or // cursor keys (all keyboards?) to move around. // Note: If you want to change any keys, use Settings! if (Input.Keyboard.IsKeyDown(moveForwardKey) ||   Input.Keyboard.IsKeyDown(Keys.Up) ||   Input.Keyboard.IsKeyDown(Keys.NumPad8)) {   float oldPlayerSpeed = Player.Speed;   Player.Speed += 0.75f * BaseGame.MoveFactorPerSecond; } // if if (Input.Keyboard.IsKeyDown(moveBackwardKey) ||   Input.Keyboard.IsKeyDown(Keys.Down) ||   Input.Keyboard.IsKeyDown(Keys.NumPad2)) {   float oldPlayerSpeed = Player.Speed;   Player.Speed -= 0.75f * BaseGame.MoveFactorPerSecond; } // if if (Player.speedItemTimeout > 0) {   Player.speedItemTimeout -= BaseGame.ElapsedTimeThisFrameInMs;   if (Player.speedItemTimeout < 0)   {     Player.speedItemTimeout = 0;     // Reduce to max. possible speed     if (Player.Speed > Player.MaxSpeedWithoutItem)       Player.Speed = Player.MaxSpeedWithoutItem;   } // if } // if // Adjust current speed by the current player speed. float moveFactor = Player.Speed * maxMoveFactor; float slideFactor = maxSlideFactor; // Always move forward Translate(+moveFactor, MoveDirections.Z); // Slide if (Input.Keyboard.IsKeyDown(moveLeftKey) ||   Input.Keyboard.IsKeyDown(Keys.Left) ||   Input.Keyboard.IsKeyDown(Keys.NumPad4)) {   consumedAdditionalFuel = true;   Translate(-slideFactor, MoveDirections.X); } // if if (Input.Keyboard.IsKeyDown(moveRightKey) ||   Input.Keyboard.IsKeyDown(Keys.Right) ||   Input.Keyboard.IsKeyDown(Keys.NumPad6)) {   consumedAdditionalFuel = true;   Translate(+slideFactor, MoveDirections.X); } // if // Up/down if (Input.Keyboard.IsKeyDown(Keys.F)) {   Translate(+slideFactor, MoveDirections.Y); } // if if (Input.Keyboard.IsKeyDown(Keys.V)) {   Translate(-slideFactor, MoveDirections.Y); } // if #endregion 

To support the Xbox 360 controller the following code was added in the beginning of 2006 just one day before the game was released. Implementing XInput was very easy and I’m glad XNA uses XInput for all the input classes. The general idea to have all input devices in one namespace is very good in XNA; the only problematic part there is the missing mouse class for the Xbox 360 runtimes. Even if the class is not supported, Microsoft should implement a dummy class to have the code at least compile without having to change all input code that optionally uses a mouse. Well, you fixed that with your own Input class anyway.

Here’s the Xbox 360 controller code in Rocket Commander XNA:

  #region Input support for the XBox360 controller // 2006-03-09: Added Input support rotationFactor = 3.0f * BaseGame.MoveFactorPerSecond; // Change camera rotation when right thumb is used. if (Input.GamePad.ThumbSticks.Right.X != 0.0f ||   Input.GamePad.ThumbSticks.Right.Y != 0.0f) {   float xMovement = Input.GamePad.ThumbSticks.Right.X;   float yMovement = Input.GamePad.ThumbSticks.Right.Y;   Rotate(RotationAxis.Yaw, -xMovement * rotationFactor);   Rotate(RotationAxis.Pitch, yMovement * rotationFactor); } // if (Mouse.left.Pressed) // Use left thumb for moving around if (Input.GamePad.ThumbSticks.Left.Y != 0) {   float oldPlayerSpeed = Player.Speed;   Player.Speed += 0.75f * Input.GamePad.ThumbSticks.Left.Y *     BaseGame.MoveFactorPerSecond;   // Only decrease fuel if change happened   if (oldPlayerSpeed != Player.Speed)     consumedAdditionalFuel = true; } // if // Slide if (Input.GamePad.ThumbSticks.Left.X != 0) {   consumedAdditionalFuel = true;     Translate(slideFactor * Input.GamePad.ThumbSticks.Left.X * 2,       MoveDirections.X);   } // if   #endregion } // HandlePlayerInput() 

You can see all the code that used a lot of helper methods like Rotate and Translate and made heavy use of the Input class properties and some helper values from the BaseGame class like MoveFactorPerSecond.

Translate moves the current camera along the x, y, or z axis. The x axis is used for sliding to the left and right, which can be done with the A and D keys or the cursor keys in Rocket Commander. The y axis allows you to move up and down and the z axis allows you to move forward and backward. In Rocket Commander the z axis is the most important and you fly with very high speed moving on this axis.

  /// <summary> /// Translate into x, y or z axis with a specfic amount. /// </summary> /// <param name="amount">Amount</param> /// <param name="direction">Direction</param> private void Translate(float amount, MoveDirections direction) {   Vector3 dir =     direction == MoveDirections.X ? XAxis :     direction == MoveDirections.Y ? YAxis : ZAxis;   pos += dir * amount; } // Translate(amount, direction) 

Finally, the Rotate method is used to rotate the camera around. Yaw rotates you left and right and pitch allows you to rotate up and down. The original Rocket Commander used a Quanternion here and it allowed you to roll around the rocket too. In Rocket Commander XNA the rocket is automatically aligned for you to make it easier on the Xbox 360.

  /// <summary> /// Rotate around pitch, roll or yaw axis. /// </summary> /// <param name="axis">Axis</param> /// <param name="angle">Angle</param> private void Rotate(RotationAxis axis, float angle) {   if (axis == RotationAxis.Yaw)     yawRotation -= angle;   else     pitchRotation -= angle; } // Rotate(axis, angle) 

All camera classes have unit tests to test them out. Make sure you test them if you try to create your own camera class or run into troubles.




Professional XNA Game Programming
Professional XNA Programming: Building Games for Xbox 360 and Windows with XNA Game Studio 2.0
ISBN: 0470261285
EAN: 2147483647
Year: 2007
Pages: 138

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