Wysokowydajny wizualny interpreter w LuaJIT i LÖVE2D: 12 tysięcy skryptów na słabym sprzęcie
Początkujący programista zrealizował wizualny edytor bloków programistycznych, zdolny uruchomić 12289 skryptów z blokami IF, ROTATE i WHILE TRUE na jednym rdzeniu słabego laptopa przy stabilnych 30 FPS. Projekt zbudowano na LuaJIT z biblioteką LÖVE2D, zapewniającą wieloplatformowość: Windows, macOS, Linux, Android, iOS. Interpreter oddzielono od edytora, kompilacja do samodzielnego EXE już działa.
Wybór LuaJIT podyktowany jest kodem bajtowym i kompilacją JIT dla wysokiej prędkości wykonania. LÖVE2D wykorzystano za prostą składnię i doświadczenie autora z Roblox Studio. VS Code służył jako główny edytor.
Architektura projektu
Projekt podzielono na moduły dla skalowalności:
- Main.lua — główny edytor.
- Micropaint.lua — edytor sprite'ów.
- GameLoader.lua — ładowarka gier.
- BlockList.lua — rejestr bloków (518 linii, z funkcją renderowania).
GUI zaimplementowano ręcznie przez love.graphics bez zewnętrznych bibliotek. Przykład rysowania przycisków:
--PRZYCISK: Załaduj
love.graphics.rectangle("line", 230, 10, 120, 40)
love.graphics.print("Załaduj", 240, 10)
--PRZYCISK: Utwórz
love.graphics.rectangle("line", 360, 10, 100, 40)
love.graphics.print("Utwórz", 370, 10)
Obsługa kliknięć ze szczegółowymi komentarzami:
--PRZYCISK Utwórz
if x > 360 and x < 460 and y > 10 and y < 50 then
createNewGame()
end
--PRZYCISK ZAŁADUJ
if x > 230 and x < 350 and y > 10 and y < 50 then
if gload() == "suc" then
GameLoaded = true
love.window.showMessageBox( "GOTOWE!","Gra o nazwie "..game.name.." załadowana")
else
love.window.showMessageBox( "BŁĄD","Podczas ładowania wystąpił błąd")
end
end
Komentarze ułatwiają utrzymanie, choć biblioteki GUI uczyniłyby kod czystszym.
Struktura bloków i renderowanie
Bloki opisano w tabelach z metadanymi. Przykład bloku losowych liczb:
t[#t+1] = {
type = 3, --TYP BLOKU 1 - ZWYKŁY 2 - WYKONANIA 3 - DANYCH
isStarter = false, --CZY TO BLOK POCZĄTKU SKRYPTU???
DisplayName = "Wartość losowa (od, do)", -- WYŚWIETLANA NAZWA
name = "random", -- NAZWA SYSTEMOWA
args = 2, -- LICZBA ARGUMENTÓW
containBlocksIn = false, -- ZAWIERA BLOKI WEWNĄTRZ
color = {0, 0, 0}
}
Bloki obsługują zagnieżdżanie: argumenty mogą być innymi blokami. Renderowanie przez RenderBlock() z próbą rekurencji (częściowo zrealizowane). Białe kwadraty — pola wprowadzania.
Interpreter w jednym wątku dla prostoty. Bloki dzielą się na typy: zwykłe, wykonania, dane. Wykonywanie argumentów rekurencyjnie, wynik w args[i].data.
Interpretacja bloków
Kod interpretera sprawdza name i oblicza wartość:
if name == "getX" then --Pobierz X
return sprite.pos.x
elseif name == "getY" then --Pobierz Y
return sprite.pos.y
elseif name == "random" then --Losowość
return love.math.random(tonumber(args[1].data),tonumber(args[2].data))
elseif name == "getrotation" then --Obrót
return sprite.rotation
elseif name == "getcostume" then --Kostium
return sprite.costumeNumber
elseif name == "getsize" then --Rozmiar
return sprite.size
elseif name == "mathplus" then --Plus
return tonumber(args[1].data) + tonumber(args[2].data)
elseif name == "mathminus" then --Minus
return tonumber(args[1].data) - tonumber(args[2].data)
elseif name == "mathmultiply" then --Pomnóż
return tonumber(args[1].data) * tonumber(args[2].data)
elseif name == "mathdivide" then --Podziel
return tonumber(args[1].data) / tonumber(args[2].data)
end
Tablice Lua indeksowane od 1. LÖVE2D nie obsługuje polskiego domyślnie — użyto czcionek systemowych (Comic Sans i inna) przez love.graphics.newFont.
Kompilacja i wdrożenie
Kompilacja do EXE:
- Love Fusion pakuje DLL i pliki do EXE.
- Enigma Virtual Box łączy wszystko w jeden plik wykonywalny.
Obsługa APK/HTML w planach. Demonstracja: 12300 wątków z IF/ROTATE/WHILE TRUE przy 30 FPS.
Co ważne:
- LuaJIT + LÖVE2D zapewniają 12k+ skryptów na słabym CPU.
- Architektura modułowa: interpreter oddzielony od edytora.
- Ręczne GUI przez love.graphics, zagnieżdżone bloki z rekurencyjnym wykonaniem.
- Wieloplatformowa kompilacja do EXE/APK/HTML.
- Bloki typowane (dane/wykonanie), argumenty obliczane rekurencyjnie.
— Editorial Team
Brak komentarzy.