Spaces:
Running
Running
import * as THREE from "three"; | |
import { | |
PATH_POINTS, | |
ROAD_HALF_WIDTH, | |
GRID_CELL_SIZE, | |
} from "../config/gameConfig.js"; | |
export class PathBuilder { | |
constructor(scene) { | |
this.scene = scene; | |
// Clone and snap path points to the grid to ensure alignment | |
this.pathPoints = PATH_POINTS.map((p) => { | |
const snapped = p.clone | |
? p.clone() | |
: new THREE.Vector3(p.x, p.y ?? 0, p.z); | |
snapped.x = Math.round(snapped.x / GRID_CELL_SIZE) * GRID_CELL_SIZE; | |
snapped.z = Math.round(snapped.z / GRID_CELL_SIZE) * GRID_CELL_SIZE; | |
return snapped; | |
}); | |
this.roadMeshes = []; | |
// Materials | |
this.roadMat = new THREE.MeshStandardMaterial({ | |
color: 0x393c41, | |
metalness: 0.1, | |
roughness: 0.9, | |
}); | |
} | |
buildPath() { | |
// Visualize path line | |
this.createPathLine(); | |
// Build straight road segments only (no bevels or rounded corners) | |
for (let i = 0; i < this.pathPoints.length - 1; i++) { | |
this.addSegment(this.pathPoints[i], this.pathPoints[i + 1]); | |
} | |
} | |
createPathLine() { | |
const pathLineMat = new THREE.LineBasicMaterial({ color: 0xffff00 }); | |
const pathLineGeo = new THREE.BufferGeometry().setFromPoints( | |
this.pathPoints | |
); | |
const pathLine = new THREE.Line(pathLineGeo, pathLineMat); | |
pathLine.position.y = 0.01; | |
this.scene.add(pathLine); | |
} | |
addSegment(a, b) { | |
const seg = new THREE.Vector3().subVectors(b, a); | |
const len = seg.length(); | |
if (len <= 0.0001) return; | |
const mid = new THREE.Vector3().addVectors(a, b).multiplyScalar(0.5); | |
const roadGeo = new THREE.BoxGeometry(len, 0.1, ROAD_HALF_WIDTH * 2); | |
const road = new THREE.Mesh(roadGeo, this.roadMat); | |
road.castShadow = false; | |
road.receiveShadow = true; | |
road.position.set(mid.x, 0.05, mid.z); | |
const angle = Math.atan2(seg.z, seg.x); | |
road.rotation.y = -angle; | |
this.scene.add(road); | |
this.roadMeshes.push(road); | |
} | |
} | |