Files

165 lines
4.2 KiB
JavaScript

/**
* Railtrack Pro - World Management
* Handles grid system, track placement, and world state
* @author Railtrack Pro Development Team
*/
class World {
constructor(renderer) {
this.renderer = renderer;
this.gridSize = 100;
this.gridUnit = 1; // Grid unit size
this.tracks = [];
this.selectedType = null;
this.snapDistance = 0.1;
this.isPlacementMode = false;
this.initGrid();
}
/**
* Initialize grid system
*/
initGrid() {
this.gridHelper = this.renderer.gridHelper;
console.log('[World] Grid system initialized');
}
/**
* Snap position to nearest grid point
*/
snapToGrid(position) {
const x = Math.round(position.x / this.gridUnit) * this.gridUnit;
const z = Math.round(position.z / this.gridUnit) * this.gridUnit;
return new THREE.Vector3(x, 0, z);
}
/**
* Check if position is valid for track placement
*/
isValidPlacement(position) {
// Check bounds
if (Math.abs(position.x) > this.gridSize || Math.abs(position.z) > this.gridSize) {
return false;
}
// Check collisions with existing tracks
const positionSnap = this.snapToGrid(position);
const collisionBuffer = this.snapDistance * 2;
for (const track of this.tracks) {
if (track.mesh === null) continue;
const trackPos = track.mesh.position;
const distance = positionSnap.distanceTo(trackPos);
if (distance < collisionBuffer) {
return false;
}
}
return true;
}
/**
* Add track piece to world
*/
addTrackPiece(type, position, rotation) {
if (!this.isValidPlacement(position)) {
console.warn('[World] Invalid placement position');
return null;
}
const track = new TrackPiece(type, position, rotation);
track.create(this.renderer.scene);
this.tracks.push(track);
// Update stats
Game.updateStats(this.tracks.length);
console.log(`[World] Added ${type} track at ${position.x.toFixed(1)}, ${position.z.toFixed(1)}`);
return track;
}
/**
* Remove track piece from world
*/
removeTrackPiece(trackPiece) {
const index = this.tracks.indexOf(trackPiece);
if (index > -1) {
this.tracks.splice(index, 1);
this.renderer.removeTrackPiece(trackPiece.mesh);
Game.updateStats(this.tracks.length);
Game.updateSelectedInfo(null);
console.log(`[World] Removed track piece`);
return true;
}
return false;
}
/**
* Get track piece at position
*/
getTrackAtPosition(position) {
for (const track of this.tracks) {
if (track.mesh === null) continue;
const distance = position.distanceTo(track.mesh.position);
if (distance < this.snapDistance) {
return track;
}
}
return null;
}
/**
* Connect tracks at junctions
*/
connectTracks(track1, track2) {
// Simple connection logic
// In full implementation, check compatibility and adjust orientation
console.log('[World] Connecting tracks');
}
/**
* Clear all tracks
*/
clear() {
for (const track of this.tracks) {
this.removeTrackPiece(track);
}
this.tracks = [];
Game.updateStats(0);
console.log('[World] All tracks cleared');
}
/**
* Get world statistics
*/
getStats() {
const counts = {
straight: 0,
curved: 0,
junction: 0,
signal: 0
};
for (const track of this.tracks) {
if (counts[track.type] !== undefined) {
counts[track.type]++;
}
}
return {
total: this.tracks.length,
...counts
};
}
}
// Export for module usage
if (typeof module !== 'undefined' && module.exports) {
module.exports = World;
}