Using NON xbox Controllers with XNA 3.1
February 23, 2011
One of the problems with xna is that it cannot use non-xbox controllers, which, makes it harder to develop a PC game. So I have written a class to use a general game pad to solve this and for future reference, I will note it here. This example was developed using xna3.1 and Visual Studio 2008.
There are few options on how to use non-xbox controllers in xna. The examples are:
- Using Managed directx (using direct input)
- Using a library e.g. SlimDX
- Use XBOX360 Controller Emulator
Because I didn’t want to import another library or a tool to implement this feature, I decided to use Managed directx to create a reusable class that handles controller input. To start, you must add reference to Microsoft.DirectX.DirectInput and System.Windows.Forms to the xna project to use direct input in Managed Directx (reference to windows forms is needed to initialize the Microsoft.DirectX.DirectInput.Device class). To do this, right click on the Reference in the project property and select “Add Reference…” then under the .Net tab find the two references and add them.
After adding reference to them, I started writing initialization to get reference to the controller (to make my life easier, I have added using Microsoft.DirectX.DirectInput;).
Device _pad;
JoystickState _padStates;
// Get the list of devices connected
DeviceList deviceList = Manager.GetDevices(DeviceClass.GameControl, EnumDevicesFlags.AttachedOnly);
//Get the connected game pads and store them
foreach (DeviceInstance i in deviceList)
{
_pad = new Device(i.InstanceGuid));
if ( _pad )
break;
}
If a controller was found then setup the maximum values returned by analogue sticks.
// set range of values an analogue stick can return
foreach ( DeviceObjectInstance devObjIns in pad.Objects )
{
if ( ( devObjIns.ObjectId & (int)DeviceObjectTypeFlags.Axis ) != 0 )
{
_pad.Properties.SetRange(ParameterHow.ById, devObjIns.ObjectId, new InputRange( -100, 100 ) );
}
}
Finally, finish of setting up the device and acquiring it (getting access to it).
// setup _pad.Properties.AxisModeAbsolute = true; _pad.SetCooperativeLevel( window.Handle, CooperativeLevelFlags.NonExclusive | CooperativeLevelFlags.Background ); _pad.Acquire();
So once the controllers are setup, we have to remember to update it each frame to poll it and store its state to be used to check for input from the program.
public void Update() { _pad.Poll(); _padStates = _pad.CurrentJoystickState; }
Now to test input with a button.
if ( _padStates.GetButtons()[0] != 0 )
{
message = "Button 0 is being Pressed"
}
This is the basics of it, although I have quite a bit of extra code and process in the actual class that I skipped, but the fundamental parts were shown above. When I run the program at this point to test this, it crushed (well, it actually hanged) throwing an exception.
This is thrown by LoaderLock which is part of the MDA(Managed Debugging Assistants, its built in to Visual Studio to help debug a program at runtime). The reason why this exception was thrown is that Managed directx does something that causes MDA to go off (I am not entirely sure what causes it inside Managed directx). To solve this problem, LoaderLock needs to be disabled by going to: “Debug->Excecptions…” menu on the tool bar inside Visual studio (or alternatively, press Ctrl + Alt + E) and uncheck the “Thrown” tick box.
After this, it should work.
As I have already said, I skipped some of the extra steps that were taken while writing the class. So as a backup and in case anyone is interested, I well upload the project with very basic test inside it too. The class does implement the feature to support multiple controllers but I only had one to test it with so at the moment, I am not sure if it can work with multiple controllers. Also, I have only tested it on my PC so I am not entirely sure if it works on other machines.
You can download the project here:
http://www.mediafire.com/download.php?c2etdfkvivsj78r



June 10, 2012 at 8:06 am
The file is protected!!!
June 10, 2012 at 8:10 am
ok, Iv changed the setting back to public.
Can you give it try again to see if you can download it?