Skip to content

Instantly share code, notes, and snippets.

@ThereExistsX
Last active September 4, 2016 21:23
Show Gist options
  • Save ThereExistsX/5415cc491fff5d9d8f92 to your computer and use it in GitHub Desktop.
Save ThereExistsX/5415cc491fff5d9d8f92 to your computer and use it in GitHub Desktop.
Usable Item
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#include "ItemSample.h"
#include "ItemSampleCharacter.h"
#include "ItemSampleProjectile.h"
#include "Animation/AnimInstance.h"
#include "UsableItem.h"
#include "GameFramework/InputSettings.h"
DEFINE_LOG_CATEGORY_STATIC(LogFPChar, Warning, All);
//////////////////////////////////////////////////////////////////////////
// AItemSampleCharacter
AItemSampleCharacter::AItemSampleCharacter()
{
// Set size for collision capsule
GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);
// set our turn rates for input
BaseTurnRate = 45.f;
BaseLookUpRate = 45.f;
// Create a CameraComponent
FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
FirstPersonCameraComponent->AttachParent = GetCapsuleComponent();
FirstPersonCameraComponent->RelativeLocation = FVector(0, 0, 64.f); // Position the camera
FirstPersonCameraComponent->bUsePawnControlRotation = true;
// Default offset from the character location for projectiles to spawn
GunOffset = FVector(100.0f, 30.0f, 10.0f);
// Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
Mesh1P = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CharacterMesh1P"));
Mesh1P->SetOnlyOwnerSee(true); // only the owning player will see this mesh
Mesh1P->AttachParent = FirstPersonCameraComponent;
Mesh1P->RelativeLocation = FVector(0.f, 0.f, -150.f);
Mesh1P->bCastDynamicShadow = false;
Mesh1P->CastShadow = false;
//Included in 4.7, needs to be added in 4.8
PrimaryActorTick.bCanEverTick = true;
// Note: The ProjectileClass and the skeletal mesh/anim blueprints for Mesh1P are set in the
// derived blueprint asset named MyCharacter (to avoid direct content references in C++)
}
// Called every frame -- Included in 4.7, needs to be added in 4.8
void AItemSampleCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
AUsableItem* itemSeen = GetItemFocus();
static AUsableItem* oldFocus = NULL;
oldFocus = ApplyPostProcessing(itemSeen, oldFocus);
}
//////////////////////////////////////////////////////////////////////////
// Input
void AItemSampleCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
{
// set up gameplay key bindings
check(InputComponent);
InputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
InputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);
InputComponent->BindAction("Take", IE_Pressed, this, &AItemSampleCharacter::Use);
//InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AItemSampleCharacter::TouchStarted);
if( EnableTouchscreenMovement(InputComponent) == false )
{
InputComponent->BindAction("Fire", IE_Pressed, this, &AItemSampleCharacter::OnFire);
}
InputComponent->BindAxis("MoveForward", this, &AItemSampleCharacter::MoveForward);
InputComponent->BindAxis("MoveRight", this, &AItemSampleCharacter::MoveRight);
// We have 2 versions of the rotation bindings to handle different kinds of devices differently
// "turn" handles devices that provide an absolute delta, such as a mouse.
// "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick
InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
InputComponent->BindAxis("TurnRate", this, &AItemSampleCharacter::TurnAtRate);
InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
InputComponent->BindAxis("LookUpRate", this, &AItemSampleCharacter::LookUpAtRate);
}
void AItemSampleCharacter::Use(){
if (GetItemFocus()){
GetItemFocus()->GetStaticMeshComponent()->DestroyComponent();
}
}
void AItemSampleCharacter::OnFire()
{
// try and fire a projectile
if (ProjectileClass != NULL)
{
const FRotator SpawnRotation = GetControlRotation();
// MuzzleOffset is in camera space, so transform it to world space before offsetting from the character location to find the final muzzle position
const FVector SpawnLocation = GetActorLocation() + SpawnRotation.RotateVector(GunOffset);
UWorld* const World = GetWorld();
if (World != NULL)
{
// spawn the projectile at the muzzle
World->SpawnActor<AItemSampleProjectile>(ProjectileClass, SpawnLocation, SpawnRotation);
}
}
// try and play the sound if specified
if (FireSound != NULL)
{
UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation());
}
// try and play a firing animation if specified
if(FireAnimation != NULL)
{
// Get the animation object for the arms mesh
UAnimInstance* AnimInstance = Mesh1P->GetAnimInstance();
if(AnimInstance != NULL)
{
AnimInstance->Montage_Play(FireAnimation, 1.f);
}
}
}
void AItemSampleCharacter::BeginTouch(const ETouchIndex::Type FingerIndex, const FVector Location)
{
if( TouchItem.bIsPressed == true )
{
return;
}
TouchItem.bIsPressed = true;
TouchItem.FingerIndex = FingerIndex;
TouchItem.Location = Location;
TouchItem.bMoved = false;
}
void AItemSampleCharacter::EndTouch(const ETouchIndex::Type FingerIndex, const FVector Location)
{
if (TouchItem.bIsPressed == false)
{
return;
}
if( ( FingerIndex == TouchItem.FingerIndex ) && (TouchItem.bMoved == false) )
{
OnFire();
}
TouchItem.bIsPressed = false;
}
void AItemSampleCharacter::TouchUpdate(const ETouchIndex::Type FingerIndex, const FVector Location)
{
if ((TouchItem.bIsPressed == true) && ( TouchItem.FingerIndex==FingerIndex))
{
if (TouchItem.bIsPressed)
{
if (GetWorld() != nullptr)
{
UGameViewportClient* ViewportClient = GetWorld()->GetGameViewport();
if (ViewportClient != nullptr)
{
FVector MoveDelta = Location - TouchItem.Location;
FVector2D ScreenSize;
ViewportClient->GetViewportSize(ScreenSize);
FVector2D ScaledDelta = FVector2D( MoveDelta.X, MoveDelta.Y) / ScreenSize;
if (ScaledDelta.X != 0.0f)
{
TouchItem.bMoved = true;
float Value = ScaledDelta.X * BaseTurnRate;
AddControllerYawInput(Value);
}
if (ScaledDelta.Y != 0.0f)
{
TouchItem.bMoved = true;
float Value = ScaledDelta.Y* BaseTurnRate;
AddControllerPitchInput(Value);
}
TouchItem.Location = Location;
}
TouchItem.Location = Location;
}
}
}
}
void AItemSampleCharacter::MoveForward(float Value)
{
if (Value != 0.0f)
{
// add movement in that direction
AddMovementInput(GetActorForwardVector(), Value);
}
}
void AItemSampleCharacter::MoveRight(float Value)
{
if (Value != 0.0f)
{
// add movement in that direction
AddMovementInput(GetActorRightVector(), Value);
}
}
void AItemSampleCharacter::TurnAtRate(float Rate)
{
// calculate delta for this frame from the rate information
AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds());
}
void AItemSampleCharacter::LookUpAtRate(float Rate)
{
// calculate delta for this frame from the rate information
AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds());
}
bool AItemSampleCharacter::EnableTouchscreenMovement(class UInputComponent* InputComponent)
{
bool bResult = false;
if(FPlatformMisc::GetUseVirtualJoysticks() || GetDefault<UInputSettings>()->bUseMouseForTouch )
{
bResult = true;
InputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AItemSampleCharacter::BeginTouch);
InputComponent->BindTouch(EInputEvent::IE_Released, this, &AItemSampleCharacter::EndTouch);
InputComponent->BindTouch(EInputEvent::IE_Repeat, this, &AItemSampleCharacter::TouchUpdate);
}
return bResult;
}
AUsableItem* AItemSampleCharacter::ApplyPostProcessing(AUsableItem* itemSeen, AUsableItem* oldFocus){
if (itemSeen){
// An item is currently being looked at
if (itemSeen == oldFocus || oldFocus == NULL){
//The item being looked at is the same as the one on the last tick
UStaticMeshComponent* mesh = itemSeen->GetStaticMeshComponent();
mesh->SetRenderCustomDepth(true);
}
else if (oldFocus != NULL){
// An item is being looked at and the old focus was not null (and not the same as the one on the last tick)
UStaticMeshComponent* mesh = itemSeen->GetStaticMeshComponent();
mesh->SetRenderCustomDepth(true);
UStaticMeshComponent* oldMesh = oldFocus->GetStaticMeshComponent();
oldMesh->SetRenderCustomDepth(false);
}
return oldFocus = itemSeen;
}
else{
// No item currectly being looked at
if (oldFocus != NULL){
//An item was looked at last tick but isn't being looked at anymore
UStaticMeshComponent* mesh = oldFocus->GetStaticMeshComponent();
mesh->SetRenderCustomDepth(false);
}
return oldFocus = NULL;
}
}
AUsableItem* AItemSampleCharacter::GetItemFocus(){
// Attempt to use Raycasts to view an object and echo it back
FVector CameraLocation;
FRotator CameraRotation;
Controller->GetPlayerViewPoint(CameraLocation, CameraRotation);
const FVector StartTrace = CameraLocation;
const FVector Direction = CameraRotation.Vector();
const FVector EndTrace = StartTrace + Direction * 300; //where 300 is the distance it checks
FCollisionQueryParams TraceParams(FName(TEXT("")), true, this);
TraceParams.bTraceAsyncScene = true;
TraceParams.bReturnPhysicalMaterial = true;
FHitResult Hit(ForceInit);
GetWorld()->LineTraceSingleByChannel(Hit, StartTrace, EndTrace, COLLISION_VIEW, TraceParams);
return Cast<AUsableItem>(Hit.GetActor());
}
// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "GameFramework/Character.h"
#include "ItemSampleCharacter.generated.h"
class UInputComponent;
UCLASS(config=Game)
class AItemSampleCharacter : public ACharacter
{
GENERATED_BODY()
/** Pawn mesh: 1st person view (arms; seen only by self) */
UPROPERTY(VisibleDefaultsOnly, Category=Mesh)
class USkeletalMeshComponent* Mesh1P;
/** First person camera */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
class UCameraComponent* FirstPersonCameraComponent;
public:
AItemSampleCharacter();
/** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
float BaseTurnRate;
/** Base look up/down rate, in deg/sec. Other scaling may affect final rate. */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
float BaseLookUpRate;
/** Gun muzzle's offset from the characters location */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Gameplay)
FVector GunOffset;
/** Projectile class to spawn */
UPROPERTY(EditDefaultsOnly, Category=Projectile)
TSubclassOf<class AItemSampleProjectile> ProjectileClass;
/** Sound to play each time we fire */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Gameplay)
class USoundBase* FireSound;
/** AnimMontage to play each time we fire */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay)
class UAnimMontage* FireAnimation;
protected:
/** Fires a projectile. */
void OnFire();
// New Class for ItemSampleProject
void Use();
/** Handles moving forward/backward */
void MoveForward(float Val);
/** Handles stafing movement, left and right */
void MoveRight(float Val);
/**
* Called via input to turn at a given rate.
* @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
*/
void TurnAtRate(float Rate);
/**
* Called via input to turn look up/down at a given rate.
* @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
*/
void LookUpAtRate(float Rate);
struct TouchData
{
TouchData() { bIsPressed = false;Location=FVector::ZeroVector;}
bool bIsPressed;
ETouchIndex::Type FingerIndex;
FVector Location;
bool bMoved;
};
void BeginTouch(const ETouchIndex::Type FingerIndex, const FVector Location);
void EndTouch(const ETouchIndex::Type FingerIndex, const FVector Location);
void TouchUpdate(const ETouchIndex::Type FingerIndex, const FVector Location);
TouchData TouchItem;
protected:
// APawn interface
virtual void SetupPlayerInputComponent(UInputComponent* InputComponent) override;
// End of APawn interface
/*
* Configures input for touchscreen devices if there is a valid touch interface for doing so
*
* @param InputComponent The input component pointer to bind controls to
* @returns true if touch controls were enabled.
*/
bool EnableTouchscreenMovement(UInputComponent* InputComponent);
public:
/** Returns Mesh1P subobject **/
FORCEINLINE class USkeletalMeshComponent* GetMesh1P() const { return Mesh1P; }
/** Returns FirstPersonCameraComponent subobject **/
FORCEINLINE class UCameraComponent* GetFirstPersonCameraComponent() const { return FirstPersonCameraComponent; }
// Called every frame
virtual void Tick(float DeltaSeconds) override;
// New classes for ItemSampleProject
class AUsableItem* GetItemFocus();
class AUsableItem* ApplyPostProcessing(AUsableItem* itemSeen, AUsableItem* oldFocus);
};
#include "lark.h"
#include "UsableItem.h"
// Sets default values
AUsableItem::AUsableItem(const class FObjectInitializer& PCIP) : Super(PCIP)
{
// 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;
SetMobility(EComponentMobility::Movable);
}
#pragma once
#include "GameFramework/Actor.h"
#include "UsableItem.generated.h"
UCLASS()
class AUsableItem : public AStaticMeshActor
{
GENERATED_BODY()
public:
AUsableItem(const class FObjectInitializer& PCIP);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment