<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://wiki.linuxformat.ru/wiki/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://wiki.linuxformat.ru/wiki/index.php?action=history&amp;feed=atom&amp;title=LXF103%3A%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%21</id>
		<title>LXF103:Ни строчки кода! - История изменений</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.linuxformat.ru/wiki/index.php?action=history&amp;feed=atom&amp;title=LXF103%3A%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%21"/>
		<link rel="alternate" type="text/html" href="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!&amp;action=history"/>
		<updated>2026-05-13T19:48:25Z</updated>
		<subtitle>История изменений этой страницы в вики</subtitle>
		<generator>MediaWiki 1.19.20+dfsg-0+deb7u3</generator>

	<entry>
		<id>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!&amp;diff=7294&amp;oldid=prev</id>
		<title>Yaleks: Новая: {{Цикл/Ни строчки кода}} == Система управления == : ''ЧАСТЬ 2 Отсутствие кода совсем не означает, что игрова...</title>
		<link rel="alternate" type="text/html" href="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!&amp;diff=7294&amp;oldid=prev"/>
				<updated>2009-03-15T15:42:31Z</updated>
		
		<summary type="html">&lt;p&gt;Новая: {{Цикл/Ни строчки кода}} == Система управления == : &amp;#039;&amp;#039;ЧАСТЬ 2 Отсутствие кода совсем не означает, что игрова...&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Цикл/Ни строчки кода}}&lt;br /&gt;
== Система управления ==&lt;br /&gt;
: ''ЧАСТЬ 2 Отсутствие кода совсем не означает, что игровая логика возникнет сама по себе. Сегодня '''Андрей Прахов''' расскажет, как заставить объекты двигаться по вашему велению.''&lt;br /&gt;
&lt;br /&gt;
{{Врезка&lt;br /&gt;
|Заголовок=Скорая помощь&lt;br /&gt;
|Содержание=Несложно&lt;br /&gt;
представить,&lt;br /&gt;
какой хаос мог&lt;br /&gt;
бы твориться в&lt;br /&gt;
хитросплетениях&lt;br /&gt;
логических блоков,&lt;br /&gt;
если бы не было&lt;br /&gt;
возможности&lt;br /&gt;
свободного&lt;br /&gt;
перемещения&lt;br /&gt;
кирпичиков&lt;br /&gt;
вверх или вниз&lt;br /&gt;
в «закрытом»&lt;br /&gt;
состоянии. Для&lt;br /&gt;
этого просто&lt;br /&gt;
щелкните левой&lt;br /&gt;
кнопкой мышки&lt;br /&gt;
на поле нужного&lt;br /&gt;
кирпичика (Рис. 2).&lt;br /&gt;
|Ширина=300px}}&lt;br /&gt;
[[Изображение:LXF 103 93 1.png|thumb|300px|Рис. 2. Порядок во всем – и все в порядке!]]&lt;br /&gt;
{{Врезка&lt;br /&gt;
|Заголовок=Скорая помощь&lt;br /&gt;
|Содержание=Для контроля&lt;br /&gt;
текущего значения&lt;br /&gt;
переменной&lt;br /&gt;
при прогоне&lt;br /&gt;
программы вы&lt;br /&gt;
можете вывести&lt;br /&gt;
его на экран, нажав&lt;br /&gt;
кнопку D у нужной&lt;br /&gt;
переменной&lt;br /&gt;
и атикивировав&lt;br /&gt;
пункт меню Game&lt;br /&gt;
&amp;gt; Show Debug&lt;br /&gt;
Properties [Игра&lt;br /&gt;
&amp;gt; Показывать&lt;br /&gt;
отладочную&lt;br /&gt;
информацию]&lt;br /&gt;
(Рис. 3).&lt;br /&gt;
|Ширина=300px}}&lt;br /&gt;
[[Изображение:LXF 103 93 2.png|thumb|300px|Рис. 3. Отладочная информация поможет, если что-то пойдет не так.]]&lt;br /&gt;
Нет ничего хуже, чем не доведенный до конца проект. Если вы&lt;br /&gt;
считаете так же, как и я, то вперед, за мной – на покорение&lt;br /&gt;
Blender’а.&lt;br /&gt;
&lt;br /&gt;
В предыдущей статье мы уже познакомились с основами создания&lt;br /&gt;
игр в Blender и даже получили вполне работоспособный код прототипа программы (думаю, вы уже догадались, что команда File &amp;gt; Save&lt;br /&gt;
runtime как раз и создает желанный нами исполняемый файл). Однако&lt;br /&gt;
какой интерес наблюдать немеряное количество прыгающих по модели&lt;br /&gt;
шаров и захлебывающийся от всего этого движок? Пришла пора внести некоторый порядок в этот беспредел!&lt;br /&gt;
&lt;br /&gt;
Но сначала давайте заставим шар следовать за указателем и лететь&lt;br /&gt;
в точно указанном нами направлении. Кстати, это не такая уж и простая задача.&lt;br /&gt;
&lt;br /&gt;
=== Точно в яблочко! ===&lt;br /&gt;
Откройте имеющийся на LXFDVD файл lesson2_begin.blend и обратите внимание на объект Emp_boul. Как вы помните, именно с его&lt;br /&gt;
помощью на прошлом занятии мы визуализировали в сцене шар.&lt;br /&gt;
Поэкспериментируйте с этим объектом, подвигав его из стороны в&lt;br /&gt;
сторону. Заметили, что сфера создается в том же самом месте, где&lt;br /&gt;
находится Emp_boul? Вот оно и решение: сдвигая стрелку, мы будем&lt;br /&gt;
двигать и Emp_boul, а он, в свою очередь, перемещать сферу.&lt;br /&gt;
&lt;br /&gt;
Если вы подумали, что для этого стоит просто задействовать систему&lt;br /&gt;
иерархии объектов Blender, и задача будет решена, то спешу вас «обрадовать» – привычные связи типа parent+child [родитель+подчиненный]&lt;br /&gt;
в BGE не действуют, а точнее, действуют не совсем обычным образом.&lt;br /&gt;
Поэтому сегодня нам предстоит изучить еще один обширный раздел&lt;br /&gt;
игрового движка.&lt;br /&gt;
&lt;br /&gt;
Визуальный конструктор Blender’а позволяет использовать переменные и систему сообщений. С переменными мы познакомимся позднее, а сейчас разберемся с сообщениями.&lt;br /&gt;
&lt;br /&gt;
Каждый объект при определенной настройке имеет возможность&lt;br /&gt;
отсылки некоторого сообщения либо всем объектам сразу, либо&lt;br /&gt;
конкретному адресату. Происходит это при использовании логических кирпичиков Message [Сообщение] блоков Sensors [Сенсоры] и&lt;br /&gt;
Actuators [Активаторы]. Соответственно, сенсор принимает сообщение,&lt;br /&gt;
а активатор – отсылает его.&lt;br /&gt;
&lt;br /&gt;
Мы воспользуемся этой возможностью, чтобы сообщить Emp_boul&lt;br /&gt;
о необходимости сдвинуться в нужном направлении при перемещении стрелки. Для этого добавьте объекту arr еще один кирпичик блока&lt;br /&gt;
Actuators [Активаторы] и присоедините его к контроллеру, объединяющему цепочку движения влево (leftarrow &amp;gt; left). Выберите из выпадающего списка меню пункт Message [Сообщение]. Поместите в поле&lt;br /&gt;
Subject строку go_left. Именно его и будет генерировать стрелка при&lt;br /&gt;
перемещении влево. Теперь осталось научить Emp_boul следить за&lt;br /&gt;
потоком сообщений и реагировать на нужное.&lt;br /&gt;
&lt;br /&gt;
Для этого создайте еще одну логическую цепочку объекта Emp_boul&lt;br /&gt;
с кирпичиками: Message &amp;gt; And &amp;gt; Motion [Сообщение &amp;gt; Логическое&lt;br /&gt;
И &amp;gt; Движение]. В поле сенсора Subject внесите значение go_left, а в&lt;br /&gt;
Motion [Движение] измените значение координаты Y параметра dLoc&lt;br /&gt;
на -0.10. Не забывайте, что мы работаем исключительно с глобальными координатами!&lt;br /&gt;
&lt;br /&gt;
Осталось только протестировать сделанное. При движении влево и&lt;br /&gt;
нажатии клавиши «пробел» сфера должна появиться точно на кончике&lt;br /&gt;
стрелки. Если подобного не происходит, проверьте идентичность полей&lt;br /&gt;
Subject передатчика и приемника. Помните о чувствительности Blender&lt;br /&gt;
к регистру букв (Рис. 1). По образу и подобию вышесказанного проделайте то же самое и для движения вправо.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:LXF 103 92 1.png|frame|center|Рис. 1. Логическая цепочка должна выглядеть так.]]&lt;br /&gt;
&lt;br /&gt;
=== 1,2,3... Game over! ===&lt;br /&gt;
{{Врезка&lt;br /&gt;
|Заголовок=Примечание&lt;br /&gt;
|Содержание=Приведенные листинги не относятся к каким-либо из существующих&lt;br /&gt;
языков программирования и призваны только лишь облегчить восприятие логики решения поставленной задачи. Тем не менее они&lt;br /&gt;
имеют некоторые черты «настоящих» языков программирования. Так,&lt;br /&gt;
строка s1.Count = arr.Count означает присвоение значения переменной&lt;br /&gt;
arr.Count переменной s1.Count. В свою очередь, строка ЕСЛИ s1.Count==3 ТО транслируется как сравнение двух операндов и выполнение&lt;br /&gt;
кода после ТО, если указанное условие верное.&lt;br /&gt;
|Ширина=300px}}&lt;br /&gt;
Следующим шагом при разработке нашей игры будет введение ограничения количества бросков тремя попытками. И в этой части урока мы с&lt;br /&gt;
вами также познакомимся с переменными Blender Engine.&lt;br /&gt;
&lt;br /&gt;
Как и любой другой язык программирования, конструктор Blender’а&lt;br /&gt;
предоставляет несколько типов переменных: String, Integer, Float,&lt;br /&gt;
Boolean, Timer. Создать и настроить их можно, нажав кнопку Add Property&lt;br /&gt;
[Добавить свойство] в панели Logic [Логика] конкретно для каждого&lt;br /&gt;
объекта. Здесь вы сможете выбрать тип переменной, ее имя и начальное&lt;br /&gt;
значение.&lt;br /&gt;
&lt;br /&gt;
Для работы с ними имеются специальные кирпичики с названием&lt;br /&gt;
Property [Свойство] блоков Sensors и Actuators. Давайте сначала рассмотрим работу с сенсором.&lt;br /&gt;
&lt;br /&gt;
При активации данного кирпичика, вам предлагается выбрать тип&lt;br /&gt;
необходимой функции:&lt;br /&gt;
# Changed [Изменилось]. Импульс проходит, если произошло хоть какое-нибудь изменение значения переменной.&lt;br /&gt;
# Interval [Интервал]. Укажите минимальное и максимальное значение для реагирования сенсором.&lt;br /&gt;
# Not Equal [Не равно]. Истина, если значение переменной не равно значению сенсора.&lt;br /&gt;
# Equal [Равно]. Истина, если значения сенсора и переменной совпали.&lt;br /&gt;
Свойство Property блока Actuators, в свою очередь, позволяет&lt;br /&gt;
совершать некоторые манипуляции с содержимым переменной:&lt;br /&gt;
# Copy [Копировать]. Копирование значения «чужой» переменной в свою. Просто укажите названия объекта, его переменной и переменной-приемника.&lt;br /&gt;
# Add [Добавить]. Увеличение или уменьшение значения переменной на значение указанное в поле Value [Значение].&lt;br /&gt;
# Assign [Присвоить]. Присвоение нового значения указанной переменной.&lt;br /&gt;
Запомните несколько правил работы с переменными. Все переменные&lt;br /&gt;
являются локальными по отношению к своему объекту. Соответственно,&lt;br /&gt;
их имена должны быть уникальными в рамках одного объекта, но могут&lt;br /&gt;
совпадать у разных. Не забывайте о чувствительности регистра букв в&lt;br /&gt;
названиях. Следите за соответствием значения переменной ее типу.&lt;br /&gt;
&lt;br /&gt;
=== Закодируйте мне это ===&lt;br /&gt;
После такого теоретического вступления, думаю, пришла пора воплотить наши замыслы в реальность. Итак, у нас в запасе имеется всего&lt;br /&gt;
три попытки на выполнение броска. Визуально они отражаются в виде&lt;br /&gt;
такого же количества шаров, расположенных в правом нижнем углу&lt;br /&gt;
игрового экрана. При совершении очередного броска эти сферы исчезают. В связи с некоторыми особенностями игрового конструктора и заявленной целью не использовать напрямую встроенный язык программирования, решение задачи несколько усложняется. Поэтому мы пройдем&lt;br /&gt;
с вами все ступени разработки данного куска логики. В самом простом&lt;br /&gt;
варианте эту задачу можно было бы описать так:&lt;br /&gt;
&amp;lt;pre&amp;gt;кол-во_попыток =3&lt;br /&gt;
НАЧАЛО ЦИКЛА&lt;br /&gt;
бросаем шар&lt;br /&gt;
кол-во_попыток=кол-во_попыток-1&lt;br /&gt;
ПОКА кол-во_попыток &amp;lt;&amp;gt; 0 ВЫПОЛНЯТЬ ЦИКЛ&lt;br /&gt;
КОНЕЦ ЦИКЛА&amp;lt;/pre&amp;gt;&lt;br /&gt;
Это, безусловно, правильно, но уж больно далеко до реального&lt;br /&gt;
воплощения в игре. Давайте рассуждать более предметно, с точки зрения имеющихся у нас возможностей.&lt;br /&gt;
&lt;br /&gt;
Пусть имеется некая глобальная переменная Count, ответственная&lt;br /&gt;
за хранение числа имеющихся у нас попыток. При каждом бросании&lt;br /&gt;
шара всем объектам в игре отсылается сообщение go. Предположим&lt;br /&gt;
также, что каждая из сфер интерфейса при появлении подобного&lt;br /&gt;
сообщения сравнивает число, хранящееся в Count, со своим номером.&lt;br /&gt;
При совпадении происходит уменьшение значения глобальной переменной Count и удаление соответствующей сферы с экрана.&lt;br /&gt;
&lt;br /&gt;
Если вы внимательно читали написанное до этого, то могли&lt;br /&gt;
заметить некоторое несоответствие – в визуальном конструкторе Blender имеются только локальные переменные самого объекта (можно, конечно, их называть свойствами объекта, но, на мой&lt;br /&gt;
взгляд, это не совсем правильно). Но что мешает нам создать&lt;br /&gt;
переменную, скажем, объекта arr и представить, что она является&lt;br /&gt;
глобальной по отношению к остальным, а потом при появлении&lt;br /&gt;
сообщения go копировать ее значение в свойство конкретного объекта? Правильно, ничего. Чтобы было более наглядно, представим&lt;br /&gt;
это столь же схематично, но уже с учетом реальных названий объектов в нашей сцене:&lt;br /&gt;
&amp;lt;pre&amp;gt;arr.Count = 3;&lt;br /&gt;
НАЧАЛО ЦИКЛА&lt;br /&gt;
бросаем шар и отсылаем сообщение «go»;&lt;br /&gt;
...&lt;br /&gt;
// предположим, объекты s1, s2, s3 приняли сообщение «go»&lt;br /&gt;
s1.Count = arr.Count;&lt;br /&gt;
s2.Count = arr.Count;&lt;br /&gt;
s3.Count = arr.Count;&lt;br /&gt;
ЕСЛИ s1.Count ==3 ТО уменьшаем arr.Count и&lt;br /&gt;
удаляем объект s1;&lt;br /&gt;
ЕСЛИ s2.Count ==2 ТО уменьшаем arr.Count и&lt;br /&gt;
удаляем объект s2;&lt;br /&gt;
ЕСЛИ s3.Count ==1 ТО уменьшаем arr.Count и&lt;br /&gt;
удаляем объект s3;&lt;br /&gt;
ПОКА arr.Count &amp;lt;&amp;gt; 0 ВЫПОЛНЯТЬ ЦИКЛ&lt;br /&gt;
КОНЕЦ ЦИКЛА&amp;lt;/pre&amp;gt;&lt;br /&gt;
Итак, хватайтесь за мышь: начинаем «кодить». Для начала реализуем систему обмена сообщениями между объектами.&lt;br /&gt;
&lt;br /&gt;
{{Врезка&lt;br /&gt;
|Заголовок=Памятка&lt;br /&gt;
|Содержание=Хотя наш урок и называется «Ни строчки кода», тем не менее, в&lt;br /&gt;
визуальном конструкторе приходится использовать переменные разных типов. Всего их в Blender Engine 5 штук: String, Integer, Float,&lt;br /&gt;
Boolean, Timer.&lt;br /&gt;
* String предназначена для хранения текстовой информации. Впоследствии ее можно вывести на экран, проделав некоторые хитрые манипуляции (об этом – в следующий раз).&lt;br /&gt;
* Integer – целочисленное двухбайтовое число, может иметь отрицательное значение.&lt;br /&gt;
* Float – число с плавающей запятой.&lt;br /&gt;
* Boolean – логический тип переменной. Имеет два значения: True [Истина] или False [Ложь]. Наряду с этими текстовыми значениями можно использовать численные: 1 и 0.&lt;br /&gt;
* Timer – число, выраженное в миллисекундах.&lt;br /&gt;
|Ширина=300px}}&lt;br /&gt;
Так как объект Emp_boul у нас ответственен за визуализацию шара,&lt;br /&gt;
то пусть он и отсылает сообщение go. Создайте дополнительный кирпичик Message в блоке Actuators и соедините его с цепочкой, ответственной за обработку клавиши Space. Не забудьте вбить туда само&lt;br /&gt;
сообщение! (Рис. 4)&lt;br /&gt;
&lt;br /&gt;
[[Изображение:LXF 103 94 1.png|frame|center|Рис. 4. Примемся за «код».]]&lt;br /&gt;
&lt;br /&gt;
Теперь мы можем добавить логику объектам s1, s2, s3 для приема&lt;br /&gt;
этого сообщения и копирования переменной Count объекта arr в свои&lt;br /&gt;
собственные. Естественно, сперва вам нужно создать эти самые переменные для arr, s1, s2, s3. Тип переменной везде будет Integer, только&lt;br /&gt;
установите значение для arr.Count равным 3.&lt;br /&gt;
&lt;br /&gt;
Итак, создайте логическую цепочку объекта s1, состоящую из кирпичиков Message &amp;gt; And &amp;gt; Property. Для сенсора в поле Subject поместите текст сообщения go.&lt;br /&gt;
&lt;br /&gt;
Чтобы скопировать одну переменную в другую, выберите из меню&lt;br /&gt;
актуатора функцию Copy и настройте имеющиеся параметры следующим образом:&lt;br /&gt;
* Prop: – count&lt;br /&gt;
* OB: – arr&lt;br /&gt;
* Prop: – count&lt;br /&gt;
Таким образом, первое поле содержит название переменной-приемника, два остальных, соответственно, название объекта и копируемой переменной. Подобные цепочки создайте и для оставшихся&lt;br /&gt;
двух сфер.&lt;br /&gt;
&lt;br /&gt;
Однако глобальная переменная при броске у нас пока не изменяется. Что ж, исправить это несложно: нужно лишь добавить для&lt;br /&gt;
стрелки цепочку, подобную построенной выше. Для активатора&lt;br /&gt;
Property теперь выберите функцию Add [Добавить]. Пользоваться&lt;br /&gt;
ею так же просто, как и другими. Поместите в поле «Prop:» название&lt;br /&gt;
переменной count, а в параметр Value: значение -1. Как вы, надеюсь,&lt;br /&gt;
помните из школьной математики, сложение 3+(-1) в сумме даст 2.&lt;br /&gt;
&lt;br /&gt;
Вот теперь наш механизм счета произведенных бросков работает как часы. Если сомневаетесь в этом, воспользуйтесь приведенным выше советом и активируйте вывод переменной arr.count на&lt;br /&gt;
экран (можете выводить и все остальное, но это, по-моему, будет&lt;br /&gt;
излишеством).&lt;br /&gt;
&lt;br /&gt;
Осталось решить, что делать со сферами, когда надобность в них&lt;br /&gt;
исчезает. Да просто удалять их, а как выполнить это, я уже рассказывал&lt;br /&gt;
чуть выше. Удивлены? Ведь не зря некоторую часть этой статьи занял&lt;br /&gt;
псевдокод, а именно строки типа: «ЕСЛИ s1.Count ==3 ТО уменьшаем&lt;br /&gt;
arr.Count и удаляем объект s1;». В переводе на язык Blender, это будет&lt;br /&gt;
выглядеть следующим образом.&lt;br /&gt;
&lt;br /&gt;
Создайте цепочку Property &amp;gt; And &amp;gt; Edit Object для объекта s1&lt;br /&gt;
[Свойство &amp;gt; Логическое И &amp;gt; Редактирование объекта]. Задача сенсора в этом случае – выдавать импульс при одинаковом значении поля&lt;br /&gt;
Value и переменной Prop. То есть, для объекта s1 это значение составит 3, а для оставшихся двух, соответственно 2 и 1. Что же касается&lt;br /&gt;
кирпичика Edit Object, то просто выберите в нем функцию End Object –&lt;br /&gt;
она не принимает параметров и уничтожает вызвавший ее объект.&lt;br /&gt;
Соответственно, настройте подобным образом оставшиеся сферы.&lt;br /&gt;
&lt;br /&gt;
Вот так мы с вами справились с отображением информации о&lt;br /&gt;
произведенных бросках, но сами броски так и остались неограниченными. Тут также нужно будет воспользоваться механизмом сообщений. Предположим, объект arr проверяет свою переменную count на&lt;br /&gt;
равность нулю и при выполнении этого условия отсылает сообщение&lt;br /&gt;
«go_off». Осталось настроить Emp_boul на его прием и удаление при&lt;br /&gt;
положительном импульсе самого себя. Вот и все! Если вам не удастся&lt;br /&gt;
решить эту задачу самостоятельно, загляните в исходник lesson2_end.blend.&lt;br /&gt;
&lt;br /&gt;
Не знаю, как вам, но мне наскучили эти&lt;br /&gt;
унылые серые линии: настала пора вдохнуть&lt;br /&gt;
в них цвета во всем их красочном многообразии! На следующем уроке мы не только продолжим совершенствовать логику игры, но и&lt;br /&gt;
узнаем секреты игрового текстурирования, а&lt;br /&gt;
может, и добавим для разнообразия некоторые эффекты.&lt;/div&gt;</summary>
		<author><name>Yaleks</name></author>	</entry>

	</feed>