# Player Step 2: Sprite Action Guide

Use this guide after the Step 1 player design page has been approved.

Step 2 generates one focused sprite animation at a time. The input must say which action to make, such as `idle`, `walk`, `action`, or `hurt_or_death`.

Do not generate the full player pack in one request.

## Required Input

Every Step 2 run must begin with this action input:

```json
{
  "action_type": "idle",
  "direction": "down",
  "animation_name": "idle_down",
  "frame_count": 4,
  "fps": 6,
  "loop": true,
  "source_design": "player_design_page.png"
}
```

The AI should generate only the requested `animation_name`.

If the input is missing, invalid, or asks for multiple actions, stop and ask for a corrected action input.

## Allowed First-Pack Actions

The first player pack is capped at 10 actions:

1. `idle_down`
2. `idle_up`
3. `idle_side`
4. `walk_down`
5. `walk_up`
6. `walk_side`
7. `action_down`
8. `action_up`
9. `action_side`
10. `hurt_or_death`

Use horizontal flip in Godot for left/right side movement.

Do not add separate left/right sprites yet. Do not add class-specific sprites yet. Do not add sword, spell, dodge, swim, climb, emote, mount, or tool animations in the first pack.

## Allowed Input Values

Allowed `action_type` values:

- `idle`
- `walk`
- `action`
- `hurt_or_death`

Allowed `direction` values:

- `down`
- `up`
- `side`
- `universal` only for `hurt_or_death`

Animation naming rules:

- `idle` + `down` = `idle_down`
- `idle` + `up` = `idle_up`
- `idle` + `side` = `idle_side`
- `walk` + `down` = `walk_down`
- `walk` + `up` = `walk_up`
- `walk` + `side` = `walk_side`
- `action` + `down` = `action_down`
- `action` + `up` = `action_up`
- `action` + `side` = `action_side`
- `hurt_or_death` + `universal` = `hurt_or_death`

## Frame Targets

- `idle`: 2-4 frames, 4-6 fps, looping.
- `walk`: 6-8 frames, 8-12 fps, looping.
- `action`: 4-6 frames, 8-12 fps, non-looping.
- `hurt_or_death`: 3-6 frames, 6-10 fps, non-looping.

If quality drops, reduce frame count before adding more movement.

## Required Output Per Action

For each requested action, deliver:

- `sprites/actions/<action_name>.png`
- `sprites/actions/<action_name>.json`
- `preview/<action_name>_contact_sheet.png`
- `preview/<action_name>_gameplay_scale.png`
- `preview/<action_name>_alpha_edge_light.png`
- `preview/<action_name>_alpha_edge_dark.png`

The final sprite image must be a production sprite strip, not a preview image. It must be a horizontal RGBA PNG containing only the requested action frames.

Hard size rule:

- width = `frame_count * 128`
- height = `128`
- examples:
  - 4 frames = `512x128`
  - 6 frames = `768x128`
  - 8 frames = `1024x128`

Reject and regenerate if the sprite image is any other size.

Preview files are allowed to include labels, tile grids, light/dark backgrounds, or contact-sheet framing. The final file under `sprites/actions/` is not allowed to include any of those.

## Production Sprite Gate

Before packaging the zip, inspect `sprites/actions/<action_name>.png` directly. Do not rely on the contact sheet.

The action is `import_ready: true` only if all of these are true:

- PNG color mode is RGBA or equivalent with a real alpha channel.
- Alpha is not fully opaque; at least the padding around the character is transparent.
- No white, gray, checkerboard, tile, canvas texture, or matte background is baked into transparent areas.
- Image dimensions exactly equal `frame_count * 128` by `128`.
- Each frame occupies one exact 128x128 cell with no gutters between frames.
- Character silhouette stays inside each cell with transparent padding on every side.
- Feet/base point is the same pixel location in every frame.
- The sprite strip contains only the requested animation, no title text, frame numbers, labels, borders, previews, or extra poses.

If any item fails, set `import_ready: false` in the JSON and regenerate or clean the sprite before using it in Godot.

Never mark preview-style renders as production sprites. A file with a baked checkerboard is reference-only, even if it looks visually transparent.

## Quick Machine Validation

Use this check before accepting a generated action pack. Replace the paths if needed.

```bash
python3 - <<'PY'
from PIL import Image
import json
from pathlib import Path

action = "idle_down"
root = Path("player-action-work")
png_path = root / "sprites" / "actions" / f"{action}.png"
json_path = root / "sprites" / "actions" / f"{action}.json"

meta = json.loads(json_path.read_text())
im = Image.open(png_path)
expected = (meta["frame_count"] * 128, 128)
errors = []

if im.size != expected:
    errors.append(f"wrong size: {im.size}, expected {expected}")
if im.mode != "RGBA":
    errors.append(f"wrong mode: {im.mode}, expected RGBA")
else:
    alpha = im.getchannel("A")
    if alpha.getextrema() == (255, 255):
        errors.append("alpha is fully opaque; no real transparency")
    if alpha.getbbox() == (0, 0, im.size[0], im.size[1]):
        errors.append("opaque pixels touch the image bounds; no transparent padding")

if errors:
    print("IMPORT_READY=false")
    for err in errors:
        print("-", err)
    raise SystemExit(1)

print("IMPORT_READY=true")
PY
```

If this script prints `IMPORT_READY=false`, do not import the sprite into Godot and do not call the pack finished.

## Action Metadata JSON

Create one JSON file per action:

```json
{
  "action": "walk_down",
  "action_type": "walk",
  "direction": "down",
  "frame_size_px": [128, 128],
  "frame_count": 8,
  "fps": 10,
  "loop": true,
  "base_point_px": [64, 104],
  "collision_footprint_px": {
    "shape": "capsule_or_rect",
    "center": [64, 108],
    "size": [28, 18]
  },
  "source_design": "player_design_page.png",
  "side_view_flips_for_left_right": true,
  "transparent_background": true,
  "sheet_size_px": [1024, 128],
  "import_ready": true,
  "validation": {
    "rgba_with_alpha": true,
    "has_transparent_padding": true,
    "no_baked_checkerboard_or_matte": true,
    "exact_sheet_dimensions": true,
    "exact_128_px_cells": true,
    "base_point_stable": true,
    "production_sprite_not_preview": true
  },
  "notes": "Transparent RGBA PNG. Feet/base point remains stable across frames."
}
```

## Universal Sprite Requirements

- Every frame uses the same `128x128` canvas.
- The final strip size is exactly `frame_count * 128` by `128`.
- The final strip uses RGBA PNG with real transparency.
- Transparent padding must be alpha `0`, not a checkerboard, white, gray, or textured background.
- The feet/base point stays locked in every frame.
- Recommended base point: `[64, 104]`.
- Recommended collision center: `[64, 108]`.
- Recommended collision size: `[28, 18]`.
- Runtime visual height target: `56-72` px.
- Leave transparent padding on every side.
- The character cannot touch the frame edge.
- No cropped weapon, hair, shadow, hand, foot, or effect.
- No background.
- No labels.
- No baked contact-sheet border.
- No checkerboard, matte, or fake alpha.
- Real PNG transparency only.
- Match the approved design page proportions, outfit, palette, head shape, and silhouette.
- Side animations must flip cleanly for left/right.
- The sprite strip must contain only the requested action.
- Do not include unrelated poses, alternate designs, or bonus animations.
- Do not upscale the production strip into a presentation sheet.
- Do not crop frames from a contact sheet unless they are cleaned back into exact transparent 128x128 cells.

## Quality Bar By Action Type

### `idle`

- Pose should feel alive but calm.
- Use subtle breathing, blink, cloth, or hair movement.
- Feet must stay planted.
- No weapon swing, magic effect, jump, or dramatic body motion.
- Down, up, and side versions should feel like the same character from different angles.

### `walk`

- Walk cycle must read clearly at gameplay scale.
- Feet alternate cleanly.
- Body bob is subtle and does not look like jumping.
- Base point remains stable enough to avoid visual sliding in Godot.
- Side walk flips cleanly for left/right.
- Avoid long trailing cloth/hair that creates frame-edge or flip problems.

### `action`

- This is a generic first-pack action: use, cast, or basic interaction.
- It should work before the player has a class.
- The motion should be readable but not too specialized.
- It can include a small neutral arc, hand motion, or brief focus flash.
- Do not add sword-specific, spell-specific, or class-specific gear unless explicitly requested later.
- Non-looping: clear anticipation, action, and settle frames.

### `hurt_or_death`

- One universal direction is acceptable for the first pack.
- It should communicate damage/failure quickly at phone size.
- The character can recoil, slump, or fall, but must stay inside the 128x128 canvas.
- Avoid gore, scary detail, or overly dramatic deformation.
- Non-looping.

## Prompt Template

```text
Using the approved player design page, generate ONE transparent sprite animation action for a top-down Godot RPG player.

Action input:
{
  "action_type": "ACTION_TYPE_HERE",
  "direction": "DIRECTION_HERE",
  "animation_name": "ANIMATION_NAME_HERE",
  "frame_count": FRAME_COUNT_HERE,
  "fps": FPS_HERE,
  "loop": LOOP_TRUE_OR_FALSE,
  "source_design": "player_design_page.png"
}

Generate only this animation:
- ANIMATION_NAME_HERE

Do not generate the full character pack.
Do not generate other actions.
Do not generate extra directions.
Do not add class-specific variants.

Technical target:
- 128x128 px canvas per frame
- final production strip size must be frame_count * 128 px wide by 128 px tall
- for 4 frames, final production strip must be exactly 512x128 px
- transparent RGBA PNG with a real alpha channel
- alpha padding must be truly transparent pixels, not a baked checkerboard/matte
- fixed feet/base point at the same pixel location in every frame
- recommended base point: [64, 104]
- recommended collision footprint center: [64, 108]
- recommended collision footprint size: [28, 18]
- character should occupy about 56-72 px visual height at runtime
- leave safe transparent padding on all sides
- no background, no labels, no watermark
- no checkerboard, matte, or fake alpha
- no frame border or contact-sheet border baked into the final sprite strip

Animation requirements:
- use FRAME_COUNT_HERE frames
- fps: FPS_HERE
- loop: LOOP_TRUE_OR_FALSE
- direction/view: DIRECTION_HERE
- side view must be flippable for left/right in Godot
- if action_type is idle: subtle breathing/blink/cloth motion only
- if action_type is walk: clean alternating foot cycle, no visual sliding
- if action_type is action: generic classless use/cast/basic action, non-looping
- if action_type is hurt_or_death: clear damage/failure read, non-looping, no gore

Consistency:
- match the approved design page exactly
- keep the same proportions, outfit, palette, head shape, and readable silhouette
- do not add class-specific armor, weapons, or powers unless the action requires a small generic effect
- keep the same shadow/feet relationship across frames
- keep the character centered on the same base point
- preserve phone-size readability over tiny detail

Deliver:
- one horizontal sprite strip for this action
- sprite strip must be saved at sprites/actions/ANIMATION_NAME_HERE.png
- sprite strip must be exact size: frame_count * 128 by 128
- action metadata JSON
- a contact-sheet preview
- a gameplay-scale preview on a neutral 64 px tile background
- alpha-edge previews on light and dark backgrounds
- one short note describing any known limitations

Packaging rule:
- if the production sprite strip has no real alpha, wrong dimensions, labels, frame borders, or baked checkerboard, do not package it as import-ready
- set import_ready:false and mark it reference_only until regenerated
```

## Godot Import Contract

The current project uses `CharacterBody2D` with `AnimatedSprite2D`.

When all approved actions exist:

- assemble them into a `SpriteFrames` resource
- keep animation names exactly as listed in this guide
- use `flip_h` for left/right side animations
- choose idle/walk animation from movement direction
- play `action_*` as non-looping one-shots
- play `hurt_or_death` as a non-looping damage/failure state
- keep collision as a small body/feet footprint, not the full visual sprite

## Validation Checklist

Before importing an action:

- [ ] The action input was valid.
- [ ] Only one animation was generated.
- [ ] Frame size is exactly 128x128.
- [ ] Sprite strip size is exactly `frame_count * 128` by `128`.
- [ ] Frame count matches the input.
- [ ] FPS and loop flag match metadata.
- [ ] Sprite PNG is RGBA or equivalent with a real alpha channel.
- [ ] Sprite has transparent padding pixels; alpha is not fully opaque.
- [ ] No background or checkerboard is baked in.
- [ ] Final `sprites/actions/<action_name>.png` is not a contact sheet or preview.
- [ ] Final sprite contains no labels, borders, frame numbers, tile grids, or matte.
- [ ] No frame touches the image edge.
- [ ] Base point stays stable.
- [ ] Collision footprint is documented.
- [ ] Gameplay-scale preview is readable.
- [ ] Side action flips cleanly if direction is `side`.
- [ ] Walk loops without obvious foot sliding.
- [ ] Non-looping actions have clear start, action, and settle/failure poses.
