OOP Objekte entlang Pfaden bewegen

nico525

Mitglied
Hi Leute,
entweder mein Problem ist unheimlich kompliziert - was ich bezweifle - oder ich stehe einfach auf dem Schlauch.
Zunächst ist es mein Ziel eine Verkehrssimulation einer Kreuzung zu gestalten. Objekte (Autos) werden anhand einer eigens geschrieben, relaitv unkomplizierten Klasse erstellt und können sich durch die x und y Koordinaten hoch und runter sowie links und rechts bwegen.
Mein erstes Problem ist die Realisierung eines Abbiegevorganges, denn ich weiß nicht wie in diesem Fall die X und Y Koordinaten zu bewgen habe. Zunächst muss aber feststehen, dass das Auto abbiegt.
Dies realisierte ich durch eine Zufallszahl von 1-4 (die Enden der Kreuzung durchnummeriert). diese Zahl ist das neue Ziel.
Eine Möglichkeit wäre natürlich das ganze nun mit ifs abzufragen, allerdings kann ich mir nicht vorstellen, dass es hier etwas einfacheres gibt. Das ganze wäre mMn zu statisch und schlecht erweiterbar.
Das darauffolgende Problem wird dann die Realisierung der Rechts-Vor-Links-Regel, denn hierfür muss ich sozusagen 10 oder 20 ms in die Zukunft gucken, um zu prüfen, ob es zu einem Zusammenprall kommt. Die Kreuzung ist einsichtlich und sollte deshalb nicht das Anhalten fordern.

Ich hoffe es gibt so einer art Pfade in Java, denen Objekte mithilfe von X und Y koordinaten einfach folgen können :S. Habt ihr Rat?
 
Also etwas Fertiges für das Bewegen von Objekten entlang Pfaden wie in Flash oder so gibt es in Java soweit ich weiß nicht.

Generell kann man if/switch-statements vermeiden durch Polymorphie, konkret: Abstrakte Methoden. Ich hab grad keine Zeit dir etwas für deinen konkreten Fall zu basteln, aber falls du jetzt damit nix anfangen kannst ein kleines Bsp:

Java:
class Animal{

  private String name;

  public Animal(String name){
     this.name =name;
  }

  public void makeSound(){ 
     // Schlecht und undynamisch:
     if(name.equals("Hund")){  System.out.println( "Wuff!" ); }
     else if(name.equals("Katze")){  System.out.println( "Miau!" ); }
     else if(name.equals("Elefeant")) { System.out.println( "Törrööö!" ); }
  }
}

Besser:

Java:
public abstract class Animal{

      private String name;

      public Animal(String name){
         this.name =name;
      }

      public abstract void makeSound();
}
 
public class Hund extends Animal{
 
      public Hund(){
        super("Hund");
      }

      @Override
      public void makeSound(){ 
         System.out.println("Wuff!");
      }
}
...analog Klassen für Katze + Elefant.

Wegen der Polymorphie in Bezug auf die Datentypen bei Vererbung ist ein Hund, eine Katze sowie ein Elefant ein "Animal". Folgendes geht:

Java:
List<Animal> animals = new ArrayList<Animal>();
animals.add(new Hund());
animals.add(new Katze());
//...
for(Animal a : animals){
    a.makeSound();
}
Da könnte jetzt rauskommen "Wuff", "Miau", "Wuff", "wuff", "törrööö" oder sonst was, das weisst du nicht so genau, denn die einzelnen Objekte kapseln das in sich selber, du musst dich nich drum kümmern. Und damit ist dein Programm auch dynamisch, du könntest jetzt jederzeit neue Tier-Klassen erstellen die von Animal erben, und die obige Schleife funktioniert noch genauso. Keine if-else Konstrukte mehr die du jetzt ständig anpassen müsstest.

Naja sorry wie gesagt ich bin grad auf dem Sprung, aber was ich meine ist:
Mach das so auch mit der Fahrtrichtung bzw. dem Abbiegeverhalten deiner Autos. Eine Klasse Fahrtrichtung mit ner abstrakten Methode abbiegen() oder so. Deine Auto-Klasse hat dann ne Instanzvariable davon, und wann immer sich was in der Richtung ändert weist du einfach eine neue Richtung zu:

Java:
richtung = new FahrtRichtungNord();

und eine Methode wie:

Java:
public Point getNewPosition(){
    return new Point(x+richtung.getDeltaX(), y+richtung.getDeltaY());
}

Kein if-else mehr..

Hoffe ist einigermaßen klar was ich mein 😀

lg
 
Zuletzt bearbeitet:
Pfade gibt es meiner Meinung nach nicht in Java, oder in irgendeiner ernstzunehmenden Programmiersprache.

Es gibt jedoch verschiedene Wege Pfade zu realisieren.
2 davon wären beispielsweise:

1.
Koordinaten in einer Liste auflisten. Die Objekte sollen jeden Punkt in der Liste abklappern. Wurde einer erreicht, wird der nächste angefahren.

----------------
Sinnvoll währe in deinem Fall evt. auch eine 2. Liste, die ALLE möglichen Wege beinhaltet..
In der 1. Liste stehen die nächsten Punkte, die das Objekt anzufahren hat, bis zur nächsten Kreuzung.

Ist das Ende der Liste erreicht, wird in der 2. Liste eine Abfrage gestartet.
Erst wird in der 2. Liste, eine weitere Liste gesucht mit dem Namen, der letzten Anfahrtspunkte.
In dieser Liste, befinden sich weitere Listen, mit möglichen nächsten Anfahrtspunkten. Dabei wird eine Zufallszahl zwischen 0 und [Listengröße]-1 gewählt, um eine dieser neuen Wege zu wählen.

2.
Eine "Engine", die dafür sorgt, dass dein Objekt sich immer entlang einer bestimmten Farbe bewegt
-----------------------------------------------------------------------

Rechts vor Links:

Ein Weg um die Rechts vor Links Regel abzufragen, währe abzufragen, welche Objekte sich derzeit (in dem ersten genannten Beispiel) zwischen ihrem letzten Anfahrtspunkt und vorletzten Anfahrtspunkt befinden.
Alle Objekte, derren letzter Anfahrtspunkt, an der selben Kreuzung liegt UND von rechts, vom Objekt aus gesehen kommen, bekommen dann vorfahrt.


Ich hoffe ich habs nicht zu kompliziert erklärt. Ich neige leider immer sehr dazu

Gruß
 
Danke für die Antworten!
Ich rolle das Feld mal von hinten auf:
Die Möglichkeit der Verkettung zweier oder mehrere Listen habe ich bis dato nicht in Betracht gezogen. Ist das ohne weiteres möglich?

@hdi: dein Beispiel leuchtet mir ein, allerdings kann ich mir beim besten Willen nicht vorstellen, wie ich das auf die Simulation umsetzen kann... Da finde ich die Idee der multiplen Liste schon verständlicher.

zu guter letzt Michael:
wie ich soetwas realisieren kann ist ja schön und gut, soweit war ich ja auch schon. Mir ging es primär darum wie ich es so geschickt löse, dass es dnyamisch erweiterbar ist

Das mit den Listen beruht ja auf dem sleben Prinzip, finde ich aber doch etwas Anschaulicher... Nun bräcuhte ich eine Möglichkeit X und Y dynamishc zu füllen, eine händische Eingabe wäre brutal viel :-D
 
Also das mit den Listen mit allen möglichen Positionen finde ich eine nicht so gute Idee (no offense). Es ist einfach zuviel Information, solange die Straßen nicht nach jedem Pixel die Richtung ändern, musst du ja nur die Punkte der Kreuzungen kennen. Das sollten wir vllt an dieser Stelle mal klären: Bestehet dein Straßennetz denn nur aus rein horizontalen und vertikalen Straßen oder auch ganz komisch krummen Pfaden?

Wenn ersters würde ich ein simples 2d-array vorschlagen, sodass eine Kreuzung durch eine Position im Koordinatensystem gekennzeichnet ist (Spalte, Reihe).

Dann musst du jedem Auto nur zuordnen, welche Spalte bzw Reihe zuletzt besucht wurde und in welche Richtung es fährt. Damit ist ja dann klar, welche Kreuzung als nächstes erreicht wird.
 
Zuletzt bearbeitet:
Zurzeit ist es um ehrlich zu sein sogar nur eine einzige Kreuzung!

Was ich mit dynamisch befüllen meine? Naja die Autos sollten aj auch einigermaßen Kreisförmig um die Kurve gehen und nicht aprubt (schreibt man das so?) sodass ich Listen mit viel Informationen hätte...
 
Wie mein Vorredner bereits sagte. Man benötigt nur EINEN Punkt, an dem ein Richtungswechsel stattfinden soll. Also eine Gerade Strecke zwischen 2 Kreuzungen, braucht nur 2 Punkte.

Genauso bei einer Kurve. Du brauchst nur den End und Startpunkt. Danach kannst du die Punkte auf einem "Kreis" ausrechnen, der beide Punkte shcneidet, und dein Objekt dort entlangfahren lassen.

Die Punkte werden jedesmal erneut virtuell automatisch berechnet
 
Naja die Autos sollten aj auch einigermaßen Kreisförmig um die Kurve gehen
Ja, genau sowas gibt es halt in Java nicht "out of the box", denn die Sprache zielt nicht auf solche Spielchen und Animationen ab. Was nicht heißt, dass du es nicht trotzdem (schön) lösen kannst, aber es ist halt nicht ganz so einfach wie du es dir vllt vorgestellt hast.

Zunächst einmal brauchst du einen "Gameloop", auch wenn es sich bei dir vllt nicht um ein echtes Spiel handelt sondern nur eine Demo. Ist aber das selbe eigentlich..

Das Grundgerüst dafür sieht so aus:
Du hast eine Schleife (grundsätzlich Endlosschleife, die nur mittels einem Flag beendet wird), und du stoppst bei jedem Durchlauf die Zeit, die seit dem letzten Durchgang vergangen ist. Anhand dieser Zeit treibst du die Logik voran, also um wieviel Pixel sich ein Auto wohin bewegt. Diese Abhängigkeit zur Zeit ist nötig damit die Animation später sowohl auf urlangsamen als auch highspeed Rechnern bzw unter verschiedenen Systemauslastungen gleichschnell abläuft.

Für's erste kannst du das aber mal ignorieren und pseudo-konstante Abläufe mittels einem konstanten sleep() in den Durchläufen darstellen, reicht erstmal auch aus, ist halt nur nich "state of the art".

Das hat aber alles noch nix mit den Dingen zu tun von denen du hier redest, ich sag's dir nur mal, falls du das bisher irgendwie anders gemacht hast 😉

Wenn ein Auto "schön" abbiegen soll, musst du diese Animation per Hand implementieren, da kommste nich dran vorbei. Natürlich mag es im Netz irgendwo vorgefertigte Engines geben, so mit Sprites usw, aber ist die Frage worauf es dir hier ankommt: Das Endergebnis, oder das Programmieren.

edit: Ich setz mich jetz doch mal hin und versuch was zu machen
 
Zuletzt bearbeitet:
Was ich mit dynamisch befüllen meine? Naja die Autos sollten aj auch einigermaßen Kreisförmig um die Kurve gehen und nicht aprubt (schreibt man das so?) sodass ich Listen mit viel Informationen hätte...
Solche Informationen würde ich nicht in der "Weg"Liste des Autos speichern, sondern im Streckennetz. Eine Kurve/Strecke liese sich dann durch eine mathematische Funktion oder eine Abfolge von Koordinaten beschreiben. Das Auto muss dann nur noch wissen, in welcher Richtung es die Kurve durch fährt, dabei fragt das Auto in festen Zeitintervallen die nächste anzufahrende Position ab. Wie im echten Leben, da merkst Du Dir ja auch nur Kreuzungs- und Abzweigungspunkte und "tastest" beim Fahren die Strecke mit den Augen ab.
 
Und genau bei diesem Punkt sind wir - sofenr cih das als Neuling einschätzen kann - wieder bei einigen if-Bedingungen, weil die Funktion für diese hübsche Kreisform aber irgend einem Punkte keine Funktion mehr ist, sondern nurnoch aus y++ und x als Konstante besteht(Erfolgreich abgebogen).

als Kreisfunktion habe ich testweise (r^2-x^2)^0.5 genommen aber die if Abfragen machen es meiner Meinung nach nicht erweiterbar.

Beim schreiben fällt mir aber auf, dass ich die if abfragen relativ zur Kreuzung angeben kann, sodass die Punkte nicht Händisch eingegeben werden müssen. Diese Möglichkeit müsste funktionieren. Für heute ist bei mir aber vorerst mal schluss.
Weiß leider nicht, ob ich morgen direkt noch was dazu machen kann.
 
Naja du kannst if-Abfragen auch nicht immer vollständig beseitigen.Wenn du ein if in deinem Programm hast, heißt das nicht gleich dass es "undynamisch" ist. Irgendwo musst du ja ganz konkret werden, ein Programm kann ja nicht erraten was du willst.
Die Frage ist nur, wo das if steht, wenn du denn eins brauchst. Es muss halt an einer Stelle im Code/in einer Klasse stehen, die unabhängig von der restlichen Implementierung ist. Undynamisch heißt ja dass du bei Änderungen/Erweiterungen anfangen musst an etlichen Stellen etwas zu ändern. Dass du irgendwo eine Änderungen hast, ist ja klar, und wenn das jetzt ein if ist, ist das völlig ok.

Wie gesagt das find ich grad auch spannend und ich werd heut abend da bisschen was machen, ich hoff es kommt was raus was du gebrauchen kannst.

lg
 
So ich glaube mir ist heute abend eine Lösung eingefallen - hab aber leider nur Wörter um das ganze zu beschreiben^^:
Ich erstelle ein Objekt Kreuzung mit verschiedenen Parametern wie die Koordinaten, die Breite und Höhe der Straßen 0 und 1, die sich Kreuzen.
gehen wir das ganze nun exemplarisch vor
Auto1 nähert sich der Kreuzung von rechts und will rechts abbiegen. Sobald AutoX <= Math.abs(KreuzungX-KreuzungsStrasseX[1]/2) muss die Methode der Kreuzung aufgerufen werden, die eine Veränderung der Funktion f(x)=(r^2-x^2)^0.5 so übergibt, dass es auf die spezifische Kreuzung passt (Koordinatenverschiebung und strecken bzw dehnen). Der Steigung der Funktion entsprechend werden die Gradzahlen addiert bis diese 90 ergeben
Sobald das Auto den Bereich AutoX <= Math.abs(KreuzungY- KreuzungsStrasseY[0]) verlässt, wird x konstant und y erhöht sich entsprechend delta.

Hoffe das war verständlich. Ich werde mich mal morgen oder so dransetzen und dann sehen was dabei rauskommt.
 
Ich hätte jetzt vermutet, dass es eigentlich um Alles geht, was mit Interpolation zu tun hat. Als Beispiel: Man will bei einer Kreuzung zum Rechtsabbiegen eigentlich nur zwei Punkte definieren. Einen direkt vor der Kreuzung, wo das Auto senkrecht nach oben schaut. Und einen am Anfang der rechten Seitenstraße der Kreuzung, wo das Auto nach rechts schaut. Dazwischen soll sich das Auto selbst eine plausible Bewegung suchen.
Eine Möglichkeit, das umzusetzen, wäre eine Liste mit Objekten, die eine Position und einen Winkel speichern:
Eintrag 0: Position 10,10, Winkel: 90°
Eintrag 1: Position 15,15, Winkel: 0°
Dazwischen kann man mit einem Wert zwischen 0.0 und 1.0 Interpolieren, z.B. kreigt man
für 0.5: Position 12.5,12.5, Winkel: 45°

Einiges dazu gibt's im https://timingframework.dev.java.net/ oder in Java3D also sowas wie RotPosPathInterpolator (Java 3D 1.4.0) , allerdings brauchst du was recht spezielles, und nur 2D, d.h. da könnte es vielleicht(!) einfacher/sinnvoller sein, selbst was zu basteln....
 

Zurück
Oben