diff options
| author | jacqueline <me@jacqueline.id.au> | 2023-11-12 19:14:09 +1100 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2023-11-12 19:14:09 +1100 |
| commit | 8a0a167adbf3d9b6f8b6f16aaf20ca39ad5549de (patch) | |
| tree | 02b6cf23f591915747ec2994381854a79979c4a0 /lib/luavgl/examples | |
| parent | 8471046a95ab9e00f7d42b56dbbc9ce3e5b424b9 (diff) | |
| download | tangara-fw-8a0a167adbf3d9b6f8b6f16aaf20ca39ad5549de.tar.gz | |
Convert the main menu screen to lua lol
Diffstat (limited to 'lib/luavgl/examples')
34 files changed, 1418 insertions, 0 deletions
diff --git a/lib/luavgl/examples/analogTime.lua b/lib/luavgl/examples/analogTime.lua new file mode 100644 index 00000000..375459a9 --- /dev/null +++ b/lib/luavgl/examples/analogTime.lua @@ -0,0 +1,13 @@ +local analogTime = lvgl.AnalogTime(nil, { + border_width = 0, + x = lvgl.HOR_RES() // 2, + y = lvgl.VER_RES() // 2, + hands = { + hour = SCRIPT_PATH .. "/assets/hand-hour.png", + minute = SCRIPT_PATH .. "/assets/hand-minute.png", + second = SCRIPT_PATH .. "/assets/hand-second.png", + }, + period = 33, +}) + +print("analogTime: ", analogTime) diff --git a/lib/luavgl/examples/animation.lua b/lib/luavgl/examples/animation.lua new file mode 100644 index 00000000..95ee5f5a --- /dev/null +++ b/lib/luavgl/examples/animation.lua @@ -0,0 +1,61 @@ +local root = lvgl.Object() +root:set { w = lvgl.HOR_RES(), h = lvgl.VER_RES() } + +-- create image on root and set position/img src/etc. properties. +root:Object():Image { + src = SCRIPT_PATH .. "/assets/lvgl-logo.png", + x = 0, + y = 0, + bg_color = 0x004400, + pad_all = 0, + align = lvgl.ALIGN.CENTER, +}:Anim { + run = true, + start_value = 0, + end_value = 3600, + duration = 2000, + repeat_count = 2, + path = "bounce", + exec_cb = function(obj, value) + obj:set { + angle = value + } + end, + done_cb = function (anim, obj) + print("anim done.: ", anim, "obj:", obj) + anim:delete() + end +} + +-- second anim example with playback +local obj = root:Object { + bg_color = "#F00000", + radius = lvgl.RADIUS_CIRCLE, + align = lvgl.ALIGN.LEFT_MID, +} +obj:clear_flag(lvgl.FLAG.SCROLLABLE) + +--- @type AnimPara +local animPara = { + run = true, + start_value = 10, + end_value = 50, + duration = 1000, + playback_delay = 100, + playback_time = 500, + repeat_count = lvgl.ANIM_REPEAT_INFINITE, + path = "ease_in_out", +} + +animPara.exec_cb = function(obj, value) + obj:set { size = value } +end + +obj:Anim(animPara) + +animPara.end_value = 240 +animPara.exec_cb = function(obj, value) + obj:set { x = value } +end + +obj:Anim(animPara) diff --git a/lib/luavgl/examples/assets/hand-hour.png b/lib/luavgl/examples/assets/hand-hour.png Binary files differnew file mode 100644 index 00000000..6f5857a9 --- /dev/null +++ b/lib/luavgl/examples/assets/hand-hour.png diff --git a/lib/luavgl/examples/assets/hand-minute.png b/lib/luavgl/examples/assets/hand-minute.png Binary files differnew file mode 100644 index 00000000..52f6f1ba --- /dev/null +++ b/lib/luavgl/examples/assets/hand-minute.png diff --git a/lib/luavgl/examples/assets/hand-second.png b/lib/luavgl/examples/assets/hand-second.png Binary files differnew file mode 100644 index 00000000..9caf4649 --- /dev/null +++ b/lib/luavgl/examples/assets/hand-second.png diff --git a/lib/luavgl/examples/assets/lvgl-logo.png b/lib/luavgl/examples/assets/lvgl-logo.png Binary files differnew file mode 100644 index 00000000..b032d1b8 --- /dev/null +++ b/lib/luavgl/examples/assets/lvgl-logo.png diff --git a/lib/luavgl/examples/assets/second.png b/lib/luavgl/examples/assets/second.png Binary files differnew file mode 100644 index 00000000..d09ea5a3 --- /dev/null +++ b/lib/luavgl/examples/assets/second.png diff --git a/lib/luavgl/examples/dropdown.lua b/lib/luavgl/examples/dropdown.lua new file mode 100644 index 00000000..037f51cb --- /dev/null +++ b/lib/luavgl/examples/dropdown.lua @@ -0,0 +1,74 @@ +-- a dropdown on top left +local dd = lvgl.Dropdown(nil, { + -- note there are two "Orange" + options = "Apple\nBanana\nOrange\nCherry\nGrape\nRaspberry\nMelon\nOrange\nLemon\nNuts", + symbol = "\xEF\x81\x94", + dir = lvgl.DIR.RIGHT, + highlight = false, + text = nil, + align = { + type = lvgl.ALIGN.TOP_LEFT, + x_ofs = 20, + y_ofs = 20, + } +}) +local list = dd:get("list") +print("get dropdown list: ", list) +list:set { text_font = lvgl.BUILTIN_FONT.MONTSERRAT_20 } + +print("available options:", dd:get("options")) + +local cnt = 0 +dd:onevent(lvgl.EVENT.VALUE_CHANGED, + ---comment + ---@param obj Dropdown + ---@param code ObjEventCode + function(obj, code) + obj:add_option(string.format("Option:%d", cnt), dd:get("option_cnt")) + cnt = cnt + 1 + print(obj:get("selected_str"), "option_cnt" .. obj:get("option_cnt")) + end +) + +-- another dropdown on top left +local dd = lvgl.Dropdown(nil, { + options = "Apple\nBanana\nOrange\nCherry\nGrape\nRaspberry\nMelon\nOrange\nLemon\nNuts", + symbol = "\xEF\x81\xB7", + dir = lvgl.DIR.BOTTOM, + text = "SetText", + selected = 5, + text_font = lvgl.BUILTIN_FONT.MONTSERRAT_20, + align = { + type = lvgl.ALIGN.BOTTOM_MID, + x_ofs = 0, + y_ofs = -20, + } +}) + + +dd:get("list"):set { text_font = lvgl.Font("montserrat", 24) } +dd:onevent(lvgl.EVENT.VALUE_CHANGED, function(obj, code) + print(obj:get("selected_str") .. ":" .. obj:get("selected"), + "dir:" .. obj:get("dir"), + "option_index" .. dd:get("option_index", obj:get("selected_str"))) +end) + + + +lvgl.Timer { + period = 1000, + cb = function(t) + t:delete() + dd:open() + print("now dd should be opened: " .. (dd:is_open() and "open" or "closed")) + end +} + +lvgl.Timer { + period = 2000, + cb = function(t) + t:delete() + dd:close() + print("now dd should be closed: " .. (dd:is_open() and "open" or "closed")) + end +} diff --git a/lib/luavgl/examples/examples.lua b/lib/luavgl/examples/examples.lua new file mode 100644 index 00000000..64e0b631 --- /dev/null +++ b/lib/luavgl/examples/examples.lua @@ -0,0 +1,44 @@ +local container = lvgl.Object(nil, { + w = lvgl.HOR_RES(), + h = lvgl.VER_RES(), + bg_color = "#888", + bg_opa = lvgl.OPA(100), + border_width = 0, + radius = 0, + flex = { + flex_direction = "row", + flex_wrap = "wrap" + } +}) + +print("created container", container) + +local function createBtn(parent, name) + local root = parent:Object { + w = lvgl.SIZE_CONTENT, + h = lvgl.SIZE_CONTENT, + bg_color = "#ccc", + bg_opa = lvgl.OPA(100), + border_width = 0, + radius = 10, + pad_all = 20, + } + + root:onClicked(function() + container:delete() + require(name) + end) + + root:Label { + text = name, + text_color = "#333", + align = lvgl.ALIGN.CENTER, + } +end + +createBtn(container, "keyboard") +createBtn(container, "animation") +createBtn(container, "pointer") +createBtn(container, "analogTime") +createBtn(container, "flappyBird/flappyBird") +createBtn(container, "tests") diff --git a/lib/luavgl/examples/extension.lua b/lib/luavgl/examples/extension.lua new file mode 100644 index 00000000..e51f355c --- /dev/null +++ b/lib/luavgl/examples/extension.lua @@ -0,0 +1,14 @@ +-- demo of external widget added to lvgl. See simulator/extension.c + +local extension = lvgl.Extension(nil, { + border_width = 1, + w = lvgl.PCT(20), + h = lvgl.PCT(20), + align = lvgl.ALIGN.CENTER, +}) + +extension:onClicked(function () + print("clicked") +end) + +print("extension: ", extension) diff --git a/lib/luavgl/examples/flappyBird/bg_day.png b/lib/luavgl/examples/flappyBird/bg_day.png Binary files differnew file mode 100644 index 00000000..6d24cc26 --- /dev/null +++ b/lib/luavgl/examples/flappyBird/bg_day.png diff --git a/lib/luavgl/examples/flappyBird/bird1.png b/lib/luavgl/examples/flappyBird/bird1.png Binary files differnew file mode 100644 index 00000000..72b202d5 --- /dev/null +++ b/lib/luavgl/examples/flappyBird/bird1.png diff --git a/lib/luavgl/examples/flappyBird/bird2.png b/lib/luavgl/examples/flappyBird/bird2.png Binary files differnew file mode 100644 index 00000000..46050452 --- /dev/null +++ b/lib/luavgl/examples/flappyBird/bird2.png diff --git a/lib/luavgl/examples/flappyBird/bird3.png b/lib/luavgl/examples/flappyBird/bird3.png Binary files differnew file mode 100644 index 00000000..2fc5128d --- /dev/null +++ b/lib/luavgl/examples/flappyBird/bird3.png diff --git a/lib/luavgl/examples/flappyBird/button_play.png b/lib/luavgl/examples/flappyBird/button_play.png Binary files differnew file mode 100644 index 00000000..ae3d330b --- /dev/null +++ b/lib/luavgl/examples/flappyBird/button_play.png diff --git a/lib/luavgl/examples/flappyBird/flappyBird.lua b/lib/luavgl/examples/flappyBird/flappyBird.lua new file mode 100644 index 00000000..26018bba --- /dev/null +++ b/lib/luavgl/examples/flappyBird/flappyBird.lua @@ -0,0 +1,765 @@ +local lvgl = require("lvgl") + +local MOVE_SPEED = 480 / 8000 -- 8s for 480 pixel, pixel per ms +local PIXEL_PER_METER = 80 +local TOP_Y = 20 +local BOTTOM_Y = 480 - 112 +local PIPE_COUNT = 5 +local PIPE_GAP = 100 +local PIPE_SPACE = 120 + +-- SCRIPT_PATH is set in simulator/main.c, used to get the abs path of first +-- lua script lua get called. In this example, SCRIPT_PATH is set to +-- path of `examples.lua`, flappyBird.lua is called when button is clicked. + +local IMAGE_PATH = SCRIPT_PATH +if not IMAGE_PATH then + IMAGE_PATH = "/" + print("Note image root path is set to: ", IMAGE_PATH) +end + +IMAGE_PATH = IMAGE_PATH .. "/flappyBird/" +print("IMAGE_PATH:", IMAGE_PATH) + +local function randomY() + return math.random(TOP_Y + 30, BOTTOM_Y - 50 - 50) +end + +local function screenCreate(parent) + local property = { + w = 480, + h = 480, + bg_opa = 0, + border_width = 0, + pad_all = 0 + } + + local scr + if parent then + scr = parent:Object{ + w = 480, + h = 480, + bg_opa = 0, + border_width = 0, + pad_all = 0 + } + else + scr = lvgl.Object(nil, property) + end + scr:clear_flag(lvgl.FLAG.SCROLLABLE) + scr:clear_flag(lvgl.FLAG.CLICKABLE) + return scr +end + +local function Image(parent, src) + local img = {} + img.widget = parent:Image{ + src = src + } + + img.w, img.h = img.widget:get_img_size() + if not img.w or not img.h then + error("failed to load image: " .. src) + end + return img +end + +local function ImageScroll(root, src, animSpeed, y) + -- image on right + local right = Image(root, src).widget + right:set{ + src = src, + x = 480, + y = y, + pad_all = 0 + } + + local img = Image(root, src).widget + img:set{ + x = 0, + y = y, + src = src, + pad_all = 0 + } + + img:Anim{ + run = true, + start_value = 0, + end_value = -480, + time = 480 / animSpeed, + repeat_count = lvgl.ANIM_REPEAT_INFINITE, + path = "linear", + exec_cb = function(obj, value) + img:set{ + x = value + } + + right:set{ + x = value + 480 + } + end + } + + img:clear_flag(lvgl.FLAG.CLICKABLE) + + return img +end + +local function Frames(parent, src, fps) + local frame = Image(parent, src[1]) + fps = fps ~= 0 and fps or 25 + + frame.src = src + frame.len = #src + frame.i = 0 + + frame.timer = lvgl.Timer { + period = 1000 / fps, + cb = function(t) + frame.widget:set{ + src = frame.src[frame.i] + } + + frame.i = frame.i + 1 + if frame.i == frame.len then + frame.i = 1 + end + end + } + + frame.start = function(self) + self.timer:resume() + end + + frame.pause = function(self) + self.timer:pause() + end + + return frame +end + +local function Pipe(parent) + local up = Image(parent, IMAGE_PATH .. "pipe_up.png") + local down = Image(parent, IMAGE_PATH .. "pipe_down.png") + local pipe = { + up = up.widget, + down = down.widget, + w = up.w, + h = up.h, + x = 0, + y = 0 + } + + function pipe:updatePipePos() + self.up:set{ + x = self.x, + y = self.y - up.h + } + + self.down:set{ + x = self.x, + y = self.y + PIPE_GAP + } + end + + pipe:updatePipePos() + return pipe +end + +local function ObjInfo(x, y, w, h) + return { + x = x, + y = y, + w = w, + h = h + } +end + +local function Pipes(parent) + local pipes = {} + + -- add initial pipe + for i = 1, PIPE_COUNT do + pipes[i] = Pipe(parent) + if i == 1 then + pipes.w = pipes[i].w -- record pipe size + pipes.h = pipes[i].h + end + end + + local function pipesPosinit() + local x = 480; + local y = randomY() + + for i = 1, PIPE_COUNT do + local pipe = pipes[i] + pipe.x = x + pipe.y = y + pipe:updatePipePos() + pipes[i] = pipe + x = x + PIPE_SPACE + pipe.w + y = randomY() + end + end + + pipesPosinit() + + pipes.score = 0 + pipes.last = PIPE_COUNT -- first pipe index in pipes.pipes + pipes.totalWidth = (PIPE_COUNT) * (PIPE_SPACE + pipes.w) + pipes.birdInfo = ObjInfo(0, 0, 0, 0) + pipes.gapInfo = ObjInfo(0, 0, 0, 0) + + function pipes:setObjInfo(x, y, w, h) + self.birdInfo.x = x + self.birdInfo.y = y + if w then + self.birdInfo.w = w + end + if h then + self.birdInfo.h = h + end + end + + local function setGapInfo(x, y, w, h) + pipes.gapInfo.x = x + pipes.gapInfo.y = y + pipes.gapInfo.w = w + pipes.gapInfo.h = h + end + + pipes.objPassing = -1 + + local function isBirdCollision() + local bird = pipes.birdInfo + local gap = pipes.gapInfo + + -- far left + if bird.x + bird.w < gap.x then + return false + end + + -- far right + if bird.x > gap.x + gap.w then + return false + end + + -- in middle + + if (bird.y > gap.y) and (bird.y + bird.h < gap.y + gap.h) then + return false + end + return true + end + + local function moveVirtualX(dx) + for i = 1, PIPE_COUNT do + local pipe = pipes[i] + local newX = pipe.x + dx + + if newX + pipes.w < 0 then + newX = newX + pipes.totalWidth + pipe.y = randomY() + pipes.last = i + end + + pipe.x = newX + pipe.updatePipePos(pipe) + end + end + + local function checkScore(i) + local pipe = pipes[i] + + local bird = pipes.birdInfo + local gap = pipes.gapInfo + local passing = pipes.objPassing + + -- far left or right + if bird.x + bird.w < gap.x or bird.x > gap.x + gap.w then + if passing > 0 and i == passing then + pipes.score = pipes.score + 1 + passing = -1 + pipes.scoreUpdateCB(pipes.score) + end + else + if passing < 0 then + passing = i + end + end + + pipes.objPassing = passing + end + + --- Detect if obj has collision with pipes + local function collisionDetect() + local first = (pipes.last % PIPE_COUNT) + 1 + for idx = 0, PIPE_COUNT - 1 do + local i = (first + idx - 1) % PIPE_COUNT + 1 + local pipe = pipes[i] + setGapInfo(pipe.x, pipe.y, pipe.w, PIPE_GAP) + + if isBirdCollision() then + local bird = pipes.birdInfo + if pipes.collisionCB then + pipes.collisionCB() + end + end + + checkScore(i) + end + end + + pipes.preValue = 0 + pipes.anim = pipes[1].up:Anim{ + run = false, + start_value = 0, + end_value = 480, + time = 480 / MOVE_SPEED, -- MOVE_SPEED + repeat_count = lvgl.ANIM_REPEAT_INFINITE, + path = "linear", + exec_cb = function(obj, value) + local x = pipes.preValue + local d + if value < x then + d = value + 480 - x + else + d = value - x + end + pipes.preValue = value + moveVirtualX(-d) + collisionDetect() + end + } + + function pipes:start() + self.anim:start() + end + + function pipes:stop() + self.anim:stop() + end + + function pipes:reset() + pipesPosinit() + pipes.score = 0 + pipes.preValue = 0 + pipes.objPassing = -1 + end + + function pipes:setCollisionCB(collisionCB) + self.collisionCB = collisionCB + end + + function pipes:setScoreUpdateCB(cb) + self.scoreUpdateCB = cb + end + + return pipes +end + +local function Bird(parent, birdMovedCB) + -- create bird Frame(sprite) in 5FPS + local bird = Frames(parent, + {IMAGE_PATH .. "bird1.png", IMAGE_PATH .. "bird2.png", IMAGE_PATH .. "bird3.png"}, 5) + + local function birdVarInit() + bird.x = 240 - bird.w / 2 + bird.y = 240 - bird.h / 2 + bird.widget:set{ + x = bird.x, + y = bird.y + } + + bird.head = 0 + bird.force = 0 -- in unit of m/s^2 rather than N + bird.velocity = 0 -- vertical verlocity + bird.time = 0 -- time stamp when it updates + bird.moving = false + end + + birdVarInit() + + bird.setY = function(self) + bird.widget:set{ + y = bird.y + } + end + + bird.setHead = function(self) + bird.widget:set{ + angle = self.head + } + end + + bird.applyForce = function(self, force) + self.force = force + if bird.moving then + return + end + + bird.moving = true + self.y_anim:start() + end + + bird.pressed = function(self) + bird:applyForce(-13) + bird.velocity = 0 + end + + bird.released = function(self) + bird:applyForce(9.8) + bird.velocity = 0 + end + + local function velocity2HeadAngle(v) + -- -9.8 ~ 9.8:90 ~ -90 + return v * 60 + end + + -- y moving anim, in time. + bird.y_anim = bird.widget:Anim{ + run = false, + start_value = 0, + end_value = 1000, + time = 1000, -- 1000 ms + repeat_count = lvgl.ANIM_REPEAT_INFINITE, + path = "linear", + exec_cb = function(obj, tNow) + -- we use anim to get current time, can calculate position based on force/velocity + if tNow < bird.time then + tNow = tNow + 1000 + end + local y = bird.y + local preT = bird.time + local v = bird.velocity + local t = tNow < preT and tNow + 1000 - preT or tNow - preT + t = t * 0.001 -- ms to s + + v = bird.force * t + v + if v > 10 then + v = 10 + end + + if v < -10 then + v = -10 + end + + y = y + v * t * PIXEL_PER_METER + if y > BOTTOM_Y - 30 then + y = BOTTOM_Y - 30 + v = 0 + end + if y < TOP_Y then + y = TOP_Y + v = 0 + end + + bird.y = y + bird.time = tNow + bird.velocity = v + bird.head = velocity2HeadAngle(v) + + birdMovedCB(bird.x, bird.y) + -- set y + bird:setY() + bird:setHead() + end + } + + function bird:stop() + bird.y_anim:stop() + end + + function bird:gameOver() + -- like it's released forever + bird.released() + end + + function bird:start() + bird.y_anim:start() + end + + function bird:reset() + bird.stop() + birdVarInit() + end + + return bird; +end + +local function Background(root, bgEventCB) + local bgLayer = screenCreate(root) -- background layer + bgLayer:add_flag(lvgl.FLAG.CLICKABLE) -- we accept event here + + local bg = ImageScroll(bgLayer, IMAGE_PATH .. "bg_day.png", MOVE_SPEED * 0.4, 0) + local pipes = Pipes(bgLayer) + local land = ImageScroll(bgLayer, IMAGE_PATH .. "land.png", MOVE_SPEED, BOTTOM_Y) + + bgLayer:onevent(lvgl.EVENT.PRESSED, function(obj, code) + bgEventCB(lvgl.EVENT.PRESSED) + end) + + bgLayer:onevent(lvgl.EVENT.RELEASED, function(obj, code) + bgEventCB(lvgl.EVENT.RELEASED) + end) + + return { + pipes = pipes + } +end + +local function SysLayer(root) + local sysLayer = screenCreate(root) -- upper layer + return sysLayer +end + +local function createPlayBtn(sysLayer, onEvent) + local playBtn = Image(sysLayer, IMAGE_PATH .. "button_play.png").widget + playBtn:add_flag(lvgl.FLAG.CLICKABLE) + playBtn:set{ + align = { + type = lvgl.ALIGN.CENTER, + y_ofs = 80 + } + } + + playBtn:onevent(lvgl.EVENT.PRESSED, onEvent) + + return playBtn +end + +local function entry() + local scr = screenCreate() + local bgLayer + local mainLayer + local sysLayer + local bird + local pipes + local bgEventCB -- background layer pressed/released event + local birdMovedCB -- callback when bird position updates + local collisionCB -- callback when collision happends + local flagRunning = false + local gameStart -- API to start game + local gameOver -- API to stop game + local scoreLabel + local scoreBest = 0 + local scoreNow = 0 + local debouncing = false + -- global event process + + local scoreUpdateCB = function(score) + scoreLabel:set{ + text = string.format("%03d", score) + } + scoreNow = score + end + + print("font:", lvgl.BUILTIN_FONT.MONTSERRAT_26) + gameStart = function() + if flagRunning then + return + end + + bird:reset() + pipes:reset() + pipes:start() + bird:start() + flagRunning = true + scoreNow = 0 + if scoreLabel then + scoreLabel:set{ + text = string.format("%03d", 0) + } + end + end + + gameOver = function() + if not flagRunning then + return + end + + debouncing = true + flagRunning = false + + pipes:stop() + bird:gameOver() + if scoreNow > scoreBest then + scoreBest = scoreNow + end + + local gameoverImg = Image(sysLayer, IMAGE_PATH .. "text_game_over.png").widget + gameoverImg:set{ + align = { + type = lvgl.ALIGN.TOP_MID, + y_ofs = 100 + } + } + + gameoverImg:Anim{ + run = true, + start_value = 0, + end_value = 3600, + time = 2000, + repeat_count = 2, + path = "bounce", + exec_cb = function(obj, value) + obj:set{ + angle = value + } + end + } + + local scoreImg = Image(sysLayer, IMAGE_PATH .. "score.png").widget + scoreImg:set{ + align = { + type = lvgl.ALIGN.CENTER, + y_ofs = -20, + x_ofs = 0 + } + } + scoreImg:Anim{ + run = true, + start_value = 480, + end_value = 0, + time = 1000, + repeat_count = 1, + path = "ease_in", + exec_cb = function(obj, value) + obj:set{ + align = { + type = lvgl.ALIGN.CENTER, + x_ofs = value, + y_ofs = -20 + } + } + end + } + + local scoreResultLabel = scoreImg:Label{ + text = string.format("%03d", scoreNow), + text_font = lvgl.BUILTIN_FONT.MONTSERRAT_22, + align = { + type = lvgl.ALIGN.TOP_MID, + x_ofs = 0, + y_ofs = 25 + } + } + + local scoreBestLabel = scoreImg:Label{ + text = string.format("%03d", scoreBest), + text_font = lvgl.BUILTIN_FONT.MONTSERRAT_22, + align = { + type = lvgl.ALIGN.BOTTOM_MID, + x_ofs = 0, + y_ofs = -5 + } + } + scoreNow = 0 + + local playBtn; + playBtn = createPlayBtn(sysLayer, function(obj, code) + if debouncing then + return + end + + gameStart() + playBtn:delete() + playBtn = nil + gameoverImg:delete() + gameoverImg = nil + scoreImg:delete() + scoreImg = nil + end) + + lvgl.Timer { + period = 1000, + cb = function(t) + t:delete() + debouncing = false + end + } + end + + bgEventCB = function(event) + if not flagRunning then + return + end + + if event == lvgl.EVENT.PRESSED then + bird:pressed() + else + bird:released() + end + end + + local birdMovedCB = function(x, y) + pipes:setObjInfo(bird.x, bird.y) -- set intial bird position. + end + + local collisionCB = function() + print("bird collision, stop game") + -- call later + lvgl.Timer { + period = 10, + cb = function(t) + t:delete() + gameOver() + end + } + + end + + -- background layer, including sky, then pipes and land above + bgLayer = Background(scr, bgEventCB) -- background layer + pipes = bgLayer.pipes -- get pipes from bg layer for set bird info etc. + pipes:setCollisionCB(collisionCB) + pipes:setScoreUpdateCB(scoreUpdateCB) + + -- main layer, the bird + mainLayer = screenCreate(scr) -- main layer + bird = Bird(mainLayer, birdMovedCB) + pipes:setObjInfo(bird.x, bird.y, bird.w, bird.h) + -- system layer, score etc. + sysLayer = SysLayer(scr) + + local title = Image(sysLayer, IMAGE_PATH .. "title.png").widget + title:set{ + align = { + type = lvgl.ALIGN.TOP_MID, + y_ofs = 80 + } + } + + local playBtn; + playBtn = createPlayBtn(sysLayer, function() + print("pressed") + gameStart() + playBtn:delete() + playBtn = nil + title:delete() + title = nil + + local medal = Image(sysLayer, IMAGE_PATH .. "medals.png").widget + medal:set{ + align = { + type = lvgl.ALIGN.TOP_MID, + y_ofs = 10, + x_ofs = -50 + } + } + scoreLabel = sysLayer:Label{ + text = " 000", + text_font = lvgl.BUILTIN_FONT.MONTSERRAT_28, + align = { + type = lvgl.ALIGN.TOP_MID, + x_ofs = 10, + y_ofs = 20 + } + } + end) +end + +entry() + +-- bird = Bird(, nil) diff --git a/lib/luavgl/examples/flappyBird/land.png b/lib/luavgl/examples/flappyBird/land.png Binary files differnew file mode 100644 index 00000000..b93a861a --- /dev/null +++ b/lib/luavgl/examples/flappyBird/land.png diff --git a/lib/luavgl/examples/flappyBird/medals.png b/lib/luavgl/examples/flappyBird/medals.png Binary files differnew file mode 100644 index 00000000..c440df81 --- /dev/null +++ b/lib/luavgl/examples/flappyBird/medals.png diff --git a/lib/luavgl/examples/flappyBird/pipe_down.png b/lib/luavgl/examples/flappyBird/pipe_down.png Binary files differnew file mode 100644 index 00000000..e02d6946 --- /dev/null +++ b/lib/luavgl/examples/flappyBird/pipe_down.png diff --git a/lib/luavgl/examples/flappyBird/pipe_up.png b/lib/luavgl/examples/flappyBird/pipe_up.png Binary files differnew file mode 100644 index 00000000..6e8e8d5d --- /dev/null +++ b/lib/luavgl/examples/flappyBird/pipe_up.png diff --git a/lib/luavgl/examples/flappyBird/score.png b/lib/luavgl/examples/flappyBird/score.png Binary files differnew file mode 100644 index 00000000..cf567b0c --- /dev/null +++ b/lib/luavgl/examples/flappyBird/score.png diff --git a/lib/luavgl/examples/flappyBird/text_game_over.png b/lib/luavgl/examples/flappyBird/text_game_over.png Binary files differnew file mode 100644 index 00000000..b8c30fc2 --- /dev/null +++ b/lib/luavgl/examples/flappyBird/text_game_over.png diff --git a/lib/luavgl/examples/flappyBird/title.png b/lib/luavgl/examples/flappyBird/title.png Binary files differnew file mode 100644 index 00000000..557340f2 --- /dev/null +++ b/lib/luavgl/examples/flappyBird/title.png diff --git a/lib/luavgl/examples/flexLayout.lua b/lib/luavgl/examples/flexLayout.lua new file mode 100644 index 00000000..afafa5c8 --- /dev/null +++ b/lib/luavgl/examples/flexLayout.lua @@ -0,0 +1,27 @@ +local lvgl = require("lvgl") + +local root = lvgl.Object(nil, { + flex = { + flex_direction = "row", + flex_wrap = "wrap", + justify_content = "center", + align_items = "center", + align_content = "center", + }, + w = lvgl.HOR_RES(), + h = lvgl.VER_RES(), + align = lvgl.ALIGN.CENTER +}) + +for i = 1, 10 do + local item = root:Object { + w = 100, + h = lvgl.PCT(100), + } + item:clear_flag(lvgl.FLAG.SCROLLABLE) + + local label = item:Label { + text = string.format("label %d", i) + } + label:center() +end diff --git a/lib/luavgl/examples/font.lua b/lib/luavgl/examples/font.lua new file mode 100644 index 00000000..7d650cc0 --- /dev/null +++ b/lib/luavgl/examples/font.lua @@ -0,0 +1,18 @@ +local label1 = lvgl.Label(nil, { + x = 0, y = 0, + text_font = lvgl.Font("montserrat", 32, "normal"), + text = "Hello Font", + align = lvgl.ALIGN.CENTER +}) + +print("label1: ", label1) + +lvgl.Label(nil, { + -- x= 0, y = 0, + -- text_font = lvgl.Font("MiSansW medium, montserrat", 24), + text_font = lvgl.BUILTIN_FONT.MONTSERRAT_22, + text = "Hello Font2", +}):align_to({ + type = lvgl.ALIGN.OUT_BOTTOM_LEFT, + base = label1, +}) diff --git a/lib/luavgl/examples/fs.lua b/lib/luavgl/examples/fs.lua new file mode 100644 index 00000000..6672f4d0 --- /dev/null +++ b/lib/luavgl/examples/fs.lua @@ -0,0 +1,59 @@ +local function fs_example() + -- local f <close>, msg, code = lvgl.open_file(SCRIPT_PATH .. "/tmp.txt") -- for lua 5.4 + local f, msg, code = lvgl.fs.open_file(SCRIPT_PATH .. "/tmp.txt", "rw") + if not f then + print("failed: ", msg, code) + return + end + + print("f: ", f) + + f:write("0123456789", 123, "\n", "the remaining text") + f:seek("set", 0) -- go back + local header, remaining = f:read(10, "*a") + f:close() + if not header then + print("read failed or EOF") + return + end + + print("header len:", #header, ": ", header) + print("remaining: ", remaining) + + lvgl.Label(nil, { + x = 0, + y = 0, + text_font = lvgl.Font("montserrat", 20, "normal"), + text = header .. remaining, + align = lvgl.ALIGN.TOP_LEFT + }) + + local list = lvgl.List(nil, { + align = lvgl.ALIGN.TOP_RIGHT, + pad_all = 10, + text_font = lvgl.BUILTIN_FONT.MONTSERRAT_12 + }) + list:add_text("Directory list:") + + -- local dir <close>, msg, code = lvgl.fs.open_dir(SCRIPT_PATH .. "/") + local dir, msg, code = lvgl.fs.open_dir(SCRIPT_PATH .. "/") + if not dir then + print("open dir failed: ", msg, code) + return + end + + while true do + local d = dir:read() + if not d then break end + local is_dir = string.byte(d, 1) == string.byte("/", 1) + local str = (is_dir and "dir: " or "file: ") .. d + print(str) + + list:add_text(str):set{ + border_width = 1, + } + end + dir:close() +end + +fs_example() diff --git a/lib/luavgl/examples/group.lua b/lib/luavgl/examples/group.lua new file mode 100644 index 00000000..f80dd325 --- /dev/null +++ b/lib/luavgl/examples/group.lua @@ -0,0 +1,61 @@ +local function group_example() + local g = lvgl.group.create() + g:set_default() + + -- for demo purpose, set all indev to use this group + local indev = nil + while true do + indev = lvgl.indev.get_next(indev) + if not indev then break end + + local t = indev:get_type() + if t == 2 or t == 4 then + indev:set_group(g) + end + end + + local style = lvgl.Style({ + border_width = 5, + border_color = "#a00", + }) + + local root = lvgl.Object(nil, { + w = lvgl.PCT(100), + h = lvgl.PCT(100), + align = lvgl.ALIGN.CENTER, + bg_color = "#aaa", + flex = { + flex_direction = "row", + flex_wrap = "wrap" + } + }) + + root:add_style(style, lvgl.STATE.FOCUSED) + + for _ = 1, 5 do + local obj = root:Object({ + w = lvgl.PCT(50), + h = lvgl.PCT(50), + bg_color = "#555", + }) + + obj:add_style(style, lvgl.STATE.FOCUSED) + + obj:onClicked(function(obj, code) + print("clicked: ", obj) + end) + + obj:onevent(lvgl.EVENT.FOCUSED, function(obj, code) + print("focused: ", obj) + obj:scroll_to_view(true) + end) + + obj:onevent(lvgl.EVENT.DEFOCUSED, function(obj, code) + print("defocused: ", obj) + end) + + g:add_obj(obj) + end +end + +group_example() diff --git a/lib/luavgl/examples/indev.lua b/lib/luavgl/examples/indev.lua new file mode 100644 index 00000000..563b0f00 --- /dev/null +++ b/lib/luavgl/examples/indev.lua @@ -0,0 +1,61 @@ +local function indev_example() + local indev = lvgl.indev.get_act() + print("act indev: ", indev) + + + indev:on_event(lvgl.EVENT.SHORT_CLICKED, function () + print("indev pressed") + end) + local obj_act = lvgl.indev.get_obj_act() + print("obj_act: ", obj_act) + + local root = lvgl.Object(nil, { + w = lvgl.PCT(30), + h = lvgl.PCT(30), + align = lvgl.ALIGN.CENTER, + bg_color = "#aaa", + }) + + root:Object({ + w = 1000, + h = 1000, + align = lvgl.ALIGN.CENTER, + bg_color = "#555", + }):onevent(lvgl.EVENT.ALL, function(obj, code) + local indev = lvgl.indev.get_act() + + if not indev then return end + + if code == lvgl.EVENT.PRESSED then + local x, y = indev:get_point() + print("pressed: ", x, y) + end + + if code == lvgl.EVENT.PRESSING then + local x, y = indev:get_vect() + print("vect: ", x, y) + end + + if code == lvgl.EVENT.GESTURE then + local gesture_dir = indev:get_gesture_dir() + print("gesture_dir: ", gesture_dir) + end + + if code == lvgl.EVENT.RELEASED then + local scroll_dir = indev:get_scroll_dir() + print("scroll_dir: ", scroll_dir) + + local scroll_obj = indev:get_scroll_obj() + print("scroll_obj: ", scroll_obj) + + local x, y = indev:get_vect() + local obj_search = obj:indev_search(x, y) + print("indev search obj: ", obj_search) + + local obj_search = obj:indev_search({x, y}) + print("indev search obj2: ", obj_search) + end + end) +end + +indev_example() diff --git a/lib/luavgl/examples/keyboard.lua b/lib/luavgl/examples/keyboard.lua new file mode 100644 index 00000000..feb85d32 --- /dev/null +++ b/lib/luavgl/examples/keyboard.lua @@ -0,0 +1,46 @@ +local root = lvgl.Object(nil, { + w = lvgl.HOR_RES(), + h = lvgl.VER_RES(), + pad_all = 0, + bg_color = "#333", + bg_opa = lvgl.OPA(50), +}) +root:add_flag(lvgl.FLAG.CLICKABLE) + +local ta = root:Textarea { + password_mode = false, + one_line = true, + text_font = lvgl.Font("montserrat", 22), + text_color = "#FFF", + text = "Input text here", + w = lvgl.SIZE_CONTENT, + h = lvgl.SIZE_CONTENT, + bg_opa = 0, + border_width = 2, + pad_all = 2, + align = lvgl.ALIGN.TOP_MID, +} + +print("created textarea: ", ta) + +local keyboard = root:Keyboard { + textarea = ta, + align = lvgl.ALIGN.BOTTOM_MID, +} +print("created keyboard: ", keyboard) + +ta:onevent(lvgl.EVENT.PRESSED, function(obj, code) + keyboard:clear_flag(lvgl.FLAG.HIDDEN) +end) + +ta:onevent(lvgl.EVENT.READY, function() + keyboard:add_flag(lvgl.FLAG.HIDDEN) +end) + +ta:onevent(lvgl.EVENT.CANCEL, function(obj, code) + keyboard:add_flag(lvgl.FLAG.HIDDEN) +end) + +root:onClicked(function (obj, code) + keyboard:add_flag(lvgl.FLAG.HIDDEN) +end) diff --git a/lib/luavgl/examples/pointer.lua b/lib/luavgl/examples/pointer.lua new file mode 100644 index 00000000..c344f77b --- /dev/null +++ b/lib/luavgl/examples/pointer.lua @@ -0,0 +1,46 @@ +local root = lvgl.Object(nil, { + w = 0, + h = 0, + pad_all = 0, + align = lvgl.ALIGN.CENTER, + border_width = 1, + border_color = "#F00", +}) + +local pointer = root:Pointer { + src = SCRIPT_PATH .. "/assets/second.png", + x = -20, + y = -233, + border_width = 1, + border_color = "#0F0", + range = { + valueStart = 0, + valueRange = 60000, + angleStart = 0, + angleRange = -3600 + }, +} + +-- lvgl requires src set firstly, since lua cannot guarantee table order, +-- we set pivot after image src is set. +pointer:set { + pivot = { x = 20, y = 233 }, +} + +print("img w,h: ", pointer:get_img_size()) + +pointer:Anim{ + run = true, + start_value = 0, + end_value = 60000, + duration = 60000, + path = "linear", + repeat_count = lvgl.ANIM_REPEAT_INFINITE, + exec_cb = function(obj, value) + obj:set { + value = value + } + end, +} + +print("created pointer: ", pointer) diff --git a/lib/luavgl/examples/protectedcall.lua b/lib/luavgl/examples/protectedcall.lua new file mode 100644 index 00000000..a23fd9db --- /dev/null +++ b/lib/luavgl/examples/protectedcall.lua @@ -0,0 +1,36 @@ + +local function testCrash() + print(nil .. "") +end + +local function testCrash2() + testCrash() +end +local function testCrash3() + testCrash2() +end +local function testCrash4() + testCrash3() +end + +local function testCrash5() + testCrash4() +end + +local function testCrash6() + testCrash5() +end + +lvgl.Label(nil, { + text = "crash in 1 second.", + align = lvgl.ALIGN.CENTER +}) + +lvgl.Timer { + period = 1000, + cb = function(t) + t:delete() + -- crash in callback function is protected. + testCrash6() + end +}
\ No newline at end of file diff --git a/lib/luavgl/examples/roller.lua b/lib/luavgl/examples/roller.lua new file mode 100644 index 00000000..0d763327 --- /dev/null +++ b/lib/luavgl/examples/roller.lua @@ -0,0 +1,14 @@ +local roller = lvgl.Roller(nil, { + options = { + options = "January\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember", + mode = lvgl.ROLLER_MODE.INFINITE, + }, + visible_cnt = 4, + align = lvgl.ALIGN.CENTER +}) + +print("create roller:", roller) +roller:onevent(lvgl.EVENT.VALUE_CHANGED, function (obj, code) + print(obj:get_selected_str()) +end) + diff --git a/lib/luavgl/examples/tests.lua b/lib/luavgl/examples/tests.lua new file mode 100644 index 00000000..88d224ff --- /dev/null +++ b/lib/luavgl/examples/tests.lua @@ -0,0 +1,45 @@ +local container = lvgl.Object(nil, { + w = lvgl.HOR_RES(), + h = lvgl.VER_RES(), + bg_color = "#888", + bg_opa = lvgl.OPA(100), + border_width = 0, + radius = 0, + flex = { + flex_direction = "row", + flex_wrap = "wrap" + } +}) + +local function createBtn(parent, name) + local root = parent:Object { + w = lvgl.SIZE_CONTENT, + h = lvgl.SIZE_CONTENT, + bg_color = "#ccc", + bg_opa = lvgl.OPA(100), + border_width = 0, + radius = 10, + pad_all = 20, + } + + root:onClicked(function() + container:delete() + require(name) + end) + + root:Label { + text = name, + text_color = "#333", + align = lvgl.ALIGN.CENTER, + } +end + +createBtn(container, "font") +createBtn(container, "uservalue") +createBtn(container, "roller") +createBtn(container, "dropdown") +createBtn(container, "extension") +createBtn(container, "fs") +createBtn(container, "indev") +createBtn(container, "group") +createBtn(container, "protectedcall") diff --git a/lib/luavgl/examples/uservalue.lua b/lib/luavgl/examples/uservalue.lua new file mode 100644 index 00000000..414d8f0b --- /dev/null +++ b/lib/luavgl/examples/uservalue.lua @@ -0,0 +1,34 @@ +collectgarbage("collect") +print("initial: ", collectgarbage("count")) + +local str_t = {} +for i = 1, 1024 * 1024 do + str_t[#str_t + 1] = 'a' +end + +local str = table.concat(str_t) +str_t = nil + +collectgarbage("collect") +collectgarbage("collect") +print("after string collect: ", collectgarbage("count")) + +for i = 1, 10 do + local label = lvgl.Label(nil) + label:set_text_static(str) + label:delete() +end +str = nil + +print("after set text: ", collectgarbage("count")) +collectgarbage("collect") +print("after collect: ", collectgarbage("count")) +print("again: ", collectgarbage("count")) +collectgarbage("collect") +print("again2: ", collectgarbage("count")) +collectgarbage("collect") +print("again3: ", collectgarbage("count")) + +local label = lvgl.Label(nil) +label:set({ text = "Test Done" }) +label:center() |
