So, yesterday I thought to myself, ooh, having a sprite batch of sorts in SFML would be very nice, so I started on one, and in my ignorance failed to check the wiki/forum for results. Which... resulted in this:
https://github.com/dabbertorres/SwiftSpriteBatchFor those who don't know what a SpriteBatch is or does, it is essentially a container of vertices that all use one texture. So, rather than having 1 draw call per sf::Sprite, it allows you to have only 1 draw call for (almost) any number of vertices, or swift::Sprites, which turns out to be much faster.
It works very much like the
sprite batch on the wiki, but rather than working based off indices, it uses classes.
It consists of 2 classes, a SpriteBatch class, and a Sprite Class.
Here's the example from the Github page:
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <iostream>
#include "SpriteBatch.hpp"
#include "Sprite.hpp"
int main(int argc, char **argv)
{
sf::RenderWindow window;
window.create({800, 600, 32}, "SFML");
sf::Texture texture;
if(!texture.loadFromFile("ftlGrizzly.png"))
{
std::cerr << "error loading texture\n";
}
swift::SpriteBatch batch(texture, 2);
swift::Sprite spriteOne(batch);
spriteOne.setOrigin({spriteOne.getLocalBounds().width / 2, spriteOne.getLocalBounds().height / 2});
spriteOne.setScale({2, 2});
spriteOne.setPosition({400, 400});
spriteOne.scale({0.5, 0.5});
swift::Sprite spriteTwo(batch);
spriteTwo.setPosition({400, 200});
while(window.isOpen())
{
sf::Event event;
while(window.pollEvent(event))
{
switch(event.type)
{
case sf::Event::Closed:
window.close();
break;
default:
break;
}
}
window.clear();
window.draw(batch);
window.display();
}
return 0;
}
The constructor of the SpriteBatch takes a sf::Texture, and the number of Sprites you would like to have. I went with locking the size because Sprites work with pointers, and if the memory needs to be relocated due to resizing, that invalidates pointers, which causes a whole bunch of issues.
There are 2 constructors for Sprite, both take the batch you want to add the Sprite to, and 1 takes a sf::IntRect to set as the texture rectangle.
Upon destruction of a Sprite, the vertices the Sprite used are kept, but all with position (0, 0) and color (0, 0, 0, 0). This effectively makes it non-visible, without invalidating pointers.
I tried to keep similar (if not the exact same) behavior as an sf::Sprite in regards to functions to call on swift::Sprite. In my testing, it seems to act the same, so here's to hoping it is truly that way. Hehe.
I'd love any feedback anyone has and am happy to answer any questions anyone may have!
EDIT: Should add that it uses C++11.