Начал осваивать LUA, помогите пожалуйста, в справке нет многих операторов.
Сразу возник вопрос, как загрузить массив из файла (аналог load_array), наверняка ответ на форуме есть, но я не нашёл. В обычном скрипте код такой.
load_array %cfg $ConfigFile
Ну и сохранить соответственно тоже не знаю как.
чтение/запись файла
Код
--lua
log "clear" log "mode compact"
local f = io.open([[C:\111.txt]], "r") -- открыть файл для чтения
if f then -- если файл открылся
local cfg = {} -- объявили массив
for v in f:lines() do -- читаем файл 111.txt по строкам
cfg[#cfg+1]=v -- добавляем в массив
end
f:close(); -- закрыть файл
log(table.concat(cfg, " ")) -- вывести массив в лог
for i=1, #cfg do -- для всех элементов массива
cfg[i]=tostring(i) .. " " .. cfg[i] -- вначале строки добавим номер строки
end
f = io.open([[C:\222.txt]], "w") -- открыть файл для записи
if f then
for i=1, #cfg do -- для всех элементов массива
f:write(cfg[i] .. "\r\n") -- запись в файл
end
f:close(); -- закрыть файл
end
end
DarkMaster
25.10.2018, 8:43
Поскольку lua весь на деревьях и размеры массивов могут быть различными даже в части вложенности элементов (они не прямоугольные в lua), то лучше использовать что-то более серьезное, хотя в базовом виде работать бесспроно будет.
Например есть вот такое творение:
http://lua-users.org/wiki/TablePersistenceоригинал
Код
local write, writeIndent, writers, refCount;
persistence =
{
store = function (path, ...)
local file, e = io.open(path, "w");
if not file then
return error(e);
end
local n = select("#", ...);
-- Count references
local objRefCount = {}; -- Stores reference that will be exported
for i = 1, n do
refCount(objRefCount, (select(i,...)));
end;
-- Export Objects with more than one ref and assign name
-- First, create empty tables for each
local objRefNames = {};
local objRefIdx = 0;
file:write("-- Persistent Data\n");
file:write("local multiRefObjects = {\n");
for obj, count in pairs(objRefCount) do
if count > 1 then
objRefIdx = objRefIdx + 1;
objRefNames[obj] = objRefIdx;
file:write("{};"); -- table objRefIdx
end;
end;
file:write("\n} -- multiRefObjects\n");
-- Then fill them (this requires all empty multiRefObjects to exist)
for obj, idx in pairs(objRefNames) do
for k, v in pairs(obj) do
file:write("multiRefObjects["..idx.."][");
write(file, k, 0, objRefNames);
file:write("] = ");
write(file, v, 0, objRefNames);
file:write(";\n");
end;
end;
-- Create the remaining objects
for i = 1, n do
file:write("local ".."obj"..i.." = ");
write(file, (select(i,...)), 0, objRefNames);
file:write("\n");
end
-- Return them
if n > 0 then
file:write("return obj1");
for i = 2, n do
file:write(" ,obj"..i);
end;
file:write("\n");
else
file:write("return\n");
end;
if type(path) == "string" then
file:close();
end;
end;
load = function (path)
local f, e;
if type(path) == "string" then
f, e = loadfile(path);
else
f, e = path:read('*a')
end
if f then
return f();
else
return nil, e;
end;
end;
}
-- Private methods
-- write thing (dispatcher)
write = function (file, item, level, objRefNames)
writers[type(item)](file, item, level, objRefNames);
end;
-- write indent
writeIndent = function (file, level)
for i = 1, level do
file:write("\t");
end;
end;
-- recursively count references
refCount = function (objRefCount, item)
-- only count reference types (tables)
if type(item) == "table" then
-- Increase ref count
if objRefCount[item] then
objRefCount[item] = objRefCount[item] + 1;
else
objRefCount[item] = 1;
-- If first encounter, traverse
for k, v in pairs(item) do
refCount(objRefCount, k);
refCount(objRefCount, v);
end;
end;
end;
end;
-- Format items for the purpose of restoring
writers = {
["nil"] = function (file, item)
file:write("nil");
end;
["number"] = function (file, item)
file:write(tostring(item));
end;
["string"] = function (file, item)
file:write(string.format("%q", item));
end;
["boolean"] = function (file, item)
if item then
file:write("true");
else
file:write("false");
end
end;
["table"] = function (file, item, level, objRefNames)
local refIdx = objRefNames[item];
if refIdx then
-- Table with multiple references
file:write("multiRefObjects["..refIdx.."]");
else
-- Single use table
file:write("{\n");
for k, v in pairs(item) do
writeIndent(file, level+1);
file:write("[");
write(file, k, level+1, objRefNames);
file:write("] = ");
write(file, v, level+1, objRefNames);
file:write(";\n");
end
writeIndent(file, level);
file:write("}");
end;
end;
["function"] = function (file, item)
-- Does only work for "normal" functions, not those
-- with upvalues or c functions
local dInfo = debug.getinfo(item, "uS");
if dInfo.nups > 0 then
file:write("nil --[[functions with upvalue not supported]]");
elseif dInfo.what ~= "Lua" then
file:write("nil --[[non-lua function not supported]]");
else
local r, s = pcall(string.dump,item);
if r then
file:write(string.format("loadstring(%q)", s));
else
file:write("nil --[[function could not be dumped]]");
end
end
end;
["thread"] = function (file, item)
file:write("nil --[[thread]]\n");
end;
["userdata"] = function (file, item)
file:write("nil --[[userdata]]\n");
end;
}
Пример использования:
Код
t_original = {1, 2, ["a"] = "string", b = "test", {"subtable", [4] = 2}};
persistence.store("storage.lua", t_original);
t_restored = persistence.load("storage.lua");
Это позволит сохранят таблицы с любой структурой при этом сохраненный файл является полностью валидным lua кодом и может быть загружен через loadstring (что на самом деле и делает функция persistence.load). Вид при этом читабельный, никаких дурных проблем с зарезервированными символами и т.д.
Почему для себя я бы не стал это использовать... Сделано оно так, что должно находиться в коде скрита, а не подгружаться из отдельного файла. Это просто не удобно. К тому же мы получаем километровое название функции которое еще и правильно нужно написать. Поэтому для себя я сделал небольшие модификации.
Допиленный вариант
Код
local write, writeIndent, writers, refCount;
local persistence =
{
save = function (path, ...)
local file, e = io.open(path, "w");
if not file then
return error(e);
end
local n = select("#", ...);
-- Count references
local objRefCount = {}; -- Stores reference that will be exported
for i = 1, n do
refCount(objRefCount, (select(i,...)));
end;
-- Export Objects with more than one ref and assign name
-- First, create empty tables for each
local objRefNames = {};
local objRefIdx = 0;
file:write("-- Persistent Data\n");
file:write("local multiRefObjects = {\n");
for obj, count in pairs(objRefCount) do
if count > 1 then
objRefIdx = objRefIdx + 1;
objRefNames[obj] = objRefIdx;
file:write("{};"); -- table objRefIdx
end;
end;
file:write("\n} -- multiRefObjects\n");
-- Then fill them (this requires all empty multiRefObjects to exist)
for obj, idx in pairs(objRefNames) do
for k, v in pairs(obj) do
file:write("multiRefObjects["..idx.."][");
write(file, k, 0, objRefNames);
file:write("] = ");
write(file, v, 0, objRefNames);
file:write(";\n");
end;
end;
-- Create the remaining objects
for i = 1, n do
file:write("local ".."obj"..i.." = ");
write(file, (select(i,...)), 0, objRefNames);
file:write("\n");
end
-- Return them
if n > 0 then
file:write("return obj1");
for i = 2, n do
file:write(" ,obj"..i);
end;
file:write("\n");
else
file:write("return\n");
end;
if type(path) == "string" then
file:close();
end;
end;
load = function (path)
local f, e;
if type(path) == "string" then
f, e = loadfile(path);
else
f, e = path:read('*a')
end
if f then
return f();
else
return nil, e;
end;
end;
}
-- Private methods
-- write thing (dispatcher)
write = function (file, item, level, objRefNames)
writers[type(item)](file, item, level, objRefNames);
end;
-- write indent
writeIndent = function (file, level)
for i = 1, level do
file:write("\t");
end;
end;
-- recursively count references
refCount = function (objRefCount, item)
-- only count reference types (tables)
if type(item) == "table" then
-- Increase ref count
if objRefCount[item] then
objRefCount[item] = objRefCount[item] + 1;
else
objRefCount[item] = 1;
-- If first encounter, traverse
for k, v in pairs(item) do
refCount(objRefCount, k);
refCount(objRefCount, v);
end;
end;
end;
end;
-- Format items for the purpose of restoring
writers = {
["nil"] = function (file, item)
file:write("nil");
end;
["number"] = function (file, item)
file:write(tostring(item));
end;
["string"] = function (file, item)
file:write(string.format("%q", item));
end;
["boolean"] = function (file, item)
if item then
file:write("true");
else
file:write("false");
end
end;
["table"] = function (file, item, level, objRefNames)
local refIdx = objRefNames[item];
if refIdx then
-- Table with multiple references
file:write("multiRefObjects["..refIdx.."]");
else
-- Single use table
file:write("{\n");
for k, v in pairs(item) do
writeIndent(file, level+1);
file:write("[");
write(file, k, level+1, objRefNames);
file:write("] = ");
write(file, v, level+1, objRefNames);
file:write(";\n");
end
writeIndent(file, level);
file:write("}");
end;
end;
["function"] = function (file, item)
-- Does only work for "normal" functions, not those
-- with upvalues or c functions
local dInfo = debug.getinfo(item, "uS");
if dInfo.nups > 0 then
file:write("nil --[[functions with upvalue not supported]]");
elseif dInfo.what ~= "Lua" then
file:write("nil --[[non-lua function not supported]]");
else
local r, s = pcall(string.dump,item);
if r then
file:write(string.format("loadstring(%q)", s));
else
file:write("nil --[[function could not be dumped]]");
end
end
end;
["thread"] = function (file, item)
file:write("nil --[[thread]]\n");
end;
["userdata"] = function (file, item)
file:write("nil --[[userdata]]\n");
end;
}
return persistence
Пример использования:
Код
local tableToFile = require[[luaPlugins\tableToFile]] -- объявляется один раз в начале скрипта.
-- Объявляем массив
local arr = {10,9,8,7,6,5,4,3,{21,22,23,"'}\"\t\'",{}},1,0}
-- Сохраняем массив
tableToFile.save("1.txt",arr)
-- Закгружаем массив
arr2=tableToFile.load("1.txt")
Изменения оригинального кода - минимальные. Просто теперь можно спокойно подгрузить одной строкой, а не таскать весь код каждый раз за собой. Ну и store нам save поменял.
DarkMaster
25.10.2018, 8:54
Предчувствуя следующий вопрос:
Отобразить содержимое таблицы
Код
local function lg(data, comment)
if comment ~= nil then
log(comment)
end
local tab = ""
local deep = 0
local function show(data)
-- Пишем в лог комментарий.
deep = deep + 1 -- Уровень вложенности вызовов функции.
if type(data) == "table" then
local element_counter = 0
for k,v in pairs(data) do
element_counter = element_counter + 1
if type (v) == "table" then
log(tab..'table: '..k)
tab = tab .. " "
show(v)
tab = string.sub(tab, 1, -5)
else
if type(v) == "nil" then v = "nil"
elseif type(v) == "string" then v = '"' .. v .. '"'
elseif type(v) == "number" then v = tostring(v)
elseif type(v) == "function" then v = tostring(v)
elseif type(v) == "thread" then v = tostring(v)
elseif type(v) == "userdata" then v = "userdata"
elseif type(v) == "boolean" then v = tostring(v)
elseif type(v) == "table" then
log(tab..""..k.." = "..v or "nil")
else
v = "uknown data type"
end
log(tab..""..k.." = " .. v)
end
end
log("Elements in table: " .. element_counter)
else
log('table is "' .. type(data) .. '" data type. Value: ' .. tostring(data))
end
-- Пишем в лог комментарий.
deep = deep - 1 -- Уровень вложенности вызовов функции.
end
show(data)
end
Выдернуто куском из кода, там чуть лишнего есть. Использование:
lg(table, "комментарий")
Комментарий можно не писать.
Спасибо большое парни! Оба здорово помогли мне. Сделал средний вариант, не так сложно как у Дарка, но с поддержкой двумерных строково-числовых массивов. И на будущее ещё много чего понял. Ещё раз спасибо.
DarkMaster
26.10.2018, 0:36
Цитата
Сделал средний вариант, не так сложно как у Дарка
Смысл в том, что это делать уже не надо - оно уже сделано. Достаточно просто подключить. В итоге получается обыкновенная функция, а что там внутри наворочено вам и не нужно знать по большому счету.
Дарк, а есть такая возможность получить некий результат в виде переменной из скрипта Lua в обычный скрипт? Или только через файл. Замечание я принял, спасибо. Но я всё люблю попробовать сам и понять как это работает, так сказать на всякий случай, в целях самообразования. Просто читаешь иногда посты, там говорят что мол это невозможно, а начинаешь пробовать и всё получается. Вот не помню уж где-то видел, что нельзя анализировать звук, а я анализирую без проблем.
DarkMaster
26.10.2018, 14:25
Цитата
Дарк, а есть такая возможность получить некий результат в виде переменной из скрипта Lua в обычный скрипт?
Нет. И подозреваю, что даже между запущенными на луа скриптами будет определенная проблема передать данные. Изначально там была глобальная область видимости для глобальных переменных, т.е.
local a = 10 -- видно в пределах вкладки
a = 10 -- видно из любой. Но т.к. это приводило к катастрофам - все было разделено.
Так что только файликами. В луа думаю можно поискать дллки чтобы с ком портами работать, но в стандартном синтаксисе это только плагин писать либо какими-то невероятным костылями со сторонними exe, и может буфером.
Про звук поделиться не хотите?
WKnight
26.10.2018, 14:35
Цитата
а есть такая возможность получить некий результат в виде переменной из скрипта Lua в обычный скрипт?
Теоретически есть. А смысл?
Смысла нет, просто скрипт огромный, хотел частями попробовать, так что проехали.
А про звук ... Ну программер из меня хреновый, а вот придумывать я мастак. Сначала хотел всё делать "по уму", но как я уже сказал, программер из меня... Поэтому сделал просто. Вывожу микшер куда мне надо (засунул на второй монитор в самый низ). А потом всё тем же Файндом просто контролирую шкалу громкости. Как минимум длительность звука и его пиковые пороги контролировать элементарно. Теоретически можно и синусоиду контролировать, тогда нужно чтобы постоянно висела какая-нибудь программулина, но это уж точно изврат.
Файнды - ЭТО СИЛА. Думаю в Lua всё будет "летать" и я никаких проблем и ограничений для себя не вижу. Ещё раз спасибо Кнайту. Несмотряна то, что я нищий, если заведу себе яндекс деньги, то отблагодарю.
С одним монитором в полноэкранном режиме естественно не прокатит. А меня вполне устраивает. А по уму надо как я понимаю плагин прикручивать. Только как вытащить туда звуки системы я не знаю, но теоретически однозначно можно. Микшер то вытаскивает ...
В башке "месиво" сплошное от всех этих языков, тяжко продвигается. То set поставлю, то вместо "==" одиночное "=", то then забуду. Залез тут как-то в Делфи, про begin-ы и точки с запятыми забываю, ну там быстро напоминают, ещё до компиляции. Никаких стандартов, каждый норовит своё придумать, ладно хоть Escape у всех одинаково работает, а вот уже с Enter-ом проблемы встречаются. По уму должны перевод строки приклеивать, но это не факт.
olduo.com
27.10.2018, 0:51
Цитата(sutra @ 26.10.2018, 16:49)
В башке "месиво" сплошное от всех этих языков, тяжко продвигается. То set поставлю, то вместо "==" одиночное "=", то then забуду. Залез тут как-то в Делфи, про begin-ы и точки с запятыми забываю, ну там быстро напоминают, ещё до компиляции.
проблема в том, что твое месиво в башке ты не знаешь углубленно =)
не забывай ставить ; в луа, это удобно если не знаешь на чем будешь кодить завтра =) из личного опыта)
а так луа это школьный язык, его там нужно вместо паскаля и бесика преподавать)
DarkMaster
27.10.2018, 1:59
Цитата
а так луа это школьный язык, его там нужно вместо паскаля и бесика преподавать)
И да и нет. Пока не лезешь в классы и метатаблицы - да. И вопрос не в том, что это что-то невероятно сложное, тут скорее проблема читаемости и понимания структуры кода. В рамках луа, который гибкий просто до безобразия в свой функциональщине, считаю использование классов нежеланием переучиваться плюсовиков.
Cockney
27.10.2018, 12:44
Цитата
считаю использование классов нежеланием переучиваться плюсовиков.
Да вот только сам по себе луа пустой. Его сфера применение - встраивание. И как бы если луа может реализовывать классы, то не факт что те же плюсы смогут реализовать фичи луа (имеется ввиду из коробки). Да и к тому же, есть устоя́вшиеся нормы и правила написания софта. Класс - удобно, красиво, хоть иногда и громоздко. А луа сегодня есть, завтра нет...отсюда как бы еще и вытекает вопрос а зачем собственно и переучиваться на луа и вникать в него, если он не востребован практически нигде(по сравнению с питоном, js и другими) ?
DarkMaster
27.10.2018, 14:00
Цитата
Да вот только сам по себе луа пустой.
Классы этого никак не меняют.
Цитата
Его сфера применение - встраивание.
И справляется на самом деле очень неплохо. Тем не менее есть те же сокеты, биндинги под wxWidgets и Qt. Т.е. на нем пишут. Его распространненость скорее следствие работы не шибко большой группы и отсутствия макетинга. Это не Google который штампует языки и на них _будут_ писать вне зависимости от качества продукта.
Цитата
Класс - удобно, красиво, хоть иногда и громоздко.
Тут холивар может быть очень большим. Я не сторнник ооп. Да, оно бывает в определенных ситуациях нужно, но количество этих ситуаций и количество "написал на классах потому, что модно и современно" я не считал. Для меня очень неожиданно было, когда случайно наткнутся на статистику кода в линях: кода на чистом си оказалось в 2.5 раза больше, чем на плюсах. Заставило задуматься на самом деле.
Цитата
А луа сегодня есть, завтра нет...отсюда как бы еще и вытекает вопрос а зачем собственно и переучиваться на луа и вникать в него, если он не востребован практически нигде(по сравнению с питоном, js и другими) ?
У него есть своя ниша в которую он плотно засел - геймдев. Сейчас по сути он там стандарт. Тот же wow по части аддонов полностью на нем написан (это просто дикий объем кода - их сотни тысяч), GTA вся логика на lua описывается. Причем если вов был изначально такой, то переход на lua такой большой корпорации, как Rockstar не мог не быть тщательно взвешан. Так же в обработке траффика его частенько используют - nginx, wireshark. Это маркеры. Серьезные проекты и встаривание в них было вполне успешным. Да, язык не топ популярности, но ниша занята, его там никто не теснит, а нужное он делает на 5.
Зачем переучиваться? Ну я, например, знаю одну студию разработки в которой плюсовики нафигачили кода с классами и кучей переназначений в метатаблицах. Т.е. использовали возможности языка на все 100%. Вот только когда приходишь со своим самоваром в другой язык, то не очень хорошо получается в плане результа. Потом команда сильно разосралась, т.к. натуральным луашникам этот изврат не очень нравился, а плюсовикам было все пофигу и пальцы веером. В итоге выкинули всех за не совсем адекватность, уже год ищут луашников именно для переписывания всей этой крутоты на классах. Обрывки кода видел лично - искать где, что править в 10 раз переназначенных метаблицах полный бред. Это нужно делать либо тому человеку, который это писал, либо сидеть с маном в котором вся структура чуда. Луа не святой, есть свои огрехи, си я уважаю больше, асм еще больше, но у всего есть ниша и причины почему ни один язык не стал универсальным и доминирующим везде. Это я все к чему - со своим самоваром не стоит =)
Cockney
27.10.2018, 14:48
Цитата(DarkMaster @ 27.10.2018, 14:00)
Классы этого никак не меняют.
И справляется на самом деле очень неплохо. Тем не менее есть те же сокеты, биндинги под wxWidgets и Qt. Т.е. на нем пишут. Его распространненость скорее следствие работы не шибко большой группы и отсутствия макетинга. Это не Google который штампует языки и на них _будут_ писать вне зависимости от качества продукта.
Как бы меняют, ведь qt и виджеты являются ооп (или нет ?). Если бы не поддержка ооп из коробки, он бы загнулся в самом начале.
Цитата
Тут холивар может быть очень большим. Я не сторнник ооп. Да, оно бывает в определенных ситуациях нужно, но количество этих ситуаций и количество "написал на классах потому, что модно и современно" я не считал. Для меня очень неожиданно было, когда случайно наткнутся на статистику кода в линях: кода на чистом си оказалось в 2.5 раза больше, чем на плюсах. Заставило задуматься на самом деле.
это про линуксы ? Статистика чего ? Ядра ? Ну тогда не удивительно, что там си больше. printf быстрее потоков раза в 3 если не больше. А попробуй вывести через него сложную структуру, класс. Неудобно, не так ли ?
Цитата
У него есть своя ниша в которую он плотно засел - геймдев. Сейчас по сути он там стандарт. Тот же wow по части аддонов полностью на нем написан (это просто дикий объем кода - их сотни тысяч), GTA вся логика на lua описывается. Причем если вов был изначально такой, то переход на lua такой большой корпорации, как Rockstar не мог не быть тщательно взвешан. Так же в обработке траффика его частенько используют - nginx, wireshark. Это маркеры. Серьезные проекты и встаривание в них было вполне успешным. Да, язык не топ популярности, но ниша занята, его там никто не теснит, а нужное он делает на 5.
Да никто и не спорит с этим. Только вот учить его чтобы попасть на одну из 2 вакансий в Москве (hh.ru), когда есть unity c# 360+ вакансий.....Это если говорить о реальной его пользе, а не уровне пилота. Конечно, на нем пишут, только где....
Цитата
Зачем переучиваться? Ну я, например, знаю одну студию разработки в которой плюсовики нафигачили кода с классами и кучей переназначений в метатаблицах. Т.е. использовали возможности языка на все 100%. Вот только когда приходишь со своим самоваром в другой язык, то не очень хорошо получается в плане результа. Потом команда сильно разосралась, т.к. натуральным луашникам этот изврат не очень нравился, а плюсовикам было все пофигу и пальцы веером. В итоге выкинули всех за не совсем адекватность, уже год ищут луашников именно для переписывания всей этой крутоты на классах. Обрывки кода видел лично - искать где, что править в 10 раз переназначенных метаблицах полный бред. Это нужно делать либо тому человеку, который это писал, либо сидеть с маном в котором вся структура чуда. Луа не святой, есть свои огрехи, си я уважаю больше, асм еще больше, но у всего есть ниша и причины почему ни один язык не стал универсальным и доминирующим везде. Это я все к чему - со своим самоваром не стоит =)
Не стоит. А еще не стоит ставить человека на луа проект, который знает только c++.
Ради интереса зашел на одну из вакансий по луа:
Цитата
Для этого необходимо:
Опыт разработки на C#/C++
Опыт разработки на Android платформе: SDK, NDK
Английский язык - технический
Умение работать в команде
Желание работать в игровой индустрии
Желание и способность учиться
Необходимо знание языка LUA
И вот риторический вопрос, а зачем знание плюсов, да еще и тем более шарпов (где все классы) луашнику ? Сам по себе луа самодостаточен. Модули, метатаблицы - все что хочешь. Никак работодатель желает биндить классы (ведь для этого нужен опыт шарпа ?) через луа ?
Во какую тему замутил. А я вот со своим дилетантским взглядом считаю так, что если мне нужно вбить колышек, я беру кувалду, пару раз стукну и всё, а не вызываю машину для забивки свай. 99% пользователей Пилота "забивают колышки". Здесь не игрушки пишут и не рассчитывают турбулентность. Поэтому овчинка должна стоить выделки. Зачем мне тратить уйму времени и забивать голову ненужной информацией если нужно выполнить примитивнейшие действия. Лично для меня язык Пилота был абсолютно понятен сразу на 100%. И я быстро разберусь с любым скриптом, если будут адекватные имена переменных. С Lua намного сложней, там уже нужно частенько вникать подробно и с ходу в чужом коде можно мозги вывихнуть. Для меня Пилот, просто полезный и лёгкий в освоении инструмент. И меня практически всё в нём устраивает, но возникло пару моментов, где не хватает быстродействия, вот и решил перейти на Lua , но придётся потратить немало времени.
DarkMaster
27.10.2018, 17:08
Цитата
Как бы меняют, ведь qt и виджеты являются ооп (или нет ?).
Насколько я понял там вообще пофигу ибо линкуется там все через очередь и пушится каждый параметр. Что есть дикий минус ибо дллки нужно обертывать весьма своеобразно и спокойно ту же сишную либу не подключишь. Так что едва ли =)
Цитата
И вот риторический вопрос, а зачем знание плюсов, да еще и тем более шарпов (где все классы) луашнику ? Сам по себе луа самодостаточен. Модули, метатаблицы - все что хочешь. Никак работодатель желает биндить классы (ведь для этого нужен опыт шарпа ?) через луа
Ну собственно ответ выше. Да и как бы начали с того, что это встраиваемый язык. Встраивать то его тоже надо =) А вот что там классы или не классы суть не важно.
Цитата
Лично для меня язык Пилота был абсолютно понятен сразу на 100%.
И да и нет. Честно? Разницы по сложности - ноль. Самого языка. Вот когда на грабли вставать будете - поймете, что луа намного проще) Разница в том, что луа в рамках пилота не настолько интегрирован. Те же записи/чтения файла. Не так много людей идут на луа (очень зря кстати), а те кто идут зачастую не считают проблемой самим написать такие вещи. Это недоработки интеграции. Пилот 20 лет почти вылизывался, луа - год. Ну и примеров совсем другое количество. Cirus вон какую сказку с допиливанием вики сделал. Для луа этого просто нет. Мне - это не нужно, я и так сориентируюсь по старым примерам, а человеку который только вникает и не имеет опыта программирования - это сложно. Грубо говоря не обжитой он просто.
olduo.com
27.10.2018, 18:17
Цитата(Cockney @ 27.10.2018, 14:48)
Ради интереса зашел на одну из вакансий по луа:
Цитата
Для этого необходимо:
Опыт разработки на C#/C++
Опыт разработки на Android платформе: SDK, NDK
Английский язык - технический
Умение работать в команде
Желание работать в игровой индустрии
Желание и способность учиться
Необходимо знание языка LUA
И вот риторический вопрос, а зачем знание плюсов, да еще и тем более шарпов (где все классы) луашнику ? Сам по себе луа самодостаточен. Модули, метатаблицы - все что хочешь. Никак работодатель желает биндить классы (ведь для этого нужен опыт шарпа ?) через луа ?
хороший пример, именно потому что из игровой индустрии. большинство серверов с которыми работал в качестве скриптового движка используют луа, но не всегда все его возможности. обычно это просто серверный хук, который вызывает обработку в скрипте. потом ты уверен, что это вакансия луашника? ну т.е. если это серверный программист, то тебе нужно и "Опыт разработки на C#/C++" и "Необходимо знание языка LUA". если это луашник, то согласен, опыт в остальном второстепенен. я както тут писал про пацаньчика, которого взял на серверный луа.
Я попробовал и даже простейшую функцию не смог сделать в Lua. Что-то не так с видимостью. А что не так пока не понимаю.
Цитата
Я попробовал и даже простейшую функцию не смог сделать в Lua.
Выкладывайте код, поправим.
Для примера:
Код
--lua
-- функция должна находится выше её вызова
function f(x, y) -- принимает 2 параметра
return x+y -- возвращает сумму
end
local z=f(5, 6) -- вызов функции
log (z)
Не смог реализовать goto как только не пробовал, даёт ошибку.
Такая и у меня работает. Мне нужно передать в неё переменную, там с ней выполняются действия и мне нужна модифицированная ПЕРЕМЕННАЯ. А точнее таблица.
То есть я должен передать в функцию таблицу.
Хотя и с обычной переменной ничего не получилось.
Надо типа такого, чего не работает.
--lua
function proba(a)
return a = 12
end
log "clear"
local zz = 5
local tt = proba(zz)
log(tt)
если без return то в основном теле будет nil
Цитата
Не смог реализовать goto
Лучше сразу забудьте про него.
Код
--lua
function proba(a)
a = 12
return a
end
log "clear"
local zz = 5
local tt = proba(zz)
log(tt)
Код
--lua
log "clear" log "mode compact"
function f(arr2)
for i=1, #arr2 do
arr2[i]=arr2[i]*2 -- умножить все элементы на 2
end
end
local arr={}
for i=1, 10 do -- заполнить массив числами от 1 до 10
arr[i]=i
end
log (table.concat(arr, " ")) -- содержимое массива
f(arr) -- вызов функции
log (table.concat(arr, " ")) -- содержимое массива после вызова функции
Спасибо. То есть goto не работает??
Цитата
То есть goto не работает??
Нет. Он и не нужен.
В луа его вообще нет. Вроде как есть в луа 5.3.
Меня конечно учили в своё время, что goto использовать является минимум признаком дурного стиля, но иногда это сильно упрощает код.
Всё верно, именно Lua 3 я и смотрел.
Буду думать, если не смогу модифицировать скрипт без goto придётся отказаться от Lua.
Да, конечно можно без goto , но придётся городить огород с кучей while-ов код будет ужасно плохо читаемым. У меня goto использовался например для рестарта скрипта в случае отключения интернета, ну и ещё в 2-х критических случаях, придётся всё заключать в циклы и брейками прерывать скрипт.
DarkMaster
28.10.2018, 2:11
Цитата
Да, конечно можно без goto , но придётся городить огород с кучей while-ов код будет ужасно плохо читаемым. У меня goto использовался например для рестарта скрипта в случае отключения интернета, ну и ещё в 2-х критических случаях, придётся всё заключать в циклы и брейками прерывать скрипт.
Как правило подобные проблемы говорят о том, что изначально структура кода не очень хорошо продумана.
Цитата
Всё верно, именно Lua 3 я и смотрел.
У нас luajit - стабильный релиз которого соответсвует версии 5.1. Это форк с динамической компиляцией, который существенно шустрее в работе. Сейчас он, пожалуй, более распространен, чем оригинальный луа. Можно смело исользовать мануалы от 5.1.
А оператор continue в цикле while есть?
Это очень нехорошо. Если честно, то я не понимаю. С одной стороны типа прогрессивная вещь, а с другой стороны вроде очевидных вещей нет. Придётся буквально весь код запихивать в функции, которые будут содержать куски кода без особой логики. Видимо придётся их так и называть blok01 .. blok77. А основное тело будет состоять из вызова этих кусков. Просто в моём случае десятки раз вызывается функция обработки ошибок и обработки возникших неадекватных ситуаций. Собственно там и были goto которые перенаправляли код на повторные действия. Так что придётся работать брейками и кусками с ретурнами.
DarkMaster
29.10.2018, 4:29
Код
while var > 1 do
local result = check_some_params()
if result then
some_actions()
end
end
данная конструкция позволит сделать логику аналогичную continue. Согласен, это немного неудобно, непривычно, тем не менее так писать можно и костылей получается избежать. Читаемость кода при этом вполне адекватная.
Цитата
Придётся буквально весь код запихивать в функции,
Он там и должен быть. Весь. Не в функциях у тебя может быть какая-то инициализация (подгрузка параметров из файла настроек, например, или массивов). Кроме этого у меня не в функции вот такая строчка:
main()
Т.е. вызов основной функции. Больше там ничего и не должно быть.
Цитата
Видимо придётся их так и называть blok01 .. blok77
А вот так делать не надо. Уверяю можно найти нормальное решение.
Цитата
В луа нет continue.
5.3, но, в классическом 5.1 нет, ну и в luajit релизе тоже нет.
Спасибо Дарк. Но у меня так не получится. Допустим у меня проверка в 4-ом колене ветвления if . После проверки происходит дальнейшее выполнение кода в этом же ИФе. То есть проверить и по результатам что-то выполнить - это не требуется, а наоборот в обязательном порядке прекратить выполнение кода (ну глупо что-то выполнять если отключили интернет или сервер недоступен) и в данном примере идти почти в самое начало скрипта и крутить цикл пока не появится связь с сервером. Поэтому выход вижу только один всё пихать в функции. После проверки выполнять return из функции, а вот весь остальной код придётся запихивать в if. И таких ифов до конца всего кода будет ну с десяток точно.
Слишком сложный код. никакого линейного выполнения кода нет. Всё постоянно меняется, поэтому много проверок всяких. Управление конечно попытался упростить насколько смог. Всё управляется несколькими десятками файлов конфигурации. А файлами конфигурации управляет файл сценария. Хотя и сценарий тоже может изменяться по ходу скрипта. В итоге ну полная иллюзия, что играет живой человек. Игра выполняется хоть круглые сутки и нет повторения событий. Я только контролирую и занимаюсь не ерундой, а пытаюсь ещё и чем-то полезным заниматься.
По логике у тебя тоже всё правильно. Собственно так примерно и будет, только эти вайлы будут как снежный ком. И формат уедет настолько сильно вправо, что код будет плохо читаемым. Буду как-то сочетать. Что-то сделаю локальным распихав по функциям, что-то придётся умещать в одном блоке кода.
Грубо говоря есть определённое количество событий, которые могут вызываться один из другого. И простыми вызовами функций я могу получить неконтролируемую рекурсию. Поэтому в Пилотовском коде я и использовал goto. Тут придётся крепко репу почесать, чтобы было красиво и эффективно.
local n = "123.txt"
local f = io.open(n, "r")
Не смог открыть файл при помощи переменной. Перепробовал всё что знал - результат нуль. Просветите меня пожалуйста. Что-то мне подсказывает, что намаюсь я ещё. И большая просьба в примерах показывайте работу с переменными, поскольку у меня всё только через переменные.
DarkMaster
29.10.2018, 14:44
Цитата
Не смог открыть файл при помощи переменной
А лежит он где? Рядом с ехе пилота? Пилот перезапускали?
По поводу break можно делать вызов функции через assert и внутри функции потом вызывать ошибку, это приведет к ее завершению.
Тем не менее не забывайте про return. При раскидывании по функциям он зачастую полноценно заменяет break.
Обычным текстом открывает [[123.txt]]
Минутку, теперь и обычным не открывает, сейчас гляну.
Доигрался, вообще Пилот завис.
Цитата
вообще Пилот завис.
Скорее всего были какие-то ошибки.
Код
--lua
local n = "123.txt" -- файл лежит рядом с exe пилота
local f = io.open(n, "r")
log "clear" log "mode compact"
if f then -- если файл открылся
log(f:read()) -- первая строка из файла
else
log ("Файл не открылся")
end
Перегрузил Пилот через прибивалку, всё заработало, спасибо Дарк.
Видимо крепко я накуралесил, да ещё и игра играет в параллельном скрипте.
И тебе cirus тоже спасибо.
Теперь буду знать, что иногда надо пнуть ногой по баллону.
Понял причину, забыл поставить двойной слеш при указании полного пути.
DarkMaster
29.10.2018, 18:00
Цитата
Понял причину, забыл поставить двойной слеш при указании полного пути.
Не редактируйте код перед тем, как выложить. Ну либо тестируйте перед тем, как выкладывать =)
Чтобы не писать двойные слэши просто ставьте вместо кавычек [[текст]]
Я не редактировал. Просто сначала использовал полный путь. Потом пути были без слешей и не работало только с переменной, потом вообще не работало, причину Вы мне подсказали (перегрузить).
Я понял почему изначально не работало.
DarkMaster
30.10.2018, 5:31
Цитата
причину Вы мне подсказали (перегрузить).
это фиксанули буквально пару дней назад
Добрался до файндов. и как и думал ничего у меня не получилось. Не могли бы кинуть реальный пример findimage. Хотел потестировать косяк. Параметры интересуют когда есть адрес загруженной картинки и адрес области экрана. И думаю, что и с findcolor тоже сам не врублюсь, поэтому и его примерчик тоже неплохо бы самому поглядеть.
И конечно примеры на lua "надёжно" зарыты. Через спецстраницы, через страницы-сироты. Но и там есть далеко не всё, а если бы было, то дилетанты типа меня не донимали бы элементарными вопросами.
Цитата
реальный пример findimage
Код
--lua
local a, c = findimage(0, 0, 1920, 1080, {[[C:\Users\abc\Desktop\image.bmp]]}, 2)
-- a - это массив, c - количество картинок или точность поиска, если картинка одна
if a then
move(a[1][1], a[1][2])
end
Цитата
findcolor
Вроде как не доделан. Поэтому костыль. Передавать все параметры в виде строки.
Код
--lua
local a = findcolor("0, 0, 1920, 1080, 1, 1, 7223552, 2")
hint (a)
Цитата
примеры на lua "надёжно" зарыты
http://uopilot.tati.pro/index.php?title=Список_функций_(Lua)Только то, что работает в 2.40 (релиз, а не бета).
Спасибо.
Цитата
Только то, что работает в 2.40 (релиз, а не бета).
Так я и говорю надёжно спрятано. Я случайно туда попал. Надо бы прямую ссылочку сделать.
Цитата
Надо бы прямую ссылочку сделать.
Когда выйдет полноценная версия пилота на луа, тогда и будет дописана (где-то исправлена) справка и дана ссылка.
--lua
log "clear" log "mode compact"
addressl, widthl, heightl, lengthl = loadimage ([[C:\TMP\Original.bmp]])
log(widthl, heightl, lengthl)
addressg, widthg, heightg, lengthg = getimage (470, 924, 500, 933)
log(widthg, heightg, lengthg)
local a, c = FindImage(0, 0, 1920, 1080, addressl, addressg, 100)
deleteimage (addressl)
deleteimage (addressg)
Не работает, дает ошибку.
Сорри, забыл на строчные переделать. Спасибо.
Да, в findimage есть баг, если искать на скрине от координат 0 0, то нормально ищет. Иначе не находит.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста,
нажмите сюда.