Pathfinding in SQF

  • Auf Grund eines Videos und einem provokativen Kommentar nachdem ich Optimierungen vorschlug, habe ich mich entschlossen das ganz selbst umzusetzen.


    Prinzipiell geht es darum einen Weg zwischen zwei Straßen zu finden und dabei Kreuzungen in die Berechnung mit einzubeziehen.


    Ich habe den A*-Algorithmus verwendet.
    Das Ergebnis ist zufriedenstellend:



    Mein Code:

  • Würde eine Gewichtung der Straßen vorschlagen.
    Da eine Route über Feldwege zwar die kürzeste aber nicht immer die schnellste ist.


    Als Beispiel A-B Feldweg 5km
    A-C 3km Landstraße
    C-B 3km Autobahn
    Trotz der längeren Strecke wäre der Weg über C effektiver in Betracht auf die Zeit.

  • I worked a bit on the code :D
    nice work
    Verdammt dieses Englisch...
    Schöne arbeit!
    Hab da ein wenig dran gebastelt und den Thread gekarpert ;)

  • Man kann zumindest die Hauptstraße von den Nebenstraßen unterscheiden.
    Das macht man, indem man die Straßenbreite analysiert -> die Hauptstraße ist ein Stück breiter als die Nebenstraßen.


    (Richtungsvektor der Straße drehen und dann stück für Stück schauen, wie breit sie ist.) Link



    Ein weiterer Weg wäre den Untergrund zu überprüfen mit "surfacetype"
    Die Variante hat sich bei mir jedoch nicht unbedingt als so zuverlässig herausgestellt. Auf Altis klappt das im Westen sehr gut, aber im Osten klappt es gar nicht.



    EDIT:
    Die Variante mit der Straßenbreite ist relativ zuverlässig. Jedoch in Kreuzungsbereichen ist sie es natürlich nicht.
    Insgesamt könnte man jedoch die Breite der Straße, sozusagen der Wert der Straßensegmente, immer über die Einzelnen Abschnitte (Kreuzung bis Kreuzung) glätten.

  • Da der Algorithmus aktuell die Anzahl der Straßensegmente als Gewichtung nimmt, sollte er sogar Hauptstraßen bevorzugen, da diese meiner Meinung nach größere Abstände zwischen den einzelnen Segmenten haben. Vielleicht irre ich mich da auch...


    Deine Idee mit der Bereite ist eine gute Idee. Mit dem neuen Befehl roadAt könnte man dann in der Messschleife noch prüfen ob es sich tatsächlich um das gleiche Segment handelt und damit auch Probleme in Kreuzungsbereichen umgehen.

  • Danke für den Hinweis. Ich werde bei Gelegenheit einmal das Script neu schreiben.
    Noch ein kleines Bild mit den Straßen laut meinem veraltetem Script:



    Deine Unterscheidung mittels des Abstandes würde ich noch einmal prüfen. Ich glaube eher, dass es abhängig von der Kurvigkeit der Strecke ist.
    Als Alternative könntest du die echte Strecke zwischen Segmenten nehmen und nur die Kreuzungen jeweils als Wegpunkte nutzen.


    Was mir damals aufgefallen war, ist das bei manchen Kreuzungen die Straßen nur optisch kreuzen. Das tritt selten auf, ist jedoch möglich.
    Die Brücken sind auch eine kleine Ausnahme.

  • Ein weiterer Weg wäre den Untergrund zu überprüfen mit "surfacetype"
    Die Variante hat sich bei mir jedoch nicht unbedingt als so zuverlässig herausgestellt. Auf Altis klappt das im Westen sehr gut, aber im Osten klappt es gar nicht.

    "surfaceType" gibt den Typ des Untergrundes unter der Straße wieder und hat mit der Straße leider nix zu tun. Da gibt (gab?) es auch ein Ticket für.

  • da ich es die Code Strucktur von Coding echt abschreckend fand... sorry aber foreach und dann auch noch neue zeile heueueu, und du auch noch einen non stackable EH nutzt musste ich das anpssen. dazu habe ich auch ein function etwas mehr zusammen gefasst denn etwas was man 2x schreibt lohnt es sich eine function zu benutzten. dazu finde ich es grausam wenn man ein einer code datei 2 typen von Function/Variablen Tags nutzt alles Bad Code Practice


  • NF ist denke ich mal das Tag von NetFusion und CODI ist meins...
    Finde da kein BadPractice.
    Weshalb ist foreach böse?
    Ich finde count im gegenzug sehr verwirrend.
    PF_fnc_getNearestRoad ist schick, ebenso PF_fnc_start
    Korrekterweise fehlt da aber noch das OnPlayerRespawnZeugs :P
    Ich wäre im übrigen sparsamer mit Kritik wenn ich ungetesteten Code poste...


    Denke nicht, dass das der Optimale Weg ist:
    http://images.akamai.steamuser…A64C16452BABF5577521E8BE/

  • Statt "onMapSingleClick {}" müsste man:

    C
    1. addMissionEventHandler ["MapSingleClick", {}];

    benützen, da diese Mod ansonsten alle anderen Addons, die irgendwas in der Art mit der Karte machen, zerstört.


    Außerdem fügt "(on)MapSingleClick" das Event zu jedem Karten-Control hinzu, d.h. auch diverse andere GPS / Navipads / mDAGRs würden mit diesen Skript beladen werden, was wahrscheinlich zu Fehlern führt. Man müsste also eigentlich die Events zum richtigen Karten-Control via "ctrlAddEventHandler" hinzufügen.


    Bei joko fehlt in Z:55 das Semikolon.

  • einfach auf nil setzten. dadurch hat man die variable "gelöscht" jedoch geht das !nur! auf Namespace, d.h. auf objecten Locations Displays und wo set/getVariable noch überall geht nicht da sie dort nicht gelöscht wird sonder nur auf nil gesetzt wird. mal wieder so ein doofer BI bug

  • Hab A* nochmal implementiert.
    Kosten = distanz von einem RoadTeil zum anderen (Straßenart wird nicht berücksichtigt)
    Heuristik = 1.33*Distanz zum Ziel


    berührte knoten:


    route:


    Code: