Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

.NET

Using XNA Input for Controllers


Draw Methods

The final game screen that you see is made up of many independent components. I've broken the task of rendering all of these components into separate, specialized drawing methods.

  • DrawButton renders a graphic based on a digital button's state (pressed or released).
  • DrawHBar renders a slider bar and its arrow to reflect the state of one of the thumbstick's x-axis values.
  • DrawVBar renders a slider bar and its arrow to reflect the state of one of triggers or one of the thumbstick's y-axis values. Since triggers have a range of values from zero to one, and thumbsticks report values between negative one and positive one, this method assumes that the vertical bar represents a trigger. By passing it a value of -- 1 for the optional min parameter, the bar can represent the full range of a thumbstick.
  • DrawGraph fills the screen with the graph paper tile, rendered relative to the ship's current location. The results of this render step will be overlayed with the background image and the graph paper will show through the viewport. You could save some processing by only rendering the part of the paper that will be visible through the viewport, but filling the entire screen means that you can move your viewport to another part of the screen in your graphics editor without editing the rendering code.
  • DrawCursor draws the ship, at its current rotation. For details on the implementation of these methods, keep reading. They're described in greater detail in the section entitled, "Drawing the Game."

    Update()

    The Update method of this game includes logic to poll the controllers and update the ship's location based on the player's input. The ship itself doesn't actually move on the screen. The paper texture below the ship moves to show the relative direction and speed of the ship.

    The Update method is where the code that tracks the state of each of the controller buttons is housed. And this is also where the vibration motors on the controller are set to rumble as long as the A button is pressed on the controller. While the state of each of the four controllers is polled, only the controller in port one can affect the state of the button images on the screen. The other controller states are only used to detect when those controllers are added or removed, updating the port connection indicator images.

    /// run logic such as updating the world
    protected override void Update(GameTime gameTime)
    {
    // capture pad state once per frame
    m_pad1 = GamePad.GetState(PlayerIndex.One);
    m_pad2 = GamePad.GetState(PlayerIndex.Two);
    m_pad3 = GamePad.GetState(PlayerIndex.Three);
    m_pad4 = GamePad.GetState(PlayerIndex.Four);
    // only process input from player one, and only if
    // the controller is connected
    if (m_pad1.IsConnected)
    {
       // combine states to rotate left, true if any are pressed
       bool bLeft = m_pad1.DPad.Left == ButtonState.Pressed;
       bLeft |= m_pad1.ThumbSticks.Left.X < 0;
       bLeft |= m_pad1.ThumbSticks.Right.X < 0;
       if (bLeft) { m_angle -= 5.0f; }
       // combine states to rotate right, true if any are pressed
       bool bRight = m_pad1.DPad.Right == ButtonState.Pressed;
       bRight |= m_pad1.ThumbSticks.Left.X > 0;
       bRight |= m_pad1.ThumbSticks.Right.X > 0;
       if (bRight) { m_angle += 5.0f; }
       // distance to travel per frame, split into X and Y
       float dx = (float)Math.Cos(m_angle * ToRadians);
       float dy = (float)Math.Sin(m_angle * ToRadians);
       // check button states to determine thrust
       float fMove = 0.0f; // assume no movement
       // is the player moving the ship?
       if (m_pad1.ThumbSticks.Left.Y != 0.0f)
       {
          fMove = m_pad1.ThumbSticks.Left.Y;
       }
       else if (m_pad1.ThumbSticks.Right.Y != 0.0f)
       {
          fMove = m_pad1.ThumbSticks.Right.Y;
       }
       else if (m_pad1.Triggers.Right != 0.0f)
       {
          fMove = m_pad1.Triggers.Right;
       }
       else if (m_pad1.Triggers.Left != 0.0f)
       {
          fMove = -m_pad1.Triggers.Left;
       }
       else if (m_pad1.DPad.Up == ButtonState.Pressed)
       {
       // treat as max thumbstick Y
          fMove = 1.0f;
       }
       else if (m_pad1.DPad.Down == ButtonState.Pressed)
       {
       // treat as min thumbstick Y
          fMove = -1.0f;
       }
       // ship's thrust is relative to analog button states
          m_GraphOrigin.X -= dx * fMove;
          m_GraphOrigin.Y -= dy * fMove;
       // make sure that 0 <= graph origin x <= 50
       while (m_GraphOrigin.X < 0.0f)
       {
          m_GraphOrigin.X += 50.0f;
       }
       while (m_GraphOrigin.X > 50.0f)
       {
          m_GraphOrigin.X -= 50.0f;
       }
       // make sure that 0 <= graph origin y <= 50
       while (m_GraphOrigin.Y < 0.0f)
      {
          m_GraphOrigin.Y += 50.0f;
      }
      while (m_GraphOrigin.Y > 50.0f)
      {
          m_GraphOrigin.Y -= 50.0f;
      }
      // shake the controller while the A button is pressed
      if (m_pad1.Buttons.A == ButtonState.Pressed)
      {
      GamePad.SetVibration(PlayerIndex.One, 1.0f, 1.0f);
      }
      else
      {
      GamePad.SetVibration(PlayerIndex.One, 0f, 0f);
      }
      }
      base.Update(gameTime);
    }
    

    Drawing the Game

    The standard Draw method of this game includes logic to build the screen, piece by piece. First, the graph paper is drawn via a call to DrawGraph. Then, the background image is rendered over the graph tiles so that they can show through the viewport. Then, all of the digital and analog buttons are drawn, along with the four controller connection states, via a call to DrawButtons (note the plural version). And finally, the ship is drawn via a call to DrawCursor.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.