Skip to main content
skill CX Codex

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.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add SpriteCook/skills --skill spritecook-use-dual-grid-tilesets -a claude-code
Open on GitHub

What 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 frameByMask lookup.
  • 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-code

2Manually: put the files in place

~/.claude/skills/spritecook-use-dual-grid-tilesets/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/spritecook-use-dual-grid-tilesets/

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

Similar skills

Everything for Game dev and 3D: Unity, Unreal, Godot, Blender →

From the same set9

spritecook-generate-sprites A skill that guides agents through still-image generation in SpriteCook: model choice, sizing, and style consistency via reference assets. CX Codex +1 1,200installs spritecook-workflow-essentials Sets the ground rules for SpriteCook asset work: credit checks, a local manifest, safe handling of keys. Sits alongside the other SpriteCook skills. CX Codex +1 1,000installs spritecook-animate-assets A skill for animating game assets through the SpriteCook MCP server: turns an existing sprite into a short pixel-art or detailed animation. CX Codex +1 1,000installs spritecook-generate-tilesets A skill that walks the agent through SpriteCook tileset generation: picking perspective, tile size and edge mode, launching the job, then checking variations. CX Codex +1 575installs spritecook-use-assets-in-godot Turns SpriteCook spritesheets into Godot SpriteFrames resources and AnimatedSprite2D nodes. Useful once the animations exist but the engine scene does not. CX Codex +1 555installs spritecook-upload-assets Uploads a selected image into a SpriteCook asset library through the MCP upload tools and returns an asset_id for generation, animation or editing. CX Codex +1 520installs spritecook-use-presets This skill pulls your saved SpriteCook presets through MCP and maps their settings onto new asset generation. Useful when a set of images has to share one look. CX Codex +1 517installs spritecook-build-ui-kits Builds a game UI kit through the SpriteCook MCP server: concept, component sheets, extraction, finalization. For menus, HUDs, inventories and dialogs. CX Codex +1 342installs

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor