A pixel art asset is a picture you paint pixel by pixel, in layers and frames, with the colours of a palette. Like vector art it is drawn rather than uploaded, and worn exactly like a texture: a sprite names it in its Texture row, a tile or an animation key can name one of its frames, a shader samples it. See Textures for the contract behind that.
Making one. + → Pixel art creates the asset and opens it in the Pixel art tab. It stands in the assets panel under Pixel drawings. The first pixel art of a project brings a palette along in the same undo step; later ones take the palette that is already there. Pixel art is not placed in a scene, it is worn by something that is.
The canvas
A new canvas is 32x32 pixels, at most 512x512. Resize… in the tab's header asks for the new width and height and for the anchor: nine buttons for the corners, the edges and the centre. The picture keeps its place at that anchor, and whatever sticks out on the far side is cut off. A resize is one undo step, for every layer on every frame at once.
The inspector shows three rows: Palette (which palette the picture is painted in), Filter, Nearest by default so the pixels stay sharp when a sprite scales them up, and Nine-slice scale (see below).
Nine-slice and sort line
A sprite wearing pixel art can be nine-sliced and given a sort line, exactly as a sprite wearing a texture frame (Textures). The settings sit on the asset, under Nine-slice and Sorting in its inspector, in canvas pixels. One set serves every frame: the frames share the canvas size, and the frames of one animation want the same corners and the same feet.
- The tab draws the borders that are set as dashed lines and the sort line in yellow. They are not dragged there, the painting tools own the canvas. Type the numbers in the inspector.
- With two frames or more, the asset itself names the strip of all frames side by side. That strip is not sliced, only a single frame is. With one frame the asset and its frame are the same picture.
- Resizing the canvas keeps the numbers, and they are held inside the new size when drawn.
Colours and the palette
Every pixel is an index into the palette. Index 0 is transparent. A palette is an asset of its own, so several pictures can share one, and changing a colour of the palette recolours every pixel painted with it, in every picture that uses that palette. Pointing a picture's Palette row at another palette with the same number of colours is a palette swap.
A new palette starts with the sixteen colours of PICO-8. The COLOURS block of the tab shows them as swatches across the whole width of the panel; the first swatch, a checkerboard, is transparent. A click picks the colour to paint with.
| Control | What it does |
|---|---|
| Colour field | Changes the picked colour of the palette, one undo step per change |
| Add | Adds a copy of the picked colour at the end and picks it (up to 255 colours) |
| Remove | Takes the picked colour out of the palette |
| Create palette | Only while the picture names no palette: makes one and names it |
Remove rewrites every picture painted with the palette, because pixels store their colour by index. The pixels of the removed colour turn transparent, the colours after it move down one index, and every other pixel keeps the colour it had. Palette and pictures change in one undo step. Transparent itself cannot be removed. A pixel whose index runs past the end of the palette is transparent.
Tools
The TOOLS block holds seven tools. A stroke, a fill or a shape is one undo step.
| Tool | What a press does |
|---|---|
| Pencil | Paints the picked colour; a drag paints a gapless line under the pointer |
| Eraser | The same, with transparent |
| Fill | Fills the area of the clicked colour, joined along edges (not corners). With Contiguous off, every pixel of that colour on the layer |
| Picker | Picks the colour under the pointer: the top visible layer that paints the pixel, else transparent |
| Line | A straight line from the press to the release |
| Rectangle | The border of the rectangle between press and release, or all of it with Filled shapes |
| Ellipse | The ellipse that fits that rectangle, as a one pixel outline or filled |
Alt+click picks a colour with any tool. Brush sets the pencil, the eraser and the outlines of line, rectangle and ellipse from 1 to 8 pixels; an even brush reaches one pixel further right and down than left and up.
Below the tools stand only the options of the tool in use: Brush with the pencil, the eraser, the line and an outlined rectangle or ellipse, Filled shapes with rectangle and ellipse, Contiguous with fill. The picker has none.
There are no keyboard shortcuts for the tools yet. Selecting, copying and mirroring are #198, more tools (symmetry, lasso, dithering, replacing a colour) are #200.
Layers
The LAYERS list shows the top layer first. Each row pictures its layer alone on the frame being painted. A click on a row picks the layer the tools paint on.
- Dragging a row moves the layer to another place in the drawing order.
- The eye in a row leaves the layer out of the picture, and puts it back. A hidden layer cannot be painted on.
- The number left of the eye is the layer's opacity in percent. Click it to type a value, or drag it sideways to scrub (Shift ten times faster, Alt ten times slower). The canvas follows while you drag, and the whole drag is one undo step.
- A double-click on a layer's name edits it right in the row. Enter or a click elsewhere keeps it, Esc goes back. A blank name is not taken.
- The + in the list's header puts a new empty layer above the picked one.
- The copy mark (two squares) and the ✕ show at the right end of the row under the pointer and of the picked row. The copy mark puts a copy of the layer right above it, with the same pixels on every frame, and paints on the copy. The ✕ takes that layer out. The last layer has no ✕, it stays.
- Merge down lays the layer onto the one below it, on every frame, and takes it out. Every pixel it paints covers the one below. Its opacity is not kept: an indexed picture has no colour between two palette entries, so the merged layer keeps the opacity of the lower one.
Frames
Every frame has the same layers. The FRAMES list shows them in order, first on top, each row with a picture of the whole frame; a click picks the frame the canvas shows and paints on.
- Dragging a row moves the frame to another place in the order.
- The + in the list's header puts an empty frame after the picked one. The copy mark on a row puts a copy of that frame right after it, the ✕ takes that frame out. Both show on the row under the pointer and on the picked one. The last frame has no ✕, it stays.
- Onion skin (in the VIEW block) shows the frames before and after the picked one faintly under it.
- PREVIEW plays the frames in a loop. Frames per second belongs to the preview only; how long a frame lasts in the game is up to the Animation that keys it.
How frames are worn. All frames of an asset are drawn side by side into one picture, and each frame is a cut of it, like a frame of a sliced texture. Once there is more than one frame, a Texture row offers the asset and each frame by name (Walk / Frame 2). Create sprite from picture in the assets panel's menu makes a sprite wearing the first frame, and Create animation from frames makes a sprite and an animation that keys every frame in order, one step each.
The view
The canvas zooms with the wheel in whole steps (1x, 2x, 3x, 4x, 6x, 8x, 12x, 16x, 24x, 32x), so every pixel is a square of the same size on screen. From 8x on a grid runs between the pixels. Shift+drag or the middle mouse button pans, Fit picks the largest step that fits. Tile preview in the VIEW block repeats the picture around the canvas, three by three, for tiles that have to join.
How the pixels are stored
The project file holds names, not pixels. The pixels of one layer on one frame, a cel, are a file
of their own on the server, data/pixels/<sha256>.px, named by the hash of its bytes like an
uploaded image. An empty cel is no file at all. A stroke names its cel at once, in the browser, and
the cels the server does not have yet are uploaded before the project that names them is saved.
Undo swaps names, so it never waits for the server. The format is in the API.
Known limits
Using the editor
- Concepts
- Accounts
- Agents (MCP)
- Scenes
- Scene editing
- Behaviors
- Structs
- Colliders
- Physics
- Textures
- Vector art
- Pixel art
- Fonts
- Videos
- Sounds
- Instruments
- Patterns
- Songs
- Animations
- Curves
- Tiles
- Tilemaps
- State machines
- Shaders
- Particles
- Containers
- Compositions
- Keyboard
Working on the code