UE4小游戏4

记录UE4小游戏

创建一个继承与AIController的AIEnemy用于控制Enemy,Enemy类负责做状态的转换。
Enemy.h

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "..\Public\PacManCharacter.h"
#include "Enemy.generated.h"UCLASS()
class MYPACMAN_API AEnemy : public ACharacter
{GENERATED_BODY()public:// Sets default values for this character's propertiesAEnemy();protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;public:	// Called every framevirtual void Tick(float DeltaTime) override;// Called to bind functionality to inputvirtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;void SetVulnerable(); //状态转换void SetInVulnerable();//状态转换void SetMove(bool bMoveIt);//移动用AIEnemy类实现void Killed();//void ReArm();//死亡后恢复UPROPERTY(VisibleAnywhere,Category = Body)UStaticMeshComponent* EnemyBody;UFUNCTION()void OnCollision(class UPrimitiveComponent* HitComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);//碰撞函数bool bIsDead;
private:class UMaterialInterface* DefaultMaterial;//材质class UMaterialInterface* VulnerableMaterial;FTimerHandle TimeVulnerable; //处于可被吃状态的时间bool bIsVulnerable;};

Enemy.cpp

// Fill out your copyright notice in the Description page of Project Settings.//#include "Enemy.h"
#include "..\Public\Enemy.h"
#include "UObject/ConstructorHelpers.h"
#include "Components/CapsuleComponent.h"
//#include "GameFramework/Actor.h"
#include "TimerManager.h"
#include "..\Public\AIEnemy.h"
#include "GameFramework/CharacterMovementComponent.h"
// Sets default values
AEnemy::AEnemy()
{// 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;//创建bodyEnemyBody = CreateDefaultSubobject<UStaticMeshComponent> (TEXT("Body"));//用圆柱绑定外形static ConstructorHelpers::FObjectFinder<UStaticMesh> CylinderObj(TEXT("'/Game/StarterContent/Shapes/Shape_Cylinder'"));if (CylinderObj.Succeeded()){EnemyBody->SetStaticMesh(CylinderObj.Object);}//设置大小EnemyBody->SetWorldScale3D(FVector(0.7f, 0.7f, 1.0f));EnemyBody->SetRelativeLocation(FVector(0, 0, -50.0f));//为了和碰撞体适配下移动EnemyBody->SetupAttachment(RootComponent);//绑定为默认根组件//设置碰撞体大小GetCapsuleComponent()->SetCapsuleRadius(40.0f);GetCapsuleComponent()->SetCapsuleHalfHeight(50.0f);
//绑定材质static ConstructorHelpers::FObjectFinder<UMaterial> VulnerableMat(TEXT("Material'/Game/Materials/M_Enemy_Vulnerable.M_Enemy_Vulnerable'"));if (VulnerableMat.Succeeded()){VulnerableMaterial = Cast<UMaterialInterface>(VulnerableMat.Object);}//BaseCollisionComponent->SetSphereRadius(16);
//开启碰撞SetActorEnableCollision(true);AIControllerClass = AAIEnemy::StaticClass();
}// Called when the game starts or when spawned
void AEnemy::BeginPlay()
{Super::BeginPlay();DefaultMaterial = EnemyBody->GetMaterial(0); //游戏开始获取默认材质GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &AEnemy::OnCollision);//绑定碰撞GetCharacterMovement()->MaxWalkSpeed = 150.0f;//VulnerableMaterial//VulnerableMaterial = EnemyBody->GetMaterial(0, VulnerableMat);//SetVulnerable();}// Called every frame
void AEnemy::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}// Called to bind functionality to input
void AEnemy::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{Super::SetupPlayerInputComponent(PlayerInputComponent);}void AEnemy::SetVulnerable()
{GetWorldTimerManager().SetTimer(TimeVulnerable, this, &AEnemy::SetInVulnerable, 10.0f, false);//每隔TimeVulnerable时间变为SetInVulnerableif (bIsVulnerable)return;bIsVulnerable = true;EnemyBody->SetMaterial(0, VulnerableMaterial);GetCharacterMovement()->MaxWalkSpeed = 50.0f;
}void AEnemy::SetInVulnerable()
{//清楚TimeVulnerableGetWorldTimerManager().ClearTimer(TimeVulnerable);bIsVulnerable = false;EnemyBody->SetMaterial(0, DefaultMaterial);GetCharacterMovement()->MaxWalkSpeed = 150.0f;
}void AEnemy::SetMove(bool bMoveIt)
{
//用AIEnemy来控制EnemyAAIEnemy* AI = Cast<AAIEnemy>(GetController());if (bMoveIt){AI->SearchNewPoint();}else {AI->StopMove();}
}void AEnemy::Killed()
{if (bIsDead) {return;}bIsDead = true;GetCharacterMovement()->MaxWalkSpeed = 300.0f;AAIEnemy* AI = Cast<AAIEnemy>(GetController());AI->GoHome();
}void AEnemy::ReArm()
{bIsDead = false;GetCharacterMovement()->MaxWalkSpeed = 150.0f;if (bIsVulnerable) {SetInVulnerable();}SetMove(true);
}
void AEnemy::OnCollision(UPrimitiveComponent * HitComp, AActor * OtherActor, UPrimitiveComponent * OtherComp, int OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
{if (OtherActor->IsA(APacManCharacter::StaticClass())){if (bIsVulnerable) {Killed();}else{APacManCharacter* PacMan = Cast<APacManCharacter>(OtherActor);PacMan->Killed();}}
}

AIEnemy.h

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"
#include "AIController.h"
#include "..\Public\Enemy.h"
#include "..\MypacmanGameModeBase.h"
#include "..\Public\PacManCharacter.h"
#include "AIEnemy.generated.h"/*** */
UCLASS()
class MYPACMAN_API AAIEnemy : public AAIController
{GENERATED_BODY()public:void OnPossess(class APawn* InPawn) override; //==beginplayvirtual void OnMoveCompleted(FAIRequestID RequestID, const FPathFollowingResult& Result) override;//移动停止做什么void SearchNewPoint();void GoHome();void ReArm();//void StopMove();private:class AEnemy* Bot;FVector HomeLocation;FTimerHandle DeadTime;AMypacmanGameModeBase* GameMode;
};

AIEnemy.cpp

// Fill out your copyright notice in the Description page of Project Settings.//#include "AIEnemy.h"
#include "..\Public\AIEnemy.h"
#include "NavigationSystem.h"
#include "Kismet/GameplayStatics.h"
#include "TimerManager.h"void AAIEnemy::OnPossess(class APawn* InPawn) {Super::OnPossess(InPawn);Bot = Cast<AEnemy>(InPawn);HomeLocation = Bot->GetActorLocation();SearchNewPoint();GameMode = Cast<AMypacmanGameModeBase>(UGameplayStatics::GetGameMode(this));}void AAIEnemy::OnMoveCompleted(FAIRequestID RequestID, const FPathFollowingResult & Result)
{if (!Bot->bIsDead && GameMode->GetCurrentState()!=EGameState::Epause) {SearchNewPoint();}
}
//这个函数很重要,最好看下底层源码
void AAIEnemy::SearchNewPoint()
{UNavigationSystemV1* NavMesh = FNavigationSystem::GetCurrent<UNavigationSystemV1>(this);if (NavMesh) {const float SearchRadius = 10000.0f;FNavLocation RandomPt;const bool bFound = NavMesh->GetRandomReachablePointInRadius(Bot->GetActorLocation(), SearchRadius, RandomPt);//const bool bFound = NavMesh->GetRandomReachablePointInRadius(myPacMan->GetActorLocation(), SearchRadius, RandomPt);if (bFound){MoveToLocation(RandomPt);}}
}void AAIEnemy::GoHome()
{MoveToLocation(HomeLocation);GetWorldTimerManager().SetTimer(DeadTime,this,&AAIEnemy::ReArm,5.0f,false);
}void AAIEnemy::ReArm()
{GetWorldTimerManager().ClearTimer(DeadTime);Bot->ReArm();
}void AAIEnemy::StopMove()
{//StopMovement();MoveToLocation(Bot->GetActorLocation());
}

这里还需要改个东西
在这里插入图片描述
MypacmanGameModeBase.h

// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.#pragma once#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
//#include "PacManCharacter.h"
#include "MypacmanGameModeBase.generated.h"/*** */
enum class EGameState :short {EMenu,EPlaying,Epause,EGameOver,EWin
};
UCLASS()
class MYPACMAN_API AMypacmanGameModeBase : public AGameModeBase
{GENERATED_BODY()public:virtual void BeginPlay() override;EGameState GetCurrentState() const;void SetCurrentState(EGameState value);void SetEnemyVulnerable();private:EGameState currentState;TArray<class AEnemy*> Enemys;
};FORCEINLINE EGameState AMypacmanGameModeBase::GetCurrentState() const { return currentState; };

AMypacmanGameModeBase.cpp

// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.#include "MypacmanGameModeBase.h"
#include "Public/Enemy.h"
#include "EngineUtils.h"void AMypacmanGameModeBase::SetCurrentState(EGameState value)
{currentState = value;switch (value){case EGameState::EPlaying:for (auto Iter(Enemys.CreateIterator()); Iter; ++Iter){(*Iter)->SetMove(true);}break;case EGameState::Epause:for (auto Iter(Enemys.CreateIterator()); Iter; ++Iter){(*Iter)->SetMove(false);}break;case EGameState::EGameOver:for (auto Iter(Enemys.CreateIterator()); Iter; ++Iter){(*Iter)->Destroy();}break;case EGameState::EWin:for (auto Iter(Enemys.CreateIterator()); Iter; ++Iter){(*Iter)->Destroy();}break;default:break;}
}
void AMypacmanGameModeBase::SetEnemyVulnerable()
{for (auto Iter(Enemys.CreateIterator()); Iter; ++Iter){(*Iter)->SetVulnerable();}
}
void AMypacmanGameModeBase::BeginPlay()
{Super::BeginPlay();SetCurrentState(EGameState::EMenu);for (TActorIterator<AEnemy> enemyIter(GetWorld()); enemyIter; ++enemyIter){AEnemy* enemy = Cast<AEnemy>(*enemyIter);if (enemy){Enemys.Add(enemy);}}}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部