MovementArrow functionality; StarFog implemented; Refactoring

This commit is contained in:
Maximilian Fajnberg 2022-06-01 20:25:33 +02:00
parent 21f7dd4e67
commit aa02fb8093
10 changed files with 269 additions and 33 deletions

View File

@ -3,6 +3,7 @@
#include "AdventureMap.h" #include "AdventureMap.h"
#include "HexTile.h" #include "HexTile.h"
#include "StarFog.h"
#include "AdventurePlayerController.h" #include "AdventurePlayerController.h"
#include "Kismet/GameplayStatics.h" #include "Kismet/GameplayStatics.h"
#include "Algo/Reverse.h" #include "Algo/Reverse.h"
@ -10,8 +11,8 @@
// Sets default values // Sets default values
AAdventureMap::AAdventureMap() AAdventureMap::AAdventureMap()
{ {
FHexVector NBs[] = { NNE, E, SSE, SSW, W, NNW }; FHexVector NBs[] = { E, SSE, SSW, W, NNW, NNE };
NeighborUnitVectors.Append(NBs, UE_ARRAY_COUNT(NBs)); UnitVectors.Append(NBs, UE_ARRAY_COUNT(NBs));
FHexVector DNBs[] = { N, ENE, ESE, S, WSW, WNW }; FHexVector DNBs[] = { N, ENE, ESE, S, WSW, WNW };
DiagonalUnitVectors.Append(DNBs, UE_ARRAY_COUNT(DNBs)); DiagonalUnitVectors.Append(DNBs, UE_ARRAY_COUNT(DNBs));
} }
@ -25,6 +26,11 @@ void AAdventureMap::BeginPlay()
if (IsValid(BaseTileClass)) { if (IsValid(BaseTileClass)) {
MakeGrid(); MakeGrid();
} }
for (auto& Tile : Grid) {
AStarFog* Fog = World->SpawnActor<AStarFog>(BaseFogClass, Tile->GetActorTransform());
Fog->CoveredHex = Tile;
Tile->CoveringFog = Fog;
}
} }
// Called once on Begin Play // Called once on Begin Play
@ -69,6 +75,9 @@ int32 AAdventureMap::GridIndex(int32 qAxial, int32 rAxial)
AHexTile* AAdventureMap::RandomHex() AHexTile* AAdventureMap::RandomHex()
{ {
//debug
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("Picking A Random Hex"));
int32 RandHex = FMath::RandRange(0, GridSize*GridSize-1); int32 RandHex = FMath::RandRange(0, GridSize*GridSize-1);
return Grid[RandHex]; return Grid[RandHex];
} }
@ -76,7 +85,7 @@ AHexTile* AAdventureMap::RandomHex()
TArray<AHexTile*> AAdventureMap::Neighbors(AHexTile* OfHex, bool bFreeOnly = false) TArray<AHexTile*> AAdventureMap::Neighbors(AHexTile* OfHex, bool bFreeOnly = false)
{ {
TArray<AHexTile*> Results; TArray<AHexTile*> Results;
for (auto& V : NeighborUnitVectors) { for (auto& V : UnitVectors) {
int32 I = GridIndex(OfHex->Q + V.Q, OfHex->R + V.R); int32 I = GridIndex(OfHex->Q + V.Q, OfHex->R + V.R);
if (Grid.IsValidIndex(I)) { if (Grid.IsValidIndex(I)) {
AHexTile* H = Grid[I]; AHexTile* H = Grid[I];
@ -180,13 +189,14 @@ TArray<AHexTile*> AAdventureMap::FindPathAStar(AHexTile* Start, AHexTile* Goal,
} }
Algo::Reverse(Path); Algo::Reverse(Path);
if (bDiags) { if (bDiags) { // DO NOT USE
Path = ShortcutAStar(Path); Path = ShortcutAStar(Path);
} }
return Path; return Path;
} }
// very bro-sciency approach to pathfinding for diagonal Hex-movement // very bro-sciency approach to pathfinding for diagonal Hex-movement
// DO NOT USE
TArray<AHexTile*> AAdventureMap::ShortcutAStar(TArray<AHexTile*> Path) TArray<AHexTile*> AAdventureMap::ShortcutAStar(TArray<AHexTile*> Path)
{ {
TArray<AHexTile*> Shortcut; TArray<AHexTile*> Shortcut;

View File

@ -1,5 +1,3 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
@ -9,6 +7,7 @@
#include "AdventureMap.generated.h" #include "AdventureMap.generated.h"
class AHexTile; class AHexTile;
class AStarFog;
class AMapObject; class AMapObject;
class AAdventurePlayerController; class AAdventurePlayerController;
@ -25,6 +24,8 @@ public:
UWorld* World; UWorld* World;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config")
TSubclassOf<AHexTile> BaseTileClass; TSubclassOf<AHexTile> BaseTileClass;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config")
TSubclassOf<AStarFog> BaseFogClass;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config")
int32 GridSize = 60; int32 GridSize = 60;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config")
@ -71,7 +72,7 @@ public:
UPROPERTY(BlueprintReadOnly, VisibleAnywhere) UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
FHexVector NNW = FHexVector(0, -1); FHexVector NNW = FHexVector(0, -1);
UPROPERTY(BlueprintReadOnly, VisibleAnywhere) UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
TArray<FHexVector> NeighborUnitVectors; TArray<FHexVector> UnitVectors;
UPROPERTY(BlueprintReadOnly, VisibleAnywhere) UPROPERTY(BlueprintReadOnly, VisibleAnywhere)
TArray<FHexVector> DiagonalUnitVectors; TArray<FHexVector> DiagonalUnitVectors;
UFUNCTION(BlueprintCallable, Category = "Utility") UFUNCTION(BlueprintCallable, Category = "Utility")

View File

@ -7,6 +7,8 @@
#include "AdventureCameraPawn.h" #include "AdventureCameraPawn.h"
#include "AdventureCharacter.h" #include "AdventureCharacter.h"
#include "MapObject.h" #include "MapObject.h"
#include "MovementArrow.h"
AAdventurePlayerController::AAdventurePlayerController() AAdventurePlayerController::AAdventurePlayerController()
@ -19,7 +21,9 @@ void AAdventurePlayerController::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
World = GetWorld(); World = GetWorld();
HoveredHex = CurrentHex; HoveredHex = CurrentHex;
} }
// Called every frame // Called every frame
void AAdventurePlayerController::Tick(float DeltaTime) void AAdventurePlayerController::Tick(float DeltaTime)
@ -36,13 +40,19 @@ void AAdventurePlayerController::SetupInputComponent()
// This is initialized on startup, you can go straight to binding // This is initialized on startup, you can go straight to binding
InputComponent->BindAction("LeftClick", IE_Pressed, this, &AAdventurePlayerController::LeftClick); 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() void AAdventurePlayerController::LeftClick()
{ {
if (!IsValid(HoveredHex)) { return; } if (IsValid(HoveredHex)) {
if (bInPlacementMode) { PlaceObject(PlaceObjClass, HoveredHex); } if (!bInPlacementMode) {
}
else { PlaceObject(PlaceObjClass, HoveredHex); }
}
else { return; }
} }
TArray<AHexTile*> AAdventurePlayerController::Vision(int32 Radius) TArray<AHexTile*> AAdventurePlayerController::Vision(int32 Radius)
@ -59,11 +69,38 @@ TArray<AHexTile*> AAdventurePlayerController::Vision(int32 Radius)
return Results; return Results;
} }
void AAdventurePlayerController::TogglePlacing() void AAdventurePlayerController::MarkPath(TArray<AHexTile*> Path)
{ {
bInPlacementMode = !bInPlacementMode; FHexVector DirA = FHexVector(Path[0]->Q - CurrentHex->Q, Path[0]->R - CurrentHex->R);
if (bInPlacementMode) { PlaceObj = World->SpawnActor<AMapObject>(PlaceObjClass, FTransform()); } FHexVector DirB;
else { if (IsValid(PlaceObj)) { PlaceObj->Destroy(); } } 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<AMovementArrow>(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<AMapObject>(PlaceObjClass, FTransform());
}
void AAdventurePlayerController::DisablePlacing()
{
bInPlacementMode = false;
// if (IsValid(PlaceObj)) { PlaceObj->Destroy(); }
} }
void AAdventurePlayerController::FitOnGrid(AMapObject* MapObject) void AAdventurePlayerController::FitOnGrid(AMapObject* MapObject)

View File

@ -1,5 +1,3 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
@ -12,6 +10,8 @@ class AHexTile;
class AAdventureCameraPawn; class AAdventureCameraPawn;
class AAdventureCharacter; class AAdventureCharacter;
class AMapObject; class AMapObject;
class AMovementArrow;
/** /**
* *
*/ */
@ -32,19 +32,34 @@ public:
AAdventureCameraPawn* CamRef; AAdventureCameraPawn* CamRef;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite) UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
AHexTile* SpawnHex; AHexTile* SpawnHex;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Runtime") UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Runtime")
AHexTile* CurrentHex; AHexTile* CurrentHex;
UPROPERTY(BlueprintReadWrite, EditAnywhere) UPROPERTY(BlueprintReadWrite, EditAnywhere)
AHexTile* HoveredHex; AHexTile* HoveredHex;
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
void LeftClick(); void LeftClick();
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSet<AHexTile*> ExploredHexes; UPROPERTY(BlueprintReadOnly, EditDefaultsOnly)
TSubclassOf<AMovementArrow> MoveArrowClass;
UFUNCTION(BlueprintCallable)
void MarkPath(TArray<AHexTile*> Path);
UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
TArray<AMovementArrow*> PathArrows;
UFUNCTION(BlueprintCallable)
void ClearPath();
UPROPERTY(EditAnywhere, BlueprintReadWrite) UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 VisionRadius = 6; int32 VisionRadius = 6;
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
TArray<AHexTile*> Vision(int32 Radius); TArray<AHexTile*> Vision(int32 Radius);
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSet<AHexTile*> ExploredHexes;
protected: protected:
virtual void BeginPlay() override; virtual void BeginPlay() override;
@ -60,7 +75,9 @@ public:
UPROPERTY(BlueprintReadWrite, VisibleAnywhere) UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
AMapObject* PlaceObj; AMapObject* PlaceObj;
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
void TogglePlacing(); void EnablePlacing();
UFUNCTION(BlueprintCallable)
void DisablePlacing();
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
void FitOnGrid(AMapObject* MapObject); void FitOnGrid(AMapObject* MapObject);
UFUNCTION() UFUNCTION()

View File

@ -1,5 +1,3 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
@ -10,6 +8,7 @@
class USceneComponent; class USceneComponent;
class UStaticMeshComponent; class UStaticMeshComponent;
class AAdventureMap; class AAdventureMap;
class AStarFog;
class AAdventurePlayerController; class AAdventurePlayerController;
UCLASS() UCLASS()
@ -23,10 +22,13 @@ public:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config") UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Config")
float TileSize; float TileSize;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Config") //UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Config")
USceneComponent* SceneComponent; // USceneComponent* SceneComponent;
UPROPERTY(BlueprintReadWrite, Category = "Config") UPROPERTY(BlueprintReadWrite, Category = "Config")
AAdventureMap* MapRef; AAdventureMap* MapRef;
UPROPERTY(BlueprintReadWrite, Category = "Config")
AStarFog* CoveringFog;
UFUNCTION(BlueprintCallable, Category = "debug") UFUNCTION(BlueprintCallable, Category = "debug")
FVector Corner(int32 i); FVector Corner(int32 i);
@ -63,9 +65,9 @@ public:
// MapObject Placement // MapObject Placement
UPROPERTY(BlueprintReadWrite, VisibleAnywhere) UPROPERTY(BlueprintReadWrite, VisibleAnywhere)
bool bFree = true; bool bFree = true;
UPROPERTY(BlueprintReadWrite, EditAnywhere) UPROPERTY(BlueprintReadWrite, EditDefaultsOnly)
bool bTouchable = false; bool bTouchable = false;
UPROPERTY(BlueprintReadWrite, EditAnywhere) UPROPERTY(BlueprintReadWrite, EditDefaultsOnly)
bool bSteptivatable = false; bool bSteptivatable = false;
FORCEINLINE bool operator == (const AHexTile &Other) FORCEINLINE bool operator == (const AHexTile &Other)

View File

@ -14,23 +14,17 @@ struct FHexVector
FORCEINLINE explicit FHexVector(AHexTile* InHex); FORCEINLINE explicit FHexVector(AHexTile* InHex);
FORCEINLINE explicit FHexVector(AHexTile* InHexA, AHexTile* InHexB); FORCEINLINE explicit FHexVector(AHexTile* InHexA, AHexTile* InHexB);
UPROPERTY(BlueprintReadWrite) UPROPERTY(BlueprintReadWrite)
int32 Q; int32 Q;
UPROPERTY(BlueprintReadWrite) UPROPERTY(BlueprintReadWrite)
int32 R; int32 R;
UPROPERTY(BlueprintReadWrite) UPROPERTY(BlueprintReadWrite)
int32 S; int32 S;
UPROPERTY(BlueprintReadWrite) UPROPERTY(BlueprintReadWrite)
bool bIsDiagonal; bool bIsDiagonal;
UPROPERTY(BlueprintReadWrite) UPROPERTY(BlueprintReadWrite)
bool bUnit; bool bUnit;
TArray<FHexVector> Related;
}; };
FORCEINLINE FHexVector::FHexVector() FORCEINLINE FHexVector::FHexVector()
@ -44,15 +38,19 @@ FORCEINLINE FHexVector::FHexVector(AHexTile* InHex)
FORCEINLINE FHexVector::FHexVector(AHexTile* InHexA, AHexTile* InHexB) FORCEINLINE FHexVector::FHexVector(AHexTile* InHexA, AHexTile* InHexB)
: Q(InHexA->Q - InHexB->Q), R(InHexA->R - InHexB->R) {} : Q(InHexA->Q - InHexB->Q), R(InHexA->R - InHexB->R) {}
FORCEINLINE bool operator==(const FHexVector& A, const FHexVector& B) FORCEINLINE bool operator==(const FHexVector& A, const FHexVector& B)
{ {
if (A.Q == B.Q && A.R == B.R) { return true; } if (A.Q == B.Q && A.R == B.R) { return true; }
else { return false; } else { return false; }
} }
FORCEINLINE bool operator!=(const FHexVector& A, const FHexVector& B) FORCEINLINE bool operator!=(const FHexVector& A, const FHexVector& B)
{ {
if (A.Q == B.Q && A.R == B.R) { return false; } if (A.Q == B.Q && A.R == B.R) { return false; }
else { return true; } else { return true; }
}
FORCEINLINE uint32 GetTypeHash(const FHexVector& Thing)
{
uint32 Hash = FCrc::MemCrc32(&Thing, sizeof(FHexVector));
return Hash;
} }

65
MovementArrow.cpp Normal file
View File

@ -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<USceneComponent>(TEXT("Scene"));
RootComponent = SceneComponent;
MeshStraight = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Straight"));
MeshRight = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Right"));
MeshRightSharp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("RightSharp"));
MeshLeftSharp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("LeftSharp"));
MeshLeft = CreateDefaultSubobject<UStaticMeshComponent>(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);
}

48
MovementArrow.h Normal file
View File

@ -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<UStaticMeshComponent*> 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;
};

27
StarFog.cpp Normal file
View File

@ -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);
}

31
StarFog.h Normal file
View File

@ -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;
};