Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: TileMap: array of sprites vs vertexArray  (Read 6052 times)

0 Members and 2 Guests are viewing this topic.

albert_lazaro

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
TileMap: array of sprites vs vertexArray
« on: May 02, 2021, 09:15:21 pm »
Hi,
I'm doing a videogame (or I'm trying to do  :P) that renders a top-down map based on tiles. I had followed the guides and I saw that there is an example that used a vertex array for displaying a map and I had implemented it, but now, before I proceed further, I want to make the correct decisions for the design of the game.

I have been reading some posts related to this topic and I have extracted the next points:

  • So first, Sprites are lightweight objects, so it does not represent a noticeable difference.
  • With VertexArray, the tiles are in a single entity and it does only a draw call, but with the sprite array it makes a draw call per tile. Performance depends on the number of calls to the draw function.
  • With vertexArray, the tiles are static, so they can't change and with sprite array, you can animate them (for example the typical tiles of sea that simulates waves.)
  • With vertexArray, I can draw a map larger than the view, and it does not affect performance. With the tiles, I should only render the tiles that are visible in the view.

Are the points correct? I'm missing something?

For the moment I'm using VertexArray for displaying a 64x128 tiled map, where tiles are 16x16 pixels and the view is 256*224 pixels (SNES resolution).

Stauricus

  • Sr. Member
  • ****
  • Posts: 369
    • View Profile
    • A Mafia Graphic Novel
    • Email
Re: TileMap: array of sprites vs vertexArray
« Reply #1 on: May 02, 2021, 10:23:59 pm »
you're kind of right. just some points:
  • you CAN animate a VertexArray. just like sprites, the animation is done by changing the tile texture from time to time (for example, each 1000 milliseconds you put the next 'water' frame).
  • the downside is that every sprite can have its own texture; but the VertexArray must have a texture for all its planes("tiles").
  • if you are going to use few tiles per screen, it doesn't really make a noticeable difference. if you are going to have a huge world,in any case its better to load and unload parts of the map on the run (like the famous chunks from Minecraft)
  • in any case you can draw a map larger than the screen. but that's just wasted resources, mainly for sprites. for vertexarrays not so much, since as you said, they're drawn in a single draw call; yet, having a big vertexarray loaded 100% of the time the game is running, considering most of it won't be used at the same time... its also a waste (there is no point it having all cities and forests and deserts loaded in memory at once if you character is located in only one of these).

if you need any directions on how to do these, just ask, i'm also a lover of tiles :)
« Last Edit: May 02, 2021, 10:26:27 pm by Stauricus »
Visit my game site (and hopefully help funding it? )
Website | IndieDB

kojack

  • Sr. Member
  • ****
  • Posts: 343
  • C++/C# game dev teacher.
    • View Profile
Re: TileMap: array of sprites vs vertexArray
« Reply #2 on: May 03, 2021, 12:21:56 am »
Another way to go is using a tile shader.

Using just a single quad and 1 draw call, you can have a huge area with no off screen drawing. Have an atlas texture for all your tiles and an index texture to specify which tiles to use.
The colour of each pixel in the index texture is the index of a tile in the atlas.
By changing the pixels of the index texture, you can animate tiles.

albert_lazaro

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: TileMap: array of sprites vs vertexArray
« Reply #3 on: May 03, 2021, 07:37:49 pm »
Thanks a lot, Stauricus!

For the second point, I can use one texture that is the atlas and set the corresponding sprite to the tiles by an index in the int array that represents the map.

I will try to make or find an algorithm to draw only what is viewed in the viewport. I will try to do it with the VertexArray instead of with tiles.


kojack, I don't want to use a shader for this. I think there are other options before that.

albert_lazaro

  • Newbie
  • *
  • Posts: 18
    • View Profile
    • Email
Re: TileMap: array of sprites vs vertexArray
« Reply #4 on: May 04, 2021, 09:08:13 pm »
I want to render only what is viewed in the view, the first thing I need is to obtain the left top pixel of the current visualization, in order to get first tile that I want to draw. How can I obtain this pixel? I have been looking the View wiki and didn't found anything.

----- EDIT

I'm looking the tutorials and I see that you can define the Viewport, setting a FloatRect with left, top, witdh and height parameters.

So I have to get the viewport from the current view and get the x and y attributes. This would work if viewport is defined with pixels, not with relative position to the window.

I'm lost at this point.
« Last Edit: May 04, 2021, 09:15:52 pm by albert_lazaro »

Stauricus

  • Sr. Member
  • ****
  • Posts: 369
    • View Profile
    • A Mafia Graphic Novel
    • Email
Re: TileMap: array of sprites vs vertexArray
« Reply #5 on: May 05, 2021, 02:20:03 am »
shaders are also great. too bad I'm not good at them  :(


I want to render only what is viewed in the view, the first thing I need is to obtain the left top pixel of the current visualization, in order to get first tile that I want to draw. How can I obtain this pixel? I have been looking the View wiki and didn't found anything.

you can do something like this (i'm not getting the first pixel, but the first tile to be drawn). chunk_size is in tiles, not in pixels.
sf::Vector2i central_tile(std::floor(view.getCenter().x/tile_size.x), std::floor(view.getCenter().y/tile_size.y)); //central tile in the view
sf::Vector2i first_tile(central_tile.x-chunk_size.x/2, central_tile.y-chunk_size.y/2); //first tile, upper left
sf::Vector2i last_tile(first_tile + chunk_size); //last tile, bottom right

//[...]

for(size_t y=first_tile.y; y<last_tile.y; y++){
    for(size_t x=first_tile.x; y<last_tile.x; x++){
        //draw tile[x][y];
    }
}
 
Visit my game site (and hopefully help funding it? )
Website | IndieDB