create-threejs-game 1.0.0 → 1.0.5
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.
- package/README.md +56 -52
- package/bin/cli.js +113 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,70 +2,67 @@
|
|
|
2
2
|
|
|
3
3
|
Scaffold a Three.js game project with AI-assisted design documents.
|
|
4
4
|
|
|
5
|
-
##
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npx create-threejs-game my-game
|
|
9
|
-
cd my-game
|
|
10
|
-
# Add assets to public/assets/my_game/
|
|
11
|
-
node scripts/pipeline.js
|
|
12
|
-
```
|
|
5
|
+
## Prerequisites
|
|
13
6
|
|
|
14
|
-
|
|
7
|
+
Before running the CLI, have these ready:
|
|
15
8
|
|
|
16
|
-
|
|
9
|
+
### 1. 3D Assets (Required)
|
|
10
|
+
Download a GLTF asset pack from:
|
|
11
|
+
- [itch.io](https://itch.io/game-assets/tag-3d)
|
|
12
|
+
- [Kenney.nl](https://kenney.nl/assets)
|
|
13
|
+
- [Quaternius](https://quaternius.com/)
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
- **Automation scripts** to generate:
|
|
20
|
-
- Asset index (assets.json)
|
|
21
|
-
- Concept mockup (via Google AI Studio)
|
|
22
|
-
- Product Requirements Document (PRD)
|
|
23
|
-
- Technical Design Document (TDD)
|
|
24
|
-
- Implementation plan
|
|
25
|
-
- **Prompt templates** for each generation step
|
|
15
|
+
The CLI will ask for the path to your downloaded assets folder and validate it contains `.gltf` or `.glb` files.
|
|
26
16
|
|
|
27
|
-
|
|
17
|
+
### 2. Preview Image (Recommended)
|
|
18
|
+
Most asset packs include a `Preview.jpg`. If not, take a screenshot of your assets. This is used by the AI to generate concept mockups.
|
|
28
19
|
|
|
29
|
-
|
|
20
|
+
### 3. API Keys (Required for automation)
|
|
21
|
+
Set these as environment variables for the smoothest experience:
|
|
30
22
|
|
|
31
23
|
```bash
|
|
32
|
-
|
|
24
|
+
export GOOGLE_API_KEY="your-key" # or GOOGLE_AI_STUDIO_API_KEY
|
|
25
|
+
export ANTHROPIC_API_KEY="your-key"
|
|
33
26
|
```
|
|
34
27
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
3. API keys (only if not found in environment)
|
|
39
|
-
|
|
40
|
-
**Supported environment variables:**
|
|
41
|
-
- `GOOGLE_API_KEY` or `GOOGLE_AI_STUDIO_API_KEY`
|
|
42
|
-
- `ANTHROPIC_API_KEY`
|
|
43
|
-
|
|
44
|
-
## Manual Steps
|
|
28
|
+
Get keys from:
|
|
29
|
+
- [Google AI Studio](https://aistudio.google.com/) - free tier available
|
|
30
|
+
- [Anthropic Console](https://console.anthropic.com/)
|
|
45
31
|
|
|
46
|
-
|
|
32
|
+
If not set, the CLI will prompt for them.
|
|
47
33
|
|
|
48
|
-
|
|
49
|
-
- Download from itch.io, Kenney.nl, Quaternius, etc.
|
|
50
|
-
- GLTF format preferred
|
|
51
|
-
|
|
52
|
-
2. **Add Preview.jpg** to the assets folder
|
|
53
|
-
- Most asset packs include one
|
|
54
|
-
- Or screenshot your assets
|
|
34
|
+
## Quick Start
|
|
55
35
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
36
|
+
```bash
|
|
37
|
+
npx create-threejs-game
|
|
38
|
+
```
|
|
59
39
|
|
|
60
|
-
|
|
40
|
+
The CLI will:
|
|
41
|
+
1. Ask for your **project name**
|
|
42
|
+
2. Ask for a **game description** (1-3 sentences describing your game)
|
|
43
|
+
3. Check for **API keys** (from env vars, or prompt if missing)
|
|
44
|
+
4. Ask for **path to your assets folder** (required for automation)
|
|
45
|
+
5. Validate everything and tell you if anything is missing
|
|
46
|
+
6. Create your project with assets copied in
|
|
61
47
|
|
|
62
|
-
|
|
48
|
+
Then run the automation:
|
|
63
49
|
|
|
64
50
|
```bash
|
|
51
|
+
cd my-game
|
|
65
52
|
node scripts/pipeline.js
|
|
66
53
|
```
|
|
67
54
|
|
|
68
|
-
|
|
55
|
+
## What Gets Generated
|
|
56
|
+
|
|
57
|
+
The automation pipeline creates:
|
|
58
|
+
|
|
59
|
+
| Step | Output | AI Service |
|
|
60
|
+
|------|--------|------------|
|
|
61
|
+
| Asset Index | `public/assets/{game}/assets.json` | Local script |
|
|
62
|
+
| Concept Mockup | `public/{game}/concept.jpg` | Google AI Studio |
|
|
63
|
+
| PRD | `docs/prd.md` | Claude (Anthropic) |
|
|
64
|
+
| TDD | `docs/tdd.md` | Claude (Anthropic) |
|
|
65
|
+
| Execution Plan | `plans/plan.md` | Claude (Anthropic) |
|
|
69
66
|
|
|
70
67
|
## Project Structure
|
|
71
68
|
|
|
@@ -75,22 +72,29 @@ my-game/
|
|
|
75
72
|
├── .codex/skills/ # Three.js skills for Codex
|
|
76
73
|
├── docs/ # Generated PRD and TDD
|
|
77
74
|
├── plans/ # Generated implementation plans
|
|
78
|
-
├── prompts/ #
|
|
75
|
+
├── prompts/ # Prompt templates (fallback/reference)
|
|
79
76
|
├── public/
|
|
80
|
-
│ └── assets/{game}/ # Your 3D assets
|
|
77
|
+
│ └── assets/{game}/ # Your 3D assets (copied by CLI)
|
|
81
78
|
├── scripts/
|
|
82
|
-
│ ├── config.json #
|
|
79
|
+
│ ├── config.json # API keys and game config
|
|
83
80
|
│ ├── pipeline.js # Run full automation
|
|
84
81
|
│ └── generate-*.js # Individual generators
|
|
85
|
-
└── README.md
|
|
82
|
+
└── README.md
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Final Step
|
|
86
|
+
|
|
87
|
+
After the pipeline completes, open your project in Claude Code or Cursor and follow the generated execution plan:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
Please proceed with implementing based on the plan in plans/plan.md
|
|
86
91
|
```
|
|
87
92
|
|
|
88
93
|
## Requirements
|
|
89
94
|
|
|
90
95
|
- Node.js 18+
|
|
91
|
-
- API keys (
|
|
92
|
-
|
|
93
|
-
- [Anthropic](https://console.anthropic.com/) - API access required
|
|
96
|
+
- API keys (see Prerequisites)
|
|
97
|
+
- 3D assets in GLTF format
|
|
94
98
|
|
|
95
99
|
## License
|
|
96
100
|
|
package/bin/cli.js
CHANGED
|
@@ -194,6 +194,67 @@ async function main() {
|
|
|
194
194
|
console.log('');
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
+
// Ask for assets location (required for automation)
|
|
198
|
+
console.log(c('bright', '📁 3D Assets (Required)'));
|
|
199
|
+
console.log(c('dim', '─'.repeat(50)));
|
|
200
|
+
console.log(c('dim', 'The automation pipeline needs 3D assets to generate mockups and docs.'));
|
|
201
|
+
console.log(c('dim', 'Download a GLTF asset pack from itch.io, Kenney.nl, etc. first.\n'));
|
|
202
|
+
|
|
203
|
+
let assetsSourcePath = '';
|
|
204
|
+
|
|
205
|
+
while (!assetsSourcePath) {
|
|
206
|
+
let inputPath = await ask(c('bright', 'Path to assets folder'));
|
|
207
|
+
|
|
208
|
+
if (!inputPath) {
|
|
209
|
+
const skipAnyway = await confirm(
|
|
210
|
+
c('yellow', 'Without assets, the automation pipeline cannot run. Skip anyway?'),
|
|
211
|
+
false
|
|
212
|
+
);
|
|
213
|
+
if (skipAnyway) {
|
|
214
|
+
console.log(c('yellow', '\n ⚠ No assets provided. You\'ll need to add them manually before running the pipeline.\n'));
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Expand ~ to home directory
|
|
221
|
+
if (inputPath.startsWith('~')) {
|
|
222
|
+
inputPath = path.join(process.env.HOME || process.env.USERPROFILE, inputPath.slice(1));
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Resolve relative paths
|
|
226
|
+
if (!path.isAbsolute(inputPath)) {
|
|
227
|
+
inputPath = path.resolve(process.cwd(), inputPath);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Validate path
|
|
231
|
+
if (!fs.existsSync(inputPath)) {
|
|
232
|
+
console.log(c('red', ` ✗ Path not found: ${inputPath}`));
|
|
233
|
+
console.log(c('dim', ' Please check the path and try again.\n'));
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const stat = fs.statSync(inputPath);
|
|
238
|
+
if (!stat.isDirectory()) {
|
|
239
|
+
console.log(c('red', ' ✗ Path is not a directory.'));
|
|
240
|
+
console.log(c('dim', ' Please provide a folder path.\n'));
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Check if it has any gltf/glb files
|
|
245
|
+
const hasModels = fs.readdirSync(inputPath, { recursive: true })
|
|
246
|
+
.some(f => f.endsWith('.gltf') || f.endsWith('.glb'));
|
|
247
|
+
|
|
248
|
+
if (!hasModels) {
|
|
249
|
+
console.log(c('yellow', ' ⚠ No .gltf or .glb files found in this folder.'));
|
|
250
|
+
const useAnyway = await confirm('Use this folder anyway?', false);
|
|
251
|
+
if (!useAnyway) continue;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
assetsSourcePath = inputPath;
|
|
255
|
+
console.log(c('green', ' ✓ ') + 'Assets folder validated\n');
|
|
256
|
+
}
|
|
257
|
+
|
|
197
258
|
// Copy template
|
|
198
259
|
console.log(c('bright', '📦 Creating project...'));
|
|
199
260
|
console.log(c('dim', '─'.repeat(50)));
|
|
@@ -244,8 +305,31 @@ async function main() {
|
|
|
244
305
|
// Create assets directory
|
|
245
306
|
const assetsDir = path.join(projectPath, 'public', 'assets', gameName);
|
|
246
307
|
fs.mkdirSync(assetsDir, { recursive: true });
|
|
247
|
-
|
|
248
|
-
|
|
308
|
+
|
|
309
|
+
// Copy assets if path was provided
|
|
310
|
+
if (assetsSourcePath) {
|
|
311
|
+
console.log(c('dim', ' Copying assets...'));
|
|
312
|
+
copyDir(assetsSourcePath, assetsDir, ['node_modules', '.git', '.DS_Store']);
|
|
313
|
+
|
|
314
|
+
// Count copied files
|
|
315
|
+
const countFiles = (dir) => {
|
|
316
|
+
let count = 0;
|
|
317
|
+
const items = fs.readdirSync(dir, { withFileTypes: true });
|
|
318
|
+
for (const item of items) {
|
|
319
|
+
if (item.isDirectory()) {
|
|
320
|
+
count += countFiles(path.join(dir, item.name));
|
|
321
|
+
} else {
|
|
322
|
+
count++;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return count;
|
|
326
|
+
};
|
|
327
|
+
const fileCount = countFiles(assetsDir);
|
|
328
|
+
console.log(c('green', ' ✓ ') + `public/assets/${gameName}/ (${fileCount} files copied)`);
|
|
329
|
+
} else {
|
|
330
|
+
fs.writeFileSync(path.join(assetsDir, '.gitkeep'), '');
|
|
331
|
+
console.log(c('green', ' ✓ ') + `public/assets/${gameName}/`);
|
|
332
|
+
}
|
|
249
333
|
|
|
250
334
|
console.log('');
|
|
251
335
|
console.log(c('green', `✅ Project created at: ${projectPath}`));
|
|
@@ -264,21 +348,34 @@ async function main() {
|
|
|
264
348
|
const steps = [];
|
|
265
349
|
let stepNum = 1;
|
|
266
350
|
|
|
267
|
-
//
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
351
|
+
// Check if assets were copied and if Preview exists
|
|
352
|
+
const hasAssets = assetsSourcePath && fs.existsSync(assetsDir);
|
|
353
|
+
const previewExists = hasAssets && (
|
|
354
|
+
fs.existsSync(path.join(assetsDir, 'Preview.jpg')) ||
|
|
355
|
+
fs.existsSync(path.join(assetsDir, 'Preview.png')) ||
|
|
356
|
+
fs.existsSync(path.join(assetsDir, 'preview.jpg')) ||
|
|
357
|
+
fs.existsSync(path.join(assetsDir, 'preview.png'))
|
|
358
|
+
);
|
|
359
|
+
|
|
360
|
+
// Step: Add assets (only if not already copied)
|
|
361
|
+
if (!hasAssets) {
|
|
362
|
+
steps.push({
|
|
363
|
+
num: stepNum++,
|
|
364
|
+
manual: true,
|
|
365
|
+
text: `Add your 3D assets to ${c('cyan', `public/assets/${gameName}/`)}`,
|
|
366
|
+
detail: 'Download a GLTF asset pack from itch.io, Kenney.nl, or similar'
|
|
367
|
+
});
|
|
368
|
+
}
|
|
274
369
|
|
|
275
|
-
// Step: Add preview
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
370
|
+
// Step: Add preview (only if not found)
|
|
371
|
+
if (!previewExists) {
|
|
372
|
+
steps.push({
|
|
373
|
+
num: stepNum++,
|
|
374
|
+
manual: true,
|
|
375
|
+
text: `Ensure ${c('cyan', 'Preview.jpg')} exists in the assets folder`,
|
|
376
|
+
detail: 'Most asset packs include one, or take a screenshot of your assets'
|
|
377
|
+
});
|
|
378
|
+
}
|
|
282
379
|
|
|
283
380
|
// Step: API keys
|
|
284
381
|
if (!hasGoogleKey || !hasAnthropicKey) {
|