/// <summary> /// Ermittelt, wie weit wir uns vertikal entlang einer Seite des getroffenen Hindernisses /// bewegen können. /// </summary> /// <param name="kollision">Das aktuelle Hindernis, das wir an der Seite getroffen haben.</param> /// <returns>Der vertikale Abstand, den wir uns noch bewegen dürfen.</returns> private GenaueZahl ErstesVertikalesHindernisFinden( Hindernis kollision ) { // Die vertikale Achse am Ende der aktuellen Bewegung var schritt = kollision.SchrittweiteBisZurKollision.Value; var achse = Bereich.Erzeugen( schritt.Breite, schritt.Höhe, GenaueZahl.Null, VolleStrecke.Höhe ); // Mit Ausnahme des bereits bekannten Hindernisses alle Hindernisse, die diese Achse schneiden var hindernisseAufDerAchse = m_hindernisse .Where( hindernis => !ReferenceEquals( hindernis, kollision ) ) .Where( hindernis => hindernis.Bereich.ÜberschneidetSichMit( achse ) ); // Wir wollen uns maximal bis zum Ende des Hindernisses bewegen var vertialesEndeDesHindernisses = kollision.Bereich.GrößteVertikalePosition; // Wenn nichts im Weg steht, verwenden wir diesen Abstand var erstesHindernisAufDerAchse = BestesHindernisFinden( hindernisseAufDerAchse, hindernis => hindernis.Bereich.KleinsteVertikalePosition ); if (erstesHindernisAufDerAchse == null) return vertialesEndeDesHindernisses; // Wenn etwas im Weg steht und wir eher darauf treffen, so wird der freie Weg entsprechend reduziert var vertikalesEnde = erstesHindernisAufDerAchse.Bereich.KleinsteVertikalePosition; if (vertikalesEnde < vertialesEndeDesHindernisses) return vertikalesEnde; // Ansonsten bleibt alles beim Alten return vertialesEndeDesHindernisses; }
/// <summary> /// Nachdem ein Hindernis an der Unterseite getroffen wurde kann die Bewegung horizontal /// maximal bis zum Ende des Hindernisses fortgesetzt werden. /// </summary> /// <param name="kollision">Dieses Hindernis haben wir von unten getroffen.</param> /// <returns>Die horizontale Bewegung, die wir noch ausführen können.</returns> private GenaueZahl ErstesHorizontalesHindernisFinden( Hindernis kollision ) { // Die horizontale Achse am Auftreffpunkt var schritt = kollision.SchrittweiteBisZurKollision.Value; var achse = Bereich.Erzeugen( schritt.Breite, schritt.Höhe, VolleStrecke.Breite, GenaueZahl.Null ); // Mit Ausnahme des bereits bekannten Hindernisses alle Hindernisse, die diese Achse schneiden var hindernisseAufDerAchse = m_hindernisse .Where( hindernis => !ReferenceEquals( hindernis, kollision ) ) .Where( hindernis => hindernis.Bereich.ÜberschneidetSichMit( achse ) ); // Geplant ist es, an dem Hindernis vorbei zu ziehen var horizontalesEndeDerBewegung = kollision.Bereich.GrößteHorizontalePosition; // Wenn nichts im Weg steht machen wir das so var erstesHindernisAufDerAchse = BestesHindernisFinden( hindernisseAufDerAchse, hindernis => hindernis.Bereich.KleinsteHorizontalePosition ); if (erstesHindernisAufDerAchse == null) return horizontalesEndeDerBewegung; // Liegt das Hindernis näher als das geplante Ende der Bewegung, so müssen wir früher aufhören var horizontalesEnde = erstesHindernisAufDerAchse.Bereich.KleinsteHorizontalePosition; if (horizontalesEnde < horizontalesEndeDerBewegung) return horizontalesEnde; // Wir können den vollen Weg wie geplant nutzen return horizontalesEndeDerBewegung; }