Sprite Forge guide
← Back to the app

Adding and swapping your own sprites

Sprite Forge draws its built-in art with code. This guide shows the two ways to put your own art in: the Workshop inside the app (no coding), and editing the part files (for bodies, outfits and anything else).

1. Workshop walkthrough

The Workshop can make five kinds of part: hair, headgear, faces, weapons and off-hand items. These are the parts that keep their shape while the character moves, so one small drawing is enough for every animation.

  1. Set up the character first. Pick the race, hair and gear you want to design around. The Workshop uses that character as the guide.
  2. Click ✏️ Workshop in the top bar and choose what you are making.
  3. Draw. Pick a colour from the palette and click or drag on the grid. Right-click erases. The faint picture underneath is your character, and the red cross marks the anchor (the head centre or the hand). To get a head start, click Start from current: it copies the part your character is wearing so you can change it.
  4. Watch the live preview. It plays your drawing on the moving character. Switch the animation and flip between front and back to check it.
  5. Fill in both views. Hair, headgear and off-hand items have a front view on the left and a back view on the right. If you leave the back empty, the part disappears when the character faces away.
  6. Name it and save. Click Save to my parts. It now appears in the normal menus marked with ★, and is put on your character straight away.
Parts you save are kept in this browser. To move them to another computer, save a character that uses them (see section 5).

Options

2. Template sizes

Each kind of part is one small PNG. Views sit side by side, front first.

PartImage sizeViewsAnchor pixel in each viewNotes

3. Palette colours

Pixels drawn in the exact colours below are recoloured to match each character's colour settings. For example, anything drawn in the Hair colours follows the Hair picker. Any other colour stays exactly as you drew it.

MaterialOutlineShadowBaseLightShine
Pink is the guide colour. Any pixel that is pure pink or magenta (red and blue at 250 or more, green at 215 or less) is treated as empty when you import. That's how templates can show the character without it ending up in your part. Avoid those colours in your own art.

4. Using a pixel editor

You can draw in Aseprite, LibreSprite, Piskel, GIMP or any editor that saves PNGs.

  1. In the Workshop, choose the part kind and click Download template. You get a PNG of the right size with your character shown in pink.
  2. Open it in your editor and draw over the pink guide. Keep the image size the same. Use the palette colours from section 3 for anything that should recolour.
  3. Save as PNG. You can leave the pink in; it is removed on import. Use a transparent background.
  4. Back in the Workshop, click Import PNG, check the preview, name it and save.

Export PNG does the reverse: it downloads the part you are editing so you can keep working on it elsewhere.

5. Saving and sharing

6. Adding parts in code

Bodies, outfits, armour, capes, races and animations bend with the skeleton, so they are drawn by code and can't be made in the Workshop. They live in a few plain JavaScript files. After editing one, refresh the page.

FileWhat it holds
js/parts.jsRaces, outfits, armour, faces, hair, headgear, capes and tails
js/gear.jsWeapons, off-hand items and effects (slashes, sparkles, muzzle flashes)
js/poses.jsThe skeleton and every animation
js/render.jsLayer order and job presets
js/palette.jsColour slots, swatches and how shades are made

How drawing works

A part draws simple shapes into a layer L using a material (not a colour): M.skin, M.hair, M.cloth1, M.metal and so on. The engine then shades the layer, outlines it and colours it from the character's palette. Useful shapes:

L.ellipse(cx, cy, rx, ry, M.hair)        // filled oval
L.capsule(a, b, radius, M.wood)          // thick line with round ends
L.poly([p1, p2, p3], M.metal)            // filled polygon
L.chain([p1, p2, p3], r0, r1, M.hair)    // tapering curve (tails, ponytails)
L.px(x, y, M.gold, 3)                    // one pixel with a fixed tone (0 outline … 4 shine)
L.clipped(() => L.rect(x, y, w, h, M.gold)) // paint only over what is already there (trim, belts)

Points are {x, y} in design units on a 64×64 grid; the engine draws every shape 1.5× finer, into a 96×96 pixel frame. For pixel-exact detail use L.dot, L.box or L.art, which work in pixels. The skeleton S gives you where things are: S.head (centre, with rx/ry), S.neck, S.hip, S.na.hd (near hand), S.fa.hd (far hand), and S.back, which is true in the back view. Forward is always +x.

Example: a new hairstyle

// js/parts.js, inside SF.HAIR = { ... }
sidecut: {
  label: 'Side Cut',
  front(L, S) {
    cap(L, S);                                   // the standard hair cap with fringe
    const h = S.head;
    if (!S.back) L.taper({ x: h.x + 3, y: h.y - 4 }, { x: h.x + 7, y: h.y + 1 }, 1.6, 0.6, M.hair);
  },
  back() {},                                     // anything that hangs behind the body
},

Example: a new weapon

// js/gear.js, inside SF.WEAPONS = { ... }
club: {
  label: 'Club', grip: 'one', attack: 'slash', idleAng: 115, reach: 10,
  draw(L, h, a) {                                // h = hand, a = angle the weapon points
    const d = vec(a);
    L.taper(add(h, d, -2), add(h, d, 10), 0.7, 1.8, M.wood);
  },
},

grip is one of one, two, pole, rifle, bow or none. attack is slash, thrust, gun, bow or punch.

Example: a new race

// js/parts.js, inside SF.RACES = { ... }
giant: {
  label: 'Giant',
  dims: dims({ thigh: 5, shin: 5, torso: 10, sw: 5, ww: 4, armR: 1.6, legR: 1.8 }),
  ears: 'round', skin: '#d9a077', hair: '#3a2e3f',
},

Flags you can add: beard, tusks, jaw, nose, snout, horns, skull, muzzle, and tail: 'lizard' | 'cat' | 'spade'. Ear types are round, long, wide, small and cat.

Example: a new job preset

// js/render.js, inside SF.JOBS = { ... }
//            label     weapon   off-hand  outfit   armour   headgear  back     colours
bard: job('Bard', 'rapier', 'none', 'vest', 'none', 'cap', 'short', { cloth1: '#8a5ab4', cloth2: '#ecc95c' }),

Example: a new animation

// js/poses.js, inside SF.ANIMS = { ... }, then add 'wave' to SF.ANIM_ORDER
wave: {
  label: 'Wave', fps: 8,
  build: () => [0, 1, 0, 1].map((k) => ({ fUA: 150, fFA: 160 + k * 25, free: true })),
},

Each frame lists only what differs from the standing pose. Angles are in degrees: 0 is straight down, 90 is forward, 180 is up. nUA/nFA are the near upper arm and forearm, fUA/fFA the far arm, lean tilts the body, bx/by move it, and nFoot/fFoot place the feet.

Replacing a built-in part with an image

The simplest route is the Workshop: make your version, save it, and select it. To make it the default for a job, put its id (shown in the saved character file) into the job preset.

7. Using sheets in a game

8. Troubleshooting