使用KeyDown事件平滑移动控件

5

我正在使用Visual Studio Windows Form Application用C#编写一个简单的游戏。我想让用户可以使用相应的键自由地将蓝色框向上、向右、向下和向左移动。

我使用了定时器来每0.1秒检测框的新位置,并使用按键事件来实际更改框的位置。当按键被按下时,框需要保持向相应方向移动。

我的问题是,我的当前程序可以完成任务,但是当用户第一次按下键时,框会稍微移动一下然后暂停一会儿才继续移动。我希望在第一次按下键时,这个框能够更加流畅地移动而不会像那样暂停。这可能很难以言语表达,所以我添加了一个gif文件。

enter image description here

有没有办法解决这个问题?以下是我的当前代码。

private int posX, posY; //Both initialized in Form Load event

private void Form1_KeyDown(object sender, KeyEventArgs e)
{ 
    if (e.KeyCode == Keys.Up)
        posY -= 3;
    else if (e.KeyCode == Keys.Right)
        posX += 3;
    else if (e.KeyCode == Keys.Down)
        posY += 3;
    else if (e.KeyCode == Keys.Left)
        posX -= 3;
}

//Timer ticks every 0.1 second
private void Timer_Tick(object sender, EventArgs e)
{
    Box.Location = new Point(posX, posY);
    labelPosX.Text = posX.ToString(); //Testing purposes
    labelPosY.Text = posY.ToString(); //Testing purposes
}

我希望使用KeyDown事件来实现这个目标,但如果有更好或更常见的方法在真实的游戏世界中使用,我也很想了解!

1个回答

6

在你的 Timer_Tick 方法中使用 Keyboard.IsKeyDown 方法,不要监听按键按下事件。

示例:

double posX, posY;

private void Timer_Tick(object sender, EventArgs e)
{
    double velocity = /*(speed: pixels per seconds)*/ 100 * /*(timer tick time in seconds)*/ 0.003;

    if (Keyboard.IsKeyDown(Keys.Up))
    {
        posY -= velocity;
    }
    else if (Keyboard.IsKeyDown(Keys.Down))
    {
        posY += velocity;
    }
    //Also, don't put else here, so you can go diagonally.
    if (Keyboard.IsKeyDown(Keys.Left))
    {
        posX -= velocity;
    }
    else if (Keyboard.IsKeyDown(Keys.Right))
    {
        posX += velocity;
    }

    Box.Location = new Point((int)posX, (int)posY);
    labelPosX.Text = posX.ToString(); //Testing purposes
    labelPosY.Text = posY.ToString(); //Testing purposes
}

public static class Keyboard
{
    private static readonly HashSet<Keys> keys = new HashSet<Keys>();

    public static void OnKeyDown(object sender, KeyEventArgs e)
    {
        if (keys.Contains(e.KeyCode) == false)
        {
            keys.Add(e.KeyCode);
        }
    }

    public static void OnKeyUp(object sender, KeyEventArgs e)
    {
        if (keys.Contains(e.KeyCode))
        {
            keys.Remove(e.KeyCode);
        }
    }

    public static bool IsKeyDown(Keys key)
    {
        return keys.Contains(key);
    }
}

要使用Keyboard类,需要在InitializeComponent方法中设置Form1的KeyDown和KeyUp事件。

KeyDown += Keyboard.OnKeyDown;
KeyUp += Keyboard.OnKeyUp;

通过改变速度,您可以控制它的速度。


谢谢!我需要安装.dll文件或者什么东西吗?我的Visual Studio无法识别Keyboard。我已经添加了"Using System.Windows.Input;"但是它仍然无法识别。=/ - Mika Jones
哦,我忘记了 Forms 没有一个 Keyboard 类。让我为你编辑答案。 - rokkerboci
谢谢,我在想Keyboard类也适用于WPF。 - Mika Jones
这是我在SO上得到过的最好的答案。谢谢!它运行得很好! - Mika Jones
为什么这个解决方案比Form1_KeyDown变体更好?它有什么优势? - P_Gate

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接