Skip to content

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 PixelSprite2D
var summer := load("res://art/summer.jcpalette") as PixelPalette
var winter := load("res://art/winter.jcpalette") as PixelPalette
player.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 TileSet brings 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 "" or 0 stays behind.
  • An .aseprite or .ase brings 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 with the wheel open on the selected swatchThe rack's Palette section with the wheel open on the selected swatch

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.