A* algorithm now working as intended

This commit is contained in:
Maximilian Fajnberg 2022-01-18 17:01:31 +01:00
parent 5c1535da32
commit 80e990c432
2 changed files with 41 additions and 51 deletions

View File

@ -78,39 +78,39 @@ void AAdventureCameraPawn::EdgeScrollSide(float AxisValue)
if (mousePosX <= ESASize) // if in LEFT area if (mousePosX <= ESASize) // if in LEFT area
{ {
////// Scroll LEFT with Vert Accelleration ////// Scroll LEFT
float SpeedX = (mousePosX * ESAMinBoundSlope + ESAMinBoundIntercept) * BaseScrollSpeed; float SpeedX = (mousePosX * ESAMinBoundSlope + ESAMinBoundIntercept) * BaseScrollSpeed;
AddActorLocalOffset(FVector(0, -SpeedX, 0)); AddActorLocalOffset(FVector(-SpeedX, 0, 0));
if (mousePosY > .005) // if not touching EDGE if (mousePosY > .005) // if not touching TOP EDGE
{ {
AddActorLocalOffset(FVector(VertAccelleration, 0, 0)); AddActorLocalOffset(FVector(0, -VertAccelleration, 0));
} }
if (AxisValue < .0 && mousePosX <= .005) // if mouse moving LEFT and touching EDGE if (AxisValue < .0 && mousePosX <= .005) // if mouse moving LEFT and touching EDGE
{ {
////// Add LEFT accelleration ////// Add LEFT accelleration
SpeedX = AxisValue * ScrollAccelleration; SpeedX = AxisValue * ScrollAccelleration;
AddActorLocalOffset(FVector(0, SpeedX, 0)); AddActorLocalOffset(FVector(SpeedX, 0, 0));
} }
} }
if (mousePosX >= 1-ESASize) // if in RIGHT area if (mousePosX >= 1-ESASize) // if in RIGHT area
{ {
////// Scroll RIGHT with Vert Accelleration ////// Scroll RIGHT
float SpeedX = (mousePosX * ESAMaxBoundSlope + ESAMaxBoundIntercept) * BaseScrollSpeed; float SpeedX = (mousePosX * ESAMaxBoundSlope + ESAMaxBoundIntercept) * BaseScrollSpeed;
AddActorLocalOffset(FVector(0, SpeedX, 0)); AddActorLocalOffset(FVector(SpeedX, 0, 0));
if (mousePosY < .995) // if not touching EDGE if (mousePosY < .995) // if not touching BOT EDGE
{ {
AddActorLocalOffset(FVector(VertAccelleration, 0, 0)); AddActorLocalOffset(FVector(0, -VertAccelleration, 0));
} }
if (AxisValue > .0 && mousePosX >= .995) // if mouse moving RIGHT and touching EDGE if (AxisValue > .0 && mousePosX >= .995) // if mouse moving RIGHT and touching EDGE
{ {
////// Add RIGHT accelleration ////// Add RIGHT accelleration
SpeedX = AxisValue * ScrollAccelleration; SpeedX = AxisValue * ScrollAccelleration;
AddActorLocalOffset(FVector(0, SpeedX, 0)); AddActorLocalOffset(FVector(SpeedX, 0, 0));
} }
} }
} }
@ -126,39 +126,39 @@ void AAdventureCameraPawn::EdgeScrollVert(float AxisValue)
if (mousePosY <= ESASize) // if in TOP area if (mousePosY <= ESASize) // if in TOP area
{ {
////// Scroll TOP with Side Accelleration ////// Scroll TOP
float SpeedY = (mousePosY * ESAMinBoundSlope + ESAMinBoundIntercept) * BaseScrollSpeed; float SpeedY = (mousePosY * ESAMinBoundSlope + ESAMinBoundIntercept) * BaseScrollSpeed;
AddActorLocalOffset(FVector(SpeedY, SideAccelleration, 0)); AddActorLocalOffset(FVector(0, -SpeedY, 0));
if (mousePosX > .005) // if not touching EDGE if (mousePosX > .005) // if not touching EDGE
{ {
AddActorLocalOffset(FVector(0, SideAccelleration, 0)); AddActorLocalOffset(FVector(SideAccelleration, 0, 0));
} }
if (AxisValue > .0 && mousePosY <= .005) // if mouse moving TOP and touching EDGE if (AxisValue > .0 && mousePosY <= .005) // if mouse moving TOP and touching EDGE
{ {
////// Add TOP accelleration ////// Add TOP accelleration
SpeedY = AxisValue * ScrollAccelleration; SpeedY = AxisValue * ScrollAccelleration;
AddActorLocalOffset(FVector(SpeedY, 0, 0)); AddActorLocalOffset(FVector(0, -SpeedY, 0));
} }
} }
if (mousePosY >= 1-ESASize) // if in BOTTOM area if (mousePosY >= 1-ESASize) // if in BOTTOM area
{ {
////// Scroll BOTTOM with Side Accelleration ////// Scroll BOTTOM
float SpeedY = (mousePosY * ESAMaxBoundSlope + ESAMaxBoundIntercept) * BaseScrollSpeed; float SpeedY = (mousePosY * ESAMaxBoundSlope + ESAMaxBoundIntercept) * BaseScrollSpeed;
AddActorLocalOffset(FVector(-SpeedY, SideAccelleration, 0)); AddActorLocalOffset(FVector(0, SpeedY, 0));
if (mousePosX < .995) // if not touching EDGE if (mousePosX < .995) // if not touching BOT EDGE
{ {
AddActorLocalOffset(FVector(0, SideAccelleration, 0)); AddActorLocalOffset(FVector(SideAccelleration, 0, 0));
} }
if (AxisValue < .0 && mousePosY >= .995) // if mouse moving BOTTOM and touching EDGE if (AxisValue < .0 && mousePosY >= .995) // if mouse moving BOTTOM and touching EDGE
{ {
////// add BOTTOM accelleration ////// add BOTTOM accelleration
SpeedY = AxisValue * ScrollAccelleration; SpeedY = AxisValue * ScrollAccelleration;
AddActorLocalOffset(FVector(SpeedY, 0, 0)); AddActorLocalOffset(FVector(0, -SpeedY, 0));
} }
} }

View File

@ -82,57 +82,43 @@ int32 AAdventureMap::GridIndex(int32 qAxial, int32 rAxial)
AHexTile* AAdventureMap::RandomHex() AHexTile* AAdventureMap::RandomHex()
{ {
int32 RandHex = GridIndex(FMath::RandRange(0, GridSize-1), FMath::RandRange(0, GridSize-1)); int32 RandHex = FMath::RandRange(0, GridSize*GridSize-1);
return Grid[RandHex]; return Grid[RandHex];
} }
TArray<AHexTile*> AAdventureMap::Neighbors(AHexTile* OfHex) TArray<AHexTile*> AAdventureMap::Neighbors(AHexTile* OfHex)
{ {
TArray<AHexTile*> Neighbors; TArray<AHexTile*> Neighbors;
int32 I; int32 Arr[] = { GridIndex(OfHex->Q+1, OfHex->R), GridIndex(OfHex->Q+1, OfHex->R-1),
GridIndex(OfHex->Q, OfHex->R-1), GridIndex(OfHex->Q-1, OfHex->R),
I = GridIndex(OfHex->Q + 1 , OfHex->R + 0 ); GridIndex(OfHex->Q-1, OfHex->R+1), GridIndex(OfHex->Q, OfHex->R+1) };
if (Grid.IsValidIndex(I) && OfHex->Distance(Grid[I]) == 1) { Neighbors.Add(Grid[I]); } TArray<int32> Indeces;
Indeces.Append(Arr, UE_ARRAY_COUNT(Arr));
I = GridIndex(OfHex->Q + 1 , OfHex->R - 1 );
if (Grid.IsValidIndex(I) && OfHex->Distance(Grid[I]) == 1) { Neighbors.Add(Grid[I]); }
I = GridIndex(OfHex->Q + 0 , OfHex->R - 1 );
if (Grid.IsValidIndex(I) && OfHex->Distance(Grid[I]) == 1) { Neighbors.Add(Grid[I]); }
I = GridIndex(OfHex->Q - 1 , OfHex->R + 0 );
if (Grid.IsValidIndex(I) && OfHex->Distance(Grid[I]) == 1) { Neighbors.Add(Grid[I]); }
I = GridIndex(OfHex->Q - 1 , OfHex->R + 1 );
if (Grid.IsValidIndex(I) && OfHex->Distance(Grid[I]) == 1) { Neighbors.Add(Grid[I]); }
I = GridIndex(OfHex->Q + 0 , OfHex->R + 1 );
if (Grid.IsValidIndex(I) && OfHex->Distance(Grid[I]) == 1) { Neighbors.Add(Grid[I]); }
Neighbors.Add(RandomHex());
for (auto& I : Indeces) { if (Grid.IsValidIndex(I) && OfHex->Distance(Grid[I]) == 1) { Neighbors.Add(Grid[I]); } }
return Neighbors; return Neighbors;
} }
// Massive memory leak when Goal is more than 2 distance away from Start (leading to the Editor freezing)
// Also freezes when the Goal is on the Edge of the map (i.e. has only 3 Neighbors)
TArray<AHexTile*> AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal) TArray<AHexTile*> AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal)
{ {
TArray<AHexTile*> PQ; // Makeshift Priority Queue. (High value = Low priority) TArray<AHexTile*> PQ; // Makeshift Priority Queue. (High value = Low priority)
PQ.Init(Start, 1); PQ.Add(Start);
// The goal of this loop is to edit the Hex->CameFrom pointers, So as to chain Hexes from Goal to Start // The goal of this loop is to edit the Hex->CameFrom pointers, So as to chain Hexes from Goal to Start
while (!PQ.IsEmpty()) while (!PQ.IsEmpty())
{ {
AHexTile* Current = PQ[0]; AHexTile* Current = PQ[0];
PQ.RemoveAt(0); PQ.RemoveAt(0);
UE_LOG(LogTemp, Warning, TEXT("Popping top priority Hex Q:%d|R:%d"), Current->Q, Current->R); // UE_LOG(LogTemp, Warning, TEXT("Popping top priority Hex %d:%d"), Current->Q, Current->R); // debug
if (Current == Goal) // early exit if (Current == Goal) // early exit
{ {
UE_LOG(LogTemp, Warning, TEXT("Goal found!!!")); // debug // UE_LOG(LogTemp, Warning, TEXT("Goal found!!!")); // debug
break; break;
} }
UE_LOG(LogTemp, Warning, TEXT("Expanding the frontier...")); // debug // UE_LOG(LogTemp, Warning, TEXT("Expanding the frontier...")); // debug
for (AHexTile* Next : Neighbors(Current)) for (AHexTile* Next : Neighbors(Current))
{ {
int32 NewCost = Current->CostSoFar + Next->MoveCost; int32 NewCost = Current->CostSoFar + Next->MoveCost;
@ -143,33 +129,36 @@ TArray<AHexTile*> AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal)
PQ.Remove(Next); PQ.Remove(Next);
int32 NewPrio = NewCost + Next->Distance(Goal); // Higher value = Lower priority int32 NewPrio = NewCost + Next->Distance(Goal); // Higher value = Lower priority
UE_LOG(LogTemp, Warning, TEXT("Hex Q:%d|R:%d pathing updated. Readjusting priorities..."), Next->Q, Next->R); // debug // no crash up to this point
// UE_LOG(LogTemp, Warning, TEXT("Hex %d:%d path info updated. Readjusting priorities..."), Next->Q, Next->R); // debug
if (!PQ.IsEmpty()) if (!PQ.IsEmpty())
{ {
int32 OldPrio; int32 OldPrio;
int32 OldIndex = PQ.Num() - 1; // To be inserted as lowest priority by default int32 OldIndex = PQ.Num() - 1; // default to lowest priority
for (AHexTile* Hex : PQ) for (auto& Hex : PQ)
{ {
OldPrio = Hex->CostSoFar + Hex->Distance(Goal); OldPrio = Hex->CostSoFar + Hex->Distance(Goal);
if (NewPrio <= OldPrio) // looking for 1. Hex in "PQ" with a lower priority than that of "Next" if (NewPrio <= OldPrio) // looking for 1. Hex in "PQ" with a lower priority than that of "Next"
{ {
PQ.Find(Hex, OldIndex); // redefining of "OldIndex" PQ.Find(Hex, OldIndex); // redefine OldIndex
break; break;
} }
} }
UE_LOG(LogTemp, Warning, TEXT("Inserting Hex at priority %d"), OldIndex); // debug // UE_LOG(LogTemp, Warning, TEXT("Saving at PQ index %d"), OldIndex); // debug
PQ.Insert(Next, OldIndex); PQ.Insert(Next, OldIndex);
} }
else else
{ {
PQ.Add(Next); PQ.Add(Next);
UE_LOG(LogTemp, Warning, TEXT("Adding one last Candidate.")); // debug // UE_LOG(LogTemp, Warning, TEXT("Adding (PQ was empty)")); // debug
} }
} }
} }
} }
TArray<AHexTile*> Path; TArray<AHexTile*> Path;
/*
AHexTile* Hex = Goal; AHexTile* Hex = Goal;
while (Hex != Start) while (Hex != Start)
{ {
@ -177,5 +166,6 @@ TArray<AHexTile*> AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal)
Hex = Hex->CameFrom; Hex = Hex->CameFrom;
} }
Algo::Reverse(Path); Algo::Reverse(Path);
*/
return Path; return Path;
} }