i trying create a small village dinamicly that its my result
my code
“VillageGenerator.h”
“Kismet/KismetMathLibrary.h”
AVillageGenerator::AVillageGenerator()
{
PrimaryActorTick.bCanEverTick = false;
RootScene = CreateDefaultSubobject<USceneComponent>(TEXT("RootScene"));
RootComponent = RootScene;
ISMC_Grass = CreateDefaultSubobject<UInstancedStaticMeshComponent>(TEXT("ISMC_Grass"));
ISMC_Grass->SetupAttachment(RootComponent);
ISMC_Grass->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
ISMC_Dirt = CreateDefaultSubobject<UInstancedStaticMeshComponent>(TEXT("ISMC_Dirt"));
ISMC_Dirt->SetupAttachment(RootComponent);
ISMC_Roads = CreateDefaultSubobject<UInstancedStaticMeshComponent>(TEXT("ISMC_Roads"));
ISMC_Roads->SetupAttachment(RootComponent);
ISMC_Houses = CreateDefaultSubobject<UInstancedStaticMeshComponent>(TEXT("ISMC_Houses"));
ISMC_Houses->SetupAttachment(RootComponent);
}
void AVillageGenerator::OnConstruction(const FTransform& Transform)
{
Super::OnConstruction(Transform);
}
void AVillageGenerator::BeginPlay()
{
Super::BeginPlay();
GenerateFullVillage();
}
void AVillageGenerator::GenerateFullVillage()
{.
FMath::RandInit(VillageSeed);
ClearVillage();
InitializeGrid();
GenerateRoads();
GenerateHousePlots();
GenerateBiomes();
SpawnVillage();
}
void AVillageGenerator::ClearVillage()
{
if (ISMC_Grass) ISMC_Grass->ClearInstances();
if (ISMC_Dirt) ISMC_Dirt->ClearInstances();
if (ISMC_Roads) ISMC_Roads->ClearInstances();
if (ISMC_Houses) ISMC_Houses->ClearInstances();
Grid.Empty();
}
void AVillageGenerator::InitializeGrid()
{
Grid.SetNum(GridSizeX * GridSizeY);
FVector Origin = FVector::ZeroVector;
for (int32 Y = 0; Y < GridSizeY; Y++)
{
for (int32 X = 0; X < GridSizeX; X++)
{
int32 i = GetIndex(X, Y);
Grid[i].GridX = X;
Grid[i].GridY = Y;
Grid[i].WorldPosition = Origin + FVector(X * TileSize, Y * TileSize, 0.0f);
Grid[i].Type = EVillageTileType::Empty;
}
}
}
void AVillageGenerator::GenerateRoads()
{
int32 WalkerX = GridSizeX / 2;
int32 WalkerY = GridSizeY / 2;
int32 Steps = (GridSizeX * GridSizeY) / 5;
for (int32 i = 0; i < Steps; i++)
{
if (IsValidCoordinate(WalkerX, WalkerY))
{
Grid[GetIndex(WalkerX, WalkerY)].Type = EVillageTileType::Road;
}
int32 Direction = FMath::RandRange(0, 3);
switch (Direction)
{
case 0: WalkerY++; break;
case 1: WalkerY--; break;
case 2: WalkerX++; break;
case 3: WalkerX--; break;
}
WalkerX = FMath::Clamp(WalkerX, 1, GridSizeX - 2);
WalkerY = FMath::Clamp(WalkerY, 1, GridSizeY - 2);
}
}
void AVillageGenerator::GenerateHousePlots()
{
for (int32 Y = 1; Y < GridSizeY - 1; Y++)
{
for (int32 X = 1; X < GridSizeX - 1; X++)
{
int32 CurrentIndex = GetIndex(X, Y);
if (Grid[CurrentIndex].Type == EVillageTileType::Empty)
{
bool bHasRoadNeighbor =
(Grid[GetIndex(X, Y + 1)].Type == EVillageTileType::Road) ||
(Grid[GetIndex(X, Y - 1)].Type == EVillageTileType::Road) ||
(Grid[GetIndex(X + 1, Y)].Type == EVillageTileType::Road) ||
(Grid[GetIndex(X - 1, Y)].Type == EVillageTileType::Road);
if (bHasRoadNeighbor)
{
if (FMath::FRand() < 0.4f)
{
Grid[CurrentIndex].Type = EVillageTileType::HousePlot;
}
}
}
}
}
}
void AVillageGenerator::GenerateBiomes()
{
for (int32 i = 0; i < Grid.Num(); i++)
{
if (Grid[i].Type == EVillageTileType::Empty)
{
float SampleX = (float)Grid[i].GridX * NoiseScale + (VillageSeed * 0.1f);
float SampleY = (float)Grid[i].GridY * NoiseScale + (VillageSeed * 0.1f);
float NoiseValue = FMath::PerlinNoise2D(FVector2D(SampleX, SampleY));
if (NoiseValue > 0.2f)
{
Grid[i].Type = EVillageTileType::Dirt;
}
else
{
Grid[i].Type = EVillageTileType::Grass;
}
}
}
}
void AVillageGenerator::SpawnVillage()
{
for (const FVillageTile& Tile : Grid)
{
FTransform Transform;
Transform.SetScale3D(FVector(1.0f));
float ZOffset = 0.0f;
switch (Tile.Type)
{
case EVillageTileType::Road:
ZOffset = 2.0f;
Transform.SetLocation(Tile.WorldPosition + FVector(0, 0, ZOffset));
if (ISMC_Roads->GetStaticMesh()) ISMC_Roads->AddInstance(Transform);
break;
case EVillageTileType::HousePlot:
ZOffset = 4.0f;
Transform.SetLocation(Tile.WorldPosition + FVector(0, 0, ZOffset));
Transform.SetRotation(FRotator(0, FMath::RandRange(0, 3) * 90.0f, 0).Quaternion());
if (ISMC_Houses->GetStaticMesh()) ISMC_Houses->AddInstance(Transform);
Transform.SetLocation(Tile.WorldPosition + FVector(0, 0, 1.0f));
Transform.SetRotation(FQuat::Identity);
if (ISMC_Dirt->GetStaticMesh()) ISMC_Dirt->AddInstance(Transform);
break;
case EVillageTileType::Dirt:
ZOffset = 0.0f;
Transform.SetLocation(Tile.WorldPosition + FVector(0, 0, ZOffset));
if (ISMC_Dirt->GetStaticMesh()) ISMC_Dirt->AddInstance(Transform);
break;
case EVillageTileType::Grass:
default:
ZOffset = 0.0f;
Transform.SetLocation(Tile.WorldPosition + FVector(0, 0, ZOffset));
if (ISMC_Grass->GetStaticMesh()) ISMC_Grass->AddInstance(Transform);
break;
}
}
}
int32 AVillageGenerator::GetIndex(int32 X, int32 Y) const
{
X = FMath::Clamp(X, 0, GridSizeX - 1);
Y = FMath::Clamp(Y, 0, GridSizeY - 1);
return X + (Y * GridSizeX);
}
bool AVillageGenerator::IsValidCoordinate(int32 X, int32 Y) const
{
return X >= 0 && X < GridSizeX && Y >= 0 && Y < GridSizeY;
}
what i doing wrong i using unreal engine 4.27.2
