使用 KeyDown 事件平滑地移动控件

Move a control smoothly using KeyDown event

我正在尝试使用 Visual Studio Windows 表单应用程序在 C# 中制作一个简单的游戏。我想让用户可以使用相应的键自由地向上、向右、向下和向左移动蓝色框。

我正在使用一个定时器,它每 0.1 秒检测一次盒子的新位置,以及一个实际改变盒子位置的按键事件。 按住键的同时,盒子需要继续朝相应的方向移动。

我的问题是,除了当用户第一次按下某个键时,方框移动一点点并暂停片刻,然后继续移动之外,我当前的程序可以完成这项工作。我想让这个盒子从第一次按键开始移动得更顺畅,而不是那样停顿。这可能很难用文字解释,所以我添加了一个 gif 文件。

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

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 事件来实现这一点,但如果在真实游戏世界中有更好或更常见的实际使用方式,我也很想知道!

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

像这样:

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);
    }
}

要使用键盘 class,请在 InitializeComponent 方法中设置 Form1 的 KeyDown 和 KeyUp 事件。

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

你可以通过改变速度来控制它的速度。