Game Development Community

dev|Pro Game Development Curriculum

Proper Fps Joystick\Gamepad

by Derrick (sypherce) Wirth · 12/23/2004 (10:15 pm) · 5 comments

Basically what this code does it make the pitch and yaw work on a joystick/gamepad. I couldn't find any documentation on how to do this, but I did find one good peice in an old forum page, wasn't complete, but I figured out how to fix it, and here it is...

In "GameConnectionsMove.cc" after:
F32 MoveManager::mRightAction = 0;
add
bool MoveManager::mMouseActive = true;
Also replace:
MoveManager::mPitch = 0;
MoveManager::mYaw = 0;
MoveManager::mRoll = 0;
with:
if(MoveManager::mMouseActive == true)
{
    MoveManager::mPitch = 0;
    MoveManager::mYaw = 0;
    MoveManager::mRoll = 0;
}
Then after:
Con::addVariable("mvRightAction", TypeF32, &mRightAction);
add
Con::addVariable("mvMouseActive", TypeBool, &mMouseActive);

Last peice of c++ code to edit is in "MoveManager.h" after:
static F32 mRightAction;
add
static bool mMouseActive;

Now for some scripting...
In "default.bind.cs" after
function pitch(%val)
{
   if($pref::Input::InvertMouse)
   {
      $mvPitch -= getMouseAdjustAmount(%val);
   }
   else
   {
	  $mvPitch += getMouseAdjustAmount(%val);
   }
}
add
function joyyaw(%val)
{
   if ($pref::Input::Deadzone < %val | - $pref::Input::Deadzone > %val)
   {
      $mvYaw = %val * $pref::Input::Sensitivity;
   }
   else
   {
      $mvYaw = 0;
   }
}

function joypitch(%val)
{
   if ($pref::Input::Deadzone < %val | - $pref::Input::Deadzone > %val)
   {
      if($pref::Input::InvertMouse)
      {
         $mvPitch = (- %val) * $pref::Input::Sensitivity;
      }
      else
      {
	     $mvPitch = %val * $pref::Input::Sensitivity;
      }
      
   }
   else
   {
      $mvPitch = 0;
   }
}

function joymovex(%val)
{
   if ($pref::Input::Deadzone < %val | - $pref::Input::Deadzone > %val)
   {
      $mvRightAction = %val * $pref::Input::Sensitivity;
   }
   else
   {
      $mvRightAction = 0;
   }
}

function joymovey(%val)
{
   if ($pref::Input::Deadzone < %val | - $pref::Input::Deadzone > %val)
   {
      $mvBackwardAction = %val * $pref::Input::Sensitivity;
   }
   else
   {
      $mvBackwardAction = 0;
   }
}

In "Config.cs" after:
moveMap.bind(mouse0, "yaxis", pitch);
add
moveMap.bind(joystick0, "xaxis", joymovex);
moveMap.bind(joystick0, "yaxis", joymovey);
moveMap.bind(joystick0, "zaxis", joyyaw);
moveMap.bind(joystick0, "rzaxis", joypitch);
That should be it, just type "$pref::Input::Deadzone=0.25;", "$pref::Input::Sensitivity=1;", "$mvMouseActive = false;" in the console and it should switch settings, you might want to disable the mouse though, just to make it look more professional.

About the author

Recent Blogs


#1
12/22/2005 (11:35 pm)
#2
12/22/2005 (11:40 pm)
This bit:

MoveManager::mPitch = 0;
MoveManager::mYaw = 0;
MoveManager::mRoll = 0;

is in GameConnection::getNextMove

I thought it was the initialization at the top of the file and posted an error report here - I was wrong though. Thought I'd mention where to find this in case anyone else gets confused like me.
#3
02/10/2007 (11:05 am)
I'd make one extra change to this...

The right joystick's up/down motion is currently setting the amount to *CHANGE* the pitch by in the next move update. I want a 1-to-1 mapping with the right joystick's y-axis and the head-look angle. When the stick is all the way up, I want the player to be looking all the way up. When the stick is all the way down, I want the player to look down (or vice versa for invert look). When the stick is centered, I want the player to be looking straight forward. The miniscule change below allows for that type of control.

In player.cc, I changed Player::UpdateMove(const Move* move) like so...

original (around line 1401 in mine...might be a little off, though):
mHead.x = mClampF(mHead.x + p,mDataBlock->minLookAngle,
                    mDataBlock->maxLookAngle);

to...

mHead.x = mClampF(p,mDataBlock->minLookAngle,
                    mDataBlock->maxLookAngle);

(a big whopping change of removing the "mHead.x +")


Now adjust the Vertical Sensitivity to be 1.0. Or, even better, use some of the code from the Marble Blast Article on analog input to remove your deadzone values and prevent jumpiness from 0 to 0.26 or whatever your deadzone is. My code is:

function correctedStickValue(%val)
{

  if ($pref::Input::Deadzone < %val | - $pref::Input::Deadzone > %val)
  {
     %rV = (mAbs(%val) - $pref::Input::Deadzone)/(1.0 - $pref::Input::Deadzone);
  }else{
     %rV = 0;
  }
  
  //fancy e^x code not needed for me, just fix the sign and pass it back

  if(%val < 0) %rv *= -1.0;
  return %rv;
  
}
#4
03/15/2007 (8:47 pm)
Will,
I tried your method of connecting the joystick axis directly to the output and for a game pad it is terrible. I would do it for a joystick, but not a game pad. It is very hard to control pitch with it springing back so fast.
#5
02/20/2008 (5:19 pm)
Anyone have any thoughts on how I can use the right analog to adjust yaw continuously? In other words, if I'm holding it all the way to the right, my yaw continues to adjust to the right. Currently, once it reaches full right (or whatever direction, for that matter), or %val = 1, it no longer triggers the function.