您的位置:首页 > 编程语言 > C语言/C++

UE4 C++示例工程Battery Collector(4.10版本又更名为3rd Person Power-up)

2016-07-25 21:38 676 查看
这个是官方的一个C++示范工程,一共有21个教学视频,总时长2个小时。从游戏逻辑上、引擎功能使用程度上来说,都属于比较简单的层次,不过以入门、了解虚幻4的C++特性为目的,这个还是不错的素材。最终效果见优酷链接。下面是主要代码,包含5个类:Pickup,BattertyPickup,BatteryCollectorCharacter,BatteryCollectorGameMode,SpawnVolume,还有少量UMG功能也使用了C++,这里不再列出。



Pickup类

Pickup.h

#include "GameFreamework/Actor.h"
#include "Pickup.generated.h"

UCLASS()
class BATTERYCOLLECTOR_API APickup :public AActor
{
GENERATED_BODY();

public:
//构造函数,设置初始值
APickup();

//当游戏开始或者被spawn时函数被调用
virtual void BeginPlay() override;

//每帧调用
virtual void Tick(float DeltaSeconds) override;

//返回static mesh
FORCEINLINE class UStaticMeshComponent* GetMesh() const
{
return PickupMesh;
}

//返回pickup当前状态
UFUNCTION(BlueprintPure, Category = "Pickup")
bool IsActive();
//允许其他类安全的改变pickup的状态
UFUNCTION(BlueprintCallable, Category = "Pickup")
void SetActive(bool NewPickupState);

//当pickup被拾取时调用
UFUNCTION(BlueprintNativeEvent)
void WasCollected();

virtual void WasCollected_Implementation();

protected:
//pickup 是否在激活状态
bool bIsActive;

private:

//static mesh 是pickup的实体表现
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Pickup", meta = (AllowPrivateAccess = "true"))
class UStaticMeshComponent* PickupMesh;
}


Pickup.cpp

#include "BatteryCollector.h"
#include "Pickup.h"

APickup::APickup()
{
PrimaryActorTick.bCanEverTick = false;
//创建static mesh 组件,CreateDefaultSubobject<>()函数
PickupMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("PickupMesh"));
RootComponent = PickupMesh;
bIsActive = true;
}

void APickup::BeginPlay()
{
Super::BeginPlay();
}

void APickup::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}

bool APickup::IsActive()
{
return bIsActive;
}

void APickup::SetActive(bool NewPickupState)
{
bIsActive = NewPickupState;
}
void APickup::WasCollected()
{
Fstring PickupDebugString = GetName();
UE_LOG(LogClass,Log, TEXT("You have collected %s",PickupDebugString));
}


BatteryPickup类

BatteryPickup.h

#include "Pickup.h"
#include "BatteryPickup.generated.h"

UCLASS()
class BATTERYCOLLECTOR_API ABatteryPickup : public APickup
{
GENERATED_BODY();
public:
ABatteryPickup();

void WasCollected_Implementation() override;

float GetPower();
protected:
//BatteryPickup的能量值
UPROPERTY(EditAnywhere,BlueprintReadWrite, Category = "Power" , meta = (BlueprintProtected = "true"));
float BatteryPower
}


BatteryPickup.cpp

#include "BatteryCollector.h"
#include "BatteryPickup.h"

ABatteryPickup::ABatteryPickup()
{
//电池pickup子类,模拟物理效果
GetMesh()->SetSimulatePhysics(true);

BatteryPower = 150.f;
}

void ABatteryPickup::WasCollected_Implementation()
{
//使用基类的函数
Super::WasCollected_Implementation();
//销毁battery
Destroy();
}

float ABatteryPickup::GetPower()
{
return BatteryPower;
}


SpawnVolume类

SpawnVolume.h

#include "GameFramework/Actor.h"
#include "SpawnVolume.generated.h"

UCLASS()
class BATTERYCOLLECTOR_API ASpawnVolume : public AActor
{
GENERATED_BODY()

public:
ASpawnVolume();

virtual void BeginPlay() override;

virtual void Tick(float DeltaSeconds) override;
//返回GetWhereToSpawn组件
FORCEINLIE class UBoxComponent* GetWhereToSpawn() const { return WhereToSpawn;}

//返回spawnvolume中任意一点
UFUNCTION(BlueprintPure, Category = "Spawning")
FVector GetRandomPointInVolume();

//设置是否可以spawn
UFUNCTION(BlueprintCallable, Category = "Spawning")
void SetSpawningActive(bool bShouldSpawn);
private:
//box component 实例化pick up的地点
UPROPERTY(VisibleAnywhere,BlueprintReanOnly,Category = "Spawning", meta = (AllowPrivateAccess = "true"))
class UBoxComponent* WhereToSpawn;
//
void SpawnPickup();

//当前spawn的时间间隔
float SpawnDelay;
protected:
//spawn的pickup类
UPROPERTYY(EditAnywhere, Category = "Spawning")
TSubclassof<class APickup> WhatToSpawn;

FTimerHandle SpawnTimer;

//spawn 时间间隔
UPROPERTY(EditAnywhere,BlueprintReadWrite,category = "Spawning")
float SpawnDelayRangeHigh;
UPROPERTY(EditAnywhere,BlueprintReadWrite,category = "Spawning")
float SpawnDelayRangeLow
}


SpawnVolume.cpp

#include "BatteryCollector.h"
#include "SpawnVolume.h"
#include "Kismet/KismetMathLiibrary.h"
#include "Pickup.h"

ASpawnVolume::ASpawnVolume()
{
PrimaryActorTick.bCanEverTick = false;

WhereToSpawn = CreateDefaultSubobject<UBoxComponent>(TEXT("WhereToSpawn"));
RooComponent = WhereToSpawn;

SpawnDelayRangeLow = 1.0f;
SpawnDelayRangeHigh = 4.5f;

}

void ASpawnVolume::BeginPlay()
{
Super::BeginPlay();

}

FVector ASpawnVolume::GetRandomPointInVolume()
{
FVector SpawnOrigin = WhereToSpawn->Bounds.Origin;
Fvector SpawnExtent = WhereToSpawn->Bounds.BoxExtent;
//返回box  component内任意一点
return UKismetMathLibrary::RandomPointInBoundingBox(SpawnOrigin,SpawnExtent);
}

void ASpawnVolume::SetSpawningActive(bool bShouldSpawn)
{

if(bShouldSpawn)
{
//如果spawn时,通过timer定时器不断激活SpawnPickup()函数
SpawnDelay = FMath::FRandRange(SpawnDelayRangeLow,SpawnDelayRangeHigh);
GetWorldTimerManager().SetTimer(SpawnTimer,this,&ASpawnVolume::SpawnPickup,SpawnDelay,false);
}
else
{
//不spawn时,清除定时器即可
GetWorldTimerManager().ClearTimer(SpawnTimer);
}
}

void ASpawnVolume::SpawnPickup()
{
//pickup是否存在
if(WhatToSpawn != NULL)
{
//当前世界是否有效
UWorld* const World = GetWorld();
if(World)
{

//设置spawn参数
FActorSpawnParameters SpawnParams;
SpawnParams.Owner = this;
SpawnParams.Instigator = Instigator;

Fvector SpawnLocation = GetRandomPointInVolume();
FRotator SpawnRotation;
SpawnRotation.Yaw = FMath::FRand()*360.f
SpawnRotation.Pitch = FMath::FRand()*360.f
SpawnRotation.Roll = FMath::FRand()*360.f

//生成pickup
APickup* const SpawnedPickup = World->SpawnActor<APickup>(WhatToSpawn,SpawnLocation,SpawnRotation,SpawnParams);
}
}
}


BatteryCollectorCharacter类

限于篇幅,不再摘抄Character类自带的大量代码,只显示新增的代码

BatteryCollectorCharacter.h

#include "BatteryCollectorCharacter.generated.h"

UCLASS(config=Game)
{
private:
//pickup接触到的范围
UPROPERTY(VisibleAnywhere,BlueprintReadOnly,Category = Camera)
class USphereComponent* CollectionSphere;

//当前能量值
UPROPERTY(VisibleAnywhere, Category = "Power")
float CharecterPower;

public;

ABatteryCollectorCharacter();

FORCEINLINE class USphereComponent* GetCollectionSphere const { return CollectionSphere;}

UFUNCTION(BlueprintPure,Category = "Power")
float GetInitialPower();
UFUNCTION(BlueprintPure,Category = "Power")
float GetCharecterPower();
//更新当前能量值
UFUNCTION(BlueprintCallable, Category = "Power")
void UpdatePower(float PowerChange);

protected:

//当按下按键开始收集pickup
UFUNCTION(BlueprintCallable, Category = "Pickups")
void CollectPickups();

//初始能量值
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Power", Meta  = (BlueprintProtected = "true"))
float InitialPower;

//玩家速度影响因子
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Power", Meta  = (BlueprintProtected = "true"))
float SpeedFactor;

//玩家初始速度
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Power", Meta  = (BlueprintProtected = "true"))
float BaseSpeed;

//
UFUNCTION(BlueprintImplementableEvent,Category = "Power")
void PowerChangeEffect();
}


BatteryCollectorCharacter.cpp

#include "BatteryCollector.h"
#include "BatteryCollectorCharacter.h"
#include "BatteryPickup.h"

ABatteryCollectorCharacter::ABatteryCollectorCharater()
{
CollectionSphere = CreatDefaultSubobject<USphereComponent>(TEXT("CollectionSphere"));
CollectionSphere->AttachTo(RootComponent);
CollectionSphere->SetSphereRadius(200.f);

InitialPower = 200.0f;
CharacterPower = InitialPower;
SpeedFactor = 0.75f;
BaseSpeed = 10.0f
}

void ABatteryCollectorCharacter::SetupPlayerInputComponent(class UIputComponent* InputComponent)
{
InputComponent->BindAction("Collect",IE_Pressed,this,&ABatteryCollectorCharacter::CollectPickups);
}

void ABatteryCollectorCharacter::CollectPickups()
{
//得到所有overlapping的物体
TArray<AActor*> CollectedActors;
CollectionSphere->GetOverlappingActors(CollectedActors);
//记录获得的能量值
float CollectedPower = 0;

//遍历得到的物体,转换为 APickup类
for(int32 iCollected = 0; iCollected < CollectedActors.Num(); ++iCollected)
{
APickup* const TestPickup = Cast<APickup> (CollectedActors[iCollected]);

if(TestPickup && !TestPickup->IsPendingKill() && TestPickup->IsActive())
{
//调用pickup类的WasCollected()函数
TestPickup->WasCollected();
ABatteryPickup* const TestBattery= Cast<ABatteryPickup>(TestPickup);
if(TestBattery)
{
CollectedPower += TestBattery->GetPower();
}
TestPickup->SetActive(false);
}
}
if(CollectedPower > 0)
{
UpdatePower(CollectedPower);
}
}

float ABatteryCollectorCharacter::GetInitialPower()
{
return InitialPower;
}

float ABatteryCollectorCharacter::GetCharacterPower()
{
return CharacterPower;
}

void ABatteryCollectorCharacter::UpdatePower(float PowerChange)
{
CharacterPower = CharacterPower + PowerChange;
GetCharacterMovement()->MaxWalkSpeed = BaseSpeed + SpeedFactor*CharacterPower;
//视觉效果
PowerChangeEffect();
}


BatteryCollectorGameMode类

BatteryCollectorGameMode.h

#include "GameFramework/GameMode.h"
#include "BatteryCollectorGameMode.generated.h"

UENUM(BlueprintType)
enum class EBatteryPlayState
{
EPlaying,
EGameOver,
EWon,
EUnknown
};

UCLASS(minimalapi)
class ABatteryCollectorGameMode :public AGameMode
{
GENERATED_BODY()
public:
ABatteryCollectorGameMode();

virtual void Tick(float DeltaTime)

UFUNCTION(BlueprintPure, Category = "Power")
float GetPowerTowin() const();

virtual void BeginPlay() override;

UFUNCTION(BlueprintPure, Category = "Power")
EBatteryPlayState GetCurrentState();

void  SetCurrentState(EBatteryPlayState NewState);

protected:
//玩家角色能量值减少频率
UPROPERTY(EditDefaultOnly, BlueprintReadWrite, Category = "Power", BlueprintProtected = "true")
float DecayRate;

//玩家获胜的能量值
UPROPERTY(EditDefaultOnly, BlueprintReadWrite, Category = "Power", BlueprintProtected = "true")
float PowerToWin;

private:
EBatteryPlayState CurrentState;

TArray<class ASpawnVolume*> SpawnVolumeActors;

//改变state
void HandleNewState(EBatteryPlayState NewState);
}


BatteryCollectorGameMode.cpp

#include "BatteryCollector.h"
#include "BatteryCollectorGameMode.h"
#include "BatteryCollectorCharacter.h"
#include "Kismet/GameplayStatics.h"

ABatteryCollectorGameMode:: ABatteryCollectorGameMode()
{

DecayRate = 0.01f;
}

void ABatteryCollectorGameMode ::BeginPlay()
{
Super::BeginPlay();

//从场景内找到所有SpawnVolume类
TArray<AActors*> FoundActors;
UGameplayStatics::GetAllActorsOfClass(GetWorld(),ASpawnVolume::StaticClass(),FoundActors);

for(auto Actor :FoundActors)
{
ASpawnVolume* SpawnVolumeActor = Cast<ASpawnVolume>(Actor);
if(SpawnVolumeActor)
{
SpawnVolumeActors.AddUnique(SpawnVolumeActor);
}
}
}

SetCurrentState(EBatteryPlayState::EPlaying);

ABatteryCollectorCharacter* MyCharacter = Cast<ABatteryCollectorCharacter>(UGameplayStatics::GetPlayerPawn(this,0));
if(MyCharacter)
{
PowerToWin = MyCharacter->GetInitialPower()*1.25f;
}

void ABatteryCollectorGameMode::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);

ABatteryCollectorCharacter* MyCharacter = Cast<ABatteryCollectorCharacter>(UGameplayStatics::GetPlayerPawn(this,0));

if(MyCharacter)
{
if(MyCharacter->GetCurrentPower() > PowerToWin)
{
SetCurrentState(EBatteryPlayState::EWon);
}

else if(MyCharacter->GetPlayerPower() > 0)
{
MyCharacter->UpdatePower(-DeltaTime*DecayRate*(MyCharacter->GetInitialPower()));
}

else
{
SetCurrentState(EBatteryPlayState::EGameOver);
}
}
}

EBatteryPlayState ABatteryCollectorGameMode::GetCurrentState() const
{
return CurrentState;
}
void ABatteryCollectorGameMode::SetCurrentState(EBatteryPlayState NewState)
{
CurrentState = NewState;
HandleNewState(CurrentState);
}

//切换游戏状态
void ABatteryCollectorGameMode::HandleNewState(EBatteryPlayState NewState)
{
switch(NewState)
{
case EBatteryPlayState::EPlaying:
{
//激活spawnvolume
for(ASpawnVolume* Volume : SpawnVolumeActors)
{
Volume->SetSpawningActive(true);
}
}
break;
case EBatteryPlayState::EWon:
{
for(ASpawnVolume* Volume : SpawnVolumeActors)
{
Volume->SetSpawningActive(false);
}
//关闭player的输入接收
APlayerController* PlayerController = UGameplayStatics::GetPlayerController(this,0);
if(PlayerController)
{
PlayerController->SetCinematicMode(true,false,false,true);
}
//ragdoll ,最后玩家没电时的瘫痪效果
ACharacter* MyCharacter = UGameplayStatics::GetPlayerCharacter(this,0);
if(MyCharacter)
{
MyCharacter->GetMesh()->SetSimulatePhysics(true);
MyCharacter->GetMovementComponent->MovementState.bCanJump = false;
}
}
break;
case EBatteryPlayState::EGameOver:
{
for(ASpawnVolume* Volume : SpawnVolumeActors)
{
Volume->SetSpawningActive(false);
}
}
break;
case EBatteryPlayState::EUnknown:
{

}
break;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: