Animation brings your pixel art to life by displaying a sequence of frames over time. Aseprite provides powerful tools for creating frame-by-frame animations with precise timing control.
-- Create a spritelocal sprite = Sprite(32, 32)local layer = sprite.layers[1]-- Add more framesfor i = 1, 7 do sprite:newFrame()endprint(#sprite.frames) -- 8 frames-- Set timing (10 FPS = 0.1 seconds per frame)sprite:setDurationForAllFrames(0.1)-- Now draw different content in each framefor i, frame in ipairs(sprite.frames) do local cel = layer:cel(frame.frameNumber) if cel then -- Draw on cel.image for each frame endend
Control the playback speed by adjusting frame durations:
local sprite = Sprite(32, 32)-- Create 8-frame animationfor i = 1, 7 do sprite:newFrame()end-- Fast animation (20 FPS)sprite:setDurationForAllFrames(0.05) -- 50ms per frame-- Slow animation (5 FPS) sprite:setDurationForAllFrames(0.2) -- 200ms per frame-- Custom timing per framesprite.frames[1].duration = 0.5 -- Hold first frame longersprite.frames[5].duration = 0.15 -- Slow down middle frame
local sprite = Sprite(32, 32)-- Get all tagslocal tags = sprite.tagsprint(#tags) -- Number of tags-- Iterate tagsfor i, tag in ipairs(sprite.tags) do print(tag.name, tag.fromFrame, tag.toFrame)end-- Find tag by namefunction findTag(sprite, name) for i, tag in ipairs(sprite.tags) do if tag.name == name then return tag end end return nilendlocal walkTag = findTag(sprite, "walk")
local sprite = Sprite(32, 32)for i = 1, 8 do sprite:newFrame()endlocal tag = sprite:newTag(1, 4)print(#sprite.tags) -- 1sprite:deleteTag(tag)print(#sprite.tags) -- 0
local sprite = Sprite(32, 32)local layer = sprite.layers[1]-- Create 8 framesfor i = 1, 7 do sprite:newFrame()end-- Draw on each framefor frameNum = 1, 8 do app.activeFrame = sprite.frames[frameNum] local cel = layer:cel(frameNum) if cel then local img = cel.image -- Draw different content on each frame -- img:drawPixel(x, y, color) endend
While Aseprite provides onion skinning in the UI, you can simulate it programmatically:
-- Access previous and next frames while drawinglocal currentFrame = app.activeFrameif currentFrame.previous then local prevCel = layer:cel(currentFrame.previous.frameNumber) -- Use prevCel as referenceend
local sprite = Sprite(32, 32)local layer = sprite.layers[1]-- Create framesfor i = 1, 8 do sprite:newFrame()end-- Link cels for static partslocal baseCel = layer:cel(1)for i = 2, 8 do -- Create linked cel (shares same image) sprite:newCel(layer, i, baseCel.image)end-- Now frame 1-8 all show the same image-- Editing one affects all
Animate different parts independently using layers:
local sprite = Sprite(32, 32)-- Create layers for different partslocal bodyLayer = sprite.layers[1]bodyLayer.name = "Body"local eyesLayer = sprite:newLayer()eyesLayer.name = "Eyes"-- Create framesfor i = 1, 8 do sprite:newFrame()end-- Body can have a 4-frame cycle-- Eyes can have a 2-frame blink-- They animate independently
function getTagDuration(tag) local sprite = tag.sprite local duration = 0 for i = tag.fromFrame.frameNumber, tag.toFrame.frameNumber do duration = duration + sprite.frames[i].duration end return durationendlocal walkTag = sprite:newTag(1, 8)sprite:setFrameRangeDuration(1, 8, 0.1)print("Walk duration:", getTagDuration(walkTag), "seconds") -- 0.8s
-- Save as animated GIFsprite:saveAs("animation.gif")-- Save as sprite sheetapp.command.ExportSpriteSheet{ ui = false, type = SpriteSheetType.HORIZONTAL, textureFilename = "spritesheet.png", dataFilename = "spritesheet.json"}