# hitbox-tool (`hitbox`) Scans **sprite sheet PNGs** and writes per-frame **collision boxes as JSON**, computed from the alpha channel. Closes the loop with [`pixel-sprite-maker`](../pixel-sprite-maker/): render a sheet with `spritec`, scan it with `hitbox`, and your game gets both graphics and hitboxes without a human drawing rectangles. Go, zero dependencies, single static binary. ## Build ```bash # Arch/Garuda: sudo pacman -S go cd hitbox-tool go build -o build/hitbox . # or the VS Code task "build hitbox-tool" go test ./... ``` ## Usage ```bash # spritec-named sheets need no flags — layout is parsed from the name, # and integer upscales are auto-detected (a _8x8_4x1 sheet that is # 256x64 px was rendered at --scale 8, so cells are 64x64): hitbox scan walk_8x8_4x1.png -o walk.hitbox.json hitbox scan boss.png --cell 32x32 -o boss.json # explicit frame size hitbox scan portrait.png # whole image = one frame, JSON to stdout hitbox show walk_8x8_4x1.png --frame 2 # verify visually in the terminal # tuning: --threshold 128 # ignore faint pixels (alpha < 128) --shrink 1 # tighter, more forgiving hitboxes (n px per side) --pad 2 # generous hitboxes (e.g. pickups) ``` ## Output ```json { "image": "walk_8x8_4x1.png", "cellW": 8, "cellH": 8, "cols": 4, "rows": 1, "alphaThreshold": 1, "frames": [ { "index": 0, "col": 0, "row": 0, "empty": false, "box": { "x": 1, "y": 0, "w": 5, "h": 8 } }, { "index": 1, "col": 1, "row": 0, "empty": true, "box": null } ] } ``` - Boxes are **relative to each frame's top-left corner**. - Frame order is row-major (`index = row * cols + col`), matching spritec sheets. - Cells with no solid pixels get `"empty": true`. In game code: ``` hit = px >= frameX + box.x && px < frameX + box.x + box.w && py >= frameY + box.y && py < frameY + box.y + box.h ``` `hitbox show` draws each frame with `#` for solid pixels and `+` for the box outline, so an agent can verify the result without an image viewer.