Sign in to follow this  

Moving Veiwport for SDL tile game.

This topic is 4202 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

Hi, Im just started making a Tile based SDL game(C++). It's a 2D RPG and the player should be moving in fairly big worlds. I have no real problem drawing the map, but i dont know how i shall move the viewport so the world moves width the player. I dont wanna limit my world to 1 screen! So please any suggestions?

Share this post


Link to post
Share on other sites
To move a tilemap, it is usually enough to add an offset to the index of the tile you are drawing.

For example:
You usually start drawing you map at the tile (0, 0). If your player moves one tile up, start drawing your map at the tile (0, 1), leaving the first row out. If your player moves one tile to the right afterwards, start drawing your map at the tile (1, 1), leaving the first row and the first column out - etc.

This would allow a tile-perfect scrolling, which might look a bit ugly. It is used in a lot of oldschool tile based games where it always looked as if you character was jumping from tile to another.
If you got this to work and dont like the look of it, you can try to improve it to pixel-perfect, smooth scrolling. How you can implement this depends on how your character is able to move in the world (only from one tile to another tile or also in-between tiles).

Dont forget that if your world is "really big", you should only draw the visible part of the world!

There are quite a few helpful articles here.

Share this post


Link to post
Share on other sites
Thanks you so much for the reply, but im pretty stuck again.
Ok, i wernt really sure how i was going to solve this so i did this:


void DrawMap(SDL_Surface *screen)
{
int tile;
int xpos;
int ypos;
int XX = pPlayer->GetpositionX() - 10;
int YY = pPlayer->GetpositionY() - 10;
for (int y = 0 + YY; y < MAP_SIZEY; y++)
{
for (int x = 0 + XX; x < MAP_SIZEX; x++)
{
tile = map[y][x];
//calc position
xpos = x * 25;
ypos = y * 25;
DrawIMG(Tile[tile], xpos, ypos, screen);

}
}
}



Now the problem is that fucked the program up. Now it crashes when i move the player. You dont have solution again do you ? :)

Share this post


Link to post
Share on other sites
You're also going to have to shift all the tiles over by -1*WidthOfOneTile*XX and -1*HeightOfOneTile*YY.

But, you might want to tell us more. What happened to the program? What type of crash?

Your indexes are probably out of bounds. If player->GetPositionX() is less than 10, it will be out of bounds. Same with GetPositionY().

Share this post


Link to post
Share on other sites
Well , ok.

1. The program crashed (simply shout down) when i were moving up in the area where the indexes got out of bounds. I could go downhill. So you were right :) But the player were always in the corner and the stuff "behind" him weren't drawn. I need to have an area around the player were the game always draw.

2. I dont really get what you mean by shift tile's over?

And sorry if this is unclear!

Share this post


Link to post
Share on other sites
Quote:
1. The program crashed (simply shout down) when i were moving up in the area where the indexes got out of bounds
There you got the bug.

I will post an excerpt of my tile draw routine (simplified, of course).

This is by far not the best way to handle tile map drawing, but a rather comfortable way. I first determine the map draw boundings, the area of the map which is on the screen, then I loop through my tiles and check which I have to draw. I draw them from the left bottom corner to the upper right corner. It works quite well and can be easily extended to pixel perfect scrolling. :-)

//Get the Map Draw Boundings (the map excerpt we want to draw)
int x_min = ( pPlayer->GetpositionX() * tilesize - SCREEN.resolution.x / 2.0f ) / float( tilesize );
int y_min = ( pPlayer->GetpositionY() * tilesize - SCREEN.resolution.y / 2.0f ) / float( tilesize );
int x_max = x_min + float( SCREEN.resolution.x ) / float( tilesize );
int y_max = y_min + float( SCREEN.resolution.y ) / float( tilesize );

//The following 2 variables determine the position on the screen (in pixels)
//where we want the current tile image to be drawn.
int draw_position_x = 0; //Start to draw at pixel 0 (left bottom corner)
int draw_position_y = 0; //Start to draw at pixel 0 (left bottom corner)

//Go through all neccessary rows
for( int yi = y_min; yi <= y_max; yi++ )
{
//Jump to beginning of the new line (pixel 0)
draw_position_x = 0;

//Go through all neccessary columns
for( int xi = x_min; xi <= x_max; xi++ )
{
//Try to get the current tile
int *Tile = GetTile( xi, yi );

//Look if the current tile is valid (VERY IMPORTANT!)
if( Tile )
DrawIMG( Tile[tile], draw_position_x, draw_position_y, screen);
//(I dont know if I am using DrawIMG correctly)

//Shift x-Position
draw_position_x += tilesize;
}

//Jump to the next line
draw_position_y += tilesize;
}







The most important part of this code are the map draw boundings, I will explain them further:

x_min =
( pPlayer->GetpositionX() * tilesize - SCREEN.resolution.x / 2.0f ) / float( tilesize );

The current position of the player (which we assume is always in the middle of the screen!) multiplied with the tilesize is the position of the player measured in pixels. This value minus the half screen resolution is the point in the lower left corner of the screen, the x-ID of the first tile we want to draw.

y_min =
( pPlayer->GetpositionY() * tilesize - SCREEN.resolution.y / 2.0f ) / float( tilesize );

Works exaktly in the same way as x_min.

x_max = x_min + float( SCREEN.resolution.x ) / float( tilesize );
The screen resolution divided through the tilesize is the screen resolution measured in tiles. This value plus the x-ID of the first tile we want to draw is the x-ID of the last tile we want to draw.

y_min = y_min + float( SCREEN.resolution.y ) / float( tilesize );
Works exaktly in the same way as x_max.

I hope this makes things a bit clearer for you.

EDIT: fixed code.
EDIT: just noticed, but is is only important if you got the rest working: you have to add x_min -= tilesize / 2 etc. if your character should be centered in the middle of the tile. Otherwise the map draw boundings will be cut as if he was standing at the upper right corner of each tile.

Share this post


Link to post
Share on other sites

This topic is 4202 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this