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

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


help:principle

Различия

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

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

Both sides previous revision Предыдущая версия
Следущая версия
Предыдущая версия
help:principle [2013/10/19 07:37]
newsash
help:principle [2024/10/14 07:28] (текущий)
aleks_versus проба обновления до 5.9.0
Строка 1: Строка 1:
-Принцип работы QSP+[[help:​objs|Назад: ​Предметы]]
  
-Top Previous Next+====== Порядок работы интерпретатора ======
  
-При ​обработке новой локации (например, при переходе с помощью операторов "GOTOXGOTO, GOSUB"​) выполняются следующие действия:+**Несмотря на то, что эта статья ​обросла некоторыми подробностями, она всё ещё требует серьёзной редактурыупрощения и расширения. Так что пока что это всё ещё черновой вариант.**
  
 +Эта статья подробно рассказывает о порядке работы интерпретатора (плеера) **QSP**. Она может показаться вам довольно сложной,​ но читать её всю не обязательно. Вернитесь к ней, когда у вас возникнут сложности в понимании того, как ведёт себя плеер. А пока достаточно ознакомиться с общими принципами:​
  
 +  * При запуске игры автоматически воспроизводится только самая первая в игре локация. На остальные локации нужно осуществлять переходы с помощью **''​GOTO''​** или **''​XGOTO''​**,​ или вызывать их с помощью **''​GOSUB''​**,​ **''​FUNC''​**,​ или иным предусмотренным плеером способом.
 +  * Код действий "​прикрепляется"​ к действию и не выполняется,​ пока игрок не нажмёт на действие.
 +  * Все команды выполняются последовательно одна за другой,​ и никогда не выполняются одновременно.
  
-1) Очистка списка ​действий предыдущей ​локации, если был осуществлен непосредственный переход ​на локацию (например,​ с помощью операторов "GOTO, XGOTO"​);​+Ниже по тексту будут использоваться ​следующие определения:
  
-2Обновление поля описания локации (замена существующего основного описаниялибо добавление к нему текста базового описания новой локации ​в зависимости от того, каким образом был произведён переход);+  * **Переход на локацию** — это событие в игре, которое происходит при обращении к локации с помощью операторов **''​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]]**)
  
-3) Добавление базовых действий новой локации;+===== Запуск игры =====
  
-4) Последовательное выполнение операторов, находящихся в поле ​"​Выполнить ​при посещении";+Каждая игра на **QSP** структурно представляет собой ​набор локаций, последовательно записанных в файл.
  
-5) При непосредственном переходе на локацию выполняется обработка локациибработчика ​перехода на новую локацию, ​если ​таковая указана;​+Когда мы открываем игру в плеере (интерпретаторе), автоматически запускается чтение самой первой локации в файле (далее **Стартовая локация**), как если бы на неё ​был совершён ​переход ​с помощью оператора **''​GOTO''​**. То есть:
  
-6) Если переменная локации-счётчика не пустато происходит обработка соответствующей локации ​(по умолчанию, ​раза в секунду);+  * В Окно основного описания добавляется текст ​из поля "​**Базовое описание**" локации (поле "​**Описание**"​ в **Quest Generator**). 
 +  * В Окно действий добавляются действия из поля "​**Базовые действия**" ​локации ​(поле "​**Базовые действия**" в **Quest Generator**). 
 +  * Выполняется код из поля "​**Выполнить при посещении**"​ локации. 
 +  * Если на Стартовой локации в переменную **''​$ONNEWLOC''​** было помещено название локации-обработчика ​события "​**Переход ​на новую локацию**", произойдёт автоматический вызов этой самой локации-обработчика события "​**Переход на новую локацию**"​ (см. [[help:​service_locations|"​Служебные локации"​]]). 
 +  * После того, как Стартовая локация была прочитана,​ плеер "останавливается"​ и ожидает действий от игрока. При этом ​локация остаётся "​активной", т.е. функция **''​$CURLOC''​** в любой ​момент может вернуть её название, а в массиве **''​ARGS[]''​** данной локации сохраняются значениякоторые на ней были выставлены,​ и эти ​значения могут использоваться, например, в действиях,​ выведенных в **Окно действий**.
  
-7) Обновление ​интерфейса рифтцвета, заданные с помощью системных ​переменных) - такжепо умолчанию, 2 раза в секунду;+Если на Стартовой локации в переменную **''​$COUNTER''​** было помещено название локации-счётчика, ​примерно через равные промежутки времени (по умолчанию раз в пол ​секунды) плеер будет вызывать локацию-счётчик (см. [[help:​service_locations|"​Служебные локации"​]]).
  
-8) При выборе действия или предмета ​пользователем, происходит обработка локаций-обработчиков выбора действий и предметов;​+===== Выполнение кода ​=====
  
-9) При загрузке или сохранении ​состояния игры, ​происходит обработка локаций-обработчиков загрузки ​и сохранения игры;+Код в **QSP** всегда выполняется последовательнокоманда за командой. Чтение команд происходит сверху вниз и справа налево:​
  
-10) Если пользователь щёлкает на действии, ​то выполняются операторы, определённые ​для этого действия;​+<sxh qsp> 
 +*pl "​Первая команда
 +*pl "Вторая команда"​ 
 +*pl "​Третья команда"
  
-11) Если пользователь нажимает "​Enter" ​в строке ввода, то происходит обработка локации-обработчика строки ввода.+*pl "Четвёртая команда" & *pl "Пятая команда" & *pl "Шестая команда
 +</​sxh>​
  
 +**QSP** не способен выполнить две команды одновременно,​ или случайно выполнить вторую команду раньше первой. Поэтому в большинстве случаев,​ если вам кажется,​ что плеер "​забывает"​ выполнить какую-либо команду,​ скорее всего эта команда написана в таком месте, где плеер просто не может до неё добраться.
  
 +Например,​ если написано невыполнимое условие,​ команда никогда не будет выполнена:​
  
-Системные переменные +<sxh qsp> 
-Системные переменные - переменные,​ значения которых обрабатываются интерпретатором специальным образом. Системные переменные ​используются как обычные переменные,​ т.е. в них можно заносить и считывать из них значения (правда стоит помнить,​ что в результате ​вы можете ​получить, ​например, чёрный цвет текста на чёрном же фоне - и ничего не будет видно).+if 5>6: 
 +  *pl "Данная команда никогда не будет выполнена
 +end 
 +</​sxh>​
  
 +Команды,​ стоящие после **''​GOTO''​** или **''​XGOTO''​**,​ так же никогда не будут выполнены:​
  
-Базовые системные переменные ​основные переменные. +<sxh qsp> 
-Переменные,​ задающие обработчики событий ​позволяют обрабатывать такие события,​ как выбор предмета,​ переход на новую локацию,​ ввод строки в поле ввода..+*pl "​Текст на локации"​ & ! этот текст будет ​виден на локации всегда 
-Переменные настройки интерфейса - позволяют настраивать цвета, шрифт, а также использовать в описаниях ​HTML.+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|Вперёд:​ Переменные]]
  
-PS: 
-При использовании операторов "​KILLALL,​ KILLVAR"​ удаляются также все системные переменные. 
help/principle.1382168240.txt.gz · Последние изменения: 2013/10/19 11:37 (внешнее изменение)