Тетрис (анимация)
На основании предыдущего урока давайте сделаем упрощенную анимацию по мотивам игры Тетрис. Для этого давайте научимся проверять нижнуюю линиюю на заполненность и удалять ее.
Сделаем кубики разноцветными
В предыдущем уроке было заадние сделать кубики разноцветными, надеюсь вы справились самостоятельно. Давайте выполним это задание здесь. Для того чтобы кодировать цвет давайте введем новые правила представления сцены в массиве wall. Пустое место будем кодировать -1, а наличие шарика будем кодировать индексом цвета из массива brushes.
Введем массив кистей (цветов)
// возможные цвета наших кубиков
Brush[] brushes = [
Brushes.LimeGreen,
Brushes.DeepPink,
Brushes.Blue,
Brushes.Chocolate,
Brushes.Orange
];
Проверим что кубики стали разноцветными, запустим и убедимся:

Сделаем кубики объемными
Для того чтобы кубики стали выглядеть более красиво, давайте отрисуем псевдо затемнения для создания эффекта объема.
Запустим и проверим

Как мы видим после полного заполнения поля выставляется флаг состояние конец игры gameOver и анимация прекращается. Нажав кнопку R можем сбросить демо-сцену.
Удаление нижней линии
Теперь давайте сделаем удаление нижней линии если она заполнена. Чтобы сделать анимацию бесконечной и приблизиться к игре Тетрис. Удаление нижней линии происходит когда она полностью заполнена, давайте объявим функцию проверки линии на заполненность
bool IsLineFilled(int lineIdx)
{
bool filled = true;
for (int i = 0; i < wall.GetLength(0); i++)
{
if (wall[i, lineIdx] == 0)
{
filled = false;
break;
}
}
return filled;
}
Теперь напишем функцию которая сместит все строки на одну вниз, а первую строчку сделает пустой (заполнит нулями)
private void RemoveBottomLine()
{
//shift all rows
for (int i = wall.GetLength(1) - 1; i > 0; i--)
{
for (int j = 0; j < wall.GetLength(0); j++)
{
wall[j, i] = wall[j, i - 1];
}
}
//clear first line
for (int i = 0; i < wall.GetLength(0); i++)
{
wall[i, 0] = 0;
}
}
Добавим проверку и удаление нижней линии в игровой цикл:
private void Form1_Paint(object? sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
if (!gameOver) // если игра не окончена
UpdateScene(); // обновить сцену
e.Graphics.Clear(Color.Black);
var gr = e.Graphics;
DrawBlock(gr, BrickX, BrickY, colorIdx); // рисуем игровой блок
DrawBlocks(gr); // рисуем статичные блоки
if (IsLineFilled(wall.GetLength(1) - 1)) // если нижняя линия заполнена
RemoveBottomLine(); // удалить нижнуюю линию
if (IsLineFilled(0)) // если заполнена верхняя линия
gameOver = true; // выставить флаг состояние конец игры
}
Запустим и убедимся что нижняя линия будет удаляться

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