C# WPF Игра: Управление змейкой с клавиатуры

Этот урок посвящен добавлению динамики в игру — созданию механизма управления змейкой с помощью клавиатуры. Для реализации динамических действий будем использовать таймер, позволяющий выполнять код через определённые интервалы времени.

Подготовка: Описание полей

Удалим поле FoodColor, так как для отображения фрукта теперь используется изображение. Определим перечисление Direction для хранения информации о направлении движения змейки:

public enum Direction
{
    Left,
    Right,
    Up,
    Down
}

Создадим поле для хранения текущего направления движения змейки:

public Direction CurrentDirection { get; set; } = Direction.Right; // Изначальное направление – вправо

Для работы с таймером определим поля:

private const int TimerInterval = 200; // Интервал срабатывания таймера в миллисекундах
private DispatcherTimer _timer;

Реализация таймера и функции движения

В обработчике события GameCanvas_Loaded инициализируем и настроим таймер:

_timer = new DispatcherTimer();
_timer.Tick += TimerTick;
_timer.Interval = TimeSpan.FromMilliseconds(TimerInterval);
_timer.Start();

Функция TimerTick, вызываемая при каждом срабатывании таймера:

private void TimerTick(object sender, EventArgs e)
{
    Point newHeadPosition = CalculateNewHeadPosition();
    // ... код для обновления позиции змейки на канвасе ...
}

Функция CalculateNewHeadPosition вычисляет новые координаты головы змейки:

private Point CalculateNewHeadPosition()
{
    double left = Canvas.GetLeft(SnakeHead) / SnakeSquareSize;
    double top = Canvas.GetTop(SnakeHead) / SnakeSquareSize;
    Point headCurrentPosition = new Point(left, top);
    Point newHeadPosition = new Point();

    switch (CurrentDirection)
    {
        case Direction.Left:
            newHeadPosition = new Point(headCurrentPosition.X - 1, headCurrentPosition.Y);
            break;
        case Direction.Right:
            newHeadPosition = new Point(headCurrentPosition.X + 1, headCurrentPosition.Y);
            break;
        case Direction.Up:
            newHeadPosition = new Point(headCurrentPosition.X, headCurrentPosition.Y - 1);
            break;
        case Direction.Down:
            newHeadPosition = new Point(headCurrentPosition.X, headCurrentPosition.Y + 1);
            break;
    }

    return newHeadPosition;
}

В TimerTick после вычисления новых координат обновим позицию головы змейки на канвасе:

Canvas.SetLeft(SnakeHead, newHeadPosition.X * SnakeSquareSize);
Canvas.SetTop(SnakeHead, newHeadPosition.Y * SnakeSquareSize);

Обработка нажатий клавиш

Добавим обработчик события KeyDown к окну приложения:

<Window ... KeyDown="Window_KeyDown">
    ...
</Window>

В обработчике Window_KeyDown проверим нажатую клавишу и изменим направление движения змейки:

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    switch (e.Key)
    {
        case Key.Up:
            if (CurrentDirection != Direction.Down) CurrentDirection = Direction.Up;
            break;
        case Key.Down:
            if (CurrentDirection != Direction.Up) CurrentDirection = Direction.Down;
            break;
        case Key.Left:
            if (CurrentDirection != Direction.Right) CurrentDirection = Direction.Left;
            break;
        case Key.Right:
            if (CurrentDirection != Direction.Left) CurrentDirection = Direction.Right;
            break;
    }
}

Теперь змейка будет двигаться в соответствии с нажатыми клавишами. Проверка на противоположное направление предотвращает мгновенное изменение направления на противоположное, что сделало бы игру неиграбельной.

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

Что будем искать? Например,программа