You won’t be able to interface with joysticks with a DirectX project through the MG API. XInput won’t work because it’s for gamepads (and it’s what MG itself uses), but you could try using DirectInput. There’s a SharpDX package for it on NuGet.
If you create a MonoGame cross-platfrom desktop project, you can use the JoyStick API.
Yes SDL does support joysticks (using DInput on Windows), that’s why I said:
“If you create a MonoGame cross-platfrom desktop project, you can use the JoyStick API.”
@Jjagg can’t do a cross platform game. My terrain rendering is very directx
I have solved the problem by downloading and rewriting a HID library.
Using this I am able to poll the joystick and receive an array of bytes back.
The mapping for the X56 Rhino stick is…
/// <summary>
/// Byte 0 - 3 Joystick position 16 bit centre 8000
/// Byte 4 - 5 Joystick twist position 12 bit centre 800
/// Byte 5 top 4 bits POV 8 directions
/// Byte 6
/// Bit 1 = Fire
/// Bit 2 = A button
/// Bit 4 = B button
/// Bit 8 = Thumbstick depressed
/// Bit 16 =
/// Bit 32 = Pinky
/// Bit 64 = H1 Up
/// Bit 128 = H1 right
/// Byte 7
/// Bit 1 = H1 down
/// Bit 2 = H1 left
/// Bit 4 = H2 up
/// Bit 8 = H2 right
/// Bit 16 = H2 down
/// Bit 32 = H2 left
/// Bit 64 =
/// Bit 128 =
/// Byte 9 and 10 Thumbstick position (8 bit centre 80)
I am now moving on to the Throttle, damn that’s a lot of buttons to process though
Mapping for the throttle module, annoyingly the mode wheel does nothing
///
/// Byte 0 Left throttle 0 = forward
/// Byte 1 - 2 Right throttle 12 bits 0 = forward
///
/// Byte 2
/// Bit 16 E button
/// Bit 128 I button
///
/// Byte 3
/// Bit 1 H button
/// Bit 2 Sw1
/// Bit 4 Sw2
/// Bit 8 Sw3
/// Bit 16 Sw4
/// Bit 32 Sw5
/// Bit 64 Sw6
/// Bit 128 tgl 1 up
///
/// Byte 4
/// Bit 1 tgl 1 down
/// Bit 2 tgl 2 up
/// Bit 4 tgl 2 down
/// Bit 8 tgl 3 up
/// Bit 16 tgl 3 down
/// Bit 32 tgl 4 up
/// Bit 64 tgl 4 down
/// Bit 128 H3 up
///
/// Byte 5
/// Bit 1 H3 forward
/// Bit 2 H3 down
/// Bit 4 H3 back
/// Bit 8 H4 up
/// Bit 16 H4 forward
/// Bit 32 H4 down
/// Bit 64 h4 back
///
/// Bit 128 K1 up
///
/// Byte 6
/// Bit 1 K1 down
/// Bit 2 Click wheel up
/// Bit 4 Click wheel down
/// Bit 16 SLD forward
///
/// Byte 7 Wheel F
/// Byte 8 Thumbstick X
/// Byte 9 Wheel g
/// Byte 10 Thumbstick Y
/// Byte 11 RTY 4
/// Byte 12 RTY 3
///
///
Has anyone got a working example for getting this joystick input working? I’m also using a Rhino x56 and would really like to get this control into a game.
I’m not interested in cross platform, Windows only.
I got DirectInput working with SharpDX in MonoGame! @StainlessTobii and @MuntyScruntFundle, if you want to try this out, I recommend MonoGame 3.7.1 or newer, as I’ve only tested on 3.7.1 and 3.8.
-Open Visual Studio (I used the 2017 version) and your existing MonoGame Windows Project, or make a new one.
-Make sure you’re connected to the Internet, then go to Tools>NuGet Package Manager>Package Manager Console. The console will appear at the bottom of your VS window, replacing Output/Build/Debug.
-If you’re using a MonoGame Shared Project, make sure the console’s “Default project” is your WindowsDX project.
-Paste the following into the console and press Enter: Install-Package SharpDX.DirectInput -Version 4.0.1
-You now have DInput! You can use the following complete code to test it out. I named my project DInputTest: using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using SharpDX.DirectInput; using System; using Keyboard = Microsoft.Xna.Framework.Input.Keyboard; using Mouse = Microsoft.Xna.Framework.Input.Mouse;
namespace DInputTest
{
public class Game1 : Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
//DirectInput vars, partially copied from online sources
DirectInput directInput = new DirectInput(); // Initialize DirectInput
Guid gamepadGuid = Guid.Empty, joystickGuid = Guid.Empty; //there may be DInput gamepads out there (Logitech Dual Action Gamepad?), let's test for them
SharpDX.DirectInput.Joystick joystick;
bool noDInputsConnected = false, pressed = false;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
DInputChecker(); //this can be called from Update() as well whenever the user may have plugged in a new joystick, maybe good for the Options menu
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
}
protected override void UnloadContent()
{
// TODO: Unload any non ContentManager content here
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
if (!noDInputsConnected)
{
try
{
joystick.Poll(); //ask the joystick for input
var state = joystick.GetCurrentState(); //return the state of all buttons, axes, etc.
if(state.Buttons[0]) pressed = true; else pressed = false;
}
catch {} //catches any odd SharpDX errors
}
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
//Simple way to demonstrate that the joystick is connected without SpriteFonts:
if(!pressed)
GraphicsDevice.Clear(Color.CornflowerBlue); //standard blue background means Button 0 is not being pressed
else
GraphicsDevice.Clear(Color.Yellow); //light up to show that Button 0 has been read and is being pressed!
base.Draw(gameTime);
}
private void DInputChecker()
{
foreach (var deviceInstance in directInput.GetDevices(DeviceType.Gamepad, DeviceEnumerationFlags.AllDevices)) //look for connected DInput gamepads
gamepadGuid = deviceInstance.InstanceGuid;
foreach (var deviceInstance in directInput.GetDevices(DeviceType.Joystick, DeviceEnumerationFlags.AllDevices)) //if, or even if none found, look for DInput joysticks
joystickGuid = deviceInstance.InstanceGuid;
if (gamepadGuid != Guid.Empty || joystickGuid != Guid.Empty)
{
noDInputsConnected = false;
joystick = new SharpDX.DirectInput.Joystick(directInput, joystickGuid);
joystick.Properties.BufferSize = 128; //allocate a buffer to hold the device's state
joystick.Acquire(); //do this for every joystick that's plugged in, the user may have multiple joysticks plugged in
}
else
noDInputsConnected = true; //if this variable did not exist, the game would crash when 0 joysticks are connected
}
}
}
Of course, this is just an example and you’ll want to check if more than one joystick is connected in a real game.
Two other caveats I’m aware of, one of which is fixed in the code at lines 6 & 7:
Adding SharpDX.DirectInput creates ambiguity between i.e. “Microsoft.Xna.Framework.Input.Keyboard” and “SharpDX.DirectInput.Keyboard”. I recommend including those using statements at the top to associate Keyboard and Mouse only with XNA’s handling.
On 3.7.1 at least, this reference can add several seconds to the game’s startup time compared to not using SharpDX.DirectInput in the project. On my mid-range PC from 2015, it adds about 5 seconds of Windows’ spinning cursor before the game opens.