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:
Ich lasse das ganz in einem spawn laufen, da es doch ein paar Frames dauern kann bis die Suche abgeschlossen ist.
Beachtet, dass die Paramter Straßenstücke sein müssen:
Beispiel Aufruf: [player nearRoads 10 select 0, (getMarkerPos (allMapMarkers select 0)) nearRoads 10 select 0] call NF_fnc_AStar;
Code
- NF_fnc_AStar = {
- _this spawn {
- params ["_start", "_goal"];
- private _closedSet = [];
- private _openSet = [_start];
- private _current = _start;
- while {!(_openSet isEqualTo [])} do {
- private _closest = objNull;
- {
- if (_goal distance _x < _goal distance _closest) then {
- _closest = _x;
- };
- nil
- } count _openSet;
- _current = _closest;
- private _tmpMarker = createMarker ["tmp" + str _current, getPos _current];
- _tmpMarker setMarkerShape "ICON";
- _tmpMarker setMarkerColor "ColorBlack";
- _tmpMarker setMarkerType "MIL_DOT";
- if (_current == _goal) exitWith {
- private _parent = missionNamespace getVariable ("NF_neighborParent_" + str _current);
- while {!(isNil "_parent")} do {
- private _marker = createMarker [str _parent, getPos _parent];
- _marker setMarkerShape "ICON";
- _marker setMarkerColor "ColorRed";
- _marker setMarkerType "MIL_DOT";
- _parent = missionNamespace getVariable ("NF_neighborParent_" + str _parent);
- };
- };
- _openSet = _openSet - [_current];
- _closedSet pushBack _current;
- private _neighbors = (getPos _current) nearRoads 15; // This includes current
- _neighbors append (roadsConnectedTo _current);
- {
- if (!(_x in _closedSet)) then {
- private _currentG = missionNamespace getVariable ["NF_neighborG_" + str _current, 0];
- private _gScore = _currentG + 1;
- private _gScoreIsBest = false;
- if (!(_x in _openSet)) then {
- _gScoreIsBest = true;
- _openSet pushBack _x;
- } else {
- private _neighborG = missionNamespace getVariable ("NF_neighborG_" + str _x);
- _gScoreIsBest = _gScore < _neighborG;
- };
- if (_gScoreIsBest) then {
- missionNamespace setVariable ["NF_neighborParent_" + str _x, _current];
- missionNamespace setVariable ["NF_neighborG_" + str _x, _gScore];
- };
- };
- nil
- } count _neighbors;
- };
- };
- };