diff --git a/Config/DefaultEngine.ini b/Config/DefaultEngine.ini index d57fa16..a1f6f93 100644 --- a/Config/DefaultEngine.ini +++ b/Config/DefaultEngine.ini @@ -2,6 +2,7 @@ [/Script/EngineSettings.GameMapsSettings] GameDefaultMap=/Engine/Maps/Templates/OpenWorld +GlobalDefaultGameMode=/Script/Tactica.TacticaGameMode [/Script/Engine.RendererSettings] r.AllowStaticLighting=False diff --git a/Source/Tactica/Private/GridCell.cpp b/Source/Tactica/Private/GridCell.cpp index d43fcfc..2b21df9 100644 --- a/Source/Tactica/Private/GridCell.cpp +++ b/Source/Tactica/Private/GridCell.cpp @@ -1,6 +1,7 @@ #include "GridCell.h" #include "Components/StaticMeshComponent.h" #include "Engine/StaticMesh.h" +#include "Materials/MaterialInstanceDynamic.h" #include "UObject/ConstructorHelpers.h" AGridCell::AGridCell() @@ -23,4 +24,34 @@ AGridCell::AGridCell() MeshComponent->SetRelativeScale3D(FVector(0.95f, 0.95f, 0.1f)); // 板の上面がActorの原点の高さに来るよう、厚さの半分(5cm)下げる MeshComponent->SetRelativeLocation(FVector(0.0f, 0.0f, -5.0f)); + + // カーソルのレイキャスト(Visibilityチャンネル)に当たるようにする + MeshComponent->SetCollisionEnabled(ECollisionEnabled::QueryOnly); + MeshComponent->SetCollisionResponseToAllChannels(ECR_Ignore); + MeshComponent->SetCollisionResponseToChannel(ECC_Visibility, ECR_Block); + + // 標準マテリアルを割り当てる(色パラメータ"Color"を持つ) + static ConstructorHelpers::FObjectFinder BaseMaterial( + TEXT("/Engine/BasicShapes/BasicShapeMaterial.BasicShapeMaterial")); + if (BaseMaterial.Succeeded()) + { + MeshComponent->SetMaterial(0, BaseMaterial.Object); + } +} + +void AGridCell::BeginPlay() +{ + Super::BeginPlay(); + + DynamicMaterial = MeshComponent->CreateDynamicMaterialInstance(0); + SetHighlighted(false); +} + +void AGridCell::SetHighlighted(bool bHighlighted) +{ + if (DynamicMaterial) + { + DynamicMaterial->SetVectorParameterValue(TEXT("Color"), + bHighlighted ? HighlightColor : NormalColor); + } } \ No newline at end of file diff --git a/Source/Tactica/Private/TacticaCameraPawn.cpp b/Source/Tactica/Private/TacticaCameraPawn.cpp new file mode 100644 index 0000000..1f943c2 --- /dev/null +++ b/Source/Tactica/Private/TacticaCameraPawn.cpp @@ -0,0 +1,15 @@ +#include "TacticaCameraPawn.h" +#include "Camera/CameraComponent.h" + +ATacticaCameraPawn::ATacticaCameraPawn() +{ + PrimaryActorTick.bCanEverTick = false; + + Camera = CreateDefaultSubobject(TEXT("Camera")); + SetRootComponent(Camera); + + // 3x3グリッド(中心 (100,100))を斜め上から見下ろす位置。 + // 配置したPawnのActor位置を変えれば調整できる + Camera->SetRelativeLocation(FVector(-250.0f, 100.0f, 450.0f)); + Camera->SetRelativeRotation(FRotator(-60.0f, 0.0f, 0.0f)); +} diff --git a/Source/Tactica/Private/TacticaGameMode.cpp b/Source/Tactica/Private/TacticaGameMode.cpp new file mode 100644 index 0000000..2b86830 --- /dev/null +++ b/Source/Tactica/Private/TacticaGameMode.cpp @@ -0,0 +1,9 @@ +#include "TacticaGameMode.h" +#include "TacticaPlayerController.h" +#include "TacticaCameraPawn.h" + +ATacticaGameMode::ATacticaGameMode() +{ + DefaultPawnClass = ATacticaCameraPawn::StaticClass(); + PlayerControllerClass = ATacticaPlayerController::StaticClass(); +} diff --git a/Source/Tactica/Private/TacticaPlayerController.cpp b/Source/Tactica/Private/TacticaPlayerController.cpp new file mode 100644 index 0000000..748a731 --- /dev/null +++ b/Source/Tactica/Private/TacticaPlayerController.cpp @@ -0,0 +1,62 @@ +#include "TacticaPlayerController.h" +#include "GridCell.h" +#include "Components/InputComponent.h" +#include "InputCoreTypes.h" + +DEFINE_LOG_CATEGORY_STATIC(LogTacticaInput, Log, All); + +ATacticaPlayerController::ATacticaPlayerController() +{ + bShowMouseCursor = true; +} + +void ATacticaPlayerController::SetupInputComponent() +{ + Super::SetupInputComponent(); + + if (InputComponent) + { + InputComponent->BindKey(EKeys::LeftMouseButton, IE_Pressed, this, + &ATacticaPlayerController::OnClick); + } +} + +void ATacticaPlayerController::PlayerTick(float DeltaTime) +{ + Super::PlayerTick(DeltaTime); + + AGridCell* Cell = GetCellUnderCursor(); + if (Cell == HoveredCell) + { + return; + } + + if (HoveredCell) + { + HoveredCell->SetHighlighted(false); + } + HoveredCell = Cell; + if (HoveredCell) + { + HoveredCell->SetHighlighted(true); + } +} + +AGridCell* ATacticaPlayerController::GetCellUnderCursor() const +{ + FHitResult Hit; + if (GetHitResultUnderCursor(ECC_Visibility, false, Hit)) + { + return Cast(Hit.GetActor()); + } + return nullptr; +} + +void ATacticaPlayerController::OnClick() +{ + if (const AGridCell* Cell = GetCellUnderCursor()) + { + UE_LOG(LogTacticaInput, Log, TEXT("Cell clicked: (%d, %d)"), + Cell->GridCoord.X, Cell->GridCoord.Y); + } +} diff --git a/Source/Tactica/Public/GridCell.h b/Source/Tactica/Public/GridCell.h index 25af9e8..b3697ce 100644 --- a/Source/Tactica/Public/GridCell.h +++ b/Source/Tactica/Public/GridCell.h @@ -5,6 +5,7 @@ #include "GridCell.generated.h" class UStaticMeshComponent; +class UMaterialInstanceDynamic; UCLASS() class TACTICA_API AGridCell : public AActor @@ -29,4 +30,23 @@ public: // 歩行可能か UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Grid") bool bIsWalkable = true; + + // 通常時の色 + UPROPERTY(EditAnywhere, Category = "Grid|Highlight") + FLinearColor NormalColor = FLinearColor(0.15f, 0.15f, 0.15f); + + // ハイライト時の色 + UPROPERTY(EditAnywhere, Category = "Grid|Highlight") + FLinearColor HighlightColor = FLinearColor(1.0f, 0.8f, 0.1f); + + // ハイライトのON/OFF + void SetHighlighted(bool bHighlighted); + +protected: + virtual void BeginPlay() override; + +private: + // 色変更用のダイナミックマテリアル + UPROPERTY() + TObjectPtr DynamicMaterial; }; \ No newline at end of file diff --git a/Source/Tactica/Public/TacticaCameraPawn.h b/Source/Tactica/Public/TacticaCameraPawn.h new file mode 100644 index 0000000..79fb300 --- /dev/null +++ b/Source/Tactica/Public/TacticaCameraPawn.h @@ -0,0 +1,20 @@ +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/Pawn.h" +#include "TacticaCameraPawn.generated.h" + +class UCameraComponent; + +// 固定の俯瞰カメラ +UCLASS() +class TACTICA_API ATacticaCameraPawn : public APawn +{ + GENERATED_BODY() + +public: + ATacticaCameraPawn(); + + UPROPERTY(VisibleAnywhere, Category = "Camera") + TObjectPtr Camera; +}; diff --git a/Source/Tactica/Public/TacticaGameMode.h b/Source/Tactica/Public/TacticaGameMode.h new file mode 100644 index 0000000..ba7bbe7 --- /dev/null +++ b/Source/Tactica/Public/TacticaGameMode.h @@ -0,0 +1,14 @@ +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/GameModeBase.h" +#include "TacticaGameMode.generated.h" + +UCLASS() +class TACTICA_API ATacticaGameMode : public AGameModeBase +{ + GENERATED_BODY() + +public: + ATacticaGameMode(); +}; diff --git a/Source/Tactica/Public/TacticaPlayerController.h b/Source/Tactica/Public/TacticaPlayerController.h new file mode 100644 index 0000000..da68ee7 --- /dev/null +++ b/Source/Tactica/Public/TacticaPlayerController.h @@ -0,0 +1,30 @@ +#pragma once + +#include "CoreMinimal.h" +#include "GameFramework/PlayerController.h" +#include "TacticaPlayerController.generated.h" + +class AGridCell; + +UCLASS() +class TACTICA_API ATacticaPlayerController : public APlayerController +{ + GENERATED_BODY() + +public: + ATacticaPlayerController(); + +protected: + virtual void SetupInputComponent() override; + virtual void PlayerTick(float DeltaTime) override; + +private: + // カーソル下のマスを返す(なければnullptr) + AGridCell* GetCellUnderCursor() const; + + void OnClick(); + + // 現在ハイライト中のマス + UPROPERTY() + TObjectPtr HoveredCell; +};