Installs into .claude/skills of the current project.
Are you the author of Design Level?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/summerengine-design-level)
---
name: design-level
description: "Design one level (layout, pacing, encounters, secrets) as a design doc plus a node-tree skeleton."
license: MIT
compatibility: [Cursor, Claude Code, Windsurf, Codex]
category: level-design
user-invocable: true
allowed-tools: Read Grep Glob Write Edit summer_get_scene_tree summer_create_scene summer_open_scene summer_run_script summer_add_node summer_set_prop summer_save_scene summer_get_script_errors
paths: ["**/*.tscn", "**/*.gd", ".summer/**", "levels/**"]
---
# /design-level — Design One Level
## Overview
A level is a controlled sequence of player experiences in physical space. Layout, pacing, encounters, secrets, and reward gating must work together — a "fun layout" with a flat pacing curve still feels boring. This skill walks the six design beats of a single level and drops a node-tree skeleton ready for `summer_create_scene`.
**Core principle:** A level has a *pacing curve* and a *teaching arc*. If you can't draw the tension graph and name what the player learned by the end, the level isn't designed yet.
## Steps
### 1. Pin the level type
Ask exactly one question:
> What kind of level? Pick one: tutorial / hub / combat encounter / boss / exploration / puzzle / stealth / platforming-challenge / mixed.
Each type has different beats. Don't blend types in v1 — a "boss room with stealth and puzzles" is three levels poorly squeezed into one.
### 2. Read context
If `.summer/GameSoul.md` exists, read it. The level must serve the brief's core loop and the three mechanics.
```
Read .summer/GameSoul.md
```
If `.summer/mechanics/` exists, list the mechanics. Quote them back:
> Brief says mechanics are: dash, parry, double-jump. This level should *exercise* at least one and ideally combine two.
### 3. Define the teaching / experience goal
Ask plain:
> What does the player know by the end of this level that they didn't at the start?
Tutorial-level answer: "How to dash." Combat-encounter answer: "That parrying converts damage to mana, and that big enemies need parry, not dodge." Exploration answer: "That this region's secrets are hidden behind double-jumpable gaps."
If the user can't answer, the level has no purpose. Say it:
> If there's no answer to that question, the level is filler. Either give it a teaching goal, give it a *failure-state* goal (the player must die here to progress), or merge it into the next level.
### 4. Sketch the pacing curve
Draw it as text. Five beats, intensity 0-10:
```
Intro Build Peak Release Hook
2 → 5 → 8 → 3 → 6
```
For a 5-minute encounter level:
| Beat | Duration | Intensity | Player feels | Designer plants |
|---|---|---|---|---|
| Intro | 30s | 2 | Calm, oriented | Visual landmark for the goal direction |
| Build | 90s | 5 | Tension rising, small pressure | First weak enemy / first puzzle clue |
| Peak | 60s | 8 | Stakes high, mistakes hurt | Main encounter / hardest fight |
| Release | 60s | 3 | Catharsis, loot | Reward + breath room |
| Hook | 30s | 6 | Curiosity for next | Visible-but-locked secret or path |
Show the curve. Ask:
> Pacing above. Does the peak land where you want, or does the level need a second wave?
### 5. List encounters and secrets
Encounters = explicit player tests (combat, puzzle, platforming). Secrets = optional rewards that respect the pacing curve.
State them flat. For a combat encounter level:
```
Encounters (in player-traversal order):
1. E1 — Tutorial enemy (1 weak grunt) at 0:30, in the open atrium. Teaches the basic attack.
2. E2 — Forced parry (mid-tier enemy with telegraphed wind-up) at 1:30, in a corridor with no dodge room. Teaches parry.
3. E3 — Mixed wave (2 grunts + 1 parry-required) at 3:00, in the peak arena. Tests both.
4. E4 — Mini-boss at 4:00 in the chamber. Combines.
Secrets (3 total — one per beat after intro):
- S1 (build beat): Behind a breakable wall in the corridor, holds 50 currency. Teaches "walls can break".
- S2 (peak beat): Visible from the arena, accessible only via parrying off an enemy. Rewards mastery.
- S3 (hook beat): Locked door, key in a future level. Plants curiosity for next level.
```
### 6. Define reward gating
What's behind which gate? Levels feel cheap when they hand out rewards without respecting the difficulty curve.
| Reward | Gate | Why |
|---|---|---|
| Heal pickup | After E2 | Player just learned parry; reward + safety net before the peak |
| New ability unlock | After mini-boss | Mastery-pinned; player demonstrates parry before getting upgrade |
| Currency cache | Behind S1 (breakable wall) | Optional; rewards observation |
| Story note | At the calm intro | Free; orients the player to the level's narrative |
Ask:
> Reward gating above. Anything missing or mis-placed?
### 7. Define the layout primitives
Every level is built from a small vocabulary of spaces. Name them. Most levels need 4-6 distinct spaces, no more.
For a combat-encounter level:
```
Spaces (node-tree skeleton):
World (Node3D)
├── Geometry (Node3D)
│ ├── IntroAtrium (Node3D) # open, calm, well-lit
│ ├── Corridor (Node3D) # tight, forces parry
│ ├── PeakArena (Node3D) # large, multiple cover, exit visible
│ └── BossChamber (Node3D) # contained, single exit, dramatic lighting
├── Spawns (Node3D)
│ ├── PlayerSpawn (Node3D) # marker
│ ├── E1_Spawn (Node3D)
│ ├── E2_Spawn (Node3D)
│ ├── E3_Wave_Spawns (Node3D)
│ └── MiniBoss_Spawn (Node3D)
├── Triggers (Node3D)
│ ├── E2_GateTrigger (Area3D) # locks door behind player on entry
│ ├── PeakWaveTrigger (Area3D)
│ └── BossDoorTrigger (Area3D)
├── Pickups (Node3D)
│ ├── HealAfterE2 (Node3D)
│ └── CurrencyS1 (Node3D)
├── Secrets (Node3D)
│ ├── S1_BreakableWall (StaticBody3D)
│ ├── S2_ParryLedge (StaticBody3D)
│ └── S3_LockedDoor (StaticBody3D)
└── Lighting (Node3D) # WorldEnvironment + DirectionalLight3D
```
Show the skeleton. Ask:
> Tree above. May I create the level scene `levels/<level-name>.tscn` with this skeleton?
### 8. Scaffold via MCP
**Preferred (Summer MCP):** create the scene, then build the whole skeleton in one script.
`summer_create_scene` takes `path`, `rootName` and `rootType` (default `Node3D`) and writes the new scene to disk without opening it. `summer_run_script` with that `scenePath` opens it, runs, and gives the user their tab back; the run is one undo step, so one Ctrl+Z removes the skeleton.
```
summer_create_scene(path="res://levels/level_01.tscn", rootName="World", rootType="Node3D")
summer_run_script(scenePath="res://levels/level_01.tscn", source="""
func run(ctx):
var skeleton = {
"Geometry": [["Node3D", "IntroAtrium"], ["Node3D", "Corridor"], ["Node3D", "PeakArena"], ["Node3D", "BossChamber"]],
"Spawns": [["Node3D", "PlayerSpawn"], ["Node3D", "E1_Spawn"], ["Node3D", "E2_Spawn"], ["Node3D", "E3_Wave_Spawns"], ["Node3D", "MiniBoss_Spawn"]],
"Triggers": [["Area3D", "E2_GateTrigger"], ["Area3D", "PeakWaveTrigger"], ["Area3D", "BossDoorTrigger"]],
"Pickups": [["Node3D", "HealAfterE2"], ["Node3D", "CurrencyS1"]],
"Secrets": [["StaticBody3D", "S1_BreakableWall"], ["StaticBody3D", "S2_ParryLedge"], ["StaticBody3D", "S3_LockedDoor"]],
"Lighting": [["WorldEnvironment", "WorldEnvironment"], ["DirectionalLight3D", "Sun"]],
}
for group in skeleton:
var parent = ctx.add_node("Node3D", group)
for child in skeleton[group]:
ctx.add_node(child[0], child[1], parent)
ctx.report("skeleton", ctx.summary())
ctx.save_scene()
""")
```
Compare the `skeleton` report (node counts by class) with the tree you showed the user, then `summer_get_scene_tree` on the new scene.
This is a **skeleton, not playable geometry**. Markers and Area3Ds, no meshes, no enemy scripts. Implementation in subsequent sessions / templates.
**Fallback (no MCP):** Print the `.tscn` file contents for the user to save manually.
### 9. Save the level design doc
Always write the design doc — it's the artifact that drives implementation. Path: `.summer/levels/<level-name>.md`.
```markdown
# Level: <Name>
**Type:** combat encounter
**Duration target:** 5 min
**Teaching goal:** Player learns parry and that parrying mid-tier enemies is required, not optional.
**Pacing curve:** 2 → 5 → 8 → 3 → 6
**Beats:** Intro (30s) | Build (90s) | Peak (60s) | Release (60s) | Hook (30s)
## Encounters
- E1 — Tutorial grunt @ 0:30 (IntroAtrium)
- E2 — Forced parry @ 1:30 (Corridor)
- E3 — Mixed wave @ 3:00 (PeakArena)
- E4 — Mini-boss @ 4:00 (BossChamber)
## Secrets
- S1 — Breakable wall (Corridor) → 50 currency
- S2 — Parry-ledge (PeakArena) → cosmetic
- S3 — Locked door (BossChamber) → next level
## Reward Gating
- Heal pickup after E2
- Ability unlock after mini-boss
## Spaces
1. IntroAtrium — open, calm
2. Corridor — tight, forces parry
3. PeakArena — large with cover
4. BossChamber — contained, dramatic
## Open questions
<list anything the user couldn't answer>
```
Ask:
> May I create `.summer/levels/<level-name>.md` with this design doc?
### 10. Route to the next step
End with:
> Skeleton + design doc saved. Next:
> - `/design-mechanic` to design any mechanics this level requires that aren't designed yet.
> - `/design-npc` to design the enemies (E1-E4) in detail.
> - `/art-direction` if the visual style isn't pinned yet.
> - Or open `levels/<level-name>.tscn` and start blocking out geometry.
## Common mistakes
| Mistake | Fix |
|---|---|
| No teaching goal | Every level teaches something or fails. State it explicitly. |
| Flat pacing curve | If intensity stays at 5 the whole time, you have a hallway, not a level. |
| Too many spaces | 4-6 distinct spaces max. More fragments the player's mental map. |
| Encounters not tied to mechanics | E2 should *require* parry, not just allow it. Forced use teaches; optional use doesn't. |
| Secrets ignore the pacing curve | Don't put a major secret in the calm intro — players aren't curious yet. |
| Reward gating too generous | Free heals before the peak deflate the peak. Gate them after the test. |
| Blending level types | Stealth + puzzle + boss in one level = three half-baked levels. Pick one. |
| Building geometry before the skeleton | Skeleton-first lets you iterate on layout cheaply. Geometry comes after the design is locked. |
| Calling SetResourceProperty before the property holds a resource | Explicit `resource is null` error, not a silent drop. Assign the resource first (`summer_set_prop key="mesh" value="BoxMesh"`), then set its sub-properties. Scene-embedded sub_resources are fully supported targets. |
## Collaborative protocol
This skill creates a new scene file (`.tscn`) and a design doc (`.md`). Group writes per phase. Always ask before `summer_create_scene`.
## Want a working starter?
This is a workflow that produces a skeleton scene. For runnable level examples, see:
- `summer create 3d-fps-old-school` ships a sample arena.
- `summer create 3d-third-person-controller` gives a jump-capable character to test level layouts against.
The skeleton this skill produces is meant to be filled in via `/design-mechanic`, gridmap blockout, or a template merge.
## See also
- `brainstorm-game` — produces `.summer/GameSoul.md`
- `design-mechanic` — designs the verbs the level exercises
- `design-npc` — designs the enemies the encounters reference
- `3d-lighting` — sets the lighting in `WorldEnvironment` + lights
- `art-direction` — defines the visual style the level expresses
<!-- shell-commands: generated from the operation catalog by npm run generate:registry; do not edit by hand -->
## From a shell
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.
| In this skill | Command |
|---|---|
| `summer_add_node` | `summer engine add-node` |
| `summer_create_scene` | `summer engine create-scene` |
| `summer_get_scene_tree` | `summer engine get-scene-tree` |
| `summer_get_script_errors` | `summer engine get-script-errors` |
| `summer_open_scene` | `summer engine open-scene` |
| `summer_run_script` | `summer engine run-script` |
| `summer_save_scene` | `summer engine save-scene` |
| `summer_set_prop` | `summer engine set-prop` |
<!-- /shell-commands -->