The community is working on translating this tutorial into Macedonian, but it seems that no one has started the translation process for this article yet. If you can help us, then please click "More info".
In this article series, we're building a complete Snake game from scratch. It makes sense to start with the Introduction and then work your way through the articles one by one, to get the full understanding.
If you want to get the complete source code for the game at once, to get started modifying and learning from it right now, consider downloading all our samples!
Controlling the Snake
At this point in our article series on SnakeWPF, we now have a nice looking background and a moving snake. Unfortunately, the snake just moves in one direction until it leaves the area. We obviously need to add some code so that we can control the snake with the keyboard.
Most WPF controls have events for receiving input from the mouse and keyboard. So, depending on where you want to check the input, you can subscribe to these events for one or several controls and then perform the magic there. However, since this is a game, we want to catch keyboard input no matter where the focus might be, so we'll simply subscribe to the event directly on the Window.
For what we want to accomplish, the KeyUp event is a great match. So, find your XAML file for the Window and modify the Window tag so that it includes the KeyUp event like this:
<Window x:Class="WpfTutorialSamples.Games.SnakeWPFSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTutorialSamples.Games"
mc:Ignorable="d"
Title="SnakeWPF - Score: 0" SizeToContent="WidthAndHeight"
ContentRendered="Window_ContentRendered" KeyUp="Window_KeyUp">
In your Code-behind, add the Window_KeyUp event handler, like this:
private void Window_KeyUp(object sender, KeyEventArgs e)
{
SnakeDirection originalSnakeDirection = snakeDirection;
switch(e.Key)
{
case Key.Up:
if(snakeDirection != SnakeDirection.Down)
snakeDirection = SnakeDirection.Up;
break;
case Key.Down:
if(snakeDirection != SnakeDirection.Up)
snakeDirection = SnakeDirection.Down;
break;
case Key.Left:
if(snakeDirection != SnakeDirection.Right)
snakeDirection = SnakeDirection.Left;
break;
case Key.Right:
if(snakeDirection != SnakeDirection.Left)
snakeDirection = SnakeDirection.Right;
break;
case Key.Space:
StartNewGame();
break;
}
if(snakeDirection != originalSnakeDirection)
MoveSnake();
}
The first thing we do is to save a reference to the current direction that the snake is going in - we need this to make sure that the player is not trying to do something we won't allow, like reversing back over the snake body (e.g. from right to left). In other words, if the snake is moving vertically and the player wants to change the direction, it has to go horizontally first - you can't go directly from up to down or from left to right.
Next up is a switch statement, where we check which key was pressed. Here we check if one of the arrow keys (Up, Down, Left, Right) were pressed - if so, they are allowed to change the direction of the snake, unless the change is physically impossible, as described above. Also notice that I have added a check for the Space key: It will call the StartNewGame() method, to allow the player to choose when the game is started, instead of just starting it automatically. It will also allow the player to start a new game when the previous game has ended.
At the end of the method, we check if the direction has changed in comparison to the original direction - if it has, we call the MoveSnake() method, so that the change is reflected immediately.
We previously added a call to the StartNewGame() method in the Window_ContentRendered event - you can now remove this and instead start the game by pressing the Space key. Now lo and behold, the snake can be controlled - it's now close to being an actual game and not just an animated snake!
Summary
In this article, we added some pretty important functionality to our SnakeWPF implementation: Control of the snake! However, if you try to play it, you will notice that we still need one very important aspect, because the snake is currently disappearing out of the wall boundaries and it refuses to eat the food even when you hit it. In other words, we need to add some collision detection! More on that in the next article.