Тетрис на C++: Статическая модель

Тетрис на C++ Статическая модель

Рекомендую сначала ознакомиться с вводной заметкой, посвященной реализации тетриса на C++, если вы еще этого не сделали.

Игровое поле тетриса

Игровое поле тетриса представляет собой простой двумерный массив или матрицу. На C++ для этого можно использовать следующую структуру:

Каждый элемент матрицы, представляющей игровое поле, определяет состояние соответствующего «блока» на некоторой позиции (x; y). Под блоками будем понимать клетки игрового поля. Для самих состояний достаточно иметь всего 3 условных обозначения:

  1. Пустой блок: подойдет значение 0;
  2. Занятый блок: 1, 2, и т.д.;
  3. Блок за пределами игрового поля: -1.

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

Как видно на рисунке слева, каждому числовому обозначению мы можем назначить некоторый цвет. Однако этот аспект не касается Модели, а полностью зависит от Представления, поэтому сейчас мы на нем останавливаться не будем.

Изображенному игровому полю на C++ соответствует следующая матрица:

Для вывода на экран текущего состояния игрового поля нам требуется лишь доступ к его размерности и элементам. Обратите внимание, что если запрос элементов организовать на манер Представления, то есть по координатам (а не рядам и столбцам), то возникает небольшая путаница. Элемент fieldMatrix[ x ][ y ] на самом деле соответствует элементу из x-го ряда (ходим вверх-вниз) и y-го столбца (ходим влево-вправо). То есть координаты оказываются перепутаны, поэтому для исправления ситуации приходится использовать конструкцию вида fieldMatrix[ y ][ x ].

Игровые элементы тетриса

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

По оси x элемент может быть сдвинут лишь на расстояние, эквивалентное величине блока игрового поля. Однако при своем падении, для обеспечения плавности перемещения, элемент смещается не на целый блок, а на какую-то его долю. Поэтому возникает необходимость ввести еще одну единицу измерения. Условно назовем ее «точкой». И скажем, что блок состоит из точек.

Таким образом, активный элемент должен позиционироваться с помощью точек, а не блоков для получения приемлемой точности. Например, для представления L-образного элемента вновь используем матричную структуру:

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

Заключение

На уровне статики можно считать, что игровое поле и активный элемент живут в параллельных вселенных. Для Представления это не имеет никакого значения, поскольку ему достаточно уметь рисовать блоки по заданным координатам в точках, что мы уже обеспечили. Модель должна сама гарантировать, что состояние игры остается корректным в каждый момент времени. А это достигается путем введения обнаружения столкновений, о чем мы поговорим в следующий раз…

Понравилась статья? Поделиться с друзьями:
Добавить комментарий