Создание «Тетриса» в С++/SFML: Часть №3

  Дмитрий Бушуев  | 

  Обновл. 30 Ноя 2019  | 

 412

Вот мы и подошли к заключительной части нашей серии уроков по созданию Тетриса средствами C++\SFML: вот Часть №1, а вот Часть №2. Сегодня мы рассмотрим реализацию механизма проверки тетрамино на выход за пределы игрового поля, сделаем генерацию рандомных типов фигурок и их цветов, добавим возможность ускорить падение тетрамино, будем уничтожать полученную из тетрамино линию и установим рамки игрового поля, вместе с фоном.

Проверка границ и случайная генерация тетрамино

Функция проверки тетрамино на выход за границы игрового поля довольно-таки простая и состоит из двух условий if():

   первое условие if() проверяет, не вышли ли мы за границы поля слева, справа и снизу. Т.к. мы движемся сверху-вниз, то выйти за границу сверху мы не можем, соответственно, проверять её нет смысла.

   второе условие if() проверяет, свободна ли сейчас ячейка или занята другими тетрамино.

Код:

Теперь реализуем рандомную генерацию тетрамино с помощью генератора случайных чисел. Для этого подключаем заголовочный файл time.h:

А в теле функции main() дописываем следующую строчку:

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

Рассмотрим этот код детальнее. Сначала мы перемещаем координаты массива a[] во вспомогательный массив b[]:

Далее на игровой доске делаем «шаг влево» или «шаг вправо»:

А затем проверяем, не вышли ли мы за пределы игрового поля. Если вышли, то возвращаем старые координаты из вспомогательного массива b[]:

То же самое проделываем с секцией «Вращение»:

А теперь секция «Тик таймера». Здесь мы добавим цикл for(), в котором, при помощи генератора случайных чисел, будем задавать тип и цвет тетрамино:

Не забываем, что нужно объявить переменную, которая будет определять цвет тетрамино:

Ловим баг


Далее у автора видео идет довольно спорный момент. Он, видимо, посчитав, что алгоритм первоначального задания тетрамино теперь перенесён в секцию «Движение тетрамино вниз («Тик» таймера)», легким взмахом руки удаляет из проекта следующий кусок кода:

Из-за чего мы получаем неприятный баг, о котором я расскажу ниже. А пока, продолжая повествование видеоролика, отредактируем нижеследующую секцию кода «Отрисовка»:

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

Баг — это одинокий квадратик, который постоянно присутствует на поле. Данная ошибка возникает из-за того, что в самом начале игры, при создании первой фигурки-тетрамино, не выполняется код, который отвечает за следующее:

Для начала, чтобы исправить этот баг, нам нужно создать новую переменную beginGame. И сюда же перенесем инициализацию переменной n, при помощи которой задаётся тип тетрамино:

Далее частично продублируем секцию кода «Движение тетрамино вниз («Тик» таймера)», чтобы появление первой фигурки-тетрамино происходило корректно. Для этого сделаем следующие изменения:

Код, расположенный внутри блока if(beginGame), вызывается только один раз при старте приложения. Благодаря ему задаётся первоначальный тип тетрамино. В результате этих действий стартовый тетрамино отображается корректно и бага больше нет:


Ускоряем движение тетрамино вниз

Если вы уже знаете, куда поставить тетрамино и не хотите ждать, пока оно своим ходом доберется до этого положения, то логичным будет ускорить падение фигурки по нажатию на кнопку «Стрелка вниз», как это и реализовано в многочисленных вариантах тетриса. Для этого добавим проверку на нажатие соответствующей клавиши на клавиатуре. И, если условие выполняется, то уменьшим задержку между «тиками» до 0.05 секунды, тем самым заставив тетрамино падать быстрее:

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

Разукрашиваем тетрамино


До этого момента все тетрамино имели одинаковый цвет. Пришло время их немного разукрасить:

Результат:


Уничтожение полученной из тетрамино линии

Рассмотрим вопрос о реализации функции проверки на наличие заполненной тетрамино линии, которую по правилам тетриса нужно удалять. В этом нам поможет цикл for() с помощью которого мы снизу-вверх пройдёмся по массиву field[][], который представляет наше игровое поле, и проверим каждый элемент массива на равенство нулю.

Если элемент field[i][j] не равен нулю (т.е. эта позиция поля уже занята), то увеличиваем счётчик на единицу (count++) и присваиваем данный элемент самому себе (field[k][j] = field[i][j];). При этом, мы как бы с двух сторон ползём вверх по массиву field[][], увеличивая сначала индекс i и, если у нас есть пробелы в текущей строке (count < N), индекс k. И опять присваиваем каждый элемент строки самому себе. Тем самым текущая строка не изменяется.

Но если условие if (count < N) не выполняется (т.е. в данной строке все места заняты), то индекс  k не меняется. И тогда при очередном присваивании field[k][j] = field[i][j]; индекс k не будет равен индексу i. А это означает, что элементы верхней строки будут присвоены элементам нижней строки. Тем самым наше игровое поле «сдвинется» вниз на одну строчку:

Картинка для понимания процесса:

Результат:


Установка текстуры фона


Осталось дело за малым: установить фоновую текстуру и рамку игрового поля. Для этого создадим две дополнительные переменные текстур — texture_background и texture_frame и соответствующие им две переменные спрайтов sprite_background и sprite_frame:

Добавим отрисовку новых спрайтов в секцию «Отрисовка». Т.к. наши фигуры появляются от края окна, а текстура фона немного смещена к центру, то нужно немного сместить тетрамино, чтобы всё выглядело красиво. Для этого воспользуемся функцией sprite.move(28, 31):

Окончательная версия нашего Тетриса:


Заключение

Ну вот и всё, друзья! Наше приложение готово! Конечно, здесь можно ещё много чего реализовать, например: отображение игровых очков, функция для подсчёта очков, музыкальное сопровождение, разные уровни сложности с динамическим увеличением скорости тетрамино и т.д. Но это уже вы можете попробовать сделать сами, добавляя новый функционал или изменяя текущий. Я же хочу сказать вам за ваше внимание и интерес к моим статьям: «Большое Спасибо!».

И до скорых встреч! 🙂

Исходный код. Создание Тетриса — Часть №3


Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (3 оценок, среднее: 5,00 из 5)
Загрузка...

Добавить комментарий

Ваш E-mail не будет опубликован. Обязательные поля помечены *