我怎么能识别2个单独的按键作为一个键

本文关键字:一个 2个 识别 单独 怎么能 | 更新日期: 2023-09-27 18:09:17

对于我正在制作的游戏,我有一堆不同的键做不同的事情(例如w键让玩家向上看,e键让角色向右看)。

我想知道是否有一种方法可以使W + D键使玩家向上看,即使这些键已经被使用了。

private void FrmGM_KeyDown(object sender, KeyEventArgs e)
    {            
        if (e.KeyCode == Keys.W)
        {
            picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player1));
            bulletnumb = 1;
        }
        if (e.KeyCode == Keys.E)
        {
            picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player2));
            bulletnumb = 2;
        }
        if (e.KeyCode == Keys.D)
        {
            picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player3));
            bulletnumb = 3;
        }
        if (e.KeyCode == Keys.C)
        {
            picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player4));
            bulletnumb = 4;
        }
        if (e.KeyCode == Keys.X)
        {
            picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player5));
            bulletnumb = 5;
        }
        if (e.KeyCode == Keys.Z)
        {
            picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player6));
            bulletnumb = 6;
        }
        if (e.KeyCode == Keys.A)
        {
            picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player7));
            bulletnumb = 7;
        }
        if (e.KeyCode == Keys.Q)
        {
            picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player8));
            bulletnumb = 8;
        }

这是我按键的代码

我怎么能识别2个单独的按键作为一个键

KeyDown事件到达时将字母存储在一个集合中,并在KeyUp事件处理程序中删除它们。这样,您的KeyDown将能够"看到"如果"伴侣键"已按下:

private readonly ISet<char> keysCurrentlyDown = new HashSet<char>();
private void FrmGM_KeyDown(object sender, KeyEventArgs e) {            
    if (e.KeyCode == Keys.W)
    {
        if (keysCurrentlyDown.Contains('D')) {
            // Call some method to handle W+D
        } else {
            ...
        }
        keysCurrentlyDown.Add('W');
    } else if (e.KeyCode == Keys.D)
    {
        if (keysCurrentlyDown.Contains('W')) {
            // Call some method to handle W+D
        } else {
            ...
        }
        keysCurrentlyDown.Add('D');
    }
    ...
}
private void FrmGM_KeyUp(object sender, KeyEventArgs e) {            
    if (e.KeyCode == Keys.W) {
        keysCurrentlyDown.Remove('W');
    } else if (e.KeyCode == Keys.D) {
        keysCurrentlyDown.Remove('D');
    } ...
}
}

处理这类事情的第一步是确保每个键可以并发激活,并且每个键的组合效果具有您想要的结果。如果您遵循这种方法,而不是尝试对组合键输入进行特殊处理,那么您的代码将更易于维护和编写。

例如,你可以有一组代表当前键状态的标志,然后在游戏的帧更新中,检查这些标志并将角色状态设置为正确的东西(即,而不是像你现在所做的那样在键处理本身中设置特定的图像)。

所以你可以有这样的标志:
bool lookUp, lookRight, lookDown, lookLeft;

则按下W将设置lookUp标志,而按上相同的键将清除该标志。同样地,例如对于D,对于lookRight标志。

然后在你的游戏框架更新,你检查标志。如果设置了lookUplookRight,则使用"向上和向右查找"图形。如果只设置了一个或另一个标志,则使用普通的"查找"或"正确查找"图形。其他键及其组合也是如此。你甚至可以解析lookUplookDown,或者lookLeftlookRight,无论默认图形是什么(即,如果用户没有按任何键)。


请注意,如果您愿意使用p/invoke,则可以使用GetAsyncKeyState()函数,甚至不必为键下事件操心。在游戏的每一帧更新前检查按键状态,并根据当前键盘状态更新视觉效果。这样,你让Windows完成所有的键状态跟踪,你就不会浪费时间跟踪无关紧要的键状态(例如,如果用户在帧之间对键状态进行多次更改)。


也就是说,如果你不能/不愿做以上任何一件事,那么是的……所有你需要做的就是先检查组合(也就是说,你得到了两个键的下键,而没有组合的初始键的上键)。

请注意,采用这种方法意味着您将仍然采用按下的第一个键的效果,然后必须切换到组合效果

使用

PresentationCore.dllWindowsBase.dll作为项目参考

PresentationCore.dll有一个Keyboard - Class, WindowsBase.dll有一个Key - Class。

:

    using System;
    using System.Windows.Forms;
    using System.Windows.Input;
            namespace ViewTest
            {
                public partial class ViewTest : Form
                {
                    private void ViewTest_KeyDown(object sender, KeyEventArgs e)
                    {
                        if (Keyboard.IsKeyDown(System.Windows.Input.Key.W) && 
                            Keyboard.IsKeyDown(System.Windows.Input.Key.D))
                        {
                            // do something
                        }
                    }
            }

这是一个简单的方法来做到这一点:)

考虑重写ProcessCmdKey

protected override bool ProcessCmdKey(ref Message m, Keys k)
{
    if (k == (Keys.Control | Keys.D))
    {
        MessageBox.Show("CTRL+D");
        return true;
    }
    return base.ProcessCmdKey(ref m, k);
}