PikaGodStoneMacroLib.h
#pragma once #include "Kismet/GameplayStatics.h" #pragma region SaveSlot //关于我们自己的游戏储存 #define PIKA_CREATESAVE_SLOT( MyParameter) UGameplayStatics::CreateSaveGameObject(MyParameter) #define PIKA_SAVE_SLOT( MyParameter1,MyParameter2,MyParameter3) UGameplayStatics::SaveGameToSlot(MyParameter1,MyParameter2,MyParameter3) #define PIKA_ISSAVE_SLOT( MyParameter1, MyParameter2) UGameplayStatics::DoesSaveGameExist( MyParameter1, MyParameter2) #define PIKA_LOADGAME_SLOT( MyParameter1, MyParameter2) UGameplayStatics::LoadGameFromSlot(MyParameter1, MyParameter2) #define PIKA_DELETEGAME_SLOT( MyParameter1, MyParameter2) UGameplayStatics::DeleteGameInSlot(MyParameter1, MyParameter2) #pragma endregion SaveSlot //我们游戏存储的名字 #define PIKA_SAVE_SLOT_NAME "PikaSaveSlot" #define PIKA_SAVE_GAME_NAME "PikaSaveGame" //默认填充字体 #define PIKA_SAVE_PIKA "Pikaqiu" //FOV间隔值 #define PIKA_FOVMAX_VALUE (200.0f) #define Pika_Debug 1 //方便我们测试游戏 //定义UE4打印屏幕 #if Pika_Debug #define PIKA_UE_PRINT(MyString) if(GEngine) { GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Red, MyString); } #else #define PIKA_UE_PRINT(MyString) #endif // 0 #define PIKA_ZERO (0) #define PIKA_STANDARD_VALUE 1 //关于存储内容设定 #define Pika_SAVE_SaveBarNumber 20 //默认的条数量 //获取场景内所有Actor #define PikaGETALLACTOR(MyParameter1,MyParameter2,MyParameter3) UGameplayStatics::GetAllActorsOfClass(MyParameter1,MyParameter2,MyParameter3) //日志打印 #define PIKA_LOG(Cen) PikaLogPrintf(Cen) //播放声音 #define PIKA_SPAWN_SOUND_LOCATION(MyParameter1,MyParameter2,MyParameter3,MyParameter4,MyParameter5,MyParameter6,MyParameter7,MyParameter8) UGameplayStatics::PlaySoundAtLocation(MyParameter1,MyParameter2,MyParameter3,MyParameter4,MyParameter5,MyParameter6,MyParameter7,MyParameter8) #pragma region PikaSaveDataChannel //作为一个单数据通道使用 struct PikaFSaveSlotDataChannel { //存储游戏的区域 //------------------------------------ //PikaUIReadAndWrite循环创建PikaUISaveLoadBar时, //将循环的index存入PikaUISaveLoadBar类里的PikaSaveGameBoxNumber //点击某个PikaUISaveLoadBar类的按钮后, //通过读取PikaUISaveLoadBar类里的PikaSaveGameBoxNumber属性就能得到PikaCurrentSaveGameBoxNumber的值 int32 PikaCurrentSaveGameBoxNumber; //存储游戏的编号 //------------------------------------ //在空的存档上新建存档时,在PikaUIReadAndWrite::PikaSaveArchiveSlot的新建逻辑里, //通过PikaGetGameInstance()->PikaGetCurrentSaveArchiveNumber获取已有存档的数量, //并用该数量来进行设置PikaCurrentGameArchiveNumber //------------------------------------ //在已有的存档上进行覆盖存档时,由PikaUIReadAndWrite::PikaReadArchive读取的本地存档, //并将PikaCurrentGameArchiveNumber的值保存在PikaUISaveLoadBar里的PikaGameArchiveNumber属性里 //点击某个PikaUISaveLoadBar类的按钮后, //通过读取PikaUISaveLoadBar类里的PikaGameArchiveNumber属性就能得到PikaCurrentGameArchiveNumber的值 int32 PikaCurrentGameArchiveNumber; //构造赋值 PikaFSaveSlotDataChannel(int32 SaveGameBoxNumber) { PikaCurrentSaveGameBoxNumber = SaveGameBoxNumber; PikaCurrentGameArchiveNumber = INDEX_NONE; } PikaFSaveSlotDataChannel(int32 SaveGameBoxNumber, int32 GameArchiveNumber) { PikaCurrentSaveGameBoxNumber = SaveGameBoxNumber; PikaCurrentGameArchiveNumber = GameArchiveNumber; } }; #pragma endregion PikaSaveDataChannel
PikaGodStone.Build.cs
// Fill out your copyright notice in the Description page of Project Settings. using UnrealBuildTool; public class PikaGodStone : ModuleRules { public PikaGodStone(ReadOnlyTargetRules Target) : base(Target) { PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" , "UMG" , "MoviePlayer" }); PrivateDependencyModuleNames.AddRange(new string[] { }); // Uncomment if you are using Slate UI PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); // Uncomment if you are using online features // PrivateDependencyModuleNames.Add("OnlineSubsystem"); // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true } }
PikaGodStone.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaGodStoneMacroLib.h"
PikaGodStone.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "PikaGodStone.h" #include "Modules/ModuleManager.h" IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, PikaGodStone, "PikaGodStone" );
PikaGodStoneGameModeBase.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/GameModeBase.h" #include "PikaGodStoneGameModeBase.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API APikaGodStoneGameModeBase : public AGameModeBase { GENERATED_BODY() public: APikaGodStoneGameModeBase(); virtual void BeginPlay()override; };
PikaGodStoneGameModeBase.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "PikaGodStoneGameModeBase.h" #include "Public/PikaGodStoneGameStateBase.h" #include "Public/PikaGodStonePlayerController.h" #include "Public/PikaGodStoneCamera.h" #include "Public/PikaGodStonePlayerState.h" #include "Public/PikaHUDBase.h" #include "Public/PikaGameUserSettings.h" APikaGodStoneGameModeBase::APikaGodStoneGameModeBase() { //加载GameState GameStateClass = APikaGodStoneGameStateBase::StaticClass(); //加载Controller PlayerControllerClass = APikaGodStonePlayerController::StaticClass(); //加载ContorllerPawn DefaultPawnClass = APikaGodStoneCamera::StaticClass(); //加载PlayerState PlayerStateClass = APikaGodStonePlayerState::StaticClass(); //加载HUD HUDClass = APikaHUDBase::StaticClass(); } void APikaGodStoneGameModeBase::BeginPlay() { Super::BeginPlay(); //设置PikaGameUserSettings的UWorld if (UPikaGameUserSettings::PikaGetGameUserSettings()) { UPikaGameUserSettings::PikaGetGameUserSettings()->PikaSetretrieveWorldContext(GetWorld()); } }
PikaAITargetPoint.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Engine/TargetPoint.h" #include "PikaAITargetPoint.generated.h" /** * */ UCLASS(Blueprintable) class PIKAGODSTONE_API APikaAITargetPoint : public ATargetPoint { GENERATED_BODY() //生成怪物时的特效 UPROPERTY(EditDefaultsOnly, Category = "PikaTargetPoint") TArray<UParticleSystem*> PikaSPawnCharacterParticleArray; public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PikaTargetPoint") bool PikaTeam; protected: virtual void BeginPlay() override; public: APikaAITargetPoint(); FORCEINLINE bool PikaGetTeam() { return PikaTeam; } };
PikaAITargetPoint.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaAITargetPoint.h" #include "Kismet/GameplayStatics.h" void APikaAITargetPoint::BeginPlay() { Super::BeginPlay(); if (GetWorld()) { if (!PikaTeam) { //特效的总数 int32 PikaIndex_ParNumber = PikaSPawnCharacterParticleArray.Num(); //特效的随机数 int32 PikaRandomIndex = FMath::RandRange(0, PikaIndex_ParNumber - 1); //特效生成 if (PikaSPawnCharacterParticleArray.IsValidIndex(PikaRandomIndex)) UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), PikaSPawnCharacterParticleArray[PikaRandomIndex], GetActorLocation(), GetActorRotation()); } } } APikaAITargetPoint::APikaAITargetPoint() { PikaTeam = false; }
PikaAllowBuildTrigger.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 "PikaAllowBuildTrigger.generated.h" UCLASS() class PIKAGODSTONE_API APikaAllowBuildTrigger : public AActor { GENERATED_BODY() //碰撞组件 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBox", meta = (AllowPrivateAccess = "true")) UBoxComponent * PikaBox; UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBox", meta = (AllowPrivateAccess = "true")) USceneComponent * PikaRoot; public: // Sets default values for this actor's properties APikaAllowBuildTrigger(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: // Called every frame virtual void Tick(float DeltaTime) override; };
PikaAllowBuildTrigger.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaAllowBuildTrigger.h" // Sets default values APikaAllowBuildTrigger::APikaAllowBuildTrigger() { // 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; PikaBox = CreateDefaultSubobject<UBoxComponent>(TEXT("PikaBox")); PikaRoot = CreateDefaultSubobject<USceneComponent>(TEXT("PikaRoot")); RootComponent = PikaRoot; //绑定 PikaBox->SetupAttachment(PikaRoot); PikaBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Block); } // Called when the game starts or when spawned void APikaAllowBuildTrigger::BeginPlay() { Super::BeginPlay(); } // Called every frame void APikaAllowBuildTrigger::Tick(float DeltaTime) { Super::Tick(DeltaTime); }
PikaAttackInterface.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaAttackInterface.generated.h" // This class does not need to be modified. UINTERFACE(MinimalAPI) class UPikaAttackInterface : public UInterface { GENERATED_BODY() }; /** * */ class PIKAGODSTONE_API IPikaAttackInterface { GENERATED_BODY() // Add interface functions to this class. This is the class that will be inherited to implement this interface. public: //攻击 virtual void PikaAttackTarget(AActor * Target) {} //持续性攻击接口 virtual void PikaAttackTick() {} //接受对方的伤害 //virtual float PikaGetDefenceDamage(AActor * OtherActor); //同伴升级的值传递 virtual void PikaUpdateLevelCharacterArray(TArray<AActor*> MyActor) {}; };
PikaAttackInterface.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaAttackInterface.h" // Add default functionality here for any IPikaAttackInterface functions that are not pure virtual.
PikaBTTask_RandomWalk.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "BehaviorTree/Tasks/BTTask_BlackboardBase.h" #include "PikaBTTask_RandomWalk.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaBTTask_RandomWalk : public UBTTask_BlackboardBase { GENERATED_BODY() public: virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; public: /** Notify called after GameplayTask finishes initialization (not active yet) */ virtual void OnGameplayTaskInitialized(UGameplayTask& Task) {} /** Notify called after GameplayTask changes state to Active (initial activation or resuming) */ virtual void OnGameplayTaskActivated(UGameplayTask& Task) {} /** Notify called after GameplayTask changes state from Active (finishing or pausing) */ virtual void OnGameplayTaskDeactivated(UGameplayTask& Task) {} };
PikaBTTask_RandomWalk.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "PikaBTTask_RandomWalk.h" #include "Public/PikaMonsterAIController.h" #include "BehaviorTree/BlackboardComponent.h" #include "BehaviorTree/Blackboard/BlackboardKeyType_Vector.h" EBTNodeResult::Type UPikaBTTask_RandomWalk::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { Super::ExecuteTask(OwnerComp , NodeMemory); APikaMonsterAIController * PikaMyAIController = Cast<APikaMonsterAIController>(OwnerComp.GetOwner()); UBlackboardComponent * PikaMyBlackBoard = (UBlackboardComponent *)OwnerComp.GetBlackboardComponent(); if (PikaMyAIController == NULL) { return EBTNodeResult::Failed; } else { //获取随机点 FVector PikaRandomPoint = PikaMyAIController->PikaGetRandomLoaction(); //将随机点传出去 if (BlackboardKey.SelectedKeyType == UBlackboardKeyType_Vector::StaticClass()) { //BlackboardKey.SelectedKeyName表示在行为树的蓝图中,手动选择的变量 PikaMyBlackBoard->SetValueAsVector(BlackboardKey.SelectedKeyName , PikaRandomPoint); } return EBTNodeResult::Succeeded; } return EBTNodeResult::Failed; }
PikaBTTaskAttackTarget.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "BehaviorTree/BTTaskNode.h" #include "PikaBTTaskAttackTarget.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaBTTaskAttackTarget : public UBTTaskNode { GENERATED_BODY() public: virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; virtual void InitializeFromAsset(UBehaviorTree & Asset) override; //加载敌对目标 UPROPERTY(EditAnywhere, Category = "PikaBlackboard") struct FBlackboardKeySelector PikaBlackboardActor; //敌对目标在行为树的黑板中的变量名,在蓝图中设置 UPROPERTY(EditAnywhere, Category = "PikaBlackboard") FName PikaActorKeyName; public: /** Notify called after GameplayTask finishes initialization (not active yet) */ virtual void OnGameplayTaskInitialized(UGameplayTask& Task) {} /** Notify called after GameplayTask changes state to Active (initial activation or resuming) */ virtual void OnGameplayTaskActivated(UGameplayTask& Task) {} /** Notify called after GameplayTask changes state from Active (finishing or pausing) */ virtual void OnGameplayTaskDeactivated(UGameplayTask& Task) {} };
PikaBTTaskAttackTarget.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "PikaBTTaskAttackTarget.h" #include "Public/PikaMonsterAIController.h" #include "BehaviorTree/BlackboardComponent.h" #include "BehaviorTree/Blackboard/BlackboardKeyType_Object.h" #include "Public/PikaCharacterBase.h" //PikaBlackboardActor调用前需要先初始化 EBTNodeResult::Type UPikaBTTaskAttackTarget::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { Super::ExecuteTask(OwnerComp, NodeMemory); APikaMonsterAIController * PikaMyAIController = Cast<APikaMonsterAIController>(OwnerComp.GetOwner()); UBlackboardComponent * PikaMyBlackBoard = (UBlackboardComponent *)OwnerComp.GetBlackboardComponent(); if (PikaMyAIController == NULL) { return EBTNodeResult::Failed; } else { if (PikaBlackboardActor.SelectedKeyType == UBlackboardKeyType_Object::StaticClass()) { UObject * PikaTowerObject = PikaMyBlackBoard->GetValueAsObject(PikaActorKeyName); if (PikaTowerObject) { AActor * PikaTargetTower = (AActor *)PikaTowerObject; APikaCharacterBase * PikaMyPawn = Cast<APikaCharacterBase>(PikaMyAIController->GetPawn()); if (PikaTargetTower && PikaMyPawn) { PikaMyPawn->PikaAttackTarget(PikaTargetTower); return EBTNodeResult::Succeeded; } } } } return EBTNodeResult::Failed; } //初始化PikaBlackboardActor void UPikaBTTaskAttackTarget::InitializeFromAsset(UBehaviorTree & Asset) { Super::InitializeFromAsset(Asset); UBlackboardData * PikaBlackboardAsset = GetBlackboardAsset(); if (PikaBlackboardAsset) { PikaBlackboardActor.ResolveSelectedKey(*PikaBlackboardAsset); } else { UE_LOG(LogBehaviorTree, Warning, TEXT("Pika Can'Initialize task:%s"), *GetName()); } }
PikaBTTaskMoveToTarget.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "BehaviorTree/BTTaskNode.h" #include "PikaBTTaskMoveToTarget.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaBTTaskMoveToTarget : public UBTTaskNode { GENERATED_BODY() public: UPikaBTTaskMoveToTarget(); virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override; virtual void InitializeFromAsset(UBehaviorTree & Asset) override; //加载敌对目标 UPROPERTY(EditAnywhere, Category = "PikaBlackboard") struct FBlackboardKeySelector PikaBlackboardActor; //接触半径 UPROPERTY(EditAnywhere, Category = "PikaBlackboard") float PikaAcceptanceRadius; //敌对目标在行为树的黑板中的变量名,在蓝图中设置 UPROPERTY(EditAnywhere, Category = "PikaBlackboard") FName PikaActorKeyName; //打印测试 void PikaPrint(FString piksStr); public: /** Notify called after GameplayTask finishes initialization (not active yet) */ virtual void OnGameplayTaskInitialized(UGameplayTask& Task) {} /** Notify called after GameplayTask changes state to Active (initial activation or resuming) */ virtual void OnGameplayTaskActivated(UGameplayTask& Task) {} /** Notify called after GameplayTask changes state from Active (finishing or pausing) */ virtual void OnGameplayTaskDeactivated(UGameplayTask& Task) {} };
PikaBTTaskMoveToTarget.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "PikaBTTaskMoveToTarget.h" #include "Public/PikaMonsterAIController.h" #include "BehaviorTree/BlackboardComponent.h" #include "BehaviorTree/Blackboard/BlackboardKeyType_Object.h" UPikaBTTaskMoveToTarget::UPikaBTTaskMoveToTarget() { PikaAcceptanceRadius = 800.f; } //PikaBlackboardActor调用前需要先初始化 EBTNodeResult::Type UPikaBTTaskMoveToTarget::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) { Super::ExecuteTask(OwnerComp, NodeMemory); APikaMonsterAIController * PikaMyAIController = Cast<APikaMonsterAIController>(OwnerComp.GetOwner()); UBlackboardComponent * PikaMyBlackBoard = (UBlackboardComponent *)OwnerComp.GetBlackboardComponent(); if (PikaMyAIController == NULL) { return EBTNodeResult::Failed; } else { if (PikaBlackboardActor.SelectedKeyType == UBlackboardKeyType_Object::StaticClass()) { UObject * PikaTowerObject = PikaMyBlackBoard->GetValueAsObject(PikaActorKeyName); if (PikaTowerObject) { AActor * PikaTargetTower = (AActor *)PikaTowerObject; if (PikaTargetTower) { //PikaPrint("PikaMove"); /*FVector PikaTest = PikaTargetTower->GetActorLocation(); PikaPrint(FString::SanitizeFloat(PikaTest.X)); PikaPrint("x"); PikaPrint(FString::SanitizeFloat(PikaTest.Y)); PikaPrint("y"); PikaPrint(FString::SanitizeFloat(PikaTest.Z)); PikaPrint("z");*/ PikaMyAIController->MoveToLocation(PikaTargetTower->GetActorLocation() , PikaAcceptanceRadius); return EBTNodeResult::Succeeded; } } } } return EBTNodeResult::Failed; } //初始化PikaBlackboardActor void UPikaBTTaskMoveToTarget::InitializeFromAsset(UBehaviorTree & Asset) { Super::InitializeFromAsset(Asset); UBlackboardData * PikaBlackboardAsset = GetBlackboardAsset(); if (PikaBlackboardAsset) { PikaBlackboardActor.ResolveSelectedKey(*PikaBlackboardAsset); } else { UE_LOG(LogBehaviorTree, Warning, TEXT("Pika Can'Initialize task:%s"), *GetName()); } } void UPikaBTTaskMoveToTarget::PikaPrint(FString piksStr) { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 6.0f, FColor::Red, piksStr); } }
PikaBulletBase.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "Particles/ParticleSystemComponent.h" #include "Components/BoxComponent.h" #include "GameFramework/ProjectileMovementComponent.h" #include "Components/SphereComponent.h" #include "Components/TimelineComponent.h" #include "PikaBulletBase.generated.h" class APikaGodStonePlayerController; UENUM() namespace PikaBulletType { enum Type { PikaBULLET_Track,//跟踪子弹 PikaBULLET_Line,//直线飞行子弹 PikaBULLET_Range,//范围攻击型子弹 PikaBULLET_Chain,//闪电型攻击 PikaBULLET_MAX }; } UCLASS() class PIKAGODSTONE_API APikaBulletBase : public AActor { GENERATED_BODY() //载入显示的粒子(子弹飞行中特效) UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBulletBase", meta = (AllowPrivateAccess = "true")) class UParticleSystemComponent * PikaParticleMesh; //碰撞盒子 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBulletBase", meta = (AllowPrivateAccess = "true")) //class UBoxComponent * PikaBoxDamage; class USphereComponent * PikaBoxDamage; //根组件 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBulletBase", meta = (AllowPrivateAccess = "true")) class USceneComponent * PikaRootBullet; //具有移动属性的组件 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBulletBase", meta = (AllowPrivateAccess = "true")) class UProjectileMovementComponent * PikaProjectileMovement; //子弹的施法者 AActor * PikaCasterCharacter; UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") TSubclassOf<AActor> PikaDamageValueActor; //开火的声音 UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") TArray <USoundBase*> PikaOpenFireSound; public: // Sets default values for this actor's properties APikaBulletBase(); //蓝图中可以设置的子弹类型 UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") TEnumAsByte<PikaBulletType::Type> PikaBulletTypeBP; //蓝图中设置的子弹伤害特效 UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") UParticleSystem * PikaDamageParticle; //蓝图中设置的子弹开火特效 UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") UParticleSystem * PikaOpenFireParticle; //定时销毁子弹 float PikaDestoryTime; FTimerHandle PikaDestoryBulletTimeHandle; void PikaDestoryBullet(); //范围攻击,该曲线由蓝图载入 UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") UCurveFloat * PikaCurveFloat; UPROPERTY() FTimeline PikaRangeAttackTimeLine; UFUNCTION() void PikaTimeLineRangeAttack(float PikaValue); //范围攻击球体的半径 UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") float PikaBoxDamageTargetRadius; //攻击特效 UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") UParticleSystem * PikaRangeAttackType; UPROPERTY() TArray<ACharacter*> PikaTargetRangeArr; UFUNCTION() void PikaTimeLineFinished(); 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 PikaBeginOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult); void PikaPrint(FString PikaStr); //获取子弹的粒子特效 FORCEINLINE UParticleSystemComponent * GetParticleMesh() {return PikaParticleMesh;} //具有移动跟踪属性的子弹 FORCEINLINE UProjectileMovementComponent * GetProjectleMovment() { return PikaProjectileMovement; } //设置子弹的发射者 void PikaSetCasterCharacter(AActor * MyCharacter) { PikaCasterCharacter = MyCharacter; } FORCEINLINE class APikaGodStonePlayerController* PikaGetPlayerController(); };
PikaBulletBase.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaBulletBase.h" #include "Public/PikaTowers.h" #include "Kismet/GameplayStatics.h" #include "Public/PikaDamageValueText.h" // Sets default values APikaBulletBase::APikaBulletBase() { // 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; PikaParticleMesh = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("PikaBulletParticleMesh")); //PikaBoxDamage = CreateDefaultSubobject<UBoxComponent>(TEXT("PikaBoxDamage")); PikaBoxDamage = CreateDefaultSubobject<USphereComponent>(TEXT("PikaBoxDamage")); PikaRootBullet = CreateDefaultSubobject<USceneComponent>(TEXT("PikaRootBullet")); PikaProjectileMovement = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("PikaProjectileMovement")); RootComponent = PikaRootBullet; PikaBoxDamage->AttachToComponent(PikaRootBullet , FAttachmentTransformRules::KeepRelativeTransform); PikaParticleMesh->AttachToComponent(PikaBoxDamage , FAttachmentTransformRules::KeepRelativeTransform); //速度初始化 PikaProjectileMovement->InitialSpeed = 800.f; PikaProjectileMovement->MaxSpeed = 2000.f; PikaProjectileMovement->UpdatedComponent = PikaBoxDamage; switch (PikaBulletTypeBP) { case PikaBulletType::PikaBULLET_Track://跟踪子弹 PikaProjectileMovement->bIsHomingProjectile = true; PikaProjectileMovement->bRotationFollowsVelocity = true; break; case PikaBulletType::PikaBULLET_Line://直线飞行子弹 //取消重力模拟 PikaProjectileMovement->ProjectileGravityScale = 0.f; PikaProjectileMovement->InitialSpeed = 1200.f; break; case PikaBulletType::PikaBULLET_Range://范围攻击型子弹 PikaProjectileMovement->InitialSpeed = 0; break; case PikaBulletType::PikaBULLET_Chain://闪电型攻击 //取消重力模拟 PikaProjectileMovement->ProjectileGravityScale = 0.f; //初速度 PikaProjectileMovement->InitialSpeed = 0.f; //取消碰撞 PikaBoxDamage->SetCollisionEnabled(ECollisionEnabled::NoCollision); break; default: break; } //定时销毁子弹的时间 PikaDestoryTime = 6.5f; } void APikaBulletBase::PikaDestoryBullet() { if (PikaDestoryBulletTimeHandle.IsValid() && GetWorld()) { GetWorld()->GetTimerManager().ClearTimer(PikaDestoryBulletTimeHandle); Destroy(true); } } void APikaBulletBase::PikaTimeLineRangeAttack(float PikaValue) { float PikaBoxDamageCurentRadius = FMath::Lerp(PikaBoxDamage->GetScaledSphereRadius() , PikaBoxDamageTargetRadius , PikaValue); PikaBoxDamage->SetSphereRadius(PikaBoxDamageCurentRadius); } //TimeLine结束时触发的事件 void APikaBulletBase::PikaTimeLineFinished() { /*for (ACharacter * PikaMyCharacter:PikaTargetRangeArr) { APikaCharacterBase * PikaChar = Cast<APikaCharacterBase>(PikaMyCharacter); APikaCharacterBase * PikaCasterActor = Cast<APikaCharacterBase>(PikaCasterCharacter); if (PikaChar && PikaRangeAttackType && PikaCasterCharacter) { FVector PikaMyDistance = PikaChar->GetActorLocation() - PikaCasterActor->GetActorLocation(); if (PikaChar->PikaIsActive() && PikaMyDistance.Size()<1000) { //产生伤害,获取状态 PikaChar->PikaGetCharacterState(PikaChar->PikaGetDefenceDamage(PikaCasterActor)); //更新血条栏 PikaChar->PikaUpdateUMGHealth(); //攻击特效 UParticleSystemComponent * PikaParticleBullet = UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), PikaRangeAttackType, PikaCasterActor->GetSpawnPoint()->GetComponentLocation()); if (PikaParticleBullet) { PikaParticleBullet->SetBeamSourcePoint(0 , PikaCasterActor->GetHomingPoint()->GetComponentLocation(), 0); PikaParticleBullet->SetBeamTargetPoint(0 , PikaChar->GetHomingPoint()->GetComponentLocation(), 0); } } else { PikaTargetRangeArr.Remove(PikaChar); } } }*/ } // Called when the game starts or when spawned void APikaBulletBase::BeginPlay() { Super::BeginPlay(); //碰撞绑定 if (PikaBoxDamage) { PikaBoxDamage->OnComponentBeginOverlap.AddUniqueDynamic(this, &APikaBulletBase::PikaBeginOverlapping); } if (GetWorld()) { //开始执行销毁 GetWorld()->GetTimerManager().SetTimer(PikaDestoryBulletTimeHandle , this , &APikaBulletBase::PikaDestoryBullet , PikaDestoryTime); //生成开火特效 if (PikaOpenFireParticle) { UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), PikaOpenFireParticle, GetActorLocation()); } //曲线存在,通过代理绑定处理函数 if (PikaCurveFloat && PikaBulletTypeBP == PikaBulletType::PikaBULLET_Range) { FOnTimelineFloat PikaTimeLineDelegate; FOnTimelineEvent PikaFinishedEvent; PikaFinishedEvent.BindUFunction(this, FName("PikaTimeLineFinished")); PikaTimeLineDelegate.BindUFunction(this, FName("PikaTimeLineRangeAttack")); //添加曲线 PikaRangeAttackTimeLine.AddInterpFloat(PikaCurveFloat, PikaTimeLineDelegate); //设置停止循环 PikaRangeAttackTimeLine.SetLooping(false); //开始播放 PikaRangeAttackTimeLine.PlayFromStart(); //TimeLine结束时触发的事件 PikaRangeAttackTimeLine.SetTimelineFinishedFunc(PikaFinishedEvent); } } //播放开火声音 if (PikaGetPlayerController()) PikaGetPlayerController()->PikaPlaySoundAtVetor(PikaOpenFireSound, GetActorLocation(), PikaETowerDefenceSoundType::SOUND_EFFECT_SOUND); } // Called every frame void APikaBulletBase::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (PikaBulletTypeBP == PikaBulletType::PikaBULLET_Range) { PikaRangeAttackTimeLine.TickTimeline(DeltaTime); } } /* * OverlappedComponent:本类哪个组件触发的碰撞 * OtherActor:和本类触发碰撞的Actor * OtherComp:和本类触发碰撞的Actor的组件 */ void APikaBulletBase::PikaBeginOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult) { if (!PikaCasterCharacter) { return; } APikaCharacterBase * PikaEnemyCharacter = Cast<APikaCharacterBase>(OtherActor); APikaCharacterBase * PikaCasterActor = Cast<APikaCharacterBase>(PikaCasterCharacter); if (!OtherActor || !PikaEnemyCharacter || !PikaCasterActor) { return; } //判断是否为同一个队伍 if (PikaCasterActor->PikaCharDataPre->PikaCharBaseData.PikaTeam != PikaEnemyCharacter->PikaCharDataPre->PikaCharBaseData.PikaTeam) { if (PikaEnemyCharacter->PikaIsActive() && PikaBulletTypeBP != PikaBulletType::PikaBULLET_Chain && PikaDamageParticle && GetWorld()) { UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), PikaDamageParticle, SweepResult.Location); PikaParticleMesh->SetActive(false); PikaBoxDamage->SetCollisionEnabled(ECollisionEnabled::NoCollision); /*if (PikaBulletTypeBP == PikaBulletType::PikaBULLET_Range) { PikaTargetRangeArr.AddUnique(PikaEnemyCharacter); return; }*/ //产生伤害,获取状态 float PikaDamageValue = PikaEnemyCharacter->PikaGetDefenceDamage(PikaCasterActor); PikaEnemyCharacter->PikaGetCharacterState(PikaDamageValue); //更新血条栏 PikaEnemyCharacter->PikaUpdateUMGHealth(); //停止移动组件 PikaProjectileMovement->StopMovementImmediately(); //被子弹打中后,损失的生命数值的显示 if (PikaDamageValue > 0 && PikaDamageValueActor) { APikaDamageValueText * PikaValueText = GetWorld()->SpawnActor<APikaDamageValueText>(PikaDamageValueActor, PikaEnemyCharacter->GetActorLocation(), FRotator::ZeroRotator); if (PikaValueText) PikaValueText->PikaDrawDamage(PikaDamageValue , 1.f); } } } } void APikaBulletBase::PikaPrint(FString PikaStr) { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 6.f, FColor::Red, PikaStr); } } FORCEINLINE class APikaGodStonePlayerController* APikaBulletBase::PikaGetPlayerController() { return GetWorld() ? ((APikaGodStonePlayerController*)GetWorld()->GetFirstPlayerController()) : NULL; }
PikaCharacterBase.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "PikaCharacterData.h" #include "WidgetComponent.h" #include "PikaAttackInterface.h" #include "PikaBulletBase.h" #include "Components/ArrowComponent.h" #include "PikaGameResource.h" #include "Sound/SoundBase.h" #include "PikaCharacterBase.generated.h" class APikaGodStonePlayerController; UCLASS() class PIKAGODSTONE_API APikaCharacterBase : public ACharacter , public IPikaAttackInterface { GENERATED_BODY() //跟踪点 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBaseAttribute", meta = (AllowPrivateAccess = "true")) class USceneComponent * PikaHomingPoint; //血条显示 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBaseAttribute", meta = (AllowPrivateAccess = "true")) class UWidgetComponent * PikaShowUMG; //属性显示 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBaseAttribute", meta = (AllowPrivateAccess = "true")) class UWidgetComponent * PikaShowAttribute; //开火点 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBaseAttribute", meta = (AllowPrivateAccess = "true")) class UArrowComponent * PikaOpenFirePoint; //载入显示的粒子(子弹飞行中特效) UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBulletBase", meta = (AllowPrivateAccess = "true")) class UParticleSystemComponent * PikaParticleMesh; //捕捉射线,用来显示角色信息 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBulletBase", meta = (AllowPrivateAccess = "true")) class UBoxComponent * PikaTraceShowCharacterInfo; //受到攻击的声音 UPROPERTY(EditDefaultsOnly, Category = "PikaBulletBase") TArray<USoundBase*> PikaHitSound; int32 PikaCharacterSpawnID; public: //实始化角色信息 void PikaInitCharacterInformation(); // Sets default values for this character's properties APikaCharacterBase(); //创建一个指向角色数据类的指针 UPROPERTY() UPikaCharacterData * PikaCharDataPre; //加载子弹,该子弹实例从蓝图中手动指定 UPROPERTY(EditDefaultsOnly , Category = "PikaBullet") TSubclassOf<APikaBulletBase> PikaCharacterBullet; UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") TSubclassOf<AActor> PikaDeathRangeCharacter; //攻击目标 UPROPERTY() AActor * PikaEnemyTarget; //角色死亡后,该范围内的敌人角色升级 UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") float PikaUpdateLevelRange; /********蒙太奇start********/ //游戏开始蒙太奇 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "PikaMontage") UAnimMontage* PikaGameBeignPlayMontage; //攻击蒙太奇 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "PikaMontage") TArray<UAnimMontage*> PikaCharacterAttackSkillMontage; //死亡蒙太奇 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "PikaMontage") TArray<UAnimMontage*> PikaCharacterDeathMontage; //角色蒙太奇播放 void PikaCharacterMontage_Play(TArray<UAnimMontage*> CharacterMontageArray); //开始播放动画 void PikaPlayAnimationForBegin(bool IsSaveCharater = false); //蒙太奇开始播放通知蓝图 UFUNCTION(BlueprintImplementableEvent) void PikaBlueprintMontageBegin(UAnimMontage* Montage); //蒙太奇结束播放通知蓝图 UFUNCTION(BlueprintImplementableEvent) void PikaBlueprintMontageEnd(UAnimMontage* Montage, bool bInterrupted); //如果是读取文件则执行该函数 UFUNCTION(BlueprintImplementableEvent) void PikaEventSaveGameEnd(); protected: UFUNCTION() void PikaMontageBegin(UAnimMontage* Montage); UFUNCTION() void PikaMontageEnd(UAnimMontage* Montage, bool bInterrupted); /********蒙太奇end********/ protected: // Called when the game starts or when spawned virtual void BeginPlay() override; //获取游戏的控制 FORCEINLINE APikaGodStonePlayerController* PikaGetPlayerController() { return GetWorld() ? ((APikaGodStonePlayerController*)GetWorld()->GetFirstPlayerController()) : NULL; } public: // Called every frame virtual void Tick(float DeltaTime) override; // Called to bind functionality to input virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; void PikaPrint(FString PikaStr); //获取当前等级 FORCEINLINE int32 PikaGetCharacterLevel()const { return PikaCharDataPre != NULL ? PikaCharDataPre->PikaCharBaseData.PikaCharacterLevel : INDEX_NONE; } //获取开火点和跟踪点 FORCEINLINE UArrowComponent * GetSpawnPoint() {return PikaOpenFirePoint; } FORCEINLINE USceneComponent * GetHomingPoint() { return PikaHomingPoint; } //获取特效 FORCEINLINE UParticleSystemComponent * GetParticleMesh() { return PikaParticleMesh; } //获取角色的生命百分比 float PikaGetHealthPercentage(); //接受对方的伤害 float PikaGetDefenceDamage(AActor * OtherActor); //更新血条栏 void PikaUpdateUMGHealth(); //获取角色死亡状态 bool PikaGetCharacterState(float Damage); //是否存活 UFUNCTION(BlueprintPure , Category = "PikaAnim") bool PikaIsActive(); //是否死亡 UFUNCTION(BlueprintPure, Category = "PikaAnim") bool PikaIsDeathBP(); //延时销毁时间句柄 FTimerHandle PikaDestoryActorHandle; //销毁角色 virtual void PikaDestoryCharacter(float DelayTime = 0); //延时销毁角色 void PikaDelayDestoryCharacter(); //队伍判断 bool PikaGetTeam(); //判断是不是一个队伍 bool PikaIsTeam(); //是否升级 void PikaIsUpdateLevel(float Exp); //同伴升级的值传递 virtual void PikaUpdateLevelCharacterArray(TArray<AActor*> MyActor) override; //是否显示角色信息 void PikaCharacterAttributeDisplay(bool IsDisplay); //记录世界生成角色的ID int32 PikaGetCharacterSpawnID() const { return PikaCharacterSpawnID; } //记录世界生成角色的ID void PikaSetCharacterSpawnID(int32 NewSpawnID) { PikaCharacterSpawnID = NewSpawnID; } UPROPERTY() UPikaGameResource* PikaTest2112; };
PikaCharacterBase.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaCharacterBase.h" #include "Public/PikaUIHealthShow.h" #include "Engine/Engine.h" #include "Public/PikaToolRangeOfCharacter.h" #include "Public/PikaUICharacterAttribute.h" #include "EngineUtils.h" void APikaCharacterBase::PikaInitCharacterInformation() { //更新角色信息 UUserWidget* PikaTest = PikaShowAttribute->GetUserWidgetObject(); if (PikaCharDataPre && PikaShowAttribute->GetUserWidgetObject()) { UPikaUICharacterAttribute* PikaNewCharacterAttribute = Cast<UPikaUICharacterAttribute>(PikaShowAttribute->GetUserWidgetObject()); UPikaUIHealthShow * PikaHealthShow = Cast<UPikaUIHealthShow>(PikaShowUMG->GetUserWidgetObject()); //面板信息变化 if (PikaNewCharacterAttribute) { //注册 PikaNewCharacterAttribute->PikaSetGameCharacterData(PikaCharDataPre); PikaNewCharacterAttribute->PikaDrawUIToScreen(); //更新面板 PikaNewCharacterAttribute->PikaUpdataAll(); } //血条变化 if (PikaHealthShow) { PikaHealthShow->PikaSetGameCharacterData(PikaCharDataPre); PikaHealthShow->PikaDrawUIToScreen(); PikaHealthShow->PikaUpdateCharacterInformation(); } } } // Sets default values APikaCharacterBase::APikaCharacterBase() { // 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; PikaHomingPoint = CreateDefaultSubobject<USceneComponent>(TEXT("PikaHomingPoint")); PikaShowUMG = CreateDefaultSubobject<UWidgetComponent>(TEXT("PikaShowUMG")); PikaShowAttribute = CreateDefaultSubobject<UWidgetComponent>(TEXT("PikaShowAttribute")); PikaOpenFirePoint = CreateDefaultSubobject<UArrowComponent>(TEXT("PikaOpenFirePoint")); PikaParticleMesh = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("PikaParticleMesh")); PikaTraceShowCharacterInfo = CreateDefaultSubobject<UBoxComponent>(TEXT("PikaTraceShowCharacterInfoComponent")); //绑定 PikaOpenFirePoint->AttachToComponent(RootComponent , FAttachmentTransformRules::KeepRelativeTransform); PikaShowAttribute->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform); PikaShowUMG->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform); PikaHomingPoint->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform); PikaParticleMesh->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform); PikaTraceShowCharacterInfo->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform); //设置预设通道 PikaTraceShowCharacterInfo->SetCollisionProfileName("PikaScaning"); PikaTraceShowCharacterInfo->SetBoxExtent(FVector(50 , 50 , 100)); PikaCharacterSpawnID = -1; PikaUpdateLevelRange = 1200.f; } void APikaCharacterBase::PikaCharacterMontage_Play(TArray<UAnimMontage*> CharacterMontageArray) { if (GetMesh() && GetMesh()->SkeletalMesh && GetMesh()->GetAnimInstance()) { if (CharacterMontageArray.Num() > 0) { int32 PikaIndexM = FMath::RandRange(0, (CharacterMontageArray.Num() - 1)); GetMesh()->GetAnimInstance()->Montage_Play(CharacterMontageArray[PikaIndexM]); } } } void APikaCharacterBase::PikaPlayAnimationForBegin(bool IsSaveCharater /*= false*/) { //动画 if (GetMesh() && GetMesh()->SkeletalMesh && GetMesh()->GetAnimInstance()) { //对蒙太奇进行记录绑定 GetMesh()->GetAnimInstance()->OnMontageStarted.AddDynamic(this, &APikaCharacterBase::PikaMontageBegin); GetMesh()->GetAnimInstance()->OnMontageEnded.AddDynamic(this, &APikaCharacterBase::PikaMontageEnd); //播放起始蒙太奇(如果该数据是存储中导入不需要执行起始蒙太奇) if (!IsSaveCharater) { if (PikaGameBeignPlayMontage) GetMesh()->GetAnimInstance()->Montage_Play(PikaGameBeignPlayMontage); } else { //执行蓝图内容 //EventSaveGameEnd(); } } } void APikaCharacterBase::PikaMontageBegin(UAnimMontage* Montage) { PikaBlueprintMontageBegin(Montage); } void APikaCharacterBase::PikaMontageEnd(UAnimMontage* Montage, bool bInterrupted) { PikaBlueprintMontageEnd(Montage, bInterrupted); } // Called when the game starts or when spawned void APikaCharacterBase::BeginPlay() { Super::BeginPlay(); //默认状态下隐藏角色信息 if(PikaShowAttribute && PikaShowAttribute->GetUserWidgetObject()) PikaShowAttribute->GetUserWidgetObject()->SetVisibility(ESlateVisibility::Hidden); //生成角色需要生成一个默认的控制 if (!GetController()) { SpawnDefaultController(); } //为角色数据分配位置 TSubclassOf<UPikaCharacterData> PikaSubclassOfChartData = UPikaCharacterData::StaticClass(); if (GetWorld() && PikaSubclassOfChartData) PikaCharDataPre = NewObject<UPikaCharacterData>(GetWorld(), PikaSubclassOfChartData); } // Called every frame void APikaCharacterBase::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (!PikaGetPlayerController() && !PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon) return; //上传我们的数据,如果角色有速度变化时,更新角色在地图中的坐标 //GetVelocity().Size()表示速度变化的大小,没有移动时,该值为0 if (GetVelocity().Size()) { int32 PikaCharacterIndex = PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaGetCurrentCharacterSpawnIDIndex(PikaCharacterSpawnID); if (PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaIsActive(PikaCharacterIndex)) { PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterLocation[PikaCharacterIndex] = GetActorLocation(); PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterRotator[PikaCharacterIndex] = GetActorRotation(); } } } // Called to bind functionality to input void APikaCharacterBase::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); } void APikaCharacterBase::PikaPrint(FString PikaStr) { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 6.0f, FColor::Red, PikaStr); } } float APikaCharacterBase::PikaGetHealthPercentage() { return PikaCharDataPre != NULL ? PikaCharDataPre->PikaCharBaseData.PikaGetHealthValuePercentage() : 1 ; } float APikaCharacterBase::PikaGetDefenceDamage(AActor * OtherActor) { if (OtherActor) { APikaCharacterBase * PikaEnemy = (APikaCharacterBase *)OtherActor; if (PikaEnemy) { return PikaEnemy->PikaCharDataPre->PikaCharBaseData.PikaPhysicalAttack / ((PikaEnemy->PikaCharDataPre->PikaCharBaseData.PikaArmor / 10) + 1); } } return 0; } //更新血条栏 void APikaCharacterBase::PikaUpdateUMGHealth() { if (PikaShowUMG) { UPikaUIHealthShow * PikaHealthShow = Cast<UPikaUIHealthShow>(PikaShowUMG->GetUserWidgetObject()); UPikaUICharacterAttribute* PikaNewCharacterAttribute = Cast<UPikaUICharacterAttribute>(PikaShowAttribute->GetUserWidgetObject()); //更新血条显示 if (PikaHealthShow) PikaHealthShow->PikaUpdateCharacterInformation(); //更新面板显示 if (PikaNewCharacterAttribute) PikaNewCharacterAttribute->PikaUpdateCharacterInformation(); } } bool APikaCharacterBase::PikaGetCharacterState(float Damage) { //播放角色受伤的声音 if (PikaGetPlayerController()) PikaGetPlayerController()->PikaPlaySoundAtVetor(PikaHitSound, GetActorLocation(), PikaETowerDefenceSoundType::SOUND_EFFECT_SOUND); //产生伤害 PikaCharDataPre->PikaCharBaseData.PikaCurrentHealth -= Damage; if (PikaCharDataPre->PikaCharBaseData.PikaCurrentHealth > 0) { //上传我们血值信息 if (PikaGetPlayerController() && PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon) { int32 PikaCharacterIndex = PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaGetCurrentCharacterSpawnIDIndex(PikaCharacterSpawnID); if (PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaIsActive(PikaCharacterIndex)) PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterCurrentHealth[PikaCharacterIndex] = PikaCharDataPre->PikaCharBaseData.PikaCurrentHealth; } return PikaCharDataPre->PikaCharBaseData.PikaDeath = false; } PikaCharDataPre->PikaCharBaseData.PikaDeath = true; //角色死亡,销毁角色 PikaDestoryCharacter(2); return true; } //是否存活 bool APikaCharacterBase::PikaIsActive() { if (PikaCharDataPre) return !PikaCharDataPre->PikaCharBaseData.PikaDeath; return true; } bool APikaCharacterBase::PikaIsDeathBP() { if (PikaCharDataPre) return PikaCharDataPre->PikaCharBaseData.PikaDeath; return false; } void APikaCharacterBase::PikaDestoryCharacter(float DelayTime) { if (GetWorld()) { if (DelayTime > 0) { GetWorld()->GetTimerManager().SetTimer(PikaDestoryActorHandle , this , &APikaCharacterBase::PikaDelayDestoryCharacter , DelayTime); } else { GetWorld()->GetTimerManager().SetTimer(PikaDestoryActorHandle, this, &APikaCharacterBase::PikaDelayDestoryCharacter, 0.1f); } //该角色死亡后对角色范围内的非队友进行经验值增加 for (TActorIterator<APikaCharacterBase>it(GetWorld(), APikaCharacterBase::StaticClass()); it; ++it) { APikaCharacterBase* PikaNewATCharacter = *it; if (PikaNewATCharacter && PikaNewATCharacter->PikaIsTeam() != PikaIsTeam()) { if ((PikaNewATCharacter->GetActorLocation() - GetActorLocation()).Size() <= PikaUpdateLevelRange) { PikaNewATCharacter->PikaIsUpdateLevel(PikaCharDataPre->PikaCharBaseData.PikaAddExp); } } } /*if (PikaDeathRangeCharacter) { APikaToolRangeOfCharacter * PikaCompanion = GetWorld()->SpawnActor<APikaToolRangeOfCharacter>(PikaDeathRangeCharacter , GetActorLocation() , GetActorRotation()); }*/ if (PikaGetPlayerController()) { //播放我们的死亡声音 //GetTowerDefencePlayerController()->PlaySoundAtVetor(DeathSound, GetActorLocation(), ETowerDefenceSoundType::SOUND_EFFECT_SOUND); //上传我们的死亡信息 if (PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon) { int32 PikaCharacterIndex = PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaGetCurrentCharacterSpawnIDIndex(PikaCharacterSpawnID); if (PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaIsActive(PikaCharacterIndex)) { PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterActive[PikaCharacterIndex] = false; PikaGetPlayerController()->PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterCurrentHealth[PikaCharacterIndex] = 0; } } /*//通知Control添加奖励玩家金币 if (GameCharacterData) { if (!IsTeam()) { //添加金币 GetTowerDefencePlayerController()->Confo->TDGameData.AddGlobalGold(GameCharacterData->CharacterDataBase.RewardGlod); //显示增加金币数字 ATool_DamageValueText* MyValueText = GetWorld()->SpawnActor<ATool_DamageValueText>(DamageValueActor, GetActorLocation(), FRotator::ZeroRotator); if (MyValueText) MyValueText->DrawGold(GameCharacterData->CharacterDataBase.RewardGlod, .7f); } //条件是否成功 GetTowerDefencePlayerController()->GameCondition(ELevelCondition::ExceedingSpiritualForce); //播放我们的金币声音 GetTowerDefencePlayerController()->PlaySoundAtVetor(GetTowerDefencePlayerController()->TDGameResources->GoldSound, GetActorLocation(), ETowerDefenceSoundType::SOUND_EFFECT_SOUND); }*/ } } } //延时销毁角色 void APikaCharacterBase::PikaDelayDestoryCharacter() { if (PikaDestoryActorHandle.IsValid() && GetWorld()) { GetWorld()->GetTimerManager().ClearTimer(PikaDestoryActorHandle); } if (PikaCharDataPre) { PikaCharDataPre->ConditionalBeginDestroy(); PikaCharDataPre = NULL; } UPikaGameResource * PikaTest1 = PikaGetPlayerController()->PikaGameResourcePtr; if (PikaGetPlayerController()) PikaGetPlayerController()->PikaClearTmpRuleOfTheCharacter(); Destroy(true); } bool APikaCharacterBase::PikaGetTeam() { return PikaCharDataPre->PikaCharBaseData.PikaTeam; } bool APikaCharacterBase::PikaIsTeam() { return PikaCharDataPre != NULL ? PikaCharDataPre->PikaCharBaseData.PikaTeam : false; } void APikaCharacterBase::PikaIsUpdateLevel(float Exp) { PikaCharDataPre->PikaCharBaseData.PikaCurrentExperienceValue += Exp; if (PikaCharDataPre->PikaCharBaseData.PikaCurrentExperienceValue >= PikaCharDataPre->PikaCharBaseData.PikaMaxExperienceValue) { PikaCharDataPre->PikaCharBaseData.PikaUpdateLevel(); UPikaUICharacterAttribute* PikaNewCharacterAttribute = Cast<UPikaUICharacterAttribute>(PikaShowAttribute->GetUserWidgetObject()); // 更新面板 if (PikaNewCharacterAttribute) PikaNewCharacterAttribute->PikaUpdateLevelCharacterElement(); } } void APikaCharacterBase::PikaUpdateLevelCharacterArray(TArray<AActor*> MyActor) { for (AActor* PikaOurActor : MyActor) { APikaCharacterBase * PikaTempCharacterBase = Cast<APikaCharacterBase>(PikaOurActor); if (PikaTempCharacterBase) { PikaTempCharacterBase->PikaIsUpdateLevel(PikaCharDataPre->PikaCharBaseData.PikaAddExp); } } } void APikaCharacterBase::PikaCharacterAttributeDisplay(bool IsDisplay) { if (PikaShowAttribute && PikaShowAttribute->GetUserWidgetObject()) { if (IsDisplay) { PikaShowAttribute->GetUserWidgetObject()->SetVisibility(ESlateVisibility::Visible); } else { PikaShowAttribute->GetUserWidgetObject()->SetVisibility(ESlateVisibility::Hidden); } } }
PikaCharacterData.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "PikaCharacterData.generated.h" //角色基础数据结构体 USTRUCT() struct FPikaCharacterDataAttribute { GENERATED_USTRUCT_BODY() //角色名字 UPROPERTY() FName PikaCharacterName; //角色ID UPROPERTY() int32 PikaCharacterID; //角色等级 UPROPERTY() int32 PikaCharacterLevel; //最大生命值 UPROPERTY() float PikaMaxHealth; //当前生命值 UPROPERTY() float PikaCurrentHealth; //死亡状态 UPROPERTY() bool PikaDeath; //角色组:True为友方,False为敌对方 UPROPERTY() bool PikaTeam; //物理攻击 UPROPERTY() float PikaPhysicalAttack; //护甲 UPROPERTY() float PikaArmor; //最大经验值 UPROPERTY() float PikaMaxExperienceValue; //当前经验值 UPROPERTY() float PikaCurrentExperienceValue; //攻击速度 UPROPERTY() float PikaAttackSpeed; //最小攻击速度 UPROPERTY() float PikaAttackSpeedMin; //建造时需要消耗的金币数 UPROPERTY() float PikaComsumeGold; //消灭时获得的金币数 UPROPERTY() float PikaAddComsume; //升级(每级加多少) //添加生命值 UPROPERTY() float PikaAddHealth; //添加攻击力 UPROPERTY() float PikaAddPhsicalAttack; //添加护甲 UPROPERTY() float PikaAddArmor; //添加经验值 UPROPERTY() float PikaAddExp; //添加攻击速度 UPROPERTY() float PikaAddAttackSpeed; //添加金币 UPROPERTY() float PikaAddGlod; //奖励金币 UPROPERTY() float PikaRewardGlod; //属性初始化 FPikaCharacterDataAttribute(); //获取经验值百分比 float PikaGetEmpircalValuePercentage() const { return PikaMaxExperienceValue ? PikaCurrentExperienceValue / PikaMaxExperienceValue : 0; } //生命值百分比 float PikaGetHealthValuePercentage() const { return PikaMaxHealth ? PikaCurrentHealth / PikaMaxHealth : 0; } //角色注册后主动调用一次,用导入的csv数据进行初始化 void PikaInitCharacterAttrubute(float PikaMyMaxHealth , float PikaMyPhysicalAttack , float PikaMyAttackSpeed , float PikaMyMaxExperienceValue , float PikaMyArmor) { PikaMaxHealth = PikaMyMaxHealth; PikaPhysicalAttack = PikaMyPhysicalAttack; PikaAttackSpeed = PikaMyAttackSpeed; PikaMaxExperienceValue = PikaMyMaxExperienceValue; PikaArmor = PikaMyArmor; PikaCurrentExperienceValue = 0; PikaCurrentHealth = PikaMaxHealth; PikaDeath = false; //保存初始速度 PikaAttackSpeedMin = PikaAttackSpeed; PikaCharacterLevel = 0; } //角色注册后主动调用一次 void PikaInitAddCharacterAttribute(float PikaMyAddHealth , float PikaMyAddPhsicalAttack , float PikaMyAddArmor , float PikaMyAddExp , float PikaMyAddAttackSpeed) { PikaAddHealth = PikaMyAddHealth; PikaAddPhsicalAttack = PikaMyAddPhsicalAttack; PikaAddArmor = PikaMyAddArmor; PikaAddExp = PikaMyAddExp; PikaAddAttackSpeed = PikaMyAddAttackSpeed; } //角色升级 void PikaUpdateLevel() { PikaCharacterLevel += 1; PikaMaxHealth += (PikaCharacterLevel - 1)*PikaAddHealth; PikaPhysicalAttack += (PikaCharacterLevel - 1)*PikaAddPhsicalAttack; PikaAttackSpeed += (PikaCharacterLevel - 1)*PikaAddAttackSpeed; //PikaMaxExperienceValue += (PikaCharacterLevel - 1)*PikaAddExp; PikaArmor += (PikaCharacterLevel - 1)*PikaAddArmor; PikaCurrentExperienceValue = 0; PikaCurrentHealth = PikaMaxHealth; UE_LOG(LogTemp, Log, TEXT("Pika:UpdateLevel Successfully!")); return; } }; /** * */ UCLASS() class PIKAGODSTONE_API UPikaCharacterData : public UObject { GENERATED_BODY() public: FPikaCharacterDataAttribute PikaCharBaseData; };
PikaCharacterData.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaCharacterData.h" FPikaCharacterDataAttribute::FPikaCharacterDataAttribute() { //角色名字 PikaCharacterName = "NoOne"; //角色ID PikaCharacterID = 1; //角色等级 PikaCharacterLevel = 1; //最大生命值 PikaMaxHealth = 1000; //当前生命值 PikaCurrentHealth = 1000; //死亡状态 PikaDeath = false; //角色组:True为友方,False为敌对方 PikaTeam = false; //物理攻击 PikaPhysicalAttack = 100.f; //护甲 PikaArmor = 10.f; //最大经验值 PikaMaxExperienceValue = 6000.f; //当前经验值 PikaCurrentExperienceValue = 0.f; //增加经验值 PikaAddExp = 100.f; //攻击速度 PikaAttackSpeed = PikaAttackSpeedMin = 0.66; //建造时需要消耗的金币数 PikaComsumeGold = 100.f; //消灭时获得的金币数 PikaAddComsume = 10.f; }
PikaCharacterInfoDataTable.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Engine/DataTable.h" #include "PikaCharacterInfoDataTable.generated.h" UENUM() namespace EPikaCharacterInfoDataTableType { enum Type { // 基础数据 DATA_PikaCharacterHealth, DATA_PikaCharacterAttack, DATA_PikaCharacterArm, DATA_PikaCharacterEmpircalValue, DATA_PikaCharacterAttackSpeed, DATA_PikaCharacterComsumeGlod, DATA_PikaCharacterConstructionTime, //增加数据 DATA_PikaCharacterAddGlod, DATA_PikaCharacterAddHealth, DATA_PikaCharacterAddPhysicalAttack, DATA_PikaCharacterAddArmor, DATA_PikaCharacterAddEmpiricalValue, DATA_PikaCharacterAddAttackSpeed, DATA_PikaCharacterMax }; } /** * */ USTRUCT(BlueprintType) struct FPikaCharacterInfoDataTable : public FTableRowBase { GENERATED_BODY() public: //角色ID UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") int32 PikaCharacterID; //角色图片 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") TAssetPtr<UTexture2D> PikaIcon; //角色蓝图实例 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") TAssetSubclassOf<AActor> PikaCharacterBlueprintKey; //基础属性 //最大生命值 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") float PikaMaxHealth; //物理攻击 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") float PikaPhysicalAttack; //护甲 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") float PikaArmor; //最大经验值 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") float PikaMaxExperienceValue; //攻击速度 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") float PikaAttackSpeed; //建造时需要消耗的金币数 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") float PikaComsumeGold; //建造时需要的时间 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") float PikaConstructionTime; //角色简介 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") FText PikaComment; //添加 //增加经验值 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") float PikaAddExperienceValue; //消灭时获得的金币数 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") float PikaAddComsume; //增加生命值 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") float PikaAddHealth; //增加攻击力 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") float PikaAddPhysicalAttack; //增加护甲 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") float PikaAddArmor; //添加攻击速度 UPROPERTY(EditDefaultsOnly, Category = "PikaDataTable") float PikaAddAttackSpeed; FPikaCharacterInfoDataTable(); };
PikaCharacterInfoDataTable.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaCharacterInfoDataTable.h" FPikaCharacterInfoDataTable::FPikaCharacterInfoDataTable(): //角色ID PikaCharacterID(1), //最大生命值 PikaMaxHealth(1000), //物理攻击 PikaPhysicalAttack(100.f), //护甲 PikaArmor(10.f), //最大经验值 PikaMaxExperienceValue(6000.f), //增加经验值 PikaAddExperienceValue(100.f), //攻击速度 PikaAttackSpeed(0.66), //建造时需要消耗的金币数 PikaComsumeGold(100.f), //消灭时获得的金币数 PikaAddComsume(10.f) { }
PikaDamageValueText.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "WidgetComponent.h" #include "Components/SceneComponent.h" #include "Components/TimelineComponent.h" #include "PikaDamageValueText.generated.h" UCLASS() class PIKAGODSTONE_API APikaDamageValueText : public AActor { GENERATED_BODY() UPROPERTY(VisibleAnywhere , BlueprintReadOnly , Category="PikaDamage" , meta=(AllowPrivateAccess = "true")) class UWidgetComponent * PikaDamageValueUMG; UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaDamage", meta = (AllowPrivateAccess = "true")) class USceneComponent * PikaRootPoint; UPROPERTY(EditDefaultsOnly, Category = "PikaDamage") float PikaTextHeight; public: // Sets default values for this actor's properties APikaDamageValueText(); //绘制伤害 void PikaDrawDamage(float DamageValue, float DamagePercentage); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: // Called every frame virtual void Tick(float DeltaTime) override; // 范围攻击,该曲线由蓝图载入 UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") UCurveFloat * PikaCurveFloat; UPROPERTY() FTimeline PikaRangeAttackTimeLine; //范围攻击球体的半径 UPROPERTY(EditDefaultsOnly, Category = "PikaBullet") float PikaBoxDamageTargetRadius; UFUNCTION() void PikaTimeLineRangeAttack(float PikaValue); UFUNCTION() void PikaTimeLineFinished(); };
PikaDamageValueText.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaDamageValueText.h" #include "Public/PikaUI_InformationWeight.h" // Sets default values APikaDamageValueText::APikaDamageValueText() { // 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; PikaDamageValueUMG = CreateDefaultSubobject<UWidgetComponent>(TEXT("PikaParticleMesh")); PikaRootPoint = CreateDefaultSubobject<USceneComponent>(TEXT("PikaHomingPoint")); RootComponent = PikaRootPoint; PikaDamageValueUMG->AttachToComponent(PikaRootPoint, FAttachmentTransformRules::KeepRelativeTransform); } //绘制伤害 void APikaDamageValueText::PikaDrawDamage(float DamageValue, float DamagePercentage) { if (PikaDamageValueUMG && PikaDamageValueUMG->GetUserWidgetObject()) { UPikaUI_InformationWeight* PikaMyInformationWidget = Cast<UPikaUI_InformationWeight>(PikaDamageValueUMG->GetUserWidgetObject()); if (PikaMyInformationWidget) { PikaMyInformationWidget->PikaDrawUIToScreen(); PikaMyInformationWidget->PikaDrawSubtractionHealthInformation(DamageValue, DamagePercentage); } } } // Called when the game starts or when spawned void APikaDamageValueText::BeginPlay() { Super::BeginPlay(); if (GetWorld()) { //曲线存在,通过代理绑定处理函数 if (PikaCurveFloat) { FOnTimelineFloat PikaTimeLineDelegate; FOnTimelineEvent PikaFinishedEvent; PikaFinishedEvent.BindUFunction(this, FName("PikaTimeLineFinished")); PikaTimeLineDelegate.BindUFunction(this, FName("PikaTimeLineRangeAttack")); //添加曲线 PikaRangeAttackTimeLine.AddInterpFloat(PikaCurveFloat, PikaTimeLineDelegate); //设置停止循环 PikaRangeAttackTimeLine.SetLooping(false); //开始播放 PikaRangeAttackTimeLine.PlayFromStart(); //TimeLine结束时触发的事件 PikaRangeAttackTimeLine.SetTimelineFinishedFunc(PikaFinishedEvent); } } } // Called every frame void APikaDamageValueText::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (PikaCurveFloat) { PikaRangeAttackTimeLine.TickTimeline(DeltaTime); } } void APikaDamageValueText::PikaTimeLineRangeAttack(float PikaValue) { if (PikaDamageValueUMG && PikaTextHeight>0) { FVector PikaBoxDamageCurrentRadius = FMath::Lerp(FVector::ZeroVector , FVector(0 , 0 , PikaTextHeight) , PikaValue); PikaDamageValueUMG->AddRelativeLocation(PikaBoxDamageCurrentRadius); } } void APikaDamageValueText::PikaTimeLineFinished() { Destroy(true); }
PikaDisplaceTrigger.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 "PikaGodStoneCamera.h" #include "PikaDisplaceTrigger.generated.h" UCLASS() class PIKAGODSTONE_API APikaDisplaceTrigger : public AActor { GENERATED_BODY() //碰撞组件 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBox", meta = (AllowPrivateAccess = "true")) UBoxComponent * PikaBox_1; //根组件 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "PikaBox", meta = (AllowPrivateAccess = "true")) USceneComponent * PikaRoot; //存储Camera的指针 UPROPERTY() APikaGodStoneCamera * PikaCameraPawn; public: // Sets default values for this actor's properties APikaDisplaceTrigger(); //蓝图中可以编辑的变量 UPROPERTY(EditAnywhere , BlueprintReadWrite , Category = "PikaUI") float PikaAddDistance; UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "PikaEventAddDistance"), Category = "PikaEvent") void PikaAddDistanceCamera(AActor * OtherActor); UFUNCTION(BlueprintImplementableEvent, meta = (DisplayName = "PikaEventSubstractDistance"), Category = "PikaEvent") void PikaSubstractDistanceCamera(AActor * OtherActor); 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 PikaBeginOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult); UFUNCTION() void PikaEndOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex); //打印测试 UFUNCTION() void PikaPrint(FString piksStr); };
PikaDisplaceTrigger.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaDisplaceTrigger.h" // Sets default values APikaDisplaceTrigger::APikaDisplaceTrigger() { // 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; //创建碰撞组件 PikaBox_1 = CreateDefaultSubobject<UBoxComponent>(TEXT("PikaDisplacementTrigger_1")); PikaRoot = CreateDefaultSubobject<USceneComponent>(TEXT("PikaRoot_1")); RootComponent = PikaRoot; //绑定 PikaBox_1->AttachToComponent(PikaRoot, FAttachmentTransformRules::KeepRelativeTransform); } // Called when the game starts or when spawned void APikaDisplaceTrigger::BeginPlay() { Super::BeginPlay(); //绑定碰撞的事件 PikaBox_1->OnComponentBeginOverlap.AddUniqueDynamic(this, &APikaDisplaceTrigger::PikaBeginOverlapping); PikaBox_1->OnComponentEndOverlap.AddUniqueDynamic(this, &APikaDisplaceTrigger::PikaEndOverlapping); if (GetWorld()) { //获取MainCamera的指针 PikaCameraPawn = Cast<APikaGodStoneCamera>(GetWorld()->GetFirstPlayerController()->GetPawn()); } } // Called every frame void APikaDisplaceTrigger::Tick(float DeltaTime) { Super::Tick(DeltaTime); } void APikaDisplaceTrigger::PikaBeginOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult) { PikaAddDistanceCamera(OtherActor); } void APikaDisplaceTrigger::PikaEndOverlapping(UPrimitiveComponent * OverlappedComponent, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex) { PikaSubstractDistanceCamera(OtherActor); } void APikaDisplaceTrigger::PikaPrint(FString piksStr) { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 6.0f, FColor::Red, piksStr); } }
PikaDragDropOperation.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Blueprint/DragDropOperation.h" #include "PikaUIWidgetBase.h" #include "PikaDragDropOperation.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaDragDropOperation : public UDragDropOperation { GENERATED_BODY() public: //PikaUI_InventorySlot类的指针 UPROPERTY() UPikaUIWidgetBase* PikaInventorySlot; };
PikaDragDropOperation.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaDragDropOperation.h"
PikaGameErrorHint.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "TextBlock.h" #include "PikaGameErrorHint.generated.h" class UPikaMainInterface; class UPikaUIMainHall; /** * */ UCLASS() class PIKAGODSTONE_API UPikaGameErrorHint : public UPikaUIWidgetBase { GENERATED_BODY() UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaGameLogName; public: UPikaGameErrorHint(); float PikaLogDisplayTime; bool PikaCheckTime; //相当于BeginPlay,用于解决BeginPlay执行时,有些资源可能还没加载完成的问题 virtual void PikaDrawUIToScreen() override; //负责打印GameLOG UFUNCTION() virtual void PikaLogPrintf(FString MyString) override; //NativeTick函数里会调用蓝图里的Tick virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override; UPikaMainInterface* PikaGetMainInterface() const { return PikaMainInterface; } void PikaSetMainInterface(UPikaMainInterface* NewWidget) { PikaMainInterface = NewWidget; } UPikaUIMainHall* PikaGetMainHall() const { return PikaMainHall; } void PikaSetMainHall(UPikaUIMainHall* NewWidget) { PikaMainHall = NewWidget; } private: UPikaMainInterface* PikaMainInterface; UPikaUIMainHall* PikaMainHall; UTextBlock* PikaGameLog; };
PikaGameErrorHint.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGameErrorHint.h" UPikaGameErrorHint::UPikaGameErrorHint() { PikaLogDisplayTime = 0.f; PikaCheckTime = false; } void UPikaGameErrorHint::PikaDrawUIToScreen() { PikaGameLog = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaGameLogName)); if (PikaGetMainInterface()) PikaGetMainInterface()->PikaLog.AddDynamic(this , &UPikaGameErrorHint::PikaLogPrintf); if (PikaGameLog) PikaGameLog->SetVisibility(ESlateVisibility::Hidden); } void UPikaGameErrorHint::PikaLogPrintf(FString MyString) { if (PikaGameLog) { PikaGameLog->SetText(FText::FromString(MyString)); PikaGameLog->SetVisibility(ESlateVisibility::Visible); } if (PikaUIDataPtr) PikaLogDisplayTime = PikaUIDataPtr->PikaLogDisplayTime; } void UPikaGameErrorHint::NativeTick(const FGeometry& MyGeometry, float InDeltaTime) { Super::NativeTick(MyGeometry , InDeltaTime); if (PikaLogDisplayTime > 0) { PikaLogDisplayTime -= InDeltaTime; PikaCheckTime = true; return; } if (PikaCheckTime && PikaGameLog) { PikaCheckTime = false; PikaGameLog->SetVisibility(ESlateVisibility::Hidden); } }
PikaGameManager.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/CheatManager.h" #include "Public/PikaGodStonePlayerController.h" #include "Public/PikaGodStonePlayerState.h" #include "Public/PikaGodStoneCamera.h" #include "PikaGameManager.generated.h" /** * */ UCLASS(Within = PikaGodStonePlayerController) class PIKAGODSTONE_API UPikaGameManager : public UCheatManager { GENERATED_BODY() public: UFUNCTION(exec) void PikaLogPrint(); //添加一个塔 UFUNCTION(exec) void PikaAddTowers(int32 TowerID , int32 TowerLevel , int32 TowerCount); APikaGodStonePlayerController * PikaGetPC(); APikaGodStonePlayerState * PikaGetTowersPlayerState(); APikaGodStoneCamera * PikaGetTowerCamera(); };
PikaGameManager.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGameManager.h" void UPikaGameManager::PikaLogPrint() { FString PiksStr = "pikapika"; float PikaFloat = 0.22; int32 PikaInt = 123; UE_LOG(LogTemp , Log , TEXT("PikaOK")); UE_LOG(LogTemp , Warning , TEXT("%s , %f , %i") , *PiksStr , PikaFloat , PikaInt); UE_LOG(LogTemp, Error, TEXT("%s , %f , %i"), *PiksStr, PikaFloat, PikaInt); } //添加一个塔 void UPikaGameManager::PikaAddTowers(int32 TowerID, int32 TowerLevel, int32 TowerCount) { if (!(TowerCount >= 1)) { UE_LOG(LogTemp , Warning ,TEXT("%i < 1") , TowerCount); return; } for (int32 i=0 ; i<TowerCount ; i++) { PikaGetPC()->PikaSpawnTowers(TowerID , TowerLevel); } } APikaGodStonePlayerController * UPikaGameManager::PikaGetPC() { return ((APikaGodStonePlayerController *)GetOuterAPlayerController()); } APikaGodStonePlayerState * UPikaGameManager::PikaGetTowersPlayerState() { return PikaGetPC()->PikaGetTowerPlayerState(); } APikaGodStoneCamera * UPikaGameManager::PikaGetTowerCamera() { return PikaGetPC()->PikaGetTowreCamera(); }
PikaGameResource.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "Engine/Texture2D.h" #include "Sound/SoundAttenuation.h" #include "PikaGameResource.generated.h" class APikaGodStonePlayerController; USTRUCT() struct FPikaMiniMap { GENERATED_BODY() //Minimap的地图 UPROPERTY(EditDefaultsOnly, Category = "PikaMiniMap") UTexture2D* PikaMiniMapTexture; //地图的宽 UPROPERTY(EditDefaultsOnly, Category = "PikaMiniMap") float PikaMiniMapSizeX; //地图的高 UPROPERTY(EditDefaultsOnly, Category = "PikaMiniMap") float PikaMiniMapSizeY; //地图的宽与X轴屏幕的间隔 UPROPERTY(EditDefaultsOnly, Category = "PikaMiniMap") float PikaMiniMapSizeXInterval; //地图的高与Y轴屏幕的间隔 UPROPERTY(EditDefaultsOnly, Category = "PikaMiniMap") float PikaMiniMapSizeYInterval; //真实地图的大小 UPROPERTY(EditDefaultsOnly, Category = "PikaMap") float PikaMapSizeX; //真实地图的大小 UPROPERTY(EditDefaultsOnly, Category = "PikaMap") float PikaMapSizeY; FPikaMiniMap() { PikaMiniMapSizeX = 256; PikaMiniMapSizeY = 256; PikaMiniMapSizeXInterval = 30; PikaMiniMapSizeYInterval = 30; //PikaMapSizeX和PikaMapSizeY的值需要在UE编辑器里的非透视图里,按下鼠标中键进行测量 PikaMapSizeX = 15000; PikaMapSizeY = 15000; } }; /** * */ UCLASS(Blueprintable) class PIKAGODSTONE_API UPikaGameResource : public UObject { GENERATED_BODY() public: UPikaGameResource(); /*******************MapStart********************/ UPROPERTY(EditDefaultsOnly, Category = "Mini Map") TArray<FPikaMiniMap> PikaLevelMiniMap; UPROPERTY(EditDefaultsOnly, Category = "Mini Map") UTexture2D* PikaNewCameraBoard; UPROPERTY(EditDefaultsOnly, Category = "Mini Map") FVector2D PikaNewCameraBoardSize; /*******************MapEnd********************/ //hover声音 UPROPERTY(EditDefaultsOnly, Category = "PikaSound") TArray <USoundBase*> PikaHoverSound; //unHover声音 UPROPERTY(EditDefaultsOnly, Category = "PikaSound") TArray <USoundBase*> PikaUnHoverSound; //初始化我们的资源 void PikaInitializationResource(class APikaGodStonePlayerController* MyController); FVector2D PikaPlayerLocConverMiniMapCoord(int32 CurrentLevel, AActor* NewTargetActor, APawn* Player); //战斗的声音衰减体积框 UPROPERTY(EditDefaultsOnly, Category = "PikaSoundVolume") USoundAttenuation* PikaFightingSoundVolume; };
PikaGameResource.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGameResource.h" UPikaGameResource::UPikaGameResource() { } void UPikaGameResource::PikaInitializationResource(class APikaGodStonePlayerController* MyController) { } FVector2D UPikaGameResource::PikaPlayerLocConverMiniMapCoord(int32 CurrentLevel, AActor* NewTargetActor, APawn* Player) { FVector2D PikaMiniMapSize = FVector2D::ZeroVector; if (Player && NewTargetActor) { FVector PikaPlayerLocation = (-1 * (NewTargetActor->GetActorRotation())).RotateVector(Player->GetActorLocation() - NewTargetActor->GetActorLocation()); PikaMiniMapSize = FVector2D(PikaPlayerLocation.X / PikaLevelMiniMap[CurrentLevel].PikaMapSizeX, PikaPlayerLocation.Y / (PikaLevelMiniMap[CurrentLevel].PikaMapSizeY)); } return PikaMiniMapSize; }
PikaGameSaveData.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/SaveGame.h" #include "PikaGodStoneMacroLib.h" #include "PikaGameSaveData.generated.h" #define LevelMax (5) //读存数据表 USTRUCT() struct FPikaReadGameData { GENERATED_USTRUCT_BODY() //我们存了多少个档,存储的内容和日期 UPROPERTY(SaveGame) TArray<FString> PikaSaveDataText; //对应有存档的角标 UPROPERTY(SaveGame) TArray<int32> PikaSaveGameBoxNumberArray; //关卡完成度 UPROPERTY(SaveGame) TArray<float> PikaDegreeOfCompletion; //最大关卡 UPROPERTY(SaveGame) int32 PikaMaxLevel; //还原某个数据 void PikaClearReadGameDataAt(int32 IndexNumber) { if (PikaSaveDataText.IsValidIndex(IndexNumber)) { PikaSaveDataText[IndexNumber] = PIKA_SAVE_PIKA; int32 PikaNewIndexGameBox = PikaSaveGameBoxNumberArray.Find(IndexNumber); if (PikaNewIndexGameBox != INDEX_NONE) { PikaSaveGameBoxNumberArray[PikaNewIndexGameBox] = -1; } else { PIKA_UE_PRINT(FString::Printf(TEXT("SaveGameBoxNumberArray[NewIndexGameBox] = !&&**%&^@$ ,NewIndexGameBox = %i"), PikaNewIndexGameBox)); } } else { PIKA_UE_PRINT(FString::Printf(TEXT("Nothingness %i"), IndexNumber)); } } //清空数据 void PikaClearData() { PikaSaveDataText.Empty(); PikaSaveGameBoxNumberArray.Empty(); PikaDegreeOfCompletion.Empty(); } //初始化数据尺寸 void PikaInitDataSzie() { PikaSaveDataText.SetNum(Pika_SAVE_SaveBarNumber); PikaSaveGameBoxNumberArray.SetNum(Pika_SAVE_SaveBarNumber); PikaDegreeOfCompletion.SetNum(LevelMax); PikaMaxLevel = 0; for (int32 i = 0; i < Pika_SAVE_SaveBarNumber; i++) { PikaSaveDataText[i] = PIKA_SAVE_PIKA; PikaSaveGameBoxNumberArray[i] = INDEX_NONE; } for (int32 i = 0; i < LevelMax; i++) { PikaDegreeOfCompletion[i] = 0; } } //获取PIKA_SAVE_SLOT_NAME存档里第一个空位置的index int32 PikaGetSerialNumber() { int32 PikaSaveBarNumber = Pika_SAVE_SaveBarNumber; if (!((PikaSaveDataText.Num() & PikaSaveGameBoxNumberArray.Num())) == PikaSaveBarNumber) return INDEX_NONE; int32 PikaIntIndex = INDEX_NONE; for (int32 i = 0; i < Pika_SAVE_SaveBarNumber; i++) { if (PikaSaveDataText[i] == PIKA_SAVE_PIKA) { PikaIntIndex = i; break; } } return PikaIntIndex; } FPikaReadGameData() { if (PikaSaveGameBoxNumberArray.Num() == 0) { PikaInitDataSzie(); } } //需要载入operator=,如果是基础的数据元素,不需要,但是其中有TArray<>,该类需要operator= FPikaReadGameData& operator=(const FPikaReadGameData& object) { PikaSaveDataText = object.PikaSaveDataText; PikaSaveGameBoxNumberArray = object.PikaSaveGameBoxNumberArray; PikaDegreeOfCompletion = object.PikaDegreeOfCompletion; PikaMaxLevel = PikaMaxLevel; return *this; } }; //此数据是我们游戏角色在场景内的缓存 USTRUCT() struct FPikaTemporaryCacheData { GENERATED_USTRUCT_BODY() //角色生成的混合ID UPROPERTY(SaveGame) TArray<int32> PikaCharacterSpawnID; //角色队伍 UPROPERTY(SaveGame) TArray<bool> PikaCharacterTeam; //角色存活 UPROPERTY(SaveGame) TArray<bool> PikaCharacterActive; //角色位置 UPROPERTY(SaveGame) TArray<FVector> PikaCharacterLocation; //角色旋转 UPROPERTY(SaveGame) TArray<FRotator> PikaCharacterRotator; //角色名字(通过角色的名字寻找到该角色) UPROPERTY(SaveGame) TArray<FName> PikaCharacterName; //当前生命值 UPROPERTY(SaveGame) TArray<float> PikaCharacterCurrentHealth; //当前经验值 UPROPERTY(SaveGame) TArray<float> PikaCharacterCurrentExp; //当前等级 UPROPERTY(SaveGame) TArray<int32> PikaCharacterCurrentLevel; FPikaTemporaryCacheData() { } //全部移除 ~FPikaTemporaryCacheData() { for (int32 IndexNumber = 0; IndexNumber < PikaCharacterSpawnID.Num(); IndexNumber++) { PikaRemoveIt(IndexNumber); } } //获取当前的角标 int32 PikaGetCurrentCharacterSpawnIDIndex(int32 PawnSpawnID) { return PikaCharacterSpawnID.Find(PawnSpawnID); } //判断角标是不是存在数组范围内 判断当前是不是锁住状态 bool PikaIsActive(int32 Index) { return (Index >= 0 && Index < PikaCharacterSpawnID.Num()) ? true : false; } //判断ID是否有相同的 bool PikaIsExistSpawnID(int32 SpawnID) { return (PikaCharacterSpawnID.Find(SpawnID) != INDEX_NONE) ? true : false; } //移除单个 void PikaRemoveIt(int32 Index = INDEX_NONE) { if (PikaIsActive(Index)) { if(PikaCharacterSpawnID.IsValidIndex(Index)) PikaCharacterSpawnID.RemoveAt(Index); if (PikaCharacterTeam.IsValidIndex(Index)) PikaCharacterTeam.RemoveAt(Index); if (PikaCharacterActive.IsValidIndex(Index)) PikaCharacterActive.RemoveAt(Index); if (PikaCharacterLocation.IsValidIndex(Index)) PikaCharacterLocation.RemoveAt(Index); if (PikaCharacterRotator.IsValidIndex(Index)) PikaCharacterRotator.RemoveAt(Index); if (PikaCharacterName.IsValidIndex(Index)) PikaCharacterName.RemoveAt(Index); if (PikaCharacterCurrentHealth.IsValidIndex(Index)) PikaCharacterCurrentHealth.RemoveAt(Index); if (PikaCharacterCurrentExp.IsValidIndex(Index)) PikaCharacterCurrentExp.RemoveAt(Index); if (PikaCharacterCurrentLevel.IsValidIndex(Index)) PikaCharacterCurrentLevel.RemoveAt(Index); } } FPikaTemporaryCacheData & operator=(const FPikaTemporaryCacheData &object) { PikaCharacterSpawnID = object.PikaCharacterSpawnID; PikaCharacterTeam = object.PikaCharacterTeam; PikaCharacterActive = object.PikaCharacterActive; PikaCharacterLocation = object.PikaCharacterLocation; PikaCharacterRotator = object.PikaCharacterRotator; PikaCharacterName = object.PikaCharacterName; PikaCharacterCurrentHealth = object.PikaCharacterCurrentHealth; PikaCharacterCurrentExp = object.PikaCharacterCurrentExp; PikaCharacterCurrentLevel = object.PikaCharacterCurrentLevel; return *this; } }; USTRUCT() struct FPikaTowersData { GENERATED_USTRUCT_BODY() float PikaTimeInterval; FPikaTowersData() { PikaTimeInterval = .5; } }; //关卡管理 USTRUCT() struct FPikaGameLevelManangenment { GENERATED_USTRUCT_BODY() //该关卡内怪物数量 UPROPERTY(SaveGame) int32 PikaNumberOfMonster; //怪物等级(和游戏难度有关) UPROPERTY(SaveGame) int32 PikaAddMonsterLevel; //如果所有的主塔死亡,该值为true,并且禁止建造任何建筑 UPROPERTY(SaveGame) uint8 PikaIsAllMainTowerDie : 1; //所有塔死亡,游戏结束 UPROPERTY(Transient) uint8 PikaGameOver : 1; //所有塔死亡,则游戏结束 UPROPERTY(Transient) uint8 PikaCurrentLevelMissionSuccess : 1; //塔等级 UPROPERTY(SaveGame) int32 PikaTowersLevel; //生成怪物阶段 UPROPERTY(SaveGame) int32 PikaSpawnMonsterStage; //当前关卡 UPROPERTY(SaveGame) int32 PikaCurrentLevel; //时间间隔(多久生成一次怪物) UPROPERTY(SaveGame) float PikaTimeInterval; //生成怪物的时间记录 UPROPERTY(SaveGame) float PikaSetTimeMnanagenment; //第几部分内容 UPROPERTY(SaveGame) int32 PikaParts; //有多少波怪物 UPROPERTY(SaveGame) int32 PikaMaxStagesAreMonsters; //当前是哪一波怪物 UPROPERTY(SaveGame) int32 PikaCurrentStagesAreMonsters; //每波怪物当前数量 UPROPERTY(SaveGame) TArray<int32> PikaPerNumberOfMonsters; //判定怪物全部消灭没 void PikaDataSubtraction() { if (PikaCurrentStagesAreMonsters < PikaPerNumberOfMonsters.Num()) { if (PikaPerNumberOfMonsters[PikaCurrentStagesAreMonsters] > 0) { PikaPerNumberOfMonsters[PikaCurrentStagesAreMonsters]--; } else { PikaLock(); } } else { PikaCurrentLevelMissionSuccess = true; PikaLock(); } } //分配数量梯度,数量从少变多 void PikaAssignedMonsterAmount() { //检查构成条件,怪物数量需要大于阶段数量,负责会按照阶段数生成至少一个怪物 if (PikaNumberOfMonster <= PikaMaxStagesAreMonsters) PikaNumberOfMonster = PikaMaxStagesAreMonsters; //多少的怪物 int32 PikaCurrentMonsterNumber = PikaNumberOfMonster; //最大阶段 int32 PikaCurrentStagesNumber = PikaMaxStagesAreMonsters; //每阶段的数量 int32 PikaCurrentAssignedNum = INDEX_NONE; for (int32 i = 0; i < PikaMaxStagesAreMonsters; i++) { if (PikaCurrentStagesNumber > 0) { //每阶段的平均值 int32 PikaStagesNumber = PikaCurrentMonsterNumber / PikaCurrentStagesNumber; if (PikaCurrentMonsterNumber > 1) { //减去该阶段 PikaCurrentStagesNumber--; if (PikaCurrentStagesNumber != 0) { //随机阶段,从平均值一般到平均值分配 PikaCurrentAssignedNum = FMath::RandRange(PikaStagesNumber / 2, PikaStagesNumber); } else { PikaCurrentAssignedNum = PikaStagesNumber; } PikaPerNumberOfMonsters.Add(PikaCurrentAssignedNum); //减去分配的数量 PikaCurrentMonsterNumber -= PikaCurrentAssignedNum; } else if (PikaCurrentMonsterNumber == 1) { //对于最后一个阶段 PikaPerNumberOfMonsters.Add(PikaCurrentAssignedNum); break; } } } } //是否大于生成怪物的时间间隔 bool PikaIsTimeRight() { return PikaSetTimeMnanagenment > PikaTimeInterval; } FPikaGameLevelManangenment() { PikaNumberOfMonster = 455; PikaAddMonsterLevel = 2; PikaSpawnMonsterStage = 3; PikaTimeInterval = 6; PikaSetTimeMnanagenment = 0; PikaTowersLevel = 1; PikaCurrentLevel = 0; PikaIsAllMainTowerDie = false; PikaGameOver = false; //PikaMaxStagesAreMonsters = INDEX_NONE; PikaMaxStagesAreMonsters = 6; PikaCurrentStagesAreMonsters = 0; PikaLockSpanwData = false; PikaParts = 0; } FPikaGameLevelManangenment& operator=(const FPikaGameLevelManangenment& NewObj) { PikaNumberOfMonster = NewObj.PikaNumberOfMonster; PikaAddMonsterLevel = NewObj.PikaAddMonsterLevel; PikaSpawnMonsterStage = NewObj.PikaSpawnMonsterStage; PikaSetTimeMnanagenment = NewObj.PikaSetTimeMnanagenment; PikaTowersLevel = NewObj.PikaTowersLevel; PikaCurrentLevel = NewObj.PikaCurrentLevel; PikaTimeInterval = NewObj.PikaTimeInterval; PikaIsAllMainTowerDie = NewObj.PikaIsAllMainTowerDie; PikaPerNumberOfMonsters = NewObj.PikaPerNumberOfMonsters; PikaMaxStagesAreMonsters = NewObj.PikaMaxStagesAreMonsters; PikaCurrentStagesAreMonsters = NewObj.PikaCurrentStagesAreMonsters; PikaLockSpanwData = NewObj.PikaLockSpanwData; PikaParts = NewObj.PikaParts; return *this; } //数据锁 FORCEINLINE void PikaLock() { PikaLockSpanwData = true; } FORCEINLINE void PikaUnLock() { PikaLockSpanwData = false; } FORCEINLINE bool PikaGetLock() const { return PikaLockSpanwData; } FORCEINLINE bool PikaIsExistDataMonster() const { return PikaPerNumberOfMonsters.IsValidIndex(PikaCurrentStagesAreMonsters) ? (PikaPerNumberOfMonsters[PikaCurrentStagesAreMonsters] > 0) : false; } private: //锁住数据 UPROPERTY(SaveGame) uint8 PikaLockSpanwData : 1; }; //故事 struct FPikaGameStory { TArray<FString> PikaStoryNor; TArray<FString> PikaStorySuc; TArray<FString> PikaStoryFai; }; //游戏本地的玩家数据 USTRUCT() struct FPikaGodStoneSaveGameData { GENERATED_BODY() //总时间的倒计时 UPROPERTY(SaveGame) float PikaGameCount; //总时间的倒计时 UPROPERTY(SaveGame) float PikaMaxGameCount; UPROPERTY(Transient) float PikaGoldGrowthTime; UPROPERTY(Transient) float PikaGoldGrowthMaxTime; //杀死敌人总数量 UPROPERTY(SaveGame) float PikaKillSoldierNumber; //杀死Boss数量 UPROPERTY(SaveGame) float PikaKillBossNumber; //塔死亡总数 UPROPERTY(SaveGame) float PikaTowersDeathNumber; //主塔死亡数 UPROPERTY(SaveGame) float PikaMainTowersDeathNumber; //准备建造塔的数量 UPROPERTY(SaveGame) TArray<int32> PikaTowerPrepareBuildingNumber; //已完成的塔的数量 UPROPERTY(SaveGame) TArray<int32> PikaTowerConstructionNumber; //已经完成的数量 UPROPERTY(SaveGame) TArray<int32> PikaTowerLikeID; //显示数字的CD UPROPERTY(SaveGame) TArray<float> PikaTowersCurrentCDNumber; //是否更新TowerCD UPROPERTY(SaveGame) TArray<bool> PikaIsUpdateTowersCDArray; /*****************玩家技能********************/ //当前技能(4个技能) UPROPERTY(SaveGame) TArray<float> PikaCurrentSkillCDArray; //处于技能中状态 UPROPERTY(SaveGame) TArray<bool> PikaIsSkillCDArray; //技能数量 UPROPERTY(SaveGame) TArray<int32> PikaSkillNumberArray; //最大技能值 UPROPERTY(SaveGame) TArray<int32> PikaMaxSkillCDArray; FPikaGodStoneSaveGameData(int32 Set_Size, bool IsSkill = false) { if (IsSkill) { PikaReSkillSzie(Set_Size); } else { PikaReSzie(Set_Size); } } FPikaGodStoneSaveGameData() { PikaMaxGameCount = 3600; PikaGameCount = 1800; PikaKillSoldierNumber = 0; PikaGold = 6000; PikaTowersDeathNumber = 0; PikaTowersCurrentCDNumber.Empty(); PikaIsUpdateTowersCDArray.Empty(); PikaTowerLikeID.Empty(); PikaTowerConstructionNumber.Empty(); PikaNumSize = 0; PikaSkillNumSize = 0; PikaCurrentSkillCDArray.Empty(); PikaIsSkillCDArray.Empty(); PikaSkillNumberArray.Empty(); PikaMaxSkillCDArray.Empty(); PikaGoldGrowthMaxTime = 1.0; PikaGoldGrowthTime = 0; } FPikaGodStoneSaveGameData& operator=(const FPikaGodStoneSaveGameData& NewObj) { PikaGameCount = NewObj.PikaGameCount; PikaMaxGameCount = NewObj.PikaMaxGameCount; PikaKillSoldierNumber = NewObj.PikaKillSoldierNumber; PikaTowersDeathNumber = NewObj.PikaTowersDeathNumber; PikaTowerPrepareBuildingNumber = NewObj.PikaTowerPrepareBuildingNumber; PikaTowerConstructionNumber = NewObj.PikaTowerConstructionNumber; PikaTowersCurrentCDNumber = NewObj.PikaTowersCurrentCDNumber; PikaGold = NewObj.PikaGetGlobalGold(); PikaTowerLikeID = NewObj.PikaTowerLikeID; PikaIsUpdateTowersCDArray = NewObj.PikaIsUpdateTowersCDArray; PikaNumSize = NewObj.PikaNumSize; PikaSkillNumSize = NewObj.PikaSkillNumSize; PikaCurrentSkillCDArray = NewObj.PikaCurrentSkillCDArray; PikaIsSkillCDArray = NewObj.PikaIsSkillCDArray; PikaSkillNumberArray = NewObj.PikaSkillNumberArray; PikaMaxSkillCDArray = NewObj.PikaMaxSkillCDArray; return *this; } //获取金币 int32 PikaGetGlobalGold()const { return PikaGold; } //添加金币 void PikaAddGlobalGold(int32 AddGold) { PikaGold += AddGold; } //减去金币 void PikaConsumeGlobalGold(int32 ConsumeGold) { PikaGold -= ConsumeGold;} //判断金币增长时间 bool PikaIsJudgement() const { return PikaGoldGrowthTime > PikaGoldGrowthMaxTime; } //关卡进度百分比 float PikaGetLevelPercentage() { return (PikaGameCount >= 0) ? PikaGameCount / PikaMaxGameCount : 0; } //清除某个数据 void PikaClearIndexData(int32 PIndex) { check(PikaTowerPrepareBuildingNumber.IsValidIndex(PIndex)); PikaTowerPrepareBuildingNumber[PIndex] = 0; PikaTowerConstructionNumber[PIndex] = 0; PikaTowersCurrentCDNumber[PIndex] = 0; PikaTowerLikeID[PIndex] = INDEX_NONE; PikaIsUpdateTowersCDArray[PIndex] = false; } //移动数据 void PikaDataMoveTo(int32 Index, int32 TargetIndex) { if (Index != TargetIndex) { PikaTowerPrepareBuildingNumber[TargetIndex] = PikaTowerPrepareBuildingNumber[Index]; PikaTowerConstructionNumber[TargetIndex] = PikaTowerConstructionNumber[Index]; PikaTowersCurrentCDNumber[TargetIndex] = PikaTowersCurrentCDNumber[Index]; PikaTowerLikeID[TargetIndex] = PikaTowerLikeID[Index]; PikaIsUpdateTowersCDArray[TargetIndex] = PikaIsUpdateTowersCDArray[Index]; PikaClearIndexData(Index); } } //是否有意义(和塔相关) bool IsActive(int32 Index) { return (PikaNumSize != 0) ? (Index >= 0 && Index < PikaNumSize) : false; } //是否有意义(和技能相关) bool IsSkillActive(int32 Index) { return (PikaSkillNumSize != 0) ? (Index >= 0 && Index < PikaSkillNumSize) : false; } //交换数据 //@:Index 需要交换的数据 //@:TargetIndex 交换的目标数据 void SwapMyData(int32 Index, int32 TargetIndex) { if (IsActive(Index) && IsActive(TargetIndex) && Index != TargetIndex) { FPikaGodStoneSaveGameData PikaTmpData(PikaNumSize); PikaTmpData.PikaTowerPrepareBuildingNumber[TargetIndex] = PikaTowerPrepareBuildingNumber[TargetIndex]; PikaTmpData.PikaTowerConstructionNumber[TargetIndex] = PikaTowerConstructionNumber[TargetIndex]; PikaTmpData.PikaTowersCurrentCDNumber[TargetIndex] = PikaTowersCurrentCDNumber[TargetIndex]; PikaTmpData.PikaTowerLikeID[TargetIndex] = PikaTowerLikeID[TargetIndex]; PikaTmpData.PikaIsUpdateTowersCDArray[TargetIndex] = PikaIsUpdateTowersCDArray[TargetIndex]; PikaTowerPrepareBuildingNumber[TargetIndex] = PikaTowerPrepareBuildingNumber[Index]; PikaTowerConstructionNumber[TargetIndex] = PikaTowerConstructionNumber[Index]; PikaTowersCurrentCDNumber[TargetIndex] = PikaTowersCurrentCDNumber[Index]; PikaTowerLikeID[TargetIndex] = PikaTowerLikeID[Index]; PikaIsUpdateTowersCDArray[TargetIndex] = PikaIsUpdateTowersCDArray[Index]; PikaTowerPrepareBuildingNumber[Index] = PikaTmpData.PikaTowerPrepareBuildingNumber[TargetIndex]; PikaTowerConstructionNumber[Index] = PikaTmpData.PikaTowerConstructionNumber[TargetIndex]; PikaTowersCurrentCDNumber[Index] = PikaTmpData.PikaTowersCurrentCDNumber[TargetIndex]; PikaTowerLikeID[Index] = PikaTmpData.PikaTowerLikeID[TargetIndex]; PikaIsUpdateTowersCDArray[Index] = PikaTmpData.PikaIsUpdateTowersCDArray[TargetIndex]; } } //重新设置尺寸 void PikaReSzie(int32 MySize) { for (int32 i = 0; i < MySize; i++) { PikaTowerPrepareBuildingNumber.Add(0); PikaTowerConstructionNumber.Add(0); PikaTowersCurrentCDNumber.Add(0.0f); PikaTowerLikeID.Add(INDEX_NONE); PikaIsUpdateTowersCDArray.Add(false); } //赋值 PikaNumSize = MySize; } //重新Skill设置尺寸 void PikaReSkillSzie(int32 MySize) { for (int32 i = 0; i < MySize; i++) { PikaCurrentSkillCDArray.Add(0.f); PikaIsSkillCDArray.Add(false); PikaSkillNumberArray.Add(0); PikaMaxSkillCDArray.Add(0); } //赋值 PikaSkillNumSize = MySize; } private: //金币 UPROPERTY(SaveGame) int32 PikaGold; //Towers数据数量 UPROPERTY(SaveGame) int32 PikaNumSize; //Skill数据数量 UPROPERTY(SaveGame) int32 PikaSkillNumSize; }; /** * */ UCLASS() class PIKAGODSTONE_API UPikaGameSaveData : public USaveGame { GENERATED_BODY() public: UPROPERTY() FPikaGodStoneSaveGameData PikaGodStongSaveData; UPROPERTY(SaveGame) uint64 PikaSaveCount; UPikaGameSaveData(); UPROPERTY(SaveGame) bool PikaIsSave; //UPROPERTY(SaveGame) //FMissionState MissionState; UPROPERTY() FPikaGameLevelManangenment PikaGameLevelManangenment; UPROPERTY() FPikaTowersData PikaTowersData; UPROPERTY() FPikaTemporaryCacheData PikaTemporaryCacheData; UPROPERTY() FPikaReadGameData PikaReadGameData; void AddStorageTime() { PikaSaveCount++; } };
PikaGameSaveData.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGameSaveData.h" UPikaGameSaveData::UPikaGameSaveData() { PikaIsSave = false; }
PikaGameSettingsAudio.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "TextBlock.h" #include "PikaGameSettingsAudio.generated.h" class UPikaUIHallGameSetting; /** * */ UCLASS() class PIKAGODSTONE_API UPikaGameSettingsAudio : public UPikaUIWidgetBase { GENERATED_BODY() UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaSoundControllSliderName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaSoundEffectSliderName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaMusicSliderName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaAudioSliderName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaSoundControllSliderTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaSoundEffectSliderTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaMusicSliderTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaAudioSliderTextName; public: //调用去初始化我们的UI virtual void PikaDrawUIToScreen()override; void PikaSetHallGameSettings(UPikaUIHallGameSetting* NewWidget) { PikaHallGameSettings = NewWidget; } virtual void PikaChangedValue(float Val) override; virtual void PikaUpdateAttibe() override; FORCEINLINE UPikaUIHallGameSetting* PikaGetHallGameSettings() const { return PikaHallGameSettings; } FORCEINLINE USlider* PikaGetSoundControllSlider() const { return PikaSoundControllSlider; } FORCEINLINE USlider* PikaGetSoundEffectSlider() const { return PikaSoundEffectSlider; } FORCEINLINE USlider* PikaGetAudioSlider() const { return PikaAudioSlider; } FORCEINLINE USlider* PikaGetMusicSlider() const { return PikaMusicSlider; } private: //总声音控件 USlider* PikaSoundControllSlider; //特效音乐 USlider* PikaSoundEffectSlider; //背景音乐 USlider* PikaMusicSlider; //按钮音效 USlider* PikaAudioSlider; UTextBlock* PikaSoundControllSliderText; UTextBlock* PikaSoundEffectSliderText; UTextBlock* PikaMusicSliderText; UTextBlock* PikaAudioSliderText; UPikaUIHallGameSetting* PikaHallGameSettings; };
PikaGameSettingsAudio.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGameSettingsAudio.h" void UPikaGameSettingsAudio::PikaDrawUIToScreen() { PikaSoundControllSlider = PikaGetSliderFormBlueprint(PikaSoundControllSliderName); PikaSoundEffectSlider = PikaGetSliderFormBlueprint(PikaSoundEffectSliderName); PikaMusicSlider = PikaGetSliderFormBlueprint(PikaMusicSliderName); PikaAudioSlider = PikaGetSliderFormBlueprint(PikaAudioSliderName); PikaSoundControllSliderText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaSoundControllSliderTextName)); PikaSoundEffectSliderText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaSoundEffectSliderTextName)); PikaMusicSliderText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaMusicSliderTextName)); PikaAudioSliderText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaAudioSliderTextName)); } void UPikaGameSettingsAudio::PikaChangedValue(float Val) { PikaUpdateAttibe(); } void UPikaGameSettingsAudio::PikaUpdateAttibe() { if (PikaSoundControllSliderText && PikaSoundControllSlider) { uint16 PikaIndexNumber = PikaSoundControllSlider->GetValue() * 10; FString PikaString_Text = FString::Printf(TEXT("%02d"), PikaIndexNumber); PikaSoundControllSliderText->SetText(FText::FromString(PikaString_Text)); } if (PikaSoundEffectSliderText && PikaSoundEffectSlider) { uint16 PikaIndexNumber = PikaSoundEffectSlider->GetValue() * 10; FString PikaString_Text = FString::Printf(TEXT("%02d"), PikaIndexNumber); PikaSoundEffectSliderText->SetText(FText::FromString(PikaString_Text)); } if (PikaMusicSliderText && PikaMusicSlider) { uint16 PikaIndexNumber = PikaMusicSlider->GetValue() * 10; FString PikaString_Text = FString::Printf(TEXT("%02d"), PikaIndexNumber); PikaMusicSliderText->SetText(FText::FromString(PikaString_Text)); } if (PikaAudioSliderText && PikaAudioSlider) { uint16 PikaIndexNumber = PikaAudioSlider->GetValue() * 10; FString PikaString_Text = FString::Printf(TEXT("%02d"), PikaIndexNumber); PikaAudioSliderText->SetText(FText::FromString(PikaString_Text)); } }
PikaGameSettingsGameSettings.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "PikaGameSettingsGameSettings.generated.h" class UPikaUIHallGameSetting; /** * */ UCLASS() class PIKAGODSTONE_API UPikaGameSettingsGameSettings : public UPikaUIWidgetBase { GENERATED_BODY() public: //调用去初始化我们的UI virtual void PikaDrawUIToScreen()override; void PikaSetHallGameSettings(UPikaUIHallGameSetting* NewWidget) { PikHallGameSettings = NewWidget; } private: UPikaUIHallGameSetting* PikHallGameSettings; };
PikaGameSettingsGameSettings.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGameSettingsGameSettings.h" void UPikaGameSettingsGameSettings::PikaDrawUIToScreen() { }
PikaGameSettingsOtherSettings.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "PikaGameSettingsOtherSettings.generated.h" class UPikaUIHallGameSetting; /** * */ UCLASS() class PIKAGODSTONE_API UPikaGameSettingsOtherSettings : public UPikaUIWidgetBase { GENERATED_BODY() public: //调用去初始化我们的UI virtual void PikaDrawUIToScreen()override; void PikaSetHallGameSettings(UPikaUIHallGameSetting* NewWidget) { PikHallGameSettings = NewWidget; } private: UPikaUIHallGameSetting* PikHallGameSettings; };
PikaGameSettingsOtherSettings.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGameSettingsOtherSettings.h" void UPikaGameSettingsOtherSettings::PikaDrawUIToScreen() { }
PikaGameSettingsVideo.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "PikaUIWidgetBase.h" #include "TextBlock.h" #include "PikaGameSettingsVideo.generated.h" class UPikaUIHallGameSetting; /** * */ UCLASS() class PIKAGODSTONE_API UPikaGameSettingsVideo : public UPikaUIWidgetBase { GENERATED_BODY() UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaResolutionBoxStringName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaFullScreenCheckBoxName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaWindowScreenCheckBoxName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaOverallScalabilityLevelSliderName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaTextureQualitySliderName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaShadowQualitySliderName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaAntiAliasingSliderName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaPostProcessingSliderName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaEffectsSliderName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaFoliageSliderName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaViewDistanceSliderName; UPROPERTY(EditDefaultsOnly, Category = "PikaUI") FName PikaFOVSliderName; //---------------------------------------------------------------- UPROPERTY(EditDefaultsOnly, Category = "PikaUIText") FName PikaOverallScalabilityLevelSliderTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUIText") FName PikaTextureQualityTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUIText") FName PikaShadowQualityTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUIText") FName PikaAntiAliasingTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUIText") FName PikaPostProcessingTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUIText") FName PikaEffectsTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUIText") FName PikaFoliageTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUIText") FName PikaViewDistanceTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUIText") FName PikaFOVTextName; UPROPERTY(EditDefaultsOnly, Category = "PikaUIText") FName PikaLanguageStringName; public: //调用去初始化我们的UI virtual void PikaDrawUIToScreen()override; virtual void PikaUpdateAttibe() override; virtual void PikaSelectionChangedBySelf(UWidget* MyWidget, FString SelectedItem, ESelectInfo::Type SelectionType) override; virtual void PikaChangedValue(float Val) override; virtual void PikaClickedCheckBox(UWidget* MyWidget, bool ClickedWidget); void PikaSetHallGameSettings(UPikaUIHallGameSetting* NewWidget) { PikaHallGameSettings = NewWidget; } FORCEINLINE UPikaUIHallGameSetting* PikaGetHallGameSettings() const { return PikaHallGameSettings; } FORCEINLINE UComboBoxString* PikaGetResolutionBoxString() const { return PikaResolutionBoxString; } //FORCEINLINE UComboBoxString* PikaGetLanguageString() const { return PikaLanguageString; } FORCEINLINE USlider* PikaGetAntiAliasingSlider() const { return PikaAntiAliasingSlider; } FORCEINLINE USlider* PikaGetShadowQualitySlider() const { return PikaShadowQualitySlider; } FORCEINLINE USlider* PikaGetTextureQualitySlider() const { return PikaTextureQualitySlider; } FORCEINLINE USlider* PikaGetFOVSlider() const { return PikaFOVSlider; } FORCEINLINE UCheckBox* PikaGetFullScreenCheckBox() const { return PikaFullScreenCheckBox; } FORCEINLINE UCheckBox* PikaGetWindowScreenCheckBox() const { return PikaWindowScreenCheckBox; } FORCEINLINE USlider* PikaGetPostProcessingSlider() const { return PikaPostProcessingSlider; } FORCEINLINE USlider* PikaGetEffectsSlider() const { return PikaEffectsSlider; } FORCEINLINE USlider* PikaGetFoliageSlider() const { return PikaFoliageSlider; } FORCEINLINE USlider* PikaGetViewDistanceSlider() const { return PikaViewDistanceSlider; } FORCEINLINE USlider* PikaGetOverallScalabilityLevelSlider() const { return PikaOverallScalabilityLevelSlider; } private: //分辨率 UComboBoxString* PikaResolutionBoxString; //全屏checkBox UCheckBox* PikaFullScreenCheckBox; //窗口checkBox UCheckBox* PikaWindowScreenCheckBox; //总级别控制 USlider* PikaOverallScalabilityLevelSlider; //贴图 USlider* PikaTextureQualitySlider; //阴影 USlider* PikaShadowQualitySlider; //抗锯齿 USlider* PikaAntiAliasingSlider; //后期 USlider* PikaPostProcessingSlider; //特效 USlider* PikaEffectsSlider; //Foliage叶子 USlider* PikaFoliageSlider; //视距 USlider* PikaViewDistanceSlider; //摄像机FOV USlider* PikaFOVSlider; //语言 //UComboBoxString* PikaLanguageString; //总级别控制数字显示 UTextBlock* PikaOverallScalabilityLevelSliderText; //贴图数字显示 UTextBlock* PikaTextureQualityText; //阴影数字显示 UTextBlock* PikaShadowQualityText; //抗锯齿数字显示 UTextBlock* PikaAntiAliasingText; //后期数字显示 UTextBlock* PikaPostProcessingText; //特效数字显示 UTextBlock* PikaEffectsText; //Foliage叶子数字显示 UTextBlock* PikaFoliageText; //视距数字显示 UTextBlock* PikaViewDistanceText; //摄像机FOV数字显示 UTextBlock* PikaFOVText; UPikaUIHallGameSetting* PikaHallGameSettings; };
PikaGameSettingsVideo.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGameSettingsVideo.h" #include "Public/PikaWorldSettings.h" void UPikaGameSettingsVideo::PikaDrawUIToScreen() { PikaResolutionBoxString = PikaGetComboBoxStringFormBlueprint(PikaResolutionBoxStringName); PikaFullScreenCheckBox = PikaGetCheckBoxFormBlueprint(PikaFullScreenCheckBoxName); PikaWindowScreenCheckBox = PikaGetCheckBoxFormBlueprint(PikaWindowScreenCheckBoxName); PikaOverallScalabilityLevelSlider = PikaGetSliderFormBlueprint(PikaOverallScalabilityLevelSliderName); PikaTextureQualitySlider = PikaGetSliderFormBlueprint(PikaTextureQualitySliderName); PikaShadowQualitySlider = PikaGetSliderFormBlueprint(PikaShadowQualitySliderName); PikaAntiAliasingSlider = PikaGetSliderFormBlueprint(PikaAntiAliasingSliderName); PikaPostProcessingSlider = PikaGetSliderFormBlueprint(PikaPostProcessingSliderName); PikaEffectsSlider = PikaGetSliderFormBlueprint(PikaEffectsSliderName); PikaFoliageSlider = PikaGetSliderFormBlueprint(PikaFoliageSliderName); PikaViewDistanceSlider = PikaGetSliderFormBlueprint(PikaViewDistanceSliderName); PikaFOVSlider = PikaGetSliderFormBlueprint(PikaFOVSliderName); //PikaLanguageString = GetComboBoxStringFormBlueprint(LanguageStringName); PikaOverallScalabilityLevelSliderText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaOverallScalabilityLevelSliderTextName)); //贴图数字显示 PikaTextureQualityText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaTextureQualityTextName)); //阴影数字显示 PikaShadowQualityText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaShadowQualityTextName)); //抗锯齿数字显示 PikaAntiAliasingText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaAntiAliasingTextName)); //后期数字显示 PikaPostProcessingText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaPostProcessingTextName)); //特效数字显示 PikaEffectsText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaEffectsTextName)); //Foliage叶子数字显示 PikaFoliageText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaFoliageTextName)); //视距数字显示 PikaViewDistanceText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaViewDistanceTextName)); //摄像机FOV数字显示 PikaFOVText = Cast<UTextBlock>(PikaqiuGetBlueprintWidget(PikaFOVTextName)); } void UPikaGameSettingsVideo::PikaUpdateAttibe() { //材质质量级别 if (PikaOverallScalabilityLevelSliderText && PikaOverallScalabilityLevelSlider) { uint16 PikaIndexNumber = PikaOverallScalabilityLevelSlider->GetValue() * 5; FString PikaString_Text = FString::Printf(TEXT("%02d"), PikaIndexNumber); PikaOverallScalabilityLevelSliderText->SetText(FText::FromString(PikaString_Text)); } //贴图 if (PikaTextureQualityText && PikaTextureQualitySlider) { uint16 PikaIndexNumber = PikaTextureQualitySlider->GetValue() * 5; FString PikaString_Text = FString::Printf(TEXT("%02d"), PikaIndexNumber); PikaTextureQualityText->SetText(FText::FromString(PikaString_Text)); } //阴影 if (PikaShadowQualityText && PikaShadowQualitySlider) { uint16 PikaIndexNumber = PikaShadowQualitySlider->GetValue() * 5; FString PikaString_Text = FString::Printf(TEXT("%02d"), PikaIndexNumber); PikaShadowQualityText->SetText(FText::FromString(PikaString_Text)); } //锯齿 if (PikaAntiAliasingText && PikaAntiAliasingSlider) { uint16 PikaIndexNumber = PikaAntiAliasingSlider->GetValue() * 5; FString PikaString_Text = FString::Printf(TEXT("%02d"), PikaIndexNumber); PikaAntiAliasingText->SetText(FText::FromString(PikaString_Text)); } //后期 if (PikaPostProcessingText && PikaPostProcessingSlider) { uint16 PikaIndexNumber = PikaPostProcessingSlider->GetValue() * 5; FString PikaString_Text = FString::Printf(TEXT("%02d"), PikaIndexNumber); PikaPostProcessingText->SetText(FText::FromString(PikaString_Text)); } //特效 if (PikaEffectsText && PikaEffectsSlider) { uint16 PikaIndexNumber = PikaEffectsSlider->GetValue() * 5; FString PikaString_Text = FString::Printf(TEXT("%02d"), PikaIndexNumber); PikaEffectsText->SetText(FText::FromString(PikaString_Text)); } //Foliage if (PikaFoliageText && PikaFoliageSlider) { uint16 PikaIndexNumber = PikaFoliageSlider->GetValue() * 5; FString PikaString_Text = FString::Printf(TEXT("%02d"), PikaIndexNumber); PikaFoliageText->SetText(FText::FromString(PikaString_Text)); } //视距 if (PikaViewDistanceText && PikaViewDistanceSlider) { uint16 PikaIndexNumber = PikaViewDistanceSlider->GetValue() * 5; FString PikaString_Text = FString::Printf(TEXT("%02d"), PikaIndexNumber); PikaViewDistanceText->SetText(FText::FromString(PikaString_Text)); } //相机FOV if (PikaFOVText && PikaFOVSlider) { //最大值 float PikaMaxValue = 240; float PikaIndexNumber = PikaFOVSlider->GetValue() * PIKA_FOVMAX_VALUE + 40.0f; FString PikaString_Text = FString::Printf(TEXT("%02d"), (int32)PikaIndexNumber); PikaFOVText->SetText(FText::FromString(PikaString_Text)); } } void UPikaGameSettingsVideo::PikaSelectionChangedBySelf(UWidget* MyWidget, FString SelectedItem, ESelectInfo::Type SelectionType) { //关于分辨率的一些设置 if (MyWidget == PikaResolutionBoxString) { } } void UPikaGameSettingsVideo::PikaChangedValue(float Val) { PikaUpdateAttibe(); } void UPikaGameSettingsVideo::PikaClickedCheckBox(UWidget* MyWidget, bool ClickedWidget) { if (MyWidget == PikaFullScreenCheckBox) { if (PikaWindowScreenCheckBox && PikaWindowScreenCheckBox->GetCheckedState() == ECheckBoxState::Checked) { PikaWindowScreenCheckBox->SetCheckedState(ECheckBoxState::Unchecked); } } if (MyWidget == PikaWindowScreenCheckBox) { if (PikaFullScreenCheckBox && PikaFullScreenCheckBox->GetCheckedState() == ECheckBoxState::Checked) { PikaFullScreenCheckBox->SetCheckedState(ECheckBoxState::Unchecked); } } }
PikaGameUserSettings.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/GameUserSettings.h" #include "Sound/SoundClass.h" #include "PikaGameUserSettings.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API UPikaGameUserSettings : public UGameUserSettings { GENERATED_BODY() public: //用UPROPERTY(config)形式定义的变量,会自动存储到ini设置里 //背景音乐 UPROPERTY(config) float PikaBackgroundSoundControl; //特效音乐 UPROPERTY(config) float PikaEffectsSoundControl; //分辨率 UPROPERTY(config) float PikaResolution_HControl; UPROPERTY(config) float PikaResolution_WControl; //屏幕模式 //0-窗口 1-全屏 UPROPERTY(config) float PikaScreenModeControl; //总控制 UPROPERTY(config) float PikaOverallScalabilityLevelControl; //贴图 UPROPERTY(config) float PikaTextureQualityControl; //阴影 UPROPERTY(config) float PikaShadowQualityControl; //抗锯齿 UPROPERTY(config) float PikaAntiAliasingControl; //后期 UPROPERTY(config) float PikaPostProcessingControl; //特效 UPROPERTY(config) float PikaEffectsControl; //Foliage叶子 UPROPERTY(config) float PikaFoliageControl; //视距 UPROPERTY(config) float PikaViewDistanceControl; //FOV UPROPERTY(config) float PikaCameraFOV; UPikaGameUserSettings(); static UPikaGameUserSettings* PikaGetGameUserSettings(); virtual void ApplySettings(bool bCheckForCommandLineOverrides)override; TArray<USoundClass*> PikaGetAllMusicClass(); virtual void LoadSettings(bool bForceReload = false) override; virtual void SaveSettings() override; void PikaSeveIni(); bool PikaLoadIni(); virtual void SetToDefaults()override; void PikaPlayBGM(); //设置屏幕模式和分辨率 void PikaSetVideo(); /*PiksWorldStart*/ virtual class UWorld* GetWorld() const; void PikaSetretrieveWorldContext(UWorld* NewWorld); /*PiksWorldEnd*/ private: class UWorld * PikaWorld; };
PikaGameUserSettings.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGameUserSettings.h" #include "Sound/AmbientSound.h" #include "Components/AudioComponent.h" //PikaGameUserSettings属于ini配置类,该构造函数只会在代码编译时调用一次,在运行中不会再次执行 UPikaGameUserSettings::UPikaGameUserSettings() { if (!PikaLoadIni()) { SetToDefaults(); } } UPikaGameUserSettings* UPikaGameUserSettings::PikaGetGameUserSettings() { return GEngine != NULL ? ((UPikaGameUserSettings*)GEngine->GetGameUserSettings()) : NULL; } void UPikaGameUserSettings::ApplySettings(bool bCheckForCommandLineOverrides) { Super::ApplySettings(bCheckForCommandLineOverrides); //背景音乐 if (GetWorld()) { TArray<USoundClass*> PikaTmpSound = PikaGetAllMusicClass(); for (USoundClass* PikaNewSoundClass : PikaTmpSound) { if (PikaNewSoundClass->GetFullName().Contains(TEXT("Master"))) { //总体音量 PikaNewSoundClass->Properties.Volume = PikaBackgroundSoundControl * PikaqiuTotalSoundControl; } } TArray<AActor*> PikaClassArrayTmp; TArray<USoundClass*> PikaSoundClassArray; PikaGETALLACTOR(GetWorld(), AAmbientSound::StaticClass(), PikaClassArrayTmp); for (AActor* PikaSound_m : PikaClassArrayTmp) { AAmbientSound* PikaAmbient_sound = Cast<AAmbientSound>(PikaSound_m); PikaAmbient_sound->AdjustVolume(1, PikaBackgroundSoundControl * PikaqiuTotalSoundControl); } } // Apply the new settings and save them Scalability::SetQualityLevels(ScalabilityQuality); Scalability::SaveState(GGameUserSettingsIni); //存储到配置 PikaSeveIni(); } TArray<USoundClass*> UPikaGameUserSettings::PikaGetAllMusicClass() { TArray<AActor*> PikaClassArrayTmp; TArray<USoundClass*> PikaSoundClassArray; PikaGETALLACTOR(GetWorld(), AAmbientSound::StaticClass(), PikaClassArrayTmp); for (AActor* PikaSound_m : PikaClassArrayTmp) { AAmbientSound* PikaAmbient_sound = Cast<AAmbientSound>(PikaSound_m); if (PikaAmbient_sound && PikaAmbient_sound->GetAudioComponent() && PikaAmbient_sound->GetAudioComponent()->Sound && PikaAmbient_sound->GetAudioComponent()->Sound->DefaultSoundClassObject ) { PikaSoundClassArray.Add(PikaAmbient_sound->GetAudioComponent()->Sound->DefaultSoundClassObject); } } return PikaSoundClassArray; } void UPikaGameUserSettings::LoadSettings(bool bForceReload /*= false*/) { Super::LoadSettings(bForceReload); PikaLoadIni(); } void UPikaGameUserSettings::SaveSettings() { Super::SaveSettings(); } void UPikaGameUserSettings::PikaSeveIni() { const TCHAR* PikaSection = TEXT("PikaGodStoneINI"); // looks like cvars but here we just use the name for the ini GConfig->SetFloat(PikaSection, TEXT("PikaIni_BackgroundSoundControl"), PikaBackgroundSoundControl, GGameUserSettingsIni); GConfig->SetFloat(PikaSection, TEXT("PikaIni_EffectsSoundControl"), PikaEffectsSoundControl, GGameUserSettingsIni); GConfig->SetFloat(PikaSection, TEXT("PikaIni_ButtonSoundControl"), PikaqiuButtonSoundControl, GGameUserSettingsIni); GConfig->SetFloat(PikaSection, TEXT("PikaIni_TotalSoundControl"), PikaqiuTotalSoundControl, GGameUserSettingsIni); /*//图像设置 //分辨率 GConfig->SetFloat(PikaSection, TEXT("PikaIni_Resolution_H"), PikaResolution_HControl, GGameUserSettingsIni); GConfig->SetFloat(PikaSection, TEXT("PikaIni_Resolution_W"), PikaResolution_WControl, GGameUserSettingsIni); //屏幕模式 //0-窗口 1-全屏 GConfig->SetFloat(PikaSection, TEXT("PikaIni_ScreenMode"), PikaScreenModeControl, GGameUserSettingsIni); //总控制 GConfig->SetFloat(PikaSection, TEXT("PikaIni_OverallScalabilityLevel"), PikaOverallScalabilityLevelControl, GGameUserSettingsIni); //贴图 GConfig->SetFloat(PikaSection, TEXT("PikaIni_TextureQuality"), PikaTextureQualityControl, GGameUserSettingsIni); //阴影 GConfig->SetFloat(PikaSection, TEXT("sg.ShadowQuality"), PikaShadowQualityControl, GGameUserSettingsIni); //抗锯齿 GConfig->SetFloat(PikaSection, TEXT("PikaIni_AntiAliasing"), PikaAntiAliasingControl, GGameUserSettingsIni); //后期 GConfig->SetFloat(PikaSection, TEXT("PikaIni_PostProcessing"), PikaPostProcessingControl, GGameUserSettingsIni); //特效 GConfig->SetFloat(PikaSection, TEXT("PikaIni_Effects"), PikaEffectsControl, GGameUserSettingsIni); //Foliage叶子 GConfig->SetFloat(PikaSection, TEXT("PikaIni_Foliage"), PikaFoliageControl, GGameUserSettingsIni); //视距 GConfig->SetFloat(PikaSection, TEXT("PikaIni_ViewDistance"), PikaViewDistanceControl, GGameUserSettingsIni); //FOV GConfig->SetFloat(PikaSection, TEXT("PikaIni_CameraFOV"), PikaCameraFOV, GGameUserSettingsIni);*/ //GConfig->SetString(PikaSection, TEXT("sg.TDLanguage"), *GetCurrentLanguageType(), GGameUserSettingsIni); } bool UPikaGameUserSettings::PikaLoadIni() { const TCHAR* PikaSection = TEXT("PikaGodStoneINI"); FString PikaLanguageStr = ""; bool PikaIsLoadSuc = GConfig->GetFloat(PikaSection, TEXT("PikaIni_BackgroundSoundControl"), PikaBackgroundSoundControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_EffectsSoundControl"), PikaEffectsSoundControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_ButtonSoundControl"), PikaqiuButtonSoundControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_TotalSoundControl"), PikaqiuTotalSoundControl, GGameUserSettingsIni); /*GConfig->GetFloat(PikaSection, TEXT("PikaIni_Resolution_H"), PikaResolution_HControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_Resolution_W"), PikaResolution_WControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_ScreenMode"), PikaScreenModeControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_OverallScalabilityLevel"), PikaOverallScalabilityLevelControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_TextureQuality"), PikaTextureQualityControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_ShadowQuality"), PikaShadowQualityControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_AntiAliasing"), PikaAntiAliasingControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_PostProcessing"), PikaPostProcessingControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_Effects"), PikaEffectsControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_Foliage"), PikaFoliageControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_ViewDistance"), PikaViewDistanceControl, GGameUserSettingsIni) && GConfig->GetFloat(PikaSection, TEXT("PikaIni_CameraFOV"), PikaCameraFOV, GGameUserSettingsIni);*/ //GConfig->GetString(PikaSection, TEXT("sg.TDLanguage"), PikaLanguageStr, GGameUserSettingsIni) && //设置语言 //if (LanguageStr != "") //SetCuurrLanguage(LanguageStr); //return PikaIsLoadSuc; return true; } void UPikaGameUserSettings::SetToDefaults() { Super::SetToDefaults(); //背景音乐 PikaBackgroundSoundControl = 1.0f; //特效音乐 PikaEffectsSoundControl = 1.0f; PikaqiuTotalSoundControl = 1.0f; PikaqiuButtonSoundControl = 1.0f; //图像设置 //分辨率 PikaResolution_HControl = 800; PikaResolution_WControl = 600; //屏幕模式 PikaScreenModeControl = 1.0f; //总控制 PikaOverallScalabilityLevelControl = 0.5f; //贴图 PikaTextureQualityControl = 0.5f; //阴影 PikaShadowQualityControl = 0.5f; //抗锯齿 PikaAntiAliasingControl = 0.5f; //后期 PikaPostProcessingControl = 0.5f; //特效 PikaEffectsControl = 0.5f; //Foliage叶子 PikaFoliageControl = 0.5f; //视距 PikaViewDistanceControl = 0.5f; //FOV PikaCameraFOV = 90.f; } void UPikaGameUserSettings::PikaPlayBGM() { //背景音乐,由gameMode调用 if (GetWorld()) { TArray<AActor*> PikaClassArrayTmp; TArray<USoundClass*> PikaSoundClassArray; PikaGETALLACTOR(GetWorld(), AAmbientSound::StaticClass(), PikaClassArrayTmp); for (AActor* PikaSound_m : PikaClassArrayTmp) { AAmbientSound* PikaAmbient_sound = Cast<AAmbientSound>(PikaSound_m); PikaAmbient_sound->AdjustVolume(1, PikaBackgroundSoundControl * PikaqiuTotalSoundControl); } } } //由gameMode调用 void UPikaGameUserSettings::PikaSetVideo() { //分辨率 SetScreenResolution(GetScreenResolution()); //屏幕模式 SetFullscreenMode(GetLastConfirmedFullscreenMode()); } class UWorld* UPikaGameUserSettings::GetWorld() const { return PikaWorld; } void UPikaGameUserSettings::PikaSetretrieveWorldContext(UWorld* NewWorld) { PikaWorld = NewWorld; }
PikaGameViewportClient.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Engine/GameViewportClient.h" #include "SlateDynamicImageBrush.h" #include "SCompoundWidget.h" #include "PikaGameViewportClient.generated.h" struct PikaFShooterGameLoadingScreenBrush : public FSlateDynamicImageBrush, public FGCObject { PikaFShooterGameLoadingScreenBrush(const FName InTextureName, const FVector2D& InImageSize) : FSlateDynamicImageBrush(InTextureName, InImageSize) { ResourceObject = LoadObject<UObject>(NULL, *InTextureName.ToString()); } virtual void AddReferencedObjects(FReferenceCollector& Collector) { if (ResourceObject) { Collector.AddReferencedObject(ResourceObject); } } }; class PikaSShooterLoadingScreen : public SCompoundWidget { public: SLATE_BEGIN_ARGS(PikaSShooterLoadingScreen) {} SLATE_END_ARGS() void Construct(const FArguments& InArgs); private: EVisibility PikaGetLoadIndicatorVisibility() const { return EVisibility::Visible; } /** loading screen image brush */ TSharedPtr<FSlateDynamicImageBrush> PikaLoadingScreenBrush; }; /** * */ UCLASS() class PIKAGODSTONE_API UPikaGameViewportClient : public UGameViewportClient { GENERATED_BODY() public: UPikaGameViewportClient(); void PikaShowLoadingScreen(); void PikaHideLoadingScreen(); private: void PikaHideExistingWidgets(); void PikaShowExistingWidgets(); TSharedPtr<PikaSShooterLoadingScreen> PikaLoadingScreenWidget; TArray<TSharedRef<class SWidget>> PikaHiddenViewportContentStack; TArray<TSharedRef<class SWidget>> PikaViewportContentStack; };
PikaGameViewportClient.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGameViewportClient.h" UPikaGameViewportClient::UPikaGameViewportClient() { } void UPikaGameViewportClient::PikaShowLoadingScreen() { if (PikaLoadingScreenWidget.IsValid()) { return; } PikaLoadingScreenWidget = SNew(PikaSShooterLoadingScreen); AddViewportWidgetContent(PikaLoadingScreenWidget.ToSharedRef()); } void UPikaGameViewportClient::PikaHideLoadingScreen() { if (!PikaLoadingScreenWidget.IsValid()) { return; } //销毁LoadingScreenWidget RemoveViewportWidgetContent(PikaLoadingScreenWidget.ToSharedRef()); PikaLoadingScreenWidget = NULL; } void UPikaGameViewportClient::PikaHideExistingWidgets() { check(PikaHiddenViewportContentStack.Num() == 0); TArray<TSharedRef<class SWidget>> PikaCopyOfViewportContentStack = PikaViewportContentStack; for (int32 i = PikaViewportContentStack.Num() - 1; i >= 0; i--) { RemoveViewportWidgetContent(PikaViewportContentStack[i]); } PikaHiddenViewportContentStack = PikaCopyOfViewportContentStack; } void UPikaGameViewportClient::PikaShowExistingWidgets() { check(PikaViewportContentStack.Num() == 0); for (int32 i = 0; i < PikaHiddenViewportContentStack.Num(); i++) { AddViewportWidgetContent(PikaHiddenViewportContentStack[i]); } check(PikaViewportContentStack.Num() == PikaHiddenViewportContentStack.Num()); PikaHiddenViewportContentStack.Empty(); } void PikaSShooterLoadingScreen::Construct(const FArguments& InArgs) { //static const FName PikaLoadingScreenName(TEXT("/Game/Movies/PikaLoading")); //PikaLoadingScreenBrush = MakeShareable(new PikaFShooterGameLoadingScreenBrush(PikaLoadingScreenName, FVector2D(1920, 1080))); /*ChildSlot [ SNew(SOverlay) + SOverlay::Slot() .HAlign(HAlign_Fill) .VAlign(VAlign_Fill) [ SNew(SImage) .Image(PikaLoadingScreenBrush.Get()) ] + SOverlay::Slot() .HAlign(HAlign_Fill) .VAlign(VAlign_Fill) [ SNew(SSafeZone) .VAlign(VAlign_Bottom) .HAlign(HAlign_Right) .Padding(10.0f) .IsTitleSafe(true) [ SNew(SThrobber) .Visibility(this, &PikaSShooterLoadingScreen::GetLoadIndicatorVisibility) ] ] ];*/ }
PikaGlobalConfig.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "PikaGameSaveData.h" #include "PikaGlobalConfig.generated.h" //鼠标全局配置结构体 USTRUCT() struct FPikaMouseSettingConfiguration { GENERATED_USTRUCT_BODY() //蓝图的配置方式 //UPROPERTY(EditDefaultsOnly, Category = "PikaGlobal") //float MouseSpeed; public: //c++的配置方式 float MouseSpeed; //QE键模型的旋转角度 float PikaAngleOfRotation; FPikaMouseSettingConfiguration(); }; /** * */ //蓝图下的配置方式 //UCLASS(Blueprintable) UCLASS() class PIKAGODSTONE_API UPikaGlobalConfig : public UObject { GENERATED_BODY() UPROPERTY(Transient) bool PikaSkillPermissions; public: UPikaGlobalConfig(); //蓝图的配置方式 //UPROPERTY(EditDefaultsOnly , Category = "GlobalConfig") //FPikaMouseSettingConfiguration PikaMouseSetConf; //c++的配置方式 UPROPERTY() FPikaMouseSettingConfiguration PikaMouseSetConf; //游戏UI相关数据,包括游戏快捷栏内物品,玩家技能等 UPROPERTY() FPikaGodStoneSaveGameData PikaGameData; //是否是存储的数据经过读取而来,默认是非读取状态 bool PikaIsSave; //鼠标缩放数据记录 float PikaMouseZoom; //游戏存储 uint64 PikaSaveCount; //关卡游戏规则相关的数据 UPROPERTY() FPikaGameLevelManangenment PikaGameLevelManangenment; // UPROPERTY() FPikaTowersData PikaTowersData; //游戏场景内角色的数据 UPROPERTY() FPikaTemporaryCacheData PikaTemporaryCacheData; //描述数据的数据 //UPROPERTY() //FPikaReadGameData PikaReadGameData; //GameStory FPikaGameStory PikaGameStory; //UPROPERTY() //FCurrentLevelCondition CurrentLevelCondition; //UPROPERTY() //FMissionState MissionState; void PikaSetSkillPermissions(bool IsPermissions) { PikaSkillPermissions = IsPermissions; } //数据初始化完毕 FORCEINLINE void PikaInitializationDataComplete() { PikaIsSave = false; } //使用技能的权限 FORCEINLINE bool PikaGetPlayerSkillPermissions() const { return PikaSkillPermissions; } };
PikaGlobalConfig.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGlobalConfig.h" FPikaMouseSettingConfiguration::FPikaMouseSettingConfiguration() { //c++方式配置的实始化 MouseSpeed = 50.f; PikaAngleOfRotation = 15.f; } UPikaGlobalConfig::UPikaGlobalConfig() : PikaSkillPermissions(true), PikaIsSave(false) { PikaSaveCount = 0; PikaMouseZoom = 1; }
PikaGodStoneCamera.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Pawn.h" #include "GameFramework/SpringArmComponent.h" #include "Camera/CameraComponent.h" #include "Components/BoxComponent.h" #include "PikaGodStoneCamera.generated.h" UCLASS() class PIKAGODSTONE_API APikaGodStoneCamera : public APawn { GENERATED_BODY() //摄像机组件 //根组件 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) USceneComponent* PikaCameraRootComponent; //控制摄像机离场景的距离 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) USpringArmComponent * PikaCameraBoom; //主摄像机 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) UCameraComponent * PikaMainCamera; //摄像机的碰撞标识 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true")) UBoxComponent * PikaMarkBox; public: // Sets default values for this pawn's properties APikaGodStoneCamera(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: // Called every frame virtual void Tick(float DeltaTime) override; // Called to bind functionality to input virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; //摄像机缩放,MouseSpeed该值由playerController传进来 void PikaCameraZoom(bool ZoomDirection, float MouseSpeed); void PikaSetCameraFOV(float NewFOV); //获取摄像机 FORCEINLINE UCameraComponent* PikaGetMainCamera() const { return PikaMainCamera; } //获取FOV FORCEINLINE float PikaGetCameraFOV() const { return PikaGetMainCamera() ? PikaGetMainCamera()->FieldOfView : 0; } };
PikaGodStoneCamera.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGodStoneCamera.h" // Sets default values APikaGodStoneCamera::APikaGodStoneCamera() { // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; //创建组件 //CreateDefaultSubobject该创建object的方法只能用在构造函数里,非构造函数要用其它创建方式,如newObject PikaCameraRootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("PikaCameraRootComponent")); PikaCameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("PikaCameraBoom")); PikaMainCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("PikaMainCamera")); PikaMarkBox = CreateDefaultSubobject<UBoxComponent>(TEXT("PikaHitSign")); //赋值根组件 RootComponent = PikaCameraRootComponent; //绑定组件 PikaCameraBoom->AttachToComponent(PikaCameraRootComponent, FAttachmentTransformRules::KeepRelativeTransform); PikaMainCamera->AttachToComponent(PikaCameraBoom, FAttachmentTransformRules::KeepRelativeTransform); PikaMarkBox->AttachToComponent(PikaCameraRootComponent, FAttachmentTransformRules::KeepRelativeTransform); //设置摄像机角距离地面的长度 PikaCameraBoom->TargetArmLength = 800.f; PikaCameraBoom->RelativeRotation = FRotator(-60.f, 0, 0); //碰撞,QueryOnly表示只能有碰撞和重叠 PikaMarkBox->SetCollisionEnabled(ECollisionEnabled::QueryOnly); //忽略所有通道,然后单独开启ECC_Visibility和ECC_WorldDynamic这两个通道 PikaMarkBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore); PikaMarkBox->SetCollisionResponseToChannel(ECollisionChannel::ECC_Visibility, ECollisionResponse::ECR_Overlap); PikaMarkBox->SetCollisionResponseToChannel(ECollisionChannel::ECC_WorldDynamic, ECollisionResponse::ECR_Overlap); } // Called when the game starts or when spawned void APikaGodStoneCamera::BeginPlay() { Super::BeginPlay(); } // Called every frame void APikaGodStoneCamera::Tick(float DeltaTime) { Super::Tick(DeltaTime); } // Called to bind functionality to input void APikaGodStoneCamera::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); } //缩放控制 void APikaGodStoneCamera::PikaCameraZoom(bool ZoomDirection, float MouseSpeed) { if (ZoomDirection) { //判断摄像机组件是否存在 if (PikaCameraBoom) { //PikaMinZoomVal为缩放的最小值 int32 PikaMinZoomVal = 400; if (PikaCameraBoom->TargetArmLength > PikaMinZoomVal) { PikaCameraBoom->TargetArmLength -= (MouseSpeed * 2); } } } else { if (PikaCameraBoom) { //PikaMaxZoomVal为缩放的最大值 int32 PikaMaxZoomVal = 1600; if (PikaCameraBoom->TargetArmLength < PikaMaxZoomVal) { PikaCameraBoom->TargetArmLength += (MouseSpeed * 2); } } } } void APikaGodStoneCamera::PikaSetCameraFOV(float NewFOV) { if (PikaGetMainCamera()) { PikaGetMainCamera()->SetFieldOfView(NewFOV); } }
PikaGodStoneGameInstance.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "Engine/GameInstance.h" #include "PikaGameSaveData.h" #include "PikaGlobalConfig.h" #include "PikaGodStoneGameInstance.generated.h" #define PikaSTANDARD_VALUE 1 /** * */ UCLASS() class PIKAGODSTONE_API UPikaGodStoneGameInstance : public UGameInstance { GENERATED_BODY() UPROPERTY() FString PikaCurrentSaveSlotName; //Loading界面 //Loading需要在PikaGodStone.Build.cs里添加"MoviePlayer"模块 TSubclassOf<UUserWidget> PikaUI_LoadingTemplate; UUserWidget* PikaLoadingWidget; UPikaGameSaveData* PikaGodStoneGaveSaveDataPtr; public: UPikaGodStoneGameInstance(); virtual void Init(); //解决UPikaGodStoneGameInstance的构造执行时,GetWorld还没有初始化完成的问题 virtual FGameInstancePIEResult InitializeForPlayInEditor(int32 PIEInstanceIndex, const FGameInstancePIEParameters& Params) override; UPikaGameSaveData* PikaGetGameSaveData() { return PikaGodStoneGaveSaveDataPtr;} //游戏全局的时间增量的设置 void PikaSetGlobalGameTime(float TimeDilation = 0); //Loading void PikaShowLoadingScreen(); UFUNCTION() virtual void BeginLoadingScreen(const FString& MapName); UFUNCTION() virtual void EndLoadingScreen(UWorld* NewWorld); bool PikaIsLoadingFinsh(); //////////////////////////////////////读取和存储//////////////////////////////////// //作为临时读取之用 int32 PikaTmpArchive; //验证存档,如果没有就创建一个 UPikaGameSaveData* PikaVerificationSaveData()const; //存储我们的游戏数据 bool PikaSaveGameData(UPikaGlobalConfig* EnvironmentConfiguration, PikaFSaveSlotDataChannel SaveSlotDataChannel); //读取存档的序列号 void PikaSetCurrentSaveSloatNmber(int32 NewNumber); FORCEINLINE FString PikaGetCurrentGameSaveName() const { return PikaCurrentSaveSlotName; } //是否可以读取进度 bool PikaIsLoadingGameData(int32 SaveNumber); //获取当前存储了多少个存档,返回值将做为下一次创建新存档时的index int32 PikaGetCurrentSaveArchiveNumber()const; //删除存档 bool PikaDeleteGameData(int32 SaveNumber); private: //关联我们的游戏数据搭配存储点 bool PikaCorrelationGameData(UPikaGlobalConfig* EnvironmentConfiguration, PikaFSaveSlotDataChannel SaveSlotDataChannel); };
PikaGodStoneGameInstance.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGodStoneGameInstance.h" #include "ConstructorHelpers.h" #include "../MoviePlayer/Public/MoviePlayer.h" #include "UserWidget.h" #include "Public/PikaGameViewportClient.h" UPikaGodStoneGameInstance::UPikaGodStoneGameInstance() { //载入Loading ConstructorHelpers::FClassFinder<UUserWidget> PikaTmpLoading(TEXT("/Game/HUD/OtherUI/LoadingBP")); PikaUI_LoadingTemplate = PikaTmpLoading.Class; PikaTmpArchive = INDEX_NONE; } void UPikaGodStoneGameInstance::Init() { Super::Init(); //对两个Loading代理进行绑定 FCoreUObjectDelegates::PreLoadMap.AddUObject(this, &UPikaGodStoneGameInstance::BeginLoadingScreen); FCoreUObjectDelegates::PostLoadMapWithWorld.AddUObject(this, &UPikaGodStoneGameInstance::EndLoadingScreen); } FGameInstancePIEResult UPikaGodStoneGameInstance::InitializeForPlayInEditor(int32 PIEInstanceIndex, const FGameInstancePIEParameters& Params) { FGameInstancePIEResult PIEResult = Super::InitializeForPlayInEditor(PIEInstanceIndex , Params); TSubclassOf<UPikaGameSaveData> PikaMySaveGame = UPikaGameSaveData::StaticClass(); if (GetWorld() && PikaMySaveGame) { PikaGodStoneGaveSaveDataPtr = NewObject<UPikaGameSaveData>(GetWorld(), PikaMySaveGame); } return PIEResult; } //游戏全局的时间增量的设置 void UPikaGodStoneGameInstance::PikaSetGlobalGameTime(float TimeDilation /*= 0*/) { if (GetWorld() && GetWorld()->GetWorldSettings()) { float const PikaActualTimeDilation = GetWorld()->GetWorldSettings()->SetTimeDilation(TimeDilation); /*if (TimeDilation != PikaActualTimeDilation) { UE_LOG(LogBlueprintUserMessages, Warning, TEXT("Time Dilation must be between %f and %f. Clamped value to that range."), GetWorld()->GetWorldSettings()->MinGlobalTimeDilation, GetWorld()->GetWorldSettings()->MaxGlobalTimeDilation); }*/ } } void UPikaGodStoneGameInstance::PikaShowLoadingScreen() { if (!IsRunningDedicatedServer()) { FLoadingScreenAttributes PikaLoadingScreen; PikaLoadingScreen.bAutoCompleteWhenLoadingCompletes = true; PikaLoadingScreen.bMoviesAreSkippable = true;//任意键打断如果加载完成 PikaLoadingScreen.bWaitForManualStop = false;// PikaLoadingScreen.PlaybackType = EMoviePlaybackType::MT_Looped; if (!PikaLoadingWidget) PikaLoadingWidget = CreateWidget<UUserWidget>(this, PikaUI_LoadingTemplate); if (PikaLoadingWidget) { PikaLoadingScreen.WidgetLoadingScreen = PikaLoadingWidget->TakeWidget(); //添加mp4文件,位置为Content\Movies\PikaLoading.mp4 PikaLoadingScreen.MoviePaths.Add("PikaLoading"); GetMoviePlayer()->SetupLoadingScreen(PikaLoadingScreen); } } UPikaGameViewportClient * PikaShooterViewport = Cast<UPikaGameViewportClient>(GetGameViewportClient()); if (PikaShooterViewport != NULL) { PikaShooterViewport->PikaShowLoadingScreen(); } } void UPikaGodStoneGameInstance::BeginLoadingScreen(const FString& MapName) { PikaShowLoadingScreen(); if (GetGameViewportClient()) GetGameViewportClient()->SetDisableSplitscreenOverride(false); } void UPikaGodStoneGameInstance::EndLoadingScreen(UWorld* NewWorld) { UPikaGameViewportClient * PikaShooterViewport = Cast<UPikaGameViewportClient>(GetGameViewportClient()); if (PikaShooterViewport != NULL) { if (PikaLoadingWidget) { PikaLoadingWidget = nullptr; } //进行销毁工作 PikaShooterViewport->PikaHideLoadingScreen(); } } bool UPikaGodStoneGameInstance::PikaIsLoadingFinsh() { return false; } //验证存档,如果没有就创建一个 UPikaGameSaveData* UPikaGodStoneGameInstance::PikaVerificationSaveData() const { //读取游戏存档在本地 UPikaGameSaveData* PikaGameSaveData = Cast<UPikaGameSaveData>(PIKA_LOADGAME_SLOT(PIKA_SAVE_SLOT_NAME, 0)); //获取存档信息 if (!PikaGameSaveData) { PikaGameSaveData = Cast<UPikaGameSaveData>(PIKA_CREATESAVE_SLOT(UPikaGameSaveData::StaticClass())); if (PikaGameSaveData) PIKA_SAVE_SLOT(PikaGameSaveData, PIKA_SAVE_SLOT_NAME, 0); else UE_LOG(LogTemp, Error, TEXT("There was a problem with the stored content at initialization time")); } return PikaGameSaveData; } bool UPikaGodStoneGameInstance::PikaSaveGameData(UPikaGlobalConfig* EnvironmentConfiguration, PikaFSaveSlotDataChannel SaveSlotDataChannel) { if (EnvironmentConfiguration) { //存档,提取数据 return PikaCorrelationGameData(EnvironmentConfiguration, SaveSlotDataChannel); } return false; } void UPikaGodStoneGameInstance::PikaSetCurrentSaveSloatNmber(int32 NewNumber) { PikaCurrentSaveSlotName = PIKA_SAVE_GAME_NAME + FString::FromInt(NewNumber); } bool UPikaGodStoneGameInstance::PikaIsLoadingGameData(int32 SaveNumber) { if (SaveNumber != INDEX_NONE) { //读取游戏存档在本地 UPikaGameSaveData* PikaNewSaveDatas = Cast<UPikaGameSaveData>(PIKA_LOADGAME_SLOT(PIKA_SAVE_GAME_NAME + FString::FromInt(SaveNumber), 0)); if (PikaNewSaveDatas) { //还原游戏数据 return true; } } return false; } //获取PIKA_SAVE_SLOT_NAME存档里第一个空位置的index,以该index还作为本次存档的index int32 UPikaGodStoneGameInstance::PikaGetCurrentSaveArchiveNumber() const { UPikaGameSaveData* PikaSaveSlot = Cast<UPikaGameSaveData>(PIKA_LOADGAME_SLOT(PIKA_SAVE_SLOT_NAME, 0)); if (PikaSaveSlot) { return PikaSaveSlot->PikaReadGameData.PikaGetSerialNumber(); } else { PikaSaveSlot = PikaVerificationSaveData(); if (PikaSaveSlot) { return PikaSaveSlot->PikaReadGameData.PikaGetSerialNumber(); } else { UE_LOG(LogTemp, Error, TEXT("There was a problem with the stored content at initialization time")); } } return INDEX_NONE; } bool UPikaGodStoneGameInstance::PikaDeleteGameData(int32 SaveNumber) { if (SaveNumber != INDEX_NONE) { if (PIKA_ISSAVE_SLOT(PIKA_SAVE_GAME_NAME + FString::FromInt(SaveNumber), 0)) { //让数据默认显示,防止溢出 UPikaGameSaveData* PikaNewSoltGameData = Cast<UPikaGameSaveData>(PIKA_LOADGAME_SLOT(PIKA_SAVE_SLOT_NAME, 0)); if (PikaNewSoltGameData) { //将PIKA_SAVE_SLOT_NAME存档里对应的数据项删除 PikaNewSoltGameData->PikaReadGameData.PikaClearReadGameDataAt(SaveNumber); return (PIKA_DELETEGAME_SLOT(PIKA_SAVE_GAME_NAME + FString::FromInt(SaveNumber), 0) && PIKA_SAVE_SLOT(PikaNewSoltGameData, PIKA_SAVE_SLOT_NAME, 0)); } } } return false; } //关联我们的游戏数据搭配存储点 bool UPikaGodStoneGameInstance::PikaCorrelationGameData(UPikaGlobalConfig* GlobalConfig, PikaFSaveSlotDataChannel SaveSlotDataChannel) { //存储的序列号ID //PikaGameSaveSlot为游戏里整个存档数组里,存档时间和存档编号的信息 //PikaGameSaveDatas为单个PikaUISaveLoadBar里对应的存档信息 bool PikaIsGameSaveDatas = false; bool PikaIsGameSaveSlot = false; UPikaGameSaveData* PikaGameSaveDatas = Cast<UPikaGameSaveData>(PIKA_CREATESAVE_SLOT(UPikaGameSaveData::StaticClass())); UPikaGameSaveData* PikaGameSaveSlot = Cast<UPikaGameSaveData>(PIKA_LOADGAME_SLOT(PIKA_SAVE_SLOT_NAME, 0)); //////////////////////////////////数据判断//////////////////////////////////////// //判断GameSaveSlot是否存在 if (PikaGameSaveSlot) { PikaIsGameSaveSlot = true; } else { PikaGameSaveSlot = Cast<UPikaGameSaveData>(PIKA_CREATESAVE_SLOT(UPikaGameSaveData::StaticClass())); if (PikaGameSaveSlot) { PikaIsGameSaveSlot = true; } } //判断GameSaveDatas是否存在 if (PikaGameSaveDatas) { PikaIsGameSaveDatas = true; } else { PikaGameSaveDatas = Cast<UPikaGameSaveData>(PIKA_CREATESAVE_SLOT(UPikaGameSaveData::StaticClass())); if (PikaGameSaveDatas) PikaIsGameSaveDatas = true; } //////////////////////////////////数据保存//////////////////////////////////////// //执行GameSaveSlot保存 if (PikaIsGameSaveSlot) { //PikaSaveGameBoxNumberArray数组里,index为循环出来的PikaUISaveLoadBar的编号 //value为存档的编号,默认值为-1的那个,该值由UPikaUIReadAndWrite::PikaSaveArchiveSlot里的新建逻辑,获取当前存档数的最大值来设置 if (PikaGameSaveSlot->PikaReadGameData.PikaSaveGameBoxNumberArray.IsValidIndex(SaveSlotDataChannel.PikaCurrentSaveGameBoxNumber)) PikaGameSaveSlot->PikaReadGameData.PikaSaveGameBoxNumberArray[SaveSlotDataChannel.PikaCurrentSaveGameBoxNumber] = SaveSlotDataChannel.PikaCurrentGameArchiveNumber; //该存储条内的信息 if (PikaGameSaveSlot->PikaReadGameData.PikaSaveDataText.IsValidIndex(SaveSlotDataChannel.PikaCurrentGameArchiveNumber)) PikaGameSaveSlot->PikaReadGameData.PikaSaveDataText[SaveSlotDataChannel.PikaCurrentGameArchiveNumber] = FDateTime::Now().ToString(); } //执行GameSaveDatas保存 if (PikaIsGameSaveDatas) { //存储到我们的SavePoint //PikaGameSaveDatas->PikaMissionState = EnvironmentConfiguration->PikaMissionState; PikaGameSaveDatas->PikaGodStongSaveData = GlobalConfig->PikaGameData; PikaGameSaveDatas->PikaGameLevelManangenment = GlobalConfig->PikaGameLevelManangenment; PikaGameSaveDatas->PikaTemporaryCacheData = GlobalConfig->PikaTemporaryCacheData; PikaGameSaveDatas->PikaSaveCount = GlobalConfig->PikaSaveCount; } ////////////////////////////////////////////////////////////////////////// PikaIsGameSaveDatas = PIKA_SAVE_SLOT(PikaGameSaveDatas, PIKA_SAVE_GAME_NAME + FString::FromInt(SaveSlotDataChannel.PikaCurrentGameArchiveNumber), 0); PikaIsGameSaveSlot = PIKA_SAVE_SLOT(PikaGameSaveSlot, PIKA_SAVE_SLOT_NAME, 0); return PikaIsGameSaveDatas && PikaIsGameSaveSlot; }
PikaGodStoneGameStateBase.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/GameStateBase.h" #include "PikaGodStoneGameStateBase.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API APikaGodStoneGameStateBase : public AGameStateBase { GENERATED_BODY() };
PikaGodStoneGameStateBase.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGodStoneGameStateBase.h"
PikaGodStonePlayerController.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/PlayerController.h" #include "Public/PikaGlobalConfig.h" #include "Public/PikaAITargetPoint.h" #include "Engine/DataTable.h" #include "Public/PikaGodStonePlayerState.h" #include "Public/PikaGodStoneCamera.h" #include "PikaTowerDoll.h" #include "Public/PikaCharacterInfoDataTable.h" #include "PikaCharacterBase.h" #include "PikaMonster.h" #include "PikaGameResource.h" #include "PikaGodStoneGameInstance.h" #include "PikaGodStonePlayerController.generated.h" //带参数的代理 DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPikaMouseMiddleButtonPressed, APikaGodStonePlayerController*, APikaGodStonePlayerController); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FPikaMouseMiddleButtonReleased, APikaGodStonePlayerController*, APikaGodStonePlayerController); /** * */ UCLASS() class PIKAGODSTONE_API APikaGodStonePlayerController : public APlayerController { GENERATED_BODY() //替身类指针 UPROPERTY() APikaTowerDoll* PikaTowerDollPtr; //是否运行建造塔 UPROPERTY() bool PikaIsAllowBuillingTowers; FHitResult PikaMouseTraceHit; //保存我们的指针 APikaCharacterBase* PikaTempCharacterBasePtr; //uint8 BlockingProgram : 1; uint8 PikaIsSuccessLevel : 1; //uint8 IsFire : 1; //集中火力的目标 UPROPERTY() APikaMonster* PikaMonstersTarget; UPROPERTY() ATargetPoint* PikaMapMarkPoint; public: APikaGodStonePlayerController(); virtual void Tick(float DeltaTime) override; virtual void BeginPlay() override; /****************************************代理Start****************************************/ //按键响应在本类的SetupInputComponent里进行绑定 //按下鼠标的代理 FPikaMouseMiddleButtonPressed PikaEventMouseMiddlePressed; //松开鼠标的代理 FPikaMouseMiddleButtonReleased PikaEventFMouseMiddleReleased; /****************************************代理End****************************************/ /****************************************数据Start****************************************/ //数据配置 UDataTable * PikaAITowrerData; UDataTable * PikaAIMonsterData; UPikaGameResource * PikaGameResourcePtr; //指向全局配置的指针 UPikaGlobalConfig * PikaGlobalConfigPrePlayerCon; //和上面一样,指向同一个内存地址 UPikaGlobalConfig * PikaGlobalConfigPre; float** PikaTowersCharacterData; float** PikaMonsterCharacterData; //注册角色信息 float** PikaRegisterCharacterData(UDataTable* CharacterData); /****************************************数据End****************************************/ /****************************************塔相关函数Start****************************************/ //获取塔的图片 TArray<UTexture2D*> PikaGetTowerIocn(); //名字 TArray<FName> PikaGetTowersName(); //简介 TArray<FText> PikaGetTowersIntroduction(); //获取塔的建造CD TArray<float> PikaGetBuildCD(); //获取塔的Mesh,即特效内部的模型 TArray<UStaticMesh*> PikaGetTowerMeshFromParticle(int32 TowerID , FPikaComponentSpaceInfo& MyPikaComponentSpaceInfo); //获取建造所需的金币 TArray<int32> PikaGetTowerComsumeGold(); //GM,读取数据表中的数据,并将其中的数据转换成蓝图实例 //如果用该方法在场景里进行拖拽生成模型时,角色内部是没有数据的 AActor* PikaSpawnTowers(int32 TowerID, int32 TowerLevel , bool PikaIsLoading = false, int32 CharacterIndex = INDEX_NONE , FVector CharacterLocation = FVector::ZeroVector); //生成替身类 APikaTowerDoll* PikaSpawnTowerDoll(int32 SerialNum); //销毁替身类 void PikaDestoryTowerDoll(); //获取替换模型 APikaTowerDoll* PikaGetTowersDoll() { return PikaTowerDollPtr; } //设置替换模型 void PikaSetTowerDoll(APikaTowerDoll* NewTowerDoll) { PikaTowerDollPtr = NewTowerDoll; } //获取允许建筑的塔 bool PikaGetAllowBuillingTowers() { return PikaIsAllowBuillingTowers; } //运行建造塔 void PikaSetAllowBuillingTowers(bool AllowBuillingCondition) { PikaIsAllowBuillingTowers = AllowBuillingCondition; } //获取塔的数据 TArray<float> PikaGetTowerData(EPikaCharacterInfoDataTableType::Type CharacterInformationDataType); //获取塔的当前等级 int32 PikaGetCurrentTowersAverageLevel()const; //获取当前关卡所有Towers TArray<APikaCharacterBase*> PikaGetCurrentLevelTowers(); /****************************************塔相关函数End****************************************/ /****************************************怪物相关函数Start****************************************/ //获取怪物图片 TArray<UTexture2D*> PikaGetMonsterIocn(); //简介 TArray<FText> PikaGetMonsterIntroduction(); //名字 TArray<FName> PikaGetMonsterName(); //获取怪物的Mesh,即特效内部的模型 TArray<UStaticMesh*> PikaGetMonsterMeshFromParticle(int32 MonsterID , FPikaComponentSpaceInfo& MyPikaComponentSpaceInfo); //GM,读取数据表中的数据,并将其中的数据转换成蓝图实例 //如果用该方法在场景里进行拖拽生成模型时,角色内部是没有数据的 AActor* PikaSpawnMonster(int32 MonsterID, int32 MonsterLevel , bool PikaIsLoading = false, int32 CharacterIndex = INDEX_NONE , FVector CharacterLocation = FVector::ZeroVector); //获取怪物的数据 TArray<float> PikaGetMonsterData(EPikaCharacterInfoDataTableType::Type CharacterInformationDataType); //获取当前关卡所有Monsters TArray<APikaCharacterBase*> PikaGetCurrentLevelMonsters(); //获取手动目标 FORCEINLINE APikaMonster* PikaGetTargetMonster() const { return PikaMonstersTarget; } /****************************************怪物相关函数End****************************************/ /****************************************控制函数Start****************************************/ //允许玩家自己更新自己的绑定响应 virtual void SetupInputComponent() override; //鼠标上滚的响应函数 void PikaMouseWheelUp(); //鼠标下滚的响应函数 void PikaMouseWheelDown(); //判断鼠标移动的方向 void PikaCursorMoveDirection(); //根据鼠标移动的方向移动摄像机 void PikaCameraMove(bool Direction, bool Axle); //鼠标中键控制 void PikaMouseMiddleButtonPressed(); void PikaMouseMiddleButtonReleased(); //键盘的Q和E旋转模型设置 void PikaCounterClockWiseRotationKey(); void PikaClockWiseRotationKey(); /****************************************控制函数End****************************************/ /****************************************其它函数Start****************************************/ //获取场景中已经设置的目标点,目标点会作为GM命令的出生点(测试中) //获取场景所有出生点,作为怪物的生成点 TArray<APikaAITargetPoint*> PikaGetAllOfTargetPoint(); ATargetPoint* PikaGetAllOfLevelMapTargetPoint(TSubclassOf<ATargetPoint> MyTargetPointCalss); //获取玩家数据实例 APikaGodStonePlayerState * PikaGetTowerPlayerState(); //获取场景相机实例(Pawn) APikaGodStoneCamera * PikaGetTowreCamera(); //测试打印函数 void PikaPrint(FString PikaStr); //清除临时指针 void PikaClearTmpRuleOfTheCharacter() { PikaTempCharacterBasePtr = NULL; } //获取当前关卡的地图 UTexture2D* PikaGetCurrentLevelMiniMap() const; //获取地图标记点 FVector PikaGetMapMarkPointLocation(); FRotator PikaGetMapMarkPointRotator(); FORCEINLINE AActor* PikaGetMapMarkPoint()const { return PikaMapMarkPoint; } UPikaGodStoneGameInstance* PikaGetGameInstance() const; //载入数据到场景角色(载入数据) bool PikaReductionGameData(bool IsReduction); //存储游戏数据的功能(储存数据) bool PikaSaveGameData(PikaFSaveSlotDataChannel SaveSlotDataChannel); //获取读取信息 FText PikaGetSaveInformation(int32 NumData); //播放随机声音 void PikaPlaySoundAtVetor(TArray<USoundBase*> CharacterSound, FVector CharcterLocation = FVector::ZeroVector, PikaETowerDefenceSoundType TowerDefenceSoundType = PikaETowerDefenceSoundType::SOUND_NONE); //播放声音 void PikaPlaySoundAtVetor(USoundBase* CharacterSound, FVector CharcterLocation = FVector::ZeroVector, PikaETowerDefenceSoundType TowerDefenceSoundType = PikaETowerDefenceSoundType::SOUND_NONE); /****************************************其它函数End****************************************/ private: //数据导入,GM,读取数据表中的数据,并将其中的数据转换成蓝图实例 AActor* PikaCreateAndDataImport(int32 CharacterID, int32 CharacterLevel, UDataTable* CharacterData , bool PikaIsLoading = false, int32 CharacterIndex = INDEX_NONE , FVector CharacterLocation = FVector::ZeroVector); //获取物品栏图标 TArray<UTexture2D*> PikaGetCharacterIocn(UDataTable* CharacterData); //获取特效中的Mesh TArray<UStaticMesh*> PikaGetDataStaticMeshFormPartcle(UDataTable* MyCharacterDataTable , int32 CharacterID , FPikaComponentSpaceInfo& MyPikaComponentSpaceInfo); //名字 TArray<FName> PikaGetCharacterName(UDataTable* CharacterData); //简介 TArray<FText> PikaGetCharacterIntroduction(UDataTable* CharacterData); //获取角色数据 TArray<float> PikaGetCharacterData(UDataTable* CharacterData, float** NewFloatArray, EPikaCharacterInfoDataTableType::Type CharacterInformationDataType); //释放掉我们的角色数据 void PikaReleaseCharacterData(); //获取场景内一个标准的等级(全部塔的平均等级) int32 PikaGetCurrentCharacterAverageLevel(bool CharacterClass = true) const; };
PikaGodStonePlayerController.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGodStonePlayerController.h" #include "Public/PikaGodStonePlayerState.h" #include "Public/PikaGodStoneCamera.h" #include "Public/PikaGameManager.h" #include "Engine.h" #include "ConstructorHelpers.h" #include "Particles/ParticleLODLevel.h" #include "Particles/TypeData/ParticleModuleTypeDataMesh.h" #include "Particles/Size/ParticleModuleSize.h" #include "Particles/Location/ParticleModuleLocation.h" #include "Particles/Rotation/ParticleModuleMeshRotation.h" #include "Public/PikaMonster.h" #include "Public/PikaTowers.h" #include "Public/PikaGameUserSettings.h" APikaGodStonePlayerController::APikaGodStonePlayerController() { //显示鼠标 bShowMouseCursor = true; //初始GM类 CheatClass = UPikaGameManager::StaticClass(); static ConstructorHelpers::FClassFinder<ATargetPoint> PikaMapPointClass(TEXT("/Game/ToolActor/MapPointBP")); if (GetWorld()) { //地图标记点 if (PikaMapPointClass.Class) { PikaMapMarkPoint = PikaGetAllOfLevelMapTargetPoint(PikaMapPointClass.Class); } } PikaIsAllowBuillingTowers = true; PikaMonstersTarget = nullptr; } void APikaGodStonePlayerController::Tick(float DeltaTime) { Super::Tick(DeltaTime); //获取鼠标移动的方向 PikaCursorMoveDirection(); //皮卡射线 if (PikaTowerDollPtr) { if (PikaMouseTraceHit.Location != FVector::ZeroVector) PikaMouseTraceHit.Location = FVector::ZeroVector; FHitResult PikaTraceOutHit; //ECC_EngineTraceChannel4为自定义的射线检测的通道 GetHitResultUnderCursor(ECollisionChannel::ECC_GameTraceChannel4, true, PikaTraceOutHit); //利用射线设置替身类的坐标 PikaTowerDollPtr->SetActorLocation(PikaTraceOutHit.Location); } else { //鼠标扫描场景,通道名称为PikaScanTrace GetHitResultUnderCursor(ECollisionChannel::ECC_GameTraceChannel7, true, PikaMouseTraceHit); } if (PikaMouseTraceHit.Actor.IsValid()) { APikaCharacterBase* PikaNewCharacterBase = Cast<APikaCharacterBase>(PikaMouseTraceHit.Actor.Get()); if (PikaNewCharacterBase) { PikaTempCharacterBasePtr = PikaNewCharacterBase; PikaTempCharacterBasePtr->PikaCharacterAttributeDisplay(true); } } else if (PikaTempCharacterBasePtr && PikaTempCharacterBasePtr->IsA(APikaCharacterBase::StaticClass())) { PikaTempCharacterBasePtr->PikaCharacterAttributeDisplay(false); } //关卡中角色控制 if (PikaGlobalConfigPre && !PikaIsSuccessLevel && !PikaGlobalConfigPre->PikaGameLevelManangenment.PikaGameOver) { /*//添加灵力 Confo->TDGameData.GoldGrowthTime += DeltaSeconds; if (Confo->TDGameData.IsJudgement()) { Confo->TDGameData.GoldGrowthTime = 0; Confo->TDGameData.AddGlobalGold(2); //验证条件否成功 GameCondition(ELevelCondition::ExceedingSpiritualForce); }*/ //时间倒计时 if (PikaGlobalConfigPre->PikaGameData.PikaGameCount > 0) { PikaGlobalConfigPre->PikaGameData.PikaGameCount -= DeltaTime; } else { //GameOver(); } //检测玩家是否死亡 //存在数量 int32 PikaExistNumber = 0; int32 PikaTowersNum = 0; TArray<APikaCharacterBase*> PikaARuleOfTheTowers = PikaGetCurrentLevelTowers(); for (APikaCharacterBase* PikaAloneTower : PikaARuleOfTheTowers) { if (PikaAloneTower->PikaIsActive()) { PikaExistNumber++; APikaTowers* PikaTowers = Cast<APikaTowers>(PikaAloneTower); if (PikaTowers) PikaTowersNum++; } } //场景内没有塔,玩家输 if (PikaTowersNum == 0) { //GameOver(); } //当前关卡是否胜利 if (!PikaGlobalConfigPre->PikaGameLevelManangenment.PikaCurrentLevelMissionSuccess) { //输掉比赛没 if (!PikaGlobalConfigPre->PikaGameLevelManangenment.PikaGameOver) { //准备开始怪物登场 if (!PikaGlobalConfigPre->PikaGameLevelManangenment.PikaGetLock()) { if (PikaGlobalConfigPre->PikaGameLevelManangenment.PikaPerNumberOfMonsters.Num()) { PikaGlobalConfigPre->PikaGameLevelManangenment.PikaSetTimeMnanagenment += DeltaTime; //是否大于生成怪物的时间间隔 if (PikaGlobalConfigPre->PikaGameLevelManangenment.PikaIsTimeRight()) { PikaGlobalConfigPre->PikaGameLevelManangenment.PikaSetTimeMnanagenment = PIKA_ZERO; //获取怪物生成点 TArray<APikaAITargetPoint*> PikaSpawnPointArr = PikaGetAllOfTargetPoint(); TArray<APikaAITargetPoint*> PikaSpawnMonsterPoint; if (PikaSpawnPointArr.Num() > 0) { for (APikaAITargetPoint* PikaMySpawnPoint : PikaSpawnPointArr) { if (!PikaMySpawnPoint->PikaTeam) { PikaSpawnMonsterPoint.Add(PikaMySpawnPoint); } } } //生成怪物 int32 PikaSpawnPoint = FMath::RandRange(0, PikaSpawnMonsterPoint.Num() - 1); if (PikaSpawnPoint != INDEX_NONE && PikaSpawnMonsterPoint.IsValidIndex(PikaSpawnPoint)) { //数据中是否存在角色 if (PikaGlobalConfigPre->PikaGameLevelManangenment.PikaIsExistDataMonster()) { int32 PikaCurrentTowersLevelAverage = PikaGetCurrentTowersAverageLevel(); FVector PikaMonsterLocation = PikaSpawnMonsterPoint[PikaSpawnPoint]->GetActorLocation(); AActor* PikaMyMonster = PikaSpawnMonster(FMath::RandRange(0, 3), PikaGlobalConfigPre->PikaGameLevelManangenment.PikaAddMonsterLevel + PikaCurrentTowersLevelAverage , false , -1 , PikaMonsterLocation); if ((APikaCharacterBase*)PikaMyMonster) { PikaMyMonster->SetActorLocation(PikaMonsterLocation); //((APikaCharacterBase*)PikaMyMonster)->PikaPlayBornSound(); } } //对数据进行操作 PikaGlobalConfigPre->PikaGameLevelManangenment.PikaDataSubtraction(); } } } } else { //存在数量 int32 PikaExistNumber = 0; //获取怪物 TArray<APikaCharacterBase*> PikaCurrentMonters = PikaGetCurrentLevelMonsters(); //是否活着 for (APikaCharacterBase* PikaRuleOfTheMonster : PikaCurrentMonters) { if (PikaRuleOfTheMonster->PikaIsActive()) { PikaExistNumber++; } } if (PikaExistNumber == 0) { //解锁,开始下一波怪物登场 PikaGlobalConfigPre->PikaGameLevelManangenment.PikaUnLock(); //准备下一个阶段 PikaGlobalConfigPre->PikaGameLevelManangenment.PikaCurrentStagesAreMonsters++; } } } } else { //GameSuccess(); } } } void APikaGodStonePlayerController::BeginPlay() { Super::BeginPlay(); //获取playerState类中的蓝图配置 APikaGodStonePlayerState * PikaPlayerStatePre = Cast<APikaGodStonePlayerState>(PlayerState); if (PikaPlayerStatePre) { PikaGlobalConfigPrePlayerCon = PikaPlayerStatePre->PikaGlobalConfigPre; if (PikaGlobalConfigPrePlayerCon) { } } //PikaGetTowerIocn(); //初始化主塔 if (PikaGlobalConfigPre) { if (!PikaGlobalConfigPre->PikaIsSave) { TArray<APikaAITargetPoint*> PikaSpawnPointArr = PikaGetAllOfTargetPoint(); if (PikaSpawnPointArr.Num() > 0) { for (APikaAITargetPoint* MySpawnPoint : PikaSpawnPointArr) { if (MySpawnPoint->PikaTeam) { APikaCharacterBase* PikaMianTowers = Cast<APikaCharacterBase>(PikaSpawnTowers(4, PikaGlobalConfigPre->PikaGameLevelManangenment.PikaTowersLevel)); if (PikaMianTowers) PikaMianTowers->SetActorLocation(MySpawnPoint->GetActorLocation()); //上传我们的位置信息数据 if (PikaGlobalConfigPrePlayerCon) { int32 PikaCharacterIndex = PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaGetCurrentCharacterSpawnIDIndex(PikaMianTowers->PikaGetCharacterSpawnID()); if (PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaIsActive(PikaCharacterIndex)) { PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterLocation[PikaCharacterIndex] = PikaMianTowers->GetActorLocation(); PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterRotator[PikaCharacterIndex] = PikaMianTowers->GetActorRotation(); } } } } } //初始化怪物梯度 PikaGlobalConfigPre->PikaGameLevelManangenment.PikaAssignedMonsterAmount(); } else { /*//数据读取完毕 Confo->InitializationDataComplete(); //将数据读取完毕告诉数据 if (GetTowerDefenceGameInstance()) GetTowerDefenceGameInstance()->InitializationDataComplete(); //解锁 UnTDLock();*/ } } } void APikaGodStonePlayerController::PikaPrint(FString PikaStr) { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 1.f, FColor::Red, PikaStr); } } UTexture2D* APikaGodStonePlayerController::PikaGetCurrentLevelMiniMap() const { if (PikaGameResourcePtr && PikaGlobalConfigPrePlayerCon && PikaGameResourcePtr->PikaLevelMiniMap.IsValidIndex(PikaGlobalConfigPrePlayerCon->PikaGameLevelManangenment.PikaCurrentLevel)) { int32 PikaCurrentLevel = PikaGlobalConfigPrePlayerCon->PikaGameLevelManangenment.PikaCurrentLevel; if (PikaGameResourcePtr->PikaLevelMiniMap[PikaCurrentLevel].PikaMiniMapTexture) return PikaGameResourcePtr->PikaLevelMiniMap[PikaCurrentLevel].PikaMiniMapTexture; } return NULL; } FVector APikaGodStonePlayerController::PikaGetMapMarkPointLocation() { return PikaMapMarkPoint != NULL ? PikaMapMarkPoint->GetActorLocation() : FVector::ZeroVector; } FRotator APikaGodStonePlayerController::PikaGetMapMarkPointRotator() { return PikaMapMarkPoint != NULL ? PikaMapMarkPoint->GetActorRotation() : FRotator::ZeroRotator; } UPikaGodStoneGameInstance* APikaGodStonePlayerController::PikaGetGameInstance() const { return GetWorld() != NULL ? ((UPikaGodStoneGameInstance*)GetWorld()->GetGameInstance()) : NULL; } bool APikaGodStonePlayerController::PikaSaveGameData(PikaFSaveSlotDataChannel SaveSlotDataChannel) { if (PikaGetGameInstance()) { if (PikaGlobalConfigPrePlayerCon) return PikaGetGameInstance()->PikaSaveGameData(PikaGlobalConfigPrePlayerCon, SaveSlotDataChannel); } return false; } FText APikaGodStonePlayerController::PikaGetSaveInformation(int32 NumData) { FText PikaNewText; UPikaGameSaveData* PikaNewGameSaveData = Cast<UPikaGameSaveData>(PIKA_LOADGAME_SLOT(PIKA_SAVE_SLOT_NAME, 0)); if (PikaNewGameSaveData) { if (PikaNewGameSaveData->PikaReadGameData.PikaSaveDataText.IsValidIndex(NumData)) PikaNewText = FText::FromString(PikaNewGameSaveData->PikaReadGameData.PikaSaveDataText[NumData]); } return PikaNewText; } //播放随机声音 void APikaGodStonePlayerController::PikaPlaySoundAtVetor(TArray<USoundBase*> CharacterSound, FVector CharcterLocation /*= FVector::ZeroVector*/, PikaETowerDefenceSoundType TowerDefenceSoundType /*= PikaETowerDefenceSoundType::SOUND_NONE*/) { //随机序列 int32 PikaRandomIndex = FMath::RandRange(0, (CharacterSound.Num() - 1)); if (!CharacterSound.IsValidIndex(PikaRandomIndex)) return; //播放声音 PikaPlaySoundAtVetor(CharacterSound[PikaRandomIndex], CharcterLocation, TowerDefenceSoundType); } //播放声音 void APikaGodStonePlayerController::PikaPlaySoundAtVetor(USoundBase* CharacterSound, FVector CharcterLocation /*= FVector::ZeroVector*/, PikaETowerDefenceSoundType TowerDefenceSoundType /*= PikaETowerDefenceSoundType::SOUND_NONE*/) { if (GetWorld() && CharacterSound) { //设置塔防播放类型 CharacterSound->PikaqiuTowerDefenceSoundType = TowerDefenceSoundType; //总声音收益 float PikaCurrentSound = 1; //声音大小调节 if (UPikaGameUserSettings::PikaGetGameUserSettings()) { switch (TowerDefenceSoundType) { case PikaETowerDefenceSoundType::SOUND_MUSIC: PikaCurrentSound = UPikaGameUserSettings::PikaGetGameUserSettings()->PikaqiuTotalSoundControl * UPikaGameUserSettings::PikaGetGameUserSettings()->PikaBackgroundSoundControl; break; case PikaETowerDefenceSoundType::SOUND_EFFECT_SOUND: PikaCurrentSound = UPikaGameUserSettings::PikaGetGameUserSettings()->PikaqiuTotalSoundControl * UPikaGameUserSettings::PikaGetGameUserSettings()->PikaEffectsSoundControl; break; case PikaETowerDefenceSoundType::SOUND_KEY_SOUND: PikaCurrentSound = UPikaGameUserSettings::PikaGetGameUserSettings()->PikaqiuTotalSoundControl * UPikaGameUserSettings::PikaGetGameUserSettings()->PikaqiuButtonSoundControl; break; } } //播放声音 if (PikaCurrentSound > 0) { float pika = PikaCurrentSound > 1 ? 1 : PikaCurrentSound; //是否有衰减 if (CharcterLocation != FVector::ZeroVector) { USoundAttenuation* PikaFightingSoundVolume = nullptr; //获取战斗衰减框 if (PikaGameResourcePtr) PikaFightingSoundVolume = PikaGameResourcePtr->PikaFightingSoundVolume; if (PikaFightingSoundVolume != nullptr) PIKA_SPAWN_SOUND_LOCATION(GetWorld(), CharacterSound, CharcterLocation, PikaCurrentSound > 1 ? 1 : PikaCurrentSound, 1, 0, PikaFightingSoundVolume, nullptr); } else { PIKA_SPAWN_SOUND_LOCATION(GetWorld(), CharacterSound, CharcterLocation, PikaCurrentSound > 1 ? 1 : PikaCurrentSound, 1, 0, nullptr, nullptr); } } } } void APikaGodStonePlayerController::PikaCursorMoveDirection() { //屏幕尺寸 int32 PikaScreenSize_X, PikaScreenSize_Y; //鼠标位置 float PikaMousePosi_X, PikaMousePosi_Y; //获取屏幕尺寸 GetViewportSize(PikaScreenSize_X, PikaScreenSize_Y); //获取鼠标位置 GetMousePosition(PikaMousePosi_X, PikaMousePosi_Y); //IsNearlyEqual的第三个参数为误差宽容度 float ErrorTolerance = 6; if (FMath::IsNearlyEqual(PikaMousePosi_X, PikaScreenSize_X, ErrorTolerance)) { PikaCameraMove(0, 0); return; } else if (FMath::IsNearlyEqual(PikaMousePosi_X, 0.0f, ErrorTolerance)) { PikaCameraMove(1, 0); return; } if (FMath::IsNearlyEqual(PikaMousePosi_Y, PikaScreenSize_Y, ErrorTolerance)) { PikaCameraMove(1, 1); return; } else if (FMath::IsNearlyEqual(PikaMousePosi_Y, 0.0f, ErrorTolerance)) { PikaCameraMove(0, 1); return; } } void APikaGodStonePlayerController::PikaCameraMove(bool Direction, bool Axle) { if (Direction) { if (Axle) { //x轴正方向 FVector PikaTmpLocation = FVector(PikaGlobalConfigPrePlayerCon->PikaMouseSetConf.MouseSpeed, 0.0f, 0.0f); //视角移动 GetPawn()->AddActorWorldOffset(PikaTmpLocation); } else { //y轴正方向 FVector PikaTmpLocation = FVector(0.0f, PikaGlobalConfigPrePlayerCon->PikaMouseSetConf.MouseSpeed, 0.0f); GetPawn()->AddActorWorldOffset(PikaTmpLocation); } } else { if (Axle) { //x轴负方向 FVector PikaTmpLocation = FVector(PikaGlobalConfigPrePlayerCon->PikaMouseSetConf.MouseSpeed*(-1), 0.0f, 0.0f); GetPawn()->AddActorWorldOffset(PikaTmpLocation); } else { //y轴负方向 FVector PikaTmpLocation = FVector(0.0f, PikaGlobalConfigPrePlayerCon->PikaMouseSetConf.MouseSpeed*(-1), 0.0f); GetPawn()->AddActorWorldOffset(PikaTmpLocation); } } } void APikaGodStonePlayerController::PikaMouseMiddleButtonPressed() { PikaEventMouseMiddlePressed.Broadcast(this); } void APikaGodStonePlayerController::PikaMouseMiddleButtonReleased() { PikaEventFMouseMiddleReleased.Broadcast(this); } void APikaGodStonePlayerController::PikaCounterClockWiseRotationKey() { if (PikaTowerDollPtr && PikaGlobalConfigPrePlayerCon) PikaTowerDollPtr->AddActorLocalRotation(FRotator(0, -1 * PikaGlobalConfigPrePlayerCon->PikaMouseSetConf.PikaAngleOfRotation , 0)); } void APikaGodStonePlayerController::PikaClockWiseRotationKey() { if (PikaTowerDollPtr && PikaGlobalConfigPrePlayerCon) PikaTowerDollPtr->AddActorLocalRotation(FRotator(0, PikaGlobalConfigPrePlayerCon->PikaMouseSetConf.PikaAngleOfRotation , 0)); } void APikaGodStonePlayerController::SetupInputComponent() { Super::SetupInputComponent(); /*按键绑定需要在UE4编辑器里的输入里设置绑定的键位信息*/ //鼠标滚轮 InputComponent->BindAction("PikaWheelUp", IE_Pressed, this, &APikaGodStonePlayerController::PikaMouseWheelUp); InputComponent->BindAction("PikaWheelDown", IE_Pressed, this, &APikaGodStonePlayerController::PikaMouseWheelDown); //鼠标中间绑定 InputComponent->BindAction("PikaMiddleButtonPressed", IE_Pressed, this, &APikaGodStonePlayerController::PikaMouseMiddleButtonPressed); InputComponent->BindAction("PikaMiddleButtonReleased", IE_Released, this, &APikaGodStonePlayerController::PikaMouseMiddleButtonReleased); //键盘Q和E绑定 InputComponent->BindAction("PikaCounterClockWiseRotation", IE_Pressed, this, &APikaGodStonePlayerController::PikaCounterClockWiseRotationKey); InputComponent->BindAction("PikaClockWiseRotation", IE_Pressed, this, &APikaGodStonePlayerController::PikaClockWiseRotationKey); } void APikaGodStonePlayerController::PikaMouseWheelUp() { if (GetPawn()) { APikaGodStoneCamera * PikaPartCamera = Cast<APikaGodStoneCamera>(GetPawn()); if (PikaPartCamera) { PikaPartCamera->PikaCameraZoom(1, PikaGlobalConfigPrePlayerCon->PikaMouseSetConf.MouseSpeed); } } } void APikaGodStonePlayerController::PikaMouseWheelDown() { if (GetPawn()) { APikaGodStoneCamera * PikaPartCamera = Cast<APikaGodStoneCamera>(GetPawn()); if (PikaPartCamera) { PikaPartCamera->PikaCameraZoom(0, PikaGlobalConfigPrePlayerCon->PikaMouseSetConf.MouseSpeed); } } } AActor* APikaGodStonePlayerController::PikaCreateAndDataImport(int32 CharacterID, int32 CharacterLevel, UDataTable* CharacterData , bool PikaIsLoading , int32 CharacterIndex , FVector CharacterLocation) { AActor* PikaMyActor = NULL; if (CharacterData && CharacterID >= 0 && CharacterID < PikaAITowrerData->RowMap.Num()) { TArray<FPikaCharacterInfoDataTable*> PikaInfomationData; TArray<FName> PikaCharacterNameArray = PikaGetCharacterName(CharacterData); CharacterData->GetAllRows("PikaInfo", PikaInfomationData); //获取角色蓝图实例 UClass * PikaMyClass = PikaInfomationData[CharacterID]->PikaCharacterBlueprintKey.LoadSynchronous(); if (PikaMyClass) { //获取场景中已经设置的目标点 //TArray<APikaAITargetPoint*> PikaMyPoint = PikaGetAllOfTargetPoint(); //if (PikaMyPoint.Num() > 0) //{ //PikaMyActor = GetWorld()->SpawnActor<AActor>(PikaMyClass, PikaMyPoint[0]->GetActorLocation(), FRotator::ZeroRotator); //生成模型 PikaMyActor = GetWorld()->SpawnActor<AActor>(PikaMyClass, FVector::ZeroVector, FRotator::ZeroRotator); //更新模型数据到面板UI if (PikaMyActor) { APikaCharacterBase * PikaMyCharacterBase = Cast<APikaCharacterBase>(PikaMyActor); FName PikaCurrentCharacterName; if (PikaMyCharacterBase) { //播放蒙太奇和绑定蒙太奇 PikaMyCharacterBase->PikaPlayAnimationForBegin(PikaIsLoading); //获取角色ID和金币 PikaMyCharacterBase->PikaCharDataPre->PikaCharBaseData.PikaCharacterID = PikaInfomationData[CharacterID]->PikaCharacterID; PikaMyCharacterBase->PikaCharDataPre->PikaCharBaseData.PikaComsumeGold = PikaInfomationData[CharacterID]->PikaComsumeGold; //获取名字 if (PikaCharacterNameArray.IsValidIndex(CharacterLevel)) { PikaMyCharacterBase->PikaCharDataPre->PikaCharBaseData.PikaCharacterName = PikaCharacterNameArray[CharacterID]; PikaCurrentCharacterName = PikaCharacterNameArray[CharacterID]; } //数据导入 PikaMyCharacterBase->PikaCharDataPre->PikaCharBaseData.PikaInitCharacterAttrubute( PikaInfomationData[CharacterID]->PikaMaxHealth, PikaInfomationData[CharacterID]->PikaPhysicalAttack, PikaInfomationData[CharacterID]->PikaAttackSpeed, PikaInfomationData[CharacterID]->PikaMaxExperienceValue, PikaInfomationData[CharacterID]->PikaArmor ); PikaMyCharacterBase->PikaCharDataPre->PikaCharBaseData.PikaInitAddCharacterAttribute( PikaInfomationData[CharacterID]->PikaAddHealth, PikaInfomationData[CharacterID]->PikaAddPhysicalAttack, PikaInfomationData[CharacterID]->PikaAddAttackSpeed, PikaInfomationData[CharacterID]->PikaAddExperienceValue, PikaInfomationData[CharacterID]->PikaAddArmor ); } //自定义角色等级 if (CharacterLevel >= 1) { for (int32 i = 0; i < CharacterLevel; i++) { PikaMyCharacterBase->PikaCharDataPre->PikaCharBaseData.PikaUpdateLevel(); } } //更新角色数据到面板 PikaMyCharacterBase->PikaInitCharacterInformation(); //注册我们的生成序列 if (PikaGlobalConfigPrePlayerCon) { //是否是载入类型的spawn if (PikaIsLoading) { if (CharacterIndex != INDEX_NONE) { /*//载入我们的数据 MyRuleOfTheCharacter->SetCharacterSpawnID(Confo->TemporaryCacheData.CharacterSpawnID[CharacterIndex]); MyRuleOfTheCharacter->SetActorLocation(Confo->TemporaryCacheData.CharacterLocation[CharacterIndex] + FVector(0, 0, 100));//防止生成的角色掉下去 MyRuleOfTheCharacter->SetActorRotation(Confo->TemporaryCacheData.CharacterRotator[CharacterIndex]); MyRuleOfTheCharacter->SetCharacterCurrentLevel(Confo->TemporaryCacheData.CharacterCurrentLevel[CharacterIndex]); MyRuleOfTheCharacter->SetCharacterCurrentHealth(Confo->TemporaryCacheData.CharacterCurrentHealth[CharacterIndex]); MyRuleOfTheCharacter->SetCharacterCurrentEXP(Confo->TemporaryCacheData.CharacterCurrentExp[CharacterIndex]); MyRuleOfTheCharacter->SetCharacterActive(Confo->TemporaryCacheData.CharacterActive[CharacterIndex]);*/ } else { UE_LOG(LogTemp, Error, TEXT(" Generation failed")); } } else { int32 PikaMySpawnID = 10000 + FMath::RandRange(0, 10000); while (PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaIsExistSpawnID(PikaMySpawnID)) { PikaMySpawnID = 10000 + FMath::RandRange(0, 10000); } PikaMyCharacterBase->PikaSetCharacterSpawnID(PikaMySpawnID); //上传信息到我们的数据包 PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterSpawnID.Add(PikaMySpawnID); PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterActive.Add(true); PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterTeam.Add(PikaMyCharacterBase->PikaIsTeam()); PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterLocation.Add(CharacterLocation); PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterRotator.Add(PikaMyCharacterBase->GetActorRotation()); PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterName.Add(PikaCurrentCharacterName); PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterCurrentHealth.Add(PikaInfomationData[CharacterID]->PikaMaxHealth); PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterCurrentLevel.Add(CharacterLevel); PikaGlobalConfigPrePlayerCon->PikaTemporaryCacheData.PikaCharacterCurrentExp.Add(0); } } } //} } } return PikaMyActor; } //GM,读取数据表中的数据,并将其中的数据转换成蓝图实例 AActor* APikaGodStonePlayerController::PikaSpawnTowers(int32 TowerID, int32 TowerLevel , bool PikaIsLoading , int32 CharacterIndex , FVector CharacterLocation) { return PikaCreateAndDataImport(TowerID, TowerLevel, PikaAITowrerData , PikaIsLoading, CharacterIndex , CharacterLocation); } AActor* APikaGodStonePlayerController::PikaSpawnMonster(int32 MonsterID, int32 MonsterLevel , bool PikaIsLoading , int32 CharacterIndex , FVector CharacterLocation) { return PikaCreateAndDataImport(MonsterID, MonsterLevel, PikaAIMonsterData , PikaIsLoading, CharacterIndex , CharacterLocation); } TArray<float> APikaGodStonePlayerController::PikaGetMonsterData(EPikaCharacterInfoDataTableType::Type CharacterInformationDataType) { return PikaGetCharacterData(PikaAIMonsterData, PikaMonsterCharacterData, CharacterInformationDataType); } TArray<APikaCharacterBase*> APikaGodStonePlayerController::PikaGetCurrentLevelMonsters() { TArray<APikaCharacterBase*> PikaCurrentLevelTowers; //临时 TArray<AActor*> PikaTempCharacter; if (GetWorld()) { PikaGETALLACTOR(GetWorld(), APikaCharacterBase::StaticClass(), PikaTempCharacter); for (AActor* PikaCurrentActor : PikaTempCharacter) { if (PikaCurrentActor->IsA(APikaMonster::StaticClass())) { PikaCurrentLevelTowers.Add(Cast<APikaCharacterBase>(PikaCurrentActor)); } } } return PikaCurrentLevelTowers; } //获取场景中已经设置的目标点 TArray<APikaAITargetPoint*> APikaGodStonePlayerController::PikaGetAllOfTargetPoint() { TArray<APikaAITargetPoint*> PikaTargetPointArr; if (!GetWorld()) { UE_LOG(LogTemp , Error , TEXT("Pika:GetWorld() is fail")); return PikaTargetPointArr; } TSubclassOf<APikaAITargetPoint> PikaAITargetPointInstance = APikaAITargetPoint::StaticClass(); if (PikaAITargetPointInstance) { for (TActorIterator<APikaAITargetPoint>It(GetWorld() , PikaAITargetPointInstance); It; ++It) { APikaAITargetPoint * PikaMySpawnPoint = *It; if (PikaMySpawnPoint) { PikaTargetPointArr.Add(PikaMySpawnPoint); } } } else { UE_LOG(LogTemp , Error , TEXT("Pika:PikaTargetPointArr is fail")); return PikaTargetPointArr; } UE_LOG(LogTemp , Log , TEXT("Pika:Successfully")); return PikaTargetPointArr; } ATargetPoint* APikaGodStonePlayerController::PikaGetAllOfLevelMapTargetPoint(TSubclassOf<ATargetPoint> MyTargetPointCalss) { if (MyTargetPointCalss) { for (TActorIterator<ATargetPoint>It(GetWorld(), MyTargetPointCalss); It; ++It) { ATargetPoint* MySpawnPoint = *It; if (MySpawnPoint && !MySpawnPoint->IsA(APikaAITargetPoint::StaticClass())) return MySpawnPoint; } } return NULL; } APikaGodStonePlayerState * APikaGodStonePlayerController::PikaGetTowerPlayerState() { return ((APikaGodStonePlayerState*)PlayerState); } APikaGodStoneCamera * APikaGodStonePlayerController::PikaGetTowreCamera() { return ((APikaGodStoneCamera*)GetPawn()); } TArray<UTexture2D*> APikaGodStonePlayerController::PikaGetTowerIocn() { return PikaGetCharacterIocn(PikaAITowrerData); } TArray<FName> APikaGodStonePlayerController::PikaGetTowersName() { return PikaGetCharacterName(PikaAITowrerData); } TArray<FText> APikaGodStonePlayerController::PikaGetTowersIntroduction() { return PikaGetCharacterIntroduction(PikaAITowrerData); } TArray<float> APikaGodStonePlayerController::PikaGetTowerData(EPikaCharacterInfoDataTableType::Type CharacterInformationDataType) { return PikaGetCharacterData(PikaAITowrerData, PikaTowersCharacterData, CharacterInformationDataType); } int32 APikaGodStonePlayerController::PikaGetCurrentTowersAverageLevel() const { return PikaGetCurrentCharacterAverageLevel(); } TArray<APikaCharacterBase*> APikaGodStonePlayerController::PikaGetCurrentLevelTowers() { TArray<APikaCharacterBase*> PikaCurrentLevelTowers; //临时 TArray<AActor*> PikaTempCharacter; if (GetWorld()) { PikaGETALLACTOR(GetWorld(), APikaCharacterBase::StaticClass(), PikaTempCharacter); for (AActor* PikaCurrentActor : PikaTempCharacter) { if (PikaCurrentActor->IsA(APikaTowers::StaticClass())) { PikaCurrentLevelTowers.Add(Cast<APikaCharacterBase>(PikaCurrentActor)); } } } return PikaCurrentLevelTowers; } TArray<UTexture2D*> APikaGodStonePlayerController::PikaGetMonsterIocn() { return PikaGetCharacterIocn(PikaAIMonsterData); } TArray<FText> APikaGodStonePlayerController::PikaGetMonsterIntroduction() { return PikaGetCharacterIntroduction(PikaAIMonsterData); } TArray<FName> APikaGodStonePlayerController::PikaGetMonsterName() { return PikaGetCharacterName(PikaAIMonsterData); } TArray<float> APikaGodStonePlayerController::PikaGetBuildCD() { TArray<float> PikaArrayFloat; if (PikaAITowrerData) { TArray<FPikaCharacterInfoDataTable*> PikaInfomationData; PikaAITowrerData->GetAllRows("PikaInfo", PikaInfomationData); for (int32 i = 0; i < PikaAITowrerData->RowMap.Num(); i++) { float PikaFloat = PikaInfomationData[i]->PikaConstructionTime; PikaArrayFloat.Add(PikaFloat); } } return PikaArrayFloat; } TArray<int32> APikaGodStonePlayerController::PikaGetTowerComsumeGold() { TArray<int32> PikaArrayGlod; if (PikaAITowrerData) { TArray<FPikaCharacterInfoDataTable*> PikaInfomationData; PikaAITowrerData->GetAllRows("PikaInfo", PikaInfomationData); for (int32 i = 0; i < PikaAITowrerData->RowMap.Num(); i++) { float PikaGlod = PikaInfomationData[i]->PikaComsumeGold; PikaArrayGlod.Add(PikaGlod); } } return PikaArrayGlod; } TArray<UStaticMesh*> APikaGodStonePlayerController::PikaGetTowerMeshFromParticle(int32 TowerID , FPikaComponentSpaceInfo& MyPikaComponentSpaceInfo) { return PikaGetDataStaticMeshFormPartcle(PikaAITowrerData , TowerID , MyPikaComponentSpaceInfo); } TArray<UStaticMesh*> APikaGodStonePlayerController::PikaGetMonsterMeshFromParticle(int32 MonsterID , FPikaComponentSpaceInfo& MyPikaComponentSpaceInfo) { return PikaGetDataStaticMeshFormPartcle(PikaAIMonsterData , MonsterID , MyPikaComponentSpaceInfo); } APikaTowerDoll* APikaGodStonePlayerController::PikaSpawnTowerDoll(int32 SerialNum) { TSubclassOf<APikaTowerDoll> PikaMyDoll = APikaTowerDoll::StaticClass(); //记录我们的空间位置 FPikaComponentSpaceInfo PikaComponentSpaceInformation; if (GetWorld() && PikaMyDoll) { PikaTowerDollPtr = GetWorld()->SpawnActor<APikaTowerDoll>(PikaMyDoll, FVector::ZeroVector, FRotator::ZeroRotator); if (PikaTowerDollPtr) { //注册 PikaTowerDollPtr->PikaSetController(this); TArray<UStaticMesh*> PikaMeshArray = PikaGetTowerMeshFromParticle(SerialNum, PikaComponentSpaceInformation); if (PikaMeshArray.Num() < 1) { PikaMeshArray = PikaGetTowerMeshFromParticle(SerialNum, PikaComponentSpaceInformation); if (PikaMeshArray.Num() < 1) { return nullptr;//无Mesh载入 } } //生成替身的颜色 PikaTowerDollPtr->PikaSetMeshAddToMeshComponet(PikaMeshArray , PikaComponentSpaceInformation); PikaTowerDollPtr->PikaSetMeshColor(true); } return PikaTowerDollPtr; } return NULL; } void APikaGodStonePlayerController::PikaDestoryTowerDoll() { if (PikaTowerDollPtr) PikaTowerDollPtr->Destroyed(); PikaTowerDollPtr = NULL; } TArray<UTexture2D*> APikaGodStonePlayerController::PikaGetCharacterIocn(UDataTable* CharacterData) { TArray<UTexture2D*> PikaArrayTexture; if (CharacterData) { TArray<FPikaCharacterInfoDataTable*> PikaInfomationData; CharacterData->GetAllRows("PikaInfo", PikaInfomationData); for (int32 i = 0; i < CharacterData->RowMap.Num(); i++) { UTexture2D* PikaTexture = PikaInfomationData[i]->PikaIcon.LoadSynchronous(); if (PikaTexture) { PikaArrayTexture.Add(PikaTexture); } } } return PikaArrayTexture; } //获取特效中的Mesh TArray<UStaticMesh*> APikaGodStonePlayerController::PikaGetDataStaticMeshFormPartcle(UDataTable* MyCharacterDataTable, int32 CharacterID , FPikaComponentSpaceInfo& MyPikaComponentSpaceInfo) { TArray<UStaticMesh*> PikaMyStaticMeshArray; if (MyCharacterDataTable) { TArray<FPikaCharacterInfoDataTable*> PikaInfomationData; MyCharacterDataTable->GetAllRows("PikaInfo", PikaInfomationData); if (CharacterID >= 0 && CharacterID < PikaInfomationData.Num()) { //获取蓝图实例 UClass* PikaMyClass = PikaInfomationData[CharacterID]->PikaCharacterBlueprintKey.LoadSynchronous(); if (PikaMyClass && GetWorld()) { APikaCharacterBase* PikaMyCharacter = GetWorld()->SpawnActor<APikaCharacterBase>(PikaMyClass, FVector::ZeroVector, FRotator::ZeroRotator); //PikaMyCharacter->GetParticleMesh()->Template为加载特效的地方,此处相当于获取了特效 if (PikaMyCharacter && PikaMyCharacter->GetParticleMesh() && PikaMyCharacter->GetParticleMesh()->Template) { //判断该特效中的发射器个数是否大于0 if (PikaMyCharacter->GetParticleMesh()->Template->Emitters.Num()) { //从特效中的发射器中搜索Mesh for (int32 i = 0; i < PikaMyCharacter->GetParticleMesh()->Template->Emitters.Num(); i++) { const UParticleEmitter* PikaMyEmitter = PikaMyCharacter->GetParticleMesh()->Template->Emitters[i]; if (PikaMyEmitter) { UParticleLODLevel* PikaMyLOD = PikaMyEmitter->LODLevels[0]; //PikaMyLOD->bEnabled表示当前LOD是否为启动状态 if (PikaMyLOD && PikaMyLOD->bEnabled) { UParticleModuleTypeDataMesh* PikaMyParticleDataMesh = Cast<UParticleModuleTypeDataMesh>(PikaMyLOD->TypeDataModule); //获取特效中的Mesh if (PikaMyParticleDataMesh && PikaMyParticleDataMesh->Mesh) { //复制Mesh UStaticMesh* PikaMyParticleMeshCopy = Cast<UStaticMesh>(StaticDuplicateObject(PikaMyParticleDataMesh->Mesh, this)); if (PikaMyParticleMeshCopy) { PikaMyStaticMeshArray.Add(PikaMyParticleMeshCopy); //获取特效的尺寸,用来控制生成绿色模型的大小 //PikaMyLOD->Modules是指特效个每个发射器里的一行,如Lifetime、Inital Size等 for (int32 IndexMesh = 0 ; IndexMesh < PikaMyLOD->Modules.Num() ; IndexMesh++) { bool PikaIsComponentSpaceInformation = false; UParticleModuleSize* PikaMeshSize = Cast<UParticleModuleSize>(PikaMyLOD->Modules[IndexMesh]); UParticleModuleLocation* PikaMeshLocation = Cast<UParticleModuleLocation>(PikaMyLOD->Modules[IndexMesh]); UParticleModuleMeshRotation* PikaMeshRotation = Cast<UParticleModuleMeshRotation>(PikaMyLOD->Modules[IndexMesh]); //判断是不是MeshSize if (PikaMeshSize) { MyPikaComponentSpaceInfo.PikaComponentSize.Add(PikaMeshSize->StartSize.PikaqiuGetMaxValueVec()); PikaIsComponentSpaceInformation = true; } //判断是不是MeshLocation if (PikaMeshLocation) { MyPikaComponentSpaceInfo.PikaComponentLocation.Add(PikaMeshLocation->StartLocation.PikaqiuGetMaxValueVec()); PikaIsComponentSpaceInformation = true; } //判断是不是MeshRotation if (PikaMeshRotation) { MyPikaComponentSpaceInfo.PikaComponentRotation.Add((PikaMeshRotation->StartRotation.PikaqiuGetMaxValueVec()).Rotation()); PikaIsComponentSpaceInformation = true; } if (PikaIsComponentSpaceInformation) { if (!MyPikaComponentSpaceInfo.PikaComponentRotation.IsValidIndex(MyPikaComponentSpaceInfo.PikaGetMax() - 1)) { //MyPikaComponentSpaceInfo.PikaComponentRotation为无效值时,添加一个基本值 MyPikaComponentSpaceInfo.PikaComponentRotation.Add(FRotator::ZeroRotator); } if (!MyPikaComponentSpaceInfo.PikaComponentLocation.IsValidIndex(MyPikaComponentSpaceInfo.PikaGetMax() - 1)) { //MyPikaComponentSpaceInfo.PikaComponentLocation为无效值时,添加一个基本值 MyPikaComponentSpaceInfo.PikaComponentLocation.Add(FVector::ZeroVector); } if (!MyPikaComponentSpaceInfo.PikaComponentSize.IsValidIndex(MyPikaComponentSpaceInfo.PikaGetMax() - 1)) { //MyPikaComponentSpaceInfo.PikaComponentSize为无效值时,添加一个基本值 MyPikaComponentSpaceInfo.PikaComponentSize.Add(FVector(1, 1, 1)); } } } } } } } } } PikaMyCharacter->Destroy(true); PikaMyCharacter = NULL; } } } } return PikaMyStaticMeshArray; } TArray<FName> APikaGodStonePlayerController::PikaGetCharacterName(UDataTable* CharacterData) { TArray<FName> PikaTArrayFName; return CharacterData != NULL ? CharacterData->GetRowNames() : PikaTArrayFName; } TArray<FText> APikaGodStonePlayerController::PikaGetCharacterIntroduction(UDataTable* CharacterData) { TArray<FText> PikaTArrayFText; TArray<FPikaCharacterInfoDataTable*> PikaInformationData; CharacterData->GetAllRows("InformationData", PikaInformationData); for (int32 i = 0; i < PikaInformationData.Num(); i++) { PikaTArrayFText.Add(PikaInformationData[i]->PikaComment); } return PikaTArrayFText; } float** APikaGodStonePlayerController::PikaRegisterCharacterData(UDataTable* CharacterData) { float** PikaSaveCharacterData = NULL; if (CharacterData) { TArray<FPikaCharacterInfoDataTable*> PikaInformationData; CharacterData->GetAllRows("InformationData", PikaInformationData); //申请行空间 PikaSaveCharacterData = new float*[PikaInformationData.Num()]; //申请列排空间 for (int32 i = 0; i < PikaInformationData.Num(); i++) { PikaSaveCharacterData[i] = new float[EPikaCharacterInfoDataTableType::DATA_PikaCharacterMax]; } for (int32 i = 0; i < PikaInformationData.Num(); i++) { for (int32 indexI = 0; indexI < PikaInformationData.Num(); indexI++) { switch (indexI) { case EPikaCharacterInfoDataTableType::DATA_PikaCharacterHealth: PikaSaveCharacterData[i][indexI] = PikaInformationData[i]->PikaMaxHealth; break; case EPikaCharacterInfoDataTableType::DATA_PikaCharacterAttack: PikaSaveCharacterData[i][indexI] = PikaInformationData[i]->PikaPhysicalAttack; break; case EPikaCharacterInfoDataTableType::DATA_PikaCharacterArm: PikaSaveCharacterData[i][indexI] = PikaInformationData[i]->PikaArmor; break; case EPikaCharacterInfoDataTableType::DATA_PikaCharacterEmpircalValue: PikaSaveCharacterData[i][indexI] = PikaInformationData[i]->PikaMaxExperienceValue; break; case EPikaCharacterInfoDataTableType::DATA_PikaCharacterAttackSpeed: PikaSaveCharacterData[i][indexI] = PikaInformationData[i]->PikaAttackSpeed; break; case EPikaCharacterInfoDataTableType::DATA_PikaCharacterComsumeGlod: PikaSaveCharacterData[i][indexI] = PikaInformationData[i]->PikaComsumeGold; break; case EPikaCharacterInfoDataTableType::DATA_PikaCharacterConstructionTime: PikaSaveCharacterData[i][indexI] = PikaInformationData[i]->PikaConstructionTime; break; case EPikaCharacterInfoDataTableType::DATA_PikaCharacterAddGlod: PikaSaveCharacterData[i][indexI] = PikaInformationData[i]->PikaAddComsume; break; case EPikaCharacterInfoDataTableType::DATA_PikaCharacterAddHealth: PikaSaveCharacterData[i][indexI] = PikaInformationData[i]->PikaAddHealth; break; case EPikaCharacterInfoDataTableType::DATA_PikaCharacterAddPhysicalAttack: PikaSaveCharacterData[i][indexI] = PikaInformationData[i]->PikaAddPhysicalAttack; break; case EPikaCharacterInfoDataTableType::DATA_PikaCharacterAddArmor: PikaSaveCharacterData[i][indexI] = PikaInformationData[i]->PikaAddArmor; break; case EPikaCharacterInfoDataTableType::DATA_PikaCharacterAddAttackSpeed: PikaSaveCharacterData[i][indexI] = PikaInformationData[i]->PikaAddAttackSpeed; break; case EPikaCharacterInfoDataTableType::DATA_PikaCharacterAddEmpiricalValue: PikaSaveCharacterData[i][indexI] = PikaInformationData[i]->PikaAddExperienceValue; break; } } } } return PikaSaveCharacterData; } TArray<float> APikaGodStonePlayerController::PikaGetCharacterData(UDataTable* CharacterData, float** NewFloatArray, EPikaCharacterInfoDataTableType::Type CharacterInformationDataType) { TArray<float> PikaBaseArrayCharacterData; if (CharacterData && NewFloatArray) { TArray<FPikaCharacterInfoDataTable*> PikaInformationData; CharacterData->GetAllRows("InformationData", PikaInformationData); for (int32 i = 0; i < PikaInformationData.Num(); i++) { PikaBaseArrayCharacterData.Add(NewFloatArray[i][CharacterInformationDataType]); } } return PikaBaseArrayCharacterData; } void APikaGodStonePlayerController::PikaReleaseCharacterData() { if (PikaAITowrerData) { TArray<FPikaCharacterInfoDataTable*> PikaInformationData; PikaAITowrerData->GetAllRows("InformationData", PikaInformationData); for (int32 i = 0; i < PikaInformationData.Num(); i++) { delete[] PikaMonsterCharacterData[i]; } delete[] PikaMonsterCharacterData; } if (PikaAIMonsterData) { TArray<FPikaCharacterInfoDataTable*> PikaInformationData; PikaAIMonsterData->GetAllRows("InformationData", PikaInformationData); for (int32 i = 0; i < PikaInformationData.Num(); i++) { delete[] PikaMonsterCharacterData[i]; } delete[] PikaMonsterCharacterData; } } int32 APikaGodStonePlayerController::PikaGetCurrentCharacterAverageLevel(bool CharacterClass /*= true*/) const { if (GetWorld()) { TArray<AActor*> PikaOutArray; //总和 int32 PikaTheSum = PIKA_ZERO; int32 PikaCharacterNumber = PIKA_ZERO; if (CharacterClass) { PikaGETALLACTOR(GetWorld(), APikaTowers::StaticClass(), PikaOutArray); } else { PikaGETALLACTOR(GetWorld(), APikaMonster::StaticClass(), PikaOutArray); } //获取数量 PikaCharacterNumber = PikaOutArray.Num(); for (AActor* PikaCharacterOriginal : PikaOutArray) { APikaCharacterBase* PikaCurrentRuleOfTheCharacter = (APikaCharacterBase*)PikaCharacterOriginal; if (PikaCurrentRuleOfTheCharacter) { //获取值 PikaTheSum += PikaCurrentRuleOfTheCharacter->PikaGetCharacterLevel(); } } if (PikaCharacterNumber != PIKA_ZERO) { return PikaTheSum / PikaCharacterNumber; } } return INDEX_NONE; }
PikaGodStonePlayerState.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/PlayerState.h" #include "PikaGlobalConfig.h" #include "Public/PikaGodStoneGameInstance.h" #include "PikaGameResource.h" #include "PikaGodStonePlayerState.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API APikaGodStonePlayerState : public APlayerState { GENERATED_BODY() public: //UPROPERTY() //TSubclassOf<UPikaGlobalConfig> PikaGlobalConfigInstance; UPROPERTY() UPikaGlobalConfig * PikaGlobalConfigPre; UPROPERTY() UPikaGameResource* PikaGameResources; APikaGodStonePlayerState(); void Tick(float DeltaTime) override; UPikaGodStoneGameInstance* PikaGetGameInstance(); void PikaPrint(FString PikaStr); };
PikaGodStonePlayerState.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaGodStonePlayerState.h" #include "ConstructorHelpers.h" #include "Public/PikaGodStonePlayerController.h" APikaGodStonePlayerState::APikaGodStonePlayerState() { PrimaryActorTick.bCanEverTick = true; //加载蓝图中的全局配置 //static ConstructorHelpers::FClassFinder<UPikaGlobalConfig>PikaGConfig(TEXT("/Game/GlobalConfig/PikaGlobalConfigBP")); //PikaGlobalConfigInstance = PikaGConfig.Class; //加载C++方式的全局配置 //PikaGlobalConfigInstance = UPikaGlobalConfig::StaticClass(); //在c++中引用蓝图中的全局配置 /*if (GetWorld() && PikaGlobalConfigInstance) { PikaGlobalConfigPre = NewObject<UPikaGlobalConfig>(GetWorld(), PikaGlobalConfigInstance); }*/ //数据配置 static ConstructorHelpers::FClassFinder<UPikaGameResource> PikaMyGameResourceClass(TEXT("/Game/MinMap/BP/PikaGameResourceBP")); static ConstructorHelpers::FObjectFinder<UDataTable> PikaMyDataTable(TEXT("/Game/TowerAI/DataTable/PikaTower")); static ConstructorHelpers::FObjectFinder<UDataTable> PikaMyDataTableMonster(TEXT("/Game/MonsterAI/DataTable/PikaMonster")); if (GetWorld()) { if (UPikaGlobalConfig::StaticClass()) { PikaGlobalConfigPre = NewObject<UPikaGlobalConfig>(GetWorld(), UPikaGlobalConfig::StaticClass()); //将存档进行赋值 if (PikaGetGameInstance()) { //获取当前正确的读取名字 FString DataName = PikaGetGameInstance()->PikaGetCurrentGameSaveName(); UPikaGameSaveData* PikaNewGameSaveData = Cast<UPikaGameSaveData>(PIKA_LOADGAME_SLOT(DataName, 0)); if (PikaNewGameSaveData) { PikaGlobalConfigPre->PikaGameData = PikaNewGameSaveData->PikaGodStongSaveData; PikaGlobalConfigPre->PikaGameLevelManangenment = PikaNewGameSaveData->PikaGameLevelManangenment; PikaGlobalConfigPre->PikaTowersData = PikaNewGameSaveData->PikaTowersData; PikaGlobalConfigPre->PikaTemporaryCacheData = PikaNewGameSaveData->PikaTemporaryCacheData; //PikaGlobalConfigPre->IsSave = NewGameSaveData->IsSave; //PikaGlobalConfigPre->MissionState = NewGameSaveData->MissionState; } } //加载资源 if (PikaMyGameResourceClass.Class) { PikaGameResources = NewObject<UPikaGameResource>(GetWorld(), PikaMyGameResourceClass.Class); /*//关卡条件载入 if (PikaGlobalConfigPre && PikaGameResources && PikaGameResources->CLevel.IsValidIndex(EnvironmentConfiguration->TDGameLevelManangenment.CurrentLevel) ) { //PikaGlobalConfigPre->PikaCurrentLevelCondition = TDGameResources->GetCurrentCondition(EnvironmentConfiguration->TDGameLevelManangenment.CurrentLevel); }*/ } //初始化Control数据 if (((APikaGodStonePlayerController*)GetWorld()->GetFirstPlayerController())) { //PikaAITowrerData = PikaMyDataTable.Object; //PikaAIMonsterData = PikaMyDataTableMonster.Object; //注册信息 //PikaTowersCharacterData = PikaRegisterCharacterData(PikaAITowrerData); //PikaMonsterCharacterData = PikaRegisterCharacterData(PikaAIMonsterData); //载入角色 ((APikaGodStonePlayerController*)GetWorld()->GetFirstPlayerController())->PikaAITowrerData = PikaMyDataTable.Object; ((APikaGodStonePlayerController*)GetWorld()->GetFirstPlayerController())->PikaAIMonsterData = PikaMyDataTableMonster.Object; //注册信息 ((APikaGodStonePlayerController*)GetWorld()->GetFirstPlayerController())->PikaTowersCharacterData = ((APikaGodStonePlayerController*)GetWorld()->GetFirstPlayerController())->PikaRegisterCharacterData(PikaMyDataTable.Object); ((APikaGodStonePlayerController*)GetWorld()->GetFirstPlayerController())->PikaMonsterCharacterData = ((APikaGodStonePlayerController*)GetWorld()->GetFirstPlayerController())->PikaRegisterCharacterData(PikaMyDataTableMonster.Object); //数据 ((APikaGodStonePlayerController*)GetWorld()->GetFirstPlayerController())->PikaGlobalConfigPre = PikaGlobalConfigPre; ((APikaGodStonePlayerController*)GetWorld()->GetFirstPlayerController())->PikaGameResourcePtr = PikaGameResources; //((APikaGodStonePlayerController*)GetWorld()->GetFirstPlayerController())->InitConditionUI(); } } } } void APikaGodStonePlayerState::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (PikaGlobalConfigPre) { float PikaMouseSpeed = PikaGlobalConfigPre->PikaMouseSetConf.MouseSpeed; return; } } UPikaGodStoneGameInstance* APikaGodStonePlayerState::PikaGetGameInstance() { return GetWorld() ? ((UPikaGodStoneGameInstance*)GetWorld()->GetGameInstance()) : NULL ; } void APikaGodStonePlayerState::PikaPrint(FString PikaStr) { if (GEngine) { GEngine->AddOnScreenDebugMessage(-1, 6.0f, FColor::Red, PikaStr); } }
PikaHallGameMode.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/GameModeBase.h" #include "Matinee/MatineeActor.h" #include "PikaHallGameMode.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API APikaHallGameMode : public AGameModeBase { GENERATED_BODY() //描边时间 //float PikaStrokeCurrentTime; public: APikaHallGameMode(); virtual void BeginPlay()override; private: //Matinee TArray<TWeakObjectPtr<AMatineeActor>> PikaMatineeArray; TArray<TWeakObjectPtr<ACameraActor>> PikaCameraArray; //描边材质 //UMaterialInstanceDynamic* PikaM_PostProcessBase; };
PikaHallGameMode.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaHallGameMode.h" #include "Public/PikaHallHUD.h" #include "Public/PikaHallPawn.h" #include "Public/PikaGameUserSettings.h" APikaHallGameMode::APikaHallGameMode() { //加载PlayerState PlayerStateClass = APikaGodStonePlayerState::StaticClass(); HUDClass = APikaHallHUD::StaticClass(); DefaultPawnClass = APikaHallPawn::StaticClass(); } void APikaHallGameMode::BeginPlay() { TArray<AActor*> PikaCurrentLevelActor; //获取场景内的ACameraActor PikaGETALLACTOR(GetWorld(), ACameraActor::StaticClass(), PikaCurrentLevelActor); //PikaCameraArray.SetNum(PikaCurrentLevelActor.Num()); //初始化相机 for (AActor* ElemCamera : PikaCurrentLevelActor) { ACameraActor* PikaCurrentCamera = Cast<ACameraActor>(ElemCamera); if (PikaCurrentCamera) { //游戏开始的相机 if (PikaCurrentCamera->GetName() == "CameraNewGame") { GetWorld()->GetFirstPlayerController()->SetViewTargetWithBlend(PikaCurrentCamera, 0); //CameraArray[ECameraArray::Camera_NewGame] = CurrentCamera; //continue; } } } //获取场景内的Matinee PikaCurrentLevelActor.Empty(); PikaGETALLACTOR(GetWorld(), AMatineeActor::StaticClass(), PikaCurrentLevelActor); PikaMatineeArray.SetNum(PikaCurrentLevelActor.Num()); //初始化Matinee for (AActor* ElemMatinee : PikaCurrentLevelActor) { AMatineeActor* PikaCurrentMatinee = Cast<AMatineeActor>(ElemMatinee); if (PikaCurrentMatinee) { //播放进入 if (PikaCurrentMatinee->GetName() == "MatineeNewGame") { PikaCurrentMatinee->Play(); //PikaMatineeArray[EMatineeArray::Matinee_Coming] = CurrentMatinee; continue; } } } //设置PikaGameUserSettings的UWorld if (UPikaGameUserSettings::PikaGetGameUserSettings()) { UPikaGameUserSettings::PikaGetGameUserSettings()->PikaSetretrieveWorldContext(GetWorld()); //播放背景音乐 UPikaGameUserSettings::PikaGetGameUserSettings()->PikaPlayBGM(); //设置分辨率和窗口模式 UPikaGameUserSettings::PikaGetGameUserSettings()->PikaSetVideo(); } }
PikaHallHUD.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/HUD.h" #include "PikaUIMainHall.h" #include "PikaHallHUD.generated.h" /** * */ UCLASS() class PIKAGODSTONE_API APikaHallHUD : public AHUD { GENERATED_BODY() public: APikaHallHUD(); UPROPERTY() UPikaUIData* PikaUIDataPtr; //virtual void Tick(float DeltaSeconds)override; //释放 virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override; private: UPikaUIMainHall* PikaMianHallPtr; };
PikaHallHUD.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaHallHUD.h" #include "ConstructorHelpers.h" APikaHallHUD::APikaHallHUD() { if (GetWorld()) { //加载我们的mainHall PikaUIDataPtr = NewObject<UPikaUIData>(GetWorld(), UPikaUIData::StaticClass()); static ConstructorHelpers::FClassFinder<UPikaUIMainHall> PikaMyGameInterface(TEXT("/Game/HUD/HallUI/PikaUIMainHallBP")); if (PikaMyGameInterface.Class && PikaUIDataPtr) { PikaMianHallPtr = CreateWidget<UPikaUIMainHall>(GetWorld(), PikaMyGameInterface.Class); PikaMianHallPtr->PikaUIDataPtr = PikaUIDataPtr; PikaMianHallPtr->AddToViewport(); PikaMianHallPtr->PikaDrawUIToScreen(); } //打开我们的鼠标箭头 if (GetWorld()->GetFirstPlayerController()) GetWorld()->GetFirstPlayerController()->bShowMouseCursor = true; } } void APikaHallHUD::EndPlay(const EEndPlayReason::Type EndPlayReason) { if (PikaMianHallPtr) PikaMianHallPtr->RemoveFromViewport(); PikaMianHallPtr = NULL; Super::EndPlay(EndPlayReason); }
PikaHallPawn.h
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "GameFramework/Pawn.h" #include "PikaHallPawn.generated.h" UCLASS() class PIKAGODSTONE_API APikaHallPawn : public APawn { GENERATED_BODY() public: // Sets default values for this pawn's properties APikaHallPawn(); protected: // Called when the game starts or when spawned virtual void BeginPlay() override; public: // Called every frame virtual void Tick(float DeltaTime) override; // Called to bind functionality to input virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; };
PikaHallPawn.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Public/PikaHallPawn.h" // Sets default values APikaHallPawn::APikaHallPawn() { // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; } // Called when the game starts or when spawned void APikaHallPawn::BeginPlay() { Super::BeginPlay(); } // Called every frame void APikaHallPawn::Tick(float DeltaTime) { Super::Tick(DeltaTime); } // Called to bind functionality to input void APikaHallPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); }
11
22