как сделать скрипт куба для головоломки движения вверх и вниз
Unity3d. Уроки от Unity 3D Student (B04-B08)
Предыдущие уроки вы можете найти в соответствующем топике.
Теперь в каждом посте в скобках (в конце) будут указываться номера уроков. Буква в начале номера обозначает раздел (B-Beginner, I — Intermediate).
PS: Если вы не проходили предыдущие уроки, очень рекомендую их пройти, т.к. последующие изредка на них ссылаются.
Базовый Урок 04 — Уничтожение объектов
В уроке рассказывается как удалять объекты со сцены, использую команду Destroy (уничтожить).
Создайте пустую сцену и добавьте в нее сферу (GameObject->Create Other->Sphere) и куб (GameObject->Create Other->Cube). Куб назовем “Box”. Расположите объекты как показано на рисунке ниже.
Добавьте C#-Скрипт (Project View->Create->C# Script) и назовите его Destroyer. Как уже говорилось, при создании C#-скрипта Unity создает некий каркас, состоящий из подключенных библиотек и основного класса (используемого скриптом) с методами Start() и Update(). В Базовом Уроке 02 (основы ввода) использовался метод Update(), который вызывается каждый кадр. В данном случае мы воспользуемся методом Start(), который выполняется сразу после загрузки сцены. Добавим в тело метода Start() функцию Destroy() и передадим в нее gameObject, указав таким образом, что скрипт должен уничтожить объект, компонентом которого он является:
Добавим скрипт к сфере. Сделать это можно несколькими путями. Перетащив скрипт из Project View на сферу в Scene View.
Или на имя объекта в Hierarchy.
Так же можно выбрать сферу и добавить скрипт через меню компонентов (Component->Scripts->Destroyer) или просто перетащив скрипт в Inspector View выбранного объекта.
Снова выберите сферу и убедитесь, что среди компонентов присутствует ваш скрипт.
Нажмите на Play и вы увидите, что сразу после загрузки сцены сфера исчезает.
Давайте теперь попробуем уничтожить другой объект. Для этого нам понадобится статический метод Find класса GameObject. Заменим код в методе Start() следующим:
Примечание от автора перевода: Обратите внимание, что во втором случае мы передаем значение, вызывая статическую функцию, поэтому пишем имя класса (GameObject — с большой буквы), в то время как в первом мы передаем объект этого класса (gameObject — с маленькой буквы). В противном случае компилятор выдаст ошибку:
error CS0176: Static member `UnityEngine.GameObject.Find(string)’ cannot be accessed with an instance reference, qualify it with a type name instead
что переводится как:
“статический член UnityEngine.GameObject.Find(string) не может быть доступен по ссылки экземпляра (класса), вместо этого определите (вызовите) его с именем типа.”
Сохраним изменения в коде скрипта. Скрипт не требуется убирать со сферы и добавлять к нашему кубу, т.к. назависимо от того, к какому объекту он теперь прикреплен, скрипт будет искать любой объект (на сцене) с именем Box. Нажмем Play и увидим как теперь сфера остается в сцене, а куб пропадает.
Что делать, если нам требуется уничтожить объект не сразу, а спустя какое-то время? Это можно сделать передав значение во 2ой параметр функции Destroy:
Нажмите Play и убедитесь, что куб изчезает через 3и секунды после того, как сцена целиком загрузится.
Дополнительные материалы:
Базовый Урок 05 — Реализация создание объектов
В уроке рассказывается как создавать объекты в сцене в реальном времени (runtime), используя префабы и команду Instantiate (инстанциирование)
Если вы хотите добавлять объекты на сцену, когда сцена уже загружена, то вам требуется использовать скрипты, а точнее команду Instantiate().
Загрузите сцену из Базового урока 03 (Префабы) или создайте такую же новую. В нашей сцене присутствует префаб BouncyBox.
Нажмите Play и убедитесь, что куб по-прежнему падает и отталкивается от поверхностей.
Теперь удалите со сцены экземпляр BouncyBox.
После этого добавьте пустой объект (напоминаю, GameObject->Create Empty или Ctrl + Shift + N в Windows, Cmd + Shift + N в MacOS). Расположите его примерно в том месте, где раньше был экземпляр BouncyBox.
Создадим C#-Скрипт и назовем его Creater. Начнем редактирование скрипта. Заведем открытую (public) переменную типа GameObject и назовем ее thePrefab. Модификатор public требуется указывать, если, например, вы хотите передавать значение переменной через Inspector View. После чего в теле функции Start() создадим еще один GameObject (с именем instance) и проинициализируем его значением с помощью статической функции Instantiate().
Рассмотрим метод Instantiate() подробнее.
Метод клонирует объект original с заданными вектором положения (position) и кватернионом поворота (rotation).
Тип Vector3 является обычным 3х компонентым вектором (аналогично вектору из R 3 ).
Тип Quaternion — кватернион, задающий поворот объекта.
Добавьте скрипт к пустому объекту (c именем GameObject).Напоминаю, поскольку thePrefab объявлен с модификатором public, вы можете задавать его начальное значение прямо в Inspector View (у соответствующего компонента, то есть в нашем случае это Creator у GameObject’а). Перетащите наш префаб в место указания значения (или выберете его из списка, кликнув на кружок справа).
Нажмем Play и увидим, что на сцене появился наш прыгающий кубик.
Но наш кубик прыгает просто вверх и вниз, потому что не имеет начального угла поворота. Выберите GameObject и поверните его под небольшим углом.
Теперь, нажав Play, вы увидите, что кубик падает и отталкивается под различными углами.
Дополнительные материалы:
Базовый Урок 06 — Простой таймер
В данном уроке рассказывается как в Unit при помощи скриптов
создавать простой таймер, используя Time.deltaTime и переменную типа float.
Воспользуемся сценой из предыдущего урока (с пустым игровым объектом,
генерирующим экземпляры префаба, т.е. BouncyBox).
Создадим С#-скрипт и назовем его Timer. Добавим переменную myTimer, и напишем следующий код.
Сохраняем скрипт и переключаемся назад в Unity. Добавим скрипт к объекту GameObject.
Напомню, т.к. myTimer объявлена открытой (public), то в Inspector View вы можете менять ее начальное значение.
Жмем Play. Как только значение myTimer упадет до нуля, в статус баре вы увидите строку GAME OVER. Значение переменной myTimer будет продолжать опускаться (это можно увидеть в Inspector View).
Для того, чтобы переменная myTimer не опускалась ниже нуля, добавим еще одно ветвление в функцию Update(), в итоге мы получаем следующий код:
Нажмем Play и проследим за поведением переменной myTimer. Когда ее значение будет достаточно близким к нулю, то оно перестанет изменяться.
Дополнительные материалы:
Базовый Урок 07 — Основы движения
В уроке рассказывается, как двигать объекты c помощью функции transform.Translate.
Создадим сцену с кубом, камерой и источником света.
Создадим новый C#-скрипт и назовем его Move.
Поскольку движение должно быть непрерывно во времени, то основной код будет располагаться в методе Update(). Вызовем функцию Translate, объекта transform и передадим ей в качестве параметра Vector3(0, 0, 1). Получим следующий код:
Разберемся подробнее в коде. Тут transform — это объект класса Transform, привязанный к нашему объекту. Метод Translate() двигает объект вдоль вектора на расстояние равное его длине (параллельный перенос).
Сохраним наш скрипт и добавим его к нашему кубу. Нажмите Play и увидите как куб стремительно улетает вдоль оси Oz.
Давайте уменьшим скорость движения, например, умножив наш вектор на Time.deltaTime, то есть:
Нажмите Play и убедитесь, что куб начинает двигаться заметно медленнее.
Можно сделать наш скрипт более удобным в использовании, если скорость задать не фиксированным вектором, а через переменную. Заведем public переменную типа float и назовем ее speed. С помощью этой переменной можно будет задавать начальную скорость через Inspector View (по умолчанию она будет равна 5.0f):
Сохраним скрипт и убедимся, что в Inspector View у компонента Move появилась переменная Speed.
Посмотрите, как будет меняться скорость движения нашего объекта в соответствии с заданным начальным значением этой переменной. Например, при Speed = 3 скорость объекта не очень быстрая, но и не медленная.
Примечение: Для выражения Vector3(0.0f, 0.0f, 1.0f) существует короткая (но видимо чуть более медленная, если не прав, прошу поправить) запись Vector3.forward.
Кусок кода из обертки:
Дополнительные материалы:
Базовый Урок 08 — Основы движения с помощью силы.
В уроке рассказывается как c помощью приложения силы двигать физическое тело (Rigidbody).
Если у вас на сцене есть объект с компонентом Rigidbody, то нужно задавать ему движение с помощью приложения силы (передав таким образом все расчеты движения физическому движку игры). В противном случае вы можете начать конфликтовать с физикой объекта. Мы по-прежнему используем сцену из Базового урока 03.
Создадим C#-скрипт и назовем его Force. В методе Start() вызовем метод AddForce() компонента rigidbody (cвязанного с нашим объектом) и передадим ему вектор приложенной силы Vector3(0.0f, 0.0f, power). В классе заведем переменную типа float с именем power и значением, по умолчанию равным 500.0f:
Сохраним скрипт и добавим его к нашему объекту (или префабу). Теперь, если нажать Play, вы увидите как куб падает не вниз а под углом, из-за воздействия силы приложенной вдоль оси Oz.
Перемещение объекта по нажатии кнопки в Unity3d на C#
Доброго времени суток.
Сегодня поговорим про движение объекта по нажатию кнопки на экране в Unity3D. Эта тема очень проста, но часто используется в разного рода играх.
Для начала давайте создадим пустой 3D проект. Открываем Unity, нажимаем кнопку в правом верхнем углу с надписью «New». В поле «Project name» указываем название проекта. В строке «Location» указываем расположение проекта на диске. Ниже поля «Location» ставим флажок «3D» и нажимаем «Create project».
Затем создаем куб который будет заменять нам землю (GameObject->3D Object->Cube). Потом сделаем его более плоским и растянем. Открываем окно «Inspector», выделяем наш куб, в параметре «Transform» пункт «Scale» задаем x:10, y:0.2, z:10. У нас должно получится такое полотно:
Теперь перемещаем камеру на координаты x:0,y:5,z:0. Затем поворачиваем ее на 90 градусов по оси x. Затем нам нужно создать объект который мы будем перемещать. Создаем сферу (GameObject->3D Object->Sphere), задаем параметр «Position» в «Transform» как x:0, y:1, z:0. После этого чтобы лучше видеть нашу сцену ищем на вкладке «Hierarchy» объект с именем «Directional Light» и задаем ему параметр «Rotation» в «Transform» как x:180, y:-30, z:0. Наш проект теперь должен выглядеть вот так:
Теперь нам нужна кнопка, по нажатию которой мы будем определять двигать ли наш объект. Сначала создаем экран на котором будет располагаться наша кнопка (GameObject->UI->Canvas). Следующий этап — создаем кнопку (GameObject->UI->Button). Затем надо написать скрипт для перемещения нашей сферы. В окне «Project» выбираем «Create», а там выбираем C# Script. Далее приведен код:
Сначала создаем переменную нашего объекта для перемещения. Вторая переменная — это расстояние на которое мы будем перемещать объект. Публичный метод «OnButtonDown» отвечает за перемещение при нажатии кнопки. Сначала задаем переменной S значение 1 или 2, после чего двигаем объект по оси X на S расстояние.
Затем выделяем нашу кнопку, в панели «Inspector» в самом низу нажимаем кнопку «Add Component», выбираем в «Scripts» наш код. Далее в компоненте «Button» снизу в пункте «On Click ()» нажимаем «+». Нажимаем на получившееся окно в параметре «On Click ()» в поле, где стоит «None (Object)». В нем выбираем нашу кнопку. Вот как это должно выглядеть:
Потом в нашем параметре «On Click ()» выбираем блок в котором стоит «No Function», внутри него выбираем название нашего кода, а в нем выбираем метод «OnButtonDown()». Теперь когда кнопка настроена переходим к коду. В окне «Inspector» должен отображаться компонент с названием нашего кода. В поле «Sphere» выбираем нашу сферу. Вот что должно получится:
Затем в окне «Game» нажимаем на «Maximize On Play». Теперь нажимаем на кнопку запуска игры. На экране отображается наша кнопка. Если кликнуть по ней, то наша сфера переместится по оси X.
Большое спасибо за прочтение публикации. Надеюсь, Вы приобрели для себя новые знания.
Создание игр-головоломок на Puzzle Script
Puzzle Script — это минималистичный игровой движок для создания головоломок для HTML5, имеет открытые исходники. Примеры готовых игр можно посмотреть здесь.
Часть 1. Создаём первую игру на Puzzle Script.
Puzzle Script — это бесплатная онлайн-программа, которая используется для создания игр-головоломок. Наиболее известен она благодаря созданию головоломок с толканием блоков наподобие моей The Nodus. В этой части мы создадим игру, изучив базовые функции Puzzle Script, а в следующей приступим к программированию.
Загрузка примеров
Для начала давайте рассмотрим несколько примеров. В верхней части экрана откройте список «Load Example» и выберите первый пример под названием «Basic». Теперь нажмите на «Run».
Появится экран игры. Щёлкните внутри его окна и нажмите Enter на клавиатуре.
Попробуйте сыграть в игру. Ваша цель — дотолкать оранжевые ящики до чёрных квадратов-целей. Когда на каждой цели будет стоять по ящику, уровень будет пройден. Можно нажимать на клавиатуре Z для отмены хода или R для перезапуска уровня.
Делаем первую игру
Теперь мы создадим несколько уровней. Один я создам вместе с вами, а другие советую придумать самостоятельно. Нажмите на «Level Editor» в верхнем меню.
Если вы не видите экрана редактора уровней, то нажмите «Run» и запустите игру. Попав на уровень, снова нажмите на кнопку «Level Editor». Это позволит редактировать уровень, на котором вы только что находились.
Создаём новый уровень
Вверху находятся игровые объекты. При левом щелчке отрисовывается выбранный объект. Правый щелчок отрисовывает «фоновый» объект. Левый щелчок на краю карты увеличивает её размер, правый щелчок его уменьшает.
Чтобы пройти уровень, нужно поставить по ящику на каждую из целей, поэтому на каждом уровне должны быть минимум:
Добавляем его в список уровней
Закончив создание уровня, мы добавим его в список уровней. В редакторе уровней нажмите на белую букву S рядом со списком игровых объектов, чтобы сохранить созданный уровень.
Под редактором уровней должно отобразиться сообщение об успешной компиляции и сетка из забавных символов, как показано ниже.
Эти забавные символы обозначают только что созданный нами уровень. Каждый символ представляет отдельный объект. В левой части экрана опуститесь вниз и найдите LEGEND. В легенде представлено объяснение каждого из символов:
. = Background
# = Wall
P = Player
* = Crate
@ = Crate and Target
O = Target
Всё, что находится в левой части экрана — это код игры, разделённый на разные части, такие как OBJECTS или LEGEND. Опуститесь вниз к LEVELS. Здесь мы видим уровни, которые используются в примере.
Чтобы добавить новый уровень, создадим новую пустую строку в нижней части раздела уровней. Затем скопируем символы, сгенерированные для нашего уровня и вставим их туда. Всё, уровень добавлен.
Протестируем его. После создания нового уровня нужно снова нажать кнопку «Run» в верхней части экрана, чтобы перезагрузить игру с новым уровнем. Иногда это не срабатывает, и тогда нужно нажать кнопку «Rebuild», а затем снова нажать «Run».
Сохранение и загрузка игры
Попробуйте создать ещё несколько новых уровней. Когда будете готовы сохранить игру, поднимитесь вверх к началу кода и введите собственное название, имя автора и домашнюю страницу, а затем нажмите на кнопку «Save».
Ограниченное количество сохранений хранится в меню «Load» на используемом вами компьютере. Однако в верхней части экрана существует кнопка «Share». При нажатии на неё генерируется сообщение с двумя веб-ссылками.
Одна из ссылок — исходный код вашего проекта. Вторая — это ссылка на играбельную версию игры, которой можно поделиться с друзьями. Рекомендую периодически создавать новую ссылку на исходный код и сохранять её в какой-нибудь текстовый документ, чтобы у вас оставалась постоянно хранимая версия проекта.
Экспорт игр
Также можно экспортировать игру как файл html5, который вы затем сможете загрузить на игровые порталы, например на itch.io, Kongregate или Newgrounds. Просто нажмите «Export» и загрузите скачанный файл html на игровой портал.
Наш пример проекта можно посмотреть здесь.
Часть 2. Начинаем программировать в Puzzle Script
В этой части мы узнаем, как начать программировать в Puzzle Script.
Откройте пример проекта. Код программы находится в левой части экрана, он разделён на части: Objects, Legend, Sounds и т.д. В разделе Rules задаются правила взаимодействия объектов. Зайдите в него. Здесь должна быть только одна строка кода:
Эта строка означает, что если игрок находится рядом с ящиком и перемещается в его сторону, то игра перемещает игрока и толкает ящик. Чтобы объяснить, как это работает, нужно понять, что код Puzzle Script следует такой структуре:
Это означает следующее:
Puzzle Script проверяет истинность условий слева от стрелки, например, находится ли объект игрока рядом с объектом ящика. Если условие истинно, то мы что-то делаем, например, толкаем ящик.
Примеры условий
Вот пример условия:
Приведённый выше код проверяет, находятся ли рядом друг с другом два ящика.
[ crate | crate | crate ]
Это условие проверяет, находятся ли рядом три ящика.
Данное условие проверяет, находится ли ящик поверх цели, потому что прямой | линии между двумя объектами нет. Объекты могут находиться друг на друге, если они расположены в разных слоях коллизий, которые мы рассмотрим в следующих частях туториала.
Сохраняем равенство
Правила должны быть уравновешены. И проверка условия, и следующее за ним событие должны описываться одинаковым образом. Я покажу, что это значит.
Эта строка кода уничтожает ящик, если рядом с ним находится игрок. Нельзя записать:
потому что условие слева проверяет наличие соседних объектов в двух отдельных пространствах сетки, но событие описывает только одно пространство сетки, которое занимает игрок. Puzzle Script должен знать, что делать с проверяемыми им пространствами. Правильный код для уничтожения ящика должен сообщать следующее:
То есть даже пустые пространства в коде имеют значение. Однако следующая запись допустима:
Так как в условии мы говорим только об одном пространстве сетки, то событие описывает то же пространство сетки.
Как двигать ящики
Вернёмся к исходной строке кода.
Стрелка > подчёркивает движение.
Иногда нам требуется писать комментарии, чтобы помнить, что делает код. Puzzle Script игнорирует комментарии — они предназначены только для пользователя. Чтобы записать комментарий, нужно поместить текст в скобки. Напишем над нашим правилом комментарий, описывающий то, что оно делает:
Теперь под кодом толкания ящика напишем следующее:
Перевёрнутая стрелка означает, что если игрок движется от ящика, то он тянет ящик. Нажмите «Run», чтобы протестировать это действие. У вас должна появиться возможность толкать и тащить ящики. В программировании даже при опечатке в одну букву компьютер может не понять код, поэтому избавляйтесь от всех ошибок. При внесении изменений в код снова нажимайте «Run», чтобы загрузить изменения. Если игра ведёт себя не так, как нужно, попробуйте нажать на «Rebuild», чтобы очистить память программы, а затем нажмите «Run».
Иногда бывает нужно деактивировать строку кода. Просто превратите её в комментарий, чтобы сохранить на будущее. Давайте закомментируем код толкания ящиков, чтобы игрок мог только таскать ящики:
Если это сработало, то закомментируйте код таскания ящиков и попробуйте сделать следующее:
Если игрок отодвигается от ящика, то игрок и ящик переместятся в противоположных направлениях. Стрелки определяют, в каком направлении объект или движется, или будет двигаться. Теперь закомментируем это и попробуем следующее:
Ящик двигается, но игрок остаётся на месте. Поэкспериментируйте с ^ и v (буква v), чтобы посмотреть, как будут двигаться объекты.
Ошибки
Давайте намеренно напишем неверное правило и посмотрим, что произойдёт. Введите такую строку:
Попробуйте запустить программу. Вы должны увидеть такое сообщение:
line 81: In a rule, each pattern to match on the left must have a corresponding pattern on the right of equal length (number of cells).
Обычно Puzzle Script очень хорошо описывает ошибку. Однако иногда Puzzle Script ошибается сам. В таких случаях вам нужно самим пройтись по коду и разобраться, где ошибка.
Ещё немного экспериментов
Попробуйте ещё поэкспериментировать и самостоятельно писать правила. Вот несколько примеров.
В показанном выше примере игрок будет толкать ящик, если они находятся в любом месте одной строки уровня, и игрок движется к ящику.
Этот код меняет игрока и ящик местами.
В этом коде если игрок рядом с ящиком и движется к нему, то игрок перестанет двигаться, но ящик превратится в цель. Самое лучшее в Puzzle Script — простота создания нового и возможность экспериментов.
Часть 3. Создание объектов
Все графические фрагменты в играх на Puzzle Script обозначают объекты. Для создания игр на Puzzle Script необходимо создавать собственные объекты. В этой части я расскажу, как создавать их и добавлять в свой код.
Общие сведения
Откройте пример проекта. Процесс создания объекта состоит из следующих шагов:
Создание объекта
Несколько объектов уже существует. В каждой игре должен быть фоновый объект. Все объекты создаются из сетки размером 5 x 5 пикселей и имеют хотя бы один цвет. Ниже показан фоновый объект.
Background
LIGHTGREEN GREEN
11111
01111
11101
11111
10111
Числа обозначают пиксели изображения. Каждое число соответствует своему цвету. Первый цвет имеет число 0, второй — 1, и так до 9. Может быть до десяти цветов. В нашем случае каждая 1 окрашивает пиксель в светло-зелёный (Light Green), а 0 — в зелёный (Green). Результат выглядит так:
Объекты всегда создаются следующим образом:
Background
LIGHTGREEN
Этот код создаст объект с названием «Background», который будет сеткой 5 x 5 пикселей светло-зелёного цвета. Если не описать сетку изображения, то мы получим блок сплошного цвета, что иногда может быть полезно.
Даём названия объектам
Объекты можно называть как угодно, но название не может начинаться с символа и оно должно быть одним словом без пробелов. Давайте объектам понятные названия, но не переборщите. PlayerStill — хорошее название, PlayerThatIsStandingStill — слишком длинное и многословное.
Цвета
Необходимо объявить цвета, которые вы хотите использовать для объекта, и разделить их пробелом. Puzzle Script имеет заранее заданные цвета:
Название
#51A2BD #ff0000 #ffffff
Коду цвета всегда предшествует символ #.
Добавляем объект в легенду
Создав объект, нужно добавить его в легенду. Легенда выглядит так:
. = Background
# = Wall
P = Player
* = Crate
@ = Crate and Target
O = Target
Каждый символ обозначает объект на уровне. То есть когда мы видим такую сетку символов:
#p.*.##
#.**.##
#..#..#
##. #
##. o#
#######
то на самом деле она описывает наш уровень:
Каждому создаваемому объекту нужно присвоить букву, символ или число, обозначающие этот объект на уровне. Вот так:
Группируем объекты в легенде
Также мы можем создавать в легенде группы объектов. Например, если у нас есть несколько разноцветных ящиков, то можно сделать так:
O = OrangeCrate
B = BlueCrate
G = GreenCrate
Что позволит нам использовать ящики в редакторе уровне. Но для создания кода можно в Legend сгруппировать их вместе, вот так:
Crates = OrangeCrate or GreenCrate or BlueCrate
И всё вместе это будет выглядеть так:
=======
LEGEND
=======
O = OrangeCrate
B = BlueCrate
G = GreenCrate
Crates = OrangeCrate or GreenCrate or BlueCrate
Зачем это делать? Потому что тогда вместо создания таких правил:
можно просто записать:
И этот код будет работать для всей группы объектов.
Кроме того, в разделе Слои коллизий можно будет ссылаться на слой, в котором находится группа, а не вводить каждый отдельный объект.
Слои коллизий
По умолчанию раздел слоёв коллизий выглядит следующим образом:
Background
Target
Player, Wall, Crate
Каждая строка выделяет объекты в свой собственный слой. Порядок расположения слоёв объектов определяет, какие объекты будут поверх других. Объекты в верхней строке будут находиться на нижнем слое, следующая строка будет в слое над ним, и так далее. Фон всегда должен находиться в верхней строке, чтобы располагаться на нижнем слое. Объекты в одном слое не могут находиться друг поверх другого. То есть такого быть не может:
Можно сделать так, чтобы объекты в разных слоях взаимодействовали друг с другом. Например, можно написать:
Эксперимент
Создайте несколько новых объектов. Создайте тип ящиков, которые можно только толкать. Создайте другой ящик, который можно только тащить. Создайте ящик, который исчезает, когда его касаешься. Продолжая эксперименты, вы будете лучше запоминать, как всё делается.
Часть 4. Условия победы
Все любят побеждать. Мы, как игроки, хотим побеждать. В этой части мы узнаем, как запрограммировать условия победы в игре.
Условия победы
Загрузите пример проекта и перейдите к разделу кода Win Conditions. Вы должны увидеть следующее:
All Target on Crate
Игра выиграна, если на каждой цели есть ящик. Если у вас есть 3 ящика и 2 цели, то выиграете, поставив на цели всего 2 ящика. Если поменять местами:
All crate on target
то каждый ящик должен будет находиться на цели.
Условий может быть одно или несколько. В случае множественных условий они должны выполняться все. Например, у нас может быть следующее:
All Target on Crate
All Target2 on Crate2
Если на уровне есть target и target2, то на них, соответственно, crate и crate2. Если на уровне нет ни одного из объектов, необходимых для выполнения определённого условия победы, например, нет target2, то это условие выполняется автоматически.
Различные типы условий победы
Существует несколько разных типов условий победы.
В этом случае победа настаёт тогда, когда на уровне нет ни одного такого объекта.
Вы выигрываете, когда на уровне есть хотя бы один объект указанного типа.
Some Object1 on Object2
Нужно, чтобы хотя бы один из объектов Object1 находился на Object2.
No Object1 On Object2
Эксперимент
Поэкспериментируем с разными условиями победы. Попробуйте создать игру, в которой выигрыш наступает, если все ящики находятся не на целях. Или сделайте игру, в которой нужно уничтожить все ящики определённого типа, но на вашем пути находятся другие толкаемые ящики.
Мой завершённый пример проекта можно посмотреть здесь.
Часть 5. Команда late
В PuzzleScript есть очень полезная команда под названием «late». Порядок происхождения событий в игре важен, и иногда для получения нужных результатов нужен код, который выполняется позже. В этой части я расскажу об использовании команды late.
Зачем она нам понадобится
Откройте пример проекта, после чего вставьте в игру следующий код и запустите её:
Можно ожидать, что как только игрок встанет рядом с целью, цель будет уничтожена, однако этого не происходит. Вместо этого цель исчезает в ходе после того, как рядом с ней встал игрок. Поэтому попробуем другой код:
Как только вы встанете рядом с целью, она исчезнет. Так получилось потому, что всё, обозначенное как late, происходит после выполнения всего остального кода. Иногда такое бывает нужно.
Порядок событий
Вот как выполняется код в Puzzle Script при каждом перемещении.
Если игрок не стоит рядом с ловушкой из кольев, то код продолжает выполнение. Это значит, что важен порядок написания строк кода. Можно применять команду late в некоторых случаях, которые вы узнаете со временем на практике.
Способы использования Late на практике
По моему опыту, лучше всего использовать команду late, когда вы проверяете, находятся ли объекты поверх друг друга или рядом друг с другом, но бывают и другие случаи. Если вы проверяете, находится ли один объект на другом, то событие не зарегистрируется до следующего хода, если только не использовать команду late:
В приведённом выше случае игрок не будет убит ловушкой с кольями до следующего хода после перемещения в ловушку. Чтобы игрок умер мгновенно, просто добавим команду late,
Чтобы перезапустить весь уровень при смерти персонажа, можно сделать следующее:
И уровень перезапустится, когда игрок попадёт в ловушку с кольями.
Готовый пример проекта можно посмотреть здесь.
Часть 6. Работа со звуковыми эффектами
Мы сделали отличную игру на Puzzle Script, но теперь нужно добавить в неё звуки. Как это сделать? Сейчас я вам расскажу!
Генерация звуков
Откройте пример проекта. Добавим в него звуков. Под экраном игры можно увидеть чёрные квадраты с белыми символами. Они используются для генерации звука. Каждый символ генерирует уникальный тип звука, а крестик удаляет созданные звуки. Попробуйте понажимать на квадраты и послушайте звуки.
Жёлтые числа — это уникальные коды, которые нужно копировать и вставлять в те места кода, где необходимы звуки.
Как использовать звуки
Найдя подходящий звук, вы должны вставить его в раздел Sounds кода игры.
Звуки можно использовать несколькими способами. Наиболее простой — создание нового звукового эффекта (sfx). Они должны быть пронумерованы. Мы создаём новый sfx, назначая ему число от 0 до 10 при вставке числового ID звука. В списке Sounds создадим новый sfx под названием sfx0 и присвоим ему сгенерированный звук:
sfx0 36301705
Для использования звука нужно вставить его в правила после события. Давайте прикрепим только что созданный sfx0 к событию уничтожения ящика (событие уже присутствует в примере проекта):
Также звуки можно объявлять для воспроизведения с определёнными событиями, например:
Crate MOVE 36772507
В этом случае звук воспроизведётся при перемещении Crate. Сгенерируем новый звуковой эффект для перетаскивания объектов CratePull и заставим его воспроизводиться при перемещении CratePull:
CratePull MOVE 12735307
Звуки событий нужно объявлять только в разделе Sounds: их не требуется упоминать в правилах.
Список способов воспроизведения звуков
Ниже представлен список различных звуков событий, которые можно использовать, взятый из документации Puzzle Script.
Object Action 541566 — воспроизводится, когда объект во время хода подвергается действию (action).
Object Create 641667 — воспроизводится при создании определённого объекта.
EndGame 5416789 — воспроизводится при завершении игры.
EndLevel 6417822 — воспроизводится после завершения уровня.
Object CantMove 781673 — воспроизводится, когда объект безуспешно пытался сдвинуться в любом направлении.
Player CantMove Down Left 464674 — воспроизводится, когда объект безуспешно пытался сдвинуться вниз или влево.
CloseMessage 344456 — воспроизводится, когда игрок закрывает окно с сообщением.
Object Destroy 187975 — воспроизводится при уничтожении объекта.
Object Move 264567 — воспроизводится, когда объект успешно перемещается в любом направлении.
Object Move Down Left 765432 — воспроизводится, когда объект успешно сдвинулся вниз или влево.
Object Move Horizontal 345367 — воспроизводится, когда объект успешно переместился по горизонтали. Можно также использовать Vertical.
Restart 7865435 — воспроизводится, когда игрок нажимает кнопку перезапуска R.
SFX0 765743 — может быть чем угодно от SFX0 до SFX10. Это особые звуковые события, которые можно выполнять из правил.
ShowMessage 478483 — воспроизводится при отображении сообщения.
StartGame 234626 — воспроизводится в начале новой игры.
Startlevel 765436 — воспроизводится при начале каждого уровня.
TitleScreen 876543 — воспроизводится после загрузки экрана заставки.
Undo 436234 — воспроизводится, когда игрок нажимает клавишу отмены (Z).
Для move и cantmove можно указывать направления, чтобы при перемещении в разных направлениях воспроизводились разные звуки.
Готовый пример проекта находится здесь.
Часть 7. Воспроизведение музыки
Мы научились создавать игры на Puzzle Script, но разве не здорово будет добавить в них музыку? Это возможно, и сейчас я расскажу, как это делается.
Примечание: похоже, на данный момент эта функция в Puzzle Script сломана, так что переходите к следующей части.
Что нужно делать
Откройте заготовку проекта. Музыка работает в Puzzle Script следующим образом: в игру можно вставить ссылку на одно видео с Youtube PuzzleScript автоматически будет воспроизводить все звуки этого видео. Откройте Youtube и выберите любое видео, или используйте следующее:
Чтобы воспроизвести музыку из видео, нам нужно получить уникальный ID видео. Выделенная зелёным часть в строке выше и есть уникальный ID.
Под меткой домашней страницы автора в начале проекта добавьте метку youtube, а после неё уникальный ID видео, например, так:
youtube CKAc3nYEatw
Чтобы убедиться в правильности работы, нажмите на «Share» и щёлкните по ссылке игры (не по ссылке исходного кода). Во время тестирования внутри редактора музыку Puzzle Script воспроизводить невозможно. Если вы хотите, чтобы в игре была музыка, то нужно загрузить её как видео на Youtube и вставить в свой проект уникальный ID. В каждом проекте может быть только одно видео Youtube.
Пример проекта
Пример проекта Puzzle Script можно найти здесь.
Часть 8. Как использовать команду Action
Мы уже знаем, как перемещаться, толкать и тащить блоки, но что если нам нужно сделать что-то при нажатии определённой клавиши, например пробела?
Возможности ввода в PuzzleScript довольно ограничены, в основном это клавиши-стрелки, Z для отмены, R для перезапуска, и мы не можем их изменить. Но движок даёт нам дополнительную клавишу для действий — нажатие на пробел или клавишу X.
Работа с командой Action следует описанному выше формату. Мы использовали базовый формат кода PuzzleScript:
Если условие истинно, то мы выполняем событие. Команда action используется таким же образом, но у неё есть собственные правила. Она выглядит вот так:
Вот пример использования команды Action:
Во-первых, Action всегда является первым словом условия.
Во-вторых, если мы хотим воздействовать на определённый объект в игре, то нужно упомянуть этот объект и в условии, и в событии (если упомянуть другой объект, то программа удалит исходный и заменит его на новый объект, а если объект не указать, то он просто удалится).
Наконец, слово Action нужно использовать только в условии, однако иногда стоит использовать его и в условии, и в событии. Об этом я расскажу ниже.
Проверим показанный выше код в проекте игры. Можно начать с этого примера. Вы увидите, что при нажатии на пробел или X игрок становится ящиком.
Теперь попробуем в примере проекта следующий код:
Сделайте так, чтобы вас со всех сторон окружали ящики, как на изображении выше. Вы заметите, что действие влияет только на один ящик за раз. Не знаю точно, в чём причина, но если вы хотите воздействовать с помощью команды Action на несколько объектов, то нужно указать её и в условии, и в событии.
Заменим код обновлённой версией:
Теперь мы можем толкать все ящики одновременно. Если вам нужно применить действие к нескольким объектам, то поместите Action и в условие, и в событие.
Часть 9. Проверка множественных условий
Давайте научимся проверять несколько условий, например, наличие бомбы И разрушаемого блока.
Откройте пример проекта. Теперь добавьте в него следующий код:
Код соответствует такому формату:
Если условие 1 истинно и условие 2 истинно, то выполняются действие 1 и действие 2. В нашем случае в условии 1 проверяется, находится ли Player на Switch. Если да, то проверяется условие 2, то есть наличие на уровне закрытой двери? Если условие истинно, то объект DoorClosed превращается в объект DoorOpen, открывая дверь.
Допустим, нам нужно, чтобы дверь закрывалась, когда герой уходит с переключателя, потому что мы хотим, чтобы для открывания двери игрок толкнул ящик на переключатель. Можно написать нечто подобное:
Если игрок стоит рядом с переключателем и где-то на уровне есть открытая дверь, то мы закрываем дверь. Наконец, нам нужно, чтобы дверь оставалась открытой, если мы толкнём ящик на переключатель:
Теперь дверь будет оставаться открытой, пока на переключателе стоит ящик.
Готовый пример проекта можно посмотреть здесь.
Часть 10. Создание контрольных точек
Возможно, у вас есть хорошая идея для игры на Puzzle Script, но для неё нужны контрольные точки (чекпоинты), чтобы игрок в случае смерти восстанавливался на них. Как это сделать? Довольно просто, и сейчас я объясню, как.
Создание контрольных точек
Откройте пример проекта. Теперь нам нужно запрограммировать контрольную точку. Для этого достаточно всего одной строки кода:
FlagRed — это контрольная точка. Когда игрок находится поверх флага, этот код создаёт контрольную точку (CHECKPOINT). Если не использовать late, то функция контрольной точки не сработает.
Протестируйте игру. Пройдите над контрольной точкой, а затем немного дальше и нажмите R. Вы должны будете начать с контрольной точки.
Несколько контрольных точек
При наличии нескольких контрольных точек игра использует последнюю, активированную игроком.
Чтобы избежать повторной активации уже использованной контрольной точки, нужно сменить её на другой объект. Для этого создадим в разделе OBJECTS кода под красным флагом его белую копию.
Теперь перепишем эту строку в легенде:
Flag = FlagRed or FlagWhite
Мы можем создать группу объектов. В таком случае Flag будет или FlagRed, или FlagWhite. Пока хотя бы одному из сгруппированных объектов присвоен символ (мы присвоили FlagRed символ F), нам не нужно будет присваивать символы другим объектам группы, при этом получить доступ к ним вы сможете только в коде, но не в редакторе уровней. Затем можно присвоить группе слои коллизий, что мы сделали. Обращение к группе объектов, например, Flag, обращается ко всей группе. Поэтому:
Этот код повлияет и на красный, и на белый флаг.
Изменение объекта флага
Вот как поменять FlagRed на FlagWhite:
Если в конце хода игрок находится на красном флаге, то мы превращаем его в белый. Однако нужно сделать так, чтобы графика флага менялась после создания контрольной точки, потому что код читается сверху вниз. Протестируйте программу.
Изменение второго флага
В проекте есть два флага. Давайте сделаем так, чтобы при активации второго флага старый белый флаг превращался в чёрный, чтобы его нельзя было снова использовать. Запишем следующее:
Код сообщает: если игрок находится на красном флаге и где-то в игре есть белые флаги, то нужно сделать белые флаги чёрными. Так как код считывается сверху вниз, нам нужно выполнить это в следующем порядке:
Если вы не понимаете, почему код должен быть в таком порядке, то попробуйте поменять порядок строк и протестируйте программу. Чтобы решать собственные задачи, вам нужно научиться делать шаг назад и обдумывать то, что делает код. Но я дам вам подсказку — когда вы играете, где находятся красные флаги во время последней строки кода в следующем неправильном примере?
Просмотреть готовый пример проекта можно здесь. Кроме того, я только что продемонстрировал вам простейший способ анимации. В следующей части я расскажу о создании более сложных анимаций, например взрывов.
Часть 11. Анимации
Анимация объектов
Для 2D-анимаций необходимо несколько рисунков объекта, переходящего из одного состояния в другое, например, спрайт бегущего Марио. Он содержит 4 кадра анимации.
Для симуляции перехода одного кадра анимации в другой мы создадим в PuzzleScript несколько объектов, которые будут кадрами анимации, а затем используем код для переключения между ними.
Бомба
Создадим такой объект-бомбу.
Не забудьте добавить его в слои и в легенду.
Explosion2
black yellow grey red
..1..
..1..
.333.
03330
.333.
Explosion3
black yellow grey red
..1..
.333.
33333
33333
.333.
Explosion4
black yellow grey red
.333.
33333
33333
33333
.333.
Explosion5
black yellow grey red
.333.
33333
33.33
33333
.333.
Explosion6
black yellow grey red
.333.
3. 3
3. 3
3. 3
.333.
Правильно будет пронумеровать объекты, чтобы знать, какой кадр анимации нам нужен. После добавления их в слои и в легенду мы можем дописать несколько строк кода.
Использование команды Again
Чтобы анимировать всё вместе, нам нужна команда again. Again означает, что после считывания всего кода PuzzleScript сделает паузу, а затем считает код снова, выполняя все команды again. Её можно использовать для гравитации, скольжения по льду, а в нашем случае и для анимаций. Всё, что нужно — это переписать код следующим образом:
Протестируйте игру. Вы увидите, что вся анимация бомбы воспроизводится сразу. Если на ваш взгляд она слишком медленная или быстрая, то скорость можно изменить. В самом начале текста программы, под homepage напишите следующий код:
Это часть того, что в PuzzleScript называется prelude. Это место, в котором до остальной части кода можно задать дополнительные правила, определяющие поведение игры. Теперь анимация должна воспроизводиться быстрее. Попробуйте изменить число после again_interval и проверьте, что поменялось.
Готовый пример проекта можно посмотреть здесь.
Часть 12. Гравитация
Обычно PuzzleScript используется для создания игр с видом сверху (top down), но на самом деле можно симулировать некоторые элементы сайдскроллеров, хоть и с ограниченными правилами PuzzleScript, то есть они всё равно будут пошаговыми. В этой части я расскажу, как реализовать гравитацию.
Пример проекта
Откройте пример проекта. Я создал простой уровень, в нём есть игрок, ящик на уступе и дверь внизу. Мы хотим сделать так, чтобы когда игрок толкает ящик с уступа, тот падал на землю. Также мы хотим, чтобы сойдя с края, игрок тоже падал на землю.
Падение, этап 1
Вот первая часть кода, который мы будем использовать:
Попробуйте столкнуть ящик с края. Вы заметите, что после перемещения ящик зависает в воздухе, но после ещё одного хода он падает на землю. Тут происходит несколько вещей.
Во-первых, давайте поговорим о ключевом слове down. Добавляя down, мы ограничиваем правило тем, что оно применяется только в направлении «вниз». Именно поэтому ящик сдвигается вниз. Если заменить down на right, то вы увидите, что ящик застрянет в правой стене, как в игре с антигравитацией. Попробуйте так сделать.
Далее сделаем что-нибудь необычное. Вместо того, чтобы проверять, находится ли игрок рядом с определённым объектом (например, ящиком), мы проверяем, находится ли он рядом с обобщённым object. Если посмотреть на легенду в коде примера, то вы увидите, что мы определили object как группу объектов, то есть при каждом использовании слова object мы подразумеваем группу объектов. То есть мы проверяем, есть ли какие-то из этих объектов под игроком. Если нет, то мы приказываем игроку занять это пустое пространство и покинуть предыдущее пространство, из-за слова down следуя в направлении вниз.
Но также можно заметить, что после сталкивания с уступа ящик не падает до следующего хода, и что он мгновенно достигает земли. Чтобы устранить это отложенное падение, можно использовать ключевое слово late:
Но как сделать так, чтобы он падал постепенно, кадр за кадром?
Падение, этап 2
Теперь мы используем ключевое слово random. Перепишем код следующим образом:
Запустите код. Он работает очень похоже на предыдущий код, но одним важным различием. Ящик зависает в воздухе, но при каждом перемещении игрока он падает вниз на одну ячейку. Это происходит благодаря слову random. Строго говоря, random предназначено для создания игр со случайными элементами, но нам оно пригодилось здесь. Оно заставляет выполняться соответствующую строку кода по одному разу за ход. PuzzleScript выполняет за один ход каждое правило сколько может раз, и только потом игрок видит графические изменения. Именно поэтому кажется, что ящик падает на землю мгновенно. Но при использовании слова random мы разрешаем ему падать только на одну ячейку за раз.
Падение, этап 3
Теперь мы добавим ключевое слово again:
Запустите игру. Всё почти идеально. Ящик на какое-то время зависает в воздухе, но если вы ещё раз переместитесь, то он постепенно падает на землю. Мы уже знакомы с ключевым словом again, по сути оно означает, что в конце хода PuzzleScript снова считывает код и пытается выполнить все команды again как отдельный ход, после чего делает паузу, затем повторяет их снова столько раз, сколько сможет. Важно здесь то, что он делает паузы между ходами again, что позволяет нам увидеть падение ящика.
Последний этап
И последний штрих. Чтобы ящик падал до самой земли сразу после выталкивания с края, нам нужно добавить ещё одну строку кода над той, которую мы только что написали:
Ключевое слово moving, использованное в квадратных скобках [] перед player означает, что мы проверяем, движется ли игрок. Это значит, что если игрок движется, то мы приказываем ему продолжать двигаться и запускать команду again. Тогда сразу же сработает всё, что использует ключевое слово again; в нашем случае это анимации падения ящика.
Готовый пример проекта можно посмотреть здесь.
Часть 13. Проверка направления движения
Указание направления
Иногда бывает, что нужно проверить что-то только в одном направлении. Например, вам нужно сделать блоки, которые можно толкать только по горизонтали, или создать утку, которая может ходить только влево.
Как бы то ни было, мы можем указывать, чтобы события происходили только в определённых направлениях.
Откройте PuzzleScript, создайте игру на основе примера Basic и замените его Rules следующим кодом:
Запустите игру и посмотрите, что произойдёт.
Если попытаться пойти влево, то игрок превратится в ящик. Это хороший пример того, как работает указание направлений.
Мы уже привыкли к формату, в котором я объяснял код PuzzleScript:
Если событие истинно, то происходит событие.
Но теперь, когда нам нужно проверять направления, он будет следовать новым правилам:
То есть наш предыдущий код:
проверяет, движется ли игрок влево (Left). Если да, то мы заменяем игрока на объект ящика.
Типы направлений
Можно выбирать из следующих типов направлений:
Часть 14. Создание настраиваемых перемещений
По каким-то причинам в игре может понадобиться настраиваемое перемещение. Утки могут ходить только влево, ящики можно толкать только по горизонтали, и так далее. Сделать это очень просто. Давайте ещё раз взглянем на базовый формат кода PuzzleScript:
Если условие истинно, то происходит событие. Чтобы создать настраиваемое перемещение, нужно сделать следующее:
Вот как будет выглядеть пример:
Загрузите PuzzleScript, откройте пример Basic, вставьте этот код и посмотрите, что произойдёт. Подходите к ящику, вокруг которого нет стен.
Вы увидите, что когда рядом с ящиком находится игрок, то ящик толкается влево. Однако так как ключевого слова Late нет, это происходит в ходе после того, как вы сделали первый шаг к нему.
При указании в Event кроме объекта ещё и направления движения, например Left, PuzzleScript будет пытаться переместить объект в указанном направлении. Именно поэтому ящик, а не игрок движется влево — Left находится рядом с Crate.
Помните этот код из предыдущей части?
Если указать направление движения в условии рядом с объектом, то оно проверяет, двигается ли этот объектов данном направлении. Это важное отличие. Можно переписать это так:
Допустимые настраиваемые перемещения
Настраиваемые движения можно создавать с любым из этих слов:
Часть 15. Проверка ячеек рядом с объектами
Иногда бывает необходимо проверить, что находится рядом с объектом. Сделать это довольно просто. Давайте ещё раз посмотрим на формат кода PuzzleScript:
Чтобы проверить по сторонам от объекта, нам нужно добавить один элемент. Формат выглядит так:
Перед условием мы проверяем, в какой стороне от объекта мы хотим выполнить проверку.
Внутри условия мы предполагаем, что нужно не меньше двух ячеек. Ячейка — это, по сути, любые объекты, находящиеся в одном пространстве и не рядом друг с другом.
[ Это первая ячейка | это вторая ячейка | это третья ячейка ]
Первая ячейка — это объект, стороны которого мы проверяем. Вторая ячейка — это объект, наличие которого мы проверяем. Попробуйте следующие примеры:
Показанный выше код удаляет ящики, если они находятся в квадрате слева от игрока.
Этот код проверяет, находится ли ящик слева от другого ящика. Если да, то ящик, сторона которого проверяется, станет новым объектом игрока.
В приведённом выше коде есть такая же проверка, но объектом игрока становится ящик слева.
В этом коде тоже используется аналогичный паттерн. Ящик непосредственно слева от проверяемого становится игроком, если 3 ящика находятся рядом друг с другом по горизонтали.
Если 3 ящика находятся рядом друг с другом по горизонтали, то самый левый становится игроком.
Если вы протестируете каждый из этих примеров, то начнёте понимать закономерность. Первая ячейка — это объект, который мы проверяем, чтобы увидеть, что находится рядом. Следующие ячейки, от ближайшей до дальней, являются объектами, наличие которых мы проверяем.