651193674c
tools/aseprite/maps/ holds the source of truth: char-grid pixel maps + shared palette for five _ph placeholder sprites (M03 32px per MOE.md design law cues — round silhouette, mismatched eyes, bolted hardpoint, pillar feet; grunt 16px untagged olive; burster 20px HEAT glow band; KINETIC slug; scrap diamond). Two interchangeable renderers: gen_sprites.lua (aseprite -b, emits .aseprite + .png — run on any machine with Aseprite) and preview.py (Pillow, identical PNGs headless + nearest-neighbor zoom for review). Outputs gitignored; greybox scenes untouched — art stays out of the game per the greybox rule.
74 lines
2.3 KiB
Lua
74 lines
2.3 KiB
Lua
-- Headless Aseprite sprite generator for U R M03 placeholder sprites.
|
|
--
|
|
-- Run from the repo root:
|
|
-- aseprite -b --script tools/aseprite/gen_sprites.lua
|
|
-- Optional params:
|
|
-- aseprite -b --script-param out=assets/sprites_ph \
|
|
-- --script-param maps=tools/aseprite/maps \
|
|
-- --script tools/aseprite/gen_sprites.lua
|
|
--
|
|
-- Source of truth is the text pixel maps in tools/aseprite/maps/
|
|
-- (shared with tools/aseprite/preview.py, which renders identical
|
|
-- PNGs without Aseprite). Outputs .aseprite + .png per map.
|
|
-- All output is _ph placeholder-grade per the asset policy.
|
|
|
|
local params = app.params or {}
|
|
local MAPS_DIR = params["maps"] or "tools/aseprite/maps"
|
|
local OUT_DIR = params["out"] or "assets/sprites_ph"
|
|
|
|
local SPRITES = { "m03_ph", "grunt_ph", "burster_ph", "slug_ph", "scrap_ph" }
|
|
|
|
local function parse_palette(path)
|
|
local pal = {}
|
|
for line in io.lines(path) do
|
|
local ch, hex = line:match("^(%S)%s+(%x%x%x%x%x%x)%s*$")
|
|
if ch and ch ~= "#" then
|
|
local v = tonumber(hex, 16)
|
|
pal[ch] = {
|
|
r = math.floor(v / 65536) % 256,
|
|
g = math.floor(v / 256) % 256,
|
|
b = v % 256,
|
|
}
|
|
end
|
|
end
|
|
return pal
|
|
end
|
|
|
|
local function parse_map(path)
|
|
local rows = {}
|
|
for line in io.lines(path) do
|
|
if #line > 0 then
|
|
rows[#rows + 1] = line
|
|
assert(#line == #rows[1],
|
|
path .. ": row " .. #rows .. " width " .. #line .. " != " .. #rows[1])
|
|
end
|
|
end
|
|
return rows
|
|
end
|
|
|
|
if app.fs and app.fs.makeAllDirectories then
|
|
app.fs.makeAllDirectories(OUT_DIR)
|
|
end
|
|
|
|
local pal = parse_palette(MAPS_DIR .. "/palette.txt")
|
|
|
|
for _, name in ipairs(SPRITES) do
|
|
local rows = parse_map(MAPS_DIR .. "/" .. name .. ".txt")
|
|
local w, h = #rows[1], #rows
|
|
local spr = Sprite(w, h, ColorMode.RGB)
|
|
local img = spr.cels[1].image
|
|
for y, row in ipairs(rows) do
|
|
for x = 1, w do
|
|
local ch = row:sub(x, x)
|
|
if ch ~= "." then
|
|
local c = assert(pal[ch], name .. ": unknown palette char '" .. ch .. "'")
|
|
img:putPixel(x - 1, y - 1, app.pixelColor.rgba(c.r, c.g, c.b, 255))
|
|
end
|
|
end
|
|
end
|
|
spr:saveAs(OUT_DIR .. "/" .. name .. ".aseprite")
|
|
spr:saveCopyAs(OUT_DIR .. "/" .. name .. ".png")
|
|
spr:close()
|
|
print("wrote " .. OUT_DIR .. "/" .. name .. ".aseprite (+.png) " .. w .. "x" .. h)
|
|
end
|