213 lines
6.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "FishingMapSystem.h"
#include "Engine/Engine.h"
UFishingMapNode::UFishingMapNode()
{
NodeID = FGuid::NewGuid();
NodeType = EMapNodeType::Battle;
LayerIndex = 0;
IndexInLayer = 0;
Position = FVector2D::ZeroVector;
}
void UFishingMapNode::RandomNodeType()
{
NodeType = static_cast<EMapNodeType>(FMath::RandRange(0, 1));
}
UFishingMapSystem::UFishingMapSystem()
{
}
void UFishingMapSystem::GenerateMap()
{
GenerateMapWithConfig(MapConfig);
}
void UFishingMapSystem::GenerateMapWithConfig(const UMapConfigAsset* Config)
{
// 清空现有数据
ClearMap();
// 生成节点
GenerateNodes();
// 计算节点位置
CalculateNodePositions();
// 生成连线
GenerateConnections();
UE_LOG(LogTemp, Log, TEXT("地图生成完成:%d层共%d个节点%d条连线"),
GetLayerCount(), AllNodes.Num(), AllConnections.Num());
}
int32 UFishingMapSystem::GetNodeAtLayerIndex(FGuid NodeID) const
{
for (FMapLayer Layer: AllLayers)
{
for (int i = 0; i < Layer.GetNodeNum(); i++)
{
if ( Layer.GetNode(i)->NodeID == NodeID)
return i;
}
}
return -1;
}
void UFishingMapSystem::ClearMap()
{
AllNodes.Empty();
AllConnections.Empty();
AllLayers.Empty();
}
void UFishingMapSystem::GenerateNodes()
{
AllLayers.SetNum(MapConfig->TotalLayers);
for (int32 LayerIndex = 0; LayerIndex < MapConfig->TotalLayers ; ++LayerIndex)
{
if (LayerIndex == MapConfig->TotalLayers - 1)
{
//最后一层 只有一个Boss
UFishingMapNode* NewNode = NewObject<UFishingMapNode>(this);
NewNode->LayerIndex = LayerIndex;
NewNode->IndexInLayer = 0;
NewNode->NodeType = EMapNodeType::Boss;
AllNodes.Add(NewNode);
AllLayers[LayerIndex].AddNode(NewNode);
}
else
{
// 随机生成节点数量
int32 NodeCount = FMath::RandRange(MapConfig->Layer_MinNodes, MapConfig->Layer_MaxNodes);
// 生成节点
for (int32 NodeIndex = 0; NodeIndex < NodeCount; ++NodeIndex)
{
UFishingMapNode* NewNode = NewObject<UFishingMapNode>(this);
NewNode->LayerIndex = LayerIndex;
NewNode->IndexInLayer = NodeIndex;
// 随机节点类型
NewNode->RandomNodeType();
AllNodes.Add(NewNode);
AllLayers[LayerIndex].AddNode(NewNode);
}
}
}
}
void UFishingMapSystem::CalculateNodePositions()
{
// float LayerSpacing = 1000.0f; // 层之间的距离
// float NodeSpacing = 300.0f; // 节点之间的距离
//
// for (int32 LayerIndex = 0; LayerIndex < AllLayers.Num(); ++LayerIndex)
// {
// FMapLayer& Layer= AllLayers[LayerIndex];
// int32 NodeCount = Layer.GetNodeNum();
//
// float X = LayerIndex * LayerSpacing;
// float TotalWidth = (NodeCount - 1) * NodeSpacing;
// float StartY = -TotalWidth * 0.5f;
//
// for (int32 NodeIndex = 0; NodeIndex <NodeCount; ++NodeIndex)
// {
// if (LayerNodes[NodeIndex])
// {
// float Y = StartY + NodeIndex * NodeSpacing;
// LayerNodes[NodeIndex]->Position = FVector2D(X, Y);
// }
// }
// }
}
void UFishingMapSystem::GenerateConnections()
{
AllConnections.Empty();
// 为每对相邻层生成连线
for (int32 LayerIndex = 0; LayerIndex < AllLayers.Num() - 1; ++LayerIndex)
{
TArray<FSimpleConnection> LayerConnections = GenerateNonCrossingConnections(LayerIndex, LayerIndex + 1);
AllConnections.Append(LayerConnections);
}
// 更新节点的连接信息
for (const FSimpleConnection& Connection : AllConnections)
{
// 找到起始节点并添加连接
for (UFishingMapNode* Node : AllNodes)
{
if (Node && Node->NodeID == Connection.FromNodeID)
{
Node->ConnectedNodes.AddUnique(Connection.ToNodeID);
break;
}
}
}
}
TArray<FSimpleConnection> UFishingMapSystem::GenerateNonCrossingConnections(int32 FromLayer, int32 ToLayer)
{
TArray<FSimpleConnection> Connections;
if (FromLayer == AllLayers.Num() - 2)
{
//倒数第二行所有都连接到最终boss房间
FMapLayer FromNodes = AllLayers[FromLayer];
FGuid BossID = AllLayers[ToLayer].GetNode(0)->NodeID;
for (int32 NodeIndex = 0; NodeIndex < FromNodes.GetNodeNum(); ++NodeIndex)
{
Connections.Add(FSimpleConnection(FromNodes.GetNode(NodeIndex)->NodeID, BossID));
}
}
else
{
//第一步 随机为每个fromnode 分配指定范围的上层节点
FMapLayer FromNodes = AllLayers[FromLayer];
FMapLayer ToNodes = AllLayers[ToLayer];
int32 LastToNodeIndex = 0;
for (int32 NodeIndex = 0; NodeIndex < FromNodes.GetNodeNum(); ++NodeIndex)
{
int32 connectionBeginIndex = LastToNodeIndex;
int32 endIndex = ToNodes.GetNodeNum() - 1;
//随机连线的最左侧位置根据当前所在layer的index 调整概率
int32 connectionEndIndex = FMath::Max(connectionBeginIndex,
(FMath::RandRange(connectionBeginIndex, endIndex + (FromNodes.GetNodeNum() - NodeIndex)) - (FromNodes.GetNodeNum() - NodeIndex)) );
//随机指定当前node 连接上层node的范围
LastToNodeIndex = FMath::RandRange(connectionBeginIndex, connectionEndIndex);
for(int32 i = connectionEndIndex; i < connectionEndIndex; ++i)
{
//添加连线
Connections.Add(FSimpleConnection(FromNodes.GetNode(NodeIndex)->NodeID, ToNodes.GetNode(connectionEndIndex)->NodeID));
}
}
//第二步 确保tolayer 每个节点都有连接线,没有连接线的分配 指定范围内的下层节点
if(LastToNodeIndex != ToNodes.GetNodeNum() - 1)
{
//还有上层节点是没有被连线状态,都连接到下层的最后一个节点
for(int32 ToNodeIndex = LastToNodeIndex; ToNodeIndex < ToNodes.GetNodeNum(); ++ToNodeIndex)
{
Connections.Add(FSimpleConnection(FromNodes.GetNode(FromNodes.GetNodeNum() - 1)->NodeID, ToNodes.GetNode(ToNodeIndex)->NodeID));
}
}
}
UE_LOG(LogTemp, Log, TEXT("生成层级 %d -> %d 的随机连接"),FromLayer, ToLayer);
for(auto connection: Connections)
{
UE_LOG(LogTemp, Log, TEXT("下层 %d -> 上层 %d "),GetNodeAtLayerIndex(connection.FromNodeID),
GetNodeAtLayerIndex(connection.FromNodeID));
}
return Connections;
}