@@ -61,31 +61,29 @@ AbstractSegment.prototype.prevSegment = null;
61
61
// Reference to the turnout this track segment belongs to (if any).
62
62
AbstractSegment . prototype . turnout = null ;
63
63
64
- // Starting on this track segment, and the specified 'startDistance' (measured
65
- // from the start of this segment), walk 'delta' (negative is towards the
66
- // headshunt, positive is towards the buffers).
64
+ // Measuring from the start of this track segment, walk 'distance'
65
+ // (negative is towards the headshunt, positive is towards the buffers).
67
66
// Return a location tuple composed of the track segment and distance
68
67
// (measured from the start of that segment).
69
68
// If the walk exceeds the length of the track (e.g. hitting a buffer), return
70
- // the location of the end of the track.
71
- AbstractSegment . prototype . walk = function ( startDistance , delta ) {
72
- var endDistance = startDistance + delta ;
73
- if ( endDistance < 0 ) {
69
+ // the location of the end of the track, as well as the difference between what
70
+ // was requested vs what was obtained.
71
+ AbstractSegment . prototype . walk = function ( distance ) {
72
+ if ( distance < 0 ) {
74
73
if ( this . prevSegment ) {
75
- return this . prevSegment . walk (
76
- startDistance + this . prevSegment . length , delta ) ;
74
+ return this . prevSegment . walk ( distance + this . prevSegment . length ) ;
77
75
}
78
- // End of track (headshunt or turnout ).
79
- return [ this , 0 ] ;
76
+ // End of track (headshunt).
77
+ return [ this , 0 , - distance ] ;
80
78
}
81
- if ( endDistance > this . length ) {
79
+ if ( distance > this . length ) {
82
80
if ( this . nextSegment ) {
83
- return this . nextSegment . walk ( startDistance - this . length , delta ) ;
81
+ return this . nextSegment . walk ( distance - this . length ) ;
84
82
}
85
83
// End of track (buffer).
86
- return [ this , this . length ] ;
84
+ return [ this , this . length , distance - this . length ] ;
87
85
}
88
- return [ this , endDistance ] ;
86
+ return [ this , distance , 0 ] ;
89
87
} ;
90
88
91
89
// Calculate the X/Y SVG coordinates of a point 'distance' down this segment.
@@ -271,14 +269,23 @@ Vehicle.prototype.couple = function(nextVehicle) {
271
269
this . coupler . style . visibility = 'visible' ;
272
270
} ;
273
271
272
+ // Length from the front of this vehicle to the end of the train.
273
+ Vehicle . prototype . lengthToEnd = function ( ) {
274
+ var len = this . LENGTH + 2 ;
275
+ if ( this . nextVehicle ) {
276
+ len += this . nextVehicle . lengthToEnd ( ) ;
277
+ }
278
+ return len ;
279
+ } ;
280
+
274
281
// Decouple this locomotive or care from another car.
275
282
// Ok to call if not already coupled (does nothing).
276
283
Vehicle . prototype . uncouple = function ( ) {
277
284
if ( this . nextVehicle ) {
278
- if ( nextVehicle . prevVehicle !== this ) {
285
+ if ( this . nextVehicle . prevVehicle !== this ) {
279
286
throw Error ( "nextVehicle wasn't connected to us" ) ;
280
287
}
281
- nextVehicle . prevVehicle = null ;
288
+ this . nextVehicle . prevVehicle = null ;
282
289
trains . push ( this . nextVehicle ) ;
283
290
this . nextVehicle = null ;
284
291
}
@@ -296,17 +303,30 @@ Vehicle.prototype.moveTo = function(segment, distance) {
296
303
// Move this vehicle up (positive) or down (negative) the track by `delta`.
297
304
Vehicle . prototype . moveBy = function ( delta ) {
298
305
if ( delta >= 0 ) { // Moving backwards (towards the buffers).
299
- var locBackAxle = this . segment_ . walk ( this . distance_ , delta ) ;
300
- var locFrontAxle = locBackAxle [ 0 ] . walk ( locBackAxle [ 1 ] , - 2 * this . AXLE_DISTANCE ) ;
306
+ if ( ! this . prevVehicle ) {
307
+ var locTrainEnd = this . segment_ . walk ( this . distance_ + delta -
308
+ this . AXLE_DISTANCE - this . LENGTH / 2 + this . lengthToEnd ( ) ) ;
309
+ if ( locTrainEnd [ 2 ] !== 0 ) {
310
+ // Crashed into buffer.
311
+ locoActualSpeed = 0 ;
312
+ delta -= locTrainEnd [ 2 ] ;
313
+ }
314
+ }
315
+ var locBackAxle = this . segment_ . walk ( this . distance_ + delta ) ;
316
+ var locFrontAxle = locBackAxle [ 0 ] . walk ( locBackAxle [ 1 ] - 2 * this . AXLE_DISTANCE ) ;
301
317
} else { // Moving forwards (towards the headshunt).
302
- var locFrontAxle = this . segment_ . walk ( this . distance_ - 2 * this . AXLE_DISTANCE , delta ) ;
303
- var locBackAxle = locFrontAxle [ 0 ] . walk ( locFrontAxle [ 1 ] , 2 * this . AXLE_DISTANCE ) ;
318
+ var locFrontAxle = this . segment_ . walk ( this . distance_ - 2 * this . AXLE_DISTANCE + delta ) ;
319
+ var locBackAxle = locFrontAxle [ 0 ] . walk ( locFrontAxle [ 1 ] + 2 * this . AXLE_DISTANCE ) ;
304
320
var backSegment = locBackAxle [ 0 ] ;
305
321
if ( ! this . prevVehicle && backSegment . turnout &&
306
322
backSegment . prevSegment . nextSegment !== backSegment ) {
307
323
// We are a locomotive running through a turnout switched the wrong way.
308
324
backSegment . turnout . toggle ( ) ;
309
325
}
326
+ if ( locFrontAxle [ 2 ] !== 0 ) {
327
+ // Crashed into end of headshunt.
328
+ locoActualSpeed = 0 ;
329
+ }
310
330
}
311
331
this . segment_ = locBackAxle [ 0 ] ;
312
332
this . distance_ = locBackAxle [ 1 ] ;
@@ -349,13 +369,13 @@ var PATH_SEGMENTS = [
349
369
new CurveSegment ( 48 , 71 , 180 , 45 ) , // 2: Headshunt curve
350
370
new StraightSegment ( 19.716 , 42.716 , 22.627 , - 22.628 ) , // 3: Turnout #1 straight
351
371
new CurveSegment ( 70.627 , 48.372 , 225 , 45 ) , // 4: Siding A curve
352
- new StraightSegment ( 70.627 , 8.372 , 3 * 16 , 0 ) , // 5: Siding A straight
372
+ new StraightSegment ( 70.627 , 8.372 , 3 * 16 + 3 , 0 ) , // 5: Siding A straight
353
373
new CurveSegment ( 48 , 71 , 225 , 45 ) , // 6: Turnout #1 curve
354
374
new StraightSegment ( 48 , 31 , 2 * 16 , 0 ) , // 7: Turnout #2 straight
355
- new StraightSegment ( 48 + 2 * 16 , 31 , 3 * 16 , 0 ) , // 8: Siding B
375
+ new StraightSegment ( 48 + 2 * 16 , 31 , 3 * 16 + 3 , 0 ) , // 8: Siding B
356
376
new CurveSegment ( 48 , 71 , 270 , 45 ) , // 9: Turnout #2 curve
357
377
new CurveSegment ( 104.568 , 14.431 , 135 , - 45 ) , // 10: Siding C curve
358
- new StraightSegment ( 104.568 , 54.431 , 16 , 0 ) // 11: Siding C straight
378
+ new StraightSegment ( 104.568 , 54.431 , 16 + 3 , 0 ) // 11: Siding C straight
359
379
] ;
360
380
361
381
// On page load, draw the track, initialize event handlers, and reset the game.
0 commit comments