/// <summary> /// Bewegt das Auto /// </summary> /// <param name="tickLength">Länge eines Ticks in Sekunden (berechnet sich mit 1/#Ticks pro Sekunde)</param> public void Move(double tickLength) { if (!alreadyMoved) { _physics.velocity += physics.acceleration; // Rückwärts fahren geht nicht if (_physics.velocity < 0) _physics.velocity = 0; double arcLengthToMove = (physics.velocity * tickLength * 10); if (_physics.velocity < 0.1) { if (!isStopped) { ++_statistics.numStops; } isStopped = true; } else { isStopped = false; } // wenn ich gerade am Spurwechseln bin, sollte ich das erstmal behandeln if (currentlyChangingLine) { currentPositionOnLineChangePoint += arcLengthToMove; // ich bewege mich echt auf dem LCP _state.position += arcLengthToMove * ratioProjectionOnTargetConnectionvsLCPLength; // ich muss meine Position auf der Ziel-NodeConnection entsprechend anpassen } else { _state.position += arcLengthToMove; } // wenn meine aktuelle NodeConnection zu Ende ist, sollte ich das auch behandeln if (currentPosition > currentNodeConnection.lineSegment.length) { // gucken, ob es mit ner Connection weitergeht if ((currentNodeConnection.endNode.nextConnections.Count != 0) && (wayToGo.SegmentCount() > 0)) { _physics.multiplierTargetVelocity = 1; _state.UnsetLineChangeVehicleInteraction(); double startDistance = (currentPosition - currentNodeConnection.lineSegment.length); // falls ich mehrere Connections zur Auswahl habe, berechne die mit dem kürzesten Weg // (dieser könnte sich geändert haben, weil dort plötzlich mehr Autos fahren) if (currentNodeConnection.endNode.nextConnections.Count > 1) { _wayToGo = Routing.CalculateShortestConenction(currentNodeConnection.endNode, targetNodes, _vehicleType); if (_wayToGo.SegmentCount() == 0 || _wayToGo.Top() == null) { RemoveFromCurrentNodeConnection(true, null, 0); return; } } visitedNodeConnections.AddFirst(currentNodeConnection); // nächsten Wegpunkt extrahieren Routing.RouteSegment rs = wayToGo.Pop(); if (rs == null) { RemoveFromCurrentNodeConnection(true, null, 0); return; } else { // ist ein Spurwechsel nötig, so die entsprechenden Felder füllen if (rs.lineChangeNeeded) rs.startConnection.lineChangeIntervals.TryGetValue(rs.nextNode.hashcode, out lci); else lci = null; lineChangeNeeded = (lci != null); LinkedListNode<IVehicle> lln = rs.startConnection.GetVehicleListNodeBehindArcPosition(startDistance); if (lln == null || lln.Value.currentPosition - lln.Value.length >= startDistance) { RemoveFromCurrentNodeConnection(true, rs.startConnection, startDistance); } else { RemoveFromCurrentNodeConnection(true, null, 0); } } } else { // Ende der Fahnenstange, also selbstzerstören RemoveFromCurrentNodeConnection(true, null, 0); } } else if (Double.IsNaN(currentPosition)) { RemoveFromCurrentNodeConnection(false, null, 0); } // Der Spurwechsel ist fertig, dann sollte ich diesen auch abschließen: if (currentlyChangingLine && currentPositionOnLineChangePoint >= currentLineChangePoint.lineSegment.length) { FinishLineChange(currentPositionOnLineChangePoint - currentLineChangePoint.lineSegment.length); _statistics.startTimeOnNodeConnection = GlobalTime.Instance.currentTime; _statistics.arcPositionOfStartOnNodeConnection = _state.position; } alreadyMoved = true; } }