My problem is simple, my FPS count is around 30 or less when drawing around 1000 sprites and even when drawing little as 40 or less sprites I can't get it to raise from 50 (using 60 as a maximum) no matter how much I optimize, the problem seems to get worse when I use many textures.
The entire code for the issue is a bunch of classes and files, so I doubt I could post a minimal example of it that could be analyzable in an easy way. I'll just post the main function and explain what all the objects do.
const int num = 10;
const unsigned radius = 25;
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "Bullet Testing");
sf::Event event;
sf::Time FrameTime = sf::seconds(1.f);
sf::Time T = sf::seconds(1.5);
bool check = false;
TextureHolder Hold;
Hold.setBasicTextures();
///What the name says.
unsigned n = 0;
BulletPlacer Put(num, num);
///Quantity as first parameter and bullets to be used as second.
BulletPlacer Put2(num, num);
BulletPlacer Put3(num, num);
BulletPlacer Put4(num, num);
Put.setBulletProperties(Hold, sf::Color(255, 0, 0, 255), sf::Vector2f(200.f, 100.f),1.f, 1);
/// TextureHolder, Color, Position, Speed, and Type (to know which texture to use).
Put2.setBulletProperties(Hold, sf::Color(0, 255, 0, 255), sf::Vector2f(400.f, 300.f),1.5, 7);
Put3.setBulletProperties(Hold, sf::Color(0, 0, 255, 255), sf::Vector2f(600.f, 100.f),1.f, 2);
Put4.setBulletProperties(Hold, sf::Color(250, 50, 120, 255), sf::Vector2f(400.f, 400.f),1.f, 3);
Put.ShotCircleCalculate(num, radius);
///Amount of bullets to be used and radius of the circle.
Put2.ShotCircleCalculate(num, radius);
Put3.ShotCircleCalculate(num, radius);
Put4.ShotCircleCalculate(num, radius);
Put.Bit = Put.ShotList.begin();
Put2.Bit = Put2.ShotList.begin();
Put3.Bit = Put3.ShotList.begin();
Put4.Bit = Put4.ShotList.begin();
std::list<Bullet>::iterator C = Put.Bit;
std::list<Bullet>::iterator D = Put2.Bit;
std::list<Bullet>::iterator E = Put3.Bit;
std::list<Bullet>::iterator F = Put4.Bit;
window.setFramerateLimit(60);
sf::Clock Time, FrameCount;
///Clocks for frame counting and controlling when to draw the second BulletPlacer.
while (window.isOpen())
{
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
window.close();
Hold.~TextureHolder();
Put.~BulletPlacer();
Put2.~BulletPlacer();
Put3.~BulletPlacer();
Put4.~BulletPlacer();
}
}
window.clear();
if(FrameCount.getElapsedTime() <= FrameTime)
{ ++n; }
else
{ std::cout << "Frames Per Second: " << n << std::endl; n = 0; FrameCount.restart(); }
Put.CLinearMove();
Put3.CLinearMove();
Put4.CLinearMove();
if(Time.getElapsedTime() >= T)
{ Put2.CLinearMove(); check = true; }
C = Put.ShotList.begin();
D = Put2.ShotList.begin();
E = Put3.ShotList.begin();
F = Put4.ShotList.begin();
for (unsigned i = 0; i < num; ++i)
{ if(C != Put.ShotList.end() && E != Put3.ShotList.end() && F != Put4.ShotList.end())
{ window.draw(*C); ++C; window.draw(*E); ++E; window.draw(*F); ++F; }
else
break;
if (check)
{ if(D != Put2.ShotList.end())
{window.draw(*D); ++D;}
else
break;
}
}
window.display();
}
return 0;
}
BulletPlacer is a container for Bullets (using a std::list for bullet objects), which have many variables and methods to control movement from a contained sprite, it does inherit from drawable, but not from transformable.
TextureHolder is a container for textures and images to be used (then again a std::list for textures and images), BulletPlacer gets a reference to it in order to give the sprites within the bullets something to draw.
What the program does is draw the amount of usable bullets in the BulletPlacer object in a circle, the amount determines angle frequency in the circle, once placed they inmediately start moving linearly based on their given angle. I had a pretty inefficient code at first, then fixed it but the FPS didn't go up at all, it stayed the same. It goes slower the more bullets you put in the BulletPlacer, but even with a small amount there is still a loss of 10 FPS.
I've fixed all I know I can and still have gotten no results in that matter. If this were to be not enough I can provide a minimal code, but I'd rather only do it unless it's truly needed since I would have to compress a lot of code. Thanks in advance for all help I may get.
I haven't started to manage states manually yet, and while I do understand the concept well enough, a code example would help me a lot.
States are more low level tool, they are additional things you want to happen, but often they'll get changed, like sprite, ignores texture passed to it in states and uses it's own.
I don't understand how changing to pointers breaks anything(except adding additional dereferencings here and there). Does bullet class look like something heavy to copy?
#define EE_MCR_AVERAGER_BEGIN(x) sf::Clock EEAV_CLOCK_##x; static sf::Int64 EEAV_MS_##x=0; static int EEAV_FR_##x=0;
#define EE_MCR_AVERAGER_END(x) std::cout<<"Averaging clock("#x"):"<<(EEAV_MS_##x+=EEAV_CLOCK_##x.getElapsedTime().asMicroseconds())/(++EEAV_FR_##x)<<std::endl;
You can measure time between lines by placing begin macro before and end macro after them. Try to find out which part of code uses most time.
Well yes, vertex arrays and single texture sheet performance improvements are, frankly speaking, completely insane.
Laurent said that drawing things with one texture first, then other ect. may improve performance.
I think it's related to these lines but that's borderline too low level for me, I don't know open gl.
Uint64 textureId = states.texture ? states.texture->m_cacheId : 0;
if (textureId != m_cache.lastTextureId)
applyTexture(states.texture);
Last line ends up in gl's bind which (apparenly) is so heavy that creating tilesheets is worthwhile task peformance wise, but this really may not be true.
Also keep in mind size of texture matters(at least in my case). I got almost 2x more time usage with 1024x1024 texture instead of 32x32 one with around 6-9 untransformed vertex arrays, each with 1024 vertices(but still extremely ahead of required time cap).