fix approval stat; save game; customize color

This commit is contained in:
Evan Scamehorn
2025-12-04 12:51:32 -06:00
parent e501a2c480
commit 8fc551ad68
8 changed files with 451 additions and 199 deletions

View File

@@ -3,31 +3,39 @@ import * as THREE from 'three';
export class VehicleSystem {
constructor(scene) {
this.scene = scene;
this.buses = []; // { mesh, points, dists, totalLen, currentDist, speed, direction }
this.buses = []; // { mesh, points, dists, totalLen, currentDist, speed, direction, routeIndex }
this.busGeom = new THREE.BoxGeometry(3.5, 4.0, 10.0);
this.busGeom.translate(0, 3.5, 0);
this.busMat = new THREE.MeshStandardMaterial({
color: 0xF59E0B, // Amber body
emissive: 0xB45309, // Slight orange glow so they don't get lost in shadow
emissiveIntensity: 0.4,
this.baseBusMat = new THREE.MeshStandardMaterial({
color: 0xF59E0B,
emissive: 0xB45309,
emissiveIntensity: 0.2,
roughness: 0.2
});
}
addBusToRoute(routePathPoints) {
addBusToRoute(routePathPoints, colorStr, routeIndex) {
if (!routePathPoints || routePathPoints.length < 2) return;
// Clone points to ensure they aren't affected by outside changes
const points = routePathPoints.map(p => p.clone());
const mesh = new THREE.Mesh(this.busGeom, this.busMat);
// Create material specific to this bus/route
const mat = this.baseBusMat.clone();
if (colorStr) {
mat.color.set(colorStr);
// Slight emissive tint of same color
const c = new THREE.Color(colorStr);
mat.emissive.set(c.multiplyScalar(0.5));
}
const mesh = new THREE.Mesh(this.busGeom, mat);
mesh.position.copy(points[0]);
mesh.castShadow = true;
this.scene.add(mesh);
// Pre-calculate cumulative distances for smooth interpolation
// Pre-calculate
let totalLen = 0;
const dists = [0];
for (let i = 0; i < points.length - 1; i++) {
@@ -42,17 +50,36 @@ export class VehicleSystem {
dists: dists,
totalLen: totalLen,
currentDist: 0,
speed: 40, // Speed in units/sec
direction: 1 // 1 = Forward, -1 = Backward
speed: 40,
direction: 1,
routeIndex: routeIndex
});
}
updateRouteColor(routeIndex, hexColor) {
// Update all buses belonging to this route
this.buses.forEach(bus => {
if (bus.routeIndex === routeIndex) {
bus.mesh.material.color.set(hexColor);
const c = new THREE.Color(hexColor);
bus.mesh.material.emissive.set(c.multiplyScalar(0.5));
}
});
}
clearVehicles() {
this.buses.forEach(bus => {
this.scene.remove(bus.mesh);
bus.mesh.geometry.dispose();
bus.mesh.material.dispose();
});
this.buses = [];
}
update(deltaTime) {
this.buses.forEach(bus => {
// 1. Move
bus.currentDist += bus.speed * deltaTime * bus.direction;
// 2. Check Bounds & Reversal
if (bus.currentDist >= bus.totalLen) {
bus.currentDist = bus.totalLen;
bus.direction = -1;
@@ -61,27 +88,20 @@ export class VehicleSystem {
bus.direction = 1;
}
// 3. Find current segment index
let i = 0;
// Simple linear search (efficient enough for small N points)
while (i < bus.dists.length - 2 && bus.currentDist > bus.dists[i + 1]) {
i++;
}
// 4. Interpolate Position
const startDist = bus.dists[i];
const endDist = bus.dists[i + 1];
const segmentLen = endDist - startDist;
// Avoid divide by zero if 2 points are identical
const alpha = segmentLen > 0.0001 ? (bus.currentDist - startDist) / segmentLen : 0;
const pStart = bus.points[i];
const pEnd = bus.points[i + 1];
bus.mesh.position.lerpVectors(pStart, pEnd, alpha);
// 5. Rotation (Look at target)
const lookTarget = bus.direction === 1 ? pEnd : pStart;
bus.mesh.lookAt(lookTarget);
});