23

I searched around on Google for this, but the only things I came up with were outdated and did not work.

Does anyone have any information on how to get joystick data using C# .NET?

Arseny
  • 6,961
  • 4
  • 35
  • 52
chris12892
  • 1,474
  • 2
  • 15
  • 30
  • The guy who wrote that is a friend of mine. He says it will not work with modern .NET. I'm talking to him over IM right now. – chris12892 Oct 14 '10 at 03:07
  • I've never programmed for a joystick as an interface device, but my understanding as a user is that joystick controls map to keyboard and mouse controls (i.e.: when I configure my logitech USB PS2 style controller for HL2, I map each button on the controller to a key or mouse button) – Brian Driscoll Oct 14 '10 at 03:14
  • 1
    How Ironic, 5 years later, when I now google the same question, I find this question mentioning outdated and not working :| – Spiked3 May 19 '15 at 16:14
  • 9 years later and this is still quite pertinent. Any updates? I don't want to post the same question again. I'm using Logitech F710 wireless controller. – A. Vieira Mar 06 '20 at 11:43

4 Answers4

28

Since this was the top hit I got on google while researching joystick / gamepad input in C#, I thought I should post a response for others to see.

The easiest way I found was to use SharpDX and DirectInput. You can install it via NuGet (SharpDX.DirectInput)

After that, it's simply a matter of calling a few methods:

Sample code from SharpDX

static void Main()
{
    // Initialize DirectInput
    var directInput = new DirectInput();

    // Find a Joystick Guid
    var joystickGuid = Guid.Empty;

    foreach (var deviceInstance in directInput.GetDevices(DeviceType.Gamepad, 
                DeviceEnumerationFlags.AllDevices))
        joystickGuid = deviceInstance.InstanceGuid;

    // If Gamepad not found, look for a Joystick
    if (joystickGuid == Guid.Empty)
        foreach (var deviceInstance in directInput.GetDevices(DeviceType.Joystick, 
                DeviceEnumerationFlags.AllDevices))
            joystickGuid = deviceInstance.InstanceGuid;

    // If Joystick not found, throws an error
    if (joystickGuid == Guid.Empty)
    {
        Console.WriteLine("No joystick/Gamepad found.");
        Console.ReadKey();
        Environment.Exit(1);
    }

    // Instantiate the joystick
    var joystick = new Joystick(directInput, joystickGuid);

    Console.WriteLine("Found Joystick/Gamepad with GUID: {0}", joystickGuid);

    // Query all suported ForceFeedback effects
    var allEffects = joystick.GetEffects();
    foreach (var effectInfo in allEffects)
        Console.WriteLine("Effect available {0}", effectInfo.Name);

    // Set BufferSize in order to use buffered data.
    joystick.Properties.BufferSize = 128;

    // Acquire the joystick
    joystick.Acquire();

    // Poll events from joystick
    while (true)
    {
        joystick.Poll();
        var datas = joystick.GetBufferedData();
        foreach (var state in datas)
            Console.WriteLine(state);
    }
}

I hope this helps.

I even got this to work with a DualShock3 and the MotioninJoy drivers.

Valdemar
  • 874
  • 1
  • 10
  • 18
13

One: use SlimDX.

Two: it looks something like this (where GamepadDevice is my own wrapper, and the code is slimmed down to just the relevant parts).

Find the joystick / pad GUIDs:

    public virtual IList<GamepadDevice> Available()
    {
        IList<GamepadDevice> result = new List<GamepadDevice>();
        DirectInput dinput = new DirectInput();
        foreach (DeviceInstance di in dinput.GetDevices(DeviceClass.GameController, DeviceEnumerationFlags.AttachedOnly))
        {
            GamepadDevice dev = new GamepadDevice();
            dev.Guid = di.InstanceGuid;
            dev.Name = di.InstanceName;
            result.Add(dev);
        }
        return result;
    }

Once the user has selected from the list, acquire the gamepad:

   private void acquire(System.Windows.Forms.Form parent)
    {
        DirectInput dinput = new DirectInput();

        pad = new Joystick(dinput, this.Device.Guid);
        foreach (DeviceObjectInstance doi in pad.GetObjects(ObjectDeviceType.Axis))
        {
            pad.GetObjectPropertiesById((int)doi.ObjectType).SetRange(-5000, 5000);
        }

        pad.Properties.AxisMode = DeviceAxisMode.Absolute;
        pad.SetCooperativeLevel(parent, (CooperativeLevel.Nonexclusive | CooperativeLevel.Background));
        pad.Acquire();
    }

Polling the pad looks like this:

        JoystickState state = new JoystickState();

        if (pad.Poll().IsFailure)
        {
            result.Disconnect = true;
            return result;
        }

        if (pad.GetCurrentState(ref state).IsFailure)
        {
            result.Disconnect = true;
            return result;
        }

        result.X = state.X / 5000.0f;
        result.Y = state.Y / 5000.0f;
        int ispressed = 0;
        bool[] buttons = state.GetButtons();
Adrian Cox
  • 5,934
  • 5
  • 36
  • 65
  • 4
    As people are still reading this answer, I should note that I later switched to RawInput: http://stackoverflow.com/a/12988935/184998 – Adrian Cox Jan 13 '13 at 21:06
  • the part up to acquire works for me so far, I did skip the set cooperative level call. I'm on windows 7. answers elsewhere on SO say microsoft recommends you use RawInput instead of DirectInput – Maslow Jan 30 '16 at 16:46
4

The bad news is that Microsoft seems to stop supporting their NET libraries for DirectX and focus on XNA instead. I don't work in GameDev so I don't need to use XNA but you may try it if you developing computer games. The good news is that there are other approaches. One is SlimDX the new framework to help you to wok with DirectX from C#. The other way is to directly add references of "Microsoft.DirectX.dll" and "Microsoft.DirectX.DirectInput.dll" to your project. you can find them "..\Windows\Microsoft.NET\DirectX for Managed Code\". if you you are going to use last approach here is a link to codeproject where you can read how to work with a joystick.

EDIT: If your application is based on NET version newer then 2.0 the application may hang on. To fix this problem change config file and add this:

<startup useLegacyV2RuntimeActivationPolicy="true"> 
Arseny
  • 6,961
  • 4
  • 35
  • 52
3

Google led me here and while not a requirement of this question, OpenTK is a good option for Windows and Linux (under mono) support.

From the OpenTK docs, this code works on Raspberry Pi + Raspbian + Mono 3.12.0:

for (int i = 0; i < 4; i++)
{
    var state = Joystick.GetState(i);
    if (state.IsConnected)
    {
        float x = state.GetAxis(JoystickAxis.Axis0);
        float y = state.GetAxis(JoystickAxis.Axis1);

        // Print the current state of the joystick
        Console.WriteLine(state);
    }
}
fiat
  • 13,753
  • 6
  • 72
  • 94
  • 2
    Still works great in 2020, this post worked so effortlessly compared to anything else (but also because OpenTK makes it simple too!) – Water Jul 25 '20 at 01:40