Инструменты пользователя

Инструменты сайта


help:principle

Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

Both sides previous revision Предыдущая версия
Следущая версия
Предыдущая версия
help:principle [2015/04/05 12:29]
190.75.187.96 GetE7U0R35VL
help:principle [2024/10/14 07:28] (текущий)
aleks_versus проба обновления до 5.9.0
Строка 1: Строка 1:
-AKAIK <a href="http://gxrvjhrm.com">yov'ue</agot the answer in one!+[[help:​objs|Назад:​ Предметы]] 
 + 
 +====== Порядок работы интерпретатора ====== 
 + 
 +**Несмотря на то, что эта статья обросла некоторыми подробностями,​ она всё ещё требует серьёзной редактуры,​ упрощения и расширения. Так что пока что это всё ещё черновой вариант.** 
 + 
 +Эта статья подробно рассказывает о порядке работы интерпретатора (плеера) **QSP**. Она может показаться вам довольно сложной,​ но читать её всю не обязательно. Вернитесь к ней, когда у вас возникнут сложности в понимании того, как ведёт себя плеер. А пока достаточно ознакомиться с общими принципами:​ 
 + 
 +  * При запуске игры автоматически воспроизводится только самая первая в игре локация. На остальные локации нужно осуществлять переходы с помощью **''​GOTO''​** или **''​XGOTO''​**,​ или вызывать их с помощью **''​GOSUB''​**,​ **''​FUNC''​**,​ или иным предусмотренным плеером способом. 
 +  * Код действий "​прикрепляется"​ к действию и не выполняется,​ пока игрок не нажмёт на действие. 
 +  * Все команды выполняются последовательно одна за другой,​ и никогда не выполняются одновременно. 
 + 
 +Ниже по тексту будут использоваться следующие определения:​ 
 + 
 +  * **Переход на локацию** — это событие в игре, которое происходит при обращении к локации с помощью операторов **''​GOTO''​** или **''​XGOTO''​**. При этом локация становится "​активной",​ или "​текущей"​. Функция **''​$CURLOC''​** возвращает название локации,​ на которую был совершён переход,​ а массив **''​ARGS[]''​** этой локации сохраняет свои значения,​ пока снова не будет осуществлён переход на локацию (другую,​ или ту же самую). После добавления текста из поля "​Базовое описание"​ в Окно основного описания,​ действий из поля "​**Базовые действия**"​ в **Окно действий**,​ и выполнения кода из поля "​**Выполнить при посещении**",​ плеер "​останавливается"​ и ожидает участия игрока,​ при этом локация,​ на которую был осуществлён переход,​ остаётся "​активной"​ ("​текущей"​),​ т.е. функция **''​$CURLOC''​** в любой момент может вернуть название этой локации,​ а массив ''​ARGS[]''​ сохраняет значения.\\ Для переходов существуют только два оператора (подробнее см. статью [[help:​goto|"​Переходы"​]]):​ 
 +    * **''​GOTO''​** — осуществляет переход на указанную локацию с автоматической очисткой **Окна основного описания** и **Окна действий**. 
 +    * **''​XGOTO''​** — осуществляет переход на указанную локацию с автоматической очисткой **Окна действий**. **Окно основного описания** НЕ очищается. 
 +  * **Вызов локации** — это событие в игре, которое происходит при обращении к локации с помощью оператора **''​GOSUB''​**,​ функции **''​FUNC''​**,​ или в связи с выполнением другого события (например,​ "​**Выделение предмета**",​ "​**Загрузка сохранения**",​ "​**Ввод в поле ввода**",​ "​**Выбор пункта меню**"​). В отличие от **перехода на локацию**,​ при **вызове** локация не становится "​активной"​ ("​текущей"​),​ т.е. функция **''​$CURLOC''​** не возвращает название этой локации,​ а массив **''​ARGS[]''​** сохраняет свои значения только пока выполняется код локации. После выполнения кода локации,​ продолжается выполнение того блока кода, который выполнялся до вызова. Например,​ если локация была **вызвана** из действия,​ то после выполнения её кода, продолжится выполнение кода действия,​ при этом в массив **''​ARGS[]''​** внутри действия не попадут значения массива **''​ARGS[]''​** из вызванной локации. При вызове локации в **Окно основного описания** добавляется текст из поля "​**Базовое описание**"​ локации,​ в **Окно действий** добавляются действия из поля "​**Базовые действия**"​ локации,​ и выполняется код из поля "​**Выполнить при посещении**"​ локации. Очистка окон при вызове локации НЕ ПРОИСХОДИТ. <sxh qsp> 
 +act "​Действие с вызовом локации":​ 
 +  *pl "​Выводим текст до вызова"​ 
 +  gosub '​foo'​ & ! вызываем локацию foo 
 +  *pl "​Продолжаем выполнять код после вызова локации foo" 
 +end 
 +</​sxh>​ Вызвать локацию можно разными способами:​ 
 +    * Оператор **''​GOSUB''​** вызывает локацию без возвращения результата (подробнее в статье [[help:​organizing|"​Пользовательские функции и процедуры"​]]). 
 +    * Оператор **FUNC** вызывает локацию с возвращением результата (подробнее в статье [[help:​organizing|"​Пользовательские функции и процедуры"​]]). 
 +    * Нажатием пункта всплывающего меню (см. статью [[help:​menu|"​Всплывающее меню"​]]) 
 +    * Выполнением какого-либо события в игре, как то: "​Выделение предмета",​ "​Выделение действия",​ "​Загрузка сохранения",​ "​Ввод текста в поле ввода"​ и т.д. (подробнее в статье [[help:​service_locations|"​Служебные локации"​]]). 
 +  * **Блок кода** — это выделенный в отдельное целое фрагмент кода игры. Отдельными блоками кода в **QSP** являются:​ 
 +    * Локации сами со себе. 
 +    * Код, передаваемый оператору **''​DYNAMIC''​** или функции **''​DYNEVAL''​** в виде текста. 
 +    * Код, выполняемый при нажатии на гиперссылку. 
 +    * Код каждого отдельного Действия (**[[help:​acts|ACT]]**). 
 +    * Код каждого отдельного Цикла (**[[help:​cycle|LOOP]]**) 
 + 
 +===== Запуск игры ===== 
 + 
 +Каждая игра на **QSP** структурно представляет собой набор локаций,​ последовательно записанных в файл. 
 + 
 +Когда мы открываем игру в плеере (интерпретаторе),​ автоматически запускается чтение самой первой локации в файле (далее **Стартовая локация**),​ как если бы на неё был совершён переход с помощью оператора **''​GOTO''​**. То есть: 
 + 
 +  * В Окно основного описания добавляется текст из поля "​**Базовое описание**"​ локации (поле "​**Описание**"​ в **Quest Generator**). 
 +  * В Окно действий добавляются действия из поля "​**Базовые действия**"​ локации (поле "​**Базовые действия**"​ в **Quest Generator**). 
 +  * Выполняется код из поля "​**Выполнить при посещении**"​ локации. 
 +  * Если на Стартовой локации в переменную **''​$ONNEWLOC''​** было помещено название локации-обработчика события "​**Переход на новую локацию**",​ произойдёт автоматический вызов этой самой локации-обработчика события "​**Переход на новую локацию**"​ (см. [[help:​service_locations|"​Служебные локации"​]]). 
 +  * После того, как Стартовая локация была прочитана,​ плеер "​останавливается"​ и ожидает действий от игрока. При этом локация остаётся "​активной",​ т.е. функция **''​$CURLOC''​** в любой момент может вернуть её название,​ а в массиве **''​ARGS[]''​** данной локации сохраняются значения,​ которые на ней были выставлены,​ и эти значения могут использоваться,​ например,​ в действиях,​ выведенных в **Окно действий**. 
 + 
 +Если на Стартовой локации в переменную **''​$COUNTER''​** было помещено название локации-счётчика,​ примерно через равные промежутки времени (по умолчанию раз в пол секунды) плеер будет вызывать локацию-счётчик (см. [[help:​service_locations|"​Служебные локации"​]]). 
 + 
 +===== Выполнение кода ===== 
 + 
 +Код в **QSP** всегда выполняется последовательно,​ команда за командой. Чтение команд происходит сверху вниз и справа налево:​ 
 + 
 +<sxh qsp> 
 +*pl "​Первая команда"​ 
 +*pl "​Вторая команда"​ 
 +*pl "​Третья команда"​ 
 + 
 +*pl "​Четвёртая команда"​ & *pl "​Пятая команда"​ & *pl "​Шестая команда"​ 
 +</​sxh>​ 
 + 
 +**QSP** не способен выполнить две команды одновременно,​ или случайно выполнить вторую команду раньше первой. Поэтому в большинстве случаев,​ если вам кажется,​ что плеер "​забывает"​ выполнить какую-либо команду,​ скорее всего эта команда написана в таком месте, где плеер просто не может до неё добраться. 
 + 
 +Например,​ если написано невыполнимое условие,​ команда никогда не будет выполнена:​ 
 + 
 +<sxh qsp> 
 +if 5>6: 
 +  *pl "​Данная команда никогда не будет выполнена"​ 
 +end 
 +</​sxh>​ 
 + 
 +Команды,​ стоящие после **''​GOTO''​** или **''​XGOTO''​**,​ так же никогда не будут выполнены:​ 
 + 
 +<sxh qsp> 
 +*pl "​Текст на локации"​ & ! этот текст будет виден на локации всегда 
 +act "​Переход по XGOTO":​ 
 +  *pl "​Этот текст виден благодаря тому, что вы перешли с помощью XGOTO"​ 
 +  xgoto $curloc & ! переходим на текущую локацию 
 +  *pl "А эта команда никогда не будет выполнена"​ 
 +end 
 + 
 +act "​Переход по GOTO":​ 
 +  *pl "​Эта команда будет выполнена"​ 
 +  ! но при переходе по GOTO Окно основного описания очистится,​ 
 +  ! так что эту строчку вы всё равно не увидите. 
 +  goto $curloc & ! переходим на текущую локацию 
 +  *pl "А эта команда никогда не будет выполнена"​ 
 +end 
 +</​sxh>​ 
 + 
 +Код действий (**''​ACT''​**) не выполняется сразу, а "​прикрепляется"​ к этим действиям. Он будет выполнен только тогда, когда игрок нажмёт на соответствующее действие. 
 + 
 +<sxh qsp> 
 +example=12 & ! присваиваем переменной число 12 
 +! создаём действие 
 +act "​Вывести значение переменной example":​ 
 +  *pl example 
 +end 
 +example=37 & ! меняем значение в переменной 
 +</​sxh>​ 
 + 
 +То же самое происходит с кодом в гиперссылках. Он не выполняется сразу, когда мы создаём гиперссылку,​ он выполняется только тогда, когда мы на гиперссылку нажимаем:​ 
 + 
 +<sxh qsp> 
 +usehtml=1 & ! включаем режим распознавание HTML 
 +example=12 
 +! выводим на экран гиперссылку с кодом 
 +*pl "<a href='​EXEC:​*pl example'>​Вывести значение переменной example</​a>​" 
 +example=37 
 +</​sxh>​ 
 + 
 +При выполнении команды,​ которая содержит строки с вложенными выражениями,​ сначала раскрываются вложенные выражения,​ и только затем происходит работа со строкой,​ например,​ передача её оператору для вывода на экран: 
 + 
 +<sxh qsp> 
 +яблоки = 23 
 +! Сначала в строку подставится значение,​ 
 +! потом строка выведется на экран:​ 
 +*pl "​Яблок в кармане:​ <<​яблоки>>​."​ 
 +</sxh> 
 + 
 +===== Переход на новую локацию ===== 
 + 
 +Переход на новую локацию может осуществляться с помощью двух операторов **''​GOTO''​** и **''​XGOTO''​**. Различие в их работе заключается в следующем:​ 
 + 
 +  * При переходе с помощью оператора **''​GOTO''​** очищаются Окно основного описания и Окно действий. 
 +  * При переходе с помощью оператора **''​XGOTO''​** очищается только Окно действий. Окно основного описания не очищается. 
 + 
 +В остальном работа этих операторов схожа:​ 
 + 
 +  * В Окно основного описания добавляется текст из поля "​Базовое описание"​ локации (поле "​Описание"​ в **Quest Generator**). 
 +  * В Окно действий добавляются действия из поля "​Базовые действия"​ локации (поле "​Базовые действия"​ в **Quest Generator**). 
 +  * Выполняется код из поля "​Выполнить при посещении"​ локации. 
 +  * Если в переменную **''​$ONNEWLOC''​** было помещено название локации-обработчика события "​Переход на новую локацию",​ произойдёт автоматический вызов этой самой локации-обработчика события "​Переход на новую локацию"​ (см. [[help:​service_locations|"​Служебные локации"​]]). 
 +  * После этого плеер "​останавливается"​ и ожидает действий от игрока. При этом локация остаётся "​активной",​ т.е. функция **''​$CURLOC''​** в любой момент может вернуть её название,​ а в массиве **''​ARGS[]''​** данной локации сохраняются значения,​ которые на ней были выставлены,​ и эти значения могут использоваться,​ например,​ в действиях,​ выведенных в **Окно действий**. 
 + 
 +Если в переменную **''​$COUNTER''​** было помещено название локации-счётчика,​ примерно через равные промежутки времени (по умолчанию раз в пол секунды) плеер будет вызывать локацию-счётчик (см. [[help:​service_locations|"​Служебные локации"​]]). 
 + 
 +P.S.: "​Переход на новую локацию"​ — это устоявшееся название события. Технически более правильно называть такие переходы просто "​Переход на локацию",​ поскольку мы можем переходить не только на новые, но и на текущую локацию:​ 
 + 
 +<sxh qsp> 
 +"​Счёт:​ <<​count>>"​ 
 +act "​Обновить":​ 
 +  count+=1 
 +  goto $curloc & ! перезаходим на текущую локацию 
 +end 
 +</sxh> 
 + 
 +Поэтому,​ столкнувшись с выражением "​Переход на новую локацию"​ помните,​ что оно может значить в том числе и переход на текущую локацию. 
 + 
 +===== Вызов локации ===== 
 + 
 +Вызов локации может быть выполнен напрямую через оператор [[help:​organizing|**GOSUB**]] или функцию [[help:​organizing|**FUNC**]] или в привязке к какому-либо [[help:​service_locations|событию]]. 
 + 
 +При вызове:​ 
 + 
 +  * В Окно основного описания добавляется текст из поля ​"Базовое описание"​ локации (поле "​Описание"​ в **Quest Generator**). 
 +  * В Окно действий добавляются действия из поля "​Базовые действия"​ локации (поле "​Базовые действия"​ в **Quest Generator**). 
 +  * Выполняется код из поля "​Выполнить при посещении"​ локации. 
 + 
 +Дополнительно,​ при вызове с помощью оператора **''​GOSUB''​**,​ или функции **''​FUNC''​**,​ а так же с помощью оператора [[help:​menu|**MENU**]],​ осуществляется возврат к тому коду, из которого был осуществлён вызов, и продолжается выполнение этого кода. Например,​ если локация была вызвана из действия,​ то произойдёт возврат к выполнению кода действия. 
 + 
 +<sxh qsp> 
 +act "​Действие с вызовом локации":​ 
 +  *pl "​Выводим текст до вызова"​ 
 +  gosub 'foo' & ! вызываем локацию foo 
 +  *pl "​Продолжаем выполнять код после вызова локации foo" 
 +end 
 +</sxh> 
 + 
 +Более подробно работа оператора **''​GOSUB''​** и функции **''​FUNC''​** освещена в разделе [[help:​organizing|"​Пользовтальские функции и процедуры"​]]. 
 + 
 +О работе оператора **''​MENU''​** более подробно можно почитать в разделе [[help:​menu|"​Меню"​]]. 
 + 
 +===== Обработка событий ===== 
 + 
 +События,​ если смотреть на это понятие с точки зрения работы плеера,​ — это некое изменение состояния в написанной нами игре. Например,​ у нас все предметы были не выделены,​ и вот игрок щёлкает мышью по одному из предметов,​ и предмет оказывается выделен. То есть предмет изменил своё состояние с "не выделен",​ на "​выделен"​. Это и есть **событие выделения предмета**. 
 + 
 +Конечно,​ мы могли бы и сами отслеживать некоторые события,​ например,​ с помощью локации-счётчика постоянно проверять,​ какое значение возвращает нам функция **''​$SELOBJ''​**,​ и в момент,​ когда функция изменяет своё значение с одного на другое,​ мы точно знаем, что произошло выделение нового предмета,​ или иными словами:​ событие "​Выделение предмета"​. Однако,​ для нас это, во-первых,​ лишний код, а, во-вторых,​ очень неудобный и неточный инструмент по отслеживанию событий,​ поскольку локация-счётчик имеет ряд ограничений и на скорость выполнения,​ и на очерёдность. Мы хотим, чтобы миллисекунда в миллисекунду мы знали, что какое-то событие произошло,​ и чтобы при этом мы могли выполнить какой-либо код. 
 + 
 +Именно для этого в **QSP** введены специальные служебные локации:​ локации-обработчики событий (и локация-счётчик). 
 + 
 +Любая локация,​ названная как угодно,​ и написанная каким угодно образом,​ может быть назначена обработчиком-события или локацией-счётчиком. Для этого название этой локации нужно прописать в специальную системную переменную. Например:​ 
 + 
 +<sxh qsp> 
 +$counter = '​счётчик'​ & назначаем локацию-счётчик 
 +$onobjsel = '​onClick'​ & ! назначаем локацию-обработчик события "​Выделение предмета"​ 
 +$usercom = '​debugger'​ & ! назначаем локацию-обработчик события "​Нажатие клавиши ввода в Поле ввода"​ 
 +</​sxh>​ 
 + 
 +Как видите,​ название локации может быть совершенно любым, главное,​ чтобы она была прописана в нужную системную переменную. И как только это происходит,​ как только мы прописываем имя локации в нужную переменную,​ эта локация становится **связана** с указанным событием. Это значит,​ что как только это событие случится,​ будет выполнен код на указанной локации. 
 + 
 +Подробнее о том, какая системная переменная за **связку** с каким событием отвечает,​ вы можете прочитать в статье [[help:​service_locations|"​Служебные локации"​]]. 
 + 
 +Чтобы отвязать локацию от события,​ достаточно в нужную системную переменную прописать пустое значение:​ 
 + 
 +<sxh qsp> 
 +$counter = ''​ & ! отключаем локацию-счётчик 
 +$onobjsel = ''​ & ! отключаем локацию-обработчик события "​Выделение предмета"​ 
 +</​sxh>​ 
 + 
 +===== Процессы в настоящем времени ===== 
 + 
 +Если была назначена локация-счётчик,​ то с приблизительно равной периодичностью будет происходить вызов указанной локации-счётчика. По умолчанию локация-счётчик вызывается 2 раза в секунду,​ то есть каждые 500 миллисекунд — это значение можно изменять с помощью оператора **''​SETTIMER''​**. 
 + 
 +<sxh qsp> 
 +settimer 100 & ! устанавливаем период обращения к локации-счётчику в 100 мс 
 +$counter = '​отсчёт_времени'​ & ! плеер будет вызывать локацию **отсчёт времени** примерно 10 раз в секунду 
 +</​sxh>​ 
 + 
 +Так же с заданной периодичностью (по умолчанию 2 раза в секунду) происходит полное обновление интерфейса:​ шрифт и цвета, заданные с помощью системных переменных. 
 + 
 +Подробнее о локации-счётчике и создании игровых событий в реальном времени читайте в статье [[help:​realtime|"​Реальное время"​]]. 
 + 
 +[[help:​variables|Вперёд:​ Переменные]] 
help/principle.1428236988.txt.gz · Последние изменения: 2015/04/05 15:29 (внешнее изменение)