Files
BusyRabbit/Source/BusyRabbit/Private/Level/Generator/TerrainGeneratorBase.cpp
2025-09-23 02:52:33 +08:00

159 lines
3.6 KiB
C++

#include "Level/Generator/TerrainGeneratorBase.h"
UTerrainGeneratorBase::UTerrainGeneratorBase()
{
}
int32 UTerrainGeneratorBase::AddTerrain(const FGameplayTag& TerrainTag)
{
FTerrainNodeInfo NewNode;
NewNode.TerrainTag = TerrainTag;
NewNode.Probability = 1.0f;
NewNode.Weight = 1.0f;
NewNode.ParentHandle = -1;
NewNode.bIsLeafNode = true;
int32 Handle = NextHandle++;
TerrainNodes.Add(Handle, NewNode);
return Handle;
}
void UTerrainGeneratorBase::SetWeight(int32 Handle, float Weight)
{
if (FTerrainNodeInfo* Node = TerrainNodes.Find(Handle))
{
Node->Weight = FMath::Max(0.0f, Weight);
}
}
void UTerrainGeneratorBase::SetProbability(int32 Handle, float Probability)
{
if (FTerrainNodeInfo* Node = TerrainNodes.Find(Handle))
{
Node->Probability = FMath::Clamp(Probability, 0.0f, 1.0f);
}
}
void UTerrainGeneratorBase::SetExclusive(const TArray<int32>& Handles){
if (Handles.Num() <= 1) return;
ExclusiveGroups.Add(TSet<int32>(Handles));
}
void UTerrainGeneratorBase::BindChildTerrain(int32 ParentHandle, const TArray<int32>& ChildHandles)
{
if (FTerrainNodeInfo* ParentNode = TerrainNodes.Find(ParentHandle))
{
// 设置父节点为非叶子节点
ParentNode->bIsLeafNode = false;
// 添加子节点
ParentNode->ChildHandles = ChildHandles;
// 设置子节点的父节点
for (int32 ChildHandle : ChildHandles)
{
if (FTerrainNodeInfo* ChildNode = TerrainNodes.Find(ChildHandle))
{
ChildNode->ParentHandle = ParentHandle;
}
}
}
}
FGameplayTag UTerrainGeneratorBase::GetFinalTerrainTag(const int32 Handle) const{
if (const FTerrainNodeInfo* Node = TerrainNodes.Find(Handle)){
return Node->TerrainTag;
}
return FGameplayTag();
}
TArray<int32> UTerrainGeneratorBase::GetValidLeafNodes() const
{
TSet<int32> ValidNodes;
GetPreCheckVisibleHandles(ValidNodes);
// 检查互斥关系, 待实现
TSet<int32> FinalNodes;
for (int32 Handle : ValidNodes){
if (FinalNodes.Find(Handle)) continue;
FinalNodes.Add(Handle);
}
// 只保留叶子节点
TArray<int32> LeafNodes;
for (int32 Handle : FinalNodes)
{
const FTerrainNodeInfo* Node = TerrainNodes.Find(Handle);
if (Node && Node->bIsLeafNode)
{
LeafNodes.Add(Handle);
}
}
return LeafNodes;
}
void UTerrainGeneratorBase::GetPreCheckVisibleHandles(TSet<int32>& VisibleHandles)const{
bool bShouldAppear;
TArray<bool> AppearanceCheckResult;
const int TerrainNodeCount = TerrainNodes.Num();
AppearanceCheckResult.Init(true, TerrainNodeCount);
for (const auto& Pair : TerrainNodes) {
const int Handle = Pair.Key;
const FTerrainNodeInfo* Node = &Pair.Value;
if (AppearanceCheckResult[Handle]) {
bShouldAppear = FMath::FRand() < Node->Probability;
AppearanceCheckResult[Handle] = bShouldAppear;
}
else {
bShouldAppear = false;
}
if (!bShouldAppear) {
for (const int32 ChildHandle : Pair.Value.ChildHandles) {
AppearanceCheckResult[ChildHandle] = false;
}
}
}
for (int i = 0; i < TerrainNodeCount; ++i) {
if (AppearanceCheckResult[i]) {
VisibleHandles.Add(i);
}
}
}
TArray<FGameplayTag> UTerrainGeneratorBase::GenerateMap(int32 Width, int32 Height)
{
TArray<FGameplayTag> Map;
Map.SetNum(Width * Height);
// 获取有效的叶子节点
TArray<int32> ValidLeafNodes = GetValidLeafNodes();
if (ValidLeafNodes.Num() == 0)
{
UE_LOG(LogTemp, Error, TEXT("No valid terrain nodes to generate map!"));
return Map;
}
if (GenerateWithNodes(Map, Width, Height, ValidLeafNodes))
{
return Map;
}
else
{
return TArray<FGameplayTag>();
}
}
bool UTerrainGeneratorBase::GenerateWithNodes(TArray<FGameplayTag>& Map, int32 Width, int32 Height, const TArray<int32>& ValidLeafNodes)
{
return false;
}