--- name: draw title: Draw a sprite description: Draw a sprite from silhouette to finished pixels, in the order that catches mistakes while they are still cheap — block in, check the silhouette, shade, outline, verify. Use for the main body of any drawing task. --- # Draw a sprite The order matters more than the technique. Detail added before the form is right just makes the wrongness harder to see and more expensive to fix. ## Procedure ### 1. Look before you draw `preflight`, then `sprite_info`. You need the real layer names, frame count and palette. Do not assume them — a wrong layer name means drawing into the user's finished art. If `aseprite:concept` produced a PixelSpec, it is the plan: its landmarks and bounding boxes are where the shapes go, its palette mapping is which colour each mass gets, its deviations are what you leave out. When a reference layer exists (`reference op="list"`), you are drawing over it — the steps below are the same, and step 3 gains a comparison. Then read the subject rules for what you are drawing — the table in `skill://studio` under *Subject rules* names them. A hand, a face, a horse, an isometric crate or a waterfall each has its own file with size budgets and ` ```grid ` templates. A template is a starting point you transcribe with `draw` op `grid`, mapping each legend role onto the sprite's palette; adapt it to the pose rather than inventing the shape from nothing. ### 2. Block in the silhouette One flat colour, no detail. Target the `base` layer. Everything in one `draw` call. For anything up to about 32×32, write it as a **grid**: one character per pixel, so you see the whole silhouette while you write it instead of finding out afterwards what a stack of ellipses and rects added up to. ``` draw layer="base" label="block in slime" ops=[ { kind:"grid", x:8, y:10, legend:{ "O":"#5f574f" }, rows:[ "....OOOO....", "..OOOOOOOO..", ".OOOOOOOOOO.", "OOOOOOOOOOOO", "OOOOOOOOOOOO", ".OOOOOOOOOO." ] } ] ``` Every row must be the same width, `.` is transparent, and transparent cells erase what is under them (`transparent:"skip"` to stamp over existing art instead). Bigger sprites: one grid per body part or per layer, each at its own `x`/`y` — long rows of identical characters are where a model miscounts, and a ragged row is refused with its row number rather than silently shifted. Shapes are still the right tool for big regular forms — a sky gradient, a floor, a 40-pixel circle: ``` draw layer="base" label="block in knight" ops=[ { kind:"ellipse", rect:{x:12,y:4,width:8,height:8}, color:"#5f574f", fill:"#5f574f" }, { kind:"rect", rect:{x:11,y:12,width:10,height:10}, color:"#5f574f", fill:"#5f574f" }, … ] ``` Batch aggressively. One call is one undo step for the user; forty calls are forty. See `rules://03-silhouette-and-form`. ### 3. Check the silhouette immediately ``` look op="preview" ``` Ask yourself the only question that matters here: **is it recognisable as one flat shape?** If not, fix it now. Shading a bad silhouette is wasted work. Watch for: symmetry that reads as a statue, tangents where an arm fuses into the torso, limbs all the same thickness. With a reference, `preview` blends the half-transparent reference into the art — use `look op="compare"` instead: reference left, art right. Name the three to five largest mismatches (silhouette, proportion, pose, where the colour masses sit), fix only those in one `draw` call, compare again. Stop when what is left is a deviation the PixelSpec lists. This loop repeats after materials (step 4) and after shading (step 5): the reference is a check on every stage, not only the first. ### 4. Separate the materials Replace regions of the blockout with each material's base colour — skin, metal, leather, cloth. Still flat. Still one `draw` call. ### 5. Shade See `aseprite:shade`. One shadow step, look, one light step, look. Stop there unless the sprite is 32px+ and genuinely needs more. ### 6. Outline Pick one style from `rules://04-outlines-and-edges` and apply it consistently. Selective outlining — outside only — is usually right. `transform` op `outline` does the mechanical part: `side="outside"` grows the shape by a pixel, `side="inside"` recolours its edge and keeps the size; `diagonals=true` fills the corner pixels for square corners, off leaves them cut and softer. Hand-place where you want it broken. ### 6b. Text, if the art has words `draw` op kind `text` lays out a string from a bitmap font and draws it in the same batch as everything else. Pass `measureOnly: true` with only `text` ops first to get the ink bounds back without touching the sprite — that is how you centre a label or size a panel around it before committing to a position. See [TOOLS.md](../../docs/TOOLS.md#font-format) for the font format. ### 7. Verify precisely ``` look op="ascii" ``` The text grid is where you catch the pixel one row too low and the line run of 3 in a sequence of 2s. A preview cannot show you those. To fix what it shows, edit the grid itself: `look op="ascii" layer="base" rulers=false region=…` returns bare rows plus `origin`; change the cells that are wrong and send the rows back as `draw` kind `grid` at that origin, with the legend `look` gave you. Only the region you send is touched. A glyph is a palette index and means the same colour in every region you read. ### 8. Validate and report ``` validate ``` Fix every error. Report warnings you chose not to fix, with the reason. ## Batching rules - Ops run in array order, so paint fills before outlines and outlines before highlights. - Leave `paletteLock` on. When the result says a colour moved with ΔE > 12, the palette has no colour for what you asked — say so rather than turning the lock off. - Use `label` to describe the intent; it becomes the user's undo entry. ## Related `rules://00-core-principles`, `rules://02-shading-and-light`, `rules://03-silhouette-and-form`, `rules://04-outlines-and-edges`, `rules://10-lines-and-curves`, `rules://11-clusters-and-noise`, and the subject files listed in `skill://studio` under *Subject rules*.