从QuickDraw项目入门,制作一个简单的2D小游戏2

一.类继承
继续上一次的工作,在内容浏览器中右键Samurai类,创建派生自Samurai类的C++类,并将其命名为Samurai_Player。

然后进行同样的操作,创建一个名为Samurai_NPC的派生类。
创建一个名为BP_Samurai_Player的蓝图类,并替换原先的BP_Samurai实例,最后删除蓝图类BP_Samurai。


替换完后需要重新设置一下变量参数,再把这个实例名字改成Samurai_Player
再创建一个基于Samurai_NPC的蓝图类,命名为BP_Samurai_NPC,相同的,在场景中创建一个它的实例,命名为Samurai_NPC。
设定这个实例的滑动参数

设定这个实例用到的精灵

二.感叹号精灵
新建一个C++类,父类选择Actor

命名为Exclamation,然后在Exclamation.h里这样写

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
//Paper2D的部分头文件
#include "PaperFlipbookComponent.h"
#include "PaperSpriteComponent.h"
#include "Exclamation.generated.h"

UCLASS()
class QUICKDRAW_API AExclamation : public AActor
{
	GENERATED_BODY()
	
public:	
	AExclamation();

	//精灵组件,赋予Samurai类有形实体
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	TObjectPtr<UPaperSpriteComponent> SpriteComponent;

protected:
	virtual void BeginPlay() override;

public:	
	virtual void Tick(float DeltaTime) override;

	//控制组件是否可见
	UFUNCTION()
	void SetVisibility(bool IsVisible);

};

在Exclamation.cpp中这样写

#include "Exclamation.h"

AExclamation::AExclamation()
{
	PrimaryActorTick.bCanEverTick = true;

	//创建精灵组件,并将其作为根组件
	this->SpriteComponent = CreateDefaultSubobject<UPaperSpriteComponent>(TEXT("T_Exclamation_Sprite"));
	this->SpriteComponent->SetupAttachment(this->RootComponent);

}

void AExclamation::BeginPlay()
{
	Super::BeginPlay();
	//游戏开始时不可见
	this->SetVisibility(false);
}

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

}

void AExclamation::SetVisibility(bool IsVisible)
{
	this->SpriteComponent->SetVisibility(IsVisible);
}

然后基于这个C++类新建一个蓝图类,命名为BP_Exclamation

在关卡中创建一个该蓝图类的实例,再进行编辑,选择精灵和材质,不要忘记将透明排序设置为1

最后把这个实例放到地图中间位置

三.游戏模式实现
创建一个基于GameMode的C++类,命名为GM_Duel

GM_Duel.h中这样实现

#pragma once

#include "CoreMinimal.h"
#include "Exclamation.h"
#include "GameFramework/GameMode.h"
#include "GM_Duel.generated.h"

//枚举类
UENUM(BlueprintType)
enum class E_Phase : uint8
{
	Intro UMETA(DisplayName = "Intro"),
	Wait UMETA(DisplayName = "Wait"),
	Draw UMETA(DisplayName = "Draw"),
	Finished UMETA(DisplayName = "Finished")
};

UCLASS()
class QUICKDRAW_API AGM_Duel : public AGameMode
{
	GENERATED_BODY()
	
	

public:
	//统计游戏开始时长
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	double ElapsedTime;

	//Draw阶段最小开始时间
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	double MinDrawStartTime = 2.0;

	//Draw阶段最大开始时间
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	double MaxDrawStartTime = 5.0;

	//标识目前游戏阶段
	E_Phase Phase = E_Phase::Intro;
	
	//感叹号组件的指针
	TObjectPtr<AActor> Exclamation;

	//游戏开始的时间,用于游戏阶段变更
	double StartTime = 1.0;

	//游戏开始时执行
	virtual void BeginPlay() override;

	//每帧处理
	virtual void Tick(float DeltaTime) override;
	
	//从wait阶段转化到draw阶段
	UFUNCTION(BlueprintCallable)
	void TransWaitToDraw();
};

GM_Duel.cpp中这样实现

#include "GM_Duel.h"
#include "Kismet/GameplayStatics.h"
#include <Kismet/KismetSystemLibrary.h>


void AGM_Duel::BeginPlay()
{
	//游戏开始时取得第一个Exclamation类的实例的指针
	this->Exclamation = UGameplayStatics::GetActorOfClass(this->GetWorld(), AExclamation::StaticClass());

}

void AGM_Duel::Tick(float DeltaTime)
{
	this->ElapsedTime += DeltaTime;
	//GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Green, FString::Printf(TEXT("%f"), this->ElapsedTime));
	switch (this->Phase)
	{
	case E_Phase::Intro:
	{
		//在intro阶段,等两个精灵滑动结束后,切换到wait阶段,然后延迟一段时间转进draw阶段
		if (this->ElapsedTime >= this->StartTime)
		{
			this->Phase = E_Phase::Wait;
			FLatentActionInfo LatentAction(0, FMath::Rand(), TEXT("TransWaitToDraw"), this);
			UKismetSystemLibrary::Delay(this, FMath::FRandRange(MinDrawStartTime, MaxDrawStartTime), LatentAction);
		}
		break;
	}
		

	case E_Phase::Wait:
	{
		
		break;
	}
		

	case E_Phase::Draw:
	{
		//GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Green, FString::Printf(TEXT("draw %i"), this->Phase));
		if (this->Exclamation != NULL)
		{
			//假如指针有效,将一个指向Exclamation类的指针指向他,然后设置可见性为true
			AExclamation* tem = Cast<AExclamation>(this->Exclamation);
			tem->SetVisibility(true);
		}
		break;
	}

	case E_Phase::Finished:
	{
		//GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Green, FString::Printf(TEXT("Finished %i"), this->Phase));
		break;
	}

	default:
	{
		break;
	}
	}

}

void AGM_Duel::TransWaitToDraw()
{
	this->Phase = E_Phase::Draw;
	//GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Green, FString::Printf(TEXT("TransWaitToDraw %i"), this->Phase));
}

编译保存一下之后来到项目设置

在地图模式中,设置游戏模式和地图

之后再次运行游戏能看到感叹号精灵在Draw阶段被绘制,而在其他阶段不可见

posted @ 2025-02-20 17:58  SuzumiyaYui  阅读(6)  评论(0)    收藏  举报