1

I've made a snake game in WPF which works perfectly using WASD, but when I use the arrow keys instead, using the exact same code, it lags for 5 seconds after each key press.

A feature of the game is that you can adjust the play area size. When the play area size is small, the delay is short to non-existant. When the play area size is large, the delay is much more noticable. I do not however think the issue is with the game size, as it works fine with WASD.

The code I use to capture key input is below:

    private void Window_KeyDown(object sender, KeyEventArgs e) {    // Window_KeyDown is called every time the user presses a key. If the key is one of W, A, S, D, Up, Down, Left, Right (movement direction) or Space (play/pause), it will call the relevant functions.
        if (gameStateBools.isInGame && !gameStateBools.isPaused) {
            switch (e.Key) {
                case (Key.Space):    // Space "Clicks" the playPauseButton.
                    playPauseButton.RaiseEvent(new RoutedEventArgs(Button.ClickEvent));
                    break;
                case (Key.W):    // W changes the pendingDirection to move up.
                    if (gameState.direction != 1) {
                        pending.pendingDirection = 0;
                        ArrowFromDirection();
                    }
                    break;
                case (Key.S):    // S changes the pendingDirection to move down.
                    if (gameState.direction != 0) {
                        pending.pendingDirection = 1;
                        ArrowFromDirection();
                    }
                    break;
                case (Key.A):    // A changes the pendingDirection to move left.
                    if (gameState.direction != 3) {
                        pending.pendingDirection = 2;
                        ArrowFromDirection();
                    }
                    break;
                case (Key.D):    // D changes the pendingDirection to move right.
                    if (gameState.direction != 2) {
                        pending.pendingDirection = 3;
                        ArrowFromDirection();
                    }
                    break;
                case (Key.Up):    // Up changes the pendingDirection to move up.
                    if (gameState.direction != 1) {
                        pending.pendingDirection = 0;
                        ArrowFromDirection();
                    }
                    break;
                case (Key.Down):    // Down changes the pendingDirection to move down.
                    if (gameState.direction != 0) {
                        pending.pendingDirection = 1;
                        ArrowFromDirection();
                    }
                    break;
                case (Key.Left):    // Left changes the pendingDirection to move left.
                    if (gameState.direction != 3) {
                        pending.pendingDirection = 2;
                        ArrowFromDirection();
                    }
                    break;
                case (Key.Right):    // Right changes the pendingDirection to move right.
                    if (gameState.direction != 2) {
                        pending.pendingDirection = 3;
                        ArrowFromDirection();
                    }
                    break;
            }
        }
    }

EDIT: I've open sourced the project now that it's fixed :) https://github.com/jacobcxdev/UTC-Snake. Please note that this is my first C# project, so I've probably overcomplicated many things!

JacobCXDev
  • 417
  • 6
  • 16

1 Answers1

1

Set e.Handled = true in all cases.

The arrow keys have a function in the WPF framework (positioning, resizing). If you indicate that your user code has handled them, they are no longer forwarded to the windowing framework, which obviously takes its time processing those.

Another option is to capture the keystrokes earlier in the event pipeline, by overriding OnPreviewKeyDown and call its base only for keystrokes you don't process.

Cee McSharpface
  • 8,493
  • 3
  • 36
  • 77
  • 1
    Will he also need to do that in the PreviewKeyDown event, rather than KeyDown? – Robin Bennett Nov 13 '18 at 12:10
  • 1
    OP confirmed the first solution worked for them; using the tunneling version (previewkeydown) makes more sense though, [because this is what it was made for](https://stackoverflow.com/a/1460266/1132334). It may not make a difference here if there are no other focusable controls on their game canvas, we don't know. – Cee McSharpface Nov 13 '18 at 12:17
  • @dlatikay Here's the latest version of the game: https://github.com/jacobcxdev/files/raw/master/Snake.exe. My teacher at school wrote a rather disfunctional snake game for us to debug. I took one look at the code and thought "F*** it I'll just rewrite the whole thing", and so my first C# project was born! – JacobCXDev Nov 13 '18 at 12:26
  • and there goes my day's productivity. not bad, for a first project! love the attention to detail. if you add a two player mode I could waste one more coworker's time. now we have to take turns. – Cee McSharpface Nov 13 '18 at 12:34
  • Thanks! I've open sourced it here: https://github.com/jacobcxdev/UTC-Snake, in case you wanted to see the code (I've probably overcomplicated many things haha!). – JacobCXDev Nov 13 '18 at 12:52
  • @dlatikay As well as opensourcing it at the link in my previous comment, I've added `e.Handled = true` to the spacebar. In the version you have it's created a strange behaviour where it doesn't pause properly. – JacobCXDev Nov 13 '18 at 13:05