Hello everyone.
I’m new into procedural generation and I am stuck at making rules to control locations objects are placed. The system I have created is based off of Ian Shadden’s design. Here is an example of my code and then a photo of what it does.
// Sets default values
ARoomGeneration::ARoomGeneration()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
ISM_Floor = CreateDefaultSubobject<UInstancedStaticMeshComponent>(TEXT("ISM_Floor"));
ISM_Floor->SetStaticMesh(SM_Floor);
this->SetRootComponent(ISM_Floor);
ISM_Wall = CreateDefaultSubobject<UInstancedStaticMeshComponent>(TEXT("ISM_Wall"));
ISM_Wall->SetStaticMesh(SM_Wall);
ISM_Wall->AttachTo(RootComponent);
ISM_Door = CreateDefaultSubobject<UInstancedStaticMeshComponent>(TEXT("ISM_Door"));
ISM_Door->SetStaticMesh(SM_Door);
ISM_Door->AttachTo(RootComponent);
}
//Called when the object is placed, changed, or spawned in editor/scene
void ARoomGeneration::OnConstruction(const FTransform& Transform)
{
//Select Door Count for exit doors to be spawned
DoorCount = FMath::RandRange(0, 3);
GenerateFloor();
GenerateWall();
GenerateDoors();
//Set Location of child instances to match the floor's location
ISM_Wall->SetRelativeLocation(FVector(0, 0, 0));
ISM_Door->SetRelativeLocation(FVector(0, 0, 0));
}
// Called when the game starts or when spawned
void ARoomGeneration::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ARoomGeneration::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
}
//Generate a tile system to create a floor
void ARoomGeneration::GenerateFloor()
{
ISM_Floor->ClearInstances();
for (int32 n = 0; n < GridSizeX * GridSizeY; n++)
{
FTransform newTransform = FTransform(FVector((n / GridSizeY) * TileSize, (n % GridSizeY) * TileSize, 0));
ISM_Floor->AddInstance(newTransform);
}
}
//Generate walls on the outer most edges of the floor
void ARoomGeneration::GenerateWall()
{
ISM_Wall->ClearInstances();
//Generate North Walls
for(int32 n = 0; n < GridSizeX; n++)
{
FTransform newTransform = FTransform(FVector((n % GridSizeX) * TileSize, (n / GridSizeX) * TileSize, 300));
ISM_Wall->AddInstance(newTransform);
}
//Generate West Walls
for (int32 n = 1; n < GridSizeY; n++)
{
FTransform newTransform = FTransform(FVector((n / GridSizeY) * TileSize, n % GridSizeY * TileSize, 300));
ISM_Wall->AddInstance(newTransform);
}
//Generate East Walls
for (int32 n = 1; n < GridSizeY; n++)
{
FTransform newTransform = FTransform(FVector(GridSizeX * TileSize - TileSize, n % GridSizeY * TileSize, 300));
ISM_Wall->AddInstance(newTransform);
}
//Generate South Walls
for (int32 n = 1; n < GridSizeX - 1; n++)
{
FTransform newTransform = FTransform(FVector((n % GridSizeX) * TileSize, GridSizeY * TileSize - TileSize, 300));
ISM_Wall->AddInstance(newTransform);
}
}
//Replace single instanced wall components with Door Meshes
void ARoomGeneration::GenerateDoors()
{
ISM_Door->ClearInstances();
bHasEntryDoor = false;
bHasExitDoor = false;
//Create an entry door to give access to the room
if(bHasEntryDoor == false)
{
int32 randInt = FMath::RandRange(0, ISM_Wall->GetInstanceCount());
FTransform doorTransform;
ISM_Wall->GetInstanceTransform(randInt, doorTransform);
ISM_Door->AddInstance(doorTransform);
ISM_Wall->RemoveInstance(randInt);
bHasEntryDoor = true;
}
//Create exit doors if door count is greater than 0
if(bHasEntryDoor == true && bHasExitDoor == false && DoorCount > 0)
{
for(int32 d = 0; d < DoorCount; ++d)
{
int32 randInt = FMath::RandRange(0, ISM_Wall->GetInstanceCount());
FTransform doorTransform;
ISM_Wall->GetInstanceTransform(randInt, doorTransform);
ISM_Door->AddInstance(doorTransform);
ISM_Wall->RemoveInstance(randInt);
}
bHasExitDoor = true;
}
}
grey tiles are the floor, red tiles are walls, and green tiles are the doors
To be more specific about what I’m looking to learn here is a list of questions.
- How do i keep doors from spawning in corners?
- How could I make the walls spawn in different patterns, like in the shape of Tetris pieces?
I think if those questions are answered I will be able to figure out the rest. I’m not looking for people to create the code for me just an explanation or some examples of the logic used would be great.
Thanks in advance,
Russ.