public override void elapse(ElapseData data) { globalTime = data.TotalTime; if (!applyBreak && (data.Vehicle.Speed.KilometersPerHour > 0 || securityTest)) { if (!hold && (globalTime.Milliseconds - time.Milliseconds) > delayBeforeBreaking) { soundManager.startSound(ref vacmaHorn, SoundIndex.Vacma); if ((globalTime.Milliseconds - time.Milliseconds) > delayBeforeBreaking * 2) { applyBreak = true; soundManager.stopSound(ref vacmaHorn); handleManager.applyEmergencyBrake(); } } else if ((globalTime.Milliseconds - time.Milliseconds) > delayBeforeRinging) { soundManager.startSound(ref vacmaRing, SoundIndex.VacmaRing); if ((globalTime.Milliseconds - time.Milliseconds) > (delayBeforeRinging + delayBeforeBreaking)) { applyBreak = true; soundManager.stopSound(ref vacmaRing); handleManager.applyEmergencyBrake(); } } } else time = globalTime; }
public TrainSoundManager(PlaySoundDelegate playSound) { this.playSound = playSound; loopSounds = new List<LoopSound>(); loopSoundsFor = new List<LoopSoundFor>(); lastSoundTime = new Time(0); lastSoundIndex = SoundIndex.None; }
public void playSoundOnce(SoundIndex index, int delayBeforeRepeating) { if (index != lastSoundIndex || (globalTime.Milliseconds - lastSoundTime.Milliseconds > delayBeforeRepeating)) { lastSoundIndex = index; lastSoundTime = globalTime; playSound((int) index,volume,pitch,false); } }
public void elapse(ElapseData data) { globalTime = data.TotalTime; loopSoundsFor.ForEach(delegate (LoopSoundFor sound) { if (globalTime.Milliseconds - sound.start > sound.duration) { sound.sound.Stop(); loopSoundsFor.Remove(sound); } }); }
public Vacma(TrainSoundManager soundManager, TrainHandleManager handleManager, TrainControlManager controlManager) : base(soundManager, handleManager, controlManager) { time = new Time(0); securityTest = false; hold = false; vacmaHorn = -1; vacmaRing = -1; applyBreak = false; }
internal double UpdateAcceleration(ElapseData data) { double speedPrev = accelerationLastSpeed; double speedNow = data.Vehicle.Speed.MetersPerSecond; double time = (data.TotalTime.Seconds - accelerationLastPoll.Seconds); accelerationRate = (speedNow - speedPrev) / time; accelerationLastPoll = data.TotalTime; accelerationLastSpeed = speedNow; return accelerationRate; }
// --- constructors --- /// <summary>Creates a new instance of this class.</summary> /// <param name="vehicle">The state of the train.</param> /// <param name="precedingVehicle">The state of the preceding train, or a null reference if there is no preceding train.</param> /// <param name="handles">The virtual handles.</param> /// <param name="totalTime">The current absolute time.</param> /// <param name="elapsedTime">The elapsed time since the last call to Elapse.</param> public ElapseData(VehicleState vehicle, PrecedingVehicleState precedingVehicle, Handles handles, Time totalTime, Time elapsedTime) { this.MyVehicle = vehicle; this.MyPrecedingVehicle = precedingVehicle; this.MyHandles = handles; this.MyTotalTime = totalTime; this.MyElapsedTime = elapsedTime; this.MyDebugMessage = null; }
internal void Elapse(ATP2.ATPElapseData data) { vState = data.ElapseData; Handles atpHandlesResult = data.ElapseData.Handles; // UNDONE: if (vState.TotalTime.Milliseconds >= lastTimeRefreshATOAccelerationRate.Milliseconds + 100) { ATO_AccelerationRate = (vState.Vehicle.Speed.KilometersPerHour - lastTimeRefreshATOAccelerationRate_SpeedKMHS) / (vState.TotalTime.Milliseconds - lastTimeRefreshATOAccelerationRate.Milliseconds) * 1000; lastTimeRefreshATOAccelerationRate_SpeedKMHS = vState.Vehicle.Speed.KilometersPerHour; lastTimeRefreshATOAccelerationRate = vState.TotalTime; } // vState.DebugMessage = "Accel:" + ATO_AccelerationRate + "km/h/s; " + vState.DebugMessage; // fail the ATO if handles fail whilst ATO running if (ATOStarted && vState.Handles.PowerNotch != 0 && vState.Handles.BrakeNotch != vSpec.BrakeNotches) { ATOFail = true; } // reset fail only if (1) ATO is not start and (2) train is steady and (3) handles are OK and (4) ATO is on fail state if (ATOFail && !ATOStarted && vState.Vehicle.Speed.KilometersPerHour == 0 && vState.Handles.PowerNotch == 0 && vState.Handles.BrakeNotch == vSpec.BrakeNotches) { ATOFail = false; } // what will happen if ATO fails? if (ATOFail) { vState.DebugMessage = "!ATO FAIL!"; if (vState.Vehicle.Speed.KilometersPerHour == 0) { ATOFail = false; ATOStarted = false; } else { // emg beep beep beep ATOPower = 0; ATOBrake = vSpec.BrakeNotches + 1; } } // how is ATO working? else if (ATOStarted) { // jump to stop working if not powering and stopped // OK: ATOStates.START + ATOStates.POWER if (vState.Vehicle.Speed.KilometersPerHour == 0.0 && ATOCurrentState > ATOStates.POWER) { ATOStarted = false; } #region Analysis and Switch States // brake due to next speed flag if (data.CurrentTargetSpeed < prevTargetSpeed) { ATOCurrentState = ATOStates.BRAKE_SPEED; } // accelerate else if (data.CurrentPermittedSpeed > prevPermittedSpeed) { ATOCurrentState = ATOStates.POWER; } // brake due to arriving at next stop // if next stop is available else if (lastCompletedDockingIndex + 1 < Stations.Count) { // if next stop should stop if (Stations[lastCompletedDockingIndex + 1].DoorOpen > -2) { // arriving at platform // UNDONE: double BrakingDistanceByPermittedSpeed = AccelerationPhysics.GetDisplacement(data.CurrentPermittedSpeed, 0, BrakeRate[ATP2.DefaultNormalBrakeNotch]); if (Stations[lastCompletedDockingIndex + 1].StopPosition - GeneralSettings.BrakeCurveHigh_ReservingDistance - vState.Vehicle.Location <= BrakingDistanceByPermittedSpeed) { if (vState.Vehicle.Speed.KilometersPerHour < data.CurrentPermittedSpeed - 2) { // vState.DebugMessage += "S1:" + ATOStartLocation + " >= " + (Stations[lastCompletedDockingIndex + 1].StopPosition - BrakingDistanceByPermittedSpeed) + ", "; if (vState.Vehicle.Speed.KilometersPerHour < data.CurrentPermittedSpeed - 5 && ATOStartLocation >= Stations[lastCompletedDockingIndex + 1].StopPosition - BrakingDistanceByPermittedSpeed) { vState.DebugMessage += "SPower, "; ATOCurrentState = ATOStates.POWER; } else { ATOCurrentState = ATOStates.COASTING; } } else { ATOCurrentState = ATOStates.BRAKE_STOP; } } } } // remember things for analysis on next frame if (data.CurrentTargetSpeed != prevTargetSpeed) prevTargetSpeed = data.CurrentTargetSpeed; if (data.CurrentPermittedSpeed != prevPermittedSpeed) prevPermittedSpeed = data.CurrentPermittedSpeed; if (data.CurrentEmergencyBrakeSpeed != prevEmergencyBrakeSpeed) prevEmergencyBrakeSpeed = data.CurrentEmergencyBrakeSpeed; #endregion #region Behaviour if (data.ATPFail) { ATOFail = true; } else if (!data.ATPBrakeApplying) { data.ElapseData.DebugMessage += ATOCurrentState.ToString() + ", "; switch (ATOCurrentState) { case ATOStates.START: if (vState.Vehicle.Speed.KilometersPerHour >= 1) { ATOCurrentState = ATOStates.POWER; goto case ATOStates.POWER; } ATOPower = vSpec.PowerNotches; ATOBrake = 0; break; case ATOStates.POWER: if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + atoProfiles[profileID].StopAcceleratingSpeed) { ATOCurrentState = ATOStates.COASTING; goto case ATOStates.COASTING; } ATOPower = vSpec.PowerNotches; ATOBrake = 0; break; case ATOStates.COASTING: if (atoProfiles[profileID].HoldSpeedNotCoasting) { goto case ATOStates.KEEPSPEED; } #region brake to hold speed? // if new to coasting state, reset brake notch if(lastFrame_ATOState != ATOCurrentState) ATOBrake = BrakeToHoldSpeedNotch = 0; // if notches are interrupted, then recount the timer if (lastFrame_ATOState != ATOCurrentState || last1s_PowerNotch != lastFrame_PowerNotch || last1s_BrakeNotch != lastFrame_BrakeNotch) { // System.Windows.Forms.MessageBox.Show(lastCheckSpeedCoasting + ""); lastCheckSpeedCoasting = vState.TotalTime; last1s_Speed = vState.Vehicle.Speed.KilometersPerHour; last1s_PowerNotch = lastFrame_BrakeNotch; last1s_BrakeNotch = lastFrame_BrakeNotch; } if (vState.TotalTime.Milliseconds >= lastCheckSpeedCoasting.Milliseconds + 1000) { if (vState.Vehicle.Speed.KilometersPerHour - last1s_Speed > 0) { // accelerating for (int i = BrakeRate.Length - 1; i >= 0; i--) { if (vState.Vehicle.Speed.KilometersPerHour - last1s_Speed >= BrakeRate[i] * -1) { ATOPower = 0; ATOBrake = BrakeToHoldSpeedNotch = i; break; } } } else { ATOBrake = BrakeToHoldSpeedNotch = 0; } lastCheckSpeedCoasting = vState.TotalTime; last1s_Speed = vState.Vehicle.Speed.KilometersPerHour; last1s_PowerNotch = ATOPower; last1s_BrakeNotch = ATOBrake; } #endregion #region slight slope that above command cannot detect else if (vState.Vehicle.Speed.KilometersPerHour <= data.CurrentPermittedSpeed && slightSlopeBrakeEnabled) { slightSlopeBrakeEnabled = false; ATOPower = 0; ATOBrake = BrakeToHoldSpeedNotch = 0; } else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + 4) { vState.DebugMessage += "(S)"; slightSlopeBrakeEnabled = true; ATOPower = 0; ATOBrake = BrakeToHoldSpeedNotch = 3; } else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + 3) { vState.DebugMessage += "(S)"; slightSlopeBrakeEnabled = true; ATOPower = 0; ATOBrake = BrakeToHoldSpeedNotch = 2; } else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + 2) { vState.DebugMessage += "(S)"; slightSlopeBrakeEnabled = true; ATOPower = 0; ATOBrake = BrakeToHoldSpeedNotch = 1; } #endregion if (BrakeToHoldSpeedNotch > 0) vState.DebugMessage += "(" + (vState.Vehicle.Speed.KilometersPerHour - last1s_Speed) + ")BrakeToHoldSpeed(" + BrakeToHoldSpeedNotch + "),"; if (slightSlopeBrakeEnabled) vState.DebugMessage += "slightSlopeBrakeEnabled,"; // TODO: power if too low speed? else if (vState.Vehicle.Speed.KilometersPerHour <= data.CurrentPermittedSpeed + atoProfiles[profileID].CoastingTooSlowForcePowerSpeed) { ATOCurrentState = ATOStates.POWER; goto case ATOStates.POWER; } else { ATOPower = 0; ATOBrake = BrakeToHoldSpeedNotch; } break; case ATOStates.KEEPSPEED: throw new NotImplementedException(); if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + atoProfiles[profileID].StopAcceleratingSpeed) { PowerToHoldSpeedNotch = 0; } #region slight slope that above command cannot detect else if (vState.Vehicle.Speed.KilometersPerHour <= data.CurrentPermittedSpeed && slightSlopeBrakeEnabled) { slightSlopeBrakeEnabled = false; ATOPower = 0; ATOBrake = BrakeToHoldSpeedNotch = 0; } else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + 4) { vState.DebugMessage += "(S)"; slightSlopeBrakeEnabled = true; ATOPower = 0; ATOBrake = BrakeToHoldSpeedNotch = 3; } else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + 3) { vState.DebugMessage += "(S)"; slightSlopeBrakeEnabled = true; ATOPower = 0; ATOBrake = BrakeToHoldSpeedNotch = 2; } else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed + 2) { vState.DebugMessage += "(S)"; slightSlopeBrakeEnabled = true; ATOPower = 0; ATOBrake = BrakeToHoldSpeedNotch = 1; } #endregion #region power to keep speed else if (true) { #region deceleration caused by gradient // Rate = 1000 * Y / X double pitchInPerMill_KEEPSPEED = gPtMem[gPtMem.CurrentIndex(vState.Vehicle.Location)].Pitch; // Acceleration due to gravity is 9.79 ms^-2 double accelerationCausedByGradient_KEEPSPEED = 9.79 / (1 / (-1 * pitchInPerMill_KEEPSPEED / 1000)); vState.DebugMessage += "pitch: " + pitchInPerMill_KEEPSPEED + "; DCBG: " + accelerationCausedByGradient_KEEPSPEED + ", "; #endregion #region calculation #endregion } #endregion // debug if (BrakeToHoldSpeedNotch > 0) vState.DebugMessage += "(" + (vState.Vehicle.Speed.KilometersPerHour - last1s_Speed) + ")BrakeToHoldSpeed(" + BrakeToHoldSpeedNotch + "),"; if (slightSlopeBrakeEnabled) vState.DebugMessage += "slightSlopeBrakeEnabled,"; ATOPower = PowerToHoldSpeedNotch; ATOBrake = 0; break; case ATOStates.BRAKE_SPEED: if (vState.Vehicle.Speed.KilometersPerHour <= data.CurrentTargetSpeed + atoProfiles[profileID].StopBrakingSpeed) { ATOCurrentState = ATOStates.COASTING; goto case ATOStates.COASTING; } ATOPower = 0; // TODO: deceleration baused by gradient // for (int i = 0; i < BrakeRate.Length; i++) { // brake rates are negative numbers if (Math.Abs(BrakeRate[i]) >= Math.Abs(AccelerationPhysics.GetAccelerationRate(data.CurrentTargetSpeed, vState.Vehicle.Speed.KilometersPerHour, data.NextSpeedFlag.StartingLocation - vState.Vehicle.Location))) { ATOBrake = i; break; } } if (vState.Vehicle.Speed.KilometersPerHour > data.CurrentTargetSpeed + 4) { ATOBrake = vSpec.BrakeNotches; } break; case ATOStates.BRAKE_STOP: ATOPower = 0; // TODO: more accurate calculation for gradient #region deceleration caused by gradient // Rate = 1000 * Y / X double pitchInPerMill_BRAKE_STOP = gPtMem[gPtMem.CurrentIndex(vState.Vehicle.Location)].Pitch; // Acceleration due to gravity is 9.79 ms^-2 double accelerationCausedByGradient_BRAKE_STOP = 9.79 / (1 / (-1 * pitchInPerMill_BRAKE_STOP / 1000)); vState.DebugMessage += "pitch: " + pitchInPerMill_BRAKE_STOP + "; DCBG: " + accelerationCausedByGradient_BRAKE_STOP + ", "; #endregion #region calculation for (int i = 0; i < BrakeRate.Length; i++) { if (Stations[lastCompletedDockingIndex + 1].StopPosition - vState.Vehicle.Location <= GeneralSettings.BrakeCurveHigh_ChangeToLowDistance) { // brake rates are negative numbers if (Math.Abs(BrakeRate[i]) - accelerationCausedByGradient_BRAKE_STOP >= Math.Abs(AccelerationPhysics.GetAccelerationRate(0, vState.Vehicle.Speed.KilometersPerHour, Stations[lastCompletedDockingIndex + 1].StopPosition - vState.Vehicle.Location))) { ATOBrake = i; break; } } else { // brake rates are negative numbers if (Math.Abs(BrakeRate[i]) - accelerationCausedByGradient_BRAKE_STOP >= Math.Abs(AccelerationPhysics.GetAccelerationRate(0, vState.Vehicle.Speed.KilometersPerHour, Stations[lastCompletedDockingIndex + 1].StopPosition - vState.Vehicle.Location - GeneralSettings.BrakeCurveHigh_ReservingDistance))) { ATOBrake = i; break; } } } #endregion #region don't decelerate if speed is too low if (vState.Vehicle.Speed.KilometersPerHour < data.CurrentTargetSpeed - 5) { resistBrakingNotch = vSpec.BrakeNotches; } else if (resistBrakingNotch == 2) { if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed - 3 && vState.Vehicle.Speed.KilometersPerHour < data.CurrentPermittedSpeed - 1) { resistBrakingNotch = 1; } else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed - 1) { resistBrakingNotch = 0; } } else if (resistBrakingNotch == 1) { if (vState.Vehicle.Speed.KilometersPerHour < data.CurrentPermittedSpeed - 4) { resistBrakingNotch = 2; } else if (vState.Vehicle.Speed.KilometersPerHour >= data.CurrentPermittedSpeed - 1) { resistBrakingNotch = 0; } } else if (resistBrakingNotch == 0) { if (vState.Vehicle.Speed.KilometersPerHour < data.CurrentPermittedSpeed - 4) { resistBrakingNotch = 2; } else if (vState.Vehicle.Speed.KilometersPerHour < data.CurrentPermittedSpeed - 2) { resistBrakingNotch = 1; } } ATOBrake -= (ATOBrake - resistBrakingNotch < 0 ? 0 : resistBrakingNotch); // debug if (resistBrakingNotch > 0) vState.DebugMessage += "ForceB-" + resistBrakingNotch + ", "; #endregion break; } } #endregion } else { ATOPower = 0; ATOBrake = vSpec.BrakeNotches; } vState.Handles.PowerNotch = ATOPower; vState.Handles.BrakeNotch = ATOBrake; lastFrame_ATOState = ATOCurrentState; lastFrame_Speed = vState.Vehicle.Speed.KilometersPerHour; lastFrame_PowerNotch = ATOPower; lastFrame_BrakeNotch = ATOBrake; }
public override void trainEvent(TrainEvent _event) { VirtualKeys key; if (_event.getEventType() == EventTypes.EventTypeBlowHorn || _event.getEventType() == EventTypes.EventTypeChangeBrake || _event.getEventType() == EventTypes.EventTypeChangeDoors || _event.getEventType() == EventTypes.EventTypeChangePower || _event.getEventType() == EventTypes.EventTypeSwitchReverser) { time = globalTime; } if (_event.getEventType() == EventTypes.EventTypeKeyDown) { key = (VirtualKeys) _event.getEventData(); if (key == VirtualKeys.S && !hold) resetHolding(); } if (_event.getEventType() == EventTypes.EventTypeKeyUp) { key = (VirtualKeys) _event.getEventData(); if (key == VirtualKeys.S) { hold = false; time = globalTime; } } }
private void resetHolding() { hold = true; time = globalTime; soundManager.stopSound(ref vacmaHorn); soundManager.stopSound(ref vacmaRing); }
// --- constructors --- /// <summary>Creates a new instance of this class.</summary> /// <param name="vehicle">The state of the train.</param> /// <param name="precedingVehicle">The state of the preceding train, or a null reference if there is no preceding train.</param> /// <param name="handles">The virtual handles.</param> /// <param name="totalTime">The current absolute time.</param> /// <param name="elapsedTime">The elapsed time since the last call to Elapse.</param> /// <param name="stations">The current route's list of stations.</param> /// <param name="cameraView">The current camera view mode</param> /// <param name="languageCode">The current language code</param> public ElapseData(VehicleState vehicle, PrecedingVehicleState precedingVehicle, Handles handles, Time totalTime, Time elapsedTime, List<Station> stations, CameraViewMode cameraView, string languageCode) { this.MyVehicle = vehicle; this.MyPrecedingVehicle = precedingVehicle; this.MyHandles = handles; this.MyTotalTime = totalTime; this.MyElapsedTime = elapsedTime; this.MyDebugMessage = null; this.MyStations = stations; this.MyCameraViewMode = cameraView; this.MyLanguageCode = languageCode; }