Lua

Материал из wiki.appsalutecreator.com
Перейти к: навигация, поиск

Lua - скриптовый язык программирования.

Введение

Lua - динамически типизированный язык, предназначенный для использования в качестве расширения или в качестве скриптового языка, и при этом достаточно компактный, чтобы поместиться на различных исполняющих платформах. Он поддерживает небольшое количество структур данных, такие как логические значения, числа (по умолчанию — двойной точности с плавающей точкой), а также строки.

Используется для удобства вычислений и увеличения скорости исполнения кода.

Создание скрипта

В машине состояний, выбрав добавляемое свойство, создаем или открываем уже существующий скрипт (edit script).

При сохранении проекта в редакторе все скрипты объединяются в один файл scripts.lua, при этом удаляются все комментарии.

При экспорте проекта остается только общий файл scripts.lua

Edit script.png

Основные функции

При создании скриптов в первой вкладке всегда создается файл viewer.lua, где перечислен список доступных функций и параметров.

Существует четыре вида функций для взаимодействия скрипта с машиной состояний:

Func.png


Функции для работы с текстовой базой

viewer.getResFromTxtDB(txtID,tp,defValue) - возвращает id (integer) графического ресурса текстового объекта с txtID. tp - номер картинки ( 0 - main, 1 - ico1 ...) ;
viewer.getStrFromTxtDB(txtID,sense,defValue) - возвращает строку (string) вытянутую из txtID с учётом локализации. sense - номер sense;

С их помощью можно вытянуть иконку из текстовой базы и вытянуть текст по текущей локализации.


Функции для работы с таблицей

function viewer.tableAddCellObj(tblID,objID,col,row) - помещает объект (objID) в таблицу (tblID), в координаты (col,row).
function viewer.tableClear(tblID) - очищает таблицу от элементов добавленных функцией viewer.tableAddCellObj(). Все элементы возвращаются обратно в исходного родителя ( кот. был до помещения в таблицу);

Важно: если вы засовываете в таблицу клонов, то перед инитом таблицы - нужно ей передать viewer.tableClear(tblID).

Макрос ID("")

ID("control") - макросс, который возвращает ID объекта с именем "control" при сохранении проекта - сделано для удобства переноса скриптов из одного проекта в другой, не подвязываясь к ID объекта. НО, при импорте скрипта в другой проект важно проверять наличие объектов с таким же именем. Их быть не должно! В противном случае при сохранении проекта в редакторе будет выдаваться ошибка

Errorscript.png

Макрос TXT("") и RES("")

TXT("123456") - макросс, который при сохранении скриптов исчезнет (останется только число "123456"), но пройдёт валидация ресурса по id (в данном случае, поищет наличие текстовой ячейки в текстовой базе с id="123456"). Если id ресурса не валидный - всплывёт окно с ошибкой, где будет указано - "("123456")" и файл скрипта в котором найдено.

TXT("123,456,789") - макросс-последовательность, идентичный обычному, но указываем n ресурсов через запятую ( превратится в "123,456,789"). Макрос RES("") идентичен.

Функция изменения команды машины состояний

При необходимости в realtime изменять комманду машины состояний(применять только в случаях где без этого ну никак), можно воспользоватся данной функцией. Функция является аналогичной команде "Set" машины состояний: viewer.setMachineCommandParam(objID,mSt,mCmd,mCmdN,mPar,val)

  • objID - object ID (integer) изменяемой машины состояний;
  • mSt - state name (string);
  • mCmd - command name (string) or command type (integer);
  • mCmdN - command number (integer);
  • mPar - parameter name (string);
  • val - parameter value (string or number);

В логе команда принтуется:

  • I/IScriptLanguageLUA IScriptViewerLUALib::setMachineCommandParam() viewer_setMachineCommandParam: obj(103)->mSt(state_spline)->mCmd(spline(0))->mPar(key) = -100, -100, 200, 200

Доступные библиотеки

Базовая библиотека стандартных функций Lua (Basic Functions)

Функции базовой библиотеки Lua размещаются в глобальном контексте.

В базовую библиотеку входят следующие функции:

  • assert (v [, message]) - Генерирует ошибку с необязательным сообщением об ошибке, если значение первого аргумента false или nil.
  • collectgarbage ([opt [, arg]]) - Обеспечивает интерфейс к сборщику мусора. Первый аргумент определяет выполняемое действие (остановка, запуск сборщика мусора, выполнение сборки мусора и др.).
  • error (message [, level]) - Завершает выполнение последней функции, вызванной в защищённом режиме, с заданным сообщением об ошибке.
  • getfenv - Возвращает таблицу контекста заданной функции. Аргумент, определяющий функцию, может быть как, собственно, Lua-функцией, так и числом, определяющим уровень стека, на котором расположена функция. Если он равен 0, возвращается глобальный контекст.
  • getmetatable (object) - Если объект не имеет метатаблицы, возвращает nil. Иначе, если в метатаблице есть поле __metatable, возвращает значение этого поля. В противном случае возвращает метатаблицу объекта.
  • ipairs (t) - Возвращает итератор, таблицу и 0. Возвращаемый итератор проходит таблицу по целочисленным индексам от значения 1 до первого индекса со значением nil. Итератор возвращает текущий индекс и соответствующее ему значение.
  • next (table [, index]) - Возвращает следующий (после заданного) индекс в таблице и соответствующее ему значение. Позволяет последовательно получить все поля таблицы.
  • pairs (t) - Возвращает итератор next(), таблицу и nil. Возвращаемый итератор проходит таблицу по всем значениям индекса. Итератор возвращает текущий индекс и соответствующее ему значение.
  • pcall (f [, arg1, ···]) - Вызывает заданную функцию с аргументами в защищённом режиме. Возвращает статус успешности выполнения.
  • rawequal (v1, v2) - Сравнивает два объекта, без вызова каких-либо метаметодов. Возвращает значение типа boolean.
  • rawget (table, index) - Возвращает реальное значение с заданным индексом из таблицы, без вызова каких-либо метаметодов.
  • rawset (table, index, value) - Помещает значение в поле таблицы с заданным индексом, без вызова каких-либо метаметодов.
  • select (index, ···) - Если первый аргумент функции имеет числовое значение, возвращаются все аргументы, следующие за аргументом с этим номером. Если первый аргумент — строка ’#’, возвращается общее число полученных аргументов.
  • setfenv - Устанавливает таблицу в качестве контекста для заданной функции. Аргумент, задающий функцию, может быть числом, определяющим положение функции на стеке вызовов. Если он равен 0, устанавливается глобальный контекст текущего потока.
  • setmetatable (table, metatable) - Устанавливает (удаляет) метатаблицу для данной таблицы. Если метатаблица содержит поле __metatable, генерирует ошибку.
  • tonumber (e [, base]) - Пытается конвертировать аргумент в число. Если конвертирование не удаётся, возвращает nil.
  • tostring (v) - Преобразует аргумент любого типа в строку.
  • type (v) - Возвращает тип аргумента в виде строки.
  • unpack - Возвращает элементы из заданной таблицы.
  • xpcall (f, msgh [, arg1, ···]) Вызывает заданную функцию в защищённом режиме. В отличие от pcall, позволяет установить обработчик ошибок. Не поддерживает передачу аргументов в функцию.

Библиотека для работы со строками Lua (String Manipulation)

Все функции для работы со строками собраны в таблице string. Поэтому для вызова функций используется запись вида: string.имя_функции(...)

  • string.len (s) - Возвращает длину строки.
  • string.rep (s, n [, sep]) - Возвращает строку, содержащую указанное число копий исходной строки.
  • string.lower (s) - Заменяет все прописные буквы в строке на строчные.
  • string.upper (s) - Заменяет в строке все строчные буквы на прописные.
  • string.reverse (s) - Возвращает строку, в которой символы исходной строки расположены в обратном порядке.
  • string.format (formatstring, ···) - Генерирует строку по форматной строке и аргументам по правилам, принятым в языке C.
  • string.byte (s [, i [, j]]) - Возвращает числовые коды символов строки.
  • string.char (···) - Преобразует набор числовых кодов символов в строку.
  • string.find (s, pattern [, init [, plain]]) - Выполняет поиск в строке первого вхождения подстроки, соответствующей заданному шаблону. Возвращает индексы начального и конечного символов найденной подстроки.
  • string.match (s, pattern [, init]) - Выполняет поиск в строке первого вхождения подстроки, соответствующей заданному шаблону. Возвращает найденную подстроку.
  • string.gmatch (s, pattern) - Возвращает итератор, который на каждой итерации возвращает подстроку, соответствующую заданному шаблону.
  • string.sub (s, i [, j]) - Возвращает подстроку исходной строки.
  • string.gsub (s, pattern, repl [, n]) - Возвращает копию исходной строки, в которой все вхождения шаблона заменены на строку, заданную третьим аргументом. Этот аргумент может быть строкой, таблицей или функцией.
  • string.dump (function [, strip]) - Возвращает строку, содержащую двоичное представление функции Lua с заданным именем.

Библиотека для работы с таблицами Lua (Table Manipulation)

Все функции для работы с таблицами собраны в таблице table. Для вызова функций используется запись вида: table.имя_функции(...)

  • table.insert (list, [pos,] value) - Вставляет элемент в заданную позицию таблицы, сдвигая остальные элементы таблицы вправо.
  • table.remove (list [, pos]) - Удаляет заданный элемент таблицы, сдвигая остальные элементы влево. Возвращает значение удалённого элемента.
  • table.sort (list [, comp]) - Сортирует элементы таблицы в заданном порядке. Вторым аргументом может быть задана функция, которая будет использована вместо стандартного оператора «<» для сравнения элементов в процессе сортировки.
  • table.concat (list [, sep [, i [, j]]]) - Выполняет склейку указанных элементов массива через заданный разделитель. По умолчанию разделителем является пустая строка.

Математическая библиотека Lua (Mathematical Functions)

Математические функции собраны в таблице math. Для вызова функций используется запись вида: math.имя_функции(...)

  • math.abs (x) - Возвращает модуль числа.
  • math.ceil (x) - Возвращает наименьшее целое число, большее или равное заданному (выполняет округление «вверх»).
  • math.floor (x) - Возвращает наибольшее целое число, меньшее или равное заданному (выполняет округление «вниз»).
  • math.max (x, ···) - Возвращает максимальный из аргументов.
  • math.min (x, ···) - Возвращает минимальный из аргументов.
  • math.fmod (x, y) - Возвращает остаток от деления одного числа на другое.
  • math.modf (x) - Возвращает целую и дробную части исходного числа.
  • pow - Возводит число в степень. Вместо вызова функции возможно использование выражения вида x^y.
  • math.sqrt (x) - Вычисляет квадратный корень числа. Вместо вызова функции возможно использование выражения вида x^0.5.
  • math.exp (x) - Возвращает eх.
  • math.log (x [, base]) - Вычисляет натуральный логарифм.
  • log10 - Вычисляет логарифм по основанию 10.
  • math.cos (x) - Вычисляет косинус угла, заданного в радианах.
  • math.sin (x) - Вычисляет синус угла, заданного в радианах.
  • math.tan (x) - Вычисляет тангенс угла, заданного в радианах.
  • cosh - Вычисляет гиперболический косинус.
  • sinh - Вычисляет гиперболический синус.
  • tanh - Вычисляет гиперболический тангенс.
  • math.acos (x) - Вычисляет арккосинус (в радианах).
  • math.asin (x) - Вычисляет арксинус (в радианах).
  • math.atan (y [, x]) - Вычисляет арктангенс (в радианах).
  • atan2 - Возвращает арктангенс x/y (в радианах), но использует знаки обоих параметров для вычисления «четверти» на плоскости. Также корректно обрабатывает случай когда y равен нулю.
  • math.deg (x) - Переводит величину угла из радиан в градусы.
  • math.rad (x) - Переводит величину угла из градусов в радианы.
  • math.random ([m [, n]]) - Функция, вызванная без аргументов, возвращает псевдослучайное число из интервала [0, 1). Эта же функция, вызванная с аргументом n, возвращает целое псевдослучайное число из интервала [1, n]. Эта же функция, вызванная с двумя аргументами l, u возвращает целое псевдослучайное число из интервала [l, u].
  • math.randomseed (x) - Устанавливает стартовое число генератора псевдослучайных чисел.

Библиотека для доступа к средствам OC(Operating System Facilities)

Функции, обеспечивающие доступ к средствам операционной системы, собраны в таблице os. Для вызова функций используется запись вида: os.имя_функции(...). Можно использовать при форматировании времени.

  • os.date ([format [, time]]) - Возвращает строку или таблицу, содержащую дату и время, отформатированные в соответствии с заданными параметрами. При вызове функции без параметров, возвращает текущий файл ввода по умолчанию. В случае ошибок, данная функция возбуждает ошибку вместо того, чтобы возвратить код ошибки.
  • os.difftime (t2, t1) - Возвращает число секунд, прошедшее от времени t1 до времени t2.
  • os.time ([table]) - Возвращает текущее время при вызове без аргументов, или время и дату, указанные в передаваемой таблице. Эта таблица должна иметь поля year, month, и day, и может иметь поля hour, min, sec, и isdst.

The Debug Library

Эта библиотека обеспечивает отладку программам Lua.

  • debug.debug () - Переходит в интерактивный режим, выполняя все команды, которые вводит пользователь. Используя простые команды и другие средства отладки, пользователь может получать значения глобальных и локальных переменных, изменять их значения, получать значения выражений, и т.д. Строка, содержащая только слово cont, завершает выполнение функции, т.о. вызвавшая программа продолжает выполнение. Команды для функции debug.debug лексически не вложены ни в какую функцию, т.о. не имеют прямого доступа к локальным переменным.
  • debug.gethook ([thread]) - Возвращает текущие настройки перехвата (hook settings) нити (thread), как три значения: текущая функция перехвата, текущая маска перехвата, и текущее количество перехватов (hook count) (в соответствии с параметрами, установленными функцией debug.sethook).
  • debug.getinfo ([thread,] f [, what]) - Возвращает таблицу с информацией о функции. Вы можете задать функцию непосредственно, или вы можете задать номер функции, который соответствует функции, запущенной на уровне function стека вызововзаданной нити: уровень 0 соответствует текущей функции (getinfo непосредственно); уровень 1 – это функция, которая вызвала getinfo; и т.д. Если в параметре function задано число, большее, чем количество запущенных функций, то getinfo возвращает nil.
  • debug.getlocal ([thread,] f, local) - Данная функция возвращает имя и значение локальной переменной с индексом local функции на уровне level стека. (Первая локальная переменная функции имеет индекс 1, и т.д., вплоть до последней локальной переменной.)
  • debug.getmetatable (value) - Возвращает метатаблицу заданного объекта object или nil если объект не имеет метатаблицы.
  • debug.getregistry () - Возвращает таблицу реестра (регистра???) (registry table)
  • debug.getupvalue (f, up) - Данная функция возвращает имя и значение внешней локальной переменной (upvalue) с индексом up функции func. Функция возвращает nil если не существует внешней локальной переменной (upvalue) с заданным индексом.
  • debug.getuservalue (u) - Возвращает значение, связанное с (u). Если (u) - это не пользовательские данные, возвращает ноль.
  • debug.sethook ([thread,] hook, mask [, count]) - Делает данную функцию функцией перехвата (hook).
  • debug.setlocal ([thread,] level, local, value) - Эта функция присваивает значение value локальной переменной с индексом local функции на уровне level стека. Функция возвращает nil, если не существует переменной с данным индексом, и возбуждает ошибку при вызове с уровнем level, выходящем за границы стека.
  • debug.setmetatable (value, table) - Изменяет метатаблицу заданного объекта object на таблицу table (которая также может быть nil).
  • debug.setupvalue (f, up, value) - Данная функция присваивает значение value локальной внешней переменной (upvalue) с индексом up функции func. Функция возвращает nil, если не существует локальной внешней переменной (upvalue) с данным индексом. В противном случае, возвращает имя локальной внешней переменной (upvalue).
  • debug.traceback ([thread,] [message [, level]]) - Возвращает строку со следом (traceback) стека вызовов. Опциональный параметр message добавляется в начало следа. Опциональный параметр level – число, обозначающее уровень, с которого необходимо начинать след (traceback) (значение по умолчанию равно 1, т.е. соответствует функции, вызывающей traceback).


Все доступные библиотеки можно найти в Разделах Basic Functions, String Manipulation, Table Manipulation, Mathematical Functions, Operating System Facilities (только date, difftime, time), Debug Library на сайте: http://www.lua.org/manual/5.3/manual.html#6.7

Отладка

print(e1, e2, ...) Печатает значения аргументов. В конце выводится перевод строки. Эта функция не предназначена для форматного вывода, а только для быстрого (отладочного) вывода значений переменных.


В app.icf при установке

[GameTrace]

Level="Verbose"

В логе у нас появятся данные из скриптов со всеми операциями:

D/IScript IScript::callScriptMethod() callScriptMethod: "lottery_scpt:init"

D/IScript viewer_getResFromTxtDB() viewer.getResFromTxtDB(5670,0,666)->666


Self2.png

Пример использования

Рассмотрим пример использования скрипта для написания программы Калькулятор

Project.png

Создаем машину состояний с именем "control", в ней создаем скрипт obj_control.lua. В функции init () объявляем переменные:

Self.png

1. По тапу на кнопки 0-9 записываем машине соответствующий параметр и вызываем состояние pressedDigit:

0digit.png

При вызове состояния pressedDigit скрипт вызывает функцию pressedDigit():

Объявляем локальную переменную local digit, в которую будем записывать значение параметра pressed (записанное по тапу на кнопку).

Presseddigit.png

2. Аналогично по тапу на кнопки операторов записываем параметр и вызываем функцию pressedOperator():

Operator.png

Oper.png

3. Вызов функции pressedRavnо(), вычисление и вывод результата:

Ravno.png

Res2.png

Тонкости LUA + Viewer

viewer.changeObjState() + локальные переменные

При переводе объекта в новое состояние функцией viewer.changeObjState() у нас происходит выход из скрипта, и выполнение инструкций объекта, после окончания инструкций объекта, управление возвращается в скрипт. Но все локальные переменные теряют свои значения и являются nil.

Чтобы такого не было нужно использовать self параметры или глобальные. К примеру вот так : 2aa3540a7e.jpg



Right Style

Далее описан правильный и очень удобный стиль оформления LUA скрипта. Рекомендации:

  • 1) Самой первой функцией в скрипте д.б. "init" - в которой мы должны про инициализировать все "self" параметры (да, именно - все). Нужно для того чтобы просмотрев функцию инит - узнать какие переменные хранит объект и что они означают
  • 2) Каждая "self" или глобальная переменная должны быть прокомментированы в месте обьявления
self.packState = -1 -- состояние пака, 0 - не существует; 1 - не скачан; 2 - в процессе закачки; 3 - всё норм
  • 3) Второй функцией в скрипте д.б. "state" - в которой мы указываем интерфейс класса (скрипта). Посмотрев на данную функцию можно узнать, какие методы (состояния), мы можем вызывать из вьювера;
П.С. Не д.б. функций объявленных внутри интерфейса (внутри функции "state") - портит читабельность методов;
Также не забываем об принтовании ошибки в интерфейсе класса - если не нашли метод;

Lua metods error.jpg

  • 4) Все пространства кода должны правильно форматироваться табуляцией (уровни вложенности), каждому последующему уровню - добавляем одну табуляцию в начало строки;

Таким образом достигается отличная читабельность кода.

  • 5) Все входные данные из вьювера - должны валидироваться (проверятся на адекватность). Связано с тем, что из лейаута, мы можем очень легко задать невалидное значение. К примеру попросить открыть акцию с номером 1000, хотя такой акции нет.

В случае нахождения ошибки - мы должны принтовать ошибку с описанием "ERROR - описание" и просто её скипать. Т.е. не обрабатываем некорректные данные ( лучше не вызвать некорректную логику, чем завалить вьювер; т.к. вы не знаете, когда у кого воспроизведётся бага))) ).

  • 6) Между каждой функцией нужно добавлять строку символов ('-'; 80 символов); строку с описанием работы функции; строку с описанием аргументов функции(если они не очевидные)
"---------------------------------------------------------------------------------------------"
"-- возвращаем уровень который может получить игрок"
"-- index - индекс аччивки self.Ach"

Lua scoped func.jpg

  • 7) Принтование вызова функции и значений аргументов (исключение функции которые вызываются очень часто - и в них принтование не имеет смысла);
function obj_awlMngr:state(state,guestID)
print("obj_awlMngr:state("..state..","..guestID..")")
П.С. принтовать массивы и nil значения - мы не можем(валится вьювер). Поэтому можно сделать вот так(в проекте Hidden365 так реализовано):

Lua get argum .jpg


Использование:

Lua get argum using.jpg

Таким способом, достаточно удобно принтуются одномерные массивы и nil value:
    • одномерный массив:
obj__BASE:notificationManage(Ar_txtID:[#4:1:9188,2:9189,3:9190,4:9191],str:1day,time:86400)
    • nil:
obj_AnimMngr:clone_locate(clone_array:[#1:1:13545],type_locate:1,x_:10,y_:-10,scaleStart:nil,scaleEnd:nil)
    • двухмерный массив:
obj_Sales:Templated_dropRewardCom(Ar_coord:[#2:1:[#2:1:-100,2:100],2:[#2:1:50,2:100]],num:1,clone_need:20,w:160,h:160)
  • 8) Очень полезно, создать скрипт с именем "obj__BASE" в котором объявить все глобальные переменные используемые в проекте. В него же можно добавить функции, которые являются специфическими для данного проекта и могут вызываться из разных мест(или разовые функции).
  • 9) Удобно создать скрипт с именем "obj__COM" в котором собраны универсальные функции - которые не завязываются к текущему проекту и могут быть использованы везде:
Функции принтования аргументов;
Функции сливания массивов в один;
Функции поворота точки на угол;
Функции выдавания ресурса из текста;
И д.р.


В итоге получается вот такие скрипты:

Lua right style.jpg

Пример реализации

Download

Литература

1. Официальный сайт Lua - http://www.lua.org/home.html

2. http://tylerneylon.com/a/learn-lua/

3. http://docs.madewithmarmalade.com/display/MD/Introduction+to+Lua

4. Программа - интерпретатор для работы со скриптами Lua - ZeroBrane Studio: http://studio.zerobrane.com/