Question

I have a WinForms program, where I have a certain animated object that moves around when I press Up, Down, Left and Right. The movement of the object is animated inside a timer, that is called every 30 ms. The timer starts on KeyDown event, and stops on KeyUp event.

So, if I hold for example left, and then immediately after I release the left key and press another one, there's a slight pause (about half a second), before it moves in that direction. That problem does not appear, if I hold left, the release it, and wait a little bit, and then press right. In such case, it would immediately move right. It also doesn't appear if I am holding down left, and then start holding down right, while I'm still holding left. In that case, it would start moving right immediately, too. The problem only appears, when I release the key and immediately press another one afterwards.

KeyDown event:

private void form_KeyDown(object sender, KeyEventArgs e)
    {
        k = 0;
        watch.Start();

        if (e.KeyCode == Keys.Left)
        {
            direction = MOVE_LEFT;
        }
        else if (e.KeyCode == Keys.Right)
        {
            direction = MOVE_RIGHT;
        }
        else if (e.KeyCode == Keys.Up)
        {
            direction = MOVE_UP;
        }
        else if (e.KeyCode == Keys.Down)
        {
            direction = MOVE_DOWN;
        }
        timerMove.Start();
    }

KeyUp event:

private void form_KeyUp(object sender, KeyEventArgs e)
    {
        timerMove.Stop();
    }

Timer event (animation movement)

void charMovement(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (direction == MOVE_LEFT)
        {
                timerMove.Interval = 30;
                CharSize(11, 15); //mainChar.Size = new System.Drawing.Size(11, 15);
                //code for movement

        }
        else if (direction == MOVE_RIGHT) //... etc. etc.
Was it helpful?

Solution

The problem is not the timers, but the repeat pause setting of your keyboard. If you press and hold a key, there is a pause between the first and the second letter. A longer pause then between the following letters. That is what you see.

You could forget about the keyboard events and use a single heart beat timer, check what keys are pressed and then act on it. It seems WinForms does not have something like GetKeySate, but you could P/Invoke the win32 function.

Or you could roll your own version of GetKeyState and remember what keys are presses in KeyDown and reset the flag in KeyUp. The move timer keeps running as long as at least one key is pressed.

OTHER TIPS

try doing this if you haven't done it yet

FormName.KeyPreview = true;

also, only use one method.. not two.. tendency is the keypress would be read twice since there is an up and a down... try using KeyPreview = true; then use KeyPress instead of KeyDown and KeyUp

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top