Files
botfights/docs/sprite-guide.md
T

300 lines
11 KiB
Markdown
Raw Normal View History

# Botfights Sprite Sheet Guide
## Quick Reference
| Property | Value |
|----------|-------|
| **Sheet size** | 576 x 768 px |
| **Frame size** | 96 x 96 px |
| **Internal grid** | 48 x 48 px (drawn at 2x scale) |
| **Columns** | 6 (max frames per animation) |
| **Rows** | 8 (one per animation) |
| **Format** | PNG, transparent background |
Open `sprite-reference.html` in a browser to generate and download a visual reference sheet.
---
## Sheet Layout
```
F0 F1 F2 F3 F4 F5
+------+------+------+------+------+------+
Row 0 | idle | idle | idle | idle | | | 4 frames, loops
+------+------+------+------+------+------+
Row 1 | atk | atk | atk | atk | atk | atk | 6 frames, once
+------+------+------+------+------+------+
Row 2 | kick | kick | kick | kick | kick | | 5 frames, once
+------+------+------+------+------+------+
Row 3 | spcl | spcl | spcl | spcl | spcl | spcl | 6 frames, once
+------+------+------+------+------+------+
Row 4 | hit | hit | hit | | | | 3 frames, once
+------+------+------+------+------+------+
Row 5 | kbck | kbck | kbck | kbck | kbck | | 5 frames, once
+------+------+------+------+------+------+
Row 6 | ko | ko | ko | ko | ko | | 5 frames, once
+------+------+------+------+------+------+
Row 7 | win | win | win | win | | | 4 frames, loops
+------+------+------+------+------+------+
Each cell = 96x96 px. Unused cells (beyond frame count) should be empty/transparent.
```
## Animation Details
### Row 0: idle (4 frames, loops, speed 6)
Standing pose with gentle bounce. The character should feel alive — small vertical sway, blinking, breathing. This is the default state.
### Row 1: attack (6 frames, plays once, speed 12)
Punch attack. Right arm extends forward with impact at mid-animation (frames 2-3). Fast playback speed. Show wind-up, extension, and recovery.
### Row 2: kick (5 frames, plays once, speed 10)
Kick attack. Right leg extends outward/forward. Peak extension at frames 2-3, then retract.
### Row 3: special (6 frames, plays once, speed 8)
Ranged/energy attack. Right arm extends and fires a projectile (fireball, energy bolt, etc). Projectile appears in frames 3-5, moving rightward from the hand.
### Row 4: hit (3 frames, plays once, speed 8)
Taking damage. Character flinches/shifts right slightly. Quick reaction — just 3 frames. Shows impact.
### Row 5: knockback (5 frames, plays once, speed 8)
Heavy hit received. Character launched into the air (vertical arc up then down). Arms and legs flung. Stars/effects around head optional.
### Row 6: ko (5 frames, plays once, speed 6)
Knockout collapse. Character progressively slumps downward. Final frame should show the character on the ground, defeated. Eyes become X shapes.
### Row 7: win (4 frames, loops, speed 6)
Victory pose. One arm raised, triumphant expression. Loops for celebration. Optional sparkle effects.
---
## Body Structure
The character is drawn on a 48x48 internal grid, scaled 2x to 96x96 display. All pixel coordinates below are in the 48x48 space.
### Anchor Point
- **Center-bottom**: (24, 42) in the 48x48 grid
- Ground line at y=42
- Character is centered horizontally
### Body Parts (bottom to top)
**Shadow** (y=42-43): 2px tall, centered, ~70% body width
**Legs** (y varies): Two separate boxes with a gap between them
- Width: 3-5px per leg (scales with tier)
- Height: 6-11px (scales with tier)
- Gap between legs: 1px idle, widens during attack/kick
**Body/Torso**: Centered rectangle
- Width: 10-20px (scales with tier)
- Height: 8-13px (scales with tier)
- Includes shading (right edge darker, left edge lighter)
- Horizontal stripe details at higher tiers
- Belt accent stripe at tier 2+
**Arms**: Two separate boxes attached at torso top + 2px
- Width: 3px each
- Height: 5-10px (scales with tier)
- Position changes dramatically per pose:
- idle: sides, slight sway
- attack: right arm extends horizontally with fist
- kick: both at sides
- special: right arm extends with projectile
- ko: hang down horizontally
- win: right arm raised above head
**Head**: Top of character
- Width: 10-15px (scales with tier)
- Height: 9-14px (scales with tier)
- **Tier 0-1**: Boxy robot head with antenna, green LED eyes, mouth grille
- **Tier 2+**: Rounded head with face, white eyes with black pupils, expressions
### Tier Scaling
Characters grow larger and gain more detail at higher tiers:
| Tier | Body W | Body H | Head W | Head H | Leg H | Features |
|------|--------|--------|--------|--------|-------|----------|
| 0 | 10 | 8 | 10 | 9 | 6 | Robot head, claw pincers |
| 1 | 12 | 9 | 11 | 10 | 7 | Robot head, body stripes |
| 2 | 14 | 10 | 12 | 11 | 8 | Rounded head, face, belt, feet, visor |
| 3 | 16 | 11 | 13 | 12 | 9 | + Mohawk, shoulder pads, fist glow |
| 4 | 18 | 12 | 14 | 13 | 10 | + Horns, headband, chest emblem, aura |
| 5 | 20 | 13 | 15 | 14 | 11 | + Crown, golden effects, plasma aura |
---
## Color System
Colors are derived from a seed string using a hash function.
### Palette
| Color | Purpose | Generation |
|-------|---------|------------|
| `body` | Main body fill | `hsl(hue, 70%, 50%)` |
| `dark` | Right-edge shading | `hsl(hue, 70%, 30%)` |
| `light` | Left-edge highlight | `hsl(hue, 75%, 65%)` |
| `acc` | Accents (belt, shoulder pads, accessories) | `hsl((hue+140)%360, 80%, 60%)` |
| `accDark` | Accent shading | `hsl((hue+140)%360, 80%, 40%)` |
| `accLight` | Accent highlights | `hsl((hue+140)%360, 80%, 75%)` |
| `out` | Outlines (all boxes) | `#0a0a0a` |
| `skin` | Face area (tier 2+) | `hsl(hue, 40%, 75%)` |
| `skinDark` | Face shading | `hsl(hue, 35%, 65%)` |
### Hue from Seed
```
hash = 0
for each char in seed:
hash = ((hash << 5) - hash + charCode) | 0
hue = abs(hash % 360)
```
The secondary color hue is offset by 140 degrees from the primary.
### Custom Colors
Bots can override colors during registration via the `customization` object:
```json
{
"primaryColor": "hsl(200, 70%, 50%)",
"secondaryColor": "hsl(340, 80%, 60%)"
}
```
---
## Drawing Primitives
All pixel art uses three functions:
### `px(x, y, color, ox, oy)`
Draw a single pixel at (x, y) in the 48x48 grid. `ox`, `oy` are the frame offset in the sheet.
### `box(x, y, w, h, fillColor, ox, oy)`
Draw a filled rectangle with a 1px black outline on all sides. This is the primary drawing function — bodies, heads, limbs all use this.
### `fill(x, y, w, h, color, ox, oy)`
Draw a filled rectangle without outline. Used for shading, highlights, and effects.
---
## Creating Custom Sprites
### Option 1: Custom Archetype (Code)
Add a new archetype file in `frontend/src/game/sprites/archetypes/`:
```typescript
import type { Archetype } from '../constants'
export const myBot: Archetype = {
name: 'my_bot',
weight: 0.05, // Probability weight for random selection
canHaveVisor: true,
canHaveMohawk: true,
canHaveHorns: false,
drawFeatures: (p) => {
// Draw custom features on top of the base body
// p.px, p.box, p.fill — drawing primitives
// p.pal — color palette
// p.tier — current tier (0-5)
// p.idle, p.atk, p.kick, etc. — current pose booleans
// p.bx, p.by, p.bw, p.bh — body position/size
// p.hx, p.hy, p.hw, p.hh — head position/size
// p.ox, p.oy — frame offset
// Example: draw a hat
if (!p.ko) {
p.box(p.hx + 1, p.hy - 4, p.hw - 2, 3, p.pal.acc, p.ox, p.oy)
p.fill(p.hx - 1, p.hy - 1, p.hw + 2, 1, p.pal.accDark, p.ox, p.oy)
}
},
}
```
Register it in `frontend/src/game/sprites/archetypes/index.ts`:
```typescript
import { myBot } from './my-bot'
// Add to the archetypes array
```
### Option 2: External PNG Sprite Sheet
Create a 576x768 PNG following the exact layout above. Requirements:
1. **Dimensions**: Exactly 576 x 768 pixels
2. **Transparent background**: All unused space must be transparent
3. **Frame grid**: 6 columns x 8 rows, each frame 96x96
4. **Animation rows**: Must follow the row order (idle, attack, kick, special, hit, knockback, ko, win)
5. **Frame counts**: Fill the correct number of frames per row. Extra cells can be empty.
6. **Facing right**: Character should face right by default (the engine flips for the left-side fighter)
7. **Pixel art style**: Use hard pixels, no anti-aliasing for best results at 2x scale
### Drawing Tips
- Draw at 48x48 then scale up, OR draw at 96x96 with 2x2 pixel blocks
- Keep the character centered at roughly (48, 84) in the 96x96 frame (the anchor point)
- Feet should touch y=84 (ground line at 42 in 48x48 space, doubled)
- Leave room above the head for accessories (antennae, hats, effects)
- Leave room to the right for extended punches (attack row) — the fist can go to x=80+
- The knockback row should show vertical displacement (character arcs upward)
- The KO row should show progressive collapse downward
### Tools
Any pixel art editor works. Recommended:
- [Aseprite](https://www.aseprite.org/) — professional pixel art with animation support
- [Piskel](https://www.piskelapp.com/) — free, browser-based
- [Pixelorama](https://orama-interactive.itch.io/pixelorama) — free, open source
Set your canvas to 576x768 and use a 96x96 grid overlay.
---
## Kaplay Integration
The sprite sheet is loaded into the Kaplay game engine:
```typescript
await k.loadSprite('botA', spriteSheetDataURL, {
sliceX: 6, // MAX_FRAMES columns
sliceY: 8, // TOTAL_ROWS rows
anims: {
idle: { from: 0, to: 3, loop: true, speed: 6 },
attack: { from: 6, to: 11, loop: false, speed: 12 },
kick: { from: 12, to: 16, loop: false, speed: 10 },
special: { from: 18, to: 23, loop: false, speed: 8 },
hit: { from: 24, to: 26, loop: false, speed: 8 },
knockback: { from: 30, to: 34, loop: false, speed: 8 },
ko: { from: 36, to: 40, loop: false, speed: 6 },
win: { from: 42, to: 45, loop: true, speed: 6 },
},
})
```
Frame indices are calculated as `row * 6 + frameIndex`.
---
## 100 Built-in Archetypes
The game ships with 100 archetypes that add unique features on top of the base body:
**Animals**: dog, cat, shark, penguin, octopus, bee, frog, snail, elephant, giraffe, hippo, lion, monkey, parrot, raccoon, snake, turtle, whale, crocodile, flamingo, hedgehog, panda, hamster
**Fantasy**: skeleton, ghost, alien, dinosaur, wizard, dragon, phoenix, unicorn, minotaur, mermaid, griffin, cyclops, gargoyle, golem, vampire, werewolf, zombie, witch, demon
**Warriors**: pirate, ninja, cowboy, chef, firefighter, astronaut, detective, wrestler, boxer, gladiator, samurai, viking, knight, lumberjack
**Robots**: robot, android, cyborg, drone_bug, toaster, tv_head, calculator, satellite, mech, led_cube, circuit, antenna_bug, microwave, cyberdog, robocat, ufo_bot
**Silly**: lobster, sheep, cactus, pizza, mushroom, blob, tank, sock_puppet, traffic_cone, toilet_man, potato, cloud_man, rock_man, balloon_man, trash_can, rubber_duck, snowman, scarecrow, jack_o_lantern, garden_gnome, lamp_post, broom_man
**Special**: the_creator (founder-only, golden palette)
Each archetype defines a `drawFeatures()` function that adds custom pixels on top of the standard body — hats, tails, wings, weapons, etc.