UE4C++吃豆子游戏

 创建空项目,做如下设置:

复制到如下目录:

创建基于Pawn的C++类

在PacmanPawn.h中添加属性

添加该类的蓝图类并添加FloatingPawnMovement以及Sphere组件

打开如下选项并选择sphere

设置材质

添加StaticMesh组件,并设置Static Mesh

把第一个StaticMesh的visible属性设置为false改变大小

新建GameMode蓝图类

放置Camera

添加定制事件

实现该蓝图

设置游戏模式

绑定碰撞函数

实现Tick与SetDirection函数

新建Player Controller C++类并取名为PacmanController.h

PacmanController.h中添加属性

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/PlayerController.h"
#include "PacmanPawn.h"
#include "PacmanController.generated.h"

/**
 * 
 */
UCLASS()
class PACMAN_API APacmanController : public APlayerController
{
	GENERATED_BODY()

protected:
	void SetupInputComponent() override;

	APacmanPawn* GetPacmanPawn() const;

public:
	void MoveUp();
	void MoveDown();
	void MoveLeft();
	void MoveRight();

	
};

Player Controller Class设置为PacmanController,这样在C++类中就能获取到场景中Actor

设置完以上后,在PacmanController.cpp中GetPawn就可以得到场景中的Pawn

添加输入

添加输入绑定

实现绑定的函数:

void APacmanController::MoveDown()
{
	if (GetPacmanPawn() != nullptr) {
		GetPacmanPawn()->SetDirection(FVector::DownVector);
	}
}

void APacmanController::MoveLeft()
{
	if (GetPacmanPawn() != nullptr) {
		GetPacmanPawn()->SetDirection(FVector::LeftVector);
	}
}

void APacmanController::MoveRight()
{
	if (GetPacmanPawn() != nullptr) {
		GetPacmanPawn()->SetDirection(FVector::RightVector);
	}
}

在游戏开始设置Frozen状态

之所以能调用SetFrozen函数是因为:

添加继承自Actor的C++类Foodie

Foodie.h添加如下属性

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"


#include "Kismet/GameplayStatics.h"
#include "Sound/SoundCue.h"

#include "Foodie.generated.h"

UENUM(BlueprintType)
enum class EFoodieType : uint8 {
	Regula,
	PowerUp
};


//创建委托,用于事件的触发
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FFoodieEatenEvent, EFoodieType, FoodieType);

UCLASS()
class PACMAN_API AFoodie : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AFoodie();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;


	void Consume();


	UPROPERTY(EditAnywhere)
		EFoodieType FoodieType = EFoodieType::Regula;

	UPROPERTY(BlueprintAssignable, BlueprintCallable)
		FFoodieEatenEvent FoodieEatenEvent;

private:
	UPROPERTY(EditAnywhere)
		USoundCue* ConsumptionSound;

};

编译并设置属性

添加StaticMesh并设置属性

实现Foodie的Consume函数

在PacmanPawn.cpp中实现碰撞函数

在Foodie_Regula_BP中添加Tag

接下来把Foodie_Regular_BP放在地图上:

添加敌人Pawn C++类

EnemyPawn.h中添加属性

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "EnemyPawn.generated.h" 

UENUM(BlueprintType)
enum class EEnemyState : uint8 {
	Default,
	Idle
};

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FEnemyStateChangedEventIn, EEnemyState, NewStata);

UCLASS()
class PACMAN_API AEnemyPawn : public APawn
{
	GENERATED_BODY()

public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		EEnemyState State = EEnemyState::Default;

	UFUNCTION(BlueprintCallable)
		void Hunt();

	UFUNCTION(BlueprintCallable)
		void Idle();

	FEnemyStateChangedEventIn& OnStateChanged() { return StateChangedEventIn; }

private:
	UPROPERTY(BlueprintAssignable, BlueprintCallable)
		FEnemyStateChangedEventIn 	StateChangedEventIn;
	;
	 

};

EnemyPawn.cpp中实现:

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


#include "EnemyPawn.h"

void AEnemyPawn::Hunt()
{
	State = EEnemyState::Default;

	StateChangedEventIn.Broadcast(State);
}

void AEnemyPawn::Idle()
{
	State = EEnemyState::Idle ;

	StateChangedEventIn.Broadcast(State);
}

添加该类的蓝图类

在蓝图类中进行设置

添加两个Static Mesh

设置Mesh和Material

设置碰撞

设置物理属性的Gravity属性

设置另外一个Static Mesh

设置碰撞:

设置第一个StaticMesh visible为false

设置第二个StaticMesh的重力属性

添加AIController变量:

在Enemy_BP中添加函数并实现:

需要注意的是这个事件需要添加参数

添加碰撞函数

实现碰撞函数

新建Foodie蓝图类

打开并设置属性

添加StaticMes并设置属性

绑定事件并添加函数

添加变量并分别设置速度大小

添加设置速度函数并实现:

实现Eaten函数

添加到地图中

设置生效时间:

运行截图

完善功能,添加瞬移功能

添加基类为Actor的C++类,并取名为TeleporterActor

TeleporterActor.h

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "TeleporterActor.generated.h"

class USoundCue;

UCLASS()
class PACMAN_API ATeleporterActor : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ATeleporterActor();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	void TeleportToTarget(AActor* Actor);

	UPROPERTY(EditAnywhere)
		ATeleporterActor* Target = nullptr;

	UPROPERTY(EditAnywhere)
		USoundCue* TeleportSound;

	UFUNCTION()
		void OnOverlapBegin(AActor* TeleporterActor, AActor* OtherActor);

};

TeleporterActor.cpp

// Fill out your copyright notice in the Description page of Project Settings.
#include "TeleporterActor.h"


#include "Engine/Public/TimerManager.h"
#include "Kismet/GameplayStatics.h"
#include "Sound/SoundCue.h"
#include "Components/SceneComponent.h"

// Sets default values
ATeleporterActor::ATeleporterActor()
{
 	// 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;

}

// Called when the game starts or when spawned
void ATeleporterActor::BeginPlay()
{
	Super::BeginPlay();
	
	OnActorBeginOverlap.AddDynamic(this, &ATeleporterActor::OnOverlapBegin);
}

// Called every frame
void ATeleporterActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void ATeleporterActor::TeleportToTarget(AActor* Actor)
{
	UE_LOG(LogTemp, Warning, TEXT("cOLLISION"));
	USceneComponent* TargetSpawn = Cast<USceneComponent>(Target->GetDefaultSubobjectByName("Spawn"));

	if (TargetSpawn != nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("Spawn is not null"));
		UGameplayStatics::PlaySound2D(this, TeleportSound);

		Actor->SetActorLocation(TargetSpawn->GetComponentLocation());
	}
	else
	{
		UE_LOG(LogTemp, Warning, TEXT("Spawn is null"));
	}
	
}

void ATeleporterActor::OnOverlapBegin(AActor* TeleporterActor, AActor* OtherActor)
{
	if (OtherActor->ActorHasTag("Pacman"))
	{
		//下一帧调用
		GetWorldTimerManager().SetTimerForNextTick([OtherActor, this]() {TeleportToTarget(OtherActor); });
	}
}

添加该类的蓝图类

做如下设置:

改名之后这里就可以得到这个组件:

放入关卡中,并设置Target:

游戏已经完成,在以上两个位置可以实现穿越的功能。

 代码链接:CodingInn/UE4 Basic Tutorial

猜你喜欢

转载自blog.csdn.net/Learning_xzj/article/details/124705311