如何修复这两个键按下冲突?

时间:2013-01-22 13:28:38

标签: c# forms class events event-handling

我有一个问题,我正在努力..我想用键盘向左,向右,向上或向下以对角线方式移动图像。我在网上搜索并发现,要使用2个不同的密钥,我需要记住以前的密钥,所以我正在使用bool字典。

在我的主要Form类中,这就是KeyDown事件的样子:

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    baseCar.carAccelerate(e.KeyCode.ToString().ToLower());
    carBox.Refresh(); //carbox is a picturebox in my form that store the image I want to move.
}

我的KeyUp事件:

private void Form1_KeyUp(object sender, KeyEventArgs e)
{
    baseCar.carBreak(e.KeyCode.ToString().ToLower());
}

我的油漆事件:

private void carBox_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.DrawImage(Car, baseCar.CharPosX, baseCar.CharPosY); // Car is just an image
}

我的baseCar类:

private Dictionary KeysD = new Dictionary(); // there is a method to set the W|A|S|D Keys, like: KeysD.Add("w",false)

public void carAccelerate(string moveDir)
{       
    KeysD[moveDir] = true;
    moveBeta();
}
public void moveBeta()
{
    if (KeysD["w"])
    {
        this.CharPosY -= this.carMoveYSpeed;
    }
    if (KeysD["s"])
    {
        CharPosY += carMoveYSpeed;
    }
    if (KeysD["a"])
    {
        CharPosX -= carMoveXSpeed;
    }
    if (KeysD["d"])
    {
        CharPosX += carMoveXSpeed;
    }
}
public void carBreak(string str)
{
    KeysD[str] = false;
}

无论如何它可行,但我的问题是我无法回到第一个按下的键,例如:

我按W向上移动,然后D键向对角线移动,当我释放D键时,它不会再次上升,因为KeyDown事件是“死”并且不会再次调用carAccelerate()方法。我无法弄清楚如何解决它..

任何人都能帮帮我吗?也许有更好的方法来处理密钥?我愿意接受任何想法!我希望你能理解它,我的英语不是最好的:S

1 个答案:

答案 0 :(得分:1)

通常,您不会直接针对这些事情处理关键事件。相反,您可以跟踪当前按下的键。物理计算在某个时间间隔内完成,可以使用计时器完成。下面快速而肮脏的例子。但是,这不是你应该尝试使用WinForms的那种东西。

    private const int ACCELERATION = 1;

    private HashSet<Keys> pressed;
    private int velocityX = 0;
    private int velocityY = 0;

    public Form1()
    {
        InitializeComponent();
        pressed = new HashSet<Keys>();
    }

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        pressed.Add(e.KeyCode);
    }

    private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
        pressed.Remove(e.KeyCode);
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        car.Location = new Point(
            car.Left + velocityX,
            car.Top + velocityY);
        if (pressed.Contains(Keys.W)) velocityY -= ACCELERATION;
        if (pressed.Contains(Keys.A)) velocityX -= ACCELERATION;
        if (pressed.Contains(Keys.S)) velocityY += ACCELERATION;
        if (pressed.Contains(Keys.D)) velocityX += ACCELERATION;
    }