# Vaelis 1.0.0 — complete documentation Generated 2026-10-11 from the Vaelis engine source. 85 pages follow; each starts with a level-1 heading and its canonical path. --- # Vaelis documentation > Complete, source-verified documentation for Vaelis 1.0.0: editor workflows, scripting API, components, physics, navigation and export. > **What is Vaelis?:** A browser-based 2D game engine with a Unity-style visual editor, an entity–component runtime built on PixiJS (rendering) and Rapier2D (physics), and a JavaScript scripting API. The editor, runtime and exporter ship as a static site — no build server is needed to make or play games. ## Start here ### [Install & run](getting-started/installation.html) Use the hosted editor or serve the static distribution yourself. ### [Build your first game](getting-started/first-game.html) Entities, components and a first script in a few steps. ### [Scripting quickstart](getting-started/scripting.html) onStart, onUpdate, `this` and the component modules. ### [Editor controls](editor/controls.html) Exact menu paths, panels and keyboard shortcuts. ## Browse by topic ### [Get started](getting-started/installation.html) Run the editor, build a first game and learn the scripting model. 5 pages ### [Concepts](concepts/architecture.html) Architecture, the entity–component model, the game loop and coordinates. 4 pages ### [Editor](editor/overview.html) Every panel, menu path, shortcut and authoring workflow. 13 pages ### [Scripting](scripting/lifecycle.html) Lifecycle, globals, input, physics, navigation, saving and debugging. 18 pages ### [API reference](api/index.html) Component fields, script members, option shapes and prerequisites. 5 pages ### [Export & deploy](export/index.html) HTML5, installable PWA and Android APK builds. 4 pages ### [Reference](reference/tuning-guide.html) Tuning rules, scene and project formats, versioning and source map. 9 pages ### [AI & machine access](reference/ai-crawling.html) llms.txt, Markdown twins, JSON catalogs and guidance for assistants. 2 pages ## Component reference 25 components, each documented with serialized fields, defaults, script API and editor location. [**Transform**Position, rotation and scale. Every spatial entity uses a Transform.](api/components/transform.html)[**SpriteRenderer**Draw a 2D texture sprite for an entity.](api/components/spriterenderer.html)[**ShapeRenderer**Draw a procedural 2D shape without requiring a sprite asset.](api/components/shaperenderer.html)[**TextRenderer**Render text either in world space or as screen-space UI.](api/components/textrenderer.html)[**StrokePath**A variable-thickness strip along placed points — rivers, cables, roads, conveyor belts or walls — with flat color or…](api/components/strokepath.html)[**SpeechBubble**Speech bubble UI attached to an entity, useful for dialogue and NPC callouts.](api/components/speechbubble.html)[**ChatLog**Scrollable-style conversation log component for UI dialogue.](api/components/chatlog.html)[**TextInput**Interactive text input control driven by the runtime UI system.](api/components/textinput.html)[**Joystick**Virtual touch joystick for mobile and pointer-driven control schemes.](api/components/joystick.html)[**Rigidbody2D**2D physics body backed by the engine physics runtime. Dynamic, Kinematic and Static bodies have different script…](api/components/rigidbody2d.html)[**Collider2D**Physics collision shape and contact filtering. A Collider2D is also required for accurate pointer/touch hit tests.](api/components/collider2d.html)[**Joint2D**Connect physics bodies with Fixed, Revolute, Prismatic, Rope or Spring constraints.](api/components/joint2d.html)[**CharacterController**High-level movement modes: Character Controller, Platformer, Top-Down, Car, Follow, Patrol and Free.](api/components/charactercontroller.html)[**SpriteAnimation**Sprite-sheet/clip animation state on a SpriteRenderer.](api/components/spriteanimation.html)[**Camera**Orthographic 2D camera with reference resolutions, responsive scaling, follow, shake and optional pseudo-3D sprite…](api/components/camera.html)[**AudioSource**Play a local audio asset, optionally with distance-based 3D attenuation.](api/components/audiosource.html)[**AudioListener**Defines the hearing area for 3D audio and drives audio enter/leave callbacks.](api/components/audiolistener.html)[**Light**2D light source supporting Directional, Point, Spot, Area, GodRays and Freeform light shapes.](api/components/light.html)[**ShadowCaster**Marks an entity as a shadow occluder for the lighting system.](api/components/shadowcaster.html)[**LightingSettings**Scene-wide lighting quality and mood controls. Attach to one entity; the lighting system reads it scene-wide.](api/components/lightingsettings.html)[**NavAgent2D**Per-agent navigation settings and current path state for NavWorld2D pathfinding.](api/components/navagent2d.html)[**NavWorld2D**Shared navigation world for baked or dynamic 2D pathfinding, with 16 navigation areas.](api/components/navworld2d.html)[**Tileset**Defines a reusable 16-role autotile set. The editor can auto-slice one image or accept separate role images.](api/components/tileset.html)[**Tilemap**Sparse painted tile grid that references a Tileset entity by ID.](api/components/tilemap.html)[**Script**Script component holding a script name, source and enabled state.](api/components/script.html) ## For automated systems Every page is complete static HTML with a Markdown twin (same URL, `.md`). Machine entry points: [llms.txt](../../llms.txt), [llms-full.txt](../../llms-full.txt) (all documentation in one file), [search-index.json](../../search-index.json), [api/v1.0.0/index.json](../../api/v1.0.0/index.json), [sitemap.xml](../../sitemap.xml) and [robots.txt](../../robots.txt). See [AI & crawlers](reference/ai-crawling.html). --- # Vaelis documentation > Complete, source-verified documentation for Vaelis 1.0.0: editor workflows, scripting API, components, physics, navigation and export. > **What is Vaelis?:** A browser-based 2D game engine with a Unity-style visual editor, an entity–component runtime built on PixiJS (rendering) and Rapier2D (physics), and a JavaScript scripting API. The editor, runtime and exporter ship as a static site — no build server is needed to make or play games. ## Start here ### [Install & run](getting-started/installation.html) Use the hosted editor or serve the static distribution yourself. ### [Build your first game](getting-started/first-game.html) Entities, components and a first script in a few steps. ### [Scripting quickstart](getting-started/scripting.html) onStart, onUpdate, `this` and the component modules. ### [Editor controls](editor/controls.html) Exact menu paths, panels and keyboard shortcuts. ## Browse by topic ### [Get started](getting-started/installation.html) Run the editor, build a first game and learn the scripting model. 5 pages ### [Concepts](concepts/architecture.html) Architecture, the entity–component model, the game loop and coordinates. 4 pages ### [Editor](editor/overview.html) Every panel, menu path, shortcut and authoring workflow. 13 pages ### [Scripting](scripting/lifecycle.html) Lifecycle, globals, input, physics, navigation, saving and debugging. 18 pages ### [API reference](api/index.html) Component fields, script members, option shapes and prerequisites. 5 pages ### [Export & deploy](export/index.html) HTML5, installable PWA and Android APK builds. 4 pages ### [Reference](reference/tuning-guide.html) Tuning rules, scene and project formats, versioning and source map. 9 pages ### [AI & machine access](reference/ai-crawling.html) llms.txt, Markdown twins, JSON catalogs and guidance for assistants. 2 pages ## Component reference 25 components, each documented with serialized fields, defaults, script API and editor location. [**Transform**Position, rotation and scale. Every spatial entity uses a Transform.](api/components/transform.html)[**SpriteRenderer**Draw a 2D texture sprite for an entity.](api/components/spriterenderer.html)[**ShapeRenderer**Draw a procedural 2D shape without requiring a sprite asset.](api/components/shaperenderer.html)[**TextRenderer**Render text either in world space or as screen-space UI.](api/components/textrenderer.html)[**StrokePath**A variable-thickness strip along placed points — rivers, cables, roads, conveyor belts or walls — with flat color or…](api/components/strokepath.html)[**SpeechBubble**Speech bubble UI attached to an entity, useful for dialogue and NPC callouts.](api/components/speechbubble.html)[**ChatLog**Scrollable-style conversation log component for UI dialogue.](api/components/chatlog.html)[**TextInput**Interactive text input control driven by the runtime UI system.](api/components/textinput.html)[**Joystick**Virtual touch joystick for mobile and pointer-driven control schemes.](api/components/joystick.html)[**Rigidbody2D**2D physics body backed by the engine physics runtime. Dynamic, Kinematic and Static bodies have different script…](api/components/rigidbody2d.html)[**Collider2D**Physics collision shape and contact filtering. A Collider2D is also required for accurate pointer/touch hit tests.](api/components/collider2d.html)[**Joint2D**Connect physics bodies with Fixed, Revolute, Prismatic, Rope or Spring constraints.](api/components/joint2d.html)[**CharacterController**High-level movement modes: Character Controller, Platformer, Top-Down, Car, Follow, Patrol and Free.](api/components/charactercontroller.html)[**SpriteAnimation**Sprite-sheet/clip animation state on a SpriteRenderer.](api/components/spriteanimation.html)[**Camera**Orthographic 2D camera with reference resolutions, responsive scaling, follow, shake and optional pseudo-3D sprite…](api/components/camera.html)[**AudioSource**Play a local audio asset, optionally with distance-based 3D attenuation.](api/components/audiosource.html)[**AudioListener**Defines the hearing area for 3D audio and drives audio enter/leave callbacks.](api/components/audiolistener.html)[**Light**2D light source supporting Directional, Point, Spot, Area, GodRays and Freeform light shapes.](api/components/light.html)[**ShadowCaster**Marks an entity as a shadow occluder for the lighting system.](api/components/shadowcaster.html)[**LightingSettings**Scene-wide lighting quality and mood controls. Attach to one entity; the lighting system reads it scene-wide.](api/components/lightingsettings.html)[**NavAgent2D**Per-agent navigation settings and current path state for NavWorld2D pathfinding.](api/components/navagent2d.html)[**NavWorld2D**Shared navigation world for baked or dynamic 2D pathfinding, with 16 navigation areas.](api/components/navworld2d.html)[**Tileset**Defines a reusable 16-role autotile set. The editor can auto-slice one image or accept separate role images.](api/components/tileset.html)[**Tilemap**Sparse painted tile grid that references a Tileset entity by ID.](api/components/tilemap.html)[**Script**Script component holding a script name, source and enabled state.](api/components/script.html) ## For automated systems Every page is complete static HTML with a Markdown twin (same URL, `.md`). Machine entry points: [llms.txt](../../llms.txt), [llms-full.txt](../../llms-full.txt) (all documentation in one file), [search-index.json](../../search-index.json), [api/v1.0.0/index.json](../../api/v1.0.0/index.json), [sitemap.xml](../../sitemap.xml) and [robots.txt](../../robots.txt). See [AI & crawlers](reference/ai-crawling.html). --- # Installation > Install and run the Vaelis portable distribution. ## How you actually use Vaelis > **You do not have to install or self-host Vaelis to use it.:** The normal path is to visit the Vaelis website in a supported browser and use the editor online. Your browser runs the editor and game runtime. If you want the project/game available like an installed app, use the engine’s PWA/install option when available on your deployment. | Method | When to use it | What you do | | --- | --- | --- | | **Use the website** | Normal users and beginners | Visit the deployed Vaelis website and open the editor. No local server or Node.js setup is required. | | **Install the PWA** | You want an app-like shortcut/offline-capable experience supported by the deployment | Use the browser’s install/add-to-home-screen option when the site exposes it. The PWA is still the same web application; installation does not require running a local development server. | | **Self-host** | You want to host Vaelis yourself—for example on your own web server, CodeSpaces/Codespaces, VS Code local development server, Vercel, or another static host | Use the local/server method below. This is an optional deployment/development method, not a prerequisite for ordinary use. | ## Self-hosting / local development **The method below is only for people who want to host the engine themselves.** The supplied distribution is a static web application, so it can be served by a simple HTTP server. This is useful when developing the engine, modifying its source, testing local files, or deploying your own copy. ### Option A — simple local server ``` python3 -m http.server 5000 ``` Run that command from the folder containing the Vaelis distribution, then open `http://localhost:5000/`. The browser must access the files through HTTP; opening the HTML file directly with `file://` can break module/WASM/network behavior. ### Option B — CodeSpaces / VS Code Use a development server or forwarded port that serves the project directory over HTTP/HTTPS. The important requirement is not the editor you use—it is that the browser receives the static Vaelis files from a web origin. ### Option C — static hosting Upload the distribution to a static host that serves JavaScript modules, JSON, WASM, assets, and the included routes. The supplied `vercel.json` contains route handling for Vercel-style hosting. ## Technical requirements | Requirement | Detail | | --- | --- | | Browser | A modern browser capable of ES modules, WebAssembly, Canvas/WebGL as used by the runtime, and the browser APIs used by the editor. | | Node.js | Not required to simply use the deployed editor or to serve the static client with Python. | | Local HTTP server | Only required when you choose to self-host/preview locally. | | Android APK export | Uses the separate build-server workflow described in the Android export documentation; the browser editor itself does not require an Android SDK. | ## Standalone builds A standalone Vaelis game export contains `index.html`, `main.js` and `runtime/index.js`, built entirely client-side by the editor’s Export window. This export has no editor code in it and can be hosted anywhere that serves static files. ## Android APK > **Requires a build server you provide:** The client distribution does not include an Android SDK, Gradle, or any local APK builder, and there is no bundled command-line exporter. Building an APK means sending your web export to an external build server you connect in the editor. See Android APK for the exact contract. --- # The Vaelis Hub > Projects, starter templates, Learn and Installs tabs, offline PWA install and .vs file association. ## Overview The Hub is the launcher page (`index.html` of the Vaelis site). Choose **Open Editor** or open a project card to enter the editor. A narrow icon rail on the left switches between three tabs. | Tab | What it does | | --- | --- | | Projects | Recent projects with name, template and last-opened time. Click a card to open it, use the pencil to rename inline (Enter saves, Esc cancels) and the trash to remove it from the launcher. **New Project** opens the template picker. | | Learn | Documentation entry point (quick start, scripting API, safety). Works offline because it is in the offline cache. | | Installs | Shows the single engine build that ships with the Hub (Vaelis 1.0.0, Stable). | ## Starter templates | Template | Contents | | --- | --- | | Blank Canvas | An empty environment for pure 2D rendering and custom logic (default). | | Platformer Kit | Kinematic controller, one-way platforms and coyote-time jump tuning. | | Top-Down | Playable starter with player, NPCs, collectible coins and a lit dungeon scene. | | Flappy Bird | Complete flap-to-fly clone with state machine, scoring and juice, commented for beginners. | | Sky Jumper | Endless cloud-hopping jumper with bouncy platforms, collectible stars, climbing camera and jump SFX. | | Physics Sandbox | Rapier2D bodies, colliders and joints pre-wired for prototyping. | Templates other than Blank Canvas are bundled real projects, applied the first time the new project opens in the editor. ## Install and offline use 1. Serve the client over HTTP(S) and open `/index.html` once while connected. 2. Wait for the first load to finish so the service worker can precache the editor, player, runtime and vendor files listed in `offline-manifest.json`. 3. Install the PWA from the browser. The editor, player and engine then launch without a network. The service worker also serves the `/editor`, `/play` and `/player` aliases while offline. Android APK creation still needs the external build server. If the editor looks out of date after an update, reload once while online to refresh the cache. ## .vs project files A `.vs` file is a ZIP archive with Vaelis's own extension. The web manifest declares a **file handler** for it. After installing Vaelis from Chrome or Edge, `.vs` files get the Vaelis icon (Windows, ChromeOS and Linux Chromium browsers), and double-click or **Open with → Vaelis** opens the editor with that project loaded as an unsaved session; use **File → Save Project** to write changes out. macOS and mobile browsers keep a generic icon. For machines without the installed app, `file-association/` in the distribution has an optional Windows `.reg` file and a Linux install script. They set only the icon and type name, and are untested on real desktops. --- # Build your first game > A practical first-game path using entities, components and a simple script. ## 1. Start with a scene Create a scene and add an entity. The editor stores scene state as JSON-compatible data: entities have IDs, names, tags, active state, optional hierarchy folders/prefab metadata, and a component map. ## 2. Add a visual Attach a `SpriteRenderer` and assign a sprite asset, or use a `ShapeRenderer` when you want a procedural primitive. Add a `Camera` and mark one camera as the main camera. ## 3. Add physics when you need it A typical physics actor uses a `Rigidbody2D` plus a `Collider2D`. Choose Dynamic, Kinematic or Static based on who is responsible for movement. ## 4. Add a Script component Put a script on the entity and define lifecycle functions. Vaelis calls `onStart()` once and `onUpdate(dt)` every render frame. ``` function onStart() { this.speed = 220; } function onUpdate(dt) { if (input.keyDown("ArrowRight")) { this.x += this.speed * dt; } if (input.keyDown("ArrowLeft")) { this.x -= this.speed * dt; } } ``` ## 5. Prefer frame-rate-independent movement Use `time.deltaTime` (or the `dt` lifecycle argument) when movement is expressed in units per second. Keep physics-step work in `onFixedUpdate(dt)` when the logic should track the fixed simulation cadence. ## 6. Run, iterate, export Use the editor’s Play flow to test, inspect the Debug HUD when diagnosing runtime behavior, then use **Export** for HTML5, PWA or Android APK. --- # Scripting quickstart > Learn the Vaelis JavaScript scripting model in one page. ## Script shape Vaelis scripts are plain JavaScript functions executed by the ScriptSystem. You do not create a class instance yourself. The engine binds the entity context to `this`. ``` function onStart() { this.health = 100; } function onUpdate(dt) { this.x += 100 * dt; } ``` ## The two layers of the API | Layer | Examples | Use when | | --- | --- | --- | | Entity context (`this`) | `this.x`, `this.sprite`, `this.rigidbody`, `this.destroy()` | You are acting on the current entity. | | Globals | `findFirst()`, `scene.load()`, `physics.raycast()`, `input.keyDown()` | You need scene-wide services or another entity. | ## Common component shortcuts When a component exists on the entity, the corresponding module is exposed on `this`: `this.sprite`, `this.shape`, `this.text`, `this.rigidbody`, `this.controller`, `this.animator`, `this.camera`, `this.audio`, `this.collider`, `this.joint`, `this.navAgent`, `this.light`, `this.shadowCaster`, `this.strokePath`, and more. ## Discoverability The editor’s script autocomplete is sourced from the same public API lists documented here. A good rule for generated code is: use documented globals and component modules; do not reach into internal runtime systems or editor modules. --- # Architecture > How Vaelis separates runtime, editor, standalone runtime, components and systems. ## Runtime / editor / target The distribution follows a hard separation: `project/runtime/` is the engine shipped with games; `project/editor/` is the development tool; `project/player/` is the standalone runtime shell. Runtime must not import editor code; editor may import runtime code. ## Components are data Components are plain data objects. Rendering, physics, lighting, audio and other behavior live in systems. This keeps scene serialization straightforward and makes the same scene data usable by the editor and standalone runtime. ## Systems run in an explicit order | Order | System | | --- | --- | | 1 | ControllerSystem | | 2 | PhysicsSystem | | 3 | AnimationSystem | | 4 | SpeechBubbleSystem | | 5 | TextInputSystem | | 6 | JoystickSystem | | 7 | AudioSystem | | 8 | AudioListenerSystem | | 9 | ScriptSystem | | 10 | Late controller work | | 11 | RenderSystem | | 12 | TilemapSystem | | 13 | NavWorldSystem | | 14 | LightingSystem | | 15 | CameraRenderSystem | ## Rendering containers The runtime separates game-content rendering, screen-space UI and late letterbox/pillarbox bars. Debug lines render in the world container. This separation explains why screen-space UI components such as TextRenderer can remain fixed while the world camera moves. --- # Entities & components > Understand Vaelis scene entities, IDs, tags, component composition and runtime cloning. ## Entity identity An entity has a unique stable ID such as `e12`, a human-facing name, a tag, active state, optional hierarchy folder, prefab metadata and a component map. Names and tags are not unique; IDs are. ## Why IDs matter Use `findById(id)` when you mean one exact entity. Use name/tag queries when you intentionally want one or many matches. Runtime clones keep unique IDs and expose `isClone`. ## Component composition A gameplay actor can combine Transform + SpriteRenderer + Collider2D + Rigidbody2D + Script. A UI button might combine Transform + TextRenderer + Collider2D + Script. There is no requirement that every entity have every component. ## Runtime cloning Use `spawn()` or `this.spawn()` to clone an authored entity. The returned context is the new live entity; `onClone()` runs for runtime clones before `onStart()`. ``` function onUpdate() { if (input.keyPressed("Space")) { var bullet = spawn("Bullet", { x: this.x, y: this.y }); bullet.rotation = this.rotation; // configure the clone right after spawning } } // Inside Bullet’s own script: function onClone() { this.tag = "projectile"; // runs once, before this clone’s onStart() } ``` ## Destroying entities `this.destroy()` queues destruction for the end of the frame. `onDestroy()` runs before removal. Waiting/repeating timers owned by the entity are automatically cancelled when the entity is destroyed. --- # Game loop & scenes > Understand frame updates, fixed physics updates and scene transitions. ## Render-frame lifecycle | Hook | When it runs | | --- | --- | | onStart() | Once before the first onUpdate(). | | onClone() | Once for runtime clones, immediately before onStart(). | | onUpdate(dt) | Every render frame. | | onClick() | On the frame a mouse/finger press targets an entity with a collider. | | onFixedUpdate(dt) | Fixed 60 Hz simulation cadence. | | onDestroy() | Before the entity is removed or the scene ends. | ## Collision & trigger lifecycle Use `onCollisionEnter(other)`, `onCollisionStay(other)` and `onCollisionExit(other)` for physical contacts. `onCollision(other)` remains an alias for collision-enter behavior. Trigger-only callbacks are `onTriggerEnter(other)` and `onTriggerExit(other)`. ## Scene controls Use `scene.current` to read the current scene name, `scene.load(name)` to switch scenes, `scene.restart()` to restart, and `scene.pause()`/`scene.resume()` to freeze gameplay while leaving rendering responsive. ``` function onTriggerEnter(other) { if (other.name === "Target") scene.load("Level2"); } function onUpdate() { if (input.keyPressed("Escape")) { scene.isPaused ? scene.resume() : scene.pause(); } } ``` ## Pause semantics During `scene.pause()`, physics, scripts, animation and audio stop advancing until resume. Rendering stays responsive, which is useful for pause menus and debugging UI. --- # Coordinate system & conventions > The signs, units, axes, rotation conventions and reference-resolution rules that prevent common Vaelis scripting mistakes. > **Core convention:** Vaelis is a 2D screen-style coordinate system: +X is right and +Y is down. Treat Y signs accordingly when writing movement, offsets, camera/UI positioning, and physics examples. ## Transform axes | Value | Positive direction | Common use | | --- | --- | --- | | `x` | Right | Horizontal world movement and placement. | | `y` | Down | Vertical placement; jumping/falling code should use negative/positive signs according to the movement system being used. | | `z` | Depth layer / pseudo-3D input | Affects pseudo-3D rendering only when the camera’s pseudo-3D behavior is enabled. | | `rotation` | Degrees around Z | Used by sprites, lights and directional orientation; 0 points along +X for directional/spot style aiming. | | `scaleX` / `scaleY` | 1 = native size | Values above 1 enlarge; values below 1 shrink; negative values mirror the axis. | ## UI coordinates Screen-space Text, TextInput, ChatLog and Joystick components use the reference-resolution pixel convention supplied by the Camera/device-fit pipeline. This is why HUD coordinates remain stable when the physical device resolution changes. ## Angles and vectors Vector-like APIs use ordinary JavaScript objects such as `{x, y}`. When converting a direction to an angle, remember that the canvas/world Y axis points downward, so visually “up” is negative Y. ## Timing | Concept | Meaning | | --- | --- | | `time.deltaTime` | Seconds since the previous script update; multiply speeds expressed per second by deltaTime. | | `wait(seconds,...)` | Wall-clock game/script timer in seconds. | | `repathInterval` | Navigation re-plan period in seconds. | --- # Editor overview > Navigate the Vaelis editor and understand the main development surfaces. ## Main surfaces | Area | Purpose | | --- | --- | | Hierarchy | Shows entities in the current scene, including hierarchy folders. | | Inspector | Edits entity metadata and component properties. | | Viewport | Scene/game editing and gizmos. | | Script editor | Edit JavaScript with engine-aware autocomplete. | | Bottom panels | Animation, tileset, navigation, status and related workflows. | | Toolbar / menus | Save, project I/O, physics layers, navigation areas, entity creation and export. | ## Entity creation The Add Component workflow exposes the engine’s authoring components, including Rigidbody2D, Collider2D, Joint2D, CharacterController, SpriteRenderer, SpriteAnimation, ShapeRenderer, StrokePath, Light, AudioSource, AudioListener, ShadowCaster, LightingSettings, Tileset, Tilemap, NavWorld2D, NavAgent2D, TextRenderer, SpeechBubble, ChatLog, TextInput and Joystick. ## Editor principle The editor writes serializable scene/project data. Runtime systems consume that data. Private helper modules under `project/editor/` should be treated as implementation details, not game scripting APIs. --- # Editor controls & exact locations > Exact Vaelis UI paths, panel positions, keyboard shortcuts, conditional tools, and where feature-specific buttons live. > **Navigation rule:** This page is an index, not a substitute for feature docs. Each feature page also states the exact control path needed to perform its workflow. ## Editor layout | Region | Location | What it contains | | --- | --- | --- | | Top toolbar | Across the top | File, Edit, GameObject, UI, Window; transform/navigation tools; Play/Pause; Export; Hub. | | Hierarchy | Left, fixed-width column (~213px) | Current scene entity tree, search, folders, selection and add shortcuts. | | Viewport | Center | Scene/Game tabs, viewport toolbar, canvas and editor gizmos. | | Inspector | Right, fixed-width column (~255px) | Selected entity name/tag, components, property fields, Add Component and feature-specific buttons. | | Bottom panel | Bottom edge | Project and Console tabs; scenes, sprites, audio, scripts, prefabs and runtime/editor logs. | ## Top menu paths | Path | Open by clicking | Available commands | | --- | --- | --- | | File | File | Save Now / Saved, Save Project, Optimize Assets on Save, Load Project…, Export…, Extra Backup Storage, Restore from Backup Folder. | | Edit | Edit | Physics Layers… and Nav Areas…. | | Window | Window | Hierarchy, Asset Panel and Inspector show/hide checkboxes; Show All Panels while any panel is hidden. See [Editor settings & performance](settings.html). | | GameObject | GameObject | Empty GameObject, Light, 2D Object, Shape. | | UI | UI | Text, Speech Bubble, Chat Log, Message Input, Joystick. | | GameObject → Light | GameObject → Light | Directional Light, Point Light, Spot Light, Area Light, God Rays, Freeform Light. | | GameObject → 2D Object | GameObject → 2D Object | Tileset, Tilemap, Nav World 2D, Stroke Path. | | GameObject → Shape | GameObject → Shape | Square, Circle, Capsule, Triangle. | ## Toolbar tools and shortcuts | Key | Tool | When visible | Exact behavior | | --- | --- | --- | --- | | Q | Hand / Pan | Always | Drag to pan; scroll to zoom. | | W | Translate | Always | Move selected entity with transform gizmo. | | E | Rotate | Always | Rotate selected entity. | | R | Scale | Always | Scale selected entity. | | T | Tile | When a Tilemap or Tileset exists | Paint tile cells. | | Y | Erase | When a Tilemap or a Nav World 2D exists | Erase tiles / relevant paint data. | | P | Path | When a Stroke Path exists | Append/move/insert path points. | | U | Nav paint walkable | When a Nav World 2D exists | Click = walkable; Alt-click = clear override. | | I | Nav paint blocked | When a Nav World 2D exists | Click = blocked; Alt-click = clear override. | | O | Nav area paint | When a Nav World 2D exists | Click = assign selected area; Alt-click = clear area. | ## Selection, history and playback shortcuts These global shortcuts are ignored while you type in a text field, while the Script Editor is open, and while the Export window is open. Ctrl is Cmd on macOS. | Shortcut | Action | Notes | | --- | --- | --- | | Delete / Backspace | Delete the selected entities | Requires a selection. | | Ctrl+C | Copy selection | Yields to normal text copy when text is selected on the page. | | Ctrl+V | Paste | | | Ctrl+D | Duplicate selection | Copy + paste in one step. | | Ctrl+Z | Undo | Scene edits and Animation-editor edits keep separate histories; undo acts on whichever editor is active. Up to 100 steps. | | Ctrl+Shift+Z or Ctrl+Y | Redo | | | Space | Toggle Play | Opens or closes the Play window. | ## Conditional controls Some controls intentionally do not exist until the related scene object exists. This is important when documenting or generating instructions: do not tell users to click a hidden tool before creating the required object. | Control | Condition | | --- | --- | | Tile (T) | A Tilemap or Tileset exists in the current world. | | Erase (Y) | A Tilemap or a Nav World 2D exists (a Tileset alone does not enable it). | | Path (P) | A Stroke Path exists. | | U / I / O Nav brushes | A Nav World 2D exists. | | Nav bounds/cells view | A Nav World 2D exists. | | Paint Area selector | Nav Area tool O is active and named areas exist. | --- # Editor settings & performance > Window menu panels, File menu storage options, Inspector component notes, Console buttons and the performance settings that cap editor and game frame rates. ## Window menu The **Window** menu in the top toolbar shows or hides the three big panels. Each row is a checkbox. | Item | Panel | | --- | --- | | Hierarchy | Left column. | | Asset Panel | Bottom strip (Console and Project tabs). | | Inspector | Right column. | | Show All Panels | Appears only while at least one panel is hidden; restores all three. | Hiding a panel removes its column and the Scene viewport grows into the freed space. The choice is remembered across reloads per browser, not per project. Only an explicit hide is saved, so a damaged value can never leave you without a way to get panels back. ## File menu storage options | Item | What it does | | --- | --- | | Save Now / Saved | Saves immediately instead of waiting for the next auto-save and reports whether it worked. Shows *Saved* when nothing has changed. | | Save Project | Downloads a re-loadable project file. | | Optimize Assets on Save: ON / OFF | When ON, Save Project losslessly re-encodes PNGs and repacks WAV audio before zipping. Smaller file, slower save. Off by default. | | Load Project… | Opens a `.vs` or `.zip` project. If the project contains scripts the editor asks for confirmation first. | | Export… | Opens the [Export window](../export/export-window.html). | | Enable Extra Backup Storage… | Pick a folder on your real disk; every auto-save is also mirrored there, beyond the browser's storage limit. The menu then shows *Extra Backup Storage: ON (click to turn off)*; turning it off only stops future mirroring and deletes nothing. | | Restore from Backup Folder… | Appears while backup is on. Loads the last mirrored version of this project, replacing what is open. | ## Inspector component notes The small **info (i)** button at the right of the Inspector tab bar shows or hides the grey explanatory notes under each component. Notes are **off by default** so an entity with many components stays compact. The setting is remembered. Orange warnings (for example a missing Collider 2D) are always shown regardless of this toggle. ## Console panel The Console tab in the bottom panel collects script output and engine messages from Play. Use **Copy** to copy the log text and **Clear** to empty it. Console text is shown as plain text, never interpreted as HTML. ## Performance settings The engine keeps a small performance settings object in the browser's `localStorage` under the key `vaelis_engine_settings`. Missing or invalid fields fall back to their defaults individually. In 1.0.0 these values are read by the editor and Play window; there is no settings dialog yet, so changing them means editing that stored value. | Setting | Default | Meaning | | --- | --- | --- | | `editorFpsFocused` | 60 | Frame cap for the editor viewport while its window is focused. | | `editorFpsUnfocused` | 24 | Frame cap while the editor is not focused, to save power. | | `gameFps` | 60 | Frame cap for the Play window. Allowed values: 30, 60, 120, or 0 for unlimited. | | `backgroundRendering` | true | Keep the editor rendering (throttled) when unfocused instead of pausing fully. | | `vsync` | true | Stored toggle for vertical sync. | | `showComponentNotes` | false | The Inspector notes toggle described above. | The Play window applies `gameFps` through the game loop's target FPS. **Exported games are not capped**: they run unlimited (0) and use whatever frame rate the device sustains. The bottom **status bar** shows live FPS, memory and object count, and the engine version. > **Game-side debug HUD:** Inside Play, call debug.show() from a script to see FPS and per-system frame times, and debug.log("label", value) to add your own lines. See Global API . ## Memory protection While a game runs, a memory watchdog monitors JavaScript heap use. If it climbs past a high threshold the engine runs a safe reclaim pass: it asks the GPU texture collector to evict unused textures, drops regenerable placeholder textures and sweeps stale render caches. Textures and audio used by the live scene are never wiped, so sprites do not turn into missing-texture markers. --- # Hierarchy & Inspector > Organize the current scene and edit entities/components with stable serialized data. > **Exact control path:** Select the entity in the left Hierarchy panel or click it in the center Scene view. Its properties appear immediately in the right Inspector . The Add Component button is at the bottom of the Inspector’s component list; use its search field to find a component by name. ## Hierarchy The Hierarchy shows only entities that belong to the active scene. Entities can also belong to hierarchy folders. The saved scene stores folders separately so folder IDs remain stable across save/load. ## Inspector The Inspector edits the entity name, tag, active state, component properties and component-specific authoring fields. For many components, the Inspector exposes more authoring fields than the runtime script API intentionally does. ## Gizmos and shapes Spatial editing uses scene-view gizmos for things such as triangle collider/shape points and other editable geometry. Treat these as authoring controls; scripts should use the documented component APIs instead of manipulating editor gizmo state. --- # Scenes & projects > Save, load, switch, duplicate and serialize Vaelis scenes and project manifests. > **Exact control path:** Project-level scene/file operations are in the bottom Project panel. Scene creation uses Project → Scenes → New Scene ; Save Project and Load Project are in the top File menu. The autosave indicator/action is also exposed through File → Save Now / Saved . ## Scene workflow The Scene Manager supports creating, saving, switching, renaming, duplicating and deleting scenes. The last remaining scene cannot be deleted. ## Project versioning Saved projects are stamped with the engine version. The editor compares an incoming project manifest version with the current engine version and warns when a project was saved by a newer engine. ## Recommended practice Keep source projects with explicit scene names, tags and stable IDs. Treat the serialized format as versioned data; do not silently reinterpret old scene JSON when a breaking engine change is introduced. --- # Assets & animation > Use sprites, animation clips and audio assets from the editor. > **Exact control path:** Imported sprites/audio/scripts/prefabs live in the bottom Project panel. Drag supported assets into the center Scene viewport. For animation, add Sprite Animation in the Inspector, then use the Animation editor window to create clips and import frames. ## Sprites SpriteRenderer points at an asset key rather than embedding image data in the component. This keeps scene JSON lightweight and lets exported runtime assets remain separate. ## Animation SpriteAnimation stores clips and current playback state. Scripts can call `this.animator.play("Run")`, stop playback and inspect current clip/frame information. ## Audio AudioSource stores the asset key plus playback properties. 3D sources use `minDistance` for full volume and fade toward silence at `maxDistance`. AudioListener defines the hearing radius and sound enter/leave callbacks are available to scripts. --- # Prefab workflow > Create, place, edit, update, revert and unpack Vaelis prefabs with the exact editor controls involved. > **What a prefab is:** In Vaelis 1.0.0 a prefab is a reusable one-entity template. Instances keep a prefabId and track field-level overrides. Updating a prefab can propagate the canonical data to other instances. ## Create a prefab Select an entity in the Scene viewport or Hierarchy. In the right Inspector, use the small prefab/box action next to the entity name. The engine creates a prefab from that entity and links the source entity to it. ## Place an instance Use the bottom Project panel → Prefabs folder. Drag a prefab asset into the center Scene viewport. The editor instantiates the template and places the new instance in the scene. ## Edit an instance Change component values normally in the Inspector. Vaelis records changed fields as prefab overrides for that instance. ## Update the prefab When an instance is selected, the Inspector shows a blue Prefab strip. Optional Update Transform checkboxes control whether Position, Rotation, and Scale should also propagate to other instances. Click Update Prefab to make this instance the new canonical template. ## Revert / Unpack | Inspector control | Effect | | --- | --- | | `Revert Prefab` | Discard the instance’s overrides and re-sync its values from the prefab. | | `Unpack Prefab` | Detach this instance while keeping its current values. Future prefab updates no longer reach it. | ## Delete a prefab asset Bottom Project → Prefabs. Use the asset delete control. Existing objects keep their current data but are no longer linked to the deleted prefab. ## Important implementation fact Prefab data is stored in the project’s `prefabs.json` catalogue and is included by Save Project/import/export flows. --- # Physics authoring > Configure rigid bodies, colliders, joints, layers and one-way platforms. > **Exact control path:** Physics components are added from Inspector → Add Component (Rigidbody 2D, Collider 2D, Joint 2D, Movement Type). Global named physics layer slots are edited at Edit → Physics Layers… . ## Rigid bodies | Body type | Typical responsibility | | --- | --- | | Dynamic | Physics solver controls movement; scripts apply forces/impulses or read/write velocity. | | Kinematic | Scripts/controllers request movement; collision resolution produces contact state. | | Static | Fixed world geometry; no dynamic motion. | ## Colliders Collider2D supports Box, Circle, Capsule and Triangle shapes. You can enable triggers, one-way platforms, friction/restitution, density, offsets and 16-layer collision filtering. ## Collision layers Each collider belongs to one layer (0-15) and exposes a 16-bit mask of layers it can interact with. A raycast can use `physics.layer(…)` to build the same mask model for query filtering. ## Joints Joint2D supports Fixed, Revolute, Prismatic, Rope and Spring. Rope and Spring use multi-segment chains for visual/physical behavior and expose anchors, length, stiffness/damping and optional motors/limits. ## One-way platforms > **Direction matters:** A one-way platform is a Collider2D with isOneWayPlatform = true . The physics system distinguishes pass-through movement from the blocking direction, so the behavior should be tested with the body moving from both sides. --- # Navigation authoring > Bake 2D navigation with NavWorld2D and configure NavAgent2D. > **Exact control path:** Create the shared nav grid with GameObject → 2D Object → Nav World 2D . Then the top toolbar exposes U walkable, I blocked and O area paint tools. Brush −/+ controls sit directly beside those nav tools. Named areas are configured at Edit → Nav Areas… . ## NavWorld2D A NavWorld2D defines world bounds, cell size and authored/baked cell data. It supports 16 navigation areas, per-area costs, optional diagonal traversal and optional dynamic rebuilding. ## Agents NavAgent2D adds radius, speed, acceleration/deceleration, stopping distance, automatic repathing and avoidance. Vehicle-oriented settings are available for car-style navigation/steering. ## Script access Scripts use the global `nav` module: `nav.findPath()`, `nav.isWalkable()` and `nav.bake()`. A NavAgent exposes its live `currentPath` and `currentPathIndex` as read-only script state. ## Pathfinding behavior Path endpoints are snapped to the nearest walkable cell. Returned waypoints are world-space points with straight runs merged, but they are not geometrically smoothed. --- # Lighting, audio & UI > Build atmospheric scenes, sound behavior and responsive UI with Vaelis components. > **Exact control path:** Create lights from GameObject → Light or add Light/Audio/UI components through Inspector → Add Component . Screen-space UI entities can also be created directly from the top UI menu. ## Lighting Lights support Directional, Point, Spot, Area, GodRays and Freeform types. LightingSettings controls scene-wide shadow quality, ambient darkness and visible glow strength. ShadowCaster controls per-entity shadow geometry and softness. ## Shadow quality ShadowMode `quad` is the cheaper analytic mode. `raymarch` enables per-pixel ray-marched occlusion; `raymarchSteps` controls accuracy/cost and is clamped to 1-200. ## UI TextRenderer can be screen-space, while SpeechBubble, ChatLog, TextInput and Joystick provide higher-level UI behaviors. TextInput exposes `justSubmitted`; Joystick exposes normalized x/y input and engagement state. ## Audio listeners AudioSource can be 3D distance-attenuated. AudioListener receives hearing-area transitions that map to `onHearSound(source)` and `onLoseSound(source)`. --- # Tilemaps & tilesets > Author sparse tile grids and 16-role autotile tilesets. > **Exact control path:** Create a reusable tileset via GameObject → 2D Object → Tileset and the tile grid via GameObject → 2D Object → Tilemap . Once present, T selects tile painting and Y selects erase. The Tileset Editor exposes the 4×4 role grid and import actions. ## Tileset authoring The editor can take one image and auto-slice it into a 4×4 role grid, or accept up to 16 separate role images. The stored result is sixteen role-to-sprite-key mappings. ## The 16 roles The canonical order is `cornerTL, edgeT, cornerTR, stubT, edgeL, center, edgeR, lineV, cornerBL, edgeB, cornerBR, stubB, stubL, lineH, stubR, single`. ## Tilemap data A Tilemap references a Tileset by entity ID and stores a sparse set of filled cells keyed as `col,row`. The runtime computes the visual tile role from orthogonal neighbors; it does not store the final role per cell. ## Scripting > **No direct Tilemap script module in 1.0.0:** Tilemap/Tileset are editor/scene-data components. There is no documented this.tilemap runtime API in this version. --- # Components: complete workflow > A complete guide to adding, configuring, testing, removing, and scripting components. This page complements each individual component reference; it does not replace the per-component settings tables. ## 1. Select the entity first Click an entity in the **Hierarchy** on the left or select it in the Scene viewport. The selected entity's properties appear in the **Inspector** on the right. ## 2. Add a component At the bottom of the Inspector click **Add Component**. A centered **Add Component** modal opens with a search field and a scrollable list. Type the component name, then click its row. The list excludes components the entity already has. ## 3. Configure the component After adding it, scroll the Inspector to the new component section. Start with the component's mode/type field if it has one. Changing a mode can expose or hide related settings. Configure required references/assets before tuning numbers. ## 4. Understand values versus runtime state Serialized authoring settings are saved with the scene. Runtime state fields can change while the game runs and are useful for debugging. Examples include Rigidbody2D velocity/ground state and CharacterController request/state values. ## 5. Test in Play mode Run the game, observe the result, and inspect the component again when debugging. Change one setting at a time so you can identify which property caused the behavior. ## 6. Use the dedicated editor tools | System | Where | What it does | | --- | --- | --- | | Sprite | Inspector SpriteRenderer section / asset picker | Assign the visual asset. | | Animation | SpriteAnimation → Open Animation Window | Create and edit clips/frames. | | Physics | Collider/Transform gizmos in Scene viewport | Visually inspect/edit geometry. | | Navigation | NavWorld2D + navigation toolbar + Edit → Nav Areas… | Author areas, bake/debug navigation, then use NavAgent2D. | | Tiles | Tileset/Tilemap panels | Create tile data and paint the map. | | Stroke Path | Stroke Path viewport tool/gizmo | Edit path points and inspect serialized path settings. | | Scripts | Script → Create New Script / Load Script… / Open Script Editor | Create, attach, edit, and enable scripts. | | Lighting | Light/ShadowCaster gizmos + Inspector | Author light geometry and shadow participation. | ## 7. Component combinations that matter - **Dynamic physics actor:** Rigidbody2D + Collider2D; add SpriteRenderer/ShapeRenderer for visuals. - **Platformer controller:** Rigidbody2D + Collider2D + CharacterController; choose Platformer and configure its movement group. - **Navigation agent:** NavWorld2D in the navigation world + NavAgent2D on the moving entity; bake/configure the world before testing agent movement. - **Animated character:** SpriteRenderer + SpriteAnimation, optionally with Rigidbody2D/CharacterController. - **Interactive UI:** the appropriate UI component (TextRenderer, TextInput, Joystick, SpeechBubble, ChatLog) plus Script when behavior is needed. ## 8. Where to go next Use the component reference for the complete field table, defaults, API members, notes, and examples. Use [Navigation: Complete Setup](../scripting/navigation-complete.html) for multi-system navigation. Use [Script API Cookbook](../scripting/api-cookbook.html) for complete scripting recipes. --- # Complete feature workflows > Use these pages when you need to build an entire subsystem, not just understand one property. Each workflow starts with prerequisites and editor locations, then moves through configuration, scripting, testing and troubleshooting. ### [Navigation authoring](../editor/navigation.html) Create Nav World 2D, configure bounds/cell size, define areas, paint or derive walkable space, add agents, bake/update navigation and debug the result. ### [Navigation from editor to script](../scripting/navigation-complete.html) Complete path from scene setup through NavAgent2D, named area masks/costs, navMoveToward/navDriveToward and runtime troubleshooting. ### [Physics authoring](../editor/physics.html) Build colliders, rigidbodies, joints and character controllers, then tune layers, masks, gravity, damping, slopes and one-way platforms. ### [Physics scripting](../scripting/physics.html) Use Rigidbody2D, Collider2D, raycasts, forces/impulses, collision state and movement APIs from scripts. ### [Lighting, audio and UI](../editor/lighting-audio-ui.html) Set up lights/shadows, audio sources/listeners, text and interactive UI components with their editor locations and runtime APIs. ### [Tilemaps and tilesets](../editor/tilemaps.html) Create tileset data, attach it to a Tilemap, paint, edit tile data and understand the navigation/physics consequences of tile geometry. ### [Assets and animation](../editor/assets-animation.html) Import/use sprites, build Sprite Animation clips, choose frames, set playback and connect animation state to scripts. ### [Prefabs](../editor/prefabs.html) Create reusable entity templates, instantiate them, understand overrides, update/revert behavior and runtime spawning. ### [Web/PWA deployment](../export/web.html) Understand the normal online workflow, standalone web export, PWA behavior and what a deployment must serve. ### [Android APK export](../export/android.html) Configure the separate build-server workflow and understand what is sent from the browser editor. ## How to use these guides 1. Start with the prerequisites section. 2. Follow the exact editor path instead of guessing which panel contains a control. 3. Configure the minimum working setup first. 4. Only then add optional tuning such as costs, smoothing, avoidance, shadows, custom input or advanced physics. 5. Run the smallest test scene before integrating the subsystem into a large project. 6. If a result is wrong, use the troubleshooting section before changing unrelated settings. --- # Lifecycle > Complete Vaelis script lifecycle and callback reference. ## Core lifecycle | Callback | Semantics | | --- | --- | | onStart() | Once before first onUpdate(). | | onClone() | Once for runtime clones, immediately before onStart(). | | onUpdate(dt) | Every render frame. | | onFixedUpdate(dt) | Fixed 60 Hz accumulator. | | onDestroy() | Before entity removal / scene end. | ``` function onStart() { this.hp = 100; // custom fields on this persist across the entity’s lifetime debug.log("HP", this.hp); } function onUpdate() { this.x += 50 * time.deltaTime; // frame-rate independent movement } function onFixedUpdate(dt) { // runs at a fixed 60 Hz step — good for deterministic physics-adjacent logic } function onDestroy() { debug.clear("HP"); } ``` ## Pointer callbacks `onClick()` is a frame pulse for mouse/finger presses targeting an entity with Collider2D. For continuous polling, use `this.isPointerOver`, `this.isClicked`, `this.isTouchOver` or `this.isTapped` where appropriate. ``` function onClick() { this.destroy(); // pops this entity when clicked or tapped } ``` ## Collision callbacks | Callback | Runs | | --- | --- | | onCollision(other) | Alias of collision-enter behavior. | | onCollisionEnter(other) | Contact begins. | | onCollisionStay(other) | Every physics step while still touching. | | onCollisionExit(other) | Contact ends. | | onTriggerEnter(other) | Trigger overlap begins. | | onTriggerExit(other) | Trigger overlap ends. | ``` function onCollisionEnter(other) { if (other.name === "Ground") this.isGrounded = true; } function onTriggerEnter(other) { if (other.hasComponent("Rigidbody2D")) scene.load("Level2"); } ``` ## State callbacks When using `this.state.change(name)`, Vaelis can call `onStateExit()`, `onStateEnter()` and `onStateUpdate(dt)` for state-specific logic. ``` function onUpdate() { if (this.hp <= 0 && this.state.current !== "dead") { this.state.change("dead"); } } function onStateEnter() { if (this.state.current === "dead") this.sprite.opacity = 0.3; } ``` ## Error isolation Lifecycle errors are caught and reported by the runtime. A one-time `onStart()` failure disables the script; recurring `onUpdate()` errors are isolated so the next frame can continue. --- # Global API > Reference the global objects and functions available inside Vaelis scripts. ## Entity lookup | API | Purpose | | --- | --- | | findFirst(name) | First entity matching a name, or null. | | findAll(name) | Every entity with a name, as an array. | | findFirstWithTag(tag) | First entity with a tag, or null. | | findAllWithTag(tag) | Every entity with a tag. | | findWithTag(tag) | Alias for findAllWithTag(). | | findById(id) | Exact entity by stable ID, or null. | | findInRadius(x,y,radius,opts) | Entities within radius, nearest first; optional name/tag filter. | ``` function onUpdate() { var target = findFirst("Target"); if (target) this.navMoveToward(target.x, target.y, 100); var nearby = findInRadius(this.x, this.y, 150, { tag: "Enemy" }); debug.log("Enemies nearby", nearby.length); } ``` ## Scene, physics & navigation modules | Module | Key members | | --- | --- | | scene | current, load, restart, pause, resume, isPaused, lighting, find\* | | physics | raycast, layer | | nav | findPath, isWalkable, bake, areaIndex, areaMask, areaCosts | ``` function onTriggerEnter(other) { if (other.name === "Target") scene.load("Level2"); } function onUpdate() { var hit = physics.raycast(this.x, this.y, this.x + 200, this.y); if (hit) debug.log("Ray hit", hit.entity ? hit.entity.name : "wall"); } ``` ## Spawning & scheduling | API | Semantics | | --- | --- | | spawn(nameOrTag, options) | Clone authored entity; supports direct entity contexts and byTag lookup. | | wait(seconds, callback) | One-shot timer; returns a timer ID. | | repeat(seconds, callback) | Recurring timer; returns a timer ID. | | cancelWait(timerId) | Cancel one-shot timer. | | cancelRepeat(timerId) | Cancel recurring timer. | ``` function onStart() { spawn("Enemy", { x: this.x + 100, y: this.y }); this._spawnTimer = repeat(2, function () { spawn("Coin", { x: Math.random() * 400, y: 0 }); }); } function onDestroy() { cancelRepeat(this._spawnTimer); } ``` ## Messaging `sendMessage(tagOrEntity, message, data)` can address every entity in a tag or one exact entity context. `broadcastMessage(message, data)` sends to all scene entities. Message handlers use the same script context model. ``` // Sender: function onCollisionEnter(other) { sendMessage("Enemy", "hit", { amount: 10 }); } // Receiver (on any entity tagged "Enemy"): function onMessage(message, sender, data) { if (message === "hit") this.hp -= data.amount; } ``` ## Tweening | Global | Purpose | | --- | --- | | `tween(target, props, duration, easing?, onComplete?)` | Smoothly animate numeric properties over game seconds; returns an id (or `-1` on invalid input). | | `cancelTween(id)` | Stop a running tween; returns `true` if it was still active. | Full reference, 33 easings and recipes: [Tween API](tween.html). ## Math & time Use `time.deltaTime`, `time.unscaledDeltaTime`, `time.elapsed` and the writable `time.scale` (see [Time scale & game speed](time-scale.html)); `random.int()`/`random.float()`; and the small `mathx` helpers `lerp`, `clamp`, `moveToward`, `remap`, `approximately` and `smoothstep`. A bare `smoothstep(a, b, x)` global is also available. Native JavaScript `Math` is also available. ``` function onUpdate() { this.x = mathx.moveToward(this.x, targetX, 200 * time.deltaTime); this.rotation = mathx.lerp(this.rotation, 90, 0.1); if (random.float() < 0.01) spawn("Powerup", { x: this.x, y: this.y }); } ``` --- # Tween API > Animate numeric properties smoothly with tween(), choose from 33 easing curves, and stop animations with cancelTween(). ## Overview `tween(target, properties, duration, easing, onComplete)` smoothly moves one or more numeric properties from their current value to a target value over a number of **game seconds**. It is a global function, available in every script with no import. It returns a numeric id you can pass to `cancelTween(id)`. | Argument | Type | Meaning | | --- | --- | --- | | `target` | object | An entity context (`this`, or the result of `findFirst()` etc.) or a scripting component object such as `this.sprite`, `this.light` or `this.camera`. | | `properties` | object | Map of property name to end value, for example `{ x: 420, y: 180 }`. Only finite numbers are accepted as end values. | | `duration` | number | Length in game seconds. `0` (or an invalid value) completes on the next tween update. | | `easing` | string | Optional. One of the [33 easing names](#easing-catalogue). Empty or omitted means `"linear"`. | | `onComplete` | function | Optional. Called once when the tween finishes, with `this` bound to the entity that started the tween. | ``` function onStart() { // Move, spin and resize over 0.8 game seconds tween(this, { x: 420, y: 180, rotation: 90, scaleX: 1.2, scaleY: 1.2 }, 0.8, "easeOutCubic", function () { // "this" is still the entity that started the tween tween(this.sprite, { opacity: 0.25 }, 0.35, "easeInOutSine"); }); } ``` ## What can be tweened A property is tweened only if it **already exists on the target and currently holds a finite number**. Properties that are missing, non-numeric (colours are hex strings, `position` and `scale` are objects) or non-finite are skipped. | Target | Typical tweenable properties | | --- | --- | | `this` (entity) | `x`, `y`, `rotation`, `scaleX`, `scaleY` | | `this.sprite` | `opacity` | | `this.shape` | `width`, `height`, `radius`, `opacity`, `outlineWidth` | | `this.text` | `fontSize`, `opacity` | | `this.light` | `intensity`, `radius`, `angle`, `shadowStrength` | | `this.audio` | `volume`, `pitch` | | `this.camera` | `zoom`, `offsetX`, `offsetY` | | `this.strokePath` | `thickness`, `opacity`, `textureOffset` | | `scene.lighting` | `ambientDarkness`, `glowStrength` | Any numeric member listed on a component's Script API table can be a tween target. Each tween writes through the normal script API, so setter rules (clamping, validation) still apply. ## Cancelling ``` var id = tween(this, { x: 700 }, 2, "easeOutBounce"); // later var wasActive = cancelTween(id); // true only if a tween with that id was still running ``` `cancelTween()` leaves the property at whatever value it had reached. `onComplete` is not called for a cancelled tween. ## Behavior and rules - **Start tweens from lifecycle callbacks** such as `onStart()`, `onClick()` or a collision handler. Calling `tween()` outside script execution logs `[tween]` warning and returns `-1`. Avoid creating a new tween every frame in `onUpdate()`; start one and let it run. - **Game time.** Tweens advance once per frame after `onUpdate` callbacks, using the scaled frame clock. [`time.scale`](time-scale.html) speeds them up or slows them down, and `scene.pause()` freezes them. - **Exact finish.** When progress reaches 1 the property is set to the exact end value, so back/elastic overshoot never leaves a rounding error. - **Several properties at once** in one call share the same duration and easing. - **Automatic cleanup.** A tween ends silently if the entity that started it, or the entity it targets, is destroyed. Restarting or switching scenes clears all tweens. - **Errors.** If an easing function or a property setter throws, that tween is removed and the error is reported in the Console with the owning entity name. A completion callback that throws is reported as `tween onComplete`. - **Return value.** Invalid input (bad target, properties not an object, unknown easing, no numeric properties, non-function `onComplete`) returns `-1` and logs a `[tween]` warning that says what to fix. An unknown easing name is never silently treated as linear. - **Easing names** are case-insensitive and ignore spaces, hyphens and underscores, so `"EASE-OUT-QUAD"` equals `"easeOutQuad"`. > **Tweening physics bodies:** Assigning x or y on an entity that has a Dynamic or Kinematic Rigidbody2D teleports the body each frame. For moving physics objects use velocities or forces; use tween for transforms, opacity, UI, lights, cameras and Static or non-physics entities. ## Editor support The Script Editor autocompletes `tween` and `cancelTween`, and offers the easing names inside the easing string (type `tween(this, { x: 100 }, 1, "easeOut` and the matching names appear). Both names are syntax-highlighted as engine globals. ## Easing catalogue Every name below is a real engine easing. Each preview is drawn from the engine's own easing function: the horizontal axis is time (0 to 1) and the vertical axis is progress. The dashed lines mark the start value (bottom) and end value (top); curves that cross them overshoot on purpose. **In** starts slowly, **Out** ends slowly, **InOut** does both. | Family | Names | | --- | --- | | Basic | `linear`, `smoothstep`, `smootherstep` | | Quad | `easeInQuad`, `easeOutQuad`, `easeInOutQuad` | | Cubic | `easeInCubic`, `easeOutCubic`, `easeInOutCubic` | | Quart | `easeInQuart`, `easeOutQuart`, `easeInOutQuart` | | Quint | `easeInQuint`, `easeOutQuint`, `easeInOutQuint` | | Sine | `easeInSine`, `easeOutSine`, `easeInOutSine` | | Expo | `easeInExpo`, `easeOutExpo`, `easeInOutExpo` | | Circ | `easeInCirc`, `easeOutCirc`, `easeInOutCirc` | | Back | `easeInBack`, `easeOutBack`, `easeInOutBack` | | Elastic | `easeInElastic`, `easeOutElastic`, `easeInOutElastic` | | Bounce | `easeInBounce`, `easeOutBounce`, `easeInOutBounce` | ### Basic `linear` `smoothstep` `smootherstep` ### Quad `easeInQuad` `easeOutQuad` `easeInOutQuad` ### Cubic `easeInCubic` `easeOutCubic` `easeInOutCubic` ### Quart `easeInQuart` `easeOutQuart` `easeInOutQuart` ### Quint `easeInQuint` `easeOutQuint` `easeInOutQuint` ### Sine `easeInSine` `easeOutSine` `easeInOutSine` ### Expo `easeInExpo` `easeOutExpo` `easeInOutExpo` ### Circ `easeInCirc` `easeOutCirc` `easeInOutCirc` ### Back `easeInBack` `easeOutBack` `easeInOutBack` ### Elastic `easeInElastic` `easeOutElastic` `easeInOutElastic` ### Bounce `easeInBounce` `easeOutBounce` `easeInOutBounce` ## Recipes ### Fade out and destroy ``` function onClick() { tween(this.sprite, { opacity: 0 }, 0.4, "easeInQuad", function () { this.destroy(); }); } ``` ### Pop-in UI ``` function onStart() { this.scaleX = 0; this.scaleY = 0; tween(this, { scaleX: 1, scaleY: 1 }, 0.5, "easeOutBack"); } ``` ### Light pulse that can be stopped ``` function onStart() { this._pulse = tween(this.light, { intensity: 2 }, 0.6, "easeInOutSine", function () { tween(this.light, { intensity: 0.5 }, 0.6, "easeInOutSine"); }); } function onDestroy() { cancelTween(this._pulse); } ``` ### Slow-motion hit stop with a tween that ignores nothing ``` function onCollisionEnter(other) { time.scale = 0.2; // tweens and timers slow down too wait(0.3, function () { time.scale = 1; }); } ``` --- # Time scale & game speed > Slow motion, speed-up and freeze with time.scale, plus time.deltaTime, time.unscaledDeltaTime and time.elapsed. ## The time object | Member | Type | Meaning | | --- | --- | --- | | `time.deltaTime` | number | Game seconds since the previous frame. Follows `time.scale`. | | `time.unscaledDeltaTime` | number | Real seconds since the previous frame, ignoring `time.scale`. Use it for menus and UI that must keep animating while the game is slowed or frozen. | | `time.elapsed` | number | Game seconds since the game started. Follows `time.scale`. | | `time.scale` | number | Read/write game speed multiplier, from 0 to 100. Default `1`. | ## Using time.scale `time.scale` changes how fast the whole game runs, like Unity's `Time.timeScale`. ``` function onClick() { time.scale = 0.3; // slow motion wait(1.5, function () { // 1.5 GAME seconds = 5 real seconds at 0.3 time.scale = 1; }); } ``` | Value | Effect | | --- | --- | | `1` | Normal speed. | | `0.5` | Slow motion (half speed). | | `2` | Double speed. | | `0` | Frozen. The world still updates with `dt = 0`, rendering continues, and scripts keep running so you can read input and show a pause menu. | ## What is and is not affected - **Affected:** physics, animation, [`tween()`](tween.html), `wait()` and `repeat()`, `onFixedUpdate`, `time.deltaTime` and `time.elapsed`. - **Not affected:** input, rendering and `time.unscaledDeltaTime`. ## Limits and gotchas - Values must be numbers from 0 to 100. Anything else (negative, NaN, text) is ignored and a console warning says the previous value was kept. Values above 100 are clamped to 100. - Each frame simulates at most half a second of game time, so on a 60 FPS screen speeds above roughly 30x will not go faster. - A tab-out or long frame spike is clamped to 0.1 real seconds before the scale is applied. - **It stays set** when you load or restart a scene. Set `time.scale = 1` yourself if the next scene should run at normal speed. - Physics catch-up steps are capped, so extreme speeds trade accuracy for stability. ## Pause menu pattern ``` function onUpdate() { if (input.keyPressed("Escape")) { time.scale = time.scale === 0 ? 1 : 0; } // Menu animation that keeps running while frozen: this.rotation += 90 * time.unscaledDeltaTime; } ``` `scene.pause()` and `scene.resume()` are the other way to freeze gameplay; see [Global API](globals.html). Unlike `time.scale = 0` (where scripts keep running with `deltaTime = 0`), `scene.pause()` stops scripts including `onUpdate`, physics, animation and audio from the next frame until `scene.resume()`. --- # Entity context > Reference the `this` object and entity-aware shortcuts available in Vaelis scripts. ## Core members | Member | Meaning | | --- | --- | | x, y | World position; writes to physics position targets when a non-static Rigidbody2D exists. | | position | Read/assign {x,y}. | | rotation | Degrees. | | scaleX, scaleY | Scale. | | translate(dx,dy) | Move by a delta. | | distanceTo(x,y) | Distance to a world point. | | name | Read-only entity name. | | tag | Read/write tag. | | id | Stable unique ID. | | visible | Show/hide entity. | | enabled | Enable/disable the current script. | | destroy() | Queue entity destruction. | | destroyed | Read-only destruction state. | | isClone | True for runtime-spawned clones. | ``` function onUpdate() { this.translate(0, -50 * time.deltaTime); // move up var target = findFirst("Target"); if (target && this.distanceTo(target.x, target.y) < 40) { this.destroy(); } } ``` ## Component modules Depending on attached components, `this` exposes modules including `transform`, `sprite`, `shape`, `text`, `speechBubble`, `chat`, `textInput`, `joystick`, `rigidbody`, `controller`, `animator`, `camera`, `audio`, `ear`, `collider`, `joint`, `navAgent`, `light`, `shadowCaster` and `strokePath`. ``` function onUpdate() { if (this.hasComponent("Rigidbody2D")) { this.rigidbody.addForce(0, -500); } this.sprite.opacity = this.isPointerOver ? 1 : 0.6; } ``` ## Timers belong to entities Both `wait()` and `repeat()` are associated with the scheduling entity. When the entity is destroyed or a scene restarts/switches, its timers are automatically cancelled. ``` function onStart() { this.wait(1.5, function () { this.sprite.opacity = 1; // this is still the entity that scheduled the timer }); } ``` ## Pointer helpers > **Collider requirement:** isPointerOver , isClicked , isTouchOver , isTapped and myTouch require Collider2D because hit testing uses the real collider shape. --- # Entity shortcuts (this.x, this.transform) > What this is inside a script, which properties are flat shortcuts, and which require a specific component. ## Flat shortcuts (always available) Inside any lifecycle function, `this` is an EntityContext bound to the entity the script is attached to. A small set of properties are flat shortcuts directly onto the entity’s Transform, because Transform has only one shape. Everything else lives behind a sub-object gated by a specific component — see the full this reference for every sub-object. | Shortcut | Meaning | | --- | --- | | this.x / this.y | Read/write live position. Writing immediately moves the entity, and correctly teleports the physics body too on a Dynamic or Kinematic Rigidbody2D rather than being silently overwritten by the next physics step. | | this.position | {x, y}; assigning moves the entity. | | this.translate(dx, dy) | Move by a delta this call. | | this.rotation, this.scaleX, this.scaleY | Degrees and scale factors, matching the Inspector’s Transform fields. | | this.visible, this.enabled | Show/hide and enable/disable the entity. | ``` function onUpdate() { this.rotation += 90 * time.deltaTime; // spin this.translate(0, -1); // drift upward one unit per frame if (this.y < -50) this.visible = false; } ``` ## Identity & lifecycle helpers | Helper | Meaning | | --- | --- | | this.destroy() | Queues the entity for removal (deferred, not instant). this.destroyed becomes true immediately even though removal has not happened yet. | | this.hasComponent(key) | True if the entity currently has the named component. "Transform" always returns true. Works on any EntityContext, including one from find() or a collision callback’s other. | | this.name, this.tag, this.id | Read-only name; read/write tag; stable unique ID. | | this.isClone | True inside onClone()/onStart() for a runtime-spawned clone. | ``` function onUpdate() { if (this.hp <= 0 && !this.destroyed) { this.destroy(); } } function onStart() { if (this.isClone) this.tag = "spawned"; // mark runtime clones differently } ``` --- # Finding & spawning entities > The find/findAll/findWithTag family, plus spawn() for runtime-instantiated clones. ## Finding entities | API | Returns | | --- | --- | | findFirst(name) | First entity with this exact name, or null. | | findAll(name) | Every entity with this name, as an array. | | findFirstWithTag(tag) / findAllWithTag(tag) | Same pair, keyed by tag instead of name. | | findById(id) | Never ambiguous — use the id from an earlier spawn() or find() call. | | findInRadius(x, y, radius, opts) | Entities within radius world units of a point, nearest first. | | entity.distanceTo(x, y) | Instance method on any EntityContext: distance from that entity to a point. | ## Spawning `spawn(nameOrTag, opts)` spawns a runtime clone of an existing entity. Looks the source up by name by default: ``` spawn("Bullet"); spawn("Bullet", { x: this.x, y: this.y }); spawn("Enemy", { byTag: true, x: 200, y: 100 }); // look up by tag, clone the first match ``` Optionally rename the clone with `opts.name`. Returns an EntityContext for the new entity (same shape as `this`), or null if no source entity matches. The clone’s own `onClone()` then `onStart()` fire automatically on the next frame, with `this.isClone === true` inside them. Also available as an instance method, `this.spawn(nameOrTagOrEntity, opts)` — pass an EntityContext directly (e.g. `this.spawn(this)`) to clone that exact entity with zero name/tag ambiguity. --- # Input > Keyboard, mouse, touch, gestures and virtual joystick input in Vaelis. ## Keyboard `input.keyDown(code)` is true while a key is held. `input.keyPressed(code)` is a one-frame pulse. Browser-style codes include `ArrowLeft`, `ArrowRight`, `KeyA`, `Space` and the special code `Any`. ``` function onUpdate() { var speed = 200 * time.deltaTime; if (input.keyDown("ArrowRight") || input.keyDown("KeyD")) this.x += speed; if (input.keyDown("ArrowLeft") || input.keyDown("KeyA")) this.x -= speed; if (input.keyPressed("Space")) { this.controller.simulateJump(); // one-frame pulse — fires once per press, not every frame held } } ``` ## Mouse | API | Semantics | | --- | --- | | mouse.x / mouse.y | World-space cursor position. | | mouse.screenX / mouse.screenY | Raw canvas-pixel cursor position. | | mouse.down(button) | Held button; 0 left, 1 middle, 2 right. | | mouse.pressed(button) | Pressed this frame. | | mouse.released(button) | Released this frame. | | mouse.isOver(target) | Shape-accurate entity hit test. | | mouse.clickedOn(target) | Hit test + pressed pulse. | ``` function onUpdate() { if (mouse.clickedOn(this.name)) { this.destroy(); // click this entity to pop it } // or, from inside the entity’s own script: if (this.isClicked) { this.sprite.opacity = 0.5; } } ``` ## Touch The global `touch` surface is array-like. Each active touch has `id`, world/screen coordinates, start coordinates, `dx`, `dy`, `distance`, `justStarted` and `justEnded`. ``` function onUpdate() { for (var t of touch) { if (t.justStarted) { debug.log("Touch " + t.id, t.x + ", " + t.y); } } if (touch.tappedOn(this.name)) { this.spawn("Explosion", { x: this.x, y: this.y }); } } ``` ## Gestures | Gesture | Properties | | --- | --- | | touch.swipe | active, direction, dx, dy, distance; active after >40 px movement. | | touch.pinch | active, scale, delta, distance for two-finger gestures. | ``` function onUpdate() { if (touch.swipe.active && touch.swipe.direction === "left") { scene.load("NextLevel"); } if (touch.pinch.active) { this.camera.zoom *= touch.pinch.scale; // pinch-to-zoom } } ``` ## Virtual joysticks The Joystick component exposes normalized read-only `x`, `y`, `magnitude`, `angle` and `active` values. This works well with Car controllers and custom movement scripts. ``` // Script attached to an entity with a Joystick component: function onUpdate() { if (this.joystick.active) { this.controller.simulateMove(this.joystick.x, this.joystick.y); } } ``` --- # Physics & navigation scripting > Use Rigidbody2D, Collider2D, raycasts and NavWorld2D from game scripts. ## Physics raycasts ``` const hit = physics.raycast(this.x, this.y, target.x, target.y, { exclude: [this], layerMask: physics.layer(2, 3), debug: true }); if (hit) { debug.log("Hit", hit.entity.name); } ``` ## Raycast results A hit returns `{ entity, point, normal, distance }`. The entity is a live script context; point and normal are world-space vectors. Triggers are skipped by raycasts. ## Navigation ``` const path = nav.findPath(this.x, this.y, target.x, target.y, { radius: this.navAgent.radius, debug: true }); ``` ## One-line agent steering Entities with NavAgent2D gain `navMoveToward(targetX,targetY,speed,opts)`. Car + NavAgent entities additionally gain `navDriveToward()` for path-following, avoidance and car steering/drift behavior. ## Physics body choice Choose the body type based on ownership of movement: Dynamic for solver-driven motion, Kinematic for script/controller-driven collision-resolved movement, Static for fixed geometry. --- # Collisions & triggers > onCollisionEnter/Stay/Exit, onTriggerEnter/Exit, the other parameter, and physics layers from script. ## Requirements Collision and trigger callbacks need a Collider2D on the entity receiving the callback (a Rigidbody2D is not strictly required — a collider with no rigidbody is treated as static, matching how Unity handles a collider-only object). ## The other parameter `other` in every collision/trigger callback is an EntityContext — the exact same shape as `this`. You can read `other.x`, `other.name`, call `other.hasComponent(...)`, or even `other.destroy()`. ## Enter vs. Stay vs. Exit ``` function onCollisionEnter(other) { if (other.name === "Ground") this.isGrounded = true; } function onCollisionExit(other) { if (other.name === "Ground") this.isGrounded = false; } ``` `onCollisionStay(other)` fires every physics step the collider remains touching — from the step after Enter, up to (not including) the step Exit fires. Use Stay sparingly for continuous effects (e.g. damage-over-time while standing in a hazard); use Enter/Exit for one-shot state changes. ## Triggers A collider with `isTrigger: true` detects overlap without physically blocking movement, and fires `onTriggerEnter`/`onTriggerExit` instead of the collision events: ``` function onTriggerEnter(other) { if (other.hasComponent("Rigidbody2D")) { scene.load("Level2"); } } ``` ## Physics layers Collider2D’s `layer`/`mask` fields (16 named layers, same slot-based model as Unity) control which pairs of colliders physically interact and receive callbacks at all. Two colliders only interact if each one’s membership layer is included in the other’s mask — see Collider2D for the full bitmask reference and `physics.layer(...)` for building a mask from script. --- # Pathfinding & NavWorld2D > navMoveToward, nav.findPath, named areas and per-area cost, and multi-agent avoidance. ## What navigation is in Vaelis Vaelis navigation is a shared 2D grid system. A scene normally contains one NavWorld2D, while NavAgent2D components query that world using agent-specific radius, area restrictions, costs, path refresh timing, and avoidance settings. > **Need the whole workflow?:** Read Navigation: complete setup for the complete editor + scripting + tuning flow. ## Quickest working path ``` function onUpdate(dt) { var target = findFirst("Target"); if (target) this.navMoveToward(target.x, target.y, 120); } ``` This requires a NavWorld2D in the scene and, for useful per-agent clearance/settings, a NavAgent2D on the moving entity. ## Manual path query ``` var path = nav.findPath(this.x, this.y, 800, 300, { radius: 16, area: nav.areaMask("Ground", "Road"), areaCosts: nav.areaCosts({ Mud: 4, Road: 1 }), debug: true }); ``` The result is an array of world-space `{x,y}` waypoints or `null` when no route is available. ## Cars For a Car-type CharacterController with NavAgent2D, use `this.navDriveToward(targetX, targetY, speed, opts)`. It adds vehicle-oriented braking, steering, lookahead, and recovery behavior rather than pretending a car is a walking agent. ## Area rules worth remembering | Tool | Use it for | | --- | --- | | `nav.areaMask("Road", "Ground")` | Hard permission: route may only cross named areas in the mask. | | `nav.areaCosts({ Road: 1, Mud: 4 })` | Soft preference: both areas remain legal, but Mud becomes more expensive. | | `NavAgent2D.radius` | Per-agent clearance; larger agents can be blocked by corridors smaller agents can use. | --- # Navigation: complete setup > Build, paint, name, script, tune, debug, and ship a complete Vaelis navigation setup without skipping the hard parts. ## The complete model: five pieces, one pipeline Vaelis navigation is easiest to understand as a pipeline rather than as one button. A scene normally has **one shared NavWorld2D**; the NavWorld stores the base walkability grid, each NavAgent2D supplies per-agent size/restrictions, and script movement consumes the resulting path. Static Collider2D geometry→NavWorld2D bake / paint→Area mask + costs→Agent radius→A\* path→Agent steering / avoidance > **Important distinction:** The navigation grid answers “which route is possible?” while avoidance answers “how should this agent steer around nearby agents/obstacles?” Do not try to solve both by constantly rebaking the world. ## End-to-end setup: from empty scene to moving NPC ### Goal: make one NPC walk around walls to the target 1 **Create the navigation world.** In the editor top menu, open GameObject → 2D Object → Nav World 2D. Select the new Nav World 2D entity in the Hierarchy; its fields appear in the right-side Inspector under **Nav World 2D**. 2 **Set the navigation rectangle.** In the Inspector, edit `Bounds X`, `Bounds Y`, `Bounds Width`, and `Bounds Height`. The bounds define the grid region; they do not move the entity's Transform by themselves. 3 **Choose Cell Size.** Smaller values give finer obstacle detail but create more cells. Start around `32` world units, then reduce it only when a corridor or obstacle genuinely needs more resolution. 4 **Make walls real navigation obstacles.** Give the walls a **Collider2D** and, for baked/static geometry, leave the Rigidbody absent or Static. Triggers and Dynamic/Kinematic rigidbodies are not treated as baked obstacles. 5 **Bake.** In the selected Nav World 2D Inspector use **Bake Nav World** after the static geometry is ready. The runtime API equivalent is `nav.bake()`. Most games bake in the editor once. 6 **Inspect the result.** When a Nav World exists, the top-center editor toolbar gains the navigation tools. Use the Bounds view to see the overall rectangle cheaply, then the Cells view for detailed walkability. 7 **Manually fix special cells.** Press U for the Walkable brush, I for the Blocked brush, and O for the Area brush. Normal click paints; **Alt+click** clears that override. The `−`/`+` brush buttons beside the nav display controls reduce/increase the brush radius. 8 **Add the agent.** Select the NPC in the Hierarchy and use Inspector → Add Component → Nav Agent 2D. Start with `Radius 16`, `Speed 120`, `Auto Repath ON`, and the default area mask. 9 **Attach the movement script.** On the NPC's Script component, use the following minimal loop: ``` function onUpdate(dt) { var target = findFirst("Target"); if (!target) return; this.navMoveToward(target.x, target.y, 120, { repathInterval: 0.25, finalArriveDist: 12, debug: true }); } ``` > **What should happen:** The NPC requests a path, advances through the returned waypoints, periodically rechecks the target, and stops inside the final arrival radius. The green debug path appears for a frame when debug:true is used and the debug overlay is visible. ## Every navigation editor control, in context | Control | Where it appears | What it does | Increase / decrease behavior | | --- | --- | --- | --- | | `Nav World 2D` | GameObject → 2D Object → Nav World 2D | Adds the shared navigation grid component/entity. | One shared world per scene is the normal design. | | `Bounds X / Y` | Right Inspector → Nav World 2D | Moves the grid rectangle relative to the Nav World entity. | Larger positive/negative values shift the grid rectangle; they do not resize it. | | `Bounds W / H` | Right Inspector → Nav World 2D | Controls navigation coverage. | Larger = larger navigable region and more cells; smaller = less coverage. | | `Cell Size` | Right Inspector → Nav World 2D | Controls grid resolution. | Smaller = more precise/narrower features represented, more cells/work. Larger = cheaper, but narrow geometry may disappear into one cell. | | `Bake Nav World` | Right Inspector → Nav World 2D | Reads eligible Collider2D geometry and produces the base walkability grid. | Run after changing static obstacles unless Dynamic mode is being used. | | `Dynamic` | Right Inspector → Nav World 2D | Enables automatic rebaking when bake-relevant static geometry changes. | ON = convenience for runtime-changing static-like geometry; OFF = avoid rebake work for mostly-static levels. | | `Allow Diagonal` | Right Inspector → Nav World 2D | Controls whether A\* may use diagonal grid neighbors. | OFF = 4-neighbor grid; ON = diagonals become valid route steps. | | `U` Walkable | Top editor toolbar; only after Nav World 2D exists | Paints an explicit walkable override. | Brush size is controlled by the nearby `−`/`+` buttons. | | `I` Blocked | Top editor toolbar; only after Nav World 2D exists | Paints an explicit blocked override. | Same brush-size controls and Alt+click erase behavior. | | `O` Area | Top editor toolbar; only after Nav World 2D exists | Paints the selected navigation area onto cells. | Area choice appears beside the brush only while Area mode is active. | | `Edit → Nav Areas…` | Top editor menu Edit | Names the 16 navigation area slots. | Names are used later by `nav.areaMask()` and `nav.areaCosts()`. | | `Bounds / Cells` view buttons | Top toolbar beside nav tools | Switches between cheap bounds visualization and detailed cell visualization. | Cells view is the one to use when diagnosing exact painted/baked coverage. | ## Named areas: hard restrictions vs soft preferences Vaelis exposes 16 navigation-area slots. Name them with Edit → Nav Areas…, then use the names in script instead of memorizing bit positions. ### Hard restriction: Area Mask ``` var allowed = nav.areaMask("Ground", "Road"); var path = nav.findPath(this.x, this.y, 800, 300, { area: allowed, radius: 16 }); ``` An area omitted from the mask is **impassable for that query**. This is different from cost. ### Soft preference: Area Cost ``` var path = nav.findPath(this.x, this.y, 800, 300, { area: nav.areaMask("Ground", "Road", "Mud"), areaCosts: nav.areaCosts({ Road: 0.5, Mud: 4 }) }); ``` Cost changes route preference among allowed areas. A cost of `1` is neutral; a higher value makes that area more expensive; a lower positive value makes it more attractive. Cost does not turn an allowed area into a hard wall. > **Common mistake:** Do not use areaCosts: { Water: 0 } to try to block water. Use nav.areaMask(...) and leave Water out of the mask. ## NavAgent2D tuning: what every major value actually changes | Field | Increase it | Decrease it | Use it when… | | --- | --- | --- | --- | | `radius` | Agent needs wider clearance; narrow passages become unavailable sooner. | Agent can fit through tighter passages. | Different NPC sizes need to share the same NavWorld. | | `speed` | Higher top movement speed. | Slower movement. | Simple traversal pacing. | | `acceleration` | Reaches the requested speed faster. | Softer/slower speed changes. | Making movement feel snappy vs floaty. | | `deceleration` | Stops more quickly. | Longer, softer stopping. | Preventing overshoot near goals. | | `stoppingDistance` | Agent intentionally stops farther away. | Agent gets closer to target. | Enemies should keep melee/shooting distance. | | `repathInterval` | Fewer route checks; cheaper. | More frequent route checks; more responsive and more expensive. | Balancing moving-target responsiveness vs CPU work. | | `repathDistance` | Target must move farther before a re-path is triggered. | Target motion triggers re-path sooner. | Fast-moving targets. | | `avoidancePriority` | Higher priority means the agent is treated as more important in avoidance decisions. | Lower priority makes it more willing to yield. | Mixed-priority crowds or special NPCs. | | `area` | Add area bits to permit additional terrain categories. | Remove bits to forbid categories. | Making a route legally impossible through a terrain class. | ## Complete car / road navigation flow Vehicle navigation is not simply “walk an NPC path with a car sprite.” Vaelis exposes `this.navDriveToward()` specifically for Car-type CharacterController movement and the NavAgent2D vehicle tuning fields. 1 Make the road surface part of the NavWorld and name it, for example, `Road`. Use another area such as `Ground` for ordinary terrain. 2 Add **Nav Agent 2D** to the car. Set `collabEnabled` or avoidance only when you actually need those behaviors. 3 Use `nav.areaMask("Road")` when the car must stay on roads. Use a wider mask if road-only routing is too restrictive. 4 Drive toward the destination: ``` function onUpdate(dt) { var target = findFirst("Destination"); if (!target) return; this.navDriveToward(target.x, target.y, 220, { repathInterval: 0.2, arriveDist: 8, finalArriveDist: 18, debug: true }); } ``` For road-vs-ground preference, allow both and use costs instead of a hard mask: ``` var path = nav.findPath(this.x, this.y, target.x, target.y, { area: nav.areaMask("Road", "Ground"), areaCosts: nav.areaCosts({ Ground: 3, Road: 1 }) }); ``` > **Tuning order for vehicles:** First make the NavWorld route correct. Then tune agent radius. Then tune speed/acceleration/deceleration. Only after that adjust the vehicle lookahead/smoothing/braking fields. This separates route problems from steering problems. ## When to use Dynamic Turn on **Dynamic** only when bake-relevant static geometry can actually change during play. The runtime checks a cheap collider signature and rebakes when the signature changes; it does not blindly rebake the entire world every frame. Dynamic navigation still has a real rebake cost when qualifying geometry changes. ``` // Procedural level example: after spawning a new static obstacle var result = nav.bake(); if (result) debug.log("Nav rebuilt: " + result.walkable + " walkable, " + result.blocked + " blocked"); ``` ## Navigation debugging checklist **1.** Is a Nav World 2D actually present in the scene? **2.** Are the walls using Collider2D and eligible for baking? **3.** Did you bake after editing static geometry? **4.** Does Cells view show the corridor as walkable? **5.** Is the agent radius too large for that corridor? **6.** Is the Area Mask accidentally excluding the only available route? **7.** Are you confusing area cost with a hard restriction? **8.** Is your target inside the NavWorld bounds or at least near a walkable cell? **9.** Is the script calling the correct method for the movement type (`navMoveToward` vs `navDriveToward`)? **10.** Turn on `debug:true` and make the debug overlay visible to inspect the actual route. ## LLM/code-generation rule When generating navigation code, preserve this dependency order: **NavWorld2D → walkability/bake → named areas → NavAgent2D → script movement → tuning**. Do not invent properties such as `destination`, `setDestination`, or a Unity/Godot class when Vaelis's documented API is `this.navMoveToward()`, `nav.findPath()`, and `this.navAgent.*`. --- # State & messaging > Build lightweight state machines and decoupled entity communication. ## State machine Every entity gets `this.state` without a dedicated component. `current` starts as `"default"`; `previous` is the state before the last transition. `change(name)` is a no-op when the name is already current. ## State callbacks ``` function onStateEnter() { if (this.state.current === "chasing") { this.animator.play("Run"); } } function onStateUpdate(dt) { if (this.state.current === "chasing") { // chase logic } } ``` ## Messages ``` function onStart() { sendMessage("Enemy", "takeDamage", { amount: 10 }); } function onMessage(message, data) { if (message === "takeDamage") { this.hp -= data.amount; } } ``` ## When to use messages Messaging is useful when entities should react to an event without knowing another entity’s exact implementation. Use `findById`/`sendMessage(entity,...)` when you need one exact target; use a tag when you intentionally want a group. --- # Timers, state & messaging > wait()/repeat() timers, the built-in this.state machine, and sendMessage/broadcastMessage. ## Timers Timers run on game time, so [`time.scale`](time-scale.html) speeds them up, slows them down or freezes them. To animate a property over time use [`tween()`](tween.html) instead of hand-written timers. | API | Meaning | | --- | --- | | wait(seconds, callback) | Runs callback once after seconds of game time. this inside the callback is the same entity that called wait(). Returns a timer id for cancelWait(id). Also available as this.wait(...). | | repeat(seconds, callback) | Runs callback every seconds, forever, until cancelled, the entity is destroyed, or the scene restarts/switches. The first call happens seconds from now, then every seconds after. | | cancelWait(id) / cancelRepeat(id) | Stop a pending timer before it fires. Safe to call with an id that already fired or was already cancelled. | > **Timers are entity-owned:** Timers are automatically cancelled if their entity is destroyed, or if the scene restarts/switches before they fire — a wait() never fires "late" against a scene that’s already gone. ## State machine `this.state` needs no component — it works on every entity automatically. `this.state.current`/`this.state.previous` give the current/previous state name (current defaults to `"default"`). `this.state.change(name)` fires `onStateExit()` for the outgoing state, then `onStateEnter()` for the new one. ``` function onUpdate() { if (this.isGrounded && this.state.current !== "idle") { this.state.change("idle"); } } function onStateEnter() { if (this.state.current === "idle") this.animator.play("Idle"); if (this.state.previous === "jump") debug.log("Landed!", ""); } ``` ## Messaging `sendMessage(tagOrEntity, message, data)` accepts either a tag string (messages every entity with that tag — a group broadcast) or an EntityContext directly (messages that one exact entity, unambiguous even if others share its name/tag). `broadcastMessage(message, data)` sends to every scene entity. ``` function onCollisionEnter(other) { sendMessage("Enemy", "targetNearby", { x: this.x, y: this.y }); } function onMessage(message, sender, data) { if (message === "targetNearby") { this.navMoveToward(data.x, data.y, 80); } } ``` --- # Persistence > Use transient global state and durable IndexedDB saves. ## global vs save | Surface | Lifetime | | --- | --- | | global | Transient cross-script state for the current play session/page. Refreshing the page clears it. | | save | Persistent per-slot key/value storage backed by IndexedDB. Survives refresh/reopen when browser storage is available. | ## Basic save API ``` save.set("score", 1250); const score = save.get("score"); if (!save.has("tutorialSeen")) { save.set("tutorialSeen", true); } ``` ## Multiple save slots ``` await save.load("slot2"); const hp = save.get("targetHp"); const slots = await save.listSlots(); ``` ## Flush before a transition ``` async function onGameComplete() { save.set("completed", true); await save.flushNow(); scene.load("Credits"); } ``` ## Storage errors `save.set()` updates the in-memory value synchronously while IndexedDB writes happen in the background. Register `save.onError(fn)` to observe persistent-storage failures such as quota errors or unavailable IndexedDB implementations. --- # Save data > The save global: get/set/delete, save slots, and flushing writes. ## Overview `save` is a global backed by IndexedDB — the way to make a game remember things across page refreshes and browser restarts, unlike `global` (see Timers, state & messaging), which resets on every reload. ## Basic reads and writes ``` save.set("highScore", 4200); var best = save.get("highScore") ?? 0; save.has("checkpoint"); save.delete("temporaryBuff"); save.keys(); // every key currently stored save.clear(); // wipe the current slot ``` ## Save slots ``` await save.load("slot2"); // switch to a different save file save.slot; // the currently active slot name save.listSlots(); save.deleteSlot("slot3"); ``` ## Flushing & readiness `save.isReady` reflects whether the store has finished its initial load from IndexedDB. Writes are coalesced and flushed asynchronously; call `save.flushNow()` if you need a write to be durably committed before doing something else (e.g. right before `scene.load()` on a level transition). `save.onError(callback)` registers a handler for storage failures (e.g. a full or blocked IndexedDB). ## Example: persistent high score ``` function onDestroy() { var best = save.get("highScore") ?? 0; if (global.score > best) save.set("highScore", global.score); } ``` --- # Errors & debugging > How script errors are classified and reported, and the on-screen debug HUD. ## How errors are reported A thrown error inside one lifecycle call is caught right there and reported to the editor Console — it does not disable the whole script (except `onStart`, which only ever runs once). Identical errors repeating every frame are throttled: reported immediately once, then suppressed and periodically summarized with a repeat count, so a bug in `onUpdate` doesn’t spam the console 60 times a second. ## Error kinds Errors thrown by the scripting API are tagged with a machine-readable `kind` so the Console can show a specific, actionable message instead of a generic "X is not a function": | Kind | Meaning | Example | | --- | --- | --- | | missing-component | Accessed this.rigidbody/.sprite/etc. but the entity does not have that component at all. | this.sprite.opacity on an entity with no Sprite Renderer | | unsupported-body-type | Called a member that does not apply to this entity’s current body/controller type. | this.rigidbody.addForce() on a Kinematic or Static body | | unknown-api | A property or method that does not exist at all — almost always a typo. | this.rigidbody.addFrce() | | script-error | Anything without a kind — a plain script bug (null dereference, bad logic, etc). | — | Every `unknown-api` error also lists the valid member names for that sub-object, so a typo is a one-line fix rather than a trip back to this documentation. ## The on-screen debug HUD ``` debug.show(); // turn the HUD on (visible in the Play window, not the editor console) debug.showFps(false); // keep the HUD on but hide just the FPS line debug.log("Target HP", this.hp); debug.clear("Target HP"); debug.clearAll(); ``` --- # Script API cookbook > Concrete Vaelis script examples with setup, placement, required components, options, expected behavior, and common mistakes. ## How to use the cookbook Every example assumes a **Script** component exists on the entity that owns the code. In the editor, select the entity in the left Hierarchy, then use the right Inspector to open its **Script** component. Paste the example into the script's lifecycle function or adapt it to your existing script. > **Read API reference + recipe together:** The API reference tells you what a function/property means. The recipes show when to call it, what object should own the script, and what other setup the feature needs. ## 1. Find an entity and move toward it ### Setup Create an entity named `Target`. Put this script on the enemy. ### Code ``` function onUpdate(dt) { var target = findFirst("Target"); if (!target) return; this.navMoveToward(target.x, target.y, 140); } ``` `findFirst(name)` returns one matching entity or `null`. `navMoveToward()` supplies the navigation movement behavior. ## 2. Spawn a runtime clone Author a source entity in the scene first, for example an entity named `Bullet`. The script below can live on a target, weapon, or spawner. ``` var bullet = spawn("Bullet", { x: this.x + 24, y: this.y, name: "Bullet_Instance" }); if (bullet) { bullet.velocityX = 500; } ``` > **Why the source entity matters:** spawn() clones an existing authored entity. It is not a constructor that invents a new component set from scratch. ## 3. Raycast toward an entity Put this on the entity performing the vision/sensor check. ``` function onUpdate(dt) { var target = findFirst("Target"); if (!target) return; var hit = physics.raycast(this.x, this.y, target.x, target.y, { layerMask: 1 << 0, exclude: [this], debug: true }); this.hasLineOfSight = !hit || hit.entity === target; } ``` The result is either a hit object containing `entity`, `point`, `normal`, and `distance`, or a falsy result when nothing is hit. ## 4. Send an event without hard-coding the receiver's logic ``` // Sender var enemy = findFirst("Enemy"); if (enemy) sendMessage(enemy, "takeDamage", { amount: 25 }); // Receiver function onMessage(message, sender, data) { if (message === "takeDamage") { this.hp -= data.amount; } } ``` Use an EntityContext when you need exactly one receiver. Use a tag string when you intentionally want a group to receive the same message. ## 5. Keyboard movement with frame-independent speed ``` function onUpdate(dt) { var dx = 0; var dy = 0; if (input.keyDown("ArrowLeft")) dx -= 1; if (input.keyDown("ArrowRight")) dx += 1; if (input.keyDown("ArrowUp")) dy -= 1; if (input.keyDown("ArrowDown")) dy += 1; var length = Math.hypot(dx, dy); if (length > 0) { dx /= length; dy /= length; this.x += dx * 220 * dt; this.y += dy * 220 * dt; } } ``` This is useful for simple non-physics entities. Use Rigidbody2D/CharacterController APIs when movement is supposed to participate in physics/controller resolution. ## 6. Delay work without hand-written countdown variables ``` function onStart() { this.wait(1.5, function () { this.sprite.opacity = 0.4; }); this.repeat(2, function () { debug.log("heartbeat"); }); } ``` Entity-owned timers are automatically cancelled when the scheduling entity is destroyed or the scene changes. ## 7. Persistent save data ``` function onStart() { this.hp = save.get("targetHp") ?? 100; } function onCheckpointReached() { save.set("targetHp", this.hp); save.set("checkpoint", { x: this.x, y: this.y }); } async function onGameComplete() { save.set("completed", true); await save.flushNow(); scene.load("Credits"); } ``` > **Important:** save.set() updates the in-memory save immediately. Use await save.flushNow() when the next action must wait for durable storage before continuing. ## 8. Ask the navigation system for a path ``` var path = nav.findPath(this.x, this.y, goalX, goalY, { radius: this.navAgent.radius, area: nav.areaMask("Ground", "Road"), areaCosts: nav.areaCosts({ Road: 1, Mud: 4 }), debug: true }); if (path) { debug.log("Waypoints: " + path.length); } ``` This example demonstrates four separate concepts: agent clearance, hard area permission, soft area preference, and debug visualization. ## 9. Change a NavAgent2D at runtime Select the moving entity and add **Nav Agent 2D** in Inspector → Add Component → Nav Agent 2D. The exposed script properties are read/write. ``` this.navAgent.speed = 180; this.navAgent.radius = 12; this.navAgent.avoidanceEnabled = true; this.navAgent.repathInterval = 0.2; // Read-only current route state: var path = this.navAgent.currentPath; var index = this.navAgent.currentPathIndex; ``` > **Read-only fields:** currentPath and currentPathIndex are managed by navMoveToward() . Do not assign to them; call this.navMoveToward(newX,newY,...) to change the destination. ## 10. Use named navigation areas instead of raw bitmasks First name the slots in Edit → Nav Areas…. For example: `Ground`, `Road`, `Mud`, `Water`. ``` var roadOnly = nav.areaMask("Road"); var mixed = nav.areaMask("Road", "Ground"); var waterSlot = nav.areaIndex("Water"); ``` This keeps scripts readable and means you do not have to remember which slot number was assigned to each named area. ## 11. Camera follow ``` function onUpdate(dt) { var target = findFirst("Target"); if (target) { this.camera.follow(target, { smoothing: 0.1 }); } } ``` Put the script on the entity that has the Camera component. The engine template also demonstrates this pattern. ## 12. Switch animations from gameplay state ``` function onUpdate(dt) { if (!this.rigidbody) return; if (!this.rigidbody.grounded) { if (this.rigidbody.velocityY > 0) this.animator.play("fall"); else this.animator.play("Jump"); } else if (Math.abs(this.rigidbody.velocityX) > 5) { this.animator.play("Run"); } else { this.animator.play("Idle"); } } ``` ## 13. Touch / joystick control For a Joystick component, select an entity, then use Inspector → Add Component → Joystick. The script can read normalized values: ``` function onUpdate(dt) { if (!this.joystick || !this.joystick.active) return; this.controller.simulateMove(this.joystick.x, this.joystick.y); } ``` `x` and `y` are normalized joystick axes; `magnitude` tells you how far the thumb is displaced. ## 14. Trigger a scene change on overlap Give the portal entity a **Collider2D** and enable its **Is Trigger** checkbox in the right Inspector. ``` function onTriggerEnter(other) { if (other.name === "Target") { scene.load("Level2"); } } ``` Trigger callbacks depend on Collider2D overlap. A trigger does not behave like a solid blocking collider. ## 15. Build your own tiny diagnostic HUD ``` function onUpdate(dt) { debug.log( "pos=" + Math.round(this.x) + "," + Math.round(this.y) + " speed=" + Math.round(this.navAgent ? this.navAgent.speed : 0) ); } ``` Use this while developing, then remove or gate noisy logging before a final release. ## Patterns that scale well | Need | Prefer | Avoid | | --- | --- | --- | | Exact entity | `findById()` or a known EntityContext | Assuming a shared name is unique when it is not. | | Group communication | Tag + `sendMessage()` | Duplicating the same lookup in every receiver. | | Persistent data | `save.*` | Using `global.*` for data that must survive reload. | | Pathfinding | One NavWorld2D + NavAgent2D per mover | Creating a navigation world per NPC. | | Physics movement | Rigidbody2D / CharacterController APIs | Directly changing `x/y` when you need collision resolution. | | Frame-independent custom movement | Multiply speed by `dt` | Using a raw pixels-per-frame constant. | ## Where to go next ### Complete Navigation [Full editor-to-runtime navigation setup, areas, costs, vehicles and debugging.](./navigation-complete.html) ### Option schemas [Exact `opts` objects, defaults, types and override rules.](../api/options.html) ### Component reference [Every component and its editor/runtime contract.](../api/index.html) --- # API reference > Vaelis 1.0.0 component and scripting API reference. > **Need to know what must exist first?:** Use the API requirements & complete usage map to see prerequisites for every global and component API. **API surface:**  component references document scene data and the intentionally exposed script surface. Global runtime modules are in [Runtime modules](runtime.html). ## Components [**Transform**Position, rotation and scale. Every spatial entity uses a Transform.](components/transform.html)[**SpriteRenderer**Draw a 2D texture sprite for an entity.](components/spriterenderer.html)[**ShapeRenderer**Draw a procedural 2D shape without requiring a sprite asset.](components/shaperenderer.html)[**TextRenderer**Render text either in world space or as screen-space UI.](components/textrenderer.html)[**StrokePath**A variable-thickness strip along placed points — rivers, cables, roads, conveyor belts or walls — with flat color or textured fill.](components/strokepath.html)[**SpeechBubble**Speech bubble UI attached to an entity, useful for dialogue and NPC callouts.](components/speechbubble.html)[**ChatLog**Scrollable-style conversation log component for UI dialogue.](components/chatlog.html)[**TextInput**Interactive text input control driven by the runtime UI system.](components/textinput.html)[**Joystick**Virtual touch joystick for mobile and pointer-driven control schemes.](components/joystick.html)[**Rigidbody2D**2D physics body backed by the engine physics runtime. Dynamic, Kinematic and Static bodies have different script controls.](components/rigidbody2d.html)[**Collider2D**Physics collision shape and contact filtering. A Collider2D is also required for accurate pointer/touch hit tests.](components/collider2d.html)[**Joint2D**Connect physics bodies with Fixed, Revolute, Prismatic, Rope or Spring constraints.](components/joint2d.html)[**CharacterController**High-level movement modes: Character Controller, Platformer, Top-Down, Car, Follow, Patrol and Free.](components/charactercontroller.html)[**SpriteAnimation**Sprite-sheet/clip animation state on a SpriteRenderer.](components/spriteanimation.html)[**Camera**Orthographic 2D camera with reference resolutions, responsive scaling, follow, shake and optional pseudo-3D sprite depth scaling.](components/camera.html)[**AudioSource**Play a local audio asset, optionally with distance-based 3D attenuation.](components/audiosource.html)[**AudioListener**Defines the hearing area for 3D audio and drives audio enter/leave callbacks.](components/audiolistener.html)[**Light**2D light source supporting Directional, Point, Spot, Area, GodRays and Freeform light shapes.](components/light.html)[**ShadowCaster**Marks an entity as a shadow occluder for the lighting system.](components/shadowcaster.html)[**LightingSettings**Scene-wide lighting quality and mood controls. Attach to one entity; the lighting system reads it scene-wide.](components/lightingsettings.html)[**NavAgent2D**Per-agent navigation settings and current path state for NavWorld2D pathfinding.](components/navagent2d.html)[**NavWorld2D**Shared navigation world for baked or dynamic 2D pathfinding, with 16 navigation areas.](components/navworld2d.html)[**Tileset**Defines a reusable 16-role autotile set. The editor can auto-slice one image or accept separate role images.](components/tileset.html)[**Tilemap**Sparse painted tile grid that references a Tileset entity by ID.](components/tilemap.html)[**Script**Script component holding a script name, source and enabled state.](components/script.html) ## Script reference rules Use `this` for the current entity and global modules for scene-wide services. Conditional component modules are available only when that component exists on the entity. Unsupported/unknown properties are surfaced as runtime API errors rather than silently creating arbitrary engine fields. --- # Runtime modules > Vaelis 1.0.0 global scripting and runtime module reference. > **Need to know what must exist first?:** Use the API requirements & complete usage map to see prerequisites for every global and component API. ## Global runtime API | Module/function | Summary | | --- | --- | | `findFirst(name)` | Find the first entity by name. | | `findAll(name)` | Find all entities by name. | | `findById(id)` | Find one exact entity by stable ID. | | `findWithTag(tag)` | Find all entities with a tag. | | `findInRadius(x,y,radius,opts)` | Find nearby entities, nearest first. | | `scene` | Scene lookup, loading, restart, pause/resume and lighting. | | `physics` | Raycasts and collision-layer masks. | | `nav` | Pathfinding, walkability and navigation area utilities. | | `input` | Keyboard held/pressed state. | | `mouse` | Cursor position, button state and shape-accurate hit tests. | | `touch` | Multitouch state plus swipe/pinch gestures. | | `time` | Frame delta and elapsed game time. | | `random` | Random integers/floats. | | `mathx` | Gameplay math helpers. | | `global` | Transient cross-script state. | | `save` | Persistent per-slot IndexedDB state. | | `debug` | On-screen debugging HUD/logging. | | `spawn()` | Clone authored entities at runtime. | | `wait()/repeat()` | Entity-owned timers. | | `sendMessage()` | Targeted or tag-group messaging. | | `broadcastMessage()` | Scene-wide message broadcast. | ## Fixed update `onFixedUpdate(dt)` is driven at a fixed 60 Hz accumulator. Keep physics-step decisions here when deterministic cadence matters; use `onUpdate(dt)` for per-render-frame behavior. ## Coordinate spaces Entity positions, mouse world coordinates, touch world coordinates and raycast points share the game world’s 2D coordinate space. Screen coordinates (`screenX/screenY`) are raw canvas pixels. Camera reference resolutions are separate from world units. --- # this (EntityContext) reference > Every this.* sub-object reachable inside a script, its required component, and its exact members. > **Need to know what must exist first?:** Use the API requirements & complete usage map to see prerequisites for every global and component API. ## Scope This page lists every sub-object reachable from `this` inside a script, and what each requires. For the flat shortcuts (`this.x`, `this.position`, etc.) and the lookup/lifecycle helpers (`this.destroy()`, `this.hasComponent()`, `this.isClone`), see Entity shortcuts — this page covers only the per-component sub-objects. > **Typed errors, not undefined:** Every sub-object below throws a clear, typed error (see Errors & debugging) if accessed on an entity missing the required component, and throws a distinct error on an unknown member name (a typo) rather than returning undefined. ## this.transform Requires: nothing (every entity has one). Mirrors the flat shortcuts as an object: `position {x,y}`, `rotation`, `scale {x,y}`, `translate(dx, dy)`, `lookAt(x, y)` (rotates to face a point). ## this.rigidbody Requires: Rigidbody2D. The exposed shape depends on the body’s current `bodyType` (Dynamic / Kinematic / Static) — checked live on every access, so changing `bodyType` at runtime is reflected immediately. | Member | Dynamic | Kinematic | Static | | --- | --- | --- | --- | | velocity, velocityX, velocityY | ✓ | ✓ (drives movement) | — | | mass, gravityScale, linearDamping, angularDamping | ✓ | — | — | | addForce(x,y), addImpulse(x,y), addTorque(t), addAngularImpulse(t) | ✓ | — | — | | move(dx, dy) | — | ✓ | — | | isGrounded, isOnCeiling, isOnWall, isOnSlope, groundAngle | ✓ | ✓ | — | ``` // Dynamic body — apply forces: function onUpdate() { if (input.keyPressed("Space") && this.rigidbody.isGrounded) { this.rigidbody.addImpulse(0, -400); } } // Kinematic body — drive movement directly: function onUpdate() { this.rigidbody.move(50 * time.deltaTime, 0); } ``` See Rigidbody2D for what each field means physically. ## this.controller Requires: CharacterController. Shape depends on `controllerType`. Shared across the walk-family types (Character/Platformer/Top-Down): `moveSpeed`, `acceleration`, `airControl`, `canJump`, `jumpForce`, `maxJumps`, `simulateMove(x,y)`, `simulateJump()`, `isGrounded`/`isOnCeiling`/`isOnWall`/`isOnSlope`/`groundAngle`. Car adds `maxSpeed`, `brakeForce`, `turnSpeed`, `driftFactor`, `simulateDrive(throttle, steer)`, `simulateDriveJoystick(x,y)`, `simulateDriveToward(x,y)`. Follow adds `targetName`, `followSpeed`, `followDistance`. Patrol adds `patrolMode`, `patrolAxis`, `patrolDistance`, `flipDirection()`, `facingDirection`. ## this.collider Requires: Collider2D. Read-mostly: `shape`, `width`, `height`, `radius`, `offset {x,y}`, `isTrigger`, `isOneWayPlatform`, `friction`, `restitution`, `density`, `layer`, `mask`, and the read-only `isColliding` contact state. ## this.sprite / this.shape / this.text Requires SpriteRenderer, ShapeRenderer or TextRenderer respectively. See each component’s own reference page for the exact field list — the object shape mirrors the component data one-to-one. ## this.strokePath, this.speechBubble, this.chat, this.textInput, this.joystick Each requires its matching component (StrokePath, SpeechBubble, ChatLog, TextInput, Joystick) and mirrors that component’s script API — see the component’s own reference page. ## this.animator, this.camera, this.audio, this.ear, this.joint, this.navAgent, this.light, this.shadowCaster Each requires SpriteAnimation, Camera, AudioSource, AudioListener, Joint2D, NavAgent2D, Light or ShadowCaster respectively, and exposes that component’s documented script API. --- # Option schemas & opts > Exact option objects, types, defaults and semantics for the most important Vaelis APIs, with machine-readable JSON for tooling and LLMs. > **Need to know what must exist first?:** Use the API requirements & complete usage map to see prerequisites for every global and component API. > **Hands-on examples:** See the Script API cookbook for complete scripts showing where each API lives and how the pieces fit together. > **Authoritative option metadata:** Navigation option names are defined once in runtime/scripting/NavAPI.js and consumed by both runtime behavior and editor IntelliSense. The machine-readable api-options.json mirrors the documented public option groups. ## nav.findPath | Option | Type | Default | Effect | | --- | --- | --- | --- | | `debug` | boolean | False | Draw the current path as green debug segments for one frame. | | `radius` | number | 0 | Agent clearance against the shared NavWorld2D. Larger radius can close narrow passages. | | `area` | number | 65535 | 16-bit allowed-area mask. Default 0xffff allows every area. | | `areaCosts` | number[]|null | None | Per-call 16-slot cost overrides; null entries use NavWorld2D defaults. | ## this.navMoveToward | Option | Type | Default | Effect | | --- | --- | --- | --- | | `repathInterval` | number | 0.35 | Seconds between re-path checks when autoRepath is enabled. | | `arriveDist` | number | 4 | Distance at which an intermediate waypoint is considered reached. | | `finalArriveDist` | number | 1 | Distance from final target considered arrived. | | `targetChangeDistance` | number | 4 | Target movement that forces an immediate re-path; effective default is max(4, arriveDist). | | `debug` | boolean | False | Draw the current path as green debug segments for one frame. | ## this.navDriveToward | Option | Type | Default | Effect | | --- | --- | --- | --- | | `repathInterval` | number | 0.35 | Seconds between re-path checks when autoRepath is enabled. | | `arriveDist` | number | 4 | Distance at which an intermediate waypoint is considered reached. | | `finalArriveDist` | number | 1 | Distance from final target considered arrived. | | `targetChangeDistance` | number | 4 | Target movement that forces an immediate re-path; effective default is max(4, arriveDist). | | `debug` | boolean | False | Draw the current path as green debug segments for one frame. | ## findInRadius | Option | Type | Default | Effect | | --- | --- | --- | --- | | `name` | string|undefined | None | Only return entities with this exact name. | | `tag` | string|undefined | None | Only return entities with this exact tag when name is not provided. | ## spawn | Option | Type | Default | Effect | | --- | --- | --- | --- | | `x` | number|undefined | source x | Spawn position X override. | | `y` | number|undefined | source y | Spawn position Y override. | | `name` | string|undefined | source name | Rename the clone. | | `byTag` | boolean | False | Interpret the first argument as a tag instead of a name. | ## physics.raycast | Option | Type | Default | Effect | | --- | --- | --- | --- | | `layerMask` | number|undefined | engine default | Restrict ray hits to collider layers included in the mask. | | `debug` | boolean | False | Draw the ray debug line for one frame. | | `exclude` | array|undefined | None | Exclude listed entity/entity-context targets from hit testing. | ## mouse.isOver / clickedOn | Option | Type | Default | Effect | | --- | --- | --- | --- | | `byTag` | boolean | False | Interpret the string target as a tag instead of an entity name. | ## touch.isOver / tappedOn | Option | Type | Default | Effect | | --- | --- | --- | --- | | `byTag` | boolean | False | Interpret the string target as a tag instead of an entity name. | | `justStarted` | boolean | False | Only match touches that began this frame. | ## Examples ``` this.navMoveToward(target.x, target.y, 160, { repathInterval: 0.2, arriveDist: 6, finalArriveDist: 12, debug: true, }); const hits = physics.raycast(this.x, this.y, target.x, target.y, { layerMask: 1 << 0, exclude: [this], debug: true, }); ``` ## How `opts` overrides work Vaelis uses options in a few different ways. An explicit option normally wins for that call; otherwise the method uses the component/default value. This matters most for navigation and raycasts. | Pattern | What it means | | --- | --- | | `this.navMoveToward(x,y,160)` | Explicit speed is used for this call; other behavior can come from the NavAgent2D component. | | `this.navMoveToward(x,y,160,{ finalArriveDist: 12 })` | Only `finalArriveDist` changes for this call; unrelated options keep their defaults/component behavior. | | `nav.findPath(...,{ radius: 24 })` | Manual query uses the supplied radius instead of assuming the caller's component radius. | | `physics.raycast(...,{ exclude:[this] })` | The current entity is removed from the query results, preventing self-hits. | > **Do not invent option names.:** Vaelis is not drop-in Unity/Unreal/Godot API compatibility. Use the exact option names documented here and in the editor's IntelliSense. ## Navigation option recipes ### Hard route restriction ``` var route = nav.findPath(this.x, this.y, goalX, goalY, { area: nav.areaMask("Road", "Ground") }); ``` Only named areas in the mask are legal. An omitted area is not a fallback route; it is forbidden. ### Soft route preference ``` var route = nav.findPath(this.x, this.y, goalX, goalY, { area: nav.areaMask("Road", "Ground", "Mud"), areaCosts: nav.areaCosts({ Road: 1, Ground: 2, Mud: 5 }) }); ``` All three areas remain legal, but the pathfinder prefers cheaper traversals when route length is otherwise comparable. ### Per-agent runtime override ``` var costs = this.navAgent.areaCosts || []; costs[2] = 4; this.navAgent.areaCosts = costs; ``` `areaCosts` is an indexed 16-slot array on the component. Assign a new normalized array back to the property; mutating a previously-read temporary is not enough unless you reassign it. ## LLM usage rule When generating Vaelis code, prefer the documented option name and shape exactly as listed. Do not invent Unity/Unreal/Godot option names just because they sound familiar; Vaelis’s runtime and IntelliSense contract is the authority. --- # API requirements & complete usage map > Complete prerequisites and usage map for Vaelis scripting APIs. > **Prerequisites matter.:** Vaelis does not expose every component API on every entity. this.sprite , this.rigidbody , this.navAgent , and the other component sub-objects are created only when the corresponding component exists on that same entity. If the component is absent, the sub-object is undefined . Use this.hasComponent("...") when you need to guard optional behavior. ## Universal component-API workflow 1. Select the entity in the **Hierarchy**. 2. In the **Inspector** on the right, click **Add Component**. 3. Search for the required component and click it. 4. Configure its Inspector properties and any component-specific editor tool that appears. 5. Add a **Script** component to the same entity and open/edit its script. 6. Inside the script, access the matching sub-object, for example `this.rigidbody` or `this.sprite`. 7. Play the scene and inspect the Console if the component is missing or an API call is invalid. ``` // Example: Rigidbody2D is required for this API. function onStart() { if (!this.rigidbody) return; this.rigidbody.velocity = { x: 100, y: 0 }; } ``` ## Global APIs — no component required These are injected into every running game script. They are not added through **Add Component**. - `enabled` - `showFps` - `stats` - `debugLines` - `entity` - `point` - `normal` - `distance` - `findWithTag` - `findFirst` - `findAll` - `findFirstWithTag` - `findAllWithTag` - `findById` - `findInRadius` - `scene` - `physics` - `nav` - `sendMessage` - `broadcastMessage` - `spawn` - `wait` - `cancelWait` - `repeat` - `cancelRepeat` - `input` - `mouse` - `touch` - `time` - `random` - `smoothstep` - `mathx` - `global` - `save` - `debug` | Global family | Required setup | Typical use | | --- | --- | --- | | `scene` | A running scene. | Load/restart/pause/resume scenes and access scene-level services. | | `physics` | Physics runtime for physics queries. | Raycasts and collision-layer/mask operations. | | `nav` | Configured Nav World 2D for meaningful pathfinding. | Find paths, test walkability, use named navigation areas/costs. | | `input`, `mouse`, `touch` | Running game input; touch requires a touch-capable device for actual touch events. | Keyboard, mouse, touch, swipe and pinch controls. | | `time`, `random`, `mathx` | None. | Frame timing, randomness and gameplay math. | | `save` | Browser storage available to the deployment. | Persistent save slots. | | `debug` | Running game/editor debug surface. | Debug messages and visual diagnostics. | | `spawn`, `wait`, `repeat` | Running entity script/runtime. | Runtime clones and entity-owned timers. | | `sendMessage`, `broadcastMessage` | Running scene with target entities when targeting by name/tag. | Script-to-script communication. | ## Component APIs — prerequisites and members | API | Required setup | Public members found in the runtime API module | | --- | --- | --- | | `SpriteAnimation` | Add a Sprite Animation component to the same entity before using this.animator. | `reset, playing, currentClip, currentFrame, totalFrames, speed, it, trap, property, directly` | | `AudioSource` | Add an Audio Source component to the same entity before using this.audio. | `volume, pitch, playing, to, trap, directly` | | `AudioListener` | Add an Audio Listener component to the same entity before using this.ear. | `radius, enabled, sourcesInRange, check` | | `Camera` | Add a Camera component to the same entity before using this.camera. | `zoom, backgroundColor, aspectMode, landscapeWidth, landscapeHeight, portraitWidth, portraitHeight, squareSize, customWidth, customHeight, enablePseudo3D, scalingMode, keepHeight, aspectRatioLock, allowStretching, letterboxing, pillarboxing, barColor, integerScaling, x, y, entity, center, each, offsetX, offsetY, applies, is, that, by, from, the, of` | | `ChatLog` | Add a Chat Log component to the same entity before using this.chat. | `messages, maxMessages, visibleCount, width, lineHeight, fontSize, fontFamily, messageColor, senderColor, backgroundColor, backgroundOpacity, padding, showSender, screenSpace, visible, directly` | | `Collider2D` | Add a Collider 2D component to the same entity before using this.collider. | `shape, width, height, radius, capsuleHalfHeight, capsuleRadius, offset, isTrigger, isOneWayPlatform, friction, restitution, density, layer, mask, isColliding, get, set` | | `CharacterController` | Add a Character Controller component to the same entity before using this.controller. | `heading, directional, it, controllerType, moveSpeed, acceleration, airControl, useGravity, gravityScale, useDefaultInput, maxSpeed, brakeForce, turnSpeed, driftFactor, driveTowardArriveDistance, patrolDistance, patrolMode, patrolAxis, targetName, followSpeed, followDistance, of, every, directly, if` | | `Joint2D` | Add a Joint 2D component to the same entity before using this.joint. | `jointType, connectedEntity, anchor1, anchor2, axis, length, stiffness, damping, segmentCount, ropeMass, visualEnabled, visualColor, visualThickness, useTexture, textureKey, textureMode, textureTiling, textureScale, textureOffset, textureFlip, limitsEnabled, limitMin, limitMax, motorEnabled, motorSpeed, motorMaxForce, collideConnected, enabled, key, get, set` | | `Joystick` | Add a Joystick component to the same entity before using this.joystick. | `x, y, magnitude, angle, active, positionMode, regionX, regionY, regionWidth, regionHeight, baseRadius, knobRadius, baseColor, baseOpacity, knobColor, knobOpacity, outlineColor, outlineWidth, deadZone, returnToCenter, hideWhenIdle, idleOpacityMultiplier, directly` | | `Light` | Add a Light component to the same entity before using this.light. | `type, color, intensity, radius, angle, width, height, castsOnWorld, castShadows, shadowColor, shadowStrength, flicker, flickerSpeed, flickerDuration, coreSize, coreVisible, for, on` | | `LightingSettings` | Use the global scene.lighting surface; it is not an ordinary entity component API. | `shadowMode, raymarchSteps, ambientDarkness, glowStrength` | | `NavAgent2D` | Add a Nav Agent 2D component to the same entity for this.navAgent. A Nav World 2D must also be configured for actual pathfinding. | `radius, speed, acceleration, deceleration, stoppingDistance, autoRepath, repathInterval, repathDistance, avoidanceEnabled, avoidancePriority, collabEnabled, collabGroupRadius, vehicleLookahead, vehicleCornerLookahead, vehicleObstacleLookahead, vehicleObstacleWidth, vehicleSteerSmoothing, vehicleSpeedSmoothing, vehicleCornerSlowdown, vehicleObstacleBrake, vehicleRecoveryTime, vehicleRecoveryReverseTime, area, areaCosts, currentPath, currentPathIndex, here, get, set` | | `Rigidbody2D` | Add a Rigidbody 2D component to the same entity before using this.rigidbody. | `x, type, silently, velocity, velocityX, velocityY, mass, gravityScale, linearDamping, angularDamping, isGrounded, grounded, isOnCeiling, isOnWall, isOnSlope, groundAngle, resolvedVelocity, groundAngleLimit, wallAngleLimit, slopeMinAngle, it, property, directly, for, if` | | `ShadowCaster` | Add a Shadow Caster component to the same entity before using this.shadowCaster. | `enabled, width, height, offsetX, offsetY, opacity, length, softness, its, from` | | `ShapeRenderer` | Add a Shape Renderer component to the same entity before using this.shape. | `shapeType, width, height, radius, capsuleHalfHeight, capsuleRadius, fillColor, opacity, outlineEnabled, outlineColor, outlineWidth, trap, directly` | | `SpeechBubble` | Add a Speech Bubble component to the same entity before using this.speechBubble. | `text, visible, backgroundColor, textColor, borderColor, borderWidth, fontSize, fontFamily, padding, cornerRadius, maxWidth, offsetX, offsetY, tailDirection, tailSize, from, directly` | | `SpriteRenderer` | Add a Sprite Renderer component to the same entity before using this.sprite. | `texture, color, flipX, flipY, opacity, directly` | | `State` | See complete reference. | `current, previous, to, at` | | `StrokePath` | Add a Stroke Path component to the same entity before using this.strokePath. | `points, thickness, color, opacity, useTexture, textureKey, textureMode, textureTiling, textureScale, textureOffset, textureFlip, textureRotation, jointMode, capMode, pointCount, firstPoint, lastPoint, for, by, to, key, getLength, getPoint, setPoint, addPoint, insertPoint, removePoint, worldToLocal, localToWorld` | | `TextRenderer` | Add a Text Renderer component to the same entity before using this.text. | `value, fontSize, color, fontFamily, bold, italic, align, anchorX, anchorY, opacity, screenSpace, wordWrap, wrapWidth, directly` | | `TextInput` | Add a Text Input component to the same entity before using this.textInput. | `value, placeholder, maxLength, fontSize, fontFamily, textColor, placeholderColor, backgroundColor, borderColor, borderWidth, cornerRadius, width, height, padding, clearOnSubmit, focused, justSubmitted, directly` | | `Transform` | Every entity has a Transform; this.transform is therefore available on normal entity scripts. | `position, doc, rotation, scale, trap` | | `StateAPI` | Available as `this.state` on entity scripts; no separate component is required. | `current, previous` plus state-transition behavior documented in State & messaging. | | `TouchTrackAPI` | Available as `this.myTouch` for the scripted entity; touch input must be enabled/available in the runtime. | `active, enabled, x, y` | | `SaveAPI` | Available as global `save`; no entity component is required. Persistent storage depends on the browser/deployment environment. | `isReady, slot` | ## Entity context APIs Inside lifecycle functions such as `onStart()` and `onUpdate(dt)`, `this` is the current entity context. Core transform shortcuts such as `this.x`, `this.y`, `this.position`, `this.rotation`, `this.scaleX` and `this.scaleY` are available without adding a separate Transform component. Other capabilities are deliberately grouped under their component sub-object: `this.rigidbody`, `this.collider`, `this.joint`, `this.controller`, `this.sprite`, `this.animator`, `this.camera`, `this.audio`, `this.ear`, `this.navAgent`, `this.light`, `this.shadowCaster`, `this.strokePath`, and the UI APIs documented above. ## Guarding optional components ``` function onUpdate(dt) {{ if (this.hasComponent("Rigidbody2D")) {{ // Safe to use this.rigidbody here. this.rigidbody.velocityX = 100; }} }} ``` Use the exact component name expected by the engine. For systems with additional world-level prerequisites—especially navigation—having the entity component is necessary but not sufficient. ## How to read opts Whenever a function accepts an `opts` object, the reference must be read as a contract: each property has a type, default, allowed/meaningful range, and effect. Omitted properties use the documented default. Options that are explicitly per-call do not permanently rewrite the component or world setting unless the API says they do. ``` const path = nav.findPath(startX, startY, goalX, goalY, {{ radius: 18, area: nav.areaMask("Ground", "Road"), areaCosts: nav.areaCosts({{ Mud: 4 }}), debug: true }}); ``` For navigation, configure the world and areas in the editor first, then use script options to select/override behavior for the particular query. See [Navigation: complete setup](../scripting/navigation-complete.html) for the complete editor-to-script workflow. ## Source-of-truth rule This page and the individual API references describe the public game-script contract implemented by the supplied runtime source. Internal editor classes, renderer internals, and private helper functions are not presented as supported game APIs simply because they exist in the source tree. --- # Export overview > Choose a Vaelis build target and understand the exported runtime package. ## Available targets | Target | Status | Description | | --- | --- | --- | | HTML5 | Available | Static site: index.html + game files, built entirely client-side; upload to a web host or serve through HTTP. | | PWA | Available | HTML5 plus manifest + service worker for installable/offline behavior. | | Android APK | Available, through the APK service | Debug-signed APK. The editor cannot compile it locally: it POSTs your HTML5/PWA export to the Vaelis APK service, or you upload the HTML export on the service website. | | Desktop Windows/Mac/Linux | Planned | Listed in the editor as coming soon. | For every control in the Export window see [Export window reference](export-window.html). For Android, see [Android APK](android.html): use an API key, or export HTML5 and upload it at [the APK service](https://apk-builder--vaelis-server.replit.app/). ## Standalone game contract The web export is a self-contained game package that includes `index.html`, `main.js` and the shipped runtime at `runtime/index.js`. It has no editor code in it — the same shape as the standalone target. ## Browser behavior Pointer Events are used on modern platforms with raw Touch Events as a fallback. The runtime supports multi-touch, swipe, pinch, joystick and pen/stylus input. --- # HTML5 & PWA > Export Vaelis games as static web builds or installable PWAs. ## HTML5 HTML5 export produces a static site containing the game entry point and runtime assets. Serve it through an HTTP(S) server or upload it to a normal static host. Unused sprites and audio clips are not bundled, and assets are re-encoded (AVIF/WebP, Opus/WebM) where the exporting browser supports it. ## PWA PWA export adds a web manifest and service worker so the game can install and run offline. ## Hosting checklist - Serve the exported directory from a web server rather than opening the HTML with `file://` when ES modules or other browser security policies require HTTP. - Keep the exported `runtime/` folder alongside the main game entry point. - Use HTTPS in production when browser permissions, storage or installability require a secure context. --- # Export window reference > Every control in the Export window: game title, favicon, formats, asset optimization, Android build servers, progress, cancel and results. Open it from **File → Export…** or the toolbar **Export** button. ## Game details | Field | Behavior | | --- | --- | | Game title | Up to 80 characters; defaults to the project name. Used as the page title and, for APKs, the app name. | | Favicon (optional) | Choose any image; **Change…** and **Remove** manage it. Used as the page icon and the Android launcher icon. | ## Format cards | Card | Status | Output | | --- | --- | --- | | HTML5 | Available | Static site: `index.html` plus game files. | | PWA | Available | HTML5 plus manifest and service worker for install and offline play. | | Desktop (Windows/Mac/Linux) | Coming soon (disabled) | Not built in 1.0.0. | | Android APK | Available | One debug-signed APK built on a server. See [Android APK](android.html). | ## What the build does - Runs entirely in the browser. Images are re-encoded to AVIF when the browser can encode it, otherwise WebP, otherwise left as is. Every candidate is decoded back to verify it before it is trusted. Audio becomes Opus in WebM when the browser can record it. - Sprites and audio not referenced by any scene, prefab or script are left out. - Assets are written as real binary files, never base64. - No editor code is included. The game owns its own render loop and is not frame-capped. ## Result screen After HTML5 or PWA export the download starts and the window shows how many images and audio clips were bundled, the size saved (before and after), and how many unused assets were skipped. A warning reminds you not to double-click `index.html`: from `file://` the game shows a blank page, so upload the folder to a static host (itch.io, GitHub Pages, Vercel, Netlify) or run a local server (`npx serve .`). If an Android build server is saved, **Build APK from this HTML5 (or PWA) export** sends the export you just made without rebuilding. **Export another format** resets the window. ## Android build servers Under the Android card you can save several servers (label, URL, API key), pick the active one, edit or remove entries. They are stored only in this browser. A badge shows *Checking server…*, *Server awake* or *Server may be asleep* (free hosts sleep after inactivity; building wakes them, but the first request can be slow or time out, so try again). ## Progress and cancel Android builds show a **Cancel build** button. Do not restart or leave the editor while an APK builds; cancelling (or leaving) asks the server to stop the job. The editor polls the build every 2.5 seconds and gives up after 10 minutes. HTML5 and PWA exports finish locally and cannot be cancelled. --- # Android APK > Build a debug-signed Android APK with the Vaelis APK service: use an API key in the editor, or export HTML5 and upload it on the service website. > **The APK service:** APKs are built by the Vaelis APK service at https://apk-builder--vaelis-server.replit.app/ . The editor cannot compile APKs itself, and the client distribution contains no Android SDK or Gradle. The service is needed only while the APK is built; the finished APK runs on its own. ## Two ways to get your APK ### Option 1: use an API key in the editor 1. Get your API key: under the Android card in the Export window click **Click HERE** in "Need an API key?" (it opens [the APK service](https://apk-builder--vaelis-server.replit.app/)). 2. In the editor open **Export → Android APK** and click **+ Add build server**. 3. Enter a label (optional), check the **Server URL** (prefilled with `https://apk-builder--vaelis-server.replit.app`) and paste your **API Key**, then click **Add server**. The button is always clickable; if the URL or key is empty it tells you which one is missing. 4. Click the **Android APK** card. The editor builds your game, uploads it, shows progress and downloads the APK when it is ready. ### Option 2: no API key, export as HTML and upload on the website 1. In the editor choose **Export** and export as **HTML5** (PWA also works). A ZIP downloads. 2. Open in your browser. 3. Click **Upload** and choose the exported ZIP (the project export from step 1). 4. When the build finishes, download your APK. > **Upload the exported game ZIP:** The ZIP must have index.html at its root. A saved project file ( .vs from File → Save Project) is not an export and will not build. ## Build behavior - The server badge shows whether the service is awake. A sleeping free-tier host wakes when you build; the first attempt can time out, so retry. - Use **Cancel build** in the Export window to stop a running job. Do not restart or close the editor mid-build. - The server keeps a finished APK for about 30 minutes; the editor tells it to delete its copy as soon as the download is complete. - The APK is debug-signed, suitable for installing and testing directly on a device. - The game loads from the APK itself in a local WebView origin, so ES modules, JSON, audio, images and the physics WASM work with no server or internet at runtime. Pointer Events are preferred with Touch Events as a fallback. - The favicon you choose in the Export window becomes the launcher icon. ## Request contract (for people running a build server) The editor sends exactly this request, with the export ZIP as the body: ``` POST /api/v1/build?name= Content-Type: application/zip X-Api-Key: ``` - No other custom headers are sent; extra headers would fail the browser's CORS preflight. The server tells a standalone export apart by the ZIP contents (`index.html` at the root) and can read `manifest.webmanifest` and `sw.js` to tell PWA from plain HTML5. - The response is a JSON job ticket with `statusUrl` (top level or under `job`). The completed status must provide `downloadUrl`. Relative URLs are resolved against the server URL. - `GET /api/healthz` (CORS-enabled JSON) powers the awake badge. - `DELETE ` (from the ticket, falling back to `statusUrl`) cancels a job. It must be idempotent and the final status is `cancelled`, which the editor treats like `failed`. Status polling is also a heartbeat; a server should cancel jobs whose editor stops polling (about 60 seconds suggested). - After a download the editor posts to the `/confirm-delivery` sibling of the download URL so the server can delete the APK early. --- # Tuning guide > Practical “increase/decrease this” rules for movement, physics, navigation, lighting, UI and path authoring. ## How to tune movement | Goal | Raise | Lower | | --- | --- | --- | | More responsive character movement | acceleration, airControl | acceleration, airControl | | Longer/faster jump | jumpForce, maxJumps if desired | gravityScale / jumpForce | | More stable vehicle | turn/brake smoothing, recovery settings | overly aggressive steering values | | Faster NavAgent | speed, acceleration | stoppingDistance if you want it closer before stopping | ## How to tune physics | Goal | Typical setting | Direction | | --- | --- | --- | | Make dynamic body fall faster | Rigidbody2D.gravityScale | Increase above 1. | | Make body coast longer | linearDamping | Decrease toward 0. | | Make body stop rotating sooner | angularDamping | Increase. | | Make contact bouncier | Collider2D.restitution | Increase. | | Reduce sliding | Collider2D.friction | Increase. | | Make a platform one-way | Collider2D.isOneWayPlatform | Enable; contact filtering then only allows landing from the supported side. | ## How to tune navigation | Setting | Increase means | Decrease means | | --- | --- | --- | | NavWorld2D.cellSize | coarser/faster grid, less geometric detail | finer grid, narrower detail but more work | | NavAgent2D.radius | larger clearance requirement | smaller agent clearance | | NavAgent2D.repathInterval | less frequent replanning | more responsive replanning | | NavWorld2D.areaCosts slot | more expensive path cost through that area | closer to the cheapest route | ## How to tune lighting | Setting | Increase means | Decrease means | | --- | --- | --- | | Light.intensity | brighter/stronger contribution | dimmer | | Light.radius | larger influence region | tighter/localized light | | ShadowCaster.length | longer shadow reach | shorter/contact shadow | | ShadowCaster.softness | softer/wider penumbra | crisper edge | | LightingSettings.raymarchSteps | more samples/detail, more GPU work | less GPU work, potentially less detail | | LightingSettings.ambientDarkness | darker unlit regions | brighter ambient base | > **Rule for numeric documentation:** Vaelis documentation should state not only what a field is, but what increasing and decreasing it does, its units, default, and whether the value is clamped/validated. The API catalog in api-options.json follows this model for option objects. --- # Scene JSON > Reference the Vaelis scene serialization format. ## Top-level shape ``` { "sceneName": "Level1", "hierarchyFolders": [], "entities": [] } ``` ## Entity shape ``` { "id": "e12", "name": "Target", "tag": "Target", "active": true, "folderId": null, "prefabId": null, "prefabOverrides": {}, "components": { "Transform": { "x": 0, "y": 0, "z": 0, "rotation": 0, "scaleX": 1, "scaleY": 1 } } } ``` ## Component registry SceneSerializer recognizes the runtime component types: Transform, Camera, SpriteRenderer, ShapeRenderer, StrokePath, TextRenderer, SpeechBubble, ChatLog, TextInput, Joystick, Rigidbody2D, Collider2D, Joint2D, Light, ShadowCaster, CharacterController, LightingSettings, SpriteAnimation, AudioSource, AudioListener, Tileset, Tilemap, NavWorld2D, NavAgent2D and Script. ## Authoring rules Scene files are plain JSON and can be authored by the editor, generated by tools or hand-written. The serializer deep-copies folder/prefab override data so saved snapshots do not alias live state. ## Default camera A fresh/default scene uses a **Main Camera** entity with tag `MainCamera`, active state enabled, Transform at 0,0 and a main Camera flag. --- # Project format > Understand the engine-versioned project container and portable distribution layout. ## Project version Vaelis 1.0.0 stores the engine version in its runtime and launcher version constants. Saved manifests are stamped with that version so opening a project created by a newer engine can produce a compatibility warning. ## Distribution layout | Path | Purpose | | --- | --- | | project/runtime/ | Engine runtime shipped with games. | | project/editor/ | Development editor, including the HTML5/PWA exporter. | | `project/player/` | Standalone standalone runtime shell. | | project/vendor/ | Local third-party runtime/editor dependencies (Pixi, Rapier, Hammer, Monaco, JSZip). | | css/, icons/, js/ | The engine hub client (project browser, new-project flow, templates). | | sw.js, offline-manifest.json | Offline PWA support for the hub/editor itself. | ## What is not included > **No local Android tooling:** This client distribution is intentionally static: it ships no Android SDK, Gradle, Java build scripts, Node server, or local APK builder. Android APKs are built by an external build server the person running the editor configures themselves — see Android APK. ## Runtime boundary Runtime never imports editor modules. This keeps exported games independent from the editor and is one of the core architectural invariants of the distribution. --- # Engine conventions (RULES.txt) > The architectural rules that govern how Vaelis’s own codebase is organized. ## Scope This is the engine’s own internal contract for where code goes and how the three top-level folders relate. It applies to people extending Vaelis itself; if you’re only writing game scripts, you don’t need it — see Scripting quickstart instead. ## 1. The core rule: runtime never depends on editor `runtime/` is the actual game engine. `editor/` is the Unity-style level editor UI, a development tool only. `target/` is the standalone game shell, importing only from `runtime/`. No file under `runtime/` may ever import, reference, or depend on anything under `editor/` — not for debugging, not temporarily, not ever. You must be able to delete the `editor/` folder entirely and the game (`standalone runtime play entry point`) keeps working with zero changes. `editor/` may import from `runtime/` — that direction is allowed and expected, since the editor is built on top of the engine. ## 2. One feature = new file(s), not a growing old file Adding a new component, system, editor panel, scripting API, or asset type creates a new file in the appropriate subfolder. Unrelated functionality is never appended into an existing file just because it’s nearby or already open. If a feature doesn’t fit any existing subfolder, a new subfolder is created (matching the existing lowercase, pluralized naming style) rather than dumping it into an unrelated folder. | Adding… | Goes in… | | --- | --- | | A new gameplay component | runtime/components/YourComponent.js | | A new gameplay/rendering/physics system | runtime/systems/YourSystem.js | | A new editor panel | editor/panels/YourPanel.js | | A new asset type | runtime/assets/YourManager.js | | A new scripting capability | A method/property on the relevant file in runtime/scripting/components/, or a new file there | ## 3. Components stay plain data Files under `runtime/components/` hold only plain serializable data (numbers, strings, booleans). No PixiJS objects, no DOM references, no behavior/update logic — behavior belongs in `runtime/systems/`. This is what keeps SceneSerializer.js able to save and load any component generically. ## 4. Rendering is centralized `runtime/systems/RenderSystem.js` is the only place that creates or updates PixiJS display objects from entity data. Both the editor’s viewport and the standalone target use it, so visuals never drift between edit mode and play mode. Editor-only chrome (grid lines, selection gizmos) may be drawn in its own separate layer on top of the runtime’s render output — that chrome must never be visible in `/target`. ## 5. Scene data flows through the runtime’s public API only The editor never invents its own scene format or its own copy of scene state. The single source of truth is the live World instance, and the single way to read/write its persisted form is `runtime/scene/SceneSerializer.js`. New scene-level functionality (undo, multi-scene, prefabs) extends the runtime’s `scene/` folder, not the editor’s `state/` folder. ## One API per capability (scripting) `this.x`, `this.y`, `this.position`, `this.rotation`, `this.translate()`, and `this.visible` are flat shortcuts because Transform has only one shape. Everything else — velocity, physics forces, sprite properties, animation, camera, audio, movement-type tunables — is reached only through its sub-object (`this.rigidbody.*`, `this.sprite.*`, `this.controller.*`, etc). There is deliberately no flat-shortcut duplicate of any of these, because RigidbodyAPI exposes a different shape per body type and ControllerAPI exposes a different shape per controller type — a second flat copy would either duplicate that per-type logic or drift out of sync with it. > **Source note:** These rules come from the engine repository’s RULES.txt . That file is not included in the client distribution ( project/ contains editor/ , player/ , runtime/ and vendor/ only), so it is documented here rather than linked. --- # Debugging > Diagnose common Vaelis runtime and authoring problems. ## Use the Debug HUD The `debug` module can show the HUD, FPS and logging. Performance/profiling displays are useful while diagnosing update and rendering behavior. ## Lifecycle failures If a lifecycle callback throws, the runtime reports the error and isolates it. Look for the callback name and error classification in the runtime output. ## Physics checklist - Confirm the entity has the expected Rigidbody2D body type. - Confirm Collider2D shape, layer and mask settings. - For one-way platforms, test motion from both sides. - Use `physics.raycast(...,{debug:true})` to verify what the query actually sees. ## Navigation checklist - Confirm a NavWorld2D exists in the scene. - Confirm the queried point is inside walkable bounds. - Check NavAgent2D radius/area settings. - Use `nav.findPath(...,{debug:true})` to visualize the result. ## Common API mistake > **Editor code is not game code:** If code is only found in project/editor/ , it is not automatically a supported game-script API. The public script surface is the documented this.\* context and global runtime modules. --- # Security & play origin > Scripts are not sandboxed. How the separate play origin works, what the editor protects, and what stays exposed. > **Game scripts are not sandboxed:** A project's scripts are compiled with new Function() and run as normal page code. Whatever origin the game runs on is what the script can reach. Only open projects from people you trust. ## Recommended setup: play on a separate origin 1. Deploy the **same folder** on a second hostname, for example `play.yourdomain.com` (on Vercel, add another domain to the same project). 2. In `project/editor/index.html` set ``. Pressing Play then opens the game on the play origin and the editor sends the scene with `postMessage`. Scripts there cannot read the editor's `localStorage`, IndexedDB (saved projects, Android build server keys) or DOM, because browsers keep each origin's data apart. - **Empty meta tag** keeps same-origin play. Fine for a private, local setup; not fine once you share projects. - **Offline:** the other host cannot be reached, so the editor falls back to same-origin play and logs a warning. - **`save` data** from Play lives on the play origin, separate from the editor's. - Use `https://` in production and put nothing private (login cookies, editor data) on the play origin. ## What is protected - **Message handling:** the editor accepts messages only from the play window it opened, on the origin it opened it on. The play window accepts messages only from the editor. - **Escaped Console:** script output is escaped, so `console.log("")` cannot run code in the editor. - **Escaped project data:** entity, script, tag and asset names come from project files and are escaped in the Hierarchy, Inspector, dropdowns and asset grid. - **Shadowed globals:** inside a script, `window`, `document`, `globalThis`, `self`, `top`, `parent`, `frames`, `opener`, `open`, `localStorage`, `sessionStorage`, `indexedDB`, `caches`, `fetch`, `XMLHttpRequest`, `WebSocket` and `Function` are `undefined`. This stops accidents and one-line snooping only; the separate origin is the real protection. Use `save` and `global` instead of browser storage. - **Import prompt:** loading a project that contains scripts asks for confirmation first. - **No secrets shipped:** Android build server URLs and API keys are typed by the user and stored only in that browser's `localStorage`. ## What is still exposed - In same-origin mode, everything a page on that origin can reach, including saved projects and build keys. - A script can still make network requests from the play origin and affect its own game window. That is the nature of running someone's code. ## Third-party licenses Vaelis bundles open-source libraries; see `THIRD_PARTY_LICENSES.md` in the distribution. Exported games include `THIRD_PARTY_LICENSES.txt`. Keep it in the folder when you publish. --- # Versioning > Vaelis engine version policy and documentation version strategy. ## Semantic version rules | Increment | Use for | | --- | --- | | MAJOR | Scene/manifest-format-breaking changes. | | MINOR | New backward-compatible engine features. | | PATCH | Fixes that do not change save-format compatibility. | ## Why docs are versioned API details and serialized scene formats can evolve. Keep `/docs/v1.0.0/` intact when 1.0.0 or 2.0.0 ships, then add a new version directory and version entry. This keeps old tutorials and AI-generated code anchored to the engine version they target. ## Adding a new version ``` docs/v1.0.0/ docs/1.0.0/ docs/2.0.0/ # Then update versions.json and regenerate the site. ``` ## Compatibility warning The engine itself compares incoming project manifest versions against the current editor version and warns when a project comes from a newer engine. Treat the documented version in generated code and scene data as part of the compatibility context. > **Stable versioned URLs.:** Each engine version has its own URL namespace, such as /docs/v1.0.0/ . When a new engine version is released, publish it under a new path such as /docs/v1.0.0/ instead of replacing the older version. This keeps old projects and AI/search results tied to the documentation version they were built against. --- # Source map & verification > A source-grounded map of where Vaelis’s public behavior and editor controls are actually implemented. > **Verified source:** This documentation pass was checked against the supplied the Vaelis client distribution distribution, including runtime components, scripting API modules, editor panels/state, navigation, physics, scene serialization, and export code. ## Engine architecture map | Area | Primary source locations | Purpose | | --- | --- | --- | | Public runtime entry | `project/runtime/index.js` | Wires World + systems + scripting and exposes createGame(). | | Components | `project/runtime/components/` | Serializable component data used by scene entities. | | Systems | `project/runtime/systems/` | Runtime behavior such as physics, rendering, animation, lighting, audio, navigation and scripting. | | Scripting | `project/runtime/scripting/` | User-facing script surface, EntityContext and option metadata. | | Physics | `project/runtime/physics/` | Rapier-backed collider/body/joint queries and contact behavior. | | Navigation | `project/runtime/pathfinding/` | A\* grid bake, dynamic bake, area masks/costs and navigation support. | | Editor UI | `project/editor/panels/` | Toolbar, Hierarchy, Inspector, Project/Console, animation, tileset, export and settings windows. | | Editor state/events | `project/editor/state/` | Persistence, dirty state, layer/area registries and DOM event handling. | | Scene serialization | `project/runtime/scene/SceneSerializer.js` | Serialized scene/entity component format. | ## Important source files for documentation truth | Question | Verify here | | --- | --- | | What components exist? | `project/runtime/components/*.js` | | What script members exist? | `project/runtime/scripting/components/*API.js` + `ScriptAPI.js` | | What opts are accepted? | `project/runtime/scripting/NavAPI.js` and the relevant ScriptAPI doc comments | | Where is a button? | `project/editor/panels/*.js` | | What appears only conditionally? | `project/editor/panels/Toolbar.js` + `editor/state/EditorEvents.js` | | How does an interaction actually behave? | Relevant runtime system + component + tests in the same area. | --- # Changelog > Release notes and documentation scope for Vaelis 1.0.0. ## 1.0.0 features - **Tween API:** `tween()` and `cancelTween()` with 33 easings, editor autocomplete and highlighting. - **Time scale:** writable `time.scale` and new `time.unscaledDeltaTime`; global `smoothstep`. - **Physics:** breakable Revolute joints, `jointDrag`, `restStiffness`, `disableConnectedCollision`; Rigidbody `autoMass`, `angularDamping` and `addForceAtPoint`. - **Editor:** Window menu panel toggles, Inspector component notes toggle, Console copy, performance settings, memory watchdog. - **Export:** Export window with game title, favicon, asset optimization and unused-asset skipping; Android builds via the APK service with cancel, health badge and an API-key-free HTML upload route. - **Security:** optional separate play origin, shadowed globals, escaped console and import confirmation. - **Hub:** six starter templates, Learn and Installs tabs, offline PWA and `.vs` file association. - Corrected the Android request contract: only `Content-Type` and `X-Api-Key` are sent. ## 1.0.0 documentation baseline This documentation snapshot reflects the portable Vaelis distribution provided with the request. It captures the public runtime API, component serialization model, editor surfaces, export targets and recent engine behaviors implemented in the distribution. ## Recent engine areas represented The source includes rope/spring visual/physics refinements, Swing physics fixes, one-way platform collision work, lighting/shadow pipeline improvements, scripting autocomplete exposure and export/runtime file fixes. This documentation describes the resulting public surfaces without treating internal implementation notes as separate APIs. ## Documentation policy When future versions ship, add release-specific API/reference pages and preserve the previous version. Breaking serialized-format changes belong in a new MAJOR version; compatible API additions can be MINOR releases. ## Corrections in this edition This edition corrects the Android export documentation: earlier drafts described a local Gradle wrapper, an auto-downloaded Android SDK, a Java 17 requirement and a bundled `export-apk.js` command-line tool, none of which exist in the distribution. Android APK builds require an external, user-connected build server; see Android APK and the distribution README for the corrected description. It also adds the StrokePath component reference, the per-body-type this reference, several granular scripting pages, and the engine’s internal architecture rules — none of which change existing script-facing APIs. ## Documentation corrections (site redesign) This edition of the documentation was re-verified against the client distribution source. Corrections: - Android build requests send only `Content-Type` and `X-Api-Key`; the server identifies standalone exports from the ZIP contents. - The Erase tool (Y) appears when a Tilemap or a Nav World 2D exists; a Tileset alone does not enable it. - Added the editor’s Delete, copy/paste/duplicate, undo/redo and Space play shortcuts. - Component field tables now list every serialized field with its source default (for example StrokePath defaults: thickness 40, colour `#8a8a8a`, round joints and caps, texture mode `stretch`). Engine-managed runtime fields are labelled as such. - Script API tables now include members previously missing, such as `this.ear.canHear()` / `sourcesInRange`, `this.camera.x`/`y`, Rigidbody slope/wall angle limits, StrokePath `jointMode`/`capMode`/`textureRotation`, and the remaining Joystick styling members. `this.transform.scale` is an `{x, y}` object. --- # AI & crawlers > How this documentation is structured so search engines and language models can discover and understand Vaelis. > **Recommended retrieval order:** For a UI question, read editor/controls.html first, then the feature page, then the relevant component page. For a script question, read the component/API page plus api/options.json . For a disputed behavior, consult reference/source-map.html and the cited runtime subsystem. ## The important design choice Core documentation is rendered as ordinary HTML pages with real headings, links, tables and code—not a client-only documentation app. JavaScript enhances navigation/search but does not hold the only copy of the API content. ## Stable version URLs Every 1.0.0 topic lives under `/docs/v1.0.0/`. Future versions can coexist at their own paths. The root documentation page is a version chooser, while `/docs/latest/` currently aliases the current version. ## Crawler files | File | Purpose | | --- | --- | | `robots.txt` | Allows general crawling and explicitly keeps OpenAI search/training crawlers unblocked unless you change the policy. | | `sitemap.xml` | Enumerates the HTML and machine-readable URLs for discovery. | | `llms.txt` | Compact Markdown-style index of the most useful documentation entry points. | | `llms-full.txt` | Broader index of guide/API/reference pages. | | `api/v1.0.0/index.json` | Machine-readable engine/component/API catalog. | | `search-index.json` | Client-side site search index, also easy for tooling to ingest. | ## Publishing correctly Set `VAELIS_DOCS_ORIGIN` to your real public documentation origin before deployment if you want absolute canonical URLs, sitemap URLs and structured data. Until it is published publicly and not blocked by your crawl rules, no AI service can be expected to discover it. ## OpenAI crawler controls OpenAI documents separate crawler controls for search and model-training use. The site therefore leaves both `OAI-SearchBot` and `GPTBot` crawlable in `robots.txt`; you can change those directives later if your publishing policy changes. ## AI-friendly API language API pages state exact member names, types, defaults, return shapes and prerequisites. That is deliberately more useful for code-generating models than prose-only descriptions or a single giant page. --- # For AI assistants & LLMs > A dense, link-backed summary of Vaelis’s API surface for models generating or explaining Vaelis code. > **Machine-readable contract:** For retrieval/code-generation systems, load api-options.json for opts schemas, reference-ui-map.json for editor controls and conditional buttons, and source-manifest.json for implementation/source coverage. Use the component pages for defaults/tuning and the source map for resolving behavior conflicts. ## Purpose This page exists specifically for AI assistants and language models that are helping someone write a game with Vaelis, or that are being asked what Vaelis is. It is a dense, load-bearing summary — every claim on it is also documented in full elsewhere on this site, linked inline from the sidebar. ## What to tell someone who asks “what is Vaelis?” Vaelis is a browser-based 2D game engine with a Unity-style visual editor, an entity-component-system runtime built on PixiJS (rendering) and Rapier2D (physics), and a sandboxed JavaScript scripting API. The editor and runtime ship as a static distribution with no Node.js/build step of their own. It exports to a standalone static web build (HTML5/PWA) directly in the browser; a debug-signed Android APK is also available but is built by an external server the developer connects themselves, not locally. Full detail: Architecture and Export overview. ## The one rule that governs every engine-source suggestion If you are generating or editing Vaelis engine source (not a game script), the load-bearing constraint is: code under `/runtime` must never import anything from `/editor`. If you’re only writing a gameplay script (the far more common case), this rule doesn’t apply to you directly. See Engine conventions (RULES.txt). ## What NOT to claim about export > **A common mistake to avoid:** Do not tell someone that Vaelis bundles a Gradle wrapper, downloads an Android SDK locally, requires Java 17, or ships a command-line export-apk.js tool. None of that exists in the distribution. Android APK export always requires a separately hosted build server that the developer configures with a URL and API key in Export → Android APK. ## Script API shape Inside a script, `this` is bound to the current entity; conditional sub-objects (`this.rigidbody`, `this.sprite`, etc.) are only present when the matching component exists, and accessing a missing one throws a typed `missing-component` error rather than returning undefined. Prefer documented globals (`findFirst`, `scene`, `physics`, `nav`, `input`, `time`, `save`, `spawn`, `wait`/`repeat`, `sendMessage`/`broadcastMessage`) and component sub-objects over reaching into internal runtime systems or editor modules. --- # Transform > Vaelis 1.0.0 Transform component reference: fields, script API, behavior and examples. > **Scope:** This page documents the Transform component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector (right side) → Transform component, automatically present on every GameObject. Use W/E/R toolbar tools for scene manipulation. ## What it does Position, rotation and scale. Every spatial entity uses a Transform. > **Component setup & editor tools:** Transform is automatically present on entities. Select an entity in the Hierarchy; its Transform section appears in the Inspector. ## How to add and use Transform **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **Transform** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select an entity in the Hierarchy; edit Transform fields in the Inspector. Use the Scene viewport transform gizmo to move/rotate/scale visually. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `x` | number | World position X. | `0` | | `y` | number | World position Y. | `0` | | `z` | number | Pseudo-3D depth; affects sprite scale only when Camera.enablePseudo3D is enabled. | `0` | | `rotation` | number | Rotation in degrees around Z. | `0` | | `scaleX` | number | Horizontal scale multiplier. | `1` | | `scaleY` | number | Vertical scale multiplier. | `1` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `x / y` | World position. Increasing X moves right; increasing Y moves down in the engine’s 2D world convention. | | `rotation` | Degrees clockwise visually in the screen coordinate convention; 0 points along +X for directional/spot light orientation. | | `scaleX / scaleY` | 1 is native scale; >1 enlarges; 0.5 halves size; negative values mirror the corresponding axis. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `position` | Property | { x, y } world-space position; read or assign. | | `rotation` | Property | Rotation in degrees. | | `translate(dx, dy)` | Method | Move by a delta amount. | | `lookAt(x, y)` | Method | Point the entity toward a world-space point. | | `scale` | Property | Available on this module. | ## Examples ``` this.position = { x: 200, y: 120 }; ``` ``` this.rotation = 45; ``` ``` this.translate(50 * time.deltaTime, 0); ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # SpriteRenderer > Vaelis 1.0.0 SpriteRenderer component reference: fields, script API, behavior and examples. > **Scope:** This page documents the SpriteRenderer component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector → Add Component → Sprite Renderer; choose or import sprites from bottom Project → Sprites, then assign the Sprite Renderer sprite. ## What it does Draw a 2D texture sprite for an entity. > **Component setup & editor tools:** In the Inspector, use the SpriteRenderer section to choose the sprite, then use its visual fields and the Scene viewport to verify the result. ## How to add and use SpriteRenderer **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **SpriteRenderer** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Inspector → SpriteRenderer → sprite field: choose the sprite asset. Use the viewport to see the result. FlipX/FlipY are visual orientation controls; color/opacity change appearance without changing the source asset. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `spriteKey` | string|null | Asset key for the sprite texture. | `null` | | `color` | hex string | Tint color. | `#ffffff` | | `opacity` | number | Opacity multiplier. | `1` | | `flipX` | boolean | Mirror horizontally. | `false` | | `flipY` | boolean | Mirror vertically. | `false` | | `referenceWidth` | number|null | Optional reference width used by rendering/layout. | `null` | | `referenceHeight` | number|null | Optional reference height used by rendering/layout. | `null` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `opacity` | 0 is invisible; 1 is fully opaque; values between are translucent. | | `flipX / flipY` | Boolean mirror. Flip X changes left/right without changing the Transform position. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `texture` | Property | Sprite asset key. | | `color` | Property | Hex tint color. | | `flipX` | Property | Horizontal mirror. | | `flipY` | Property | Vertical mirror. | | `opacity` | Property | Opacity. | ## Examples ``` this.sprite.texture = "target"; ``` ``` this.sprite.flipX = input.keyDown("ArrowLeft"); ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # ShapeRenderer > Vaelis 1.0.0 ShapeRenderer component reference: fields, script API, behavior and examples. > **Scope:** This page documents the ShapeRenderer component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Create directly from top GameObject → Shape → Square/Circle/Capsule/Triangle, or Inspector → Add Component → Shape Renderer. ## What it does Draw a procedural 2D shape without requiring a sprite asset. > **Component setup & editor tools:** Use ShapeRenderer when you want a procedural shape without importing an image. ## How to add and use ShapeRenderer **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **ShapeRenderer** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Inspector → ShapeRenderer: choose the shape type and edit its dimensions. For triangle/freeform shapes, the corresponding viewport gizmo is used when available. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `shapeType` | enum | Square, Circle, Triangle or Capsule. | `Square` | | `width` | number | Square width. | `100` | | `height` | number | Square height. | `100` | | `radius` | number | Circle radius. | `50` | | `capsuleHalfHeight` | number | Capsule half-height along its vertical axis. | `50` | | `capsuleRadius` | number | Capsule cap radius. | `30` | | `trianglePoints` | 3 points | Triangle vertices in local space. | `[{x:-50,y:50}, {x:50,y:50}, {x:0,y:-50}]` | | `fillColor` | hex string | Fill color. | `#3a8ede` | | `opacity` | number | Opacity. | `1` | | `outlineEnabled` | boolean | Enable outline. | `false` | | `outlineColor` | hex string | Outline color. | `#ffffff` | | `outlineWidth` | number | Outline width. | `2` | ## Script API | Member | Kind | Description | | --- | --- | --- | | `shapeType` | Property | Square | Circle | Capsule | Triangle. | | `width` | Property | Shape width. | | `height` | Property | Shape height. | | `radius` | Property | Circle radius. | | `capsuleHalfHeight` | Property | Capsule half-height. | | `capsuleRadius` | Property | Capsule radius. | | `fillColor` | Property | Fill hex color. | | `opacity` | Property | Opacity. | | `outlineEnabled` | Property | Whether the outline is rendered. | | `outlineColor` | Property | Outline hex color. | | `outlineWidth` | Property | Outline width. | ## Examples ``` this.shape.fillColor = "#22c55e"; ``` ``` this.shape.shapeType = "Circle"; ``` ``` this.shape.radius = 32; ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # TextRenderer > Vaelis 1.0.0 TextRenderer component reference: fields, script API, behavior and examples. > **Scope:** This page documents the TextRenderer component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Top UI menu → Text, or Inspector → Add Component → Text; screen-space text is authored from the same Inspector component. ## What it does Render text either in world space or as screen-space UI. > **Component setup & editor tools:** TextRenderer displays text as a screen/world-space rendering component depending on the entity/camera context. ## How to add and use TextRenderer **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **TextRenderer** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Inspector → TextRenderer: edit the text and presentation properties. For runtime changes, use the documented this.text API. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `value` | string | Displayed text. | `Text` | | `fontSize` | number | Font size. | `32` | | `color` | hex string | Text color. | `#ffffff` | | `fontFamily` | string | Font family name. | `Arial` | | `bold` | boolean | Bold text. | `false` | | `italic` | boolean | Italic text. | `false` | | `align` | enum | left | center | right. | `left` | | `anchorX` | number | Horizontal anchor from 0 to 1. | `0.5` | | `anchorY` | number | Vertical anchor from 0 to 1. | `0.5` | | `opacity` | number | Opacity. | `1` | | `screenSpace` | boolean | Render as fixed UI overlay instead of world-space text. | `true` | | `wordWrap` | boolean | Enable wrapping. | `false` | | `wrapWidth` | number | Wrap width when enabled. | `300` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `fontSize` | Higher = larger text. | | `anchorX / anchorY` | 0 = top/left pivot, 0.5 = center, 1 = bottom/right pivot for the text block. | | `wrapWidth` | Only used when wordWrap is enabled; larger width permits longer lines before wrapping. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `value` | Property | Displayed text. | | `fontSize` | Property | Font size. | | `color` | Property | Hex text color. | | `fontFamily` | Property | Font family. | | `bold` | Property | Bold toggle. | | `italic` | Property | Italic toggle. | | `align` | Property | left | center | right. | | `anchorX` | Property | Horizontal anchor. | | `anchorY` | Property | Vertical anchor. | | `opacity` | Property | Opacity. | | `screenSpace` | Property | Use screen-space UI behavior. | | `wordWrap` | Property | Enable word wrapping. | | `wrapWidth` | Property | Wrap width. | ## Examples ``` this.text.value = "Score: " + score; ``` ``` this.text.screenSpace = true; ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # StrokePath > Vaelis 1.0.0 StrokePath component reference: fields, script API, behavior and examples. > **Scope:** This page documents the StrokePath component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Top GameObject → 2D Object → Stroke Path. After a Stroke Path exists, the toolbar exposes Path (P); click empty space to append, drag points, and click segments to insert. ## What it does A variable-thickness strip along placed points — rivers, cables, roads, conveyor belts or walls — with flat color or textured fill. > **Component setup & editor tools:** StrokePath creates a drawable strip/path; its editing is performed with the Stroke Path viewport tool/gizmo. ## How to add and use StrokePath **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **StrokePath** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select an entity with StrokePath → use the Stroke Path viewport tool/gizmo to edit path points. Keep the Inspector open for serialized path/material settings. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `points` | array of {x,y} | Local-space point list defining the open polyline (not rotated/scaled by the Transform). | `[{x:-100,y:0}, {x:100,y:0}]` | | `thickness` | number | Strip thickness. | `40` | | `color` | hex string | Flat fill color, used when useTexture is false. | `#8a8a8a` | | `opacity` | number | Opacity. | `1` | | `useTexture` | boolean | Use an image texture along the path instead of a flat fill. | `false` | | `textureKey` | string|null | Texture asset key. | `null` | | `textureMode` | enum | stretch | tile. | `stretch` | | `textureTiling` | number | Tiling length when textureMode is tile. | `100` | | `textureScale` | number | Texture scale. | `1` | | `textureOffset` | number | Texture offset; animatable for a flowing river/conveyor-belt look. | `0` | | `textureFlip` | boolean | Flip texture. | `false` | | `textureRotation` | number | Texture rotation. | `0` | | `jointMode` | enum | Joint style between segments. | `round` | | `capMode` | enum | End-cap style. | `round` | | `smoothing` | number | 0-1. Runs the authored `points` through a Catmull-Rom spline resample BEFORE tessellation, turning the raw straight-segment polyline into a smooth curve — same idea as a… | `0` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `thickness` | Larger values make the strip wider. | | `textureTiling` | In TILE mode, larger values make each repeated texture cover more path length, so the image repeats less often. | | `textureScale` | Higher scales the texture; lower makes it smaller/repeated more densely. | | `textureOffset` | Changing this over time scrolls the texture along the path. | | `opacity` | 0 invisible, 1 opaque. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `points` | Property | Local-space point array; reads return a fresh deep copy, writes replace the component’s array with a deep copy. | | `thickness` | Property | Strip thickness. | | `color` | Property | Flat fill color. | | `opacity` | Property | Opacity. | | `useTexture` | Property | Whether a texture is used instead of a flat fill. | | `textureKey` | Property | Texture asset key. | | `textureMode` | Property | stretch | tile. | | `textureTiling` | Property | Tiling length. | | `textureScale` | Property | Texture scale. | | `textureOffset` | Property | Texture offset. | | `textureFlip` | Property | Texture flip. | | `getPoint(i)` | Method | Read one point by index. | | `setPoint(i,x,y)` | Method | Overwrite one point. | | `addPoint(x,y)` | Method | Append a point. | | `insertPoint(i,x,y)` | Method | Insert a point at index i. | | `removePoint(i)` | Method | Remove a point by index. | | `pointCount` | Property | Read-only point count. | | `getLength()` | Method | Total path length. | | `firstPoint` | Property | Read-only first point. | | `lastPoint` | Property | Read-only last point. | | `worldToLocal(x,y)` | Method | Convert a world-space point to the entity’s local point space. | | `localToWorld(x,y)` | Method | Convert a local-space point to world space. | | `capMode` | Property | 'none' | 'box' | 'round' — see StrokePathCapMode in components/StrokePath.js. | | `jointMode` | Property | 'sharp' | 'bevel' | 'round' — see StrokePathJointMode in components/StrokePath.js. | | `textureRotation` | Property | Texture rotation in degrees, around each tile's own center. | ## Notes & behavior - Points are placed with the Path tool in the Scene viewport, then adjusted by dragging a point or clicking a segment to insert a new one between two existing points. - An open polyline (A to B), not a closed loop. - Reads/writes on this.strokePath.points always operate on a copy, so mutating a returned array can never silently corrupt the live component; assign it back (or use the point methods) to apply a change. ## Examples ``` this.strokePath.addPoint(this.x, this.y); ``` ``` this.strokePath.textureOffset += 20 * time.deltaTime; // flowing river/conveyor look ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # SpeechBubble > Vaelis 1.0.0 SpeechBubble component reference: fields, script API, behavior and examples. > **Scope:** This page documents the SpeechBubble component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Top UI → Speech Bubble, or Inspector → Add Component → Speech Bubble. ## What it does Speech bubble UI attached to an entity, useful for dialogue and NPC callouts. > **Component setup & editor tools:** SpeechBubble provides an in-scene speech presentation attached to an entity. ## How to add and use SpeechBubble **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **SpeechBubble** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Inspector → SpeechBubble: configure its display properties; use the documented SpeechBubble API to change content at runtime. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `text` | string | Current bubble text. | `Hello!` | | `visible` | boolean | Whether visible. | `false` | | `backgroundColor` | hex string | Bubble background. | `#ffffff` | | `textColor` | hex string | Text color. | `#111111` | | `borderColor` | hex string | Border color. | `#111111` | | `borderWidth` | number | Border width. | `2` | | `fontSize` | number | Font size. | `20` | | `fontFamily` | string | Font family. | `Arial` | | `padding` | number | Bubble padding. | `12` | | `cornerRadius` | number | Corner radius. | `10` | | `maxWidth` | number | Maximum text width. | `220` | | `offsetX` | number | World/UI X offset. | `0` | | `offsetY` | number | World/UI Y offset. | `-60` | | `tailDirection` | enum | Tail direction. | `down` | | `tailSize` | number | Tail size. | `14` | | `hideTimer` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `maxWidth` | Higher lets a line run longer before wrapping. | | `offsetY` | Negative values move the bubble upward from the entity in the default screen convention. | | `padding` | Higher creates more interior space around text. | | `cornerRadius` | Higher makes corners rounder. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `text` | Property | Current text. | | `visible` | Property | Visibility. | | `backgroundColor` | Property | Background color. | | `textColor` | Property | Text color. | | `borderColor` | Property | Border color. | | `borderWidth` | Property | Border width. | | `fontSize` | Property | Font size. | | `fontFamily` | Property | Font family. | | `padding` | Property | Padding. | | `cornerRadius` | Property | Corner radius. | | `maxWidth` | Property | Maximum width. | | `offsetX` | Property | Horizontal offset. | | `offsetY` | Property | Vertical offset. | | `tailDirection` | Property | Tail direction. | | `tailSize` | Property | Tail size. | | `show(text, duration)` | Method | Set text and show; optional duration hides automatically. | | `hide()` | Method | Hide the bubble. | ## Examples ``` this.speechBubble.show("Hello!", 2); ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # ChatLog > Vaelis 1.0.0 ChatLog component reference: fields, script API, behavior and examples. > **Scope:** This page documents the ChatLog component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Top UI → Chat Log, or Inspector → Add Component → Chat Log. ## What it does Scrollable-style conversation log component for UI dialogue. > **Component setup & editor tools:** ChatLog provides a dialogue/log display component intended for scripted text updates. ## How to add and use ChatLog **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **ChatLog** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Inspector → ChatLog: configure the log; use its script-facing API for runtime messages/entries. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `messages` | array | Current messages. | `[]` | | `maxMessages` | number | Maximum retained messages. | `50` | | `visibleCount` | number | Messages visible at once. | `6` | | `width` | number | Log width. | `320` | | `lineHeight` | number | Line height. | `26` | | `fontSize` | number | Font size. | `16` | | `fontFamily` | string | Font family. | `Arial` | | `messageColor` | hex string | Message color. | `#ffffff` | | `senderColor` | hex string | Sender name color. | `#ffd700` | | `backgroundColor` | hex string | Background. | `#000000` | | `backgroundOpacity` | number | Background opacity. | `0.5` | | `padding` | number | Padding. | `10` | | `showSender` | boolean | Show sender names. | `true` | | `screenSpace` | boolean | Use screen-space UI behavior. | `true` | | `visible` | boolean | Visibility. | `true` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `maxMessages` | Total retained history before oldest messages are dropped. | | `visibleCount` | How many recent messages are shown at once. | | `backgroundOpacity` | 0 transparent, 1 opaque. | | `lineHeight` | Higher creates more vertical spacing between messages. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `messages` | Property | Read-only snapshot of messages {sender,text,senderColor}. | | `maxMessages` | Property | Maximum retained messages. | | `visibleCount` | Property | Number of visible rows. | | `width` | Property | Panel width. | | `lineHeight` | Property | Line height. | | `fontSize` | Property | Font size. | | `fontFamily` | Property | Font family. | | `messageColor` | Property | Message color. | | `senderColor` | Property | Default sender color. | | `backgroundColor` | Property | Background color. | | `backgroundOpacity` | Property | Background opacity. | | `padding` | Property | Padding. | | `showSender` | Property | Show sender names. | | `screenSpace` | Property | Screen-space mode. | | `visible` | Property | Visibility. | | `send(sender, text, color)` | Method | Append a message. | | `clear()` | Method | Clear the log. | ## Examples ``` this.chat.send("Guard", "Halt!", "#ef4444"); ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # TextInput > Vaelis 1.0.0 TextInput component reference: fields, script API, behavior and examples. > **Scope:** This page documents the TextInput component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Top UI → Message Input, or Inspector → Add Component → Text Input. ## What it does Interactive text input control driven by the runtime UI system. > **Component setup & editor tools:** TextInput creates an editable text-entry control and is typically created from GameObject → UI or the Inspector Add Component picker. ## How to add and use TextInput **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **TextInput** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - GameObject → UI → Message Input creates a TextInput entity. You can also select an entity → Inspector → Add Component → Text Input. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `value` | string | Current text. | | | `placeholder` | string | Placeholder text. | `Type a message...` | | `maxLength` | number | Maximum characters. | `200` | | `fontSize` | number | Font size. | `18` | | `fontFamily` | string | Font family. | `Arial` | | `textColor` | hex string | Text color. | `#111111` | | `placeholderColor` | hex string | Placeholder color. | `#999999` | | `backgroundColor` | hex string | Background. | `#ffffff` | | `borderColor` | hex string | Border. | `#888888` | | `borderWidth` | number | Border width. | `2` | | `cornerRadius` | number | Corner radius. | `8` | | `width` | number | Control width. | `260` | | `height` | number | Control height. | `40` | | `padding` | number | Horizontal/vertical padding. | `10` | | `clearOnSubmit` | boolean | Clear after submit. | `true` | | `focused` | boolean | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `false` | | `justSubmitted` | boolean | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `false` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `maxLength` | Hard cap on typed characters. | | `width / height` | Changes the visual input box size. | | `borderWidth` | Higher = thicker border. | | `padding` | Higher moves the text farther from the box edge. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `value` | Property | Text value. | | `placeholder` | Property | Placeholder. | | `maxLength` | Property | Character cap. | | `fontSize` | Property | Font size. | | `fontFamily` | Property | Font family. | | `textColor` | Property | Text color. | | `placeholderColor` | Property | Placeholder color. | | `backgroundColor` | Property | Background color. | | `borderColor` | Property | Border color. | | `borderWidth` | Property | Border width. | | `cornerRadius` | Property | Corner radius. | | `width` | Property | Control width. | | `height` | Property | Control height. | | `padding` | Property | Padding. | | `clearOnSubmit` | Property | Whether submit clears the text. | | `focused` | Property | Read-only focus state. | | `justSubmitted` | Property | Read-only one-frame submit pulse. | | `clear()` | Method | Clear the current input. | ## Examples ``` if (this.textInput.justSubmitted) { sendMessage("Chat", "message", this.textInput.value); this.textInput.clear(); } ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # Joystick > Vaelis 1.0.0 Joystick component reference: fields, script API, behavior and examples. > **Scope:** This page documents the Joystick component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Top UI → Joystick, or Inspector → Add Component → Joystick. ## What it does Virtual touch joystick for mobile and pointer-driven control schemes. > **Component setup & editor tools:** Joystick provides a touch/drag virtual control for mobile-oriented input. ## How to add and use Joystick **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **Joystick** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - GameObject → UI → Joystick creates a joystick entity. You can also select an entity → Inspector → Add Component → Joystick. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `positionMode` | enum | Fixed or pointer-positioned joystick. | `Fixed` | | `regionX` | number | Region X. | `0` | | `regionY` | number | Region Y. | `0` | | `regionWidth` | number | Region width. | `640` | | `regionHeight` | number | Region height. | `720` | | `baseRadius` | number | Base radius. | `60` | | `knobRadius` | number | Knob radius. | `28` | | `baseColor` | hex string | Base color. | `#ffffff` | | `baseOpacity` | number | Base opacity. | `0.25` | | `knobColor` | hex string | Knob color. | `#ffffff` | | `knobOpacity` | number | Knob opacity. | `0.6` | | `outlineColor` | hex string | Outline color. | `#ffffff` | | `outlineWidth` | number | Outline width. | `2` | | `deadZone` | number | Input dead zone. | `0.1` | | `returnToCenter` | boolean | Knob returns to center when released. | `true` | | `hideWhenIdle` | boolean | Hide when idle. | `false` | | `idleOpacityMultiplier` | number | Opacity multiplier while idle. | `0.35` | | `x` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | | `y` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | | `magnitude` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | | `angle` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | | `active` | boolean | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `false` | | `baseScreenX` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | | `baseScreenY` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `deadZone` | 0 means even tiny stick displacement is reported; increasing it keeps small movements at zero until the knob moves farther. | | `baseRadius / knobRadius` | Larger values make the on-screen joystick physically larger. | | `idleOpacityMultiplier` | Lower makes an idle joystick more transparent when hideWhenIdle is false. | | `returnToCenter` | True snaps back on release; false preserves the last knob position. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `x` | Property | Normalized horizontal input, typically -1..1 (read-only). | | `y` | Property | Normalized vertical input, typically -1..1 (read-only). | | `magnitude` | Property | Input magnitude (read-only). | | `angle` | Property | Input angle (read-only). | | `active` | Property | Whether the joystick is engaged (read-only). | | `positionMode` | Property | Joystick positioning mode. | | `regionX` | Property | Touch/pointer region X. | | `regionY` | Property | Touch/pointer region Y. | | `regionWidth` | Property | Region width. | | `regionHeight` | Property | Region height. | | `baseRadius` | Property | Base radius. | | `knobRadius` | Property | Knob radius. | | `deadZone` | Property | Dead-zone threshold. | | `returnToCenter` | Property | Return-to-center behavior. | | `baseColor` | Property | Available on this module. | | `baseOpacity` | Property | Available on this module. | | `hideWhenIdle` | Property | true = invisible until actively being dragged. | | `idleOpacityMultiplier` | Property | Available on this module. | | `knobColor` | Property | Available on this module. | | `knobOpacity` | Property | Available on this module. | | `outlineColor` | Property | Available on this module. | | `outlineWidth` | Property | Available on this module. | ## Examples ``` this.rigidbody.velocityX = this.joystick.x * 250; ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # Rigidbody2D > Vaelis 1.0.0 Rigidbody2D component reference: fields, script API, behavior and examples. > **Scope:** This page documents the Rigidbody2D component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector (right) → Add Component → Rigidbody 2D. Pair with Collider 2D for a colliding body. Edit → Physics Layers… controls named layer slots. ## What it does 2D physics body backed by the engine physics runtime. Dynamic, Kinematic and Static bodies have different script controls. > **Component setup & editor tools:** Rigidbody2D gives an entity a Rapier 2D body. Collider2D is normally paired with it when physical contact is required. ## How to add and use Rigidbody2D **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **Rigidbody2D** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select entity → Inspector → Add Component → Rigidbody 2D. After adding it, the Rigidbody2D section exposes body type, gravity/damping, velocity/drive values, rotation locking, and controller/ground state fields. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `bodyType` | enum | Dynamic | Kinematic | Static. | `Dynamic` | | `simulated` | boolean | Whether the body participates in physics simulation. | `true` | | `mass` | number | Dynamic body mass. | `1` | | `autoMass` | boolean | See the Inspector field of the same name. | `true` | | `gravityScale` | number | Gravity multiplier. | `1` | | `linearDamping` | number | Linear damping. | `0` | | `angularDamping` | number | Angular damping. | `0` | | `lockRotation` | boolean | Prevent rotation. | `false` | | `velocityX` | number | X velocity. | `0` | | `velocityY` | number | Y velocity. | `0` | | `angularVelocity` | number | Angular velocity. | `0` | | `driveVelocityX` | number | null | Set transiently by the engine (controller/navigation input); not an authored setting. *(engine-managed runtime state)* | `null` | | `driveVelocityY` | number | null | Set transiently by the engine (controller/navigation input); not an authored setting. *(engine-managed runtime state)* | `null` | | `driveAngularVelocity` | number | null | Set transiently by the engine (controller/navigation input); not an authored setting. *(engine-managed runtime state)* | `null` | | `grounded` | boolean | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `false` | | `resolvedVelocityX` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | | `resolvedVelocityY` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | | `pendingForceX` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | | `pendingForceY` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | | `pendingImpulseX` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | | `pendingImpulseY` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | | `pendingTorque` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | | `pendingAngularImpulse` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `mass` | Higher mass makes the body harder to accelerate from the same force/impulse. It does not make gravity itself stronger. | | `gravityScale` | 1 is the normal engine gravity response for Dynamic bodies; 2 doubles it; 0 disables gravity contribution. | | `linearDamping` | Higher values remove linear velocity faster; 0 leaves the body with no linear damping. | | `angularDamping` | Higher values remove rotational velocity faster. | ## Automatic mass and force at a point - `autoMass` (default `true`): a Dynamic body computes its mass from the attached collider geometry and density. Uncheck it in the Inspector to use the `mass` value instead. - `angularDamping`: resistance to spinning, separate from linear damping. - `addForceAtPoint(...)` in the script API pushes the body at a world point, so it also creates torque. ## Script API | Member | Kind | Description | | --- | --- | --- | | `type` | Property | Dynamic | Kinematic | Static; switching type is supported at runtime. | | `velocity` | Property | {x,y} velocity. | | `velocityX` | Property | Horizontal velocity. | | `velocityY` | Property | Vertical velocity. | | `mass` | Property | Dynamic mass. | | `gravityScale` | Property | Gravity multiplier. | | `linearDamping` | Property | Linear damping. | | `angularDamping` | Property | Angular damping. | | `addForce(x,y)` | Method | Apply force to a Dynamic body. | | `addImpulse(x,y)` | Method | Apply impulse to a Dynamic body. | | `addTorque(t)` | Method | Apply torque. | | `addAngularImpulse(t)` | Method | Apply angular impulse. | | `isGrounded` | Property | Current ground contact state. | | `move(dx,dy)` | Method | Kinematic movement request. | | `isOnCeiling` | Property | Kinematic contact state. | | `isOnWall` | Property | Kinematic contact state. | | `isOnSlope` | Property | Kinematic contact state. | | `groundAngle` | Property | Kinematic ground angle. | | `resolvedVelocity` | Property | Kinematic velocity after collision resolution. | | `addForceAtPoint(…)` | Method | Applies a force at a world-space point. | | `groundAngleLimit` | Property | Maximum angle from horizontal (degrees) that counts as walkable ground for THIS body. | | `grounded` | Property (read-only) | Deprecated alias for isGrounded — kept for compatibility with existing scripts. | | `slopeMinAngle` | Property | Minimum groundAngle (degrees) before isOnSlope becomes true. | | `wallAngleLimit` | Property | Contacts between groundAngleLimit and this angle (degrees) are "too steep" but NOT walls. | ## Notes & behavior - Kinematic-only methods are meaningful for Kinematic bodies; Dynamic-only force methods apply to Dynamic bodies. - Position assignment through this.x/this.y is treated as a physics teleport target for non-static bodies. ## Examples ``` this.rigidbody.addImpulse(0, -350); ``` ``` this.rigidbody.velocityX = 200; ``` ``` this.rigidbody.move(100 * time.deltaTime, 0); ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # Collider2D > Vaelis 1.0.0 Collider2D component reference: fields, script API, behavior and examples. > **Scope:** This page documents the Collider2D component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector → Add Component → Collider 2D. One-way platform, trigger, shape, friction, restitution, density, layer and mask settings live here. ## What it does Physics collision shape and contact filtering. A Collider2D is also required for accurate pointer/touch hit tests. > **Component setup & editor tools:** Collider2D defines the collision/trigger shape used by the physics system. ## How to add and use Collider2D **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **Collider2D** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select entity → Inspector → Add Component → Collider 2D. After adding it, edit Shape, dimensions, Offset, Trigger, Friction, Restitution, Density, Layer, and Mask in the Collider2D section. The viewport Collider gizmo shows the collision shape. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `shape` | enum | Box | Circle | Capsule | Triangle. | `Box` | | `width` | number | Box width. | `1` | | `height` | number | Box height. | `1` | | `radius` | number | Circle radius. | `0.5` | | `capsuleHalfHeight` | number | Capsule half-height. | `0.5` | | `capsuleRadius` | number | Capsule radius. | `0.3` | | `trianglePoints` | 3 points | Triangle vertices in local space. | `[{x:-0.5,y:0.5}, {x:0.5,y:0.5}, {x:0,y:-0.5}]` | | `offsetX` | number | Local X offset. | `0` | | `offsetY` | number | Local Y offset. | `0` | | `isTrigger` | boolean | Trigger-only collider. | `false` | | `isOneWayPlatform` | boolean | One-way platform behavior. | `false` | | `friction` | number | Surface friction. | `0.5` | | `restitution` | number | Bounciness. | `0` | | `density` | number | Density. | `1` | | `layer` | 0-15 | Collision layer. | `0` | | `mask` | 16-bit mask | Layers this collider can interact with. | `0xFFFF` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `restitution` | 0 behaves as non-bouncy; increasing it produces more bounce. Keep in a physically sensible range for predictable results. | | `friction` | Higher values resist sliding more strongly. Lower values let contacts slide more easily. | | `density` | Affects mass/inertia when the physics world builds the body from colliders; it is not a direct “heaviness” multiplier on gravity. | | `offsetX / offsetY` | Moves the collider relative to the entity’s pivot; positive X/right and positive Y/down in world-space convention. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `shape` | Property | Box | Circle | Capsule | Triangle. | | `width` | Property | Box width. | | `height` | Property | Box height. | | `radius` | Property | Circle radius. | | `capsuleHalfHeight` | Property | Capsule half-height. | | `capsuleRadius` | Property | Capsule radius. | | `offset` | Property | {x,y} collider offset. | | `isTrigger` | Property | Trigger-only collider. | | `isOneWayPlatform` | Property | One-way platform flag. | | `friction` | Property | Friction. | | `restitution` | Property | Restitution. | | `density` | Property | Density. | | `layer` | Property | Layer index 0-15. | | `mask` | Property | 16-bit interaction mask. | | `isColliding` | Property | Read-only contact state. | ## Notes & behavior - Collision layers use 16 membership layers (0-15). The mask determines which layers the collider can interact with. - One-way platforms are intended to block from one side while allowing traversal from the non-blocking side. ## Examples ``` this.collider.isTrigger = true; ``` ``` this.collider.layer = 2; ``` ``` this.collider.mask = 0xFFFF; ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # Joint2D > Vaelis 1.0.0 Joint2D component reference: fields, script API, behavior and examples. > **Scope:** This page documents the Joint2D component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector → Add Component → Joint 2D; choose Fixed/Revolute/Prismatic/Rope/Spring and configure anchors/limits/motor. ## What it does Connect physics bodies with Fixed, Revolute, Prismatic, Rope or Spring constraints. > **Component setup & editor tools:** Joint2D constrains one physics body relative to another and requires compatible Rigidbody2D setup. ## How to add and use Joint2D **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **Joint2D** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select entity → Inspector → Add Component → Joint 2D. Configure the joint from its Inspector section and make sure the connected physics bodies satisfy the joint’s requirements. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `jointType` | enum | Fixed | Revolute | Prismatic | Rope | Spring. | `Revolute` | | `connectedEntityId` | string|null | Entity ID of the connected body, or null for a world anchor. | `null` | | `anchor1X` | number | Local anchor X on this entity. | `0` | | `anchor1Y` | number | Local anchor Y on this entity. | `0` | | `anchor2X` | number | Local anchor X on the connected body/world anchor. | `0` | | `anchor2Y` | number | Local anchor Y on the connected body/world anchor. | `0` | | `axisX` | number | Prismatic axis X. | `1` | | `axisY` | number | Prismatic axis Y. | `0` | | `length` | number | Rope maximum length or Spring rest length. | `100` | | `stiffness` | number | Spring stiffness. | `6000` | | `damping` | number | Spring damping. | `18` | | `flexibility` | number | Revolute only: how freely the connected body may rotate. | `100` | | `segmentCount` | integer | Rope/Spring visual/physical segments. | `18` | | `ropeMass` | number | Mass per rope/spring segment. | `0.5` | | `visualEnabled` | boolean | Enable visual joint rendering. | `true` | | `visualColor` | hex string | Joint/rope visual color. | `#c8a66a` | | `visualThickness` | number | Visual thickness. | `3` | | `useTexture` | boolean | Use texture for rope-like visuals. | `false` | | `textureKey` | string|null | Texture asset key. | `null` | | `textureMode` | enum | stretch | tile. | `stretch` | | `textureTiling` | number | Tiling length. | `32` | | `textureScale` | number | Texture scale. | `1` | | `textureOffset` | number | Texture offset. | `0` | | `textureFlip` | boolean | Flip texture. | `false` | | `limitsEnabled` | boolean | Enable joint angle/position limits where supported. | `false` | | `limitMin` | number | Minimum limit. | `-45` | | `limitMax` | number | Maximum limit. | `45` | | `motorEnabled` | boolean | Enable motor. | `false` | | `motorSpeed` | number | Motor target speed. | `0` | | `motorMaxForce` | number | Maximum motor force. | `0` | | `jointDrag` | number | Revolute-only passive rotational response. | `0` | | `restStiffness` | number | See the Inspector field of the same name. | `0` | | `breakable` | boolean | Revolute-only structural failure. | `false` | | `breakForce` | number | See the Inspector field of the same name. | `10000` | | `disableConnectedCollision` | boolean | When enabled, only this joint's two connected entities stop generating contact pairs with one another. | `false` | | `collideConnected` | boolean | Allow connected bodies to collide. | `undefined` | | `enabled` | boolean | Enable the joint. | `true` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `length` | For Rope/Spring, higher length increases the rest/maximum link distance depending on the joint type. | | `stiffness` | For Spring, higher values pull toward the rest length more strongly. | | `damping` | Higher damping reduces oscillation faster. | | `segmentCount` | Rope visual/solver subdivision count; higher can look smoother but costs more. | ## Breakable joints and drag - `breakable` / `breakForce` (Revolute only): when the joint load exceeds `breakForce` the joint snaps apart. Script `joint.breakable` and `joint.breakForce`. - `jointDrag` and `restStiffness` (Revolute only): drag/damping and the springiness that pulls the joint back to its rest pose. - `disableConnectedCollision`: stop the two connected bodies from colliding with each other. It replaces the old `collideConnected` field, which is kept only for loading older projects. ## Script API | Member | Kind | Description | | --- | --- | --- | | `jointType` | Property | Joint type. | | `connectedEntity` | Property | Connected entity context, when one exists. | | `anchor1` | Property | {x,y} local anchor on this body. | | `anchor2` | Property | {x,y} local anchor on connected body/world anchor. | | `axis` | Property | {x,y} prismatic axis. | | `length` | Property | Joint length/rest length. | | `stiffness` | Property | Spring stiffness. | | `damping` | Property | Spring damping. | | `segmentCount` | Property | Rope/spring segment count. | | `ropeMass` | Property | Rope/spring segment mass. | | `visualEnabled` | Property | Visual enabled. | | `visualColor` | Property | Visual color. | | `visualThickness` | Property | Visual thickness. | | `useTexture` | Property | Use texture. | | `textureKey` | Property | Texture asset key. | | `textureMode` | Property | stretch | tile. | | `textureTiling` | Property | Texture tiling. | | `textureScale` | Property | Texture scale. | | `textureOffset` | Property | Texture offset. | | `textureFlip` | Property | Texture flip. | | `limitsEnabled` | Property | Limits enabled. | | `limitMin` | Property | Minimum limit. | | `limitMax` | Property | Maximum limit. | | `motorEnabled` | Property | Motor enabled. | | `motorSpeed` | Property | Motor speed. | | `motorMaxForce` | Property | Maximum motor force. | | `collideConnected` | Property | Collision between connected bodies. | | `enabled` | Property | Joint enabled. | | `breakForce` | Property | Available on this module. | | `breakable` | Property | Revolute-only: enables structural breaking when estimated joint demand exceeds breakForce. | | `disableConnectedCollision` | Property | Available on this module. | | `jointDrag` | Property | Revolute-only passive rotational drag/damping. | | `restStiffness` | Property | Revolute-only torsional stiffness toward the joint's creation/rest angle. | ## Examples ``` this.joint.connectedEntity = findFirst("Target"); ``` ``` this.joint.jointType = "Spring"; ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # CharacterController > Vaelis 1.0.0 CharacterController component reference: fields, script API, behavior and examples. > **Scope:** This page documents the CharacterController component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector → Add Component → Movement Type. Pick Character Controller, Platformer, Top-Down, Car, Follow or Patrol; fields in the Inspector change with the selected mode. ## What it does High-level movement modes: Character Controller, Platformer, Top-Down, Car, Follow, Patrol and Free. > **Component setup & editor tools:** CharacterController provides the higher-level movement behaviors such as Platformer, Car, Follow, or Patrol when configured with the required physics components. ## How to add and use CharacterController **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **CharacterController** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select entity → Inspector → Add Component → Movement Type (CharacterController). Choose the controller type first; the Inspector then exposes the relevant movement fields. Platformer/Car/Follow/Patrol fields are not interchangeable—configure only the group belonging to the selected controller type. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `controllerType` | enum | Character Controller | Platformer | Top-Down | Car | Follow | Patrol | Free. | `Character Controller` | | `moveSpeed` | number | General movement speed. | `200` | | `acceleration` | number | Acceleration. | `20` | | `airControl` | number | Air control multiplier. | `0.5` | | `canJump` | boolean | Jump enabled. | `true` | | `jumpForce` | number | Jump impulse/velocity. | `420` | | `maxJumps` | integer | Maximum sequential jumps. | `1` | | `useGravity` | boolean | Use gravity where supported. | `true` | | `gravityScale` | number | Gravity multiplier. | `1` | | `useDefaultInput` | boolean | Use built-in input mapping. | `true` | | `maxSpeed` | number | Car maximum speed. | `350` | | `carAcceleration` | number | Car acceleration. | `200` | | `brakeForce` | number | Car braking force. | `400` | | `turnSpeed` | number | Car turning speed. | `150` | | `driftFactor` | number | Car drift behavior. | `0.92` | | `driveTowardArriveDistance` | number | Car drive-toward arrival distance. | `12` | | `targetName` | string | Follow target entity name. | | | `followSpeed` | number | Follow speed. | `150` | | `followDistance` | number | Follow spacing. | `5` | | `patrolDistance` | number | Patrol distance. | `150` | | `patrolMode` | enum | Platformer | Top-Down. | `Platformer` | | `patrolAxis` | enum | Horizontal | Vertical. | `Horizontal` | | `requestJump` | boolean | Set transiently by the engine (controller/navigation input); not an authored setting. *(engine-managed runtime state)* | `false` | | `requestMoveX` | value | null | Set transiently by the engine (controller/navigation input); not an authored setting. *(engine-managed runtime state)* | `null` | | `requestMoveY` | value | null | Set transiently by the engine (controller/navigation input); not an authored setting. *(engine-managed runtime state)* | `null` | | `requestThrottle` | value | null | Set transiently by the engine (controller/navigation input); not an authored setting. *(engine-managed runtime state)* | `null` | | `requestSteer` | value | null | Set transiently by the engine (controller/navigation input); not an authored setting. *(engine-managed runtime state)* | `null` | | `requestJoystickX` | value | null | Set transiently by the engine (controller/navigation input); not an authored setting. *(engine-managed runtime state)* | `null` | | `requestJoystickY` | value | null | Set transiently by the engine (controller/navigation input); not an authored setting. *(engine-managed runtime state)* | `null` | | `requestDriveTowardX` | value | null | Set transiently by the engine (controller/navigation input); not an authored setting. *(engine-managed runtime state)* | `null` | | `requestDriveTowardY` | value | null | Set transiently by the engine (controller/navigation input); not an authored setting. *(engine-managed runtime state)* | `null` | | `requestFlip` | boolean | Set transiently by the engine (controller/navigation input); not an authored setting. *(engine-managed runtime state)* | `false` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `moveSpeed` | Higher = faster target movement. | | `acceleration` | Higher = reaches the requested speed faster; lower = softer/slower ramp. | | `airControl` | For Platformer, 0 removes horizontal air steering; 1 gives full ground-like acceleration in air. | | `jumpForce` | Higher = stronger/faster upward launch; lower = shorter jump. | | `gravityScale` | 1 = normal controller gravity, 0 = no controller gravity; higher magnifies the pull. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `controllerType` | Property | Read-only movement type. | | `moveSpeed` | Property | Movement speed. | | `acceleration` | Property | Acceleration. | | `airControl` | Property | Air-control factor. | | `useGravity` | Property | Gravity toggle. | | `gravityScale` | Property | Gravity scale. | | `useDefaultInput` | Property | Built-in input mapping. | | `simulateMove(x,y)` | Method | Drive movement by script. | | `isGrounded` | Property | Ground state. | | `isOnCeiling` | Property | Ceiling contact. | | `isOnWall` | Property | Wall contact. | | `isOnSlope` | Property | Slope contact. | | `groundAngle` | Property | Ground angle. | | `canJump` | Property | Whether jumping is available. | | `jumpForce` | Property | Jump force. | | `maxJumps` | Property | Maximum jumps. | | `simulateJump()` | Method | Request a jump. | | `maxSpeed` | Property | Car maximum speed. | | `brakeForce` | Property | Car brake force. | | `turnSpeed` | Property | Car turn speed. | | `driftFactor` | Property | Car drift factor. | | `simulateDrive(throttle, steer)` | Method | Drive a Car controller by script. | | `simulateDriveJoystick(x,y)` | Method | Drive using joystick-style vector input. | | `simulateDriveToward(x,y)` | Method | Drive toward a world point. | | `targetName` | Property | Follow target name. | | `followSpeed` | Property | Follow speed. | | `followDistance` | Property | Follow distance. | | `patrolMode` | Property | Platformer | Top-Down. | | `patrolAxis` | Property | Horizontal | Vertical. | | `patrolDistance` | Property | Patrol distance. | | `flipDirection()` | Method | Reverse Patrol direction. | | `facingDirection` | Property | Current patrol facing direction. | | `driveTowardArriveDistance` | Property | Available on this module. | ## Notes & behavior - Car-only fields/actions are meaningful for the Car controller. Patrol has its own patrolMode and patrolAxis. Free is script-driven with no built-in input mapping. ## Examples ``` this.controller.simulateMove(input.keyDown("ArrowRight") ? 1 : 0, 0); ``` ``` this.controller.simulateJump(); ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # SpriteAnimation > Vaelis 1.0.0 SpriteAnimation component reference: fields, script API, behavior and examples. > **Scope:** This page documents the SpriteAnimation component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector → Add Component → Sprite Animation, then use the Animation editor window to create clips/import frames. The Animation editor is an editor window/modal, not the bottom Project panel. ## What it does Sprite-sheet/clip animation state on a SpriteRenderer. > **Component setup & editor tools:** SpriteAnimation stores clips and frames and is edited through the Animation Window. ## How to add and use SpriteAnimation **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **SpriteAnimation** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select entity → Inspector → SpriteAnimation → Open Animation Window. Create/edit clips, frames, FPS, looping, and playback there; use the Inspector for component-level playback state. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `clips` | array | Animation clip definitions. | `[]` | | `currentClipId` | string|null | Current clip. | `null` | | `playing` | boolean | Playback state. | `true` | | `speed` | number | Playback speed multiplier. | `1` | | `currentFrameIndex` | integer | Current frame index. | `0` | | `frameElapsed` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | ## Script API | Member | Kind | Description | | --- | --- | --- | | `play(name)` | Method | Play an animation clip. | | `stop()` | Method | Stop playback. | | `playing` | Property | Read-only playback state. | | `currentClip` | Property | Read-only current clip name. | | `currentFrame` | Property | Current frame index. | | `totalFrames` | Property | Read-only frame count. | | `speed` | Property | Playback speed. | ## Examples ``` this.animator.play("Run"); ``` ``` this.animator.speed = 1.5; ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # Camera > Vaelis 1.0.0 Camera component reference: fields, script API, behavior and examples. > **Scope:** This page documents the Camera component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector → Add Component → Camera. Main camera and scaling/presentation settings are edited in the Inspector; Play/Export use the same runtime camera path. ## What it does Orthographic 2D camera with reference resolutions, responsive scaling, follow, shake and optional pseudo-3D sprite depth scaling. > **Component setup & editor tools:** Camera controls the 2D view and rendering/scaling behavior. The Scene viewport exposes a camera gizmo when a Camera entity is selected. ## How to add and use Camera **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **Camera** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select the Camera entity → Inspector → Camera. The Camera gizmo appears in the Scene viewport. Mark the intended camera as Main and configure projection/scaling/aspect settings in the Inspector. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `backgroundColor` | hex string | Background color. | `#314D79` | | `projection` | string | Projection mode. | `Orthographic` | | `size` | number | Orthographic camera size. | `5` | | `nearClip` | number | Near clip. | `0.3` | | `farClip` | number | Far clip. | `1000` | | `isMain` | boolean | Whether this is the main camera. | `false` | | `aspectMode` | enum | Landscape | Portrait | Square | Custom. | `Landscape` | | `landscapeWidth` | number | Landscape reference width. | `960` | | `landscapeHeight` | number | Landscape reference height. | `540` | | `portraitWidth` | number | Portrait reference width. | `540` | | `portraitHeight` | number | Portrait reference height. | `960` | | `squareSize` | number | Square reference size. | `720` | | `customWidth` | number | Custom width. | `800` | | `customHeight` | number | Custom height. | `600` | | `enablePseudo3D` | boolean | Use Transform.z for sprite depth scaling. | `false` | | `renderToSpriteEntityId` | string | null | See the Inspector field of the same name. | `null` | | `scalingMode` | enum | Expand | Fit | Fill | Stretch. | `Fit` | | `keepHeight` | boolean | Axis choice used by Expand mode. | `true` | | `aspectRatioLock` | boolean | Lock aspect ratio. | `true` | | `allowStretching` | boolean | Allow distortion where applicable. | `false` | | `letterboxing` | enum | Auto | On | Off. | `Auto` | | `pillarboxing` | enum | Auto | On | Off. | `Auto` | | `barColor` | hex string | Letterbox/pillarbox color. | `#000000` | | `integerScaling` | boolean | Use integer scaling. | `false` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `size / zoom` | For this 2D camera, larger effective view size shows more world; increasing zoom makes the scene appear smaller/farther, while reducing it magnifies the world. | | `scalingMode` | FIT preserves the reference aspect and uses bars when necessary; FILL crops to fill; STRETCH changes aspect; EXPAND keeps the reference height and reveals more/less horizontal world. | | `integerScaling` | When enabled, device-fit scale is constrained toward integer multiples to keep pixel-art rendering crisp. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `zoom` | Property | Camera zoom/scale control. | | `backgroundColor` | Property | Background color. | | `shake(intensity,duration)` | Method | Camera shake. | | `follow(target, options)` | Method | Follow an entity; options can include smoothing. | | `stopFollow()` | Method | Stop following. | | `offsetX` | Property | Follow/render X offset. | | `offsetY` | Property | Follow/render Y offset. | | `renderToSprite(spriteEntity)` | Method | Render camera output to a sprite target. | | `aspectMode` | Property | Landscape | Portrait | Square | Custom. | | `landscapeWidth` | Property | Landscape reference width. | | `landscapeHeight` | Property | Landscape reference height. | | `portraitWidth` | Property | Portrait reference width. | | `portraitHeight` | Property | Portrait reference height. | | `squareSize` | Property | Square reference size. | | `customWidth` | Property | Custom width. | | `customHeight` | Property | Custom height. | | `enablePseudo3D` | Property | Enable Transform.z-based sprite depth scaling. | | `scalingMode` | Property | Expand | Fit | Fill | Stretch. | | `keepHeight` | Property | Expand axis behavior. | | `aspectRatioLock` | Property | Aspect lock. | | `allowStretching` | Property | Allow stretching. | | `letterboxing` | Property | Auto | On | Off. | | `pillarboxing` | Property | Auto | On | Off. | | `barColor` | Property | Bar color. | | `integerScaling` | Property | Integer scaling. | | `x` | Property | Camera world-space X position (same as this.x on the camera entity). | | `y` | Property | Camera world-space Y position (same as this.y on the camera entity). | ## Examples ``` var cam = findFirst("Main Camera"); ``` ``` cam.camera.follow(findFirst("Target"), { smoothing: 0.1 }); ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # AudioSource > Vaelis 1.0.0 AudioSource component reference: fields, script API, behavior and examples. > **Scope:** This page documents the AudioSource component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector → Add Component → Audio Source; audio assets are under bottom Project → Audio and can be assigned to Audio Source. ## What it does Play a local audio asset, optionally with distance-based 3D attenuation. > **Component setup & editor tools:** AudioSource plays an imported audio asset from an entity. ## How to add and use AudioSource **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **AudioSource** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select entity → Inspector → Add Component → Audio Source. Assign an imported audio asset in the AudioSource section and use the script API for playback/state control. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `audioKey` | string|null | Audio asset key. | `null` | | `is3D` | boolean | Enable distance attenuation. | `false` | | `volume` | number | Volume 0-1. | `1` | | `pitch` | number | Pitch multiplier; runtime API clamps to 0.25-4. | `1` | | `loop` | boolean | Loop playback. | `true` | | `autoplay` | boolean | Play automatically. | `true` | | `minDistance` | number | Full-volume distance for 3D audio. | `100` | | `maxDistance` | number | Silent distance for 3D audio. | `600` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `volume` | 0 silent; 1 the base configured level. | | `pitch` | 1 normal playback speed; >1 faster/higher; <1 slower/lower. | | `minDistance` | 3D only: inside this radius the source remains at full base volume. | | `maxDistance` | 3D only: beyond this radius the source is silent. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `play()` | Method | Start/restart playback. | | `playOnce()` | Method | Play without persistent looping. | | `stop()` | Method | Stop playback. | | `volume` | Property | Volume 0-1. | | `pitch` | Property | Pitch multiplier. | | `playing` | Property | Read-only playback state. | ## Examples ``` this.audio.playOnce(); ``` ``` this.audio.volume = 0.5; ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # AudioListener > Vaelis 1.0.0 AudioListener component reference: fields, script API, behavior and examples. > **Scope:** This page documents the AudioListener component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector → Add Component → Audio Listener. Usually keep one active listener in a scene for 3D hearing queries. ## What it does Defines the hearing area for 3D audio and drives audio enter/leave callbacks. > **Component setup & editor tools:** AudioListener defines the listening point used by positional audio behavior. ## How to add and use AudioListener **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **AudioListener** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select entity → Inspector → Add Component → Audio Listener. Use one intended listener for the active view; its radius/enabled settings control listening behavior. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `radius` | number | Hearing radius. | `300` | | `enabled` | boolean | See the Inspector field of the same name. | `true` | ## Script API | Member | Kind | Description | | --- | --- | --- | | `radius` | Property | Listener radius. | | `enabled` | Property | Enable/disable listener processing. | | `canHear(…)` | Method | True if the named (or tagged, with {byTag:true}) 3D AudioSource entity is currently within range of this listener — the beginner-friendly single-target check, so a… | | `sourcesInRange` | Property (read-only) | Every 3D AudioSource entity currently inside this listener's radius, as an array of live EntityContexts (empty array if none — never null, matches findAll()'s "always an… | ## Notes & behavior - With an AudioListener present, scripts can receive onHearSound(source) and onLoseSound(source) transitions. > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # Light > Vaelis 1.0.0 Light component reference: fields, script API, behavior and examples. > **Scope:** This page documents the Light component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Top GameObject → Light → Directional/Point/Spot/Area/God Rays/Freeform. Existing lights expose their settings in the Inspector. ## What it does 2D light source supporting Directional, Point, Spot, Area, GodRays and Freeform light shapes. > **Component setup & editor tools:** Light adds the engine’s 2D lighting source and exposes a viewport gizmo for spatial editing. ## How to add and use Light **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **Light** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select entity → Inspector → Add Component → Light. The Light gizmo appears in the Scene viewport; use it to position/edit freeform geometry where supported. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `type` | enum | Directional | Point | Spot | Area | GodRays | Freeform. | `Point` | | `color` | hex string | Light color. | `#ffffff` | | `intensity` | number | Light intensity. | `1` | | `radius` | number | Reach for Point/Spot/GodRays. | `200` | | `angle` | number | Cone angle for Spot/GodRays. | `45` | | `width` | number | Area-light width. | `200` | | `height` | number | Area-light height. | `200` | | `castsOnWorld` | boolean | Light the world. | `true` | | `castShadows` | boolean | Cast shadows. | `false` | | `shadowColor` | hex string | Shadow color. | `#000000` | | `shadowStrength` | number | Shadow strength. | `1` | | `flicker` | boolean | Flicker enabled. | `false` | | `flickerSpeed` | number | Flicker speed. | `8` | | `flickerDuration` | number | Flicker duration. | `0` | | `coreSize` | number | Visible light-core size. | `0.22` | | `coreVisible` | boolean | Show visible light core. | `true` | | `points` | array|null | Freeform local polygon points. | `null` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `intensity` | 0 is off; 1 is the normal baseline; >1 produces stronger/brighter illumination. | | `radius` | Larger values extend point/spot/area reach. Smaller values concentrate the light. | | `angle` | For Spot/God Rays, larger values widen the cone; 0 is very narrow. | | `shadowStrength` | 0 removes visible shadow contribution; 1 gives full light-side shadow strength. | | `flickerSpeed` | Higher = faster flicker cycles. | | `flickerDuration` | 0 = indefinite flicker when enabled; positive values stop the flicker after that many seconds. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `type` | Property | Light type. | | `color` | Property | Light color. | | `intensity` | Property | Intensity. | | `radius` | Property | Light radius. | | `angle` | Property | Spot/GodRays cone angle. | | `width` | Property | Area width. | | `height` | Property | Area height. | | `castsOnWorld` | Property | Affects world lighting. | | `castShadows` | Property | Shadow casting. | | `shadowColor` | Property | Shadow color. | | `shadowStrength` | Property | Shadow strength. | | `flicker` | Property | Flicker toggle. | | `flickerSpeed` | Property | Flicker speed. | | `flickerDuration` | Property | Flicker duration. | | `coreSize` | Property | Light core size. | | `coreVisible` | Property | Show light core. | ## Examples ``` this.light.intensity = 1.5; ``` ``` this.light.castShadows = true; ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # ShadowCaster > Vaelis 1.0.0 ShadowCaster component reference: fields, script API, behavior and examples. > **Scope:** This page documents the ShadowCaster component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector → Add Component → Shadow Caster. Enable it on objects that should occlude light; pair with a Light whose Cast Shadows is enabled. ## What it does Marks an entity as a shadow occluder for the lighting system. > **Component setup & editor tools:** ShadowCaster defines geometry that participates in the lighting/shadow system. ## How to add and use ShadowCaster **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **ShadowCaster** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select entity → Inspector → Add Component → Shadow Caster. Configure its serialized geometry in the Inspector and verify shadows in the viewport/game preview with a Light configured to cast shadows. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `enabled` | boolean | Enable shadow casting. | `true` | | `width` | number|null | Shadow source width; null can derive from visual bounds. | `null` | | `height` | number|null | Shadow source height; null can derive from visual bounds. | `null` | | `offsetX` | number | Shadow offset X. | `0` | | `offsetY` | number | Shadow offset Y. | `0` | | `opacity` | number | Shadow opacity. | `1` | | `length` | number | Shadow length multiplier. | `1` | | `softness` | number | Shadow softness. | `0` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `opacity` | 0 contributes no visible shadow; 1 is full caster contribution. | | `length` | 1 uses the light’s natural reach; 0.5 makes a shorter shadow; 2 makes it reach twice as far. | | `softness` | 0 is a crisp edge; increasing it broadens the penumbra. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `enabled` | Property | Enable shadow casting. | | `width` | Property | Explicit caster width. | | `height` | Property | Explicit caster height. | | `offsetX` | Property | X offset. | | `offsetY` | Property | Y offset. | | `opacity` | Property | Shadow opacity. | | `length` | Property | Shadow length. | | `softness` | Property | Shadow softness. | ## Examples ``` this.shadowCaster.length = 2; ``` ``` this.shadowCaster.softness = 0.25; ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # LightingSettings > Vaelis 1.0.0 LightingSettings component reference: fields, script API, behavior and examples. > **Scope:** This page documents the LightingSettings component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector → Add Component → Lighting Settings. This is scene-wide; one entity carrying the component supplies quality/mood values to the LightingSystem. ## What it does Scene-wide lighting quality and mood controls. Attach to one entity; the lighting system reads it scene-wide. > **Component setup & editor tools:** LightingSettings configures scene/entity lighting quality and ambient/shadow parameters used by the lighting system. ## How to add and use LightingSettings **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **LightingSettings** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select entity → Inspector → Add Component → Lighting Settings. Adjust quality/ambient/shadow parameters and verify changes with an active Light/ShadowCaster setup. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `shadowMode` | enum | quad | raymarch. | `quad` | | `raymarchSteps` | number | 1-200 raymarch steps; only used in raymarch mode. | `24` | | `ambientDarkness` | number | 0-1 darkness in unlit areas. | `0.65` | | `glowStrength` | number | Visible light glow strength. | `1` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `ambientDarkness` | 0 leaves the unlit world bright; increasing toward 1 makes unlit areas darker. | | `glowStrength` | Higher makes open-air light glow more strongly; 0 removes visible glow. | | `raymarchSteps` | Higher improves raymarch shadow sampling but costs more GPU work; lower is cheaper but less detailed. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `shadowMode` | Property | quad | raymarch. | | `raymarchSteps` | Property | Raymarch sample count 1-200. | | `ambientDarkness` | Property | 0 = no darkening; 1 = darkest unlit areas. | | `glowStrength` | Property | Visible light glow strength. | ## Examples ``` scene.lighting.shadowMode = "raymarch"; ``` ``` scene.lighting.raymarchSteps = 48; ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # NavAgent2D > Vaelis 1.0.0 NavAgent2D component reference: fields, script API, behavior and examples. > **Scope:** This page documents the NavAgent2D component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector → Add Component → Nav Agent 2D. For radius and area painting, use the Nav toolbar after a Nav World 2D exists; Match Collider is in the Nav Agent inspector section. ## What it does Per-agent navigation settings and current path state for NavWorld2D pathfinding. > **Component setup & editor tools:** NavAgent2D is the moving-agent side of Vaelis navigation. It works with NavWorld2D and the navigation API. ## How to add and use NavAgent2D **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **NavAgent2D** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select the agent → Inspector → Add Component → Nav Agent 2D. Configure agent parameters, then use the NavWorld2D + navigation workflow before expecting paths. Runtime movement is driven by the NavAgent2D API. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `radius` | number | Agent clearance radius. | `16` | | `speed` | number | Preferred speed. | `120` | | `acceleration` | number | Acceleration. | `800` | | `deceleration` | number | Deceleration. | `1000` | | `stoppingDistance` | number | Arrival distance. | `1` | | `autoRepath` | boolean | Automatically recompute path. | `true` | | `repathInterval` | number | Minimum seconds between automatic repaths. | `0.35` | | `repathDistance` | number | Distance target can move before repathing. | `4` | | `avoidanceEnabled` | boolean | Obstacle/agent avoidance. | `true` | | `avoidancePriority` | number | Avoidance priority. | `50` | | `collabEnabled` | boolean | Vehicle/collaborative avoidance mode. | `false` | | `collabGroupRadius` | number | Collaborative group radius. | `96` | | `vehicleLookahead` | number | Vehicle path lookahead. | `72` | | `vehicleCornerLookahead` | number | Corner lookahead. | `110` | | `vehicleObstacleLookahead` | number | Obstacle lookahead. | `120` | | `vehicleObstacleWidth` | number | Obstacle width estimate. | `28` | | `vehicleSteerSmoothing` | number | Steering smoothing. | `7` | | `vehicleSpeedSmoothing` | number | Speed smoothing. | `5` | | `vehicleCornerSlowdown` | number | Corner slowdown multiplier. | `0.72` | | `vehicleObstacleBrake` | number | Obstacle braking factor. | `0.9` | | `vehicleRecoveryTime` | number | Recovery time. | `1.35` | | `vehicleRecoveryReverseTime` | number | Reverse recovery time. | `0.9` | | `area` | 16-bit mask | Allowed navigation areas. | `0xffff` | | `areaCosts` | array|null | Optional 16-entry per-agent cost overrides. | `null` | | `currentPath` | value | null | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `null` | | `currentPathIndex` | number | Written by the engine each frame; not an authored setting. *(engine-managed runtime state)* | `0` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `radius` | The clearance needed around this agent. Larger radius makes narrow passages become non-walkable for this agent. | | `speed` | Top travel speed in world units/second. | | `acceleration / deceleration` | Higher values make movement and stopping snappier; lower values make it softer. | | `stoppingDistance` | Larger values let the agent stop farther from the final target. | | `repathInterval` | Lower reacts faster to changing routes/targets but costs more path queries. | | `area` | Hard allowed-area mask; excluding an area prevents the route from crossing it. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `radius` | Property | Agent radius. | | `speed` | Property | Preferred speed. | | `acceleration` | Property | Acceleration. | | `deceleration` | Property | Deceleration. | | `stoppingDistance` | Property | Stopping distance. | | `autoRepath` | Property | Auto-repath. | | `repathInterval` | Property | Repath interval. | | `repathDistance` | Property | Target-move repath threshold. | | `avoidanceEnabled` | Property | Avoidance toggle. | | `avoidancePriority` | Property | Avoidance priority. | | `collabEnabled` | Property | Collaborative vehicle avoidance. | | `collabGroupRadius` | Property | Group radius. | | `vehicleLookahead` | Property | Vehicle lookahead. | | `vehicleCornerLookahead` | Property | Corner lookahead. | | `vehicleObstacleLookahead` | Property | Obstacle lookahead. | | `vehicleObstacleWidth` | Property | Obstacle width. | | `vehicleSteerSmoothing` | Property | Steering smoothing. | | `vehicleSpeedSmoothing` | Property | Speed smoothing. | | `vehicleCornerSlowdown` | Property | Corner slowdown. | | `vehicleObstacleBrake` | Property | Obstacle brake factor. | | `vehicleRecoveryTime` | Property | Recovery time. | | `vehicleRecoveryReverseTime` | Property | Reverse recovery time. | | `area` | Property | Allowed area mask. | | `areaCosts` | Property | 16-entry area cost overrides. | | `currentPath` | Property | Read-only world-space waypoint array or null. | | `currentPathIndex` | Property | Read-only current waypoint index. | ## Examples ``` this.navAgent.speed = 180; ``` ``` this.navAgent.autoRepath = true; ``` > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # NavWorld2D > Vaelis 1.0.0 NavWorld2D component reference: fields, script API, behavior and examples. > **Scope:** This page documents the NavWorld2D component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Top GameObject → 2D Object → Nav World 2D. Once present, toolbar U/I/O brushes and Bounds/Cells view controls appear. Configure named areas with Edit → Nav Areas…. ## What it does Shared navigation world for baked or dynamic 2D pathfinding, with 16 navigation areas. > **Component setup & editor tools:** NavWorld2D owns the navigation world/bake configuration used by NavAgent2D and the navigation API. ## How to add and use NavWorld2D **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **NavWorld2D** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select/create an entity → Inspector → Add Component → Nav World 2D. Use the Navigation toolbar and Edit → Nav Areas… controls to define/bake the navigation world; then connect agents to it through the documented navigation workflow. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `boundsX` | number | World-space bounds X. | `-400` | | `boundsY` | number | World-space bounds Y. | `-400` | | `boundsWidth` | number | Bounds width. | `800` | | `boundsHeight` | number | Bounds height. | `800` | | `cellSize` | number | Navigation cell size. | `32` | | `cells` | sparse map | Authored filled cells. | `{}` | | `bakedCells` | data|null | Derived baked representation. | `null` | | `paintOverrides` | sparse map | Explicit walkability overrides. | `{}` | | `cellAreas` | sparse map | Per-cell area assignment overrides. | `{}` | | `areaCosts` | 16-entry array|null | Traversal cost multipliers. | `null` | | `allowDiagonal` | boolean | Allow diagonal A\* connections. | `false` | | `dynamic` | boolean | Rebuild from dynamic scene obstacles. | `false` | | `minObstacleFootprint` | number | Minimum obstacle footprint used for baking. | `0` | ## Tuning behavior These are the practical direction-of-change rules for the most important controls on this component. | Setting | What changing it does | | --- | --- | | `cellSize` | Smaller cells give a finer grid and can represent narrower corridors, but increase navigation work/memory. | | `allowDiagonal` | Off means 4-neighbor movement; on adds diagonal connections. | | `dynamic` | When enabled, navigation can be rebuilt dynamically from current geometry; use only when runtime rebaking is actually needed. | | `areaCosts` | 1 means neutral cost; 3 makes an allowed area approximately three times as expensive to traverse. Cost is preference, not a hard exclusion. | ## Script API | Member | Kind | Description | | --- | --- | --- | | `nav.findPath()` | Global | Find world-space path through a NavWorld2D. | | `nav.isWalkable()` | Global | Check a world-space point. | | `nav.bake()` | Global | Bake navigation data after authored changes. | | `nav.areaIndex` | Property | Current/selected navigation area index surface. | | `nav.areaMask` | Property | Navigation area mask. | | `nav.areaCosts` | Property | Navigation area costs. | ## Notes & behavior - NavWorld2D is a scene component; there is no `this.navWorld` object. Scripts use the global `nav` module. > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # Tileset > Vaelis 1.0.0 Tileset component reference: fields, script API, behavior and examples. > **Scope:** This page documents the Tileset component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Top GameObject → 2D Object → Tileset, then open the Tileset Editor window from the Inspector. Import one auto-sliced 4×4 sheet or 16 role images. ## What it does Defines a reusable 16-role autotile set. The editor can auto-slice one image or accept separate role images. > **Component setup & editor tools:** Tileset stores tile definitions used by Tilemap and is edited through the Tileset panel. ## How to add and use Tileset **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **Tileset** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select/create a Tileset entity → Inspector → Add Component → Tileset → open the Tileset panel. Define tile data there, then assign/use the Tileset from a Tilemap. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `name` | string | Tileset display name. | `New Tileset` | | `tileWidth` | number | Tile width in pixels/world units. | `32` | | `tileHeight` | number | Tile height. | `32` | | `slots` | object | 16 named autotile role → sprite asset key. | `{}` | ## Autotile roles | Slot | Role | Meaning | | --- | --- | --- | | 1 | `cornerTL` | Canonical role slot | | 2 | `edgeT` | Canonical role slot | | 3 | `cornerTR` | Canonical role slot | | 4 | `stubT` | Canonical role slot | | 5 | `edgeL` | Canonical role slot | | 6 | `center` | Canonical role slot | | 7 | `edgeR` | Canonical role slot | | 8 | `lineV` | Canonical role slot | | 9 | `cornerBL` | Canonical role slot | | 10 | `edgeB` | Canonical role slot | | 11 | `cornerBR` | Canonical role slot | | 12 | `stubB` | Canonical role slot | | 13 | `stubL` | Canonical role slot | | 14 | `lineH` | Canonical role slot | | 15 | `stubR` | Canonical role slot | | 16 | `single` | Canonical role slot | ## Notes & behavior - Autotile selection is computed from the four orthogonal neighbors; the stored Tilemap data is the filled-cell set, not a baked per-cell sprite choice. > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # Tilemap > Vaelis 1.0.0 Tilemap component reference: fields, script API, behavior and examples. > **Scope:** This page documents the Tilemap component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Top GameObject → 2D Object → Tilemap. Assign a Tileset entity in the Inspector; T and Y tools appear when a Tilemap/Tileset exists. ## What it does Sparse painted tile grid that references a Tileset entity by ID. > **Component setup & editor tools:** Tilemap paints a tile grid and exposes tilemap-specific viewport/panel tools. ## How to add and use Tilemap **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **Tilemap** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select/create a Tilemap entity → Inspector → Add Component → Tilemap. Use the Tilemap viewport/panel tools to paint the configured Tileset. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `tilesetEntityId` | string|null | Entity ID containing the Tileset component. | `null` | | `cells` | sparse object | Filled cell keys in `col,row` format. | `{}` | ## Notes & behavior - Tilemap has no dedicated `this.tilemap` script API in 1.0.0. It is edited as scene data by the editor and rendered by TilemapSystem. - Cells may use negative coordinates. The key format is `col,row`. > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components. --- # Script > Vaelis 1.0.0 Script component reference: fields, script API, behavior and examples. > **Scope:** This page documents the Script component in Vaelis 1.0.0. Runtime fields are serialized scene data; the Script API section lists only members intentionally exposed to game scripts. > **Where to find it in the editor:** Inspector → Add Component → Script, then use the script editor via the script asset/project item. IntelliSense completion is driven from the same runtime option metadata. ## What it does Script component holding a script name, source and enabled state. > **Component setup & editor tools:** Script attaches a JavaScript file to an entity. The Inspector provides Create New Script, Load Script…, and Open Script Editor controls. ## How to add and use Script **Editor path:** Select the target entity in the **Hierarchy** (left side) → look at the **Inspector** (right side) → click **Add Component** at the bottom of the Inspector → search for **Script** → click the component row. The Add Component picker is a centered modal with a search box; it only lists components not already attached. For components with a dedicated editor tool, the tool is opened or activated from the location described below. Do not assume that adding the component alone activates its editor; some systems require a separate window, panel, or viewport tool. ## Component setup & editor tools - Select entity → Inspector → Script section → Create New Script, Load Script…, or Open Script Editor. After attachment, Enabled controls whether the script runs. ### What you should see after adding it The component appears as its own section in the Inspector. Its serialized settings are listed in the **Component data** table below. If a field is conditional, it appears only when the relevant mode/type is selected. If a field is a runtime state field (for example grounded or resolved velocity), treat it as read-only diagnostic state unless the API reference explicitly documents it as writable. ### How to read the settings For every setting below, the documentation distinguishes **type**, **default**, **meaning**, and tuning direction where behavior is known. When a value represents a direction, use the engine's coordinate convention documented in [Coordinate system](../../reference/coordinate-system.html); do not substitute Unity/Godot conventions. ## Component data | Field | Type | Purpose | Default | | --- | --- | --- | --- | | `scriptName` | string | Script asset/name. | `NewScript` | | `source` | string | Script source code. | | | `enabled` | boolean | Whether the script is enabled. | `true` | ## Notes & behavior - Scripts are executed by ScriptSystem and receive the lifecycle/globals documented under Scripting. Script components are scene data rather than a `this.script` runtime API. > **Need the full workflow?:** Components: complete workflow covers adding, configuring, testing, combining, and removing components.