Files
railtrack-pro/js/tracks.js
T

190 lines
5.4 KiB
JavaScript

/**
* Railtrack Pro - Track Piece System
* Defines track geometries and placement logic
* @author Railtrack Pro Development Team
*/
class TrackPiece {
constructor(type, position, rotation) {
this.type = type; // 'straight', 'curved', 'junction', 'signal'
this.id = position ? Math.floor(Math.random() * 10000) : null;
this.position = position || new THREE.Vector3(0, 0, 0);
this.rotation = rotation || new THREE.Vector3(0, Math.PI / 2, 0);
this.connections = [];
this.geometry = null;
this.material = null;
this.mesh = null;
}
/**
* Create track piece in scene
*/
create(scene) {
this.geometry = this.getGeometry();
this.material = new THREE.MeshStandardMaterial({
color: 0x888888,
roughness: 0.6,
metalness: 0.4
});
this.mesh = new THREE.Mesh(this.geometry, this.material);
this.mesh.position.copy(this.position);
this.mesh.rotation.copy(this.rotation);
this.mesh.castShadow = true;
this.mesh.receiveShadow = true;
this.mesh.userData = { type: 'track', id: this.id, piece: this };
scene.add(this.mesh);
return this;
}
/**
* Get geometry based on track type
*/
getGeometry() {
switch (this.type) {
case 'straight':
return new THREE.BoxGeometry(1, 0.3, 2);
case 'curved':
return this.createCurvedGeometry();
case 'junction':
return this.createJunctionGeometry();
case 'signal':
return this.createSignalGeometry();
default:
return new THREE.BoxGeometry(1, 0.3, 2);
}
}
/**
* Create curved track geometry
*/
createCurvedGeometry() {
const points = [];
const segments = 20;
const radius = 2;
for (let i = 0; i <= segments; i++) {
const angle = (i / segments) * Math.PI;
const x = Math.sin(angle) * radius;
const z = -Math.cos(angle) * radius + radius;
points.push(new THREE.Vector3(x, 0, z));
}
const curve = new THREE.CatmullRomCurve3(points);
const geometry = new THREE.TubeGeometry(curve, segments, 0.5, 8, false);
return geometry;
}
/**
* Create junction track geometry (T-junction)
*/
createJunctionGeometry() {
const group = new THREE.Group();
// Main stem
const stem = new THREE.Mesh(
new THREE.BoxGeometry(1, 0.3, 2),
this.material
);
stem.position.set(0, 0, 1);
// Top branch
const top = new THREE.Mesh(
new THREE.BoxGeometry(1, 0.3, 2),
this.material
);
top.position.set(0, 0, -1);
// Side branch
const side = new THREE.Mesh(
new THREE.BoxGeometry(2, 0.3, 1),
this.material
);
side.position.set(0, 0, 0);
group.add(stem, top, side);
const geometry = new THREE.Group(group);
return geometry;
}
/**
* Create signal track piece
*/
createSignalGeometry() {
const group = new THREE.Group();
// Signal pole
const pole = new THREE.Mesh(
new THREE.CylinderGeometry(0.1, 0.1, 1.5),
new THREE.MeshStandardMaterial({ color: 0x333333 })
);
pole.position.set(0, 0.75, 0);
// Signal lights
const lightBox = new THREE.Mesh(
new THREE.BoxGeometry(0.3, 0.2, 0.1),
new THREE.MeshStandardMaterial({ color: 0xff0000 })
);
lightBox.position.set(0, 1.5, 0);
// Track base
const base = new THREE.Mesh(
new THREE.BoxGeometry(1, 0.3, 1),
this.material
);
base.position.set(0, 0, 0);
group.add(base, pole, lightBox);
const geometry = new THREE.Group(group);
return geometry;
}
/**
* Get connection points for track joining
*/
getConnectionPoints() {
const points = [];
switch (this.type) {
case 'straight':
points.push(new THREE.Vector3(0, 0, -1));
points.push(new THREE.Vector3(0, 0, 1));
break;
case 'curved':
points.push(new THREE.Vector3(0, 0, -2));
points.push(new THREE.Vector3(2, 0, 0));
break;
case 'junction':
points.push(new THREE.Vector3(0, 0, -2));
points.push(new THREE.Vector3(0, 0, 2));
points.push(new THREE.Vector3(-2, 0, 0));
points.push(new THREE.Vector3(2, 0, 0));
break;
}
return points;
}
}
/**
* Track type configuration
*/
const TrackConfig = {
types: {
straight: { name: 'Straight Track', color: 0x888888, cost: 10 },
curved: { name: 'Curved Track', color: 0x888888, cost: 15 },
junction: { name: 'Junction', color: 0x888888, cost: 25 },
signal: { name: 'Signal', color: 0xff0000, cost: 30 }
},
placement: {
snapDistance: 0.1,
maxConnections: 4
}
};
// Export for module usage
if (typeof module !== 'undefined' && module.exports) {
module.exports = { TrackPiece, TrackConfig };
}