// 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(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(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(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()->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(Hit.GetActor()); }