Содержание

Назад: Предметы

Порядок работы интерпретатора

Несмотря на то, что эта статья обросла некоторыми подробностями, она всё ещё требует серьёзной редактуры, упрощения и расширения. Так что пока что это всё ещё черновой вариант.

Эта статья подробно рассказывает о порядке работы интерпретатора (плеера) QSP. Она может показаться вам довольно сложной, но читать её всю не обязательно. Вернитесь к ней, когда у вас возникнут сложности в понимании того, как ведёт себя плеер. А пока достаточно ознакомиться с общими принципами:

Ниже по тексту будут использоваться следующие определения:

Запуск игры

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

Когда мы открываем игру в плеере (интерпретаторе), автоматически запускается чтение самой первой локации в файле (далее Стартовая локация), как если бы на неё был совершён переход с помощью оператора GOTO. То есть:

Если на Стартовой локации в переменную $COUNTER было помещено название локации-счётчика, примерно через равные промежутки времени (по умолчанию раз в пол секунды) плеер будет вызывать локацию-счётчик (см. "Служебные локации").

Выполнение кода

Код в QSP всегда выполняется последовательно, команда за командой. Чтение команд происходит сверху вниз и справа налево:

*pl "Первая команда"
*pl "Вторая команда"
*pl "Третья команда"

*pl "Четвёртая команда" & *pl "Пятая команда" & *pl "Шестая команда"

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

Например, если написано невыполнимое условие, команда никогда не будет выполнена:

if 5>6:
  *pl "Данная команда никогда не будет выполнена"
end

Команды, стоящие после GOTO или XGOTO, так же никогда не будут выполнены:

*pl "Текст на локации" & ! этот текст будет виден на локации всегда
act "Переход по XGOTO":
  *pl "Этот текст виден благодаря тому, что вы перешли с помощью XGOTO"
  xgoto $curloc & ! переходим на текущую локацию
  *pl "А эта команда никогда не будет выполнена"
end

act "Переход по GOTO":
  *pl "Эта команда будет выполнена"
  ! но при переходе по GOTO Окно основного описания очистится,
  ! так что эту строчку вы всё равно не увидите.
  goto $curloc & ! переходим на текущую локацию
  *pl "А эта команда никогда не будет выполнена"
end

Код действий (ACT) не выполняется сразу, а "прикрепляется" к этим действиям. Он будет выполнен только тогда, когда игрок нажмёт на соответствующее действие.

example=12 & ! присваиваем переменной число 12
! создаём действие
act "Вывести значение переменной example":
  *pl example
end
example=37 & ! меняем значение в переменной

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

usehtml=1 & ! включаем режим распознавание HTML
example=12
! выводим на экран гиперссылку с кодом
*pl "<a href='EXEC:*pl example'>Вывести значение переменной example</a>"
example=37

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

яблоки = 23
! Сначала в строку подставится значение,
! потом строка выведется на экран:
*pl "Яблок в кармане: <<яблоки>>."

Переход на новую локацию

Переход на новую локацию может осуществляться с помощью двух операторов GOTO и XGOTO. Различие в их работе заключается в следующем:

В остальном работа этих операторов схожа:

Если в переменную $COUNTER было помещено название локации-счётчика, примерно через равные промежутки времени (по умолчанию раз в пол секунды) плеер будет вызывать локацию-счётчик (см. "Служебные локации").

P.S.: "Переход на новую локацию" — это устоявшееся название события. Технически более правильно называть такие переходы просто "Переход на локацию", поскольку мы можем переходить не только на новые, но и на текущую локацию:

"Счёт: <<count>>"
act "Обновить":
  count+=1
  goto $curloc & ! перезаходим на текущую локацию
end

Поэтому, столкнувшись с выражением "Переход на новую локацию" помните, что оно может значить в том числе и переход на текущую локацию.

Вызов локации

Вызов локации может быть выполнен напрямую через оператор **GOSUB** или функцию **FUNC** или в привязке к какому-либо событию.

При вызове:

Дополнительно, при вызове с помощью оператора GOSUB, или функции FUNC, а так же с помощью оператора **MENU**, осуществляется возврат к тому коду, из которого был осуществлён вызов, и продолжается выполнение этого кода. Например, если локация была вызвана из действия, то произойдёт возврат к выполнению кода действия.

act "Действие с вызовом локации":
  *pl "Выводим текст до вызова"
  gosub 'foo' & ! вызываем локацию foo
  *pl "Продолжаем выполнять код после вызова локации foo"
end

Более подробно работа оператора GOSUB и функции FUNC освещена в разделе "Пользовтальские функции и процедуры".

О работе оператора MENU более подробно можно почитать в разделе "Меню".

Обработка событий

События, если смотреть на это понятие с точки зрения работы плеера, — это некое изменение состояния в написанной нами игре. Например, у нас все предметы были не выделены, и вот игрок щёлкает мышью по одному из предметов, и предмет оказывается выделен. То есть предмет изменил своё состояние с "не выделен", на "выделен". Это и есть событие выделения предмета.

Конечно, мы могли бы и сами отслеживать некоторые события, например, с помощью локации-счётчика постоянно проверять, какое значение возвращает нам функция $SELOBJ, и в момент, когда функция изменяет своё значение с одного на другое, мы точно знаем, что произошло выделение нового предмета, или иными словами: событие "Выделение предмета". Однако, для нас это, во-первых, лишний код, а, во-вторых, очень неудобный и неточный инструмент по отслеживанию событий, поскольку локация-счётчик имеет ряд ограничений и на скорость выполнения, и на очерёдность. Мы хотим, чтобы миллисекунда в миллисекунду мы знали, что какое-то событие произошло, и чтобы при этом мы могли выполнить какой-либо код.

Именно для этого в QSP введены специальные служебные локации: локации-обработчики событий (и локация-счётчик).

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

$counter = 'счётчик' & ! назначаем локацию-счётчик
$onobjsel = 'onClick' & ! назначаем локацию-обработчик события "Выделение предмета"
$usercom = 'debugger' & ! назначаем локацию-обработчик события "Нажатие клавиши ввода в Поле ввода"

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

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

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

$counter = '' & ! отключаем локацию-счётчик
$onobjsel = '' & ! отключаем локацию-обработчик события "Выделение предмета"

Процессы в настоящем времени

Если была назначена локация-счётчик, то с приблизительно равной периодичностью будет происходить вызов указанной локации-счётчика. По умолчанию локация-счётчик вызывается 2 раза в секунду, то есть каждые 500 миллисекунд — это значение можно изменять с помощью оператора SETTIMER.

settimer 100 & ! устанавливаем период обращения к локации-счётчику в 100 мс
$counter = 'отсчёт_времени' & ! плеер будет вызывать локацию **отсчёт времени** примерно 10 раз в секунду

Так же с заданной периодичностью (по умолчанию 2 раза в секунду) происходит полное обновление интерфейса: шрифт и цвета, заданные с помощью системных переменных.

Подробнее о локации-счётчике и создании игровых событий в реальном времени читайте в статье "Реальное время".

Вперёд: Переменные