101 Рис. 6.16 Вновь появилось окно графического редактора. Выберите серый цвет, нарисуйте кружок диаметром, примерно равным двойной ширине линии разметки (20 пикселей), ориентируясь на расположенное рядом изображение. Используйте инструмент "Закрашенный эллипс" (рис. 6.17). Чтобы кружок получился ровным, держите зажатой клавишу "Shift". Рис. 6.17 При помощи инструмента "Установка центра вращения" убедитесь, что перекрестье лежит в центре круга, закончите редактирование, нажав на кнопку "ОК". Переименуйте новый спрайт, дав ему название "Сенсор1". Передняя часть робота в настоящий момент направлена направо, перетащите мышкой сенсор, поменяв его положение так, чтобы он был расположен впереди слева по направлению движения робота (рис. 6.18).
102 Рис. 6.18 Сдублируйте спрайт сенсора (используем правую кнопку мыши, щелкнув по нужному по спрайту, рис. 6.19). Рис. 6.19 Дайте дублю название "Сенсор2". Перетащите второй сенсор, чтобы он располагался впереди справа по направлению движения робота (рис. 6.20).
103 Рис. 6.20 Теперь мы сделаем очень интересную операцию - объединим несколько спрайтов, чтобы они стали одним целостным объектом. После этого все спрайты, составляющие объект, будут перемещаться вместе. "Ухватите" мышкой иконку спрайта "Сенсор2" на панели спрайтов и "бросьте" её на изображение робота на сцене (рис.6.21). Рис. 6.21
104 Иконка вернулась на панель спрайтов, но кое-что изменилось: появились дополнительные значки, обозначающие взаимосвязанность спрайтов. Главным спрайтом ("хозяином") является спрайт "Робот" (рис. 6.22). Рис. 6.22 Повторите операцию для спрайта "Сенсор1", "зацепите" его иконку и "бросьте" на изображение робота на сцене. Готово, все три спрайта взаимосвязаны, и теперь при перемещении робота будут перемещаться и его сенсоры. Проверьте это, перетащив робота и поставив на линию (рис. 6.23). Рис. 6.23 Давайте чуть уменьшим размер робота. Выберите спрайт "Робот" (рис. 6.24).
105 Рис. 6.24 Переключитесь на вкладку "Скрипты". Найдите на панели скриптов блок "установить размер в" (категория "Внешность") и вытяните на рабочее поле рис. 6.25). Рис. 6.25 Отредактируйте значение и щёлкните по блоку, задав размер 50%. И сам робот, и его сенсоры стали меньше, пропорционально поменяв свой размер (рис. 6.26).
106 Рис. 6.26 Готово! Осталось сохранить свой проект, чтобы можно было вернуться к нему после паузы для написания программы следования по линии. Откройте меню "Файл", "Сохранить как" (рис. 6.27). Рис. 6.27 Выберите "Компьютер", напечатайте имя проекта, нажмите кнопку "Сохранить" (рис. 6.28).
107 Рис. 6.28 В стандартном диалоговом окне выберите папку, в которую будет помещён сохраняемый файл "Робот на линии.xml". Обратите внимание, что заголовок нашего проекта тоже изменился (рис. 6.29). Внимание! Если вы используете он-лайн версию среды, запуская ее прямо в Интернетбраузере, то файл просто сохранится в папку по умолчанию (Загрузки) и вам придется вручную задать ему имя и потом (для удобства) перенести в то расположение, где вы будете хранить все файлы проекта. Рис. 6.29 Теперь среду Snap4arduino можно закрывать, результаты нашей работы сохранятся.
108 Этап 2: Программируем робота для движения по линии Снова откройте среду Snap4arduino. Загрузите проект "Робот на линии.xml" командой "Файл", "Открыть". Далее мы будем составлять программу для робота, убедитесь, что выбран именно спрайт "Робот". Обратите внимание, что поле скриптов спрайта "Робот" уже содержит блок "Установить размер в", который мы туда ранее поместили (рис. 6.30). Рис. 6.30 Масштаб отображения сцены можно менять кнопкой, расположенной над сценой слева, это позволяет с большим удобством работать со скриптами. В нашем проекте мы будем использовать пропорциональное регулирование: чем дальше линия отклонилась от средней позиции, тем быстрее робот будет поворачиваться в соответствующую сторону, чтобы линия оказалась снова посередине. Давайте для наглядности создадим необходимые переменные и назовём их понятными именами. Нам нужны 4 переменные: "яркость1", "яркость2", "ошибка_положения_линии", "управляющее_воздействие". Обратите внимание, что большинство языков программирования не позволяют использовать в именах пробелы, поэтому мы заменяем их символами подчеркивания. Щелкните по кнопке "Объявить переменную" (рис. 6.31).
109 Рис. 6.31 Корректнее использовать локальные переменные ("только для текущего спрайта"), которые будут доступны лишь в спрайте "Робот". В будущем наш проект может быть дополнен другими спрайтами, которые будут иметь собственные переменные с аналогичными названиями. Итак, создайте 4 локальных переменных (рис. 6.32). Рис. 6.32 Снимите маркеры, чтобы значения переменных не отображались на сцене и не мешали нам (рис. 6.33). Рис. 6.33
110 В нашей программе будет использоваться очень полезный блок из категории "Сенсоры" (рис. 6.34), который позволяет определять яркость, насыщенность цвета и оттенок под выбранным объектом. Рис. 6.34 Соберите скрипт из блоков по образцу ниже (рис. 6.35). Ещё раз убедитесь, что выбран именно спрайт "Робот". Все остальные объекты нашей программы не нуждаются в собственных скриптах. Рис. 6.35 Запустите программу и проверьте её функционирование. Робот должен уверенно следовать по линии (рис. 6.36).
111 Рис. 6.36 Переключитесь на режим "Турбо" (рис. 6.37). Рис. 6.37 Попробуйте запустить робота вне линии, проверьте, что получится. Экспериментируйте, меняя время задержки цикла, скорость движения (количество шагов за один цикл), а также коэффициент пропорциональности, превращающий ошибку положения линии в управляющее воздействие. Сохраните свой проект. При сохранении в новое место опять выберите "Computer", при необходимости дайте новое имя.
112 Этап 3 (дополнительно): Выясняем недостатки модели, определяем пути усовершенствования Что будет, если запустить по линии одновременно двух роботов? Давайте проверим. Сдублируйте спрайт "Робот" (рис. 6.38). Вы видите, что сдублировались и подчинённые спрайты сенсоров. Теперь у нас 6 спрайтов: "Робот", "Сенсор1", "Сенсор2", "Робот(2)", "Сенсор1(2)" и "Сенсор2(2)". Рис. 6.38 Второй робот получил и копию управляющего скрипта. Однако этот скрипт необходимо поправить (рис. 6.39), чтобы второй робот использовал свои собственные сенсоры, а не сенсоры первого робота.
113 Рис. 6.39 Поставьте второго робота на линию так, чтобы он двигался навстречу первому, и запустите программу (рис. 6.40). Рис. 6.40 Как видите, следует ещё поработать над моделью столкновений объектов. Предлагаем вам самостоятельно доработать скрипты, придумав сценарий поведения роботов при столкновении. Кстати, это позволит нашему виртуальному роботу в будущем решать задачи по перемещению (толканию) грузов. Но об этом подробнее – в следующем проекте.
114 6.3 Столкновения В этом проекте сделаем так, чтобы наш виртуальный робот был способен толкать и перемещать груз по игровому полигону (рис. 6.41). Рис. 6.41 Моделирование столкновений – очень полезный навык, в том числе часто используемый при написании компьютерных игр, аркадных или логических. Многим знакома симпатичная игра "Snail and Sokoban", в которой необходимо расставить ящики по нужным местам. Реализация подобного проекта в среде Snap4arduino может оказаться весьма интересной и познавательной задачей. В Scratch для проверки столкновений зачастую используют блок "касается цвета". Подобный метод, несмотря на свою простоту, имеет много недостатков. Существуют иной, гораздо более универсальный способ путём проверки касания отдельного спрайта или касания одного из элементов в списке спрайтов. Среда Snap4arduino содержит множество средств, облегчающих нам работу. Давайте посмотрим, насколько удобно ими пользоваться. Итак, определим задачи. Вначале мы создадим спрайт компьютерного персонажа ("робота"), управляемый при помощи клавиатурных кнопок. Научим его останавливаться перед препятствиями (любыми другими спрайтами). А затем добавим в проект перемещаемые спрайты - "бочки" и сделаем так, чтобы робот мог их двигать по полю. Будем решать всё шаг за шагом, поэтапно.
115 Этап 1. Подготовка. Нам понадобится четыре изображения для наших объектов, загрузите их на свой компьютер (рис. 6.42, щёлкните правой кнопкой мыши по каждому изображению и воспользуйтесь контекстным меню "Сохранить как…", или возьмите уже готовые файлы из папки электронного архива). "робот.png" "захват.png" " бочка.png " "стенка.png" Рис. 6.42 Запустите Snap4arduino. Выберите сцену и добавьте ей фон, закрашенный каким-нибудь цветом светлого оттенка (рис. 6.43). Рис. 6.43
116 Этап 2. Создаём робота. Робот останавливается, когда врезается в препятствия. Выберите спрайт с названием "Спрайт", переименуйте его в "Робот1" (рис. 6.44, это будет первый робот в нашем проекте, в будущем мы можем добавить дополнительных). Рис. 6.44 Добавьте новый костюм из файла " робот.png", перетащив его на вкладку "Костюмы" (рис. 6.45). Рис. 6.45 Переключитесь на вкладку "Скрипты". Обеспечим возможность ручного управления роботом с использованием компьютерной клавиатуры. Соберите скрипт по образцу (рис. 6.46).
117 Рис. 6.46 Запустите программу и проверьте управление роботом. Имейте ввиду, что он может уехать далеко за пределы отображаемого пространства. Используйте для возврата блок "перейти в точку X (0) Y (0)" – рис. 6.47. Рис. 6.47 Добавьте в проект ещё один спрайт (любой). Например, нажмите кнопку "создать новый стандартный спрайт" (рис. 6.48). Рис. 6.48
118 Запустите программу ещё раз и проверьте, будет ли робот останавливаться, врезавшись в этот спрайт. Как видите, спрайты пока никак не взаимодействуют. Рис. 6.49 Будем дорабатывать скрипт робота. Обратите внимание, что в настоящий момент выбран новый спрайт, и у него пока нет собственного скрипта. Переключитесь на спрайт робота. Найдите на палитре скриптов в разделе "Сенсоры" блок "атрибут" (английский вариант названия - "my") и вытащите его на рабочее поле (рис. 6.50). По умолчанию выбран атрибут "соседи" ("my neighbors"). Рис. 6.50 Данный блок способен возвращать разные свойства объекта, в том числе список расположенных поблизости спрайтов. Причём это не просто имена, а ссылки, позволяющие данные объекты использовать, что может оказаться очень мощным инструментом в самых разных ситуациях.
119 Щёлкните по блоку. Вы увидите, что список состоит лишь из одного объекта, это добавленный нами новый спрайт (рис. 6.51). Он попал в список, поскольку располагается на сцене рядом со спрайтом "Робот1". Рис. 6.51 Если "стрелочку" отодвинуть подальше, список окажется пустым (рис. 6.52). Рис. 6.52 Вытащите на рабочее пространство блок "касается" и поместите внутрь блок "атрибут" рис. 6.53). Теперь мы можем проверить, касается ли один спрайт другого, без указания их имён. Это очень важно с точки зрения универсальности, результаты нашей работы мы сможем использовать во всех будущих проектах.
120 Рис. 6.53 Давайте теперь создадим специальный новый блок, который будет перемещать робота, проверять, не коснулся ли он чего-либо, и если это произошло, отодвигать робота назад (и даже на всякий случай чуть дальше). Кроме того, для удобства сделаем так, чтобы скорость перемещения робота была пропорциональна масштабу его отображения. Выберите категорию "Прочее", нажмите кнопку "Новый блок". Вы увидите диалоговое окно (рис. 6.54). Рис. 6.54
121 Создаваемый блок мог бы работать одинаково хорошо с любыми спрайтами, однако выберите опцию "только для текущего спрайта" (рис. 6.55). Это упростит нам в будущем использование данного спрайта в других проектах. Дайте блоку имя "переместиться" (рис. 6.55), нажмите на кнопку "ОК". Рис. 6.55 Появилось окно редактора блоков (рис. 6.56). Рис. 6.56 Нажмите на "плюсик" и добавьте числовой параметр, назовите его "дистанция" (рис. 6.57). Рис. 6.57
122 Теперь можно собирать скрипт (рис. 6.58). Вам понадобится блок "размер" из категории "Внешность", это текущий масштаб отображения спрайта. Блок "ждать" служит для того, чтобы другие спрайты успевали отреагировать на касание робота, если это предусмотрено их скриптами. Рис. 6.58 Отредактируйте основной скрипт спрайта "Робот1" (рис. 6.59). Рис. 6.59
123 Запустите программу, проверьте, как ведёт себя робот. Теперь он "отказывается" перемещаться за границы экрана и туда, где расположен какой-нибудь спрайт. Причём этот спрайт может иметь любое название и костюм. Рис. 6.60
124 Этап 3. Создаём спрайт "Бочка1", который можно будет толкать по сцене. Добавим в наш проект полезный груз. У нас уже есть спрайт со "стрелочкой", замените ему костюм с использованием файла "бочка.png". Дайте спрайту название "Бочка1" (рис. 6.61). Рис. 6.61 Скрипт данного спрайта должен предусматривать отодвигание от любого другого спрайта, которого он касается, а в случае касания нескольких - отодвигание от каждого из них. Поэтому придётся немножко поработать со списками. Мы будем проверять список спрайтов-соседей элемент за элементом. Блок "сразу" заставляет эту часть скрипта выполняться максимально быстро. Соберите скрипт для спрайта "Бочка1" по образцу на рисунке 6.62. Рис. 6.62
125 Проверьте, как всё функционирует. Робот толкает груз! Рис. 6.63 Этап 4. Добавляем копии спрайта "Бочка1", и спрайты препятствий. На основе созданной нами заготовки уже можно реализовать множество проектов, в которых, например, робот должен будет отодвинуть препятствие в сторону. Но оказывается, наши спрайты уже готовы к тому, чтобы взаимодействовать друг с другом более сложным образом. Добавьте в проект копии спрайта "Бочка1"(рис. 6.64). Неважно, какие имена они при этом получат. Запустите проект и проверьте, что выйдет, если бочки "нагромождены" одна на другую. Рис. 6.64
126 Что будет, если толкать одну из бочек на другую, или сразу на несколько? Рис. 6.65 Наконец, добавьте спрайты статических препятствий. Используемый нами алгоритм работает оптимально со спрайтами округлой формы, но слегка вытянутые свою роль тоже выполняют. Спрайт "Стенка" препятствует сдвиганию груза вбок при перемещении (рис. 6.66). Рис. 6.66 Из подготовленных спрайтов как из конструктора можно собирать самые разнообразные игровые задания. Теперь мы в состоянии построить лабиринт, по которому робот должен будет перемещать бочки.
127 Этап 5. Робот с захватами. Осваиваем операции с множествами. Было бы неплохо снабдить нашего робота "лапками" или "захватами", чтобы он был способен без проблем перемещать груз в произвольном направлении по свободному полю сцены. Захваты нужны, чтобы груз не смещался в сторону при движении. Добавить роботу "лапки" можно путём объединения нескольких спрайтов в единый взаимосвязанный объект. Метод объединения нескольких спрайтов уже был рассмотрен в проекте " Программируем робота для движения по линии ". Повторим. Добавьте новый стандартный спрайт, переименуйте, замените костюм (рис. 6.67). Рис. 6.67 Подберите подходящий масштаб отображения, например, 50%. Щёлкните по соответствующему блоку. Рис. 6.68
128 Разместите "Захват1" так, чтобы он располагался спереди слева по направлению движения робота (рис. 6.69). Рис. 6.69 Сдублируйте спрайт, назовите "Захват2". Разместите спереди справа. Рис. 6.70
129 Ухватите мышкой иконку спрайта "Захват1" и бросьте на изображение робота на сцене (рис. 6.71). Рис. 6.71 Теперь на панели спрайтов иконки "Робот1" и "Захват1" располагаются рядом. Кроме того, появилась маркировка, что эти спрайты связаны. Рис. 6.72
130 Повторите операцию для спрайта "Захват2" (рис. 6.73). Рис. 6.73 Готово, спрайт "Робот1" является хозяином для спрайтов "Захват1" и "Захват2". Рис. 6.74 Запустите программу, проверьте возможность управления роботом. Он поворачивается вместе со своими захватами, но сдвигаться с места отказывается. Всё выглядит так, как будто робот касается препятствия. Рис. 6.75
131 Так и есть: робот теперь непрерывно "касается" собственных захватов. Это можно проверить, выбрав спрайт робота и используя соответствующие блоки (рис. 6.76). Рис. 6.76 Чтобы восстановить работоспособность программы и сохранить её универсальность (отсутствие зависимости от имён подчинённых спрайтов и даже от их количества), нам придётся освоить операции с множествами. Блок "атрибут соседи" возвращает список расположенных поблизости спрайтов, то есть множество некоторых объектов (рис. 6.77). Рис. 6.77 Блок "атрибут части" возвращает множество объектов, которые принадлежат роботу (рис. 6.78).
132 Рис. 6.78 Осталось вычесть одно множество из другого, чтобы появилась возможность узнать, касается ли робот какого-то объекта, который не является его собственной частью. Мы создадим специальный блок с названием "касается_препятствия", который будет возвращать одно из двух значений: "истина" или "ложь". Внутри этого блока будет происходить вычитание одного множества из другого. Проверьте, что выбран спрайт "Робот1". Создайте блок, указав опцию "только для текущего спрайта" и тип блока "Предикат" (рис. 6.79). Рис. 6.79 Скрипт "касается_препятствия" выглядит так, как на рисунке 6.80. Для изменения количества "окошечек" в блоках "список" и "переменные скрипта" пользуйтесь стрелочками. Блок "список" с нулевым количеством элементов возвращает пустой список (пустое множество).
133 Рис. 6.80 Проверьте функционирование блока "касается_препятствия", перетаскивая спрайты и щёлкая по блоку курсором мыши (рис. 6.81). Рис. 6.81 Поправьте скрипт блока "переместиться" (рис. 6.82).
134 Рис. 6.82 Робот снова начал выполнять наши команды. И бочка при перемещении не пытается "уползти" в сторону. Теперь можно будет запрограммировать робота для самостоятельного передвижения и выполнения какого-нибудь игрового задания. Дело за вами!))) Рис. 6.83
135 Этап 6. Сохраняем результаты. Мы проделали много работы. Плодами нашего труда можно будет пользоваться словно элементами конструктора, собирая из готовых спрайтов и блоков новые проекты. Для пользования созданными программными компонентами не обязательно даже чётко понимать, как именно они работают. Например, мы можем кому-нибудь предоставить файлы с экспортированными спрайтами, он придумает дизайн игрового задания и разместит все объекты, после чего передаст кому-то третьему со словами: "Составь такой алгоритм, чтобы робот, перемещаясь по полю, выполнил своё задание". Итак, приступим. Первым делом сохраним сам проект на свой жёсткий диск. Следует задать имя и выбрать "Computer". Полученный файл имеет расширение "xml". Рис. 6.84 Теперь сохраним ещё и отдельные спрайты "Робот1" и "Бочка1", поскольку они подготовлены нами для самостоятельной работы в любом новом окружении. Щёлкните правой кнопкой мыши по спрайту и воспользуйтесь контекстным меню (рис. 6.85). Рис. 6.85
136 При экспорте спрайта "Робот1" в файл будут автоматически добавлены и спрайты "Захват1" и "Захват2". Файлы экспорта, содержащие спрайты, тоже получают расширение "xml". Рекомендуется в имя файла включать упоминание о том, что это именно спрайт, а не целый проект (рис. 6.86). Рис. 6.86 В любой новый частично или полностью созданный проект можно будет добавить готовые спрайты (а также блоки, см. ниже) командой "Импорт". Рис. 6.87 Следует помнить о том, что, если при импорте выбрать файл, содержащий не спрайт или библиотеку блоков, а обычный проект, прежний проект, открытый в среде Snap4arduino, будет без предупреждений заменён новым. Рекомендуется сохранять результаты своей работы перед попыткой импортировать дополнительные объекты. Можно ли созданные нами сегодня блоки со скриптами использовать с любыми другими спрайтами? Да, можно, но требуется их сохранить с опцией "для всех спрайтов". Кроме того, в некоторых случаях будет полезно подготовить эти блоки таким образом, чтобы их запуск был возможен даже Сценой. Давайте это сделаем. Создадим универсальный блок, возвращающий список (с типом "Генератор значений") и названием "разность_множеств". Не обязательно собирать его полностью заново, можно просто скопировать и немного поправить скрипт блока "касается_препятствия" (рис. 6.88).
137 Рис. 6.88 Проверим работу на элементах одного типа. Рис. 6.89
138 А теперь на элементах другого типа. Рис. 6.90 Как видите, блок работает независимо от типа элементов. Точно таким же образом при необходимости можно создать "объединение_множеств" и "пересечение_множеств". Все необходимые блоки можно экспортировать для дальнейшего использования командой меню "Экспортировать блоки" (рис. 6.91). Можно выбрать именно те, которые мы хотим сохранить в отдельном xml-файле. Рис. 6.91 Итоги, планы на будущее. Используемая нами модель столкновений ещё далека от совершенства. Бочки стремятся отодвинуться от центра препятствия, между тем как со спрайтами вытянутой формы это работает плохо. Если усовершенствовать модель столкновений, можно будет добавлять в проекты объекты, перемещающиеся по инерции, и правдоподобным образом отскакивающие от препятствий произвольной формы. Тем не менее, даже с учётом существующих недостатков, подготовленные спрайты с запрограммированной реакцией на столкновения позволяют реализовать много интересных учебных и игровых проектов.
139 6.4. Проект – "Робот-спасатель в лабиринте" . А теперь продемонстрируем уже готовый проект, иллюстрирующий возможности виртуальной робототехники. В данном игровом проекте робот-спасатель должен искать некий объект "Потеряшка" в лабиринте и возвращаться с ним на базу. Ваша задача – разобраться в алгоритме возвращения на базу и оптимизировать его, чтобы робот вместе с потеряшкой возвращался на базу как можно быстрее. Начало работы. Откроем готовый проект и посмотрим его состав. Нажмите значок папки, выберите команду Открыть. Выберите вариант открытия с компьютера (Computer). Рис. 6.92 Откройте файл электронного архива, 6 блок, файл спасатель_в_лабиринте.xml Открывается проект (рис. 6.93)
140 Рис. 6.93 В проекте подготовлена сцена – нарисованный лабиринт. В левом верхнем углу лабиринта видно Список –путь (серый квадрат Робот путь), в котором будут хранится все перемещения робота. На текущем этапе он пуст. В правом верхнем углу сцены (база) находиться зеленый робот. Рядом с роботом видно розовый кружок – спрайт Потеряшка, именно его будет искать робот и запоминать свой путь, что будет использоваться для возвращения на базу. Стрелка на поле лабиринта – это маркер, который можно перемещать с помощью курсора мыши, и в эту точку будет помещен Потеряшка при запуске игры. Данный проект уже готов и содержит алгоритм поиска. Перед запуском рекомендуем в настройках включить режим Турбо (рис. 94), чтобы действие происходило быстрее. Рис. 6.94
141 Запустите проект на исполнение. Нажмите на зеленый флажок запуска (справа вверху над сценой, справа от него - пауза и красный кружок – остановка выполнения скриптов). Потеряшка перемещается в область, указанную стрелкой. Робот начинает движение, обыскивая лабиринт. Выполняется алгоритм поиска с проверкой стены слева. Обратите внимание на список путь, который наполняется в соответствии с последовательностью движения робота (рис. 6.95). Рис. 6.95 Робот находит Потеряшку и вместе с ней возвращается на базу по своему пути. Внимание! Мы иногда сталкивались с тем, что при первом запуске робот проскакивает мимо Потеряшки. Просто перезапустите программу, это какая-то ошибка выполнения. Можно перетащить стрелку в другую точку лабиринта и вновь запустить процесс поиска. Например, в следующем скриншоте видно, что путь до Потеряшки содержит уже 236 участвов (смотрим на окно списка на рис. 6.96). Робот вновь отыскивает Потеряшку и уносит ее на базу.
142 Рис. 6.96 Обратите внимание, обратный маршрут уже частично оптимизирован. Сразу после подхвата объекта список пути показывает уже не 236, а 132 участка движения (рис. 6.97). Здесь довольно простая оптимизация, убирающая лишние повороты к стене для проверки. Рис. 6.97 Теперь начнем разбираться в проекте и искать варианты повышения степени оптимизации алгоритма поиска. Остановите работу программы. Мы покажем, как посмотреть и редактировать содержимое блоков на примере блока оптимизировать_путь. Как и в Scratch, разбираем для удобства главный управляющий скрипт на части. Разделим скрипт на три части (см. рис 6.98):
143 Рис. 6.98 Здесь верхняя часть отвечает за поиск Потеряшки (до касания). Средняя часть – за оптимизацию и отображение пути. Нижняя – за возвращение на базу. Теперь, после разборки, для наглядности можно вновь запустить программу на выполнение (зеленый флажок). Робот проходит свой маршрут и останавливается. Можно растянуть список и увидеть все элементы движения. В приведенном на рис. 6.99 примере это 76 элементов. Рис. 6.99
144 Теперь посмотрим содержание блока опимизировать_путь. Щелкните по нему правой клавишей мыши (наведя курсор на блок), вызывая всплывающее меню и выберите Редактировать (рис. 6.100). Рис. 6.100 Теперь мы видим в окошке содержимое блока и можем его редактировать. Рис. 6.101 Здесь видно, что операцией оптимизации является замена в списке путь всех элементов Лв и Прв (левый и правый повороты) на пустую последовательность. Если теперь щелкнуть левой кнопкой мыши на блок оптимизировать_путь, мы увидим в окне списка уже оптимизированный путь (рис. 6.102). Теперь в нем осталось только 40 элементов.
145 Рис. 6.102 Но мы видим, что оптимизация явно не оптимальна. Да, часть лишних поворотов мы убрали, но осталось много лишних заездов в тупики. Требуется понять, какие элементы пути являются лишними и подумать, как их можно убрать. Покрутите список, приглядитесь к командам. Бросаются в глаза блоки элементов пути вида: Впрд, Прв, Прв, Впрд (рис. 6.103). Это ситуация, когда робот заехал в тупик, уперся в стену, два раза повернулся вправо и вернулся в исходную точку. Рис. 6.103 Всю эту комбинацию можно заменить командой разворота, т.е. просто два раза повернутся направо: Прв, Прв. В окне редактирования блока оптимизировать_путь добавьте еще одну команду замен. Для простоты продублируйте уже имеющуюся (рис. 6.104)
146 Рис. 6.104 Поставьте дубль в нужную позицию. Рис. 6.105 Нажимая на черные стрелки в списке, добавьте пару окошек для новых элементов (рис. 6.106).
147 Рис. 6.106 Теперь в 4 окошка впишите нужные команды. Регистр имеет значение (заглавные буквы должны быть заглавными, смотрите на образец рис. 6.107)! Рис. 6.107 К списку, на который меняем эту комбинацию, тоже добавьте пару окошек (черная стрелка вправо) и впишите туда команды поворота (рис. 6.108)
148 Рис. 6.108 Нажмите на кнопку Применить. Проверим, работает ли наш код. Щелкните левой кнопкой по блоку оптимизации, проверьте, изменился ли список элементов пути. В нашем примере стало 36 элементов, т.е. были заменены 2 полных блока разворотов (рис. 6.109). Рис. 6.109
149 Теперь еще раз щелкнем по блоку оптимизации. Ура! Теперь элементов осталось 30! Рис. 6.110 Щелкнем еще раз… 26. Пробуем еще раз и количество участков сократилось до 24. Все, дальнейшие щелчки оптимизации не приносят, участки вращения закончились. Но результат отличный! Мы начинали с 76 участков, а применив два блока замен добились всего 24! Далее можно попробовать избавиться от многократных ручных запусков блоков оптимизации. Попробуйте поставить Потеряшку в удаленные точки карты, попробуйте оптимизировать пути, зафиксируйте, сколько раз нажатие блока оптимизации приводит к уменьшению элементов пути. После этого можно изменить главный скрипт, добавив нужное количество повторов оптимизации. Лишние повторы (в случае близкого расположения Потеряшки к базе) на время существенно не повлияют, а от ручных запусков мы избавимся. Теперь можно вновь собрать полный скрипт программы. Пример на рис. 6.111:
150 Рис. 6.111 Проверьте, как теперь работает программа для разных точек нахождения Потеряшки. Понятно, что можно двигаться и дальше. Можно автоматизировать точный поиск количества циклов оптимизации, можно искать другие повторяющиеся участки, оттачивать алгоритм оптимизации. Можно вообще сначала прогнать робота по всему лабиринту и построить его карту, а потом уже вычислять наиболее короткий путь на базу с любого расположения найденной Потеряшки. Но уже на рассмотренном примере можно понять насколько интересные задачи можно решать в условиях "виртуальной" робототехники. Дополнительно к проекту. Для исследовательской работы можно использовать и находящиеся на сцене отдельные блоки _на_старт_, В_П_Е_Р_Е_Д_ и т.д. Вручную отправить робота на базу, потом пошагово идти по лабиринту, отсматривая, как работает список. Можно перейти в блок команд Прочее (слева вверху), и использовать другие отдельные блоки, такие как блоки отрисовки пути, оптимизации маршрута и другие, наблюдая и разбираясь в том, как работают данные команды. Сохранение проекта. Для сохранения ваших проектов используется все та же кнопкуа с изображением папки. Выберите Сохранить, или Сохранить как, указывая, что сохранение идет на компьютер. В случае on-line версии проект просто сохраняется в папку по умолчанию (папка Загрузки). Вам стоит изменить название файла и его расположение для дальнейшей работы и понимания, что это за проект, т.к., несмотря на то, что мы вносим имя проекта в специальное поле, сам файл сохраняется в виде undefined.xml. В случае версии для компьютера такой проблемы нет, т.к. появляется окно с выбором пути и возможностью ввести имя файла.