Skip to content

Instantly share code, notes, and snippets.

@nftchance
Last active February 27, 2023 15:57
Show Gist options
  • Save nftchance/676f43ffb816883b4c89b9fd718f4b2a to your computer and use it in GitHub Desktop.
Save nftchance/676f43ffb816883b4c89b9fd718f4b2a to your computer and use it in GitHub Desktop.
Aesprite Procedural Generation Tilemap Builder
--[[
@title: Aesprite Procedural Generation Tilemap Builder
@author: nftchance
@note: This was written in mind off on-chain (blockchain) pixel art however this is not just limited to the utilization of blockchain needs. This is an incredibly efficient workflow for all "procedural generation" populations.
@license: MIT
@installation: to use this script you need to import this script into your Aesprite scripts folder.
This script is utilized within the pixel art tool, Aesprite (https://www.aseprite.org/). The tool is incredibly easy to use and what most on-chain artists should realistically be using due to the workflow that can be created. The quality of art and workflow are significantly improved. However, with character-heavy art it is vital that you can export each individual layer tilemap and the pieces that are contained within that. This scripts solves that problem.
1. To use this script all you have to do is create your individual layers as Tilemaps as you will need each piece for your generation system (whether it is on-chain or not)
2. Select the script
3. Select the tilemaps to export
4. Relax as the script handles all tiling and creation of your tile-ready assets
5. Straight to action no more time wasted messing with art massaging
@returns: segmented assets of pixel project
]]--
local spr = app.activeSprite
if not spr then return print "CHOOSE AN ACTIVE SPRITE MFER" end
local fs = app.fs
-- save all images into the asset folder
local output_folder = fs.filePath(spr.filename) .. "/assets"
local dlg = Dialog('EXPORT TILEMAP')
-- function that runs the actual processing of splitting and saving tiles
local function exportTileset(tileset, name, n, padding)
local grid = tileset.grid
local size = grid.tileSize
if #tileset > 0 then
-- bark the orders of the image we need
local spec = spr.spec
spec.width = size.width + (padding * 2)
spec.height = ((size.height + (padding * 2) - padding) * #tileset) + padding
-- if we are using pieces we need one the dimensions to be one tile
if dlg.data.pieces then
spec.height = size.height + (padding * 2)
end
-- create the actual image object
local image = Image(spec)
image:clear()
-- default filename is a collective tileset image
local imageFilename = fs.joinPath(
output_folder .. "/" ..name,
name .. ".png"
)
-- todo: is it an issue that we aren't increasing i ?
for i = 0, #tileset - 1 do
local tile = tileset:getTile(i)
-- if we are reusing the same object we need to clear it
local tilePadding = padding + ((i * size.height) + (i * padding))
if dlg.data.pieces then
image:clear()
tilePadding = padding
imageFilename = fs.joinPath(
output_folder .. "/" .. name,
i .. ".png"
)
end
-- actually draw the tile
image:drawImage(
tile, -- tile to draw
padding, -- horizontal padding
tilePadding -- vertical padding
)
-- save the piece if we are using pieces
if dlg.data.pieces then
image:saveAs(imageFilename)
end
end
-- save the collective image if we haven't yet (overwrites the last piece of pieces is enabled but that is fine)
image:saveAs(imageFilename)
-- open the image (or last image if pieces is enabled)
if dlg.data.openFiles then
app.open(imageFilename)
end
end
end
-- function that handles which tiles to generate based on the dialog
local function startExport()
local data = dlg.data
local n = 0
for _, layer in ipairs(spr.layers) do
if layer.isTilemap then
n = n + 1 -- note: i have no idea why we must pre-incremente here
if data["tileset" .. n] then
exportTileset(
layer.tileset,
layer.name,
n,
data.padding
)
end
end
end
dlg:close()
end
-- function that adds the tilemap options that can be chosen to the dialog
local function addTilemapOptions()
local n = 0
for _, layer in ipairs(spr.layers) do
if layer.isTilemap then
n = n + 1
dlg:check{ id = "tileset" .. n, text = layer.name, selected=true }
end
end
end
-- building the actual dialog (inline script)
dlg:check{ id = "pieces", text = "PIECES", selected=true }
dlg:check{ id = "openFiles", text = "OPEN FILES ON GEN.", selected=false }
dlg:number{ id = "padding", label = "PADDING: ", text = "16" }
addTilemapOptions()
dlg:button{ text = "&CANCEL", onclick=function() dlg:close() end }
dlg:button{ text = "&START", onclick=function() startExport() end }
dlg:show{ wait = false }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment