首页 > 编程语言 >UE4 C++ 随机生成迷宫地图

UE4 C++ 随机生成迷宫地图

时间:2024-06-24 09:58:25浏览次数:21  
标签:房间 迷宫 C++ 生成 BoxComponent Actor 数组 UE4 TArray

参考

参考
原理就是利用一个房间的三个方向(排除进入口)出口(可以减少,即设置墙壁),从而获得下一次房间生成的位置,其中涉及到对于多个房间重叠,生成结束后如何对缺口进行修补等功能实现

RoomBaseActor

该Actor类是后续创建房间的基类,如果想要固定所有房间形状即只改变出口个数,那么在该类中可以添加StaticMeshComponent,实现房间的统一。

基本成员

这些成员变量或者函数是所有房间都需要具备的。

  1. BoxComponent:盒型碰撞器,该组件将用来检测生成时房间的重叠
  2. TArray<UArrowComponent*> 该数组将存储当前房间的出口
  3. TArray<UBoxComponent*> 该数组将存储当前房间的所有BoxComponent

Child Room Actor

如果在RoomBase只设置了基本成员,没有添加StaticMesh,那么就可以在Child中自定义房间类型,只需要注意每个房间的出入口匹配就可以了。在Child类中,才进行UArrowComponent组件的构建,因为只有Child类才会确定房间的出口

加载模型

即StaticMeshComponent在构造函数中加载模型,实现效果如同在蓝图中选择Mesh的示例。首先需要在项目文件夹中存在对应的模型,这样才能进行加载。

static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshAsset(TEXT("StaticMesh'/Game/StarterContent/Architecture/Wall_400x200.Wall_400x200'"));
if (MeshAsset.Succeeded())
{
	WallClose1->SetStaticMesh(MeshAsset.Object);
}

利用该函数ConstructorHelpers::FObjectFinder可以在项目文件夹中找到所需资源即TEXT后面的文本,而该文本可以直接在打开编辑器后,右键资源Copy Ref即可

Room Gernerate Actor

控制房屋生成的主要类

主要成员

  1. 生成结束封闭所有开放口的Actor

  2. 第一个生成的房间Actor

  3. 后续生成的房间Actor列表:将从中随机选择Actor
    上述3个成员变量,将利用TSubclassOf的方式在编辑器中选择对应的蓝图进行生成

  4. TArray<UArrowComponent*> 该数组将添加新创建房间的对应数组,并移除已使用的Arrow,之后的创建位置将通过Arrow获得

  5. TArray<UPrimitiveComponent*> 存放当前添加房间的BoxComponent的重叠结果,如果数组长度大于0,说明该位置已经有房间,那么最新生成的房间应该失效,即被删除

成员函数

初始化函数

该函数将生成第一个房间,初始化TArray<UArrowComponent*>数组

void AXRoomGenerate::GernerateStartRoom()
{
	AXRoomBase* SpawnTemp = GetWorld()->SpawnActor<AXRoomBase>(SpawnClass, GetActorTransform());
	LatestRoom = SpawnTemp;
	NextSpawDir.Append(LatestRoom->ArrowList);
}

检测当前位置是否已有生成

首先需要设置一个GameTrace,因为对于默认的BoxComponent他将对所有Trace检测出Overlap,而为了只检测已有房间的BoxComponent,需要将BoxComponent的Trace设置为新增Trace,然后设置BoxComponent的碰撞检测,只开启新增Trace,其他全部Ignore
在该函数中,将遍历新创建房间的TArray<UBoxComponent>数组,对每个BoxComponent进行检测,当有重叠,会将结果加入到TArray<UPrimitiveComponent>数组中。

bool AXRoomGenerate::CheckSpawnInSameLoc()
{
	for (auto& it : LatestRoom->BoxComponentList)
	{
		//存放重叠的可能
		TArray<UPrimitiveComponent*> temp;
		it->GetOverlappingComponents(temp);
		UnderOverlapList.Append(temp);
	}
	if (UnderOverlapList.Num() != 0) return false; // need Destroy
	else return true;
}

生成下一个房间

该函数为一个递归函数,通过设置的生成房间个数以及TArray<UArrowComponent>个数确定退出条件,每次会从TArray<UArrowComponent>随机选择一个Arrow位置来进行生成,删除Arrow,之后检测该房间位置是否已有生成,如果有,那么删除新生成的房间,并清空TArray<UPrimitiveComponent>数组,递归。如果没有,清空TArray<UPrimitiveComponent>数组,然后将该房间的Arrow数组添加到TArray<UArrowComponent*>数组中,控制次数-1,递归。

void AXRoomGenerate::SpawnNextRoom()
{
	if (CurSpawnTimes <= 0 || NextSpawDir.Num() == 0)
	{
		CloseHoles();
		return;
	}
	UArrowComponent* NextArrow = NextSpawDir[FMath::RandRange(0, NextSpawDir.Num() - 1)];
	NextSpawDir.Remove(NextArrow);
	FActorSpawnParameters FASP;
	FASP.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
	AXRoomBase* NextSpawnTemp = GetWorld()->SpawnActor<AXRoomBase>(
		NextSpawnRoomList[FMath::RandRange(0, NextSpawnRoomList.Num() - 1)],
		NextArrow->GetComponentTransform(),
		FASP
	);
	LatestRoom = NextSpawnTemp;
	if (!CheckSpawnInSameLoc())
	{
		UE_LOG(LogTemp, Warning, TEXT("Destroy"));
		UnderOverlapList.Empty();
		LatestRoom->Destroy();
		GetWorldTimerManager().SetTimer(SpawnTimer, this, &AXRoomGenerate::SpawnNextRoom, 1.0f, false);
		//SpawnNextRoom();
	}
	else
	{
		NextSpawDir.Append(LatestRoom->ArrowList);
		UnderOverlapList.Empty();
		CurSpawnTimes--;
		GetWorldTimerManager().SetTimer(SpawnTimer, this, &AXRoomGenerate::SpawnNextRoom, 1.0f, false);
		//SpawnNextRoom();
	}
}

标签:房间,迷宫,C++,生成,BoxComponent,Actor,数组,UE4,TArray
From: https://www.cnblogs.com/XTG111/p/18264141

相关文章