Графическая библиотека SFML. Создание Тетриса – Часть №2

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

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

 289

 ǀ   7 

Вот и подоспела вторая часть туториала по созданию тетриса на C++/SFML. Сегодня мы рассмотрим вопросы реализации механизма вращения фигурок тетрамино, а также их горизонтальные и вертикальные перемещения по игровому полю.

Горизонтальное перемещение тетрамино

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

Данный код очень простой. Сначала мы отлавливаем событие нажатия клавиши на клавиатуре (Event::KeyPressed), а затем проверяем, была ли это «стрелка влево» (Keyboard::Left) или «стрелка вправо» (Keyboard::Right). В зависимости от нажатой клавиши мы делаем шаг влево (dx = -1) или же шаг вправо (dx = 1). Далее, при помощи цикла for(), мы сдвигаем все части тетрамино в нужном направлении. И в конце мы присваивем ноль для переменной, обозначающей горизонтальное перемещение (dx = 0;).

Рассмотрим детальнее следующий код:

Здесь мы задаём первоначальные координаты для тетрамино. Строчка if(a[0].x == 0) является проверкой, убрав которую мы будем постоянно затирать изменяющиеся в результате горизонтального перемещения координаты тетрамино первоначальными координатами. Исходя из этого наши фигуры будут постоянно отрисовываться в верхнем левом углу игрового поля. Но, благодаря проверке выше, код, отвечающий за первоначальное размещение тетрамино на игровом поле, будет выполняться только тогда, когда наша фигура находится в «стартовом» положении и будет пропускаться тогда, когда тетрамино совершило перемещение вдоль оси.

В результате у нас получится что-то вроде следующего:


Вращение тетрамино


Теперь мы переходим к чуть более сложной части нашего туториала. Как вы наверняка помните, в тетрисе, помимо перемещения фигурок тетрамино вдоль горизонтальной оси, фигурки можно вращать. Для реализации данного функционала нам понадобятся знания линейной алгебры, а именно то, что вращение спрайта вокруг заданной точки с координатами (x_0; y_0) описывается уравнениями следующего вида:

X = x_0 + (x − x_0) * cos⁡(a) − (y − y_0 ) * sin⁡(a);
Y = y_0 + (y − y_0) * cos⁡(a) + (x − x_0 ) * sin⁡(a);

где (x; y) — это старые (исходные) координаты точки, (X; Y) — это новые координаты (после вращения), а а — это угол поворота. Так как все повороты у нас идут исключительно на 90°, а из школьного курса алгебры мы знаем, что:

sin⁡(90°) = 1
cos⁡(90°) = 0

то, подставляя соответствующие значения синуса и косинуса, исходные уравнения упрощаются до следующего вида:

X = x_0 − (y − y_0);
Y = y_0 + (x − x_0);

А теперь на практике:

Результат:


Вертикальное перемещение тетрамино

Осталось реализовать падение тетрамино вниз. Для этого мы создадим таймер при помощи класса Clock и по истечению 0.3 секунды с начала отсчёта времени мы будем сдвигать все части тетрамино на 1 позицию вниз. Для получения времени, прошедшего с момента старта таймера, мы будем использовать метод getElapsedTime(), а для перевода времени в секунды — метод asSeconds():

Как вы можете заметить, код довольно простой. В результате мы получим следующее:


Заключение


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

До скорых встреч 🙂

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

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

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

Комментариев: 7

  1. Аватар Александр:

    Странно. Нифига не получилось Скачал исходники — открыл — тоже не получилось =)
    Пустое белое игровое поле..

    1. Дмитрий Бушуев Дмитрий Бушуев:

      >>"Пустое белое игровое поле.."
      Только что проверил — всё работает. Скорее всего ваша проблема в том, что неправильно указан путь до текстуры. Обратите внимание на строчку:

      У меня путь — это "C:\dev\SFML_Tutorial\Images\tiles.png"
      Для вас 2 варианта решения:
      1 Вариант.
      Сделать путь относительным. Для этого замените строчку:

      на

      2. Вариант.
      Распакуйте архив с исходниками. Найдите в нем папку:
      "SFML — Tetris. Part2 — Sources"
      Скопируйте всё её содержимое в "С:\dev\SFML_Tutorial" (предварительно создав на диске С: папку "dev", а в ней — папку "SFML_Tutorial"). Таким образом, картинки с текстурами должны будут лежать в "С:\dev\SFML_Tutorial\images"

      1. Аватар Александр:

        С путем все ок.
        Показывает тетрамино N=3 если закомментарю строку

      2. Аватар Александр:

        Вот мой код если что
        https://onlinegdb.com/ryid1CIoH

        1. Дмитрий Бушуев Дмитрий Бушуев:

          А зачем же вы все глобальные переменные перенесли внутрь функции main()? В особенности эти:

          Ведь пока эти массивы структур были объявлены вне функции main() (т.е. как глобальные), то их элементы автоматически инициализировались нулями, благодаря чему проходилась проверка if (a[0].x == 0) и происходило отрисовывание тетрамино.

          А вот когда вы эти массивы переместили внутрь функции main(), то они стали инициализироваться "мусором", отличным от нуля. Именно поэтому, проверка не проходила и тетрамино не отрисовывались. И именно же поэтому тетрамино снова отображались, когда вы закомментировали строчку с проверкой.

          Картинка для наглядности:
          https://ibb.co/0QbCGhY

  2. Аватар Виктор:

    Шикарно! Большое спасибо за ваш разбор:) В следующий раз, пожалуйста, разберите, как реализованы шахматы.

    1. Дмитрий Бушуев Дмитрий Бушуев:

      Пожалуйста. Постараюсь сделать и про шахматы 🙂

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

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