Перейти к содержимому

ECS

Гуру
  • Публикации

    533
  • Зарегистрирован

  • Посещение

  • Победитель дней

    203

Сообщения, опубликованные пользователем ECS


  1. В магазин добавлено кеширование иконок для ускорения загрузки, быстрое удаление установленного ПО одной кнопкой, анимация "деланья чего-то там" для особо нетерпеливых личностей, а также Очень Важная Вкладка со статистикой магазина и мини-игрой с прыгающими иконками наиболее популярных приложений:

     

    Спойлер

    MEyGlYZ.gif

     

    • Нравится 4

  2. Библиотека обновлена с общим увеличением производительности в ~1.4 раза и уменьшением потребления памяти на 140 Кбайт путем смены концепции хранения данных. Опытным путем выяснилось, что 2 пиксельных массива вида { 0xFFFFFF, 0xFFFFFF, "S", ... } кушают в разы больше, нежели 6 таких же массивов для цветов фона, текста и символов по раздельности (пруфскрипт - https://pastebin.com/mPynSL2H):

     

    wHfWMBE.png

     

    Судя по всему, подобная разница возникает из-за попеременной смены типов данных в таблице. Разумеется, это послужило отличным поводом перекодить методы отрисовки, избавившись от инкрементирования индексов в циклах. Так что все прожки, написанные на данной библиотеке, стали кушать меньше и работать быстрее. Наглядно по тикам результат следующий (см. скрины выше):

     

    00Jd1aw.png?1

    • Нравится 6

  3. Никаких улучшений графика не планируется?

     

    Не-а, модуль графика писал не я, а у автора никаких иных пожеланий к нему нет. Если напишешь более функциональный вариант - кидай пулл реквест на гит, буду рад смержить. К слову, хоть оси статично расположены по левому и нижнему краям объекта, отрицательные значения он вполне поддерживает:

     

    5AxtBgL.png?1

     

    А что касается обновления - объект графика имеет таблицу values, в которую ты можешь в реальном времени вставлять необходимые значения X и Y, а после всех манипуляций вызывать методы mainContainer:draw(); buffer.draw() для отображения результата на экране. То бишь, получил по сети нужную инфу - закинул ее в таблицу графика - отрисовал. Разумеется, библиотека никакой отсебятины делать не станет: когда ты ей скажешь перерисовать графон, тогда он и перерисуется, в этом ее фишечка. 

    • Нравится 2

  4. Собственно отсюда мой вопрос и вытекал, вроде можно, а вроде и нет

     

    Можно, можно. Год назад писал аналогичную систему, разделяющую экран на указанное число "строк" по вертикали, при этом каждой "строке" назначался индивидуальный компьютер с видеокартой и модемом. Контроль производился с серверной стойки, хранящей в памяти пиксельное содержимое экрана и отсылающей инфу о новых графических данных по сети. Т.е. сначала пользователь осуществлял отрисовку в экранный буфер, а затем данные об изменившихся пикселях массово отсылались одним broadcast-сообщением. Самая большая задница, с которой столкнулся - это крайне невысокая скорость передачи данных по модему, теоретически решаемая поднятием внешнего сокет-сервера и использованием интернет-платы. Было бы занятно увидеть более продуктивную реализацию 

    • Нравится 1

  5.  

     

    не могу понять как сделать 2 разних контейнера на весь екран и кнопкой в одном контейнере активировать второй
    local GUI = require("GUI")
    local buffer = require("doubleBuffering")
    
    -----------------------------------------------------
    
    -- Создаем главный полноэкранный контейнер для обработки событий и добавляем в него фоновую панель
    local mainContainer = GUI.fullScreenContainer()
    mainContainer:addChild(GUI.panel(1, 1, mainContainer.width, mainContainer.height, 0x2D2D2D))
    
    -- Добавляем в главный контейнер еще один контейнер, будем именовать его "первым". Добавляем в первый контейнер кнопку, позволяющую переключиться на второй контейнер
    local container1 = mainContainer:addChild(GUI.container(1, 1, mainContainer.width, mainContainer.height))
    local button1 = container1:addChild(GUI.button(3, 2, 30, 3, 0xFFFFFF, 0x0, 0xAAAAAA, 0x0, "Переключиться на 2"))
    
    -- Аналогично добавляем второй контейнер, по умолчанию он будет скрыт
    local container2 = mainContainer:addChild(GUI.container(1, 1, mainContainer.width, mainContainer.height))
    local button2 = container2:addChild(GUI.button(3, 2, 30, 3, 0xFFFFFF, 0x0, 0xAAAAAA, 0x0, "Переключиться на 1"))
    container2.hidden = true
    
    -- Назначаем кнопкам функцию, переключающую скрытость контейнеров
    button1.onTouch = function()
      container1.hidden, container2.hidden = not container1.hidden, not container2.hidden
      mainContainer:draw()
      buffer.draw()
    end
    
    button2.onTouch = button1.onTouch
    
    -----------------------------------------------------
    
    mainContainer:draw()
    buffer.draw(true)
    mainContainer:startEventHandling()
    

  6.  

     

    По нажатию на выход  попап не удаляется с поля полностью, а отходит как бы на задний план под все слои. как полностью удалять объекты?

     

    Не понял, что значит "отходит как бы на задний план". При вызове :delete() элемент полностью удаляется из своего родительского контейнера, и больше не отображается. Если этот объект более нигде не используется, он будет подтерт сборщиком мусора. В описанном же тобой примере объект, содержащийся в переменной container, хоть и удаляется, однако продолжает существовать в своей области видимости до конца работы программы, и если хочешь его удалить - присвой переменной значение nil. Ты это имел в виду? Полное удаление из оперативной памяти?

     

    И еще один оч оч важный момент: форсированная отрисовка содержимого буфера через с аргументом true нужна лишь в тех случаях, когда на экране отрисовано нечто средствами прямого обращения к GPU, т.е. не учтенное в буфере. К примеру, если ты запускаешь софтину, работающую с буфером, напрямую из терминала OpenOS (работающего на "чистой" GPU), то будет разумно разово отрисовать содержимое буфера, чтобы не упустить некоторые мелкие детали.


  7.  

     

    У изображений функция .onTouch работает?

     

    Нет. Любые функции по типу onTouch/onStateChanged/onKeyDown создавались у определенной группы объектов (кнопки, слайдеры) исключительно для удобства их использования. По сути они являются следствием назначения объектам соответствующего обработчика событий и вызова этих методов в обработчике. Если вкратце, то у кнопки обоаботчик выглядит следующим образом:

    button.eventHandler = function(mainContainer, button, eventData)
      if eventData[1] == "touch" then
        -- Тут кнопочка визуально "нажимается"
        
        ...
    
        -- Если у кнопки создавался метод .onTouch, то он вызывается
        if button.onTouch then
          button.onTouch()
        end
      end
    end
    

    Аналогичную фишечку ты можешь легко провернуть с любым объектом, включая image. Пили eventHandler, короче.

    • Нравится 1

  8. Либа обновлена. По большей части изменения направлены на ускорение отрисовки графоуни и обработки событий, в результате чего местный FPS в прожорливом софте значительно повысился. Убрана зависимость от библиотеки palette, ее функционал включен в GUI. Ну, хоть на один файл меньше докачивать, ага.

     

    Но есть и визуальные плюхи: для кнопок добавлена поддержка плавного цветового перехода при нажатии, а также возможность отключения анимаций по желанию. Помимо этого у них появился режим "переключателя", при котором кнопка не отжимается автоматически:

     

    Q2sX0P5.gif

    • Нравится 4

  9. Первое: можно ли поменять цвет элементов контекстного меню?

     

    Можно, просто фича не задокументирована. Слишком много таких мелочей имеется, чтобы прописывать их в доке для каждого из объектов. Контекстное меню наследуется от dropDownMenu, включая таблицу цветов colors. Ее структура выглядит следующим образом:

     

    2eThJLx.png?1

     

    Поэтому все, что тебе требуется - это создать объект меню, изменить цвета по своему усмотрению и вызвать привычный метод menu:show(). К примеру, вот так можно создать непрозрачную серенькую менюшку:

    local buffer = require("doubleBuffering")
    local GUI = require("GUI")
    
    ------------------------------------------------------------------------------------------
    
    local contextMenu = GUI.contextMenu(2, 2)
    
    contextMenu:addItem("New")
    contextMenu:addItem("Open")
    contextMenu:addSeparator()
    contextMenu:addItem("Save", true)
    contextMenu:addItem("Save as")
    contextMenu:addSeparator()
    contextMenu:addItem("Close")
    
    contextMenu.colors.default.background = 0x444444
    contextMenu.colors.default.text = 0xFFFFFF
    contextMenu.colors.separator = 0x999999
    contextMenu.colors.transparency = nil
    
    ------------------------------------------------------------------------------------------
    
    buffer.clear(0x2D2D2D)
    buffer.draw(true)
    contextMenu:show()
    

    В результате получится что-то подобное:

     

    DEaZwuD.png

     

    При нажатии на кнопку пропадают все объекты из контейнера(он дочерний у основного)

     

    Конкретизируй с примером кода, пожалуйста. Разумеется, это баг, который нужно срочно фиксить (при условии, что ты сам не делаешь что-то некорректно, что более вероятно). В этом скрипте все работает адекватно:

    local buffer = require("doubleBuffering")
    local GUI = require("GUI")
    
    ------------------------------------------------------------------
    
    local mainContainer = GUI.fullScreenContainer()
    mainContainer:addChild(GUI.panel(1, 1, mainContainer.width, mainContainer.height, 0x2D2D2D))
    mainContainer:addChild(GUI.button(1, 1, 12, 3, 0x008800, 0xFFFFFF, 0x440000, 0xFFFFFF, "Кнопка 1"))
    
    local secondContainer = mainContainer:addChild(GUI.container(4, 3, 30, 10))
    secondContainer:addChild(GUI.panel(1, 1, secondContainer.width, secondContainer.height, 0xDDDDDD))
    secondContainer:addChild(GUI.button(3, 2, 12, 3, 0x880000, 0xFFFFFF, 0x440000, 0xFFFFFF, "Кнопка 2"))
    
    ------------------------------------------------------------------
    
    mainContainer:draw()
    buffer.draw(true)
    mainContainer:startEventHandling()
    

  10. Добавлена поддержка строковой конвертации. Эта фича довольно полезна в тех случаях, когда нет возможности/желания перегружать хард тонной мелких зависимых картинок ради одной программы:
     
    nzlo6cv.png?2
     
    К примеру, грустную девку со скрина выше можно отрисовать следующим образом:

    local image = require("image")
    local devka = image.fromString([[200B305B00⡸2A6100⢲619100⢐61BD00⣴92C300⢀BDC800⢮C2F300⣲C2F300⣵C2F300⣵C2F300⡧C2F300⡷C2F300⢗98F300⣄2AC300⣛2BC300⠛309200⠏286000⠁296100⠈2AF300⢠30D600⣶8DD600⣦92F300⣶8DC300⣄619200⣦616100⠀536100⡧305B00⡑302A00⢇2B2A00⢎293000⡑283000⠌28AC00⠐2A6100⢴608D00⢕8D9200⣴92C200⣼C2F300⣽C8F300⢺C8F400⢀CDF900⣶F3F900⣸F3FF00⣴F8FF00⣶CDFF00⣦C8F900⡌30C200⢇288D00⣤2B6000⣀295C00⢆2AC300⢰35C800⡏98FF00⢻53FF00⡿92D700⢿BDF300⣷929800⠅618D00⠄536100⡟2A5B00⢌2B2A00⡑2B2A00⣜2B3000⢷283000⠐00AA00⠚5B6100⢕619200⢾8DBD00⢐BDC300⠨C7F300⣾CDF400⡣C9F900⣮F9FE00⢐D3FE00⣛FFFF00⠀FFFF00⠀D7FF00⣷92F900⣏539200⣠308D00⢬5C9200⣵5B6100⢸2A9200⢸299200⠇29F900⠙299200⢰61F300⠾92C800⢟7E9300⠌618D00⠁536100⣏305B00⢂302A00⡱2B2A00⡱2B2900⣯283000⡀002800⡗5B6100⢕609200⢽8CBD00⢿92C300⠈C2F300⢿C8F800⡽CDF900⠐CDF900⠙CEF900⡯C7FF00⠿8DFF00⠿C2FF00⠟C7F300⠿309200⡏5B9200⡽309200⠟308C00⢸5B6100⢮285B00⡆283500⢡299200⢶309200⣼8D9200⡿617E00⠅616600⡀2A6100⢇305C00⡇2B2A00⣇292A00⠄282900⠇282800⠀002800⣏285C00⢀285B00⠈286100⠉288D00⠉2B9200⠉29BD00⠉29C200⠉29C200⠉2BC200⠉29C200⠉296100⣙2ABD00⡉28BD00⠉306100⢅2B5B00⢀2A6100⢣539200⢸2A6100⠝2B3000⢧2B5300⠘292C00⡀295C00⡁285B00⡁295C00⢉616100⠀2A6100⡣305C00⠁2B3000⣯293000⠠282800⠀002800⣷002800⢧295B00⢐283000⠌285B00⠁285B00⠉285C00⠉285C00⠉286100⠙296100⢹308D00⠋538D00⠉289200⠉286600⠃282B00⣜2A6100⢹282A00⡀2B6100⠨2A6100⢺296100⠇2B2900⠨285600⠄2B5C00⢲308C00⠋296100⠛286100⠛538D00⠠308D00⡇295C00⢀2B5C00⢀285B00⡀282900⠁282900⠠002800⣆295B00⠐282900⡨283000⠢282A00⢜2B6100⢀2B6100⣤2B8D00⣴2A9200⣶2A9200⣶5B9200⣶307E00⢦2B8C00⣠288D00⣀005C00⣈283000⡁002B00⠁005C00⠹283000⣮2B5600⡀2B2A00⢶2B8000⢰539800⣄306100⡱305C00⡱308D00⢸306100⡆2B8D00⠴2B6100⢢295C00⣆286100⡀000100⠐002800⣑295B00⠈282900⠰2B5B00⠐306100⢺2A6100⠻2A6100⠻536600⠿308D00⠿306100⡿2B6100⡟2B6100⠘285C00⠉286100⠙288D00⠻308D00⠷5B8D00⡕2B5C00⢐2B5600⠄285600⠐283000⠳2B5500⡘539800⠉549800⠁306100⣶296100⣾2A5500⣦296100⣤286100⣤282A00⡭282A00⣇002900⢿282900⠑285C00⠤286100⠴285B00⠴282A00⢖2B2A00⢝285B00⠂285300⠓286100⠓285B00⠹306100⠦608D00⣹285B00⠁282A00⡙282900⠁002800⢋005C00⠈282A00⢉282900⡀002800⣵282800⠀282900⠩2A5500⢺536100⠋535500⠿615500⢍617E00⠎2A5500⡷2A6100⡏2B2A00⣟282A00⡇282900⠨283000⢵282A00⡁002900⢯002800⣾002800⢽002800⣯282900⢤282900⢢002900⣾002800⣮006100⠸288D00⠏282A00⠊282900⠁002800⢋002800⣴002900⢿282A00⠃282800⠀002800⡿002800⣽282900⠈283100⠊285300⠍285C00⠉286100⠉285500⠛2B6100⠢306100⠃2B2A00⡿282A00⡇282900⠨2B3000⡯283000⡢002800⣧002800⡻002800⡯282800⠀282800⠀282A00⢜283000⢡005B00⢠296100⣶298D00⠦283000⠄002900⣇002800⡫002800⡿282800⠀002900⢾002800⢷002900⣨002900⡨002900⣫005C00⣀005C00⢀286000⣀005B00⣀285B00⣀285B00⢀282A00⠖282A00⠇2B5C00⡂295C00⠄2B5B00⠢]])
    image.draw(4, 3, devka)

    Разумеется, обработка строк занимает больше времени, нежели прямая загрузка с диска, однако для изображений среднего размера такой метод дает более чем приемлемый профит:
     
    R4C68ob.png?2

    • Нравится 2
    • Спасибо 1

  11. А чего париться-то, API всякие искать... гуглим что-то наподобие "unix time", выбираем первый попавшийся сайт (к примеру, https://www.unixtimestamp.com/), отсылаем обычный запрос на получение контента веб-страницы, парсим результат через регулярку и наслаждаемся:

    -- Получаем содержимое веб-страницы через дефолтную internet-либу
    local data = ""
    for chunk in require("internet").request("https://www.unixtimestamp.com/") do
      data = data .. chunk
    end
    
    -- Извлекаем время и корректируем часовой пояс
    local timezone = 3
    local timestamp = tonumber(data:match("(%d+)[^%d]+seconds since Jan")) + 3600 * timezone
    print(os.date("%c", timestamp))

  12. Слегка обновил установщик: теперь показывается прогресс загрузки текущего файла через HTTP-заголовок "Content-Length", также добавлена всевозможная кастомизация внешнего вида и текстовых полей. Ну, и имеется общее увеличение производительности при отрисовке графики

    • Нравится 1

  13.  

     

    Не даёт строить, но так же и не даёт рушить объекты в радиусе

    К сожалению, он не позволяет именно строить, разрушение же никто не отменял:

     

    eikXbVc.png

     

    Ну, а взрыв зарядов в свою очередь легко разносит сейфы/кровати/etc. Понятно, что в этом и заключается суть геймплея всех растоподобных игрушек, но тут и развитие в разы медленнее за счет долгого гринда и системы перков. Хотя тру-хардкорщикам вполне норм, наверное


  14.  

     

    Мне например тут и воды и еды вполне хватает и радиация не мешает, что я делаю не так?

    Мне тоже вполне хватает, но я не хочу тратить по 5 часов своей жизни на выживание, чтобы любой мамкин подрывник со бомбой из банки пепси разнес мою хату и свел весь прогресс на ноль. Выжить - не проблема, а выживать вновь и вновь из-за беспочвенной агрессии игроков - вот эт уже другое дело

    • Нравится 1

  15. @@Ingr Да, скучновато, однако, имхо, куда приятнее, нежели таскаться на карачках и выискивать очищающие таблетки по принципу "лишь бы не сдохнуть", теряя всяческое удовольствие от игры. В принципе, все это дело легко компенсировать выставлением более высокой сложности (для контроля экспы, жажды и голода), повышением шансов спавна более мощных зомбей и слегка подпорченных предметов, а также сохранением прежнего шанса дропа лута (ибо на данный момент его вполне достаточно для комфортного геймплея). Это ж, млен, тонкое дело, желаний у игроков масса - и все не учтешь, да и админа дергать попусту не хочется

    • Нравится 1

  16. @@1Ridav, за сервер Unturned спасибо - теперь хоть есть, где и с кем покатать. Однако хотелось бы чутка повысить шансы спавна лута, ибо смерть от голода/жажды уже утомила. Найти воду вообще крайне проблематично, если не скрафтить себе фляжечку. А скрафтить не успеваешь, т.к. доооохнешь хд

    • Нравится 1

  17. Не получается вообще ни в какую, может есть функция которая разбивает строку на символы и пробегает по массиву заменяя их на маленькие

     

    Если Lua-интерпретатор вшит в скомпилированное .exe-приложение, то крайне маловероятно, что тебе удастся прикрутить стороннюю либу без продажи души дьяволу. Также штатными средствами без поддержки юникода разбить строку на юникод-символы не представляется возможным, так как любая строка в Lua - это последовательность байт, воспринимаемых string-библиотекой в виде ASCII-символов.

     

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

     

    na4UKyy.png?1

    local stroka = "Привет"
    local bytes = {string.byte(stroka, 1, #stroka)}

    Затем придется перебирать полученный байт-массив итеративно и вручную извлекать из него UTF-8 символы, используя бинарные операции. Обратимся к великой и могучей Википедии, чтобы разобраться в структуре кодирования данных в UTF-8:

     

    rdo3XQV.png?1

     

    В целом все довольно просто: каждый символ - это последовательность нескольких байт. Чтобы определить количество байт в последовательности, необходимо специфичным образом обработать первый байт из последовательности. Для этого находим в нем первый "нолик слева" и считаем число "единичек до нолика" - это самое количество единичек и будет количеством байт, необходимых для кодирования выбранного символа.

     

    Дальше - дело техники. Зная размерность символа, ты можешь легко извлечь эти байты из массива байт через table.unpack(), затем "склеить" их в символ через string.char(), а потом уже работать с получившимся символом так, как тебе требуется. Чтобы не ходить вокруг да около, держи рабочий скрипт:

    local function getUTF8Chars(stroka)
      -- Получаем байт-последовательность указанной строки
      local bytes = {string.byte(stroka, 1, #stroka)}
      local symbols = {}
    
      -- Перебираем все имеющиеся байты
      local i = 1
      while i <= #bytes do
        -- Определяем позицию нулевого бита в первом байте UTF-8 символа. Это же число и будет размером символа
        local utf8CharSize = 1
        for j = 1, 7 do
          if bit32.band(bit32.rshift(bytes[i], 8 - j), 0x1) == 0x0 then
            utf8CharSize = j
            break
          end
        end   
    
        -- Если размер символа единичный, то используем все тот же байт для его идентификации
        if utf8CharSize == 1 then
          table.insert(symbols, string.char(bytes[i]))
          i = i + 1
        -- В противном случае используем последовательность байт
        else
          table.insert(symbols, string.char(table.unpack(bytes, i, i + utf8CharSize - 2)))
          i = i + utf8CharSize - 1
        end
      end
    
      return symbols
    end
    
    -- Переводим любую входную строку в массив UTF-8 символов
    local chars = getUTF8Chars("Hello, юникод")
    for i = 1, #chars do
      print(chars[i])
    end
    

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

     

    my66STC.png?1

     

    При пробелах находить это же слово, вот так М а т

    Используй stroka:gsub("%s+", "") для удаления пробелов. Если работа с UTF-8 все же будет кривой - напиши функцию, перебирающую полученный выше массив символов и удаляющую из него пробелы:

    local function removeWhitespaces(chars)
      local i = 1
      while i <= #chars do
        if chars[i] == " " then
          table.remove(chars, i)
        else
          i = i + 1
        end
      end
    end

    Перевести текст Unicode в нижний регистр

     

    Теперь что касается конвертации регистра - тут уже все не столь однозначно. Под каждую языковую группу зарезервирован определенный диапазон кодов - и, в зависимости, от размера алфавита, его размер также различается: к примеру, все буквы русского языка умещаются в 64 байт-последовательности, а английского - уже в 52. При этом сначала перечисляются буквы в верхнем регистре, а затем уже в нижнем. Соответственно, для "изменения" регистра в русском алфавите с верхнего на нижний достаточно прибавить к коду буквы 32, ну, а для обратной конвертации использовать уже вычитание. Отсюда можно сделать вывод, что без указания конкретного языкового диапазона прямая конвертация невозможна, и следует создать таблицы символов в верхнем и нижнем регистрах, а затем уже выбирать из них необходимые данные:

    local cases = {
      ["а"] = "А",
      ["б"] = "Б",
      ...
    }

    Безусловно, такой подход крайне неэффективен, но что поделать?

    • Нравится 4
×
×
  • Создать...