feat: initial commit of Railtrack Pro prototype with complete test suite
This commit is contained in:
+164
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
Reference in New Issue
Block a user