XBox 360 controller non-customisable mapping

595 Views Asked by At

I would like to make a program that utilises the XBox 360 controller's inputs to give outputs, for example if you press A on the controller, it would be the same as pressing A on the keyboard. I plan to use this for game development and do not want the outputs to be customisable, but I do want a window to be visible so that it can be closed at any time. How would I go about making this program (For Windows) and have it be simple to use.

1

There are 1 best solutions below

0
On

I would advise using an input abstract class and converting the input types you need using concrete classes to convert input (A on keyboard or RTrigger on Xbox) into a input action in your game (punch button press, jump button press, Movement in X direction etc).

In C# this can be done relatively easily. Create a class/struct to be the target of your conversion return. In my case I did a fighting game platform with actions and movement with camera control, I call this InputState:

public class InputState
{
    public struct Axis
    {   
        public float X;
        public float Y;

        public float XNorm
        {
            get{ return Math.Abs(X); }
        }

        public float YNorm
        {
            get{ return Math.Abs(Y); }
        }
    }

    public struct ActionStates
    {
        public bool Jump;
        public bool Punch;
        public bool Kick;
        public bool Special;
        public bool Grab;
        public bool Guard;
    }

    public Axis MovementAxis;
    public Axis CameraAxis;
    public ActionStates Actions;
 }

You can then create a abstract InputConverter class that takes an input of some type and returns this InputState class:

public abstract class InputConverter
{
    public abstract InputState Convert(); 
}   

You can then extend this class into others, for example in Unity3D I use this class I created to make input with an XBox controller convert to the InputState class above. When initialized it required the player ID to get the correct controller. The most import part here is the public override InputState Convert that returns your games InputState object:

using XInputDotNetPure;
public class XInputConverter : InputConverter
{       

    bool playerIndexSet = false;
    PlayerIndex playerIndex;
    GamePadState gamePadState;
    GamePadState prevState;

    public XInputConverter(int playerSlot)
    {
        VerifyControllerConnected(playerSlot);

    }

    private void VerifyControllerConnected(int playerSlot)
    {
        // Find a PlayerIndex, for a single player game
        if (!playerIndexSet || !prevState.IsConnected)
        {
            PlayerIndex testPlayerIndex = (PlayerIndex)playerSlot - 1;
            GamePadState testState = GamePad.GetState(testPlayerIndex);
            if (testState.IsConnected)
            {
                //Debug.Log (string.Format ("GamePad found {0}", testPlayerIndex));
                playerIndex = testPlayerIndex;
                playerIndexSet = true;
            } else
            {
                throw new Exception(string.Format("GamePad {0} has been unplugged or is not connecting properly", testPlayerIndex));
            }
        }
    }

    public override InputState Convert()
    {
        InputState outputState = new InputState();

        gamePadState = GamePad.GetState(playerIndex);

        //Actions 
        outputState.Actions.Jump = gamePadState.Buttons.Y == ButtonState.Pressed;

        //Offense
        outputState.Actions.Punch = gamePadState.Buttons.X == ButtonState.Pressed;
        outputState.Actions.Kick = gamePadState.Buttons.A == ButtonState.Pressed;
        outputState.Actions.Special = gamePadState.Buttons.B == ButtonState.Pressed;

        //Defense
        outputState.Actions.Grab = gamePadState.Buttons.LeftShoulder == ButtonState.Pressed || gamePadState.Buttons.RightShoulder == ButtonState.Pressed;
        outputState.Actions.Guard = gamePadState.Triggers.Left > 0 || gamePadState.Triggers.Right > 0;

        //Movement from DPad
        short xAxis = 0;
        short yAxis = 0;

        //Determine if Dpad has any input
        if (gamePadState.DPad.Right == ButtonState.Pressed)
            xAxis += 1;
        if (gamePadState.DPad.Left == ButtonState.Pressed)
            xAxis -= 1;
        if (gamePadState.DPad.Up == ButtonState.Pressed)
            yAxis += 1;
        if (gamePadState.DPad.Down == ButtonState.Pressed)
            yAxis -= 1;

        //Set the movement to either the Thumsticks or the DPad 
        outputState.MovementAxis.X = xAxis == 0 ? gamePadState.ThumbSticks.Left.X : xAxis;
        outputState.MovementAxis.Y = yAxis == 0 ? gamePadState.ThumbSticks.Left.Y : yAxis;

        //Camera
        outputState.CameraAxis.X = gamePadState.ThumbSticks.Right.X;
        outputState.CameraAxis.X = gamePadState.ThumbSticks.Right.Y;

        return outputState;     
    }               
}  

Using this class you can specifically use the buttons you want for the actions you need and do this with whatever inputs you choose. Here is the unity Keyboard converter:

using UnityEngine;
public class UnityKeyboardInputConverter : InputConverter
{
    public override InputState Convert()
    {
        InputState state = new InputState();

        //Actions
        state.Actions.Jump = Input.GetKey(KeyCode.Space);

        //Offense
        state.Actions.Punch = Input.GetKey(KeyCode.J);
        state.Actions.Kick = Input.GetKey(KeyCode.K);
        state.Actions.Special = Input.GetKey(KeyCode.L);

        //Defense
        state.Actions.Grab = Input.GetKey(KeyCode.RightShift);
        state.Actions.Guard = Input.GetKey(KeyCode.LeftShift);

        //Movement
        state.MovementAxis.X = Input.GetAxisRaw("Horizontal");
        state.MovementAxis.Y = Input.GetAxisRaw("Vertical");

        //Camera
        state.CameraAxis.X = Input.GetAxisRaw("Mouse X");
        state.CameraAxis.X = Input.GetAxisRaw("Mouse Y");

        return state;     
    }        
}

Finally

Depending on player choice I can simply instantiate the input converter of my choosing using an enumerator and use an InputHandler class to call an update and retrieve the state of input from the appropriate one without needing to know which one it was that the player uses. This is important as you want to only call these inputs when your game engine is ready and using the settings the player has selected (XBox, Keyboard+Mouse, PC GamePad, etc.) :

public class InputHandler
{
    //Controller handlers and properties
    private int playerNumber;

    public enum InputType
    {
        None = 0,
        KeyboardMouse,
        XBoxController,
        PCGamePad
    }

    public InputType SelectedInputType = InputType.None;
    public InputState CommandState;

    //Ambiguous Abstract input converter allows us to assign Xbox or keyboard as input
    private InputConverter converter;

    public InputHandler(int playerNumber, InputType inputType)
    {
        SelectedInputType = inputType;
        this.playerNumber = playerNumber;
        if (playerNumber > 4 || playerNumber < 1)
        {
            throw new Exception("Player must be set to 1, 2, 3 or 4");
        }
        //Check type and load converter
        switch (SelectedInputType)
        {
        case InputType.XBoxController: 
            converter = new XInputConverter(playerNumber);
            break;
        case InputType.KeyboardMouse
            converter = new UnityKeyboardInputConverter();
            break;
        case InputType.PCGamePad: 
            converter = new PCGamePadInputConverter(playerNumber);
            break;
        case InputType.None: 
            //Do nothing but would be a good idea to handle it in game
        }

    }

    // Update is called once per frame by Unity Update functions
    public void InputUpdate()
    {
        if (converter != null)
        {
            CommandState = converter.Convert();
        }

        //Debug if in the Unity editor
        #if UNITY_EDITOR
        Debug.Log(CommandState.ToString());
        #endif
    }
}

Hope this helps.