TOC

This article has been localized into Russian by the community.

Создание игры: WPF змейка:
Chapter introduction:

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!

Непрерывное движение с помощью DispatcherTimer'а

В предыдущих статьях мы создали симпатичное игровое поле для нашей Змейки и описали в коде ее создание и движение. Однако, как уже упоминалось, код, описывающий движение должен вызываться вновь и вновь для отображения изменений пока игра не завершится. Другими словами нам понадобится таймер.

В общих словах в программировании таймеры обычно используются как механизм, позволяющий засекать точные промежутки времени для повторяющихся действий. То есть срабатывание таймера (tick) происходит через определенный интервал времени и в результате выполняется определенный код. Это именно то, что нам нужно для поддержания нашей Змейки в движении, поэтому мы добавим DispatcherTimer в наше Окно:

public partial class SnakeWPFSample : Window        
{        
    private System.Windows.Threading.DispatcherTimer gameTickTimer = new System.Windows.Threading.DispatcherTimer();  
    ....

Теперь нам потребуется подписаться на одно-единственное событие - Tick. И сделаем мы это в конструкторе нашего окна:

public SnakeWPFSample()  
{  
    InitializeComponent();  
    gameTickTimer.Tick += GameTickTimer_Tick;      
}

А тут реализация выполнения события:

private void GameTickTimer_Tick(object sender, EventArgs e)  
{  
    MoveSnake();  
}

Итак, при каждом срабатывании таймера вызывается событие Tick, которое вызывает метод MoveSnake(), реализованный ранее. Чтобы насладиться результатами проделанной работы и увидеть движущуюся змейку нам нужно всего лишь создать, инициализировать части змейки и запустить таймер. Создадим метод StartNewGame() и будем использовать его как для начала первой игры, так и для начала новой игры после смерти игрока. Начнем с базовой версии. Потом я добавлю функциональности, а теперь - заставим змейку двигаться!

Первым делом добавим еще набор констант, необходимых для начала новой игры:

public partial class SnakeWPFSample : Window  
{  
    const int SnakeSquareSize = 20;  
    const int SnakeStartLength = 3;  
    const int SnakeStartSpeed = 400;  
    const int SnakeSpeedThreshold = 100;  
    ......

На этом этапе используются только три первые константы, отвечающие за размер, длину и начальную скорость Змейки. SnakeSpeedThreshold понадобится позже, а сейчас, как обещали, добавим простую реализацию метода StartNewGame():

private void StartNewGame()  
{  
    snakeLength = SnakeStartLength;  
    snakeDirection = SnakeDirection.Right;  
    snakeParts.Add(new SnakePart() { Position = new Point(SnakeSquareSize * 5, SnakeSquareSize * 5) });  
    gameTickTimer.Interval = TimeSpan.FromMilliseconds(SnakeStartSpeed);  

    // Draw the snake  
    DrawSnake();  

    // Go!      
    gameTickTimer.IsEnabled = true;  
}

Мы начали с установки snakeLength и snakeDirection в начальные значения. Затем мы добавили одну часть змейки в snakeParts List (другие позже), задавая ей прекрасную начальную позицию для движения вправо - мы еще раз используем константу SnakeSquareSize для вычисления подходящей позиции. С этого места мы можем рисовать змейку вызывая метод DrawSnake() и включая таймер, который начинает движение змейки.

Наконец мы почти подошли к месту, когда можно откинуться и насладиться самой первой версией того, что вполне выглядит игрой - действительно, все, что осталось сделать это вызвать метод StartNewGame(). Это действительно необходимо сделать, и сейчас, когда все остальное готово мы вернемся немного назад и воспользуемся событием ContentRendered из Window, которое мы добавляли в первых статьях. Просто добавьте вызов метода StartNewGame() и мы окончательно готовы к сборке и запуску:

private void Window_ContentRendered(object sender, EventArgs e)  
{  
    DrawGameArea();  
    StartNewGame();  
}

Если вы сделали все, как описано, то вы сможете начать игру и увидеть как змейка после создания сразу начнет двигаться:

Заметьте - змейка появляется из ниоткуда, начиная с одного квадратика и постепенно вырастая до 3 клеток в длину. Так происходит потому, что изначально мы добавляем лишь один элемент в список snakeParts. В свою очередь, метод MoveSnake(), вызываемый таймером, каждый раз доавляет к змейке новый фрагмент, увеличивая её размер на единицу. Хвостовые фрагменты змейки начинают удаляться только тогда, когда размер змейки начинает превышать желаемый (он опередлён константой SnakeStartLength).

Заключение

Наконец, у нас появилась класная змейка, способная передвигаться! Но как вы могли заметить на анимации выше - у нас ещё осталась работа. В первую очередь, на поле нет еды, да и столкновение змейки со стеной не производит ожидаемого эффекта. Мы поработаем над этим в следующих частях статьи.

This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!