Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement camera movement #69

Merged
merged 4 commits into from
Dec 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Config/DefaultInput.ini
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ DefaultViewportMouseCaptureMode=CapturePermanently_IncludingInitialMouseDown
bDefaultViewportMouseLock=False
DefaultViewportMouseLockMode=LockOnCapture
+ActionMappings=(ActionName="ClickTile",Key=LeftMouseButton,bShift=False,bCtrl=False,bAlt=False,bCmd=False)
+ActionMappings=(ActionName="CameraZoomIn",Key=MouseScrollUp,bShift=False,bCtrl=False,bAlt=False,bCmd=False)
+ActionMappings=(ActionName="CameraZoomOut",Key=MouseScrollDown,bShift=False,bCtrl=False,bAlt=False,bCmd=False)
+ActionMappings=(ActionName="CameraMoveModifier",Key=RightMouseButton,bShift=False,bCtrl=False,bAlt=False,bCmd=False)
+AxisMappings=(AxisName="CameraMoveHorizontal",Key=MouseX,Scale=1.000000)
+AxisMappings=(AxisName="CameraMoveVertical",Key=MouseY,Scale=1.000000)
bAlwaysShowTouchInterface=False
bShowConsoleOnFourFingerTap=True
DefaultTouchInterface=/Engine/MobileResources/HUD/DefaultVirtualJoysticks.DefaultVirtualJoysticks
Expand Down
Binary file not shown.
Binary file modified Content/EmptierThanVoid/Core/BP_GameMode_Board.uasset
Binary file not shown.
Binary file modified Content/EmptierThanVoid/Maps/Board.umap
Binary file not shown.
9 changes: 9 additions & 0 deletions Source/ETV/ETVAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ UETVAction::UETVAction()
CurrentPerform = 0;
}

UWorld* UETVAction::GetWorld() const
{
if (OwnerShip != nullptr)
{
return OwnerShip->GetWorld();
}
return nullptr;
}

void UETVAction::Init(AETVShip* OwnerShipPtr, AETVWeapon* OwnerWeaponPtr)
{
OwnerShip = OwnerShipPtr;
Expand Down
3 changes: 3 additions & 0 deletions Source/ETV/ETVAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ class ETV_API UETVAction : public UObject
int32 MaxPerforms;

public:
// Override path to world (through AActor) - UObject has no reference to the world it is in by itself (requires a path to it)
UWorld* GetWorld() const override;

UFUNCTION()
virtual void Init(AETVShip* OwnerShipPtr, AETVWeapon* OwnerWeaponPtr = nullptr);

Expand Down
125 changes: 125 additions & 0 deletions Source/ETV/ETVCameraDirector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Copyright (C) Team13. All rights reserved.

#include "ETVCameraDirector.h"
#include "ConstructorHelpers.h"
#include <algorithm>
#include "ETVGameModeBase.h"

// Sets default values
AETVCameraDirector::AETVCameraDirector()
{
bCanMove = false;
MoveSpeed = 5.0f;

ZoomStep = 25.0f;
ZoomMin = 100.0f;
ZoomMax = 500.0f;

// Create subobjects
SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComponent"));
SetRootComponent(SceneComponent);

/* Uncomment to enable visual representation (debug)
// Create and position a mesh component so we can see where our sphere is
VisualRepresentation = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
VisualRepresentation->SetupAttachment(RootComponent);
static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAsset(TEXT("/Engine/BasicShapes/Sphere.Sphere"));
if (SphereVisualAsset.Succeeded())
{
VisualRepresentation->SetStaticMesh(SphereVisualAsset.Object);
VisualRepresentation->SetWorldScale3D(FVector(0.2f));
}
*/

// Use a spring arm to give the camera smooth, natural-feeling motion
SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
SpringArm->SetupAttachment(RootComponent);
SpringArm->SetRelativeRotation(FRotator(-90.0f, 0.0f, -90.0f)); // Orient to tile map (pitch, yaw, roll vs editor's roll, pitch, yaw)
SpringArm->TargetArmLength = 300.0f;
SpringArm->bEnableCameraLag = true;

// Create a camera and attach to our spring arm
Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);
}

// Called to bind functionality to input
void AETVCameraDirector::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);

PlayerInputComponent->BindAction("CameraZoomIn", IE_Pressed, this, &AETVCameraDirector::OnZoomIn);
PlayerInputComponent->BindAction("CameraZoomOut", IE_Pressed, this, &AETVCameraDirector::OnZoomOut);
PlayerInputComponent->BindAction("CameraMoveModifier", IE_Pressed, this, &AETVCameraDirector::OnMoveModifier);
PlayerInputComponent->BindAction("CameraMoveModifier", IE_Released, this, &AETVCameraDirector::OnMoveModifier);
PlayerInputComponent->BindAxis("CameraMoveHorizontal", this, &AETVCameraDirector::OnMoveHorizontal);
PlayerInputComponent->BindAxis("CameraMoveVertical", this, &AETVCameraDirector::OnMoveVertical);
}

void AETVCameraDirector::OnZoomIn()
{
SpringArm->TargetArmLength = std::max(SpringArm->TargetArmLength - ZoomStep, ZoomMin);
}

void AETVCameraDirector::OnZoomOut()
{
SpringArm->TargetArmLength = std::min(SpringArm->TargetArmLength + ZoomStep, ZoomMax);
}

void AETVCameraDirector::OnMoveModifier()
{
bCanMove = !bCanMove;
}

void AETVCameraDirector::OnMoveHorizontal(float AxisValue)
{
if (bCanMove)
{
AETVGameModeBase* GameMode = Cast<AETVGameModeBase>(GetWorld()->GetAuthGameMode());

AxisValue *= -MoveSpeed;
FVector Location = GetActorLocation();
Location.X += AxisValue;
if (GameMode->IsPositionOnTileMap(Location)) {
AddActorLocalOffset(FVector(AxisValue, 0.0f, 0.0f));
}
}
}

void AETVCameraDirector::OnMoveVertical(float AxisValue)
{
if (bCanMove)
{
AETVGameModeBase* GameMode = Cast<AETVGameModeBase>(GetWorld()->GetAuthGameMode());

AxisValue *= MoveSpeed;
FVector Location = GetActorLocation();
Location.Y += AxisValue;
if (GameMode->IsPositionOnTileMap(Location)) {
AddActorLocalOffset(FVector(0.0f, AxisValue, 0.0f));
}
}
}

float AETVCameraDirector::GetZoom()
{
return SpringArm->TargetArmLength;
}

void AETVCameraDirector::MoveAboveTile(int32 X, int32 Y, float ZoomPercentage)
{
// Get world position from tile coordinates
AETVGameModeBase* GameMode = Cast<AETVGameModeBase>(GetWorld()->GetAuthGameMode());
FVector WorldTilePos = GameMode->GetPosition(X, Y);

// Set position
WorldTilePos.Z = GetActorLocation().Z; // Keep current height
SetActorLocation(WorldTilePos);

// Set zoom
if (ZoomPercentage >= 0.0f)
{
SpringArm->TargetArmLength = ZoomMax * ZoomPercentage;
}
}

92 changes: 92 additions & 0 deletions Source/ETV/ETVCameraDirector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright (C) Team13. All rights reserved.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "ETVCameraDirector.generated.h"

UCLASS()
class ETV_API AETVCameraDirector : public APawn
{
GENERATED_BODY()

public:
// Sets default values for this pawn's properties
AETVCameraDirector();

bool bCanMove;

protected:
// Scene component (Root Component)
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = "ETV Camera")
USceneComponent* SceneComponent;

// Spring Arm component
UPROPERTY(VisibleDefaultsOnly, BlueprintReadOnly, Category = "ETV Camera")
USpringArmComponent* SpringArm;

// Camera component
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "ETV Camera")
UCameraComponent* Camera;

// Visual Representation component
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "ETV Camera")
UStaticMeshComponent* VisualRepresentation;


UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ETV Camera")
float MoveSpeed;

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ETV Camera")
float ZoomStep;

// Minimal zoom
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ETV Camera")
float ZoomMin;

// Maximal zoom
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ETV Camera")
float ZoomMax;

public:
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

UFUNCTION()
void OnZoomIn();

UFUNCTION()
void OnZoomOut();

UFUNCTION()
void OnMoveModifier();

UFUNCTION()
void OnMoveHorizontal(float AxisValue);

UFUNCTION()
void OnMoveVertical(float AxisValue);

// Returns current zoom level (spring arm length, distance from RootComponent to Camera)
UFUNCTION(BlueprintCallable)
float GetZoom();

// Move camera above given tile with specified zoom (keep current by default)
UFUNCTION(BlueprintCallable, Category = "ETV Camera")
void MoveAboveTile(int32 X, int32 Y, float ZoomPercentage = -1.0f);

// Returns SceneComponent (RootComponent) subobject
FORCEINLINE USceneComponent* GetSceneComponent() const { return SceneComponent; }

// Returns SpringArm subobject
FORCEINLINE USpringArmComponent* GetSpringArm() const { return SpringArm; }

// Returns Camera subobject
FORCEINLINE UCameraComponent* GetCamera() const { return Camera; }

// Returns VisualRepresentation subobject
FORCEINLINE UStaticMeshComponent* GetVisualRepresentation() const { return VisualRepresentation; }
};
44 changes: 33 additions & 11 deletions Source/ETV/ETVGameModeBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
#include "ETVWeaponShieldBattery.h"
#include "ETVActionTarget_Fire.h"
#include "ETVActionTarget_Move.h"
#include "ETVCameraDirector.h"
#include "WidgetLayoutLibrary.h"
#include "UserWidget.h"
#include "ETVCalculator.h"
//#include "DrawDebugHelpers.h" // Uncomment for debug drawing

// Sets default values
AETVGameModeBase::AETVGameModeBase()
Expand Down Expand Up @@ -173,8 +175,7 @@ void AETVGameModeBase::Tick(float DeltaTime)
void AETVGameModeBase::MapGeneration()
{
// Vector for spawn location (takes into account height, width and tile size)
TileHeight = -450; // TODO Scale dynamically based on size
const FVector LocDim(-(MapHeight * TileSize / 2), -(MapWidth * TileSize / 2), TileHeight);
const FVector LocDim(-(MapHeight * TileSize / 2), -(MapWidth * TileSize / 2), 0);

// Actor spawn parameters
const FActorSpawnParameters SpawnInfo;
Expand Down Expand Up @@ -346,7 +347,8 @@ void AETVGameModeBase::GenerateShips()
void AETVGameModeBase::SpawnShip(int32 x, int32 y, UPaperTileSet* type)
{
// Vector for spawn location based on where TileSet is in TileMap
const FVector LocDim = GetPosition(x, y);
FVector LocDim = GetPosition(x, y);
LocDim.Z = 0.1f;

// Actor spawn parameters
const FActorSpawnParameters SpawnInfo;
Expand Down Expand Up @@ -515,7 +517,7 @@ AETVShip* AETVGameModeBase::GetShipActor(int32 x, int32 y)
return nullptr;
}

FVector AETVGameModeBase::GetPosition(int32 x, int32 y, int32 z)
FVector AETVGameModeBase::GetPosition(int32 x, int32 y, float z)
{
return FVector(-(TileSize / 2)*MapWidth + x * TileSize, -(TileSize / 2)*MapHeight + y * TileSize, z);
}
Expand Down Expand Up @@ -584,6 +586,14 @@ bool AETVGameModeBase::IsTargeting()
return bTargeting;
}

bool AETVGameModeBase::IsPositionOnTileMap(const FVector Location)
{
bool bInRangeX = UKismetMathLibrary::InRange_FloatFloat(Location.X, TileData[0].PointLeftTop.X, TileData.Last().PointRightBottom.X, false, false);
bool bInRangeY = UKismetMathLibrary::InRange_FloatFloat(Location.Y, TileData[0].PointLeftTop.Y, TileData.Last().PointRightBottom.Y, false, false);

return bInRangeX && bInRangeY;
}

void AETVGameModeBase::GetMouseOverTile(FETVTile& Tile)
{
APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
Expand All @@ -592,23 +602,35 @@ void AETVGameModeBase::GetMouseOverTile(FETVTile& Tile)
FVector WorldDirection;
if (PlayerController->DeprojectMousePositionToWorld(WorldLocation, WorldDirection))
{
AETVCameraDirector* Camera = Cast<AETVCameraDirector>(PlayerController->GetPawn());
if (Camera == nullptr)
{
UE_LOG(LogTemp, Error, TEXT("GetMouseOverTile(): Pawn not set to AETVCameraDirector!"))
return;
}

// Add height to tile map
WorldDirection *= abs(TileHeight / WorldDirection.Z + WorldLocation.Z);
WorldDirection *= abs((Camera->GetZoom() + 10.0f) / WorldDirection.Z); // Add 10.0f due to #68 (start is 20 UU higher, but for some reason half is taken)
WorldLocation += WorldDirection;

// Check if on tile at all
bool bInRangeX = UKismetMathLibrary::InRange_FloatFloat(WorldLocation.X, TileData[0].PointLeftTop.X, TileData.Last().PointRightBottom.X, false, false);
bool bInRangeY = UKismetMathLibrary::InRange_FloatFloat(WorldLocation.Y, TileData[0].PointLeftTop.Y, TileData.Last().PointRightBottom.Y, false, false);
if (bInRangeX && bInRangeY)
if (IsPositionOnTileMap(WorldLocation))
{
// Check each tile if in range
for (auto &CurrentTileData : TileData)
{
bInRangeX = UKismetMathLibrary::InRange_FloatFloat(WorldLocation.X, CurrentTileData.PointLeftTop.X, CurrentTileData.PointRightBottom.X, false, false);
bInRangeY = UKismetMathLibrary::InRange_FloatFloat(WorldLocation.Y, CurrentTileData.PointLeftTop.Y, CurrentTileData.PointRightBottom.Y, false, false);
bool bInRangeX = UKismetMathLibrary::InRange_FloatFloat(WorldLocation.X, CurrentTileData.PointLeftTop.X, CurrentTileData.PointRightBottom.X, false, false);
bool bInRangeY = UKismetMathLibrary::InRange_FloatFloat(WorldLocation.Y, CurrentTileData.PointLeftTop.Y, CurrentTileData.PointRightBottom.Y, false, false);
if (bInRangeX && bInRangeY)
{
//UE_LOG(LogTemp, Warning, TEXT("Loc (%s) -- Dir (%s)"), *WorldLocation.ToString(), *WorldDirection.ToString())
/* Uncomment to enable visual representation of targeting (debug), "DrawDebugHelpers.h" include required
DrawDebugPoint(GetWorld(), WorldLocation, 5.0f, FColor(255, 0, 255), false); // Current mouse position
FVector DebugPointTileCenter = FVector(CurrentTileData.PointLeftTop.X, CurrentTileData.PointLeftTop.Y, 0.0f) * 0.5f + FVector(CurrentTileData.PointRightBottom.X, CurrentTileData.PointRightBottom.Y, 0.0f) * 0.5f;
DrawDebugPoint(GetWorld(), DebugPointTileCenter, 5.0f, FColor(255, 0, 0), false);
DrawDebugLine(GetWorld(), WorldLocation, DebugPointTileCenter, FColor(255, 0, 0), false);
UE_LOG(LogTemp, Warning, TEXT("Loc (%s) -- Dir (%s) -- Zoom %g"), *WorldLocation.ToString(), *WorldDirection.ToString(), Camera->GetZoom())
*/

Tile.Set(CurrentTileData.Tile);
return;
}
Expand Down
8 changes: 6 additions & 2 deletions Source/ETV/ETVGameModeBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ class ETV_API AETVGameModeBase : public AGameModeBase
APaperTileMapActor* TileMapActor;
UPaperTileMapComponent* TileMapComp;
TArray<FETVTileData> TileData;
int32 TileHeight;

AETVShip* Ship;
AETVShipCapital* CapitalShip;
Expand All @@ -68,6 +67,7 @@ class ETV_API AETVGameModeBase : public AGameModeBase
UETVActionTarget* SelectedAction;

// Ship Tiles

UPaperTileSet* PlayerCapitalShip;
UPaperTileSet* PlayerFighterShip;
UPaperTileSet* EnemyCapitalShip;
Expand Down Expand Up @@ -194,7 +194,7 @@ class ETV_API AETVGameModeBase : public AGameModeBase

// Get Ships location from Tiles x and y
UFUNCTION()
FVector GetPosition(int32 x, int32 y, int32 z = -449);
FVector GetPosition(int32 x, int32 y, float z = 0.1f);


/* Game Loop */
Expand Down Expand Up @@ -224,6 +224,10 @@ class ETV_API AETVGameModeBase : public AGameModeBase
UFUNCTION(BlueprintCallable, Category = "ETV Targeting")
bool IsTargeting();

// Return if mouse is over the tile map
UFUNCTION(BlueprintCallable, Category = "ETV Targeting")
bool IsPositionOnTileMap(const FVector Location);

// Get tile position below mouse pointer
UFUNCTION(BlueprintCallable, Category = "ETV Targeting")
void GetMouseOverTile(/*out*/ FETVTile& Tile);
Expand Down