Compare commits
No commits in common. "e46bc230a6ecef40329d64bcb32ac1c73557f8f9" and "9513a5c4717a0bc7a5ab24a293791df0136fe31c" have entirely different histories.
e46bc230a6
...
9513a5c471
17 changed files with 208 additions and 1023 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,5 +0,0 @@
|
||||||
dev
|
|
||||||
build/
|
|
||||||
games/*
|
|
||||||
!games/.gitkeep
|
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
return function(ll)
|
|
||||||
|
|
||||||
ll.mdir = nil
|
|
||||||
ll.mgme = nil
|
|
||||||
|
|
||||||
local ffi = require 'ffi'
|
|
||||||
ffi.cdef [[
|
|
||||||
int PHYSFS_mount(const char *, const char *, int);
|
|
||||||
int PHYSFS_unmount(const char *);
|
|
||||||
]]
|
|
||||||
|
|
||||||
local baseReq = '?.lua;?/init.lua;'
|
|
||||||
function ll.mount(gme)
|
|
||||||
local mdir = gme.base .. gme.dir
|
|
||||||
ll.mgme = gme
|
|
||||||
|
|
||||||
love.filesystem.setRequirePath(''
|
|
||||||
.. mdir .. '/?.lua;'
|
|
||||||
.. mdir .. '/?/init.lua;'
|
|
||||||
.. baseReq
|
|
||||||
)
|
|
||||||
-- FIXME: Bug may appear in Linux. Recompile Love2D or use official PPA.
|
|
||||||
if ffi.C.PHYSFS_mount(mdir, '/', 0) == 0
|
|
||||||
then error('Cannot mount '..mdir)
|
|
||||||
love.filesystem.setRequirePath(baseReq)
|
|
||||||
else ll.mdir = mdir
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function ll.umount()
|
|
||||||
if ll.mdir ~= nil then
|
|
||||||
ffi.C.PHYSFS_unmount(ll.mdir)
|
|
||||||
ll.mdir = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
20
lib/fs.lua
20
lib/fs.lua
|
@ -1,20 +0,0 @@
|
||||||
return function(ll)
|
|
||||||
|
|
||||||
function ll.fsIsAbs(f)
|
|
||||||
f = f:sub(1, 1)
|
|
||||||
return f == '/' or f == '\\'
|
|
||||||
end
|
|
||||||
|
|
||||||
function ll.fsIsRel(f)
|
|
||||||
return not ll.fsIsAbs(f)
|
|
||||||
end
|
|
||||||
|
|
||||||
function ll.fsFile(f)
|
|
||||||
return f:match '([^/\\]*)[/\\]*$'
|
|
||||||
end
|
|
||||||
|
|
||||||
function ll.fsDir(f)
|
|
||||||
return f:match '^(.*)[/\\]+[^/\\]*[/\\]*$'
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
100
lib/game.lua
100
lib/game.lua
|
@ -1,100 +0,0 @@
|
||||||
return function(ll)
|
|
||||||
|
|
||||||
ll.games = {}
|
|
||||||
|
|
||||||
local function parse(conf)
|
|
||||||
local r = {}
|
|
||||||
local k, v
|
|
||||||
|
|
||||||
local buf = ''
|
|
||||||
local t = 'str'
|
|
||||||
local esc = false
|
|
||||||
local prg = true
|
|
||||||
|
|
||||||
local i = 1
|
|
||||||
repeat
|
|
||||||
local ch = conf:sub(i, i)
|
|
||||||
|
|
||||||
if ch == '\\'
|
|
||||||
then esc = true
|
|
||||||
|
|
||||||
elseif ch == '#' then
|
|
||||||
repeat i = i + 1
|
|
||||||
ch = conf:sub(i, i)
|
|
||||||
until ch == '' or ch == '\n' or ch == '\r'
|
|
||||||
|
|
||||||
elseif ch == '[' then
|
|
||||||
buf = buf:match '%s*(.*)%s*'
|
|
||||||
assert(#buf == 0, 'Unexpected array usage')
|
|
||||||
t = 'arr'
|
|
||||||
prg = true
|
|
||||||
v = {}
|
|
||||||
|
|
||||||
elseif ch == ''
|
|
||||||
or (ch == '=' and not k)
|
|
||||||
or (ch == ']' and t == 'arr')
|
|
||||||
or (ch == ';' and t == 'arr')
|
|
||||||
or ch == '\n' or ch == '\r' then
|
|
||||||
buf = buf:match '^%s*(.-)%s*$'
|
|
||||||
|
|
||||||
if ch == '=' then
|
|
||||||
assert(t == 'str', 'Cannot use other types than string for key')
|
|
||||||
end
|
|
||||||
|
|
||||||
if t == 'str'
|
|
||||||
or (t == 'arr' and ch == ']')
|
|
||||||
then prg = false end
|
|
||||||
|
|
||||||
if not prg or ch == ';' then
|
|
||||||
if #buf ~= 0 then
|
|
||||||
if k then
|
|
||||||
if t == 'str'
|
|
||||||
then v = buf
|
|
||||||
elseif t == 'arr'
|
|
||||||
then table.insert(v, buf)
|
|
||||||
else error 'wut?' end
|
|
||||||
else k = buf
|
|
||||||
end
|
|
||||||
buf = ''
|
|
||||||
elseif ch ~= ''
|
|
||||||
and ch ~= '\r'
|
|
||||||
and ch ~= '\n'
|
|
||||||
then error 'empty buffer'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if k and v and not prg then
|
|
||||||
r[k] = v
|
|
||||||
k = nil
|
|
||||||
v = nil
|
|
||||||
buf = ''
|
|
||||||
t = 'str'
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif esc then
|
|
||||||
buf = buf .. ch
|
|
||||||
esc = false
|
|
||||||
|
|
||||||
else buf = buf .. ch
|
|
||||||
end
|
|
||||||
i = i + 1
|
|
||||||
until i >= #conf + 1
|
|
||||||
return r
|
|
||||||
end
|
|
||||||
|
|
||||||
function ll.gameNew(conf, file, base, dir)
|
|
||||||
local cfg = parse(conf or '')
|
|
||||||
local gme = {
|
|
||||||
name = cfg.name or dir or 'No name',
|
|
||||||
desc = cfg.desc or 'No description provided.',
|
|
||||||
base = base,
|
|
||||||
dir = dir,
|
|
||||||
main = cfg.main or 'main.lua',
|
|
||||||
screens = cfg.screens or cfg.pics or nil,
|
|
||||||
scrcur = 1,
|
|
||||||
scrprv = 1,
|
|
||||||
dat = nil,
|
|
||||||
}
|
|
||||||
return gme
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
81
lib/keyb.lua
81
lib/keyb.lua
|
@ -1,81 +0,0 @@
|
||||||
return function(ll)
|
|
||||||
|
|
||||||
local mx, my, mb, mpb
|
|
||||||
local dir, sc1, sc2, sclm
|
|
||||||
|
|
||||||
-- d - direction (h, v, x, y, *)
|
|
||||||
-- c1 - coordinate before card (mouse) (be left or top)
|
|
||||||
-- c2 - coordinate after card (mouse) (be right or bottom)
|
|
||||||
-- clm - other coordinate limit (mouse) (set -1 to disable)
|
|
||||||
function ll.kbInit(d, c1, c2, clim)
|
|
||||||
if d == 'h' or d == 'v' or d == '*'
|
|
||||||
then dir = d
|
|
||||||
elseif d == 'y'
|
|
||||||
then dir = 'v'
|
|
||||||
elseif d == 'x'
|
|
||||||
then dir = 'h'
|
|
||||||
else error 'Direction must be *, h (x) or v (y)'
|
|
||||||
end
|
|
||||||
|
|
||||||
c1, c2 =
|
|
||||||
tonumber(c1) or 0,
|
|
||||||
tonumber(c2) or 0
|
|
||||||
sc1, sc2, sclm =
|
|
||||||
math.min(c1, c2),
|
|
||||||
math.max(c1, c2),
|
|
||||||
tonumber(clim) or -1
|
|
||||||
end
|
|
||||||
|
|
||||||
-- returns: <, >, o, m, nil
|
|
||||||
-- ^ and v if dir is *
|
|
||||||
function ll.kbGet()
|
|
||||||
assert(dir, 'Call ll.kbInit(dir, coord1, coord2, coordlimit) before')
|
|
||||||
mx, my = love.mouse.getPosition()
|
|
||||||
mpb = mb
|
|
||||||
if love.mouse.isDown(1) then mb = 1
|
|
||||||
else mb = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
if love.keyboard.isScancodeDown('up', 'w')
|
|
||||||
then return dir == '*' and '^' or '<'
|
|
||||||
|
|
||||||
elseif love.keyboard.isScancodeDown('left', 'a')
|
|
||||||
then return '<'
|
|
||||||
|
|
||||||
elseif love.keyboard.isScancodeDown('down', 's')
|
|
||||||
then return dir == '*' and 'v' or '>'
|
|
||||||
|
|
||||||
elseif love.keyboard.isScancodeDown('right', 'd')
|
|
||||||
then return '>'
|
|
||||||
|
|
||||||
elseif love.keyboard.isScancodeDown('return', 'space')
|
|
||||||
then return 'o'
|
|
||||||
|
|
||||||
elseif love.keyboard.isDown 'menu'
|
|
||||||
then return 'm'
|
|
||||||
|
|
||||||
elseif mb == 0 and mpb == 1 then -- unpressed
|
|
||||||
if dir == 'h' then
|
|
||||||
if sclm < 0 or my <= sclm then
|
|
||||||
if mx <= sc1
|
|
||||||
then return '<'
|
|
||||||
elseif mx >= sc2
|
|
||||||
then return '>'
|
|
||||||
else return 'o'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if sclm < 0 or mx <= sclm then
|
|
||||||
if my <= sc1
|
|
||||||
then return '<'
|
|
||||||
elseif my >= sc2
|
|
||||||
then return '>'
|
|
||||||
else return 'o'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
51
lib/load.lua
51
lib/load.lua
|
@ -1,51 +0,0 @@
|
||||||
return function(ll)
|
|
||||||
|
|
||||||
function ll.addGame(file, cont)
|
|
||||||
local dir = ll.fsDir(file)
|
|
||||||
file = ll.fsFile(file)
|
|
||||||
local ext = file:match '%.(%w+)$'
|
|
||||||
print(file, ext, dir)
|
|
||||||
return 'NO!', nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function ll.gameAdd(conf, file, base, dir)
|
|
||||||
local gme = ll.gameNew(conf, file, base, dir)
|
|
||||||
gme.dat = {}
|
|
||||||
|
|
||||||
if gme.screens and gme.screens[1] then
|
|
||||||
gme.dat.scr = {}
|
|
||||||
for i = 1, #gme.screens do
|
|
||||||
table.insert(gme.dat.scr, love.graphics.newImage(ll.cfg.root .. gme.dir ..'/'.. gme.screens[i]))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(ll.games, gme)
|
|
||||||
return gme
|
|
||||||
end
|
|
||||||
|
|
||||||
local lfs = love.filesystem
|
|
||||||
local info = lfs.getInfo
|
|
||||||
|
|
||||||
for _, dir in pairs(love.filesystem.getDirectoryItems(ll.cfg.root)) do
|
|
||||||
local isDir
|
|
||||||
if info
|
|
||||||
then isDir = info(ll.cfg.root .. dir).type == 'directory'
|
|
||||||
else isDir = lfs.isDirectory(ll.cfg.root .. dir)
|
|
||||||
end
|
|
||||||
|
|
||||||
if isDir then
|
|
||||||
local file = ll.cfg.root .. dir..'/'.. 'info.ll'
|
|
||||||
local realDir = love.filesystem.getRealDirectory(file)
|
|
||||||
or love.filesystem.getRealDirectory(ll.cfg.root .. dir..'/main.lua')
|
|
||||||
if realDir
|
|
||||||
then ll.gameAdd(
|
|
||||||
love.filesystem.read(file),
|
|
||||||
file,
|
|
||||||
realDir ..'/'.. ll.cfg.root,
|
|
||||||
dir
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
27
lib/main.lua
27
lib/main.lua
|
@ -1,27 +0,0 @@
|
||||||
local ll = {}
|
|
||||||
|
|
||||||
ll.cfg = {
|
|
||||||
root = 'games/',
|
|
||||||
}
|
|
||||||
|
|
||||||
require 'lib.fs' (ll)
|
|
||||||
require 'lib.game' (ll)
|
|
||||||
require 'lib.chroot' (ll)
|
|
||||||
require 'lib.load' (ll)
|
|
||||||
require 'lib.keyb' (ll)
|
|
||||||
|
|
||||||
function ll.home()
|
|
||||||
ll.umount()
|
|
||||||
love.event.push('quit', 'restart')
|
|
||||||
end
|
|
||||||
|
|
||||||
ll.dt = false
|
|
||||||
function ll.devtools()
|
|
||||||
if not ll.dt then
|
|
||||||
ll.dt = true
|
|
||||||
__LL = ll
|
|
||||||
pcall(function() require 'dev.tools' end)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return ll
|
|
11
ll-min.lua
11
ll-min.lua
|
@ -1,17 +1,8 @@
|
||||||
-- Minimal Love Loader API
|
-- minimal Love Loader API
|
||||||
-- Version 2.1
|
|
||||||
-- (c) Er2 2022 <er2@dismail.de>
|
|
||||||
-- Zlib License
|
|
||||||
|
|
||||||
if not llUsed then
|
if not llUsed then
|
||||||
|
|
||||||
COLDIV = love.getVersion() == 0 and 1 or 255
|
COLDIV = love.getVersion() == 0 and 1 or 255
|
||||||
MOBILE = love.system.getOS() == 'Android'
|
|
||||||
or love.system.getOS() == 'iOS'
|
|
||||||
|
|
||||||
if MOBILE
|
|
||||||
then love.window.setFullscreen(true)
|
|
||||||
end
|
|
||||||
|
|
||||||
function love.resize(x, y)
|
function love.resize(x, y)
|
||||||
W, H = x, y
|
W, H = x, y
|
||||||
|
|
17
luapack.lua
17
luapack.lua
|
@ -1,17 +0,0 @@
|
||||||
return {
|
|
||||||
entry = 'main.lua',
|
|
||||||
output = 'build/main.lua',
|
|
||||||
plug = {
|
|
||||||
require 'plug.minify' {
|
|
||||||
extGlob = {
|
|
||||||
'love',
|
|
||||||
'llUsed',
|
|
||||||
'llHome',
|
|
||||||
'resize',
|
|
||||||
'COLDIV',
|
|
||||||
'MOBILE',
|
|
||||||
'W', 'H',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
238
main.lua
238
main.lua
|
@ -1,71 +1,219 @@
|
||||||
local ll = require 'lib.main'
|
|
||||||
error = love.errhand or love.errorhandler
|
|
||||||
|
|
||||||
function splash()
|
local root = 'games/'
|
||||||
love.graphics.setColor(255, 255, 255, 100 / COLDIV)
|
|
||||||
if ll.mgme.screens and ll.mgme.screens[1] then
|
-- games library and selection
|
||||||
local img = love.graphics.newImage(ll.mgme.screens[1])
|
local gms = {}
|
||||||
love.graphics.draw(img, 0, 0, 0, W / img:getWidth(), H / img:getHeight())
|
local sel = 1
|
||||||
end
|
local sgme
|
||||||
love.graphics.setColor(255, 255, 255, 255)
|
|
||||||
love.graphics.print('Loading '..ll.mgme.name, W / 2, H / 2)
|
-- some internals
|
||||||
|
local cx, cy, cw, ch
|
||||||
|
local f, bf
|
||||||
|
|
||||||
|
local ffi = require 'ffi'
|
||||||
|
local fd
|
||||||
|
ffi.cdef [[
|
||||||
|
int PHYSFS_mount(const char *, const char *, int);
|
||||||
|
int PHYSFS_unmount(const char *);
|
||||||
|
]]
|
||||||
|
|
||||||
|
local function llResz()
|
||||||
|
cw, ch = W / 1.25, H / 1.25
|
||||||
|
cx, cy = (W - cw) / 2, (H - ch) / 2
|
||||||
|
|
||||||
|
local th = math.min(W, H) / 8
|
||||||
|
|
||||||
|
f = love.graphics.newFont(th / 3)
|
||||||
|
bf = love.graphics.newFont(th / 2)
|
||||||
end
|
end
|
||||||
|
resize = llResz
|
||||||
ll.skin = require 'skins.psp' (ll)
|
|
||||||
|
|
||||||
require 'll-min'
|
require 'll-min'
|
||||||
llUsed = true
|
llUsed = true
|
||||||
|
|
||||||
if love.errorhandler
|
local function chroot(dir, main)
|
||||||
then love.errorhandler = error
|
fd = love.filesystem.getSource() .. dir
|
||||||
else love.errhand = error
|
love.filesystem.setRequirePath(
|
||||||
|
'?.lua;?/init.lua;'
|
||||||
|
.. dir .. '/?.lua;'
|
||||||
|
.. dir .. '/?/init.lua;'
|
||||||
|
)
|
||||||
|
-- FIXME: Bug in Linux (Debian)
|
||||||
|
ffi.C.PHYSFS_mount(fd, '/', 0);
|
||||||
|
if main then
|
||||||
|
load(love.filesystem.read(dir ..'/'.. main), main)()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function escChroot()
|
||||||
|
if fd then
|
||||||
|
ffi.C.PHYSFS_unmount(fd);
|
||||||
|
fd = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function gmeNew(cont, dir, file)
|
||||||
|
local gme = {
|
||||||
|
name = 'No name',
|
||||||
|
desc = 'No description provided.',
|
||||||
|
dir = dir,
|
||||||
|
main = 'main.lua',
|
||||||
|
pics = nil,
|
||||||
|
psel = 2,
|
||||||
|
ppsl = 1,
|
||||||
|
}
|
||||||
|
local fi = false
|
||||||
|
cont = cont or ''
|
||||||
|
cont = cont:gsub('[^\\]#[^\n]*', '')
|
||||||
|
for v in cont:gmatch '([^\n]+)' do
|
||||||
|
local k, v = v:match '^%s*([%w_]+)%s*=%s*(.*)%s*$'
|
||||||
|
if k == 'name'
|
||||||
|
or k == 'desc'
|
||||||
|
or k == 'main'
|
||||||
|
then gme[k] = v
|
||||||
|
fi = true
|
||||||
|
elseif k == 'pic' then
|
||||||
|
gme.pics = gme.pics or {}
|
||||||
|
table.insert(gme.pics, v)
|
||||||
|
fi = true
|
||||||
|
elseif k == 'pics' then
|
||||||
|
local t = {}
|
||||||
|
v = v:sub(2, -2)
|
||||||
|
for v in v:gmatch '%s*([^;]+%a+)%s*;?'
|
||||||
|
do table.insert(t, v) end
|
||||||
|
gme[k] = t
|
||||||
|
fi = true
|
||||||
|
elseif k
|
||||||
|
then error('unknown field "'.. k ..'" in "'.. file ..'"')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if gme.pics then
|
||||||
|
for k, v in pairs(gme.pics) do
|
||||||
|
gme.pics[k] = love.graphics.newImage(root .. dir ..'/'.. v)
|
||||||
|
end
|
||||||
|
gme.psel = math.min(2, #gme.pics)
|
||||||
|
end
|
||||||
|
if not fi then
|
||||||
|
gme.name = dir
|
||||||
|
end
|
||||||
|
table.insert(gms, gme)
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, v in pairs(love.filesystem.getDirectoryItems(root)) do
|
||||||
|
local file = v..'/'.. 'info.ll'
|
||||||
|
gmeNew(love.filesystem.read(root .. file), v, file)
|
||||||
|
end
|
||||||
|
|
||||||
|
local pf, mx, mb, mpb
|
||||||
|
|
||||||
|
local pcht = 60 * 5
|
||||||
|
local pchat = math.floor(1 / pcht * 2 * 255 + 0.5)
|
||||||
|
local pchv, pcha = 0, 0
|
||||||
|
local function llUpdate()
|
||||||
|
mx = love.mouse.getX()
|
||||||
|
mpb = mb
|
||||||
|
mb = 0
|
||||||
|
if love.mouse.isDown(1) then mb = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if mpb == 1 and mb == 0 then
|
||||||
|
if mx <= cx then
|
||||||
|
sel = sel - 1
|
||||||
|
if sel < 1 then sel = #gms end
|
||||||
|
elseif mx >= cx + cw then
|
||||||
|
sel = sel + 1
|
||||||
|
if sel > #gms then sel = 1 end
|
||||||
|
else sgme = gms[sel]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
pchv = pchv + 1
|
||||||
|
if pchv >= pcht then
|
||||||
|
pchv, pcha = 0, 0
|
||||||
|
for _, v in pairs(gms) do
|
||||||
|
if v.pics then
|
||||||
|
v.ppsl = v.psel
|
||||||
|
v.psel = v.psel + 1
|
||||||
|
if v.psel > #v.pics
|
||||||
|
then v.psel = 1 end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else pcha = math.min(255, pcha + pchat)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function llDraw()
|
||||||
|
love.graphics.polygon('fill',
|
||||||
|
8, H / 2,
|
||||||
|
32, H / 2 - 32,
|
||||||
|
32, H / 2 + 32)
|
||||||
|
|
||||||
|
love.graphics.polygon('fill',
|
||||||
|
W - 8, H / 2,
|
||||||
|
W - 32, H / 2 - 32,
|
||||||
|
W - 32, H / 2 + 32)
|
||||||
|
|
||||||
|
local oy, t = 0, ''
|
||||||
|
local gme = gms[sel]
|
||||||
|
if gme then
|
||||||
|
local ph = ch / 1.5
|
||||||
|
if gme.pics then
|
||||||
|
local p, n = gme.pics[gme.ppsl], gme.pics[gme.psel]
|
||||||
|
love.graphics.draw(p, cx, cy, 0, cw / p:getWidth(), ph / p:getHeight())
|
||||||
|
love.graphics.setColor(255, 255, 255, pcha / COLDIV)
|
||||||
|
love.graphics.draw(n, cx, cy, 0, cw / n:getWidth(), ph / n:getHeight())
|
||||||
|
love.graphics.setColor(255, 255, 255, 255)
|
||||||
|
end
|
||||||
|
love.graphics.rectangle('line', cx, cy, cw, ph)
|
||||||
|
love.graphics.rectangle('line', cx, cy, cw, ch)
|
||||||
|
|
||||||
|
oy = cy + ph
|
||||||
|
love.graphics.setFont(bf)
|
||||||
|
love.graphics.print(gme.name, cx, oy)
|
||||||
|
oy = oy + bf:getHeight(gme.name)
|
||||||
|
love.graphics.setFont(f)
|
||||||
|
love.graphics.print(gme.desc, cx, oy)
|
||||||
|
|
||||||
|
else oy = H / 2
|
||||||
|
t = 'No games'
|
||||||
|
love.graphics.setFont(bf)
|
||||||
|
love.graphics.print(t, (W - bf:getWidth(t)) / 2, oy)
|
||||||
|
oy = oy + bf:getHeight(t)
|
||||||
|
love.graphics.setFont(f)
|
||||||
|
t = 'There is no projects/games to run'
|
||||||
|
love.graphics.print(t, (W - f:getWidth(t)) / 2, oy)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function llHome()
|
||||||
|
escChroot()
|
||||||
|
love.event.push('quit', 'restart')
|
||||||
end
|
end
|
||||||
|
|
||||||
local brk = false
|
local brk = false
|
||||||
while not brk and not ll.mdir do
|
while not brk and not sgme do
|
||||||
-- event handling
|
-- event handling
|
||||||
love.event.pump()
|
love.event.pump()
|
||||||
for n, a,b,c in love.event.poll() do
|
for n, a,b,c,d,e,f in love.event.poll() do
|
||||||
if n == 'quit'
|
if n == 'quit' then
|
||||||
or (n == 'keypressed' and a == 'escape')
|
escChroot()
|
||||||
then ll.umount()
|
|
||||||
love.event.push('quit')
|
love.event.push('quit')
|
||||||
brk = true; break
|
brk = true; break
|
||||||
end
|
end
|
||||||
love.handlers[n](a,b,c)
|
love.handlers[n](a,b,c,d,e,f)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- update and drawing
|
-- update and drawing
|
||||||
ll.skin.update()
|
llUpdate()
|
||||||
love.graphics.origin()
|
love.graphics.origin()
|
||||||
love.graphics.clear(0, 0, 0)
|
love.graphics.clear(0, 0, 0)
|
||||||
ll.skin.draw()
|
llDraw()
|
||||||
love.graphics.present()
|
love.graphics.present()
|
||||||
love.timer.sleep(0.001)
|
love.timer.sleep(0.001)
|
||||||
end
|
end
|
||||||
|
|
||||||
if ll.mdir then
|
if sgme then
|
||||||
love.graphics.setNewFont()
|
love.graphics.setNewFont()
|
||||||
resize = nil
|
resize = nil
|
||||||
|
chroot(root .. sgme.dir, sgme.main)
|
||||||
love.graphics.clear(0, 0, 0)
|
|
||||||
splash()
|
|
||||||
love.graphics.present()
|
|
||||||
|
|
||||||
if ll.skin.lovecb then
|
|
||||||
for _, v in pairs(ll.skin.lovecb)
|
|
||||||
do love[v] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
love.filesystem.setIdentity(ll.mgme.dir)
|
|
||||||
local f, err = load(love.filesystem.read(ll.mgme.main), ll.mgme.name)
|
|
||||||
if not f then error(err)
|
|
||||||
else xpcall(f, function(e)
|
|
||||||
error(e)
|
|
||||||
llHome()
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
love.resize(love.graphics.getDimensions())
|
|
||||||
end
|
end
|
||||||
|
|
97
readme.md
97
readme.md
|
@ -2,99 +2,31 @@
|
||||||
|
|
||||||
Custom menu for selecting game from multiple for Love2D.
|
Custom menu for selecting game from multiple for Love2D.
|
||||||
|
|
||||||
![PSP Style](./scr/psp.png)
|
|
||||||
|
|
||||||
[Other screenshots](./scr)
|
|
||||||
|
|
||||||
# How it works?
|
# How it works?
|
||||||
|
|
||||||
Just place games into `games` folder! (like `this_folder/games/game/main.lua`)
|
If simple: just place games in `games` folder with structure like `games/yourgame/main.lua`
|
||||||
|
|
||||||
Technically, this creates the loop until game wasn't selected or user wants to exit
|
If technically: creates local variables functions and variables.
|
||||||
with custom event handling and redrawing.
|
Creates the loop until game wasn't selected with manual event handling and redrawing.
|
||||||
|
|
||||||
# LibLL
|
# Things left or API
|
||||||
|
|
||||||
Love Loader from 2.0 includes backend API to simplify creating custom skins.
|
We are not keep environment super clear (except local variables ;))
|
||||||
|
so there are some variables can be used in game:
|
||||||
|
|
||||||
It have not so many functions and fields:
|
`W` and `H` variables: width and height of the screen, controlled by love.resize function.
|
||||||
|
|
||||||
- `ll.games` - field for games, which have this structure:
|
`love.resize` and optional `resize` payload: functions called when screen size when changed and at boot.
|
||||||
```lua
|
|
||||||
{
|
|
||||||
name = 'string', -- Friendly name for game or placeholder
|
|
||||||
desc = 'string', -- Description for game or placeholder
|
|
||||||
base = 'string', -- base directory used in game mounting, must end with `/`
|
|
||||||
dir = 'string', -- directory name, used if no name was defined
|
|
||||||
main = 'string', -- main file to execute or `main.lua`
|
|
||||||
screens = {'array of', 'path to screenshots'},
|
|
||||||
scrcur = 1, --[[number]] -- current index from screenshots
|
|
||||||
scrprv = 1, --[[number]] -- previous index from screenshots
|
|
||||||
dat = nil, --[[any]] -- maybe platform-dependent data to reduce operations
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- `ll.mdir` - string or nil, contains full mounted directory.
|
`love.event.quit`: function to quit to menu screen
|
||||||
|
|
||||||
- `ll.mgme` - game or nil, contains mounted game.
|
`COLDIV`: color divider (1 or 255) to setColor function
|
||||||
|
|
||||||
- `ll.gameNew(configuration --[[string]], fileName --[[string, not used]], base --[[string]], directory --[[string]])`
|
`llUsed`: is Love Loader used
|
||||||
|
|
||||||
Creates game object (defined above) and returns it.
|
`llHome`: function to quit to menu screen
|
||||||
|
|
||||||
- `ll.gameAdd(conf, file, base, dir)` - same as `ll.gameNew` with insertion into `ll.games`.
|
They also can be used without Love Loader if load `ll-min.lua`
|
||||||
|
|
||||||
- `ll.addGame(fileName, fileContent)` - function for file dropping, reserved for v3.0.
|
|
||||||
|
|
||||||
- `ll.mount(game)` - mounts game.
|
|
||||||
|
|
||||||
Can throw an error.
|
|
||||||
|
|
||||||
Sets `ll.mdir` and `ll.mgme`.
|
|
||||||
|
|
||||||
- `ll.umount()` - unmounts game if can.
|
|
||||||
|
|
||||||
Unsets `ll.mdir` and `ll.mgme`.
|
|
||||||
|
|
||||||
- `ll.home()` - calls `llHome`
|
|
||||||
|
|
||||||
- `ll.dt` - is developer tools enabled?
|
|
||||||
|
|
||||||
- `__LL` - global variable of Love Loader instance when developer tools enabled.
|
|
||||||
|
|
||||||
- `ll.devtools()` - enable developer tools.
|
|
||||||
|
|
||||||
- `ll.fsIsAbs(file)` - is file absolute (/file)?
|
|
||||||
|
|
||||||
- `ll.fsIsRel(file)` - is file relative, inverted result of ll.fsIsAbs (./file).
|
|
||||||
|
|
||||||
- `ll.fsDir(path)` - get directory name (2 from /1/2/3.file).
|
|
||||||
|
|
||||||
- `ll.fsFile(path)` - get file (including dividers after) (2 from /1/2/).
|
|
||||||
|
|
||||||
- `ll.kbInit(direction --[[string: *, h, v, x, y]], c1 --[[number, coordinate before card for mouse (left/top)]], c2 --[[number, coordinate after card for mouse (right/bottom)]], clim --[[other coordinate limit for mouse or -1 to disable]])` - initialize keyboard module for skins.
|
|
||||||
|
|
||||||
- `ll.kbGet() --[[nil, string: <, >, o, m, ^ anv v if direction is *]]` - get key pressed.
|
|
||||||
|
|
||||||
# API
|
|
||||||
|
|
||||||
To reduce things to do for game developers, this loader creates some global variables to use.
|
|
||||||
|
|
||||||
You can also use it without Love Loader (or if your game can distribute without loader) by including `ll-min.lua` file.
|
|
||||||
|
|
||||||
`W` and `H`: width and height of the screen which controls by custom love.resize function.
|
|
||||||
|
|
||||||
`love.resize` and optional `resize` payload: functions called when screen size was changed and on booting.
|
|
||||||
|
|
||||||
`love.event.quit`: function to exit to main screen.
|
|
||||||
|
|
||||||
`llHome`: function called by `love.event.quit` (broken for now).
|
|
||||||
|
|
||||||
`llUsed`: is Love Loader (not minimal API) used.
|
|
||||||
|
|
||||||
`COLDIV`: color divider (1 or 255) to `love.graphics.setColor` function.
|
|
||||||
|
|
||||||
`MOBILE`: is this device runs Android or iOS?
|
|
||||||
|
|
||||||
# Fill game information
|
# Fill game information
|
||||||
|
|
||||||
|
@ -108,6 +40,5 @@ name = New awesome game using Love Loader
|
||||||
desc = Some descripion about the game.
|
desc = Some descripion about the game.
|
||||||
# main = optional main file instead of `main.lua`
|
# main = optional main file instead of `main.lua`
|
||||||
pic = screen.png
|
pic = screen.png
|
||||||
pics = [ screen.png; screen2.png ] # wow arrays
|
pics = [ screen.png; screen2.png ] # wow array
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
BIN
scr/base.png
BIN
scr/base.png
Binary file not shown.
Before Width: | Height: | Size: 11 KiB |
BIN
scr/gui.png
BIN
scr/gui.png
Binary file not shown.
Before Width: | Height: | Size: 62 KiB |
BIN
scr/psp.png
BIN
scr/psp.png
Binary file not shown.
Before Width: | Height: | Size: 25 KiB |
190
skins/base.lua
190
skins/base.lua
|
@ -1,190 +0,0 @@
|
||||||
return function(ll)
|
|
||||||
|
|
||||||
-- Basic cmd-like style UI
|
|
||||||
-- FIXME: Console scrolling
|
|
||||||
|
|
||||||
local cw, ch, ctw, cth
|
|
||||||
local ct = 'Love Loader v2.0\n(c) Er2 2022\tZlib License\n\n'
|
|
||||||
local cce = false
|
|
||||||
local buf = ''
|
|
||||||
|
|
||||||
local mb, mpb, mt = 0, 0, 0
|
|
||||||
|
|
||||||
local function ccp()
|
|
||||||
local argv = {}
|
|
||||||
for v in buf:gmatch '%S+'
|
|
||||||
do table.insert(argv, v)
|
|
||||||
end
|
|
||||||
local cmd = (argv[1] or ''):lower()
|
|
||||||
if cmd == '' then return '' -- nothing
|
|
||||||
elseif cmd == 'help' then return 'Available commands:'
|
|
||||||
.. '\nhelp\t\tThis command'
|
|
||||||
.. '\nls\t\tList of games'
|
|
||||||
.. '\ndir\t\tSame as ls'
|
|
||||||
.. '\ncat\t<path>\tInformation about game'
|
|
||||||
.. '\ninfo\t<path>\tSame as cat'
|
|
||||||
.. '\nrun\t<path>\tStart game'
|
|
||||||
.. '\nmount\t<path>\tSame as run'
|
|
||||||
.. '\nchroot\t<path>\tSame as run'
|
|
||||||
.. '\nclear\t\tClear screen'
|
|
||||||
.. '\neval\t<code>\tExecute code'
|
|
||||||
elseif cmd == 'clear' then
|
|
||||||
ct = ''
|
|
||||||
return ''
|
|
||||||
elseif cmd == 'eval' then
|
|
||||||
local code = buf:match '^%S+%s+(.*)'
|
|
||||||
local f, err = load(code, 'test.lua')
|
|
||||||
if not f then return err
|
|
||||||
else return tostring(f() or 'nil')
|
|
||||||
end
|
|
||||||
elseif cmd == 'ls'
|
|
||||||
or cmd == 'dir' then
|
|
||||||
local r = ''
|
|
||||||
if #ll.games == 0 then
|
|
||||||
return ('%s: No games found. Add some to the library.'):format(argv[1])
|
|
||||||
end
|
|
||||||
for i = 1, #ll.games do
|
|
||||||
local v = ll.games[i]
|
|
||||||
r = r .. ('%s\t(%s)\t - %s\n'):format(v.dir, v.name, v.desc)
|
|
||||||
end
|
|
||||||
return r .. ('\nTotal: %3d games\n'):format(#ll.games)
|
|
||||||
elseif cmd == 'cat'
|
|
||||||
or cmd == 'info' then
|
|
||||||
if not argv[2]
|
|
||||||
then return ('%s: Game directory missing'):format(argv[1])
|
|
||||||
end
|
|
||||||
local r = ''
|
|
||||||
for _, v in pairs(ll.games) do
|
|
||||||
if argv[2] == v.dir
|
|
||||||
or argv[2] == v.base .. v.dir
|
|
||||||
then r = r..
|
|
||||||
( '\nFriendly name:\t%s'
|
|
||||||
..'\nDescription:\t%s'
|
|
||||||
..'\nLocation:\t%s%s'
|
|
||||||
..'\nMain file:\t%s'
|
|
||||||
..'\n\n\t\tScreenshots are not supported yet.'
|
|
||||||
..'\n'):format(v.name, v.desc, v.base, v.dir, v.main)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if r == '' then r = 'Not found' end
|
|
||||||
return r
|
|
||||||
elseif cmd == 'run'
|
|
||||||
or cmd == 'mount'
|
|
||||||
or cmd == 'chroot' then
|
|
||||||
local gme
|
|
||||||
for _, v in pairs(ll.games) do
|
|
||||||
if argv[2] == v.dir
|
|
||||||
or argv[2] == v.base .. v.dir
|
|
||||||
then if gme then
|
|
||||||
return 'Error: multiple paths found, use full location'
|
|
||||||
end
|
|
||||||
gme = v end
|
|
||||||
end
|
|
||||||
if gme
|
|
||||||
then ll.mount(gme)
|
|
||||||
love.keyboard.setTextInput(false)
|
|
||||||
return ''
|
|
||||||
else return 'Not found'
|
|
||||||
end
|
|
||||||
else return 'Unknown command "'.. cmd .. '"'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function update()
|
|
||||||
mpb = mb
|
|
||||||
if love.mouse.isDown(1) then mb = 1
|
|
||||||
if mpb ~= 1
|
|
||||||
then mt = os.time()
|
|
||||||
end
|
|
||||||
else mb = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
if mb == 0 and mpb == 1
|
|
||||||
and os.time() - mt <= 1 then
|
|
||||||
if love.system.getOS() == 'Android' then
|
|
||||||
love.keyboard.setTextInput(
|
|
||||||
not love.keyboard.hasTextInput(),
|
|
||||||
0, H, W, ch)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not cce then
|
|
||||||
cce = true
|
|
||||||
local r = ccp()
|
|
||||||
if #r ~= 0 then ct = ct.. '\n'.. r end
|
|
||||||
ct = ct.. '\n> '
|
|
||||||
buf = ''
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local utf8 = require 'utf8'
|
|
||||||
local function draw()
|
|
||||||
love.graphics.setColor(255, 255, 255)
|
|
||||||
|
|
||||||
local x, y = 0, 0
|
|
||||||
for p, cde in utf8.codes(ct) do
|
|
||||||
local chr = utf8.char(cde)
|
|
||||||
if chr == '\n'
|
|
||||||
then x, y = 0, y + 1
|
|
||||||
elseif chr == '\r'
|
|
||||||
then x = 0
|
|
||||||
elseif chr == '\t'
|
|
||||||
then x = x + 8 - (x % 8)
|
|
||||||
elseif chr == '\v'
|
|
||||||
then y = y + 1
|
|
||||||
else love.graphics.print(chr, x * cw, y * ch)
|
|
||||||
if x >= ctw
|
|
||||||
then x, y = x - ctw, y + 1
|
|
||||||
else x = x + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if os.time() % 2 == 0
|
|
||||||
then love.graphics.rectangle('fill', x * cw, y * ch, cw, ch)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function resize()
|
|
||||||
local f = love.graphics.newFont(math.min(W, H) / 32)
|
|
||||||
love.graphics.setFont(f)
|
|
||||||
cw, ch = f:getWidth 'm', f:getHeight 'A'
|
|
||||||
ctw, cth =
|
|
||||||
math.floor(W / cw) - 1,
|
|
||||||
math.floor(H / ch) - 1
|
|
||||||
|
|
||||||
love.keyboard.setTextInput(true, 0, H, W, ch)
|
|
||||||
end
|
|
||||||
|
|
||||||
function love.textinput(txt)
|
|
||||||
ct = ct.. txt
|
|
||||||
buf = buf.. txt
|
|
||||||
end
|
|
||||||
|
|
||||||
function love.keypressed(k)
|
|
||||||
if k == 'backspace' then
|
|
||||||
local off = utf8.offset(buf, -1)
|
|
||||||
if off then
|
|
||||||
buf = buf:sub(1, off - 1)
|
|
||||||
off = utf8.offset(ct, -1)
|
|
||||||
if off
|
|
||||||
then ct = ct:sub(1, off - 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif k == 'return'
|
|
||||||
then cce = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
love.keyboard.setKeyRepeat(true)
|
|
||||||
love.window.setMode(800, 600, {resizable = true})
|
|
||||||
|
|
||||||
return {
|
|
||||||
update = update,
|
|
||||||
draw = draw,
|
|
||||||
lovecb = {
|
|
||||||
'textinput',
|
|
||||||
'keypressed',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
end
|
|
198
skins/gui.lua
198
skins/gui.lua
|
@ -1,198 +0,0 @@
|
||||||
return function(ll)
|
|
||||||
|
|
||||||
ll.cfg.pcht = ll.cfg.pcht or 60 * 5
|
|
||||||
|
|
||||||
local pikchv, pikcha = 0, 0
|
|
||||||
local pikchao = math.floor(1 / ll.cfg.pcht * 2 * 255 + 0.5)
|
|
||||||
|
|
||||||
local cx, cy, cw, ch
|
|
||||||
local f, bf
|
|
||||||
|
|
||||||
local sel = 1
|
|
||||||
local cdir
|
|
||||||
|
|
||||||
function resize()
|
|
||||||
cw = W / 1.25
|
|
||||||
ch = H / 1.25
|
|
||||||
cx = (W - cw) / 2
|
|
||||||
cy = (H - ch) / 2
|
|
||||||
|
|
||||||
local th = math.min(W, H) / 8
|
|
||||||
|
|
||||||
f = love.graphics.newFont(th / 3)
|
|
||||||
bf = love.graphics.newFont(th / 2)
|
|
||||||
|
|
||||||
ll.kbInit('h', cx, cx + cw)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function update()
|
|
||||||
local sdi = ll.kbGet()
|
|
||||||
|
|
||||||
if cdir ~= sdi then
|
|
||||||
cdir = sdi
|
|
||||||
if sdi == '<'
|
|
||||||
then sel = sel - 1
|
|
||||||
elseif sdi == '>'
|
|
||||||
then sel = sel + 1
|
|
||||||
elseif sdi == 'o' and ll.games[sel]
|
|
||||||
then ll.mount(ll.games[sel])
|
|
||||||
|
|
||||||
elseif sdi == 'm'
|
|
||||||
and love.mouse.getX() >= W - 8
|
|
||||||
then ll.devtools()
|
|
||||||
end
|
|
||||||
|
|
||||||
if sel < 1 then sel = #ll.games end
|
|
||||||
if sel > #ll.games then sel = 1 end
|
|
||||||
end
|
|
||||||
|
|
||||||
pikchv = pikchv + 1
|
|
||||||
if pikchv >= ll.cfg.pcht then
|
|
||||||
pikchv = 0
|
|
||||||
pikcha = 0
|
|
||||||
for _, v in pairs(ll.games) do
|
|
||||||
if v.dat.scr then
|
|
||||||
v.scrprv = v.scrcur
|
|
||||||
v.scrcur = v.scrcur + 1
|
|
||||||
if v.scrcur > #v.dat.scr
|
|
||||||
then v.scrcur = 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else pikcha = math.min(255, pikcha + pikchao)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local tm = 0
|
|
||||||
local function draw()
|
|
||||||
love.graphics.setColor(0 / COLDIV, 50 / COLDIV, 75 / COLDIV)
|
|
||||||
love.graphics.rectangle('fill', 0, 0, W, H)
|
|
||||||
love.graphics.setColor(255, 255, 255, 100 / COLDIV)
|
|
||||||
love.graphics.setLineWidth(8)
|
|
||||||
love.graphics.setFont(bf)
|
|
||||||
local t = 'Love Loader'
|
|
||||||
local tw, th = bf:getWidth(t), bf:getHeight(t)
|
|
||||||
love.graphics.print(t, W - tw - 8, H - th)
|
|
||||||
|
|
||||||
tm = (tm + 0.02) % 6.28
|
|
||||||
local c, pc, ps = tm, math.cos(tm), math.sin(tm)
|
|
||||||
local oy = H / 2
|
|
||||||
for x = 0, W + 8, 8 do
|
|
||||||
c = c + 0.1
|
|
||||||
local c, s = math.cos(c), math.sin(c)
|
|
||||||
local cy, ncy, sy, nsy =
|
|
||||||
pc * H / 12,
|
|
||||||
c * H / 12,
|
|
||||||
ps * H / 12,
|
|
||||||
s * H / 12
|
|
||||||
|
|
||||||
love.graphics.line(x - 8, sy + oy, x-1, nsy + oy)
|
|
||||||
love.graphics.line(x - 8, sy/2 + oy, x-1, nsy/2 + oy)
|
|
||||||
love.graphics.line(x - 8, cy/1.5 + oy, x-1, ncy/1.5 + oy)
|
|
||||||
love.graphics.line(x - 8, cy*1.5 + oy, x-1, ncy*1.5 + oy)
|
|
||||||
pc, ps = c, s
|
|
||||||
end
|
|
||||||
love.graphics.setColor(255, 255, 255, 255)
|
|
||||||
love.graphics.setLineWidth(1)
|
|
||||||
|
|
||||||
local oy, t = 0, ''
|
|
||||||
local gme = ll.games[sel]
|
|
||||||
if gme then
|
|
||||||
love.graphics.polygon('fill',
|
|
||||||
8, H / 2,
|
|
||||||
32, H / 2 - 32,
|
|
||||||
32, H / 2 + 32)
|
|
||||||
|
|
||||||
love.graphics.polygon('fill',
|
|
||||||
W - 8, H / 2,
|
|
||||||
W - 32, H / 2 - 32,
|
|
||||||
W - 32, H / 2 + 32)
|
|
||||||
|
|
||||||
love.graphics.stencil(function()
|
|
||||||
love.graphics.rectangle('fill', cx, cy, cw, ch, 16)
|
|
||||||
end)
|
|
||||||
love.graphics.setStencilTest('greater', 0)
|
|
||||||
love.graphics.setColor(50 / COLDIV, 50 / COLDIV, 50 / COLDIV, 100 / COLDIV)
|
|
||||||
love.graphics.rectangle('fill', cx, cy, cw, ch)
|
|
||||||
love.graphics.setColor(255, 255, 255, 255)
|
|
||||||
|
|
||||||
if gme.dat.scr then
|
|
||||||
local p, n = gme.dat.scr[gme.scrprv], gme.dat.scr[gme.scrcur]
|
|
||||||
love.graphics.draw(p, cx, cy, 0, cw / p:getWidth(), ch / p:getHeight())
|
|
||||||
love.graphics.setColor(255, 255, 255, pikcha / COLDIV)
|
|
||||||
love.graphics.draw(n, cx, cy, 0, cw / n:getWidth(), ch / n:getHeight())
|
|
||||||
love.graphics.setColor(0, 0, 0, 150 / COLDIV)
|
|
||||||
love.graphics.rectangle('fill', cx, cy, cw, ch)
|
|
||||||
love.graphics.setColor(255, 255, 255, 255)
|
|
||||||
end
|
|
||||||
|
|
||||||
oy = cy + ch / 1.25
|
|
||||||
love.graphics.setFont(bf)
|
|
||||||
love.graphics.print(gme.name, cx + 16, oy)
|
|
||||||
oy = oy + bf:getHeight(gme.name)
|
|
||||||
love.graphics.setFont(f)
|
|
||||||
love.graphics.print(gme.desc, cx + 16, oy)
|
|
||||||
love.graphics.setStencilTest()
|
|
||||||
love.graphics.rectangle('line', cx, cy, cw, ch, 16)
|
|
||||||
|
|
||||||
elseif ll.games[1] then
|
|
||||||
sel = 1
|
|
||||||
love.graphics.setColor(255, 255, 255, 255)
|
|
||||||
love.graphics.print('Sorry :)', W / 2, H / 2)
|
|
||||||
else love.graphics.setColor(255, 255, 255, 255)
|
|
||||||
oy = H / 2.5
|
|
||||||
t = 'No games'
|
|
||||||
love.graphics.setFont(bf)
|
|
||||||
love.graphics.print(t, (W - bf:getWidth(t)) / 2, oy)
|
|
||||||
oy = oy + bf:getHeight(t)
|
|
||||||
love.graphics.setFont(f)
|
|
||||||
t = 'There are no projects/games to run'
|
|
||||||
love.graphics.print(t, (W - f:getWidth(t)) / 2, oy)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function error(msg)
|
|
||||||
msg = tostring(msg)
|
|
||||||
|
|
||||||
love.graphics.reset()
|
|
||||||
love.graphics.origin()
|
|
||||||
local bf = love.graphics.newFont(64)
|
|
||||||
local f = love.graphics.setNewFont(16)
|
|
||||||
local perc = 0
|
|
||||||
|
|
||||||
local q
|
|
||||||
repeat
|
|
||||||
perc = math.min(100, perc + 0.1 * math.random(50))
|
|
||||||
|
|
||||||
love.graphics.clear(17/COLDIV, 113/COLDIV, 172/COLDIV)
|
|
||||||
love.graphics.setColor(255, 255, 255)
|
|
||||||
love.graphics.setFont(bf)
|
|
||||||
love.graphics.print(':(', 64, 16)
|
|
||||||
love.graphics.setFont(f)
|
|
||||||
love.graphics.print(('%d%% complete'):format(perc), 64, 100)
|
|
||||||
love.graphics.printf(msg, 64, 132, W - 64)
|
|
||||||
love.graphics.print('(c) Love Loader and Er2', 8, H - 16 - 8)
|
|
||||||
love.graphics.present()
|
|
||||||
|
|
||||||
love.event.pump()
|
|
||||||
for n, a,b,c in love.event.poll() do
|
|
||||||
if n == 'quit'
|
|
||||||
or n == 'mousereleased'
|
|
||||||
or (n == 'keypressed' and a == 'escape')
|
|
||||||
then q = true end
|
|
||||||
end
|
|
||||||
|
|
||||||
love.timer.sleep(0.5)
|
|
||||||
until q or perc == 100
|
|
||||||
|
|
||||||
-- Unfortunately, we can't restart Love in error handler
|
|
||||||
llHome() -- but can outside of love.errorhandler
|
|
||||||
return function() return 1 end
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
update = update,
|
|
||||||
draw = draw,
|
|
||||||
}
|
|
||||||
|
|
||||||
end
|
|
159
skins/psp.lua
159
skins/psp.lua
|
@ -1,159 +0,0 @@
|
||||||
return function(ll)
|
|
||||||
|
|
||||||
-- New UI from Sony PSP
|
|
||||||
|
|
||||||
local sel = 1
|
|
||||||
local psel
|
|
||||||
|
|
||||||
local cx, cy, cw, ch, cg
|
|
||||||
local css, rcss = 2, 0
|
|
||||||
|
|
||||||
local f, bf
|
|
||||||
|
|
||||||
ll.cfg.pcht = ll.cfg.pcht or 60 * 5
|
|
||||||
|
|
||||||
local pikchv, pikcha = 0, 0
|
|
||||||
local pikchao = math.floor(1 / ll.cfg.pcht * 2 * 255 + 0.5)
|
|
||||||
|
|
||||||
local logger = ''
|
|
||||||
local chc = '<>><m><'
|
|
||||||
|
|
||||||
function resize()
|
|
||||||
r = math.min(W, H) / 30
|
|
||||||
|
|
||||||
cg = H / 64
|
|
||||||
cw = W / 5
|
|
||||||
ch = (H - cg) / 6
|
|
||||||
cx = W / 10
|
|
||||||
cy = -H / 2
|
|
||||||
|
|
||||||
f = love.graphics.setNewFont(math.min(W, H) / 30)
|
|
||||||
bf = love.graphics.newFont(math.min(W, H) / 20)
|
|
||||||
|
|
||||||
ll.kbInit('v', H / 2 - ch, H / 2 + ch + cg, cx + cw * 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
love.window.setMode(800, 600, {resizable = true})
|
|
||||||
|
|
||||||
local sdir
|
|
||||||
local function update()
|
|
||||||
local ty = H / 2 - (ch + cg) * sel
|
|
||||||
cy = cy + (ty - cy) * 0.1
|
|
||||||
css = css + (2 - css) * 0.2
|
|
||||||
rcss = 2 - css + 1
|
|
||||||
|
|
||||||
local sdi = ll.kbGet()
|
|
||||||
|
|
||||||
if sdi ~= sdir then
|
|
||||||
if sdi
|
|
||||||
then rcss = css
|
|
||||||
css = 1
|
|
||||||
psel = sel
|
|
||||||
logger = logger .. sdi
|
|
||||||
if logger == chc then
|
|
||||||
resize()
|
|
||||||
ll.devtools()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
sdir = sdi
|
|
||||||
if sdi == '<'
|
|
||||||
then sel = sel - 1
|
|
||||||
elseif sdi == '>'
|
|
||||||
then sel = sel + 1
|
|
||||||
elseif sdi == 'o' and ll.games[sel]
|
|
||||||
then ll.mount(ll.games[sel])
|
|
||||||
end
|
|
||||||
|
|
||||||
if sel < 1 then sel = #ll.games end
|
|
||||||
if sel > #ll.games then sel = 1 end
|
|
||||||
end
|
|
||||||
|
|
||||||
pikchv = pikchv + 1
|
|
||||||
if pikchv >= ll.cfg.pcht then
|
|
||||||
pikchv = 0
|
|
||||||
pikcha = 0
|
|
||||||
for _, v in pairs(ll.games) do
|
|
||||||
if v.dat.scr then
|
|
||||||
v.scrprv = v.scrcur
|
|
||||||
v.scrcur = v.scrcur + 1
|
|
||||||
if v.scrcur > #v.dat.scr
|
|
||||||
then v.scrcur = 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else pikcha = math.min(255, pikcha + pikchao)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function scrCard(gme, x, y, w, h, a)
|
|
||||||
if not gme.dat.scr then return end
|
|
||||||
love.graphics.setColor(255, 255, 255, a / COLDIV)
|
|
||||||
local p, n = gme.dat.scr[gme.scrprv], gme.dat.scr[gme.scrcur]
|
|
||||||
love.graphics.draw(p, x, y, 0, w / p:getWidth(), h / p:getHeight())
|
|
||||||
love.graphics.setColor(255, 255, 255, math.min(a, pikcha) / COLDIV)
|
|
||||||
love.graphics.draw(n, x, y, 0, w / n:getWidth(), h / n:getHeight())
|
|
||||||
love.graphics.setColor(0, 0, 0, 150 / COLDIV)
|
|
||||||
love.graphics.rectangle('fill', x, y, w, h)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function draw()
|
|
||||||
love.graphics.setColor(0 / COLDIV, 50 / COLDIV, 75 / COLDIV)
|
|
||||||
love.graphics.rectangle('fill', 0, 0, W, H)
|
|
||||||
if ll.games[sel] then
|
|
||||||
local cur = ll.games[sel]
|
|
||||||
scrCard(cur, 0, 0, W, H, (css - 1) * 255)
|
|
||||||
love.graphics.setColor(255, 255, 255, 255)
|
|
||||||
love.graphics.setFont(bf)
|
|
||||||
love.graphics.printf(cur.desc, cx + cw * 2, cx, W - (cx + cw * 2))
|
|
||||||
else love.graphics.setColor(255, 255, 255, 255)
|
|
||||||
sel = #ll.games
|
|
||||||
end
|
|
||||||
love.graphics.setFont(f)
|
|
||||||
local oy = 0
|
|
||||||
for k, v in pairs(ll.games) do
|
|
||||||
local x, w, h, g = cx, cw, ch, cg
|
|
||||||
if k == sel then
|
|
||||||
x = cx / css
|
|
||||||
w = cw * css
|
|
||||||
h = ch * css
|
|
||||||
g = cg * 3
|
|
||||||
oy = oy + cg * css
|
|
||||||
elseif k == psel then
|
|
||||||
x = cx / rcss
|
|
||||||
w = cw * rcss
|
|
||||||
h = ch * rcss
|
|
||||||
oy = oy + cg * rcss
|
|
||||||
end
|
|
||||||
|
|
||||||
love.graphics.stencil(function()
|
|
||||||
love.graphics.rectangle('fill', x, cy + oy, w, h, r)
|
|
||||||
end)
|
|
||||||
love.graphics.setStencilTest('greater', 0)
|
|
||||||
|
|
||||||
love.graphics.setColor(50 / COLDIV, 50 / COLDIV, 50 / COLDIV, 100 / COLDIV)
|
|
||||||
love.graphics.rectangle('fill', x, cy + oy, w, h)
|
|
||||||
love.graphics.setColor(255, 255, 255, 255)
|
|
||||||
|
|
||||||
scrCard(v, x, cy + oy, w, h, 255)
|
|
||||||
love.graphics.setColor(255, 255, 255, 255)
|
|
||||||
|
|
||||||
local th = f:getHeight(v.name)
|
|
||||||
love.graphics.print(v.name, x + cg, cy + oy + h - th - cg)
|
|
||||||
|
|
||||||
love.graphics.setStencilTest()
|
|
||||||
love.graphics.rectangle('line', x, cy + oy, w, h, r)
|
|
||||||
oy = oy + h + g
|
|
||||||
end
|
|
||||||
if #ll.games == 0 then
|
|
||||||
love.graphics.print('No games', cx, cy - ch)
|
|
||||||
love.graphics.setFont(bf)
|
|
||||||
love.graphics.print('Add some to the library', cx, cy)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
update = update,
|
|
||||||
draw = draw,
|
|
||||||
}
|
|
||||||
|
|
||||||
end
|
|
Loading…
Reference in a new issue