Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


Looping ONLY through visible tiles in a 2D engine?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 Rectangle   Members   -  Reputation: 161

Like
0Likes
Like

Posted 19 April 2013 - 12:21 AM

I'm using HGE to render a one-dimensional array of tiles. Each tile in this array stores vertex, color and texture information, which is pre-calculated (only once, before the first render cycle) and does NOT change. Instead, I have implemented a virtual camera system, storing an X/Y pixel offset + view width/height information, allowing a tilemap to be rendered at any given offset without actually changing the vertices of any tiles. This means that tilemaps are always located at 0,0 world-space coordinates, but the user is allowed to scroll through the map using the camera system.

 

I had this system working rather nicely for a while, until it was time to apply a few optimizations... One of which included calculating which tiles are within range of the camera view, and only rendering these tiles. This optimization nearly doubled my rendering speeds, but I realized the downfall is that I am still looping through each & every tile in the array. For smaler maps, this wasn't a big deal. But for larger maps, the performance hit is almost unbearable... And this is only for a single layer of tiles!

 

So, given the following variables:

  • One-dimensional Tile Array (stores vertex info)
  • Camera X Offset (pixel, world-space)
  • Camera Y Offset (pixel, world-space)
  • Camera View Width (pixel, screen-space)
  • Camera View Height (pixel, screen-space)
  • Tilemap Size (logical # of columns & rows)
  • Tile Dimensions (logical width & height, in pixels)

How could I create a loop which ONLY iterates through tiles within range of the camera's current view?


Edited by Rectangle, 19 April 2013 - 12:24 AM.


Sponsor:

#2 SimonForsman   Crossbones+   -  Reputation: 6167

Like
2Likes
Like

Posted 19 April 2013 - 12:47 AM

the left edge of the camera is at: camera_offset_x - camera-view-width / 2 and the right edge at camera_offset_x + camera_view-width / 2 right ?

(and similarily for the top and bottom edges)

 

If so then:

 

Edit: This assumes the camera position is the center of the screen (skip the -cam_width|cam_height /2 and change +width|height / 2 to just +width|height if the camera position is the top left)

firstcolumn =  floor((camera_offset_x - camera_view_width / 2) / tile_width)

lastcolumn = ceil((camera_offset_x + camera_view_width / 2) / tile_width)

firstrow = floor((camera_offset_y - camera_view_height / 2) / tile_height)

lastrow = ceil((camera_offset_y + camera_view_height / 2) / tile_height)

 

 

 

Now, assuming there are no gaps in your tile array and it is layed out row by row (so the first row comes before the 2nd row in the array etc)

If your tiles are stored in a random order you should change how they are stored.

 

firsttile = firstrow*tilemap_columncount + firstcolumn

lasttile = lastrow*tilemap_columncount + lastcolumn

 

iterate over that range


Edited by SimonForsman, 19 April 2013 - 04:10 AM.

I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!

#3 Rectangle   Members   -  Reputation: 161

Like
0Likes
Like

Posted 19 April 2013 - 02:27 AM

Thanks! With a couple of minor tweaks, I was able to get this algorithm to work:

 

void Render(HGE* hge, float cameraX, float cameraY, float cameraWidth, float cameraHeight) {
	int firstcolumn = int( floor(cameraX / m_tileWidth) );
	int firstrow = int( floor(cameraY / m_tileHeight) );
	int lastcolumn = int( ceil((cameraX + cameraWidth) / m_tileWidth) );
	int lastrow = int( ceil((cameraY + cameraHeight) / m_tileHeight) );

	for(int r = firstrow; r < lastrow; r++)
	{
		for(int c = firstcolumn; c < lastcolumn; c++)
		{
			hge->Gfx_RenderQuad(&m_tiles[r * m_nColumns + c].quad);
		}
	}
}





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS