This article details how to use the XNA Framework Input API to take user input from an Xbox 360 Controller and apply it to the model displayed in Tutorial 1.
The Complete Sample
The code in this tutorial illustrates the technique described in the text. A complete code sample for this tutorial is available for you to download, including full source code and any additional supporting files required by the sample.
Step 1: Connect Your Xbox 360 Controller
The first step in this tutorial is to make sure you can provide some input to your game. We'll use the Xbox 360 Controller. Designed for use with both a Windows computer and an Xbox 360 console, the controller features many analog and digital inputs, as well as vibration motors to give feedback to the user.
This tutorial uses only the Xbox 360 Controller, but there are more ways to take input: the XNA Framework has support for keyboard and mouse devices. Mouse devices are supported only on Windows, not on Xbox 360. For more information on the different input types, see Input Overview.
For now, connect your Xbox 360 Controller and get ready to code!
Step 2: Create Variables to Turn and Move the Model
We want our ship to move around on the screen. To do that, we'll need to create some variables to track the position and orientation of our model in the world.
Fortunately, from our last tutorial (Tutorial 1: Displaying a 3D Model on the Screen), we have two variables to do just that: modelPosition, which is a three-dimensional vector, and modelRotation, which is a floating-point value.
Currently, this system allows three degrees of translation (changing position in the world), but only one degree of rotation (changing orientation). For this demonstration, we will use that limitation to simplify our input. In many 3D games, there are three degrees of translation, and three degrees of rotation, but this is a good start.
What we can do right now to make input a little more interesting is add another vector for velocity. By updating the position with the velocity each frame, our 3D model can accelerate and decelerate smoothly. Let's try it.
The code you've just added to input runs every frame, and does a few different things. First, it gets rid of the code that automatically rotates the ship; you'll be controlling that using your controller. Next, it calls a method named UpdateInput. That method does not exist yet; you'll have to create it in the next step. Last, it adds the velocity of our model to its position, moving it in the world by its velocity, and decays the velocity so that eventually the model will slow down.
Step 3: Take Input from the User
Now that the model is set up to move with velocity, you now need to provide some logic that will change the velocity based on controller input.
A simple system that we can use is an orientation thrust method: in essence, you can point the front of your model in different directions using your controller's thumbstick, then apply thrust in the direction you are pointing using your controller's trigger. By building up thrust in a direction, the model will begin to move. This is similar to how the ships in the Spacewar Windows Starter Kit (2.0) move.
We can map our controls to the game this way.
Let's code it!
That method does a lot. Let's take it piece by piece to investigate exactly what you're doing with input and the model.
// Get the game pad state.
GamePadState currentState = GamePad.GetState(PlayerIndex.One);
This call to GetState retrieves a GamePadState object, which contains the information we need about the controller—in this case, thumbstick and trigger positions.
// Rotate the model using the left thumbstick, and scale it down.
modelRotation -= currentState.ThumbSticks.Left.X * 0.10f;
Retrieving the x-axis value of the left thumbstick (left and right movement) returns a value that is added to the modelrotation variable. The value is scaled down so that the rotation isn't too fast.
// Create some velocity if the right trigger is down.
Vector3 modelVelocityAdd = Vector3.Zero;
// Find out what direction we should be thrusting, using rotation.
modelVelocityAdd.X = -(float)Math.Sin(modelRotation);
modelVelocityAdd.Z = -(float)Math.Cos(modelRotation);
// Now scale our direction by how hard the trigger is down.
modelVelocityAdd *= currentState.Triggers.Right;
A little math here helps translate the rotation of the ship into a vector. Taking the sine value of the rotation gives us the proper amount of X (left and right) movement, and the cosine gives us the Z (forward and back) movement. Then, we take the vector and lengthen it by how hard the player is holding down the right trigger.
// Finally, add this vector to our velocity.
modelVelocity += modelVelocityAdd;
Finally, the created vector is added to the current velocity vector to create the final velocity vector that will be applied to move the model around.
GamePad.SetVibration(PlayerIndex.One, currentState.Triggers.Right,
currentState.Triggers.Right); We're using the right trigger values to give some feedback to the player with the Xbox 360 Controller vibration motors, using SetVibration . The Xbox 360 Controller has two motors that run at different speeds, so experiment to find the best combination for the action that's happening in the game.
// In case you get lost, press A to warp back to the center.
if (currentState.Buttons.A == ButtonState.Pressed)
{
modelPosition = Vector3.Zero;
modelVelocity = Vector3.Zero;
modelRotation = 0.0f;
} This little extra will move the model back to its original position and orientation in case it leaves the screen.
Congratulations!
At this point, your ship moves and gives you feedback through your Xbox 360 Controller. The player is in control of the action.
When you're ready, let's add the final element—audio—to get you on your way. Once the player can control the action, and see and hear the results of their actions, you're well on your way to creating a game.
Next...
Ideas to Expand
Want to play around some more with input? Try these ideas.
- Change the game to view your model from the top, as in a top-down arcade game. (Hint: Play with the cameraPosition vector; note that you can't set it exactly up and down because the camera vector cannot be the same as the "up" vector.)
- Scale the vibration to occur more powerfully as the ship approaches the viewer. (Hint: Use the distance between modelPosition and cameraPosition.)
- Try using a keyboard to control the ship; see the Keyboard class. (Hint: You can plug a USB keyboard into your Xbox 360 console.)
-
Get more ideas and resources at XNA Creators Club Online.