C++ loading in file by characters

I’ve been working on a tile mapping system that loads the character values of a file into an array so that it can be broken down into tile images later on. I have it ignore whitespace, tabs, new lines, carriage returns, etc. The only problem I’m having is that when my loop goes to a new row in the file ( note it loads the data horizontally row-by-row and moves to the next row as such ) the first value of that new row is used on the first three variables in my array for that row. If that doesn’t make sense, perhaps this will:

void Map::LoadMapFile( std::string filename )
	{
		
		// Opens the data file.
		MapFileData.Open( filename );

		// Loops through the data on a single row, then goes to the next row.
		for( unsigned int Vertical_Position = 0;
			 Vertical_Position < Map_Height; 
			 Vertical_Position++ )
		{
			
			// Loops through the data on a single row, assigning character value
			// data. When done with a row of data, it will exit the 'for' loop
			// and do the loop again on the next row.
			for( unsigned int Horizontal_Position = 0; 
				 Horizontal_Position < Map_Width; 
				 Horizontal_Position++ )
			{

				// Sets the tile data value for each position in the 2D map to the corresponding data
				// in the data file.
				TileMap[Horizontal_Position + ( Vertical_Position * Map_Width )] = MapFileData.GetChar(Horizontal_Position + ( Vertical_Position * Map_Width ));

			}
			
		}
		
	}



char FileIO::GetChar( int location )
	{
		
		char Character;
		std::fstream stream( fileName.c_str(), std::ifstream::in );

		stream.seekg( location );

		stream >> Character;
		return Character;
		
	}

An example file I’m using is:

3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
A780000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
v000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
1000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000001
1000500000000000000111111000000000000000000000000000000000001100000000000000000100000000000000000001
1000000000000000001111111100000000000000000000000000000000111110000000000000001100000000000000000001
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111

When the first row is loaded into memory, it does so perfectly. However, once it goes to the next row that starts with “A7800”, it assigns the value ‘A’ to the next three tiles in the array for that row rather than just the first one as it should.

Tile( 0, 1 ) = ‘A’;
Tile( 1, 1 ) = ‘A’;
Tile( 2, 1 ) = ‘A’;

When it actually should be:

Tile( 0, 1 ) = ‘A’;
Tile( 1, 1 ) = ‘7’;
Tile( 2, 1 ) = ‘8’;

I would have spaces between each tile, otherwise you’re going to get really stuck when you need run out of alphanumerics. You can then just read each value in as a string and convert it to a number, so if your map was 50x20 (50 units horizontally, 20 units vertically), you could read it in like so (C code):
char tile[10];
int y, x;

for (y=0;y<20;y++)
{
	for (x=0;x<50;x++)
	{
		fscanf(fp, "%s", tile);

		map[y][x] = atoi(tile);
	}
}

Here’s a tutorial here which might also help you

http://www.parallelrealities.co.uk/2011/10/intermediate-game-tutorial-3-tile-based.html

Thanks for the tutorial link! I’ll probably end up making the map files like that ( spaces between each tile value ) so I can handle it as you suggested, though I don’t think it would be too much of a problem at the moment since the game the map files are being made for only requires 12 values for 12 different objects ( 4 of which are actual tiles, the rest are player and enemy objects and their positions ). I was going to just have 1 layer for the files since I knew that for this 2D platformer an object being created at a location in the map would mean that there’s no tile needing to be created there. Therefore, it’s more of a tile/object file rather than just a tile file being loaded in.

Anyways, long story short I’ve already created this way of making the map and map loading for the game. I’ll have to make it like you said so that I have far more values to work with ( not just 40-50 comfortably typed ones ). If anyone can give me their thoughts on why my current design is having an issue after the first row of data being loaded into memory from the file, that would be great. I’m not 100%, but I think it has something to do with my GetChar()'s seekg() function counting ‘\n’ at the end of each row.

That might be what the problem is, so when you read in the character, check if it’s whitespace, since some OSs do all sorts of weird things when you do a carriage return, such as doing a \r\n, \n etc.

C has the function isspacewhich should help you with this problem.

Thanks for that, I do appreciate the information. I’ll be able to use that when I’m parsing data already taken from the file, as right now that won’t work with my current system due to seekg() only counting from the beginning of the file up to the character position needed ( going through and counting any whitespace ). What I ended up doing was just making the row number add itself twice to give me this:

TileMap[Horizontal_Position + ( Vertical_Position * Map_Width )] = MapFileData.GetChar(Horizontal_Position + ( Vertical_Position * Map_Width ) + Vertical_Position + Vertical_Position );

The reason for it working is because apparently the whitespace at the end of each row in the file has two characters of whitespace. Don’t ask me how or why this is, as I keep looking it up and finding that even \r\n is treated as a single character. Anyways, it make it add counts at the end of each row to guarantee that it takes whitespace at the end of the file into account. Note this means that this Map class can now use spaces for blank tiles and such since the character can be read without worry for ignoring \n, \r\n, etc.

Multiple solutions for the same problem. You’ve got to love programming :wink: . Of course, yours probably works better, but implementing both the items you stated would require a rehaul on my design for the level file loading, which at this moment I don’t feel up to doing. What mine does works for my game(s), so that’s all that I care about for now. Later on if I use it for games that have say 70 different tiles and 100 different objects, I’ll have to rehaul it to support multiple layers of data ( not just tile positions ), parse out whitespace, and break everything down into strings by row instead of character numbering by row.

Again, many thanks for the thoughts! Hope what I did helps someone with a similar design already in place. If someone reads this and hasn’t started their design yet, go with what riksweeney says. It may be C-based code, but you can always use C++ library functions for the tasks too if you’re so bent to do so.