Skip to content

Instantly share code, notes, and snippets.

@Tim-Machine
Created July 13, 2017 15:27
Show Gist options
  • Save Tim-Machine/5991192cedf47de73d7ad31a4ec527af to your computer and use it in GitHub Desktop.
Save Tim-Machine/5991192cedf47de73d7ad31a4ec527af to your computer and use it in GitHub Desktop.
// Fill out your copyright notice in the Description page of Project Settings.
#include "FPSCharacter.h"
#include "FPSProjectile.h"
#include "Engine.h"
#include "MyPlayerController.h"
#include "Components/CapsuleComponent.h"
// Sets default values
AFPSCharacter::AFPSCharacter()
{
// 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;
// Create a first person camera component.
FPSCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
// Attach the camera component to our capsule component.
FPSCameraComponent->SetupAttachment(GetCapsuleComponent());
// Position the camera slightly above the eyes.
FPSCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 50.0f + BaseEyeHeight));
// Allow the pawn to control camera rotation.
FPSCameraComponent->bUsePawnControlRotation = true;
// Create a first person mesh component for the owning player.
FPSMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("FirstPersonMesh"));
// Only the owning player sees this mesh.
FPSMesh->SetOnlyOwnerSee(true);
// Attach the FPS mesh to the FPS camera.
FPSMesh->SetupAttachment(FPSCameraComponent);
// Disable some environmental shadowing to preserve the illusion of having a single mesh.
FPSMesh->bCastDynamicShadow = false;
FPSMesh->CastShadow = false;
// The owning player doesn't see the regular (third-person) body mesh.
GetMesh()->SetOwnerNoSee(true);
}
// Called when the game starts or when spawned
void AFPSCharacter::BeginPlay()
{
Super::BeginPlay();
if (GEngine)
{
// Put up a debug message for five seconds. The -1 "Key" value (first argument) indicates that we will never need to update or refresh this message.
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter."));
}
// used for inventory && pickup system
LastItemSeen = nullptr;
// initialze our inventory
Inventory.SetNum(MAX_INVENTORY_ITEMS);
}
// Called every frame
void AFPSCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// raycast every frame.
Raycast();
}
// Called to bind functionality to input
void AFPSCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
// movement
PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward);
PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight);
// looking
PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::AddControllerYawInput);
PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::AddControllerPitchInput);
// jump action
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump);
PlayerInputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump);
PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AFPSCharacter::Fire);
// interaction button
PlayerInputComponent->BindAction("Interaction", IE_Pressed, this, &AFPSCharacter::PickupItem);
// inventory action
PlayerInputComponent->BindAction("Inventory",IE_Pressed, this, &AFPSCharacter::HandleInventoryInput);
}
void AFPSCharacter::MoveForward(float Value) {
// find out which way is "forward" and record that the player wants to move that way.
FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X);
AddMovementInput(Direction, Value);
}
void AFPSCharacter::MoveRight(float Value) {
FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y);
AddMovementInput(Direction, Value);
}
void AFPSCharacter::StartJump()
{
bPressedJump = true;
}
void AFPSCharacter::StopJump()
{
bPressedJump = false;
}
void AFPSCharacter::Fire()
{
if (ProjectileClass) {
FVector CameraLocation;
FRotator CameraRotation;
GetActorEyesViewPoint(CameraLocation, CameraRotation);
// transform muzzleoffset from camera space to world space
FVector MuzzleLocation = CameraLocation + FTransform(CameraRotation).TransformVector(MuzzleOffset);
FRotator MuzzleRotation = CameraRotation;
// skew aim to be slightly upwards
MuzzleRotation.Pitch += 10.0f;
UWorld* World = GetWorld();
if (World) {
FActorSpawnParameters SpawnParams;
SpawnParams.Owner = this;
SpawnParams.Instigator = Instigator;
// spawn the projectile at the muzzle
AFPSProjectile* Projectile = World->SpawnActor<AFPSProjectile>(ProjectileClass, MuzzleLocation, MuzzleRotation, SpawnParams);
if (Projectile) {
// set the projectil's init trajectory.
FVector LaunchDirection = MuzzleRotation.Vector();
Projectile->FireInDirection(LaunchDirection);
}
}
}
}
void AFPSCharacter::PickupItem()
{
if (LastItemSeen) {
// find the first avaible slot
int32 AvailableSlot = Inventory.Find(nullptr);
if (AvailableSlot != INDEX_NONE) {
// ADD item to the first valid slot
Inventory[AvailableSlot] = LastItemSeen;
FString ItemName = LastItemSeen->GetName();
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, ItemName);
// destory item from game;
LastItemSeen->Destroy();
}
else {
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("You can not carry anymore items"));
}
}
}
void AFPSCharacter::HandleInventoryInput()
{
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("inventory one"));
AMyPlayerController* Con = Cast<AMyPlayerController>(GetController());
if(Con) Con->HandleInventoryInput();
}
TArray<APickUpItem*> AFPSCharacter::GetInventory()
{
return Inventory;
}
void AFPSCharacter::Raycast()
{
//calculating start and end location
FVector StartLocation = FPSCameraComponent->GetComponentLocation();
FVector EndLocation = StartLocation + (FPSCameraComponent->GetForwardVector() * RaycastRange);
FHitResult RaycastHit;
// Raycast should ignore the character
FCollisionQueryParams CQP;
CQP.AddIgnoredActor(this);
GetWorld()->LineTraceSingleByChannel(RaycastHit, StartLocation, EndLocation, ECollisionChannel::ECC_WorldDynamic);
APickUpItem* Pickup = Cast<APickUpItem>(RaycastHit.GetActor());
if (LastItemSeen && LastItemSeen != Pickup){
// if our character sees a differnt pickup then disable the glowing affec on the previous seen item
LastItemSeen->SetGlowEffect(false);
}
if (Pickup) {
//Enable the glow effe on the current item
LastItemSeen = Pickup;
Pickup->SetGlowEffect(true);
}
else { // re-initialize
LastItemSeen = nullptr;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment