Sign in to follow this  
chris_j_pook

[java] Tile game (Scrolling background)

Recommended Posts

chris_j_pook    136
Hi, I am making a tile based game where the character sprite can walk around the screen but when it reaches 300px from any edge the background scrolls along to reveal the rest of the level. At the moment I have coded it so that this works, however upon reaching an edge the background scrolls 1 whole tile width(50px) which means the scroll is very jerky. Also when the background is scrolling it means the player speeds up because the background shifts in the opposite direction faster than they arre moving :/ What I would like to do is have the incomming tile come in 1 pixel at a time as the player sprite moves towards the edge... If that makes sense ? Anyway, here is the code I have at the moment. In the Run method...
// Scroll the back ground when nessesary + load next section of level when needed.
            	if(player.y < 400)
            	{
            		player.offsetY --;
            		if(player.offsetY < 0 & player.y < 30)
					{
						player.screenY--;
						tr.readFile(sr.screens[player.screenX][player.screenY]);
						player.y = GAME_HEIGHT - 30;
						player.offsetY = 30;
					}
					else if(player.offsetY < 0)
					{
						player.offsetY = 0;
					}
					else
					{
    	        		player.y += 10;
					}
            	}

            	if( player.x > GAME_WIDTH - 400)
            	{
            		player.offsetX ++;
            		if(player.offsetX >30 & player.x > GAME_WIDTH - 30)
					{
						player.screenX++;
						tr.readFile(sr.screens[player.screenX][player.screenY]);
						player.x = 30;
						player.offsetX = 0;
					}
					else if(player.offsetX > 30)
					{
						player.offsetX = 30;
					}
					else
					{
    	        		player.x -= 10;
					}
            	}

            	if( player.x < 400)
            	{
            		player.offsetX--;
            		if(player.offsetX < 0 & player.x < 30 )
					{
						player.screenX--;
						tr.readFile(sr.screens[player.screenX][player.screenY]);
						player.x = GAME_WIDTH - 30;
						player.offsetX = 30;
					}
					else if(player.offsetX < 0)
					{
						player.offsetX = 0;
					}
					else
					{
    	        		player.x += 10;
					}
            	}

            	if(player.y > GAME_HEIGHT - 400 )
            	{
            		player.offsetY++;
            		if(player.offsetY > 30 & player.y > GAME_HEIGHT -30)
					{
						player.screenY++;
						tr.readFile(sr.screens[player.screenX][player.screenY]);
						player.y = 30;
						player.offsetY = 0;
					}
					else if(player.offsetY > 30)
					{
						player.offsetY = 30;
					}
					else
					{
    	        		player.y -= 10;
					}
            	}
In the paint method
int x = 0;
				int y = 30;

				//System.out.println(tr.tiles.length);

                for(int row = 0; row < 15; row++)
                {
                	for(int column = 0; column < 15; column++)
                	{
                    	g.drawImage(tileSprites[tr.tiles[row + player.offsetY][column + player.offsetX]], x, y, this);
                    	x += 50;
                	}

                    x = 0;
                    y+= 43;
                }
Any ideas how I can get this smoother scrolling to work ? [Edited by - chris_j_pook on June 29, 2005 5:30:26 PM]

Share this post


Link to post
Share on other sites
Darragh    308
Hello,

First of all just a small reminder, when you are posting source code just pop it in between the "source" and "/source" tags (see the forum FAQ for more details)- it makes things much easier to read.

I'm not sure exactly what you are doing here but I have noticed one thing- you seem to be mixing up your bitwise / logical AND operators.

The following line of code produces a bitwise AND (&), and not a logical AND (&&)- which is what you want:

if(player.offsetY < 0 & player.y < 30)

Change this line to the following:

if( (player.offsetY < 0) && (player.y < 30) )

Now for a smooth scrolling effect, all you need to do is translate each tiles position by the players position. This will move each tile when the player moves, so your code could look something like this:


Tile_northWest_corner_x = Tile_northWest_corner_original_x - player_x;
Tile_northWest_corner_y = Tile_northWest_corner_original_y - player_y;
Tile_northEast_corner_x = Tile_northEast_corner_original_x - player_x;
Tile_northEast_corner_y = Tile_northEast_corner_original_y - player_y;

..and so on for each point or corner on the tile


Your original tile positions are the position the tiles are in when the player is at 0,0 or the origin. Their final position when drawn will depend on where the player is in the gameworld.

Now for visibility checks all you need to do is check each of the four corners of each tile against the bounds of the screen. For example, if you are checking against the right side of the screen do something like this:



if (
(!(tile_corner_1_x > SCREEN_WIDTH))
||
(!(tile_corner_2_x > SCREEN_WIDTH))
||
(!(tile_corner_3_x > SCREEN_WIDTH))
||
(!(tile_corner_4_x > SCREEN_WIDTH))
)
{

// DRAW THE TILE

}





Do something similar for the top / bottom and left of the screen and you will be able to eliminate tiles from drawing when they are not on the screen..

Finally once last piece of advice would be not to load each map tile from the disk during gameplay. Even the fastest hard-disks are still very slow compared to RAM so it would be much better if you just loaded all the tiles at once into memory and avoid disk access completely. Just pop all the tiles into a 2D array and keep them there until the level ends and you'll be fine.

Hopefully this will help..

Regards,
Darragh

Share this post


Link to post
Share on other sites
Guest Anonymous Poster   
Guest Anonymous Poster
Also, one approach you could try for smooth scrolling is to have an area 2 tiles wider than the game screen in every direction loaded in memory. This way you can smoothly scroll into the area that isn't on screen, then once you get a certain distance into, for example, the right side buffer, you can drop the left most column of tiles and load in a new right most column.

Share this post


Link to post
Share on other sites
chris_j_pook    136
Ok,

I have got this working now, my player sprite stays in the middle of the screen and the tiles scroll smothly below. However when the player walks left or upwards there is a glitch where for 1 frame the tiles display in the wrong place (exctly where they were before the scrolling started).

I cant work out why this is happening, here is the code im using. Anyone got any ideas ?

The run method ...

public void run()
{
while(true) // Loop constantly.
{
{
updatePlayer(); // Update the player animation frame.
updateEnemies(); // Update any enemies on screen
repaint(); // Repaint the game scene.

// Update player location.
if(player.moveright)
{
player.x += 2; // Increment x coordinate
if(player.x%50 == 0) // If a new tile has been reached...
{
player.offsetX ++; // Increment the offset which will bring the new tile on screen in the paint function.
}

if(player.offsetX == 30 ) // If the last tile of this section is reached ...
{
player.offsetX = 29; // Dont allow any more tiles to be brought on screen (none will exist anyway)
player.x -= 2; // Prevent player from walking further in this direction.

// Need to add code here to allow player to continue walking right up to the edge of the screen,
// at which point the next section of tiles loads in.
}
}

if(player.moveleft)
{
player.x -= 2;
if(player.x%50 == 0)
{
player.offsetX --;
}

if(player.offsetX == 1)
{
player.offsetX = 0;
player.x += 2;
}
}

if(player.moveup)
{
player.y -= 2;
if(player.y%44 == 0)
{
player.offsetY --;
}

if(player.offsetY <= 0)
{
player.offsetY = 0;
player.y += 2;
}
}

if(player.movedown)
{
player.y += 2;
if(player.y%44 == 0)
{
player.offsetY ++;
}

if(player.offsetY == 30)
{
player.offsetY = 29;
player.y -= 2;
}
}

// Pause to keep frame rate consistent.
for(int i = 0; i < 10; i++)
{
Thread.currentThread().yield();
}
}
}





The paint method ...



// Draw the background tiles.

int x = 0;
int y = 30; // Avoid drawing under the title bar of the window (there's probably a better way to do this)
System.out.println(player.x);
for(int row = 0; row < 16; row++)
{
for(int column = 0; column < 16; column++)
{

g.drawImage(tileSprites[tr.tiles[row + player.offsetY][column + player.offsetX]], x - player.x%50 , y - player.y%44 , this);
x += 50; // Move along 50 pixels before placing the next tile. (tiles are 50px wide)
}

x = 0; // Go back to the start of the row on the x coord
y+= 43;// Move down 43 pixels before placing the next tile (tiles are 43px high)
}





I think it must be to do with this line, but I cant work out how to change it so what I have already still works :/

g.drawImage(tileSprites[tr.tiles[row + player.offsetY][column + player.offsetX]], x - player.x%50 , y - player.y%44 , this);

If you want a closer look I could email the full code to you ?

Share this post


Link to post
Share on other sites
Darragh    308
Hmmm, I think the best thing would be to send me the game and source code so I can have a real good look at what is going on. A problem such as this needs much closer inspection..

I'm working on a tile based 3D engine like the original Wolfenstein at the moment so I may be able to help. I've experienced my own fair share of glitches too using tiles- most of which occur in difficult cases such as when the player is exactly between two tiles.

I'll try and mess around with the code and see if I can do anything- If I manage to solve it then i'll let you know. My e-mail address is in my profile.

Regards,
Darragh

Share this post


Link to post
Share on other sites

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