Creating independent applications
Use the included templates/starter/ or templates/object-demo/ over the project server. Run node tools/create-app.mjs --template=starter --out=apps/my-app to create a standalone copy, then move that generated folder intact.
Serve the copied application over HTTP and open its index.html. There is no installation or build step. Native browser ES modules require the entire engine folder, including index.js, src/ and vendor/. Import from ./engine/index.js, and use that API's THREE namespace rather than loading another Three.js copy. The old ./engine/src/index.js path does not exist in 0.2.
my-application/
README.md
index.html
app.js
docs/
engine/
index.js
src/
vendor/
objects/ # optional
people/
beach/
Runtime does not depend on docs, the workshop, development tools/tests, the original source checkout or the original game. The examples in templates/ use the shared engine and object packages in this download. The create-app tool installs independent copies when you request a standalone application.
Engine-only application
The physics starter has no object packages. Its app.js creates terrain, a raised platform and falling spheres with standard Three.js meshes, Heightfield, SpatialWorld and MotionBody. Its two surfaces overlap horizontally but occupy different heights. Drag to orbit, scroll to zoom and add bodies with the button. This demonstrates non-flight collision queries and fixed-step/interpolated rendering; it does not implement a general rigid-body stacking solver.
Engine.mount receives a factory with {engine, scene, camera, scope, signal}. The factory returns optional fixedUpdate(dt), update({dt,time,alpha,engine}), configure and disposal hooks. Register service cleanup/listeners in the mount scope. The engine releases the previous scene when another mount succeeds. Use a fixed update for simulation and the render update for interpolation, presentation and object animations. engine.dispose() ends the application and releases renderer resources.
Static consumers can use continuous:false and call invalidate() when their view changes. Interactive simulations update continuously. The public entry exports generic rendering, terrain, weather, wind, motion, collision, geometry and resource services. Importing the entry does not instantiate an aircraft, person, tree, water effect or scene. The complete entry is not tree-shaken; selected modules are instantiated by the consumer.
Add independently copied objects
Copy only the object folders needed by the application, then import their classes and inject the engine namespace:
import * as api from './engine/index.js';
import {AuthoredPerson, loadAuthoredAssets} from './objects/people/authored/index.js';
import {BeachUmbrella} from './objects/beach/index.js';
const assets = await loadAuthoredAssets();
const person = new AuthoredPerson(api, {assets, height:1.72, clothing:'beach', seed:38});
const umbrella = new BeachUmbrella(api, {radius:1.2, color:0x497f88});
scene.add(person.root, umbrella.root);
person.setPosition(-1.5, 0, 0).setPose('wave');
umbrella.setPosition(1, 0, 0).setOpen(true);
// In the consumer's render-update hook:
person.update(dt, time);
umbrella.update(dt, time);
// When these objects are removed:
person.dispose();
umbrella.dispose();
An object's imports stay inside its own folder. The engine is an injected service, and one object package does not require a sibling package. Copy the entire package rather than extracting a model file and losing its local base, geometry, materials or manifest. Folder locations can be changed by changing only the application's import paths. The object's constructor does not embed an engine path.
The object-demo includes exactly people/ and beach/. Its controls call actual methods: wave/idle, open/close, canopy tilt and reconstruction from saved state. Its shared WindField is passed into the umbrella. The scene owns the wind service and choreography; each object owns its geometry, materials, textures and state. See object package guide for classes and lifecycle differences.
The detailed human data is included in the people folder; photograph uploads are not required. loadAuthoredAssets({signal}) reads package-local files and returns reusable CPU data. Cache that result in the application and pass it to each AuthoredPerson; instances own their mutable rig and GPU resources. detail:0 selects the base mesh, and detail:1 adds subdivision and closer hair detail. The original procedural Person remains available from people/index.js. See authored person for supported shape controls and current asset limitations.
Application and object responsibilities
The consumer chooses scene composition, camera, input, time progression, placement, navigation, terrain contacts and activity choreography. Object classes supply reusable model geometry and supported behavior. For example, NavalFighter animates controls and displays supplied flight state; the flight shell computes motion. Person can walk toward a supplied destination, but the consumer decides the destination and handles broader path planning. A Building does not automatically register a moving collider.
Use methods to change geometry-dependent properties; assigning to an arbitrary properties field does not necessarily rebuild a model. Keep engine units and each class's documented axis convention. If a class needs borrowed services such as terrain or wind, reinject them when reconstructing from serialized data. Do not assume every class serializes a complete executable scene. Dispose objects before discarding or replacing them, and do not share their owned materials between instances without an explicit ownership arrangement.
Verification and upgrades
Run the complete project's verifier against the generated application or an internal relocated copy. It must resolve all imports/assets inside that application's own folders and keep each engine/object package individually closed. Then inspect actual rendering, exercise controls, inspect browser resource/error reports and check repeated replacement/disposal. Removing docs/ from the test copy must leave runtime behavior intact. Preserve embedded dependency license notices.
Record the installed engine version and object protocol/package versions. Keep a restorable application copy, replace the complete engine folder with a selected compatible version, and run that application's checks. Object packages can be upgraded independently when their required engine protocol/services remain compatible. Fix shared engine defects in the engine project and reusable object defects in the appropriate package; keep application-specific changes in the consumer. Do not silently create divergent engine copies in every app.