Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Question about optimizing in SFML  (Read 6441 times)

0 Members and 1 Guest are viewing this topic.

cooldog99

  • Jr. Member
  • **
  • Posts: 95
    • View Profile
    • Perilous Game Studios
Question about optimizing in SFML
« on: June 07, 2011, 10:12:37 pm »
Hey guys. It's been awhile, and if you know us, "XSG Team" you know we have a game out called "Paradox".
unfortunately this is cancelled until further notice due to an increase of lag.

My questions are why is it that our game drops 30 fps when we spawn 5 "zombies".

Zombies are basically a small simple class, with a few int variables and a sprite, NOT IMAGE.

The game DOES do frustrum culling, and currently runs at 40-50+ fps with over 256x256 tiled (64x64 pixel) tiles.

I've tried optimizing like crazy, but to no avail.
We are no C++/SFML masters, so that's why we're reaching out to this awesome community.

We've tried to make a "Stamp" sprite instead of a bunch of sprites, and just have it change image/location each call in a for loop, but that made it WORSE.

I don't get it, the game does NOT draw outside the view window, yet it lags with 5 entities that aren't drawn? The updating is only a for loop that iterates for each entity.

it's not just the entities that cause lag, unfortunately.

Is there any further optimization tricks for SFML you guys can share? (v1.6 currently, 2.0 is too buggy for our taste).

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Question about optimizing in SFML
« Reply #1 on: June 07, 2011, 10:26:52 pm »
Can you show a minimal code example of your rendering? What graphics card do you have? Do the SFML samples work well?
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Question about optimizing in SFML
« Reply #2 on: June 07, 2011, 10:30:09 pm »
There's definitely something wrong in your code if you can draw hundreds of tiles but not 5 zombies.

Quote
2.0 is too buggy for our taste

May I ask what bugs are blocking you? I think 2.0 is already more stable than 1.6.
Laurent Gomila - SFML developer

Hiura

  • SFML Team
  • Hero Member
  • *****
  • Posts: 4321
    • View Profile
    • Email
Question about optimizing in SFML
« Reply #3 on: June 07, 2011, 10:32:20 pm »
There are too many factor involved here to tell you what make your app going so slow. Did you try using some tool to find out where the bottleneck is ? (Like profiling your app.)

Quote
2.0 is too buggy for our taste
What do you mean ? Please help us make it better.  :wink:
SFML / OS X developer

cooldog99

  • Jr. Member
  • **
  • Posts: 95
    • View Profile
    • Perilous Game Studios
Question about optimizing in SFML
« Reply #4 on: June 07, 2011, 10:35:41 pm »
Quote from: "Laurent"
There's definitely something wrong in your code if you can draw hundreds of tiles but not 5 zombies.

Quote
2.0 is too buggy for our taste

May I ask what bugs are blocking you? I think 2.0 is already more stable than 1.6.


Well, me and my other dev-team partner tend to transfer our projects over to each other. and Even though we have the SAME lib, project settings/properties and files, it wont render on his but it does on mine?

As for drawing the tiles, it lags with those as well. Without them it's 150fps, with it's 50.
it only draws the ones I see too. and there is little updating on those, so what's going on?

I can't exactly show the updating code, as it's pretty messy atm.
but I can show you the drawing loops basically.

Code: [Select]

            int ZombieAmountSize = Zombies.size();
            for (int i = 0; i < ZombieAmountSize; ++i)
{
                if (Zombies[i].Alive)
{
float X1 = Zombies[i].Sprite.GetPosition().x;
float Y1 = Zombies[i].Sprite.GetPosition().y;
sf::FloatRect tempRect;
tempRect.Left = X1;
tempRect.Top = Y1;
tempRect.Right = X1 + 64;
tempRect.Bottom = Y1 + 64;

sf::FloatRect tempRect2;

tempRect2 = View.GetRect();
float R = Zombies[i].Sprite.GetColor().r;
float G = Zombies[i].Sprite.GetColor().g;
float B = Zombies[i].Sprite.GetColor().b;
Zombies[i].Sprite.SetColor(sf::Color(R, G, B, Zombies[i].Alpha));
if (tempRect.Intersects(tempRect2))
{
Window->Draw(Zombies[i].Sprite);
}
}
}


Keep in mind, this code is similar to the other drawing ones.
And the updating is really simple as well..

And yes I tried profiling, but I'm not a pro at that either =/

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Question about optimizing in SFML
« Reply #5 on: June 07, 2011, 10:40:18 pm »
Quote
and Even though we have the SAME lib, project settings/properties and files, it wont render on his but it does on mine?

So please make a detailed bug report :)

It's hard to tell what slows down a complete application. If you get better performances by simply commenting the Window->Draw(Zombie) line, then there's nothing you can do. If it doesn't help, there's definitely something to optimize in your own code.
Laurent Gomila - SFML developer

cooldog99

  • Jr. Member
  • **
  • Posts: 95
    • View Profile
    • Perilous Game Studios
Question about optimizing in SFML
« Reply #6 on: June 07, 2011, 11:01:17 pm »
Quote from: "Laurent"
Quote
and Even though we have the SAME lib, project settings/properties and files, it wont render on his but it does on mine?

So please make a detailed bug report :)

It's hard to tell what slows down a complete application. If you get better performances by simply commenting the Window->Draw(Zombie) line, then there's nothing you can do. If it doesn't help, there's definitely something to optimize in your own code.


How would I make a detailed bug report? o.O
Yeah, I know there's no real way of determining the problem. Maybe I can give more insight on our program.

the thing is, it only runs the window->Draw(zombies) code when the zombie is in view of player...

here's our basic structure of program.. VERY BASIC VIEW

main loop
App clear
game state switch loop
case game { game.sendvars(&App); game.update(); game.draw() }
App display

Game Update
for (zombies) //for each zombie in zombies (Not real code, lul)
check if collision with player/world objects/ world items.
move/hurt zombie accordingly.

Game Draw
for (zombies)
if zombies are in bounds of view rect, draw them

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Question about optimizing in SFML
« Reply #7 on: June 07, 2011, 11:13:16 pm »
Quote
check if collision with player/world objects/ world items

What about this one? It looks quite heavy in terms of computation.

Have you tried to comment the line that draws zombies and see if it makes your app run faster?

More generally, you should gradually disable parts of your code to see which one is eating all the performances -- instead of trying to find the guilty line directly, just by looking at the code.
Laurent Gomila - SFML developer

cooldog99

  • Jr. Member
  • **
  • Posts: 95
    • View Profile
    • Perilous Game Studios
Question about optimizing in SFML
« Reply #8 on: June 07, 2011, 11:25:27 pm »
Quote from: "Laurent"
Quote
check if collision with player/world objects/ world items

What about this one? It looks quite heavy in terms of computation.

Have you tried to comment the line that draws zombies and see if it makes your app run faster?

More generally, you should gradually disable parts of your code to see which one is eating all the performances -- instead of trying to find the guilty line directly, just by looking at the code.


Here it is, with minor lines taken out (minimal)
remember we're not C++ masters, so if we made a "no-no" please tell us o.o


Code: [Select]

void Zombie::Update()
{
    int BulletSizeMax2 = mainGame.bullets.size();
    for (int j = 0; j < BulletSizeMax2; ++j)
                {
                    if (mainGame.bullets[j].Alive)
                        if (PixelCollision(Sprite,mainGame.bullets[j].BulletSprite,200))
                            {
                                if (Health > 0)
                                    {
                                        //hurt/move zombie.
                                        Sprite.SetPosition(ZomX, ZomY);
                                       //add new blood effect.
                                        mainGame.BloodSplatter.push_back(blood);
                                        break;
                                    }

                            }
                }

    if (Health <= 0 && Alive)
    {
        CanHurtPlayer = false;
        if (Alpha > 0 && Alive)
            Alpha -= 10;

        if (Alpha <= 0 && Alive)
        {
            Alive = false;
        }

    }

    if (Alive)
    {

            for (std::list<Item>::iterator lolk = mainGame.WorldItems.begin(); lolk != mainGame.WorldItems.end(); ++lolk)
            {

                if ((*lolk).UniqueID == 18)
                {
                        //check if item can interact with zombie
                        if (PixelCollision(Sprite, (*lolk).Sprite, 50) && CanHurtPlayer)
                        {
                            //do stuff, then delete item.
                            mainGame.WorldItems.erase(lolk);
                            break;
                        }
                }
            }
            //move zombie

            //check for collision with player
            if (PixelCollision(mainGame.Sprite, Sprite, 50) && CanHurtPlayer)
                {
                    //hurt player
                }
            int WorldObjectsSizeMax = mainGame.WorldObjects.size();
            for (int l = 0; l < WorldObjectsSizeMax; ++l)
            {
                  //loop through world objects, and have zombie interact with them.

            }
 //move zombie finally
}
}


all the above code is called within zombie class
and the code that calls it

Code: [Select]

int ZombieSizeMax = Zombies.size();
for (int i = 0; i < ZombieSizeMax; ++i)
{
                    Zombies[i].Update();
                }



Does this help?

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
Question about optimizing in SFML
« Reply #9 on: June 07, 2011, 11:44:22 pm »
Code: [Select]
PixelCollision(Sprite,mainGame.bullets[j].BulletSprite,200))

PixelCollision?

You're not really checking every single pixel, are you?

If you are, that has to be the problem.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Question about optimizing in SFML
« Reply #10 on: June 07, 2011, 11:44:23 pm »
I'm not sure you understand what I mean.

My point is that you should do tests, which consist of disabling parts of the code (drawing, collision detection, etc.) then run the game -- in order to identify the part of your code that eats all the performances. There's no point looking at your whole code if only a very small part of it is relevant -- and you can find it easily with tests.

By the way,
Quote
How would I make a detailed bug report? o.O

Open a new topic and describe the bug, with as many useful information as you can about it.
Laurent Gomila - SFML developer

cooldog99

  • Jr. Member
  • **
  • Posts: 95
    • View Profile
    • Perilous Game Studios
Question about optimizing in SFML
« Reply #11 on: June 07, 2011, 11:46:44 pm »
Quote from: "Disch"
Code: [Select]
PixelCollision(Sprite,mainGame.bullets[j].BulletSprite,200))

PixelCollision?

You're not really checking every single pixel, are you?

If you are, that has to be the problem.


Is it really that CPU consuming??

Quote from: "Laurent"
I'm not sure you understand what I mean.

My point is that you should do tests, which consist of disabling parts of the code (drawing, collision detection, etc.) then run the game -- in order to identify the part of your code that eats all the performances. There's no point looking at your whole code if only a very small part of it is relevant -- and you can find it easily with tests.

By the way,
Quote
How would I make a detailed bug report? o.O

Open a new topic and describe the bug, with as many useful information as you can about it.


I understand, but I was trying to see if we screwed up, and someone with more C++ knowledge could help, we'll definitely do tests.

Btw, just a quick thanks to all of you who help us ;)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Question about optimizing in SFML
« Reply #12 on: June 07, 2011, 11:49:46 pm »
Quote
Is it really that CPU consuming??

Depends on how you implement it ;)

Quote
I understand, but I was trying to see if we screwed up, and someone with more C++ knowledge could help, we'll definitely do tests.

We're not gods or compilers. It's better for everyone if you can reduce the amount of code to examine before posting it ;)
Laurent Gomila - SFML developer

Disch

  • Full Member
  • ***
  • Posts: 220
    • View Profile
Question about optimizing in SFML
« Reply #13 on: June 08, 2011, 12:00:55 am »
Quote
Is it really that CPU consuming??


It can be very consuming.  Espeically if you're getting the pixel data from the video card for every check.

Every time you get pixels from the video card it has to move from VRAM to CPU RAM.  In addition to being a copy of the whole image (which is a big copy), it has to move along the bus which is also very slow.  What's more, while the video card is spending it's time getting pixel data, it can't do things it would otherwise be doing, like rendering stuff.


But all that aside, doing pixel-by-pixel collision is a rather absurd and overly complicated way to do this anyway.  Why not a simple bounding box?

cooldog99

  • Jr. Member
  • **
  • Posts: 95
    • View Profile
    • Perilous Game Studios
Question about optimizing in SFML
« Reply #14 on: June 08, 2011, 12:03:44 am »
Quote from: "Disch"
Quote
Is it really that CPU consuming??


It can be very consuming.  Espeically if you're getting the pixel data from the video card for every check.

Every time you get pixels from the video card it has to move from VRAM to CPU RAM.  In addition to being a copy of the whole image (which is a big copy), it has to move along the bus which is also very slow.  What's more, while the video card is spending it's time getting pixel data, it can't do things it would otherwise be doing, like rendering stuff.


But all that aside, doing pixel-by-pixel collision is a rather absurd and overly complicated way to do this anyway.  Why not a simple bounding box?


Erm, To be honest, I'm not even sure why most of them are pixel collision...I've reverted most back to rectangular and it helps alot.

Thanks for pointing that out ^_^