SCAR Code:
program New;
{.include paths.scar}
{.include llist.scar}
// Basic variables
var charx,chary, destx, desty:integer;
arrived: boolean;
function TPt(x,y:integer):TPoint;
begin
result.x := x;
result.y := y;
end;
// Basic math, used for path finding
function AngleBetweenPoints(x1,y1,x2,y2:integer):extended;
begin
result := Arctan2(y2-y1,x2-x1) * 180 / Pi;
if result < 0 then
result := Abs(result) + 180;
end;
// Test function, dupes move to function from reflection
function MoveTo(p:TPoint):boolean;
begin
if (charx = p.x) and (chary = p.y) then
begin
result := false;
exit;
end;
charx := p.x;
chary := p.y;
writeln('Moved to :' + inttostr(p.x) + ',' + inttostr(p.y));
result := true;
end;
// Required to create and link paths, might make the paths into an ini
// file that will update itself automatically, but this is a test version
procedure Initialize();
begin
CreatePath(path1());
CreatePath(path2());
CreatePath(path3());
CreatePath(path4());
CreatePath(path5());
LinkPath(0,1);
LinkPath(0,2);
LinkPath(0,4);
LinkPath(1,2);
LinkPath(1,3);
LinkPath(1,4);
LinkPath(2,3);
LinkPath(3,4);
end;
// Loops through all of the TPA's and checks which path has the closest average point
function FindClosestPath():integer;
var i:integer;
length: extended;
begin
length := 5000;
for i := 0 to high(paths) do
begin
if length > Distance(charx, chary, paths[i].avg.x, paths[i].avg.y) then
begin
length := Distance(charx, chary, paths[i].avg.x, paths[i].avg.y);
result := i;
end;
end;
end;
// Like previous function, but this one finds the closest point in an array
function FindClosestPointInTPA(arr:TPointArray):integer;
var i,y:integer;
z:extended;
begin
z := 5000;
for i := 0 to High(arr) do
begin
if z > Distance(charx, chary, arr[i].x, arr[i].y) then
begin
y := i;
z := Distance(charx, chary, arr[i].x, arr[i].y);
end;
end;
result := y;
end;
// Will move through the TPA, checking if it's at the destination yet, or if it finished going through the TPA
procedure AutoMoveThroughTPA(start,inc:integer; node:TPointArray);
var i:integer;
begin
i := start - inc;
repeat
i := i + inc;
if MoveTo(node[i]) = true then
wait(100);
if (node[i].x = destx) and (node[i].y = desty) then
begin
arrived := true;
exit;
end;
until (((i = 0) and (i <> start)) or ((i = high(node)) and (high(node) <> start)))
end;
// Will check if the path is accesable, because it might be only connected in the opposite side of a path
function Pathable(path:integer):boolean;
begin
result := false;
if Distance(charx, chary, paths[path].first.x, paths[path].first.y) < Distance(charx, chary, paths[path].last.x, paths[path].last.y)then
begin
if (charx = paths[path].first.x) and (chary = paths[path].first.y) then
result := true
end;
if Distance(charx, chary, paths[path].first.x, paths[path].first.y) > Distance(charx, chary, paths[path].last.x, paths[path].last.y)then
begin
if (charx = paths[path].last.x) and (chary = paths[path].last.y) then
result := true
end;
end;
// Since we don't know how the character will go through the path (increasing or decreasing) we call this function
procedure TakePath(path:integer);
begin
if Distance(charx, chary, paths[path].first.x, paths[path].first.y) < Distance(charx, chary, paths[path].last.x, paths[path].last.y) then
begin
AutoMoveThroughTPA(0, 1, paths[path].node)
end else
begin
AutoMoveThroughTPA(high(paths[path].node), -1, paths[path].node)
end;
end;
// Function that will find the farthest end of a path, takes path index
function FarthestEndX(path:integer):integer;
begin
if Distance(charx, chary, paths[path].first.x, paths[path].first.y) > Distance(charx, chary, paths[path].last.x, paths[path].last.y) then
result := paths[path].first.x
else
result := paths[path].last.x;
end;
// Function that will find the farthest end of a path, takes path index
function FarthestEndY(path:integer):integer;
begin
if Distance(charx, chary, paths[path].first.x, paths[path].first.y) > Distance(charx, chary, paths[path].last.x, paths[path].last.y) then
result := paths[path].first.y
else
result := paths[path].last.y;
end;
// Checks how far away are the angles
function DegreeDiff(A, B:extended):extended;
begin
result:= Abs(A-B);
if result>180.0 then
result:= 180.0-(result-180.0);
end;
// Dick and balls of the script, it gets the shit done
function move(x,y:integer):boolean;
var p, n, curpath, lastpath:integer;
c, cd: extended;
node: TPointArray;
begin
c := 360;
arrived := false;
destx := x;
desty := y;
lastpath := -1;
curpath := FindClosestPath;
node := paths[curpath].node;
p := FindClosestPointinTPA(paths[curpath].node);
cd := AngleBetweenPoints(charx, chary, x, y);
if (p <> 0) and (p <> high(paths[curpath].node)) then
begin
if DegreeDiff(cd,AngleBetweenPoints(charx, chary, node[p+1].x,node[p+1].y)) < DegreeDiff(cd,AngleBetweenPoints(charx, chary, node[p-1].x, node[p-1].y)) then
begin
AutoMoveThroughTPA(p+1, 1, node);
end else
begin
AutoMoveThroughTPA(p-1, -1, node);
end;
end;
while (arrived = false) do
begin
cd := AngleBetweenPoints(charx, chary, x, y);
for p := 0 to high(paths[curpath].connection) do
begin
if (c > DegreeDiff(cd, AngleBetweenPoints(FarthestEndX(paths[paths[curpath].connection[p]].index), FarthestEndY(paths[paths[curpath].connection[p]].index), x, y))) and (p <> lastpath) and (Pathable(paths[paths[curpath].connection[p]].index) = true) then
begin
c := AngleBetweenPoints(FarthestEndX(paths[paths[curpath].connection[p]].index), FarthestEndY(paths[paths[curpath].connection[p]].index), x, y);
n := p;
end;
end;
c := 360;
TakePath(paths[paths[curpath].connection[n]].index);
lastpath := curpath;
curpath := n;
end;
end;
begin
Initialize;
ClearDebug;
MoveTo(TPt(5,0));
Move(0,7);
end.
SCAR Code:
// paths.scar
function path1: TPointArray;
begin
SetLength(Result, 8);
Result[0] := Point(0, 0);
Result[1] := Point(0, 1);
Result[2] := Point(0, 2);
Result[3] := Point(0, 3);
Result[4] := Point(0, 4);
Result[5] := Point(0, 5);
Result[6] := Point(0, 6);
Result[7] := Point(0, 7);
end;
function path2: TPointArray;
begin
SetLength(Result, 8);
Result[0] := Point(0, 0);
Result[1] := Point(1, 1);
Result[2] := Point(2, 2);
Result[3] := Point(3, 3);
Result[4] := Point(4, 4);
Result[5] := Point(5, 5);
Result[6] := Point(6, 6);
Result[7] := Point(7, 7);
end;
function path3: TPointArray;
begin
SetLength(Result, 8);
Result[0] := Point(0, 0);
Result[1] := Point(1, 0);
Result[2] := Point(2, 0);
Result[3] := Point(3, 0);
Result[4] := Point(4, 0);
Result[5] := Point(5, 0);
Result[6] := Point(6, 0);
Result[7] := Point(7, 0);
end;
function path4: TPointArray;
begin
SetLength(Result, 8);
Result[0] := Point(7, 0);
Result[1] := Point(7, 1);
Result[2] := Point(7, 2);
Result[3] := Point(7, 3);
Result[4] := Point(7, 4);
Result[5] := Point(7, 5);
Result[6] := Point(7, 6);
Result[7] := Point(7, 7);
end;
function path5: TPointArray;
begin
SetLength(Result, 8);
Result[0] := Point(0, 7);
Result[1] := Point(1, 7);
Result[2] := Point(2, 7);
Result[3] := Point(3, 7);
Result[4] := Point(4, 7);
Result[5] := Point(5, 7);
Result[6] := Point(6, 7);
Result[7] := Point(7, 7);
end;