3

So I've successfully created a Snake game that functions fine with the exception of one little thing that I don't know how to solve. Let me try to explain.

So the game works on a timer where each tick of the timer means moving each block of the snake in the specified direction. It works so that if you're moving right, you cannot move left (because then the head would intersect with the body and you'd lose). The same goes for the all the other possible directions. There is a direction variable that specifies the current direction of the snake. So the problem is that when you press the left key, it will check if the direction is set to right and if it is, nothing will happen. But if you were to press the down key and then the left key both within the same interval of time, then the snake will move left and you'll lose. Here's the code that handles the KeyDown event for the form.

    private void frmMain_KeyDown(object sender, KeyEventArgs e)
    {
        switch (e.KeyData)
        {
            case Keys.Enter:
                if (lblMenu.Visible)
                {
                    lblMenu.Visible = false;
                    LoadSettings();
                    gameLoop.Start();
                }
                break;
            case Keys.Space:
                if (!lblMenu.Visible)
                    gameLoop.Enabled = (gameLoop.Enabled) ? false : true;
                break;
            case Keys.S:
                using (frmSettings f = new frmSettings())
                {
                    f.ShowDialog(this);
                }
                break;
            case Keys.Right:
                if (direction != Direction.Left)
                    direction = Direction.Right;
                break;
            case Keys.Down:
                if (direction != Direction.Up)
                    direction = Direction.Down;
                break;
            case Keys.Left:
                if (direction != Direction.Right)
                    direction = Direction.Left;
                break;
            case Keys.Up:
                if (direction != Direction.Down)
                    direction = Direction.Up;
                break;
        }
    }

Here's a download to the game if you want to experience the bug first-hand. Thank you for any help!

nvoigt
  • 75,013
  • 26
  • 93
  • 142
Minato
  • 352
  • 3
  • 13
  • You may want to have a look at [this post on how to handle time in games](http://stackoverflow.com/questions/17440555/using-timer-and-game-loop/17440807#17440807) because it's very different from normal Windows Forms programming. Having a conventional timer will cause you a lot of problems. – nvoigt Sep 24 '14 at 18:20
  • @nvoigt That post is interesting and very helpful, I had no idea that's how games could work! – Minato Sep 24 '14 at 18:28

2 Answers2

3

What you have is actually a "feature". You want to be able to go down then left, but you are doing it within a timer tick, causing the "bug".

That means that you need to wait to change direction. Your code becomes:

if (direction != Direction.Right)
   intendedDirection = Direction.Left;

...

OnTimerTick()
{
    ...
    direction = intendedDirection;
}

Now, you can press as many keys as you want (that are valid) the last will take effect on the timer tick, which will then allow the next key press (left) to work correctly.

BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
  • Ah, the classic "feature, not a bug" – tnw Sep 24 '14 at 18:10
  • @tnw Well, the code is right, just the timing is off. The feature is effectively correct here. I might leave it in just so whatever idiot tried to push the keys too fast lost the game :) Then it really would be a feature. – BradleyDotNET Sep 24 '14 at 18:12
  • @BradleyDotNET Yes I've tried something almost identical to that as well as just trying your idea exactly and while it does work, it makes the game flow less well. What I mean by that is sometimes you'll press down and left really quickly and it will continue moving down and not left on the next line. I think that I should just keep it though, it's a part of the game right? – Minato Sep 24 '14 at 18:14
  • 1
    @Minato You can't have it both ways. Either you change direction on the timer tick (and are safe) or change instantaneously (and you have your "bug"). Only you know which way you want it, but you can't have your cake and eat it too! I would consider keeping it, but thats just me. – BradleyDotNET Sep 24 '14 at 18:17
  • @BradleyDotNET Thank you, I am new to the site actually! And I didn't know that was how this worked so thank you for informing me! – Minato Sep 24 '14 at 18:25
  • @Minato Consider looking through the tour ( http://stackoverflow.com/tour ) to see more information. Welcome to Stack Overflow! – BradleyDotNET Sep 24 '14 at 18:27
0

I don't know how you store the snake positions, but I would verify that for each arrow pressed, the position in that direction differs from the snakes 'head' position otherwise you can ignore that keypress.

huysentruitw
  • 27,376
  • 9
  • 90
  • 133