Click to Rate and Give Feedback
MSDN
MSDN Library
XNA Game Studio
XNA Game Studio 2.0
 Tutorial 2: Making Your Model Move ...
XNA Game Studio 2.0
Tutorial 2: Making Your Model Move Using Input
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.
Note
This tutorial builds on code you have written during the previous tutorial: Tutorial 1: Displaying a 3D Model on the Screen. Follow the steps in the previous tutorial before starting this tutorial.

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.

  • Make sure your project from Tutorial 1: Displaying a 3D Model on the Screen is open. If it isn't, open it by selecting the File menu, clicking Open Project, and browsing to your project.
  • View the code by double-clicking Game1.cs in Solution Explorer.
  • In the code, find the Update method. Modify it to look like this:

    C#
    // Set the velocity of the model, applied each frame to the model's position.
    Vector3 modelVelocity = Vector3.Zero;
    
    protected override void Update(GameTime gameTime)
    {
        // Allows the game to exit
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();
    
        // Get some input.
        UpdateInput();
    
        // Add velocity to the current position.
        modelPosition += modelVelocity;
    
        // Bleed off velocity over time.
        modelVelocity *= 0.95f;
    
        base.Update(gameTime);
    }
    

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.

  • Pressing left or right on the left thumbstick will increase or decrease the value of the modelRotation variable by some amount.
  • Pressing on the right trigger will add a vector in the direction of our modelRotation variable to our modelVelocity vector.
  • Pressing the A button will reset the position, velocity, and rotation values of the model to "warp" the ship back to the center of the screen.

    Note
    Both the triggers and the thumbsticks are analog controls, meaning that they can report their movements in varying amounts, rather than just on or off. On the Xbox 360 Controller, the two thumbsticks and two triggers are analog controls, and all other buttons are digital buttons.

Let's code it!

  • Find some empty space in your code below the Update method.
  • Add a new method called protected void UpdateInput().
  • Modify the method to look like this:

    C#
    protected void UpdateInput()
    {
        // Get the game pad state.
        GamePadState currentState = GamePad.GetState(PlayerIndex.One);
        if (currentState.IsConnected)
        {
            // Rotate the model using the left thumbstick, and scale it down.
            modelRotation -= currentState.ThumbSticks.Left.X * 0.10f;
    
            // 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;
    
            // Finally, add this vector to our velocity.
            modelVelocity += modelVelocityAdd;
    
            GamePad.SetVibration(PlayerIndex.One, currentState.Triggers.Right,
                currentState.Triggers.Right);
    
    
            // 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;
            }
        }
    }
    

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.
Tags What's this?: Add a tag
Community Content   What is Community Content?
Add new content RSS  Annotations
Basic Model Class - For further experimentation.      ZLoserKing   |   Edit   |  

Once you've played with the tutorial you may want to add more objects to your scene.

By placing the model in a class with a position and rotation vector you'll find it easier to experiment with more objects.

 
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
#endregion
namespace YourGameName
{
public class TheModel
    {
private Model model;
private Vector3 position = Vector3.Zero;
private Vector3 rotation = Vector3.Zero;
        public TheModel(String AssetPath, ContentManager content)
{
model = content.Load<Model>(AssetPath);
}
        public Model ModelHeld
{
get
{
return model;
}
}
        #region position
        public Vector3 Position
{
get{return position;}
}
        public float pX
{
set{position.X = value;}
get{return position.X;}
}
        public float pY
{
set{ position.Y = value;}
get { return position.Y;}
}
        public float pZ
{
set { position.Z = value;}
get{ return position.Z;}
}
        #endregion #position
        #region rotation
        public float rX
{
get { return rotation.X; }
set { rotation.X = value; }
}
        public float rY
{
get { return rotation.Y; }
set { rotation.Y = value; }
}
        public float rZ
{
get { return rotation.Z; }
set { rotation.Z = value; }
}
        #endregion rotation
        public Matrix getRotation
{
get
{
return Matrix.CreateRotationX(MathHelper.ToRadians(rX)) * Matrix.CreateRotationY(MathHelper.ToRadians(rY)) * Matrix.CreateRotationZ(MathHelper.ToRadians(rZ));
}
}
}
}
Flag as ContentBug
Processing
© 2008 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Page view tracker