summer-engine 4.3.0 → 4.6.0

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 (231) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +3 -1
  3. package/.codex-plugin/plugin.json +5 -3
  4. package/.cursor-plugin/plugin.json +4 -2
  5. package/.factory-plugin/plugin.json +4 -2
  6. package/AGENTS.md +2 -2
  7. package/CHANGELOG.md +100 -0
  8. package/README.md +67 -27
  9. package/commands/start.md +19 -15
  10. package/commands/summer.md +1 -0
  11. package/dist/cli/command-usage.d.ts +3 -1
  12. package/dist/cli/command-usage.js +10 -4
  13. package/dist/cli/commands/create.d.ts +1 -25
  14. package/dist/cli/commands/create.js +10 -138
  15. package/dist/cli/commands/dev.d.ts +66 -0
  16. package/dist/cli/commands/dev.js +234 -0
  17. package/dist/cli/commands/install.d.ts +15 -58
  18. package/dist/cli/commands/install.js +31 -481
  19. package/dist/cli/commands/login.js +1 -1
  20. package/dist/cli/commands/ops.d.ts +17 -1
  21. package/dist/cli/commands/ops.js +97 -9
  22. package/dist/cli/commands/preview.d.ts +58 -0
  23. package/dist/cli/commands/preview.js +181 -0
  24. package/dist/cli/commands/run.d.ts +1 -17
  25. package/dist/cli/commands/run.js +17 -206
  26. package/dist/cli/commands/setup.js +175 -32
  27. package/dist/cli/index.js +5 -0
  28. package/dist/core/agent-host.d.ts +3 -0
  29. package/dist/core/agent-host.js +1 -1
  30. package/dist/core/api-client.d.ts +10 -2
  31. package/dist/core/api-client.js +13 -8
  32. package/dist/core/capabilities/agent-playbook.js +1 -0
  33. package/dist/core/capabilities/apps.d.ts +9 -9
  34. package/dist/core/capabilities/asset-import.d.ts +4 -1
  35. package/dist/core/capabilities/asset-import.js +15 -6
  36. package/dist/core/capabilities/capture-gameplay.js +1 -1
  37. package/dist/core/capabilities/connect-signal.d.ts +2 -2
  38. package/dist/core/capabilities/content-make/index.d.ts +81 -0
  39. package/dist/core/capabilities/content-make/index.js +706 -0
  40. package/dist/core/capabilities/content-make/media.d.ts +57 -0
  41. package/dist/core/capabilities/content-make/media.js +172 -0
  42. package/dist/core/capabilities/content-make/plan.d.ts +130 -0
  43. package/dist/core/capabilities/content-make/plan.js +433 -0
  44. package/dist/core/capabilities/content-make/render.d.ts +64 -0
  45. package/dist/core/capabilities/content-make/render.js +370 -0
  46. package/dist/core/capabilities/content-make/study.d.ts +13 -0
  47. package/dist/core/capabilities/content-make/study.js +165 -0
  48. package/dist/core/capabilities/content-make/types.d.ts +173 -0
  49. package/dist/core/capabilities/content-make/types.js +6 -0
  50. package/dist/core/capabilities/content-make/voice.d.ts +7 -0
  51. package/dist/core/capabilities/content-make/voice.js +27 -0
  52. package/dist/core/capabilities/events.d.ts +2 -2
  53. package/dist/core/capabilities/export-game.d.ts +4 -1
  54. package/dist/core/capabilities/export-game.js +4 -3
  55. package/dist/core/capabilities/export-presets.d.ts +2 -1
  56. package/dist/core/capabilities/export-presets.js +2 -1
  57. package/dist/core/capabilities/go-live.d.ts +14 -0
  58. package/dist/core/capabilities/go-live.js +408 -0
  59. package/dist/core/capabilities/image-generation.d.ts +6 -6
  60. package/dist/core/capabilities/item-manifest.d.ts +92 -0
  61. package/dist/core/capabilities/item-manifest.js +247 -0
  62. package/dist/core/capabilities/placement.d.ts +7 -7
  63. package/dist/core/capabilities/projects-local.d.ts +68 -0
  64. package/dist/core/capabilities/projects-local.js +172 -0
  65. package/dist/core/capabilities/publish-build.d.ts +13 -2
  66. package/dist/core/capabilities/publish-build.js +87 -21
  67. package/dist/core/capabilities/publish-download.js +1 -1
  68. package/dist/core/capabilities/runtime-control.d.ts +7 -2
  69. package/dist/core/capabilities/runtime-control.js +27 -1
  70. package/dist/core/capabilities/seeing/args.d.ts +2 -2
  71. package/dist/core/capabilities/store-checks.d.ts +45 -0
  72. package/dist/core/capabilities/store-checks.js +85 -0
  73. package/dist/core/capabilities/store-details.d.ts +37 -0
  74. package/dist/core/capabilities/store-details.js +94 -0
  75. package/dist/core/capabilities/summer-bundle.d.ts +21 -2
  76. package/dist/core/capabilities/summer-bundle.js +54 -7
  77. package/dist/core/capabilities/sync-items.d.ts +89 -0
  78. package/dist/core/capabilities/sync-items.js +352 -0
  79. package/dist/core/capabilities/tool-dispatch.js +66 -6
  80. package/dist/core/capabilities/video-ogv.d.ts +49 -0
  81. package/dist/core/capabilities/video-ogv.js +260 -0
  82. package/dist/core/capability-skew.js +2 -2
  83. package/dist/core/cli-usage-beacon.js +26 -2
  84. package/dist/core/cli-usage.d.ts +5 -2
  85. package/dist/core/cli-usage.js +8 -2
  86. package/dist/core/engine-install.d.ts +53 -0
  87. package/dist/core/engine-install.js +93 -0
  88. package/dist/core/engine-installer.d.ts +134 -0
  89. package/dist/core/engine-installer.js +760 -0
  90. package/dist/core/engine-launch.d.ts +126 -0
  91. package/dist/core/engine-launch.js +398 -0
  92. package/dist/core/engine-self-start.d.ts +63 -0
  93. package/dist/core/engine-self-start.js +282 -0
  94. package/dist/core/engine.d.ts +7 -1
  95. package/dist/core/engine.js +9 -2
  96. package/dist/core/error-codes.d.ts +4 -1
  97. package/dist/core/error-codes.js +7 -3
  98. package/dist/core/library-read.d.ts +2 -2
  99. package/dist/core/library-search.d.ts +2 -2
  100. package/dist/core/local-project.d.ts +50 -0
  101. package/dist/core/local-project.js +234 -0
  102. package/dist/core/ops/areas.js +9 -3
  103. package/dist/core/ops/catalog.d.ts +9 -0
  104. package/dist/core/ops/catalog.js +56 -4
  105. package/dist/core/ops/engine-answer.d.ts +4 -1
  106. package/dist/core/ops/engine-answer.js +16 -3
  107. package/dist/core/ops/engine.js +4 -4
  108. package/dist/core/ops/save-files.d.ts +6 -1
  109. package/dist/core/ops/save-files.js +67 -50
  110. package/dist/core/ops/search.js +9 -2
  111. package/dist/core/preview/input.d.ts +35 -0
  112. package/dist/core/preview/input.js +105 -0
  113. package/dist/core/preview/launch-config.d.ts +52 -0
  114. package/dist/core/preview/launch-config.js +137 -0
  115. package/dist/core/preview/page.d.ts +22 -0
  116. package/dist/core/preview/page.js +232 -0
  117. package/dist/core/preview/preview-source.d.ts +179 -0
  118. package/dist/core/preview/preview-source.js +350 -0
  119. package/dist/core/preview/server.d.ts +26 -0
  120. package/dist/core/preview/server.js +218 -0
  121. package/dist/core/telemetry.d.ts +20 -16
  122. package/dist/core/telemetry.js +92 -16
  123. package/dist/core/templates.d.ts +20 -0
  124. package/dist/core/templates.js +300 -3
  125. package/dist/core/tool-profiles.d.ts +2 -2
  126. package/dist/core/tool-profiles.js +1 -0
  127. package/dist/core/usage-fields.d.ts +41 -0
  128. package/dist/core/usage-fields.js +150 -0
  129. package/dist/core/util/sleep.d.ts +3 -0
  130. package/dist/core/util/sleep.js +12 -0
  131. package/dist/installer/agent-config.d.ts +29 -0
  132. package/dist/installer/agent-config.js +75 -11
  133. package/dist/installer/agent-detect.d.ts +44 -0
  134. package/dist/installer/agent-detect.js +166 -0
  135. package/dist/installer/agent-table.d.ts +19 -0
  136. package/dist/installer/agent-table.js +130 -0
  137. package/dist/installer/setup-error.d.ts +19 -0
  138. package/dist/installer/setup-error.js +34 -0
  139. package/dist/installer/version-check.d.ts +5 -0
  140. package/dist/installer/version-check.js +21 -0
  141. package/dist/mcp/ops-surface.d.ts +7 -0
  142. package/dist/mcp/ops-surface.js +40 -3
  143. package/dist/mcp/server.d.ts +14 -4
  144. package/dist/mcp/server.js +42 -8
  145. package/dist/mcp/tool-surface.d.ts +8 -0
  146. package/dist/mcp/tool-surface.js +19 -2
  147. package/dist/mcp/tools/creator-tools.js +92 -14
  148. package/dist/mcp/tools/debug-tools.js +2 -0
  149. package/dist/mcp/tools/local-project-tools.d.ts +6 -0
  150. package/dist/mcp/tools/local-project-tools.js +33 -0
  151. package/dist/mcp/tools/navigation-tools.js +2 -1
  152. package/dist/mcp/tools/project-tools.js +5 -8
  153. package/dist/mcp/tools/seeing-tools.js +1 -1
  154. package/dist/mcp/tools/visual-tools.js +1 -1
  155. package/dist/mcp/tools/with-engine.js +1 -1
  156. package/dist/project-memory/agent-instructions.js +11 -3
  157. package/gemini-extension.json +3 -1
  158. package/library/references/mcp-tools-reference/mcp-tools-reference.md +18 -5
  159. package/library/skills/README.md +12 -8
  160. package/library/skills/animated-loop/SKILL.md +10 -16
  161. package/library/skills/cinematic-cutscene/SKILL.md +7 -18
  162. package/library/skills/headless-scripting/SKILL.md +7 -4
  163. package/library/skills/in-game-purchases/SKILL.md +25 -8
  164. package/library/skills/in-game-purchases/resource.yaml +2 -1
  165. package/library/skills/launch-ready/SKILL.md +351 -0
  166. package/library/skills/launch-ready/resource.yaml +45 -0
  167. package/library/skills/make-content/SKILL.md +202 -0
  168. package/library/skills/make-content/resource.yaml +32 -0
  169. package/library/skills/make-game/SKILL.md +6 -4
  170. package/library/skills/make-game/resource.yaml +2 -1
  171. package/library/skills/navigate-summer/SKILL.md +4 -2
  172. package/library/skills/new-project/SKILL.md +15 -22
  173. package/library/skills/new-project/resource.yaml +2 -1
  174. package/library/skills/painted-25d-world/SKILL.md +366 -0
  175. package/library/skills/painted-25d-world/_building-blocks/blender-route.md +33 -0
  176. package/library/skills/painted-25d-world/_building-blocks/blockout_builder.gd +149 -0
  177. package/library/skills/painted-25d-world/_building-blocks/capture_paint_view.gd +32 -0
  178. package/library/skills/painted-25d-world/_building-blocks/paint_projection.gdshader +23 -0
  179. package/library/skills/painted-25d-world/_building-blocks/paintcam_check.gd +25 -0
  180. package/library/skills/painted-25d-world/_building-blocks/painted_door.gd +17 -0
  181. package/library/skills/painted-25d-world/_building-blocks/painted_location.gd +56 -0
  182. package/library/skills/painted-25d-world/_building-blocks/painted_player.gd +125 -0
  183. package/library/skills/painted-25d-world/_building-blocks/painted_world.gd +111 -0
  184. package/library/skills/painted-25d-world/_building-blocks/tools/cam.py +57 -0
  185. package/library/skills/painted-25d-world/_building-blocks/tools/detail4k.py +81 -0
  186. package/library/skills/painted-25d-world/_building-blocks/tools/overlay.py +17 -0
  187. package/library/skills/painted-25d-world/_building-blocks/tools/preview.py +60 -0
  188. package/library/skills/painted-25d-world/resource.yaml +39 -0
  189. package/library/skills/publish-your-game/SKILL.md +13 -14
  190. package/library/skills/publish-your-game/resource.yaml +4 -3
  191. package/library/skills/release-checklist/SKILL.md +188 -0
  192. package/library/skills/release-checklist/resource.yaml +40 -0
  193. package/library/skills/release-readiness/SKILL.md +1 -1
  194. package/library/skills/release-readiness/resource.yaml +1 -1
  195. package/library/skills/store-art/SKILL.md +1 -1
  196. package/library/skills/store-art/resource.yaml +1 -1
  197. package/library/skills/store-listing/SKILL.md +1 -1
  198. package/library/skills/store-listing/resource.yaml +1 -1
  199. package/library/skills/summer-cli/SKILL.md +2 -0
  200. package/library/skills/summer-store/SKILL.md +295 -39
  201. package/library/skills/summer-store/resource.yaml +9 -3
  202. package/library/skills/trailer-shot/SKILL.md +3 -3
  203. package/library/templates/README.md +5 -0
  204. package/library/tools/content-make/resource.yaml +132 -0
  205. package/library/tools/frame-shot/GUIDE.md +1 -1
  206. package/library/tools/go-live/resource.yaml +67 -0
  207. package/library/tools/import-from-url/GUIDE.md +1 -0
  208. package/library/tools/import-from-url-batch/GUIDE.md +1 -1
  209. package/library/tools/play/GUIDE.md +2 -0
  210. package/library/tools/projects-create-local/resource.yaml +55 -0
  211. package/library/tools/projects-open-local/resource.yaml +51 -0
  212. package/library/tools/publish-build/resource.yaml +3 -3
  213. package/library/tools/screenshot/GUIDE.md +1 -1
  214. package/library/tools/store-set-details/resource.yaml +114 -0
  215. package/library/tools/sync-items/resource.yaml +72 -0
  216. package/package.json +1 -1
  217. package/registry/generated/aliases.json +6 -0
  218. package/registry/generated/counts.json +3 -3
  219. package/registry/generated/gemini-extension.json +3 -1
  220. package/registry/generated/index.json +463 -37
  221. package/registry/generated/marketplace.claude.json +1 -1
  222. package/registry/generated/plugin.claude-directory.json +4 -2
  223. package/registry/generated/plugin.claude.json +3 -1
  224. package/registry/generated/plugin.codex.json +5 -3
  225. package/registry/generated/plugin.cursor.json +4 -2
  226. package/registry/generated/plugin.factory.json +4 -2
  227. package/registry/generated/server.json +2 -2
  228. package/registry/generated/skills-index.md +12 -8
  229. package/registry/generated/skills-registry.json +62 -5
  230. package/registry/operations/legacy-names.json +40 -0
  231. package/registry/operations/public-catalog.json +10144 -387
@@ -40,13 +40,15 @@ Distilled blueprints for common genres live in this skill's `references/` folder
40
40
  | Third-person action / 3D platformer | `references/3d-third-person.md` | `references/3d-third-person-systems.md` | Node3D / CharacterBody3D / SpringArm3D |
41
41
  | First-person horror | `references/3d-horror.md` | `references/3d-horror-systems.md` | Node3D / CharacterBody3D / Camera3D on Head |
42
42
 
43
+ **2D and 2.5D games look painted.** For any 2D or 2.5D request (top-down, RPG, cozy, side-scroller, platformer look), build the world with the `painted-25d-world` skill: a 3D blockout under one fixed orthographic camera, an AI paint-over projected onto the blocks, sprite characters (Node3D / CharacterBody3D / translate-only Camera3D). Use the 2D playbooks above for the core loop, mechanics and build order only, not for the scene tree or art. Do not start a 2D game from a 2D template unless the user asks for that template.
44
+
43
45
  No playbook (racing, sandbox, sim): build fresh through the phases below. The playbooks lean on these system skills — load one when its mechanic comes up: `character-movement`, `camera-rigs`, `combat-basics`, `save-load`, `ui-basics`, `multiplayer-project`.
44
46
 
45
47
  These rules from the playbooks apply to every genre:
46
48
 
47
49
  - **2D scales to the viewport.** Set `display/window/stretch/mode = canvas_items` and `stretch/aspect = expand`; UI uses Control anchors; code-positioned nodes compute from `get_viewport_rect().size`. Never hardcode 1920x1080.
48
50
  - **Playable slice, not tech demo.** Name the core loop in one sentence; every input gets feedback (tween, sound, particle, flash, shake); progression is visible; a restart exists. The bar is "feels good for 30 seconds".
49
- - **Fast first draft when someone is waiting.** The first playable version uses shapes, the palette and any template art, plus at most one or two generated assets the person specifically asked for; generation takes minutes, so it never blocks the first play. Say plainly that it is a first draft to get a feel for the game, that the art is not final, and ask if this is the direction they want. Generate the rest of the art in later passes.
51
+ - **The first playable already looks good.** People judge Summer by the first frame of their first game, so the first version looks finished even when they ask for a quick prototype: keep the features they asked for and raise the look. Sky and sun with shadows, tonemapping and a little fog; a texture on every surface; real models for the player, characters and main props from the starter project or the Summer asset library (`summer_assets_search`), never capsules or boxes as final art; one colour palette; a styled UI font. Generation takes minutes, so it never blocks the first play: use starter and library art first, plus at most one or two generated assets the person asked for, and generate the rest in later passes. Before you say it is ready, play it and look at a screenshot of the running game, not the editor (the editor shows a preview sky and sun that the game does not have).
50
52
  - **A way back to the title.** From inside play, a pause menu or a **Leave** button returns to the title screen without quitting the app.
51
53
  - **Text the default font can show.** No emoji or symbols (▲ ◀ ★ ♥ ✓) in UI text: they render as boxes with hex codes. Use words or icons; see `ui-basics`.
52
54
 
@@ -199,7 +201,7 @@ Repeat until every mechanic in the plan is implemented OR the user calls cut.
199
201
 
200
202
  ## Phase 5: Layer (look + sound)
201
203
 
202
- **Goal**: the game stops looking like a programmer art prototype.
204
+ **Goal**: deepen the look and add sound. The first playable already looks good (see "The first playable already looks good" above); this phase writes the art bible, replaces the remaining stand-in art and adds audio.
203
205
 
204
206
  ```
205
207
  Skill: art-direction
@@ -274,7 +276,7 @@ If the brief said "jam" or "prototype", skip this phase. If the brief said "game
274
276
  |---|---|
275
277
  | Skip the brainstorm because the user said "FPS" | Even with the genre named, you need the scope cut list. Otherwise mechanic 4 quietly sneaks in and the game never ships. |
276
278
  | Let mechanic 2 start before mechanic 1 is verified clean | Compounding bugs. You'll spend the rest of the session debugging which mechanic broke what. |
277
- | Stack art direction on top of unfinished mechanics | Art changes are reversible only if the underlying scene structure is stable. Get mechanics done first. |
279
+ | Change the art style while mechanics are unfinished | Art changes are reversible only if the underlying scene structure is stable. Get mechanics done before a new style; the first playable still starts good-looking. |
278
280
  | Treat "polish" as required | If the brief says "jam in 2 days", polish is a cut item. Respect the brief. |
279
281
  | Run all phases without confirming | The user owns scope. Stop at every checkpoint. |
280
282
  | Ship online play behind a setting nobody changes | Hosted join is never exercised, so it breaks without anyone noticing. Reachable by default, or the owner joins online before every release. |
@@ -311,7 +313,7 @@ No Summer MCP tools in this session? Run each one as a command; when `summer --v
311
313
 
312
314
  | In this skill | Command |
313
315
  |---|---|
314
- | `assets.search` | `summer assets search` |
316
+ | `assets.search`, `summer_assets_search` | `summer assets search` |
315
317
  | `summer_docs_read` | `summer docs read` |
316
318
  | `summer_add_node` | `summer engine add-node` |
317
319
  | `summer_batch` | `summer engine batch` |
@@ -1,6 +1,6 @@
1
1
  id: skill/make-game
2
2
  kind: skill
3
- version: 1.1.0
3
+ version: 1.2.0
4
4
  summary: "Orchestrate 'make me a game': brainstorm, plan, scaffold, mechanics, art, audio, polish, verify, ship."
5
5
  use_when:
6
6
  - the user says 'make me a game', 'build me a game', 'I want to make a [genre] game', or 'let's build something' — running the full game-dev pipeline
@@ -33,6 +33,7 @@ related:
33
33
  - skill/camera-rigs
34
34
  - skill/combat-basics
35
35
  - skill/save-load
36
+ - skill/painted-25d-world
36
37
  source: official
37
38
  license: MIT
38
39
  status: stable
@@ -24,10 +24,10 @@ Rigid skill: follow the rules below exactly.
24
24
  | The user wants to… | Do |
25
25
  |---|---|
26
26
  | **see / check / decide** — plan and billing (money), their published games and releases, usage, pricing, the MCP setup guide for their agent, docs, the scene or node you just built ("show me") | **Open the surface** with `studio.open` |
27
- | **get a result** — add a node, set a property, import an asset, run the game, publish | **Act through Summer tools** (mutation tools, `summer_play`, `store.publish`); do not open the editor to do by hand what a tool does |
27
+ | **get a result** — add a node, set a property, import an asset, run the game, publish | **Act through Summer tools** (mutation tools, `summer_play`, `store.publish`); do not click through the editor by hand to do what a tool does |
28
28
  | **both** ("add a camera and show me") | act first, then open the scene / select the node so the user sees the result |
29
29
 
30
- Never open a browser or switch the editor's tab as a side effect of building. Opening is a user-visible action — do it because the user asked to look, and say what will open before it opens.
30
+ Never open a browser or switch the editor's tab as a side effect of building. Opening a page or panel is a user-visible action — do it because the user asked to look, and say what will open before it opens. Playing the game and taking screenshots to check your own work is different: that is allowed and expected (`summer_play`, then `summer_screenshot` or `summer_frame_shot`).
31
31
 
32
32
  ## How to call it
33
33
 
@@ -70,9 +70,11 @@ No Summer MCP tools in this session? Run each one as a command; when `summer --v
70
70
  | In this skill | Command |
71
71
  |---|---|
72
72
  | `summer_docs_read` | `summer docs read` |
73
+ | `summer_frame_shot` | `summer engine frame-shot` |
73
74
  | `summer_get_project_context` | `summer engine get-project-context` |
74
75
  | `summer_is_running` | `summer engine is-running` |
75
76
  | `summer_play` | `summer engine play` |
77
+ | `summer_screenshot` | `summer engine screenshot` |
76
78
  | `store.publish` | `summer store publish` |
77
79
  | `studio.open`, `summer_open` | `summer studio open` |
78
80
  <!-- /shell-commands -->
@@ -42,37 +42,29 @@ Default: `my-game`. If they say "anything is fine" or similar, use `my-game` and
42
42
  Two built-in options:
43
43
 
44
44
  - `empty` — root `Node3D` only. Pure blank canvas. Best for: experimentation, when the user knows exactly what they want to build.
45
- - `3d-basic` — root `Node3D` with `Camera3D`, `DirectionalLight3D`, a floor `MeshInstance3D`, and a `WorldEnvironment`. Best for: first-time users who want something they can press Play on.
45
+ - `3d-basic` — root `Node3D` with a procedural sky on a `WorldEnvironment`, a sun with soft shadows, a tinted ground, one hero mesh and a `Camera3D` that frames it. Best for: first-time users who want something they can press Play on.
46
46
 
47
47
  If you're not sure which fits, ask:
48
48
 
49
49
  > "Empty (just a root node) or 3d-basic (camera, light, and a floor — you can press play immediately)?"
50
50
 
51
- If the user has clearly invoked `brainstorm-game` already and the brief calls for 3D, default to `3d-basic` and mention you did. If 2D, use `empty` (we don't ship a 2D-basic yet).
51
+ If the user has clearly invoked `brainstorm-game` already and the brief calls for 3D, default to `3d-basic` and mention you did. If 2D or 2.5D, use `empty`, keep its `Node3D` root and build the world with `painted-25d-world` (a painted 3D blockout under a fixed orthographic camera with sprite characters).
52
52
 
53
- ### 3. Create
53
+ ### 3. Create and open it
54
54
 
55
- ```
56
- summer create empty my-game
57
- ```
58
-
59
- or
55
+ One command creates the project and opens it. When Summer Engine is missing it also installs it (about 660 MB): ask the user first, and pass `--yes` only with their OK (without it nothing is installed):
60
56
 
61
57
  ```
62
- summer create 3d-basic my-game
58
+ summer dev --yes 3d-basic my-game
63
59
  ```
64
60
 
65
- The command writes `project.godot` and the chosen `main.tscn`. It makes no network call.
61
+ or `summer dev --yes empty my-game`. It writes `project.godot` and the chosen `main.tscn` (no network call for these two), opens the editor and waits until it answers.
66
62
 
67
- ### 4. Open it
68
-
69
- ```
70
- summer run my-game
71
- ```
63
+ No shell in this session (a chat app)? Call `projects.create_local` with `template` and `name`, then `projects.open_local` with its `projectPath` (and `install: true` only after the user said yes to installing the engine).
72
64
 
73
- Confirm the engine launched and the project loaded. If `summer run` fails, run `summer doctor` and surface the failure to the user.
65
+ Confirm the project loaded with `summer_get_project_context`. If it fails, run `summer doctor` and surface the failure to the user.
74
66
 
75
- ### 5. Don't keep going automatically
67
+ ### 4. Don't keep going automatically
76
68
 
77
69
  After scaffolding, **stop and let the user direct.** A common mistake: fire `fps-controller` or `design-mechanic` automatically because "now we make a game." Wait. The user might want to:
78
70
 
@@ -88,16 +80,16 @@ Ask: "Project is open. What do you want to build?"
88
80
  | Don't | Why |
89
81
  |---|---|
90
82
  | Skip the name question and use `my-game` silently | The user has opinions about the directory name. Two seconds of asking saves a `mv` later. |
91
- | Use `summer create 3d-basic` for a 2D game | Wrong starting scene. Use `empty` and let the user/agent build the 2D root from there. |
83
+ | Use `summer create 3d-basic` for a 2D game | Its light and floor fight the painted look. Use `empty` and follow `painted-25d-world`. |
92
84
  | Default to a community template | That's `browse-templates`. This skill is specifically for "blank canvas." |
93
85
  | Continue into `fps-controller` automatically | Most users want to brainstorm or set art direction first. Stop and ask. |
94
86
  | Run this when the user is in an existing project | Check `summer status` or `summer_get_project_context` first. If a project is already open, the user probably wanted to modify it, not create a new one. |
95
87
 
96
88
  ## Edge cases
97
89
 
98
- - **Engine not running** → that's fine. `summer create` doesn't need the engine. After scaffolding, `summer run <name>` will start it.
99
- - **User wants 2D but `empty` is the only 2D-friendly built-in** → use `empty`, then set up a 2D scene root via `summer_replace_node` (Node3D → Node2D). Mention this — don't surprise the user.
100
- - **Directory exists** → the CLI errors out. Ask for a different name; don't try to overwrite.
90
+ - **Engine not running** → that's fine. `summer dev` (or `projects.open_local`) starts it; `summer create` alone doesn't need it.
91
+ - **User wants 2D or 2.5D** → use `empty`, keep the `Node3D` root and follow `painted-25d-world`. Use a `Node2D` root only when the user asks for a classic 2D tile or pixel game.
92
+ - **Directory exists** → a folder that already holds `project.godot` is just opened; one with other files is refused. Ask for a different name; don't try to overwrite.
101
93
 
102
94
  ## Closing
103
95
 
@@ -111,5 +103,6 @@ No Summer MCP tools in this session? Run each one as a command; when `summer --v
111
103
  | In this skill | Command |
112
104
  |---|---|
113
105
  | `summer_get_project_context` | `summer engine get-project-context` |
114
- | `summer_replace_node` | `summer engine replace-node` |
106
+ | `projects.create_local` | `summer projects create-local` |
107
+ | `projects.open_local` | `summer projects open-local` |
115
108
  <!-- /shell-commands -->
@@ -1,6 +1,6 @@
1
1
  id: skill/new-project
2
2
  kind: skill
3
- version: 1.0.4
3
+ version: 1.0.5
4
4
  summary: "Create a blank Summer Engine project: ask for the project name and run summer create empty."
5
5
  use_when:
6
6
  - the user wants a fresh blank Summer Engine project — from scratch, blank canvas
@@ -20,6 +20,7 @@ compatibility:
20
20
  related:
21
21
  skills:
22
22
  - skill/make-game
23
+ - skill/painted-25d-world
23
24
  source: official
24
25
  license: MIT
25
26
  status: stable
@@ -0,0 +1,366 @@
1
+ ---
2
+ name: painted-25d-world
3
+ description: "Build a 2D or 2.5D game as a painted world: a 3D blockout under one fixed camera, an AI paint-over projected onto it, sprite characters."
4
+ license: MIT
5
+ compatibility: [Cursor, Claude Code, Windsurf, Codex]
6
+ category: 2d
7
+ user-invocable: true
8
+ allowed-tools: Read Write Edit Bash summer_write_file summer_read_file summer_create_scene summer_add_node summer_set_prop summer_run_script summer_save_scene summer_screenshot summer_play summer_stop summer_get_script_errors summer_assets_generate_image summer_get_project_context summer_jobs_wait summer_import_from_url summer_call
9
+ paths: ["painted/**", "**/*.gdshader", "**/*.gd", "**/*.tscn"]
10
+ ---
11
+
12
+ # Painted 2.5D world
13
+
14
+ The world looks like one hand-painted illustration, but it is real 3D: the player walks behind houses, enters
15
+ buildings and collides with walls. The trick: build the level from cheap blocks, render the blocks from one fixed
16
+ camera, have an image model paint over that render, then project the painting back onto the blocks from the same
17
+ camera. Characters are 2D sprite sheets standing in the 3D world.
18
+
19
+ ## The rule
20
+
21
+ **Whenever a user asks for a 2D or 2.5D game** (top-down, RPG, cozy village, adventure, farming, dungeon,
22
+ side-scroller, platformer look), build it with this skill. Do not start from a 2D template or a Node2D tile map.
23
+ The genre playbooks in `make-game` still decide the mechanics; this skill decides how the world is made and looks.
24
+
25
+ - Top-down / three-quarter games: camera 30 degrees down, 45 degrees around (houses show two faces). Image
26
+ models draw "isometric" as 2:1 dimetric, which is exactly 30 degrees down; use 30 so the blockout can match a
27
+ generated concept.
28
+ - Side-scrollers: the same technique with a camera that looks along the side axis (about 10-20 degrees down,
29
+ 0 degrees around) and pans left and right only. Paint one frame per screen-wide chunk.
30
+
31
+ Tell the user once, before the first character generation or animation: "The world blockout is cheap. Animating
32
+ characters costs a couple of dollars in credits and can come out with mistakes; I will check every frame." Then
33
+ continue. The blockout, the camera and the projection cost nothing.
34
+
35
+ ## Hard rules (a playtest found each one)
36
+
37
+ 1. **Scale.** Doors 2.5 m. Hero height = door height / 1.15 (2.15 m). One-storey eaves 3.5-4 m, two-storey about
38
+ 6 m. Check the hero against a door in the first screenshot.
39
+ 2. **The gait follows the game type.** Cozy, exploration and RPG games walk by default (about 1.8 m/s, walk cycle)
40
+ and run on Shift (about 4 m/s, run cycle). Action games may run by default (about 4.2 m/s, run cycle). Never
41
+ play the run cycle for the default gait of a cozy game. `painted_player.gd`: `move_speed`, `sprint_speed`,
42
+ `run_cycle_from` (3 m/s).
43
+ 3. **Animation speed follows ground speed.** A cycle's natural speed is the ground speed at which its feet stick
44
+ (stride per cycle x cycles per second, scaled to the hero height). Each sheet json carries `height_m`,
45
+ `stride_m` and `cycles_per_s` per kind; `speed_scale = speed / natural speed`, clamped. The feet must not
46
+ slide. Never one fixed fps for every speed.
47
+ 4. **Framing.** The game camera shows about 16 m across (7-8 hero heights). Clamp it inside the painting with
48
+ the real viewport aspect, never an assumed 16:9. The clear colour is the painting's edge colour, per location.
49
+ Rooms are framed whole, like a stage.
50
+ 5. **At least one enterable building** in every village: a cut-away interior, same view direction, its own 4K
51
+ paint-over, door triggers both ways, a door gap of about 1.8 m. Blockout door and step slabs are hidden in the
52
+ game; the painting shows them.
53
+ 6. **Eight directions** for idle, walk and run: down, up, left, right, down_left, down_right, up_left, up_right.
54
+ One clip per direction and animation. Mirror only where every frame holds up (never asymmetric hair, a held
55
+ weapon or a walking stick). The player picks the facing by 45 degree sectors.
56
+ 7. **Blockout proportions from the concept.** Dormers sit on the roof slope (never floating); gables and roofs
57
+ from measured concept pixels; doors 2.5 m; a low block for every flower bed, barrel and crate.
58
+ 8. **No long cast shadows in the paint.** "Soft short contact shadows only, no long cast shadows on the ground":
59
+ baked long shadows look wrong once the hero walks through them.
60
+ 9. **Verify in a real window.** Run the game with `-- --shots=<dir>`: `painted_world.gd` walks and runs the hero
61
+ through `shot_plan` (add a walk through each door) and saves a JPG per step. Look at every frame.
62
+ 10. **Generate a walk whose stride fits the default speed.** Keep the walk cycle's playback within about 1.5x
63
+ (`speed / natural <= 1.5`): a short-step clip played fast looks wrong. Measure the natural walk speed; if it
64
+ is too low, regenerate the walk clips with the brisk long-stride prompt (step 9). The plug-in walks are natural
65
+ at about 1.25-1.4 m/s at 2.15 m, so 1.8 m/s plays at 1.3-1.45x. Short, 4-heads-tall characters reach about
66
+ half a body height per cycle at most; taller proportions (6-7 heads) give longer strides.
67
+
68
+ ## Steps
69
+
70
+ ### 0. The project and the engine
71
+
72
+ - No project yet: `summer create empty <name>` (or write a plain `project.godot`), open it with
73
+ `summer run <path>`, and check that `summer_get_project_context` answers for that project.
74
+ - `engine_not_running` while an editor is open: the editor was started with another HOME, or the MCP is bound to
75
+ a different editor. Start this project's editor with `summer run <path>`, or drive it from a shell with the CLI
76
+ and `SUMMER_ENGINE_PROJECT=<path>` set.
77
+ - Image generation through Summer: always pass an `idempotencyKey` and `numImages: 1`. A call that answers
78
+ `outcome_unknown` (a timeout) may still run and charge: retry with the **same** key, never a new one.
79
+
80
+ ### 1. Concept (one image)
81
+
82
+ `summer_assets_generate_image` with `model: "seedream-5-pro"`, `width` 2048, `height` 1152 (the largest 16:9
83
+ image Summer's models return; the others stop near 1024x576):
84
+
85
+ ```
86
+ Hand-painted illustration of <place>, rich detail, warm painterly light, seen from a high three-quarter
87
+ top-down camera (looking down about 30 degrees, orthographic, no perspective distortion), like a tilted
88
+ isometric game map. In the scene: <every object with its rough position: "three cottages around a dirt
89
+ plaza, a well with a small roof in the centre, a striped market stall top left, fences, round trees">.
90
+ Clean readable shapes, soft brush texture, no characters, no text, no UI, no border.
91
+ ```
92
+
93
+ Pick the image the user likes. It is the art direction and the layout.
94
+
95
+ ### 2. Blockout (cheap: you write it)
96
+
97
+ Write one GDScript or scene that rebuilds the concept **one to one** from the fixed camera: the same building
98
+ positions and footprints, roof shapes (gable, hip, dormers on the slope, thatch overhang), chimneys, the well, the
99
+ stall, fences, paths, trees and bushes where the concept has them. Use `MeshInstance3D` with `BoxMesh`,
100
+ `PrismMesh`, `CylinderMesh`, `SphereMesh` (not CSG: only MeshInstance3D nodes get the painting). Give each
101
+ material one flat colour (red = tile roof, yellow =
102
+ thatch, dark blue = slate, cream = plaster walls, grey = stone, brown = wood, tall brown slabs = doors, green =
103
+ grass, pink low blocks = flower beds): the colours tell the painter what each block is, and the paint-over prompt
104
+ repeats them as a colour key. Name door and step slabs `..._door` / `..._steps`: they are hidden in the game.
105
+
106
+ ```
107
+ World (Node3D, painted_world.gd: player_path, start_location)
108
+ Village Node3D, painted_location.gd (paint, frame_whole = false)
109
+ PaintCamera Camera3D ORTHOGONAL, KEEP_WIDTH, size = frame width in metres (40 for a village square)
110
+ rotation_degrees = Vector3(-30, 45, 0) # 30 down, 45 around; never change it later
111
+ position = frame centre - forward * 60, far = 200
112
+ Painted Node3D every block (or blockout_builder.gd reading a spec), Ground walkable
113
+ Cottage Node3D, painted_location.gd (frame_whole = true), 100 m off to the side
114
+ PaintCamera same rotation, size 14 for a 9 x 7.5 m room
115
+ Painted ...
116
+ DoorIn Area3D, painted_door.gd (to = Cottage, spawn = a Marker3D inside the room)
117
+ DoorOut Area3D, painted_door.gd (to = Village, spawn = a Marker3D outside the village door)
118
+ GameCamera Camera3D
119
+ Player CharacterBody3D, painted_player.gd (sheet, sheet_json)
120
+ ```
121
+
122
+ One world script owns the player, the camera and the doors; locations never move the player themselves.
123
+ `painted_world.gd` sets the player up after every child is ready, so the node order is free.
124
+
125
+ In a `.tscn`, the paint camera line for 30 down, 45 around is (Godot writes the basis by rows; hand-written
126
+ columns give a wrong camera):
127
+ `transform = Transform3D(0.707107, -0.353553, 0.612372, 0, 0.866025, 0.5, -0.707107, -0.353553, 0.612372, cx + 36.742, cy + 30, cz + 36.742)`
128
+ for a frame centred on (cx, cy, cz), 60 m back along the view.
129
+
130
+ **Write the blockout as a spec** (`_building-blocks/blockout_builder.gd` documents the JSON: box, prism, cyl,
131
+ sphere, poly ground, invisible wall blockers). The same file drives the engine (the builder is the location's
132
+ `Painted` node) and an engine-free wireframe preview over the concept (`tools/preview.py`), so the fitting loop
133
+ needs no engine runs.
134
+
135
+ - **Gable roofs are two parts:** a wall-coloured prism for the gable triangle plus two thin slanted roof slabs
136
+ with an overhang. A single roof-coloured prism makes the painter paint roof on the gable wall.
137
+ - **Edges and water:** put invisible `wall` blockers along water and ledge edges, with gaps at pier roots and
138
+ doorways. Ground made from a polygon is one-sided: use the spec's `poly` (two-sided collision) or a box.
139
+
140
+ Solid things get a `StaticBody3D` and a box/cylinder shape: walls, trunks, fence posts, the well, furniture.
141
+ Things the player walks behind need real height (houses, trees, stalls).
142
+
143
+ **Paint richness follows blockout density.** The painter details what the blocks give it. Add low blocks for
144
+ flower beds, barrels, crates, benches, lanterns and window boxes wherever the concept has them; a sparse blockout
145
+ comes back as a sparse painting. Only truly flat detail (cobbles, rugs, grass) can stay paint-only.
146
+
147
+ **Match the concept.** Read positions straight from the concept by inverting the orthographic camera
148
+ (`tools/cam.py <height> <px,py> ...` does it). With the
149
+ concept W x H pixels, `s` = pixels per metre (W / frame width), `elev` = 30 degrees and a pixel (sx, sy) on the
150
+ ground (a wall's bottom corner):
151
+
152
+ ```
153
+ u = (sx - W/2) / s # metres along the camera's right axis
154
+ v = (H/2 - sy) / (s * sin(elev)) # metres along the ground, away from the camera
155
+ height = dy / (s * cos(elev)) # a vertical edge dy pixels long (wall, ridge, chimney)
156
+ world = target + right_ground * u + far_ground * v
157
+ ```
158
+
159
+ Three wall-bottom corners give a footprint; the ridge gives the roof height. Draw the spec over the concept with
160
+ `tools/preview.py` and move blocks until the red silhouettes line up, then build it in the engine.
161
+ If the blockout does not match the concept, the painting will not match the blocks.
162
+
163
+ ### 3. Render the blockout from the paint camera
164
+
165
+ - Play with the location's `paint` left empty: `painted_world.gd` then shows the blockout through that
166
+ `PaintCamera`, lit by a sun and ambient light so its faces read (an unlit blockout comes out near black).
167
+ `summer_screenshot` `target: "game"` captures it.
168
+ - Exact PNG for the painter: copy `_building-blocks/capture_paint_view.gd`, make a scene with just that node
169
+ (`level` = the world scene, `camera_path` = the location's camera, `size` = 2048x1152), and play it in a run
170
+ that renders (the editor, or a windowed run; `--headless` renders nothing). It saves
171
+ `res://painted/blockout.png` and quits.
172
+ - `summer_screenshot` `target: "scene"` renders the saved scene without running scripts: a blockout built by a
173
+ script or the spec builder shows nothing there.
174
+
175
+ Then upload it: `summer_call` `assets.upload_begin`, post its form fields plus the file to `uploadUrl`, then
176
+ `assets.upload_complete` with `publicId`, `version`, `uploadSignature` (the `signature` of the upload's answer)
177
+ and `format`. Its answer carries the `fileUrl`.
178
+
179
+ ### 4. Paint-over (strict image to image)
180
+
181
+ **Never pass the whole concept as a reference.** Even when the blockout rebuilds it one to one, frontier edit
182
+ models copy the full concept and ignore the blocks. Pass a **material sheet** instead: a 2x2 grid of close-up
183
+ crops from the concept (for a village: clay-tile roof with a timber-framed wall, thatch, market stall with
184
+ cobbles, slate roof with flower beds). It carries the style and materials but no layout.
185
+
186
+ With two images (image 1 = blockout render, image 2 = material sheet), the best frontier edit model you have, 16:9,
187
+ the largest size (4K):
188
+
189
+ ```
190
+ Image 1 is a flat-coloured 3D blockout render of <place> from a fixed game camera. Image 2 is a sheet of four
191
+ close-up material samples from the finished concept art (<the four samples>). Image 2 is a style and
192
+ material reference only: never copy its layout or composition.
193
+ Repaint image 1 in exactly that style, materials, light and detail. This is a strict image-to-image
194
+ paint-over: keep every shape, edge and position of image 1 identical, pixel-aligned. Same camera, same
195
+ framing. Every <building, roof, chimney, dormer, door, steps, well, stall, crate, bench, barrel, fence, tree and
196
+ bush> stays exactly where image 1 has it, with exactly the same silhouette and size. Do not add, remove or move
197
+ anything. Do not add extra props, buildings or trees. Only paint surface detail inside the existing shapes.
198
+ Colour key of image 1: red = clay-tile roof, yellow = golden thatch roof, dark blue = slate roof, cream =
199
+ timber-framed plaster walls, grey = mossy stone (chimneys, well, low walls, steps), brown = worn wood (tall
200
+ brown slabs on walls = wooden doors), light brown floor = cobblestone plaza, green ground = grass, green
201
+ spheres = round leafy tree canopies, small green domes = flowering bushes, orange = lit lanterns and fruit
202
+ crates, pink low blocks = dense flower beds and window boxes.
203
+ <Light and finish: e.g. warm golden late-afternoon light, soft short contact shadows only (no long cast shadows
204
+ on the ground), glowing windows, painterly near-realistic detail as in image 2: ivy on walls, moss on stones,
205
+ rich textures>. No characters, no text, no border.
206
+ ```
207
+
208
+ `summer_assets_generate_image` takes one `referenceImageUrl` (the blockout render): put the material and
209
+ style description into the prompt in words and keep the colour key. Use `model: "seedream-5-pro"`, `width`
210
+ 2048, `height` 1152, `numImages: 1` and an `idempotencyKey`: it holds pixel alignment well and is the only
211
+ Summer model that returns 2048 px.
212
+
213
+ **Check alignment before you use it.** Overlay the blockout's edges (red) on the painting
214
+ (`tools/overlay.py <blockout.png> <painting.png> <out.png>`) and look: roof lines,
215
+ wall corners, the well and the stall must sit on the red lines. Reject any painting where objects moved, were
216
+ added, or the framing zoomed; generate again rather than project a drifted painting.
217
+
218
+ ### 5. Resolution
219
+
220
+ Painting pixels per metre must be at least the screen's pixels per metre. A 4K painting (about 5500 px) over a
221
+ 40 m frame gives 137 px/m; a 16 m view on a 1080p-class game view needs about 96-120 px/m, so it stays sharp. A
222
+ 2048 px painting over 32 m (64 px/m) is soft at that view. For bigger worlds use more frames, not a wider frame.
223
+
224
+ **4K through Summer:** no Summer image model returns 4K. `tools/detail4k.py <painting_2k.png> <out_dir> "<style
225
+ words>"` upscales the 2K paint-over 2x, cuts nine overlapping 2048x1152 tiles, runs a strict "redraw sharper,
226
+ pixel-aligned" image-to-image pass on each with `seedream-5-pro` and blends them back. Nine generations; the
227
+ alignment holds.
228
+
229
+ ### 6. Projection in the engine
230
+
231
+ Copy `_building-blocks/paint_projection.gdshader`, `painted_location.gd`, `painted_world.gd`,
232
+ `painted_door.gd` and `painted_player.gd` to `res://painted/`. Set each location's `paint`. On `_ready` a
233
+ location puts one `ShaderMaterial` on every mesh under its `Painted`; the shader takes each surface point's
234
+ position in that location's paint camera frame as its UV. No UV unwrapping, no baking.
235
+
236
+ - Keep the scene's tonemap **Linear**, exposure 1, no glow, no fog: the painting already holds the light.
237
+ - Import the painting lossless (Import dock: Compress Mode Lossless, mipmaps on); VRAM compression smears it.
238
+ - Verify: `_building-blocks/paintcam_check.gd` renders the painted world through a `PaintCamera` to a PNG; it
239
+ must match the painting. Then play and look at the real window (hard rule 9).
240
+
241
+ ### 7. Camera rules
242
+
243
+ - The game camera has the paint camera's direction and only **moves** (follows the player). With an orthographic
244
+ camera, moving never reveals a surface the painting did not see. Never orbit or tilt it: turned views show the
245
+ painting's mistakes (a painted chimney next to the real one, roof edges smeared on the ground).
246
+ - Outdoors it shows about 16 m across; rooms are framed whole. `painted_world.gd` sizes and clamps it with the
247
+ real viewport aspect and sets the clear colour to the painting's edge colour.
248
+ - More world = more frames. Every frame uses the same direction, its own paint camera position and painting.
249
+ Paint neighbouring frames with an overlap strip so the seams match.
250
+
251
+ ### 8. Interiors
252
+
253
+ Every village gets at least one enterable building. Each interior is its own location far away (for example 100 m
254
+ off to the side) with the **same** camera direction and a frame that holds the whole room with its back walls
255
+ (14 m for a 9 x 7.5 m room; 12 m cut the walls off), `frame_whole = true`. Lower
256
+ the two walls nearest the camera to knee height (a dollhouse cut-away) and leave a door gap of about 1.8 m.
257
+ Blockout, render, paint over (its own 4K paint-over, the same rules and colour key: warm floorboards, plaster,
258
+ beams, fireplace, bed, shelves, rug, "keep the area outside the room plain flat dark") and project exactly like
259
+ the outside. `painted_door.gd` triggers go both ways; put each spawn marker clear of the other door's trigger.
260
+
261
+ ### 9. Characters
262
+
263
+ 1. **Ready-made:** use the painted plug-in characters first: a man, a woman, the man with a sword and an old man,
264
+ 8 directions, idle, walk and run (`hero_m_sword`: idle and walk). They live in the public repo
265
+ `SummerEngine/painted-characters`, pinned at commit `c70dae1b4043656ad23d5ab6d76fe992f593b6ba`. For `<id>`, import
266
+ `https://raw.githubusercontent.com/SummerEngine/painted-characters/c70dae1b4043656ad23d5ab6d76fe992f593b6ba/characters/<id>/<file>`
267
+ for the three files `<id>_sheet.png`, `<id>_sheet.json` and `<id>_frames.tres` into `res://characters/<id>/`
268
+ (`summer_import_from_url`; the `.tres` expects that path), then set `sheet` = `<id>_sheet.png` and
269
+ `sheet_json` = `<id>_sheet.json` on `painted_player.gd`. With a shell, `git clone` the repo and copy
270
+ `characters/` to the project root. Need a different look: make one.
271
+ 2. **New character:** generate an 8-pose turnaround (or two 4-pose sheets) in the world's style on flat pure
272
+ green:
273
+ ```
274
+ Character turnaround sheet in the art style of <the world>: <character>. Draw the same character 8 times,
275
+ same size, feet on one baseline: facing down toward the viewer, down-left, left, up-left, up (back view),
276
+ up-right, right, down-right. Seen from a high three-quarter top-down camera. Plain flat pure green
277
+ background (#00FF00), no ground, no shadows, no text.
278
+ ```
279
+ Crop each pose, pad it to 9:16 with the same green, upload it, then `summer_call` `assets.generate_video`
280
+ (`model: "minimax-h3-max"`, `aspectRatio: "9:16"`, 5 s, an `idempotencyKey`): one clip per direction and
281
+ animation:
282
+ ```
283
+ The character, <facing>, walks in place on the spot with a brisk, purposeful walk cycle: long confident strides, heel to toe, the front leg reaching far forward and the back leg pushing far back, arms swinging strongly opposite the legs, upright posture. The character
284
+ stays exactly centred at the same size and never moves across the frame or turns. Static locked camera, no
285
+ zoom. The plain flat pure green background stays perfectly flat and unchanged. Seamless loop.
286
+ ```
287
+ That is the walk prompt for a default walk (a plain "steady, simple walk cycle" takes short steps and must be
288
+ over-sped). For a longer stride still: "walks in place on the spot with a long-legged power walk: very wide
289
+ steps, at each step the front heel lands far ahead and the back foot pushes off far behind, legs nearly fully
290
+ extended front to back, arms swinging wide, a quick purposeful pace."
291
+ Idle: "stands still in a relaxed idle: gentle breathing, one blink, feet planted". Run: "runs in place".
292
+ 3. **Clip to sheet** (host with a shell and ffmpeg): key out the green by colour, take one cycle (skip the
293
+ first second), sample 8 frames evenly, crop every frame of every clip with the **same** box so the feet stay
294
+ on one line, and tile them into one sheet: one row per animation and direction (`idle_down`,
295
+ `walk_up_left`, `run_right`, ...). Write the json beside it: `{"cell_w", "cell_h", "frames", "rows",
296
+ "fps": {"idle", "walk", "run"}, "height_m", "stride_m": {"walk", "run"}, "cycles_per_s": {"walk", "run"}}`.
297
+ Measure once per kind: `stride_m` = how far a planted foot slides back during one cycle at `height_m`,
298
+ `cycles_per_s` = cycles per second at the sheet's fps. Look at every frame; regenerate a clip with a broken
299
+ frame.
300
+ Without video: `summer_call` `assets.generate_sprite_sheet` (8-frame walk from one picture, per direction).
301
+ 4. **In the game:** `painted_player.gd` makes an `AnimatedSprite3D`: Y-billboard, unshaded, alpha cut (so painted
302
+ walls hide the character), height stretched by `1 / cos(camera pitch)`, 8 facings by 45 degree sectors (a
303
+ missing diagonal falls back to its side row), the game-type gait (hard rule 2), animation speed = speed /
304
+ natural speed.
305
+ Spawn points 0.5 m or more away from walls, or the flat card cuts into them.
306
+
307
+ ### 10. Weapons
308
+
309
+ - **Variant sheet (best look):** edit the turnaround so the character holds the weapon, then animate the clips
310
+ again. One extra sheet per weapon. Never mirror a sheet with a held weapon.
311
+ - **Held sprite layer (cheap):** a second `Sprite3D` child with the weapon, a per-direction offset and draw order
312
+ (behind the body when facing up). Good for many weapons; the hand will not wrap around the grip.
313
+
314
+ ## Common mistakes
315
+
316
+ - **The whole concept as a reference:** the painting copies the concept and ignores the blocks, even when the
317
+ blockout matches it. Pass a 2x2 material sheet cropped from the concept.
318
+ - **A sparse blockout:** the painting comes back sparse. Add low blocks for flower beds, crates, barrels, benches.
319
+ - **35 degrees against a generated concept:** generated "isometric" art is 30 degrees down; the blocks will not fit.
320
+ - **A tiny or giant hero:** check the hero against a door (door = hero x 1.15) in the first screenshot.
321
+ - **Sliding feet or the wrong gait:** speed_scale = speed / natural; cozy games walk by default and run on Shift.
322
+ - **4096 px asked from Summer's image models:** refused. 2048x1152 with seedream-5-pro, then the tiled 4K pass.
323
+ - **A new idempotencyKey after a timeout:** pays twice. Retry with the same key; keep numImages 1.
324
+ - **An unlit blockout capture, CSG blocks, a one-sided polygon ground, no water blockers:** see steps 2 and 3.
325
+ - **Long baked shadows:** they lie on the ground while the hero walks through them. Contact shadows only.
326
+ - **Floating dormers, blockout door slabs left visible:** dormers on the slope; hide door and step slabs.
327
+ - **Rotating the game camera:** shows painted detail on the wrong surfaces. Translate only.
328
+ - **Filmic/ACES tonemap or lights on painted meshes:** colours shift. Unshaded material, Linear tonemap.
329
+ - **Perspective camera:** moving it reveals hidden faces. Use orthographic.
330
+ - **Assuming a 16:9 window:** the clamp shows past the painting in the editor's game view. Use the real aspect.
331
+
332
+ ## Optional: Blender route
333
+
334
+ If the host has Blender, `_building-blocks/blender-route.md` bakes the same projection into ordinary UVs and
335
+ exports glTF; use it when the scene must ship as plain textured meshes.
336
+
337
+ ## See also
338
+
339
+ - `make-game` (genre mechanics), `concept-art`, `sprite-sheet`, `scene-composition`
340
+
341
+ <!-- shell-commands: generated from the operation catalog by npm run generate:registry; do not edit by hand -->
342
+ ## From a shell
343
+
344
+ No Summer MCP tools in this session? Run each one as a command; when `summer --version` is missing or below 4.0, use `npx -y summer-engine@latest` in place of `summer`. Fields are flags in kebab-case (`--scene-path res://main.tscn`) or one `--input '<json>'`, and `summer ops describe <op>` prints the exact input. The `summer-cli` skill has the rest.
345
+
346
+ | In this skill | Command |
347
+ |---|---|
348
+ | `summer_assets_generate_image` | `summer assets generate-image` |
349
+ | `assets.generate_video` | `summer assets generate-video` |
350
+ | `assets.upload_begin` | `summer assets upload-begin` |
351
+ | `assets.upload_complete` | `summer assets upload-complete` |
352
+ | `summer_add_node` | `summer engine add-node` |
353
+ | `summer_create_scene` | `summer engine create-scene` |
354
+ | `summer_get_project_context` | `summer engine get-project-context` |
355
+ | `summer_get_script_errors` | `summer engine get-script-errors` |
356
+ | `summer_import_from_url` | `summer engine import-from-url` |
357
+ | `summer_play` | `summer engine play` |
358
+ | `summer_read_file` | `summer engine read-file` |
359
+ | `summer_run_script` | `summer engine run-script` |
360
+ | `summer_save_scene` | `summer engine save-scene` |
361
+ | `summer_screenshot` | `summer engine screenshot` |
362
+ | `summer_set_prop` | `summer engine set-prop` |
363
+ | `summer_stop` | `summer engine stop` |
364
+ | `summer_write_file` | `summer engine write-file` |
365
+ | `summer_jobs_wait` | `summer jobs wait` |
366
+ <!-- /shell-commands -->
@@ -0,0 +1,33 @@
1
+ # Blender route: bake the projection into UVs
2
+
3
+ Use this only when the host has Blender and the level must ship as plain textured meshes (no projection shader).
4
+ It gives the same picture as `paint_projection.gdshader`.
5
+
6
+ 1. Build the blockout in Blender with the same orthographic camera: rotation (60, 0, 45) degrees in Blender's
7
+ Z-up axes (90 - 30 down, 45 around), `ortho_scale` = frame width in metres. Render it (Workbench, studio light,
8
+ outlines on) at 2048x1152 or larger.
9
+ 2. Paint over the render (SKILL.md step 4) and resize the painting to the exact render size.
10
+ 3. Project: for every mesh, add one UV layer and set each loop's UV to the camera-view position of its vertex.
11
+
12
+ ```python
13
+ import bpy
14
+ from bpy_extras.object_utils import world_to_camera_view
15
+
16
+ scene, cam = bpy.context.scene, bpy.data.objects["PaintCamera"]
17
+ for ob in bpy.data.collections["blockout"].objects:
18
+ if ob.type != "MESH":
19
+ continue
20
+ me = ob.data
21
+ uv = me.uv_layers.new(name="proj")
22
+ uv.active = uv.active_render = True
23
+ for loop in me.loops:
24
+ p = world_to_camera_view(scene, cam, ob.matrix_world @ me.vertices[loop.vertex_index].co)
25
+ uv.data[loop.index].uv = (p.x, p.y)
26
+ ```
27
+
28
+ With an orthographic camera the UVs are exact per vertex, so no subdivision is needed.
29
+ 4. One material for all meshes: the painting as base colour (texture extension EXTEND). Export glTF with separate
30
+ textures. Name solid objects `<name>-col` so the engine adds collision on import.
31
+ 5. In the engine, override every imported mesh with an unshaded `StandardMaterial3D` that uses the painting, and
32
+ import the painting lossless. Blender (x, y, z) is engine (x, z, -y): rebuild the paint camera from the same
33
+ 30 / 45 degree direction with `keep_aspect` KEEP_WIDTH and `size` = the ortho scale.