SFML community forums

Help => Graphics => Topic started by: K55 on September 28, 2011, 02:29:56 am

Title: Running Heavy Graphics
Post by: K55 on September 28, 2011, 02:29:56 am
Hi everyone, I've been messing around with SFML lately and have really come to like the language. However, I am running into roadblocks literally when it comes to drawing large png images or tiles. When I draw my titlescreen images or tilemap, the framerate drags down to 8 or so fps. For example:

Code: [Select]
px = 0;
py = 0;

for (float qq = 0; qq <= 800; qq +=32)
{
for (float ii = 0; ii <= 608; ii += 32)
{
if (map[px][py] == 0)
{
App.Draw(Tile1);
Tile1.SetPosition(qq,ii);
}

if (map[px][py] == 1)
{
App.Draw(Tile2);
Tile2.SetPosition(qq,ii);
}
py++;
}
px++;
py=0;
}


Is a simple script I wrote to display tiles in a 800x600 window (yes I could have gotten the resolution and changed the array size, but that's not the point). This script running constantly to draw 475 png tiles is really slow.

So my question is, is there a way to draw a sprite or an image only once, so that it does not eat up memory or processing time?
Thanks
-K55
Title: Running Heavy Graphics
Post by: OniLinkPlus on September 28, 2011, 04:25:45 am
We need a complete and minimal code to see exactly what the problem is and to test it on our machines.
Title: Running Heavy Graphics
Post by: thePyro_13 on September 28, 2011, 04:30:15 am
You should be using one sprite per map cell. Reusing them like this may be the cause of your performance loss.

Do your math upfront and reuse it, rather than calculating which tile goes where every frame.
Title: Running Heavy Graphics
Post by: sbroadfoot90 on September 28, 2011, 06:11:13 am
Quote
You should be using one sprite per map cell. Reusing them like this may be the cause of your performance loss.


Rather, you should load each tile into a texture (or image if you are using 1.6), or your tileset into a single texture only once, and reuse this texture for each sprite that needs to use it, you can use the setsubrect member function of sprite to choose which portion of the tileset you want to use for that particular sprite .
Title: Running Heavy Graphics
Post by: K55 on September 28, 2011, 07:01:34 pm
Here's the code:
(the two tiles are 32x32 png images)
Code: [Select]
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML\System.hpp>
#include <SFML\Graphics.hpp>
#include <SFML\Window.hpp>

////////////////////////////////////////////////////////////
/// Entry point of application
///
/// \return Application exit code
///
////////////////////////////////////////////////////////////
int main()
{
    // Create the main rendering window
    sf::RenderWindow App(sf::VideoMode(800, 600, 8), "A-Mazing Game");
float movespeed = (32.0f);

sf::Image T1;
if (!T1.LoadFromFile("grass (2).png"))
return EXIT_FAILURE;
T1.SetSmooth(false);

sf::Image T2;
if (!T2.LoadFromFile("water.png"))
return EXIT_FAILURE;
T2.SetSmooth(false);

   

    // Create the sprite
    //sf::Sprite Sprite(Image);
sf::Sprite Tile1(T1);
sf::Sprite Tile2(T2);

int map[25][19]= {0};

map[24][0]= 1;


    // Start game loop
    while (App.IsOpened())
    {
        // Process events
        sf::Event Event;
        while (App.GetEvent(Event))
        {
            // Close window : exit
            if (Event.Type == sf::Event::Closed)
                App.Close();
        }

App.Clear();
int px = 0;
int py = 0;

for (float qq = 0; qq <= 800; qq +=32)
{
for (float ii = 0; ii <= 608; ii += 32)
{
if (map[px][py] == 0)
{
App.Draw(Tile1);
Tile1.SetPosition(qq,ii);
}

if (map[px][py] == 1)
{
App.Draw(Tile2);
Tile2.SetPosition(qq,ii);
}
py++;
}
px++;
py=0;
}



        // Clear screen
        // Display sprite in our window
        // Display window contents on screen
        App.Display();
    }

    return EXIT_SUCCESS;
}

Just a question, how would I go about using only one sprite per cell?
Title: Running Heavy Graphics
Post by: David on October 11, 2011, 07:26:07 pm
Just out of curiousity, why are you using floats for "ii" and "qq"?
Title: Running Heavy Graphics
Post by: slotdev on October 12, 2011, 01:39:54 pm
In addition to the above comments, there is no frame rate control, nor are you handing any time back to the CPU between, so your app will be running at 100% CPU.
Title: Running Heavy Graphics
Post by: thePyro_13 on October 12, 2011, 01:58:54 pm
Quote from: "K55"
Here's the code:
(the two tiles are 32x32 png images)
Code: [Select]
<codes>

Just a question, how would I go about using only one sprite per cell?


Create a std::vector or std::list and move your for loop above the main loop(your while loop). For each tile you create, push it into your vector or list.

Then in your draw step iterate through your list and draw every entry.

Something like this(not working code, but should get the point across), modified version of parts of your code.

Code: [Select]

//before while
for (float qq = 0; qq <= 800; qq +=32)
      {
         for (float ii = 0; ii <= 608; ii += 32)
         {
            if (map[px][py] == 0)
            {
               //App.Draw(Tile1);
               Tile1.SetPosition(qq,ii);
               vector.push_back(Tile1); //load into vecotr
            }

            if (map[px][py] == 1)
            {
               //App.Draw(Tile2);
               Tile2.SetPosition(qq,ii);
               vector.push_back(tile2); //load into vector
            }
            py++;
            }
         px++;
         py=0;
      }

//between clear() and display()

vector<sprite>::iterator iter = vector.begin()
whlie (iter != vecotr.end())
{
App.Draw(*iter);
iter++;
}