• Advertisement
Sign in to follow this  

Random Level Builder Help

This topic is 2391 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok I'm trying to make a Level builder that'll build rooms and halls but its become rather hit and miss and I'm stuck on it. For one the checker that makes sure it wont build over itself only fires when it wants it seems and two it can go from putting completely random garbage all over to getting stuck in infinite loops.

Build Level:
#include "BL.h"

bool CollisionCheck(Tile LevelCurrent[100][100],int x,int y,int width,int height)
{
int check=0;
bool fin;
for(y; y<height; y++)
{
for(x; x<width; x++)
{
if(LevelCurrent[x][y].walkable==1)
check++;
}
}
if(check>0)
fin=false;
else if(check==0)
fin=true;
return fin;
}

void BuildLevel(Tile LevelCurrent[100][100],int stair_x,int stair_y)
{
bool finish=false,cont=false;
int x,y,x2,y2,type,length,roll,counter;
type=4;

for(y=0; y<100; y++)
{
for(x=0; x<100; x++)
{
LevelCurrent[x][y].walkable=0;
LevelCurrent[x][y].flag_build=0;
LevelCurrent[x][y].tries=0;
}
}

LevelCurrent[stair_x][stair_y].flag_build=1;
LevelCurrent[stair_x][stair_y].tries=5;


while(!finish)
{
/*
TYPES:
Halls= 0-3
Standard Rooms= 4-24
Uncommon Rooms= 25-45
Rare Rooms= 46-66
*/
type=rand()%5;
for(y=0; y<100; y++)
{
for(x=0; x<100; x++)
{

//===========HALLS============================================================================================//
//===UpHall============//
if((LevelCurrent[x][y].flag_build==1||LevelCurrent[x][y].flag_build==2)&&type==0)
{
length=rand()%20;
while(!CollisionCheck(LevelCurrent,x,y-length,1,length)&&y-length>4)
{
if(length<=4)
break;
length--;
}
if(length>4)
{
for(int i=0; i<length; i++)
{
LevelCurrent[x][y-i].walkable=1;
}
LevelCurrent[x][y].flag_build=0;
LevelCurrent[x][y-length].flag_build=1;
}
else{
if(LevelCurrent[x][y].tries>0)
LevelCurrent[x][y].tries++;
else
LevelCurrent[x][y].flag_build=0;
}
}
//=====================//

//===RightHall=========//
if((LevelCurrent[x][y].flag_build==2)&&type==1)
{
length=rand()%20;
while(!CollisionCheck(LevelCurrent,x,y,length,1)&&x+length<92)
{
if(length<=4)
break;
length--;
}
if(length>4)
{
for(int i=0; i<length; i++)
{
LevelCurrent[x+i][y].walkable=1;
}
LevelCurrent[x][y].flag_build=0;
LevelCurrent[x+length][y].flag_build=1;
}
else{
if(LevelCurrent[x][y].tries>0)
LevelCurrent[x][y].tries++;
else
LevelCurrent[x][y].flag_build=0;
}
}
//=====================//

//===DownHall==========//
if((LevelCurrent[x][y].flag_build==2)&&type==2)
{
length=rand()%20;
while(!CollisionCheck(LevelCurrent,x,y,1,length)&&y+length<92)
{
if(length<=4)
break;
length--;
}
if(length>4)
{
for(int i=0; i<length; i++)
{
LevelCurrent[x][y+i].walkable=1;
}
LevelCurrent[x][y].flag_build==0;
LevelCurrent[x][y+length].flag_build=1;
}
else{
if(LevelCurrent[x][y].tries>0)
LevelCurrent[x][y].tries++;
else
LevelCurrent[x][y].flag_build=0;

}
}
//=====================//

//===LeftHall==========//
if((LevelCurrent[x][y].flag_build==2)&&type==3)
{
length=rand()%20;
while(!CollisionCheck(LevelCurrent,x-length,y,length,1)&&x-length>4)
{
if(length<=4)
break;
length--;
}
if(length>4)
{
for(int i=0; i<length; i++)
{
LevelCurrent[x-1][y].walkable=1;
}
LevelCurrent[x][y].flag_build=0;
LevelCurrent[x-length][y].flag_build=1;
}
else{
if(LevelCurrent[x][y].tries>0)
LevelCurrent[x][y].tries++;
else
LevelCurrent[x][y].flag_build=0;
}
}
//=====================//
//============================================================================================================//

//===========COMMON_ROOMS=====================================================================================//

//Diamond - Medium - Type 4
if(LevelCurrent[x][y].flag_build==1&&type==4)
{
if(CollisionCheck(LevelCurrent,x-3,y-3,7,7))
{
//=Y-3========================//
LevelCurrent[x][y-3].walkable=1;
//============================//

//=Y-2========================//
LevelCurrent[x-1][y-2].walkable=1;
LevelCurrent[x][y-2].walkable=1;
LevelCurrent[x+1][y-2].walkable=1;
//============================//

//=Y-1========================//
LevelCurrent[x-2][y-1].walkable=1;
LevelCurrent[x-1][y-1].walkable=1;
LevelCurrent[x][y-1].walkable=1;
LevelCurrent[x+1][y-1].walkable=1;
LevelCurrent[x+2][y-1].walkable=1;
//============================//

//=Y+0========================//
LevelCurrent[x-3][y].walkable=1;
LevelCurrent[x-2][y].walkable=1;
LevelCurrent[x-1][y].walkable=1;
LevelCurrent[x][y].walkable=1;
LevelCurrent[x+1][y].walkable=1;
LevelCurrent[x+2][y].walkable=1;
LevelCurrent[x+3][y].walkable=1;
//============================//

//=Y+1========================//
LevelCurrent[x-2][y+1].walkable=1;
LevelCurrent[x-1][y+1].walkable=1;
LevelCurrent[x][y+1].walkable=1;
LevelCurrent[x+1][y+1].walkable=1;
LevelCurrent[x+2][y+1].walkable=1;
//============================//

//=Y+2========================//
LevelCurrent[x-1][y+2].walkable=1;
LevelCurrent[x][y+2].walkable=1;
LevelCurrent[x+1][y+2].walkable=1;
//============================//

//=Y+3========================//
LevelCurrent[x][y+3].walkable=1;
//============================//

//=Flags======================//
if(LevelCurrent[x][y+4].walkable==0&&y+4<92) LevelCurrent[x][y+3].flag_build=2;
if(LevelCurrent[x][y-4].walkable==0&&y-4>4) LevelCurrent[x][y-3].flag_build=2;
if(LevelCurrent[x+4][y].walkable==0&&x+4<92) LevelCurrent[x+3][y].flag_build=2;
if(LevelCurrent[x-4][y].walkable==0&&x-4>4) LevelCurrent[x-3][y].flag_build=2;
//============================//
//=Tries======================//
if(LevelCurrent[x][y+4].walkable==0&&y+4<92) LevelCurrent[x][y+3].tries=5;
if(LevelCurrent[x][y-4].walkable==0&&y-4>4) LevelCurrent[x][y-3].tries=5;
if(LevelCurrent[x+4][y].walkable==0&&x+4<92) LevelCurrent[x+3][y].tries=5;
if(LevelCurrent[x-4][y].walkable==0&&x-4>4) LevelCurrent[x-3][y].tries=5;
//============================//
LevelCurrent[x][y].tries=0;
}
/*else{
if(LevelCurrent[x][y].tries>0)
LevelCurrent[x][y].tries++;
else
LevelCurrent[x][y].flag_build=0;
}*/
}

//============================================================================================================//

//===========RARE_ROOMS=======================================================================================//

//Hall Of Heroes - Type 46
if(type==46)
{

}
//============================================================================================================//
}
}
counter=0;
for(y2=0; y2<100; y2++)
{
for(x2=0; x2<100; x2++)
{
if(LevelCurrent[x2][y2].flag_build!=0)
counter++;
}
}
if(counter==0)
finish=true;
counter=0;
}
return;
}



I'm at a complete lose at this point so any help would be greatly appreciated. Thanks.

Share this post


Link to post
Share on other sites
Advertisement

Have you tried debugging it step-by-step?

Maybe adding some asserts would help pinpoint the problem(s).


Yea I've debugged if for a few hours now and I still cant find the issue.

Share this post


Link to post
Share on other sites
CollisionCheck() reports true if any walkable cell is in the portion of the map with coordinates between (x,y) and (width,height): it doesn't seem to match the call in BuildLevel(); parameter values are not checked; it assumes x<=width and y<=height; the parameters aren't, obviously, a width and height; you shouldn't iterate using x and y.
[source lang="cpp"]
bool CollisionCheck(const Tile** LevelCurrent, const int x1,const int y1,const int x2,const int y2,const int width,const int height)
{
int xmin,xmax,ymin,ymax;//iteration limits
if(x1>x2)
{
xmin=x2;
xmax=x1;
}
else
{
xmin=x1;
xmax=x2;
}
if(y1>y2)
{
ymin=y2;
ymax=y1;
}
else
{
ymin=y1;
ymax=y2;
}

if (xmin<0) xmin=0;
if (ymin<0) ymin=0;
if (xmax>width) xmax=width; if (ymax>height) ymax=height;
for(int y=ymin; y<ymax; y++)
{
for(int x=xmin; x<xmax; x++)
{
if(LevelCurrent[x][y].walkable==1)//should probably be a bool, not an integer
//if(LevelCurrent[x][y].walkable)

return false;
}
}
return true;
}

[/source]

Share this post


Link to post
Share on other sites
Ok I got the issues with the checking function (Thanks Lorenzo) and they now work fine with building the rooms but the hallways still build over everything as if nothing is there.


Here's how it does hallways moving up. All the other hall builders are basically the same as this.
if((LevelCurrent[x][y].flag_build==1||LevelCurrent[x][y].flag_build==2)&&type==0)
{
length=rand()%10;
while(!cont||y-length<4||!CollisionCheck(LevelCurrent,x,y-length,x,y))
{
length--;
if(length<=4)
cont=true;
}
if(length>4&&y>4&&LevelCurrent[x][y].direction!=2)
{
for(int i=0; i<length; i++)
{
LevelCurrent[x][y-i].walkable=1;
}
LevelCurrent[x][y].flag_build=0;
LevelCurrent[x][y-length].flag_build=1;
LevelCurrent[x][y-length].tries=5;
LevelCurrent[x][y-length].direction=0;
}
else
{
if(LevelCurrent[x][y].tries>0)
LevelCurrent[x][y].tries--;
else if(LevelCurrent[x][y].tries==0)
LevelCurrent[x][y].flag_build=0;
}
}


I'm starting to think I'm doing halls all wrong to be honest. Any input would be great.

Edit: Also if I set the compiler to Release instead of Debug (MS VC++ 2010) and set a break in the collision check function it claims it will never be hit.

Share this post


Link to post
Share on other sites
Don't debug Release builds unless you're trying to reproduce an error that only happens in Release. Debugging Release builds is a tedious process.

Have you considered putting some output into this function? For some processes, debugging step-by-step is too fine grained to figure out what is going wrong. Instead, if you printed a representation of the level at the start of each loop (possibly pausing the generation in the process), you'd be clearly able to see what was happening. Once you figure out where it is going wrong, you can use the debugger to find out why.

Your function is very big. One thing that might help narrow it down is to split it into several smaller functions.

A different idea is to build the rooms first and then create the tiled level from it. So you might build a set of objects which represent the topology of the level in terms of rooms, corridors, etc. Then use a second pass to turn that into a tile map.

Share this post


Link to post
Share on other sites
[s] Ah I've discovered the source of the issue! My only issue now is that I don't know how to actually fix it.

CollisionCheck snippet:

for(int y=x1; y<y2; y++)
{
for(int x=x1; x<x2; x++)
{
if(LevelCurrent[x][y].walkable==1)
return false;
}
}
return true;


The issue is that since the halls are 1 tile in width whenever it goes through y<y2 or x<x2 its equal to it so it just passes by without being checked.


y=y1;
x=x1;

while(y<=y2)
{
while(x<=x2)
{
if(LevelCurrent[x][y].walkable==1)
return false;
x++;
}
y++;
}
return true;

^ I tried doing this so it wouldnt just pass on and the only thing it would do after that was build halls straight up for some odd reason.

[/s]Ya know what disregard all of that I completely forgot about do while loops and it's now working perfectly. Thank you all for your help.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement