[Перевод] Создание игр-головоломок на Puzzle Script

Puzzle Script — это минималистичный игровой движок для создания головоломок для HTML5, имеет открытые исходники. Примеры готовых игр можно посмотреть здесь.

Часть 1. Создаём первую игру на Puzzle Script.


Puzzle Script — это бесплатная онлайн-программа, которая используется для создания игр-головоломок. Наиболее известен она благодаря созданию головоломок с толканием блоков наподобие моей The Nodus. В этой части мы создадим игру, изучив базовые функции Puzzle Script, а в следующей приступим к программированию.

29cad52687d6dac4be118a343acdd4c6.gif


Перейдите на веб-сайт движка. Нажмите Make a Game, чтобы открыть редактор Puzzle Script.

Загрузка примеров


Для начала давайте рассмотрим несколько примеров. В верхней части экрана откройте список «Load Example» и выберите первый пример под названием «Basic». Теперь нажмите на «Run».

5b667f473e13438840c8447d71753f44.png


9b4391ed35f1fecb29379cc35f968a5c.png


Появится экран игры. Щёлкните внутри его окна и нажмите Enter на клавиатуре.

a759be690ae818a3c878adb44fe90d29.png


Попробуйте сыграть в игру. Ваша цель — дотолкать оранжевые ящики до чёрных квадратов-целей. Когда на каждой цели будет стоять по ящику, уровень будет пройден. Можно нажимать на клавиатуре Z для отмены хода или R для перезапуска уровня.

Делаем первую игру


Теперь мы создадим несколько уровней. Один я создам вместе с вами, а другие советую придумать самостоятельно. Нажмите на «Level Editor» в верхнем меню.

6643311c5e2c10fb4fac5766c21bf5be.png


Если вы не видите экрана редактора уровней, то нажмите «Run» и запустите игру. Попав на уровень, снова нажмите на кнопку «Level Editor». Это позволит редактировать уровень, на котором вы только что находились.

Создаём новый уровень


Вверху находятся игровые объекты. При левом щелчке отрисовывается выбранный объект. Правый щелчок отрисовывает «фоновый» объект. Левый щелчок на краю карты увеличивает её размер, правый щелчок его уменьшает.

aa88a62c8f10af011f8ac761b6e7d8a6.gif


Чтобы пройти уровень, нужно поставить по ящику на каждую из целей, поэтому на каждом уровне должны быть минимум:

  • 1 ящик
  • 1 цель
  • 1 игрок


Пока правым щелчком превратим всё в траву. Затем щёлкнем левой клавишей на краю уровня, чтобы сделать его больше, и наконец нарисуем уровень, который похож на показанный ниже.

62afbbf7f15b7a8368740e55afe4e04a.png


Добавляем его в список уровней


Закончив создание уровня, мы добавим его в список уровней. В редакторе уровней нажмите на белую букву S рядом со списком игровых объектов, чтобы сохранить созданный уровень.

3dec4d298ec1ea3c2d15e3fb1383341e.png


Под редактором уровней должно отобразиться сообщение об успешной компиляции и сетка из забавных символов, как показано ниже.

9d68103f3d96a705e188940bea4767a1.png


Эти забавные символы обозначают только что созданный нами уровень. Каждый символ представляет отдельный объект. В левой части экрана опуститесь вниз и найдите LEGEND. В легенде представлено объяснение каждого из символов:

. = Background
# = Wall
P = Player
* = Crate
@ = Crate and Target
O = Target


Всё, что находится в левой части экрана — это код игры, разделённый на разные части, такие как OBJECTS или LEGEND. Опуститесь вниз к LEVELS. Здесь мы видим уровни, которые используются в примере.

a07c515308c753e5ea4aad72c60b35a2.png


Чтобы добавить новый уровень, создадим новую пустую строку в нижней части раздела уровней. Затем скопируем символы, сгенерированные для нашего уровня и вставим их туда. Всё, уровень добавлен.

b799ab86b79fb78def34aa27d274855c.png


Протестируем его. После создания нового уровня нужно снова нажать кнопку «Run» в верхней части экрана, чтобы перезагрузить игру с новым уровнем. Иногда это не срабатывает, и тогда нужно нажать кнопку «Rebuild», а затем снова нажать «Run».

Сохранение и загрузка игры


Попробуйте создать ещё несколько новых уровней. Когда будете готовы сохранить игру, поднимитесь вверх к началу кода и введите собственное название, имя автора и домашнюю страницу, а затем нажмите на кнопку «Save».

a3f0b927e1711b3bbf0c607ffcb019b2.png


a0b362ebbfd305a44fc5f78b3b16bb02.png


Ограниченное количество сохранений хранится в меню «Load» на используемом вами компьютере. Однако в верхней части экрана существует кнопка «Share». При нажатии на неё генерируется сообщение с двумя веб-ссылками.

335876037ebb3769c118a309f90619f4.png


Одна из ссылок — исходный код вашего проекта. Вторая — это ссылка на играбельную версию игры, которой можно поделиться с друзьями. Рекомендую периодически создавать новую ссылку на исходный код и сохранять её в какой-нибудь текстовый документ, чтобы у вас оставалась постоянно хранимая версия проекта.

Экспорт игр


Также можно экспортировать игру как файл html5, который вы затем сможете загрузить на игровые порталы, например на itch.io, Kongregate или Newgrounds. Просто нажмите «Export» и загрузите скачанный файл html на игровой портал.

Наш пример проекта можно посмотреть здесь.

Часть 2. Начинаем программировать в Puzzle Script


В этой части мы узнаем, как начать программировать в Puzzle Script.

29cad52687d6dac4be118a343acdd4c6.gif


Код


Откройте пример проекта. Код программы находится в левой части экрана, он разделён на части: Objects, Legend, Sounds и т.д. В разделе Rules задаются правила взаимодействия объектов. Зайдите в него. Здесь должна быть только одна строка кода:

[ > Player | Crate ] -> [ > Player | > Crate ]


Эта строка означает, что если игрок находится рядом с ящиком и перемещается в его сторону, то игра перемещает игрока и толкает ящик. Чтобы объяснить, как это работает, нужно понять, что код Puzzle Script следует такой структуре:

[ Условие ] -> [ Событие ]


Это означает следующее:

[ Если это условие выполняется ] -> тогда [ Делать это ]


Puzzle Script проверяет истинность условий слева от стрелки, например, находится ли объект игрока рядом с объектом ящика. Если условие истинно, то мы что-то делаем, например, толкаем ящик.

Примеры условий


Вот пример условия:

[ object1 | object2 ]


Данное событие проверяет, находится ли object1 рядом с object2. Можно проверить, находятся ли два объекта рядом друг с другом, поместив между ними прямую | линию, вводимую нажатием shift + \. Условия всегда заключены в квадратные [ ] скобки.

[ crate | crate ]


Приведённый выше код проверяет, находятся ли рядом друг с другом два ящика.

[ crate | crate | crate ]


Это условие проверяет, находятся ли рядом три ящика.

[ crate target ]


Данное условие проверяет, находится ли ящик поверх цели, потому что прямой | линии между двумя объектами нет. Объекты могут находиться друг на друге, если они расположены в разных слоях коллизий, которые мы рассмотрим в следующих частях туториала.

Сохраняем равенство


Правила должны быть уравновешены. И проверка условия, и следующее за ним событие должны описываться одинаковым образом. Я покажу, что это значит.

[ player | crate ] -> [ player | ]


Эта строка кода уничтожает ящик, если рядом с ним находится игрок. Нельзя записать:

[ player | crate ] -> [ player ]


потому что условие слева проверяет наличие соседних объектов в двух отдельных пространствах сетки, но событие описывает только одно пространство сетки, которое занимает игрок. Puzzle Script должен знать, что делать с проверяемыми им пространствами. Правильный код для уничтожения ящика должен сообщать следующее:

[ Если игрок | рядом с ящиком ] -> тогда [ игрок не делает ничего | ящик удаляется ]


[ player | crate ] -> [ player | ]


То есть даже пустые пространства в коде имеют значение. Однако следующая запись допустима:

[ player target ] -> [ player ]


Так как в условии мы говорим только об одном пространстве сетки, то событие описывает то же пространство сетки.

Как двигать ящики


Вернёмся к исходной строке кода.

[ > Player | Crate ] -> [ > Player | > Crate ]


Другими словами:

[ Если игрок двигается к ящику | и находится рядом с ящиком ] -> тогда [ переместить игрока | толкнуть ящик ]


Стрелка > подчёркивает движение.

Иногда нам требуется писать комментарии, чтобы помнить, что делает код. Puzzle Script игнорирует комментарии — они предназначены только для пользователя. Чтобы записать комментарий, нужно поместить текст в скобки. Напишем над нашим правилом комментарий, описывающий то, что оно делает:

(Игрок толкает ящик)
[ > Player | Crate ] -> [ > Player | > Crate ]


Теперь под кодом толкания ящика напишем следующее:

(Игрок тащит ящик)
[ < Player | Crate ] -> [ < Player | < Crate ]


Перевёрнутая стрелка означает, что если игрок движется от ящика, то он тянет ящик. Нажмите «Run», чтобы протестировать это действие. У вас должна появиться возможность толкать и тащить ящики. В программировании даже при опечатке в одну букву компьютер может не понять код, поэтому избавляйтесь от всех ошибок. При внесении изменений в код снова нажимайте «Run», чтобы загрузить изменения. Если игра ведёт себя не так, как нужно, попробуйте нажать на «Rebuild», чтобы очистить память программы, а затем нажмите «Run».

Иногда бывает нужно деактивировать строку кода. Просто превратите её в комментарий, чтобы сохранить на будущее. Давайте закомментируем код толкания ящиков, чтобы игрок мог только таскать ящики:

(Игрок толкает ящик)
([ > Player | Crate ] -> [ > Player | > Crate ])
(Игрок тащит ящик)
[ < Player | Crate ] -> [ < Player | < Crate ]


Если это сработало, то закомментируйте код таскания ящиков и попробуйте сделать следующее:

[ < Player | Crate ] -> [ < Player | > Crate ]


Если игрок отодвигается от ящика, то игрок и ящик переместятся в противоположных направлениях. Стрелки определяют, в каком направлении объект или движется, или будет двигаться. Теперь закомментируем это и попробуем следующее:

[ > Player | Crate ] -> [ Player | > Crate ]


Ящик двигается, но игрок остаётся на месте. Поэкспериментируйте с ^ и v (буква v), чтобы посмотреть, как будут двигаться объекты.

Ошибки


Давайте намеренно напишем неверное правило и посмотрим, что произойдёт. Введите такую строку:

[ < Player | Crate ] -> [ < Player ]


Попробуйте запустить программу. Вы должны увидеть такое сообщение:

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 ошибается сам. В таких случаях вам нужно самим пройтись по коду и разобраться, где ошибка.

Ещё немного экспериментов


Попробуйте ещё поэкспериментировать и самостоятельно писать правила. Вот несколько примеров.

[ > Player | … | Crate ] -> [ > Player | … | > Crate ]


В показанном выше примере игрок будет толкать ящик, если они находятся в любом месте одной строки уровня, и игрок движется к ящику.

[ > Player | Crate ] -> [ Crate | Player ]


Этот код меняет игрока и ящик местами.

[ > Player | Crate ] -> [ Player | Target ]


В этом коде если игрок рядом с ящиком и движется к нему, то игрок перестанет двигаться, но ящик превратится в цель. Самое лучшее в Puzzle Script — простота создания нового и возможность экспериментов.

Часть 3. Создание объектов


Все графические фрагменты в играх на Puzzle Script обозначают объекты. Для создания игр на Puzzle Script необходимо создавать собственные объекты. В этой части я расскажу, как создавать их и добавлять в свой код.

a759be690ae818a3c878adb44fe90d29.png


Общие сведения


Откройте пример проекта. Процесс создания объекта состоит из следующих шагов:

  • Создание его в списке объектов
  • Добавление объекта в легенду
  • Добавление в слой коллизий


Сделав все эти шаги, можно начать использовать объект.

Создание объекта


Несколько объектов уже существует. В каждой игре должен быть фоновый объект. Все объекты создаются из сетки размером 5×5 пикселей и имеют хотя бы один цвет. Ниже показан фоновый объект.

Background
LIGHTGREEN GREEN
11111
01111
11101
11111
10111


Числа обозначают пиксели изображения. Каждое число соответствует своему цвету. Первый цвет имеет число 0, второй — 1, и так до 9. Может быть до десяти цветов. В нашем случае каждая 1 окрашивает пиксель в светло-зелёный (Light Green), а 0 — в зелёный (Green). Результат выглядит так:

1d9f681dd516763462a8541954a320a4.png


Объекты всегда создаются следующим образом:

  • Название
  • Цвета
  • Изображение


Название всегда находится в верхней строке. Цвета всегда во второй строке, а изображение занимает следующие 5 строк, по 5 символов на строку, что формирует сетку 5×5. Или можно сделать следующее:

Background
LIGHTGREEN


Этот код создаст объект с названием «Background», который будет сеткой 5×5 пикселей светло-зелёного цвета. Если не описать сетку изображения, то мы получим блок сплошного цвета, что иногда может быть полезно.

Даём названия объектам


Объекты можно называть как угодно, но название не может начинаться с символа и оно должно быть одним словом без пробелов. Давайте объектам понятные названия, но не переборщите. PlayerStill — хорошее название, PlayerThatIsStandingStill — слишком длинное и многословное.

Цвета


Необходимо объявить цвета, которые вы хотите использовать для объекта, и разделить их пробелом. Puzzle Script имеет заранее заданные цвета:

  • black
  • white
  • grey
  • darkgrey
  • lightgrey
  • gray
  • darkgray
  • lightgray
  • red
  • darkred
  • lightred
  • brown
  • darkbrown
  • lightbrown
  • orange
  • yellow
  • green
  • darkgreen
  • lightgreen
  • blue
  • lightblue
  • darkblue
  • purple
  • pink
  • transparent


Можно также задавать цвета в шестнадцатеричном виде, что даёт нам гораздо больший диапазон цветов. Для выбора шестнадцатеричных цветов можно использовать веб-сайты, например такой. Выберите нужный цвет, а затем перепишите код цвета, указанный над изображением. Шестнадцатеричные коды цветов записываются в Puzzle Script следующим образом:

Название
#51A2BD #ff0000 #ffffff


Коду цвета всегда предшествует символ #.

Добавляем объект в легенду


Создав объект, нужно добавить его в легенду. Легенда выглядит так:

. = Background
# = Wall
P = Player
* = Crate
@ = Crate and Target
O = Target


Каждый символ обозначает объект на уровне. То есть когда мы видим такую сетку символов:

#p.*.##
#.**.##
#..#..#
##....#
##...o#
#######


то на самом деле она описывает наш уровень:

c0c06614b8f1653a46ce44e47ad9288f.png


Каждому создаваемому объекту нужно присвоить букву, символ или число, обозначающие этот объект на уровне. Вот так:

P = player


Группируем объекты в легенде


Также мы можем создавать в легенде группы объектов. Например, если у нас есть несколько разноцветных ящиков, то можно сделать так:

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


Зачем это делать? Потому что тогда вместо создания таких правил:

[ > Player | OrangeCrate ] -> [ > Player | > OrangeCrate ]
[ > Player | BlueCrate] -> [ > Player | > BlueCrate ]
[ > Player | GreenCrate] -> [ > Player | > GreenCrate]


можно просто записать:

[ > Player | Crates ] -> [ > Player | > Crates ]


И этот код будет работать для всей группы объектов.

Кроме того, в разделе Слои коллизий можно будет ссылаться на слой, в котором находится группа, а не вводить каждый отдельный объект.

Слои коллизий


По умолчанию раздел слоёв коллизий выглядит следующим образом:

Background
Target
Player, Wall, Crate


Каждая строка выделяет объекты в свой собственный слой. Порядок расположения слоёв объектов определяет, какие объекты будут поверх других. Объекты в верхней строке будут находиться на нижнем слое, следующая строка будет в слое над ним, и так далее. Фон всегда должен находиться в верхней строке, чтобы располагаться на нижнем слое. Объекты в одном слое не могут находиться друг поверх другого. То есть такого быть не может:

[ player wall ] -> [ player wall ]


Можно сделать так, чтобы объекты в разных слоях взаимодействовали друг с другом. Например, можно написать:

[ > Player | Target ] -> [ > Player | > Target ]


Эксперимент


Создайте несколько новых объектов. Создайте тип ящиков, которые можно только толкать. Создайте другой ящик, который можно только тащить. Создайте ящик, который исчезает, когда его касаешься. Продолжая эксперименты, вы будете лучше запоминать, как всё делается.

Часть 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, то это условие выполняется автоматически.

Различные типы условий победы


Существует несколько разных типов условий победы.

No Object


В этом случае победа настаёт тогда, когда на уровне нет ни одного такого объекта.

Some Object


Вы выигрываете, когда на уровне есть хотя бы один объект указанного типа.

Some Object1 on Object2


Нужно, чтобы хотя бы один из объектов Object1 находился на Object2.

No Object1 On Object2


Это условие противоположно All Target on Crate. В данном случае нам нужно, чтобы все указанные объекты находились отдельно друг от друга, а не друг на друге. Также можно комбинировать друг с другом различные условия победы.

Эксперимент


Поэкспериментируем с разными условиями победы. Попробуйте создать игру, в которой выигрыш наступает, если все ящики находятся не на целях. Или сделайте игру, в которой нужно уничтожить все ящики определённого типа, но на вашем пути находятся другие толкаемые ящики.

Мой завершённый пример проекта можно посмотреть здесь.

Часть 5. Команда late


В PuzzleScript есть очень полезная команда под названием «late». Порядок происхождения событий в игре важен, и иногда для получения нужных результатов нужен код, который выполняется позже. В этой части я расскажу об использовании команды late.

Зачем она нам понадобится


Откройте пример проекта, после чего вставьте в игру следующий код и запустите её:

[ player | target ] -> [ player | ]


Можно ожидать, что как только игрок встанет рядом с целью, цель будет уничтожена, однако этого не происходит. Вместо этого цель исчезает в ходе после того, как рядом с ней встал игрок. Поэтому попробуем другой код:

late [ player | target ] -> [ player | ]


Как только вы встанете рядом с целью, она исчезнет. Так получилось потому, что всё, обозначенное как late, происходит после выполнения всего остального кода. Иногда такое бывает нужно.

Порядок событий


Вот как выполняется код в Puzzle Script при каждом перемещении.

  1. Puzzle Script обнаруживает, что игрок хочет переместиться
  2. По возможности правила считываются и выполняются сверху вниз
  3. Игрок перемещается, если это возможно
  4. Применяются Late-правила


Компьютер начинает с верхней строки кода и считывает вниз, строка за строкой. проверяя каждое условие. Поэтому когда вы пытаетесь переместиться, Puzzle Script считывает все правила и проверяет, истинны ли условия, и если это так, то он что-то делает. Например, первая строка может быть такой:

[ player | spikeTrap ] -> [ | spikeTrap ]


Если игрок не стоит рядом с ловушкой из кольев, то код продолжает выполнение. Это значит, что важен порядок написания строк кода. Можно применять команду late в некоторых случаях, которые вы узнаете со временем на практике.

Способы использования Late на практике


По моему опыту, лучше всего использовать команду late, когда вы проверяете, находятся ли объекты поверх друг друга или рядом друг с другом, но бывают и другие случаи. Если вы проверяете, находится ли один объект на другом, то событие не зарегистрируется до следующего хода, если только не использовать команду late:

[ player spikeTrap ] -> [ spikeTrap ]


В приведённом выше случае игрок не будет убит ловушкой с кольями до следующего хода после перемещения в ловушку. Чтобы игрок умер мгновенно, просто добавим команду late,

late [ player spikeTrap ] -> [ spikeTrap ]


Чтобы перезапустить весь уровень при смерти персонажа, можно сделать следующее:

late [ player spikeTrap ] -> restart


И уровень перезапустится, когда игрок попадёт в ловушку с кольями.

Готовый пример проекта можно посмотреть здесь.

Часть 6. Работа со звуковыми эффектами


Мы сделали отличную игру на Puzzle Script, но теперь нужно добавить в неё звуки. Как это сделать? Сейчас я вам расскажу!

Генерация звуков


Откройте пример проекта. Добавим в него звуков. Под экраном игры можно увидеть чёрные квадраты с белыми символами. Они используются для генерации звука. Каждый символ генерирует уникальный тип звука, а крестик удаляет созданные звуки. Попробуйте понажимать на квадраты и послушайте звуки.

b96a21bb2a86c3cb300a8840cc601162.png


Жёлтые числа — это уникальные коды, которые нужно копировать и вставлять в те места кода, где необходимы звуки.

Как использовать звуки


Найдя подходящий звук, вы должны вставить его в раздел Sounds кода игры.

243881847507555bc9bb470dd89c0a23.png


Звуки можно использовать несколькими способами. Наиболее простой — создание нового звукового эффекта (sfx). Они должны быть пронумерованы. Мы создаём новый sfx, назначая ему число от 0 до 10 при вставке числового ID звука. В списке Sounds создадим новый sfx под названием sfx0 и присвоим ему сгенерированный звук:

sfx0 36301705


Для использования звука нужно вставить его в правила после события. Давайте прикрепим только что созданный sfx0 к событию уничтожения ящика (событие уже присутствует в примере проекта):

(The player destroys a crate)
[ > Player | CrateVanish ] -> [ Player | ] 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 и выберите любое видео, или используйте следующее:

youtube.com/watch? v=CKAc3nYEatw

Чтобы воспроизвести музыку из видео, нам нужно получить уникальный ID видео. Выделенная зелёным часть в строке выше и есть уникальный ID.

08081506423f3c795d47f0f242e82ed7.png


Под меткой домашней страницы автора в начале проекта добавьте метку youtube, а после неё уникальный ID видео, например, так:

youtube CKAc3nYEatw

Чтобы убедиться в правильности работы, нажмите на «Share» и щёлкните по ссылке игры (не по ссылке исходного кода). Во время тестирования внутри редактора музыку Puzzle Script воспроизводить невозможно. Если вы хотите, чтобы в игре была музыка, то нужно загрузить её как видео на Youtube и вставить в свой проект уникальный ID. В каждом проекте может быть только одно видео Youtube.

Пример проекта


Пример проекта Puzzle Script можно найти здесь.

Часть 8. Как использовать команду Action


Мы уже знаем, как перемещаться, толкать и тащить блоки, но что если нам нужно сделать что-то при нажатии определённой клавиши, например пробела?

Возможности ввода в PuzzleScript довольно ограничены, в основном это клавиши-стрелки, Z для отмены, R для перезапуска, и мы не можем их изменить. Но движок даёт нам дополнительную клавишу для действий — нажатие на пробел или клавишу X.

Работа с командой Action следует описанному выше формату. Мы использовали базовый формат кода PuzzleScript:

[ Условие ] -> [ Событие ]


Если условие истинно, то мы выполняем событие. Команда action используется таким же образом, но у неё есть собственные правила. Она выглядит вот так:

[ Action дополнительные условия ] -> [ Событие ]


Вот пример использования команды Action:

[ Action Player ] -> [ Crate ]


Во-первых, Action всегда является первым словом условия.

Во-вторых, если мы хотим воздействовать на определённый объект в игре, то нужно упомянуть этот объект и в условии, и в событии (если упомянуть другой объект, то программа удалит исходный и заменит его на новый объект, а если объект не указать, то он просто удалится).

Наконец, слово Action нужно использовать только в условии, однако иногда стоит использовать его и в условии, и в событии. Об этом я расскажу ниже.

Проверим показанный выше код в проекте игры. Можно начать с этого примера. Вы увидите, что при нажатии на пробел или X игрок становится ящиком.

Условие сообщает [ Если мы нажимаем клавишу Action и на уровне есть объект Player ] → тогда [ заменить объект игрока на ящик ]

Теперь попробуем в примере проекта следующий код:

[ Action Player | Crate ] -> [ Player | > Crate ]


5ef8d517e36f7dd7c14eaac6c51686a4.gif

Сделайте так, чтобы вас со всех сторон окружали ящики, как на изображении выше. Вы заметите, что действие влияет только на один ящик за раз. Не знаю точно, в чём причина, но если вы хотите воздействовать с помощью команды Action на несколько объектов, то нужно указать её и в условии, и в событии.

Заменим код обновлённой версией:

[ Action Player | Crate ] -> [ Action Player | > Crate ]


40487ba4ad627d53061ae5c57e97b09f.gif


Теперь мы можем толкать все ящики одновременно. Если вам нужно применить действие к нескольким объектам, то поместите Action и в условие, и в событие.

Часть 9. Проверка множественных условий


Давайте научимся проверять несколько условий, например, наличие бомбы И разрушаемого блока.

f7f004a1ef6661dffbc879351b82513d.png


Откройте пример проекта. Теперь добавьте в него следующий код:

late [Player Switch][DoorClosed] -> [Player Switch][DoorOpen]


Код соответствует такому формату:

[ Условие 1 ] [ Условие 2 ] -> [ Действие 1 ] [ Действие 2 ]


Если условие 1 истинно и условие 2 истинно, то выполняются действие 1 и действие 2. В нашем случае в условии 1 проверяется, находится ли Player на Switch. Если да, то проверяется условие 2, то есть наличие на уровне закрытой двери? Если условие истинно, то объект DoorClosed превращается в объект DoorOpen, открывая дверь.

11088afdfd4ff8dedd37d4da01ae7566.gif


Допустим, нам нужно, чтобы дверь закрывалась, когда герой уходит с переключателя, потому что мы хотим, чтобы для открывания двери игрок толкнул ящик на переключатель. Можно написать нечто подобное:

late [Player | Switch][DoorOpen] -> [Player | Switch][DoorClosed]


Если игрок стоит рядом с переключателем и где-то на уровне есть открытая дверь, то мы закрываем дверь. Наконец, нам нужно, чтобы дверь оставалась открытой, если мы толкнём ящик на переключатель:

late [Crate Switch][DoorClosed] -> [Crate Switch][DoorOpen]


Теперь дверь будет оставаться открытой, пока на переключателе стоит ящик.

Готовый пример проекта можно посмотреть здесь.

Часть 10. Создание контрольных точек


Возможно, у вас есть хорошая идея для игры на Puzzle Script, но для неё нужны контрольные точки (чекпоинты), чтобы игрок в случае смерти восстанавливался на них. Как это сделать? Довольно просто, и сейчас я объясню, как.

5da7b56bd4c1a55d0c9f8e1f49d7a7f5.gif


Создание контрольных точек


Откройте пример проекта. Теперь нам нужно запрограммировать контрольную точку. Для этого достаточно всего одной строки кода:

late [ Player FlagRed ] -> CHECKPOINT


FlagRed — это контрольная точка. Когда игрок находится поверх флага, этот код создаёт контрольную точку (CHECKPOINT). Если не использовать late, то функция контрольной точки не сработает.

Протестируйте игру. Пройдите над контрольной точкой, а затем немного дальше и нажмите R. Вы должны будете начать с контрольной точки.

Несколько контрольных

© Habrahabr.ru