LuaJIT와 LÖVE2D로 구현한 고성능 시각적 인터프리터: 저사양 하드웨어에서 12,000개 스크립트 실행
한 개발자가 저사양 노트북의 단일 코어에서 IF, ROTATE, WHILE TRUE 블록을 포함한 12,289개 스크립트를 안정적인 30 FPS로 실행할 수 있는 시각적 블록 프로그래밍 에디터를 구현했습니다. 이 프로젝트는 LuaJIT와 LÖVE2D 라이브러리를 기반으로 하여 크로스 플랫폼 호환성을 보장합니다: Windows, macOS, Linux, Android, iOS. 인터프리터는 에디터와 분리되어 있으며, 독립 실행형 EXE 빌드가 이미 작동합니다.
LuaJIT 선택은 높은 실행 속도를 위한 바이트코드와 JIT 컴파일 때문입니다. LÖVE2D는 간단한 문법과 개발자의 Roblox Studio 경험으로 사용되었습니다. VS Code가 주요 에디터로 활용되었습니다.
프로젝트 아키텍처
프로젝트는 확장성을 위해 모듈로 나뉩니다:
- Main.lua — 메인 에디터.
- Micropaint.lua — 스프라이트 에디터.
- GameLoader.lua — 게임 로더.
- BlockList.lua — 블록 레지스트리 (518줄, 렌더링 함수 포함).
GUI는 외부 라이브러리 없이 love.graphics를 통해 수동으로 구현되었습니다. 버튼 렌더링 예시:
--BUTTON: Load
love.graphics.rectangle("line", 230, 10, 120, 40)
love.graphics.print("Load", 240, 10)
--BUTTON: Create
love.graphics.rectangle("line", 360, 10, 100, 40)
love.graphics.print("Create", 370, 10)
자세한 주석이 포함된 클릭 처리:
--BUTTON Create
if x > 360 and x < 460 and y > 10 and y < 50 then
createNewGame()
end
--BUTTON LOAD
if x > 230 and x < 350 and y > 10 and y < 50 then
if gload3) == "suc" then
GameLoaded = true
love.window.showMessageBox("READY!","Game named "..game.name.." loaded")
else
love.window.showMessageBox("ERROR","An error occurred during loading")
end
end
주석은 유지 관리를 단순화하지만, GUI 라이브러리를 사용했다면 코드가 더 깔끔했을 것입니다.
블록 구조와 렌더링
블록은 메타데이터가 포함된 테이블로 설명됩니다. 랜덤 숫자 블록 예시:
t[#t+1] = {
type = 3, --BLOCK TYPE 1 - REGULAR 2 - EXECUTION 3 - DATA
isStarter = false, --IS THIS A SCRIPT START BLOCK???
DisplayName = "Random Value (from, to)", -- DISPLAY NAME
name = "random", -- SYSTEM NAME
args = 2, -- NUMBER OF ARGUMENTS
containBlocksIn = false, -- CONTAINS BLOCKS INSIDE
color = {0, 0, 0}
}
블록은 중첩을 지원합니다: 인수는 다른 블록일 수 있습니다. RenderBlock()을 통해 렌더링되며, 재귀 시도가 부분적으로 구현되었습니다. 흰색 사각형은 입력 필드입니다.
인터프리터는 단순성을 위해 단일 스레드에서 실행됩니다. 블록은 일반, 실행, 데이터 유형으로 나뉩니다. 인수 실행은 재귀적이며, 결과는 args[i].data에 저장됩니다.
블록 해석
인터프리터 코드는 name을 확인하고 값을 계산합니다:
if name == "getX" then --Get X
return sprite.pos.x
elseif name == "getY" then --Get Y
return sprite.pos.y
elseif name == "random" then --Random
return love.math.random(tonumber(args[1].data),tonumber(args[2].data))
elseif name == "getrotation" then --Rotation
return sprite.rotation
elseif name == "getcostume" then --Costume
return sprite.costumeNumber
elseif name == "getsize" then --Size
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 --Multiply
return tonumber(args[1].data) * tonumber(args[2].data)
elseif name == "mathdivide" then --Divide
return tonumber(args[1].data) / tonumber(args[2].data)
end
Lua 배열은 1부터 인덱싱됩니다. LÖVE2D는 기본적으로 러시아어를 지원하지 않습니다 — love.graphics.newFont를 통해 시스템 폰트(Comic Sans 등)가 사용되었습니다.
빌드와 배포
EXE 빌드:
- Love Fusion이 DLL과 파일을 EXE로 패키징합니다.
- Enigma Virtual Box가 모든 것을 단일 실행 파일로 결합합니다.
APK/HTML 지원이 계획되어 있습니다. 데모: IF/ROTATE/WHILE TRUE 블록을 포함한 12,300개 스레드가 30 FPS로 실행됩니다.
핵심 포인트:
- LuaJIT + LÖVE2D로 약한 CPU에서 12,000개 이상 스크립트 실행 가능.
- 모듈식 아키텍처: 인터프리터와 에디터 분리.
- love.graphics를 통한 수동 GUI, 재귀 실행을 지원하는 중첩 블록.
- 크로스 플랫폼 빌드: EXE/APK/HTML.
- 블록은 유형화(데이터/실행), 인수는 재귀적으로 계산.
— Editorial Team
아직 댓글이 없습니다.