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

Author Topic: Draw very big tilemaps  (Read 6764 times)

0 Members and 1 Guest are viewing this topic.

Millsialix

  • Guest
Draw very big tilemaps
« on: January 27, 2017, 02:52:05 pm »
(forgive the approximate english, I'm french)

Hello,
I have a problem with tilemaps. Indeed, when I create and draw little tilemaps like in the tutorials, there are no problems, but when I draw big tilemaps (like... 1000x1000 tiles, maybe more? ::) ) my computer idle.
I have tried to cut my tilemap into a grid of chunks, and draw only near chunks. Slow drawing, regardless of the chunks sizes.
I have tried to create tilemaps of the size of screen at regular intervals. Slow drawing.
So if somebody can help me...
Thanks you in advance.

(I don't know if it can be useful, but my game must work in HD, I have a tileset of 1024*1024 pixels and tiles of 64*64 pixels)

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Draw very big tilemaps
« Reply #1 on: January 27, 2017, 03:05:48 pm »
Can you provide a minimal example that reproduces the issue?
What do you mean with "computer is idle"?
What's your GPU?
Did you run your code in release mode?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Millsialix

  • Guest
Re: Draw very big tilemaps
« Reply #2 on: January 27, 2017, 03:29:59 pm »
Can you provide a minimal example that reproduces the issue?
It's just the code on the tutorial (http://www.sfml-dev.org/tutorials/2.2/graphics-vertex-array.php) but I do this every 0.5 seconds according to the position of the view.
For the chunks, I have done a vector of vector of vertexArrays and drawed the nearest chunks, but now I have no longer have the code.

What do you mean with "computer is idle"?
My program freeze, is very low (and of course, unplayable)

What's your GPU?
AMD Radeon(TM) HD 6380G

Did you run your code in release mode?
Release, debug, I have all rebuilt, nothing change

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Draw very big tilemaps
« Reply #3 on: January 27, 2017, 04:26:07 pm »
I do this every 0.5 seconds according to the position of the view.
What does that mean?

Can you provide your code and not the code that your code is based off?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Millsialix

  • Guest
Re: Draw very big tilemaps
« Reply #4 on: January 27, 2017, 04:58:48 pm »
    // NOTE : 'm_local' is the tilemap/vertexArray

Tilemap::Tilemap( ... ){}
Tilemap::~Tilemap(){}
void Tilemap::affichage( sf::RenderWindow &fenetre, sf::Texture &texture, sf::Vector2f pos, std::vector<int> tilesNiveau, sf::Vector2u taille, bool r ){
    // 'fenetre' is the renderWindow
    // 'texture' is the tileset
    // 'pos' is the center of the view
    // 'tilesNiveau' is the array with the full tilemap
    // 'taille' is the size (in tiles) of tilemap
    // 'r' is a boolean : 'true' every 0.5 sec

    // SIZE OF SCREEN-SIZED TILEMAP
    unsigned int TILEMAP_X = 25;
    unsigned int TILEMAP_Y = 15;

    if( r == true ){ // IF IT HAS ELAPSED 0.5 SEC (BECAUSE THE VIEW MOVE ABOUT A TILE IN 0.5 SEC)
       
        sf::Vector2i posT = sf::Vector2i( pos.x/64.0, pos.y/64.0 ); // TILE IN CENTER OF THE VIEW

        unsigned int tX = TILEMAP_X, tY = TILEMAP_Y; // SIZE OF TILEMAP

        if( taille.x < TILEMAP_X ) tX = taille.x; // ADJUSTMENTS FOR SMALL TILEMAPS
        if( taille.y < TILEMAP_Y ) tY = taille.y;

        int dX = posT.x-floor(tX/2.0); if( dX < 0 ) dX = 0; if( dX+tX > taille.x ) dX = taille.x-tX; // WHERE START THE SCREEN-SIZED TILEMAP ?
        int dY = posT.y-floor(tY/2.0); if( dY < 0 ) dY = 0; if( dY+tY > taille.y ) dY = taille.y-tY;

        m_local.clear(); // AND NOW IS LIKE THE SFML TUTORIAL
        m_local.resize( tX*tY*4 );
        m_local.setPrimitiveType( sf::Quads );

        for( int i = dX; i < dX+tX; ++i ){
            for( int j = dY; j < dY+tY; ++j ){
                int tile = tilesNiveau[ i+j*taille.x ]; // I FIND THE TILE NUMBER ON THE ARRAY WHO CONTAINS THE FULL TILEMAP
                int tu = tile % 16; // BECAUSE THE TEXTURE CONTAIN 16*16 TILES OF 64 PIXELS
                int tv = tile / 16;
                sf::Vertex* monQuad = &m_local[((i-dX)+(j-dY)*tX)*4]; // I FIND THE NUMBER OF THE TILE
                monQuad[0].position = sf::Vector2f(    i*64,     j*64 ); // AND I MODIFY THE VERTEXES
                monQuad[1].position = sf::Vector2f((i+1)*64,     j*64 );
                monQuad[2].position = sf::Vector2f((i+1)*64, (j+1)*64 );
                monQuad[3].position = sf::Vector2f(    i*64, (j+1)*64 );
                monQuad[0].texCoords = sf::Vector2f(    tu*64+1,     tv*64+1 );
                monQuad[1].texCoords = sf::Vector2f((tu+1)*64-1,     tv*64+1 );
                monQuad[2].texCoords = sf::Vector2f((tu+1)*64-1, (tv+1)*64-1 );
                monQuad[3].texCoords = sf::Vector2f(    tu*64+1, (tv+1)*64-1 );
            }
        }
    }
    fenetre.draw( m_local, &texture );
}
 

fallahn

  • Hero Member
  • *****
  • Posts: 507
  • Buns.
    • View Profile
    • Trederia
Re: Draw very big tilemaps
« Reply #5 on: January 28, 2017, 11:09:34 am »
This is my favourite method of drawing tilemaps. A large map of 1000x1000 tiles or more can be stored in a single texture of the same dimensions, with the bonus of hardware cropping on the GPU and reduction of any tearing artifacts caused by vertex arrays. I believe there is a practical example of it on the SFML wiki.

jamesL

  • Full Member
  • ***
  • Posts: 124
    • View Profile
Re: Draw very big tilemaps
« Reply #6 on: January 28, 2017, 02:47:47 pm »
LOL
took me 5 minutes before I realized the word "This" in your post was a link

I thought you meant "this way in the post above"

I kept reading the code and thinking ? that's your favorite way ? :)

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Draw very big tilemaps
« Reply #7 on: January 28, 2017, 08:45:19 pm »
I would like to point out that if you are drawing to Full HD (i.e. 1920x1080) with tiles of 64x64, you only need to actually have 31x18 (1920/64 + 1, 1080/64 + 1 ... rounded up - that is) tiles drawn to the screen. The "+1" is only required if the tiles leave the grid (scroll/move smoothly). 558 tiles is great deal fewer than 1 million (your 1000x1000).
Note that the drawn tilemap can be a different thing to the level definition. The (much smaller) tilemap would update from the level definition using the parts that it should be showing...
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

Chaia*

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: Draw very big tilemaps
« Reply #8 on: January 29, 2017, 02:09:06 am »
Do you rebuild your whole Tilemap every 0.5 seconds? (not sure if I correctly understood your code from above in the correct context)

If so, why? I recommend to only build it once at the start of the game and then, as you already tried, divide your tilemap in chunks, maybe 20x20 Tiles is worth a try to start with. Each chunk would then be represented by a vertex array. Then you iterate over all your chunks every frame and only draw those which are seen (= intersect with your current view). Even though your graphics card is not that powerful, this should be not a problem at all.

Your code from above is (almost) the worst case. You are rebuilding your tilemap every 0.5 seconds and you are drawing the whole map even though most of it is not even seen on screen. Worst case would be if you built your map every frame and drew the whole thing every frame.
« Last Edit: January 29, 2017, 02:13:25 am by Chaia* »

Stauricus

  • Sr. Member
  • ****
  • Posts: 369
    • View Profile
    • A Mafia Graphic Novel
    • Email
Re: Draw very big tilemaps
« Reply #9 on: January 29, 2017, 02:11:41 pm »
Do you rebuild your whole Tilemap every 0.5 seconds?

this is what i understood too, and this is very likely to be the problem.


Millsialix, don't rebuild the map every 0.5 secs. instead, just check the player position; if it changed too much (if the player is getting near to the chunk border), THEN you rebuild the map. so, try changing this line:
if( r == true ){ // IF IT HAS ELAPSED 0.5 SEC (BECAUSE THE VIEW MOVE ABOUT A TILE IN 0.5 SEC)
Visit my game site (and hopefully help funding it? )
Website | IndieDB

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Draw very big tilemaps
« Reply #10 on: January 29, 2017, 03:49:16 pm »
I've just noticed that you're passing the level definition data (tilesNiveau), which is a (large) vector of ints, by value, not by reference, so it is being copied each time.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*