Some approaches to automating Aseprite workflows, featuring lua and some babashka usage.
I cover parts of this repo via Youtube devlogs:
- Automating Aseprite tag creation: https://youtu.be/yKHnLkeyGzc
These examples:
- are things I implemented when working on my own games
- have been ripped out and simplified
- are not intended to be consumable/reusable
My goal is to share approaches to scripting Aseprite things.
I hope these make it easier for you to create your own scripts and tools!
The add_some_tags.lua script is intended to be invoked from within Aseprite itself - see ‘Invoking a script from aseprite’ below to help Aseprite find your scripts.
The use-case for this script was a need to create a large number of animations in several sprites. I got tired of creating tags by hand, when I already had a list of them in text format.
This script lets you define a big list of tags:
local tags = {
-- Shared tags
"idle", "_jump", "_dead", "run", "air", "_knocked_back", "_dying",
"_landed", "walk", "_jump", "_jump_kick",
"_punch", "_punch_2", "_kick", "_punched", "_kicked",
"_grab", "_grabbed", "_throw", "thrown", "_hit_ground", "_get_up",
}
It runs through each tag, and any tag that doesn’t already exist on the sprite is created.
Beware that there are some gotchas - if anything crazy happens, you can ‘undo’
the command (this is the benefit for running the code within
app.transaction("your-command", fn)
).
There is the beginning of a color wheel idea to help distinguish all the new tags from each other. Perhaps this will be extended to support some more useful per-tag colors at some point.
Given a directory with files:
hello_world.lua
my_art.aseprite
Where hello_world.lua
is:
-- hello_world.lua
app.transaction(
"main", function()
print("hello world!")
for k, t in pairs(app.params) do
print("argument key:", k, "value:", t)
end
end)
You can invoke the script with the Aseprite cli:
aseprite -b \
my_art.aseprite \
--script-param whatevs=foo \
--script-param bananas=bar \
--script hello_world.lua
-b
means ‘batch’ mode, which prevents the Aseprite UI from starting up
GOTCHA: be sure to pass
--script-param
ahead of--script
!
And you should see:
hello world!
argument key: whatevs value: foo
argument key: bananas value: bar
The resize_canvas.lua script can be passed to aseprite like:
aseprite -b \
assets/boxart/base_logo.aseprite \
--script-param filename=assets/boxart/header_capsule.aseprite \
--script-param width=460 \
--script-param height=215 \
--script scripts/resize_canvas.lua
That might be all you want, but if you’re interested in managing a number of these, bb/tasks.clj contains a spec for all the Steam ‘Coming Soon’ page required images, which looks something like:
{:header-capsule {:width 460 :height 215}
:small-capsule {:width 231 :height 87}
:main-capsule {:width 616 :height 353}
:vertical-capsule {:width 374 :height 448}
:page-background {:width 1438 :height 810}
:library-capsule {:width 600 :height 900}
:library-header {:width 460 :height 215}
:library-hero {:width 3840 :height 1240}
:library-logo {:width 1280 :height 720}
:client-icon {:width 16 :height 16 :skip-generate true :export-ext ".jpg"}
:community-icon {:width 184 :height 184}}
And they can all be generated and exported like:
bb regen-boxart
This depends on a few ‘base’ aseprite files existing:
assets/boxart/base_logo.aseprite
assets/boxart/base_logo_wide.aseprite
assets/boxart/base_logo_no_bg.aseprite
assets/boxart/base_bg_no_logo.aseprite
The `_wide` version of the logo image was introduced to prevent the logo from cropping poorly - note that the resize_canvas script is not very sophisticated - it does a resize, a recenter, then a crop, which will certainly not work for every base_logo.
The script could get smarter, and toggle the logo or background at generate-time via another passed option - but this was where I landed when shipping Dot Hop’s first Coming Soon images.
A file-watcher and re-export strategy is available via babashka, and implemented
in bb/tasks.clj - see watch
and export-pixels-sheet
for details.
If you’d like more on this, let me know and I’ll elaborate more here + add coverage to the video.
Aseprite looks for script files in ~~/.config/aseprite/scripts/*~. (You can open
this dir via: File > Scripts > Open Scripts Folder
)
You could add a script there manually, but I like to symlink a per-project
scripts
directory in there:
ln -s ~/russmatney/<project-name>/scripts ~/.config/aseprite/scripts/<project-name>
You’ll likely need to File > Scripts > Rescan Scripts Folder
at least once,
but you shouldn’t need to do that in-between scripts.
Then you can start writing a script in your project, and invoke it from Aseprite
via File > Scripts > <project-name> > <script-name>
.
- API docs: https://www.aseprite.org/api/app#app
- CLI docs: https://aseprite.org/docs/cli/
- Aseprite Extensions by Kacper Wozniak: https://thkaspar.itch.io/
- Big list of aseprite scripts: https://community.aseprite.org/t/aseprite-scripts-collection/3599/71
- Godot Aseprite Wizard: https://github.com/viniciusgerevini/godot-aseprite-wizard