C# WPF: Обнаружение столкновений объектов в игре

Отслеживание столкновения змеи и фрукта

Отслеживание момента поедания змеей фрукта осуществляется в функции Timer_Tick, где проверяется совпадение позиции головы змеи с позицией фрукта, хранящейся в поле FoodPosition (функция PlaceFood отвечает за размещение фрукта). Условие проверки выглядит так:

if (NewHeadPosition == FoodPosition)
{
    // Змея съела фрукт
}

Действия после поедания фрукта

При совпадении позиций выполняются следующие действия:

  1. Создание нового фрукта: вызов функции PlaceFood для отображения фрукта в новой случайной позиции.
  2. Увеличение змейки: вызов функции EatFood.

Функция EatFood

Функция EatFood не принимает и не возвращает значений. В ней выполняются следующие действия:

  1. Создание нового сегмента: создание объекта Rectangle (назовем его NewSnake) с помощью функции CreateSnakeSegment. Позиция нового квадрата устанавливается равной FoodPosition.
  2. Отображение нового сегмента: добавление NewSnake в GameCanvas с помощью GameCanvas.Children.Add(NewSnake).
// ... в функции EatFood ...
Rectangle NewSnake = new Rectangle();
CreateSnakeSegment(NewSnake, FoodPosition);
GameCanvas.Children.Add(NewSnake);
// ...

На этом этапе новый квадрат появляется, но остается статичным. Для его движения вместе со змеей, необходимо объединить все сегменты змеи в один список.

Список сегментов змеи и его использование

Создадим список Snake типа List<Rectangle> для хранения всех сегментов змеи:

private List<Rectangle> Snake = new List<Rectangle>();

При создании головы змеи (SnakeHead) добавим её в список Snake:

Snake.Add(SnakeHead);

В функции EatFood также добавим новый сегмент в список Snake:

Snake.Add(NewSnake);

Движение змеи

Для синхронного движения всех сегментов, список Snake перебирается в обратном порядке. В цикле для каждого элемента устанавливается позиция, равная позиции предыдущего элемента:

for (int i = Snake.Count - 1; i > 0; i--)
{
    Snake[i].SetValue(Canvas.LeftProperty, Snake[i - 1].GetValue(Canvas.LeftProperty));
    Snake[i].SetValue(Canvas.TopProperty, Snake[i - 1].GetValue(Canvas.TopProperty));
}

Это обеспечивает движение всех сегментов за головой.

Удаление фрукта

Для удаления фрукта после поедания используется функция Remove из GameCanvas.Children:

GameCanvas.Children.Remove(GameCanvas.Children.OfType<Image>().FirstOrDefault());

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

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