Hello everyone :D
I'm making a game, and I'm having performance issues, sadly. At first I thought it was because of some code of mine (like collision detection) but after spending some hours I noticed that it's really because of the amount of sprites.
I have all my sprites on a linked list, and draw them one by one, thinking that this is the only way of drawing a lot of stuff. The code is simply like this:
std::list <sf::Sprite> :: iterator i;
for (i = mySprites.begin(); i != mySprites.end(); i++)
myWindow.draw(*mySprite);
So, I get an awful performance hit while drawing like 30 or so sprites, which is a pretty low amount for my needs. The sprites use one of 8 or so textures, which have a size of around 400x400 pixels each.
However, I noticed that I can draw a lot of sprites without the performance hit (like 200 or so) if all the sprites have the same texture. The performance gets worse the bigger the amount of different textures used by the sprites, even if I draw the exact same amount of them. Why is that?
I kind of imagine the reason, but hopefully someone could give me an explanation :)
Anyway, while searching for a couple of hours, I read that performance may improve if I reduce the number of draw calls, and to do so I need to use "batching" (a new concept to me) and/or use sf::VectorArray (I don't know if using the vector array is actually part of batching or just a different process).
So, why batching/using a vector array is better than drawing each sprite one by one? And finally, could somebody please show me a small example of code with a vector array in action?
Sorry for the long post and for the dumb questions. I searched a lot but I didn't really understood what I found, it's like chinese to me :P
Thanks in advance.
So, I made a little code to just draw 30 sprites on screen at random, just using one sprite list and one camera. Here's the download link (it contains the textures I used, which are varied in size, and the code, of course).
http://www.mediafire.com/?t746lkri9d654ba
Here's the code (I'm deleting some stuff like camera movement, showing FPS on screen and pressing Esc to close the window, as they are unrelated to the problem).
#include <iostream>
#include <list>
#include <sstream>
#include <SFML/Graphics.hpp>
int main() {
// Window.
sf::RenderWindow window(sf::VideoMode(1280, 800), "Test", sf::Style::Fullscreen);
// Camera.
sf::Vector2f cameraSize(window.getSize().x, window.getSize().y);
sf::Vector2f cameraCenter(cameraSize.x/2, cameraSize.y/2);
sf::View camera(cameraCenter, cameraSize);
// Loading textures.
int amountTextures = 11;
sf::Texture textures[11];
std::string names[11];
...
for (int i = 0; i < amountTextures; i++)
textures[i].loadFromFile(names[i]);
// Creating sprites.
std::list <sf::Sprite> sprites;
for (int i = 0; i < 30; i++) // 30 sprites.
sprites.push_back( sf::Sprite() );
std::list <sf::Sprite> :: iterator it; // Sprite properties.
srand(time(0));
for (it = sprites.begin(); it != sprites.end(); it++) {
// Texture at random.
int random = rand() % amountTextures;
it->setTexture( textures[random] );
// Using center of sprite as origin.
it->setOrigin( it->getGlobalBounds().width/2, it->getGlobalBounds().height/2 );
// Position at random (inside the camera).
int randX = rand() % (int)cameraSize.x;
int randY = rand() % (int)cameraSize.y;
it->setPosition( randX, randY );
}
/// Game loop.
sf::Event event;
while (window.isOpen() ) {
...
// Drawing.
window.clear(sf::Color::Cyan);
window.setView(camera);
for (it = sprites.begin(); it != sprites.end(); it++)
window.draw(*it);
// Display.
window.display();
}
return 0;
}
So, the result? Around 45 FPS average after drawing 30 sprites. I managed to get 100+ FPS if all the sprites use small textures, and below 30 if they use big ones.
With that said, I guess the solution is either:
1.- Using a small resolution but keeping the camera at its original size. With this I can get over 60, but it looks blurry. Not that bad if I use "setSmooth()" on all the textures, but still...
2.- Using smaller textures, which is kind of a bummer.
Still, I thought that even a very bad GPU could handle this amount of sprites easily, regardless of size ???
Have you tryed using std::array as Sprite container?
#include <array>
...
std::array <sf::Sprite, 30> spriteContainer;
Also try to reduce the number of textures to the minimum (Use texture atlas (http://en.wikipedia.org/wiki/Texture_atlas))