From 21f7dd4e67573f76406e399616130f9724b73f27 Mon Sep 17 00:00:00 2001 From: Maximilian Fajnberg Date: Wed, 25 May 2022 20:07:51 +0200 Subject: [PATCH] port to UE5 and new development environment; consequential leeway --- AdventureCameraPawn.cpp | 8 ++++ AdventureCameraPawn.h | 2 + AdventureMap.cpp | 92 +++++++++++++++++++++++++++-------------- AdventureMap.h | 3 +- MapObject.h | 4 +- 5 files changed, 74 insertions(+), 35 deletions(-) diff --git a/AdventureCameraPawn.cpp b/AdventureCameraPawn.cpp index 97f94db..0795c8c 100644 --- a/AdventureCameraPawn.cpp +++ b/AdventureCameraPawn.cpp @@ -55,6 +55,14 @@ void AAdventureCameraPawn::Tick(float DeltaTime) { Super::Tick(DeltaTime); + // quick fix for edgescrolling after viewport resizing. + // + //TickIncrement++; + //if (TickIncrement >= 60) { + // TickIncrement = 0; + // ViewSize = Viewport->Viewport->GetSizeXY(); + //} + if (IsValid(FollowPawn)) { if (FollowPawn->bIsMoving) { FollowAdvPawn(DeltaTime); } } } diff --git a/AdventureCameraPawn.h b/AdventureCameraPawn.h index 3ba6e59..3aec94f 100644 --- a/AdventureCameraPawn.h +++ b/AdventureCameraPawn.h @@ -19,6 +19,8 @@ public: UGameViewportClient* Viewport; UPROPERTY() FIntPoint ViewSize; + UPROPERTY() + int32 TickIncrement = 0; UPROPERTY(BlueprintReadWrite, Category = "Config") class AAdventureMap* AdvMapRef; diff --git a/AdventureMap.cpp b/AdventureMap.cpp index 3ac076a..0784c32 100644 --- a/AdventureMap.cpp +++ b/AdventureMap.cpp @@ -63,7 +63,7 @@ int32 AAdventureMap::GridIndex(int32 qAxial, int32 rAxial) * The Q axis is (i.e. columns are) oriented diagonally. * The Hex Grid has a rough square shape, hence the Q coordinates must be offset by -1 every other row. */ - int32 column = qAxial + FMath::FloorToInt(rAxial / 2); + int32 column = qAxial + FMath::FloorToInt(rAxial / 2.); return (rAxial * GridSize) + column; } @@ -142,7 +142,7 @@ TArray AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal, while (!ToExamine.IsEmpty()) { AHexTile* Candidate = ToExamine[0]; ToExamine.Remove(Candidate); - // try for Hex with lower estimatet (F)cost + // find Hex with lower estimatet F-cost for (AHexTile* t : ToExamine) { t->FCost = t->GCost + t->HCost; if (t->FCost < Candidate->FCost || t->FCost == Candidate->FCost && t->HCost < Candidate->HCost) { Candidate = t; } @@ -181,64 +181,88 @@ TArray AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal, Algo::Reverse(Path); if (bDiags) { - TArray PathS = ShortcutAStar(Path); + Path = ShortcutAStar(Path); } - return Path; } +// very bro-sciency approach to pathfinding for diagonal Hex-movement TArray AAdventureMap::ShortcutAStar(TArray Path) { TArray Shortcut; int32 Len = Path.Num(); TArray WorkingSegment; - AHexTile* Start = PCRef->CurrentHex; - WorkingSegment.Add(Start); - int32 i = 0; + AHexTile* CurrentHex = PCRef->CurrentHex; + WorkingSegment.Add(CurrentHex); + int32 h = 0; - FHexVector PrevDir = FHexVector(Path[0], Start); + // create segments for each bend + FHexVector PrevDir = FHexVector(Path[0], CurrentHex); + FHexVector DirASave = PrevDir; FHexVector DirA; int32 HexesBeforeBend = 1; - for (i; i < Len-1; i++) { - WorkingSegment.Add(Path[i]); - DirA = FHexVector(Path[i+1], Path[i]); - if (DirA != PrevDir) { break; } + for (h; h < Len-1; h++) { + WorkingSegment.Add(Path[h]); + DirA = FHexVector(Path[h+1], Path[h]); + if (DirA != PrevDir) { break; } // save Path[h] into Array of Bends HexesBeforeBend++; PrevDir = DirA; } PrevDir = DirA; FHexVector DirB; int32 HexesAfterBend = 0; - for (i; i < Len - 1; i++) { - WorkingSegment.Add(Path[i+1]); - DirB = FHexVector(Path[i+1], Path[i]); + for (h; h < Len - 1; h++) { + WorkingSegment.Add(Path[h+1]); + DirB = FHexVector(Path[h+1], Path[h]); if (DirB != PrevDir) { break; } HexesAfterBend++; PrevDir = DirB; } - if (HexesAfterBend == 0) { return Path; } - // debug - UE_LOG(LogTemp, Warning, TEXT("Before bend: %d"), HexesBeforeBend); - UE_LOG(LogTemp, Warning, TEXT("After bend: %d"), HexesAfterBend); - UE_LOG(LogTemp, Warning, TEXT("Working segment length: %d"), WorkingSegment.Num()); - for (AHexTile* HexDebug : WorkingSegment) { UE_LOG(LogTemp, Warning, TEXT("HexID: %d"), HexDebug->Index); } - - - FHexVector UnitDiag = UnitDiagFromUnitNB(DirA, DirB); + if (HexesAfterBend == 0) + { return Path; } + FHexVector UnitDiag = UnitDiagFromUnitNB(DirASave, DirB); AHexTile* Milestone = WorkingSegment.Last(); + int32 NumDiags = (HexesBeforeBend >= HexesAfterBend) ? HexesAfterBend : HexesBeforeBend; + int32 NumTries = (HexesBeforeBend >= HexesAfterBend) ? HexesBeforeBend : HexesAfterBend; - // Try adding diagonal Hexes to Shortcut from Start until Milestone (if BeforeBend>=AferBend: do this AfterBend times, else: BeforeBend) - // Set a bool to 'true' as soon as the first Hex is added; Set CurrentHex to that; - // if the path is blocked and the bool is 'false': Set CurrentHex to the next in WorkingSegment; Retry. - // if the path is blocked and the bool is 'true': Append the rest recursively calling A*(Shortcut.Last(), Path.Last(), true); - // when iterated AfterBend (or BeforeBend) times: Append the rest recursively calling A*(Shortcut.Last(), Path.Last(), true); + bool bDiagAdded = false; + for (int i = 0; i < NumTries; i++) { + if (NumDiags == 0) { + Shortcut.Append(FindPathAStar(CurrentHex, Milestone, false)); + break; + } + if (DiagIsReachable(CurrentHex, UnitDiag)) { + int32 CanIndex = GridIndex(CurrentHex->Q + UnitDiag.Q, CurrentHex->R + UnitDiag.R); + if (Grid.IsValidIndex(CanIndex)) { + AHexTile* Candidate = Grid[CanIndex]; + if (Candidate->bFree) { + Shortcut.Add(Candidate); + bDiagAdded = true; + CurrentHex = Candidate; + NumDiags--; + continue; + } } } + if (!bDiagAdded && !DiagIsReachable(CurrentHex, UnitDiag)) { + Shortcut.Add(CurrentHex); + CurrentHex = WorkingSegment[i + 1]; + NumDiags--; + continue; + } + if (bDiagAdded && !DiagIsReachable(CurrentHex, UnitDiag)) { + Shortcut.Append(FindPathAStar(CurrentHex, Milestone, true)); + break; + } + } + if (Milestone != Path.Last()) { Shortcut.Append(FindPathAStar(Milestone, Path.Last(), true)); } + + UE_LOG(LogTemp, Warning, TEXT("Hexes before bend: %d"), HexesBeforeBend); + UE_LOG(LogTemp, Warning, TEXT("Hexes after bend: %d"), HexesAfterBend); return Shortcut; } - FHexVector AAdventureMap::UnitDiagFromUnitNB(FHexVector InVecA, FHexVector InVecB) { if (InVecA == NNW && InVecB == NNE||InVecB == NNW && InVecA == NNE) { return N; } if (InVecA == NNE && InVecB == E ||InVecB == NNE && InVecA == E) { return ENE; } @@ -248,6 +272,7 @@ FHexVector AAdventureMap::UnitDiagFromUnitNB(FHexVector InVecA, FHexVector InVec if (InVecA == W && InVecB == NNW||InVecB == W && InVecA == NNW) { return WNW; } return FHexVector(); } + bool AAdventureMap::DiagIsReachable(AHexTile* InStart, FHexVector InDiagUnitVec) { FHexVector BlockA; FHexVector BlockB; @@ -257,7 +282,10 @@ bool AAdventureMap::DiagIsReachable(AHexTile* InStart, FHexVector InDiagUnitVec) if (InDiagUnitVec == S) { BlockA = SSE, BlockB = SSW; } if (InDiagUnitVec == WSW) { BlockA = SSW, BlockB = W; } if (InDiagUnitVec == WNW) { BlockA = W, BlockB = NNW; } - AHexTile* HexA = Grid[GridIndex(InStart->Q + BlockA.Q, InStart->R + BlockA.R)]; - AHexTile* HexB = Grid[GridIndex(InStart->Q + BlockB.Q, InStart->R + BlockB.R)]; + int32 IndexA = GridIndex(InStart->Q + BlockA.Q, InStart->R + BlockA.R); + int32 IndexB = GridIndex(InStart->Q + BlockB.Q, InStart->R + BlockB.R); + if (!Grid.IsValidIndex(IndexA) || !Grid.IsValidIndex(IndexB)) { return false; } + AHexTile* HexA = Grid[IndexA]; + AHexTile* HexB = Grid[IndexB]; return (HexA->bFree && HexB->bFree); } \ No newline at end of file diff --git a/AdventureMap.h b/AdventureMap.h index c42cf5c..a9eeb4e 100644 --- a/AdventureMap.h +++ b/AdventureMap.h @@ -26,7 +26,7 @@ public: UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") TSubclassOf BaseTileClass; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") - int32 GridSize = 100; + int32 GridSize = 60; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") int32 TileSize = 100; @@ -90,6 +90,7 @@ public: UFUNCTION(BlueprintCallable, Category = "Runtime") TArray ShortcutAStar(TArray Path); + // considering a MapObjectManager class or moving pathfinding & search to PlayerController UPROPERTY(BlueprintReadWrite, EditAnywhere) diff --git a/MapObject.h b/MapObject.h index 63b3b65..a1db784 100644 --- a/MapObject.h +++ b/MapObject.h @@ -26,9 +26,9 @@ public: USceneComponent* SceneComponent; UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Config") UStaticMeshComponent* OrientHexMesh; - UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Config") + UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Config") bool bCollectable; - UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Config") + UPROPERTY(BlueprintReadOnly, EditDefaultsOnly, Category = "Config") bool bActivatable; UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "Generation")