# Provenance of the tutorial assets

Everything under `docs/tutorials/assets/` is **CC0 1.0** or was written for this
repository. Nothing here carries an attribution requirement, a share-alike
clause, or a field-of-use restriction, which is the whole point: a reader who
copies a tutorial into their own game inherits whatever obligation these assets
carry, and CC0 carries none. "Free to download" is not the same thing and was
not accepted -- each pack's licence was read on its Kenney page *and* in the
`License.txt` it ships, and `scripts/fetch_tutorial_assets.sh` re-checks both on
every refresh and refuses to vendor a pack that fails either.

`LICENSE` is the CC0 1.0 legal code. The three `LICENSE.kenney_*.txt` files are
the licence statements the packs themselves ship, kept beside the art in the
same way `tests/assets/akgl_test_mono.LICENSE.txt` sits beside its font.

The two tables below account for all 56 asset files: 14 carry upstream bytes and
42 were written here. This file and `README.md` are the remaining two, and are
documentation of the same kind as the rest of `docs/`.

## Upstream packs

| Pack                  | URL                                            | Licence | Licence file in this tree                  |
|-----------------------|------------------------------------------------|---------|--------------------------------------------|
| Pixel Line Platformer | https://kenney.nl/assets/pixel-line-platformer | CC0 1.0 | `LICENSE.kenney_pixel-line-platformer.txt` |
| RPG Urban Pack        | https://kenney.nl/assets/rpg-urban-pack        | CC0 1.0 | `LICENSE.kenney_rpg-urban-pack.txt`        |
| Music Jingles         | https://kenney.nl/assets/music-jingles         | CC0 1.0 | `LICENSE.kenney_music-jingles.txt`         |

Kenney asks for credit and does not require it. Credit is given here and in the
tutorial chapters.

## Files carrying upstream bytes

| File                                       | Pack                  | Source URL                                                      | Licence | Cropped / repacked into                                                                            |
|--------------------------------------------|-----------------------|-----------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------|
| `LICENSE`                                  | creativecommons.org   | https://creativecommons.org/publicdomain/zero/1.0/legalcode.txt | CC0 1.0 | The CC0 1.0 Universal legal code, fetched verbatim                                                 |
| `LICENSE.kenney_pixel-line-platformer.txt` | Pixel Line Platformer | https://kenney.nl/assets/pixel-line-platformer                  | CC0 1.0 | The pack's own `License.txt`, copied verbatim                                                      |
| `LICENSE.kenney_rpg-urban-pack.txt`        | RPG Urban Pack        | https://kenney.nl/assets/rpg-urban-pack                         | CC0 1.0 | The pack's own `License.txt`, copied verbatim                                                      |
| `LICENSE.kenney_music-jingles.txt`         | Music Jingles         | https://kenney.nl/assets/music-jingles                          | CC0 1.0 | The pack's own `License.txt`, copied verbatim                                                      |
| `sidescroller/tiles.png`                   | Pixel Line Platformer | https://kenney.nl/assets/pixel-line-platformer                  | CC0 1.0 | `Tilemap/tilemap_packed.png` copied verbatim: 160x96, 10x6 tiles of 16x16, no spacing, no margin   |
| `sidescroller/player.png`                  | Pixel Line Platformer | https://kenney.nl/assets/pixel-line-platformer                  | CC0 1.0 | Tiles 40, 41, 42 and their horizontal mirrors, bottom-centred in six 32x32 cells                   |
| `sidescroller/coin.png`                    | Pixel Line Platformer | https://kenney.nl/assets/pixel-line-platformer                  | CC0 1.0 | Tile 44, bottom-centred in one 32x32 cell                                                          |
| `sidescroller/hazard.png`                  | Pixel Line Platformer | https://kenney.nl/assets/pixel-line-platformer                  | CC0 1.0 | Tiles 55, 56, 51, 52, bottom-centred in four 32x32 cells                                           |
| `sidescroller/jingle_start.ogg`            | Music Jingles         | https://kenney.nl/assets/music-jingles                          | CC0 1.0 | `Audio/8-Bit jingles/jingles_NES00.ogg`, copied verbatim (1.8 s)                                   |
| `jrpg/tiles.png`                           | RPG Urban Pack        | https://kenney.nl/assets/rpg-urban-pack                         | CC0 1.0 | `Tilemap/tilemap_packed.png` copied verbatim: 432x288, 27x18 tiles of 16x16, no spacing, no margin |
| `jrpg/player.png`                          | RPG Urban Pack        | https://kenney.nl/assets/rpg-urban-pack                         | CC0 1.0 | Character block 0 (tileset columns 23-26, rows 0-2) regrouped into twelve 32x32 cells              |
| `jrpg/npc_shopkeeper.png`                  | RPG Urban Pack        | https://kenney.nl/assets/rpg-urban-pack                         | CC0 1.0 | Character block 3 (tileset columns 23-26, rows 9-11) regrouped into twelve 32x32 cells             |
| `jrpg/npc_elder.png`                       | RPG Urban Pack        | https://kenney.nl/assets/rpg-urban-pack                         | CC0 1.0 | Character block 2 (tileset columns 23-26, rows 6-8) regrouped into twelve 32x32 cells              |
| `jrpg/jingle_start.ogg`                    | Music Jingles         | https://kenney.nl/assets/music-jingles                          | CC0 1.0 | `Audio/Pizzicato jingles/jingles_PIZZI07.ogg`, copied verbatim (1.3 s)                             |

## Files written for this repository

These contain no upstream content. They are libakgl source in JSON form: they
name the art above, they do not embed it.

| File                                            | Kind      | What it is                                                                      |
|-------------------------------------------------|-----------|---------------------------------------------------------------------------------|
| `jrpg/character_jrpg_elder.json`                | character | State-name to sprite-name bindings; contains no upstream content                |
| `jrpg/character_jrpg_player.json`               | character | State-name to sprite-name bindings; contains no upstream content                |
| `jrpg/character_jrpg_shopkeeper.json`           | character | State-name to sprite-name bindings; contains no upstream content                |
| `jrpg/sprite_jrpg_elder_idle_down.json`         | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_elder_idle_left.json`         | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_elder_idle_right.json`        | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_elder_idle_up.json`           | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_elder_walk_down.json`         | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_elder_walk_left.json`         | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_elder_walk_right.json`        | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_elder_walk_up.json`           | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_player_idle_down.json`        | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_player_idle_left.json`        | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_player_idle_right.json`       | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_player_idle_up.json`          | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_player_walk_down.json`        | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_player_walk_left.json`        | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_player_walk_right.json`       | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_player_walk_up.json`          | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_shopkeeper_idle_down.json`    | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_shopkeeper_idle_left.json`    | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_shopkeeper_idle_right.json`   | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_shopkeeper_idle_up.json`      | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_shopkeeper_walk_down.json`    | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_shopkeeper_walk_left.json`    | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_shopkeeper_walk_right.json`   | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/sprite_jrpg_shopkeeper_walk_up.json`      | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `jrpg/town.tmj`                                 | map       | Tiled 1.8 TMJ, tileset **embedded**. 30x20 cells, ground + decoration + actors  |
| `sidescroller/character_ss_coin.json`           | character | State-name to sprite-name bindings; contains no upstream content                |
| `sidescroller/character_ss_hazard_blob.json`    | character | State-name to sprite-name bindings; contains no upstream content                |
| `sidescroller/character_ss_hazard_moth.json`    | character | State-name to sprite-name bindings; contains no upstream content                |
| `sidescroller/character_ss_player.json`         | character | State-name to sprite-name bindings; contains no upstream content                |
| `sidescroller/level1.tmj`                       | map       | Tiled 1.8 TMJ, tileset **embedded**. 40x15 cells, background + terrain + actors |
| `sidescroller/sprite_ss_coin.json`              | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `sidescroller/sprite_ss_hazard_blob.json`       | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `sidescroller/sprite_ss_hazard_moth.json`       | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `sidescroller/sprite_ss_player_idle_left.json`  | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `sidescroller/sprite_ss_player_idle_right.json` | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `sidescroller/sprite_ss_player_jump_left.json`  | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `sidescroller/sprite_ss_player_jump_right.json` | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `sidescroller/sprite_ss_player_run_left.json`   | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |
| `sidescroller/sprite_ss_player_run_right.json`  | sprite    | Frame list into the sheet named by its own `spritesheet.filename`               |

## How the repacking works, and why

**Tilesets are copied verbatim.** Both packs already ship a 16x16 grid with zero
spacing and zero margin, which is the only geometry
`akgl_tilemap_compute_tileset_offsets` gets right -- it adds `spacing` to the
tile pitch but sets the *first* row's y offset to `spacing` rather than zero,
and it ignores `margin` completely. A packed sheet with a 1 px gutter, which is
what most of Kenney's older packs ship, would render every tile in row 0 one
pixel low. That ruled several otherwise-suitable packs out.

**Character sheets are repacked into one row of 32x32 cells.** The asset
contract for these tutorials is 16x16 tiles and 32x32 character frames, and
neither pack ships 32x32 art, so each 16x16 source tile is composited at (8, 16)
inside its cell -- horizontally centred, sitting on the cell's bottom edge. The
art is not resampled: a 2x upscale would put 2x2 pixel blocks next to 1x1 tiles,
and every sprite in the repository would stop matching the source pixel for
pixel. The cost is that three quarters of each cell is empty, and the benefit is
one rule the tutorials can rely on: **an actor drawn into a 32x32 destination
rectangle has its feet on the bottom edge of that rectangle and its body
centred**, whichever sheet it came from.

**Left-facing frames are stored, not mirrored at draw time.**
`akgl_actor_render` calls `draw_texture` with `SDL_FLIP_NONE` hard-coded
(`src/actor.c`), so there is no way to ask for a mirrored blit. The sidescroller
sheet therefore carries frames 0-2 facing right and frames 3-5 as their
horizontal mirrors. The JRPG sheets need no mirroring: the RPG Urban Pack draws
both side views.

**One frame is used twice.** Pixel Line Platformer has no dedicated jump pose.
Frame 1 is the passing position of the run cycle, which is the airborne one, and
`ss_player_jump_right` reuses it. Said here rather than left for a reader to
notice.

**The coin does not animate.** Pixel Line Platformer ships one gold pickup tile
and no rotation frames, so `sprite_ss_coin.json` is a single frame. Nothing was
invented to pad it out.

## Reproducing this

```sh
scripts/fetch_tutorial_assets.sh
```

Fetches all three packs, checks each page and each shipped `License.txt` says
CC0, verifies the source images are the size the frame arithmetic assumes,
repacks into a temporary directory, checks every staged file's dimensions, and
only then moves anything into place. A failure at any step leaves the tracked
copies untouched and exits non-zero. The output is byte-for-byte reproducible --
ImageMagick's wall-clock `date:create` and `date:modify` chunks are stripped, so
a refresh that changes nothing produces no diff.

The script does not touch the JSON or the TMJ maps. Those are hand-maintained.
