使用KeyDown事件平滑移动控件

时间:2017-12-26 15:01:13

标签: c# winforms keydown

我正在尝试使用Visual Studio Windows窗体应用程序在C#中创建一个简单的游戏。我想让用户能够使用相应的键自由地向上,向右,向下和向左移动蓝框。

我正在使用一个Timer,每0.1秒检测一次该盒子的新位置,以及一个实际改变盒子位置的keydown事件。 按住键时,盒子需要保持相应方向的移动。

我的问题是,我的当前程序完成了这项工作,除了当用户第一次按下一个键时,该框移动一点并在它继续移动之前暂停一会儿。我想让这个盒子从第一次按键移动得更顺畅而不会像那样暂停。这可能很难通过单词解释,所以我添加了一个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 个答案:

答案 0 :(得分:5)

Keyboard.IsKeyDown方法中使用Timer_Tick方法,不要监听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);
    }
}

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

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

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