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

Автор: admin от 8-11-2018, 17:05, посмотрело: 29

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



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



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



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

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

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



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



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



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



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

Код



Откройте пример проекта. Код программы находится в левой части экрана, он разделён на части: 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 ] [ 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 необходимо создавать собственные объекты. В этой части я расскажу, как создавать их и добавлять в свой код.



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

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



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




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

  • Добавление объекта в легенду

  • Добавление в слой коллизий



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



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



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



Background

LIGHTGREEN GREEN

11111

01111

11101

11111

10111


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



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

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




  • Название

  • Цвета

  • Изображение



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



Background

LIGHTGREEN


Этот код создаст объект с названием «Background», который будет сеткой 5 x 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#

#######


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



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

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



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, но теперь нужно добавить в неё звуки. Как это сделать? Сейчас я вам расскажу!



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



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



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

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



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



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



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

Звуки можно использовать несколькими способами. Наиболее простой — создание нового звукового эффекта (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.



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

Под меткой домашней страницы автора в начале проекта добавьте метку 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 ]


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



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



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



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


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

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



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



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



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

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



late [Player Switch][DoorClosed] [Player Switch][DoorOpen]


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



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


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



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

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



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


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



late [Crate Switch][DoorClosed] [Crate Switch][DoorOpen]


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



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



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



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



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

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



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



late [ Player FlagRed ] CHECKPOINT


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



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



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



При наличии нескольких контрольных точек игра использует последнюю, активированную игроком.



Чтобы избежать повторной активации уже использованной контрольной точки, нужно сменить её на другой объект. Для этого создадим в разделе OBJECTS кода под красным флагом его белую копию.



FlagWhite

White Orange

.1…

.00..

.000.

.1…

.1…


Теперь перепишем эту строку в легенде:



Flag = FlagRed or FlagWhite


Мы можем создать группу объектов. В таком случае Flag будет или FlagRed, или FlagWhite. Пока хотя бы одному из сгруппированных объектов присвоен символ (мы присвоили FlagRed символ F), нам не нужно будет присваивать символы другим объектам группы, при этом получить доступ к ним вы сможете только в коде, но не в редакторе уровней. Затем можно присвоить группе слои коллизий, что мы сделали. Обращение к группе объектов, например, Flag, обращается ко всей группе. Поэтому:



[ > Player | Flag ] [ > Player | ]


Этот код повлияет и на красный, и на белый флаг.



Изменение объекта флага



Вот как поменять FlagRed на FlagWhite:



late [ Player FlagRed ] [ Player FlagWhite ]


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



Изменение второго флага



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



late [ Player FlagRed ][ FlagWhite] [ Player FlagRed ][FlagBlack]


Код сообщает: если игрок находится на красном флаге и где-то в игре есть белые флаги, то нужно сделать белые флаги чёрными. Так как код считывается сверху вниз, нам нужно выполнить это в следующем порядке:



late [ Player FlagRed ] CHECKPOINT

late [ Player FlagRed ][ FlagWhite] [ Player FlagRed ][FlagBlack]

late [ Player FlagRed ] [ Player FlagWhite ]


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



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

[ > Crate | Flag ] [ Crate | Flag ]

late [ Player FlagRed ] CHECKPOINT

late [ Player FlagRed ] [ Player FlagWhite ]

late [ Player FlagRed ][ FlagWhite] [ Player FlagRed ][FlagBlack]


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



Часть 11. Анимации



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



Откройте пример проекта. Мы создадим бомбу и серию кадров взрыва, а затем анимируем их.



Анимация объектов



Для 2D-анимаций необходимо несколько рисунков объекта, переходящего из одного состояния в другое, например, спрайт бегущего Марио. Он содержит 4 кадра анимации.



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

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



Бомба



Создадим такой объект-бомбу.



Bomb

black yellow grey

..1..

..1..

.000.

00020

.000.


Не забудьте добавить его в слои и в легенду.



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



Explosion1

black yellow grey red

..1..

..1..

.000.

00320

.000.



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.



Explosion7

black yellow grey red

.....

.....

.....

.....

.....


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



[Explosion7] []

[Explosion6] [Explosion7]

[Explosion5] [Explosion6]

[Explosion4] [Explosion5]

[Explosion3] [Explosion4]

[Explosion2] [Explosion3]

[Explosion1] [Explosion2]

[Bomb] [Explosion1]


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



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



Использование команды Again



Чтобы анимировать всё вместе, нам нужна команда again. Again означает, что после считывания всего кода PuzzleScript сделает паузу, а затем считает код снова, выполняя все команды again. Её можно использовать для гравитации, скольжения по льду, а в нашем случае и для анимаций. Всё, что нужно — это переписать код следующим образом:



[Explosion7] []

[Explosion6] [Explosion7] again

[Explosion5] [Explosion6] again

[Explosion4] [Explosion5] again

[Explosion3] [Explosion4] again

[Explosion2] [Explosion3] again

[Explosion1] [Explosion2] again

[Bomb] [Explosion1] again


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



again_interval 0.1


Это часть того, что в PuzzleScript называется prelude. Это место, в котором до остальной части кода можно задать дополнительные правила, определяющие поведение игры. Теперь анимация должна воспроизводиться быстрее. Попробуйте изменить число после again_interval и проверьте, что поменялось.



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



Часть 12. Гравитация



Обычно PuzzleScript используется для создания игр с видом сверху (top down), но на самом деле можно симулировать некоторые элементы сайдскроллеров, хоть и с ограниченными правилами PuzzleScript, то есть они всё равно будут пошаговыми. В этой части я расскажу, как реализовать гравитацию.



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



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



Падение, этап 1



Вот первая часть кода, который мы будем использовать:



down [ Player | no Object ] [ | Player ]

down [ Crate | no Object no Player ] [ | Crate ]


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



Во-первых, давайте поговорим о ключевом слове down. Добавляя down, мы ограничиваем правило тем, что оно применяется только в направлении «вниз». Именно поэтому ящик сдвигается вниз. Если заменить down на right, то вы увидите, что ящик застрянет в правой стене, как в игре с антигравитацией. Попробуйте так сделать.



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



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



late down [ Player | no Object ] [ | Player ]

late down [ Crate | no Object no Player ] [ | Crate ]


Но как сделать так, чтобы он падал постепенно, кадр за кадром?



Падение, этап 2



Теперь мы используем ключевое слово random. Перепишем код следующим образом:



random down [ Player | no Object ] [ | Player ]

random down [ Crate | no Object no Player ] [ | Crate ]


Запустите код. Он работает очень похоже на предыдущий код, но одним важным различием. Ящик зависает в воздухе, но при каждом перемещении игрока он падает вниз на одну ячейку. Это происходит благодаря слову random. Строго говоря, random предназначено для создания игр со случайными элементами, но нам оно пригодилось здесь. Оно заставляет выполняться соответствующую строку кода по одному разу за ход. PuzzleScript выполняет за один ход каждое правило сколько может раз, и только потом игрок видит графические изменения. Именно поэтому кажется, что ящик падает на землю мгновенно. Но при использовании слова random мы разрешаем ему падать только на одну ячейку за раз.



Падение, этап 3



Теперь мы добавим ключевое слово again:



random down [ Player | no Object ] [ | Player ] again

random down [ Crate | no Object no Player ] [ | Crate ] again


Запустите игру. Всё почти идеально. Ящик на какое-то время зависает в воздухе, но если вы ещё раз переместитесь, то он постепенно падает на землю. Мы уже знакомы с ключевым словом again, по сути оно означает, что в конце хода PuzzleScript снова считывает код и пытается выполнить все команды again как отдельный ход, после чего делает паузу, затем повторяет их снова столько раз, сколько сможет. Важно здесь то, что он делает паузы между ходами again, что позволяет нам увидеть падение ящика.


Источник: Хабр / Интересные публикации

Категория: Game Development

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

Добавление комментария

Имя:*
E-Mail:
Комментарий:
Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
Введите два слова, показанных на изображении: *