c语言跑酷小游戏代码,跑酷游戏代码

引擎:UE4 4.18.3

代码结构

8022e9e73786330c98e206c2bc0c1cdb.png

运行图

8c9729f20f9aa836c20a634d93009465.png

PikaqiuThirdTestGameMode.h// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"

#include "GameFramework/GameModeBase.h"

#include "PikaqiuThirdTestGameMode.generated.h"

UCLASS(minimalapi)

class APikaqiuThirdTestGameMode : public AGameModeBase

{

GENERATED_BODY()

//存储直线的地板

UPROPERTY()

TArray> pikaMidArr;

//存储左右的地板

UPROPERTY()

TArray> pikaLRArr;

public:

APikaqiuThirdTestGameMode();

virtual void BeginPlay() override;

//添加地板

void PikaAddFloor();

//打印测试

void PikaPirnt(FString piksStr);

TSubclassOf pikaNewFloor;

FTransform pikaNextTransforms;

//获取随机的地板

TSubclassOf PikaRandomInputFloor();

//将UI界面加载到屏幕上

void PikaUIAddToScreen();

//UI实例变量

UUserWidget *PikaMainUI;

TSubclassOf PikaUIMainInstance;

//确定金币的生成方向X轴或Y轴

//1:X轴负方向 2:Y轴负方向 3:X轴正方向 4:Y轴正方向

//LEFT -1 RIGHT +1

int32 IsX;

};

PikaqiuThirdTestGameMode.cpp// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.

#include "PikaqiuThirdTestGameMode.h"

#include "PikaqiuThirdTestCharacter.h"

#include "UObject/ConstructorHelpers.h"

#include "PikaFloor.h"

#include "PikaMainUI.h"

#include "Engine.h"

#include "PikaGameStateBase.h"

APikaqiuThirdTestGameMode::APikaqiuThirdTestGameMode()

{

// set default pawn class to our Blueprinted character

static ConstructorHelpers::FClassFinder PlayerPawnBPClass(TEXT("/Game/ThirdPersonCPP/Blueprints/ThirdPersonCharacter"));

if (PlayerPawnBPClass.Class != NULL)

{

DefaultPawnClass = PlayerPawnBPClass.Class;

}

//初始化容器

pikaMidArr.Empty();

pikaLRArr.Empty();

//获取蓝图中的直线地板

TSubclassOf pikaFloorBP01 = LoadClass(NULL , TEXT("Blueprint'/Game/Floor/BP/PikaFloorBP01.PikaFloorBP01_C'"));

pikaMidArr.Add(pikaFloorBP01);

TSubclassOf pikaFloorBP02 = LoadClass(NULL, TEXT("Blueprint'/Game/Floor/BP/PikaFloorBP02.PikaFloorBP02_C'"));

pikaMidArr.Add(pikaFloorBP02);

TSubclassOf pikaFloorBP03 = LoadClass(NULL, TEXT("Blueprint'/Game/Floor/BP/PikaFloorBP03.PikaFloorBP03_C'"));

pikaMidArr.Add(pikaFloorBP03);

//获取蓝图中的上下地板

TSubclassOf pikaFloorBP04 = LoadClass(NULL, TEXT("Blueprint'/Game/Floor/BP/PikaFloorBP04.PikaFloorBP04_C'"));

pikaMidArr.Add(pikaFloorBP04);

TSubclassOf pikaFloorBP05 = LoadClass(NULL, TEXT("Blueprint'/Game/Floor/BP/PikaFloorBP05.PikaFloorBP05_C'"));

pikaMidArr.Add(pikaFloorBP05);

//获取蓝图中的左右地板

TSubclassOf pikaFloorBP06 = LoadClass(NULL, TEXT("Blueprint'/Game/Floor/BP/PikaFloorBP06.PikaFloorBP06_C'"));

pikaLRArr.Add(pikaFloorBP06);

TSubclassOf pikaFloorBP07 = LoadClass(NULL, TEXT("Blueprint'/Game/Floor/BP/PikaFloorBP07.PikaFloorBP07_C'"));

pikaLRArr.Add(pikaFloorBP07);

//获取自定义的UI类实例

static ConstructorHelpers::FClassFinder PikaWidget(TEXT("/Game/UMG/PikaMainUI"));

PikaUIMainInstance = PikaWidget.Class;

//加载我们的GameState

GameStateClass = APikaGameStateBase::StaticClass();

IsX = 1;

}

void APikaqiuThirdTestGameMode::BeginPlay()

{

Super::BeginPlay();

if (GetWorld())

{

for (int32 i=0 ; i<10 ; i++)

{

PikaAddFloor();

}

}

//将UI界面加载到屏幕上

PikaUIAddToScreen();

}

void APikaqiuThirdTestGameMode::PikaAddFloor()

{

pikaNewFloor = PikaRandomInputFloor();

if (pikaNewFloor != NULL)

{

FVector const pikaLoction = pikaNextTransforms.GetLocation();

FRotator pikaRotation(pikaNextTransforms.Rotator());

//在场景中放入地板

APikaFloor *pikaFloor = GetWorld()->SpawnActor(pikaNewFloor, pikaLoction, pikaRotation);

//记录当前地板的位置,做为下一个生成的地板的初始位置

pikaNextTransforms = pikaFloor->PikaGetAttachToTransform();

//PikaPirnt(pikaNextTransforms.ToString());

}

}

void APikaqiuThirdTestGameMode::PikaPirnt(FString piksStr)

{

if (GEngine)

{

GEngine->AddOnScreenDebugMessage(-1, 10.0f, FColor::Red, piksStr);

}

}

//获取随机的地板

TSubclassOf APikaqiuThirdTestGameMode::PikaRandomInputFloor()

{

//return pikaMidArr[2];

int32 pikaRandom = FMath::RandRange(1, 100);

//生成直线地板(包括上下地板)的概率

int32 pikaProbMid = 60;

if (pikaRandom <= pikaProbMid)

{

//生成直线地板

int32 pikaSumMidArr = pikaMidArr.Num();

if (pikaSumMidArr)

{

//组数开始的下标为0

int32 pikaIndexMid = FMath::RandRange(0, pikaSumMidArr - 1);

return pikaMidArr[pikaIndexMid];

}

}

else

{

//生成左右地板

int32 pikaSumLRArr = pikaLRArr.Num();

if (pikaSumLRArr)

{

int32 pikaIndexLR = FMath::RandRange(0, pikaSumLRArr - 1);

return pikaLRArr[pikaIndexLR];

}

}

return NULL;

}

//将UI界面加载到屏幕上PikaMainUI

void APikaqiuThirdTestGameMode::PikaUIAddToScreen()

{

if (PikaUIMainInstance)

{

if (GetWorld())

{

PikaMainUI = CreateWidget(GetWorld(), PikaUIMainInstance);

if (PikaMainUI)

{

PikaMainUI->AddToViewport();

UPikaMainUI *PikaMain = Cast(PikaMainUI);

if (PikaMain)

{

//初始化金币数和步数

PikaMain->pikaCoinNum = FText::FromString(TEXT("0"));

PikaMain->pikaCharacterDistance = FText::FromString(TEXT("0"));

}

}

}

}

}

PikaqiuThirdTestCharacter.h// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"

#include "GameFramework/Character.h"

#include "PikaqiuThirdTestCharacter.generated.h"

UCLASS(config = Game)

class APikaqiuThirdTestCharacter : public ACharacter

{

GENERATED_BODY()

/** Camera boom positioning the camera behind the character */

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))

class USpringArmComponent* CameraBoom;

/** Follow camera */

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))

class UCameraComponent* FollowCamera;

public:

APikaqiuThirdTestCharacter();

/** 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;

protected:

/** Resets HMD orientation in VR. */

void OnResetVR();

/** Called for forwards/backward input */

void MoveForward(float Value);

/** Called for side to side input */

void MoveRight(float Value);

/**

* 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);

/** Handler for when a touch input begins. */

void TouchStarted(ETouchIndex::Type FingerIndex, FVector Location);

/** Handler for when a touch input stops. */

void TouchStopped(ETouchIndex::Type FingerIndex, FVector Location);

protected:

// APawn interface

virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

// End of APawn interface

public:

/** Returns CameraBoom subobject **/

FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }

/** Returns FollowCamera subobject **/

FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }

/********************************系统生成的代码分割线**********************************/

private:

//右手状态

bool rightState;

//左手状态

bool leftState;

//能否旋转

bool canTrun;

//死亡状态

bool deathState;

//导向旋转

FRotator desireRotation;

protected:

//右转身函数

void RightTurn();

//左转身函数

void LeftTurn();

//按键响应函数

void PikaSetupPlayerInputComponent(class UInputComponent *InputComponent);

public:

//模拟的构造函数

void PikaStructure();

//重载BeginPlay和Tick函数

virtual void BeginPlay() override;

virtual void Tick(float DeltaSeconds) override;

//自动向前跑

void KeepMoving();

FVector JudgeRAndL(FRotator pikaRotation);

FVector AddInputMoveForworld();

void PikaPirnt(FString  pikaStr);

FRotator PikaCombinRotation(FRotator rotation1, FRotator rotation2);

//设置角色的转向

void PikaCharacterTurn();

};

PikaqiuThirdTestCharacter.cpp// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.

#include "PikaqiuThirdTestCharacter.h"

#include "HeadMountedDisplayFunctionLibrary.h"

#include "Camera/CameraComponent.h"

#include "Components/CapsuleComponent.h"

#include "Components/InputComponent.h"

#include "GameFramework/CharacterMovementComponent.h"

#include "GameFramework/Controller.h"

#include "GameFramework/SpringArmComponent.h"

#include "Engine.h"

//

// APikaqiuThirdTestCharacter

APikaqiuThirdTestCharacter::APikaqiuThirdTestCharacter()

{

// Set size for collision capsule

GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);

// set our turn rates for input

BaseTurnRate = 45.f;

BaseLookUpRate = 45.f;

// Don't rotate when the controller rotates. Let that just affect the camera.

bUseControllerRotationPitch = false;

bUseControllerRotationYaw = false;

bUseControllerRotationRoll = false;

// Configure character movement

GetCharacterMovement()->bOrientRotationToMovement = true; // Character moves in the direction of input...

GetCharacterMovement()->RotationRate = FRotator(0.0f, 540.0f, 0.0f); // ...at this rotation rate

GetCharacterMovement()->JumpZVelocity = 600.f;

GetCharacterMovement()->AirControl = 0.2f;

// Create a camera boom (pulls in towards the player if there is a collision)

CameraBoom = CreateDefaultSubobject(TEXT("CameraBoom"));

CameraBoom->SetupAttachment(RootComponent);

CameraBoom->TargetArmLength = 300.0f; // The camera follows at this distance behind the character

CameraBoom->bUsePawnControlRotation = true; // Rotate the arm based on the controller

// Create a follow camera

FollowCamera = CreateDefaultSubobject(TEXT("FollowCamera"));

FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation

FollowCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm

// Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character)

// are set in the derived blueprint asset named MyCharacter (to avoid direct content references in C++)

PikaStructure();

}

//

// Input

void APikaqiuThirdTestCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)

{

// Set up gameplay key bindings

check(PlayerInputComponent);

PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);

PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);

PlayerInputComponent->BindAxis("MoveForward", this, &APikaqiuThirdTestCharacter::MoveForward);

PlayerInputComponent->BindAxis("MoveRight", this, &APikaqiuThirdTestCharacter::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

PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);

PlayerInputComponent->BindAxis("TurnRate", this, &APikaqiuThirdTestCharacter::TurnAtRate);

PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);

PlayerInputComponent->BindAxis("LookUpRate", this, &APikaqiuThirdTestCharacter::LookUpAtRate);

// handle touch devices

PlayerInputComponent->BindTouch(IE_Pressed, this, &APikaqiuThirdTestCharacter::TouchStarted);

PlayerInputComponent->BindTouch(IE_Released, this, &APikaqiuThirdTestCharacter::TouchStopped);

// VR headset functionality

PlayerInputComponent->BindAction("ResetVR", IE_Pressed, this, &APikaqiuThirdTestCharacter::OnResetVR);

//皮卡丘按键响应

//PikaSetupPlayerInputComponent(PlayerInputComponent);

}

void APikaqiuThirdTestCharacter::OnResetVR()

{

UHeadMountedDisplayFunctionLibrary::ResetOrientationAndPosition();

}

void APikaqiuThirdTestCharacter::TouchStarted(ETouchIndex::Type FingerIndex, FVector Location)

{

Jump();

}

void APikaqiuThirdTestCharacter::TouchStopped(ETouchIndex::Type FingerIndex, FVector Location)

{

StopJumping();

}

void APikaqiuThirdTestCharacter::TurnAtRate(float Rate)

{

// calculate delta for this frame from the rate information

AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds());

}

void APikaqiuThirdTestCharacter::LookUpAtRate(float Rate)

{

// calculate delta for this frame from the rate information

AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds());

}

void APikaqiuThirdTestCharacter::MoveForward(float Value)

{

if ((Controller != NULL) && (Value != 0.0f))

{

// find out which way is forward

const FRotator Rotation = Controller->GetControlRotation();

const FRotator YawRotation(0, Rotation.Yaw, 0);

// get forward vector

const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);

AddMovementInput(Direction, Value);

}

}

void APikaqiuThirdTestCharacter::MoveRight(float Value)

{

if ((Controller != NULL) && (Value != 0.0f))

{

// find out which way is right

const FRotator Rotation = Controller->GetControlRotation();

const FRotator YawRotation(0, Rotation.Yaw, 0);

// get right vector

const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

// add movement in that direction

AddMovementInput(Direction, Value);

}

}

/********************************系统生成的代码分割线**********************************/

//模拟的构造函数

void APikaqiuThirdTestCharacter::PikaStructure()

{

//初始化基础变量

//右手状态

rightState = false;

//左手状态

leftState = false;

//能否旋转

canTrun = true;

//死亡状态

deathState = false;

//导向旋转

desireRotation = FRotator(0);

}

//重载BeginPlay和Tick函数

void APikaqiuThirdTestCharacter::BeginPlay()

{

Super::BeginPlay();

}

void APikaqiuThirdTestCharacter::Tick(float DeltaSeconds)

{

Super::Tick(DeltaSeconds);

if (deathState)

{

}

else

{

//PikaCharacterTurn();

KeepMoving();

}

}

//自动向前跑

void APikaqiuThirdTestCharacter::KeepMoving()

{

AddMovementInput(JudgeRAndL(desireRotation), 1);

}

FVector APikaqiuThirdTestCharacter::JudgeRAndL(FRotator pikaRotation)

{

if (rightState)

{

rightState = false;

return AddInputMoveForworld();

}

else if (leftState)

{

leftState = false;

return AddInputMoveForworld();

}

else

{

return AddInputMoveForworld();

}

}

FVector APikaqiuThirdTestCharacter::AddInputMoveForworld()

{

//获取角色的旋转值

const FRotator pikaRotation = Controller->GetControlRotation();

//保证只有Yaw变化

const FRotator yawRotation(0, pikaRotation.Yaw, 0);

const FVector desiron = FRotationMatrix(yawRotation).GetUnitAxis(EAxis::X);

return desiron;

}

void APikaqiuThirdTestCharacter::PikaPirnt(FString  pikaStr)

{

if (GEngine)

{

GEngine->AddOnScreenDebugMessage(-1, 0.5f, FColor::Red, pikaStr);

}

}

//按键响应

void APikaqiuThirdTestCharacter::PikaSetupPlayerInputComponent(class UInputComponent *InputComponent)

{

//键盘按键

InputComponent->BindAction("pikaRight", IE_Pressed, this, &APikaqiuThirdTestCharacter::RightTurn);

InputComponent->BindAction("pikaLeft", IE_Pressed, this, &APikaqiuThirdTestCharacter::LeftTurn);

}

FRotator APikaqiuThirdTestCharacter::PikaCombinRotation(FRotator rotation1, FRotator rotation2)

{

FQuat aQuat = FQuat(rotation1);

FQuat bQuat = FQuat(rotation2);

return FRotator(aQuat * bQuat);

}

//右转身函数

void APikaqiuThirdTestCharacter::RightTurn()

{

if (canTrun)

{

//顺时针旋转90度

FRotator pikaRotation = FRotator(0, 90, 0);

desireRotation = PikaCombinRotation(desireRotation, pikaRotation);

rightState = true;

}

}

//左转身函数

void APikaqiuThirdTestCharacter::LeftTurn()

{

if (canTrun)

{

//逆时针旋转90度

FRotator pikaRotation = FRotator(0, -90, 0);

desireRotation = PikaCombinRotation(desireRotation, pikaRotation);

leftState = true;

}

}

// 设置角色的转向

void APikaqiuThirdTestCharacter::PikaCharacterTurn()

{

GetController()->SetControlRotation(FMath::RInterpTo(GetControlRotation(), desireRotation, GetWorld()->GetRealTimeSeconds(), 10));

}

PikaqiuThirdTest.Build.cs// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;

public class PikaqiuThirdTest : ModuleRules

{

public PikaqiuThirdTest(ReadOnlyTargetRules Target) : base(Target)

{

PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

//模块加入

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay" , "UMG"});

}

}

PikaMainUI.h// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

#include "Blueprint/UserWidget.h"

#include "PikaMainUI.generated.h"

/**

*

*/

UCLASS()

class PIKAQIUTHIRDTEST_API UPikaMainUI : public UUserWidget

{

GENERATED_BODY()

public:

//主界面UI上记录金币数和步数的变量

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = UI)

FText pikaCoinNum;

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = UI)

FText pikaCharacterDistance;

};

PikaGameStateBase.h// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

#include "GameFramework/GameStateBase.h"

#include "PikaGameStateBase.generated.h"

/**

*

*/

UCLASS()

class PIKAQIUTHIRDTEST_API APikaGameStateBase : public AGameStateBase

{

GENERATED_BODY()

public:

APikaGameStateBase();

//记录用户的金币数和步数

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = UI)

int32 PikaGlod;

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = UI)

int32 PikaDistance;

bool PikaStopLoopForCharacterDistance;

virtual void BeginPlay() override;

//计算角色移动的距离

void PikaAddDistance();

//计算三维空间的距离,即角色移动向量的模

float PikaGetVectorLeng(FVector Vctor);

FTimerHandle PikaHandle;

};

PikaGameStateBase.cpp// Fill out your copyright notice in the Description page of Project Settings.

#include "PikaGameStateBase.h"

#include "PikaqiuThirdTestCharacter.h"

#include "PikaqiuThirdTestGameMode.h"

#include "PikaMainUI.h"

#include "GameFramework/CharacterMovementComponent.h"

APikaGameStateBase::APikaGameStateBase()

{

//金币

PikaGlod = 0;

//角色距离

PikaDistance = 0;

PikaStopLoopForCharacterDistance = true;

}

void APikaGameStateBase::BeginPlay()

{

Super::BeginPlay();

GetWorldTimerManager().SetTimer(PikaHandle, this, &APikaGameStateBase::PikaAddDistance, 0.03f, true);

}

//计算角色移动的距离

void APikaGameStateBase::PikaAddDistance()

{

if (PikaHandle.IsValid())

{

//GetWorldTimerManager().ClearTimer(PikaHandle);

}

if (PikaStopLoopForCharacterDistance)

{

if (GetWorld())

{

//获取GameMode的实例

APikaqiuThirdTestGameMode *pikaGameMode = Cast(GetWorld()->GetAuthGameMode());

//获取PikaqiuThirdTestCharacter的实例

APikaqiuThirdTestCharacter *PikaCharacter = Cast(GetWorld()->GetFirstPlayerController()->GetPawn());

if (PikaCharacter && pikaGameMode)

{

//计算角色移动距离

//GetMovementComponent()需要GameFramework/CharacterMovementComponent.h头文件

int32 TempDistance = (PikaGetVectorLeng(PikaCharacter->GetMovementComponent()->Velocity))*0.03f;

PikaDistance += TempDistance;

//更新到UI界面上

UPikaMainUI *PikaMain = Cast(pikaGameMode->PikaMainUI);

if (PikaMain)

{

PikaMain->pikaCharacterDistance = FText::FromString(FString::FromInt(PikaDistance));

}

}

//设置计算一次距离的时间

GetWorldTimerManager().SetTimer(PikaHandle, this, &APikaGameStateBase::PikaAddDistance, 0.03f, true);

}

}

}

//计算三维空间的距离,即角色移动向量的模

float APikaGameStateBase::PikaGetVectorLeng(FVector Vctor)

{

return sqrt(Vctor.X*Vctor.X + Vctor.Y*Vctor.Y + Vctor.Z*Vctor.Z);

}

PikaFloor.h// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

#include "GameFramework/Actor.h"

#include "Components/BoxComponent.h"

#include "Components/ArrowComponent.h"

#include "PikaFloor.generated.h"

//Floor类型

//暴露给蓝图后,在蓝图中设置好本蓝图的类型,再在代码中根据当前类型来决定金币的生成规则

UENUM()

namespace PikaFloorType

{

enum PikaType

{

StraightFloor,//直线地板

UpFloor,//往上的地板

DownFloor,//往下的地板

LeftFloor,//左转的地板

RightFloor,//右转的地板

};

}

UCLASS()

class PIKAQIUTHIRDTEST_API APikaFloor : public AActor

{

GENERATED_BODY()

//场景组件

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "pikaqiu", meta = (AllowPrivateAccess = "true"))

USceneComponent *pikaSeceneComponent;

//根组件

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "pikaqiu", meta = (AllowPrivateAccess = "true"))

USceneComponent *pikaRootFCompoent;

//碰撞

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "pikaqiu", meta = (AllowPrivateAccess = "true"))

UBoxComponent *pikaBoxCompoent;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "pikaqiu", meta = (AllowPrivateAccess = "true"))

UBoxComponent *pikaTurnComponent;

//模型

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "pikaqiu", meta = (AllowPrivateAccess = "true"))

UStaticMeshComponent *pikaBoxMesh;

//标记地板生成的位置

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "pikaqiu", meta = (AllowPrivateAccess = "true"))

UArrowComponent *pikaSpawnPoint;

//标记左右金币生成的位置

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "pikaqiu", meta = (AllowPrivateAccess = "true"))

UArrowComponent *pikaSpawnPointR;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "pikaqiu", meta = (AllowPrivateAccess = "true"))

UArrowComponent *pikaSpawnPointL;

//金币Actor,生成金币时用

TSubclassOf PikaCoinActor;

//金币数组,存储已经生成的金币,用于在销毁地板时,一同销毁金币

TArray PikaCoinArr;

//类型枚举

UPROPERTY(EditDefaultsOnly, Category = "PikaFloorType")

TEnumAsByte<:pikatype> PikFloorTypeBP;

public:

// Sets default values for this actor's properties

APikaFloor();

protected:

// Called when the game starts or when spawned

virtual void BeginPlay() override;

public:

// Called every frame

virtual void Tick(float DeltaTime) override;

//获取当前Actor(地板)的位置信息

FTransform PikaGetAttachToTransform();

//地板里pikaBoxCompoent碰撞体的碰撞函数,使用前需要先进行绑定

UFUNCTION()

void PikaOverlap(UPrimitiveComponent *pikaOverlapppedComponent , AActor *pikaOtherActor , UPrimitiveComponent *pikaOtherComp , int32 pikaOtherBodyIndex , bool pikaFromSweepBool , const FHitResult & pikaSweepResult);

//打印测试

void PikaPrint(FString piksStr);

//计时器

FTimerHandle pikaTimer;

//销毁对象实例

void PikaDestroy();

//在地板随机放置金币

void PikaGetCoinForFloor();

//金币生成函数

void PikaSpawnCoinArr(UArrowComponent *PikaSpawnPos , bool IsMid);

};

PikaFloor.cpp// Fill out your copyright notice in the Description page of Project Settings.

#include "PikaFloor.h"

#include "Components/StaticMeshComponent.h"

#include "Engine.h"

#include "PikaqiuThirdTestCharacter.h"

#include "PikaqiuThirdTestGameMode.h"

#include "UnrealMathUtility.h"

// Sets default values

APikaFloor::APikaFloor()

{

// 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;

//组件加载

//场景组件

pikaSeceneComponent = CreateDefaultSubobject(TEXT("pikaqiuSecene"));

pikaRootFCompoent = CreateDefaultSubobject(TEXT("pikaqiuRoot"));

pikaTurnComponent = CreateDefaultSubobject(TEXT("pikaTurnBox"));

pikaBoxMesh = CreateDefaultSubobject(TEXT("pikaBoxMesh"));

//碰撞

pikaBoxCompoent = CreateDefaultSubobject(TEXT("pikaCollBox"));

//标记地板生成的位置

pikaSpawnPoint = CreateDefaultSubobject(TEXT("pikaSpanwPoint"));

//标记左右金币生成的位置

pikaSpawnPointR = CreateDefaultSubobject(TEXT("pikaSpanwPointR"));

pikaSpawnPointL = CreateDefaultSubobject(TEXT("pikaSpanwPointL"));

//将本组件的根组件设置为场景组件pikaSeceneComponent

RootComponent = pikaSeceneComponent;

//绑定

pikaRootFCompoent->AttachToComponent(pikaSeceneComponent, FAttachmentTransformRules::KeepRelativeTransform);

pikaSpawnPoint->AttachToComponent(pikaRootFCompoent, FAttachmentTransformRules::KeepRelativeTransform);

pikaSpawnPointR->AttachToComponent(pikaRootFCompoent, FAttachmentTransformRules::KeepRelativeTransform);

pikaSpawnPointL->AttachToComponent(pikaRootFCompoent, FAttachmentTransformRules::KeepRelativeTransform);

pikaBoxCompoent->AttachToComponent(pikaRootFCompoent, FAttachmentTransformRules::KeepRelativeTransform);

pikaTurnComponent->AttachToComponent(pikaRootFCompoent, FAttachmentTransformRules::KeepRelativeTransform);

pikaBoxMesh->AttachToComponent(pikaRootFCompoent, FAttachmentTransformRules::KeepRelativeTransform);

//获取金币蓝图的Actor

static ConstructorHelpers::FClassFinder PikaCoinBP(TEXT("/Game/Coin/BP/PikaCoinBP01"));

PikaCoinActor = PikaCoinBP.Class;

}

// Called when the game starts or when spawned

void APikaFloor::BeginPlay()

{

Super::BeginPlay();

//绑定pikaBoxCompoent的碰撞函数

//该函数放在构造函数中时,有可能出现UBoxComponent类没有创建完成,就执行绑定,从而导致绑定失败的情况

//OnComponentBeginOverlap.AddUniqueDynamic和OnComponentEndOverlap.AddUniqueDynamic分别为碰到碰撞体和离开碰撞体时调用的事件

pikaBoxCompoent->OnComponentBeginOverlap.AddUniqueDynamic(this, &APikaFloor::PikaOverlap);

//三渲二

//pikaBoxMesh->SetRenderCustomDepth(true);

//获取gameMode类的实例

APikaqiuThirdTestGameMode *PikaGameMode = Cast(GetWorld()->GetAuthGameMode());

//如果不是左右转弯的地板,则生成金币

if (PikFloorTypeBP == PikaFloorType::LeftFloor)

{

PikaGameMode->IsX -= 1;

}

else if (PikFloorTypeBP == PikaFloorType::RightFloor)

{

PikaGameMode->IsX += 1;

}

else if (PikFloorTypeBP == PikaFloorType::UpFloor || PikFloorTypeBP == PikaFloorType::DownFloor)

{

}

else

{

PikaGetCoinForFloor();

}

if (PikaGameMode->IsX > 4)

PikaGameMode->IsX = 1;

if (PikaGameMode->IsX 

PikaGameMode->IsX = 4;

}

// Called every frame

void APikaFloor::Tick(float DeltaTime)

{

Super::Tick(DeltaTime);

}

FTransform APikaFloor::PikaGetAttachToTransform()

{

FTransform pikaTransform;

//获取当前组件的Location和Rotation

pikaTransform.SetLocation(pikaSpawnPoint->GetComponentToWorld().GetLocation());

pikaTransform.SetRotation(pikaSpawnPoint->GetComponentQuat());

return pikaTransform;

}

void APikaFloor::PikaPrint(FString piksStr)

{

if (GEngine)

{

GEngine->AddOnScreenDebugMessage(-1, 6.0f, FColor::Red, piksStr);

}

}

//地板里pikaBoxCompoent碰撞体的碰撞函数,使用前需要先进行绑定

void APikaFloor::PikaOverlap(UPrimitiveComponent *pikaOverlapppedComponent, AActor *pikaOtherActor, UPrimitiveComponent *pikaOtherComp, int32 pikaOtherBodyIndex, bool pikaFromSweepBool, const FHitResult & pikaSweepResult)

{

//检测碰撞体碰撞到的对象是否是玩家角色

if (pikaOtherActor->IsA(APikaqiuThirdTestCharacter::StaticClass()))

{

if (GetWorld())

{

//获取GameMode的实例

APikaqiuThirdTestGameMode *pikaGameMode = Cast(GetWorld()->GetAuthGameMode());

if (pikaGameMode)

{

pikaGameMode->PikaAddFloor();

//延时5秒执行销毁地板

if (pikaTimer.IsValid())

{

GetWorldTimerManager().ClearTimer(pikaTimer);

}

GetWorldTimerManager().SetTimer(pikaTimer , this , &APikaFloor::PikaDestroy, 5.0f , true);

}

}

}

}

//销毁对象实例

void APikaFloor::PikaDestroy()

{

//销毁金币

if (PikaCoinArr.Num() > 0)

{

for (AActor *PikaCoinDestory:PikaCoinArr)

{

if (PikaCoinDestory)

{

PikaCoinDestory->Destroy(true);

}

}

}

//销毁地板

Destroy(true);

}

//在地板随机放置金币

void APikaFloor::PikaGetCoinForFloor()

{

int32 RandomNum = FMath::FRandRange(0 , 2);

switch (RandomNum)

{

case 0://在右边生成金币

if (pikaSpawnPointR)

{

PikaSpawnCoinArr(pikaSpawnPointR, false);

}

break;

case 1://在左边生成金币

if (pikaSpawnPointL)

{

PikaSpawnCoinArr(pikaSpawnPointL, false);

}

break;

default:

break;

}

/*switch (RandomNum)

{

case 0://不生成金币

break;

case 1://在左边生成金币

if (pikaSpawnPointL)

{

PikaSpawnCoinArr(pikaSpawnPointL , false);

}

break;

case 2://在中间生成金币

//PikaSpawnCoinArr(pikaSpawnPointL, true);

break;

case 3://在右边生成金币

if (pikaSpawnPointR)

{

PikaSpawnCoinArr(pikaSpawnPointR , false);

}

break;

default:

break;

}*/

}

//金币生成函数

void APikaFloor::PikaSpawnCoinArr(UArrowComponent *PikaSpawnPos , bool IsMid)

{

PikaCoinArr.Empty();

if (PikaCoinActor && GetWorld())

{

FVector PikaLocation = PikaSpawnPos->GetComponentLocation();

FRotator PikaRotator = PikaSpawnPos->GetComponentRotation();

if (IsMid)

{

//PikaLocation.Y += 340;

}

FVector PikaTempLocation;

for (int32 i=0 ; i<=15 ; i++)

{

//每隔一段距离生成一个金币

PikaTempLocation = PikaLocation;

//获取gameMode类的实例

APikaqiuThirdTestGameMode *PikaGameMode = Cast(GetWorld()->GetAuthGameMode());

if (1 == PikaGameMode->IsX)

{

PikaTempLocation.X -= (i * 120);

}

else if (2 == PikaGameMode->IsX)

{

PikaTempLocation.Y += (i * 120);

}

else if (3 == PikaGameMode->IsX)

{

PikaTempLocation.X += (i * 120);

}

else if (4 == PikaGameMode->IsX)

{

PikaTempLocation.Y -= (i * 120);

}

else

{

PikaTempLocation.X -= (i * 120);

}

/*if (PikFloorTypeBP == PikaFloorType::UpFloor)

{

PikaTempLocation.Z -= (i * 45);

}

else if (PikFloorTypeBP == PikaFloorType::DownFloor)

{

PikaTempLocation.Z += (i * 60);

}*/

AActor *PikaCoinBPObj = GetWorld()->SpawnActor(PikaCoinActor, PikaTempLocation, PikaRotator);

if (PikaCoinBPObj)

{

//存储已经生成的金币,当地板被销毁时,金币也一同销毁

PikaCoinArr.Add(PikaCoinBPObj);

}

}

}

}

PikaCoin.h// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"

#include "GameFramework/Actor.h"

#include "Components/BoxComponent.h"

#include "GameFramework/RotatingMovementComponent.h"

#include "PikaCoin.generated.h"

UCLASS()

class PIKAQIUTHIRDTEST_API APikaCoin : public AActor

{

GENERATED_BODY()

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "pikaCoin", meta = (AllowPrivateAccess = "true"))

UStaticMeshComponent *pikaCoinMesh;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "pikaCoin", meta = (AllowPrivateAccess = "true"))

UBoxComponent *pikaMeshComponent;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "pikaCoin", meta = (AllowPrivateAccess = "true"))

URotatingMovementComponent *pikaRotatingMovement;

//声音播放

UPROPERTY(EditDefaultsOnly, Category = "PikaSound")

USoundBase *PikaEatCoinSound;

public:

// Sets default values for this actor's properties

APikaCoin();

protected:

// Called when the game starts or when spawned

virtual void BeginPlay() override;

public:

// Called every frame

virtual void Tick(float DeltaTime) override;

//金币的碰撞函数

UFUNCTION()

void PikaCharacterOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult);

//打印测试

void PikaPirnt(FString piksStr);

};

PikaCoin.cpp// Fill out your copyright notice in the Description page of Project Settings.

#include "PikaCoin.h"

#include "PikaqiuThirdTestCharacter.h"

#include "PikaqiuThirdTestGameMode.h"

#include "Engine.h"

#include "PikaGameStateBase.h"

#include "PikaMainUI.h"

// Sets default values

APikaCoin::APikaCoin()

{

// 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;

pikaCoinMesh = CreateDefaultSubobject(TEXT("pikaCoinMesh"));

pikaMeshComponent = CreateDefaultSubobject(TEXT("pikaBoxComponents"));

pikaRotatingMovement = CreateDefaultSubobject(TEXT("pikaRotatingMovement"));

RootComponent = pikaMeshComponent;

pikaCoinMesh->SetupAttachment(pikaMeshComponent);

}

// Called when the game starts or when spawned

void APikaCoin::BeginPlay()

{

Super::BeginPlay();

//碰撞方式要选择OnComponentBeginOverlap,OnComponentHit方式的碰撞会产生阻力,使碰撞对象停顿

pikaMeshComponent->OnComponentBeginOverlap.AddDynamic(this, &APikaCoin::PikaCharacterOverlap);

}

// Called every frame

void APikaCoin::Tick(float DeltaTime)

{

Super::Tick(DeltaTime);

}

//金币的碰撞函数

void APikaCoin::PikaCharacterOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)

{

if (OtherActor->IsA(APikaqiuThirdTestCharacter::StaticClass()))

{

if (GetWorld())

{

//获取GameMode的实例

APikaqiuThirdTestGameMode *pikaGameMode = Cast(GetWorld()->GetAuthGameMode());

//获取GameState的实例

APikaGameStateBase *PikaGameState = Cast(GetWorld()->GetGameState());

if (pikaGameMode && PikaGameState)

{

//检测到金币的碰撞后,金币数加1并更新到屏幕上

PikaGameState->PikaGlod++;

UPikaMainUI *PikaMain = Cast(pikaGameMode->PikaMainUI);

if (PikaMain)

{

PikaMain->pikaCoinNum = FText::FromString(FString::FromInt(PikaGameState->PikaGlod));

}

}

//当吃掉金币后发出金币的声音

if (PikaEatCoinSound)

{

UGameplayStatics::PlaySoundAtLocation(GetWorld(), PikaEatCoinSound, GetActorLocation());

}

}

Destroy(true);

}

}

void APikaCoin::PikaPirnt(FString piksStr)

{

if (GEngine)

{

GEngine->AddOnScreenDebugMessage(-1, 6.0f, FColor::Red, piksStr);

}

}

1