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

Author Topic: Drawing a Tilemap the right way  (Read 12511 times)

0 Members and 1 Guest are viewing this topic.

kingcools

  • Jr. Member
  • **
  • Posts: 57
    • View Profile
Drawing a Tilemap the right way
« on: December 31, 2013, 07:34:09 pm »
hi, im working on a tilemap right now, and even though it works properly it feels slow which is probably because i use the sfml functions and classes the wrong way:

So my tiles look like this:

class Tile
{
private:
        const sf::Image* _source;
        sf::IntRect _section; //! Section of the source that is drawn

public:
    Tile(void)
    :_source(nullptr),_section(sf::IntRect()) {}
        Tile(const sf::Image* source,sf::IntRect section)
        :_source(source),_section(section) {}
    const sf::Image*         source(void)  const                    { return _source; }
    const sf::IntRect&             section(void) const                    { return _section; }
    void                     setSection(sf::IntRect section) { _section = section; }
};

_section is just the part of the source image the tile is using.
First question:
Should i already use sf::Texture here for the image reference? im not manipulating the images anyway.

Now the render function:
void Engine::renderFrame()
{
        int posx,posy;
        window.clear();
        for(unsigned int y = 0; y < level.getHeight(); ++y)
        {
                for(unsigned int x = 0; x < level.getWidth(); ++x)
                {
                        const Tile& tile  = level.getTile(x,y);
                        posx              = (x * level.getTilesize());
                        posy              = (y * level.getTilesize());
            drawTile(tile,posx,posy);
                }
        }
        window.display();
}

and my drawTile function:
void Engine::drawTile(const Tile& t,int posx,int posy)
{
    if(t.source() != nullptr){
        sf::Texture tex;
        sf::Sprite spr;

        tex.loadFromImage(*(t.source()),t.section());
        spr.setTexture(tex);
        spr.setPosition(posx,posy);
        window.draw(spr);
    }
}

This is my main concern:
i read that one should use as few textures as possible, now i always create a new one with every call, this should have a terrible performance.

How would one draw a tile based map like mine? Draw all the sprites to a single texture and draw that texture to the screen afterwards?

Thanks for any help :)

fallahn

  • Hero Member
  • *****
  • Posts: 504
  • Buns.
    • View Profile
    • Trederia
Re: Drawing a Tilemap the right way
« Reply #1 on: December 31, 2013, 07:49:25 pm »
It's generally accepted that the best way is via vertex arrays. There's even an example down the page.

G.

  • Hero Member
  • *****
  • Posts: 1593
    • View Profile
Re: Drawing a Tilemap the right way
« Reply #2 on: January 01, 2014, 01:49:46 am »
I don't think creating and loading a texture from an image for every tile every frame is good. :p Yes, you should probably directly use a texture (and set the "section" with setTextureRect) instead of an image if you don't really use the image.
vertexarrays are faster, but a little harder to use. So if you're OK with sprites why bother?

Another thing you'll probably want to do is drawing only the tiles that are on the screen instead of every tiles even those you can't see.

wintertime

  • Sr. Member
  • ****
  • Posts: 255
    • View Profile
Re: Drawing a Tilemap the right way
« Reply #3 on: January 01, 2014, 01:17:37 pm »
You better combine all tile images into a single tilemap image.
At init time you could then load that image into your program and create an array to convert tile id numbers into vertices. Then at start and every time the shown tiles change you read from the map array the needed tile ids, calculate the position from the map indices and add all vertices into a vertex array. Then you can just draw it every frame.