Player out of tile map

Started by
13 comments, last by DKdowneR 6 years, 7 months ago

Hi! I made a tile map reading from a file. Almost everything works good, but when a player go out of map, program runs into an error and says that "vector subscript out of range". My question is how to make check for it

Drawing map : 


void GameplayScreen::DrawMap(SDL_Renderer *renderer)
{
	for (int y = map.size() - 1; y >= 0; --y)
	{
		for (int x = getStartBlockX(), xEnd = getEndBlockX(); x < xEnd && x < map[y].size(); ++x)
		{
			if (map[y][x] != "0,0")
			{
				int tempX = atoi(map[y][x].substr(0, map[y][x].find(',')).c_str());
				int tempY = atoi(map[y][x].substr(map[y][x].find(',') + 1).c_str());

				srcRect.x = tempX * 32;
				srcRect.y = tempY * 32;
				srcRect.w = 32;
				srcRect.h = 32;

				destRect.x = x * 32 + posX;
				destRect.y = (y * 32 + posY);
				destRect.w = 32;
				destRect.h = 32;
              
				vBlock[Earth]->Draw(renderer, srcRect, destRect);
            }
		}
	}
}

getStartBlockX returns first map block, getEndBlockX returns last, so it's like render on screen only a piece of map, not all blocks.
tempX returns x coordinate of tile image,  tempY y coordinate. So, for example, if map is like :

0,0 0,0 0,0 0,0 0,0

0,0 0,0 0,0 0,0 0,0

1,0 2,0 0,3 1,0 1,0

0,0 is first block image, 1,0 is one next to the first, 0,3 is 2 under the first block etc.


 

 

Advertisement
1 hour ago, DKdowneR said:

Hi! I made a tile map reading from a file. Almost everything works good, but when a player go out of map, program runs into an error and says that "vector subscript out of range". My question is how to make check for it

Drawing map : 



void GameplayScreen::DrawMap(SDL_Renderer *renderer)
{
	for (int y = map.size() - 1; y >= 0; --y)
	{
		for (int x = getStartBlockX(), xEnd = getEndBlockX(); x < xEnd && x < map[y].size(); ++x)
		{
			if (map[y][x] != "0,0")
			{
				int tempX = atoi(map[y][x].substr(0, map[y][x].find(',')).c_str());
				int tempY = atoi(map[y][x].substr(map[y][x].find(',') + 1).c_str());

				srcRect.x = tempX * 32;
				srcRect.y = tempY * 32;
				srcRect.w = 32;
				srcRect.h = 32;

				destRect.x = x * 32 + posX;
				destRect.y = (y * 32 + posY);
				destRect.w = 32;
				destRect.h = 32;
              
				vBlock[Earth]->Draw(renderer, srcRect, destRect);
            }
		}
	}
}

getStartBlockX returns first map block, getEndBlockX returns last, so it's like render on screen only a piece of map, not all blocks.
tempX returns x coordinate of tile image,  tempY y coordinate. So, for example, if map is like :

0,0 0,0 0,0 0,0 0,0

0,0 0,0 0,0 0,0 0,0

1,0 2,0 0,3 1,0 1,0

0,0 is first block image, 1,0 is one next to the first, 0,3 is 2 under the first block etc.




 

 

Well you dont check x to being negative. Also when x and and xEnd are equal, you are standing on the same x-line - but from your condition you exit the loop, is this indented? Shouldnt this be x <= xEnd ? Or does getEndBlockX returns the range instead of the last index? From the name of the function i would expect, the last index.

 

Also why you dont have a getStartBlockY() and getEndBlockY() or are your player limited to X-direction only ?

 

I'm planning to do with Y direction. It doesnt matter that it's x < xEnd or x <= xEnd, because I add 1 right in the method. They looks like this: 


int GameplayScreen::getStartBlockX()
{
	return (int)(-posX + (int)posX % 32) / 32;
}
int GameplayScreen::getEndBlockX()
{
	return (int)(-posX + (int)posX % 32 + System::getFM()->getW()) / 32 + 1;
}

Also I don't think that I should check for x is negative, because it's always positive
 


 

getW() returns window width.

I don't see an error with the for loops, maybe I'm overlooking it. Are you sure the error isn't somehow in this call:

1 hour ago, Finalspace said:

vBlock[Earth]->Draw(renderer, srcRect, destRect);

What is the value of Earth?

Earth = 0. It means that I want to render first map. Do change nothing. If it would not be 0, the map would not load. Map loads properly, though.

Before this line:


if (map[y][x] != "0,0")

you need to check if x is within the map bounds. If not, skip that block.

 

What do you mean by skip block?

You can just use the keyword continue or break from that loop

1 hour ago, DKdowneR said:

int GameplayScreen::getEndBlockX() { return (int)(-posX + (int)posX % 32 + System::getFM()->getW()) / 32 + 1; }

Also, I don't think this is doing what you think it is. I think you need more parenthesis to control the order of operations.

What you think it is? It returns last block, so if window is 1280 width,  it returns 40, that's only what I need it to do and in draw for loop, loop through 0 to 40. So, it renders 40 block instead of ~90. If start block = 5, end = 45, etc. so, always depends on window it returns everything to render only that what need to be on the screen, nothing more, nuting less.

So, is posX screen coordinates for a tile, or the start block or what?

(int)(-posX + (int)posX % 32 + System::getFM()->getW()) / 32 + 1

if start block = 5

(int)(-5 + (int)5 % 32 + 1280) / 32 + 1

(int)(-5 + 5 + 1280) / 32 + 1

(int)(1280) / 32 + 1

(int)40 + 1 =

41 not 45

 

This topic is closed to new replies.

Advertisement