SFML community forums

Help => Graphics => Topic started by: Makuto on November 30, 2011, 03:09:59 pm

Title: Tilemap at 7 fps
Post by: Makuto on November 30, 2011, 03:09:59 pm
Hi.  I just finished making a simple tilemap outputter.  For some reason, it runs at 7 FPS without even drawing that much (just 40 16X16 images subrected from one 416X416 image).  The structure of my tilemap class is that it reads from a file two characters, a-z, then translates those to numbers and stores them in an array.  The displayTileMap() function then goes through the array and subrects the image according to the numbers in the array.  That image is then displayed and it loops again on the next numbers.  Once the end character is reached in the array the function is finished.  I execute the displayTileMap() function every frame.  I just tryed it with only 26 images to be drawn and it still gets only 13 fps.  What should I do to get more performance?
Title: Tilemap at 7 fps
Post by: Laurent on November 30, 2011, 03:26:39 pm
Can you show a complete and minimal code that reproduces the problem? You're probably doing something wrong, but without your code it will be hard to find out what ;)

And if the code is big, please provide the most minimal version (but still complete) of it so that we don't waste time with irrelevant details.
Title: Tilemap at 7 fps
Post by: Makuto on November 30, 2011, 08:10:33 pm
Here's the function (sorry for length, I'm planning on rewriting it):
Code: [Select]
void displayTileMapSimply(game *App, int widthPerRow)
    {
        //This will display the ENTIRE tilemap as simply as possible
        std::cout << "wpr at beginning: " << widthPerRow << std::endl;
        int u=0; //The current index in the index[];
        int intBuffer=0;
        int row;
        int column;
        int top, left, bottom, right;
        int posX, posY; //The posiiton that the tile should be displayed at
        posX=posY=0;
        row=column=0;
        std::cout <<"Displaying tile map simply..." << std::endl;
        top=left=bottom=right=0;
        int currentRow=1;
        int currentTile=0;
        //int currentColumn=widthPerRow;
        while (1) //man, I don't really use these too well
        {
            row=column=intBuffer=0;
            intBuffer=index[u];
            if (intBuffer==0)
            {
                std::cout << "FOUND 0 [END CHARACTER]" << std::endl;
                break;
            }
            if (intBuffer>=32422)
            {
                std::cout<<"intBuffer is a stupid value..." << std::endl;
                u++;
                intBuffer=index[u];
            }
            row=intBuffer;
            u++;
            intBuffer=index[u];
            if (intBuffer==0)
            {
                std::cout << "FOUND 0 [END CHARACTER]" << std::endl;
                break;
            }
            column=intBuffer;
            u++;
            //std::cout << "Row-Column: " << row << "-" << column << std::endl;
            //if (row>36445) row=1; //Random number, you get the idea
            currentTile++;
            //std::cout << "--Current Tile: " << currentTile << std::endl;
            //Now the code for displaying it from these numbers
            //TOP LEFT BOTTOM RIGHT
            top=tileY*(row-1);
            left=tileX*(column-1);
            bottom=tileY*row;
            right=tileX*column;
            //std::cout << row << "," << column << std::endl;
            //std::cout << top <<"-"<< left <<"-"<< bottom <<"-"<< right << std::endl;
            tileSheet.setSubRect(top, left, bottom, right);
            ///////////////////////////////////////////////////////////////////////////////////////////
            posX=(currentTile-1)*tileX;
            tileSheet.setPosition(posX, posY);
            //posY, u + 1(row1 is 1-20), width per row(10), and the row number (1)
            //std::cout << "Width Per Row-CurrentTile-PossiblyTrueWPR: " << widthPerRow <<"-"<<currentTile<<"-"<<currentColumn<<std::endl;
            if (currentTile==widthPerRow)
            {
                posY=currentRow*tileY;
                currentRow++;
                currentTile=0;
            }
            //std::cout <<"PosX,PosY: "<<posX<<","<<posY<<std::endl;
            //if(currentTile==10) posY-=tileY;

            App->drawObj(tileSheet);
            top=left=bottom=right=0;
            //std::cout<<"CurrentTile: " << currentTile << std::endl;

        }
     
    }


I've isolated SFML from most of the code because I am planning on making a multi-platform library (PS3 Xbox 360 etc.) so you don't need to change your code.
Title: Tilemap at 7 fps
Post by: Laurent on November 30, 2011, 08:26:02 pm
Even when repeated twice, the words "minimal" and "complete" are still ignored :roll:
Title: Tilemap at 7 fps
Post by: luiscubal on November 30, 2011, 09:16:34 pm
Is your game still slow when the cout commands are removed(or commented out)? Keep in mind that I/O is an expensive operation to be performing each frame.
Title: Tilemap at 7 fps
Post by: lezebulon on November 30, 2011, 11:08:52 pm
That's not really how a tile engine is supposesd to be  working since you are re-computing each tile position at each frame...
Anyway you have to have your basic tiles preloaded and NOT extract them from the tileset at each frame
Title: Tilemap at 7 fps
Post by: Makuto on December 01, 2011, 12:10:29 am
Sorry Laurent, I was really short on time when I posted it (and not supposed to be posting) :).  Luis, the FPS that I get is with the couts commented out except the FPS (it's difficult to read the FPS when there's 20 lines outputted per frame).  If this is important at all, I do get a better frame rate with less tiles (about 13 FPS with 20 tiles).  Lezebulon, I don't really understand what you are saying exactly.  Is it better to load a tile sheet, then make sprites for every tile in the sheet with their positions in their classes?  Would it help my function a lot if I didn't have so many sub recting calls?
Title: Tilemap at 7 fps
Post by: Laurent on December 01, 2011, 07:39:29 am
It makes no difference, you can call SetSubRect, SetPosition etc. every frame or once at init time, you'll get the same performances.

Try to disable all the std::cout (output the FPS once per second, for example -- or better: use FRAPS). These calls are really slow.
Title: Tilemap at 7 fps
Post by: Makuto on December 02, 2011, 03:36:58 am
After disabling the couts, I still get 4-5 FPS with ~120 tiles.  I think I will split the tile sheet into individual sprites, then make a list of those and print them like that.  That might get some more FPS
Title: Tilemap at 7 fps
Post by: Laurent on December 02, 2011, 07:57:07 am
Quote
That might get some more FPS

... or not.

Do other OpenGL apps/games run fine on your computer?
Title: Tilemap at 7 fps
Post by: Makuto on December 03, 2011, 01:03:17 am
I just fixed the problem for now.  If I remove the middleman class (game) from sf::RenderWindow (what I use for drawing), I get 200+ FPS.  Thanks for the help, sorry for the trouble!  By the way, why would the drawing be slower with the game class:
Code: [Select]

class game
{
public:
    sf::RenderWindow *App;
    sf::Event Event;
...
    game(int x, int y, std::string title)
    {
        App=new sf::RenderWindow(sf::VideoMode(x,y), title);
        //if (App==0) std::cout << "error" << std::endl;
        App->UseVerticalSync(useVertSync);//These are both predefined constants
        App->SetFramerateLimit(frameLimit);

    }
    game(sf::RenderWindow *newApp)
    {
        App=newApp;
    }
...
    void drawObj(object o)
    {
        App->Draw(o.spr);
    }
Title: Tilemap at 7 fps
Post by: Walker on December 03, 2011, 02:02:49 am
Quote from: "makuto"
why would the drawing be slower with the game class


Because you're taking a copy of every object you draw.
Title: Tilemap at 7 fps
Post by: Makuto on December 03, 2011, 04:01:50 am
So it should instead be an address/pointer to the object?  That would make lots of sense...
Title: Tilemap at 7 fps
Post by: luiscubal on December 03, 2011, 05:07:33 pm
C++ includes the concept of reference "type&" instead of "type", that also doesn't make any copies.
Title: Tilemap at 7 fps
Post by: Nexus on December 03, 2011, 05:32:17 pm
And you shouldn't use manual memory management (e.g. the new keyword) unless necessary. Instead of
Code: [Select]
class Game
{
        sf::RenderWindow* app;
    public:
        Game()
        {
            app = new sf::RenderWindow(width, height, videoMode);
        }
use objects and the constructor initializer list:
Code: [Select]
class Game
{
        sf::RenderWindow app;
    public:
        Game()
        : app(width, height, videoMode)
        {
        }

In case you really have to use new, don't forget delete. Or better, directly work with smart pointers.