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 properties
	AEnemy();



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;

	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;
    //创建body
	EnemyBody = 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时间变为SetInVulnerable
	if (bIsVulnerable)
		return;
	bIsVulnerable = true;
	EnemyBody->SetMaterial(0, VulnerableMaterial);

	GetCharacterMovement()->MaxWalkSpeed = 50.0f;
}

void AEnemy::SetInVulnerable()
{
     //清楚TimeVulnerable
	GetWorldTimerManager().ClearTimer(TimeVulnerable);
	bIsVulnerable = false;
	EnemyBody->SetMaterial(0, DefaultMaterial);
	GetCharacterMovement()->MaxWalkSpeed = 150.0f;
}

void AEnemy::SetMove(bool bMoveIt)
{
//用AIEnemy来控制Enemy
	AAIEnemy* 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; //==beginplay
	virtual 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);
		}
	}

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值