spritecook-use-dual-grid-tilesets について
ゲームエンジンや独自レンダラーで SpriteCook のデュアルグリッド15ピース地形タイルセットを扱うための実装ガイドです。セルの参照方法、マスクとアトラスの対応、2面タイルセットの描画規則を示します。
主な機能
- 014セルから4ビットマスクを作成
- 02マスクを4×4アトラスのフレームに対応
- 032面タイルセットのベース描画
- 04境界とピクセルアートの拡大に対応
活用シーン
- 01ゲームエンジンで地形描画を実装
- 022面マップのベースレイヤーを描画
- 03塗りつぶし領域の継ぎ目を調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ spritecook/ skills --skill spritecook-use-dual-grid-tilesetsインストール後、Claude Code で/spritecook-use-dual-grid-tilesetsを入力して読み込まれたか確認します。
詳細
SpriteCook デュアルグリッド 15 ピースタイルセット
ゲームエンジンまたはカスタムレンダラーで、トップダウン型の SpriteCook 15 ピースタイルセットを実装する際に、このスキルを使用してください。
このスキルでは、生成済みのタイルセットを使用します。生成には、spritecook-generate-tilesets を使用してください。
概念
デュアルグリッドタイルセットでは、地形を論理的なペイント済みセルとして保持し、それらのセルの間に見えるタイルを描画します。描画する各タイルは、周囲にある4つの論理セルから選択されます。
描画するタイルごとに、次のセルをサンプリングします。
- 左上の論理セル
- 右上の論理セル
- 左下の論理セル
- 右下の論理セル
この4セルのパターンが4ビットのマスクになります。このマスクによって、4x4の15ピースアトラスからフレームを1つ選択します。
マスクの順序
SpriteCook の現在のマスクビット順序を使用します。
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
マスク 0 は何も描画しません。それ以外のマスクは、次の対応表を通じて4x4アトラスにマッピングされます。
const frameByMask = [
-1,
15,
8,
9,
0,
11,
14,
7,
13,
4,
1,
10,
3,
2,
5,
6,
]
アトラスのセルは次のとおりです。
const frame = frameByMask[mask]
if (frame < 0) return null
const atlasColumn = frame % 4
const atlasRow = Math.floor(frame / 4)
レンダラーの疑似コード
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,
)
}
}
}
2面タイルセット
edges="two_surfaces" で生成されたタイルセット(たとえば草と水)には、2つ目の地形があります。フレームの参照では、アトラスのフレーム12(列0、行3、左下のセル)は使用されません。2面セットでは、このセルに、開けた水面など、もう一方の地形全体のタイルが格納されます。
まず、もう一方の地形を描画し、その上にマスクされたピースを重ねて描画します。
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)
}
このベースレイヤーがないと、マスク 0 の領域が透明になり、2つ目の地形が表示されなくなります。単一面(transparent edges)セットでは、このセルは空です。ベースレイヤーは省略してください。
実用上の注意
- 描画タイルはペイント済みの論理セルの周囲に配置されるため、論理マップのサイズよりも列と行をそれぞれ1つ多く描画してください。
- ピクセルアートでは、スムージングを無効にし、ニアレストネイバー法で拡大縮小してください。
- マスク
15は塗りつぶされた内側のタイル、マスク0は透明/描画なしとして扱ってください。2面セットでは、マスク0によってもう一方の地形のベースレイヤーが表示されます。 - セットをリリースする前に、テストマップをペイントしてください。塗りつぶしタイル(マスク
15)が正しくつながらないと、広い塗りつぶし領域に目に見えるチェッカーボードが表示されます。 - 生成されたアトラスは、同じサイズのタイルセルを並べた4x4グリッドとして、そのまま使用してください。
- シートを通常の8近傍ブロブタイルセットとして解釈しないでください。このマッピングは、SpriteCook のデュアルグリッド15ピースレイアウト専用です。