create-threejs-game 1.0.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.
- package/README.md +97 -0
- package/bin/cli.js +370 -0
- package/package.json +29 -0
- package/template/.claude/skills/threejs-animation/SKILL.md +552 -0
- package/template/.claude/skills/threejs-fundamentals/SKILL.md +488 -0
- package/template/.claude/skills/threejs-geometry/SKILL.md +548 -0
- package/template/.claude/skills/threejs-interaction/SKILL.md +660 -0
- package/template/.claude/skills/threejs-lighting/SKILL.md +481 -0
- package/template/.claude/skills/threejs-loaders/SKILL.md +623 -0
- package/template/.claude/skills/threejs-materials/SKILL.md +520 -0
- package/template/.claude/skills/threejs-postprocessing/SKILL.md +602 -0
- package/template/.claude/skills/threejs-shaders/SKILL.md +642 -0
- package/template/.claude/skills/threejs-textures/SKILL.md +628 -0
- package/template/.codex/skills/threejs-animation/SKILL.md +552 -0
- package/template/.codex/skills/threejs-fundamentals/SKILL.md +488 -0
- package/template/.codex/skills/threejs-geometry/SKILL.md +548 -0
- package/template/.codex/skills/threejs-interaction/SKILL.md +660 -0
- package/template/.codex/skills/threejs-lighting/SKILL.md +481 -0
- package/template/.codex/skills/threejs-loaders/SKILL.md +623 -0
- package/template/.codex/skills/threejs-materials/SKILL.md +520 -0
- package/template/.codex/skills/threejs-postprocessing/SKILL.md +602 -0
- package/template/.codex/skills/threejs-shaders/SKILL.md +642 -0
- package/template/.codex/skills/threejs-textures/SKILL.md +628 -0
- package/template/README.md +352 -0
- package/template/docs/.gitkeep +0 -0
- package/template/plans/.gitkeep +0 -0
- package/template/prompts/01-mockup-generation.md +44 -0
- package/template/prompts/02-prd-generation.md +119 -0
- package/template/prompts/03-tdd-generation.md +127 -0
- package/template/prompts/04-execution-plan.md +89 -0
- package/template/prompts/05-implementation.md +61 -0
- package/template/public/assets/.gitkeep +0 -0
- package/template/scripts/config.example.json +12 -0
- package/template/scripts/generate-assets-json.js +149 -0
- package/template/scripts/generate-mockup.js +197 -0
- package/template/scripts/generate-plan.js +295 -0
- package/template/scripts/generate-prd.js +297 -0
- package/template/scripts/generate-tdd.js +283 -0
- package/template/scripts/pipeline.js +229 -0
package/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# create-threejs-game
|
|
2
|
+
|
|
3
|
+
Scaffold a Three.js game project with AI-assisted design documents.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
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
|
+
```
|
|
13
|
+
|
|
14
|
+
## What it does
|
|
15
|
+
|
|
16
|
+
This CLI creates a Three.js game project with:
|
|
17
|
+
|
|
18
|
+
- **Three.js skills** for Claude/Codex AI assistance
|
|
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
|
|
26
|
+
|
|
27
|
+
## Interactive Setup
|
|
28
|
+
|
|
29
|
+
Run without arguments for interactive mode:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx create-threejs-game
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
You'll be asked for:
|
|
36
|
+
1. Project name
|
|
37
|
+
2. Game description (1-3 sentences)
|
|
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
|
|
45
|
+
|
|
46
|
+
After scaffolding, you'll need to:
|
|
47
|
+
|
|
48
|
+
1. **Add your 3D assets** to `public/assets/{game_name}/`
|
|
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
|
|
55
|
+
|
|
56
|
+
3. **Configure API keys** in `scripts/config.json`:
|
|
57
|
+
- Google AI Studio: for mockup generation
|
|
58
|
+
- Anthropic: for PRD/TDD/plan generation
|
|
59
|
+
|
|
60
|
+
## Automated Pipeline
|
|
61
|
+
|
|
62
|
+
Once configured, run:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
node scripts/pipeline.js
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
This generates all design documents automatically, leaving you with an implementation plan to follow in Claude Code or Cursor.
|
|
69
|
+
|
|
70
|
+
## Project Structure
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
my-game/
|
|
74
|
+
├── .claude/skills/ # Three.js skills for Claude
|
|
75
|
+
├── .codex/skills/ # Three.js skills for Codex
|
|
76
|
+
├── docs/ # Generated PRD and TDD
|
|
77
|
+
├── plans/ # Generated implementation plans
|
|
78
|
+
├── prompts/ # Manual prompt templates (fallback)
|
|
79
|
+
├── public/
|
|
80
|
+
│ └── assets/{game}/ # Your 3D assets go here
|
|
81
|
+
├── scripts/
|
|
82
|
+
│ ├── config.json # Your configuration
|
|
83
|
+
│ ├── pipeline.js # Run full automation
|
|
84
|
+
│ └── generate-*.js # Individual generators
|
|
85
|
+
└── README.md # Detailed workflow guide
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Requirements
|
|
89
|
+
|
|
90
|
+
- Node.js 18+
|
|
91
|
+
- API keys (for automation):
|
|
92
|
+
- [Google AI Studio](https://aistudio.google.com/) - free tier available
|
|
93
|
+
- [Anthropic](https://console.anthropic.com/) - API access required
|
|
94
|
+
|
|
95
|
+
## License
|
|
96
|
+
|
|
97
|
+
MIT
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* create-threejs-game CLI
|
|
5
|
+
*
|
|
6
|
+
* Interactive CLI to scaffold a Three.js game project with AI-assisted
|
|
7
|
+
* design documents and automation.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* npx create-threejs-game
|
|
11
|
+
* npx create-threejs-game my-game
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const readline = require('readline');
|
|
17
|
+
const { execSync, spawn } = require('child_process');
|
|
18
|
+
|
|
19
|
+
// Colors for terminal output
|
|
20
|
+
const colors = {
|
|
21
|
+
reset: '\x1b[0m',
|
|
22
|
+
bright: '\x1b[1m',
|
|
23
|
+
dim: '\x1b[2m',
|
|
24
|
+
red: '\x1b[31m',
|
|
25
|
+
green: '\x1b[32m',
|
|
26
|
+
yellow: '\x1b[33m',
|
|
27
|
+
blue: '\x1b[34m',
|
|
28
|
+
magenta: '\x1b[35m',
|
|
29
|
+
cyan: '\x1b[36m'
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const c = (color, text) => `${colors[color]}${text}${colors.reset}`;
|
|
33
|
+
|
|
34
|
+
// Banner
|
|
35
|
+
function showBanner() {
|
|
36
|
+
console.log('');
|
|
37
|
+
console.log(c('cyan', '╔═══════════════════════════════════════════════════════════════╗'));
|
|
38
|
+
console.log(c('cyan', '║') + c('bright', ' CREATE-THREEJS-GAME ') + c('cyan', '║'));
|
|
39
|
+
console.log(c('cyan', '║') + ' AI-Assisted Three.js Game Scaffolding ' + c('cyan', '║'));
|
|
40
|
+
console.log(c('cyan', '╚═══════════════════════════════════════════════════════════════╝'));
|
|
41
|
+
console.log('');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Readline interface
|
|
45
|
+
const rl = readline.createInterface({
|
|
46
|
+
input: process.stdin,
|
|
47
|
+
output: process.stdout
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Promisified question
|
|
51
|
+
function ask(question, defaultValue = '') {
|
|
52
|
+
const prompt = defaultValue
|
|
53
|
+
? `${question} ${c('dim', `(${defaultValue})`)}: `
|
|
54
|
+
: `${question}: `;
|
|
55
|
+
|
|
56
|
+
return new Promise((resolve) => {
|
|
57
|
+
rl.question(prompt, (answer) => {
|
|
58
|
+
resolve(answer.trim() || defaultValue);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Promisified yes/no
|
|
64
|
+
async function confirm(question, defaultYes = true) {
|
|
65
|
+
const hint = defaultYes ? 'Y/n' : 'y/N';
|
|
66
|
+
const answer = await ask(`${question} [${hint}]`);
|
|
67
|
+
|
|
68
|
+
if (!answer) return defaultYes;
|
|
69
|
+
return answer.toLowerCase().startsWith('y');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Copy directory recursively
|
|
73
|
+
function copyDir(src, dest, exclude = []) {
|
|
74
|
+
if (!fs.existsSync(dest)) {
|
|
75
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
79
|
+
|
|
80
|
+
for (const entry of entries) {
|
|
81
|
+
if (exclude.includes(entry.name)) continue;
|
|
82
|
+
|
|
83
|
+
const srcPath = path.join(src, entry.name);
|
|
84
|
+
const destPath = path.join(dest, entry.name);
|
|
85
|
+
|
|
86
|
+
if (entry.isDirectory()) {
|
|
87
|
+
copyDir(srcPath, destPath, exclude);
|
|
88
|
+
} else {
|
|
89
|
+
fs.copyFileSync(srcPath, destPath);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Run a script
|
|
95
|
+
function runScript(scriptPath, args = [], cwd) {
|
|
96
|
+
return new Promise((resolve, reject) => {
|
|
97
|
+
const child = spawn('node', [scriptPath, ...args], {
|
|
98
|
+
cwd,
|
|
99
|
+
stdio: 'inherit'
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
child.on('close', (code) => {
|
|
103
|
+
if (code === 0) resolve();
|
|
104
|
+
else reject(new Error(`Script exited with code ${code}`));
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
child.on('error', reject);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Main CLI
|
|
112
|
+
async function main() {
|
|
113
|
+
showBanner();
|
|
114
|
+
|
|
115
|
+
// Get project name from args or prompt
|
|
116
|
+
let projectName = process.argv[2];
|
|
117
|
+
|
|
118
|
+
if (!projectName) {
|
|
119
|
+
projectName = await ask(c('bright', 'Project name'), 'my-threejs-game');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Sanitize project name
|
|
123
|
+
projectName = projectName.toLowerCase().replace(/[^a-z0-9-_]/g, '-');
|
|
124
|
+
|
|
125
|
+
const projectPath = path.join(process.cwd(), projectName);
|
|
126
|
+
|
|
127
|
+
// Check if directory exists
|
|
128
|
+
if (fs.existsSync(projectPath)) {
|
|
129
|
+
const overwrite = await confirm(
|
|
130
|
+
c('yellow', `Directory "${projectName}" already exists. Overwrite?`),
|
|
131
|
+
false
|
|
132
|
+
);
|
|
133
|
+
if (!overwrite) {
|
|
134
|
+
console.log(c('red', '\nAborted.'));
|
|
135
|
+
rl.close();
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
fs.rmSync(projectPath, { recursive: true });
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
console.log('');
|
|
142
|
+
|
|
143
|
+
// Game name is same as project name (sanitized for folder)
|
|
144
|
+
const gameName = projectName.replace(/-/g, '_');
|
|
145
|
+
|
|
146
|
+
// Get game details
|
|
147
|
+
console.log(c('bright', '📝 Game Details'));
|
|
148
|
+
console.log(c('dim', '─'.repeat(50)));
|
|
149
|
+
console.log(c('dim', 'Describe your game in 1-3 sentences. Be specific about:'));
|
|
150
|
+
console.log(c('dim', ' - Game type (RTS, tower defense, puzzle, etc.)'));
|
|
151
|
+
console.log(c('dim', ' - Setting/theme'));
|
|
152
|
+
console.log(c('dim', ' - Core mechanics'));
|
|
153
|
+
console.log('');
|
|
154
|
+
|
|
155
|
+
const gameDescription = await ask(c('bright', 'Game description'));
|
|
156
|
+
|
|
157
|
+
if (!gameDescription) {
|
|
158
|
+
console.log(c('yellow', '\nWarning: No description provided. You can edit config.json later.'));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
console.log('');
|
|
162
|
+
|
|
163
|
+
// API Keys - check env vars first
|
|
164
|
+
let googleApiKey = process.env.GOOGLE_API_KEY || process.env.GOOGLE_AI_STUDIO_API_KEY || '';
|
|
165
|
+
let anthropicApiKey = process.env.ANTHROPIC_API_KEY || '';
|
|
166
|
+
|
|
167
|
+
const hasGoogleEnv = googleApiKey && googleApiKey.length > 10;
|
|
168
|
+
const hasAnthropicEnv = anthropicApiKey && anthropicApiKey.length > 10;
|
|
169
|
+
|
|
170
|
+
if (hasGoogleEnv && hasAnthropicEnv) {
|
|
171
|
+
console.log(c('bright', '🔑 API Keys'));
|
|
172
|
+
console.log(c('dim', '─'.repeat(50)));
|
|
173
|
+
console.log(c('green', ' ✓ ') + 'GOOGLE_API_KEY found in environment');
|
|
174
|
+
console.log(c('green', ' ✓ ') + 'ANTHROPIC_API_KEY found in environment');
|
|
175
|
+
console.log('');
|
|
176
|
+
} else {
|
|
177
|
+
console.log(c('bright', '🔑 API Keys (optional - can configure later)'));
|
|
178
|
+
console.log(c('dim', '─'.repeat(50)));
|
|
179
|
+
|
|
180
|
+
if (hasGoogleEnv) {
|
|
181
|
+
console.log(c('green', ' ✓ ') + 'GOOGLE_API_KEY found in environment');
|
|
182
|
+
} else {
|
|
183
|
+
console.log(c('dim', 'Google AI Studio enables automated mockup generation.'));
|
|
184
|
+
googleApiKey = await ask('Google AI Studio API key');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (hasAnthropicEnv) {
|
|
188
|
+
console.log(c('green', ' ✓ ') + 'ANTHROPIC_API_KEY found in environment');
|
|
189
|
+
} else {
|
|
190
|
+
console.log(c('dim', 'Anthropic enables automated PRD/TDD/plan generation.'));
|
|
191
|
+
anthropicApiKey = await ask('Anthropic API key');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
console.log('');
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Copy template
|
|
198
|
+
console.log(c('bright', '📦 Creating project...'));
|
|
199
|
+
console.log(c('dim', '─'.repeat(50)));
|
|
200
|
+
|
|
201
|
+
// Find template directory
|
|
202
|
+
const templateDir = path.join(__dirname, '..', 'template');
|
|
203
|
+
const fallbackTemplateDir = path.join(__dirname, '..');
|
|
204
|
+
|
|
205
|
+
const sourceDir = fs.existsSync(templateDir) ? templateDir : fallbackTemplateDir;
|
|
206
|
+
|
|
207
|
+
// Files/folders to copy
|
|
208
|
+
const itemsToCopy = ['.claude', '.codex', 'docs', 'plans', 'prompts', 'public', 'scripts', 'README.md'];
|
|
209
|
+
|
|
210
|
+
fs.mkdirSync(projectPath, { recursive: true });
|
|
211
|
+
|
|
212
|
+
for (const item of itemsToCopy) {
|
|
213
|
+
const srcPath = path.join(sourceDir, item);
|
|
214
|
+
const destPath = path.join(projectPath, item);
|
|
215
|
+
|
|
216
|
+
if (fs.existsSync(srcPath)) {
|
|
217
|
+
if (fs.statSync(srcPath).isDirectory()) {
|
|
218
|
+
copyDir(srcPath, destPath, ['node_modules', '.git']);
|
|
219
|
+
} else {
|
|
220
|
+
fs.copyFileSync(srcPath, destPath);
|
|
221
|
+
}
|
|
222
|
+
console.log(c('green', ' ✓ ') + item);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Create config.json
|
|
227
|
+
const config = {
|
|
228
|
+
google_ai_studio: {
|
|
229
|
+
api_key: googleApiKey || 'YOUR_GOOGLE_AI_STUDIO_API_KEY'
|
|
230
|
+
},
|
|
231
|
+
anthropic: {
|
|
232
|
+
api_key: anthropicApiKey || 'YOUR_ANTHROPIC_API_KEY'
|
|
233
|
+
},
|
|
234
|
+
game: {
|
|
235
|
+
name: gameName,
|
|
236
|
+
description: gameDescription || 'YOUR_GAME_DESCRIPTION'
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const configPath = path.join(projectPath, 'scripts', 'config.json');
|
|
241
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
242
|
+
console.log(c('green', ' ✓ ') + 'scripts/config.json');
|
|
243
|
+
|
|
244
|
+
// Create assets directory
|
|
245
|
+
const assetsDir = path.join(projectPath, 'public', 'assets', gameName);
|
|
246
|
+
fs.mkdirSync(assetsDir, { recursive: true });
|
|
247
|
+
fs.writeFileSync(path.join(assetsDir, '.gitkeep'), '');
|
|
248
|
+
console.log(c('green', ' ✓ ') + `public/assets/${gameName}/`);
|
|
249
|
+
|
|
250
|
+
console.log('');
|
|
251
|
+
console.log(c('green', `✅ Project created at: ${projectPath}`));
|
|
252
|
+
console.log('');
|
|
253
|
+
|
|
254
|
+
// Check if we can run automation
|
|
255
|
+
const hasGoogleKey = googleApiKey && !googleApiKey.includes('YOUR_');
|
|
256
|
+
const hasAnthropicKey = anthropicApiKey && !anthropicApiKey.includes('YOUR_');
|
|
257
|
+
const hasDescription = gameDescription && gameDescription.length > 10;
|
|
258
|
+
|
|
259
|
+
// Next steps
|
|
260
|
+
console.log(c('bright', '📋 Next Steps'));
|
|
261
|
+
console.log(c('dim', '─'.repeat(50)));
|
|
262
|
+
console.log('');
|
|
263
|
+
|
|
264
|
+
const steps = [];
|
|
265
|
+
let stepNum = 1;
|
|
266
|
+
|
|
267
|
+
// Step: Add assets
|
|
268
|
+
steps.push({
|
|
269
|
+
num: stepNum++,
|
|
270
|
+
manual: true,
|
|
271
|
+
text: `Add your 3D assets to ${c('cyan', `public/assets/${gameName}/`)}`,
|
|
272
|
+
detail: 'Download a GLTF asset pack from itch.io, Kenney.nl, or similar'
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
// Step: Add preview
|
|
276
|
+
steps.push({
|
|
277
|
+
num: stepNum++,
|
|
278
|
+
manual: true,
|
|
279
|
+
text: `Ensure ${c('cyan', 'Preview.jpg')} exists in the assets folder`,
|
|
280
|
+
detail: 'Most asset packs include one, or take a screenshot of your assets'
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
// Step: API keys
|
|
284
|
+
if (!hasGoogleKey || !hasAnthropicKey) {
|
|
285
|
+
const missing = [];
|
|
286
|
+
if (!hasGoogleKey) missing.push('Google AI Studio');
|
|
287
|
+
if (!hasAnthropicKey) missing.push('Anthropic');
|
|
288
|
+
|
|
289
|
+
steps.push({
|
|
290
|
+
num: stepNum++,
|
|
291
|
+
manual: true,
|
|
292
|
+
text: `Add API keys to ${c('cyan', 'scripts/config.json')}`,
|
|
293
|
+
detail: `Missing: ${missing.join(', ')}`
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Step: Description
|
|
298
|
+
if (!hasDescription) {
|
|
299
|
+
steps.push({
|
|
300
|
+
num: stepNum++,
|
|
301
|
+
manual: true,
|
|
302
|
+
text: `Add game description to ${c('cyan', 'scripts/config.json')}`,
|
|
303
|
+
detail: 'Be specific about game type, setting, and mechanics'
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Step: Run pipeline
|
|
308
|
+
steps.push({
|
|
309
|
+
num: stepNum++,
|
|
310
|
+
manual: false,
|
|
311
|
+
text: `Run ${c('cyan', 'node scripts/pipeline.js')}`,
|
|
312
|
+
detail: 'Generates assets.json, mockup, PRD, TDD, and execution plan'
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// Step: Implement
|
|
316
|
+
steps.push({
|
|
317
|
+
num: stepNum++,
|
|
318
|
+
manual: false,
|
|
319
|
+
text: 'Open in Claude Code/Cursor and follow the generated plan',
|
|
320
|
+
detail: 'The plan will be in plans/ folder with implementation instructions'
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// Print steps
|
|
324
|
+
for (const step of steps) {
|
|
325
|
+
const icon = step.manual ? c('yellow', '🖐️ ') : c('green', '🤖 ');
|
|
326
|
+
const label = step.manual ? c('yellow', '[MANUAL]') : c('green', '[AUTO]');
|
|
327
|
+
|
|
328
|
+
console.log(`${icon}${step.num}. ${step.text}`);
|
|
329
|
+
console.log(` ${label} ${c('dim', step.detail)}`);
|
|
330
|
+
console.log('');
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Summary
|
|
334
|
+
console.log(c('dim', '─'.repeat(50)));
|
|
335
|
+
console.log('');
|
|
336
|
+
console.log(c('bright', 'Quick commands:'));
|
|
337
|
+
console.log(` ${c('cyan', `cd ${projectName}`)}`);
|
|
338
|
+
console.log(` ${c('cyan', 'node scripts/pipeline.js')} ${c('dim', '# After adding assets')}`);
|
|
339
|
+
console.log('');
|
|
340
|
+
|
|
341
|
+
// Offer to open directory
|
|
342
|
+
const openDir = await confirm('Open project directory?', true);
|
|
343
|
+
|
|
344
|
+
rl.close();
|
|
345
|
+
|
|
346
|
+
if (openDir) {
|
|
347
|
+
try {
|
|
348
|
+
if (process.platform === 'darwin') {
|
|
349
|
+
execSync(`open "${projectPath}"`);
|
|
350
|
+
} else if (process.platform === 'win32') {
|
|
351
|
+
execSync(`start "" "${projectPath}"`);
|
|
352
|
+
} else {
|
|
353
|
+
execSync(`xdg-open "${projectPath}"`);
|
|
354
|
+
}
|
|
355
|
+
} catch (e) {
|
|
356
|
+
console.log(c('dim', `cd ${projectPath}`));
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
console.log('');
|
|
361
|
+
console.log(c('green', '🎮 Happy game building!'));
|
|
362
|
+
console.log('');
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Run
|
|
366
|
+
main().catch((err) => {
|
|
367
|
+
console.error(c('red', '\nError: ') + err.message);
|
|
368
|
+
rl.close();
|
|
369
|
+
process.exit(1);
|
|
370
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-threejs-game",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Scaffold a Three.js game project with AI-assisted design documents",
|
|
5
|
+
"bin": {
|
|
6
|
+
"create-threejs-game": "./bin/cli.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"bin",
|
|
10
|
+
"template"
|
|
11
|
+
],
|
|
12
|
+
"keywords": [
|
|
13
|
+
"threejs",
|
|
14
|
+
"game",
|
|
15
|
+
"scaffold",
|
|
16
|
+
"cli",
|
|
17
|
+
"ai",
|
|
18
|
+
"vibe-coding"
|
|
19
|
+
],
|
|
20
|
+
"author": "ElementTech",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/ElementTech/create-threejs-game.git"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18.0.0"
|
|
28
|
+
}
|
|
29
|
+
}
|