diff --git a/AdventureCameraPawn.cpp b/AdventureCameraPawn.cpp index 039ec6e..97f94db 100644 --- a/AdventureCameraPawn.cpp +++ b/AdventureCameraPawn.cpp @@ -18,10 +18,11 @@ AAdventureCameraPawn::AAdventureCameraPawn() // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; - ESASize = .01; BaseScrollSpeed = 20; ScrollAccelleration = BaseScrollSpeed * 3; + ESASize = .01; + ESAMaxBoundSlope = 1 / (1 - (1-ESASize)); ESAMaxBoundIntercept = 1 - ESAMaxBoundSlope; @@ -176,7 +177,6 @@ void AAdventureCameraPawn::EdgeScrollVert(float AxisValue) SpeedY = AxisValue * ScrollAccelleration; AddActorLocalOffset(FVector(0, -SpeedY, 0)); } - } } diff --git a/AdventureCharacter.cpp b/AdventureCharacter.cpp index 28192a0..ac47c3b 100644 --- a/AdventureCharacter.cpp +++ b/AdventureCharacter.cpp @@ -31,5 +31,4 @@ void AAdventureCharacter::Tick(float DeltaTime) void AAdventureCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); - } \ No newline at end of file diff --git a/AdventureMap.cpp b/AdventureMap.cpp index 23f28df..1b5c073 100644 --- a/AdventureMap.cpp +++ b/AdventureMap.cpp @@ -36,7 +36,6 @@ void AAdventureMap::MakeGrid() for (int r = 1; r <= GridSize; r++) { float XOffset = 0.f; - if (r % 2 != 0) { if (r > 1) { QOffset--; } } else { XOffset = HexWidth / 2; } @@ -45,23 +44,19 @@ void AAdventureMap::MakeGrid() NextHexAt.Y = TileSize * 1.5f * r; NextHexAt.Z = 0.f; FTransform SpawnTransform = FTransform(NextHexAt); - AHexTile* Tile = World->SpawnActor(BaseTileClass, SpawnTransform); Grid.Add(Tile); - Tile->Q = q - 1 + QOffset; Tile->R = r - 1; } } - for (auto& tile : Grid) { tile->Index = GridIndex(tile->Q, tile->R); } - bHexGridReady = true; } -// Every Hex Tile's index within the Grid Array can be derived from its Q and R coordinates +// Every Hex Tile's index within the Grid Array can be derived from its Axial Q and R coordinates int32 AAdventureMap::GridIndex(int32 qAxial, int32 rAxial) { /* @@ -78,50 +73,36 @@ AHexTile* AAdventureMap::RandomHex() return Grid[RandHex]; } -/* -* Add two TArray> members containing the Cardinal Directions - (one for immediate neighbors, one for diagonals) - { fill them in AAdventureMap::AAdventureMap } - -* This function instead returns - TMap -*/ TArray AAdventureMap::Neighbors(AHexTile* OfHex, bool bFreeOnly = false) { TArray Results; for (auto& V : NeighborUnitVectors) { int32 I = GridIndex(OfHex->Q + V.Q, OfHex->R + V.R); if (Grid.IsValidIndex(I)) { - AHexTile* R = Grid[I]; - Results.Add(Grid[I]); - if (bFreeOnly && !R->bFree) { Results.Remove(R); } + AHexTile* H = Grid[I]; + if (bFreeOnly && !H->bFree) { continue; } + if (H->Distance(OfHex) == 1) { Results.Add(H); } } } - for (auto& R : Results) { - if (bFreeOnly && !R->bFree) { Results.Remove(R); } - } return Results; } -TArray AAdventureMap::FreeDiags(AHexTile* OfHex) +TArray AAdventureMap::FreeDiagonals(AHexTile* OfHex) { TArray Results; for (auto& V : DiagonalUnitVectors) { int32 I = GridIndex(OfHex->Q + V.Q, OfHex->R + V.R); if (!Grid.IsValidIndex(I)) { continue; } - // if (!bFreeOnly) { if (Grid[I]->Distance(OfHex) == 1) { Results.Add(Grid[I]); } } else { bool bReachable = true; - for (auto& PotentialBlock : Neighbors(OfHex)) { + for (AHexTile* PotentialBlock : Neighbors(OfHex)) { if (PotentialBlock->Distance(Grid[I]) != 1) { continue; } if (!PotentialBlock->bFree) { bReachable = false; break; } } - if (bReachable) { - Results.Add(Grid[I]); - } + if (bReachable) { Results.Add(Grid[I]); } } } return Results; @@ -162,7 +143,7 @@ TArray AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal, AHexTile* Candidate = ToExamine[0]; ToExamine.Remove(Candidate); // try for Hex with lower estimatet (F)cost - for (auto& t : ToExamine) { + 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; } } @@ -174,6 +155,7 @@ TArray AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal, // expand frontier & adjust path data for (AHexTile* Neighbor : Neighbors(Candidate, true)) { if (Neighbor->Distance(Candidate) > 1) { continue; } + if (!Neighbor->bFree) { continue; } if (Processed.Contains(Neighbor)) { continue; } bool bInToExamine = ToExamine.Contains(Neighbor); @@ -186,27 +168,25 @@ TArray AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal, if (!bInToExamine) { Neighbor->HCost = Neighbor->Distance(Goal) * 10.f; ToExamine.Add(Neighbor); - } - } + } } } - if (bDiags) { // right now the heuristic for HCost (Distance func) does NOT take diagonals into account - for (AHexTile* Diag : FreeDiags(Candidate)) { + if (bDiags) { + for (AHexTile* Diag : FreeDiagonals(Candidate)) { if (Diag->Distance(Candidate) > 2) { continue; } if (!Diag->bFree) { continue; } if (Processed.Contains(Diag)) { continue; } bool bInToExamine = ToExamine.Contains(Diag); - float NewGCost = Candidate->GCost + Diag->MoveCost * 10.f; + float NewGCost = Candidate->GCost + 1 + Diag->MoveCost * 10.f; if (NewGCost < Diag->GCost || !bInToExamine) { Diag->GCost = NewGCost; Diag->CameFrom = Candidate; // chain if (!bInToExamine) { - Diag->HCost = Diag->Distance(Goal) * 10.f; + Diag->HCost = Diag->Distance(Goal) * 10.f; // not accounting for diagonals ToExamine.Add(Diag); - } - } + } } } } } diff --git a/AdventureMap.h b/AdventureMap.h index 2672d97..25ef2be 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; // squared is the number of Tiles + int32 GridSize = 100; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") int32 TileSize = 100; @@ -76,12 +76,14 @@ public: UFUNCTION(BlueprintCallable, Category = "Runtime") TArray Neighbors(AHexTile* OfHex, bool bFreeOnly); UFUNCTION(BlueprintCallable, Category = "Runtime") - TArray FreeDiags(AHexTile* OfHex); + TArray FreeDiagonals(AHexTile* OfHex); UFUNCTION(BlueprintCallable, Category = "Runtime") TSet BreadthFirstSearch(AHexTile* Start, int32 Radius); UFUNCTION(BlueprintCallable, Category = "Runtime") TArray FindPathAStar(AHexTile* Start, AHexTile* Goal, bool bDiags); +// considering a MapObjectManager class or moving pathfinding & search to PlayerController + UPROPERTY(BlueprintReadWrite, EditAnywhere) TMap MapObjects; UPROPERTY(BlueprintReadOnly) diff --git a/AdventurePlayerController.cpp b/AdventurePlayerController.cpp index ea74ded..fbc5ef2 100644 --- a/AdventurePlayerController.cpp +++ b/AdventurePlayerController.cpp @@ -60,31 +60,25 @@ TArray AAdventurePlayerController::Vision() void AAdventurePlayerController::TogglePlacing() { bInPlacementMode = !bInPlacementMode; - if (bInPlacementMode) { - PlaceObj = World->SpawnActor(PlaceObjClass, FTransform()); - } + if (bInPlacementMode) { PlaceObj = World->SpawnActor(PlaceObjClass, FTransform()); } else { if (IsValid(PlaceObj)) { PlaceObj->Destroy(); } } } void AAdventurePlayerController::FitOnGrid(AMapObject* MapObject) { if (!IsValid(HoveredHex)) { return; } - if (HoveredHex->bFree) { - MapObject->SetActorLocation(FVector(HoveredHex->GetActorLocation())); - } + if (HoveredHex->bFree) { MapObject->SetActorLocation(FVector(HoveredHex->GetActorLocation())); } } // called from BP; generally takes the Hex under the player cursor as argument void AAdventurePlayerController::PlaceObject(TSubclassOf MapObjClass, AHexTile* OnHex) { - // spawn this Actor at World location of Origin Hex; AMapObject* SpawnedObj = World->SpawnActor(MapObjClass, FTransform(OnHex->GetActorTransform().GetLocation())); SpawnedObj->Origin = OnHex; + OnHex->bFree = false; + SpawnedObj->Occupy(); - // set Hexes to bOccupied according to BlockVectors; - OnHex->bFree = false; // exact Hexes are eventually to be determined by MapObjectClass's BlockingVectors - - MapRef->MapObjects.Add(OnHex, SpawnedObj); // maybe this as well + MapRef->MapObjects.Add(OnHex, SpawnedObj); MapRef->IncID++; SpawnedObj->ID = MapRef->IncID; MapRef->MapObjectsByID.Add(MapRef->IncID, SpawnedObj); diff --git a/HexTile.cpp b/HexTile.cpp index a9b6f62..a057f64 100644 --- a/HexTile.cpp +++ b/HexTile.cpp @@ -10,40 +10,26 @@ AHexTile::AHexTile() { TileSize = 100.f; - RootComponent = CreateDefaultSubobject(TEXT("Scene")); - this->FillCornersArray(); } -void AHexTile::BeginPlay() -{ - Super::BeginPlay(); -} +void AHexTile::BeginPlay() { Super::BeginPlay(); } FVector AHexTile::Corner(int32 i) { FVector TileCenter = this->GetActorTransform().GetLocation(); - int32 Angle_Deg = 60 * i - 30; float Angle_Rad = UKismetMathLibrary::GetPI()/180 * Angle_Deg; float X = TileCenter.X + TileSize * cos(Angle_Rad); float Y = TileCenter.Y + TileSize * sin(Angle_Rad); - return FVector(X, Y, 0.f); } -void AHexTile::FillCornersArray() -{ - for (int32 i = 0 ; i < 6; i++) - { - Corners.Emplace(Corner(i + 1)); - } -} +void AHexTile::FillCornersArray() { for (int32 i = 0 ; i < 6; i++) { Corners.Emplace(Corner(i + 1)); } } int32 AHexTile::Distance(AHexTile* ToHex) { int32 CubeS1 = -this->Q - this->R; int32 CubeS2 = -ToHex->Q - ToHex->R; - return (abs(this->Q - ToHex->Q) + abs(this->R - ToHex->R) + abs(CubeS1 - CubeS2)) / 2; } \ No newline at end of file diff --git a/HexTile.h b/HexTile.h index 5bbce5f..951fdae 100644 --- a/HexTile.h +++ b/HexTile.h @@ -59,6 +59,10 @@ public: // MapObject Placement UPROPERTY(BlueprintReadWrite, VisibleAnywhere) bool bFree = true; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + bool bTouchable = false; + UPROPERTY(BlueprintReadWrite, EditAnywhere) + bool bSteptivatable = false; FORCEINLINE bool operator == (const AHexTile &Other) {