C# 高效、可扩展地将gamepad输入转换为游戏逻辑输入

C# 高效、可扩展地将gamepad输入转换为游戏逻辑输入,c#,xna,monogame,opentk,C#,Xna,Monogame,Opentk,我试图创建一个函数,该函数接受OpenTK的GamePad或GamePadState对象,并输出一个由[Flags]枚举组成的结构,其中包含我的游戏的所有有意义的输入及其基于输入映射(字典?)的状态。其思想是映射可以任意更改以允许轻松的输入重新配置,我可以通过枚举分配有意义的输入组合有用的名称,并将位标志用于时髦的其他东西。听起来这样安排会非常有用 这似乎是可能的,但不幸的是,我已经尝试过几次了,每次都是一团糟。我能得到一些关于如何构造这个的建议吗 这就是我目前正在尝试的: 输入.cs name

我试图创建一个函数,该函数接受OpenTK的GamePad或GamePadState对象,并输出一个由[Flags]枚举组成的结构,其中包含我的游戏的所有有意义的输入及其基于输入映射(字典?)的状态。其思想是映射可以任意更改以允许轻松的输入重新配置,我可以通过枚举分配有意义的输入组合有用的名称,并将位标志用于时髦的其他东西。听起来这样安排会非常有用

这似乎是可能的,但不幸的是,我已经尝试过几次了,每次都是一团糟。我能得到一些关于如何构造这个的建议吗

这就是我目前正在尝试的:

输入.cs

namespace F1.Input
{
  [Flags]
  public enum Inputs
  {
    None = 0,
    Up = 1,
    Down = 2,
    Left = 4,
    Right = 8,
    Neutral = -16, // ?
    D1 = 6,
    D2 = 2,
    D3 = 10,
    D4 = 4,
    D5 = -16,
    D6 = 8,
    D7 = 5,
    D8 = 1,
    D9 = 9,
    A = 16,
    B = 32,
    C = 64,
    D = 128,
    Start = 256,
    Accept = 512,
    Cancel = 1024,
  }
}
GameInputs.cs

namespace F1.Input
{
  public struct GameInputs : IEquatable<GameInputs>
  {
    Inputs inputs;

    public GameInputs(Inputs state)
    {
      inputs = state;
    }

    public InputState None { get { return GetInput(Inputs.None); } }
    public InputState Up { get { return GetInput(Inputs.Up); } }
    public InputState Down { get { return GetInput(Inputs.Down); } }
    public InputState Left { get { return GetInput(Inputs.Left); } }
    public InputState Right { get { return GetInput(Inputs.Right); } }
    public InputState Neutral { get { return GetInput(Inputs.Neutral); } }
    public InputState D1 { get { return GetInput(Inputs.D1); } }
    public InputState D2 { get { return GetInput(Inputs.D2); } }
    public InputState D3 { get { return GetInput(Inputs.D3); } }
    public InputState D4 { get { return GetInput(Inputs.D4); } }
    public InputState D5 { get { return GetInput(Inputs.D5); } }
    public InputState D6 { get { return GetInput(Inputs.D6); } }
    public InputState D7 { get { return GetInput(Inputs.D7); } }
    public InputState D8 { get { return GetInput(Inputs.D8); } }
    public InputState D9 { get { return GetInput(Inputs.D9); } }
    public InputState A { get { return GetInput(Inputs.A); } }
    public InputState B { get { return GetInput(Inputs.B); } }
    public InputState C { get { return GetInput(Inputs.C); } }
    public InputState D { get { return GetInput(Inputs.D); } }
    public InputState Start { get { return GetInput(Inputs.Start); } }
    public InputState Accept { get { return GetInput(Inputs.Accept); } }
    public InputState Cancel { get { return GetInput(Inputs.Cancel); } }

    #region IEquatable<GameInputs> Members

    public bool Equals(GameInputs other)
    {
      return inputs == other.inputs;
    }

    #endregion

    #region Private Members

    InputState GetInput(Inputs i)
    {
      return (inputs & i) != 0 ? InputState.Active : InputState.Inactive;
    }

    #endregion
  }
}
名称空间F1.Input
{
public struct GameInputs:IEquatable
{
投入;
公共游戏输入(输入状态)
{
输入=状态;
}
公共InputState None{get{return GetInput(Inputs.None);}
公共InputState Up{get{return GetInput(Inputs.Up);}
public-InputState-Down{get{return-GetInput(Inputs.Down);}
公共InputState Left{get{return GetInput(Inputs.Left);}
公共InputState权限{get{return GetInput(Inputs.Right);}
公共InputState中性{get{return GetInput(Inputs.Neutral);}
公共输入状态D1{get{return GetInput(Inputs.D1);}
公共输入状态D2{get{return GetInput(Inputs.D2);}
公共输入状态D3{get{return GetInput(Inputs.D3);}
公共输入状态D4{get{return GetInput(Inputs.D4);}
公共输入状态D5{get{return GetInput(Inputs.D5);}
公共输入状态D6{get{return GetInput(Inputs.D6);}
公共输入状态D7{get{return GetInput(Inputs.D7);}
公共输入状态D8{get{return GetInput(Inputs.D8);}
公共输入状态D9{get{return GetInput(Inputs.D9);}
公共输入状态A{get{return GetInput(Inputs.A);}
公共输入状态B{get{return GetInput(Inputs.B);}
公共输入状态C{get{return GetInput(Inputs.C);}
公共输入状态D{get{return GetInput(Inputs.D);}
公共InputState开始{get{return GetInput(Inputs.Start);}
公共InputState接受{get{return GetInput(Inputs.Accept);}
公共InputState取消{get{return GetInput(Inputs.Cancel);}
#区域可容纳成员
公共布尔等于(其他)
{
返回输入==其他输入;
}
#端区
#区域私人成员
InputState GetInput(输入i)
{
返回(输入和i)!=0?输入状态。活动:输入状态。非活动;
}
#端区
}
}
Input.cs

using F1.Input;
using OpenTK.Input;
using System;
using System.Collections.Generic;

namespace F1
{
  class F1Input
  {
    public Dictionary<GamePadButtons, GameInputs> buttonMap { get; set; }
    public Dictionary<GamePadDPad, GameInputs> directionMap { get; set; }
    public int gamePadIndex { get; set; }
    internal GamePadButtons gamePadButtons { get; set; }
    internal GamePadDPad gamePadDPad { get; set; }
    internal GameInputs gameInputButtons { get; set; }
    internal GameInputs gameInputDPad { get; set; }

    public F1Input(Dictionary<GamePadButtons, GameInputs> inputMap, int gamePadIndex)
    {
      this.buttonMap = DefaultButtonMapping();
      this.directionMap = DefaultDirectionMapping();
      this.gamePadIndex = gamePadIndex;
    }

    public void Update() {
      gamePadButtons = GamePad.GetState(gamePadIndex).Buttons;
      gamePadDPad = GamePad.GetState(gamePadIndex).DPad;
      GameInputs dictOut;
      buttonMap.TryGetValue(gamePadButtons, out dictOut);
      gameInputButtons = dictOut;
      directionMap.TryGetValue(gamePadDPad, out dictOut);
      gameInputDPad = dictOut;
    }

    public GameInputs getGameInputs()
    {
      return gameInputButtons;
    }

    private Dictionary<GamePadDPad, GameInputs> DefaultDirectionMapping()
    {
      return new Dictionary<GamePadDPad, GameInputs>()
      {
        // It was about here that I realized something is very wrong with my architecture.
      };
    }
    private Dictionary<GamePadButtons, GameInputs> DefaultButtonMapping()
    {
      return new Dictionary<GamePadButtons, GameInputs>()
      {
        { new GamePadButtons(Buttons.A), new GameInputs(Inputs.A) },
        { new GamePadButtons(Buttons.B), new GameInputs(Inputs.B) },
        { new GamePadButtons(Buttons.X), new GameInputs(Inputs.C) },
        { new GamePadButtons(Buttons.Y), new GameInputs(Inputs.D) }
      };
    }
  }
}
使用F1.输入;
使用OpenTK.Input;
使用制度;
使用System.Collections.Generic;
名称空间F1
{
F1类输入
{
公共字典按钮映射{get;set;}
公共字典方向映射{get;set;}
public int gamePadIndex{get;set;}
内部游戏按钮游戏按钮{get;set;}
内部GamePadDPad GamePadDPad{get;set;}
内部GameInputs gameInputButtons{get;set;}
内部GameInputs gameInputDPad{get;set;}
公共输入(字典输入映射、int GAMEPADDINDEX)
{
this.buttonMap=DefaultButtonMapping();
this.directionMap=DefaultDirectionMapping();
this.gamePadIndex=gamePadIndex;
}
公共无效更新(){
gamePadButtons=GamePad.GetState(gamePadIndex).Buttons;
gamePadDPad=GamePad.GetState(gamePadIndex).DPad;
配子输出;
buttonMap.TryGetValue(gamePadButtons,out dictOut);
游戏输入按钮=口述输出;
directionMap.TryGetValue(gamePadDPad,out dictOut);
gameInputDPad=口述输出;
}
公共游戏输入getGameInputs()
{
返回游戏输入按钮;
}
专用字典DefaultDirectionMapping()
{
返回新字典()
{
//就在这里,我意识到我的架构出了很大的问题。
};
}
专用字典DefaultButtonMapping()
{
返回新字典()
{
{新GamePadButtons(Buttons.A),新GameInputs(Inputs.A)},
{新建GamePadButtons(Buttons.B),新建GameInputs(Inputs.B)},
{新GamePadButtons(Buttons.X),新GameInputs(Inputs.C)},
{新建GamePadButtons(Buttons.Y),新建GameInputs(Inputs.D)}
};
}
}
}

这不起作用,因为(除其他外)输入组合不起作用,可能是因为我使用字典的方式。

如果您展示您尝试的内容,我们可能会帮助您。目前,对于一个问题来说,它可能有点太宽了,好吧,但我警告你,它并不漂亮。如果你想让枚举作为一个标志枚举,你必须定义每个值,就像它代表一个位位置一样。换句话说,只有两个人的力量。如果希望它是常规枚举,请删除flags属性并使用唯一值。flags属性的思想是将不同含义的多个标志组合到一个值中。在您的情况下,您希望在字典中而不是在枚举中使用该组合。这不一定是真的。标志组合在二进制中仍然有一个组合值,我没有考虑的问题是,组合标志不是它们的组成部分/独占/的。是的,Down和Left加起来等于6,并触发Down+Left标志(这显然有效),但这并不意味着标志2和4也没有设置。我最终摆脱了上/下/左/右标志,因为它们不够离散,现在用(上+右或右或下+右)和(输入)!=0以检查权利是否被保留,等等。如果您展示您尝试的内容,我们可能会帮助您。目前这个问题可能有点太宽泛了好吧,但我警告你,它不漂亮。如果你想要