Skip to content

Instantly share code, notes, and snippets.

Created November 26, 2016 18:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/b8678bd8edcafe863ae22fba0a8eabef to your computer and use it in GitHub Desktop.
Save anonymous/b8678bd8edcafe863ae22fba0a8eabef to your computer and use it in GitHub Desktop.
//==============================================================================//
//
// Purpose: Player object
//
//=============================================================================//
#include "Portfolio.h"
#include "PortChar.h"
// Sets default values
APortChar::APortChar()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
//initiate everything to false
isMovingForwardOrBack = false;
isMovingLeftOrRight = false;
isMovingForward = false;
World = GetWorld();//set up world variable
bCanStep = true; //initialize the variable so the timer can start. Timer never runs if this is false or NULL
WalkSpeed = 300;
CrouchSpeed = 150;
SprintSpeed = 600; //default sprint speed
GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
GetCapsuleComponent()->InitCapsuleSize(40.0f, 85.0f);
GetCharacterMovement()->NavAgentProps.bCanCrouch = true;
DecBEH = BaseEyeHeight;
DecCapsHeight = GetCapsuleComponent()->GetUnscaledCapsuleHalfHeight();
}
// Called when the game starts or when spawned
void APortChar::BeginPlay()
{
Super::BeginPlay();
stepRate = WalkRate;
//assign PlayerCamera for shake to player 0
PlayerCamera = UGameplayStatics::GetPlayerCameraManager(this, 0);
}
//-----------------------------------------------------------------------------
// Purpose: Detects whether the player is moving, runs the footsteps timer and sets up changing ground types
//-----------------------------------------------------------------------------
void APortChar::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (Controller)
{
CrouchImpl(DeltaTime);
}
if (isMovingForwardOrBack == true || isMovingLeftOrRight == true)
{
isMoving = true;
}
else if (isMovingForwardOrBack == false && isMovingLeftOrRight == false)
{
isMoving = false;
}
PlayFootsteps();
//ground type for footsteps sound
FHitResult RV_DownHit; //the hit that detects what the player is standing on
//the hit that detects what the player is looking at
/////////////////////////////////////////////////////
////Downward Hit
////////////////////////////////////////////////////
RV_TraceParams = FCollisionQueryParams(FName(TEXT("RV_Trace")), true, this); //set up trace params for the line tracing
RV_TraceParams.bReturnPhysicalMaterial = true; //makes it so we can detect what physical material the hit has
RV_TraceParams.bTraceComplex = true;
RV_TraceParams.bTraceAsyncScene = true;
//sets up the line trace. Extends a line from the root component down 95 units, just a little below the bottom of the capsule.
GetWorld()->LineTraceSingleByChannel(RV_DownHit, GetActorLocation(), GetActorLocation() + GetActorUpVector() * -95, ECC_Pawn, RV_TraceParams);
if (RV_DownHit.PhysMaterial == StoneMat)//if the material the player is standing on is stone
{
StepType = 0; //set the steptype to stone
}
else if (RV_DownHit.PhysMaterial == SnowMat) //if the material is snow
{
StepType = 1; //set the steptype to snow
}
else if (RV_DownHit.PhysMaterial == GrassMat)
{
StepType = 2; //set the steptype to grass
}
else if (RV_DownHit.PhysMaterial == TileMat)
{
StepType = 3; //set the steptype to tile
}
/////////////////////////////////////////////////////
////Forward Hit
////////////////////////////////////////////////////
RV_ForwardParams = FCollisionQueryParams(FName(TEXT("RV_ForwardTrace")), true, this); //sets up the parameters for forward trace
RV_TraceParams.bReturnPhysicalMaterial = true;
RV_TraceParams.bTraceComplex = true;
RV_TraceParams.bTraceAsyncScene = true;
//sets up the line trace. Extends line from the root component forward 95 units
GetWorld()->LineTraceSingleByChannel(RV_ForwardHit, GetActorLocation(), GetActorLocation() + GetActorForwardVector() * 125, ECC_Pawn, RV_ForwardParams);
}
// Called to bind functionality to input
void APortChar::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
Super::SetupPlayerInputComponent(InputComponent);
//set up movement bindings
InputComponent->BindAxis("MoveForward", this, &APortChar::MoveForward);
InputComponent->BindAxis("MoveRight", this, &APortChar::MoveRight);
//setup look bindings
InputComponent->BindAxis("Turn", this, &APortChar::AddControllerYawInput);
InputComponent->BindAxis("LookUp", this, &APortChar::AddControllerPitchInput);
//jump
InputComponent->BindAction("Jump", IE_Pressed, this, &APortChar::OnStartJump);
InputComponent->BindAction("Jump", IE_Released, this, &APortChar::OnStopJump);
//sprint
InputComponent->BindAction("Sprint", IE_Pressed, this, &APortChar::StartSprint);
InputComponent->BindAction("Sprint", IE_Released, this, &APortChar::StopSprint);
//E Interact button
InputComponent->BindAction("EInteract", IE_Pressed, this, &APortChar::Interaction);
///Crouch
InputComponent->BindAction("Crouch", IE_Pressed, this, &APortChar::StartCrouch);
InputComponent->BindAction("Crouch", IE_Released, this, &APortChar::StopCrouch);
}
//-----------------------------------------------------------------------------
// Purpose: Moves the player forward at speeds depending on whether they are sprinting
//-----------------------------------------------------------------------------
void APortChar::MoveForward(float Value)
{
//add movement forward or backward
FRotator Rotation = Controller->GetControlRotation(); //gets the player rotation
Rotation.Pitch = 0.0f;
const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X); //gets the forward direction +x
AddMovementInput(Direction, Value); //adds the movement scaled by the value parameter
//sprint
if (bIsCrouching)
{
PlayerCamera->StopAllInstancesOfCameraShake(SprintCameraShake, true); //stop sprint camera shake
}
if (Value == 1 && GetCharacterMovement()->IsMovingOnGround() == true) //is W being pressed and is the character on the ground?
{
isMovingForwardOrBack = true; //then the player is moving forward. this is used to detect any movement
isMovingForward = true; //looks weird but this is used to detect only forward movement
if (isRunning == true)//if the player wants to sprint. set to true by StartSprint() if the shift button is being held
{
if (!bIsCrouching)
{
GetCharacterMovement()->MaxWalkSpeed = SprintSpeed; //sprint
PlayerCamera->PlayCameraShake(SprintCameraShake, 0.8f);//play sprint camera shake
stepRate = SprintRate; //fix footsteps to sprint rate
}
}
else //when shift is not being held
{
if (!bIsCrouching)
{
GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
PlayerCamera->StopAllInstancesOfCameraShake(SprintCameraShake, true); //stop sprint camera shake
stepRate = WalkRate;//fix footsteps to sprint rate
PlayerCamera->PlayCameraShake(CameraShakeX, 0.23f); //begin playing walking camera shake
}
}
}
else
isMovingForward = false; //the plays is not moving forward. Could be moving other directions
if (Value == -1 && GetCharacterMovement()->IsMovingOnGround() == true) //is the player on the ground and pressing S?
{
PlayerCamera->PlayCameraShake(CameraShakeX, 0.23f); //walk camera shake
isMovingForwardOrBack = true; //he's moving back
stepRate = WalkRate; //fix foot sounds to walk rate
}
if (Value == 0.0f || GetCharacterMovement()->IsMovingOnGround() == false) //if the player is in the air or not moving
{
PlayerCamera->StopAllInstancesOfCameraShake(CameraShakeX, true); //stop walk shake
PlayerCamera->StopAllInstancesOfCameraShake(SprintCameraShake, true); //stop sprint shake
isMovingForwardOrBack = false; //he aint moving, jim
stepRate = WalkRate; //set foot interval to walk rate
}
}
//-----------------------------------------------------------------------------
// Purpose: Moves the player left or right at a constant speed
//-----------------------------------------------------------------------------
void APortChar::MoveRight(float Value)
{
//find out which way is "right" and move that way
FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y); //finds right vector
AddMovementInput(Direction, Value); //moves in that direction scaled by Value. So he moves left is value > 0
if (Value == 1 || Value == -1) //if the player is pressing a or d
{
if (GetCharacterMovement()->IsMovingOnGround() == true) //and if he's on the ground
{
PlayerCamera->PlayCameraShake(CameraShakeY, 0.23f); //play walk shake
isMovingLeftOrRight = true; //he's moving left or right
}
}
if (Value == 0.0f || GetCharacterMovement()->IsMovingOnGround() == false) //if he's still or in the air
{
PlayerCamera->StopAllInstancesOfCameraShake(CameraShakeY, true); //stop the shakes, brah. it's cold
isMovingLeftOrRight = false; //he aint moving, Jimbo
}
}
//-----------------------------------------------------------------------------
// Purpose: Starts sprinting
//-----------------------------------------------------------------------------
void APortChar::StartSprint()
{
if (isMovingForward == true) //now we see why I have a different variable for forward movement.
{
isRunning = true; //sets isrunning to true only if the player is pressing W
}
if (!bIsCrouching)
{
GetCharacterMovement()->MaxWalkSpeed = SprintSpeed;
}
}
//-----------------------------------------------------------------------------
// Purpose: ends the sprinting
//-----------------------------------------------------------------------------
void APortChar::StopSprint()
{
isRunning = false;
}
//-----------------------------------------------------------------------------
// Purpose: function sets up the timer that plays the footsteps depending on whether the timer is expired
// and whether the player is moving
//-----------------------------------------------------------------------------
void APortChar::PlayFootsteps()
{
//if the timer is not expired
if (bCanStep == true)
{ //is the player moving
if (isMoving == true)
{
//if the foosteps sound is not initialized
if (StepSoundGrass != nullptr && StepSoundSnow != nullptr && StepSoundStone != nullptr)
{
PlaySound();
}
bCanStep = false; //turn the timer off
World->GetTimerManager().SetTimer(TimerHandle_StepRate, this, &APortChar::StepTimerExpired, stepRate);//setup timer and run function at an interval
}
}
}
//-----------------------------------------------------------------------------
// Purpose: play step
//-----------------------------------------------------------------------------
void APortChar::PlaySound()
{
if (StepType == 0) //if steptype == 0. They're walking on stone or gravel
{
UGameplayStatics::PlaySoundAttached(StepSoundStone, GetRootComponent());
}
if (StepType == 1) //if it's 1. They're walking on snow
{
UGameplayStatics::PlaySoundAttached(StepSoundSnow, GetRootComponent());
}
if (StepType == 2)// if it's 2, they're walking on grass
{
UGameplayStatics::PlaySoundAttached(StepSoundGrass, GetRootComponent());
}
if (StepType == 3) //if its 3, they're walking on grass
{
UGameplayStatics::PlaySoundAttached(StepSoundTile, GetRootComponent());
}
}
//-----------------------------------------------------------------------------
// Purpose: resets timer.
//-----------------------------------------------------------------------------
void APortChar::StepTimerExpired()
{
bCanStep = true;
}
//-----------------------------------------------------------------------------
//Purpose: Plays sound DEPRECATED: Used for snow demo. Not a part of controller
//----------------------------------------------------------------------------
/*
void APortChar::PlayPiano()
{
if (PianoSound != nullptr)
{
UGameplayStatics::PlaySoundAtLocation(this, PianoSound, GetActorLocation());
}
}
*/
//-----------------------------------------------------------------------------
//Purpose: start jump
//----------------------------------------------------------------------------
void APortChar::OnStartJump()
{
if (GetCharacterMovement()->IsMovingOnGround()) //is player on the ground?
{
bPressedJump = true; // jump
if (StepType == 0) //if steptype == 0. They're walking on stone or gravel
{
UGameplayStatics::PlaySoundAttached(JumpSoundStone, GetRootComponent());
}
if (StepType == 1)
{
UGameplayStatics::PlaySoundAttached(JumpSoundSnow, GetRootComponent());
}
if (StepType == 2)
{
UGameplayStatics::PlaySoundAttached(StepSoundGrass, GetRootComponent());
}
if (StepType == 3)
{
UGameplayStatics::PlaySoundAttached(JumpSoundTile, GetRootComponent());
}
}
}
//-----------------------------------------------------------------------------
//Purpose: stop jump
//----------------------------------------------------------------------------
void APortChar::OnStopJump()
{
bPressedJump = false;
}
//-----------------------------------------------------------------------------
//Purpose: when the player lands
//----------------------------------------------------------------------------
void APortChar::Landed(const FHitResult &Hit)
{
if (StepType == 0) //if steptype == 0. They're walking on stone or gravel
{
UGameplayStatics::PlaySoundAtLocation(this, JumpSoundStone, GetActorLocation());
}
if (StepType == 1)
{
UGameplayStatics::PlaySoundAtLocation(this, JumpSoundSnow, GetActorLocation());
}
if (StepType == 2)
{
UGameplayStatics::PlaySoundAtLocation(this, StepSoundGrass, GetActorLocation());
}
if (StepType == 3)
{
UGameplayStatics::PlaySoundAtLocation(this, JumpSoundTile, GetActorLocation());
}
}
//-----------------------------------------------------------------------------
//Purpose: when the player wants to interact with something
//----------------------------------------------------------------------------
void APortChar::Interaction()
{
if (ActorToInteractWith != nullptr)
{
ActorToInteractWith->Output();
}
}
//-----------------------------------------------------------------------------
//Purpose: Starts crouch
//----------------------------------------------------------------------------
void APortChar::StartCrouch()
{
bIsCrouching = true;
GetCharacterMovement()->MaxWalkSpeed = CrouchSpeed;
stepRate = CrouchRate;
}
void APortChar::StopCrouch()
{
bIsCrouching = false;
GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
stepRate = WalkRate;
}
void APortChar::CrouchImpl(float DeltaTime)
{
const float TargetBEH = bIsCrouching ? CrouchedEyeHeight : DecBEH;
const float TargetCapsuleSize = bIsCrouching ? GetCharacterMovement()->CrouchedHalfHeight : DecCapsHeight;
BaseEyeHeight = FMath::FInterpTo(BaseEyeHeight, TargetBEH, DeltaTime, 10.0f);
GetCapsuleComponent()->SetCapsuleHalfHeight(FMath::FInterpTo(GetCapsuleComponent()->GetUnscaledCapsuleHalfHeight(), TargetCapsuleSize, DeltaTime, 10.0f), true);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment