spawnpoint-studio 0.1.0__py3-none-any.whl

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 (118) hide show
  1. spawnpoint/__init__.py +3 -0
  2. spawnpoint/_data/examples/coin_hopper.json +228 -0
  3. spawnpoint/_data/examples/neon_arena.json +251 -0
  4. spawnpoint/_data/examples/pixel_arena.json +242 -0
  5. spawnpoint/_data/examples/pixel_hopper.json +221 -0
  6. spawnpoint/_data/godot/addons/spawn_point/components/aim_component.gd +63 -0
  7. spawnpoint/_data/godot/addons/spawn_point/components/animator_component.gd +66 -0
  8. spawnpoint/_data/godot/addons/spawn_point/components/chase_ai_component.gd +107 -0
  9. spawnpoint/_data/godot/addons/spawn_point/components/collectible_component.gd +58 -0
  10. spawnpoint/_data/godot/addons/spawn_point/components/gate_component.gd +64 -0
  11. spawnpoint/_data/godot/addons/spawn_point/components/health_component.gd +83 -0
  12. spawnpoint/_data/godot/addons/spawn_point/components/hitbox_component.gd +50 -0
  13. spawnpoint/_data/godot/addons/spawn_point/components/hurtbox_component.gd +48 -0
  14. spawnpoint/_data/godot/addons/spawn_point/components/juice_component.gd +219 -0
  15. spawnpoint/_data/godot/addons/spawn_point/components/patrol_ai_component.gd +63 -0
  16. spawnpoint/_data/godot/addons/spawn_point/components/platformer_movement_component.gd +204 -0
  17. spawnpoint/_data/godot/addons/spawn_point/components/player_input_component.gd +77 -0
  18. spawnpoint/_data/godot/addons/spawn_point/components/projectile_component.gd +64 -0
  19. spawnpoint/_data/godot/addons/spawn_point/components/spawner_component.gd +58 -0
  20. spawnpoint/_data/godot/addons/spawn_point/components/stomp_component.gd +56 -0
  21. spawnpoint/_data/godot/addons/spawn_point/components/top_down_movement_component.gd +101 -0
  22. spawnpoint/_data/godot/addons/spawn_point/components/trigger_zone_component.gd +32 -0
  23. spawnpoint/_data/godot/addons/spawn_point/components/weapon_component.gd +83 -0
  24. spawnpoint/_data/godot/addons/spawn_point/manifest.json +1509 -0
  25. spawnpoint/_data/godot/addons/spawn_point/runtime/camera_rig.gd +71 -0
  26. spawnpoint/_data/godot/addons/spawn_point/runtime/cockpit.gd +62 -0
  27. spawnpoint/_data/godot/addons/spawn_point/runtime/entity_core.gd +98 -0
  28. spawnpoint/_data/godot/addons/spawn_point/runtime/fx.gd +112 -0
  29. spawnpoint/_data/godot/addons/spawn_point/runtime/game_state.gd +111 -0
  30. spawnpoint/_data/godot/addons/spawn_point/runtime/hud.gd +155 -0
  31. spawnpoint/_data/godot/addons/spawn_point/runtime/level.gd +19 -0
  32. spawnpoint/_data/godot/addons/spawn_point/runtime/sfx.gd +58 -0
  33. spawnpoint/_data/godot/addons/spawn_point/runtime/sp.gd +121 -0
  34. spawnpoint/_data/godot/addons/spawn_point/runtime/world.gd +130 -0
  35. spawnpoint/_data/godot/addons/spawn_point/shaders/flash.gdshader +9 -0
  36. spawnpoint/_data/godot/addons/spawn_point/shaders/floor_grid.gdshader +13 -0
  37. spawnpoint/_data/godot/addons/spawn_point/tools/build.gd +612 -0
  38. spawnpoint/_data/godot/addons/spawn_point/tools/build.tscn +6 -0
  39. spawnpoint/_data/godot/addons/spawn_point/tools/capture.gd +42 -0
  40. spawnpoint/_data/godot/addons/spawn_point/tools/capture.tscn +6 -0
  41. spawnpoint/_data/godot/addons/spawn_point/tools/dump_manifest.gd +91 -0
  42. spawnpoint/_data/godot/addons/spawn_point/tools/dump_manifest.tscn +6 -0
  43. spawnpoint/_data/godot/addons/spawn_point/tools/playtest.gd +428 -0
  44. spawnpoint/_data/godot/addons/spawn_point/tools/playtest.tscn +6 -0
  45. spawnpoint/_data/godot/addons/spawn_point/tools/playtest_nav.gd +152 -0
  46. spawnpoint/_data/godot/addons/spawn_point/tools/record.gd +89 -0
  47. spawnpoint/_data/godot/addons/spawn_point/tools/record.tscn +6 -0
  48. spawnpoint/_data/godot/addons/spawn_point/tools/smoke.gd +72 -0
  49. spawnpoint/_data/godot/addons/spawn_point/tools/smoke.tscn +6 -0
  50. spawnpoint/analyze.py +387 -0
  51. spawnpoint/build.py +146 -0
  52. spawnpoint/cli.py +290 -0
  53. spawnpoint/cockpit/__init__.py +0 -0
  54. spawnpoint/cockpit/server.py +473 -0
  55. spawnpoint/cockpit/static/app.css +111 -0
  56. spawnpoint/cockpit/static/app.js +327 -0
  57. spawnpoint/cockpit/static/index.html +79 -0
  58. spawnpoint/diagnostics.py +91 -0
  59. spawnpoint/expr.py +219 -0
  60. spawnpoint/gif.py +58 -0
  61. spawnpoint/godot.py +107 -0
  62. spawnpoint/graph.py +175 -0
  63. spawnpoint/level.py +157 -0
  64. spawnpoint/llm_server.py +77 -0
  65. spawnpoint/manifest.py +222 -0
  66. spawnpoint/playtest/__init__.py +104 -0
  67. spawnpoint/playtest/report.py +148 -0
  68. spawnpoint/playtest/runner.py +51 -0
  69. spawnpoint/playtest/tuner.py +151 -0
  70. spawnpoint/project.py +94 -0
  71. spawnpoint/py.typed +0 -0
  72. spawnpoint/rules.py +310 -0
  73. spawnpoint/sfx.py +352 -0
  74. spawnpoint/sprites/__init__.py +0 -0
  75. spawnpoint/sprites/ai.py +222 -0
  76. spawnpoint/sprites/contour.py +147 -0
  77. spawnpoint/sprites/generate.py +507 -0
  78. spawnpoint/sprites/importer.py +212 -0
  79. spawnpoint/sprites/resolve.py +139 -0
  80. spawnpoint/sprites/spriteset.py +159 -0
  81. spawnpoint/sprites/tiles.py +102 -0
  82. spawnpoint/studio/__init__.py +0 -0
  83. spawnpoint/studio/assemble.py +528 -0
  84. spawnpoint/studio/brief.py +197 -0
  85. spawnpoint/studio/creative.py +124 -0
  86. spawnpoint/studio/dataset.py +136 -0
  87. spawnpoint/studio/edits.py +206 -0
  88. spawnpoint/studio/levelgen.py +352 -0
  89. spawnpoint/studio/llm.py +145 -0
  90. spawnpoint/studio/orchestrator.py +341 -0
  91. spawnpoint/studio/prompts.py +122 -0
  92. spawnpoint/studio/web.py +123 -0
  93. spawnpoint/studio/webcheck.py +210 -0
  94. spawnpoint/studio_cli.py +232 -0
  95. spawnpoint_studio-0.1.0.dist-info/METADATA +360 -0
  96. spawnpoint_studio-0.1.0.dist-info/RECORD +118 -0
  97. spawnpoint_studio-0.1.0.dist-info/WHEEL +5 -0
  98. spawnpoint_studio-0.1.0.dist-info/entry_points.txt +2 -0
  99. spawnpoint_studio-0.1.0.dist-info/licenses/LICENSE +21 -0
  100. spawnpoint_studio-0.1.0.dist-info/top_level.txt +2 -0
  101. tests/conftest.py +49 -0
  102. tests/test_ai_sprites.py +122 -0
  103. tests/test_analyze.py +116 -0
  104. tests/test_cockpit.py +148 -0
  105. tests/test_e2e.py +33 -0
  106. tests/test_expr.py +59 -0
  107. tests/test_gif.py +19 -0
  108. tests/test_godot_library.py +17 -0
  109. tests/test_graph.py +44 -0
  110. tests/test_level.py +64 -0
  111. tests/test_live_llm.py +38 -0
  112. tests/test_manifest.py +54 -0
  113. tests/test_playtest.py +129 -0
  114. tests/test_rules.py +85 -0
  115. tests/test_sfx.py +30 -0
  116. tests/test_sprites.py +261 -0
  117. tests/test_studio.py +335 -0
  118. tests/test_web.py +41 -0
spawnpoint/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ """Spawn Point: compile JSON game graphs into runnable Godot 4 projects."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,228 @@
1
+ {
2
+ "spawnpoint": 1,
3
+ "name": "Coin Hopper",
4
+ "genre": "platformer",
5
+ "settings": {
6
+ "tile_size": 32,
7
+ "lives": 3,
8
+ "seed": 7
9
+ },
10
+ "entities": {
11
+ "Player": {
12
+ "shape": {
13
+ "type": "capsule",
14
+ "size": [
15
+ 22,
16
+ 34
17
+ ]
18
+ },
19
+ "components": {
20
+ "PlatformerMovement": {
21
+ "air_jumps": 1,
22
+ "dash_speed": 620
23
+ },
24
+ "PlayerInput": {},
25
+ "Health": {
26
+ "max_health": 3
27
+ },
28
+ "Hurtbox": {},
29
+ "Stomp": {}
30
+ }
31
+ },
32
+ "Slime": {
33
+ "shape": {
34
+ "type": "rect",
35
+ "size": [
36
+ 28,
37
+ 20
38
+ ]
39
+ },
40
+ "components": {
41
+ "PlatformerMovement": {
42
+ "max_speed": 60
43
+ },
44
+ "PatrolAI": {},
45
+ "Health": {
46
+ "max_health": 1
47
+ },
48
+ "Hurtbox": {
49
+ "size_scale": 1.0
50
+ },
51
+ "Hitbox": {
52
+ "damage": 1
53
+ }
54
+ }
55
+ },
56
+ "Frog": {
57
+ "shape": {
58
+ "type": "circle",
59
+ "size": [
60
+ 26,
61
+ 22
62
+ ],
63
+ "color": "#00e436"
64
+ },
65
+ "team": "enemy",
66
+ "components": {
67
+ "PlatformerMovement": {
68
+ "max_speed": 90,
69
+ "jump_velocity": 480
70
+ },
71
+ "PatrolAI": {
72
+ "jump_interval": 1.4
73
+ },
74
+ "Health": {
75
+ "max_health": 2
76
+ },
77
+ "Hurtbox": {
78
+ "size_scale": 1.0
79
+ },
80
+ "Hitbox": {
81
+ "damage": 1
82
+ }
83
+ }
84
+ },
85
+ "Spikes": {
86
+ "body": "area",
87
+ "team": "enemy",
88
+ "shape": {
89
+ "type": "spikes",
90
+ "size": [
91
+ 30,
92
+ 14
93
+ ],
94
+ "color": "#c2c3c7"
95
+ },
96
+ "components": {
97
+ "Hitbox": {
98
+ "damage": 1,
99
+ "knockback": 420
100
+ }
101
+ },
102
+ "juice": "none"
103
+ },
104
+ "Coin": {
105
+ "body": "area",
106
+ "shape": {
107
+ "type": "circle",
108
+ "size": [
109
+ 14,
110
+ 14
111
+ ]
112
+ },
113
+ "components": {
114
+ "Collectible": {
115
+ "score": 1
116
+ }
117
+ }
118
+ },
119
+ "Heart": {
120
+ "body": "area",
121
+ "shape": {
122
+ "type": "rect",
123
+ "size": [
124
+ 16,
125
+ 14
126
+ ],
127
+ "color": "#ff77a8"
128
+ },
129
+ "components": {
130
+ "Collectible": {
131
+ "kind": "heart",
132
+ "score": 0,
133
+ "heal": 1
134
+ }
135
+ }
136
+ },
137
+ "Door": {
138
+ "body": "static",
139
+ "shape": {
140
+ "type": "rect",
141
+ "size": [
142
+ 18,
143
+ 136
144
+ ]
145
+ },
146
+ "components": {
147
+ "Gate": {}
148
+ }
149
+ },
150
+ "Exit": {
151
+ "body": "area",
152
+ "shape": {
153
+ "type": "rect",
154
+ "size": [
155
+ 28,
156
+ 48
157
+ ]
158
+ },
159
+ "components": {
160
+ "TriggerZone": {}
161
+ }
162
+ }
163
+ },
164
+ "level": {
165
+ "map": [
166
+ "....................................................",
167
+ "....................................................",
168
+ "....................................................",
169
+ "....................................................",
170
+ "............................................C.......",
171
+ "............CC.............................===......",
172
+ "...........====.....................................",
173
+ ".............................CC........CC...........",
174
+ ".......CC...............C...====......====..........",
175
+ "......====.........C................................",
176
+ ".......................###..........................",
177
+ "..P............S.......###.S...^^...CS....F.H...D.E.",
178
+ "##################...############..#################",
179
+ "##################...############..#################"
180
+ ],
181
+ "legend": {
182
+ "#": "solid",
183
+ "=": "oneway",
184
+ "P": "Player",
185
+ "S": "Slime",
186
+ "F": "Frog",
187
+ "^": "Spikes",
188
+ "C": "Coin",
189
+ "H": "Heart",
190
+ "D": "Door",
191
+ "E": "Exit"
192
+ }
193
+ },
194
+ "rules": [
195
+ {
196
+ "on": "Game.ready",
197
+ "do": [
198
+ "message('Collect every coin to open the door!')"
199
+ ]
200
+ },
201
+ {
202
+ "on": "Coin.collected",
203
+ "if": "count('Coin') == 0",
204
+ "do": [
205
+ "Door.open()",
206
+ "message('The door is open!')"
207
+ ]
208
+ },
209
+ {
210
+ "on": "Slime.died",
211
+ "do": [
212
+ "add_score(5)"
213
+ ]
214
+ },
215
+ {
216
+ "on": "Frog.died",
217
+ "do": [
218
+ "add_score(10)"
219
+ ]
220
+ },
221
+ {
222
+ "on": "Exit.triggered",
223
+ "do": [
224
+ "win()"
225
+ ]
226
+ }
227
+ ]
228
+ }
@@ -0,0 +1,251 @@
1
+ {
2
+ "spawnpoint": 1,
3
+ "name": "Neon Arena",
4
+ "genre": "topdown",
5
+ "settings": {
6
+ "tile_size": 32,
7
+ "lives": 3,
8
+ "seed": 21
9
+ },
10
+ "entities": {
11
+ "Player": {
12
+ "shape": {
13
+ "type": "circle",
14
+ "size": [
15
+ 24,
16
+ 24
17
+ ],
18
+ "color": "#29adff"
19
+ },
20
+ "components": {
21
+ "TopDownMovement": {
22
+ "max_speed": 250,
23
+ "dash_speed": 720
24
+ },
25
+ "PlayerInput": {},
26
+ "Aim": {
27
+ "mode": "mouse"
28
+ },
29
+ "Weapon": {
30
+ "projectile": "Bullet",
31
+ "fire_rate": 9,
32
+ "spread_deg": 5
33
+ },
34
+ "Health": {
35
+ "max_health": 5,
36
+ "invincibility_time": 0.8
37
+ },
38
+ "Hurtbox": {}
39
+ }
40
+ },
41
+ "Bullet": {
42
+ "body": "area",
43
+ "shape": {
44
+ "type": "circle",
45
+ "size": [
46
+ 8,
47
+ 8
48
+ ],
49
+ "color": "#fff1e8"
50
+ },
51
+ "components": {
52
+ "Projectile": {
53
+ "speed": 760,
54
+ "lifetime": 1.0
55
+ },
56
+ "Hitbox": {
57
+ "damage": 1,
58
+ "knockback": 160
59
+ }
60
+ }
61
+ },
62
+ "Chaser": {
63
+ "shape": {
64
+ "type": "circle",
65
+ "size": [
66
+ 24,
67
+ 24
68
+ ],
69
+ "color": "#ff004d"
70
+ },
71
+ "components": {
72
+ "TopDownMovement": {
73
+ "max_speed": 130
74
+ },
75
+ "ChaseAI": {
76
+ "detect_radius": 380
77
+ },
78
+ "Health": {
79
+ "max_health": 2,
80
+ "invincibility_time": 0.05
81
+ },
82
+ "Hurtbox": {
83
+ "size_scale": 1.0
84
+ },
85
+ "Hitbox": {
86
+ "damage": 1,
87
+ "knockback": 300
88
+ }
89
+ }
90
+ },
91
+ "Shooter": {
92
+ "shape": {
93
+ "type": "rect",
94
+ "size": [
95
+ 26,
96
+ 26
97
+ ],
98
+ "color": "#ff77a8"
99
+ },
100
+ "team": "enemy",
101
+ "components": {
102
+ "TopDownMovement": {
103
+ "max_speed": 90
104
+ },
105
+ "ChaseAI": {
106
+ "detect_radius": 420,
107
+ "keep_distance": 220,
108
+ "fire_range": 380
109
+ },
110
+ "Weapon": {
111
+ "projectile": "EnemyBullet",
112
+ "fire_rate": 1.3,
113
+ "spread_deg": 8,
114
+ "muzzle_distance": 22
115
+ },
116
+ "Health": {
117
+ "max_health": 3,
118
+ "invincibility_time": 0.05
119
+ },
120
+ "Hurtbox": {
121
+ "size_scale": 1.0
122
+ }
123
+ }
124
+ },
125
+ "EnemyBullet": {
126
+ "body": "area",
127
+ "team": "enemy",
128
+ "shape": {
129
+ "type": "circle",
130
+ "size": [
131
+ 10,
132
+ 10
133
+ ]
134
+ },
135
+ "components": {
136
+ "Projectile": {
137
+ "speed": 300,
138
+ "lifetime": 3.0
139
+ },
140
+ "Hitbox": {
141
+ "damage": 1,
142
+ "knockback": 200
143
+ }
144
+ }
145
+ },
146
+ "Portal": {
147
+ "body": "area",
148
+ "shape": {
149
+ "type": "circle",
150
+ "size": [
151
+ 40,
152
+ 40
153
+ ],
154
+ "color": "#83769c"
155
+ },
156
+ "components": {
157
+ "Spawner": {
158
+ "entity": "Chaser",
159
+ "interval": 4.0,
160
+ "start_delay": 3.0,
161
+ "max_alive": 3,
162
+ "total": 6
163
+ }
164
+ },
165
+ "juice": "none"
166
+ },
167
+ "HealthPack": {
168
+ "body": "area",
169
+ "shape": {
170
+ "type": "rect",
171
+ "size": [
172
+ 18,
173
+ 18
174
+ ],
175
+ "color": "#00e436"
176
+ },
177
+ "components": {
178
+ "Collectible": {
179
+ "kind": "heart",
180
+ "score": 0,
181
+ "heal": 2
182
+ }
183
+ }
184
+ }
185
+ },
186
+ "level": {
187
+ "map": [
188
+ "########################################",
189
+ "#......................................#",
190
+ "#..O...................................#",
191
+ "#...................X..................#",
192
+ "#....Z............####............Z....#",
193
+ "#......................................#",
194
+ "#.......##....................##.......#",
195
+ "#.......##....................##.......#",
196
+ "#...................+..................#",
197
+ "#......................................#",
198
+ "#......................................#",
199
+ "#...#..............................#...#",
200
+ "#...#.......X.......P.......X......#...#",
201
+ "#...#..............................#...#",
202
+ "#......................................#",
203
+ "#......................................#",
204
+ "#.......##..........+.........##.......#",
205
+ "#.......##....................##.......#",
206
+ "#......................................#",
207
+ "#....Z............####............Z....#",
208
+ "#......................................#",
209
+ "#...................................O..#",
210
+ "#......................................#",
211
+ "########################################"
212
+ ],
213
+ "legend": {
214
+ "#": "solid",
215
+ "P": "Player",
216
+ "Z": "Chaser",
217
+ "X": "Shooter",
218
+ "O": "Portal",
219
+ "+": "HealthPack"
220
+ }
221
+ },
222
+ "rules": [
223
+ {
224
+ "on": "Game.ready",
225
+ "do": [
226
+ "message('Score 200 to clear the arena!')"
227
+ ]
228
+ },
229
+ {
230
+ "on": "Chaser.died",
231
+ "do": [
232
+ "add_score(10)"
233
+ ]
234
+ },
235
+ {
236
+ "on": "Shooter.died",
237
+ "do": [
238
+ "add_score(25)",
239
+ "shake(0.3)"
240
+ ]
241
+ },
242
+ {
243
+ "on": "GameState.score_changed",
244
+ "if": "score >= 200",
245
+ "do": [
246
+ "message('Arena cleared!')",
247
+ "win()"
248
+ ]
249
+ }
250
+ ]
251
+ }