pixling 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. pixling-0.1.0/.claude/skills/pixling/SKILL.md +80 -0
  2. pixling-0.1.0/.gitignore +28 -0
  3. pixling-0.1.0/LICENSE +21 -0
  4. pixling-0.1.0/PKG-INFO +105 -0
  5. pixling-0.1.0/README.md +85 -0
  6. pixling-0.1.0/docs/ARTIST.md +256 -0
  7. pixling-0.1.0/docs/ENVIRONMENTS.md +30 -0
  8. pixling-0.1.0/docs/PIPELINES.md +258 -0
  9. pixling-0.1.0/docs/STYLES.md +137 -0
  10. pixling-0.1.0/docs/WORKFLOW.md +40 -0
  11. pixling-0.1.0/docs/brand/README.md +65 -0
  12. pixling-0.1.0/docs/brand/favicon-16.png +0 -0
  13. pixling-0.1.0/docs/brand/favicon-32.png +0 -0
  14. pixling-0.1.0/docs/brand/favicon-64.png +0 -0
  15. pixling-0.1.0/docs/brand/fonts/DepartureMono-Regular.otf +0 -0
  16. pixling-0.1.0/docs/brand/fonts/DepartureMono-Regular.woff2 +0 -0
  17. pixling-0.1.0/docs/brand/fonts/Jersey15-OFL.txt +93 -0
  18. pixling-0.1.0/docs/brand/fonts/Jersey15-Regular.ttf +0 -0
  19. pixling-0.1.0/docs/brand/fonts/OFL.txt +93 -0
  20. pixling-0.1.0/docs/brand/pixling-app-icon.png +0 -0
  21. pixling-0.1.0/docs/brand/pixling-banner-dark.png +0 -0
  22. pixling-0.1.0/docs/brand/pixling-banner-dark.svg +1 -0
  23. pixling-0.1.0/docs/brand/pixling-banner.png +0 -0
  24. pixling-0.1.0/docs/brand/pixling-banner.svg +1 -0
  25. pixling-0.1.0/docs/brand/pixling-forge-duckling.png +0 -0
  26. pixling-0.1.0/docs/brand/pixling-idle.gif +0 -0
  27. pixling-0.1.0/docs/brand/pixling-logo-dark.png +0 -0
  28. pixling-0.1.0/docs/brand/pixling-logo-dark.svg +1 -0
  29. pixling-0.1.0/docs/brand/pixling-logo.png +0 -0
  30. pixling-0.1.0/docs/brand/pixling-logo.svg +1 -0
  31. pixling-0.1.0/docs/brand/pixling-mark-1x.png +0 -0
  32. pixling-0.1.0/docs/brand/pixling-mark-idle.gif +0 -0
  33. pixling-0.1.0/docs/brand/pixling-mark-plain.svg +1 -0
  34. pixling-0.1.0/docs/brand/pixling-mark.png +0 -0
  35. pixling-0.1.0/docs/brand/pixling-mark.svg +1 -0
  36. pixling-0.1.0/docs/brand/pixling-paint.gif +0 -0
  37. pixling-0.1.0/docs/brand/pixling-social.png +0 -0
  38. pixling-0.1.0/docs/brand/pixling-sprite.png +0 -0
  39. pixling-0.1.0/docs/brand/pixling-walk.gif +0 -0
  40. pixling-0.1.0/npm/README.md +12 -0
  41. pixling-0.1.0/painted/README.md +96 -0
  42. pixling-0.1.0/painted/__init__.py +2 -0
  43. pixling-0.1.0/painted/__main__.py +219 -0
  44. pixling-0.1.0/painted/bpy/assets.py +530 -0
  45. pixling-0.1.0/painted/bpy/hilltop.py +401 -0
  46. pixling-0.1.0/painted/bpy/kit.py +186 -0
  47. pixling-0.1.0/painted/bpy/painter.py +439 -0
  48. pixling-0.1.0/painted/build_game.py +125 -0
  49. pixling-0.1.0/painted/compose.py +108 -0
  50. pixling-0.1.0/painted/game.html +310 -0
  51. pixling-0.1.0/painted/layouts/hollow_brook.json +61 -0
  52. pixling-0.1.0/painted/styles/painted_cards.json +59 -0
  53. pixling-0.1.0/painted/textures.py +104 -0
  54. pixling-0.1.0/pp/__init__.py +7 -0
  55. pixling-0.1.0/pp/__main__.py +230 -0
  56. pixling-0.1.0/pp/anim.py +790 -0
  57. pixling-0.1.0/pp/aseprite.py +80 -0
  58. pixling-0.1.0/pp/blocks.py +354 -0
  59. pixling-0.1.0/pp/brand.py +80 -0
  60. pixling-0.1.0/pp/cli.py +718 -0
  61. pixling-0.1.0/pp/color.py +161 -0
  62. pixling-0.1.0/pp/detail.py +247 -0
  63. pixling-0.1.0/pp/flora.py +150 -0
  64. pixling-0.1.0/pp/forge.py +763 -0
  65. pixling-0.1.0/pp/inspect.py +225 -0
  66. pixling-0.1.0/pp/io.py +70 -0
  67. pixling-0.1.0/pp/iso.py +570 -0
  68. pixling-0.1.0/pp/iso_line.py +149 -0
  69. pixling-0.1.0/pp/layers.py +181 -0
  70. pixling-0.1.0/pp/light.py +233 -0
  71. pixling-0.1.0/pp/lint.py +213 -0
  72. pixling-0.1.0/pp/map.py +1320 -0
  73. pixling-0.1.0/pp/meaning.py +168 -0
  74. pixling-0.1.0/pp/motion.py +719 -0
  75. pixling-0.1.0/pp/pack.py +85 -0
  76. pixling-0.1.0/pp/paths.py +17 -0
  77. pixling-0.1.0/pp/pixcheck.py +57 -0
  78. pixling-0.1.0/pp/render.py +368 -0
  79. pixling-0.1.0/pp/review.py +87 -0
  80. pixling-0.1.0/pp/scenario/__init__.py +193 -0
  81. pixling-0.1.0/pp/scenario/auth.py +291 -0
  82. pixling-0.1.0/pp/scenario/mcp.py +131 -0
  83. pixling-0.1.0/pp/scene.py +161 -0
  84. pixling-0.1.0/pp/sdf.py +154 -0
  85. pixling-0.1.0/pp/secondary.py +78 -0
  86. pixling-0.1.0/pp/shade.py +348 -0
  87. pixling-0.1.0/pp/size.py +158 -0
  88. pixling-0.1.0/pp/states.py +239 -0
  89. pixling-0.1.0/pp/variants.py +229 -0
  90. pixling-0.1.0/pp/vfx.py +528 -0
  91. pixling-0.1.0/pyproject.toml +80 -0
  92. pixling-0.1.0/reel/README.md +138 -0
  93. pixling-0.1.0/reel/WORKFLOW.md +115 -0
  94. pixling-0.1.0/reel/__init__.py +0 -0
  95. pixling-0.1.0/reel/__main__.py +89 -0
  96. pixling-0.1.0/reel/chars/_template/char.json +96 -0
  97. pixling-0.1.0/reel/cut.py +179 -0
  98. pixling-0.1.0/reel/demo.py +167 -0
  99. pixling-0.1.0/reel/finish.py +141 -0
  100. pixling-0.1.0/reel/fx/black_1024.png +0 -0
  101. pixling-0.1.0/reel/fx/fireball_rain.json +29 -0
  102. pixling-0.1.0/reel/fx/necro_signet.json +24 -0
  103. pixling-0.1.0/reel/fx.py +137 -0
  104. pixling-0.1.0/reel/game.py +290 -0
  105. pixling-0.1.0/reel/io.py +81 -0
  106. pixling-0.1.0/reel/key.py +145 -0
  107. pixling-0.1.0/reel/keys.py +189 -0
  108. pixling-0.1.0/reel/pack.py +33 -0
  109. pixling-0.1.0/reel/page.py +130 -0
  110. pixling-0.1.0/reel/qc.py +249 -0
  111. pixling-0.1.0/reel/split.py +83 -0
  112. pixling-0.1.0/reel/synth.py +49 -0
  113. pixling-0.1.0/reel/take.py +44 -0
  114. pixling-0.1.0/research/motion/NOTES.md +61 -0
  115. pixling-0.1.0/research/reel/NOTES.md +107 -0
  116. pixling-0.1.0/research/reel/SCENARIO_SKILL.md +591 -0
  117. pixling-0.1.0/research/styles/README.md +17 -0
  118. pixling-0.1.0/research/styles/SHARED_LAYER.md +74 -0
  119. pixling-0.1.0/research/styles/img/flat_v1_v2.png +0 -0
  120. pixling-0.1.0/research/styles/img/marsh_compare.jpg +0 -0
  121. pixling-0.1.0/research/styles/img/round1_compare.jpg +0 -0
  122. pixling-0.1.0/research/styles/img/round3_board.jpg +0 -0
  123. pixling-0.1.0/research/styles/img/saffron_compare.jpg +0 -0
  124. pixling-0.1.0/research/styles/img/tactics_before_after_8x.png +0 -0
  125. pixling-0.1.0/research/styles/proto_flat_v2.md +71 -0
  126. pixling-0.1.0/research/styles/proto_frost_flat_v1.md +101 -0
  127. pixling-0.1.0/research/styles/proto_marsh.md +90 -0
  128. pixling-0.1.0/research/styles/proto_saffron.md +96 -0
  129. pixling-0.1.0/research/styles/proto_tactics_v2.md +83 -0
  130. pixling-0.1.0/research/styles/round1_FINDINGS.md +38 -0
  131. pixling-0.1.0/research/styles/round2_DNA.md +208 -0
  132. pixling-0.1.0/research/styles/round3_NOTES.md +38 -0
  133. pixling-0.1.0/site/README.md +17 -0
  134. pixling-0.1.0/specs/blocks/ashwyrm.json +75 -0
  135. pixling-0.1.0/specs/blocks/bibi.json +42 -0
  136. pixling-0.1.0/specs/blocks/bramblehorn.json +43 -0
  137. pixling-0.1.0/specs/blocks/hoot.json +62 -0
  138. pixling-0.1.0/specs/blocks/pip.json +47 -0
  139. pixling-0.1.0/specs/blocks/sludgeling.json +38 -0
  140. pixling-0.1.0/specs/duskborne/ashen_knight.json +1420 -0
  141. pixling-0.1.0/specs/duskborne/bone_grunt.json +767 -0
  142. pixling-0.1.0/specs/duskborne/dusk_rock.json +200 -0
  143. pixling-0.1.0/specs/duskborne/dusk_tree.json +424 -0
  144. pixling-0.1.0/specs/duskborne/grave_ghoul.json +2409 -0
  145. pixling-0.1.0/specs/duskborne/hollow_cultist.json +1559 -0
  146. pixling-0.1.0/specs/duskborne/shade_wolf.json +1234 -0
  147. pixling-0.1.0/specs/sunmeadow/boar.json +577 -0
  148. pixling-0.1.0/specs/sunmeadow/bush.json +537 -0
  149. pixling-0.1.0/specs/sunmeadow/bush_berry.json +577 -0
  150. pixling-0.1.0/specs/sunmeadow/dead_tree.json +456 -0
  151. pixling-0.1.0/specs/sunmeadow/deer.json +788 -0
  152. pixling-0.1.0/specs/sunmeadow/elder.json +803 -0
  153. pixling-0.1.0/specs/sunmeadow/fox.json +472 -0
  154. pixling-0.1.0/specs/sunmeadow/hero.json +1553 -0
  155. pixling-0.1.0/specs/sunmeadow/oak.json +1 -0
  156. pixling-0.1.0/specs/sunmeadow/oak_autumn.json +1 -0
  157. pixling-0.1.0/specs/sunmeadow/orc_warrior.json +852 -0
  158. pixling-0.1.0/specs/sunmeadow/pine.json +731 -0
  159. pixling-0.1.0/specs/sunmeadow/pixling.json +612 -0
  160. pixling-0.1.0/specs/sunmeadow/rabbit.json +403 -0
  161. pixling-0.1.0/specs/sunmeadow/ranger.json +1687 -0
  162. pixling-0.1.0/specs/sunmeadow/rock.json +155 -0
  163. pixling-0.1.0/specs/sunmeadow/rock_mossy.json +106 -0
  164. pixling-0.1.0/specs/sunmeadow/rock_small.json +107 -0
  165. pixling-0.1.0/specs/vermilion/antler_ward.json +579 -0
  166. pixling-0.1.0/specs/vermilion/cinder_imp.json +809 -0
  167. pixling-0.1.0/specs/vermilion/ember_brute.json +636 -0
  168. pixling-0.1.0/specs/vermilion/ember_tree.json +29 -0
  169. pixling-0.1.0/specs/vermilion/ink_stone.json +10 -0
  170. pixling-0.1.0/specs/vermilion/shrike_crier.json +722 -0
  171. pixling-0.1.0/specs/vista/chapel.json +206 -0
  172. pixling-0.1.0/specs/vista/fountain_small.json +109 -0
  173. pixling-0.1.0/specs/vista/highgate.map.json +903 -0
  174. pixling-0.1.0/specs/vista/highgate_hub.map.json +1829 -0
  175. pixling-0.1.0/specs/vista/highgate_streets.map.json +804 -0
  176. pixling-0.1.0/specs/vista/highgate_town.map.json +2194 -0
  177. pixling-0.1.0/specs/vista/house_1.json +167 -0
  178. pixling-0.1.0/specs/vista/house_2.json +188 -0
  179. pixling-0.1.0/specs/vista/house_3.json +230 -0
  180. pixling-0.1.0/specs/vista/house_4.json +209 -0
  181. pixling-0.1.0/specs/vista/house_5.json +167 -0
  182. pixling-0.1.0/specs/vista/house_6.json +188 -0
  183. pixling-0.1.0/specs/vista/house_7.json +146 -0
  184. pixling-0.1.0/specs/vista/house_8.json +251 -0
  185. pixling-0.1.0/specs/vista/keep.json +747 -0
  186. pixling-0.1.0/specs/vista/lighthouse.json +180 -0
  187. pixling-0.1.0/specs/vista/market.json +148 -0
  188. pixling-0.1.0/specs/vista/sailboat.json +133 -0
  189. pixling-0.1.0/specs/vista/streets/banner_pole_v.json +246 -0
  190. pixling-0.1.0/specs/vista/streets/st_arena.json +2592 -0
  191. pixling-0.1.0/specs/vista/streets/st_barrels.json +159 -0
  192. pixling-0.1.0/specs/vista/streets/st_boat.json +207 -0
  193. pixling-0.1.0/specs/vista/streets/st_bridge_ew.json +314 -0
  194. pixling-0.1.0/specs/vista/streets/st_cart.json +198 -0
  195. pixling-0.1.0/specs/vista/streets/st_fountain.json +290 -0
  196. pixling-0.1.0/specs/vista/streets/st_gate.json +521 -0
  197. pixling-0.1.0/specs/vista/streets/st_hall.json +976 -0
  198. pixling-0.1.0/specs/vista/streets/st_house_a.json +569 -0
  199. pixling-0.1.0/specs/vista/streets/st_house_b.json +566 -0
  200. pixling-0.1.0/specs/vista/streets/st_house_c.json +532 -0
  201. pixling-0.1.0/specs/vista/streets/st_house_d.json +511 -0
  202. pixling-0.1.0/specs/vista/streets/st_house_e.json +615 -0
  203. pixling-0.1.0/specs/vista/streets/st_house_f.json +509 -0
  204. pixling-0.1.0/specs/vista/streets/st_house_g.json +316 -0
  205. pixling-0.1.0/specs/vista/streets/st_house_h.json +730 -0
  206. pixling-0.1.0/specs/vista/streets/st_house_i.json +474 -0
  207. pixling-0.1.0/specs/vista/streets/st_house_j.json +385 -0
  208. pixling-0.1.0/specs/vista/streets/st_lamp.json +170 -0
  209. pixling-0.1.0/specs/vista/streets/st_lighthouse.json +183 -0
  210. pixling-0.1.0/specs/vista/streets/st_rowboat.json +190 -0
  211. pixling-0.1.0/specs/vista/streets/st_ship.json +378 -0
  212. pixling-0.1.0/specs/vista/streets/st_stall_gold.json +284 -0
  213. pixling-0.1.0/specs/vista/streets/st_stall_red.json +284 -0
  214. pixling-0.1.0/specs/vista/streets/st_stall_teal.json +284 -0
  215. pixling-0.1.0/specs/vista/streets/st_wall.json +271 -0
  216. pixling-0.1.0/specs/vista/streets/st_well.json +185 -0
  217. pixling-0.1.0/specs/vista/world/vale.map.json +2857 -0
  218. pixling-0.1.0/specs/vista/world/w_bandit_camp.json +338 -0
  219. pixling-0.1.0/specs/vista/world/w_banner.json +225 -0
  220. pixling-0.1.0/specs/vista/world/w_camp.json +220 -0
  221. pixling-0.1.0/specs/vista/world/w_crypt.json +324 -0
  222. pixling-0.1.0/specs/vista/world/w_goblin_warren.json +412 -0
  223. pixling-0.1.0/specs/vista/world/w_mine.json +318 -0
  224. pixling-0.1.0/specs/vista/world/w_portal.json +289 -0
  225. pixling-0.1.0/specs/vista/world/w_smuggler_cove.json +318 -0
  226. pixling-0.1.0/specs/vista/world/w_spire.json +350 -0
  227. pixling-0.1.0/specs/vista/world/w_windmill.json +247 -0
  228. pixling-0.1.0/specs/vista/world/w_wolf_den.json +284 -0
  229. pixling-0.1.0/styles/duskborne.json +453 -0
  230. pixling-0.1.0/styles/flat.json +94 -0
  231. pixling-0.1.0/styles/flat_dunes.json +94 -0
  232. pixling-0.1.0/styles/sunmeadow.json +519 -0
  233. pixling-0.1.0/styles/tactics.json +149 -0
  234. pixling-0.1.0/styles/tactics_autumn.json +149 -0
  235. pixling-0.1.0/styles/vermilion.json +215 -0
  236. pixling-0.1.0/styles/vista.json +329 -0
  237. pixling-0.1.0/tools/flat/build.py +90 -0
  238. pixling-0.1.0/tools/flat/kit.py +202 -0
  239. pixling-0.1.0/tools/flat/scenes.py +212 -0
  240. pixling-0.1.0/tools/make_styles.py +386 -0
  241. pixling-0.1.0/tools/tactics/build.py +79 -0
  242. pixling-0.1.0/tools/tactics/kit.py +354 -0
  243. pixling-0.1.0/tools/tactics/scenes.py +343 -0
  244. pixling-0.1.0/tools/vista/aerial.py +64 -0
  245. pixling-0.1.0/tools/vista/build.py +39 -0
  246. pixling-0.1.0/tools/vista/layout_hub.py +121 -0
  247. pixling-0.1.0/tools/vista/layout_streets.py +70 -0
  248. pixling-0.1.0/tools/vista/layout_town.py +130 -0
  249. pixling-0.1.0/tools/vista/layout_vale.py +124 -0
  250. pixling-0.1.0/tools/vista/slib.py +58 -0
  251. pixling-0.1.0/tools/vista/streets.py +179 -0
  252. pixling-0.1.0/tools/vista/vlib.py +50 -0
  253. pixling-0.1.0/tools/vista/world.py +116 -0
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: pixling
3
+ description: Make game art with code using pixling (the Pixel Perfect forge), a catalogue of pipelines, styles and taste notes. Pipelines: JSON spec -> 8-direction pixel sprites; exact-iso scenes from Python kits; living maps with states, hour light and a meaning layer; VFX sheets; AI image -> video -> keyed sprite frames (Scenario + reel); Blender -> painterly sprites. Each style ships with how it was made (hand, kit code, lab notes), so you can reuse it or build a new one. Use when asked for sprites, characters, creatures, trees, buildings, spell effects, a town or world map, an iso scene, a new art style, an itch.io pack, or AI image/video generation through Scenario.
4
+ ---
5
+
6
+ # Pixel Perfect (`pixling`)
7
+
8
+ You are the artist. You never paint pixels: you pick a pipeline, drive it with code (a JSON spec, a Python kit, a
9
+ Blender layout, video takes), and judge the images by eye. pixling is a catalogue. Run the pipelines as they are, or
10
+ read how they and the styles were made and take what helps into the user's own project. Run `pixling` for every command.
11
+
12
+ ## Pick a pipeline
13
+ - `pixling pipelines`: spec (sprites), iso (exact-iso scenes), map (living maps), fx, video (image -> video ->
14
+ frames), painted (Blender), style (a new style from scratch). `pixling pipelines NAME` gives the steps, the code
15
+ and what we learned.
16
+ - `pixling styles NAME --how`: how a launch style (vista, tactics, flat) was made: hand, kit, code, lab notes.
17
+ `pixling code tactics.kit` prints a kit module and its path, so you can read it whole or copy it.
18
+ - `pixling guide styles "The shared taste layer"`: the rules every style keeps. Apply them to your own work too.
19
+
20
+ ## Before the first asset (spec pipeline)
21
+ - `pixling doctor`: dependencies. If `pixling` is missing, use `python3 -m pp` from the Pixel Perfect repo.
22
+ - `pixling guide artist "The loop"` and `pixling guide artist "Spec format"`: how specs work. `pixling guide` lists every doc;
23
+ `pixling guide --grep WORD` searches them.
24
+ - `pixling styles` lists the styles; `pixling styles NAME` shows materials and ramps. Use the style's materials; never invent colours.
25
+ - `pixling specs STYLE`: copy the closest example spec and change it. Don't start from a blank file.
26
+
27
+ ## The loop (minutes per asset)
28
+ ```
29
+ pixling build SPEC --clips idle --dirs S,E # fast: only what you're judging
30
+ pixling review out/NAME --clips idle --dirs S,E # look at the PNG it prints
31
+ # fix the spec, rebuild, look again; then the full build:
32
+ pixling build SPEC
33
+ pixling scene out/NAME out/oak --style STYLE # next to its family and a tree, at game scale
34
+ pixling lint out/NAME # hints, not gates
35
+ ```
36
+ Use `--out DIR` on build to write into your own project. `pixling inspect SPEC` shows what's under the pixels
37
+ (bone/material maps); `pixling variants SPEC --vary key=a,b,c` builds versions side by side, and `--apply N` keeps one.
38
+
39
+ ## Rules
40
+ - Judge by looking at the images (your image-reading tool), at 1x in `scene` and animated. No measurement essays.
41
+ - Big shapes first, details last. Prototype ONE asset, get the user's sign-off, then make the family.
42
+ - Done: it reads at 1x next to its family, all 8 directions are the same character, the attack reads, nothing
43
+ swims in idle, and you can explain every lint WARN in one sentence.
44
+ - If the engine can't do something, say what's missing. Don't work around it with dozens of micro-parts.
45
+
46
+ ## Iso scenes (Crisp Tactics, Flat Minimal)
47
+ `pixling world tactics|flat [--only SCENE]` builds a style's scenes and animal sheets with its kit. For new scenes,
48
+ copy `tools/<style>/scenes.py` (path from `pixling code tactics.scenes`) and render with `pp.iso`; `pixling pipelines iso`.
49
+
50
+ ## Board pieces (units, creatures on an iso board)
51
+ `pixling pipelines blocks`. Build them as block tokens (`pixling blocks`): a few chunky voxels (3 x 3 footprint, 2-4
52
+ layers, ~12 px: a third of a tile) in the board's exact iso, face light and cast shadow, facings by rotation. Not
53
+ side-view sprites, not 3D-rendered animals. Keep them small and pull the camera back rather than growing them. Judge
54
+ them standing in the real scene (`--on SCREENSHOT_1x.png`), and never restyle the environment to fix the pieces.
55
+
56
+ ## Maps, states, light, VFX, packs
57
+ `pixling guide environments` and `pixling guide artist "Maps (pp.map)"`. Commands: `pixling map MAP.json --still`,
58
+ `pixling states SPEC`, `pixling light MAP.json --gif`, `pixling fx KIND --style S`, `pixling pack NAME DIRS --style S`.
59
+
60
+ ## Scenario (AI images, video, 3D, audio)
61
+ - Run `pixling scenario status`. If signed out, ask the user to run `! pixling scenario login` (it opens a browser; use
62
+ `--device` for a code to type on another device). Sign-in is once per machine; tokens refresh themselves.
63
+ - Discover models with `pixling scenario call recommend '{"query": "..."}'` or `pixling scenario call models_list '{"query": "..."}'`.
64
+ `pixling scenario tools` lists every tool, and `pixling scenario schema TOOL` shows its inputs.
65
+ - Before a run: `pixling scenario call model_schema_get '{"model_id": "M"}'`, then `pixling scenario cost M '{...}'`.
66
+ Tell the user the cost in CU and ask before spending beyond their budget.
67
+ - `pixling scenario run M '{...model inputs...}' --out file.png` waits for the job and downloads the outputs.
68
+ File inputs are asset ids: `pixling scenario upload FILE`.
69
+ - Video for sprites: `pixling guide reel-workflow`. Use MiniMax H3 only.
70
+
71
+ ## Painted format (not pixel art)
72
+ When the user wants a painterly look instead of pixels: `pixling guide painted`. Needs Blender (`pixling painted doctor`).
73
+ `pixling painted kit` renders a style + layout as sprites (shadow layers, sway loops, 8 headings) into
74
+ out/painted/<layout>/kit; `compose` lays the scene out from them; `game` packs a walkable web scene. Look at
75
+ `scene/kit_sheet.png` and `scene/scene.png` before showing anything. New assets are builders in painted/bpy/assets.py,
76
+ new colours are ramps in painted/styles/*.json, places are painted/layouts/*.json. Never mix pixel and painted sprites in one scene.
77
+
78
+ ## Reading the engine
79
+ `pixling code` lists the modules and `pixling code forge` shows one module's functions with their docstrings. Read the
80
+ source only when you need it.
@@ -0,0 +1,28 @@
1
+ out/
2
+ __pycache__/
3
+ *.pyc
4
+ *.mp4
5
+ *.zip
6
+ *.aseprite
7
+ research/**/_*/
8
+ packs/
9
+ viewer/
10
+
11
+ # local clutter
12
+ .DS_Store
13
+ .claude/*
14
+ !.claude/skills/
15
+ .env
16
+ # parked experiments kept local only: the toon/cutout/Blender study
17
+ research/toon/
18
+ # reel: big facing sheets stay local (the committed ref/start_<facing>.png are cut from them)
19
+ reel/chars/*/ref/sheet*.png
20
+
21
+ # local reference media
22
+ references/
23
+ *.egg-info/
24
+ dist/
25
+ build/
26
+
27
+ # private/: secrets never get committed (keep them in a password manager)
28
+ private/secrets/
pixling-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Trinity Labs Pte. Ltd.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
pixling-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,105 @@
1
+ Metadata-Version: 2.5
2
+ Name: pixling
3
+ Version: 0.1.0
4
+ Summary: The pixel artist for your coding agent: pipelines, styles and taste for making game sprites with code
5
+ Project-URL: Homepage, https://pixling.dev
6
+ Project-URL: Repository, https://github.com/trinity-works/pixling
7
+ License: MIT
8
+ License-File: LICENSE
9
+ Keywords: agents,claude-code,cli,codex,gamedev,pixel-art,procedural,sprites
10
+ Classifier: Environment :: Console
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Games/Entertainment
14
+ Classifier: Topic :: Multimedia :: Graphics
15
+ Requires-Python: >=3.9
16
+ Requires-Dist: numpy>=1.24
17
+ Requires-Dist: pillow>=10.0
18
+ Requires-Dist: scipy>=1.10
19
+ Description-Content-Type: text/markdown
20
+
21
+ <p align="center">
22
+ <picture>
23
+ <source media="(prefers-color-scheme: dark)" srcset="docs/brand/pixling-banner-dark.png">
24
+ <img src="docs/brand/pixling-banner.png" alt="pixling" width="560">
25
+ </picture>
26
+ </p>
27
+
28
+ <p align="center">
29
+ <b>The pixel artist for your coding agent.</b><br>
30
+ Pipelines, styles and taste for making game sprites with code. Works with Claude Code, Codex and Cursor.<br>
31
+ <a href="https://pixling.dev">pixling.dev</a>
32
+ </p>
33
+
34
+ <p align="center">
35
+ <img src="docs/img/tactics_valley.gif" alt="A Crisp Tactics valley rendered by pixling" width="720">
36
+ </p>
37
+
38
+ Coding agents can write your game, but they can't draw. pixling gives them pipelines that render real pixel art from
39
+ code, curated styles that ship with how they were made, and the taste rules behind them. The agent writes a spec,
40
+ builds it, looks at the result and iterates, the way it does with a failing test.
41
+
42
+ ## Install
43
+ ```bash
44
+ uv tool install pixling # or: pipx install pixling · or: npx pixling
45
+ pixling agent install . # in your game repo: adds the skill and an AGENTS.md block
46
+ ```
47
+ Then ask your agent:
48
+
49
+ > make a harbour town in the vista style, with lamps that light up at dusk, into assets/maps
50
+
51
+ ## Quickstart
52
+ ```bash
53
+ pixling new house_5 inn # start a spec from an example -> specs/inn.json
54
+ pixling build specs/inn.json # -> out/inn/: sprite sheets, GIFs, JSON
55
+ pixling review out/inn # a zoomed sheet to judge by eye
56
+ pixling # every command; each takes -h, the ones agents parse take --json
57
+ ```
58
+
59
+ ## Pipelines
60
+ | Pipeline | Makes |
61
+ |---|---|
62
+ | **spec** | 8-direction sprites, props and buildings from a JSON spec, byte-for-byte reproducible |
63
+ | **blocks** | small iso units and creatures from a few voxel layers, in your board's projection, light and shadow |
64
+ | **iso** | exact 2:1 isometric scenes and animal sheets from a Python kit |
65
+ | **map** | living maps: building states, hour-of-day lighting, a meaning layer, engine layers |
66
+ | **fx** | VFX sheets posterised to a style's palette |
67
+ | **video** | sprites cut from AI video into 8-direction sheets (via [Scenario](https://scenario.com), optional) |
68
+ | **painted** | painterly, non-pixel sprites and scenes rendered in Blender |
69
+ | **style** | a new art style from scratch: refs, hand, kit, review |
70
+
71
+ `pixling pipelines NAME` shows each one's steps, code and lessons. Output is engine-ready: sheets, GIFs, JSON metadata,
72
+ `.aseprite` files, and for maps collision, depth and light layers.
73
+
74
+ ## Styles
75
+ Three launch styles, each with its own hand (camera, shading, line, shadows) and kit. `pixling styles NAME --how`
76
+ shows how each was made.
77
+
78
+ | **Vista** | **Crisp Tactics** | **Flat Minimal** |
79
+ |---|---|---|
80
+ | <img src="docs/img/highgate_town.gif" alt="Vista town" width="260"> | <img src="docs/img/tactics_valley.gif" alt="Crisp Tactics valley" width="260"> | <img src="docs/img/flat_dunes.png" alt="Flat Minimal island" width="260"> |
81
+ | painted aerial towns and world maps | exact isometric, flat faces, soft line | exact isometric, two hues, long flat shadows |
82
+
83
+ Everything above is rendered by the engine. Units and creatures for these boards are block tokens
84
+ (`pixling blocks`): a few voxels in the board's own iso, light and shadow.
85
+
86
+ ## Docs
87
+ - [docs/PIPELINES.md](docs/PIPELINES.md): every pipeline, step by step
88
+ - [docs/ARTIST.md](docs/ARTIST.md): the spec format and design rules
89
+ - [docs/STYLES.md](docs/STYLES.md): the styles and how a new one is made
90
+ - [docs/ENVIRONMENTS.md](docs/ENVIRONMENTS.md): living maps
91
+
92
+ The same docs are built into the CLI: `pixling guide`.
93
+
94
+ ## Develop
95
+ ```bash
96
+ git clone https://github.com/trinity-works/pixling && cd pixling
97
+ pip install -e .
98
+ python3 -m unittest discover -s tests # the video tests need ffmpeg
99
+ ```
100
+ Rules for agents working on the engine are in [AGENTS.md](AGENTS.md). Issues and pull requests are welcome.
101
+
102
+ ## License
103
+ [MIT](LICENSE). Fonts in `docs/brand/fonts` and `site/fonts` are under the SIL Open Font License: wordmark in
104
+ [Jersey 15](https://github.com/scfried/soft-type-jersey) by the Soft Type Project, tagline in
105
+ [Departure Mono](https://departuremono.com) by Helena Zhang, site in Geist.
@@ -0,0 +1,85 @@
1
+ <p align="center">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="docs/brand/pixling-banner-dark.png">
4
+ <img src="docs/brand/pixling-banner.png" alt="pixling" width="560">
5
+ </picture>
6
+ </p>
7
+
8
+ <p align="center">
9
+ <b>The pixel artist for your coding agent.</b><br>
10
+ Pipelines, styles and taste for making game sprites with code. Works with Claude Code, Codex and Cursor.<br>
11
+ <a href="https://pixling.dev">pixling.dev</a>
12
+ </p>
13
+
14
+ <p align="center">
15
+ <img src="docs/img/tactics_valley.gif" alt="A Crisp Tactics valley rendered by pixling" width="720">
16
+ </p>
17
+
18
+ Coding agents can write your game, but they can't draw. pixling gives them pipelines that render real pixel art from
19
+ code, curated styles that ship with how they were made, and the taste rules behind them. The agent writes a spec,
20
+ builds it, looks at the result and iterates, the way it does with a failing test.
21
+
22
+ ## Install
23
+ ```bash
24
+ uv tool install pixling # or: pipx install pixling · or: npx pixling
25
+ pixling agent install . # in your game repo: adds the skill and an AGENTS.md block
26
+ ```
27
+ Then ask your agent:
28
+
29
+ > make a harbour town in the vista style, with lamps that light up at dusk, into assets/maps
30
+
31
+ ## Quickstart
32
+ ```bash
33
+ pixling new house_5 inn # start a spec from an example -> specs/inn.json
34
+ pixling build specs/inn.json # -> out/inn/: sprite sheets, GIFs, JSON
35
+ pixling review out/inn # a zoomed sheet to judge by eye
36
+ pixling # every command; each takes -h, the ones agents parse take --json
37
+ ```
38
+
39
+ ## Pipelines
40
+ | Pipeline | Makes |
41
+ |---|---|
42
+ | **spec** | 8-direction sprites, props and buildings from a JSON spec, byte-for-byte reproducible |
43
+ | **blocks** | small iso units and creatures from a few voxel layers, in your board's projection, light and shadow |
44
+ | **iso** | exact 2:1 isometric scenes and animal sheets from a Python kit |
45
+ | **map** | living maps: building states, hour-of-day lighting, a meaning layer, engine layers |
46
+ | **fx** | VFX sheets posterised to a style's palette |
47
+ | **video** | sprites cut from AI video into 8-direction sheets (via [Scenario](https://scenario.com), optional) |
48
+ | **painted** | painterly, non-pixel sprites and scenes rendered in Blender |
49
+ | **style** | a new art style from scratch: refs, hand, kit, review |
50
+
51
+ `pixling pipelines NAME` shows each one's steps, code and lessons. Output is engine-ready: sheets, GIFs, JSON metadata,
52
+ `.aseprite` files, and for maps collision, depth and light layers.
53
+
54
+ ## Styles
55
+ Three launch styles, each with its own hand (camera, shading, line, shadows) and kit. `pixling styles NAME --how`
56
+ shows how each was made.
57
+
58
+ | **Vista** | **Crisp Tactics** | **Flat Minimal** |
59
+ |---|---|---|
60
+ | <img src="docs/img/highgate_town.gif" alt="Vista town" width="260"> | <img src="docs/img/tactics_valley.gif" alt="Crisp Tactics valley" width="260"> | <img src="docs/img/flat_dunes.png" alt="Flat Minimal island" width="260"> |
61
+ | painted aerial towns and world maps | exact isometric, flat faces, soft line | exact isometric, two hues, long flat shadows |
62
+
63
+ Everything above is rendered by the engine. Units and creatures for these boards are block tokens
64
+ (`pixling blocks`): a few voxels in the board's own iso, light and shadow.
65
+
66
+ ## Docs
67
+ - [docs/PIPELINES.md](docs/PIPELINES.md): every pipeline, step by step
68
+ - [docs/ARTIST.md](docs/ARTIST.md): the spec format and design rules
69
+ - [docs/STYLES.md](docs/STYLES.md): the styles and how a new one is made
70
+ - [docs/ENVIRONMENTS.md](docs/ENVIRONMENTS.md): living maps
71
+
72
+ The same docs are built into the CLI: `pixling guide`.
73
+
74
+ ## Develop
75
+ ```bash
76
+ git clone https://github.com/trinity-works/pixling && cd pixling
77
+ pip install -e .
78
+ python3 -m unittest discover -s tests # the video tests need ffmpeg
79
+ ```
80
+ Rules for agents working on the engine are in [AGENTS.md](AGENTS.md). Issues and pull requests are welcome.
81
+
82
+ ## License
83
+ [MIT](LICENSE). Fonts in `docs/brand/fonts` and `site/fonts` are under the SIL Open Font License: wordmark in
84
+ [Jersey 15](https://github.com/scfried/soft-type-jersey) by the Soft Type Project, tagline in
85
+ [Departure Mono](https://departuremono.com) by Helena Zhang, site in Geist.
@@ -0,0 +1,256 @@
1
+ # ARTIST.md — how to make sprites with Pixel Perfect
2
+
3
+ You are the artist. You never paint pixels by hand. You **design** (concept, silhouette, proportions,
4
+ materials, motion feel) by writing a JSON spec, and the forge renders it into palette-locked,
5
+ 8-direction, pixel-stable sprite sheets. Then you **look** at the result, judge it like an art
6
+ director, and iterate. Target quality: sellable itch.io packs next to the best hand-made ones.
7
+ The launch styles, how a new style is made and the taste rules every style keeps: [docs/STYLES.md](STYLES.md).
8
+
9
+ ## The loop
10
+
11
+ ```
12
+ python3 -m pp build specs/<style>/<name>.json # -> out/<name>/ (sheets, gifs, json, contact.png)
13
+ python3 -m pp review out/<name> --clips idle,attack --dirs S,E,N --scale 5 # zoomed grid on the style's bg (--bg to override)
14
+ python3 -m pp scene out/<a> out/<b> out/oak --style <style> # side by side on the ground at game scale
15
+ python3 -m pp lint out/<a> out/<b> ... # short numeric hints + family silhouette overlap
16
+ python3 -m pp silhouettes out/<a> out/<b> ... # white-fill silhouette row (design check)
17
+ python3 -m pp inspect specs/<style>/<name>.json --clip attack --dir E --frame 7 # what's under the pixels (below)
18
+ python3 -m pp variants specs/<style>/<name>.json --vary anim.drag=0.6,1,1.5 --clips attack --dirs E # pick by eye
19
+ ```
20
+ Fast iteration: `--clips idle --dirs S,E` renders only what you're judging (seconds).
21
+ Look at images with your image-reading tool. **Judge by eye first; lints are hints, not gates.**
22
+ Don't write measurement reports. One look, one fix, rebuild.
23
+
24
+ ## Design process
25
+ 1. **Theme + family first.** A family shares palette, materials, eye/nose treatment, proportions.
26
+ Members differ by **one big defining feature** each (huge sword, slingshot, lantern, antlers, shield).
27
+ 2. **Silhouette first.** Build the big shapes only (1-3 parts per bone), check `pp silhouettes`.
28
+ Silhouettes in a family must read apart (IoU < 0.75). Exaggerate: big weapons, big heads, odd shapes.
29
+ 3. **Readability = gameplay.** Big = tanky/slow, small = quick, spiky = dangerous, round = friendly.
30
+ 4. **2-3 shades per part is plenty.** Tiny parts (hands, feet, ears) get 1-2 materials max.
31
+ 5. **Details last**: eyes, belt, trim, glow accents. One glowing accent per character (eyes, rune, lantern).
32
+ 6. **Zoom out.** Always check the `scene` view at 3-4x, not only the 5x review.
33
+ 7. **Attack first.** If the attack looks bad, the design is wrong — fix the design, not the animation.
34
+
35
+ ## Targets
36
+ - Humanoid **22-30 px** tall (hero ~26), boss 34-60, critters 8-14, quadrupeds 16-24 tall.
37
+ - Head **0.40-0.50** of height (chibi), or deliberately the opposite ("small head, big body" brutes).
38
+ - **8-20 colours** per sprite. No #000 / #fff. No semi-transparency (the forge guarantees this).
39
+ - No black outline: edges keep their fill, darken on the shadow side, rim-light on the light side (automatic).
40
+ - Separate touching parts by value (ΔL ≥ 0.08): don't put two mid-grey materials next to each other.
41
+ - Timing is automatic: one 75 ms frame; idle 8, walk 8, run 8, attack 13 (4 anticipation / 3 raise / 1 smear / 5 recovery),
42
+ hit 2 (recoil + flash), death 14, cast 12.
43
+
44
+ ## Spec format
45
+
46
+ ```jsonc
47
+ {
48
+ "name": "ashen_knight", "style": "duskborne", "rig": "humanoid", // or "quadruped", "prop"
49
+ "concept": "one line: who, role, defining feature",
50
+ "frame": [48, 48], "anchor": [24, 40], // canvas and the feet pixel. Leave room for smears (~2x body)
51
+ "shadow": {"w": 13, "h": 3}, // ground contact ellipse, never wider than the body+2
52
+ "smear": {"color": "#ebede9", "edge": "#6ff0f0", "radius": 13, "width": 6, "height": 8}, // weapon arc
53
+ "fx": {"ramp": "glow_pink", "hand_h": 14, "reach": 6}, // cast charge/burst colour + where hands are
54
+ "anim": {"props": ["scarf_tail"], "prop_swing": 8, "attack_lunge": 3, "idle_bob": 2, "run_bounce": 0.5,
55
+ "raise_weapon_rot": [45, 70, 0]}, // turn a small weapon toward the camera during the wind-up
56
+ "materials": {"my_mat": {"ramp": "cloth_red", "shades": [0, 1, 2, 3]}}, // optional extra materials
57
+ "clips": ["idle", "walk", "run", "attack", "hit", "death"], // optional subset
58
+ "bones": [ { "name": "root" },
59
+ { "name": "hips", "parent": "root", "at": [0, 0, 6], "parts": [ ...primitives... ] },
60
+ ... ]
61
+ }
62
+ ```
63
+ Units are **pixels**. Axes: **x right, y away from the viewer (character faces −y = south), z up**.
64
+ Feet are at z = 0. `at` on a bone = its joint position in the parent's space (rotation pivot).
65
+
66
+ **Primitives** (in the bone's local space): every part has `shape`, `mat`, optional `at`, `rot` [deg x,y,z], `blend` (smooth-merge radius).
67
+ - `ellipsoid`/`sphere` `r` (number or [rx, ry, rz]) — heads, bodies, clumps
68
+ - `capsule` `a`, `b`, `r1`, `r2` — limbs, tails, horns, branches (tapers)
69
+ - `box` `half` [hx, hy, hz], `round` — blades, belts, visors, armour plates
70
+ - `cylinder` `r`, `h` (half height), `round`; `cone` `r`, `h` (apex at +z; add `"flat": true` or `"r_top"` for a
71
+ flat-based cone / frustum — robes, hats, skirts, tree tiers) — hats, ears, spikes; `torus` `R`, `r` (flat ring) — collars, scarves
72
+ - `roof` `half` [hx, hy], `h` (ridge height), `gable` (bool): a pitched roof on a flat base; hip roof (pyramid on a square), or vertical gable ends.
73
+ - `"subtract": true` carves the part out of the bone.
74
+ - `stamp` — exact hand-placed pixels pinned to the bone (faces, teeth, glints, runes, buttons). Not 3D:
75
+ `{"shape": "stamp", "at": [x,y,z], "normal": [0,-1,0], "rows": ["a.a", ".b."], "key": {"a": "pupil", "b": "bone:3"}}`
76
+ Drawn centred on the projected point when the normal faces the viewer (`min_facing`, default 0.2) and not behind a
77
+ nearer part. `.` = transparent. Key values are `material` (its brightest shade) or `material:shade`. For 3/4 views give
78
+ each eye its own stamp with a normal tilted outward (e.g. [-0.5,-1,0] / [0.5,-1,0]) so the far eye hides by itself.
79
+ For profile views lower `min_facing` (e.g. 0.05) and add `"clamp": 2` so a stamp that lands just outside the
80
+ silhouette slides inward onto the head instead of vanishing.
81
+ - `stamp_row` — a row of stamps along a wall (windows, a door), laid out on the face as drawn instead of as separate
82
+ 3D points: `{"shape": "stamp_row", "normal": [0,-1,0], "at": [0,0,z], "count": 6, "rows": ["a"], "key": {"a": "window"}}`
83
+ One whole-pixel pitch between `margin` px (default 1) from the face's edges; windows are dropped rather than packed
84
+ closer than `min_pitch` (3); each sits z px above the face's drawn bottom edge in its own column, so a row runs
85
+ parallel to that edge and floors line up in columns. Skips pixels off the face (under an eave) and keeps
86
+ `keep_clear` px (1) from earlier rows: put the door first. `tools/vista/vlib.facade` writes these.
87
+
88
+ **Pixel-scale modelling rules**
89
+ - Nothing thinner than **1.2 px radius** (it disappears or flickers between frames). Eyes: r ≥ 0.6 and push them 0.3-0.6 px *out of* the face surface.
90
+ - Each bone is a rigid layer: **it keeps identical pixels while it only moves** — that's the anti-swim guarantee.
91
+ So put things that should move together on one bone, and parts that should overlap with a visible seam on different bones
92
+ (the forge draws a dark inner line where a nearer bone overlaps a farther one).
93
+ - Front details face **−y**. Put the lit side's interest on the upper-left (light comes from the upper left, front).
94
+ - Weapons: a `sword`/`weapon` bone parented to `armR` at the hand. It is auto-hidden on the smear frame.
95
+ - bone `"hidden": true` — only drawn on frames that list it in `"show": ["arrow"]` (custom clip frames): arrows,
96
+ thrown knives, spell orbs. A `sweep` on a bone that moves along its own axis (a loosed arrow, a thrust: pose the
97
+ bone's `at` far ahead on the release frame) draws a straight comet streak instead of an arc.
98
+ - spec `"strings"`: 1 px lines between bone points (bowstrings, ropes, chains), hidden behind nearer parts:
99
+ `[{"name": "bowstring", "points": [["bow", [0,1.5,10]], ["bow", [0,1.5,-10]]], "pull": ["foreR", [0,0,-3.3]],
100
+ "mat": "shirt:3"}]`. Frames that `"show"` the string's name bend it through `pull` (a drawn bow).
101
+ - Archer draw (specs/sunmeadow/ranger.json): body side-on (hips rz ~70), bow arm aimed straight at the target,
102
+ bow `aim` [0,1,0] + `roll` -90 (upright), draw shoulder pulled in (`armR.at`), elbow high, hand at the cheek.
103
+
104
+ **Bone & spec options (engine v2)**
105
+ - bone `"seam": true` — always draw a dark seam + contact shadow where this bone overlaps another (tiers, plates, layered cloth).
106
+ - bone `"z_bias": -2` — pull a bone toward the viewer in depth sorting (e.g. a small weapon that hides behind a big hat).
107
+ - material `"sky": 0.3` / `"sky_obj": 0.2` — tops of each part / of the whole object lighter, undersides darker
108
+ (crowns, bushes, fur backs). `"bias"` shifts all light; `"thresholds"` sets shade bands per material.
109
+ - spec `"view": {"yaw": {"S": 14, "N": 14}, "widen": {"S": 1.15, "N": 1.15}}` — cheat front/back views like pixel
110
+ artists do: turn a few degrees to show the body side, and widen on screen so long animals don't become columns.
111
+ - flora params: `tree_round` trunk_frac, trunk_r; `tree_pine` tips, droop; `bush` berry_r.
112
+
113
+ **Detail materials** (the fix for "too round"): add to a material
114
+ `"detail": {"kind": "fur|feather|cloth|plate|scale|leaf|bark|stone|hide", "scale": 1.0, "amount": 1.0}` for a surface
115
+ pattern (fur strands, feather scallops, cloth folds, plate seams with rivet glints, leaf clusters, bark and stone cracks,
116
+ hide wrinkles) and `"edge": {"kind": "fur|feather|leaf", "amount": 0.35}` for a broken silhouette (tufts, notches).
117
+ Patterns are painted in the part's own space, so they stick to it and stay pixel-stable while it moves. The duskborne,
118
+ sunmeadow style materials already carry sensible defaults; set `"detail": null` in a spec material to turn one off.
119
+ Optional carved shading: spec `"shading": {"facets": 14 | 26, "crease": 0.35}` (flat planes + crease lines).
120
+
121
+ **Rigs & required bone names**
122
+ - `humanoid`: `root > hips > torso > head`, `torso > armL, armR`, `hips > legL, legR`. Optional anything else (props list swings 2x).
123
+ Arms hang along −z from the shoulder; legs along −z from the hip.
124
+ Optional elbows: `foreL`/`foreR` bones parented to `armL`/`armR` at the elbow (hand + weapon go on the fore bone);
125
+ the built-in clips bend them automatically.
126
+ - `quadruped`: `root > body > head (> jaw, ears)`, `body > legFL, legFR, legHL, legHR, tail`. Body length along y (head at −y).
127
+ Clips: idle, walk, run, attack (leap-bite), hit, death.
128
+ - `prop`: use `"generator": "tree_round" | "tree_pine" | "bush" | "rock" | "dead_tree"` with `"params"` (see pp/flora.py),
129
+ or write bones yourself with `"rig": "prop"` and `"directions": ["S"]`.
130
+
131
+ **Smear options** (spec `smear` or per fx event): `"plane": "h"` (horizontal sweep) or `"v"` (overhead chop),
132
+ `"tilt"` degrees (diagonal), `"side"` lateral offset of a vertical arc, `"forward"` push the arc centre forward, per-event `a0`/`a1`/`thick` to shape the arc.
133
+
134
+ **In-sprite VFX**: any standalone effect can play inside a clip, one effect frame per sprite frame:
135
+ `{"kind": "vfx", "effect": "shockwave", "frame": 2, "at": "front|hand|feet|centre|above", "offset": [dx, dy],
136
+ "ramp": "stone", "params": {...}, "pivot_y": 0.6, "behind": true}` (behind = drawn under the body).
137
+
138
+ **Custom clips**: `"custom_clips": {"name": {"loop": false, "frames": [{"pose": {"armR": {"rot": [-90,0,0]}}, "hold": 2,
139
+ "squash": [1.1, 0.8], "root": [0,-2,0], "fx": [{"kind": "smear", "arc": "wide"}], "hide": ["sword"], "flash": false}]}}`
140
+ — pose values are offsets from the rest pose. `"away": true` on a frame keeps a backward fall readable: it rolls
141
+ sideways in S/N and falls face-down away from the camera in NE/NW (the built-in death does this, and slides
142
+ the feet forward `death_slide` px, default 0.4 x body height, so the body lies inside the frame). Add the clip name to `clips`.
143
+
144
+ ## Size and 2D-HD maps
145
+ - **`"size"`** in a spec: `"tiny"` 14, `"small"` 22, `"medium"` 32, `"large"` 44, `"huge"` 58 (visible rest height in
146
+ px; a ~30 px humanoid hero is about medium) or `{"height": px}`. A style may override the table with `"sizes"`.
147
+ The forge scales the whole spec (lengths and the style's motion lengths, never angles/timing/colours), refits the
148
+ frame, and writes `height_px` / `width_px` / `size` into the build json. Author at any size, declare the size.
149
+ Check a family with `pp sizes <builds...>` (sorted lineup with class rulers); `pp lint` flags classes out of order.
150
+ - **`"maps": ["normal", "height"]`** (or `pp build --maps normal,height`) writes `<name>_<clip>_normal.png`
151
+ (RGB = world normal * 0.5 + 0.5; x right, y away, z up) and `_height.png` (grey = px above the feet x
152
+ `height_scale`) beside each sheet, same layout, alpha only on the model's pixels. For real-time lighting in a game
153
+ (2D-HD): light the finished sprite, keep the added light in a few steps so it stays pixel art.
154
+
155
+ ## Motion (family feel)
156
+ Each style has a `motion` block, so a family moves as one. A spec's `anim` overrides any key.
157
+ - `gait` (walk + run, humanoid and quadruped): `stride` (classic), `hop` (both feet, off the ground; rabbits, spirits;
158
+ `walk_hop`/`run_hop` px), `lurch` (bent forward, hip sway, heavy footfall; quadrupeds prowl low), `bounce` (springy,
159
+ squash on every step), `glide` (low, level, arms still; run = low dash with arms swept back).
160
+ - `idle_style: "float"` + `hover` px: the body floats off the ground in every clip (shadow stays down and shrinks);
161
+ deaths drop to the ground. `float_bob` = idle drift px.
162
+ - `attack_style` (built-in attack): `slash` (13 f), `dart` (leap in, strike mid-air, drift back), `heavy` (trembling
163
+ wind-up, crushing impact, hit-stop), `hop` (spring up, strike on landing), `iaido` (stillness, one-frame draw, frozen
164
+ follow-through). `hitstop: n` freezes the impact of hand-written `custom_clips.attack` for n frames.
165
+ - Families: Hollow Court lurch/heavy, Meadowfolk bounce/hop, Wayfarers stride/slash,
166
+ Ember Spirits float + hop/dart.
167
+ - Walks are keyed contact (0, 4: full stride, footstep, 1 px weight shift) / passing (2, 6: body high, 2 px foot lift).
168
+ Runs lean `run_lean` (22) with the chest `run_lead` px (2) ahead of the hips. Props trail 1 frame and get spring
169
+ follow-through; weapon bones (`smear_hides`) lag the hand instead of swinging with it.
170
+ - **Limited animation** (stop-motion timing, on by default): built-in clips show fewer, stronger poses and hold
171
+ each one, like Guilty Gear Xrd / anime "on twos". Loops step on twos (walk = 8 poses x 2 frames); one-shots keep
172
+ their designed key poses (wind-up held 3, one-frame cut, follow-through held 3). `anim.on` sets the hold
173
+ (1 = every frame moves, 2 default, 3-4 choppier) or per clip `{"walk": 2, "run": 1}`; run and hit stay on ones.
174
+ Hand-written `custom_clips` keep their frames unless the clip sets `"on": n`. Frame counts never change.
175
+ - Runs are keyed contact / down (lowest, squash) / push-off (rear leg long, knee drive, stretch) / flight (both
176
+ feet off, highest), leaning forward `run_lean` with the hips countering the shoulders.
177
+ - `anim.carry = {"bow": {"aim": [x,y,z], "up": [0,0,1]}}` keeps a carried item at one body-frame angle in idle,
178
+ walk and run (no flailing bow or spear). `"up"` on any aim also fixes the bone's twist (its local z).
179
+ - Check motion with `pp review <dir> --onion`: each clip's frames overlaid (blue = first, red = last) over the ground line.
180
+
181
+ ## Inspect, variants, layers
182
+ - **`pp inspect <spec> --clip C --dir D --frame N`**: reads the real bake of one frame. It prints a table with one
183
+ line per part, nearest first: pixels, bbox, value (Oklab L), materials and colours. It also lists parts hidden in
184
+ this view, touching parts whose values are too close (dL < 0.08), attach points, and a glyph grid (one letter per
185
+ part). It writes an image: sprite | part map | material map, with the same letters. Use it when you can't tell
186
+ what a blob is, why a part vanished, or where the hand is. Don't use it to write reports.
187
+ - **`pp variants <spec> --vary key=a,b,c`** (dotted path; `bones.head.parts.0.r` addresses bones by name;
188
+ `key=lo..hi --sample 6 --seed 3` draws keyed values) builds each row as a normal build in /tmp and shows a
189
+ labelled still grid plus an animated grid. Row v00 is the spec as it is. A row that renders identically to an
190
+ earlier one is flagged, e.g. `attack_style` under a hand-written attack. Each row lists its lint WARNs.
191
+ `--apply N` writes row N into the spec. Choose by looking at the animated grid, not the still.
192
+ - **`"attach": true`** (or `{"muzzle": ["gun", [0, -6, 0]]}`; where = `tip|joint|centre|[x,y,z]`) writes per-frame
193
+ points into the build json: `clips.<c>.attach.<dir>[frame] = {head, hand_R, hand_L, weapon_tip, feet: [x, y,
194
+ visible], box: [x0, y0, x1, y1]}`. Games use them for spawn points (spells, muzzles) and hitboxes.
195
+ - **Combo clips** (`"layers"`): `{"run_attack": {"base": "run", "over": [{"clip": "attack", "bones": "torso/",
196
+ "spine": 0.5}]}}`. The legs keep running while the torso subtree plays the attack (`name/` = the bone and its
197
+ children). `spine` blends the waist. The hit, smear and hitstop come from the attack (the legs freeze on impact
198
+ too); footsteps and ground speed come from the base. Combos are listed with the rig's clips and baked into their
199
+ own sheets.
200
+ - **Life** (`"life"` in a spec, or as a style default): small additive motion in whole pixels, off unless asked for.
201
+ `sway` {bones, px, frames, wave}: sideways travelling wave for crowns, flags and sails. Flora trees use it by
202
+ default. `flutter` {bones, px}: cloth tips flick 1 px on an 8-beat. `look` {every, deg}: every Nth idle breath
203
+ the head glances aside and back (the idle gets N times longer). Keep it subtle. The idle-change lint and
204
+ `pp review --onion` catch parts that boil.
205
+ - Map kits (pp.map): an object's `"build"` can be a list of **same-footprint** variants. Each placement gets a keyed
206
+ pick, never the same as its nearest same-kit neighbour. Don't mix sizes (rows break) and don't flip lit sprites.
207
+
208
+ ## Concept sheet → sprites: what to avoid (failed "wayfarers" party, 2026-09-27)
209
+ - Don't force chibi. Copy the concept's proportions (lanky, small head); the chibi default killed the look first.
210
+ - Don't transcribe detail. At 26-30 px keep 3-4 colour blocks + skin + one accent; studs, vials, checkers, scales, trim = noise.
211
+ - Don't build angular designs from ellipsoids/capsules: they bake into lumpy blobs. Graphic concepts need boxes/wedges/flat cones.
212
+ - Don't let 8 artists invent 8 bodies. One shared base body first, then costume + one defining feature each.
213
+ - Don't fix "too busy" afterwards by stripping: the result is flat but generic. Decide the simple read before modelling.
214
+ - Prototype ONE character against the concept and get sign-off before fanning out to the family.
215
+
216
+ ## Styles (styles/*.json, generated by tools/make_styles.py)
217
+ Materials are shared by every asset in a style — that's the consistency. Use style materials; add a spec material only
218
+ by pointing at an existing style ramp. List them: `python3 -m pp materials <style>`.
219
+ - **duskborne** — dark fantasy action. Deep desaturated bodies, near-black ink, ONE glowing accent (cyan/pink/fire).
220
+ - **sunmeadow** — bright cozy adventure. Warm saturated mids, soft values, coloured outlines, green ground.
221
+ - **vermilion** — folk-print spirits. Three inks on cream paper: black masses (`ink`, `ink_flat` for sticks),
222
+ red coats/flames (`red`, `canopy` for crowns), painted marks (`red_mark`, `bone_mark`), dry-brush `fur`.
223
+ No outline, 1-2 tones; VFX use `fx_ink` (hot core = darkest ink). Put markings on as stamps (chevrons, bands).
224
+
225
+ ## VFX sheets
226
+ `python3 -m pp fx <kind> --style <style> --ramp <ramp> [--param k=v ...]`: kinds `slash, hit_spark, burst, eruption, aura,
227
+ dust, projectile, lightning, sparkle, leaves, shockwave`. Eruption takes `spike_h`, `spike_w`, `rune_r`; leaves take `leaf_size` (2 = specks, 3 = two-tone leaves), `count`;
228
+ aura takes `radius`, `tongues`, `tongue_w`, `tongue_h`, `motes`, `sustain`; hit_spark `scale`, `ray_w`, `rays`, `sparks`;
229
+ dust `puffs`, `radius`, `two_tone`; sparkle `star_size` (3 = 7 px cross), `ring_w`, `ring_r`, `stars`; shockwave `ring_w`, `chips`.
230
+ Poses also take per-bone `"at"` offsets (e.g. lift a hand above the head in a gesture clip). VFX dirs can be passed to `pp pack` (they land in vfx/). Posterized to the ramp; timing rules are built in (fast build, slow fragmenting decay).
231
+
232
+ ## Shipping
233
+ `python3 -m pp pack <pack_name> out/<a> out/<b> ... --style <style>` → `packs/<pack_name>/` (sheets, gifs, .aseprite
234
+ sources, palette.png/.gpl, preview.png, lineup.png, README.txt). `python3 -m pp aseprite out/<a>` exports one source.
235
+
236
+ ## When the engine is the problem
237
+ If you can't get something right with the spec (a missing primitive, a rig limit, an ugly automatic rule), write it in
238
+ `REQUESTS.md` (one line: what you tried, what you need, which image shows it). The engineer fixes the engine.
239
+ Don't hack around it with dozens of micro-parts.
240
+
241
+ ## Maps (pp.map)
242
+ `python3 -m pp.map <map.json> [--still] [--layers]` lays built props out on painted terrain and animates them.
243
+ - **terrain** (in order): `fill`, `land` (optional `cliff`), `path`, `paving` (quiet slabs), `planks`, `sea` (1-3 calm tones),
244
+ `shore` (shallows + foam), `canopy` (forests of round clumps; `clear` keeps roads open with a row of crowns along them),
245
+ `massif` (one mountain range from blended summits; `valleys` cut hollows and gorges), `bridge` (a deck at any angle), `wall_face`.
246
+ Regions are `rect` / `ellipse` / `poly` / `path`, with a noisy edge (`rough`). Colours are ramp roles (`tones`), never hex.
247
+ - **objects** sort by feet y (`z` changes the order only). `place: id` + `icon` export tap bounds, an outline ring and an
248
+ atlas glyph; `over: true` also draws it above movers (bridges, walls). `cast_shadow` darkens the ground by a ramp step.
249
+ - **fx**: smoke, glints, waves, `flow` (streaks down a river path), birds, clouds; **walkers** move along paths.
250
+ - **fog**: `regions` (bitmask: each region's own rounded, overlapping shape, so lifting one leaves a soft edge), `ramp`
251
+ (the vista `mist`), a faint ghost of the land beneath; `permanent` regions never lift.
252
+ - `--layers` is the engine export: a delta-encoded base loop (only changed pixels), occluders, mover strips with
253
+ px/s speeds, sky clouds, fog + bitmask, places with outlines, extra `sprites`, and an `atlas` (the hand-drawn map, read
254
+ back from the rendered colours, in ink layers). Keep clip lengths divisors of the map's `frames` so the loop is seamless.
255
+ Vista kits, layouts and maps: `python3 tools/vista/build.py`.
256
+
@@ -0,0 +1,30 @@
1
+ # Environments: painted maps that live
2
+
3
+ pp paints a whole map as one picture (`pp.map`), in one locked palette. These tools turn that picture into a place.
4
+
5
+ | Command | What it gives you |
6
+ |---|---|
7
+ | `python3 -m pp states specs/vista/house_5.json` | a building's **ruin**, its **construction** stages (walls rising course by course inside a scaffold, rafters, roof) and the finished building, re-rendered by the engine from the building's own spec. Place `house_5~ruin` in a map like any object. |
8
+ | `python3 -m pp.map <map> --still --meaning` | the **meaning layer**: what every pixel is (material, collision, water depth, occlusion depth, object ids), written by the painters while they paint. `--layers` always includes it. |
9
+ | `python3 -m pp light <map> --gif` | the map at **every hour**: day, golden hour, sunset, dusk, night; windows light building by building, lamps pool warm light, water reflects it. `light.json` lets an engine do it at runtime. |
10
+ | `land "blades"`, `water "bank"` | painters for **grass by density** (small pixel blades, no tone patches) and **water from bank to middle** (dithered seams, flat deep middle). |
11
+
12
+ ## Rules that keep a map believable
13
+ Learned building the open-world scenes (2026-10). They hold for any environment.
14
+
15
+ - **The vista look is the identity:** soft, painterly, aerial, muted cream walls, terracotta roofs, teal water, calm
16
+ forest masses. Fix what is flagged inside that language; never swap in a new style.
17
+ - **One painter per material, strictly.** Every tree, bush, hedge and forest in a scene comes from the same canopy
18
+ painter at one leaf size. A tree is a bigger crown over a short shaded trunk with a soft down-right ground shadow.
19
+ Mixing kit tree sprites with painted forest breaks the immersion. Check every new asset family against what is
20
+ already on screen for the same material.
21
+ - **One scale axiom.** Pick the size of a person and derive everything from it. At walk
22
+ scale a person is 14 px = 1.70 m and the street kit (st_house_*, lamps, fountain, stalls) agrees with it.
23
+ - **Paint by density, not patches.** Grass blades whose density drifts; water as a bank-to-middle gradient. Hard tone
24
+ patches read as jagged blotches.
25
+ - **Buildings carry the story.** A ruin that rebuilds in beats (scaffold, courses, roof, dust, then smoke and lit
26
+ windows) was the most loved moment of every scene. Light is the other one: a town answering the dusk.
27
+ - **Less is more.** One authored, atmospheric place beats many scenes built to a checklist; judge by "do I want to be
28
+ there?", not by measurements.
29
+ - **For a game on top:** never round the camera. Draw the world 1 px oversize, scale by a whole number and offset by
30
+ the camera's sub-pixel fraction; non-integer scaling is what makes pixel art look uneven.