California gets roads, traffic, and a car to follow
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
/** Render-layer contract tests that do not require a WebGL context. */
|
||||
|
||||
import assert from "node:assert/strict";
|
||||
import { describe, it } from "node:test";
|
||||
import * as THREE from "three";
|
||||
import type { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
|
||||
import CALIFORNIA_TRANSPORT from "../transport/california.ts";
|
||||
import { createRoadTrafficLayer } from "../engine/roadTraffic.ts";
|
||||
import type { World } from "../engine/world.ts";
|
||||
|
||||
function fixture() {
|
||||
const world = {
|
||||
project(lat: number, lng: number): [number, number] {
|
||||
return [(lng + 121) * 20, -(lat - 36) * 20];
|
||||
},
|
||||
groundAt(): number {
|
||||
return 0;
|
||||
},
|
||||
} as unknown as World;
|
||||
const camera = new THREE.PerspectiveCamera(42, 16 / 9, 0.1, 2_000);
|
||||
const controls = {
|
||||
target: new THREE.Vector3(),
|
||||
enabled: true,
|
||||
} as unknown as OrbitControls;
|
||||
const layer = createRoadTrafficLayer(world, camera, controls, {
|
||||
pack: CALIFORNIA_TRANSPORT,
|
||||
routeId: "la-sf-us-101",
|
||||
count: 8,
|
||||
seed: 115,
|
||||
});
|
||||
return { layer, camera, controls };
|
||||
}
|
||||
|
||||
describe("road traffic render layer", () => {
|
||||
it("draws one articulated hero and instanced background parts", () => {
|
||||
const { layer } = fixture();
|
||||
const hero = layer.group.getObjectByName("model-x-hero");
|
||||
assert.ok(hero);
|
||||
assert.equal(hero.scale.x, 0.18);
|
||||
assert.ok(layer.group.children.some((child) => child instanceof THREE.InstancedMesh));
|
||||
assert.equal(layer.hero()?.routeId, "la-sf-us-101");
|
||||
assert.ok(Math.abs(hero.position.y - 0.155) < 1e-9);
|
||||
layer.dispose();
|
||||
});
|
||||
|
||||
it("switches routes and owns the orbit-control handoff while following", () => {
|
||||
const { layer, camera, controls } = fixture();
|
||||
layer.setRoute("la-sf-i-5");
|
||||
assert.equal(layer.routeId(), "la-sf-i-5");
|
||||
assert.equal(layer.hero()?.routeId, "la-sf-i-5");
|
||||
|
||||
layer.setFollowing(true);
|
||||
assert.equal(layer.following(), true);
|
||||
assert.equal(controls.enabled, false);
|
||||
layer.tick(0.1);
|
||||
assert.ok(camera.position.toArray().every(Number.isFinite));
|
||||
assert.ok(controls.target.toArray().every(Number.isFinite));
|
||||
|
||||
layer.setCameraMode("driver");
|
||||
assert.equal(layer.cameraMode(), "driver");
|
||||
layer.tick(1 / 60);
|
||||
assert.ok(camera.position.y > layer.group.getObjectByName("model-x-hero")!.position.y);
|
||||
|
||||
layer.setFollowing(false);
|
||||
assert.equal(controls.enabled, true);
|
||||
layer.dispose();
|
||||
});
|
||||
|
||||
it("hands manual input to the deterministic hero and resumes assistance", () => {
|
||||
const { layer } = fixture();
|
||||
for (let index = 0; index < 20; index += 1) {
|
||||
layer.setVehicleActions({ throttle: 1, steering: 0.8 });
|
||||
layer.tick(1 / 30);
|
||||
}
|
||||
assert.equal(layer.hero().mode, "manual");
|
||||
assert.ok(layer.hero().lateralOffsetM > 0);
|
||||
|
||||
layer.setVehicleActions({ modeRequest: "assisted" });
|
||||
layer.tick(1 / 30);
|
||||
assert.equal(layer.hero().mode, "assisted");
|
||||
layer.dispose();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user