-
Notifications
You must be signed in to change notification settings - Fork 27
Sprite Batch
A sprite batch class that allows internal storage of sprites that are automatically batched into a single draw call.
It stores multiple sprites (however many you want!) and each one can be modified in the same way as a normal sf::Sprite with the addition of an index that references which sprite you are modifying.
During its update phase, it converts all sprites into triangles and builds a single vertex array of those triangles.
It automatically executes the update phase when it is drawn but only if an update is required (something has changed).
Only one texture (per Sprite Batch) can be used as it is a single draw call. However, as normal, each sprite can have its own texture rectangle.
Note that Sprite Batch is a drawable that stores internal sprites and allows standard sf::Sprite access them and is able to make some optimizations and extra functionality due to storing them internally. If what you are looking for is just an automatic batcher for sprites that you use externally, you can use this Simple Sprite Batcher
-
sw::SpriteBatch spriteBatch;
creates a Sprite Batch
This class inherits from sf::Drawable so it is drawn in the same way as all SFML drawables:
window.draw(spriteBatch);
where window is an sf::RenderWindow.
Note: actually, window could be any sf::RenderTarget.
All exceptions thrown by Sprite Batch are of type selbaward::Exception (or sw::Exception if you're using the shortcut), which inherits from std::exception.
-
remove
can throw an exception if there are no sprites or if the index is out-of-range. -
Specifying an out-of-range index can throw an exception.
-
setTexture(texture)
sets the Sprite Batch's texture used for all sprites. The texture here is an [sf::Texture] and if it is omitted, the texture is set to null. -
setNumberOfSprites(numberOfSprites)
sets the number of sprites in the batch. The numberOfSprites parameter is of type std::size_t. -
insertSprite(insertIndex, numberOfSprites, sprite)
inserts a single sprite or multiple identical sprites before the one at insertIndex. Each sprite inserted is a copy of sprite, which is of type sf::Sprite. If sprite is omitted, a default sf::Sprite is inserted. If numberOfSprites is omitted, a single sprite is inserted.
Returns the total number of sprites stored after the insert.
-
addSprite(numberOfSprites, sprite)
adds a single sprite or multiple identical sprites after the currently stores sprites. Each sprite inserted is a copy of sprite, which is of type sf::Sprite. If sprite is omitted, a default sf::Sprite is inserted. If numberOfSprites is omitted, a single sprite is inserted.
Returns the total number of sprites stored after the add.
-
removeSprite(removeIndex, numberOfSprites)
removes a single sprite or multiple sprites starting from the removeIndex. If removeIndex is omitted, the sprite(s) are removed from the back/end.
Returns the total number of sprites stored after the removal.
-
batchSprites(sprites)
copies all sprites into the internally stored sprites. The number of sprites will be changed to match the number of sprites passed. Note that sprites can either be a vector of sf::Sprites or a vector of pointers to sf::Sprites. -
updateSprite(index, sprite)
updates a sprite from sprite, which is a standard sf::Sprite. The index is the sprite index.
Sprite Batch can automatically order the sprites during the updates phase.
You can provide either an ordering function (a predicate: a sorting function that return a boolean) or a vector on indices (a list of sprite indices that specify the order that they should be drawn).
-
setOrderingFunction(orderFunction)
sets the function used for ordering the sprites during the update phase. The orderFunction should take two pointers to sf::Sprites as parameters and return a boolean. Note that this automatically clears any manual order previously given. If orderFunction is omitted, the ordering function is cleared but any manual order that may be present is not cleared.
The exact type of the function should be:
const std::function<bool(const sf::Sprite* a, const sf::Sprite* b)>
-
setOrder(indices)
sets the order of the sprites. This overrides the ordering function; if it is set, the ordering function is no longer used. However, the ordering function is not cleared. If indices is omitted, the manual order is cleared and the ordering function is re-instated, if available. The indices is a vector of std::size_t, representing the index of each sprite in the order to be drawn. If any indices are missing for sprites that exist, those missing will be added to the end of the order in numerical index order. -
clearAllOrdering()
clears all ordering including both the ordering function and the manual order.
All the usual sf::Sprite methods are available for each sprite, just required an additional index as the first parameter.
-
setPosition(index, position)
sets the position of index sprite. -
setOrigin(index, origin)
sets the origin of index sprite. -
setRotation(index, rotation)
sets the rotation of index sprite. -
setScale(index, scale)
sets the scale of index sprite. Scale can either be a 2-dimensional sf::Vector2f or a single float that is applied to both components (x and y). -
setTextureRect(index, textureRect)
sets the textureRect of index sprite. -
setColor(index, color)
sets the color of index sprite.
-
move(index, offset)
moves the position of index sprite by offset. -
rotate(index, angle)
rotates index sprite by angle. Equivalent to setting its rotation to its current value plus angle. -
scale(index, factor)
scales the current scale factor by factor. This multiplies the current scale components by factor. If factor is a 2-dimensional sf::Vector2f then each component is multiplied separately otherwise (if factor is a float), both components are multiplied by the same value: factor.
These are the usual sf::Sprite getters.
-
getPosition(index)
gets the position of index sprite. -
getOrigin(index)
gets the origin of index sprite. -
getRotation(index)
gets the rotation of index sprite. -
getScale(index)
gets the rotation of index sprite. Note that this is an sf::Vector2f regardless of the type used to set the scale. -
getTextureRect(index)
gets the texture rectangle of index sprite. -
getColor(index)
gets the colour of index sprite. -
getLocalBounds(index)
gets the local bounds of index sprite. -
getGlobalBounds(index)
gets the global bounds of index sprite. -
getTransform(index)
gets the transform or index sprite. -
getInverseTransform(index)
gets the inverse transform of index sprite.
These take no index and apply relative modifications to all sprites.
-
move(offset)
move the position of all sprites by offset. -
rotate(angle)
rotates all sprites by angle. Equivalent to setting their rotations to their current values plus angle. -
scale(factor)
scales all sprites' scale factor by factor. This multiplies the current scale components by factor. If factor is a 2-dimensional sf::Vector2f then each component is multiplied separately otherwise (if factor is a float), both components are multiplied by the same value: factor.
-
getNumberOfSprites()
gets the current number of internal sprites. -
getSprite(index)
returns a copy of index sprite. This is an sf::Sprite. Note that using the operator [] on Sprite Batch also returns a copy in the same way.
#include <SelbaWard.hpp>
#include <SFML/Graphics.hpp>
int main()
{
sf::Texture texture;
if (!texture.loadFromFile("resources/Card Face - SFML.png"))
return EXIT_FAILURE;
sf::RenderWindow window(sf::VideoMode(150u, 200u), "Sprite Batch simple example");
sw::SpriteBatch spriteBatch;
spriteBatch.setTexture(texture);
spriteBatch.setNumberOfSprites(165u); // 165 sprites
const sf::Vector2i spriteSize{ 10, 10 };
for (std::size_t i{ 0u }; i < spriteBatch.getNumberOfSprites(); ++i)
{
spriteBatch.setTextureRect(i, { { (static_cast<int>(i) % 11) * spriteSize.x, (static_cast<int>(i) / 11) * spriteSize.y }, spriteSize });
spriteBatch.setPosition(i, sf::Vector2f(spriteBatch.getTextureRect(i).getPosition()) * 1.1f);
}
while (window.isOpen())
{
sf::Event event; while (window.pollEvent(event)) if (event.type == sf::Event::Closed) window.close();
window.clear();
window.draw(spriteBatch); // a single draw call
window.display();
}
}
The code above displays something similar to:
#include <SelbaWard.hpp>
#include <SFML/Graphics.hpp>
int main()
{
sf::Texture texture;
if (!texture.loadFromFile("resources/Card Face - SFML.png"))
return EXIT_FAILURE;
sf::RenderWindow window(sf::VideoMode(150u, 200u), "Sprite Batch simple example");
std::vector<sf::Sprite> sprites(165u); // 165 sprites
const sf::Vector2i spriteSize{ 10, 10 };
for (std::size_t i{ 0u }; i < sprites.size(); ++i)
{
sprites[i].setTextureRect({ { (static_cast<int>(i) % 11) * spriteSize.x, (static_cast<int>(i) / 11) * spriteSize.y }, spriteSize });
sprites[i].setPosition(sf::Vector2f(sprites[i].getTextureRect().getPosition()) * 1.1f);
}
sw::SpriteBatch spriteBatch;
spriteBatch.setTexture(texture);
spriteBatch.batchSprites(sprites); // batches all 165 sprites
while (window.isOpen())
{
sf::Event event; while (window.pollEvent(event)) if (event.type == sf::Event::Closed) window.close();
window.clear();
window.draw(spriteBatch); // a single draw call
window.display();
}
}
The code above displays something similar to:
Note that both Simple Example and Simple Example 2 both give the same result but do it in different ways:
Simple Example
uses the provided methods to modify the internal sprites directly.Simple Example 2
creates a vector of sf::Sprites manually and then passes them to Sprite Batch, which automatically copies them and updates.
(Sprite Batch v1.0)