C# 带有代理的游戏控件绑定字典
我的游戏的属性类型为C# 带有代理的游戏控件绑定字典,c#,dictionary,delegates,game-engine,key-bindings,C#,Dictionary,Delegates,Game Engine,Key Bindings,我的游戏的属性类型为IInput: private IInput Input; 在游戏循环之前,我添加了一些键绑定,如下所示: protected override void Initialize() { input.BindKey( Keys.Escape, Exit ); // etc... } internal class Input : IInput { private readonly IDictionary<Keys, Tuple<Action&l
IInput
:
private IInput Input;
在游戏循环之前,我添加了一些键绑定,如下所示:
protected override void Initialize()
{
input.BindKey( Keys.Escape, Exit );
// etc...
}
internal class Input : IInput
{
private readonly IDictionary<Keys, Tuple<Action<Directions>, Directions>> keyBindings;
public void BindKey( Keys key, Tuple<Action<Directions>, Directions> action)
{
keyBindings.Add( key, action );
}
public void Process()
{
// update keyboard state...
foreach ( var binding in keyBindings )
{
if ( keyboard.IsKeyDown( binding.Key )
{
binding.Value.Item1(binding.Value.Item2);
}
}
}
}
input.BindKey(Keys.W, Tuple.Create<Action<Directions>, Directions>(Move, Directions.Up));
input.BindKey(Keys.W, () => Move(Directions.Up));
BindKey
方法将一项添加到Input
类的键绑定字典中:
internal class Input : IInput
{
private readonly IDictionary<Keys, Action> keyBindings;
public void BindKey( Keys key, Action action )
{
keyBindings.Add( key, action );
}
public void Process()
{
// update keyboard state...
foreach ( var binding in keyBindings )
{
if ( keyboard.IsKeyDown( binding.Key )
{
binding.Value();
}
}
}
}
private readonly IDictionary<Keys, Delegate> keyBindings;
我该怎么做?我尝试更改Input
类的keyBindings
属性:
internal class Input : IInput
{
private readonly IDictionary<Keys, Action> keyBindings;
public void BindKey( Keys key, Action action )
{
keyBindings.Add( key, action );
}
public void Process()
{
// update keyboard state...
foreach ( var binding in keyBindings )
{
if ( keyboard.IsKeyDown( binding.Key )
{
binding.Value();
}
}
}
}
private readonly IDictionary<Keys, Delegate> keyBindings;
但类似的方法不适用于带参数的绑定方法:
// compiler error: "Method name is expected"
input.BindKey( Keys.W, new Func<Directions>( Move( Directions.Up ) ) );
// compiler error: "Delegate constructor is invoked with 2 argument(s)"
input.BindKey( Keys.W, new Func<Directions>( Move, Directions.Up ) );
编辑
我错误地使用了Func
。我想为一个方法提供方向,但我不在乎它返回什么。我也没有走多远:
// 1. Cannot use "void" as a type argument
// 2. Method name is expected
input.BindKey( Keys.W, new Func<Vector2, void>( Move( Directions.Up ) );
// Cannot apply operator ">" to operands of type "null" and "void"
input.BindKey( Keys.W, new Func<Vector2, null>( Move( Directions.Up ) );
这里的关键概念是,使用委托,您只是指向一个接受输入参数的方法,因此它不会像您在代码中编写的那样工作,参数应该在调用期间传递!因此,作为一种解决方法,您可以这样编写st:
protected override void Initialize()
{
input.BindKey( Keys.Escape, Exit );
// etc...
}
internal class Input : IInput
{
private readonly IDictionary<Keys, Tuple<Action<Directions>, Directions>> keyBindings;
public void BindKey( Keys key, Tuple<Action<Directions>, Directions> action)
{
keyBindings.Add( key, action );
}
public void Process()
{
// update keyboard state...
foreach ( var binding in keyBindings )
{
if ( keyboard.IsKeyDown( binding.Key )
{
binding.Value.Item1(binding.Value.Item2);
}
}
}
}
input.BindKey(Keys.W, Tuple.Create<Action<Directions>, Directions>(Move, Directions.Up));
input.BindKey(Keys.W, () => Move(Directions.Up));
编辑:
您甚至可以使用原始的Input
类执行此操作,而不是指向Move
方法,您可以创建一个代理来为您执行此操作(s.t如@Magus在评论中所说),如下所示:
protected override void Initialize()
{
input.BindKey( Keys.Escape, Exit );
// etc...
}
internal class Input : IInput
{
private readonly IDictionary<Keys, Tuple<Action<Directions>, Directions>> keyBindings;
public void BindKey( Keys key, Tuple<Action<Directions>, Directions> action)
{
keyBindings.Add( key, action );
}
public void Process()
{
// update keyboard state...
foreach ( var binding in keyBindings )
{
if ( keyboard.IsKeyDown( binding.Key )
{
binding.Value.Item1(binding.Value.Item2);
}
}
}
}
input.BindKey(Keys.W, Tuple.Create<Action<Directions>, Directions>(Move, Directions.Up));
input.BindKey(Keys.W, () => Move(Directions.Up));
这样,在调用过程中,将调用此delate,并依次调用带有必需参数的
Move
方法。为什么要使用Func
执行此操作?它会返回s.t吗?您在那里编写的Func
,需要一个不带参数的方法,该方法返回一个字典
!不幸的是,您在这方面不会有太多的运气,因为代理不能像那样动态地更改其参数数/返回值。我建议你让所谓的行动做任何任务。我和一位朋友实际上做了一些非常类似的事情,不过在一个额外的抽象层后面是标志枚举按钮,还有一个队列,它可以识别最近按下的按钮序列,并将它们与正确的委托进行匹配。请注意,如果您尝试这样做,这并不容易。@ArinGhazarian只是因为我认为我需要使用Func
@davidkennedy85,如果是这样,那么您想要一个接受方法作为输入并返回方向的委托,对吗?基本上,您可以执行类似Action Action=()=>\u ownerPositionVector=Move(Direction.Left)代码>。该操作将根据调用move的方式在执行时分配字段。它并不比这样做的方法更危险,只是你可能不希望它发生。我个人认为这很酷。我的整个控制方案都是基于它的,它允许我通过简单地更改绑定来隐式地更改事物的状态,而不使用布尔标志。我认为他的主要问题是他有N个参数,可能返回也可能不返回任何内容。这input.BindKey(Keys.W,()=>Move(Directions.Up))代码>正是我要找的!