Add browser-only editor export and 2.5D runtime presentation

This commit is contained in:
emil28092005
2026-09-12 00:05:19 +03:00
parent a25ed40805
commit 1a0bf725fa
16 changed files with 883 additions and 53 deletions
+49
View File
@@ -0,0 +1,49 @@
# Fixed-camera games and runtime presentation
Forma supports fixed orthographic scenes that combine 3D geometry and transparent GLB sprite planes. This is optional: projects without these settings retain the existing camera, controls, and player UI.
## Camera and rendering
An entity can have `camera: { mode: "fixed", lookAt: [0, 0, 0], projection: "orthographic", orthoWidth: 24, aspect: 16 / 9 }`. The camera uses the entity's world position, faces `lookAt`, and preserves the specified aspect ratio with letterboxing. Omit `aspect` to fill the current viewport. The inspector exposes fixed mode, projection, width and look-at position. Perspective and follow/first-person cameras remain supported.
`settings.rendering` accepts `toneMapping`, `exposure` and `contrast`. Disabling tone mapping is useful for artwork that already contains lighting. Generated mesh materials accept `unlit`, `alpha` (01) and `doubleSided`; scripts can update them through `api.patch`. Imported GLB materials retain their authoring settings unless a material override is requested.
## Controls
`settings.controls` optionally maps `attack`, `jump`, `dash`, `sprint` and `reset` to arrays of browser `KeyboardEvent.code` values. Empty arrays disable a keyboard action. Mouse attack and pointer aiming retain the existing runtime input API. Movement remains WASD/arrows; a project's script may transform those axes into its camera basis. Dash/jump/reset also have one-frame pressed events.
## Presentation
Optional `settings.presentation` enables the same lightweight overlay in the editor and exported standalone player:
```json
{
"title": "Example game",
"accent": "#d74732",
"instructions": "WASD — move · J — attack · Space — dash",
"start": { "title": "Example game", "body": "Reach the exit." }
}
```
The start screen pauses simulation until the player continues. The overlay supplies pause/resume, fullscreen, sound, touch movement/attack/dash and keyboard restart. On restart it emits `resetPressed`; the project script owns resetting its gameplay state. Stop in the editor restores the original scene document.
Scripts can emit these presentation events:
```js
api.emit("hud", {
objective: "Wave 1 / 3",
counters: ["Enemies: 4", "Defeated: 0"],
meters: [
{ id: "life", label: "Health", value: 4, max: 5, style: "hearts" },
{ id: "dash", label: "Dash", value: 0.7, max: 1, style: "bar" }
]
});
api.emit("hud", { overlay: { title: "Victory", body: "You reached the exit.", button: "Play again" } });
api.emit("hud", { overlay: null }); // Clear an outcome overlay when resetting.
api.emit("feedback", {}); // Brief damage vignette.
api.emit("sound", { frequency: 520, endFrequency: 90, duration: 0.1, type: "triangle", gain: 0.025 });
```
Outcome overlays pause simulation. HUD text is assigned as text content, meter values and list lengths are bounded. Audio starts after a user gesture and can be muted. Runtime callbacks continue receiving these events, including during headless tests.
The concrete arena, artwork, combat, enemy AI and wave progression live in `projects/InfernalCourtyard`, not in the engine or default project templates.