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
{
////// Scroll LEFT with Vert Accelleration
////// Scroll LEFT
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
{
////// Add LEFT accelleration
SpeedX = AxisValue * ScrollAccelleration;
AddActorLocalOffset(FVector(0, SpeedX, 0));
AddActorLocalOffset(FVector(SpeedX, 0, 0));
}
}
if (mousePosX >= 1-ESASize) // if in RIGHT area
{
////// Scroll RIGHT with Vert Accelleration
////// Scroll RIGHT
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
{
////// Add RIGHT accelleration
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
{
////// Scroll TOP with Side Accelleration
////// Scroll TOP
float SpeedY = (mousePosY * ESAMinBoundSlope + ESAMinBoundIntercept) * BaseScrollSpeed;
AddActorLocalOffset(FVector(SpeedY, SideAccelleration, 0));
AddActorLocalOffset(FVector(0, -SpeedY, 0));
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
{
////// Add TOP accelleration
SpeedY = AxisValue * ScrollAccelleration;
AddActorLocalOffset(FVector(SpeedY, 0, 0));
AddActorLocalOffset(FVector(0, -SpeedY, 0));
}
}
if (mousePosY >= 1-ESASize) // if in BOTTOM area
{
////// Scroll BOTTOM with Side Accelleration
////// Scroll BOTTOM
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
{
////// add BOTTOM accelleration
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()
{
int32 RandHex = GridIndex(FMath::RandRange(0, GridSize-1), FMath::RandRange(0, GridSize-1));
int32 RandHex = FMath::RandRange(0, GridSize*GridSize-1);
return Grid[RandHex];
}
TArray<AHexTile*> AAdventureMap::Neighbors(AHexTile* OfHex)
{
TArray<AHexTile*> Neighbors;
int32 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]); }
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]); }
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),
GridIndex(OfHex->Q-1, OfHex->R+1), GridIndex(OfHex->Q, OfHex->R+1) };
TArray<int32> Indeces;
Indeces.Append(Arr, UE_ARRAY_COUNT(Arr));
Neighbors.Add(RandomHex());
for (auto& I : Indeces) { if (Grid.IsValidIndex(I) && OfHex->Distance(Grid[I]) == 1) { Neighbors.Add(Grid[I]); } }
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*> 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
while (!PQ.IsEmpty())
{
AHexTile* Current = PQ[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
{
UE_LOG(LogTemp, Warning, TEXT("Goal found!!!")); // debug
// UE_LOG(LogTemp, Warning, TEXT("Goal found!!!")); // debug
break;
}
UE_LOG(LogTemp, Warning, TEXT("Expanding the frontier...")); // debug
// UE_LOG(LogTemp, Warning, TEXT("Expanding the frontier...")); // debug
for (AHexTile* Next : Neighbors(Current))
{
int32 NewCost = Current->CostSoFar + Next->MoveCost;
@ -143,33 +129,36 @@ TArray<AHexTile*> AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal)
PQ.Remove(Next);
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())
{
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);
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;
}
}
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);
}
else
{
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;
/*
AHexTile* Hex = Goal;
while (Hex != Start)
{
@ -177,5 +166,6 @@ TArray<AHexTile*> AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal)
Hex = Hex->CameFrom;
}
Algo::Reverse(Path);
*/
return Path;
}