Тетрис, разработка игр на SFML C++
"Тетрис" - легендарная игра, которую знает каждый. Она была создана в 1984 году российским программистом Алексеем Пажитновым и с тех пор завоевала сердца миллионов игроков по всему миру.
Игровой процесс заключается в заполнении горизонтального ряда в нижней части экрана фигурами из различных геометрических форм, известных как тетрамино. Довольно сложно описать, какие именно фигуры есть в игре, поэтому проще показать пример: это могут быть фигуры, состоящие из четырех квадратов (квадрат, "буква T", "буква L", "буква S", "буква Z", "буква I" и "буква J").
Существует несколько способов вращать и перемещать тетрамино по сетке, но главная цель - заполнить пустые места и создать полные ряды. Как только весь ряд заполнен, он исчезает, а оставшиеся сегменты сбрасываются на освободившееся место, при этом за каждый собранный ряд начисляются очки.
Сложность игры постепенно возрастает, поскольку скорость перемещения тетрамино со временем увеличивается, а количество свободного пространства уменьшается. Теоретически игра не имеет конца, но очень многие игроки не могут дойти даже до 10-го ряда.
Несмотря на то, что игра довольно проста по конструкции и правилам, она оказывает довольно сильное влияние на игроков. Универсальность тетрамино - практически безграничное количество комбинаций при относительно небольшом количестве фигур - придает игре яркий интеллектуальный стимул. Кроме того, благодаря высокоскоростному и динамичному игровому процессу, игроки часто испытывают предел своей концентрации, что делает игру еще более захватывающей.
Тетрис - это не просто игра, это легенда, которая живет и радует новые поколения игроков. Прошло уже более 35 лет с момента ее выхода, а она все еще не теряет своей популярности. Будь то на консолях, в мобильных приложениях или в онлайн-версиях, сейчас выбор игр больше, чем когда-либо прежде. Она отличается простым и ярким дизайном, уникальным геймплеем и невероятной культурной актуальностью, а также создает уникальные возможности для того, чтобы улучшить свою концентрацию и научиться быстро принимать сложные решения.
Тетрис
Проект Тетрис состоит из пяти классов: GameEngine, GameSound, Tetramino, Button, AssetManager.
AssetManager – управляет игровыми ресурсами, в которые входят текстуры, музыка, шрифты.
Button – создаёт объекты кнопок игрового интерфейса.
Tetramino – создаёт игровую логику для игры тетрис.
GameSound – создаёт и управляет звуковыми эффектами.
GameEngine – игровой движок.
Класс Button
Конструктор создаёт кнопку в графическом окне. В параметрах принимает координаты кнопки, текстуру с нормальным отображением и текстуру нажатой кнопки.
Метод checkClick() обрабатывает события нажатия на кнопку курсором мышки.
В параметрах передаются координаты курсора мышки для проверки, находится ли курсор мышки в пределах поля кнопки.
Метод setState(), устанавливает значение свойства состояния кнопки current и меняет значение указателя на спрайт отображение кнопки currentSpr соответствующим значением.
Класс GameSound
Создаём константу, значением которой будет количество звуковых эффектов в массиве namefilebuf и GSound. Создаём массив объектов Sound, которые будут воспроизводить загруженные аудио данные. В конструкторе создаем массив путей для загрузки аудио данных и загружаем звуковые эффекты в объекты воспроизведения звуковых эффектов GSound с помощью метода setBuffer(), аналогично тому, как мы загружаем текстуры для спрайтов. Затем устанавливаем объект с нулевым индексом с помощью метода setLoop() в положение true, чтобы зациклить воспроизведение, поскольку этот объект будет воспроизводить фоновую музыку.
Метод play() запускает воспроизведение звукового эффекта в соответствии с заданным параметром индекса, при условии, что эффект не воспроизводится.
Метод stop() останавливает воспроизведение звукового эффекта в соответствии с заданным параметром индекса, при условии, что эффект воспроизводится.
Метод AllStop() отключает воспроизведение всех звуковых эффектов.
Класс Tetramino
Открытая область класса Tetramino
Закрытая область класса Tetramino
Конструктор в параметрах принимает ссылку на графическое окно window, координаты игрового поля pos, размер игрового поля square_size, масштаб игрового поля и фигур тетрамино scale. В определении конструктора устанавливаем контур для фигуры прямоугольника размером в одну единицу setOutlineThickness(-1), минус обозначает внутренний контур прямоугольника, без знака внешний. Метод setOutlineColor(sf::Color(78, 87, 84)) устанавливает цвет контура серый. С помощью цикла создаём элементы массива игрового поля square, заполняя каждый значением Color::Black (чёрный цвет – пустое поле). Метод restart(), задаём начальные значения всех свойств тетрамино
В методе restart(), заполняем массив игровое поле пустыми значениями т.е. чёрным цветом. Устанавливаем случайное значение для типа typeTet.y и цвета colTet.y тетрамино. Количество набранных очков score, инициализируем значением ноль. Методом newFigrois() строим фигуру тетрамино.
В методе newFigrois(), присваиваем предварительные значения типа и цвета тетрамина, новому тетрамину в игровом поле.
С помощью формул высчитываем глобальные координаты по иксу и по игреку каждого элемента, из которого состоит тетрамино.
В массиве figures каждая фигура представлена в локальных координатах. Чтобы отобразить фигуру в глобальных координатах используем специальные формулы, в которых для нахождения значение по иксу берём остаток от деления локальных координат на два и добавляем ширину игрового поля, делённую на два, таким образом фигура начинает движение по центру игрового поля на оси икс. Для получения значения по игреку локальные координаты делим на два и округляем в меньшую сторону.
Используя генератор случайных чисел, находим новые значения типа и цвета фигуры тетрамино и присваиваем эти значения переменным макета тетрамино.
Задаём интервал обработки игровой логики delay.
В теле метода update(), измеряем интервал прошедшего времени frameRate, если интервал превышает установленные границы, обнуляем значение переменной подсчёта интервала времени. Если был задан вектор движения по иксу, проверяем на возможное столкновение фигуры тетрамино с препятствиями используя метод check(ch::x). Если препятствий нет перемещаем фигуру тетрамино, озвучиваем перемещение mus.play(3) и обнуляем вектор перемещения по иксу.
Аналогичную проверку делаем при движении тетрамино по игреку и перемещаем тетрамино. Если же движение по игреку невозможно, тогда проверяем выход за границы игрового поля и если это так, начинаем игру заново, иначе заполняем массив игрового поля цветом текущей фигуры тетрамино, используя координаты тетрамино, как индексы двумерного массива.
Следующий код определяет заполненную горизонталь игрового поля и удаляет её. Последней строчкой создаём новую фигуру на игровом поле newFigrois().
Методом tetDirection, меняем вектор движения фигуры по горизонтали.
В методе вращения фигуры rotate(), делаем предварительную проверку на столкновение фигуры с препятствиями check(ch::rotation), если таковых нет вращаем фигуру.
Для вычисления новых координат фигуры при вращении используем формулу из линейной алгебры.
Метод speed(), изменяет интервал обработки игровой логики на десять, таким образом ускоряя перемещение тетрамино.
Метод lineDead, уничтожает заполненную горизонталь, перезаписывая на её место в игровом поле предыдущие элементы тетрамино. В параметрах метод получает индекс заполненной горизонтали в массиве игрового поля.
Метод check(), в зависимости от установленного параметра, делает проверку на выход за границы игрового поля или столкновение с элементами фигур тетрамино в игровом поле, если столкновение или выход за границы присутствуют, возвращает значение false иначе true.
Метод draw(), если заданы координаты макета тетрамино рисует его в графическом окне. Рисует игровое поле и фигуру тетрамино.
Метод mustet() включает выключает фоновую музыку изменяя свойство playMus.
Метод getscore(), возвращает набранные игровые очки.
Метод getPositio() возвращает глобальные координаты центра вращения тетрамино.
Метод maket(), задаёт координаты макета тетрамино.
Класс GameEngine
В конструкторе задаём текстуру для игрового фона, шрифт и цвет текста, координаты макета тетрамино.
В методе input(), создаём обработку событий управления фигурой тетрамино стрелками на клавиатуре: движение влево, движение вправо, ускоренное падение фигуры вниз, поворот фигуры тетрамино.
При вращении колёсика мышки event.type == sf::Event::MouseButtonPressed фигура тетрамино ускоряет падение.
В разделе обработки нажатия кнопок мыши event.type == sf::Event::MouseButtonPressed, при нажатии левой кнопки, проверяем положение курсора мыши. Если курсор находится в зоне расположения кнопки игрового меню, выполняется код её нажатия и соответствующий этой кнопке алгоритм действия. Если курсор находится в пределах игрового поля, перемещаем фигуру тетрамино по горизонтали в ту сторону с какой стороны от фигуры находится курсор мыши.
При отпускании левой кнопки мыши, если клавиши рестарт или выход были нажаты, их положение возвращается в исходное.
При нажатии правой кнопки, если курсор находится в игровом поле происходит вращение тетрамино.
В методе update(), если пауза выключена проигрывается игровая логика тетрамино. При включении свойства выход, выход с приложения происходит с небольшой задержкой.
Метод draw() рисует в графическом окне: игровое поле с элементами тетрамино, фон игры, кнопки игрового интерфейса, текст подсчёта очков.
Метод run() создаёт игровой цикл, включая в него выше описанные методы.
Более подробную инструкцию вы можете получить, посмотрев видео «SFML C++ Тетрис»