spawnpoint-studio 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 (125) hide show
  1. spawnpoint_studio-0.1.0/LICENSE +21 -0
  2. spawnpoint_studio-0.1.0/MANIFEST.in +4 -0
  3. spawnpoint_studio-0.1.0/PKG-INFO +360 -0
  4. spawnpoint_studio-0.1.0/README.md +336 -0
  5. spawnpoint_studio-0.1.0/compiler/spawnpoint/__init__.py +3 -0
  6. spawnpoint_studio-0.1.0/compiler/spawnpoint/analyze.py +387 -0
  7. spawnpoint_studio-0.1.0/compiler/spawnpoint/build.py +146 -0
  8. spawnpoint_studio-0.1.0/compiler/spawnpoint/cli.py +290 -0
  9. spawnpoint_studio-0.1.0/compiler/spawnpoint/cockpit/__init__.py +0 -0
  10. spawnpoint_studio-0.1.0/compiler/spawnpoint/cockpit/server.py +473 -0
  11. spawnpoint_studio-0.1.0/compiler/spawnpoint/cockpit/static/app.css +111 -0
  12. spawnpoint_studio-0.1.0/compiler/spawnpoint/cockpit/static/app.js +327 -0
  13. spawnpoint_studio-0.1.0/compiler/spawnpoint/cockpit/static/index.html +79 -0
  14. spawnpoint_studio-0.1.0/compiler/spawnpoint/diagnostics.py +91 -0
  15. spawnpoint_studio-0.1.0/compiler/spawnpoint/expr.py +219 -0
  16. spawnpoint_studio-0.1.0/compiler/spawnpoint/gif.py +58 -0
  17. spawnpoint_studio-0.1.0/compiler/spawnpoint/godot.py +107 -0
  18. spawnpoint_studio-0.1.0/compiler/spawnpoint/graph.py +175 -0
  19. spawnpoint_studio-0.1.0/compiler/spawnpoint/level.py +157 -0
  20. spawnpoint_studio-0.1.0/compiler/spawnpoint/llm_server.py +77 -0
  21. spawnpoint_studio-0.1.0/compiler/spawnpoint/manifest.py +222 -0
  22. spawnpoint_studio-0.1.0/compiler/spawnpoint/playtest/__init__.py +104 -0
  23. spawnpoint_studio-0.1.0/compiler/spawnpoint/playtest/report.py +148 -0
  24. spawnpoint_studio-0.1.0/compiler/spawnpoint/playtest/runner.py +51 -0
  25. spawnpoint_studio-0.1.0/compiler/spawnpoint/playtest/tuner.py +151 -0
  26. spawnpoint_studio-0.1.0/compiler/spawnpoint/project.py +94 -0
  27. spawnpoint_studio-0.1.0/compiler/spawnpoint/py.typed +0 -0
  28. spawnpoint_studio-0.1.0/compiler/spawnpoint/rules.py +310 -0
  29. spawnpoint_studio-0.1.0/compiler/spawnpoint/sfx.py +352 -0
  30. spawnpoint_studio-0.1.0/compiler/spawnpoint/sprites/__init__.py +0 -0
  31. spawnpoint_studio-0.1.0/compiler/spawnpoint/sprites/ai.py +222 -0
  32. spawnpoint_studio-0.1.0/compiler/spawnpoint/sprites/contour.py +147 -0
  33. spawnpoint_studio-0.1.0/compiler/spawnpoint/sprites/generate.py +507 -0
  34. spawnpoint_studio-0.1.0/compiler/spawnpoint/sprites/importer.py +212 -0
  35. spawnpoint_studio-0.1.0/compiler/spawnpoint/sprites/resolve.py +139 -0
  36. spawnpoint_studio-0.1.0/compiler/spawnpoint/sprites/spriteset.py +159 -0
  37. spawnpoint_studio-0.1.0/compiler/spawnpoint/sprites/tiles.py +102 -0
  38. spawnpoint_studio-0.1.0/compiler/spawnpoint/studio/__init__.py +0 -0
  39. spawnpoint_studio-0.1.0/compiler/spawnpoint/studio/assemble.py +528 -0
  40. spawnpoint_studio-0.1.0/compiler/spawnpoint/studio/brief.py +197 -0
  41. spawnpoint_studio-0.1.0/compiler/spawnpoint/studio/creative.py +124 -0
  42. spawnpoint_studio-0.1.0/compiler/spawnpoint/studio/dataset.py +136 -0
  43. spawnpoint_studio-0.1.0/compiler/spawnpoint/studio/edits.py +206 -0
  44. spawnpoint_studio-0.1.0/compiler/spawnpoint/studio/levelgen.py +352 -0
  45. spawnpoint_studio-0.1.0/compiler/spawnpoint/studio/llm.py +145 -0
  46. spawnpoint_studio-0.1.0/compiler/spawnpoint/studio/orchestrator.py +341 -0
  47. spawnpoint_studio-0.1.0/compiler/spawnpoint/studio/prompts.py +122 -0
  48. spawnpoint_studio-0.1.0/compiler/spawnpoint/studio/web.py +123 -0
  49. spawnpoint_studio-0.1.0/compiler/spawnpoint/studio/webcheck.py +210 -0
  50. spawnpoint_studio-0.1.0/compiler/spawnpoint/studio_cli.py +232 -0
  51. spawnpoint_studio-0.1.0/compiler/spawnpoint_studio.egg-info/PKG-INFO +360 -0
  52. spawnpoint_studio-0.1.0/compiler/spawnpoint_studio.egg-info/SOURCES.txt +123 -0
  53. spawnpoint_studio-0.1.0/compiler/spawnpoint_studio.egg-info/dependency_links.txt +1 -0
  54. spawnpoint_studio-0.1.0/compiler/spawnpoint_studio.egg-info/entry_points.txt +2 -0
  55. spawnpoint_studio-0.1.0/compiler/spawnpoint_studio.egg-info/requires.txt +6 -0
  56. spawnpoint_studio-0.1.0/compiler/spawnpoint_studio.egg-info/top_level.txt +2 -0
  57. spawnpoint_studio-0.1.0/compiler/tests/conftest.py +49 -0
  58. spawnpoint_studio-0.1.0/compiler/tests/test_ai_sprites.py +122 -0
  59. spawnpoint_studio-0.1.0/compiler/tests/test_analyze.py +116 -0
  60. spawnpoint_studio-0.1.0/compiler/tests/test_cockpit.py +148 -0
  61. spawnpoint_studio-0.1.0/compiler/tests/test_e2e.py +33 -0
  62. spawnpoint_studio-0.1.0/compiler/tests/test_expr.py +59 -0
  63. spawnpoint_studio-0.1.0/compiler/tests/test_gif.py +19 -0
  64. spawnpoint_studio-0.1.0/compiler/tests/test_godot_library.py +17 -0
  65. spawnpoint_studio-0.1.0/compiler/tests/test_graph.py +44 -0
  66. spawnpoint_studio-0.1.0/compiler/tests/test_level.py +64 -0
  67. spawnpoint_studio-0.1.0/compiler/tests/test_live_llm.py +38 -0
  68. spawnpoint_studio-0.1.0/compiler/tests/test_manifest.py +54 -0
  69. spawnpoint_studio-0.1.0/compiler/tests/test_playtest.py +129 -0
  70. spawnpoint_studio-0.1.0/compiler/tests/test_rules.py +85 -0
  71. spawnpoint_studio-0.1.0/compiler/tests/test_sfx.py +30 -0
  72. spawnpoint_studio-0.1.0/compiler/tests/test_sprites.py +261 -0
  73. spawnpoint_studio-0.1.0/compiler/tests/test_studio.py +335 -0
  74. spawnpoint_studio-0.1.0/compiler/tests/test_web.py +41 -0
  75. spawnpoint_studio-0.1.0/examples/coin_hopper.json +228 -0
  76. spawnpoint_studio-0.1.0/examples/neon_arena.json +251 -0
  77. spawnpoint_studio-0.1.0/examples/pixel_arena.json +242 -0
  78. spawnpoint_studio-0.1.0/examples/pixel_hopper.json +221 -0
  79. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/aim_component.gd +63 -0
  80. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/animator_component.gd +66 -0
  81. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/chase_ai_component.gd +107 -0
  82. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/collectible_component.gd +58 -0
  83. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/gate_component.gd +64 -0
  84. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/health_component.gd +83 -0
  85. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/hitbox_component.gd +50 -0
  86. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/hurtbox_component.gd +48 -0
  87. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/juice_component.gd +219 -0
  88. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/patrol_ai_component.gd +63 -0
  89. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/platformer_movement_component.gd +204 -0
  90. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/player_input_component.gd +77 -0
  91. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/projectile_component.gd +64 -0
  92. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/spawner_component.gd +58 -0
  93. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/stomp_component.gd +56 -0
  94. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/top_down_movement_component.gd +101 -0
  95. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/trigger_zone_component.gd +32 -0
  96. spawnpoint_studio-0.1.0/godot/addons/spawn_point/components/weapon_component.gd +83 -0
  97. spawnpoint_studio-0.1.0/godot/addons/spawn_point/manifest.json +1509 -0
  98. spawnpoint_studio-0.1.0/godot/addons/spawn_point/runtime/camera_rig.gd +71 -0
  99. spawnpoint_studio-0.1.0/godot/addons/spawn_point/runtime/cockpit.gd +62 -0
  100. spawnpoint_studio-0.1.0/godot/addons/spawn_point/runtime/entity_core.gd +98 -0
  101. spawnpoint_studio-0.1.0/godot/addons/spawn_point/runtime/fx.gd +112 -0
  102. spawnpoint_studio-0.1.0/godot/addons/spawn_point/runtime/game_state.gd +111 -0
  103. spawnpoint_studio-0.1.0/godot/addons/spawn_point/runtime/hud.gd +155 -0
  104. spawnpoint_studio-0.1.0/godot/addons/spawn_point/runtime/level.gd +19 -0
  105. spawnpoint_studio-0.1.0/godot/addons/spawn_point/runtime/sfx.gd +58 -0
  106. spawnpoint_studio-0.1.0/godot/addons/spawn_point/runtime/sp.gd +121 -0
  107. spawnpoint_studio-0.1.0/godot/addons/spawn_point/runtime/world.gd +130 -0
  108. spawnpoint_studio-0.1.0/godot/addons/spawn_point/shaders/flash.gdshader +9 -0
  109. spawnpoint_studio-0.1.0/godot/addons/spawn_point/shaders/floor_grid.gdshader +13 -0
  110. spawnpoint_studio-0.1.0/godot/addons/spawn_point/tools/build.gd +612 -0
  111. spawnpoint_studio-0.1.0/godot/addons/spawn_point/tools/build.tscn +6 -0
  112. spawnpoint_studio-0.1.0/godot/addons/spawn_point/tools/capture.gd +42 -0
  113. spawnpoint_studio-0.1.0/godot/addons/spawn_point/tools/capture.tscn +6 -0
  114. spawnpoint_studio-0.1.0/godot/addons/spawn_point/tools/dump_manifest.gd +91 -0
  115. spawnpoint_studio-0.1.0/godot/addons/spawn_point/tools/dump_manifest.tscn +6 -0
  116. spawnpoint_studio-0.1.0/godot/addons/spawn_point/tools/playtest.gd +428 -0
  117. spawnpoint_studio-0.1.0/godot/addons/spawn_point/tools/playtest.tscn +6 -0
  118. spawnpoint_studio-0.1.0/godot/addons/spawn_point/tools/playtest_nav.gd +152 -0
  119. spawnpoint_studio-0.1.0/godot/addons/spawn_point/tools/record.gd +89 -0
  120. spawnpoint_studio-0.1.0/godot/addons/spawn_point/tools/record.tscn +6 -0
  121. spawnpoint_studio-0.1.0/godot/addons/spawn_point/tools/smoke.gd +72 -0
  122. spawnpoint_studio-0.1.0/godot/addons/spawn_point/tools/smoke.tscn +6 -0
  123. spawnpoint_studio-0.1.0/pyproject.toml +41 -0
  124. spawnpoint_studio-0.1.0/setup.cfg +4 -0
  125. spawnpoint_studio-0.1.0/setup.py +22 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 smoky1496
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.
@@ -0,0 +1,4 @@
1
+ include README.md LICENSE setup.py
2
+ recursive-include godot/addons/spawn_point *.gd *.tscn *.gdshader *.json
3
+ recursive-include examples *.json
4
+ recursive-include compiler/spawnpoint/cockpit/static *
@@ -0,0 +1,360 @@
1
+ Metadata-Version: 2.4
2
+ Name: spawnpoint-studio
3
+ Version: 0.1.0
4
+ Summary: Turn a sentence into a juicy, playable Godot 4 game — locally, on a consumer GPU.
5
+ Author: smoky1496
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/leluong141996-dev/Spawn-Point
8
+ Project-URL: Model, https://huggingface.co/smoky1496/SpawnPoint-Coder-7B-AWQ
9
+ Keywords: godot,gamedev,llm,procedural-generation,game-design
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Topic :: Games/Entertainment
14
+ Classifier: Topic :: Software Development :: Code Generators
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: pydantic>=2.5
19
+ Requires-Dist: numpy>=1.24
20
+ Requires-Dist: pillow>=10
21
+ Provides-Extra: dev
22
+ Requires-Dist: pytest>=7; extra == "dev"
23
+ Dynamic: license-file
24
+
25
+ # Spawn Point
26
+
27
+ **Compile a small JSON "game graph" into a juicy, runnable Godot 4 game — in seconds.**
28
+
29
+ <p align="center">
30
+ <img src="https://raw.githubusercontent.com/leluong141996-dev/Spawn-Point/main/docs/media/pixel-hopper.gif" width="48%" alt="Pixel Hopper — generated platformer">
31
+ <img src="https://raw.githubusercontent.com/leluong141996-dev/Spawn-Point/main/docs/media/pixel-arena.gif" width="48%" alt="Pixel Arena — generated top-down shooter">
32
+ </p>
33
+ <p align="center"><sub>Both games are built from <code>examples/pixel_hopper.json</code> and
34
+ <code>examples/pixel_arena.json</code>: generated sprites, collision traced from pixels, juice on by
35
+ default. Recorded with <code>spawnpoint gif</code> (autopilot).</sub></p>
36
+
37
+ Spawn Point is the foundation of an autonomous game-studio agent. Instead of asking an LLM to type
38
+ hundreds of lines of GDScript (slow, expensive, and easy to break with Godot 3/4 mix-ups), the LLM
39
+ assembles **pre-tested components** like LEGO, places them on an **ASCII map**, and wires gameplay
40
+ with **declarative rules**. A deterministic compiler validates everything and lets Godot itself write
41
+ the scenes.
42
+
43
+ ```
44
+ graph.json ──► validate (Python) ──► build scenes (Godot headless) ──► smoke-run ──► playable project
45
+ ~1 ms, LLM-friendly ~2 s ~0.3 s
46
+ error messages
47
+ ```
48
+
49
+ | | Typical LLM-writes-code agents | Spawn Point |
50
+ |---|---|---|
51
+ | How code is produced | GDScript generated from scratch | Components + JSON graph |
52
+ | Time to a playable build | minutes to hours | ~3 seconds |
53
+ | Game feel | none by default | coyote time, jump buffer, squash & stretch, hit-stop, screen shake, particles, SFX — on by default |
54
+ | Hitboxes | drift from visuals | derived from the same shape as the visual |
55
+ | Failure mode | crashes, syntax errors | structured diagnostics *before* Godot runs |
56
+
57
+ ## Spawn Point Studio (web cockpit)
58
+
59
+ ```bash
60
+ spawnpoint studio # opens http://localhost:8070 — games live in ./out
61
+ ```
62
+
63
+ A local "studio floor" around the running game — no terminal needed:
64
+
65
+ - **Projects**: every game in the workspace; **New game** from a prompt (optionally with the
66
+ playtester and the creative pass). Progress streams live while the layers land.
67
+ - **Arcade**: the web build in the middle, reloading by itself after every change.
68
+ **Right-click an enemy or item in the game** to select it, then just say what to change:
69
+ *"double its health and make it shoot fireballs"* — the LLM returns a patch scoped to that entity,
70
+ the compiler checks it (with repair rounds), missing projectiles are created, and the game reloads.
71
+ - **Designer**: the brief, rules, tweak history, studio edits and tuning.
72
+ **Artist**: every sprite sheet. **Developer**: every entity → component → parameter as a typed
73
+ input with the manifest's ranges; editing one rebuilds the game (no LLM needed).
74
+ **QA**: run the playtester or run + tune, with the stats table and the death heatmap.
75
+
76
+ Edits are stored as overrides in `studio.json` and survive later tweaks; they win over the tuner.
77
+ Standard library only on the server, one HTML/JS page on the client, Server-Sent Events for progress.
78
+
79
+ ## Make a game from a sentence
80
+
81
+ ```bash
82
+ scripts/llm-up.sh # SpawnPoint-Coder-7B on vLLM (~11 GB VRAM) — or any OpenAI-compatible API
83
+ spawnpoint create "a ninja platformer where you collect stars"
84
+ ```
85
+
86
+ ```
87
+ Design:
88
+ “Ninja Star Dash” — platformer, palette candy, goal collect_all, short, difficulty 2
89
+ player: double_jump, stomp; jump 4.0 tiles; speed fast; feel floaty; juice subtle
90
+ enemies: 4x Goblin (walker), 2x Spider (hopper); pickups: 10x Star; hazards: spikes
91
+ [L0 core loop] ok in 5.5s (build 3.1s, web 2.4s)
92
+ ▶ playing at http://localhost:8060/ (the page reloads as layers land)
93
+ [L1 goals & enemies] ok in 5.1s
94
+ [L2 feel & polish] ok in 5.1s
95
+ Done in 25.7s (design 10.0s; LLM 2 call(s), 977 prompt + 256 completion tokens).
96
+ ```
97
+
98
+ The browser opens on the first playable layer and reloads as the next ones land. Then iterate:
99
+
100
+ ```bash
101
+ spawnpoint tweak out/ninja-star-dash "jump 20% higher and add a dash, night colors"
102
+ # palette: "candy" -> "night"
103
+ # player.abilities: ["double_jump", "stomp"] -> ["double_jump", "stomp", "dash"]
104
+ # player.jump_tiles: 4.0 -> 4.8
105
+ ```
106
+
107
+ Only what you asked for changes, and the level layout is kept. Prompts can be in any language
108
+ (non-English prompts are translated first). How it works:
109
+
110
+ 1. **Design** — the LLM fills a small, enumerated **GameBrief** (genre, palette, abilities, enemy
111
+ archetypes, pickups, goal, feel…) using guided JSON decoding, so even a 7B model cannot produce
112
+ malformed output. A normalizer repairs typical small-model mistakes (plural names, archetypes that
113
+ don't exist in the genre, impossible goals).
114
+ 2. **Assemble** — deterministic: archetypes become tuned component bundles, goals become rules,
115
+ levels are generated (platformer chunks tagged with the jump they need; top-down arenas whose
116
+ floor is always connected) and re-seeded until the compiler finds everything reachable.
117
+ 3. **Layers** — L0 core movement → L1 enemies, pickups, goal → L2 feel & juice; each one is compiled,
118
+ exported to the web and live-reloaded.
119
+ 4. **Creative pass** (`--creative`) — the LLM proposes a small graph patch (parameters, rules); the
120
+ compiler's diagnostics drive up to two repair rounds; if it still fails, it is dropped.
121
+
122
+ **The model.** [SpawnPoint-Coder-7B](https://huggingface.co/smoky1496/SpawnPoint-Coder-7B-AWQ) is a 7B model
123
+ fine-tuned to generate Godot 4 games through this pipeline: it writes the game design, tweaks and entity
124
+ edits as strict JSON, and the compiler turns that into Godot scenes and GDScript. It runs on a single 12 GB
125
+ GPU (AWQ 4-bit). v2 on 30 human-written game ideas (English and Vietnamese): 87% fully right (v1: 73%),
126
+ 97% of checks passed; on held-out tasks: briefs 88% exact (v1: 36%), Vietnamese → English 97% (v1: 52%),
127
+ tweaks 98%, entity edits 91%. It is tuned for 2D platformers and 2D top-down games only; other genres
128
+ are no better than a general 7B coder. `scripts/llm-up.sh` downloads and serves it.
129
+
130
+ LLM settings: `SPAWNPOINT_LLM_BASE_URL` (default `http://localhost:8000/v1`),
131
+ `SPAWNPOINT_LLM_MODEL` (default: the server's first model), `SPAWNPOINT_LLM_API_KEY`.
132
+ Web builds need the Godot **web export templates** (Editor → Manage Export Templates, or unpack
133
+ `web_*.zip` from the official `.tpz` into `~/.local/share/godot/export_templates/<version>/`);
134
+ use `--no-web` to skip and play natively with `spawnpoint run`.
135
+
136
+ ## Sprites: generated or your own
137
+
138
+ Layer 2 replaces placeholder shapes with **procedural pixel-art sprites** — no assets, no GPU. The
139
+ kind follows the entity (`Goblin` → humanoid, `FireBat` → flyer, `LaserBot` → robot, `Crystal` → gem…)
140
+ and details follow the name (`Ninja` → mask, `Fox` → ears and tail, `Spider` → legs). Every sprite has
141
+ idle / run / jump / fall / hurt animations driven automatically by an `Animator` component.
142
+
143
+ **Collision comes from the pixels.** Hitboxes, hurtboxes, pickups, hazards and static bodies use the
144
+ sprite's traced outline (`CollisionPolygon2D`); moving bodies keep a smooth capsule/circle fitted to
145
+ the sprite's opaque bounds, so characters never snag on tile seams.
146
+
147
+ ```bash
148
+ spawnpoint sprites kinds # hero, slime, hopper, flyer, robot, ...
149
+ spawnpoint sprites generate hero --name Knight --color "#c2c3c7" # assets/sprites/Knight.sprite.json
150
+ spawnpoint sprites import hero.png --grid 32x32 --anim idle=0-3 --anim run=4-9
151
+ spawnpoint sprites import sheet.png --rows idle,run,jump # auto-sliced by transparent gutters
152
+ spawnpoint sprites import kenney_frames/ # idle_0.png, walk_1.png, ...
153
+ spawnpoint sprites preview assets/sprites/Knight.sprite.json # contact sheet + collision outline
154
+ ```
155
+
156
+ Record a clip of any built game to share it (a window opens for a few seconds; autopilot plays):
157
+
158
+ ```bash
159
+ spawnpoint gif out/pixel-hopper -o demo.gif --seconds 8 --fps 20 --width 640
160
+ ```
161
+
162
+ **AI art (optional plug-in).** Point Spawn Point at an image model and layer 2 asks it for the look of
163
+ each entity, then makes it game-ready: flat background removed, cropped and fitted to the kind's pixel
164
+ size, a 16-color palette, animations synthesized from the single frame, collision traced from the
165
+ pixels. Results are cached by prompt; if the provider is down, a generated sprite is used instead.
166
+
167
+ ```bash
168
+ export SPAWNPOINT_IMAGE_PROVIDER=a1111 SPAWNPOINT_IMAGE_URL=http://localhost:7860 # Stable Diffusion WebUI
169
+ # or: SPAWNPOINT_IMAGE_PROVIDER=openai SPAWNPOINT_IMAGE_URL=https://api.openai.com/v1 SPAWNPOINT_IMAGE_API_KEY=...
170
+ spawnpoint create "a knight platformer in a haunted castle" --ai-art
171
+ ```
172
+
173
+ In a graph: `"sprite": {"ai": {"prompt": "a tiny knight in silver armor", "kind": "hero"}}`.
174
+
175
+ Use one in a graph with `"sprite": "assets/sprites/Knight.sprite.json"` (relative to the graph file)
176
+ or `"sprite": {"generate": {"kind": "slime", "color": "#ff004d"}}` — see `examples/pixel_hopper.json`.
177
+ When an entity has a sprite and no explicit `shape`, its collision size comes from the drawing.
178
+
179
+ ## Playtesting: bots find what's unfair, then fix it
180
+
181
+ ```bash
182
+ spawnpoint playtest out/pixel-hopper --tune
183
+ ```
184
+
185
+ ```
186
+ before:
187
+ novice won 1/3 deaths 5 (Spikes 4, Frog 1) missed jumps 3/100 pickups 69%
188
+ average won 1/3 deaths 2 (Spikes 2) missed jumps 3/92 pickups 92%
189
+ expert won 3/3 deaths 3 (fall 3) missed jumps 0/43 pickups 100%
190
+ round 1 (kept, score 0.8083 -> 0.475):
191
+ Player.Hurtbox.size_scale = 0.75 — Spikes caused 6/7 deaths
192
+ Player.Health.max_health = 4 — novice bots won only 1/3
193
+ after:
194
+ average won 2/3 deaths 2 (Spikes 1, Slime 1)
195
+ ```
196
+
197
+ Three bot skill levels (novice: slow reactions and late jumps; average; expert) press the same keys
198
+ a person would, so coyote time, jump buffering and knockback are tested for real. They navigate with
199
+ a jump-aware path planner over the tile map, so a failure means the level is hard — not that the bot
200
+ is lost. Runs are headless and seeded: 9 runs of up to a minute each take a few seconds.
201
+
202
+ - **Telemetry**: deaths with cause (`fall`, `Spikes`, `Slime`, `EnemyBullet`…) and position, missed
203
+ jumps (pressed after coyote time ran out), stuck spots, pickups, targets the bots gave up on.
204
+ - **Report**: `playtest/report.md`, `report.json` and `heatmap.png` (deaths colored by cause).
205
+ - **Tuning** (`--tune`): bounded rules (late jumps → more coyote time; one enemy dominates → it slows
206
+ down; spikes dominate → a more forgiving hurtbox; still too hard → more health…), targets set by the
207
+ game's difficulty. Each round is rebuilt and re-tested and kept only if it gets closer to the targets.
208
+ Studio games store the result in `studio.json`, so later tweaks keep it;
209
+ `spawnpoint create "..." --playtest` does all of this automatically after layer 2.
210
+
211
+ ### Collecting fine-tuning data (opt-in, local only)
212
+
213
+ ```bash
214
+ spawnpoint create "..." --record # or export SPAWNPOINT_RECORD=1 for every create/tweak
215
+ spawnpoint dataset stats # records per task, accepted, corrected by the pipeline
216
+ ```
217
+
218
+ Each LLM call is appended to `~/.local/share/spawnpoint/dataset/<date>.jsonl` (override with
219
+ `SPAWNPOINT_DATASET_DIR`) with the exact `messages`, the model's `raw` answer, and the `target` the
220
+ pipeline actually used — the normalized brief, or the patch the compiler accepted — plus `notes`,
221
+ compiler `errors`, `accepted` and `corrected`. Training on `messages → target` teaches the model to
222
+ stop making the mistakes the normalizer and compiler had to fix (roadmap item 7). Nothing is uploaded.
223
+
224
+ ## Quick start (hand-written graphs)
225
+
226
+ Requirements: Python ≥ 3.10 and [Godot 4.6](https://godotengine.org/download) on your `PATH`
227
+ (`godot4` or `godot`, or set `GODOT_BIN`).
228
+
229
+ ```bash
230
+ pip install -e ".[dev]"
231
+ spawnpoint build examples/coin_hopper.json --run # platformer
232
+ spawnpoint build examples/neon_arena.json --run # top-down shooter
233
+ ```
234
+
235
+ Controls: move **WASD / arrows**, jump **Space / Z / W**, dash **Shift / C**, shoot **X / J / left mouse**,
236
+ restart **R**.
237
+
238
+ The output in `out/<game>/` is a normal Godot project. Open `project.godot` in the editor and keep
239
+ developing; the component library is copied into `addons/spawn_point/`.
240
+
241
+ ## A game graph
242
+
243
+ ```json
244
+ {
245
+ "name": "Coin Hopper",
246
+ "genre": "platformer",
247
+ "entities": {
248
+ "Player": {
249
+ "shape": { "type": "capsule", "size": [22, 34] },
250
+ "components": { "PlatformerMovement": { "air_jumps": 1 }, "PlayerInput": {},
251
+ "Health": { "max_health": 3 }, "Hurtbox": {}, "Stomp": {} }
252
+ },
253
+ "Slime": {
254
+ "components": { "PlatformerMovement": { "max_speed": 60 }, "PatrolAI": {},
255
+ "Health": { "max_health": 1 }, "Hurtbox": {}, "Hitbox": {} }
256
+ },
257
+ "Coin": { "body": "area", "shape": { "type": "circle", "size": [14, 14] },
258
+ "components": { "Collectible": { "score": 1 } } },
259
+ "Exit": { "body": "area", "components": { "TriggerZone": {} } }
260
+ },
261
+ "level": {
262
+ "map": ["...........C......",
263
+ "......=====.......",
264
+ ".P.......C....S..E",
265
+ "##################"],
266
+ "legend": { "#": "solid", "=": "oneway", "P": "Player", "S": "Slime", "C": "Coin", "E": "Exit" }
267
+ },
268
+ "rules": [
269
+ { "on": "Exit.triggered", "if": "count('Coin') == 0", "do": ["win()"] },
270
+ { "on": "Slime.died", "do": ["add_score(5)"] }
271
+ ]
272
+ }
273
+ ```
274
+
275
+ - **Entities** are a body (`character` / `static` / `area`), a placeholder `shape`
276
+ (`rect`, `circle`, `capsule`, `triangle`, `spikes`, `none`) and components with parameters.
277
+ Colors default from the entity's role; collision shapes always match the visual.
278
+ - **Level** is an ASCII map. `solid` and `oneway` are tiles; any other legend value is an entity.
279
+ - **Rules**: `on` an event (`Entity.signal`, `Entity.Component.signal`, `GameState.score_changed`,
280
+ `Game.ready`…), optional `if` expression, `do` actions (`win()`, `add_score(n)`, `Door.open()`,
281
+ `spawn("Slime")`, `shake(0.5)`, `message("Hi")`…). They compile to a readable `rules.gd`.
282
+
283
+ List every component with its parameters, signals and methods:
284
+
285
+ ```bash
286
+ spawnpoint components # human-readable
287
+ spawnpoint components --json # the manifest an LLM can consume
288
+ ```
289
+
290
+ ## Diagnostics built for self-correction
291
+
292
+ ```bash
293
+ $ spawnpoint validate broken.json
294
+ ✗ error[E_UNKNOWN_PARAM] entities.Player.components.Health.max_hp: Health has no parameter 'max_hp' (hint: Did you mean 'max_health'?)
295
+ ✗ error[E_RULE_DO] rules[0].do[1]: Door has no method 'opne' (hint: Did you mean 'open'?)
296
+ ! warning[W_UNREACHABLE] level.map: Coin at (44,2) looks unreachable (jump ≈ 3 tiles up, 4 across)
297
+ ```
298
+
299
+ `--json` prints the same as `{severity, code, path, message, hint}` objects. Builds also run a
300
+ headless smoke test (spawn, scripted input, crash detection) and report `E_RUNTIME` errors.
301
+
302
+ ## Components
303
+
304
+ | Category | Components |
305
+ |---|---|
306
+ | Movement | `PlatformerMovement` (coyote time, jump buffer, variable jump, apex hang, dash, double jump), `TopDownMovement` (accel/friction, dash) |
307
+ | Controllers | `PlayerInput`, `PatrolAI`, `ChaseAI`, `Aim` |
308
+ | Combat | `Health`, `Hitbox`, `Hurtbox`, `Stomp`, `Weapon`, `Projectile` |
309
+ | World | `Collectible`, `TriggerZone`, `Spawner`, `Gate` |
310
+ | Feel | `Juice` — attached to every entity unless `"juice": "none"` |
311
+
312
+ Runtime autoloads: `GameState` (score, lives, variables, win/lose), `World` (spawning, rule
313
+ bindings), `FX` (hit-stop, shake, particles, floating text), `Sfx` (pooled sounds with pitch
314
+ variation). Sounds are synthesized at build time by a built-in sfxr port — no assets needed.
315
+
316
+ ## Repository layout
317
+
318
+ ```
319
+ godot/ Godot project hosting the component library and its tests
320
+ addons/spawn_point/ components/, runtime/, tools/ (build, smoke, capture), manifest.json
321
+ tests/ headless GDScript tests
322
+ compiler/spawnpoint/ Python compiler: graph schema, analysis, rules codegen, sfx, CLI
323
+ compiler/spawnpoint/studio LLM orchestrator: brief, assembler, level generators, web export, browser check
324
+ compiler/spawnpoint/sprites SpriteSet format, pixel-art generator, importer, contour → collision
325
+ compiler/tests/ pytest (includes end-to-end builds and the GDScript suite)
326
+ examples/ example graphs
327
+ docs/ design specs
328
+ ```
329
+
330
+ ## Development
331
+
332
+ ```bash
333
+ pytest # everything: compiler, studio, end-to-end builds, web + browser, GDScript suite
334
+ pytest -m "not llm" # without the live-LLM tests
335
+ spawnpoint manifest # regenerate manifest.json after changing a component
336
+ godot4 --headless --path godot --fixed-fps 60 res://tests/run_tests.tscn # GDScript suite only
337
+ ```
338
+
339
+ Adding a component: create `godot/addons/spawn_point/components/<name>_component.gd` following the
340
+ contract (typed `@export`s with ranges, `SP_NAME` / `SP_HOSTS` / `SP_REQUIRES` / `SP_CATEGORY`
341
+ constants, `##` docs on everything public), add tests in `godot/tests/`, then run `spawnpoint manifest`.
342
+
343
+ ## Roadmap
344
+
345
+ 1. ✅ Component library with juice
346
+ 2. ✅ Graph compiler (validation, rules, levels, SFX, smoke test)
347
+ 3. ✅ Studio orchestrator — prompt → brief → layered builds, web export with live reload, tweaks, creative pass
348
+ 4. ✅ Asset pipeline — procedural pixel-art sprites and tiles, sheet/folder import with auto-slicing, outline → `CollisionPolygon2D`, automatic animation, AI-art provider plug-in
349
+ 5. ✅ Playtester — skill-profiled bots with a jump-aware planner, telemetry, death heatmaps, bounded auto-tuning
350
+ 6. ✅ Web cockpit — `spawnpoint studio`: live arcade, right-click-to-edit with the LLM, parameter desk, sprite gallery, playtest desk
351
+ 7. ✅ **[SpawnPoint-Coder-7B](https://huggingface.co/smoky1496/SpawnPoint-Coder-7B-AWQ)** — a fine-tuned 7B model (QLoRA, trainable and servable on a
352
+ single 12 GB consumer GPU such as an RTX 3060) specialised in briefs, tweaks and graph patches, so
353
+ the whole studio runs well offline for free. The compiler acts as the data filter and the judge:
354
+ every training example must compile, and evaluation measures first-try validity, how often the
355
+ normalizer has to repair output, and whether tweaks change only what was asked.
356
+ Hosted providers (Claude, OpenAI, any OpenAI-compatible API) stay supported via `SPAWNPOINT_LLM_*`.
357
+
358
+ ## License
359
+
360
+ MIT