From aa02fb8093fc8d292149f7d809e7ed72876b5e6b Mon Sep 17 00:00:00 2001 From: Maximilian Fajnberg Date: Wed, 1 Jun 2022 20:25:33 +0200 Subject: [PATCH] MovementArrow functionality; StarFog implemented; Refactoring --- AdventureMap.cpp | 18 +++++++--- AdventureMap.h | 7 ++-- AdventurePlayerController.cpp | 51 +++++++++++++++++++++++---- AdventurePlayerController.h | 27 ++++++++++++--- HexTile.h | 14 ++++---- HexVector.h | 14 ++++---- MovementArrow.cpp | 65 +++++++++++++++++++++++++++++++++++ MovementArrow.h | 48 ++++++++++++++++++++++++++ StarFog.cpp | 27 +++++++++++++++ StarFog.h | 31 +++++++++++++++++ 10 files changed, 269 insertions(+), 33 deletions(-) create mode 100644 MovementArrow.cpp create mode 100644 MovementArrow.h create mode 100644 StarFog.cpp create mode 100644 StarFog.h diff --git a/AdventureMap.cpp b/AdventureMap.cpp index 0784c32..f59eead 100644 --- a/AdventureMap.cpp +++ b/AdventureMap.cpp @@ -3,6 +3,7 @@ #include "AdventureMap.h" #include "HexTile.h" +#include "StarFog.h" #include "AdventurePlayerController.h" #include "Kismet/GameplayStatics.h" #include "Algo/Reverse.h" @@ -10,8 +11,8 @@ // Sets default values AAdventureMap::AAdventureMap() { - FHexVector NBs[] = { NNE, E, SSE, SSW, W, NNW }; - NeighborUnitVectors.Append(NBs, UE_ARRAY_COUNT(NBs)); + FHexVector NBs[] = { E, SSE, SSW, W, NNW, NNE }; + UnitVectors.Append(NBs, UE_ARRAY_COUNT(NBs)); FHexVector DNBs[] = { N, ENE, ESE, S, WSW, WNW }; DiagonalUnitVectors.Append(DNBs, UE_ARRAY_COUNT(DNBs)); } @@ -25,6 +26,11 @@ void AAdventureMap::BeginPlay() if (IsValid(BaseTileClass)) { MakeGrid(); } + for (auto& Tile : Grid) { + AStarFog* Fog = World->SpawnActor(BaseFogClass, Tile->GetActorTransform()); + Fog->CoveredHex = Tile; + Tile->CoveringFog = Fog; + } } // Called once on Begin Play @@ -69,6 +75,9 @@ int32 AAdventureMap::GridIndex(int32 qAxial, int32 rAxial) AHexTile* AAdventureMap::RandomHex() { + //debug + GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("Picking A Random Hex")); + int32 RandHex = FMath::RandRange(0, GridSize*GridSize-1); return Grid[RandHex]; } @@ -76,7 +85,7 @@ AHexTile* AAdventureMap::RandomHex() TArray AAdventureMap::Neighbors(AHexTile* OfHex, bool bFreeOnly = false) { TArray Results; - for (auto& V : NeighborUnitVectors) { + for (auto& V : UnitVectors) { int32 I = GridIndex(OfHex->Q + V.Q, OfHex->R + V.R); if (Grid.IsValidIndex(I)) { AHexTile* H = Grid[I]; @@ -180,13 +189,14 @@ TArray AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal, } Algo::Reverse(Path); - if (bDiags) { + if (bDiags) { // DO NOT USE Path = ShortcutAStar(Path); } return Path; } // very bro-sciency approach to pathfinding for diagonal Hex-movement +// DO NOT USE TArray AAdventureMap::ShortcutAStar(TArray Path) { TArray Shortcut; diff --git a/AdventureMap.h b/AdventureMap.h index a9eeb4e..cb21f85 100644 --- a/AdventureMap.h +++ b/AdventureMap.h @@ -1,5 +1,3 @@ -// Fill out your copyright notice in the Description page of Project Settings. - #pragma once #include "CoreMinimal.h" @@ -9,6 +7,7 @@ #include "AdventureMap.generated.h" class AHexTile; +class AStarFog; class AMapObject; class AAdventurePlayerController; @@ -25,6 +24,8 @@ public: UWorld* World; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") TSubclassOf BaseTileClass; + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") + TSubclassOf BaseFogClass; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") int32 GridSize = 60; UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") @@ -71,7 +72,7 @@ public: UPROPERTY(BlueprintReadOnly, VisibleAnywhere) FHexVector NNW = FHexVector(0, -1); UPROPERTY(BlueprintReadOnly, VisibleAnywhere) - TArray NeighborUnitVectors; + TArray UnitVectors; UPROPERTY(BlueprintReadOnly, VisibleAnywhere) TArray DiagonalUnitVectors; UFUNCTION(BlueprintCallable, Category = "Utility") diff --git a/AdventurePlayerController.cpp b/AdventurePlayerController.cpp index f344265..338ed0c 100644 --- a/AdventurePlayerController.cpp +++ b/AdventurePlayerController.cpp @@ -7,6 +7,8 @@ #include "AdventureCameraPawn.h" #include "AdventureCharacter.h" #include "MapObject.h" +#include "MovementArrow.h" + AAdventurePlayerController::AAdventurePlayerController() @@ -19,7 +21,9 @@ void AAdventurePlayerController::BeginPlay() { Super::BeginPlay(); World = GetWorld(); + HoveredHex = CurrentHex; + } // Called every frame void AAdventurePlayerController::Tick(float DeltaTime) @@ -36,13 +40,19 @@ void AAdventurePlayerController::SetupInputComponent() // This is initialized on startup, you can go straight to binding InputComponent->BindAction("LeftClick", IE_Pressed, this, &AAdventurePlayerController::LeftClick); - InputComponent->BindAction("DebugAlt", IE_Pressed, this, &AAdventurePlayerController::TogglePlacing); // Change binding eventually + InputComponent->BindAction("DebugAlt", IE_Pressed, this, &AAdventurePlayerController::EnablePlacing); // Change binding eventually + InputComponent->BindAction("DebugAlt", IE_Released, this, &AAdventurePlayerController::DisablePlacing); // Change binding eventually } void AAdventurePlayerController::LeftClick() { - if (!IsValid(HoveredHex)) { return; } - if (bInPlacementMode) { PlaceObject(PlaceObjClass, HoveredHex); } + if (IsValid(HoveredHex)) { + if (!bInPlacementMode) { + + } + else { PlaceObject(PlaceObjClass, HoveredHex); } + } + else { return; } } TArray AAdventurePlayerController::Vision(int32 Radius) @@ -59,11 +69,38 @@ TArray AAdventurePlayerController::Vision(int32 Radius) return Results; } -void AAdventurePlayerController::TogglePlacing() +void AAdventurePlayerController::MarkPath(TArray Path) { - bInPlacementMode = !bInPlacementMode; - if (bInPlacementMode) { PlaceObj = World->SpawnActor(PlaceObjClass, FTransform()); } - else { if (IsValid(PlaceObj)) { PlaceObj->Destroy(); } } + FHexVector DirA = FHexVector(Path[0]->Q - CurrentHex->Q, Path[0]->R - CurrentHex->R); + FHexVector DirB; + for (int32 i = 0; i < Path.Num() - 1; i++) + { + DirB = FHexVector(Path[i + 1]->Q - Path[i]->Q, Path[i + 1]->R - Path[i]->R); + AMovementArrow* Arrow = World->SpawnActor(MoveArrowClass, Path[i]->GetActorTransform()); + Arrow->MapRef = MapRef; + Arrow->SetVariant(DirA, DirB); + PathArrows.Add(Arrow); + DirA = DirB; + } +} +void AAdventurePlayerController::ClearPath() +{ + for (AMovementArrow* Arrow : PathArrows) { + Arrow->Destroy(); + } + PathArrows.Empty(); +} + +void AAdventurePlayerController::EnablePlacing() +{ + bInPlacementMode = true; + PlaceObj = World->SpawnActor(PlaceObjClass, FTransform()); +} + +void AAdventurePlayerController::DisablePlacing() +{ + bInPlacementMode = false; + // if (IsValid(PlaceObj)) { PlaceObj->Destroy(); } } void AAdventurePlayerController::FitOnGrid(AMapObject* MapObject) diff --git a/AdventurePlayerController.h b/AdventurePlayerController.h index 05ad914..a1bb6b4 100644 --- a/AdventurePlayerController.h +++ b/AdventurePlayerController.h @@ -1,5 +1,3 @@ -// Fill out your copyright notice in the Description page of Project Settings. - #pragma once #include "CoreMinimal.h" @@ -12,6 +10,8 @@ class AHexTile; class AAdventureCameraPawn; class AAdventureCharacter; class AMapObject; +class AMovementArrow; + /** * */ @@ -32,19 +32,34 @@ public: AAdventureCameraPawn* CamRef; UPROPERTY(VisibleAnywhere, BlueprintReadWrite) AHexTile* SpawnHex; + + UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Runtime") AHexTile* CurrentHex; + + UPROPERTY(BlueprintReadWrite, EditAnywhere) AHexTile* HoveredHex; UFUNCTION(BlueprintCallable) void LeftClick(); - UPROPERTY(EditAnywhere, BlueprintReadWrite) - TSet ExploredHexes; + + UPROPERTY(BlueprintReadOnly, EditDefaultsOnly) + TSubclassOf MoveArrowClass; + UFUNCTION(BlueprintCallable) + void MarkPath(TArray Path); + UPROPERTY(BlueprintReadWrite, VisibleAnywhere) + TArray PathArrows; + UFUNCTION(BlueprintCallable) + void ClearPath(); + + UPROPERTY(EditAnywhere, BlueprintReadWrite) int32 VisionRadius = 6; UFUNCTION(BlueprintCallable) TArray Vision(int32 Radius); + UPROPERTY(EditAnywhere, BlueprintReadWrite) + TSet ExploredHexes; protected: virtual void BeginPlay() override; @@ -60,7 +75,9 @@ public: UPROPERTY(BlueprintReadWrite, VisibleAnywhere) AMapObject* PlaceObj; UFUNCTION(BlueprintCallable) - void TogglePlacing(); + void EnablePlacing(); + UFUNCTION(BlueprintCallable) + void DisablePlacing(); UFUNCTION(BlueprintCallable) void FitOnGrid(AMapObject* MapObject); UFUNCTION() diff --git a/HexTile.h b/HexTile.h index eb20bdf..de87a83 100644 --- a/HexTile.h +++ b/HexTile.h @@ -1,5 +1,3 @@ -// Fill out your copyright notice in the Description page of Project Settings. - #pragma once #include "CoreMinimal.h" @@ -10,6 +8,7 @@ class USceneComponent; class UStaticMeshComponent; class AAdventureMap; +class AStarFog; class AAdventurePlayerController; UCLASS() @@ -23,10 +22,13 @@ public: UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") float TileSize; - UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Config") - USceneComponent* SceneComponent; + //UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Config") + // USceneComponent* SceneComponent; UPROPERTY(BlueprintReadWrite, Category = "Config") AAdventureMap* MapRef; + UPROPERTY(BlueprintReadWrite, Category = "Config") + AStarFog* CoveringFog; + UFUNCTION(BlueprintCallable, Category = "debug") FVector Corner(int32 i); @@ -63,9 +65,9 @@ public: // MapObject Placement UPROPERTY(BlueprintReadWrite, VisibleAnywhere) bool bFree = true; - UPROPERTY(BlueprintReadWrite, EditAnywhere) + UPROPERTY(BlueprintReadWrite, EditDefaultsOnly) bool bTouchable = false; - UPROPERTY(BlueprintReadWrite, EditAnywhere) + UPROPERTY(BlueprintReadWrite, EditDefaultsOnly) bool bSteptivatable = false; FORCEINLINE bool operator == (const AHexTile &Other) diff --git a/HexVector.h b/HexVector.h index 5c2ff64..2ebba14 100644 --- a/HexVector.h +++ b/HexVector.h @@ -14,23 +14,17 @@ struct FHexVector FORCEINLINE explicit FHexVector(AHexTile* InHex); FORCEINLINE explicit FHexVector(AHexTile* InHexA, AHexTile* InHexB); - UPROPERTY(BlueprintReadWrite) int32 Q; - UPROPERTY(BlueprintReadWrite) int32 R; - UPROPERTY(BlueprintReadWrite) int32 S; UPROPERTY(BlueprintReadWrite) bool bIsDiagonal; - UPROPERTY(BlueprintReadWrite) bool bUnit; - - TArray Related; }; FORCEINLINE FHexVector::FHexVector() @@ -44,15 +38,19 @@ FORCEINLINE FHexVector::FHexVector(AHexTile* InHex) FORCEINLINE FHexVector::FHexVector(AHexTile* InHexA, AHexTile* InHexB) : Q(InHexA->Q - InHexB->Q), R(InHexA->R - InHexB->R) {} - FORCEINLINE bool operator==(const FHexVector& A, const FHexVector& B) { if (A.Q == B.Q && A.R == B.R) { return true; } else { return false; } } - FORCEINLINE bool operator!=(const FHexVector& A, const FHexVector& B) { if (A.Q == B.Q && A.R == B.R) { return false; } else { return true; } +} + +FORCEINLINE uint32 GetTypeHash(const FHexVector& Thing) +{ + uint32 Hash = FCrc::MemCrc32(&Thing, sizeof(FHexVector)); + return Hash; } \ No newline at end of file diff --git a/MovementArrow.cpp b/MovementArrow.cpp new file mode 100644 index 0000000..6199cd5 --- /dev/null +++ b/MovementArrow.cpp @@ -0,0 +1,65 @@ +#include "MovementArrow.h" +#include "AdventureMap.h" + +// Sets default values +AMovementArrow::AMovementArrow() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + SceneComponent = CreateDefaultSubobject(TEXT("Scene")); + RootComponent = SceneComponent; + MeshStraight = CreateDefaultSubobject(TEXT("Straight")); + MeshRight = CreateDefaultSubobject(TEXT("Right")); + MeshRightSharp = CreateDefaultSubobject(TEXT("RightSharp")); + MeshLeftSharp = CreateDefaultSubobject(TEXT("LeftSharp")); + MeshLeft = CreateDefaultSubobject(TEXT("Left")); + MeshVariants.Add(MeshStraight); + MeshVariants.Add(MeshRight); + MeshVariants.Add(MeshRightSharp); + MeshVariants.Add(MeshLeftSharp); + MeshVariants.Add(MeshLeft); + + for (UStaticMeshComponent* Mesh : MeshVariants) { + Mesh->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepWorldTransform); + Mesh->ToggleVisibility(); + } +} + + +void AMovementArrow::SetVariant(FHexVector InVec, FHexVector OutVec) { + + int32 InVecIndex = MapRef->UnitVectors.Find(InVec); + + SceneComponent->SetRelativeRotation(FRotator(0, InVecIndex * 60.f, 0)); + + int32 OutVecIndex = MapRef->UnitVectors.Find(OutVec); + + + int32 BackMotion = (InVecIndex + 3) % 6; + if (BackMotion < 0) { BackMotion = (((InVecIndex + 3) % 6) + 6) % 6; } // c++ modulus weirdness + + if (InVecIndex < BackMotion && OutVecIndex > BackMotion) { + OutVecIndex--; } + if (InVecIndex > BackMotion && OutVecIndex < BackMotion) { + InVecIndex--; } + + + int32 VariantIndex = (OutVecIndex - InVecIndex) % 5; + if (VariantIndex < 0) { VariantIndex = ((OutVecIndex - InVecIndex) % 5 + 5) % 5; } // c++ modulus weirdness + + MeshVariants[VariantIndex]->ToggleVisibility(); +} + +// Called when the game starts or when spawned +void AMovementArrow::BeginPlay() +{ + Super::BeginPlay(); + +} + +// Called every frame +void AMovementArrow::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} \ No newline at end of file diff --git a/MovementArrow.h b/MovementArrow.h new file mode 100644 index 0000000..87d514f --- /dev/null +++ b/MovementArrow.h @@ -0,0 +1,48 @@ +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "HexVector.h" +#include "MovementArrow.generated.h" + +class USceneComponent; +class UStaticMeshComponent; +class AAdventureMap; + +UCLASS() +class FRAY_API AMovementArrow : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + AMovementArrow(); + + UPROPERTY(BlueprintReadOnly, Category = "Config") + AAdventureMap* MapRef; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Config") + USceneComponent* SceneComponent; + + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Variant") + UStaticMeshComponent* MeshStraight; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Variant") + UStaticMeshComponent* MeshRight; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Variant") + UStaticMeshComponent* MeshRightSharp; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Variant") + UStaticMeshComponent* MeshLeftSharp; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Variant") + UStaticMeshComponent* MeshLeft; + UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Variant") + TArray MeshVariants; + UFUNCTION(BlueprintCallable, Category = "Variant") + void SetVariant(FHexVector InVec, FHexVector OutVec); + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; +}; diff --git a/StarFog.cpp b/StarFog.cpp new file mode 100644 index 0000000..cadb43a --- /dev/null +++ b/StarFog.cpp @@ -0,0 +1,27 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "StarFog.h" + +// Sets default values +AStarFog::AStarFog() +{ + // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + +} + +// Called when the game starts or when spawned +void AStarFog::BeginPlay() +{ + Super::BeginPlay(); + +} + +// Called every frame +void AStarFog::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); + +} + diff --git a/StarFog.h b/StarFog.h new file mode 100644 index 0000000..52a019b --- /dev/null +++ b/StarFog.h @@ -0,0 +1,31 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Actor.h" +#include "StarFog.generated.h" + +class AHexTile; + +UCLASS() +class FRAY_API AStarFog : public AActor +{ + GENERATED_BODY() + +public: + // Sets default values for this actor's properties + AStarFog(); + + UPROPERTY(BlueprintReadOnly, VisibleAnywhere) + AHexTile* CoveredHex; + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + +};