Журнал LinuxFormat - перейти на главную

LXF103:Ни строчки кода!

Материал из Linuxformat
Перейти к: навигация, поиск


Содержание

Система управления

ЧАСТЬ 2 Отсутствие кода совсем не означает, что игровая логика возникнет сама по себе. Сегодня Андрей Прахов расскажет, как заставить объекты двигаться по вашему велению.


(thumbnail)
Рис. 2. Порядок во всем – и все в порядке!
(thumbnail)
Рис. 3. Отладочная информация поможет, если что-то пойдет не так.

Нет ничего хуже, чем не доведенный до конца проект. Если вы считаете так же, как и я, то вперед, за мной – на покорение Blender’а.

В предыдущей статье мы уже познакомились с основами создания игр в Blender и даже получили вполне работоспособный код прототипа программы (думаю, вы уже догадались, что команда File > Save runtime как раз и создает желанный нами исполняемый файл). Однако какой интерес наблюдать немеряное количество прыгающих по модели шаров и захлебывающийся от всего этого движок? Пришла пора внести некоторый порядок в этот беспредел!

Но сначала давайте заставим шар следовать за указателем и лететь в точно указанном нами направлении. Кстати, это не такая уж и простая задача.

Точно в яблочко!

Откройте имеющийся на LXFDVD файл lesson2_begin.blend и обратите внимание на объект Emp_boul. Как вы помните, именно с его помощью на прошлом занятии мы визуализировали в сцене шар. Поэкспериментируйте с этим объектом, подвигав его из стороны в сторону. Заметили, что сфера создается в том же самом месте, где находится Emp_boul? Вот оно и решение: сдвигая стрелку, мы будем двигать и Emp_boul, а он, в свою очередь, перемещать сферу.

Если вы подумали, что для этого стоит просто задействовать систему иерархии объектов Blender, и задача будет решена, то спешу вас «обрадовать» – привычные связи типа parent+child [родитель+подчиненный] в BGE не действуют, а точнее, действуют не совсем обычным образом. Поэтому сегодня нам предстоит изучить еще один обширный раздел игрового движка.

Визуальный конструктор Blender’а позволяет использовать переменные и систему сообщений. С переменными мы познакомимся позднее, а сейчас разберемся с сообщениями.

Каждый объект при определенной настройке имеет возможность отсылки некоторого сообщения либо всем объектам сразу, либо конкретному адресату. Происходит это при использовании логических кирпичиков Message [Сообщение] блоков Sensors [Сенсоры] и Actuators [Активаторы]. Соответственно, сенсор принимает сообщение, а активатор – отсылает его.

Мы воспользуемся этой возможностью, чтобы сообщить Emp_boul о необходимости сдвинуться в нужном направлении при перемещении стрелки. Для этого добавьте объекту arr еще один кирпичик блока Actuators [Активаторы] и присоедините его к контроллеру, объединяющему цепочку движения влево (leftarrow > left). Выберите из выпадающего списка меню пункт Message [Сообщение]. Поместите в поле Subject строку go_left. Именно его и будет генерировать стрелка при перемещении влево. Теперь осталось научить Emp_boul следить за потоком сообщений и реагировать на нужное.

Для этого создайте еще одну логическую цепочку объекта Emp_boul с кирпичиками: Message > And > Motion [Сообщение > Логическое И > Движение]. В поле сенсора Subject внесите значение go_left, а в Motion [Движение] измените значение координаты Y параметра dLoc на -0.10. Не забывайте, что мы работаем исключительно с глобальными координатами!

Осталось только протестировать сделанное. При движении влево и нажатии клавиши «пробел» сфера должна появиться точно на кончике стрелки. Если подобного не происходит, проверьте идентичность полей Subject передатчика и приемника. Помните о чувствительности Blender к регистру букв (Рис. 1). По образу и подобию вышесказанного проделайте то же самое и для движения вправо.

(thumbnail)
Рис. 1. Логическая цепочка должна выглядеть так.

1,2,3... Game over!

Следующим шагом при разработке нашей игры будет введение ограничения количества бросков тремя попытками. И в этой части урока мы с вами также познакомимся с переменными Blender Engine.

Как и любой другой язык программирования, конструктор Blender’а предоставляет несколько типов переменных: String, Integer, Float, Boolean, Timer. Создать и настроить их можно, нажав кнопку Add Property [Добавить свойство] в панели Logic [Логика] конкретно для каждого объекта. Здесь вы сможете выбрать тип переменной, ее имя и начальное значение.

Для работы с ними имеются специальные кирпичики с названием Property [Свойство] блоков Sensors и Actuators. Давайте сначала рассмотрим работу с сенсором.

При активации данного кирпичика, вам предлагается выбрать тип необходимой функции:

  1. Changed [Изменилось]. Импульс проходит, если произошло хоть какое-нибудь изменение значения переменной.
  2. Interval [Интервал]. Укажите минимальное и максимальное значение для реагирования сенсором.
  3. Not Equal [Не равно]. Истина, если значение переменной не равно значению сенсора.
  4. Equal [Равно]. Истина, если значения сенсора и переменной совпали.

Свойство Property блока Actuators, в свою очередь, позволяет совершать некоторые манипуляции с содержимым переменной:

  1. Copy [Копировать]. Копирование значения «чужой» переменной в свою. Просто укажите названия объекта, его переменной и переменной-приемника.
  2. Add [Добавить]. Увеличение или уменьшение значения переменной на значение указанное в поле Value [Значение].
  3. Assign [Присвоить]. Присвоение нового значения указанной переменной.

Запомните несколько правил работы с переменными. Все переменные являются локальными по отношению к своему объекту. Соответственно, их имена должны быть уникальными в рамках одного объекта, но могут совпадать у разных. Не забывайте о чувствительности регистра букв в названиях. Следите за соответствием значения переменной ее типу.

Закодируйте мне это

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

кол-во_попыток =3
НАЧАЛО ЦИКЛА
бросаем шар
кол-во_попыток=кол-во_попыток-1
ПОКА кол-во_попыток <> 0 ВЫПОЛНЯТЬ ЦИКЛ
КОНЕЦ ЦИКЛА

Это, безусловно, правильно, но уж больно далеко до реального воплощения в игре. Давайте рассуждать более предметно, с точки зрения имеющихся у нас возможностей.

Пусть имеется некая глобальная переменная Count, ответственная за хранение числа имеющихся у нас попыток. При каждом бросании шара всем объектам в игре отсылается сообщение go. Предположим также, что каждая из сфер интерфейса при появлении подобного сообщения сравнивает число, хранящееся в Count, со своим номером. При совпадении происходит уменьшение значения глобальной переменной Count и удаление соответствующей сферы с экрана.

Если вы внимательно читали написанное до этого, то могли заметить некоторое несоответствие – в визуальном конструкторе Blender имеются только локальные переменные самого объекта (можно, конечно, их называть свойствами объекта, но, на мой взгляд, это не совсем правильно). Но что мешает нам создать переменную, скажем, объекта arr и представить, что она является глобальной по отношению к остальным, а потом при появлении сообщения go копировать ее значение в свойство конкретного объекта? Правильно, ничего. Чтобы было более наглядно, представим это столь же схематично, но уже с учетом реальных названий объектов в нашей сцене:

arr.Count = 3;
НАЧАЛО ЦИКЛА
бросаем шар и отсылаем сообщение «go»;
...
// предположим, объекты s1, s2, s3 приняли сообщение «go»
s1.Count = arr.Count;
s2.Count = arr.Count;
s3.Count = arr.Count;
ЕСЛИ s1.Count ==3 ТО уменьшаем arr.Count и
удаляем объект s1;
ЕСЛИ s2.Count ==2 ТО уменьшаем arr.Count и
удаляем объект s2;
ЕСЛИ s3.Count ==1 ТО уменьшаем arr.Count и
удаляем объект s3;
ПОКА arr.Count <> 0 ВЫПОЛНЯТЬ ЦИКЛ
КОНЕЦ ЦИКЛА

Итак, хватайтесь за мышь: начинаем «кодить». Для начала реализуем систему обмена сообщениями между объектами.


Так как объект Emp_boul у нас ответственен за визуализацию шара, то пусть он и отсылает сообщение go. Создайте дополнительный кирпичик Message в блоке Actuators и соедините его с цепочкой, ответственной за обработку клавиши Space. Не забудьте вбить туда само сообщение! (Рис. 4)

(thumbnail)
Рис. 4. Примемся за «код».

Теперь мы можем добавить логику объектам s1, s2, s3 для приема этого сообщения и копирования переменной Count объекта arr в свои собственные. Естественно, сперва вам нужно создать эти самые переменные для arr, s1, s2, s3. Тип переменной везде будет Integer, только установите значение для arr.Count равным 3.

Итак, создайте логическую цепочку объекта s1, состоящую из кирпичиков Message > And > Property. Для сенсора в поле Subject поместите текст сообщения go.

Чтобы скопировать одну переменную в другую, выберите из меню актуатора функцию Copy и настройте имеющиеся параметры следующим образом:

  • Prop: – count
  • OB: – arr
  • Prop: – count

Таким образом, первое поле содержит название переменной-приемника, два остальных, соответственно, название объекта и копируемой переменной. Подобные цепочки создайте и для оставшихся двух сфер.

Однако глобальная переменная при броске у нас пока не изменяется. Что ж, исправить это несложно: нужно лишь добавить для стрелки цепочку, подобную построенной выше. Для активатора Property теперь выберите функцию Add [Добавить]. Пользоваться ею так же просто, как и другими. Поместите в поле «Prop:» название переменной count, а в параметр Value: значение -1. Как вы, надеюсь, помните из школьной математики, сложение 3+(-1) в сумме даст 2.

Вот теперь наш механизм счета произведенных бросков работает как часы. Если сомневаетесь в этом, воспользуйтесь приведенным выше советом и активируйте вывод переменной arr.count на экран (можете выводить и все остальное, но это, по-моему, будет излишеством).

Осталось решить, что делать со сферами, когда надобность в них исчезает. Да просто удалять их, а как выполнить это, я уже рассказывал чуть выше. Удивлены? Ведь не зря некоторую часть этой статьи занял псевдокод, а именно строки типа: «ЕСЛИ s1.Count ==3 ТО уменьшаем arr.Count и удаляем объект s1;». В переводе на язык Blender, это будет выглядеть следующим образом.

Создайте цепочку Property > And > Edit Object для объекта s1 [Свойство > Логическое И > Редактирование объекта]. Задача сенсора в этом случае – выдавать импульс при одинаковом значении поля Value и переменной Prop. То есть, для объекта s1 это значение составит 3, а для оставшихся двух, соответственно 2 и 1. Что же касается кирпичика Edit Object, то просто выберите в нем функцию End Object – она не принимает параметров и уничтожает вызвавший ее объект. Соответственно, настройте подобным образом оставшиеся сферы.

Вот так мы с вами справились с отображением информации о произведенных бросках, но сами броски так и остались неограниченными. Тут также нужно будет воспользоваться механизмом сообщений. Предположим, объект arr проверяет свою переменную count на равность нулю и при выполнении этого условия отсылает сообщение «go_off». Осталось настроить Emp_boul на его прием и удаление при положительном импульсе самого себя. Вот и все! Если вам не удастся решить эту задачу самостоятельно, загляните в исходник lesson2_end.blend.

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

Персональные инструменты
купить
подписаться
Яндекс.Метрика