spritecook-use-dual-grid-tilesets — Claude Code skill
This skill explains SpriteCook’s 15-piece tileset mapping for a dual-grid terrain renderer. Use it when building or reviewing top-down game rendering.
npx skills add SpriteCook/skills --skill spritecook-use-dual-grid-tilesets -a claude-codeWhat spritecook-use-dual-grid-tilesets does
The skill maps logical terrain cells to the visible tiles between them. Each rendered position reads four surrounding cells, builds a 4-bit mask, and selects a frame from a 4x4 atlas. It includes the mask bit order, the frame lookup table, atlas coordinates, and renderer pseudocode.
For a two-surface set, the counter terrain is drawn as a base layer before the masked pieces. A transparent single-surface set skips that layer. The renderer also needs one extra tile row and column because visible tiles surround the logical cells.
Treat the atlas as sixteen equal cells in a 4x4 grid, rather than as a regular 8-neighbor blob tileset. Pixel-art output requires smoothing to be disabled and nearest-neighbor scaling to be used. Without the base layer, mask 0 leaves the counter terrain transparent in a two-surface set.
What it helps with
- map four logical cells to a rendered tile mask
- resolve a mask into a 4x4 atlas frame
- render terrain around the logical map boundary
- place a counter surface beneath masked pieces
- test filled-area joins for mask
15
Example prompts for the agent
- Implement a SpriteCook dual-grid renderer for the 4x4 atlas and include the
frameByMasklookup. - Show how to render
edges="two_surfaces"with its counter-surface base layer. - Inspect the test map and fix the checkerboard joins around a filled area with mask
15.
How to install spritecook-use-dual-grid-tilesets
1Skills CLI (Vercel)
npx skills add SpriteCook/skills --skill spritecook-use-dual-grid-tilesets -a claude-code2Manually: put the files in place
~/.claude/skills/spritecook-use-dual-grid-tilesets/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/spritecook-use-dual-grid-tilesets/
1Skills CLI (Vercel)
npx skills add SpriteCook/skills --skill spritecook-use-dual-grid-tilesets -a codex2Manually: put the files in place
.agents/skills/spritecook-use-dual-grid-tilesets/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add SpriteCook/skills --skill spritecook-use-dual-grid-tilesets -a cursor2Manually: put the files in place
.cursor/skills/spritecook-use-dual-grid-tilesets/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install SpriteCook/skills spritecook-use-dual-grid-tilesets2Manually: put the files in place
.github/skills/spritecook-use-dual-grid-tilesets/SKILL.md1Skills CLI (Vercel)
npx skills add SpriteCook/skills --skill spritecook-use-dual-grid-tilesets -a gemini-cli2Platform CLI
gemini skills install https://github.com/SpriteCook/skills --path skills/spritecook-use-dual-grid-tilesetsManually: put the files in place
.devin/skills/spritecook-use-dual-grid-tilesets/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add SpriteCook/skills --skill spritecook-use-dual-grid-tilesets -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about spritecook-use-dual-grid-tilesets
How do I install spritecook-use-dual-grid-tilesets in Claude Code?
Run npx skills add SpriteCook/skills --skill spritecook-use-dual-grid-tilesets -a claude-code, then check ~/.claude/skills/spritecook-use-dual-grid-tilesets/SKILL.md.
What does spritecook-use-dual-grid-tilesets do?
It documents SpriteCook’s dual-grid mapping for a 15-piece tileset. Four logical cells form a mask, which selects one cell in the 4x4 atlas; the skill also covers two-surface rendering.
Which platforms support this skill?
It is listed for Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, and OpenCode.
Source text
SKILL.md · MIT
---
name: spritecook-use-dual-grid-tilesets
description: "Implementation guide for using SpriteCook top-down 15-piece tilesets with a dual-grid autotile renderer. Use when explaining or coding how to map a 4x4 15-piece tileset image into terrain using SpriteCook's dual-grid mask system."
---
# SpriteCook Dual-Grid 15-Piece Tilesets
Use this skill when implementing a top-down 15-piece SpriteCook tileset in a game engine or custom renderer.
This skill is about using a generated tileset. For generation, use `spritecook-generate-tilesets`.
## Concept
A dual-grid tileset stores terrain as logical painted cells, then renders visible tiles between those cells. Each rendered tile is chosen from the four logical cells around it.
For each rendered tile, sample:
- top-left logical cell
- top-right logical cell
- bottom-left logical cell
- bottom-right logical cell
That four-cell pattern becomes a 4-bit mask. The mask chooses one frame from the 4x4 15-piece atlas.
## Mask Order
Use SpriteCook's current mask bit order:
```ts
let mask = 0
if (filled(x - 1, y - 1)) mask |= 1 // top-left
if (filled(x, y - 1)) mask |= 2 // top-right
if (filled(x - 1, y )) mask |= 4 // bottom-left
if (filled(x, y )) mask |= 8 // bottom-right
```
Mask `0` renders nothing. Other masks map into the 4x4 atlas through this lookup:
```ts
const frameByMask = [
-1,
15,
8,
9,
0,
11,
14,
7,
13,
4,
1,
10,
3,
2,
5,
6,
]
```
The atlas cell is:
```ts
const frame = frameByMask[mask]
if (frame < 0) return null
const atlasColumn = frame % 4
const atlasRow = Math.floor(frame / 4)
```
## Renderer Pseudocode
```ts
type CellMap = boolean[] // width * height logical terrain cells
function cellIndex(x: number, y: number, columns: number) {
return y * columns + x
}
function isFilled(cells: CellMap, x: number, y: number, columns: number, rows: number) {
return x >= 0 && y >= 0 && x < columns && y < rows && cells[cellIndex(x, y, columns)] === true
}
function dualGridMask(cells: CellMap, x: number, y: number, columns: number, rows: number) {
let mask = 0
if (isFilled(cells, x - 1, y - 1, columns, rows)) mask |= 1
if (isFilled(cells, x, y - 1, columns, rows)) mask |= 2
if (isFilled(cells, x - 1, y, columns, rows)) mask |= 4
if (isFilled(cells, x, y, columns, rows)) mask |= 8
return mask
}
function atlasCellForMask(mask: number) {
const frameByMask = [-1, 15, 8, 9, 0, 11, 14, 7, 13, 4, 1, 10, 3, 2, 5, 6]
const frame = frameByMask[Math.max(0, Math.min(15, Math.floor(mask)))]
if (frame < 0) return null
return { column: frame % 4, row: Math.floor(frame / 4) }
}
function renderDualGrid(ctx, atlasImage, cells: CellMap, columns: number, rows: number, tileSize: number) {
for (let y = 0; y <= rows; y += 1) {
for (let x = 0; x <= columns; x += 1) {
const mask = dualGridMask(cells, x, y, columns, rows)
const atlasCell = atlasCellForMask(mask)
if (!atlasCell) continue
ctx.drawImage(
atlasImage,
atlasCell.column * tileSize,
atlasCell.row * tileSize,
tileSize,
tileSize,
x * tileSize,
y * tileSize,
tileSize,
tileSize,
)
}
}
}
```
## Two-Surface Tilesets
Tilesets generated with `edges="two_surfaces"` (for example grass and water) have a second terrain. The frame lookup never uses atlas frame 12 (column 0, row 3, the bottom-left cell). In a two-surface set that cell holds the full counter-surface tile, such as open water.
Draw the counter surface first, then the masked pieces on top:
```ts
const counterSurfaceCell = { column: 0, row: 3 }
function renderTwoSurfaceDualGrid(ctx, atlasImage, cells: CellMap, columns: number, rows: number, tileSize: number) {
for (let y = 0; y <= rows; y += 1) {
for (let x = 0; x <= columns; x += 1) {
ctx.drawImage(
atlasImage,
counterSurfaceCell.column * tileSize,
counterSurfaceCell.row * tileSize,
tileSize,
tileSize,
x * tileSize,
y * tileSize,
tileSize,
tileSize,
)
}
}
renderDualGrid(ctx, atlasImage, cells, columns, rows, tileSize)
}
```
Without this base layer, mask `0` areas render transparent and the second terrain disappears. For a single-surface (`transparent` edges) set, that cell is empty; skip the base layer.
## Practical Notes
- Render one more tile column and row than the logical map size because rendered tiles sit around painted logical cells.
- For pixel art, disable smoothing and use nearest-neighbor scaling.
- Treat mask `15` as the filled interior tile and mask `0` as transparent/no draw. In a two-surface set, mask `0` shows the counter-surface base layer.
- Paint a test map before shipping a set. If the full tile (mask `15`) doesn't wrap, large filled areas show a visible checkerboard.
- Use the generated atlas exactly as a 4x4 grid of equal tile-sized cells.
- Do not reinterpret the sheet as a normal 8-neighbor blob tileset; this mapping is specifically SpriteCook's dual-grid 15-piece layout.
© SpriteCook · MIT · SpriteCook/skills