Skip to content

Атрибуты и обработчики как функции

Большинство атрибутов и обработчиков могут быть функциями. Так, например:

lua
disp = function()
	p 'яблоко';
end

Пример не очень удачен, так как проще было бы написать disp = 'яблоко', но показывает синтаксис записи функции.

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

lua
 return "яблоко";

При этом ход выполнения кода функции прекращается, и она возвращает движку строку. В данном случае "яблоко".

Более привычным способом вывода являются функции:

  • p ("текст") -- вывод текста и пробела;
  • pn ("текст") -- вывод текста с переводом строки;
  • pr ("текст") -- вывод текста "как есть".

Если ''p''/''pn''/''pr'' вызывается с одним текстовым параметром, то скобки можно опускать.

pn "Нет скобкам!"

Все эти функции дописывают текст в буфер и при возврате из функции возвращают его движку. Таким образом, вы можете постепенно формировать вывод за счёт последовательного выполнения p/pn/pr. Имейте в виду, что автору крайне редко необходимо явно форматировать текст, особенно, если это описание объектов, движок сам расставляет необходимые переводы строк и пробелы для разделения информации разного рода и делает это унифицированным способом.

Вы можете использовать '..' или ',' для склейки строк. Тогда '(' и ')' обязательны. Например:

lua
pn ("Строка 1".." Строка 2");
pn ("Строка 1", "Строка 2");

Основное отличие атрибутов от обработчиков событий состоит в том, что обработчики событий могут менять состояние игрового мира, а атрибуты нет. Поэтому, если вы оформляете атрибут (например, 'dsc') в виде функции, помните, что задача атрибута -- это возврат значения, а не изменение состояния игры! Дело в том, что движок обращается к атрибутам в те моменты времени, которые обычно чётко не определены, и не связаны явно с какими-то игровыми процессами!

Важно!

Ещё одной особенностью обработчиков является тот факт, что вы не должны ждать каких-то событий внутри обработчика. То есть, не должно быть каких-то циклов ожидания, или организации задержек (пауз). Дело в том, что задача обработчика -- изменить игровое состояние и отдать управление INSTEAD, который визуализирует эти изменения и снова перейдёт в ожидание действий пользователя. Если вам требуется организовать задержки вывода, вам придётся воспользоваться модулем "timer".

Функции практически всегда содержат условия и работу с переменными. Например:

lua
obj {
	nam = 'яблоко';
	seen = false;
	dsc = function(s)
		if not s.seen then
			p 'На столе {что-то} лежит.';
		else
			p 'На столе лежит {яблоко}.';
		end
	end;
	act = function(s)
		if s.seen then
			p 'Это яблоко!';
		else
			s.seen = true;
			p 'Гм... Это же яблоко!';
		end
	end;
};

Если атрибут или обработчик оформлен как функция, то всегда первый аргумент функции (s) -- сам объект. То-есть, в данном примере, 's' это синоним _'яблоко'. Когда вы работаете с самим объектом в функции, удобнее использовать параметр, а не явное обращение к объекту по имени, так как при переименовании объекта вам не придётся переписывать вашу игру. Да и запись будет короче.

В данном примере при показе сцены в динамической части сцены будет выведен текст: 'На столе что-то лежит'. При взаимодействии с 'что-то', переменная 'seen' объекта 'яблоко' будет установлена в true -- истина, и мы увидим, что это было яблоко.

Как видим, синтаксис оператора 'if' довольно очевиден. Для наглядности, несколько примеров.

if <выражение> then <действия> end

if have 'яблоко' then
	p 'У меня есть яблоко!'
end

if <выражение> then <действия> else <действия иначе> end

if have 'яблоко' then
	p 'У меня есть яблоко!'
else
	p 'У меня нет яблока!'
end

if <выражение> then <действия> elseif <выражение 2> then <действия 2> else <иначе> end -- и т.д.

if have 'яблоко' then
	p 'У меня есть яблоко!'
elseif have 'вилка' then
	p 'У меня нет яблока, но есть вилка!'
else
	p 'У меня нет ни яблока, ни вилки!'
end

Выражение в операторе if может содержать логическое "и" (and), "или" (or), "отрицание" (not) и скобки ( ) для задания приоритетов. Запись вида if <переменная> then означает, что переменная не равна false. Равенство описывается как '==', неравенство '~='.

lua
if not have 'яблоко' and not have 'вилка' then
    p 'У меня нет ни яблока, ни вилки!'
end

...
if w ~= apple then
   p 'Это не яблоко.';
end
...

if time() == 10 then
   p '10 й ход настал!'
end

Важно!

В ситуации, когда переменная не была определена, но используется в условии, INSTEAD даст ошибку. Вам придётся заранее определять переменные, которые вы используете.