Download

Implementing a basic BSP level generation algorithm with UObject classes

Hello,

This is my first time using the UE4. I am working on creating a basic 2D procedural level generation inside UE4 with c++

I am referring to the code here -> GameDev-Final-Project/BSP.cpp at master · vforeman/GameDev-Final-Project · GitHub

I implemented the algorithm with a normal c++ compiler and it works well. However I am facing some issues making it work in UE4.

My splitting of leaf logic works fine. I am getting stuck implementing this block of code below. The UPartition build() logic. It would run once or twice but after that the whole engine just crashes. If I remove the while loop it won’t crash anymore and the for loop would run once. I guess it could be an infinite loop or some initialization error but I am not quite able to figure it out. Also the way I structured the classes is different. I am extending all my base classes from unreal UObject.


#include "BSPTryoutOne.h"
#include "Partition.h"

UPartition::UPartition(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
	root = ConstructObject<ULeafObject>(ULeafObject::StaticClass());
	root->setProperties(0, 0, MAPHEIGHT, MAPWIDTH);
	leavesList.push_back(root);
}

void UPartition::build()
{
	int partitions = 0;
	while (partitions < 5)
	{
		partitions++;
		UE_LOG(LogTemp, Warning, TEXT(" LEAF LIST SIZE BEFORE %d "), leavesList.size());
		for (auto helper : leavesList)
		{
			if (leavesList.size() > 0)
			{
				if (helper->leftChild == NULL && helper->rightChild == NULL)
				{
					if (helper->split())
					{
						leavesList.push_back(helper->leftChild);
						leavesList.push_back(helper->rightChild);
						UE_LOG(LogTemp, Warning, TEXT(" LEFT child X Y HEIGHT WIDTH %d %d %d %d"), helper->leftChild->x, helper->leftChild->y, helper->leftChild->height, helper->leftChild->width);
						UE_LOG(LogTemp, Warning, TEXT(" Right child X Y HEIGHT WIDTH %d %d %d %d"), helper->rightChild->x, helper->rightChild->y, helper->rightChild->height, helper->rightChild->width);
					}
				}
			}
		}
		UE_LOG(LogTemp, Warning, TEXT(" LEAF LIST SIZE AFTER %d "), leavesList.size());
	}
}


Here is my LeafObject data structure


UCLASS()
class BSPTRYOUTONE_API ULeafObject : public UObject
{
	GENERATED_BODY()
	
public:
	ULeafObject(const FObjectInitializer& ObjectInitializer);
	int width, height, x, y;
	ULeafObject* leftChild;
	ULeafObject* rightChild;
	bool split();
	void createRooms();
	void setProperties(int x, int y, int height, int width);
	static const int MAX_LEAF_SIZE = 20;
	static const int MIN_LEAF_SIZE = 6;
};

And my LeafObject.cpp


#include "BSPTryoutOne.h"
#include "LeafObject.h"

ULeafObject::ULeafObject(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
	
}

void ULeafObject::setProperties(int a, int b, int h, int w)
{
	
	ULeafObject::x = a;
	ULeafObject::y = b;
	ULeafObject::height = h;
	ULeafObject::width = w;
	//UE_LOG(LogTemp, Warning, TEXT("INSIDE SET PROPERTIES, WIDTH HEIGHT X Y %d %d %d %d"), x, y, width, height);
}

bool ULeafObject::split()
{
	//both childs have to be NULL
	if (leftChild != NULL || rightChild != NULL) return false;

	bool splitH;
	splitH = util::coinToss();
	if (width > height && height / width >= 0.05)splitH = false;
	else if (height > width && width / height >= 0.05)splitH = true;
	int max = (splitH ? height : width) - MIN_LEAF_SIZE;
	if (max < MIN_LEAF_SIZE) return false;
	int split = util::randomRange(MIN_LEAF_SIZE, max);
	if (splitH)
	{
		//UE_LOG(LogTemp, Warning, TEXT("SPLIT H H H H H "));
		leftChild = ConstructObject<ULeafObject>(ULeafObject::StaticClass());
		leftChild->setProperties(x, y, split, width);
		//UE_LOG(LogTemp, Warning, TEXT(" LEFT SPLIT VALUES X Y HEIGHT WIDTH %d %d %d %d"), x, y, split, width);
		//UE_LOG(LogTemp, Warning, TEXT(" LEFT child X Y HEIGHT WIDTH %d %d %d %d"), leftChild->x, leftChild->y, leftChild->height, leftChild->width);
		rightChild = ConstructObject<ULeafObject>(ULeafObject::StaticClass());
		rightChild->setProperties(x, y + split, height - split, width);
		//UE_LOG(LogTemp, Warning, TEXT(" RIGHT SPLIT VALUES X Y HEIGHT WIDTH %d %d %d %d"), x, y + split, height - split, width);
		//UE_LOG(LogTemp, Warning, TEXT(" Right child X Y HEIGHT WIDTH %d %d %d %d"), rightChild->x, rightChild->y, rightChild->height, rightChild->width);
	}
	else
	{
		//UE_LOG(LogTemp, Warning, TEXT("SPLIT V V V V V "));
		leftChild = ConstructObject<ULeafObject>(ULeafObject::StaticClass());
		leftChild->setProperties(x, y, height, split);
	//	UE_LOG(LogTemp, Warning, TEXT(" LEFT SPLIT VALUES X Y HEIGHT WIDTH %d %d %d %d"), x, y, height, split);
	//	UE_LOG(LogTemp, Warning, TEXT(" LEFT child X Y HEIGHT WIDTH %d %d %d %d"), leftChild->x, leftChild->y, leftChild->height, leftChild->width);
		rightChild = ConstructObject<ULeafObject>(ULeafObject::StaticClass());
		rightChild->setProperties(x + split, y , height, width - split);
	//	UE_LOG(LogTemp, Warning, TEXT(" Right SPLIT VALUES X Y HEIGHT WIDTH %d %d %d %d"), x + split, y, height, width - split);
	//	UE_LOG(LogTemp, Warning, TEXT(" Right child X Y HEIGHT WIDTH %d %d %d %d"), rightChild->x, rightChild->y, rightChild->height, rightChild->width);
	}
	return true;
}

I read somewhere on initialized constructors for UObject classes using FObjectInitializer. I am not sure if the problem lies here or somewhere else.

Any ideas?

Thanks!

If anyone could please identify if I have done anything wrong in my implementation above?