C# 高效、可扩展地将gamepad输入转换为游戏逻辑输入
我试图创建一个函数,该函数接受OpenTK的GamePad或GamePadState对象,并输出一个由[Flags]枚举组成的结构,其中包含我的游戏的所有有意义的输入及其基于输入映射(字典?)的状态。其思想是映射可以任意更改以允许轻松的输入重新配置,我可以通过枚举分配有意义的输入组合有用的名称,并将位标志用于时髦的其他东西。听起来这样安排会非常有用 这似乎是可能的,但不幸的是,我已经尝试过几次了,每次都是一团糟。我能得到一些关于如何构造这个的建议吗 这就是我目前正在尝试的: 输入.csC# 高效、可扩展地将gamepad输入转换为游戏逻辑输入,c#,xna,monogame,opentk,C#,Xna,Monogame,Opentk,我试图创建一个函数,该函数接受OpenTK的GamePad或GamePadState对象,并输出一个由[Flags]枚举组成的结构,其中包含我的游戏的所有有意义的输入及其基于输入映射(字典?)的状态。其思想是映射可以任意更改以允许轻松的输入重新配置,我可以通过枚举分配有意义的输入组合有用的名称,并将位标志用于时髦的其他东西。听起来这样安排会非常有用 这似乎是可能的,但不幸的是,我已经尝试过几次了,每次都是一团糟。我能得到一些关于如何构造这个的建议吗 这就是我目前正在尝试的: 输入.cs name
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以检查权利是否被保留,等等。如果您展示您尝试的内容,我们可能会帮助您。目前这个问题可能有点太宽泛了好吧,但我警告你,它不漂亮。如果你想要