键盘C#WPF的多输入

时间:2010-04-06 15:14:26

标签: c# .net wpf keyboard-events

我正在WPF中编写一个俄罗斯方块克隆。如果我按住右箭头键,则当前曲目向右移动。为了可玩性,我想让用户按下另一个键(即F键)并旋转移动的片段,而不必先放开右箭头键。目前,当我这样做时,这件作品就停止了。

我对此的第一次基本尝试是挂钩

Window_PreviewKeyDown(object sender, KeyEventArgs e)

然后向控制器层发送消息。

如何构建输入监听代码以允许此操作?

我当前的代码Here

4 个答案:

答案 0 :(得分:3)

你依靠关键的自动重复来保持棋子移动。这是不合适的,用户的键盘重复延迟是可变的,将影响游戏的可玩性。当你发现时,它会在按下另一个键时停止自动重复。

通过将每个游戏对象作为动作状态来解决此问题。使用KeyDown事件来更改它。如果运动状态值仍然与键匹配,则KeyUp事件将重置它。在游戏循环中,根据动作状态更新游戏对象位置。你会以固定的速度这样做,由计时器触发。

动作状态也应指示“跌倒”。现在,您可以通过降低计时器速率让游戏更加困难。碎片下降得更快。键盘变得更具响应性,让用户有机会赢得一个级别。

答案 1 :(得分:2)

也应该存在KeyUp事件,并且通过使用KeyDown和KeyUp,您可以实现您正在寻找的效果。它可以通过几种方式完成。

一种方法是让你的KeyDown事件启动重复操作,让KeyUp取消它。

另一种方法是存储某些键是否被按下。保留一个键列表,并在KeyDown上关闭它们并在KeyUp上关闭。在游戏主循环中,您将触发与当前所有键相对应的事件。

一个例子:

bool[] heldDown = new bool[256]; // One index for the keycode of each key

void Window_PreviewKeyDown(object sender, KeyEventArgs e) {
    heldDown[e.KeyCode] = true;
}    
void Window_PreviewKeyUp(object sender, KeyEventArgs e) {
    heldDown[e.KeyCode] = false;
}    

然后你在你的主循环中经历“heldDown”并为每个有意义的关键点击事件:

if (heldDown[Key.F])
    MainController.TriggerPieceEvent(Constants.PieceEvents.RotateClockwise);
if (heldDown[Key.Left])
    MainController.TriggerPieceEvent(Constants.PieceEvents.ShiftLeft);
// etc...

答案 2 :(得分:1)

Windows只会重复您按下的最后一个键的事件。另外,首先重复密钥之前的延迟以及重复的速率取决于通常针对打字而不是针对游戏进行优化的设置。因此,对于游戏,最好完全忽略它们,并有自己的方式来实现“重复”键。

基本上,您必须保留您感兴趣的键的状态(按下或释放),并在收到KeyDown或KeyUp事件时更改它们。然后,在某种计时器中,您必须检查当时关闭的每个键的状态和触发事件。如果该计时器发生在控制器层或UI中,则取决于您的架构:-)

您可以添加额外的检查,例如左右键都向下以忽略两者,否则该片段将反复左右跳跃。

答案 3 :(得分:1)

你需要国家。创建一些变量,如'RightArrowPressed'和'RotateButtonPressed'

在Key_Down中检查按键是否按下,如果是,则将相应的变量设置为true。

在key_up中,执行相同操作但将其设置为false。

现在,您可以随时查看这两个变量并查看按下了哪些键。