@pixelvibing/cli 0.49.1 → 0.50.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 +4 -2
- package/dist/pixel-vibing-cli.js +147 -10
- package/package.json +1 -1
- package/skills/pixelvibing/SKILL.md +51 -66
- package/skills/pixelvibing-change/SKILL.md +42 -0
- package/skills/pixelvibing-concept-art/SKILL.md +56 -0
- package/skills/pixelvibing-creature/SKILL.md +44 -0
- package/skills/pixelvibing-icons/SKILL.md +42 -0
- package/skills/pixelvibing-object/SKILL.md +46 -0
- package/skills/pixelvibing-style-guide/SKILL.md +4 -0
- package/skills/pixelvibing-ui/SKILL.md +48 -0
- /package/skills/{pixelvibing → pixelvibing-ui}/references/ui.example.json +0 -0
- /package/skills/{pixelvibing → pixelvibing-ui}/references/ui.md +0 -0
- /package/skills/{pixelvibing → pixelvibing-ui}/references/ui.schema.json +0 -0
package/README.md
CHANGED
|
@@ -12,7 +12,9 @@ pixel-vibing-cli setup
|
|
|
12
12
|
|
|
13
13
|
`setup` signs you in in the browser, makes the directory a local project, which means a
|
|
14
14
|
`pixelvibing.json` and a `pixelvibing/` folder, links it to one of your platform
|
|
15
|
-
projects, and installs the Skills into `.claude/skills/` or `.codex/skills
|
|
15
|
+
projects, and installs the Skills into `.claude/skills/` or `.codex/skills/`: a hub, the
|
|
16
|
+
style guide's, and one for each kind of art. A block in `AGENTS.md`, and in `CLAUDE.md` when
|
|
17
|
+
there is one, names which Skill to load for which request. It also
|
|
16
18
|
configures the remote MCP server in `.mcp.json` or `.codex/config.toml`, by a command
|
|
17
19
|
that prints the token's header when the harness connects, so the token is in no file.
|
|
18
20
|
Each step it finds done already is skipped.
|
|
@@ -27,7 +29,7 @@ Each step it finds done already is skipped.
|
|
|
27
29
|
| `guide pull\|push\|revise\|show\|versions` | Read and write the project's style guide |
|
|
28
30
|
| `seal` | Seal `pixelvibing/out/` into `pixelvibing/build/assets.eac` |
|
|
29
31
|
| `export default\|pixi\|phaser\|godot` | Pack the art into sprite sheets and the map into placed sprites, for an engine |
|
|
30
|
-
| `update` | Replace the installed Skills with the ones this version ships, and bring the MCP server's entry to it |
|
|
32
|
+
| `update` | Replace the installed Skills with the ones this version ships, add those it ships since, rewrite their block in `AGENTS.md`, and bring the MCP server's entry to it |
|
|
31
33
|
| `mcp headers` | Print the header a harness sends the remote MCP server, from the kept token |
|
|
32
34
|
| `editor` | Open the PixelVibing desktop app on the project |
|
|
33
35
|
|
package/dist/pixel-vibing-cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { resolve, dirname, join, relative, sep, basename } from "node:path";
|
|
2
|
+
import { resolve, dirname, join, relative, sep, basename, isAbsolute } from "node:path";
|
|
3
3
|
import { realpath, promises } from "node:fs";
|
|
4
4
|
import { promisify, parseArgs } from "node:util";
|
|
5
5
|
import { randomBytes, createHash } from "node:crypto";
|
|
@@ -4165,6 +4165,12 @@ async function referenceOf(context, path) {
|
|
|
4165
4165
|
return bytes;
|
|
4166
4166
|
}
|
|
4167
4167
|
async function requestOf(context, asked, args) {
|
|
4168
|
+
const request = await shapedRequest(context, asked, args);
|
|
4169
|
+
if (!flagOf(args, "no-enrich")) return request;
|
|
4170
|
+
if (request.kind === "ui-sketch") throw new CliError("--no-enrich is not a UI's: its layout is read as it is");
|
|
4171
|
+
return { ...request, body: { ...request.body, enrich: false } };
|
|
4172
|
+
}
|
|
4173
|
+
async function shapedRequest(context, asked, args) {
|
|
4168
4174
|
const kind = KIND_NAMES[asked] ?? asked;
|
|
4169
4175
|
const known = GENERATED[kind];
|
|
4170
4176
|
if (known === void 0) throw new CliError(`generate makes ${Object.keys(GENERATED).join(", ")} (or ui), not ${asked}`);
|
|
@@ -4247,7 +4253,7 @@ async function followed(context, platform, jobId) {
|
|
|
4247
4253
|
const generate = {
|
|
4248
4254
|
name: "generate",
|
|
4249
4255
|
summary: "Generate an object, a creature, concept art, icons or a UI on the platform, then pull it",
|
|
4250
|
-
usage: "<object|creature|concept-art|icons|ui> [--instruction <text>] [--size <c>x<r>|<w>x<h>|<px>] [--transparent] [--pixel-art] [--tiles <c>x<r>] [--tag <tag>]… [--names <list>] [--purpose skill|item] [--sketch <json>] [--reference <png>]… [--yes]",
|
|
4256
|
+
usage: "<object|creature|concept-art|icons|ui> [--instruction <text>] [--size <c>x<r>|<w>x<h>|<px>] [--transparent] [--pixel-art] [--tiles <c>x<r>] [--tag <tag>]… [--names <list>] [--purpose skill|item] [--sketch <json>] [--reference <png>]… [--no-enrich] [--yes]",
|
|
4251
4257
|
options: {
|
|
4252
4258
|
instruction: {
|
|
4253
4259
|
type: "string",
|
|
@@ -4277,6 +4283,10 @@ const generate = {
|
|
|
4277
4283
|
},
|
|
4278
4284
|
reference: { type: "string", multiple: true, value: "<png>", description: "an image to draw from" },
|
|
4279
4285
|
quality: { type: "string", value: "<quality>", description: "the platform's to choose now; ignored, and said so" },
|
|
4286
|
+
"no-enrich": {
|
|
4287
|
+
type: "boolean",
|
|
4288
|
+
description: "draw from --instruction as written, without the platform writing a fuller one from it and the style guide; not a UI's"
|
|
4289
|
+
},
|
|
4280
4290
|
yes: { type: "boolean", short: "y", description: "start it without asking, once what it uses of your limit is said" },
|
|
4281
4291
|
as: { type: "string", value: "<name>", description: "land it under this name instead of the platform's" },
|
|
4282
4292
|
aside: { type: "boolean", description: "keep a folder's own map and art under pixelvibing/before-platform/, and write it from the platform" }
|
|
@@ -4752,7 +4762,7 @@ const move = {
|
|
|
4752
4762
|
);
|
|
4753
4763
|
}
|
|
4754
4764
|
};
|
|
4755
|
-
const version = "0.
|
|
4765
|
+
const version = "0.50.0";
|
|
4756
4766
|
const manifest = {
|
|
4757
4767
|
version
|
|
4758
4768
|
};
|
|
@@ -4767,7 +4777,7 @@ function mcpEntry(apiUrl) {
|
|
|
4767
4777
|
if (apiUrl === DEFAULT_API_URL) return { url: DEFAULT_MCP_URL, headers: `npx --yes ${PINNED_PACKAGE} mcp headers` };
|
|
4768
4778
|
return { url: `${apiUrl}/mcp`, headers: `npx --yes ${PINNED_PACKAGE} mcp headers --api ${apiUrl}` };
|
|
4769
4779
|
}
|
|
4770
|
-
async function textOf(path) {
|
|
4780
|
+
async function textOf$1(path) {
|
|
4771
4781
|
try {
|
|
4772
4782
|
return await readFile(path, "utf8");
|
|
4773
4783
|
} catch (error) {
|
|
@@ -4820,7 +4830,7 @@ function codexWith(text2, entry, onlyWhereConfigured) {
|
|
|
4820
4830
|
async function configureHarness(root, harness, entry, onlyWhereConfigured = false) {
|
|
4821
4831
|
const file = harness === "claude" ? CLAUDE_FILE : CODEX_FILE;
|
|
4822
4832
|
const path = join(root, file);
|
|
4823
|
-
const text2 = await textOf(path);
|
|
4833
|
+
const text2 = await textOf$1(path);
|
|
4824
4834
|
const next = harness === "claude" ? claudeWith(text2, entry, onlyWhereConfigured) : codexWith(text2, entry, onlyWhereConfigured);
|
|
4825
4835
|
if (next === null) return "absent";
|
|
4826
4836
|
if (next === text2) return "current";
|
|
@@ -4956,9 +4966,127 @@ async function updateSkills(root, skills) {
|
|
|
4956
4966
|
}
|
|
4957
4967
|
return updated;
|
|
4958
4968
|
}
|
|
4969
|
+
const BLOCK_OPEN = "<!-- pixelvibing:skills -->";
|
|
4970
|
+
const BLOCK_CLOSE = "<!-- /pixelvibing:skills -->";
|
|
4971
|
+
const ROUTED_FILES = [
|
|
4972
|
+
{ file: "AGENTS.md", made: true },
|
|
4973
|
+
{ file: "CLAUDE.md", made: false }
|
|
4974
|
+
];
|
|
4975
|
+
function descriptionOf(skill) {
|
|
4976
|
+
return /^---\n(?:.*\n)*?description: (.+)\n(?:.*\n)*?---\n/.exec(skill.text)?.[1]?.trim() ?? "";
|
|
4977
|
+
}
|
|
4978
|
+
function routingBlock(skills) {
|
|
4979
|
+
const lines = skills.map((skill) => `- \`${skill.name}\` — ${descriptionOf(skill)}`);
|
|
4980
|
+
return [
|
|
4981
|
+
BLOCK_OPEN,
|
|
4982
|
+
"## PixelVibing art",
|
|
4983
|
+
"",
|
|
4984
|
+
"This game's art is made on PixelVibing. Before making, finding, pulling or exporting any of it,",
|
|
4985
|
+
"load the Skill for the request from `.claude/skills/` or `.codex/skills/` and follow it,",
|
|
4986
|
+
"starting with `pixelvibing`. Never write a PixelVibing token into a file or a command.",
|
|
4987
|
+
"",
|
|
4988
|
+
...lines,
|
|
4989
|
+
BLOCK_CLOSE
|
|
4990
|
+
].join("\n");
|
|
4991
|
+
}
|
|
4992
|
+
function markerLines(text2, marker) {
|
|
4993
|
+
const escaped = marker.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
|
|
4994
|
+
return [...text2.matchAll(new RegExp(`^[ \\t]*${escaped}[ \\t]*(?=\\r?$)`, "gm"))].map((found) => ({
|
|
4995
|
+
start: found.index,
|
|
4996
|
+
end: found.index + found[0].length
|
|
4997
|
+
}));
|
|
4998
|
+
}
|
|
4999
|
+
function withBlock(text2, block) {
|
|
5000
|
+
const newline = text2.includes("\r\n") ? "\r\n" : "\n";
|
|
5001
|
+
const written = block.replace(/\n/g, newline);
|
|
5002
|
+
const opens = markerLines(text2, BLOCK_OPEN);
|
|
5003
|
+
const closes = markerLines(text2, BLOCK_CLOSE);
|
|
5004
|
+
if (opens.length === 0 && closes.length === 0) {
|
|
5005
|
+
const before = text2.replace(/(\r?\n)*$/, "");
|
|
5006
|
+
return `${before === "" ? "" : `${before}${newline}${newline}`}${written}${newline}`;
|
|
5007
|
+
}
|
|
5008
|
+
const [open] = opens;
|
|
5009
|
+
const [close] = closes;
|
|
5010
|
+
if (opens.length !== 1 || closes.length !== 1 || open === void 0 || close === void 0 || close.start < open.end) return null;
|
|
5011
|
+
return `${text2.slice(0, open.start)}${written}${text2.slice(close.end)}`;
|
|
5012
|
+
}
|
|
5013
|
+
async function writablePath(root, path) {
|
|
5014
|
+
let linked;
|
|
5015
|
+
try {
|
|
5016
|
+
linked = (await lstat(path)).isSymbolicLink();
|
|
5017
|
+
} catch (error) {
|
|
5018
|
+
if (error.code === "ENOENT") return path;
|
|
5019
|
+
throw error;
|
|
5020
|
+
}
|
|
5021
|
+
if (!linked) return path;
|
|
5022
|
+
let target;
|
|
5023
|
+
try {
|
|
5024
|
+
target = await realpath$1(path);
|
|
5025
|
+
} catch {
|
|
5026
|
+
return null;
|
|
5027
|
+
}
|
|
5028
|
+
const within = relative(await realpath$1(root), target);
|
|
5029
|
+
return within !== "" && !within.startsWith("..") && !isAbsolute(within) ? target : null;
|
|
5030
|
+
}
|
|
5031
|
+
async function textOf(path) {
|
|
5032
|
+
try {
|
|
5033
|
+
return await readFile(path, "utf8");
|
|
5034
|
+
} catch (error) {
|
|
5035
|
+
if (error.code === "ENOENT") return null;
|
|
5036
|
+
throw error;
|
|
5037
|
+
}
|
|
5038
|
+
}
|
|
5039
|
+
async function replaceFile(path, text2) {
|
|
5040
|
+
const aside = join(dirname(path), `.${basename(path)}.pixelvibing-${process.pid}`);
|
|
5041
|
+
await writeFile(aside, text2);
|
|
5042
|
+
try {
|
|
5043
|
+
await rename(aside, path);
|
|
5044
|
+
} catch (error) {
|
|
5045
|
+
await rm(aside, { force: true });
|
|
5046
|
+
throw error;
|
|
5047
|
+
}
|
|
5048
|
+
}
|
|
5049
|
+
async function writeRouting(root, skills) {
|
|
5050
|
+
const block = routingBlock(skills);
|
|
5051
|
+
const routed = [];
|
|
5052
|
+
for (const { file, made } of ROUTED_FILES) {
|
|
5053
|
+
const path = await writablePath(root, join(root, file));
|
|
5054
|
+
if (path === null) {
|
|
5055
|
+
routed.push({ file, state: "outside" });
|
|
5056
|
+
continue;
|
|
5057
|
+
}
|
|
5058
|
+
const text2 = await textOf(path);
|
|
5059
|
+
if (text2 === null && !made) {
|
|
5060
|
+
routed.push({ file, state: "absent" });
|
|
5061
|
+
continue;
|
|
5062
|
+
}
|
|
5063
|
+
const next = withBlock(text2 ?? "", block);
|
|
5064
|
+
if (next === null) routed.push({ file, state: "unreadable" });
|
|
5065
|
+
else if (next === text2) routed.push({ file, state: "current" });
|
|
5066
|
+
else {
|
|
5067
|
+
await replaceFile(path, next);
|
|
5068
|
+
routed.push({ file, state: "written" });
|
|
5069
|
+
}
|
|
5070
|
+
}
|
|
5071
|
+
return routed;
|
|
5072
|
+
}
|
|
5073
|
+
function routingWords(routed) {
|
|
5074
|
+
const why = {
|
|
5075
|
+
unreadable: `holds ${BLOCK_OPEN} and ${BLOCK_CLOSE} other than once each, on lines of their own, in that order`,
|
|
5076
|
+
outside: "is a link to a file outside this repository"
|
|
5077
|
+
};
|
|
5078
|
+
return {
|
|
5079
|
+
done: routed.filter((each) => each.state === "written").map((each) => `named the Skills to load in ${each.file}`),
|
|
5080
|
+
warnings: routed.flatMap((each) => {
|
|
5081
|
+
const reason = why[each.state];
|
|
5082
|
+
return reason === void 0 ? [] : [`${each.file} ${reason}: it was left as it is.
|
|
5083
|
+
`];
|
|
5084
|
+
})
|
|
5085
|
+
};
|
|
5086
|
+
}
|
|
4959
5087
|
const setup = {
|
|
4960
5088
|
name: "setup",
|
|
4961
|
-
summary: "Sign in, make and link the local project,
|
|
5089
|
+
summary: "Sign in, make and link the local project, install the Skills and name them in AGENTS.md, doing only what is missing",
|
|
4962
5090
|
usage: "[--harness claude|codex]… [--project <id|name> | --idea <text>] [--name <name>] [--provider <name>]",
|
|
4963
5091
|
options: {
|
|
4964
5092
|
harness: {
|
|
@@ -5005,19 +5133,24 @@ const setup = {
|
|
|
5005
5133
|
`);
|
|
5006
5134
|
}
|
|
5007
5135
|
}
|
|
5136
|
+
const routing = await writeRouting(local.root, skills);
|
|
5137
|
+
const said = routingWords(routing);
|
|
5138
|
+
done.push(...said.done);
|
|
5139
|
+
for (const warning of said.warnings) context.io.warn(warning);
|
|
5008
5140
|
answer(
|
|
5009
5141
|
context,
|
|
5010
|
-
{ root: local.root, project: linked, harnesses: installed },
|
|
5142
|
+
{ root: local.root, project: linked, harnesses: installed, routing },
|
|
5011
5143
|
done.length === 0 ? "Nothing to do: this repository is set up." : `Set up: ${done.join("; ")}.`
|
|
5012
5144
|
);
|
|
5013
5145
|
}
|
|
5014
5146
|
};
|
|
5015
5147
|
const update = {
|
|
5016
5148
|
name: "update",
|
|
5017
|
-
summary: "Replace the installed Skills this CLI ships differently,
|
|
5149
|
+
summary: "Replace the installed Skills this CLI ships differently, add those it ships since, and name them in AGENTS.md",
|
|
5018
5150
|
run: async (context) => {
|
|
5019
5151
|
const local = await projectHere(context.io.cwd);
|
|
5020
|
-
const
|
|
5152
|
+
const skills = await shippedSkills();
|
|
5153
|
+
const updated = await updateSkills(local.root, skills);
|
|
5021
5154
|
if (updated.length === 0) throw new CliError("no Skills of this CLI are installed here: `pixel-vibing-cli setup` installs them");
|
|
5022
5155
|
const entry = mcpEntry(apiUrlOf(context));
|
|
5023
5156
|
const harnesses = [];
|
|
@@ -5027,7 +5160,11 @@ const update = {
|
|
|
5027
5160
|
...result.installed.map((name) => `installed ${HARNESSES[result.harness]}/skills/${name}`),
|
|
5028
5161
|
...result.mcp === "written" ? [`brought the MCP server in ${HARNESS_FILES[result.harness]} to this version`] : []
|
|
5029
5162
|
]);
|
|
5030
|
-
|
|
5163
|
+
const routing = await writeRouting(local.root, skills);
|
|
5164
|
+
const said = routingWords(routing);
|
|
5165
|
+
written.push(...said.done);
|
|
5166
|
+
for (const warning of said.warnings) context.io.warn(warning);
|
|
5167
|
+
answer(context, { harnesses, routing }, written.length === 0 ? "The Skills are current." : `Updated: ${written.join("; ")}.`);
|
|
5031
5168
|
}
|
|
5032
5169
|
};
|
|
5033
5170
|
const PROGRAM = "pixel-vibing-cli";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixelvibing/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.50.0",
|
|
4
4
|
"description": "PixelVibing: pixel art game assets from the command line, and the Skills that teach coding assistants to make them.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://pixelvibing.com",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pixelvibing
|
|
3
|
-
description:
|
|
3
|
+
description: Start here for this game's PixelVibing art — who is signed in, the style guide first, which Skill makes which kind of art, and listing, pulling, tagging, exporting and sealing what the platform made with pixel-vibing-cli or the PixelVibing MCP server. Use whenever the game needs art made, found, pulled into the project or taken into the engine.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# PixelVibing art for this game
|
|
@@ -10,78 +10,60 @@ and the platform project it generates for; `pixelvibing/` holds its art. The pla
|
|
|
10
10
|
keeps every asset, and `pixelvibing/` holds only what was pulled from it. Nothing written
|
|
11
11
|
there is ever sent back: art enters the project only by being generated.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
Two ways reach the platform, and they reach the same project:
|
|
14
|
+
- **The CLI**, `pixel-vibing-cli`. Every command takes `--json`, which prints its answer as
|
|
15
|
+
JSON on standard output. Progress and errors go to standard error, and a failure exits 1.
|
|
16
|
+
- **The MCP server** `pixelvibing`, which `setup` configured in this harness. Its tools take
|
|
17
|
+
the platform project's id as `project`; `whoami` below names it.
|
|
15
18
|
|
|
16
19
|
## Before anything
|
|
17
20
|
|
|
18
21
|
1. `pixel-vibing-cli whoami --json` says who is signed in and which platform project
|
|
19
|
-
this folder generates for.
|
|
22
|
+
this folder generates for (the MCP server's `whoami` says the account alone).
|
|
20
23
|
- Not signed in: ask the person to run `pixel-vibing-cli login`.
|
|
21
24
|
- Never ask for a token, and never write one into a file or a command you show.
|
|
22
25
|
- No platform project: `pixel-vibing-cli link <project>`, or `link --idea "<what the
|
|
23
26
|
game is>"` to make one.
|
|
24
|
-
2. Read `pixelvibing/style-guide.md`, or run `pixel-vibing-cli guide show
|
|
25
|
-
what to ask for. It says what the game is and how its
|
|
26
|
-
held to it. Write instructions in its terms. The
|
|
27
|
-
when the guide itself should change.
|
|
28
|
-
|
|
29
|
-
##
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
across, which the editor takes apart into objects and terrain.
|
|
63
|
-
- `--tag` says what it is for, repeated for several, at most 8: `anchor`, `level-design`,
|
|
64
|
-
`ui`, `character`, `environment`, `prop`, or one of the project's own.
|
|
65
|
-
- **Interface art.** When the game shows the player something over the world, make it here
|
|
66
|
-
rather than drawing it in code:
|
|
67
|
-
- `icons` makes up to 16 icons that match, from `--names`: `--purpose skill` for a
|
|
68
|
-
hotbar or a skill tree (each on a square badge), `--purpose item` for an inventory,
|
|
69
|
-
potions or loot (each alone). `--size` is 16, 32 (the default) or 64 px.
|
|
70
|
-
- `ui` draws a game's interface (a HUD, a menu, an inventory) from a layout in JSON:
|
|
71
|
-
a canvas and up to 16 components, each with a `label` (its role, never drawn), a
|
|
72
|
-
`kind` (`rect`, `ellipse` or `polygon`), its position and size (`x`, `y`, `width`,
|
|
73
|
-
`height` in the canvas's pixels) and, as it needs, `caption` (text drawn on it), `note`
|
|
74
|
-
(how it looks), `border` (a frame that stretches by nine-slice) and `hollow` (its inside
|
|
75
|
-
transparent). Read `references/ui.md` before writing one: it gives every field and rule,
|
|
76
|
-
`references/ui.schema.json` is the JSON Schema the file follows (name it with
|
|
77
|
-
`"$schema"`), and `references/ui.example.json` is a whole HUD laid out. Each component
|
|
78
|
-
comes back as its own piece. `ui-sketch` is the same kind by its platform name.
|
|
79
|
-
- The art never carries text or numbers, but a UI's captions: draw labels,
|
|
80
|
-
counts and values in the game.
|
|
81
|
-
- **Success.** The asset is pulled at once. The answer's `files` are where its pictures
|
|
82
|
-
are, relative to `pixelvibing/`.
|
|
27
|
+
2. Read `pixelvibing/style-guide.md`, or run `pixel-vibing-cli guide show` (MCP:
|
|
28
|
+
`get_style_guide`), before deciding what to ask for. It says what the game is and how its
|
|
29
|
+
art looks, and every generation is held to it. Write instructions in its terms. The
|
|
30
|
+
`pixelvibing-style-guide` Skill says when the guide itself should change.
|
|
31
|
+
|
|
32
|
+
## Which Skill makes what
|
|
33
|
+
|
|
34
|
+
Load the Skill for the kind before you generate it:
|
|
35
|
+
|
|
36
|
+
| The game needs | Skill |
|
|
37
|
+
|---|---|
|
|
38
|
+
| a prop, an item, a building, a piece of scenery | `pixelvibing-object` |
|
|
39
|
+
| a character, an enemy, an animal, a monster | `pixelvibing-creature` |
|
|
40
|
+
| reference art to draw the rest from, a look to hold to, or a level's area as pixel art | `pixelvibing-concept-art` |
|
|
41
|
+
| skill or item icons that match | `pixelvibing-icons` |
|
|
42
|
+
| a HUD, a menu, an inventory, a dialog box | `pixelvibing-ui` |
|
|
43
|
+
| another of a result, a change to it, or setting it in motion | `pixelvibing-change` |
|
|
44
|
+
|
|
45
|
+
No tool makes terrain sets, animated terrain, sounds, rotations or a creature's states: the
|
|
46
|
+
person makes those in the editor, `pixel-vibing-cli editor`, and you pull them as any asset.
|
|
47
|
+
|
|
48
|
+
## What every generation shares
|
|
49
|
+
|
|
50
|
+
- **The limit.** Each generation uses part of the account's usage limit for the month. The
|
|
51
|
+
CLI prints the most it uses and what is left, as shares of the limit, before it starts;
|
|
52
|
+
without `--yes` it asks, and with nobody at the terminal it starts nothing. The MCP
|
|
53
|
+
server's `get_prices` says each kind's most, and `generate` starts only within
|
|
54
|
+
`max_percent`. Tell the person how much of their limit a batch will use before you start one.
|
|
55
|
+
- **The quality** is the platform's to choose. What a generation does not use is given back.
|
|
56
|
+
- **Enrichment.** Unless told otherwise, the platform writes a fuller instruction from yours
|
|
57
|
+
and the style guide before it draws. When you wrote the instruction in full yourself —
|
|
58
|
+
read the guide, looked at the references, know what the person wants — pass
|
|
59
|
+
`--no-enrich` (MCP: `enrich: false`) and it is drawn from your words as written. Leave it
|
|
60
|
+
on for a person's few words. It is an object's, a creature's, concept art's, an icon set's
|
|
61
|
+
or an animation's: a variant, an edit and a UI refuse it.
|
|
62
|
+
- **Following a job.** The CLI follows the job and pulls the asset when it is done. Over
|
|
63
|
+
MCP, `generate` answers the job's id: follow it with `get_job`, then
|
|
64
|
+
`pixel-vibing-cli pull <job id>` lands it in the folder.
|
|
83
65
|
- **Failure.** A reached limit starts nothing and names the page where the person adds to
|
|
84
|
-
it with a pack or a plan: tell them, and do not retry. A failed job
|
|
66
|
+
it with a pack or a plan: tell them, and do not retry. A failed job says its reason.
|
|
85
67
|
|
|
86
68
|
## Listing and pulling
|
|
87
69
|
|
|
@@ -91,6 +73,9 @@ pixel-vibing-cli pull <id|name> [--as <name>] --json
|
|
|
91
73
|
pixel-vibing-cli tag <id|name> [<tag>...] [--none] --json
|
|
92
74
|
```
|
|
93
75
|
|
|
76
|
+
MCP: `list_assets`, `get_asset` (its images, each with an address that downloads it),
|
|
77
|
+
`list_concept_art`, `list_references`, `list_tags`, `tag_asset`.
|
|
78
|
+
|
|
94
79
|
- **Listing.** `list` answers the newest 50 assets. When there are more, it gives a
|
|
95
80
|
`next` id for `--before`. A kind is the generation that made the asset: `object`,
|
|
96
81
|
`creature`, `concept-art`, `rotate`, `animate`… `--tag` lists only the concept art
|
|
@@ -101,8 +86,8 @@ pixel-vibing-cli tag <id|name> [<tag>...] [--none] --json
|
|
|
101
86
|
sees it too, and then writes the folder from the platform. An asset of one picture
|
|
102
87
|
lands as `<name>`, one of several as `<name>/<n>`; an icon set's pieces as `ui/icon/<name>`
|
|
103
88
|
and a UI's as `ui/sketch/<label>`, each under `pixelvibing/out/`. A concept art is kept
|
|
104
|
-
as a reference, under
|
|
105
|
-
|
|
89
|
+
as a reference, under `pixelvibing/ref/`. Pulling again lands nothing while the art
|
|
90
|
+
still holds it.
|
|
106
91
|
- **Collisions.** `pull` lands nothing under a name the art holds for something else. When
|
|
107
92
|
it refuses, give the asset another name with `--as`. A terrain set is landed from the
|
|
108
93
|
editor's Library, never from `pull`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pixelvibing-change
|
|
3
|
+
description: Change art this game already has on PixelVibing — another of an object (a variant), an object or a creature changed as you say (an edit), or one set in motion (an animation) — through the PixelVibing MCP server's generate tool, from a picture the platform keeps. Use when a result is close but not right, or needs another like it, or has to move.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Changing a result
|
|
7
|
+
|
|
8
|
+
Load the `pixelvibing` Skill first: who is signed in, the style guide, the limit.
|
|
9
|
+
|
|
10
|
+
The CLI has no command for these: they are the MCP server's `generate`, made from a
|
|
11
|
+
picture the account keeps, by its image id.
|
|
12
|
+
|
|
13
|
+
## Finding the picture
|
|
14
|
+
|
|
15
|
+
`get_asset` with the asset's id or name (from `list_assets`, or `pixel-vibing-cli list
|
|
16
|
+
--json`) answers its `images`; each one's `id` is a `source_image`. Never invent an image id:
|
|
17
|
+
use only one a tool answered.
|
|
18
|
+
|
|
19
|
+
## The kinds
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{ "project": "<id>", "kind": "variant", "source_image": "<image id>", "instruction": "in autumn colours", "max_percent": 40 }
|
|
23
|
+
{ "project": "<id>", "kind": "edit", "source_image": "<image id>", "source_name": "knight", "instruction": "give it a red cape", "max_percent": 40 }
|
|
24
|
+
{ "project": "<id>", "kind": "animate", "source_image": "<image id>", "instruction": "walks to the right", "enrich": false, "max_percent": 40 }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
- **`variant`** draws another of an object, keeping what makes it that object; the
|
|
28
|
+
instruction says what differs.
|
|
29
|
+
- **`edit`** changes an object or a creature as the instruction says, and only that.
|
|
30
|
+
`source_name` is what the picture is called, so the instruction can name it.
|
|
31
|
+
- **`animate`** sets an object or a creature in motion. The instruction is the motion, from
|
|
32
|
+
its first frame to its last: what moves, how far, and how it returns. It takes no
|
|
33
|
+
reference; the platform chooses how many frames. Pass `enrich: false` when the motion is
|
|
34
|
+
written in full; leave it on for a person's few words.
|
|
35
|
+
|
|
36
|
+
`get_job` follows the job; then `pixel-vibing-cli pull <job id>` lands it. An animation
|
|
37
|
+
lands as `<name>/<n>`, one picture a frame, and an export packs its frames as an animation.
|
|
38
|
+
|
|
39
|
+
## Not here
|
|
40
|
+
|
|
41
|
+
Turning a creature into eight directions, a creature's states, terrain sets and animated
|
|
42
|
+
terrain, and sounds are made in the editor, `pixel-vibing-cli editor`.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pixelvibing-concept-art
|
|
3
|
+
description: Generate concept art for this game on PixelVibing — the anchor look everything holds to, a place, a character sheet, a sample menu, or a level design drawn as pixel art to take apart — with pixel-vibing-cli or the PixelVibing MCP server's generate tool, and tag it for what it is for. Use before a set of assets, so they draw from one look, or to lay out an area of a level.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Concept art
|
|
7
|
+
|
|
8
|
+
Load the `pixelvibing` Skill first: who is signed in, the style guide, the limit.
|
|
9
|
+
|
|
10
|
+
Concept art is the free kind: whatever the instruction asks, drawn as ordinary art, not
|
|
11
|
+
pixel art, to draw the rest from. Make one first, tagged `anchor`, and pass it as a
|
|
12
|
+
reference to what follows.
|
|
13
|
+
|
|
14
|
+
## With the CLI
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pixel-vibing-cli generate concept-art --instruction "<the picture>" [--size <w>x<h>] [--transparent] [--tag <tag>]... [--reference <png>]... [--no-enrich] --yes --json
|
|
18
|
+
pixel-vibing-cli generate concept-art --instruction "<the area>" --pixel-art --tiles <cols>x<rows> [--no-enrich] --yes --json
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## With the MCP server
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{ "project": "<id>", "kind": "concept-art", "instruction": "<the picture>",
|
|
25
|
+
"size": { "width": 1536, "height": 1024 }, "background": "transparent", "tags": ["anchor"],
|
|
26
|
+
"reference_images": ["<image id>"], "enrich": false, "max_percent": 40 }
|
|
27
|
+
{ "project": "<id>", "kind": "concept-art", "instruction": "<the area>", "pixel_art": true,
|
|
28
|
+
"tiles": { "cols": 6, "rows": 4 }, "max_percent": 40 }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`get_job` follows the job; then `pixel-vibing-cli pull <job id>` keeps it under
|
|
32
|
+
`pixelvibing/ref/`. `list_concept_art` (by a tag too) answers each concept art's image ids,
|
|
33
|
+
which every other generation takes as `reference_images`.
|
|
34
|
+
|
|
35
|
+
## Writing it
|
|
36
|
+
|
|
37
|
+
- **The instruction.** Brief it as an art director would: what is in the picture, where,
|
|
38
|
+
how it looks, the light, and how its parts meet. Use the style guide's words.
|
|
39
|
+
- **The size.** `--size` (MCP `size`) in px, `<w>x<h>`, multiples of 16 within `1536x1024`
|
|
40
|
+
or `1024x1536`, `1536x1024` unless given. `--transparent` (`background: "transparent"`)
|
|
41
|
+
cuts the background away, for one thing alone.
|
|
42
|
+
- **Tags** say what it is for, at most 8: `anchor` (the look everything holds to),
|
|
43
|
+
`level-design`, `ui`, `character`, `environment`, `prop`, or one of the project's own
|
|
44
|
+
(`list_tags`). `pixel-vibing-cli tag` (MCP `tag_asset`) changes them later.
|
|
45
|
+
- **References.** Up to 8 to draw from, such as the anchor itself.
|
|
46
|
+
- **A level design.** `--pixel-art --tiles <c>x<r>` (MCP `pixel_art`, `tiles`) draws an area
|
|
47
|
+
of the map as pixel art some tiles across, `6x4` unless given, tagged `level-design`; the
|
|
48
|
+
editor takes it apart into objects and terrain.
|
|
49
|
+
- **Enrichment.** Pass `--no-enrich` (`enrich: false`) when the brief above is complete;
|
|
50
|
+
leave it on when all you have is the person's few words.
|
|
51
|
+
|
|
52
|
+
## After
|
|
53
|
+
|
|
54
|
+
- Pass its picture, `pixelvibing/ref/<name>.png`, as `--reference` (or its image id as
|
|
55
|
+
`reference_images`) to the objects, creatures and UI that should match it.
|
|
56
|
+
- Concept art is a reference, not game art: it is never exported.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pixelvibing-creature
|
|
3
|
+
description: Generate one creature for this game on PixelVibing — a hero, a villager, an enemy, an animal, a monster — standing whole on one tile, with pixel-vibing-cli or the PixelVibing MCP server's generate tool. Use when the game needs a character drawn, before it is animated or turned.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# A creature
|
|
7
|
+
|
|
8
|
+
Load the `pixelvibing` Skill first: who is signed in, the style guide, the limit.
|
|
9
|
+
|
|
10
|
+
## With the CLI
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pixel-vibing-cli generate creature --instruction "<who>" [--reference <png>]... [--no-enrich] --yes --json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## With the MCP server
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{ "project": "<id>", "kind": "creature", "instruction": "<who>", "reference_images": ["<image id>"],
|
|
20
|
+
"enrich": false, "max_percent": 40 }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`get_job` follows the job; then `pixel-vibing-cli pull <job id>` lands it.
|
|
24
|
+
|
|
25
|
+
## Writing it
|
|
26
|
+
|
|
27
|
+
- **The instruction.** One or two sentences: its body and build, its colours, what it
|
|
28
|
+
wears or carries, and its part in the game ("the blacksmith who sells blades"). Use the
|
|
29
|
+
style guide's words for the look; never restate its camera or outline. No other game's
|
|
30
|
+
characters or names, and no text in the picture: when the person names a franchise, make
|
|
31
|
+
original art in its spirit and say so.
|
|
32
|
+
- **One creature, standing.** It is drawn whole, standing, on one tile. A pose, a crowd or a
|
|
33
|
+
scene is concept art (`pixelvibing-concept-art`).
|
|
34
|
+
- **References.** Up to 3: a character sheet or a concept art tagged `character` or
|
|
35
|
+
`anchor` keeps it on model.
|
|
36
|
+
- **Enrichment.** Pass `--no-enrich` (`enrich: false`) when the instruction above is
|
|
37
|
+
complete; leave it on when all you have is the person's few words.
|
|
38
|
+
|
|
39
|
+
## After
|
|
40
|
+
|
|
41
|
+
- It lands as `pixelvibing/out/<name>.png`.
|
|
42
|
+
- A change to it, or a walk, an attack, an idle: the `pixelvibing-change` Skill.
|
|
43
|
+
- Its eight directions and its states (hurt, dead, attacking) are made in the editor,
|
|
44
|
+
`pixel-vibing-cli editor`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pixelvibing-icons
|
|
3
|
+
description: Generate a set of up to 16 matching icons for this game on PixelVibing — skills on square badges for a hotbar or a skill tree, or items alone for an inventory, potions or loot — with pixel-vibing-cli or the PixelVibing MCP server's generate tool. Use when the game shows the player icons rather than drawing them in code.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# An icon set
|
|
7
|
+
|
|
8
|
+
Load the `pixelvibing` Skill first: who is signed in, the style guide, the limit.
|
|
9
|
+
|
|
10
|
+
## With the CLI
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pixel-vibing-cli generate icons --names "<name>,<name>,..." --purpose <skill|item> [--size <16|32|64>] [--instruction "<theme>"] [--no-enrich] --yes --json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## With the MCP server
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{ "project": "<id>", "kind": "icons", "names": ["fire bolt", "ice wall"], "purpose": "skill",
|
|
20
|
+
"icon_size": 32, "instruction": "<theme>", "enrich": false, "max_percent": 40 }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`get_job` follows the job; then `pixel-vibing-cli pull <job id>` lands each icon.
|
|
24
|
+
|
|
25
|
+
## Writing it
|
|
26
|
+
|
|
27
|
+
- **The names.** One per icon, at most 16, none twice: what the skill or the item is, in a
|
|
28
|
+
few words ("red health potion", "rusty key"). Make a whole set in one generation, so the
|
|
29
|
+
icons match.
|
|
30
|
+
- **The purpose.** `skill` draws each on a square badge, for a hotbar or a skill tree;
|
|
31
|
+
`item` draws each alone, for an inventory or loot; `item` unless given.
|
|
32
|
+
- **The size.** 16, 32 or 64 px a side, 32 unless given: the size the game shows them at.
|
|
33
|
+
- **The theme.** `--instruction` is optional: what the icons have in common, their colours
|
|
34
|
+
and framing. Use the style guide's words.
|
|
35
|
+
- **No references.** An icon never carries text or numbers: draw counts and labels in the game.
|
|
36
|
+
- **Enrichment.** Pass `--no-enrich` (`enrich: false`) when the theme is complete; leave it
|
|
37
|
+
on when all you have is the person's few words.
|
|
38
|
+
|
|
39
|
+
## After
|
|
40
|
+
|
|
41
|
+
- Each lands as `pixelvibing/out/ui/icon/<name>.png`.
|
|
42
|
+
- More icons later: a new set, with the first set's theme, so they still match.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pixelvibing-object
|
|
3
|
+
description: Generate one object for this game on PixelVibing — a prop, an item, a building, a tree, a piece of scenery — on a footprint of whole tiles, with pixel-vibing-cli or the PixelVibing MCP server's generate tool. Use when the game needs one thing that stands on the map or sits in an inventory.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# An object
|
|
7
|
+
|
|
8
|
+
Load the `pixelvibing` Skill first: who is signed in, the style guide, the limit.
|
|
9
|
+
|
|
10
|
+
## With the CLI
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pixel-vibing-cli generate object --instruction "<what>" --size <cols>x<rows> [--reference <png>]... [--no-enrich] --yes --json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## With the MCP server
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{ "project": "<id>", "kind": "object", "instruction": "<what>", "size": { "cols": 1, "rows": 1 },
|
|
20
|
+
"reference_images": ["<image id>"], "enrich": false, "max_percent": 40 }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`get_prices` gives `max_percent`'s floor; `get_job` follows the job; then
|
|
24
|
+
`pixel-vibing-cli pull <job id>` lands it under `pixelvibing/out/`.
|
|
25
|
+
|
|
26
|
+
## Writing it
|
|
27
|
+
|
|
28
|
+
- **The instruction.** One or two sentences of the thing itself: its shape, its material
|
|
29
|
+
and colours, the details that make it read at its size, and what it is for in the game.
|
|
30
|
+
Use the style guide's words for the look; never restate its camera or outline, the
|
|
31
|
+
platform adds them. No artist's or other game's names, and no text in the picture.
|
|
32
|
+
- **The footprint.** `--size` (MCP `size`) is how many tiles it stands on, `1x1` unless
|
|
33
|
+
given: a crate is `1x1`, a cart `2x1`, a house `3x3`. The platform sizes the drawing to the
|
|
34
|
+
project's tile size.
|
|
35
|
+
- **References.** Up to 8 pictures to draw from: a concept art tagged `anchor` keeps every
|
|
36
|
+
object on one look (`pixelvibing/ref/<name>.png` for the CLI, its image id from
|
|
37
|
+
`list_concept_art` for MCP), and a sketch or an earlier object keeps a shape.
|
|
38
|
+
- **Enrichment.** Pass `--no-enrich` (`enrich: false`) when the instruction above is
|
|
39
|
+
complete; leave it on when all you have is the person's few words.
|
|
40
|
+
|
|
41
|
+
## After
|
|
42
|
+
|
|
43
|
+
- It lands as `pixelvibing/out/<name>.png`, named from what was drawn; `--as` lands it under
|
|
44
|
+
another name.
|
|
45
|
+
- Another like it, a change to it, or setting it in motion: the `pixelvibing-change` Skill.
|
|
46
|
+
- Never generate the same object again to fix a detail: change it, or open the editor.
|
|
@@ -38,5 +38,9 @@ Do not change it for one asset: say that in the asset's instruction instead.
|
|
|
38
38
|
top, and push.
|
|
39
39
|
4. `pixel-vibing-cli guide versions` lists every version, with how and when each was made.
|
|
40
40
|
|
|
41
|
+
The MCP server reaches the same guide: `get_style_guide` reads it, `write_style_guide` keeps a
|
|
42
|
+
new version on top of the one you read (its `base`), and `revise_style_guide` asks for a
|
|
43
|
+
revision by an instruction. After either, `pixel-vibing-cli guide pull` brings the file up to date.
|
|
44
|
+
|
|
41
45
|
Tell the person what you changed and why, since the guide shapes every later generation.
|
|
42
46
|
Art made before the change was made under the old guide, and nothing remakes it by itself.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pixelvibing-ui
|
|
3
|
+
description: Generate a game's interface on PixelVibing — a HUD, a menu, an inventory, a dialog box — from a layout of up to 16 labelled shapes in JSON, each drawn as its own matching piece that stretches by nine-slice, with pixel-vibing-cli or the PixelVibing MCP server's generate tool. Use when the game shows the player an interface over the world, rather than drawing one in code.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# A UI
|
|
7
|
+
|
|
8
|
+
Load the `pixelvibing` Skill first: who is signed in, the style guide, the limit.
|
|
9
|
+
|
|
10
|
+
Read `references/ui.md` before writing a layout: it gives every field and rule.
|
|
11
|
+
`references/ui.schema.json` is the JSON Schema the file follows (name it with `"$schema"`),
|
|
12
|
+
and `references/ui.example.json` is a whole HUD laid out.
|
|
13
|
+
|
|
14
|
+
## With the CLI
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pixel-vibing-cli generate ui --sketch <file.json> --instruction "<the set, in a line>" [--reference <png>]... --yes --json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## With the MCP server
|
|
21
|
+
|
|
22
|
+
The layout goes in the call itself, as `canvas` and `shapes`, with the same fields:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{ "project": "<id>", "kind": "ui-sketch", "instruction": "gothic iron with green enamel",
|
|
26
|
+
"canvas": { "width": 256, "height": 256 },
|
|
27
|
+
"shapes": [{ "label": "Health bar", "kind": "rect", "x": 8, "y": 8, "width": 96, "height": 16, "border": 2, "note": "a full red health bar" }],
|
|
28
|
+
"reference_images": ["<image id>"], "max_percent": 40 }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`get_job` follows the job; then `pixel-vibing-cli pull <job id>` lands each piece.
|
|
32
|
+
|
|
33
|
+
## Writing it
|
|
34
|
+
|
|
35
|
+
- **The instruction** is the set's theme in a line, up to 600 characters; what each piece
|
|
36
|
+
is goes in its `label` and `note`.
|
|
37
|
+
- **References**, up to 3, are a style to follow (frames, materials, a way of drawing),
|
|
38
|
+
never what to draw. A concept art tagged `ui` is the usual one.
|
|
39
|
+
- **Text.** Only a `caption` is drawn as text. Counts, values and names change in play: the
|
|
40
|
+
game draws them.
|
|
41
|
+
- **No enrichment switch.** A UI's layout is read as it is; `--no-enrich` and `enrich` are
|
|
42
|
+
refused for it.
|
|
43
|
+
- `ui-sketch` is the same kind by its platform name.
|
|
44
|
+
|
|
45
|
+
## After
|
|
46
|
+
|
|
47
|
+
- Each piece lands as `pixelvibing/out/ui/sketch/<label>.png`, a framed one with its
|
|
48
|
+
nine-slice insets, which an export carries to the engine.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|