Template repo for tiny cross-platform apps that can be modified on phone, tablet or computer.
1local live = require 'live'
2
3-- love.keyboard.isDown doesn't work on Android, so emulate it using
4-- keypressed and keyreleased events
5local Keys_down = {}
6function key_down(key) return Keys_down[key] end
7
8-- main entrypoint for LÖVE
9--
10-- Most apps can just use the default shown in https://love2d.org/wiki/love.run,
11-- but we need to override it to recover from errors.
12function love.run()
13 love.handlers.keypressed = function(key, scancode, is_repeat)
14 Keys_down[key] = true
15 if love.keypressed then return love.keypressed(key, scancode, is_repeat) end
16 end
17 love.handlers.keyreleased = function(key, scancode)
18 Keys_down[key] = nil
19 if love.keyreleased then return love.keyreleased(key, scancode) end
20 end
21 if love.load then
22 xpcall(function() love.load(love.arg.parseGameArguments(arg), arg) end, live.handle_initialization_error)
23 end
24
25 if love.timer then love.timer.step() end
26
27 -- protect against runtime errors
28 return function()
29 local status, result = xpcall(run_frame, live.handle_error)
30 return result
31 end
32end
33
34-- one iteration of the event loop
35-- return nil to continue the event loop, non-nil to quit
36function run_frame()
37 if love.event then
38 love.event.pump()
39 for name, a,b,c,d,e,f in love.event.poll() do
40 if name == 'quit' then
41 if not love.quit or not love.quit() then
42 return a or 0
43 end
44 end
45 love.handlers[name](a,b,c,d,e,f)
46 end
47 end
48
49 local dt = 0
50 if love.timer then dt = love.timer.step() end
51 if love.update then love.update(dt) end
52
53 if love.graphics and love.graphics.isActive() then
54 love.graphics.origin()
55 love.graphics.clear(love.graphics.getBackgroundColor())
56 if love.draw then love.draw() end
57 love.graphics.present()
58 end
59
60 if love.timer then love.timer.sleep(0.001) end
61end
62
63-- Some helpers for Carousel programs.
64--
65-- I feel ambivalent about these in Dec 2024.
66--
67-- My apps originally included a harness for automated tests.
68-- This harness depended on apps using shims for a few things I wanted to
69-- test.
70-- That way my app could call say App.screen.print, and tests would not
71-- actually draw to the real screen.
72--
73-- However, tests aren't really a focus of Lua Carousel, and they were not a
74-- priority for Carousel2's upstreams.
75-- I still ended up using some of the App.* names in older example programs on
76-- the Lua Carousel devlog.
77--
78-- I guess I'll continue to support the bare minimum of App.* names for now
79-- just because adding corrections to the devlog seems like a lot of clutter.
80--
81-- I do care very much that someone can go to any older program on the devlog
82-- and it continue to run on newer versions of Carousel.
83--
84-- But for now I don't care about these App.* names beyond making those older
85-- devlog posts work. I'm not going to actually use them going forward. For
86-- now..
87
88App = {}
89
90function App.width(text)
91 return love.graphics.getFont():getWidth(text)
92end
93
94local function solo_touch()
95 local touches = love.touch.getTouches()
96 return #touches == 1
97end
98function App.mouse_down(mouse_button)
99 return love.mouse.isDown(mouse_button) or solo_touch()
100end
101
102local function solo_touchX()
103 local touches = love.touch.getTouches()
104 if #touches ~= 1 then return end
105 local x,y = love.touch.getPosition(touches[1])
106 return x
107end
108function App.mouse_x()
109 return love.mouse.getX() or solo_touchX()
110end
111
112local function solo_touchY()
113 local touches = love.touch.getTouches()
114 if #touches ~= 1 then return end
115 local x,y = love.touch.getPosition(touches[1])
116 return y
117end
118function App.mouse_y()
119 return love.mouse.getY() or solo_touchY()
120end
121
122-- Some useful helpers for programs.
123
124local major_version, _ = love.getVersion()
125major_version = tonumber(major_version)
126if major_version < 12 then
127 nativefs = require 'nativefs'
128end
129json = require 'json'
130utf8 = require 'utf8'
131
132array = require 'array'
133my_utf8 = require 'my_utf8'
134utils = require 'utils'
135Foreground_color = {0, 0, 0} -- available to app; indexed by position rather than r/g/b to work with select_rgb
136colorize = require 'colorize' -- must come after Foreground_color is defined
137
138require 'button'
139require 'wav'