Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Создание компьютерных игр выпуск 19


Информационный Канал Subscribe.Ru

Cоздание компьютерных игр.
Выпускается еженедельно по пятницам.
Автор рассылки - Евгений Казеко.

Выпуск 19. (от 6 февраля 2004 года)
Поговорим о Тетрисе.

--------------------------------------------------------------

Приветствую всех читателей рассылки, первый раз в новом, 2004-м году! Позади январь и новогодние праздники. Позади зимняя сессия у студентов. И теперь, я надеюсь, ничто не помешает вам в спокойной обстановке прочитать этот выпуск, девятнадцатый по счету и первый в этом году.

Сперва несколько слов о самой рассылке. Знаю, что есть немало читателей, для которых эта рассылка очень важна, которые каждую пятницу с нетерпением ждут нового выпуска, и которые, наверное разочаровываются, не получая его. Поверьте, я всегда помню о вас и делаю все возможное, для того, чтобы рассылка продолжала свое существование, даже несмотря на то, что не удается выпускать ее с заявленной частотой. Была мысль выпускать рассылку раз в месяц, но я отказался от нее. Сейчас я ищу компромисс между частотой выхода и информативностью. Сами понимаете, каждую неделю готовить большой выпуск, занимаясь при этом еще и другими делами, такими как работа, очень сложно. Поэтому я решил - пускай выпуски будут поменьше и попроще, зато выходить будут почаще. Это лучше, чем делать выпуск большого объема раз в месяц. Ведь смысл рассылки и состоит в ее оперативности, а тщательная проработка тем может быть выполнена самостоятельно, например с использованием материалов www.gamecoder.nm.ru.

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

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

Во-вторых, пара слов о рассылке как о части проекта. Несмотря на то, что я стараюсь делать рассылку самодостаточным изданием, все же очень хотелось бы, чтобы ее читатели имели в виду (те, кто еще не знает), что рассылка выпускается в рамках проекта GameCoder (Школа создателей компьютерных игр), что есть сайт проекта www.gamecoder.nm.ru, материалы которого достаточно подробны и позволяют разобраться в той или иной теме рассылки, и что на этом сайте есть форум, где можно пообщаться с другими читателями рассылки и задать интересующий вопрос. Когда вы задаете его мне, вы, скорее всего, получите ответ, но, как я уже говорил, я не всегда имею возможность быстро ответить. Форум же регулярно посещают опытные люди, которые, я думаю, не откажутся оперативно вам помочь. Да чего уж говорить, мне самому проще написать ответ в форум, чем ответить по почте. Хмм, все это, конечно, звучит как призыв посетить сайт. На самом деле я просто хочу один раз подробно упомянуть о сайте и о проекте целиком, чтобы больше к этому не возвращаться. Думаю, что я буду ссылаться на сайт и его материалы в рассылке, но рассказов о том, что это за сайт и где он находится больше не будет, хорошо? Теперь вы уже это знаете.

В-третьих, об обновлениях на сайте. Я над этим работаю, но должен сказать вам, что я очень сильно разочаровался в обучалках с GameTutorials, которые я перевожу. Ну не во всех, конечно, а в некоторых из них, но тем не менее. Выполнять вывод картинки с прозрачными областями, анализируя в цикле цвет каждого пикселя... мда. Я, конечно, понимаю, что "у всех сейчас давно уже P-IV, а про видюхи уж и говорить нечего", и что про оптимизацию можно забыть, но не до такой же степени. Еще Андре Ламот в своей старой книге про создание игр для DOS, описывая такой способ, говорил: "Не используйте этот способ, он совсем не для игр". Не волнуйтесь, со временем в рассылке я покажу, как нужно выводить "прозрачные" картинки в GDI "по-человечески", с использованием масок и операций AND и OR (конечно в Win98 есть функция TransparentBlt, но не помешает знать, как можно обойтись без нее). Но вот что делать с обучалками... Скорее всего, я их конечно переведу и выложу на сайте, но мысль о создании авторских обучалок становится все более навязчивой.

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

А пока считаю нужным закрыть одну тему, которая до сих пор осталась незаконченной. Это создание игры "Тетрис". Мы начали эту тему в выпусках 13 и 14, но потом она "повисла в воздухе". Если говорить точнее, мы все время вплотную приближались к ней. И на настоящий момент вы вполне готовы написать свою версию "Тетриса" самостоятельно (если до сих пор еще не сделали этого). Причем выглядеть все это может очень даже неплохо. В свое время я сделал достаточно сырую версию "Тетриса", используя для рисования исключительно стандартные функции GDI, и недавно, размышляя о теме рассылки, я довел ее до ума. Получилось весьма интересно. Может быть даже, в скором времени я смогу выпустить release. Ну а пока, я хочу помочь читателям сделать то же самое.

Исходного кода я приводить не буду. Поверьте мне, гораздо интереснее все сделать самому. Что толку переделывать чужую программу? Намного лучше использовать собственные знания (а их у вас уже накопилось достаточно), полностью создать "Тетрис" самостоятельно и получить от этого большое удовлетворение. Я уже не говорю о том, как это полезно для обучения.

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

Думаю, что стоит "разложить все по полочкам". Итак, как же мы можем сделать Тетрис?

1) Для начала необходимо создать двумерный (или одномерный, если хотите) массив игрового поля - массив целых чисел. И тогда положение элемента будет определяться координатами x и y (например, для массива int gamefield[X][Y], где X и Y - размеры игрового поля, обращение к ячейке gamefield[x][y] дает доступ к игровому элементу с этими координатами). А содержимое ячейки будет указывать на то, что находится в этой точке игрового поля. Например, мы можем пронумеровать цвета кирпичиков, а число 0 будет означать, что в этой точке ничего нет.

2) Второй важный момент - нужно определиться с передвижением фигур в стакане. Когда мы перемещали игрока в лабиринте, все было очень просто. Всему игроку соответствовал один элемент игрового поля, и можно было перемещать игрока, изменяя его координаты. Как же быть с фигурами, если одной фигуре соответствует четыре элемента игрового поля. Разумеется нет смысла отслеживать координаты каждого элемента. Достаточно выбрать один из них, а остальные строить относительно его положения. Приведем пример.

Как мы помещали игрока в лабиринт? Если ему соответствовал элемент под номером 1, то мы просто записывали это число в соответствующую ячейку игрового поля (gamefield[3][12] = 1;). Если нам нужно поместить фигуру в стакан, то сперва мы определяем функцию, выводящую фигуры (например, она может выбирать фигуру по номеру оператором switch и строить ее, как будет показано ниже), а потом вызываем ее. Давайте напишем такую функцию для одной фигуры.

void SetFigure(int figurenumber)
{
 switch (figurenumber)
 case 1:
 {
 gamefield[x][y] = color;   // записываем номер цвета фигуры
 gamefield[x-1][y] = color; // в ячейки игрового поля.
 gamefield[x+1][y] = color; // можно просто записывать в них
        gamefield[x][y-1] = color; // значение figurenumber
 break;
 }
 default: break;
}

И теперь, если мы зададим координаты фигуры (например x=2; y=3) и вызовем Setfigure(1), то в указанном месте игрового поля построится эта фигура. А для передвижения фигуры мы просто вызовем функцию со значением 0, которому соответствует пустота (так мы сотрем фигуру из массива), изменим координаты и вновь построим ее (Setfigure(1)). Все очень просто.

3) Поворот фигур. Проще всего реализовать его, прописав каждое положение фигуры в функции Setfigure. Таким образом для каждой фигуры будет четыре положения. (И каждой фигуре будет соответствовать четыре номера).

4) Проверка столкновений. Прежде чем записать новое положение фигуры, которое возникает при передвижении или повороте, в массив, нужно проверить, все ли ячейки нового положения пусты. Если хотя бы в одной ячейке есть что-то, отличное от 0, значит перемещать или поворачивать фигуру нельзя. А если такое столкновение происходит при передвижении фигуры вниз (как мы знаем, фигура падает вниз всегда), это является сигналом для запуска новой фигуры (а также, проверок на заполненные ряды и проигрыш). Кроме того, нужно проверять столкновение со стенами, отслеживая, чтобы значения координаты х ни одного из элементов не были меньше нуля или больше максимального числа элементов в ряду.

5) Проверка условий заполнения рядов и проигрыша. Это нужно делать при каждом падении фигуры на дно или на другие фигуры. Проверить, есть ли заполненные ряды, очень просто. Нужно просканировать их все в цикле (ряды массива сканируем, изменяя координату х от нуля до максимума, оставляя при этом координату у неизменной). Если хоть один элемент равен 0, значит ряд заполнен не полностью. Точно также проверяется проигрыш - сканируется самый верхний ряд. Если там есть хоть что-нибудь, отличное от 0, значит стакан заполнен доверху и игра проиграна.

6) При заполнении рядов, удаляем их по одному, смещая все содержимое массива построчно снизу вверх (разумеется, в цикле), и дописывая пустую строку сверху.

Вот, собственно, и все ключевые моменты написания Тетриса. Остался главный игровой цикл. Выглядит он примерно так: 1) мы случайно выбираем фигуру из списка 2) помещаем ее наверх стакана 3) проверяем, не нажимаются ли клавиши передвижения и поворота 4) проверяем возможность передвижения или поворота (если нужно) и передвигаем или поворачиваем ее 5) проверяем возможность движения вниз, и если можно, двигаем фигуру вниз (проверив, а пора ли ее двигать?) 6) а вот если фигуру двигать вниз нельзя, то проверяем проигрыш/заполненные ряды с вытекающими последствиями и переходим к пункту 1.

Хмм, неужели мне удалось объяснить создание Тетриса "на пальцах"? По-моему получилось доходчиво. Я вполне доволен. "Погодите, а как же нам определять, пора ли двигать фигуру вниз?" - спросите вы, и будете правы. Это большая тема, которая называется "синхронизация". Нам просто необходим временной фактор в игре. Нам нужно задавать скорость перемещения фигур, скорость поворота и движения вниз... Но об этом мы поговорим в следующий раз, а самым нетерпеливым рекомендую посмотреть выпуск 12 про звездное небо. Кроме того, если получится, в следующий раз я расскажу про гораздо лучший способ обработки нажатия клавиш, нежели через сообщения, и подробнее коснусь темы генерации случайных чисел.

До встречи!

--------------------------------------------------------------

Архив рассылки вы найдете по адресам http://subscribe.ru/catalog/comp.games.gamecoder и http://www.gamecoder.nm.ru/subscribe.htm.

Евгений Казеко.
kazeko@list.ru
www.gamecoder.nm.ru
-----------------------------
Рассылка "Создание компьютерных игр", выпуск 19.
Выпускается еженедельно по пятницам.



http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное