2D randomly generated tile-based map not rendering correctly

Started by
1 comment, last by fragbear 12 years ago

So I am making a 2D roguelike and I'm doing the rendering of randomly generated tile-based maps with SDL.

I have two classes that my generating function uses from "mapgen.h":





extern int worldArray[][50]; //2D map of the world // 0 = space, 1 = solid



extern SDL_Rect tile[];



int generate_map();



class tileTemplate

{

public:



int type;

int xPos;

int yPos;

int tileNo;



tileTemplate();

}extern tileData[];



class dimensionData

{

public:

bool sideOpen[4];

int sideSpace[4];

};

Then I have variables declared in "mapgen.cpp" that are used in the map generating function:



SDL_Rect tile[2];

int worldArray[50][50]; //2D map of the world // 0 = space, 1 = solid

tileTemplate tileData[2500];

dimensionData dimensions;



tileTemplate::tileTemplate()

{

type;

xPos;

yPos;

tileNo;

occupied;

}

Then comes the function which I use to generate my maps, this is still in "mapgen.cpp"



int generate_map()

{

int slot = 0;

int line = 0;



//set the initial information for tiles and world construction

for (int i = 0; i < 2500; i++)

{

tileData[i].tileNo = i;

tileData[i].xPos = slot*96;

tileData[i].yPos = line*96;

tileData[i].occupied = 1;

worldArray[slot][line] = 1;



slot++;

if (slot == 50)



{

slot = 0;

line++;

}

}





int lastGeneratedTileX = genStartPointX;

int lastGeneratedTileY = genStartPointY;

int nextDirection = 0;

int comingDirection = 5;



int amountToGenerate = 0;



for (int s = 0; s < 1000;)

{



//top

if(lastGeneratedTileY == 0)

dimensions.sideOpen[0] = false;

else

dimensions.sideOpen[0] = true;

//right

if(lastGeneratedTileX == 50)

dimensions.sideOpen[1] = false;

else

dimensions.sideOpen[1] = true;

//down

if(lastGeneratedTileY == 50)

dimensions.sideOpen[2] = false;

else

dimensions.sideOpen[2] = true;

//left

if(lastGeneratedTileX == 0)

dimensions.sideOpen[3] = false;

else

dimensions.sideOpen[3] = true;



dimensions.sideSpace[0] = lastGeneratedTileY;

dimensions.sideSpace[1] = (50 - lastGeneratedTileX);

dimensions.sideSpace[2] = (50 - lastGeneratedTileY);

dimensions.sideSpace[3] = lastGeneratedTileX;



do

nextDirection = rand() % 4;

while(dimensions.sideOpen[nextDirection] == false || nextDirection == comingDirection);

comingDirection = nextDirection;

amountToGenerate = rand() % (dimensions.sideSpace[nextDirection]) + 1;

s += amountToGenerate - 1;



switch(nextDirection)

{

case 0:

for(int g = 1; g < amountToGenerate + 1; g++)

worldArray[lastGeneratedTileX][lastGeneratedTileY - g] = 0;

lastGeneratedTileY -= amountToGenerate;

break;

case 1:

for(int g = 1; g < amountToGenerate + 1; g++)

worldArray[lastGeneratedTileX + g][lastGeneratedTileY] = 0;

lastGeneratedTileX += amountToGenerate;

break;

case 2:

for(int g = 1; g < amountToGenerate + 1; g++)

worldArray[lastGeneratedTileX][lastGeneratedTileY + g] = 0;

lastGeneratedTileY += amountToGenerate;

break;

case 3:

for(int g = 1; g < amountToGenerate + 1; g++)

worldArray[lastGeneratedTileX - g][lastGeneratedTileY] = 0;

lastGeneratedTileX -= amountToGenerate;

break;

}

}

slot = 0;

line = 0;

//put the generated areas in game world data

for (int i = 0; i < 2500; i++)

{

tileData[i].type = worldArray[slot][line];

slot++;

if (slot == 50)

{

slot = 0;

line++;

}

}



return 0;

}

So the 2D array representing the game world is first filled with "solid" tiles, then the areas where the player can move are placed into it.
The data from the modified 2D map is then copied to the 2500 tileTemplate instances, which are used to render the map in the main.cpp, like this:



int draw_map()

{

int slot = 0;

int line = 0;

SDL_FillRect(screen,NULL,0x000000);



for (int i = 0; i < 2500; i++)

{

apply_surface(slot*96, line*96, tilemap, map, &tile[tileData[i].type]);

slot++;

if (slot == 50)

{

slot = 0;

line++;

}

}

apply_surface(0, 0, map, screen, &camera); //map

apply_surface(0, 0, GUI, screen, NULL); //GUI

SDL_Flip(screen);

return 0;

}

The surface "tilemap" is where all the different tiles are, the surface "map" is where all the tiles are drawn, and then this map surface is drawn to screen surface.

Most of the time all this works as it's supposed to, but sometimes the solid tiles (the ones that have value 1 in 2D map) don't get drawn at all, and you can see the map surface. Sometimes none of the tiles are drawn.

When I tried debugging this everything was seemingly going as it was supposed to, every time. Also even when no tiles are drawn the tileTemplate instances still have the correct values.

I still think the problem is in the map generating function because this didn't happen when I wasn't randomizing the tiles.

I also attached a picture of what the generated map looks like when it works, if it helps.

Advertisement

if(lastGeneratedTileY == 0)
dimensions.sideOpen[0] = false;
else
dimensions.sideOpen[0] = true;
//right
if(lastGeneratedTileX == 50)
dimensions.sideOpen[1] = false;
else
dimensions.sideOpen[1] = true;
//down
if(lastGeneratedTileY == 50)
dimensions.sideOpen[2] = false;
else
dimensions.sideOpen[2] = true;
//left
if(lastGeneratedTileX == 0)
dimensions.sideOpen[3] = false;
else
dimensions.sideOpen[3] = true;


Either ==0 or ==50 is off by one. Valid indexes are 0 to 49 inclusive.


dimensions.sideSpace[0] = lastGeneratedTileY;
dimensions.sideSpace[1] = (50 - lastGeneratedTileX);
dimensions.sideSpace[2] = (50 - lastGeneratedTileY);
dimensions.sideSpace[3] = lastGeneratedTileX;

50-... is off by one: at row/column 49 there is no "side space", exactly like on row/column 0.

Omae Wa Mou Shindeiru

Well now I'm embarrassed. rolleyes.gif Thanks for pointing that out, it fixed the problem.

This topic is closed to new replies.

Advertisement