SFML community forums

Help => Graphics => Topic started by: LucasShadow on March 28, 2012, 02:30:27 am

Title: Too many sprites?
Post by: LucasShadow on March 28, 2012, 02:30:27 am
So I am working on creating a very large tile-based map. Obviously, this requires quite a few sprites. Some of the code below:

int WorldXS = 100;
int WorldYS = 105;
sf::Sprite Tile[WorldXS * WorldYS];
 

Of course, I set positions and images for all of the tiles, and then draw them all. However, if I increase WorldXS or WorldYS by one more, it compiles, but the .exe stops working. This leads me to believe that SFML has a hard sprite limit of 10,500 sprites (WorldXS * WorldYS) ?
Title: Re: Too many sprites?
Post by: Roose Bolton of the Dreadfort on March 28, 2012, 05:17:19 am
Doubt its a hardcoded limit.. probably not healthy to a allocate 10,500 sprites at once though
Title: Re: Too many sprites?
Post by: thePyro_13 on March 28, 2012, 06:24:04 am
How big's a sprite? They're supposed to be pretty lightweight, but a block of 10 thousand of them still takes up a lot of space.

Arrays must be located as one large block of memory. How much ram do you have? It's likely that you're just expending all of your available contiguous memory(google "contiguous memory" for more info).

Try replacing the array with an std::list and see how that turns out?
Title: Re: Too many sprites?
Post by: mateandmetal on March 28, 2012, 07:41:10 am
what about creating your array on the heap.. with new?
Title: Re: Too many sprites?
Post by: eXpl0it3r on March 28, 2012, 10:04:53 am
int WorldXS = 100;
int WorldYS = 105;
sf::Sprite Tile[WorldXS * WorldYS];
 

Your lucky that you could compile that or better your compiler is enough kind to do so. You can't define an array without constant numbers. It should be const int. But s said before try to allocate them with new. The stack isn't that big.
Example: http://www.fredosaurus.com/notes-cpp/newdelete/50dynamalloc.html (http://www.fredosaurus.com/notes-cpp/newdelete/50dynamalloc.html)

unsigned int WorldXS = 100;
unsigned int WorldYS = 105;
sf::Sprite Tile = new sf::Sprite[WorldXS*WorldYS];
// Your code
delete[] Tile;

Since it's easy to forget the delete[] Tile; part or because of some exceptions it will never get called it's best to use RAII and therefor std::auto_ptr (https://en.wikipedia.org/wiki/Auto_ptr). Unfortunatly it's only in C++11 so you need one of the newer compilers.

Additionally if you don't move your sprites I'd recommend to draw them on a sf::RenderTexture (you'd have zo use SFML 2). And then just render that new texture every game loop iteration.
Title: Re: Too many sprites?
Post by: JohnB on March 28, 2012, 05:29:27 pm
just a suggestion only create the sprites visible on screen. then depending on the game position, change their image and subrect if necessary.
Title: Re: Too many sprites?
Post by: Oberon on March 30, 2012, 03:39:48 pm
Since it's easy to forget the delete[] Tile; part or because of some exceptions it will never get called it's best to use RAII and therefor std::auto_ptr (https://en.wikipedia.org/wiki/Auto_ptr).
Never ever use new for dynamic arrays in C++ (see the C++ FAQ entry on Why should I use container classes rather than simple arrays? (http://www.parashift.com/c++-faq/containers.html#faq-34.1)). Instead use an std::vector (http://www.cplusplus.com/reference/stl/vector/). With it, the above snippet could be rewritten as
unsigned int WorldXS = 100;
unsigned int WorldYS = 105;
std::vector<sf::Sprite> Tile(WorldXS * WorldYS);
// no delete[] or delete necessary
 
std::auto_ptr would cause undefined behavior here, as it uses delete instead of delete[].
Unfortunatly it's only in C++11 so you need one of the newer compilers.
Quite the opposite is true: It is old C++ 03 and deprecated in C++11 in favor of unique_ptr.

These are all basic C++ problems, I would recommend working through a good book on the language, before trying and struggling with SFML (That's just my advice, I do not want to offense anyone.)
Title: Re: Too many sprites?
Post by: bobingabout on March 30, 2012, 07:43:36 pm
Since you're working on a 2 dimentional grid, its also possible to do sf::Sprite Tile[WorldXS][WorldYS];
Not as easy to do that with vectors though...
Title: Re: Too many sprites?
Post by: Oberon on March 30, 2012, 09:15:50 pm
With vectors you can do std::vector<std::vector<sf::Sprite> >, although in this case a 2 dimensional array has higher performance.
Title: Re: Too many sprites?
Post by: Nexus on March 30, 2012, 09:31:59 pm
With vectors you can do std::vector<std::vector<sf::Sprite> >
Or just std::vector<sf::Sprite>, and map the indexes accordingly.

although in this case a 2 dimensional array has higher performance.
Raw arrays should always be avoided, wheter static or dynamic. It's a widespread myth that doing things on a lower level (aka. as much raw pointers, manual memory management and re-invented wheels as possible) magically increases performance.

A general guideline for linear sequences of elements:
Title: Re: Too many sprites?
Post by: bobingabout on March 30, 2012, 11:03:47 pm
from what i gather std::array<T, N> variable; is just a new way of of writing T variable[N];
Title: Re: Too many sprites?
Post by: Nexus on March 31, 2012, 12:15:15 am
is just a new way of of writing T variable[N];

Not at all, std::array is a class template with many advantages over raw arrays.
std::array has the same performance in release mode. But raw arrays have several drawbacks:
  • No value semantics. You can neither pass arrays to functions, nor return them from functions, nor assign nor copy them.
  • Implicit conversion to pointer to the first element, is sometimes unwanted
  • No bound checks in debug mode, leads to hard-to-track bugs
  • No STL-like interface with begin(), end(), size()
Title: Re: Too many sprites?
Post by: Silvah on March 31, 2012, 04:49:09 pm
although in this case a 2 dimensional array has higher performance.
Raw arrays should always be avoided, wheter static or dynamic. It's a widespread myth that doing things on a lower level (aka. as much raw pointers, manual memory management and re-invented wheels as possible) magically increases performance.
It's not a myth, however, that when quoting out of context you can severely distort what was actually said and take advantage of that in order to "prove" whatever you want to.

Unless, of course, the fact that an array of pointers to arrays (which vector of vectors happens to be) is slower than a single array (which T [N][M] happens to be) is also a myth. But it's not, the former requires one more indirection to access an element than the latter, and the former is very cache-unfriendly, especially when compared to the latter.

Cheers,
Advocatus Diaboli
Title: Re: Too many sprites?
Post by: Nexus on March 31, 2012, 05:02:26 pm
It's not a myth, however, that when quoting out of context you can severely distort what was actually said and take advantage of that in order to "prove" whatever you want to.
I didn't intend to correct the quoted text, but to give a general advice concerning the use of arrays. Because the sentence has a high tendence to be read like "arrays have higher performance than vectors".

Unless, of course, the fact that an array of pointers to arrays (which vector of vectors happens to be) is slower than a single array (which T [N][M] happens to be) is also a myth. But it's not [...]
Guess why I came up with the idea to use a one-dimensional vector and to map indexes ;)
Title: Re: Too many sprites?
Post by: Silvah on March 31, 2012, 05:35:12 pm
I didn't intend to correct the quoted text, but to give a general advice concerning the use of arrays.
Well, one typically quotes a message when they want to refer to it somehow. If you didn't, why were you quoting it at all?

Guess why I came up with the idea to use a one-dimensional vector and to map indexes ;)
But that's error-prone. Wasn't error-proneness one of the reasons to avoid raw arrays? So why replace them with something that's only slightly less so? I'd rather use boost::multi_array or something similar instead of a vector with manually recalculated indices.
Title: Re: Too many sprites?
Post by: Nexus on March 31, 2012, 05:57:13 pm
Wasn't error-proneness one of the reasons to avoid raw arrays? So why replace them with something that's only slightly less so?
It's not slightly less, it's far less. Computing indexes is easy. Implementing memory management, an STL interface and value semantics isn't. And one can still encapsulate the computation of indexes to make it trivial.

But anyway, we're comparing different things. For two-dimensional automatic arrays, the equivalent is a nested std::array, not std::vector.

I'd rather use boost::multi_array or something similar instead of a vector with manually recalculated indices.
boost::multi_array is buggy, on MSVC++ 2010 some operations don't even compile (https://svn.boost.org/trac/boost/ticket/4874).

By the way, why did you change your name? :)
Title: Re: Too many sprites?
Post by: Silvah on April 01, 2012, 10:27:39 pm
Computing indexes is easy. Implementing memory management, an STL interface and value semantics isn't.
Yet the latter is easier for me, because I never can get the former right. I just don't remember what is multiplied by what.

boost::multi_array is buggy, on MSVC++ 2010 some operations don't even compile (https://svn.boost.org/trac/boost/ticket/4874).
Then fix it (you'll make the world a better place! :P), or use different library - I explicitly said "or something similar", didn't I?

By the way, why did you change your name? :)
Since I'm playing the devil's advocate here quite often, I changed it to something that better reflects the reality ;)
Title: Re: Too many sprites?
Post by: Vovosunt on April 02, 2012, 05:52:57 pm
Unless you actually have 10500 DIFFERENT sprites I wouldn't do that.
You should make a tiles array/map only with the tiles that are different, then draw those tiles by moving and then rendering, not by actually making lots of sprites.

I have 7500 tiles and I'm only using 24 sprites  :P