create-pixifact 0.1.3
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 +31 -0
- package/dist/createPixifactProject.d.ts +11 -0
- package/dist/createPixifactProject.js +68 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +26 -0
- package/package.json +38 -0
- package/templates/minimal/index.html +12 -0
- package/templates/minimal/package.json +20 -0
- package/templates/minimal/pixifact.project.json +13 -0
- package/templates/minimal/src/main.ts +22 -0
- package/templates/minimal/src/pixifact-env.d.ts +1 -0
- package/templates/minimal/src/scenes/MainMenu.scene +8 -0
- package/templates/minimal/src/scenes/MainMenu.ts +29 -0
- package/templates/minimal/src/styles.css +16 -0
- package/templates/minimal/tsconfig.json +13 -0
- package/templates/minimal/vite.config.ts +10 -0
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# create-pixifact
|
|
2
|
+
|
|
3
|
+
Create a Bun-first Pixifact game project.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun create pixifact my-game
|
|
9
|
+
cd my-game
|
|
10
|
+
bun install
|
|
11
|
+
bun run dev
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The generated project includes:
|
|
15
|
+
|
|
16
|
+
- `pixifact.project.json`
|
|
17
|
+
- a minimal Pixifact Scene pair
|
|
18
|
+
- Vite project scripts
|
|
19
|
+
- `pixifact` and `pixifact-cli` dependencies
|
|
20
|
+
|
|
21
|
+
## Generated Scripts
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
bun run compile:scenes
|
|
25
|
+
bun run dev
|
|
26
|
+
bun run build
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Requirements
|
|
30
|
+
|
|
31
|
+
- Bun
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface CreatePixifactProjectOptions {
|
|
2
|
+
cwd?: string;
|
|
3
|
+
name: string;
|
|
4
|
+
template?: 'minimal';
|
|
5
|
+
}
|
|
6
|
+
export interface CreatePixifactProjectResult {
|
|
7
|
+
name: string;
|
|
8
|
+
root: string;
|
|
9
|
+
template: 'minimal';
|
|
10
|
+
}
|
|
11
|
+
export declare function createPixifactProject(options: CreatePixifactProjectOptions): Promise<CreatePixifactProjectResult>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { cp, mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
const defaultPort = 5177;
|
|
5
|
+
function packageDirectory() {
|
|
6
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
7
|
+
const sourceDirectory = path.basename(path.dirname(currentFile));
|
|
8
|
+
return sourceDirectory === 'src' || sourceDirectory === 'dist'
|
|
9
|
+
? path.resolve(currentFile, '../..')
|
|
10
|
+
: path.resolve(currentFile, '..');
|
|
11
|
+
}
|
|
12
|
+
function templateDirectory(template) {
|
|
13
|
+
return path.join(packageDirectory(), 'templates', template);
|
|
14
|
+
}
|
|
15
|
+
function projectDisplayName(name) {
|
|
16
|
+
return name
|
|
17
|
+
.split(/[-_\s]+/)
|
|
18
|
+
.filter(Boolean)
|
|
19
|
+
.map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`)
|
|
20
|
+
.join(' ');
|
|
21
|
+
}
|
|
22
|
+
async function directoryIsEmpty(target) {
|
|
23
|
+
try {
|
|
24
|
+
const targetStat = await stat(target);
|
|
25
|
+
if (!targetStat.isDirectory()) {
|
|
26
|
+
throw new Error('Target path exists and is not a directory.');
|
|
27
|
+
}
|
|
28
|
+
return (await readdir(target)).length === 0;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error.code === 'ENOENT') {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async function writeJson(filePath, value) {
|
|
38
|
+
await writeFile(filePath, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
|
|
39
|
+
}
|
|
40
|
+
export async function createPixifactProject(options) {
|
|
41
|
+
const template = options.template ?? 'minimal';
|
|
42
|
+
const cwd = options.cwd ?? process.cwd();
|
|
43
|
+
const projectRoot = path.resolve(cwd, options.name);
|
|
44
|
+
if (!(await directoryIsEmpty(projectRoot))) {
|
|
45
|
+
throw new Error('Target directory is not empty.');
|
|
46
|
+
}
|
|
47
|
+
await mkdir(projectRoot, { recursive: true });
|
|
48
|
+
await cp(templateDirectory(template), projectRoot, { recursive: true });
|
|
49
|
+
const packageJsonPath = path.join(projectRoot, 'package.json');
|
|
50
|
+
const packageJson = JSON.parse(await readFile(packageJsonPath, 'utf8'));
|
|
51
|
+
packageJson.name = options.name;
|
|
52
|
+
await writeJson(packageJsonPath, packageJson);
|
|
53
|
+
const projectJsonPath = path.join(projectRoot, 'pixifact.project.json');
|
|
54
|
+
const projectJson = JSON.parse(await readFile(projectJsonPath, 'utf8'));
|
|
55
|
+
projectJson.name = projectDisplayName(options.name);
|
|
56
|
+
projectJson.run = {
|
|
57
|
+
command: 'bun',
|
|
58
|
+
args: ['run', 'dev'],
|
|
59
|
+
cwd: '.',
|
|
60
|
+
url: `http://127.0.0.1:${defaultPort}`,
|
|
61
|
+
};
|
|
62
|
+
await writeJson(projectJsonPath, projectJson);
|
|
63
|
+
return {
|
|
64
|
+
name: options.name,
|
|
65
|
+
root: projectRoot,
|
|
66
|
+
template,
|
|
67
|
+
};
|
|
68
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { createPixifactProject } from './createPixifactProject';
|
|
3
|
+
function usage() {
|
|
4
|
+
return [
|
|
5
|
+
'Usage:',
|
|
6
|
+
' bun create pixifact <project-name>',
|
|
7
|
+
'',
|
|
8
|
+
].join('\n');
|
|
9
|
+
}
|
|
10
|
+
const name = process.argv[2];
|
|
11
|
+
if (!name || name === '--help' || name === '-h') {
|
|
12
|
+
process.stdout.write(usage());
|
|
13
|
+
process.exitCode = name ? 0 : 1;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
try {
|
|
17
|
+
const result = await createPixifactProject({ name });
|
|
18
|
+
process.stdout.write(`Created ${result.name} at ${result.root}\n`);
|
|
19
|
+
process.stdout.write(`Next: cd ${result.name} && bun install && bun run dev\n`);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export { createPixifactProject };
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-pixifact",
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "Create a Pixifact game project.",
|
|
5
|
+
"packageManager": "bun@1.3.13",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"create-pixifact": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/",
|
|
12
|
+
"templates/"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/hxg2050/pixifact.git",
|
|
17
|
+
"directory": "packages/create-pixifact"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"pixifact",
|
|
21
|
+
"create-pixifact",
|
|
22
|
+
"game",
|
|
23
|
+
"pixijs",
|
|
24
|
+
"scene"
|
|
25
|
+
],
|
|
26
|
+
"author": "youxia <243802688@qq.com>",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"registry": "https://registry.npmjs.org/"
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "bunx --no-install tsc -p tsconfig.build.json"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^25.9.1",
|
|
36
|
+
"typescript": "^5.3.3"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Pixifact Game</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="game"></div>
|
|
10
|
+
<script type="module" src="/src/main.ts"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pixifact-minimal-game",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"compile:scenes": "pixifact compile-scenes --project-root .",
|
|
8
|
+
"dev": "bun run compile:scenes && vite . --host 127.0.0.1 --port 5177 --strictPort",
|
|
9
|
+
"build": "bun run compile:scenes && vite build . --config vite.config.ts"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"pixi.js": "8.18.1",
|
|
13
|
+
"pixifact": "^0.1.3"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"pixifact-cli": "^0.1.3",
|
|
17
|
+
"typescript": "^5.3.3",
|
|
18
|
+
"vite": "^8.0.10"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import './styles.css';
|
|
2
|
+
import 'pixifact:scenes';
|
|
3
|
+
import { Application } from 'pixi.js';
|
|
4
|
+
import { MainMenu } from './scenes/MainMenu';
|
|
5
|
+
|
|
6
|
+
const root = document.querySelector<HTMLElement>('#game');
|
|
7
|
+
if (!root) {
|
|
8
|
+
throw new Error('Missing #game root.');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const app = new Application();
|
|
12
|
+
await app.init({
|
|
13
|
+
width: 960,
|
|
14
|
+
height: 540,
|
|
15
|
+
backgroundColor: 0x10131d,
|
|
16
|
+
antialias: true,
|
|
17
|
+
autoDensity: true,
|
|
18
|
+
resolution: Math.min(window.devicePixelRatio || 1, 2),
|
|
19
|
+
});
|
|
20
|
+
root.append(app.canvas);
|
|
21
|
+
|
|
22
|
+
app.stage.addChild(new MainMenu());
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module 'pixifact:scenes' {}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<Scene name="MainMenu" width="960" height="540">
|
|
2
|
+
<Graphics id="background" shape="rect" width="960" height="540" fill="#10131d" />
|
|
3
|
+
<Graphics id="panel" shape="roundRect" x="260" y="148" width="440" height="244" radius="24" fill="#182033" strokeColor="#38bdf8" strokeWidth="2" strokeAlpha="0.72" />
|
|
4
|
+
<Text id="titleText" text="Pixifact Game" x="314" y="202" fontSize="44" fontWeight="700" fill="#f8fafc" />
|
|
5
|
+
<Text id="hintText" text="Edit src/scenes/MainMenu.scene, then run pixifact validate and compile." x="300" y="278" fontSize="18" fill="#cbd5e1" />
|
|
6
|
+
<Graphics id="startButtonBack" shape="roundRect" x="378" y="326" width="204" height="50" radius="14" fill="#2563eb" />
|
|
7
|
+
<Text id="startLabel" text="START" x="435" y="340" fontSize="20" fontWeight="700" fill="#ffffff" />
|
|
8
|
+
</Scene>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Container, Graphics, Text } from 'pixi.js';
|
|
2
|
+
import { createEvent, event, part, scene } from 'pixifact/compiler';
|
|
3
|
+
|
|
4
|
+
@scene()
|
|
5
|
+
export class MainMenu extends Container {
|
|
6
|
+
@part()
|
|
7
|
+
protected declare startButtonBack: Graphics;
|
|
8
|
+
|
|
9
|
+
@part()
|
|
10
|
+
protected declare startLabel: Text;
|
|
11
|
+
|
|
12
|
+
@event()
|
|
13
|
+
readonly start = createEvent();
|
|
14
|
+
|
|
15
|
+
onMounted() {
|
|
16
|
+
this.startButtonBack.eventMode = 'static';
|
|
17
|
+
this.startButtonBack.cursor = 'pointer';
|
|
18
|
+
this.startButtonBack.on('pointertap', () => {
|
|
19
|
+
this.startLabel.text = 'READY';
|
|
20
|
+
this.start.emit();
|
|
21
|
+
});
|
|
22
|
+
this.startButtonBack.on('pointerover', () => {
|
|
23
|
+
this.startButtonBack.tint = 0xc7d2fe;
|
|
24
|
+
});
|
|
25
|
+
this.startButtonBack.on('pointerout', () => {
|
|
26
|
+
this.startButtonBack.tint = 0xffffff;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ESNext",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "Node",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"experimentalDecorators": true,
|
|
8
|
+
"useDefineForClassFields": true,
|
|
9
|
+
"lib": ["ESNext", "DOM"],
|
|
10
|
+
"skipLibCheck": true
|
|
11
|
+
},
|
|
12
|
+
"include": ["src/**/*.ts"]
|
|
13
|
+
}
|