@auraindustry/aurajs 0.1.3 → 0.1.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 +7 -0
- package/benchmarks/perf-thresholds.json +27 -0
- package/package.json +6 -1
- package/src/ai-guidance.mjs +302 -0
- package/src/authored-project.mjs +498 -2
- package/src/build-contract/capabilities.mjs +87 -1
- package/src/build-contract/constants.mjs +1 -0
- package/src/build-contract.mjs +2 -0
- package/src/bundler.mjs +143 -13
- package/src/cli.mjs +681 -13
- package/src/commands/packs.mjs +741 -0
- package/src/commands/project-authoring.mjs +128 -1
- package/src/conformance/cases/app-and-ui-runtime-cases.mjs +1 -2
- package/src/conformance/cases/core-runtime-cases.mjs +6 -2
- package/src/conformance/cases/scene3d-and-media-cases.mjs +238 -0
- package/src/conformance/cases/systems-and-gameplay-cases.mjs +265 -4
- package/src/conformance-mobile.mjs +166 -0
- package/src/conformance.mjs +89 -30
- package/src/evidence-bundle.mjs +242 -0
- package/src/headless-test/runtime-coordinator.mjs +186 -33
- package/src/headless-test.mjs +2 -0
- package/src/helpers/2d/index.mjs +183 -0
- package/src/helpers/index.mjs +26 -0
- package/src/helpers/starter-utils/adventure-objectives.js +102 -0
- package/src/helpers/starter-utils/adventure-world-2d.js +221 -0
- package/src/helpers/starter-utils/animation-2d.js +337 -0
- package/src/helpers/starter-utils/animation-packaging-2d.js +203 -0
- package/src/helpers/starter-utils/atlas-assets-2d.js +111 -0
- package/src/helpers/starter-utils/autoplay-debug-2d.js +215 -0
- package/src/helpers/starter-utils/avatar-3d.js +404 -0
- package/src/helpers/starter-utils/combat-feedback-2d.js +320 -0
- package/src/helpers/starter-utils/combat-runtime-2d.js +290 -0
- package/src/helpers/starter-utils/core.js +150 -0
- package/src/helpers/starter-utils/dialogue-2d.js +351 -0
- package/src/helpers/starter-utils/enemy-archetypes-2d.js +68 -0
- package/src/helpers/starter-utils/index.js +26 -0
- package/src/helpers/starter-utils/inventory-2d.js +268 -0
- package/src/helpers/starter-utils/journal-2d.js +267 -0
- package/src/helpers/starter-utils/platformer-3d.js +132 -0
- package/src/helpers/starter-utils/scene-audio-2d.js +236 -0
- package/src/helpers/starter-utils/streamed-world-2d.js +378 -0
- package/src/helpers/starter-utils/tilemap-nav-2d.js +499 -0
- package/src/helpers/starter-utils/tilemap-world-2d.js +205 -0
- package/src/helpers/starter-utils/triggers.js +662 -0
- package/src/helpers/starter-utils/tween-2d.js +615 -0
- package/src/helpers/starter-utils/wave-director.js +101 -0
- package/src/helpers/starter-utils/world-compositor-2d.js +253 -0
- package/src/helpers/starter-utils/world-persistence-2d.js +180 -0
- package/src/mobile/android/build.mjs +606 -0
- package/src/mobile/android/host-artifact.mjs +280 -0
- package/src/mobile/ios/build.mjs +1323 -0
- package/src/mobile/ios/host-artifact.mjs +819 -0
- package/src/mobile/shared/capabilities.mjs +174 -0
- package/src/packs/catalog.mjs +259 -0
- package/src/perf-benchmark-runner.mjs +17 -12
- package/src/perf-benchmark.mjs +408 -4
- package/src/publish-command.mjs +303 -6
- package/src/replay-runtime.mjs +257 -0
- package/src/scaffold/config.mjs +2 -0
- package/src/scaffold/fs.mjs +8 -1
- package/src/scaffold/project-docs.mjs +43 -1
- package/src/scaffold.mjs +4 -0
- package/src/session-runtime.mjs +4 -3
- package/src/web-conformance.mjs +0 -36
- package/templates/create/2d-adventure/config/gameplay/adventure.config.js +9 -6
- package/templates/create/2d-adventure/content/gameplay/dialogue.js +85 -0
- package/templates/create/2d-adventure/content/gameplay/world.js +32 -36
- package/templates/create/2d-adventure/content/gameplay/world.tilemap.json +273 -0
- package/templates/create/2d-adventure/docs/design/loop.md +4 -3
- package/templates/create/2d-adventure/prefabs/relic.prefab.js +10 -10
- package/templates/create/2d-adventure/prefabs/world.prefab.js +127 -74
- package/templates/create/2d-adventure/scenes/gameplay.scene.js +603 -112
- package/templates/create/2d-adventure/src/runtime/capabilities.js +16 -0
- package/templates/create/2d-adventure/ui/hud.screen.js +187 -4
- package/templates/create/2d-adventure/ui/journal.screen.js +183 -0
- package/templates/create/3d/scenes/gameplay.scene.js +30 -3
- package/templates/create/3d/src/runtime/capabilities.js +5 -0
- package/templates/create/3d/src/runtime/materials.js +10 -0
- package/templates/create/3d-adventure/scenes/gameplay.scene.js +30 -3
- package/templates/create/3d-adventure/src/runtime/capabilities.js +5 -0
- package/templates/create/3d-adventure/src/runtime/materials.js +11 -0
- package/templates/create/3d-collectathon/scenes/gameplay.scene.js +30 -3
- package/templates/create/3d-collectathon/src/runtime/capabilities.js +5 -0
- package/templates/create/3d-collectathon/src/runtime/materials.js +10 -0
- package/templates/create/shared/src/runtime/ui-forms.js +552 -0
- package/templates/create/shared/src/starter-utils/adventure-world-2d.js +221 -0
- package/templates/create/shared/src/starter-utils/animation-packaging-2d.js +203 -0
- package/templates/create/shared/src/starter-utils/atlas-assets-2d.js +111 -0
- package/templates/create/shared/src/starter-utils/autoplay-debug-2d.js +215 -0
- package/templates/create/shared/src/starter-utils/combat-runtime-2d.js +290 -0
- package/templates/create/shared/src/starter-utils/dialogue-2d.js +351 -0
- package/templates/create/shared/src/starter-utils/index.js +15 -1
- package/templates/create/shared/src/starter-utils/inventory-2d.js +268 -0
- package/templates/create/shared/src/starter-utils/journal-2d.js +267 -0
- package/templates/create/shared/src/starter-utils/scene-audio-2d.js +236 -0
- package/templates/create/shared/src/starter-utils/streamed-world-2d.js +378 -0
- package/templates/create/shared/src/starter-utils/tilemap-nav-2d.js +499 -0
- package/templates/create/shared/src/starter-utils/tilemap-world-2d.js +205 -0
- package/templates/create/shared/src/starter-utils/world-compositor-2d.js +253 -0
- package/templates/create/shared/src/starter-utils/world-persistence-2d.js +180 -0
- package/templates/create-bin/play.js +36 -7
- package/templates/skills/auramaxx/SKILL.md +46 -0
- package/templates/skills/auramaxx/project-requirements.md +68 -0
- package/templates/skills/auramaxx/starter-recipes.md +104 -0
- package/templates/skills/auramaxx/validation-checklist.md +49 -0
- package/templates/skills/aurajs/SKILL.md +0 -96
- package/templates/skills/aurajs/api-contract-3d.md +0 -7
- package/templates/skills/aurajs/api-contract.md +0 -7
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { describeProjectAiGuidance } from '../ai-guidance.mjs';
|
|
2
|
+
|
|
1
3
|
export function renderProjectReadme({ name, projectTitle, template, templateMetadata }) {
|
|
2
4
|
if (templateMetadata?.runtimeFamily === 'retro') {
|
|
3
5
|
return renderRetroProjectReadme({ name, projectTitle, template, templateMetadata });
|
|
@@ -7,6 +9,7 @@ export function renderProjectReadme({ name, projectTitle, template, templateMeta
|
|
|
7
9
|
const workflowSection = renderTemplateWorkflowSection(templateMetadata);
|
|
8
10
|
const projectMap = renderProjectMapSection(template);
|
|
9
11
|
const generateFilesSection = renderGenerateFilesSection(template);
|
|
12
|
+
const aiWorkflowSection = renderAiWorkflowSection(template);
|
|
10
13
|
const stateOwnershipSection = renderStateOwnershipSection();
|
|
11
14
|
const continuityOwnershipSection = renderContinuityOwnershipSection();
|
|
12
15
|
const largeAssetSection = renderLargeAssetSection();
|
|
@@ -46,6 +49,7 @@ before the first \`auramaxx publish\`.
|
|
|
46
49
|
|
|
47
50
|
${largeAssetSection}
|
|
48
51
|
${workflowSection}
|
|
52
|
+
${aiWorkflowSection}
|
|
49
53
|
${generateFilesSection}
|
|
50
54
|
${stateOwnershipSection}
|
|
51
55
|
${continuityOwnershipSection}
|
|
@@ -77,6 +81,7 @@ export function renderProjectRunbook({ projectTitle, template, templateMetadata
|
|
|
77
81
|
const workflowSection = renderTemplateWorkflowSection(templateMetadata);
|
|
78
82
|
const firstThirtyMinutes = renderFirstThirtyMinutesSteps(template);
|
|
79
83
|
const generateFilesSection = renderGenerateFilesSection(template);
|
|
84
|
+
const aiWorkflowSection = renderAiWorkflowSection(template);
|
|
80
85
|
const stateOwnershipSection = renderStateOwnershipSection();
|
|
81
86
|
const continuityOwnershipSection = renderContinuityOwnershipSection();
|
|
82
87
|
const largeAssetSection = renderLargeAssetSection();
|
|
@@ -93,6 +98,7 @@ ${stateOwnershipSection}
|
|
|
93
98
|
${continuityOwnershipSection}
|
|
94
99
|
|
|
95
100
|
${workflowSection}
|
|
101
|
+
${aiWorkflowSection}
|
|
96
102
|
${generateFilesSection}
|
|
97
103
|
|
|
98
104
|
## First-Hour Implementation Pass
|
|
@@ -131,6 +137,36 @@ ${steps.map((line) => `1. ${line}`).join('\n')}
|
|
|
131
137
|
`;
|
|
132
138
|
}
|
|
133
139
|
|
|
140
|
+
function renderAiWorkflowSection(template) {
|
|
141
|
+
const aiGuidance = describeProjectAiGuidance({
|
|
142
|
+
template,
|
|
143
|
+
starterUtils: template === 'blank'
|
|
144
|
+
? null
|
|
145
|
+
: {
|
|
146
|
+
available: true,
|
|
147
|
+
recommendedImportPath: './src/starter-utils/index.js',
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const importHint = aiGuidance.recommendedImportPath || aiGuidance.preferredPackageSpecifier || '(none)';
|
|
152
|
+
const modules = Array.isArray(aiGuidance.recommendedModules) && aiGuidance.recommendedModules.length > 0
|
|
153
|
+
? aiGuidance.recommendedModules.map((entry) => `- \`${entry.id}\` via \`${importHint}\``).join('\n')
|
|
154
|
+
: '- no starter helper lane is preselected; build outward from `src/runtime/`, `scenes/`, and `content/`';
|
|
155
|
+
|
|
156
|
+
return `## AI Workflow
|
|
157
|
+
|
|
158
|
+
- run \`auramaxx explain --json\` before moving files so the current source boundary, starter helper lane, and paved-road guidance stay explicit
|
|
159
|
+
- run \`auramaxx check --json\` after edits when you want machine-readable import and registry validation
|
|
160
|
+
- keep authored gameplay code inside \`src/\`, \`scenes/\`, \`ui/\`, \`prefabs/\`, \`config/\`, and \`content/\`
|
|
161
|
+
- preferred helper import: \`${importHint}\`
|
|
162
|
+
- AI paved road lane: \`${aiGuidance.laneId}\`
|
|
163
|
+
|
|
164
|
+
Recommended starter modules:
|
|
165
|
+
|
|
166
|
+
${modules}
|
|
167
|
+
`;
|
|
168
|
+
}
|
|
169
|
+
|
|
134
170
|
function renderRetroProjectReadme({ name, projectTitle, template, templateMetadata }) {
|
|
135
171
|
const controls = templateMetadata.controls.map((line) => `- ${line}`).join('\n');
|
|
136
172
|
const firstEdits = templateMetadata.firstEdits.map((line) => `1. ${line}`).join('\n');
|
|
@@ -352,7 +388,13 @@ export function renderProjectMapSection(template) {
|
|
|
352
388
|
- \`config/\` - editable defaults and tuning payloads.
|
|
353
389
|
- \`content/\` - authored definitions, levels, registries, and progression content.
|
|
354
390
|
- \`content/registries/\` - starter-owned registry files for cards, enemies, relics, and encounters.
|
|
355
|
-
- \`src/starter-utils/\` -
|
|
391
|
+
- \`src/starter-utils/\` - local copies of reusable authored helper modules
|
|
392
|
+
shipped with AuraJS for non-blank templates. Keep imports local here for
|
|
393
|
+
starter-facing gameplay code; use the published
|
|
394
|
+
\`@auraindustry/aurajs/helpers\` lane only when you want the shared
|
|
395
|
+
package-backed helper surface directly. Run \`auramaxx vendor helpers\` when
|
|
396
|
+
you want to seed or resync the local helper lane in a project that does not
|
|
397
|
+
already have it.
|
|
356
398
|
- \`assets/starter/\` - starter asset pack and editable design payloads.
|
|
357
399
|
- \`aura.config.json\` - identity/window/build/modules.
|
|
358
400
|
- \`aura.capabilities.json\` - canonical runtime API declaration for this scaffold.
|
package/src/scaffold.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
CREATE_TEMPLATE_DIRS,
|
|
8
8
|
GITIGNORE_TEMPLATE,
|
|
9
9
|
LEGACY_STARTER_TEMPLATE_DIR,
|
|
10
|
+
PACKAGED_STARTER_UTILS_DIR,
|
|
10
11
|
PLAY_BIN_TEMPLATE,
|
|
11
12
|
applyTemplateConfigOverrides,
|
|
12
13
|
buildCapabilitiesDeclaration,
|
|
@@ -106,6 +107,9 @@ export function scaffoldGame(options) {
|
|
|
106
107
|
copyTree(templateDir, dest, replacements);
|
|
107
108
|
if (shouldCopyCreateSharedTemplate(normalizedTemplate, templateMetadata) && existsSync(CREATE_SHARED_TEMPLATE_DIR)) {
|
|
108
109
|
copyTree(CREATE_SHARED_TEMPLATE_DIR, dest, replacements);
|
|
110
|
+
if (existsSync(PACKAGED_STARTER_UTILS_DIR)) {
|
|
111
|
+
copyTree(PACKAGED_STARTER_UTILS_DIR, join(dest, 'src', 'starter-utils'), replacements);
|
|
112
|
+
}
|
|
109
113
|
}
|
|
110
114
|
|
|
111
115
|
mkdirSync(join(dest, 'assets'), { recursive: true });
|
package/src/session-runtime.mjs
CHANGED
|
@@ -74,8 +74,10 @@ export async function bootSessionRuntime(options = {}) {
|
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
const testState = createSessionTestState();
|
|
77
|
-
const aura = createHeadlessAura({ width, height, testState });
|
|
78
|
-
const context = vm.createContext(createRuntimeContext(aura, testState
|
|
77
|
+
const aura = createHeadlessAura({ width, height, testState, projectRoot });
|
|
78
|
+
const context = vm.createContext(createRuntimeContext(aura, testState, {
|
|
79
|
+
math: options.math,
|
|
80
|
+
}));
|
|
79
81
|
|
|
80
82
|
const source = readFileSync(bundle.outFile, 'utf8');
|
|
81
83
|
const script = new vm.Script(source, {
|
|
@@ -318,4 +320,3 @@ export async function exportSessionInspect(runtime, options = {}) {
|
|
|
318
320
|
};
|
|
319
321
|
}
|
|
320
322
|
}
|
|
321
|
-
|
package/src/web-conformance.mjs
CHANGED
|
@@ -16,15 +16,6 @@ export const DEFAULT_WEB_SMOKE_CASES = Object.freeze([
|
|
|
16
16
|
testName: 'web loader installs browser-backed aura surface for 2d examples',
|
|
17
17
|
examples: [],
|
|
18
18
|
}),
|
|
19
|
-
Object.freeze({
|
|
20
|
-
id: 'web-supported-render-2d-proof-example',
|
|
21
|
-
bucket: 'supported',
|
|
22
|
-
expectation: 'supported',
|
|
23
|
-
title: 'web-render-2d-proof runs on the committed advanced draw2d browser floor',
|
|
24
|
-
file: DEFAULT_TEST_FILE,
|
|
25
|
-
testName: 'web loader browser smoke: web-render-2d-proof runs on the committed advanced draw2d browser floor',
|
|
26
|
-
examples: ['examples/web-render-2d-proof'],
|
|
27
|
-
}),
|
|
28
19
|
Object.freeze({
|
|
29
20
|
id: 'web-partial-auramon-example',
|
|
30
21
|
bucket: 'partial',
|
|
@@ -34,33 +25,6 @@ export const DEFAULT_WEB_SMOKE_CASES = Object.freeze([
|
|
|
34
25
|
testName: 'web loader browser smoke: auramon runs on the supported 2d subset with input and resize evidence',
|
|
35
26
|
examples: ['examples/auramon'],
|
|
36
27
|
}),
|
|
37
|
-
Object.freeze({
|
|
38
|
-
id: 'web-supported-starter-3d-example',
|
|
39
|
-
bucket: 'supported',
|
|
40
|
-
expectation: 'supported',
|
|
41
|
-
title: 'starter-3d runs on the committed browser 3d floor',
|
|
42
|
-
file: DEFAULT_TEST_FILE,
|
|
43
|
-
testName: 'web loader browser smoke: starter-3d runs on the committed browser 3d floor',
|
|
44
|
-
examples: ['examples/starter-3d'],
|
|
45
|
-
}),
|
|
46
|
-
Object.freeze({
|
|
47
|
-
id: 'web-unsupported-multiplayer-examples',
|
|
48
|
-
bucket: 'unsupported',
|
|
49
|
-
expectation: 'unsupported',
|
|
50
|
-
title: 'multiplayer examples fail before setup with stable capability diagnostics',
|
|
51
|
-
file: DEFAULT_TEST_FILE,
|
|
52
|
-
testName: 'web loader browser smoke: multiplayer examples fail before setup with stable capability diagnostics',
|
|
53
|
-
examples: ['examples/multiplayer-room-client', 'examples/multiplayer-room-host'],
|
|
54
|
-
}),
|
|
55
|
-
Object.freeze({
|
|
56
|
-
id: 'web-unsupported-advanced-3d-example',
|
|
57
|
-
bucket: 'unsupported',
|
|
58
|
-
expectation: 'unsupported',
|
|
59
|
-
title: 'advanced 3d examples outside the committed browser floor fail before setup with stable capability diagnostics',
|
|
60
|
-
file: DEFAULT_TEST_FILE,
|
|
61
|
-
testName: 'web loader browser smoke: advanced 3d examples still fail before setup with stable capability diagnostics',
|
|
62
|
-
examples: ['examples/custom-shader-material-proof'],
|
|
63
|
-
}),
|
|
64
28
|
]);
|
|
65
29
|
|
|
66
30
|
export class WebConformanceSuiteError extends Error {
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
export const ADVENTURE_CONFIG = {
|
|
2
2
|
playerSize: 28,
|
|
3
|
-
playerSpeed:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
playerSpeed: 216,
|
|
4
|
+
pickupSize: 28,
|
|
5
|
+
checkpointSize: 48,
|
|
6
|
+
gateGlowSize: 96,
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
export const ADVENTURE_TEXT = {
|
|
10
10
|
started: '{{PROJECT_TITLE}} started (2D adventure template)',
|
|
11
|
-
controls: 'Move: Arrows/WASD Interact: E or Enter Hint: H',
|
|
12
|
-
|
|
11
|
+
controls: 'Move: Arrows/WASD Interact: E or Enter Inventory: I or Tab Journal: J Hint: H',
|
|
12
|
+
inventoryControls: 'Inventory: A/D or Left/Right tabs W/S or Up/Down items I or Tab closes',
|
|
13
|
+
journalControls: 'Journal: A/D or Left/Right sections W/S or Up/Down entries J closes',
|
|
14
|
+
dialogueControls: 'Dialogue: W/S or Up/Down choices E, Enter, or Space confirms',
|
|
15
|
+
clearedTitle: 'ARCHIVE ROUTE SECURED',
|
|
13
16
|
clearedPrompt: 'Press Enter to restart the route',
|
|
14
17
|
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export const ARCHIVE_CONSOLE_DIALOGUE_ID = 'archive-console-link';
|
|
2
|
+
|
|
3
|
+
export const JOURNAL_ENTRY_IDS = Object.freeze({
|
|
4
|
+
routeBrief: 'route-brief',
|
|
5
|
+
consoleLog: 'archive-console-log',
|
|
6
|
+
moonGate: 'moon-gate-route',
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export const JOURNAL_CATEGORIES = [
|
|
10
|
+
{ id: 'route', label: 'Route' },
|
|
11
|
+
{ id: 'intel', label: 'Archive Intel' },
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
export const STARTING_JOURNAL_ENTRIES = [
|
|
15
|
+
{
|
|
16
|
+
id: JOURNAL_ENTRY_IDS.routeBrief,
|
|
17
|
+
label: 'Route Brief',
|
|
18
|
+
categoryId: 'route',
|
|
19
|
+
categoryLabel: 'Route',
|
|
20
|
+
description: 'Sweep the Moon Archive, recover the route note, then reopen the Moon Gate.',
|
|
21
|
+
detail: 'The archive console should reveal the final route once the relic anchors are back online.',
|
|
22
|
+
status: 'active',
|
|
23
|
+
badge: 'Active',
|
|
24
|
+
updatedAt: 'Initial route objective',
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
|
|
28
|
+
export const ADVENTURE_DIALOGUES = [
|
|
29
|
+
{
|
|
30
|
+
id: ARCHIVE_CONSOLE_DIALOGUE_ID,
|
|
31
|
+
title: 'Archive Console Link',
|
|
32
|
+
speaker: 'Archivist Sol',
|
|
33
|
+
startNodeId: 'handshake',
|
|
34
|
+
nodes: [
|
|
35
|
+
{
|
|
36
|
+
id: 'handshake',
|
|
37
|
+
lines: [
|
|
38
|
+
'Moon Archive relay restored. I can mark the exit route once you choose what to review.',
|
|
39
|
+
],
|
|
40
|
+
nextNodeId: 'prompt',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
id: 'prompt',
|
|
44
|
+
lines: [
|
|
45
|
+
'Ask for the route or confirm what still blocks the gate.',
|
|
46
|
+
],
|
|
47
|
+
choices: [
|
|
48
|
+
{
|
|
49
|
+
id: 'ask-route',
|
|
50
|
+
label: 'Ask for the route',
|
|
51
|
+
detail: 'Request the marked path through the lower gallery.',
|
|
52
|
+
nextNodeId: 'route',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 'ask-key',
|
|
56
|
+
label: 'Ask about the Dawn Key',
|
|
57
|
+
detail: 'Confirm what the Moon Gate still needs.',
|
|
58
|
+
nextNodeId: 'key',
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: 'route',
|
|
64
|
+
lines: [
|
|
65
|
+
'The final route runs south, then doubles back to the Moon Gate once the key is recovered.',
|
|
66
|
+
],
|
|
67
|
+
nextNodeId: 'briefing',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 'key',
|
|
71
|
+
lines: [
|
|
72
|
+
'The Moon Gate still listens for the Dawn Key. Recover it from the south gallery and the route will hold.',
|
|
73
|
+
],
|
|
74
|
+
nextNodeId: 'briefing',
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
id: 'briefing',
|
|
78
|
+
lines: [
|
|
79
|
+
'Route note transmitted. Check your journal and carry the Dawn Key back to the gate.',
|
|
80
|
+
],
|
|
81
|
+
outcomeId: 'route-briefed',
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
];
|
|
@@ -1,46 +1,42 @@
|
|
|
1
|
-
|
|
1
|
+
import WORLD_TILEMAP_SOURCE from './world.tilemap.json' with { type: 'json' };
|
|
2
2
|
|
|
3
|
-
export const
|
|
3
|
+
export const WORLD_ORIGIN = { x: 128, y: 72 };
|
|
4
4
|
|
|
5
|
-
export const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
export const WORLD_TILEMAP = WORLD_TILEMAP_SOURCE;
|
|
6
|
+
|
|
7
|
+
export const WORLD_OBJECT_LAYERS = Object.freeze({
|
|
8
|
+
markers: 'markers',
|
|
9
|
+
pickups: 'pickups',
|
|
10
|
+
checkpoints: 'checkpoints',
|
|
11
|
+
props: 'props',
|
|
12
|
+
locks: 'locks',
|
|
13
|
+
scenery: 'scenery',
|
|
14
|
+
});
|
|
10
15
|
|
|
11
|
-
export const
|
|
12
|
-
{ id: '
|
|
13
|
-
{ id: '
|
|
14
|
-
{ id: '
|
|
15
|
-
{ id: 'dawn-key', label: 'Dawn Key', x: 792, y: 548, radius: 20 },
|
|
16
|
+
export const INVENTORY_CATEGORIES = [
|
|
17
|
+
{ id: 'relics', label: 'Relics' },
|
|
18
|
+
{ id: 'keys', label: 'Access Keys' },
|
|
19
|
+
{ id: 'field', label: 'Field Notes' },
|
|
16
20
|
];
|
|
17
21
|
|
|
18
|
-
export const
|
|
19
|
-
{
|
|
20
|
-
id: 'north-brazier',
|
|
21
|
-
label: 'North Brazier',
|
|
22
|
-
x: 246,
|
|
23
|
-
y: 150,
|
|
24
|
-
size: 34,
|
|
25
|
-
radius: 42,
|
|
26
|
-
requiredRelics: 1,
|
|
27
|
-
},
|
|
22
|
+
export const STARTING_INVENTORY_ITEMS = [
|
|
28
23
|
{
|
|
29
|
-
id: '
|
|
30
|
-
label: '
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
24
|
+
id: 'route-brief',
|
|
25
|
+
label: 'Route Brief',
|
|
26
|
+
categoryId: 'field',
|
|
27
|
+
categoryLabel: 'Field Notes',
|
|
28
|
+
quantity: 1,
|
|
29
|
+
badge: 'BRIEF',
|
|
30
|
+
description: 'Survey the Moon Archive and restore the exit route.',
|
|
31
|
+
detail: 'Recover three relics, inspect the archive console, then use the Dawn Key on the Moon Gate.',
|
|
36
32
|
},
|
|
37
33
|
];
|
|
38
34
|
|
|
39
|
-
export const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
35
|
+
export const WORLD_TEXT = {
|
|
36
|
+
zoneLabel: 'Moon Archive',
|
|
37
|
+
objective: 'Recover the relics, inspect the archive console, and leave through the Moon Gate.',
|
|
38
|
+
inventoryHint: 'Inventory stays on the HUD while the journal and dialogue proof move through the overlay screen lane.',
|
|
39
|
+
journalHint: 'Journal tracks route progress and archive intel through one shared starter-owned log surface.',
|
|
40
|
+
consoleNoteTitle: 'Archive Console Log',
|
|
41
|
+
consoleNoteDetail: 'The route seal listens for the Dawn Key. The relic anchors simply restore power to the archive floor.',
|
|
46
42
|
};
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
{
|
|
2
|
+
"width": 16,
|
|
3
|
+
"height": 9,
|
|
4
|
+
"tilewidth": 64,
|
|
5
|
+
"tileheight": 64,
|
|
6
|
+
"solidLayerNames": [
|
|
7
|
+
"collision"
|
|
8
|
+
],
|
|
9
|
+
"layers": [
|
|
10
|
+
{
|
|
11
|
+
"name": "ground",
|
|
12
|
+
"type": "tilelayer",
|
|
13
|
+
"width": 16,
|
|
14
|
+
"height": 9,
|
|
15
|
+
"data": [
|
|
16
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
17
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
18
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
19
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
20
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
21
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
22
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
23
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
24
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "collision",
|
|
29
|
+
"type": "tilelayer",
|
|
30
|
+
"width": 16,
|
|
31
|
+
"height": 9,
|
|
32
|
+
"data": [
|
|
33
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
34
|
+
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
|
35
|
+
1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
|
|
36
|
+
1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1,
|
|
37
|
+
1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1,
|
|
38
|
+
1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1,
|
|
39
|
+
1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1,
|
|
40
|
+
1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
|
|
41
|
+
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "markers",
|
|
46
|
+
"type": "objectgroup",
|
|
47
|
+
"objects": [
|
|
48
|
+
{
|
|
49
|
+
"id": 1,
|
|
50
|
+
"name": "player-start",
|
|
51
|
+
"type": "spawn",
|
|
52
|
+
"x": 128,
|
|
53
|
+
"y": 128,
|
|
54
|
+
"point": true
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": 2,
|
|
58
|
+
"name": "camp-west",
|
|
59
|
+
"type": "spawn",
|
|
60
|
+
"x": 320,
|
|
61
|
+
"y": 448,
|
|
62
|
+
"point": true
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"name": "pickups",
|
|
68
|
+
"type": "objectgroup",
|
|
69
|
+
"objects": [
|
|
70
|
+
{
|
|
71
|
+
"id": 101,
|
|
72
|
+
"name": "Survey Lens",
|
|
73
|
+
"type": "pickup",
|
|
74
|
+
"x": 168,
|
|
75
|
+
"y": 168,
|
|
76
|
+
"width": 28,
|
|
77
|
+
"height": 28,
|
|
78
|
+
"properties": {
|
|
79
|
+
"promptText": "Press E to secure the Survey Lens",
|
|
80
|
+
"grantItemId": "survey-lens",
|
|
81
|
+
"grantCategoryId": "relics",
|
|
82
|
+
"grantCategoryLabel": "Relics",
|
|
83
|
+
"grantDescription": "Calibrates the archive's survey route.",
|
|
84
|
+
"grantDetail": "The brass housing still hums with lunar static.",
|
|
85
|
+
"grantBadge": "RELIC"
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"id": 102,
|
|
90
|
+
"name": "Signal Reel",
|
|
91
|
+
"type": "pickup",
|
|
92
|
+
"x": 456,
|
|
93
|
+
"y": 152,
|
|
94
|
+
"width": 28,
|
|
95
|
+
"height": 28,
|
|
96
|
+
"properties": {
|
|
97
|
+
"promptText": "Press E to pocket the Signal Reel",
|
|
98
|
+
"grantItemId": "signal-reel",
|
|
99
|
+
"grantCategoryId": "relics",
|
|
100
|
+
"grantCategoryLabel": "Relics",
|
|
101
|
+
"grantDescription": "Restores the relay sequence for the east hall.",
|
|
102
|
+
"grantDetail": "Stamped with route marks from the first survey team.",
|
|
103
|
+
"grantBadge": "RELIC"
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"id": 103,
|
|
108
|
+
"name": "Chorus Map",
|
|
109
|
+
"type": "pickup",
|
|
110
|
+
"x": 760,
|
|
111
|
+
"y": 344,
|
|
112
|
+
"width": 28,
|
|
113
|
+
"height": 28,
|
|
114
|
+
"properties": {
|
|
115
|
+
"promptText": "Press E to collect the Chorus Map",
|
|
116
|
+
"grantItemId": "chorus-map",
|
|
117
|
+
"grantCategoryId": "relics",
|
|
118
|
+
"grantCategoryLabel": "Relics",
|
|
119
|
+
"grantDescription": "Pins the resonant floor and old service ducts.",
|
|
120
|
+
"grantDetail": "Enough of it survived to restore the final route.",
|
|
121
|
+
"grantBadge": "RELIC"
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"id": 104,
|
|
126
|
+
"name": "Dawn Key",
|
|
127
|
+
"type": "pickup",
|
|
128
|
+
"x": 888,
|
|
129
|
+
"y": 456,
|
|
130
|
+
"width": 28,
|
|
131
|
+
"height": 28,
|
|
132
|
+
"properties": {
|
|
133
|
+
"promptText": "Press E to recover the Dawn Key",
|
|
134
|
+
"grantItemId": "dawn-key",
|
|
135
|
+
"grantCategoryId": "keys",
|
|
136
|
+
"grantCategoryLabel": "Access Keys",
|
|
137
|
+
"grantDescription": "Still accepted by the Moon Gate lock.",
|
|
138
|
+
"grantDetail": "The key teeth match the seal at the archive exit.",
|
|
139
|
+
"grantBadge": "KEY"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"name": "checkpoints",
|
|
146
|
+
"type": "objectgroup",
|
|
147
|
+
"objects": [
|
|
148
|
+
{
|
|
149
|
+
"id": 201,
|
|
150
|
+
"name": "Camp Lantern",
|
|
151
|
+
"type": "checkpoint",
|
|
152
|
+
"x": 288,
|
|
153
|
+
"y": 416,
|
|
154
|
+
"width": 48,
|
|
155
|
+
"height": 48,
|
|
156
|
+
"properties": {
|
|
157
|
+
"promptText": "Press E to mark the west camp checkpoint",
|
|
158
|
+
"checkpointId": "camp-west"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
]
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"name": "props",
|
|
165
|
+
"type": "objectgroup",
|
|
166
|
+
"objects": [
|
|
167
|
+
{
|
|
168
|
+
"id": 301,
|
|
169
|
+
"name": "Archive Console",
|
|
170
|
+
"type": "prop",
|
|
171
|
+
"x": 616,
|
|
172
|
+
"y": 192,
|
|
173
|
+
"width": 56,
|
|
174
|
+
"height": 40,
|
|
175
|
+
"properties": {
|
|
176
|
+
"promptText": "Press E to inspect the archive console"
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
]
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"name": "locks",
|
|
183
|
+
"type": "objectgroup",
|
|
184
|
+
"objects": [
|
|
185
|
+
{
|
|
186
|
+
"id": 401,
|
|
187
|
+
"name": "Moon Gate",
|
|
188
|
+
"type": "lock",
|
|
189
|
+
"x": 896,
|
|
190
|
+
"y": 448,
|
|
191
|
+
"width": 96,
|
|
192
|
+
"height": 88,
|
|
193
|
+
"properties": {
|
|
194
|
+
"promptText": "Press E to unlock the Moon Gate",
|
|
195
|
+
"lockedPromptText": "Recover the Dawn Key before opening the Moon Gate",
|
|
196
|
+
"openedPromptText": "The Moon Gate is online",
|
|
197
|
+
"requiredItemId": "dawn-key",
|
|
198
|
+
"requiredQuantity": 1,
|
|
199
|
+
"consumeRequiredItem": false
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
]
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"name": "scenery",
|
|
206
|
+
"type": "objectgroup",
|
|
207
|
+
"objects": [
|
|
208
|
+
{
|
|
209
|
+
"id": 501,
|
|
210
|
+
"name": "Central Court",
|
|
211
|
+
"type": "plaza",
|
|
212
|
+
"x": 64,
|
|
213
|
+
"y": 64,
|
|
214
|
+
"width": 896,
|
|
215
|
+
"height": 448,
|
|
216
|
+
"properties": {
|
|
217
|
+
"fill": "#14211b",
|
|
218
|
+
"border": "#294436"
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
"id": 502,
|
|
223
|
+
"name": "Mirror Pool",
|
|
224
|
+
"type": "pool",
|
|
225
|
+
"x": 704,
|
|
226
|
+
"y": 128,
|
|
227
|
+
"width": 160,
|
|
228
|
+
"height": 96,
|
|
229
|
+
"properties": {
|
|
230
|
+
"fill": "#173949",
|
|
231
|
+
"border": "#3a728c"
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"id": 503,
|
|
236
|
+
"name": "Collapsed Hall",
|
|
237
|
+
"type": "ruin",
|
|
238
|
+
"x": 256,
|
|
239
|
+
"y": 224,
|
|
240
|
+
"width": 192,
|
|
241
|
+
"height": 48,
|
|
242
|
+
"properties": {
|
|
243
|
+
"fill": "#28302d",
|
|
244
|
+
"border": "#4c5b57"
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
"id": 504,
|
|
249
|
+
"name": "South Gallery",
|
|
250
|
+
"type": "ruin",
|
|
251
|
+
"x": 512,
|
|
252
|
+
"y": 384,
|
|
253
|
+
"width": 224,
|
|
254
|
+
"height": 48,
|
|
255
|
+
"properties": {
|
|
256
|
+
"fill": "#242a29",
|
|
257
|
+
"border": "#48504c"
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
]
|
|
261
|
+
}
|
|
262
|
+
],
|
|
263
|
+
"tilesets": [
|
|
264
|
+
{
|
|
265
|
+
"firstgid": 1,
|
|
266
|
+
"image": "ruins-placeholder.png",
|
|
267
|
+
"tilewidth": 64,
|
|
268
|
+
"tileheight": 64,
|
|
269
|
+
"tilecount": 1,
|
|
270
|
+
"columns": 1
|
|
271
|
+
}
|
|
272
|
+
]
|
|
273
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# 2D Adventure Loop
|
|
2
2
|
|
|
3
|
-
1. Sweep the
|
|
4
|
-
1. Keep
|
|
5
|
-
1.
|
|
3
|
+
1. Sweep the Moon Archive, recover the route relics, inspect the archive console, and leave through the Moon Gate.
|
|
4
|
+
1. Keep authored room nouns in `content/gameplay/world.js`, `content/gameplay/world.tilemap.json`, and `content/gameplay/dialogue.js`, then keep starter-specific render/collision wrappers in `prefabs/world.prefab.js`.
|
|
5
|
+
1. Use the archive console beat to prove the shared dialogue helper lane plus the shared journal/log owner before widening into heavier narrative or quest systems.
|
|
6
|
+
1. Extend the loop by adding more object layers, item categories, checkpoints, or lock rules once the dialogue and journal proof still fits in one readable starter scene.
|