Pixel
The sprite, tileset and font editors, and the palette tab.
model/ Document, layer, palette, tag, selection, the tileset and font documents, the stores, edit commands, autosave and playback. No editor dependencies.paint/ Raster, flood fill, selection edits, onion skin, recent colours.format/ Aseprite in and out, .gpl, spritesheet slicing, tileset and font imports, export.runtime/ PixelSprite2D, PixelSpriteTexture, PixelSpriteFrames, PixelTileSet, PixelTileMapLayer, PixelFontFile. What a game opens. An export carries runtime/, model/, paint/, format/, palettes/ and icons/, and leaves the editors behind.panel/ The Pixel tab itself.tiles/ The Tiles tab: the sheet, the tile lane, the rack and the scratch map.font/ The Font tab: the glyph sheet, the glyph lane, the rack and the preview strip.palette/ The Palette tab: the style's palettes, a row each.strip/ The shell strip: the document chip and the menus.bar/ The tool strip and the context bar.stage/ The canvas.lane/ The timeline.rack/ Palette and Tags.host/ What the plugin loads: the inspector button, the FileSystem menu, the document previews and the Aseprite importer.icons/ The PixelSprite2D node icon.palettes/ default.jcpalette, the palette new documents open on until the project names its own.tests/ Headless suite and editor layout checks. Not shipped.Tools
| Tool | Key | Notes |
|---|---|---|
| Pencil | B | Square or round brush, 1 to 32 pixels, no antialiasing. Pixel-perfect at size 1 when switched on; Shift+click draws a line from where the last stroke ended |
| Eraser | E | Writes transparency, same brush, same pixel-perfect and Shift+click |
| Fill | G | Four connected, with tolerance and a whole-layer scope |
| Pick | I | Samples the flattened image; Scope on the context bar switches it to the layer in hand |
| Marquee | M | A rectangle. Drag inside to move, Delete to erase, Esc to drop |
| Lasso | Q | Drag a loop; what it encloses is selected |
| Wand | W | Click a colour; the patch of it under the pointer is selected, at the fill’s tolerance. Scope on the context bar takes every pixel of that colour on the layer instead |
| Line | L | Drawn with the brush. Shift snaps to flat, upright or diagonal |
| Rectangle | R | Outline or filled. Shift draws a square |
| Ellipse | O | Outline or filled. Shift draws a circle |
The left button paints the colour in hand and the right erases, with the pencil, the fill, the line and the shapes. The eraser and the marquee work the same on either button, and the picker picks only with the left. Alt+click samples a colour with any tool. On a touchscreen a finger held still on the canvas does nothing.
The rectangle and the ellipse share one button, and so do the three selection tools: the face shows the tool in hand, a right-click lists the others, and each key reaches its tool directly. The line has its own.
A selection is any shape, and the three tools build one between them: Shift held when a drag or a click starts adds to what is selected, Ctrl (Command on a Mac) takes away, and neither replaces it. Every edit works on the shape: move by dragging inside it with the marquee, Delete, cut, copy, paste, flip and quarter turn, and painting with any tool stays inside it until Esc drops it, whichever tool made it. Moving lifts the pixels and leaves transparency behind, content dragged past an edge is cropped, and each drag is one undo step. All layers on the context bar, shown with any selection tool, moves the selection on every layer of the frame at once; one Ctrl+Z puts them all back, and the outline with them. Paste lands at the top left of the current selection, or where the block was lifted from, and lands over what’s there, its transparent pixels leaving what’s under them. Flip mirrors the selection in place, so a rectangle’s marquee stays still; a quarter turn moves it with the pixels, and undo moves it back.
Pixel-perfect, the check item under Square and Round in the brush shape menu on the context bar, drops the corner pixel of every L a stroke makes, so a curve stays one pixel wide. It’s off by default, so the pencil paints every pixel the pointer crosses. It applies to the pencil and the eraser at size 1 only. Shift+click’s line runs from the last pixel of the previous stroke on the same layer and frame, as one undo step; with no stroke before it there it is one stamp. Shift+drag is a plain stroke.
The brush size is a count of pixels, not a radius, and an even size extends right and down from the cursor. The round brush is a plus at 3 and does nothing at 1 or 2. Outlines are stamped with the brush; filled shapes ignore it. A shape is drawn from the pixel the drag started on to the one it is over, and a filled ellipse of a given size is the same pixels as a round brush of that size.
Dither, the button on the context bar with the pencil, the line, the shapes and the fill, paints through a pattern: only the pattern’s pixels are painted, and the rest keep what’s under them. Its menu holds Off, the Bayer 2×2, 4×4 and 8×8 patterns with a density, how many of the pattern’s 4, 16 or 64 pixels paint, and tiles you draw. To make a tile, draw a small patch, up to 16 by 16, select it and press +: every drawn pixel in it is on, on the layer in hand. A sprite keeps its tiles when it saves; the Tiles editor’s button has the Bayer patterns alone. The pattern is laid from the top left of the canvas, so strokes and fills line up wherever they start. The eraser takes no pattern; the right button erasing with the pencil, the line, the shapes or the fill does.
Fill tolerance is how far each channel may differ from the clicked pixel, out of 255; on flat palette art, leave it at 0. Scope picks the region under the cursor or every matching pixel on the layer. A fill covers the current layer and frame only.
Where it lives
The document’s name is the chip on the shell strip. Click it for the File
menu. An unsaved document reads Untitled, and unsaved changes show a seed
in the warning colour on the chip. The .jcsprite suffix is left off;
the full path is in the tooltip.
Save As, under Save in the File menu, always asks where. The chip then shows the new file’s name, and the first file stays as it was, along with any sprite or scene using it. Undo carries on. The new document starts with no export paths, so its Save can’t write over the first one’s PNG. A document built into a scene gets a file of its own this way, and the scene uses that file once you save it. Save As works the same in the Tiles and Font editors.
New, Open and the inspector button ask before replacing unsaved work. Closing the dock only hides the panel. Quitting the editor names the document in Godot’s save-before-quit dialog, and Save All writes it. A document never saved anywhere is named but left alone.
Unsaved work is also written to a recovery file under
user://jamchip/autosave/ every thirty seconds, or as often as the
Saving page of Preferences says. If the editor is killed, the next
start lists every tab with work waiting, a row per tab by name and time.
Recover puts it back as unsaved work on its document, or as Untitled
when that file is gone; Discard removes the file; Later leaves the rest
for next time, and autosave waits until it has been answered. Saving, or
discarding a document by choice, removes the file. Nothing under
res:// is touched.
The editor is an EditorDock. It opens in the bottom slot, can sit in any
slot or float, and the choice is remembered per user. The panel picks its
arrangement from its own width. Wide is a column of tools, the canvas, then
palette and tags beside it. Narrow is a row of tools above the canvas
with the panels stacked under it. Crossing between the two refits the
canvas; ordinary resizing leaves your zoom alone. The rack sections and
the frames lane fold by their titles. The grip between Palette and Tags
sizes the palette, and the frames lane has one on its seam with the
canvas: drag down or up for more room, double-click to put it back. Folds and heights are kept
per project.
Controls
| Action | Input |
|---|---|
| Draw | Left drag with the colour in hand; right drag erases |
| Pan | Two-finger scroll, middle drag, or Space + drag |
| Zoom | Pinch, Cmd/Ctrl + two-finger scroll, or mouse wheel |
| Zoom by steps | Ctrl+- / Ctrl+=, or Zoom in / Zoom out in the View menu |
| Jump to a zoom level | The Zoom submenu of the View menu |
| Fit to view | Ctrl+0, the Fit button after the zoom steps, or Fit to view in the View menu |
| Undo / redo | Ctrl+Z / Ctrl+Shift+Z (also Ctrl+Y) |
| Save | Ctrl+S, or the File menu |
| Save As | Ctrl+Shift+S, or the File menu |
| Copy / cut / paste | Ctrl+C / Ctrl+X / Ctrl+V, or the Edit menu |
| Select all / deselect | Ctrl+A / Esc, or the Edit menu |
| Read the shortcuts | F1, or Keyboard shortcuts in the Help menu |
| Grid | Toggle on the context bar, or Ctrl+’; off until asked for. The grid is a cell, any width by any height, and an offset, both saved with the document and set in Grid settings in the View menu, right under Grid. The same dialog holds snap and the grid’s colour, which are yours and aren’t saved with the document |
| Onion skin | Toggle on the frames lane beside Play, or Ctrl+;, or Onion skin in the Frames menu; right-click the toggle for range and strength, which are under Frames too |
| Checkerboard | Toggle on the context bar after the symmetry toggle, or Checkerboard in the View menu |
| Symmetry | The toggle on the context bar beside the grid, which brings back the mode last picked, or Symmetry in the View menu: Off, Horizontal, Vertical or Both. Each axis is a line on the canvas with a grip at each end; drag it to move it. Centre the axes in the same submenu puts both back in the middle, and in Axes you type where each one goes, in pixels from the left and the top, where a half runs through the middle of a pixel |
| Constant rate | Toggle on the frames lane beside the onion, or Constant rate in the Frames menu; the rate is under Rate |
| Preview the animation | Play in the frames lane under the canvas, or Space |
| Step through the frames | Comma for the previous frame, full stop for the next; past the last it starts again at the first |
| Resize the canvas | Resize canvas in the document’s menu |
The shortcut dialog, the menus and the tooltips all read one table. Help, last on the strip, holds the shortcut list and this README; About JamChip, with the version installed, is on the project page’s ≡.
Getting a document into a scene
RUNTIME.md at the addon’s root has both modules’ runtime classes, and
its “Which pixel node” table says which of the three to use;
EXAMPLE-GAME.md has the example game node by node. This is the Pixel half.
PixelSprite2D is the front door. Add one from Create New Node and drag
the .jcsprite from the FileSystem dock onto its Document. It draws
crisp by default; its Texture ▸ Filter changes that. It is an
AnimatedSprite2D underneath even for a still, so a second frame added
later just plays. The scene keeps Document, Palette, Preview In
Editor and the animation it is on; the frames are rebuilt from the document. With autoplay empty, it
plays when the game starts: the node calls play() itself. A tag named in
autoplay plays instead.
An exported PNG dragged onto the 2D canvas is a plain Sprite2D of the
PNG as last exported.
autoplay means nothing in the editor, so there are two ways to see the
animation there. PixelSprite2D runs its own clock, which
preview_in_editor turns off. Any AnimatedSprite2D plays from the
SpriteFrames panel, which opens on a selected PixelSprite2D though
its frames have no row in the inspector. The frames are the document’s, so
an edit made in that panel is put back at once, with a warning in Output.
For everything a sprite is not, PixelSpriteTexture is a Texture2D
that is one frame of a document, kept in step with it, and
PixelSpriteFrames the SpriteFrames counterpart: put either anywhere
its type goes and set its Document.
PixelDocument, the .jcsprite all three read, needs no page at
jamchip.com/api: a game only hands it to one
of them, or recolours it for good with recolor, below. Everything else on
it is for the Pixel tab.
Live means the node and the panel hold the same document. Unsaved edits are visible to everything showing it, and closing the dock without saving does not put the artwork back. The game ships the document itself, layers and all. Draw against these and export when the artwork is finished.
Changing a sprite’s palette while the game runs
For one node, set its palette, in the inspector or from code:
enemy.palette = load("res://art/slime_red.jcpalette"). The document’s
own swatch list is the palette it was drawn in, and each of its swatches
is drawn as the node palette’s swatch at the same place; a colour not in
the list is left alone. The document is not touched, so two enemies on one
document wear two palettes. null goes back to the document’s colours,
and palette_changed fires once it has landed. PixelSpriteTexture and
PixelSpriteFrames take a palette the same way.
For every node at once, and for good, recolour the document itself. Give
recolor the palette the artwork was drawn in and the palette to draw it in
now, then ask the node to build itself again:
var player := $Player/Sprite as PixelSprite2Dvar summer := load("res://art/summer.jcpalette") as PixelPalettevar winter := load("res://art/winter.jcpalette") as PixelPaletteplayer.document.recolor(summer, winter)player.rebuild()Swatch by swatch: a pixel the colour of summer’s third swatch becomes
winter’s third. A colour in neither palette is left where it is, and a
shorter second palette leaves the tail of the first alone. Cels are RGBA,
not indexed, so the palette the artwork was drawn in is handed in. The
document’s own swatch list is not touched; set document.palette = winter.colors as well when it should carry the new colours, and then, if
it’s linked to a palette file of the same length, the Pixel tab puts it
back in that file’s colours the next time it opens it.
The document is the loaded resource, so every node holding that
.jcsprite is recoloured with it. It passes over every cel, so it’s a
call for when the colours change, not for every frame.
PixelSprite2D, PixelSpriteTexture and PixelSpriteFrames each have
rebuild(). All three follow a document on their own, coalesced to the
next idle frame, so rebuild() is for a change made behind that, and for
seeing it in the frame it was made in.
A save reaches the running game. Run the game from the editor, draw
in the Pixel tab, Ctrl+S: every PixelSprite2D, PixelSpriteTexture and
PixelSpriteFrames holding that file redraws in place, on the animation
and frame it was on, with no restart. A .jcsprite that changes on disk
some other way, a git pull or a tool writing into the project, reaches
the game the same way once the editor has noticed the file. It rides the
debugger connection the editor already has to the game, so an exported
build carries the listener and nothing arrives. To turn it off, the
project setting jamchip/push_to_game, Push To Game under Jamchip.
What a sprite says to the game
document_changed fires when a rebuild lands, whatever caused it: an
edit, a save reaching the running game, a palette, a layer shown or
hidden; PixelSpriteTexture and PixelSpriteFrames have it too.
tag_finished(tag) fires when a tag ends, once a loop for one that loops.
frame_event(name) fires when the animation shows a frame with a marker
on it, each time it passes. play_then("attack", "idle") plays one tag and
then the next with no handler, and a looping tag with a next plays once.
queue(tag) lines tags up; stop() empties the queue, pause() keeps it.
set_layer_visible("helmet", false) hides a layer on one node and not
another, and can show one the document hides; the document’s eye is not
changed. clear_layer_overrides() goes back to the document’s.
Playback is AnimatedSprite2D’s own: speed_scale, flip_h, flip_v,
play_backwards, pause, stop, frame, frame_progress.
From a scene back to the artwork
Sprite2D, AnimatedSprite2D and TextureRect get an Edit in
JamChip inspector button when there is something of this editor’s to
open: a live resource, or a texture with a .jcsprite beside it. For an
AnimatedSprite2D that is the spritesheet its frames cut. It opens the
document, layers and frames and all. Artwork from elsewhere opens from
the FileSystem dock’s right-click menu.
Ways in from the rest of the editor
Double-click a .jcsprite in the FileSystem dock, where it shows its
first frame. Right-click any PNG, Aseprite file or document there for Open in
JamChip, the only way in from the dock for a PNG or an Aseprite file.
Ctrl+Shift+P has JamChip: Pixel, which brings the tab forward from
anywhere in the editor; the keyed actions themselves are on F1.
Exporting
File > Export asks for the format, its options, then the path, and
opens on the format you picked last; a typed path over a file asks first.
In a browser the path is a name to download as, and Pixel document sends
the saved file. PNG writes the current frame, and Save rewrites it
from that frame. Animation writes a spritesheet, wrapped into rows,
beside a SpriteFrames of AtlasTexture regions with exact timings; set
the .tres as an AnimatedSprite2D’s Sprite Frames and play one of its
animations; it runs at the timings you drew.
The document remembers its export paths and Save writes them again, so a sprite on an exported PNG follows Ctrl+S; a deleted target is left alone. Exporting marks the document unsaved, since the path is part of it. An exported sheet is reimported, so a texture already on a node updates.
Open also accepts a PNG, as one layer on one frame, read straight from
the file.
Drawing a font
The Font pin, or Ctrl+5 with every editor shown, opens the font editor. A font is one glyph per
character, every glyph the same cell, saved as .font.tres. A new font
holds every printable ASCII character, space to ~, in an 8×8 cell;
New asks for another cell.
The stage shows the glyph in hand between five named lines: the baseline
the letters stand on, the x-height (how tall an x is), the cap height
(how tall an H is), and the cell’s top and bottom. The Guides toggle on
the bar, or View > Guides, hides them. Draw and select with the Pixel
tab’s tools and their keys; a copy from one glyph pastes onto another.
Under the glyph, two spacing lines, HHnHH and nnnnn, show it in
place of the middle letter so you can judge its spacing and weight. The
Preview strip along the bottom of the stage shows a line of text in the
font, at a zoom of its own. Both change as you draw.
Under the stage, Glyphs groups every glyph the way a font is drawn:
H O n o first, then capitals, lowercase, digits and punctuation, each
with a count of the glyphs drawn; below them, optional groups for symbols,
Latin-1 letters and your own. An empty glyph’s box is dashed. Click one, or use the arrow keys,
to put it in hand. + adds a group, − on its header removes it. The rack
names the glyph in hand, its Advance (how far along the next letter
starts) and Characters, the whole set as text; type the strip’s line in
Preview text.
File > Cell Size and Guides crops or pads every glyph from its top
left corner and moves the baseline, the x-height and the cap height. A font
saved before the cap height existed gets one worked out from its cell.
Every edit is one step on Edit > Undo.
A font switches palettes the way a sprite does, with the strips under the
swatches. On one of your style’s palettes, the font’s palette in the
inspector is that palette’s file, shown but not editable there, and the
glyphs follow when it changes.
On Custom, the font keeps a palette of its own inside its file.
File > Import makes a new font from a PNG sheet or a TTF or OTF file.
A sheet is cut at the cell size, left to right and top to bottom, a cell
for each character in Glyphs. A TTF or OTF is drawn at Size, in pixels,
which follows the cell’s height until you change it. A pixel face lands on whole pixels only at
its own size or a multiple of it, so when you draw it at another size the
Output panel says which size it is.
A character the file lacks comes in empty.
Drawing a tileset
The Tiles pin, or Ctrl+6 with every editor shown, opens the tileset editor. A tileset is one
sheet at a tile size, saved as .tiles.tres. New asks for the tile
size and how many tiles across and down. A sheet can be a .jcsprite of
its own, and Save writes it too. A tileset saved as another file keeps that
same sheet file, so what you draw then shows in both tilesets.
Draw on the sheet with any of the Pixel tab’s tools; the selections work on
the sheet only. A cell you draw, paste or drag a selection into becomes a
tile in the lane under the stage, and the one you drew last is in hand.
New Tile under the lane’s + adds the cell you last clicked, pixels or
not; − removes the tile in hand and leaves its pixels. Point at − to
see what it takes.
The rack edits the tile in hand: its name, Solid for a solid tile, Points
to shape its collision, custom data under Data’s + (3 is a number, a
word is text), and for a loose tile a terrain the sheet has, and neighbours.
Edit copies it to a new tile, as it is, flipped or rotated, in the first
blank cell outside the terrains, with its name, terrain, collision, data and
neighbours. Wrap-shift tile moves its edges to the middle so a seam is
easy to draw out; run it again to put them back. Each blank cell round the tile in
hand shows, dimmed, the edge that would meet it.
Beside the sheet is a map, the scratch. Paint it with the tile in hand to
see how it repeats: the pencil places, the eraser clears, the fill floods,
the picker picks a placed tile up. Fix a seam on the sheet and the map
follows. In a narrow dock the two are tabs, Sheet and Scratch, over the
stage. The tile grid’s size and offset are under View.
While the map is in view, Place | Paint at the head of the bar, or P,
switches what the tools do on it. On Paint they draw on the map and the
tiles under it change: a line across a seam draws into both tiles, and every
copy follows. The fill stays inside the tile you click, and a stroke over an
empty cell draws nothing. One Ctrl+Z takes the stroke back.
New Terrain under the lane’s + lays out a terrain on the sheet, as
16 corners (four by four) or 47 blob (twelve by four, the layout of
Godot 3’s “3x3 minimal” autotile template). Every slot is a tile already
set to the neighbours it matches, so all that’s left is drawing it. The sheet
outlines each terrain with its name and how many slots are drawn; click a
dashed slot to make it a tile again. Click a terrain’s name and − to
remove it: its tiles stay, loose.
To use a tileset in a game, see “A tileset in the game” below.
Exporting a TileSet
The grid is the tile. Set the cell to the tile size in Grid settings in the
View menu, or in the rows under TileSet in File > Export, and the
offset if the sheet has a margin. Export is greyed on the pixel grid.
Snap, in the same dialog, makes the selection tools work by the tile:
the marquee grows a whole cell at a time, a moved selection lands a whole
number of cells over, and a paste lands on the nearest cell corner. It is
greyed on the pixel grid and is a mode of the view, not of the document.
File > Export with TileSet writes the current frame as a PNG and a
.tileset.tres beside it: one TileSetAtlasSource over the PNG, cut at
the cell from the offset, with a tile for every cell that has a pixel in
it and none for a blank cell. Drop the .tres on a TileMapLayer and
paint with it. Save rewrites both files from the frame they came from, the
way it rewrites a PNG.
This export carries no collision or data; a tileset’s export from the Tiles tab does, under “A tileset in the game”. Collision, navigation and custom data are added in Godot’s TileSet editor, on the tiles the export declared, and survive a re-export: a tile still drawn keeps everything on it, a cell newly drawn gets a tile, and a cell erased loses its tile. Exporting over a set that is there asks first, and says whether it can keep the tiles or has to replace the file whole, which it does when the set’s first source is not an atlas.
A tileset in the game
Add a PixelTileMapLayer to the scene and drag a .tiles.tres onto its
Document. Paint the level with Godot’s own tile editor, as on any
TileMapLayer. Each tile brings its art, its collision on physics layer 0,
its custom data by key, and its terrain. Draw on the sheet, declare a tile
or give one a polygon, and the level changes with it, in the editor and in
a running game when you save.
For a TileMapLayer you already have, make a PixelTileSet in its
Tile Set slot and give that the document. It’s the same set the node
makes.
The layers’ own settings are yours: a collision layer and mask on physics layer 0, a terrain’s colour. They’re kept in the scene and every change to the tileset writes into them. The tiles themselves aren’t saved in the scene, since the tileset holds them, so edit tiles in the Tiles tab. A tile you add in Godot’s TileSet editor stays only until the scene is opened again, and a change there to a tile the tileset declares is gone the next time it saves. The Output panel says so the first time it happens.
To hand a game a plain TileSet instead, one a project without JamChip
reads, use File > Export with TileSet in the Tiles tab: a PNG and a
.tileset.tres with every tile’s collision, data and terrain. Exporting
again asks first; a tile added in Godot’s TileSet editor keeps what’s on it.
A sprite drawn as a tile sheet can follow its document too: make a
PixelSpriteTexture over it and set it as the atlas source’s Texture
in Godot’s TileSet editor. The polygons and data on the tiles stay where
they are; only the pixels under them change. The atlas cuts the texture at
its own Texture Region Size and Margins, so a sheet regridded after
the swap is set right on the atlas. Tiles past the edge of a sheet that
shrank stay in the set, marked as outside the texture, until Godot’s
TileSet editor clears them.
Bringing a tileset in
File > Import in the Tiles tab opens a PNG, a TileSet or an
Aseprite file as a new, unsaved tileset; pick which at the top of the
dialog. Every cell with a pixel in it
becomes a tile.
- A PNG has rows for the tile size, the offset and the spacing between tiles, and refuses a tile size that leaves pixels over.
- A
TileSetbrings its first atlas, and on each tile its first collision polygon, its custom data and its terrain. What a tileset can’t hold, like a second source or a tile two cells wide, is named in the Output panel. A custom data value left at""or0stays behind. - An
.asepriteor.asebrings its first tileset, without the empty tile 0. Its layers are skipped, since where tiles are placed stays in Aseprite.
Importing a spritesheet
File > Import with Spritesheet replaces the open document, asking
first if that loses work.
When the SpriteFrames that the Animation export wrote is beside the PNG,
the frames, the tags’ names and ranges, and the timings come back exactly.
You can pick the .tres itself if the PNG was renamed. Five things do not
survive: frames no tag covered, which want slicing as a grid instead; the
order the tags were made in, which comes back alphabetical; a lone tag
called default, which is read as untagged; a tag’s direction, repeat
count and colour, which the sheet bakes into its frames; and layers, since
a sheet is flat.
A PNG with nothing beside it is cut by the rows: cell size, margin from the top left, and spacing between cells. Frames come out left to right, top to bottom, as one untagged animation at the default hold. The readout under the fields says what the numbers come to. Import is unavailable while a cell size does not divide the sheet, with the leftover named, or while a cell is too large for a canvas, or there are more than 512 frames, or the cel memory budget is passed.
Empty cells at the end are dropped and counted. An empty cell with artwork after it is kept as a blank beat. A wholly empty sheet is refused.
An import does not adopt the sheet as an export target, so your first Ctrl+S cannot overwrite it. Export the animation once and the document remembers.
Importing an Aseprite file
File > Import with Aseprite opens .aseprite or .ase,
replacing the open document and asking first.
Layers come across with name, visibility, lock and opacity, frames with their durations, cels with position and links, the palette, and all three colour depths. Frame tags become animation tags with their direction, repeat count and colour: repeat-forever loops, repeat-N plays N times, and a black tag colour reads as none, so the row picks one.
Some things are reported in the Output panel and then approximated: blend modes other than Normal come in as Normal; groups are dropped and their layers come in flat with the group’s visibility and opacity folded in; per-cel opacity is baked into the pixels; an embedded ICC profile is noted and the pixels read as sRGB. Slices and external files are noted and read past, and pixels outside the canvas are clipped.
A file is refused with the reason when it has tilemap layers or cels (the Tiles tab’s Import takes its tileset, “Bringing a tileset in”), when it passes the document ceilings of 512 frames, 64 layers or the cel memory budget, or when it is not an Aseprite file or has been cut short.
An import does not adopt the .aseprite as an export target. Export once
to make it this document’s own.
An Aseprite file in the FileSystem dock
Godot imports any .aseprite or .ase in the project as a sprite
document, read the way File > Import reads it. Set it as a
PixelSprite2D’s Document and it draws, tags and all, and an export
ships it. Save it again in Aseprite and the editor imports it again when
it gets focus back, and the sprite draws the new file, in a running game
too when Push To Game is on. A file the import refuses says why in
the Output panel. Open in JamChip opens it untitled, as File > Import
does: Save writes a new document, never the Aseprite file. With another
Aseprite importer in the project, pick JamChip sprite for the file in
the Import dock.
The Import dock has two rows for it. Fallback Palette is the palette a file with none of its own uses, the default when it’s empty. Match Style Palette moves every colour outside the project’s style to the nearest one in its main palette, as Match the palette does in the tab. Choosing another style or changing its palette doesn’t import the file again, so press Reimport.
Exporting an Aseprite file
File > Export with Aseprite writes the open document as
.aseprite or .ase. Always 32 bits per pixel. Layers go bottom to top,
all Normal, a locked layer locked, with one compressed cel per painted
layer per frame and a blank cel written as no cel. Frame durations are in
milliseconds. Tags are inclusive at both ends with their direction and
colour, loop as repeat-forever and otherwise as their repeat count, so
direction and repeat survive both ways. The palette goes in both the
modern and the 2015 chunk.
A round trip cannot keep sub-millisecond timing, layer opacity beyond one 255th, a tag naming frames that are gone, or the editor’s own state such as export paths and the current frame. Save rewrites this export too.
The writer is checked against the format’s documentation and the reader beside it, and against Aseprite itself where it’s installed: it opens what the export writes and saves it out as PNGs without a complaint.
Palette

The rack’s Palette section holds the colour you’re painting with, the sprite’s swatches, and your recent colours. The row at the top shows the colour you’re painting with, its hex and the wheel.
- Pick: click a swatch. Hover to see its hex. The eyedropper selects the swatch with the colour it picks. If no swatch has it, none is selected.
- Add or remove:
+after the last swatch adds the colour you’re painting with;−beside it removes the selected swatch. On one of the style’s palettes, which all keep one length, switch to Custom first. - Edit: select a swatch, then drag on the wheel or type a hex and press Enter. With no swatch selected, the wheel and the hex change only the colour you’re painting with. In a narrow dock, Colour modes at the wheel’s foot shows RGB, HSV and the other modes.
- Reorder: drag a swatch to another place.
Every edit is one undo step. The ≡ menu saves, imports and exports palettes, sorts the swatches by hue or brightness, and clears the recent colours.
The style’s palettes
With a style chosen on the Project pin, the jar at the top of the pin rail, a new sprite opens on the style’s first palette, at its size and grid. Without one, it opens on the project’s default palette. Tilesets and fonts work the same way.
Each of the presets, JamChip, Four Shades and Ink, gives a style one palette; jamchip.com/project shows their colours. No Limits gives none and holds you to no colour.
Under the swatches is a strip for each of the style’s palettes, with Custom last. Click a strip’s dot to switch palettes: the drawing changes to its colours, swatch for swatch, as one undo step. Hold a strip to see the drawing in it; letting go changes nothing. A style with more than three palettes shows the first three and the one in use. N more, above Custom, shows the rest.
Editing a swatch edits the palette the sprite uses, and the drawing follows. A reorder moves no pixel, and no swatch may take a colour another already has. On Custom, an edit changes only the swatch. When other sprites, tilesets or fonts use the palette, the first edit asks: Edit for all changes them too when you save, and Make it Custom keeps the change to this sprite. Another tab open on a sprite that uses the palette changes with it, and its undo history is cleared; its strip says so. A sprite whose palette changed while it was closed opens in the new colours. If the palette now has a different number of colours, the sprite opens on Custom with a note.
Custom colours are the sprite’s own. Custom’s menu loads a palette file, recolouring the drawing the same way. It can also add the colours to the style as a new palette, or save them over one of the style’s palettes.
A sprite with colours outside the style gets a bar over the canvas when it opens, and whenever a stroke, an undo or a palette you wear leaves it outside; the bar goes once it’s back inside. Match the palette shows the current frame before and after, each colour outside the style moved to its nearest in the style’s main palette. Apply recolours the sprite and puts it on the main palette, as one undo step; if that palette has no file of its own, the sprite is on Custom, in the main palette’s colours. Cancel changes nothing.
Saving
Save palette as writes a .jcpalette: the palette’s name and its
colours as plain data, which any engine or script can read. Godot imports
it, and your exported game ships the import. An older .palette.tres still
opens; saving over one keeps its .palette.json beside it.
Saving over one of the style’s palettes asks first if anything uses it or the order changed. A style’s palettes are all the same length.
To open new sprites on a palette file, choose a style on the Project pin, then use Load palette on its card. The file becomes the style’s main palette.
Import and export
Import palette reads a .gpl or .hex, the formats Lospec uses, and
replaces the swatches. Unreadable lines are skipped.
Export palette writes a .gpl, a .hex, or a PNG with one square per
colour, 1 to 64 px. .gpl and .hex drop transparency; the PNG keeps it.
On the web, the file goes to your downloads.
The palette tab
The Palette pin, or Ctrl+2 with every editor shown, shows a palette
next to the others in its style. Double-click a palette in the
FileSystem dock, or use File > Open. Each of the style’s palettes is a
row, main first, and each slot is a column, so you can compare the same
slot across palettes. Each row says whether it’s the main palette or a
swap, and how many sprites, tilesets and fonts use it. A palette that
isn’t in the style opens as a single row.
Click a swatch to select its slot. The rack beside the rows, or under them in a narrow dock, edits it: type a hex in the Slot section and press Enter, or open the wheel. Sprites, tilesets and fonts that use the palette change with it as you edit.
The Ramp section fills the slots between two: select one end and press Start, select the other and press Ramp to here. The colours between are stepped evenly in lightness, colour and hue (OKLCH). Shift bends the hue of the colours in between, most at the middle, so the greens between can lean toward yellow or blue.
The Generate section tries new colours for the selected palette. Select a slot and press Lock to keep it, and press Lock again to unlock it; a locked slot is marked in the corner, in every palette, since a slot is a column. Regenerate gives each slot that isn’t locked a new hue at random, keeping how light it is, and as vivid as the new hue allows. Greys stay grey. Press it again for another try, or undo; the locks stay until the slots move or another palette opens.
The Harmony section builds a palette from colour theory. Click or drag on the wheel to pick a base colour: the hue changes around the wheel, and colours get more vivid toward the edge. Then pick a rule: Analogous, Monochromatic, Triad, Complementary, Split complementary, Square or Compound. The marks show the rule’s hues; Spread sets how far apart they sit for Analogous, Split complementary and Compound. Add as row makes a new palette with a ramp for each hue, dark to light, bent by the Ramp section’s Shift, then a dark and a light grey. With a style chosen, the new palette is as long as the style’s main palette, and any slots left over from an even split go to the base hue. With no style, No Limits, or a style with no palettes yet, it asks how many colours. Like New Palette, the new palette is saved as a file straight away, so Undo doesn’t remove it. If you’re editing the style’s palettes, you’ll be asked to save them first; if you’re editing a palette that isn’t in the style, you’re asked whether to discard those edits.
File > New Palette makes a palette of greys, black to white, as a new
row, asking how many colours. With a style chosen it joins the style, so
it has to be the same length as the style’s other palettes, and
File > New Palette from Main copies the style’s main palette.
To make a palette from a .gpl or .hex file, such as one downloaded
from Lospec, or from the colours painted in a sprite, press Import in the
Make a swap section. With a style chosen, the new palette joins the style
as a swap the length of the main palette: the closest matches are paired
first, each slot taking the nearest colour still free, and no colour is
used twice. A slot with no colour left over keeps the main palette’s. A
style with no palettes yet takes the file’s colours as its main palette.
With no style chosen, or No Limits, the file’s colours come in as they
are, as a palette of its own in the project’s root folder. A new palette
is saved as a file straight away, so Undo doesn’t remove it, and Import
asks you to save the palettes you’re editing first.
A slot is a column across every palette. In the Columns section, Add puts a new slot after the selected one; Remove, Move left and Move right act on the selected slot, in every palette at once. Drag a swatch along a row to move its slot the same way. Sort by hue and Sort by brightness sort the selected palette and put every palette’s slots in that order, so each swap still pairs slot for slot.
The Check section shows the selected palette again, as its lightness alone and as someone who’s green-blind, red-blind or blue-blind (deuteranopia, protanopia, tritanopia) sees it. In the colour views, a dot marks a slot that’s hard to tell from another; hover it to see which. The Lightness view shows no dots.
Each edit is one step for Edit > Undo (Ctrl+Z). File > Save (Ctrl+S)
saves every palette you edited. If sprites, tilesets or fonts use the
palette, or the change moves a colour that a swap palette pairs with, it
asks before saving the palette. Edits you haven’t saved are autosaved,
and offered back if the editor closes before you save them.
Layers
The layers are the rows under the frames lane’s thumbnails, topmost first,
each with its eye, its padlock and its name at the left and a dot per
frame after them. Click the eye to show or hide the layer, click the
padlock to lock it, click the name to select it, double-click the name to
rename it in place, and drag a row onto another to reorder the stack. The
+ in the corner above the rows adds a layer above the selected one; so
does Shift+N. Right-click a row for the rest: New layer above it,
Remove layer, Move up, Move down, Rename, Visible, Locked,
Opacity, a bar over the row that updates live and records one undo
step on release, and the reference layer’s two below. Painting targets the selected layer, export flattens the
visible ones, and a hidden layer’s row draws faint. Undo and redo of a
layer edit restore the selection too.
A locked layer keeps its pixels: the pencil, the eraser, the shapes, the
fill, a drag of the selection, Delete, cut, paste, flip and the quarter
turns all leave it alone, and the status line at the end of the strip
says Locked: and the layer’s name. The picker, copy and selecting still
work on it, and so do the layer commands. All layers skips a locked layer.
Locking isn’t an undo step, undo never unlocks a layer, and the lock is
saved with the document.
A reference layer holds a rough to draw over, a sketch, a doodle or a
photo of one, under every layer in its own colours. Right-click a row and
pick Add reference layer to choose a PNG, JPEG or WebP; it is fitted
inside the canvas, centred, and shown faint. No tool paints it, and no
export, sheet, .aseprite or node draws it, but it saves with the
document. Remove reference layer takes it away; each is one undo step.
Frames
The frames lane under the canvas is the timeline: a strip of thumbnails with Play, the onion toggle and the constant rate toggle above it, and the cel grid under it, a row per layer with a dot per frame. A filled dot is a cel with something drawn on it, a hollow dot an empty one, and the accent ring is the cel in hand; click a dot to select that layer and that frame together. Past four layers the rows scroll. The dashed square at the end adds an empty frame after the current one; Shift-click adds a copy. The Frames menu offers new, duplicate, remove and the two moves; a right-click on a frame offers all but new; drag one frame onto another to reorder. Delete removes a focused frame, never the last.
A marker is a name on a frame, step or land, that a PixelSprite2D
says as frame_event. Right-click a frame, Add marker, type it and
press Enter. A marked frame has a dot in its caption, and the same menu
removes each. Markers move with their frames.
Each frame holds for its own duration in milliseconds, read under its
thumbnail and set on the lane’s Hold bar: drag it, or double-click the
number to type one. Hold in the Frames menu, or a double-click on a
frame, opens that field with the keyboard in it. A frame off the default
hold shows its number in the ordinary text colour. Thumbnails follow a
stroke as it is drawn. The current frame has an accent border, and while
playing the frame shown has the playhead colour.
Onion skin ghosts the neighbouring frames, the previous warm and the next cool, as flat silhouettes. Range is how many frames either side, up to eight, each fainter than the last, and strength is how solid the nearest is. Controls has where to switch it and set both; on a touchscreen, press and hold the toggle.
Animation tags
A tag names an inclusive range of frames, and each becomes a
SpriteFrames animation of that name: idle over 1 to 4, run over 5 to
10, and play("run") in the game. An Aseprite file’s frame tags come in
as tags, with their direction, repeat count and colour.
Tags are the second section of the rack, under Palette: one row per tag
with a chip of its colour, its name, its range and, at the end of the row,
how it plays (⟳, once, 3x, ⟳ ping-pong, reverse once). Click a
row to select it and it opens into its fields: the name, from and to
counted from one as on the strip, the direction as four toggles (forward,
reverse, ping-pong, ping-pong reverse), Loops, how many times it plays
when it doesn’t loop, and the colour. Click the row again to let go. The
section’s + makes a new tag and opens its row, - removes the selected
tag. The strip draws a band under the selected tag’s frames in its colour.
A new tag claims the first contiguous run of untagged frames, which on an untagged document is all of them. Names are unique and ranges may overlap. A tag with no colour picked gets one from its place in the list; set the colour’s alpha to zero to go back to that.
Direction and repeat are expanded on export and in the live
SpriteFrames: a reverse tag’s animation holds its frames backwards, a
ping-pong’s goes out and back, and a tag that plays three times holds
three passes with loop off, so play("hop") does what the row says
without the game knowing.
When frames move, a frame inserted inside a tag extends it and one inserted before shifts it. One inserted directly after its last frame leaves the tag alone. A removed frame shrinks the tag, and a tag whose only frame goes is dropped. Dragging a frame across a tag’s edge is a removal then an insertion; dragging it within a tag leaves the span as it was.
An untagged document is one animation called default over every frame.
A node opens on the document’s first tag. Each tag is timed by its own
frames.
Playback
Play previews in the canvas at the holds you authored, or at a fixed rate
with Constant rate on; neither touches what you saved. With a tag
selected, Play runs only that tag the way it plays, reverse or ping-pong
included, and a tag that does not loop stops after its last pass. Drawing
stops the preview, and so does clicking a frame, a cel or a layer row, a
change to the frames, the layers or a marker, and adding or removing a tag.
Capacity and resizing
Cels are held decoded, so the limit is a memory budget shared by layers and frames that scales with cel size. A 16×16 sprite holds thousands of cels and a 256×256 one a couple of hundred. The add buttons grey out with a tooltip naming the limit.
Resize crops and pads with an anchor, or resamples with nearest
neighbour, across every layer and frame in one undo step. Undo restores
what a crop discarded. Past a budget of 262,144 pixels, 512×512 or
1024×256, New and Resize turn amber and say fills and frame changes may
lag, and still make the canvas; a PNG, an Aseprite file or a sheet opens
with a note on the strip. Only a canvas the cels would not fit is refused:
every cel shares one memory limit, so New refuses past 4096×4096 and Resize
sooner the more cels the document has, each naming the nearest size that
fits. A PNG too big for it doesn’t open, and says how many pixels it has
against the limit.
JamChip, by GlitterSnack. MIT licence. Built from the source on every merge. Its artwork and screenshots are made with JamChip.