feat(sandbox): add creeper themes

This commit is contained in:
Guillaume ARM 2026-06-11 05:00:27 +02:00
parent fd0a2fd110
commit 835f6f012d
3 changed files with 164 additions and 37 deletions

View File

@ -6,7 +6,7 @@
"trapos-net": "0.3.0", "trapos-net": "0.3.0",
"trapos-ui": "0.2.2", "trapos-ui": "0.2.2",
"trapos-ai": "0.6.4", "trapos-ai": "0.6.4",
"trapos-sandbox": "0.1.3", "trapos-sandbox": "0.1.4",
"trapos": "0.8.6" "trapos": "0.8.6"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "trapos-sandbox", "name": "trapos-sandbox",
"version": "0.1.3", "version": "0.1.4",
"description": "TrapOS sandbox programs for ccpm experiments and Lua learning", "description": "TrapOS sandbox programs for ccpm experiments and Lua learning",
"dependencies": ["trapos-core"], "dependencies": ["trapos-core"],
"files": [ "files": [

View File

@ -3,30 +3,97 @@ local createVersion = require('/apis/libversion');
local args = table.pack(...); local args = table.pack(...);
local FACE = { local FACE = {
'0000000000000000', 'LlGgLlGg',
'0000000000000000', 'lGGllGGL',
'0011110000111100', 'GXXggXXG',
'0011110000111100', 'gXXGGXXg',
'0011110000111100', 'LGGXXGGl',
'0011110000111100', 'gGXXXXGg',
'0000001111000000', 'LGXggXGL',
'0000001111000000', 'gGGLLGGg',
'0000111111110000',
'0000111111110000',
'0000111111110000',
'0000111111110000',
'0000110000110000',
'0000110000110000',
'0000110000110000',
'0000000000000000',
}; };
local THEMES = {
vanilla = {
title = 'Creeper',
background = colors.black,
text = colors.white,
palette = {
G = colors.green,
g = colors.lime,
L = colors.lightGray,
l = colors.gray,
X = colors.black,
},
},
charged = {
title = 'Charged Creeper',
background = colors.black,
text = colors.white,
palette = {
G = colors.blue,
g = colors.cyan,
L = colors.lightBlue,
l = colors.white,
X = colors.black,
},
},
magma = {
title = 'Magma Creeper',
background = colors.black,
text = colors.orange,
palette = {
G = colors.red,
g = colors.orange,
L = colors.yellow,
l = colors.brown,
X = colors.black,
},
},
ocean = {
title = 'Ocean Creeper',
background = colors.black,
text = colors.lightBlue,
palette = {
G = colors.blue,
g = colors.lightBlue,
L = colors.cyan,
l = colors.blue,
X = colors.black,
},
},
sand = {
title = 'Sand Creeper',
background = colors.black,
text = colors.yellow,
palette = {
G = colors.yellow,
g = colors.orange,
L = colors.white,
l = colors.lightGray,
X = colors.brown,
},
},
};
local THEME_NAMES = { 'vanilla', 'charged', 'magma', 'ocean', 'sand' };
local function printUsage() local function printUsage()
print('creeper usage:'); print('creeper usage:');
print(); print();
print(' creeper'); print(' creeper');
print(' creeper <theme>');
print(' creeper --theme <theme>');
print(' creeper --random');
print(' creeper --version'); print(' creeper --version');
print(' creeper --help'); print(' creeper --help');
print();
print('themes: vanilla, charged, magma, ocean, sand');
print();
print('examples:');
print(' creeper charged');
print(' creeper --theme sand');
print(' creeper --random');
end end
local function drawRun(x, y, len, color) local function drawRun(x, y, len, color)
@ -35,21 +102,76 @@ local function drawRun(x, y, len, color)
term.write(string.rep(' ', len)); term.write(string.rep(' ', len));
end end
local function drawCreeper() local function themeNamesText()
local width, height = term.getSize(); return table.concat(THEME_NAMES, ', ');
local pixelW = math.max(1, math.floor(width / 20)); end
local pixelH = math.max(1, math.floor(height / 18));
if pixelW > 3 then pixelW = 3; end local function parseArgs(argv)
if pixelH > 2 then pixelH = 2; end local selectedTheme = 'vanilla';
local selectedExplicitly = false;
local randomTheme = false;
local index = 1;
while index <= argv.n do
local arg = argv[index];
if arg == '--random' or arg == '-random' then
if selectedExplicitly then
return nil, '--random cannot be combined with a theme';
end
randomTheme = true;
elseif arg == '--theme' or arg == '-theme' then
if randomTheme or selectedExplicitly then
return nil, arg .. ' cannot be combined with another theme option';
end
index = index + 1;
selectedTheme = argv[index];
if selectedTheme == nil then
return nil, 'missing theme after ' .. arg;
end
selectedExplicitly = true;
elseif THEMES[arg] ~= nil then
if randomTheme or selectedExplicitly then
return nil, arg .. ' cannot be combined with another theme option';
end
selectedTheme = arg;
selectedExplicitly = true;
else
return nil, 'unknown option or theme: ' .. tostring(arg);
end
index = index + 1;
end
if randomTheme then
math.randomseed(os.epoch('utc'));
selectedTheme = THEME_NAMES[math.random(1, #THEME_NAMES)];
end
if THEMES[selectedTheme] == nil then
return nil, 'unknown theme: ' .. tostring(selectedTheme)
.. ' (available: ' .. themeNamesText() .. ')';
end
return THEMES[selectedTheme];
end
local function drawCreeper(theme)
local width, height = term.getSize();
local pixelW = math.max(1, math.floor(width / 12));
local pixelH = math.max(1, math.floor(height / 12));
if pixelW < 2 and width >= #FACE[1] * 2 then pixelW = 2; end
if pixelW > 4 then pixelW = 4; end
if pixelH > 3 then pixelH = 3; end
local artW = #FACE[1] * pixelW; local artW = #FACE[1] * pixelW;
local artH = #FACE * pixelH; local artH = #FACE * pixelH;
local startX = math.max(1, math.floor((width - artW) / 2) + 1); local startX = math.max(1, math.floor((width - artW) / 2) + 1);
local startY = math.max(1, math.floor((height - artH) / 2) + 1); local startY = math.max(1, math.floor((height - artH) / 2) + 1);
term.setBackgroundColor(colors.green); term.setBackgroundColor(theme.background);
term.setTextColor(colors.white); term.setTextColor(theme.text);
term.clear(); term.clear();
for row = 1, #FACE do for row = 1, #FACE do
@ -57,26 +179,29 @@ local function drawCreeper()
local y = startY + ((row - 1) * pixelH) + sy; local y = startY + ((row - 1) * pixelH) + sy;
local col = 1; local col = 1;
while col <= #FACE[row] do while col <= #FACE[row] do
local bit = FACE[row]:sub(col, col); local token = FACE[row]:sub(col, col);
local run = 1; local run = 1;
while col + run <= #FACE[row] while col + run <= #FACE[row]
and FACE[row]:sub(col + run, col + run) == bit do and FACE[row]:sub(col + run, col + run) == token do
run = run + 1; run = run + 1;
end end
local color = colors.green; local color = theme.palette[token] or theme.palette.G;
if bit == '1' then
color = colors.black;
end
drawRun(startX + ((col - 1) * pixelW), y, run * pixelW, color); drawRun(startX + ((col - 1) * pixelW), y, run * pixelW, color);
col = col + run; col = col + run;
end end
end end
end end
term.setBackgroundColor(colors.green); term.setBackgroundColor(theme.background);
term.setTextColor(colors.white); term.setTextColor(theme.text);
if height >= startY + artH then
term.setCursorPos(math.max(1, math.floor((width - #theme.title) / 2) + 1), startY + artH + 1);
term.write(theme.title);
end
term.setCursorPos(1, height); term.setCursorPos(1, height);
end end
@ -92,9 +217,11 @@ if command == '-version' or command == '--version' or command == 'version' then
return; return;
end end
if command ~= nil then local theme, err = parseArgs(args);
printUsage(); if not theme then
print(err);
print('utilise: creeper -help');
return; return;
end end
drawCreeper(); drawCreeper(theme);