gap between tiles in vertical tilemap scrolling

Hi, im working on a 2D shoot'em up map editor and the ground is made up of tiles moving downwards.

When the bottom row tiles go past the screen their position is set to top of screen (2.0f) + size of a tile.

The tilemap has to be atleast one row (here it is two rows) bigger than the screen (upwards) else there would be a gap when the top row moves down and the bottom row hasn't yet passed the screen.

However there's a small gap only when the first row is relocated above the screen between the "first" row and the "last" row (in the array so to speak).

All consecutive rows seems to lap over eachother fine, unless (and here's problem 2) the scroll speed is to fast, then the gaps erupts between more rows.

Objective: I want the tilemap to scroll smoothley and not have small gap's between rows independent of the scroll speed.

GameInit()

		V2f tp = v2f((32.0f / 512.0f), (32.0f / 512.0f));
		V2i tm_dim 				= v2i(32, 34);
		game->tilemap				= Push(game, SPRITE, tm_dim.x * tm_dim.y);
		game->tilemap_dim			= tm_dim;
		for(int y = 0; y < tm_dim.y; y++)
		{
			for(int x = 0; x < tm_dim.x; x++)
			{
				game->tilemap[x + (tm_dim.x * y)].pos 			= v2f(0.0f + (tp.x * x), 0.0f + (tp.y * y)); 
				game->tilemap[x + (tm_dim.x * y)].size 			= v2f(tp.x, tp.y + 0.001f); 
				game->tilemap[x + (tm_dim.x * y)].col 			= v4f(1.0f, 1.0f, 1.0f, 1.0f); 
				game->tilemap[x + (tm_dim.x * y)].tcoord_p 		= v2f(5.0f * tp.x, 1.0f - (1.0f * tp.y));
				game->tilemap[x + (tm_dim.x * y)].tcoord_sz		= v2f(1.0f * tp.x, 1.0f * tp.y);
			}
		}

GameUpdate()

	V2i tm_dim = game->tilemap_dim;
	for(int y = 0; y < tm_dim.y; y++)
	{
		for(int x = 0; x < tm_dim.x; x++)
		{
			float scroll_speed = 0.003f;

			int i = x + (tm_dim.x * y);
			float py = game->tilemap[i].pos.y;
			float szy = game->tilemap[i].size.y;


			game->tilemap[i].pos.y -= scroll_speed;

			if(py + szy <= 0.0f)
			{
				
				game->tilemap[i].pos.y = 2.0f + szy;

			}


			if(MousePressed(platform, GLFW_MOUSE_BUTTON_LEFT))
			{
				if(CursorInside_SPRITE(platform, game->tilemap[i]))
					game->tilemap[i].tcoord_p = game->currently_chosen_sprite->tcoord_p;

			}


		}
	}

Edited by C_Worm on

There is an issue with the code blocks you posted, and I assume that the code inside got modified in some way because the loops in GameInit would overwrite the same values in each iteration.

To insert a code block, use the markdown syntax: 3 backticks ( ` ) followed by the name of the language (c or cpp) to open the block, and 3 backticks to close the block.

That said, it would help us if you could make simple and minimal reproduction case that we could compile and test. Remove anything unrelated like editor features.

Out of the top of my head, if the tile texture/shader can have transparency than that might be the issue if the tile side is next to some transparent pixels. So try without textures or with opaque textures to see if the problem persists.

Thanks for the information on how to make code blocks!

I've changed so that the texture is just one color and that part from the texture-atlas is not "surrounded" by transparent pixels, and it seems to work fine.

But its still that one gap which seems to be between the first row and the last row.

And this is kind of the minimal code block i can give.

I could give you the whole game file but its dependent on my renderer.h/platform.h/engine.h and that's quite a lot i guess.

It only initializes a basic tilemap once in the init-function and updates/scrolls the tilemap downwards in the update-function.

When you move the tiles up, you set them at a fixed position 2.0f + szy (this seems odd but I'm assuming it's working with your setup). I suspect you need to remember by how much the tile was out of the screen and add that to the value (I'm assuming (0, 0) is bottom left).

game->tilemap[i].pos.y = 2.0f + szy - ( py + szy );

Another potential issue is that you initialize the position by computing the position using y * size_y. Since those are floating point, the value might not be exactly what you expect, and so when you wrap a tile from the bottom the correct value might not be 2.0f + szy but something like 1.999f + szy. Which could cause the gap. It might be better to somehow compute the new y in a similar fashion that the initialization code.


Edited by Simon Anciaux on

Hmmm okay, how would you reliably set positions/sizes based on float's then since i guess that's probably the problem??

Im setting it to 2.0f + szy because there's one row of tiles above the screen when the first goes out of the bottom bounds.

it could be 2.0f + (n * szy) depending on how many rows are above the screen.

T = one tile.

 TTTTT    <---------------------------------------------
 TTTTT                                                 |
 -----    <---- top screen boundary                    |
|TTTTT|                                                |
|TTTTT|                                                |
|TTTTT|                                                |
 -----    <---- bottom screen boundary                 |
 TTTTT    <---- tilerow out of bounds and moves here --|

Edited by C_Worm on
Replying to mrmixer (#25869)

Did you try my first suggestion has it's more likely to be the issue ?

game->tilemap[i].pos.y = 2.0f + szy - ( py + szy );

The idea is that you're moving tiles down by 0.003f each time. At the beginning the first tile as it's bottom at 0, and it's top at 0.0625 (32/512).

step 1: bottom = 0 - 0.003 = -0.003; top = 0.0595
step 2: bottom = -0.006; top = 0.0565
...
at some point we have
step n: bottom = -0.06; top = 0.0025
stop n+1: bottom = -0.063; top = -0.0005

At this point in the code you need to wrap the y value. What you do is to set it at 2.0 + 0.0625 (which I assume is the top of the screen + the size of a tile). But that doesn't take into account that it was down the screen by -0.0005 (which should be the value given by py+szy). So if you don't correct for that you'll get a small gap between the last tile that was initialized and first tile that wrapped. After that since every tile will get the same error you will most likely not get a gap again.

Another way to change the tile y value would be to add the size of the screen to it's position.

game->tilemap[i].pos.y += ( ( tm_dim.y + 1 ) * szy );

Edited by Simon Anciaux on

ooh yes thanks a lot!! I tried to the first alternative but it didn't seem to work, maybe made a fault somewhere.

but this really did the job:

game->tilemap[i].pos.y += ( ( tm_dim.y + 1 ) * szy );

Man! Sometimes trivial problems can get your head spinning 100 times and you feel like a donkey.


Replying to mrmixer (#25875)