Пока в проекте один спрайт на одну вещь, всё понятно. Но игра редко состоит из одного врага: нужны десять астероидов, двадцать монет, очередь пуль. Делать двадцать отдельных спрайтов и двадцать одинаковых скриптов невозможно — как только понадобится правка, её придётся повторить двадцать раз.
Для этого и нужны клоны. Один спрайт описывает поведение, а игра делает из него сколько угодно копий, каждая со своей жизнью. Тема считается сложной, хотя блоков в ней всего три; путаница растёт из двух правил, о которых нигде не написано большими буквами.
Три блока, и всё
| Блок | Что делает |
|---|---|
| создать клон [себя] | делает копию прямо сейчас |
| когда я начинаю как клон | шапка скрипта, который выполняет копия |
| удалить этот клон | копия исчезает навсегда |
Типичный проект выглядит так: главный скрипт в цикле создаёт клоны с паузой, а второй скрипт, под шапкой «когда я начинаю как клон», описывает, что копия делает — летит, падает, движется к игроку и в конце удаляет себя.
В выпадающем списке первого блока, кроме «себя», перечислены другие спрайты. Это понадобится реже, но бывает удобно: кнопка на сцене создаёт клоны стрелы, а не саму себя.
Что клон получает в наследство
В момент создания копия забирает у оригинала всё видимое: место, направление, размер, костюм, эффекты, видимость. Поэтому распространённый приём — перед созданием клона поставить оригинал туда, где копия должна появиться, и уже потом клонировать.
Так делают дождь, звездопад, появление врагов в случайной точке: оригинал прыгает в случайное место, создаёт клон и прыгает дальше. Сам оригинал при этом обычно спрятан, и на сцене видны только копии.
Вместе с внешним видом наследуются и значения переменных — но только тех, что созданы «только для этого спрайта». Общие переменные у всех одни, и это следующая часть темы.
Зелёный флажок для клона не работает
Вот первое правило, на котором спотыкаются все. Скрипты под шапкой «когда нажат зелёный флажок» у клонов не запускаются никогда. Флажок нажимают один раз, в начале, и к появившимся позже копиям он не имеет никакого отношения.
Ребёнок, который этого не знает, пишет поведение врага под флажком, видит, что клоны стоят неподвижно, и делает вывод, что клонирование не работает. На самом деле копии создались честно, просто им никто не дал команды.
Правило простое: всё, что должна делать копия, живёт под шапкой «когда я начинаю как клон». Под флажком остаётся только то, что делает оригинал, — чаще всего спрятаться и запустить цикл создания.
Предел в триста клонов
Второе правило, о котором Scratch не предупреждает. Одновременно в проекте может существовать до трёхсот копий. Когда лимит достигнут, блок создания просто ничего не делает — молча, без ошибки и без сообщения.
Выглядит это так: игра работает хорошо первые полминуты, а потом новые пули перестают появляться. Причина почти всегда одна — старые клоны никуда не делись. Они улетели за край экрана, стали невидимыми, но продолжают существовать и занимать место.
Лечится одной строкой: в конце скрипта копии обязательно должно быть «удалить этот клон». Пуля долетела до края — удалилась. Врага подбили — удалился. Привычку дописывать этот блок сразу стоит завести с первого же проекта с клонами, потому что искать потом причину «почему-то перестало работать» неприятно.
Собственные переменные для каждой копии
Если каждому врагу нужно своё здоровье или своя скорость, переменная должна быть создана с вариантом «только для этого спрайта». Тогда у каждой копии появляется собственное значение, и они перестают мешать друг другу.
Общая переменная в такой ситуации ведёт себя странно: попали в одного врага — здоровье исчезло у всех разом, и они погибли хором. Ошибка настолько характерная, что по ней сразу видно, какой вариант выбрали при создании.
Обратный случай тоже бывает: счёт игрока должен быть один на всю игру, и делать его локальным нельзя, иначе каждая пуля будет начислять очки сама себе в никуда.
Как клоны общаются с остальным проектом
Копия не имеет собственного способа позвать кого-то по имени, и это сначала ограничивает. Работают два механизма, и оба стоит знать.
Первый — сообщения. Блок «передать» слышит весь проект разом, включая все клоны. Удобно для общих команд: «игра закончилась», «начался следующий уровень». Все копии принимают сообщение одновременно, и каждая делает с ним что положено — обычно удаляет себя.
Второй — общие переменные. Клон может добавить себе очко в общий счёт, и это увидит вся игра. Именно так устроено большинство проектов со стрельбой: пуля-клон долетела до врага, добавила очко в общую переменную и удалилась.
Чего копия не умеет — обратиться к конкретной другой копии. Это граница инструмента, и обходить её в Scratch не стоит: если задача действительно требует такого, обычно она решается иначе.
Когда клоны не нужны
Не всякое повторение требует клонирования. Если объектов три-четыре и ведут они себя по-разному, проще и понятнее сделать отдельные спрайты. Клоны выигрывают там, где копий много и ведут они себя одинаково.
Есть и промежуточный вариант, о котором часто забывают: один спрайт, быстро перепрыгивающий между местами и оставляющий след пером. Для звездопада или узора это дешевле сотни копий и работает заметно плавнее.
Приём: оригинал-невидимка
Стандартная схема, которую стоит показать сразу целиком. Оригинал прячется на старте и больше никогда не появляется — он работает фабрикой. Всё, что видит игрок, — это копии.
Делается это так: под флажком оригинал прячется и входит в цикл, где ждёт, ставит себя в случайную точку и создаёт клон. Под шапкой клона копия показывается, движется и в конце удаляет себя.
Один нюанс: поскольку видимость наследуется, спрятанный оригинал даёт спрятанных копий. Поэтому первой строкой в скрипте клона почти всегда стоит «показаться». Забыть его — классика, и выглядит это как «клоны не создаются», хотя они есть, просто невидимые.
Как посмотреть, сколько копий сейчас в игре
Прямого блока «сколько клонов» в Scratch нет, и это неудобно именно тогда, когда подозреваешь утечку. Делается счётчик руками: общая переменная, которая увеличивается на единицу в скрипте клона и уменьшается перед удалением.
Окошко этой переменной стоит вывести на сцену во время отладки. Если число растёт и не падает — копии не удаляются, и до трёхсот дело дойдёт за минуту. Если число колеблется около десятка — всё в порядке.
Приём выглядит мелким, но он из того же семейства, что и проверка позиции окошком переменной: вместо догадок о поведении программы ребёнок получает число, которое видно. Именно этого не хватает большинству проектов, которые «почему-то тормозят».
Не забудьте обнулить счётчик на старте — иначе он унаследует значение с прошлого запуска и покажет неправду.
Три ошибки, которые повторяются
Первая: клоны создаются в цикле без паузы. За долю секунды их становится триста, лимит исчерпан, игра подвисает. Блок ожидания внутри цикла обязателен.
Вторая: «удалить этот клон» стоит посреди скрипта, до того, как копия что-то сделала. Клон исчезает мгновенно, и кажется, что он не появлялся вовсе.
Третья: проверка столкновений написана в оригинале, а не в клоне. Оригинал спрятан и стоит на месте, поэтому ничего не ловит, а копии при этом проверок не имеют. Проверять должна каждая копия сама за себя.
Клоны плотно связаны с переменными — о них есть отдельный справочник, а движение копий по сцене удобнее понимать после координат. Полный перечень блоков по категориям собран в справочнике блоков.