http://wiki.linuxformat.ru/wiki/index.php?title=LXF103:%D0%9D%D0%B8_%D1%81%D1%82%D1%80%D0%BE%D1%87%D0%BA%D0%B8_%D0%BA%D0%BE%D0%B4%D0%B0!&feed=atom&action=historyLXF103:Ни строчки кода! - История изменений2024-03-29T08:03:11ZИстория изменений этой страницы в викиMediaWiki 1.19.20+dfsg-0+deb7u3http://wiki.linuxformat.ru/wiki/index.php?title=LXF103:%D0%9D%D0%B8_%D1%81%D1%82%D1%80%D0%BE%D1%87%D0%BA%D0%B8_%D0%BA%D0%BE%D0%B4%D0%B0!&diff=7294&oldid=prevYaleks: Новая: {{Цикл/Ни строчки кода}} == Система управления == : ''ЧАСТЬ 2 Отсутствие кода совсем не означает, что игрова...2009-03-15T15:42:31Z<p>Новая: {{Цикл/Ни строчки кода}} == Система управления == : ''ЧАСТЬ 2 Отсутствие кода совсем не означает, что игрова...</p>
<p><b>Новая страница</b></p><div>{{Цикл/Ни строчки кода}}<br />
== Система управления ==<br />
: ''ЧАСТЬ 2 Отсутствие кода совсем не означает, что игровая логика возникнет сама по себе. Сегодня '''Андрей Прахов''' расскажет, как заставить объекты двигаться по вашему велению.''<br />
<br />
{{Врезка<br />
|Заголовок=Скорая помощь<br />
|Содержание=Несложно<br />
представить,<br />
какой хаос мог<br />
бы твориться в<br />
хитросплетениях<br />
логических блоков,<br />
если бы не было<br />
возможности<br />
свободного<br />
перемещения<br />
кирпичиков<br />
вверх или вниз<br />
в «закрытом»<br />
состоянии. Для<br />
этого просто<br />
щелкните левой<br />
кнопкой мышки<br />
на поле нужного<br />
кирпичика (Рис. 2).<br />
|Ширина=300px}}<br />
[[Изображение:LXF 103 93 1.png|thumb|300px|Рис. 2. Порядок во всем – и все в порядке!]]<br />
{{Врезка<br />
|Заголовок=Скорая помощь<br />
|Содержание=Для контроля<br />
текущего значения<br />
переменной<br />
при прогоне<br />
программы вы<br />
можете вывести<br />
его на экран, нажав<br />
кнопку D у нужной<br />
переменной<br />
и атикивировав<br />
пункт меню Game<br />
> Show Debug<br />
Properties [Игра<br />
> Показывать<br />
отладочную<br />
информацию]<br />
(Рис. 3).<br />
|Ширина=300px}}<br />
[[Изображение:LXF 103 93 2.png|thumb|300px|Рис. 3. Отладочная информация поможет, если что-то пойдет не так.]]<br />
Нет ничего хуже, чем не доведенный до конца проект. Если вы<br />
считаете так же, как и я, то вперед, за мной – на покорение<br />
Blender’а.<br />
<br />
В предыдущей статье мы уже познакомились с основами создания<br />
игр в Blender и даже получили вполне работоспособный код прототипа программы (думаю, вы уже догадались, что команда File > Save<br />
runtime как раз и создает желанный нами исполняемый файл). Однако<br />
какой интерес наблюдать немеряное количество прыгающих по модели<br />
шаров и захлебывающийся от всего этого движок? Пришла пора внести некоторый порядок в этот беспредел!<br />
<br />
Но сначала давайте заставим шар следовать за указателем и лететь<br />
в точно указанном нами направлении. Кстати, это не такая уж и простая задача.<br />
<br />
=== Точно в яблочко! ===<br />
Откройте имеющийся на LXFDVD файл lesson2_begin.blend и обратите внимание на объект Emp_boul. Как вы помните, именно с его<br />
помощью на прошлом занятии мы визуализировали в сцене шар.<br />
Поэкспериментируйте с этим объектом, подвигав его из стороны в<br />
сторону. Заметили, что сфера создается в том же самом месте, где<br />
находится Emp_boul? Вот оно и решение: сдвигая стрелку, мы будем<br />
двигать и Emp_boul, а он, в свою очередь, перемещать сферу.<br />
<br />
Если вы подумали, что для этого стоит просто задействовать систему<br />
иерархии объектов Blender, и задача будет решена, то спешу вас «обрадовать» – привычные связи типа parent+child [родитель+подчиненный]<br />
в BGE не действуют, а точнее, действуют не совсем обычным образом.<br />
Поэтому сегодня нам предстоит изучить еще один обширный раздел<br />
игрового движка.<br />
<br />
Визуальный конструктор Blender’а позволяет использовать переменные и систему сообщений. С переменными мы познакомимся позднее, а сейчас разберемся с сообщениями.<br />
<br />
Каждый объект при определенной настройке имеет возможность<br />
отсылки некоторого сообщения либо всем объектам сразу, либо<br />
конкретному адресату. Происходит это при использовании логических кирпичиков Message [Сообщение] блоков Sensors [Сенсоры] и<br />
Actuators [Активаторы]. Соответственно, сенсор принимает сообщение,<br />
а активатор – отсылает его.<br />
<br />
Мы воспользуемся этой возможностью, чтобы сообщить Emp_boul<br />
о необходимости сдвинуться в нужном направлении при перемещении стрелки. Для этого добавьте объекту arr еще один кирпичик блока<br />
Actuators [Активаторы] и присоедините его к контроллеру, объединяющему цепочку движения влево (leftarrow > left). Выберите из выпадающего списка меню пункт Message [Сообщение]. Поместите в поле<br />
Subject строку go_left. Именно его и будет генерировать стрелка при<br />
перемещении влево. Теперь осталось научить Emp_boul следить за<br />
потоком сообщений и реагировать на нужное.<br />
<br />
Для этого создайте еще одну логическую цепочку объекта Emp_boul<br />
с кирпичиками: Message > And > Motion [Сообщение > Логическое<br />
И > Движение]. В поле сенсора Subject внесите значение go_left, а в<br />
Motion [Движение] измените значение координаты Y параметра dLoc<br />
на -0.10. Не забывайте, что мы работаем исключительно с глобальными координатами!<br />
<br />
Осталось только протестировать сделанное. При движении влево и<br />
нажатии клавиши «пробел» сфера должна появиться точно на кончике<br />
стрелки. Если подобного не происходит, проверьте идентичность полей<br />
Subject передатчика и приемника. Помните о чувствительности Blender<br />
к регистру букв (Рис. 1). По образу и подобию вышесказанного проделайте то же самое и для движения вправо.<br />
<br />
[[Изображение:LXF 103 92 1.png|frame|center|Рис. 1. Логическая цепочка должна выглядеть так.]]<br />
<br />
=== 1,2,3... Game over! ===<br />
{{Врезка<br />
|Заголовок=Примечание<br />
|Содержание=Приведенные листинги не относятся к каким-либо из существующих<br />
языков программирования и призваны только лишь облегчить восприятие логики решения поставленной задачи. Тем не менее они<br />
имеют некоторые черты «настоящих» языков программирования. Так,<br />
строка s1.Count = arr.Count означает присвоение значения переменной<br />
arr.Count переменной s1.Count. В свою очередь, строка ЕСЛИ s1.Count==3 ТО транслируется как сравнение двух операндов и выполнение<br />
кода после ТО, если указанное условие верное.<br />
|Ширина=300px}}<br />
Следующим шагом при разработке нашей игры будет введение ограничения количества бросков тремя попытками. И в этой части урока мы с<br />
вами также познакомимся с переменными Blender Engine.<br />
<br />
Как и любой другой язык программирования, конструктор Blender’а<br />
предоставляет несколько типов переменных: String, Integer, Float,<br />
Boolean, Timer. Создать и настроить их можно, нажав кнопку Add Property<br />
[Добавить свойство] в панели Logic [Логика] конкретно для каждого<br />
объекта. Здесь вы сможете выбрать тип переменной, ее имя и начальное<br />
значение.<br />
<br />
Для работы с ними имеются специальные кирпичики с названием<br />
Property [Свойство] блоков Sensors и Actuators. Давайте сначала рассмотрим работу с сенсором.<br />
<br />
При активации данного кирпичика, вам предлагается выбрать тип<br />
необходимой функции:<br />
# Changed [Изменилось]. Импульс проходит, если произошло хоть какое-нибудь изменение значения переменной.<br />
# Interval [Интервал]. Укажите минимальное и максимальное значение для реагирования сенсором.<br />
# Not Equal [Не равно]. Истина, если значение переменной не равно значению сенсора.<br />
# Equal [Равно]. Истина, если значения сенсора и переменной совпали.<br />
Свойство Property блока Actuators, в свою очередь, позволяет<br />
совершать некоторые манипуляции с содержимым переменной:<br />
# Copy [Копировать]. Копирование значения «чужой» переменной в свою. Просто укажите названия объекта, его переменной и переменной-приемника.<br />
# Add [Добавить]. Увеличение или уменьшение значения переменной на значение указанное в поле Value [Значение].<br />
# Assign [Присвоить]. Присвоение нового значения указанной переменной.<br />
Запомните несколько правил работы с переменными. Все переменные<br />
являются локальными по отношению к своему объекту. Соответственно,<br />
их имена должны быть уникальными в рамках одного объекта, но могут<br />
совпадать у разных. Не забывайте о чувствительности регистра букв в<br />
названиях. Следите за соответствием значения переменной ее типу.<br />
<br />
=== Закодируйте мне это ===<br />
После такого теоретического вступления, думаю, пришла пора воплотить наши замыслы в реальность. Итак, у нас в запасе имеется всего<br />
три попытки на выполнение броска. Визуально они отражаются в виде<br />
такого же количества шаров, расположенных в правом нижнем углу<br />
игрового экрана. При совершении очередного броска эти сферы исчезают. В связи с некоторыми особенностями игрового конструктора и заявленной целью не использовать напрямую встроенный язык программирования, решение задачи несколько усложняется. Поэтому мы пройдем<br />
с вами все ступени разработки данного куска логики. В самом простом<br />
варианте эту задачу можно было бы описать так:<br />
<pre>кол-во_попыток =3<br />
НАЧАЛО ЦИКЛА<br />
бросаем шар<br />
кол-во_попыток=кол-во_попыток-1<br />
ПОКА кол-во_попыток <> 0 ВЫПОЛНЯТЬ ЦИКЛ<br />
КОНЕЦ ЦИКЛА</pre><br />
Это, безусловно, правильно, но уж больно далеко до реального<br />
воплощения в игре. Давайте рассуждать более предметно, с точки зрения имеющихся у нас возможностей.<br />
<br />
Пусть имеется некая глобальная переменная Count, ответственная<br />
за хранение числа имеющихся у нас попыток. При каждом бросании<br />
шара всем объектам в игре отсылается сообщение go. Предположим<br />
также, что каждая из сфер интерфейса при появлении подобного<br />
сообщения сравнивает число, хранящееся в Count, со своим номером.<br />
При совпадении происходит уменьшение значения глобальной переменной Count и удаление соответствующей сферы с экрана.<br />
<br />
Если вы внимательно читали написанное до этого, то могли<br />
заметить некоторое несоответствие – в визуальном конструкторе Blender имеются только локальные переменные самого объекта (можно, конечно, их называть свойствами объекта, но, на мой<br />
взгляд, это не совсем правильно). Но что мешает нам создать<br />
переменную, скажем, объекта arr и представить, что она является<br />
глобальной по отношению к остальным, а потом при появлении<br />
сообщения go копировать ее значение в свойство конкретного объекта? Правильно, ничего. Чтобы было более наглядно, представим<br />
это столь же схематично, но уже с учетом реальных названий объектов в нашей сцене:<br />
<pre>arr.Count = 3;<br />
НАЧАЛО ЦИКЛА<br />
бросаем шар и отсылаем сообщение «go»;<br />
...<br />
// предположим, объекты s1, s2, s3 приняли сообщение «go»<br />
s1.Count = arr.Count;<br />
s2.Count = arr.Count;<br />
s3.Count = arr.Count;<br />
ЕСЛИ s1.Count ==3 ТО уменьшаем arr.Count и<br />
удаляем объект s1;<br />
ЕСЛИ s2.Count ==2 ТО уменьшаем arr.Count и<br />
удаляем объект s2;<br />
ЕСЛИ s3.Count ==1 ТО уменьшаем arr.Count и<br />
удаляем объект s3;<br />
ПОКА arr.Count <> 0 ВЫПОЛНЯТЬ ЦИКЛ<br />
КОНЕЦ ЦИКЛА</pre><br />
Итак, хватайтесь за мышь: начинаем «кодить». Для начала реализуем систему обмена сообщениями между объектами.<br />
<br />
{{Врезка<br />
|Заголовок=Памятка<br />
|Содержание=Хотя наш урок и называется «Ни строчки кода», тем не менее, в<br />
визуальном конструкторе приходится использовать переменные разных типов. Всего их в Blender Engine 5 штук: String, Integer, Float,<br />
Boolean, Timer.<br />
* String предназначена для хранения текстовой информации. Впоследствии ее можно вывести на экран, проделав некоторые хитрые манипуляции (об этом – в следующий раз).<br />
* Integer – целочисленное двухбайтовое число, может иметь отрицательное значение.<br />
* Float – число с плавающей запятой.<br />
* Boolean – логический тип переменной. Имеет два значения: True [Истина] или False [Ложь]. Наряду с этими текстовыми значениями можно использовать численные: 1 и 0.<br />
* Timer – число, выраженное в миллисекундах.<br />
|Ширина=300px}}<br />
Так как объект Emp_boul у нас ответственен за визуализацию шара,<br />
то пусть он и отсылает сообщение go. Создайте дополнительный кирпичик Message в блоке Actuators и соедините его с цепочкой, ответственной за обработку клавиши Space. Не забудьте вбить туда само<br />
сообщение! (Рис. 4)<br />
<br />
[[Изображение:LXF 103 94 1.png|frame|center|Рис. 4. Примемся за «код».]]<br />
<br />
Теперь мы можем добавить логику объектам s1, s2, s3 для приема<br />
этого сообщения и копирования переменной Count объекта arr в свои<br />
собственные. Естественно, сперва вам нужно создать эти самые переменные для arr, s1, s2, s3. Тип переменной везде будет Integer, только<br />
установите значение для arr.Count равным 3.<br />
<br />
Итак, создайте логическую цепочку объекта s1, состоящую из кирпичиков Message > And > Property. Для сенсора в поле Subject поместите текст сообщения go.<br />
<br />
Чтобы скопировать одну переменную в другую, выберите из меню<br />
актуатора функцию Copy и настройте имеющиеся параметры следующим образом:<br />
* Prop: – count<br />
* OB: – arr<br />
* Prop: – count<br />
Таким образом, первое поле содержит название переменной-приемника, два остальных, соответственно, название объекта и копируемой переменной. Подобные цепочки создайте и для оставшихся<br />
двух сфер.<br />
<br />
Однако глобальная переменная при броске у нас пока не изменяется. Что ж, исправить это несложно: нужно лишь добавить для<br />
стрелки цепочку, подобную построенной выше. Для активатора<br />
Property теперь выберите функцию Add [Добавить]. Пользоваться<br />
ею так же просто, как и другими. Поместите в поле «Prop:» название<br />
переменной count, а в параметр Value: значение -1. Как вы, надеюсь,<br />
помните из школьной математики, сложение 3+(-1) в сумме даст 2.<br />
<br />
Вот теперь наш механизм счета произведенных бросков работает как часы. Если сомневаетесь в этом, воспользуйтесь приведенным выше советом и активируйте вывод переменной arr.count на<br />
экран (можете выводить и все остальное, но это, по-моему, будет<br />
излишеством).<br />
<br />
Осталось решить, что делать со сферами, когда надобность в них<br />
исчезает. Да просто удалять их, а как выполнить это, я уже рассказывал<br />
чуть выше. Удивлены? Ведь не зря некоторую часть этой статьи занял<br />
псевдокод, а именно строки типа: «ЕСЛИ s1.Count ==3 ТО уменьшаем<br />
arr.Count и удаляем объект s1;». В переводе на язык Blender, это будет<br />
выглядеть следующим образом.<br />
<br />
Создайте цепочку Property > And > Edit Object для объекта s1<br />
[Свойство > Логическое И > Редактирование объекта]. Задача сенсора в этом случае – выдавать импульс при одинаковом значении поля<br />
Value и переменной Prop. То есть, для объекта s1 это значение составит 3, а для оставшихся двух, соответственно 2 и 1. Что же касается<br />
кирпичика Edit Object, то просто выберите в нем функцию End Object –<br />
она не принимает параметров и уничтожает вызвавший ее объект.<br />
Соответственно, настройте подобным образом оставшиеся сферы.<br />
<br />
Вот так мы с вами справились с отображением информации о<br />
произведенных бросках, но сами броски так и остались неограниченными. Тут также нужно будет воспользоваться механизмом сообщений. Предположим, объект arr проверяет свою переменную count на<br />
равность нулю и при выполнении этого условия отсылает сообщение<br />
«go_off». Осталось настроить Emp_boul на его прием и удаление при<br />
положительном импульсе самого себя. Вот и все! Если вам не удастся<br />
решить эту задачу самостоятельно, загляните в исходник lesson2_end.blend.<br />
<br />
Не знаю, как вам, но мне наскучили эти<br />
унылые серые линии: настала пора вдохнуть<br />
в них цвета во всем их красочном многообразии! На следующем уроке мы не только продолжим совершенствовать логику игры, но и<br />
узнаем секреты игрового текстурирования, а<br />
может, и добавим для разнообразия некоторые эффекты.</div>Yaleks