Руководство по программированию с wxWidgets (12. Тетрис в wxWidgets) |
- Statistics
- Participants
- Translate into Russian
- Translation result
- Translation complete.
Тетрис в wxWidgets
Тетрис
Тетрис - это самая популярная компьютерная игра из всех когда-либо созданных. Оригинальная игра была создана русским программистом Алексеем Пажитновым в 1985. После этого тетрис портировали на всевозможные платформы в различных вариациях. Модифицированная версия тетриса есть даже на моём мобильнике.
Тетрисом называется головоломка, в которой нужно размещать падающие блоки по определённым правилам. Есть семь различных форм, называемых тетроминами. S-форма, Z-форма, T-форма, L-форма, I-форма, зеркальная L-форма, квадратная форма. Каждая из этих форм создана из четырёх квадратов. Итак, эти формы в случайном порядке падают вниз. Цель игры с помощью перемещения и вращения форм разместить их внизу как можно более компактно. Если блоки, из которых состоят формы, составят непрерывную горизонтальную линию, то она уничтожится и мы получим игровые очки. Игра заканчивается, когда не остаётся места для размещения новых форм.
wxWidgets - это тулкит разработанный для создания приложений. Существуют специальные библиотеки нацеленные на разработку компьютерных игр. Тем не менее, wxWidgets и другие тулкиты тоже могут быть использованы для этих целей.
Разработка
Мы не имеем готовых изображений для нашей игры, нам придётся нарисовать тетромины используя функции рисования тулкита wxWidgets. Основой любой компьютерной игры является математическая модель. И тетрис не исключение.
Несколько идей по игре.
* Мы востпользуемся wxTimer для создания игрового цикла.
* Нарисуем термомины
* Формы двигаются по базису от квадрата к квадрату (а не от точке к точке).
* Математически игровая доска - это простой список номеров.
Мы немного упростили игру, для лучшего понимания. Игра начинается сразу после запуска приложения. Клавиша p - пауза. Пробелом можно мгновенно опустить форму вниз. Клавишей d - ускорить падение формы. Игра идёт с постоянной скоростью, ускорение не предусмотрено. Количество очков равно количеству удалённых строк.
...
isFallingFinished = false;
isStarted = false;
isPaused = false;
numLinesRemoved = 0;
curX = 0;
curY = 0;
...
Перед началом игры мы инициализируем некоторые важные переменные. Переменная isFallingFinished определяет, закончила ли форма падение, если да, то нужно создать новую. Переменная numLinesRemoved считает строки, которые мы удалили. Переменные curX и curY определяют действительную позицию падающей формы.
for (int i = 0; i < BoardHeight; ++i) {
for (int j = 0; j < BoardWidth; ++j) {
Tetrominoes shape = ShapeAt(j, BoardHeight - i - 1);
if (shape != NoShape)
DrawSquare(dc, 0 + j * SquareWidth(),
boardTop + i * SquareHeight(), shape);
}
}
Прорисовка игры включает два шага. Первый - мы рисуем формы, или то, что осталось после падения форм вниз игрового поля. Все квадраты хранятся в массиве игрового поля. Мы получаем доступ к нему используя метод ShapeAt().
if (curPiece.GetShape() != NoShape) {
for (int i = 0; i < 4; ++i) {
int x = curX + curPiece.x(i);
int y = curY - curPiece.y(i);
DrawSquare(dc, 0 + x * SquareWidth(),
boardTop + (BoardHeight - y - 1) * SquareHeight(),
curPiece.GetShape());
}
}
Следующий шаг - прорисовка формы, падающей вниз.
...
switch (keycode) {
case WXK_LEFT:
TryMove(curPiece, curX - 1, curY);
break;
...
В методе Board::OnKeyDown() мы проверяем нажатые клавиши. Если мы нажимаем клавишу влево, то пытаемся передвинуть форму влево. Мы говорим "пытаемся", потому что иногда форму переместить не возможно.
void Board::OnTimer(wxCommandEvent& event)
{
if (isFallingFinished) {
isFallingFinished = false;
NewPiece();
} else {
OneLineDown();
}
}
В методе Board::OnTimer() мы создаем новую форму, когда предыдущая упала вниз, или передвигаем падающую форму на одну линию вниз.
void Board::DropDown()
{
int newY = curY;
while (newY > 0) {
if (!TryMove(curPiece, curX, newY - 1))
break;
--newY;
}
PieceDropped();
}
Метод Board::DropDown() моментально опускает падающую форму вниз игрового поля. Он вызывается, когда мы нажимаем пробел.
void Board::PieceDropped()
{
for (int i = 0; i < 4; ++i) {
int x = curX + curPiece.x(i);
int y = curY - curPiece.y(i);
ShapeAt(x, y) = curPiece.GetShape();
}
RemoveFullLines();
if (!isFallingFinished)
NewPiece();
}
В методе Board::PieceDropped() мы устанавливаем конкретную форму в конечной позиции. Мы вызываем метод RemoveFullLines() для проверки наличия хотя бы одной полной строки. И мы создаём новую форму, если она уже не создана в методе Board::PieceDropped().
if (lineIsFull) {
++numFullLines;
for (int k = i; k < BoardHeight - 1; ++k) {
for (int j = 0; j < BoardWidth; ++j)
ShapeAt(j, k) = ShapeAt(j, k + 1);
}
}
Этот код удаляет полные строки. После обнаружения полной строки мы увеличиваем счётчик. Мы перемещаем все строки выше полной строки на одну позицию вниз. Таким образом мы затираем полную строку. Помните, что в нашей игре мы используем так называемую простую гравитацию. Это значит, что квадраты могут перемещаться только туда, где есть свободное пространство.
void Board::NewPiece()
{
curPiece.SetRandomShape();
curX = BoardWidth / 2 + 1;
curY = BoardHeight - 1 + curPiece.MinY();
if (!TryMove(curPiece, curX, curY)) {
curPiece.SetShape(NoShape);
timer->Stop();
isStarted = false;
m_stsbar->SetStatusText(wxT("game over"));
}
Original (English): The wxWidgets programming tutorial (12. The tetris game in wxWidgets)
Translation: © ber113 .
