Dennis_Chikin 3 658 Опубликовано 4 Января 2015 Поделиться Опубликовано 4 Января 2015 (изменено) С чего начинать и где взять. Установка Lua:http://www.amk-team.ru/forum/index.php?showtopic=11584&p=629106 Руководство «Программирование на языке Lua», третье издание:http://www.amk-team.ru/forum/index.php?showtopic=11584&p=905308 Изменено 2 Марта 2015 пользователем Kirgudu Солянка обезжиренная, диетическая, полезные советы по "солянке", текущий тестовый патч Ссылка на комментарий
Viнt@rь 50 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 xStream, по поводу классов - да ты права, в той схеме, что я выложил, он вообще не нужен, но! это ведь никак не влияет на игру или работу скрипта, да и к тому же лично мне, как-то приятней видеть все в под одним классом, нежели видеть "голые функции", пусть даже каждая схема - отдельный скрипт... Такие схемы бросаются в глаза как сборник функций..., а объединяя эти функции под одним классом, сразу становится видно какие функции связаны между собой, ну это мое ИМХО, это уже кому как... Я так привык, мне так удобней, потому и пользуюсь таким методом, но, еще раз повторюсь, я с тобой полностью согласен - класс здесь не нужен... Потому я и спрашивал влияет ли такой метод на что то или нет... GUI для конвертера от бардака(всего и вся в форматы сдк) Полезный утиль-"Utilits pack(mod)" Ссылка на комментарий
Nazgool 250 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 Примерно так : --[[ P.S. 1. Функции save и load нужно переписать для сохранения в пакете 2. Защитами "от дурака" я не заморачивался. Оставил "на потом" 3. Естественно все числа секунд для сталкера нужно перевести в миллисекунды. Само собой и функции типа os.time , io... ]] ----------------------------------- -- типа экшены по завершению работы таймеров в каких-то файлах или в глобалке. Удалить нах. function Action1() print('Action1') end function Action2() print('Action2') end function Action3() print('Action3') end function Action4() print('Action4') end ----------------------------------------- --[[ В данном варианте подразумевается использование таймеров в глобальном контексте. Поэтому модуль таймеров таймеров можно записать в любой файл, расположенный в любом месте с произвольным расширением кроме script. В файле _g.script нужно добавить загрузку модуля : local f = loadfile('путь в модулю таймеров') setfenv(f, _G) f() 'путь в модулю таймеров' - можно указать либо посредством FS, либо напрямую. ]] ---------------------------------------- -- Модуль таймеров _timer = {} local updateTime = 0 function _timer:_init() self.__index = self self.timers = {} setmetatable(self.timers, _timer) end _timer:_init() function _timer:sort() table.sort(self.timers, function (a,b) return a.complete < b.complete end) self:updateID() end function _timer:stop() local ostime = os.time() self.remain = (self.complete or ostime) - ostime self.complete = math.huge _timer:sort() end function _timer:isRunning() return self.remain == nil end function _timer:start() self.complete = os.time() + (self.remain or 0) self.remain = nil _timer:sort() end function _timer:save() local file = io.open('C:\\save_test.ini','w') local tab = self.timers local w = {} for i = 1, #tab do local t = {} for k,v in pairs(tab[i]) do local pos if k == 'name' then pos = 1 elseif k == 'time' then pos = 2 elseif k == 'act' then pos = 3 elseif k == 'period' then pos = 4 elseif k == 'complete' then pos = 5 elseif k == 'remain' then pos = 6 else pos = nil end if pos then t[pos]=v end end if t[3] == nil then t[3] = '@' end table.insert(w,table.concat(t,' ')) end local s = table.concat(w,'|') file:write(s) file:close() end function _timer:load() self.timers = {} local file = io.open('C:\\save_test.ini','r') local s = file:read() for w in s:gmatch('[^|]+') do local t = {} for c in w:gmatch('%S+') do table.insert(t,c) end if t[5] == '1.#INF' then t[5] = math.huge end if t[3] == '@' then t[3] = nil end local timer = self:create(t[1], t[2] , t[3], t[4], tonumber(t[5])) if t[6] then timer.remain = t[6] end end file:close() end -- пока выключить. Нужно сохранить первоначальную функцию (act для функций changeAction и changeActionTime). -- Проще пересоздать снова --[[function _timer:restart() local name = self.name local sec = self.time local act = self.act local per = self.period self:kill(self.id) self:create(name, sec, act, per) end]] function _timer:getRemainTime() return self.complete - os.time() end function _timer:changeAction(act) self.act = act end function _timer:changeActionTime(time) self.complete = self.complete + time if self.remain then self.remain = self.remain + time end self:sort() end function _timer:setUpdatePeriod(per) self.period = per end function _timer:kill(n) local pos = n or self.id if self.name then _G[self.name] = nil end table.remove(self.timers, pos) self:updateID(pos) end function _timer:updateID(start_pos) start_pos = start_pos or 1 local t = self.timers for i = start_pos, #t do t[i].id = i end end function _timer:runAction() local action = self.timers[1].act return action and _G[action]() end function _timer:timerCreate(name, time, act, per, comp) if type(name) == 'number' then per = act act = time time = name elseif type(act) == 'number' then per = act act = nil end time = time or 0 per = per or 0 -- тут в сталке 0 изменить на 1000 (мс - т.е. 1 сек. по умолчанию) local complete = comp or os.time() + (time or -1) return { handler = function () local ostime = os.time() local t = self.timers[1] if ostime >= t.complete then self:runAction() self:kill(1) return true end updateTime = ostime + t.period return false end , name = name , time = time , complete = complete, period = per , act = act } end function _timer:timerAdd(...) local timer = self:timerCreate(...) table.insert(self.timers, timer) _timer:sort() return timer end function _timer:create(...) local obj = _timer:timerAdd(...) _G[obj.name] = obj setmetatable(obj, _timer) return obj end function _timer:action() return self.id == 1 and self.handler() end function _timer:update() -- Эту функцию на апдейт в binder actor-а. if os.time() >= updateTime then local t = self.timers[1] if t and not t.remain then t:action() end end end --------------------------------------- -- Тест _timer:create('t1', 4) _timer:create('t2', 3,1) _timer:create('t3', 6,'Action2') _timer:create('t4', 1,'Action3',1) _timer:create(2,'Action1',1) _timer:create(5,'Action4') ------------------------------------------ -- Эмуляция апдейта while _timer.timers[1] and not _timer.timers[1].remain do _timer:update() end Ссылка на комментарий
Viнt@rь 50 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 (изменено) Gun12, а что, если несколько таймеров запущено одновременно? Изменено 8 Января 2012 пользователем Viнt@rь GUI для конвертера от бардака(всего и вся в форматы сдк) Полезный утиль-"Utilits pack(mod)" Ссылка на комментарий
Nazgool 250 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 (изменено) Обрабатывается только один. Тот у которого ближайшее время срабатывания. Это и есть главная фишка. Любой другой можно проверить при необходимости (если он динамический, т.е. имеет имя, а значит и поле в таблице _G) Изменено 8 Января 2012 пользователем Gun12 Ссылка на комментарий
Viнt@rь 50 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 (изменено) а если запущено 2 таймера в одно и то же время и одинаковой частотой апдейта и с одинаковым временем срабатывания?(вообще конечно, такие случаи редкость или легче создать 1 функцию и запихнуть туда все, что надо, дабы не создавать кучу таймеров, но всетаки...) первый таймер, по идее, проиграется во время, а второй с опозданием... Изменено 8 Января 2012 пользователем Viнt@rь GUI для конвертера от бардака(всего и вся в форматы сдк) Полезный утиль-"Utilits pack(mod)" Ссылка на комментарий
xStream 86 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 (изменено) Viнt@rь, вот я об этом и писала - "работает же" Конечно, переделывать глупо. Надо просто сразу делать с умом. Еще раз - приятней видеть одним классом. В чем приятность? В именах функций видеть имя класса? Сомнительный аргумент, на мой взгляд. Код можно грамотно оформить и без класса, обрамить комментариями, организовать блоки, сделать приватные функции и т.п. В идеологии сталкера нет "голых" функций. Ты их вызываешь, предварительно указав имя файла. Объединять надо функции семантически - один файл, один набор функций. Ты сам ведь понимаешь, что дело именно привычки. Но для меня главное, что ты понимаешь, что такое псевдо-ООП. Смею на это надеяться. Gun12, вопрос сразу - это ты делаешь ООП-like, или пользуешься свойством оператора ":" для доступа к "экземпляру"? Поясню, откуда этот вопрос. На самом деле "объект" у тебя тут всего лишь один, а остальное "настройки", которые хранятся в таблице. Поэтому такое решение претендовать на ООП никак не может. В целом "нарекания" вызывает функция timerCreate - много параметров, которые могут еще и меняться местами (разный набор настроек, я понимаю). Я бы порекомендовала либо использовать один параметр options (хеш-таблица) или использовать chain-calls, несколько методов для настройки, каждый из которых возвращает self. То есть сделать пошаговое создание, так сказать. Но для не объектов (в контексте именно инстансов - у тебя их нет) это не очень удобно. Если кратко - сделай "говорящий" интерфейс: local t = timer():setAction(xxx):setPeriod(xxx):run() примерно так. Запись длиннее, но зато гораздо нагляднее, что происходит именно тут. К такому варианту еще провоцирует даже не количество параметров, а то, что они могут обозначать разное при разных наборах. Ну и, мне кажется, такой подход избавил бы от функций типа changeAction, что привело бы к упрощению интерфейса, а это всегда хорошо. Изменено 8 Января 2012 пользователем xStream Все, кто стоит на моем пути: идите нахрен и там погибните! © Ссылка на комментарий
Nazgool 250 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 (изменено) а второй с опозданием...Да я думал над этим... Когда будет большая необходимость изменю. На самом деле, на данном этапе, время срабатывания одного будет позже другого только на 1 апдейт. Это настолько критично? Если да, то буду исправлять. xStream Спасибо за совет. На ООП особо не претендую. Изначально хотел сделать меньше записей. Для того и рискнул выложить чтобы учиться (как максимум - всё-таки научиться ). Изменено 8 Января 2012 пользователем Gun12 Ссылка на комментарий
xStream 86 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 (изменено) Вдогонку - ты вполне можешь использовать замыкания для имитации "экземпляров объектов". Я за пару страниц до этого писала, что это за фигулина. В твоем случае, можно за селф принять как раз ту самую локальную переменную и этим пользоваться, аля: function createTimer(options) local self = ... тут создаем как у тебя набор настроек ... self.setAction = function() ... что-то делаем и возвращаем селф... return self end ... тут еще интерфейсные функции ... return self end То есть обернули твою таблицу настроек в интерфейс. Это просто как вариант. Пользуемся, как ты любишь, только "чистым" ЛУА Добавлено через 2 мин.: На ООП особо не претендую. Изначально хотел сделать меньше записей. Честно скажу - по мне вышло так наоборот более громоздко, если не пытаться все обернуть в такую вот таблицу. Надо проработать интерфейс - чем меньше методов, тем лучше, чем меньше параметров в них, тем тоже лучше. Говорю как архитектор приложений с пятилетним стажем (дада, надо ж похвастаться. Шутка). Просто с простыми вещами (внешне простыми) гораздо комфортнее работать, а код компактнее (опять же - не самих вещей, а тот код, где используются эти вещи) Изменено 8 Января 2012 пользователем xStream Все, кто стоит на моем пути: идите нахрен и там погибните! © Ссылка на комментарий
Nazgool 250 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 (изменено) xStream О замыкания знаю. Изначально функция timerCreate (и та, что сейчас под ключём handler в таблице) и была простым замыканием, но потом переделал в таблицу...Ну так вышло уж...Простите ------------------ Хорошо. Буду пытаться. Ещё раз спасибо за примеры и советы. Если будут ещё - "очень" не откажусь. Изменено 8 Января 2012 пользователем Gun12 Ссылка на комментарий
Viнt@rь 50 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 (изменено) xStream, Но для меня главное, что ты понимаешь, что такое псевдо-ООП. Смею на это надеяться. благодаря тебе - уже понимаю и да, все дело в уже приевшихся привычках Gun12, как я заметил(по "своим" таймерам) будет довольно таки весомым... Смотри пример: код простенький, но тут суть не столько в коде, как хоть каком-то наглядном примере... ЗЫ подправил код заметил, что пример фиговый))) local TimerTrigger=time_global()+1000 function aaa() if TimerTrigger-time_global()==0 then ... end end вот в таком виде, походу, все что после проверки условия "проиграется" только в 10% случаев, а то вообще не "проиграется", а это значит. что всегда гарантировано опоздание вызова, по примеру таймеров тех, что я выкладывал, я не спроста поставил вывод в лог разници между секундами после условия, а именно c целью отслеживать на сколько опаздывает функция, и это время всегда разное... в игровых секундах я получаю примерно такие значения -0,15*; - 0,25; к тому же не исключены фризы в игре при этом вызов опаздывает примерно на столько -7,00015* и тп и это все на 1 апдейте, если же еще считать, то что таймер вызовится на 1 апдейт позже, то смело можно умножать эти цифры на 2, ато и больше... ЗЫЫ пример приведен на основе глобального времени, цифры приведены на выводах основаных на игровом времени... но это не так важно, так как что так что так опоздание будет всеравно....в глобальном времени например к 1000 мс прибавляется до 100мс при работе без подвисаний, если было подвисание, то может быть и такое к 1000 мс около еще 3000 мс Изменено 8 Января 2012 пользователем Viнt@rь GUI для конвертера от бардака(всего и вся в форматы сдк) Полезный утиль-"Utilits pack(mod)" Ссылка на комментарий
xStream 86 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 Gun12 По идее, правильно делать так, чтоб при срабатывании одного таймера, тут же, помимо перестраивания таблицы, делалась снова проверка - а вдруг еще какой-то таймер сработать должен? В твоем коде это сделать довольно просто - принудительный вызов опять же _timer:update(). Минусы - чревато рекурсией, если таймеры таки сработают одновременно. Но учитывая реальне игровые условия, это маловероятно, а если и произойдет, то 1-3 одновременно (цифры с потолка, просто прикинула игровой процесс) максимум. Ну или для перестраховки ограничить количество рекурсий на один апдейт. Например, максимум 5 таймеров могут сработать. Остальные ждут следующего апдейта, судьба у них такая. Все, кто стоит на моем пути: идите нахрен и там погибните! © Ссылка на комментарий
Viнt@rь 50 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 (изменено) xStream, вот в таких случаях, ИМХО, и лучше использовать цикл, так как все прогоняется на 1 апдейте, НО! "голый" цикл на апдейте может быть причиной тех же фризов и тп, мое предожение сделать тип функций, в смысле "важная/неважная" функция, тоесть, если был запущен таймер функции с флагом "важная", то постоянно проверять истечение таймера для нее, если же неважная, то тогда всеравно, как часто ее проверять, можно хоть и раз в 5 сек(глобального времени, к примеру) ЗЫ идею берег для себя, но всетаки решил поделиться, заодно и узнаю, насколько она хороша) Изменено 8 Января 2012 пользователем Viнt@rь GUI для конвертера от бардака(всего и вся в форматы сдк) Полезный утиль-"Utilits pack(mod)" Ссылка на комментарий
Nazgool 250 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 По идее, правильно делать так, чтоб при срабатывании одного таймера, тут же, помимо перестраивания таблицы, делалась снова проверка - а вдруг еще какой-то таймер сработать должен?Блин, хотел же так и сделать, да подумал что вероятность ... Забыл? Лень? Не знаю. Сначала помнил что нужно это сделать, потом... как всегда. В общем я не и тестировал толком. Иначе по-любому обнаружил бы. Ссылка на комментарий
xStream 86 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 (изменено) Viнt@rь, ну у меня и используется цикл в той реализации, что я выкладывала. При срабатывании таймера, не только находим тот, который будет выполнен в следующий раз, но еще и смотрим, есть ли еще такие, что должны сработать сейчас? Если есть - отрабатываем их. Однако в реализации Gun12 это чревато нагромождением кода, лучше уж рекурсию допустить. Фризы же будут либо при тысячах таймеров, одновременно срабатывающих, либо если они дергают "тяжелые" колбеки. В реальности ни того, ни другого на практике нет. Если же случится такая ситуация, то это явный признак того, что в программе явно что-то не так и надо заняться ее ревизией Идея с флагом по сути оптимизация, но преждевременная. Надо стараться оценивать реальные ситуации, в которых этот код будет работать. В случае появления проблем делаются тесты, замеры и тогда уже делается оптимизация. Практика показывает, что оптимизировать надо зачастую совсем не там, где ты ожидаешь Добавлено через 4 мин.: Тема, кстати, тоже хорошая - циклы vs рекурсия. Выбор должен определяться условиями и окружением твоего кода, а не личными предпочтениями. Имхо. Изменено 8 Января 2012 пользователем xStream Все, кто стоит на моем пути: идите нахрен и там погибните! © Ссылка на комментарий
xStream 86 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 И правильно думал, что вероятность... Она действительно мала в реальных условиях. Учитывая архитектуру твоего кода, это можно делать через рекурсию. Все, кто стоит на моем пути: идите нахрен и там погибните! © Ссылка на комментарий
Viнt@rь 50 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 При срабатывании таймера, не только находим тот, который будет выполнен в следующий раз, но еще и смотрим, есть ли еще такие, что должны сработать сейчас кстати было такое в мыслях, но как-то отложил "на потом" вместе с идеей о флаге... GUI для конвертера от бардака(всего и вся в форматы сдк) Полезный утиль-"Utilits pack(mod)" Ссылка на комментарий
7.9 174 Опубликовано 8 Января 2012 Поделиться Опубликовано 8 Января 2012 (изменено) Gun12, для меня, алгоритмы реконструпровать - это долго - просто скажи, я правильно понял: у тебя конвейрный алгоритм? Или другое? Мог-бы ты просто (упрощённо) алгоритм описать(изобразить)? Понятно , если не в лом, конечно. Изменено 8 Января 2012 пользователем 7.9 всё легко Ссылка на комментарий
Кактус_523 1 Опубликовано 9 Января 2012 Поделиться Опубликовано 9 Января 2012 Здравствуйте люди! Пытаюсь подключить к сталку библу. Через луа.(пакеты\модули) Вроде не выпилено как debug. Ну по крайней мере не вылетает Чего то никак не пойму как это сделать. Для чего используются пути и тд... Что за С загрузчик... Мне бы примерчик по подключению и вызову функций из сторонней библы. МЯСО! Ссылка на комментарий
Nazgool 250 Опубликовано 9 Января 2012 Поделиться Опубликовано 9 Января 2012 (изменено) 7.9 После рекомендаций xStream и Vint@rь код конечно сильно измениться, но принцип думаю не очень. На данный момент примерно всё выглядит примерно так : 1. Существует модуль таймеров. Это одна большая таблица. 2. Все данные в этой таблице как бы разделены на две части. Первая часть - таблица с созданными таймерами (которые также являются таблицами). Вторая часть - функции и пр. для работы с этой таблицей 3. Каждый вызов функции create (из второй части) создаёт таблицу с таймером и помещает в таблицу всех таймеров (первая часть) 4. В каждой созданной таблице с новым таймером устанавливается поле complete в котором записывается время срабатывания. 5. При добавлении(удалении) нового таймера происходит сортировка таблиц всех таймеров по полю complete, и таймер с ближайшим временем срабатывания занимает поле с индексом 1. Это поле (таблицу таймера под индексом 1) и обрабатывает функция update. 6. Для каждого из таймеров устанавливается метатаблица - сам модуль таймеров. Поэтому возможен вызов методов из втоорой части, как то stop() и.т.д. 7. ...что-то много писать...может по ходу будешь спрашивать? Добавлено через 199 мин.: xStream Не смог удержаться. Спасибо за "путеводную нить". Начал переделывать timer = {} function timer:_init() self.__index = self self.timers = {} self.updateTime = 0 setmetatable(self, self) end timer:_init() function timer:__call() local obj = {k = 'I love lua'} setmetatable(obj, self) return obj end function timer:setName(name) name = type(name) == 'string' and name self.name = name return self end function timer:setTime(time) time = type(tonumber(time)) == 'number' and time or 0 self.time = time return self end t = timer():setName('Super'):setTime(21) print(t.k) print(t.name) print(t.time) Я просто в восторге. Аж дух захватывает. Изменено 9 Января 2012 пользователем Gun12 Ссылка на комментарий
7.9 174 Опубликовано 9 Января 2012 Поделиться Опубликовано 9 Января 2012 7.9 ... 7. ...что-то много писать...может по ходу будешь спрашивать? Того - достаточно... "По ходу" - это если что-то законченное будет... хотя-бы прототип... надеюсь всё легко Ссылка на комментарий
Рекомендуемые сообщения
Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий
Комментарии могут оставлять только зарегистрированные пользователи
Создать аккаунт
Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!
Зарегистрировать новый аккаунтВойти
Есть аккаунт? Войти.
Войти