SFML community forums

Help => General => Topic started by: SuperV1234 on June 13, 2010, 10:21:43 pm

Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 13, 2010, 10:21:43 pm
Full source code: http://www.mediafire.com/?wgimixyjtbt


---


I'm making a bullet hell game (danmaku) using SFML.NET and C#.
My source of inspiration is Danmakufu, a game where you can create your bullet patterns, share them, play them, etc.


In Danmakufu I can easily spawn 300 bullets every frame staying at 58-60FPS all the time.
In my own game, when I spawn 300 bullets every 3 frames, the game becomes unplayable due to slowdown.


The biggest difference between my game and Danmakufu is that my game's resolution is 1024x768, Danmakufu is 800x600. But can that make an enormous difference?


---


My code for bullets is this:


Code: [Select]
public class Entity
    {
        public float X { get; set; }
        public float Y { get; set; }
        public Game Game { get; set; }
        public bool Alive { get; set; }
        public Sprite Sprite { get; set; }


        public Entity(Game game)
        {
            Game = game;
            Alive = true;
        }


        public virtual void Update()
        {
            Sprite.Position = new Vector2(X, Y);
        }
        public virtual void Draw()
        {
            Game.RenderWindow.Draw(Sprite);
        }
        public virtual void Destroy()
        {
            Alive = false;
        }
    }
Entity is the basic class for any object in the game; you can draw and update entities.


Code: [Select]
public class Bullet : Entity
    {
        private float _angle;
        public float Angle
        {
            set { _angle = Data.ANormalize(Data.ARadians(value)); }
            get { return Data.ADegrees(_angle); }
        }
        public float Speed { get; set; }


        public Bullet(Game game) : base(game)
        {
            Game.BulletManager.Entities.Add(this);
        }


        public override void Draw()
        {
            base.Draw();
        }
        public override void Update()
        {
            base.Update();


            X = X + Speed * (float)Math.Cos(_angle);
            Y = Y + Speed * (float)Math.Sin(_angle);
            Sprite.Rotation = 360-Angle;


            if(Game.Playfield.IsInPlayfield(X, Y) == false)
            {
                Destroy();
            }
        }
        public override void Destroy()
        {
            base.Destroy();
 
            Game.BulletManager.Entities.Remove(this);        
        }
    }
The Bullet class inherits from Entity. When it is spawned, it is added in the Game.BulletManager.Entities list. When it is deleted, it is removed from the same list.
If you're curious about the stuff happening in the "Angle" property, here are the related methods:
Code: [Select]
public static float ARadians(float angle)
        {
            return angle * 3.14f / 180f;
        }
        public static float ADegrees(float angle)
        {
            return angle * 180f / 3.14f;
        }
        public static float ANormalize(float angle)
        {
            if (angle > 360)
            {
                angle = angle - (360 * Convert.ToInt32((angle / 360)));
            }


            if (angle < 0)
            {
                angle = angle + (360 * Convert.ToInt32((angle / 360)));
            }


            return angle;
        }
---


Here's the code for the Manager class and the Game class:


Code: [Select]
public class Manager
    {
        public List<Entity> Entities { get; set; }


        public Manager()
        {
            Entities = new List<Entity>();
        }


        public void Update()
        {
            for (int index = 0; index < Entities.Count; index++)
            {
                Entity entity = Entities[index];
                if (entity.Alive)
                {
                    entity.Update();
                }
            }
        }


        public void Draw()
        {
            for (int index = 0; index < Entities.Count; index++)
            {
                Entity entity = Entities[index];
                if (entity.Alive)
                {
                    entity.Draw();
                }
            }
        }
    }
Pretty straightforward. Updating a manager updates all of its entities; drawing a manager draws all of its entities.


Code: [Select]
public class Game
    {
        public bool Running { get; set; }
        public RenderWindow RenderWindow { get; set; }
        public Manager BulletManager { get; set; }
        public Playfield Playfield { get; set; }
        public int Frame { get; set; }


        //DEBUG---
        public int DebugFrame { get; set; }
        private int kk = 0;
        private int ff = 1;
        private bool kkb = true;
        Image image = new Image(Environment.CurrentDirectory + @"/Data/Images/b_pellet.png");
        //--------


        public Game()
        {
            Running = true;
            RenderWindow = new RenderWindow(new VideoMode(1024,768), "Bullet Hell Test");
            RenderWindow.UseVerticalSync(true);
            RenderWindow.Show(true);
            BulletManager = new Manager();
            Playfield = new Playfield(this, 250, 50, 774, 718) {Offset = 25};
            Frame = 0;
           
            Debug();


            Run();
        }


        public void Run()
        {
            while(Running)
            {
                Update();
                Draw();
            }
        }


        public void Update()
        {
            BulletManager.Update();


            if(DebugFrame == 10)
            {
                Debug();
                DebugFrame = 0;
            }


            DebugFrame++;
            Frame++;


            Console.WriteLine("{0} --- {1}", Convert.ToInt32(RenderWindow.GetFrameTime() * 1000), BulletManager.Entities.Count);
        }
        public void Draw()
        {
            RenderWindow.Clear(Color.White);
            Playfield.DrawInside();
            BulletManager.Draw();
            Playfield.DrawOutside();
            RenderWindow.Display();
        }


        //--------------------------------------------------------------------------------------------


        public Bullet CreateBullet()
        {
            return new Bullet(this);
        }


        //--------------------------------------------------------------------------------------------


        public void Debug()
        {
            float step = 300;    


            for(int i = 0; i < step; i++)
            {
                Bullet temp = new Bullet(this);
                   
                        temp.Angle = (i*(360/step));
                        temp.Speed = 5f;
                        temp.Sprite = new Sprite(image);
                        temp.X = Playfield.GetCenter().X;
                        temp.Y = Playfield.GetCenter().Y;
            }


            if (kk < 120)
            {
                kk = kk + 5;
            }
            else
            {
                kk = 120;
            }


            ff = ff + 22;
        }
    }
This one is pretty straightforward too, ignoring the debug variables that I used before to create cool-looking patterns.
Update calls the "Debug" method every 10 frames, which spawns bullets.
Bullets aren't spawned by recycling, but instead by creating "new" bullets. I've chosen this because I haven't noticed big performance improvements recycling bullets in the past.
Draw draws bullets and the playfield, which creates the usual "shoot 'em up" borders around the playing screen.


---


So, I've created this thread to kindly ask you what am I doing wrong; why can't my game spawn the same amount of bullets as Danmakufu without slowing down?


Is it a SFML.NET limitation?

---


I have also another problem:


Game.BulletManager.Entities.Remove(this); --- this line in the Bullet -> Destroy method makes a single bullet move in a strange way while uncommented.


I think this is because the for loops skips or makes an unnecessary additional cycle.
How can I prevent this?


---

Thanks.
Title: Bullet Hell performance and optimization problems
Post by: Laurent on June 13, 2010, 10:46:42 pm
It's hard to tell from your real code. It would be easier if you could test a minimal application which simply draws as many sprites as in your game, to see if it's a performances problem. If it runs fine then there's probably something wrong, and you should try to find out which part of the code is guilty by commenting stuff, testing etc.
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 13, 2010, 10:51:41 pm
Before I do that, is there any effective way to understand if it's either the Draw or the Update loop which causes the biggest slowdown?
Title: Bullet Hell performance and optimization problems
Post by: Laurent on June 13, 2010, 10:52:30 pm
Disable one, then the other, and compare performances.
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 13, 2010, 11:03:21 pm
Quote from: "Laurent"
Disable one, then the other, and compare performances.


If I disable Update then bullets won't be spawned, and even if I make it happen, they won't reach the end of the screen and be deleted.

I need some kind of timer that tells me how much time a method required to fully run. Is there anything like that?
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 13, 2010, 11:15:20 pm
Nevermind, I've measured the time using TimeSpans and DateTimes.

Update method takes 1 ms.
Draw method takes 15~18 ms.
Title: Bullet Hell performance and optimization problems
Post by: Laurent on June 13, 2010, 11:19:21 pm
I guess that Visual Studio has a good profiler for C# (it has one for C++). But maybe it is available only in the professional edition.

Anyway, if Draw is the guilty one, we're back to my first anwser: write a small app that only draws stuff, to see if it's related to your code or to your configuration.
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 13, 2010, 11:48:32 pm
Did a quick test: around 5000 8x8 sprites slow down the application.
Title: Bullet Hell performance and optimization problems
Post by: Laurent on June 14, 2010, 12:12:11 am
What graphics card do you have? On which OS ? Are your drivers up-to-date?
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 14, 2010, 09:55:31 am
I have an nVidia GTX 275, my OS is Windows 7, my drivers are up-to-date.
Title: Bullet Hell performance and optimization problems
Post by: Spodi on June 14, 2010, 10:39:46 am
Running the attached program, I get a constant spit-out of about: "13 ---- 2000". Runs nice and smooth.

Core 2 Duo E6750
nVidia 8800 GTS 320 MB
Windows 7 (x86-64)

You could try updating to the latest version of SFML since it looks like you are using a build from 4/4/2010. What I namely have in mind is the commit made on 4/24, where Laurent added the calling conventions for the .NET bindings, which was really killing performance with native assembly calls in some rare cases due to some expensive exception checking stuff that could come with .NET (I forget the name of that all - prefer to wipe that bad experience from my memory).

Finally, you can also try building for release and/or running the .exe directly, not through Visual Studio, just in case the debugger is doing something funky.
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 14, 2010, 10:49:06 am
Quote from: "Spodi"
Running the attached program, I get a constant spit-out of about: "13 ---- 2000". Runs nice and smooth.

Core 2 Duo E6750
nVidia 8800 GTS 320 MB
Windows 7 (x86-64)

You could try updating to the latest version of SFML since it looks like you are using a build from 4/4/2010. What I namely have in mind is the commit made on 4/24, where Laurent added the calling conventions for the .NET bindings, which was really killing performance with native assembly calls in some rare cases due to some expensive exception checking stuff that could come with .NET (I forget the name of that all - prefer to wipe that bad experience from my memory).

Finally, you can also try building for release and/or running the .exe directly, not through Visual Studio, just in case the debugger is doing something funky.


You mean SFML 2.0?

Anyway I'm not using the debugger since it decreases the performance a lot :)
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 14, 2010, 10:53:43 am
Using a profiler I noticed that SFML.Graphic.Sprite instances do not get cleaned up. Running a program at 60FPS for a long time can make 60.000, 70.000 Sprite instances. How can I prevent that?
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 14, 2010, 02:46:25 pm
(http://img229.imageshack.us/img229/1383/profilerinfo1.png)

Here is some useful profiler info.

The bullets are generated by this code, that is executed every frame.

Code: [Select]
public Bullet CreateBullet()
        {
            if (BulletManager.Recycle.Count > 0)
            {
                Bullet temp = (Bullet) BulletManager.Recycle[0];
                BulletManager.Recycle.RemoveAt(0);
                BulletManager.Entities.Add(temp);
                return temp;
            }

            return new Bullet(this);
        }

        public void Debug()
        {
            float step = 6;    

            for(int i = 0; i < step; i++)
            {
                for (int n = 1; n < 6; n++)
                {
                    Bullet temp = CreateBullet();

                    temp.Angle = (i * (360 / step)) + kk * n;
                    temp.Speed = 4f - (n / 2.5f);
                    temp.Sprite = new Sprite(image);
                    temp.X = Playfield.GetCenter().X;
                    temp.Y = Playfield.GetCenter().Y - 120;
                }
            }

            kk = kk + 22;
        }


Things I noticed from the profiler:
1) Recycling bullets works: the instance number of the bullets is always the same.
2) SFML Sprites instances keep growing and growing! Am I creating new instances? Isn't the garbage collector supposed to delete them?
3) Even if SFML Sprites keep growing, that's not the problem which causes low FPS, because I can spawn 5000 bullets at the same time, then stop spawning bullets, and it will still lag. However I want to look into this problem and fix it.
Title: Bullet Hell performance and optimization problems
Post by: Laurent on June 14, 2010, 02:54:21 pm
Quote
Code: [Select]
return new Bullet(this);

Aren't you supposed to store this one in BulletManager.Entities?
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 14, 2010, 08:15:24 pm
Quote from: "Laurent"
Quote
Code: [Select]
return new Bullet(this);

Aren't you supposed to store this one in BulletManager.Entities?


The bullet is stored in BulletManager.Entities thanks to its constructor.
 
Code: [Select]
public Bullet(Game game) : base(game)
        {
            Game.BulletManager.Entities.Add(this);
        }
Title: Bullet Hell performance and optimization problems
Post by: Spodi on June 14, 2010, 09:19:19 pm
Well if my 8800 GTS is running it just fine and your GTX 275 is not, its most likely not a problem with your code logic. Its not like my CPU is exactly powerful anymore, either.

For the sprites, you will definitely want to start pooling them instead of creating a new instance per each bullet. You probably can even just use a different Sprite instance for each bullet graphic, not each bullet. Or use one single global Sprite instance and just set it up before each time you draw it.
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 14, 2010, 09:25:45 pm
Quote from: "Spodi"
Well if my 8800 GTS is running it just fine and your GTX 275 is not, its most likely not a problem with your code logic. Its not like my CPU is exactly powerful anymore, either.

For the sprites, you will definitely want to start pooling them instead of creating a new instance per each bullet. You probably can even just use a different Sprite instance for each bullet graphic, not each bullet. Or use one single global Sprite instance and just set it up before each time you draw it.


It runs fine on my GTX275 with less than 5000 bullets. The source code I posted before works perfectly. It's just if I add more than 4800-4900 bullets.

I can't use a single Sprite instance. Maybe you meant a single Image instance?
Title: Bullet Hell performance and optimization problems
Post by: Ashenwraith on June 15, 2010, 05:47:56 am
You might not be able to use a single sprite, but you should be able to use a single constant instance of bounding boxes for each bullet sprite identical.

In a lot of bullet hell games the bullets come out in patterns and cannot be altered

Because of this you can do a lot of pre-guessing illusion work for example in growing rings or wave patterns of what the collision/position should be and even the graphicss.

Another example: streams/blocks of bullets can be built into rectangles for collison.

Want to go even further?

Cull collision detection for enemy bullets based on their ability to hit the character. IE, many bullets will be out of range and impossible to hit, especially if you are already surrounding the character with bullets.

Move offscreen bullets instead of destroying/creating them.

Perhaps even flickering your bullet sprites and drawing them every other frame might help too?

Make your bullets out of an sf::Shape?
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 15, 2010, 10:01:46 pm
Latest source code: http://www.mediafire.com/?ih2kojte1uo

I think I found the problem:
Code: [Select]
public virtual void Tick()
        {
            Sprite.Position = new Vector2(X, Y);
           // Game.RenderWindow.Draw(Sprite);
        }


By commenting the Draw instruction, the game handles 20000 bullets without slowdowns.

Is it a SFML limitation, or is there any chance I'm doing something wrong drawing the sprite?
Title: Bullet Hell performance and optimization problems
Post by: Ashenwraith on June 15, 2010, 11:16:30 pm
Well looking at the code above should you really be creating a new vector every time you change the position and draw the sprite?

If the problem is drawing speed you could try saving your images in dds and see if that helps, but I'd look closer at your data creation/management or any unnecessary loops.
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 15, 2010, 11:28:56 pm
Quote from: "Ashenwraith"
Well looking at the code above should you really be creating a new vector every time you change the position and draw the sprite?

If the problem is drawing speed you could try saving your images in dds and see if that helps, but I'd look closer at your data creation/management or any unnecessary loops.


X and Y are read-only in Vector2.

Why should saving imgage in dds help? I've never used dds files before.
Title: Bullet Hell performance and optimization problems
Post by: Ashenwraith on June 16, 2010, 02:17:13 am
Quote from: "SuperV1234"
Quote from: "Ashenwraith"
Well looking at the code above should you really be creating a new vector every time you change the position and draw the sprite?

If the problem is drawing speed you could try saving your images in dds and see if that helps, but I'd look closer at your data creation/management or any unnecessary loops.


X and Y are read-only in Vector2.

Why should saving imgage in dds help? I've never used dds files before.


I know it's read only because every Sprite contains an internal copy so you don't need a new Vector each time.

You can use one sf::Vector2f and use Sprite.GetPosition() to set it, transform, and then use Sprite.SetPosition(sf::Vector2f); And just repeat over and over, no?

I think the problem is there are all of these useless vectors floating around doing nothing every time you move a sprite.

DDS goes directly into video memory without any decompression/work and is much smaller so any time you are moving around lots of texture data it's a lot faster. You may just notice the initial load being faster if you aren't doing anything complex.
Title: Bullet Hell performance and optimization problems
Post by: Mindiell on June 16, 2010, 06:17:04 am
Quote from: "SuperV1234"
By commenting the Draw instruction, the game handles 20000 bullets without slowdowns.

Is it a SFML limitation, or is there any chance I'm doing something wrong drawing the sprite?

I'm not really sure about what I'll say, because I can't open your code file (Ubuntu, so C# is hard to read).

But, what I understand is that you are not drawing all your sprites in one block. I think that SFML2 was optimized for such things. If you are drawing some sprites and doing others things, you are not using SFML optimization.
Can you show us your main loop and the place where you are doing the drawings ?
I usually do updates of all my objects, then drawing of all them.
Title: Bullet Hell performance and optimization problems
Post by: Laurent on June 16, 2010, 08:28:19 am
Quote
You can use one sf::Vector2f and use Sprite.GetPosition() to set it, transform, and then use Sprite.SetPosition(sf::Vector2f); And just repeat over and over, no?

I think the problem is there are all of these useless vectors floating around doing nothing every time you move a sprite.

It's C#, not C++. So there are no GetPosition/SetPosition, and using "new Vector2" on every call is fine, the GC will take care of the unused memory.

Quote
DDS goes directly into video memory without any decompression/work and is much smaller so any time you are moving around lots of texture data it's a lot faster. You may just notice the initial load being faster if you aren't doing anything complex.

It doesn't make any difference, SFML internally handles the pixel data the same way regardless the original file format. The format information is lost right after the loading step.
Title: Bullet Hell performance and optimization problems
Post by: Ashenwraith on June 16, 2010, 08:46:59 am
Quote from: "Laurent"
Quote
You can use one sf::Vector2f and use Sprite.GetPosition() to set it, transform, and then use Sprite.SetPosition(sf::Vector2f); And just repeat over and over, no?

I think the problem is there are all of these useless vectors floating around doing nothing every time you move a sprite.

It's C#, not C++. So there are no GetPosition/SetPosition, and using "new Vector2" on every call is fine, the GC will take care of the unused memory.

Quote
DDS goes directly into video memory without any decompression/work and is much smaller so any time you are moving around lots of texture data it's a lot faster. You may just notice the initial load being faster if you aren't doing anything complex.

It doesn't make any difference, SFML internally handles the pixel data the same way regardless the original file format. The format information is lost right after the loading step.


No get and set? Well maybe the garbage man is a little fat and needs some help.  :D

Wow that's kind of disappointing to hear that about dds. I assumed that might be true because there were no sf::Uint5 or 565. That's kind of disappointing. A lot of my old tech is based on DDS optimization. I guess I have to write those in myself?
Title: Bullet Hell performance and optimization problems
Post by: Laurent on June 16, 2010, 09:02:04 am
But do you really need DDS optimizations?
Title: Bullet Hell performance and optimization problems
Post by: Ashenwraith on June 16, 2010, 09:34:16 am
Quote from: "Laurent"
But do you really need DDS optimizations?


Oh definitely!

When you are dealing with thousands of HD sprites DDS is a lifesaver. The vram usage is so much smaller. It's really not even possible to get the same graphics to work on the same hardware.

The average sprite set in my previous game is 1000-2000 sprites at approx 800x400 each for just one character. This fit in at about 80 megs of vram.

With png this is impossible.
Title: Bullet Hell performance and optimization problems
Post by: Laurent on June 16, 2010, 09:37:09 am
I see.

Unfortunately, I don't plan to add compressed texture formats to SFML.
Title: Bullet Hell performance and optimization problems
Post by: Spodi on June 16, 2010, 09:38:48 am
Quote from: "SuperV1234"
Using a profiler I noticed that SFML.Graphic.Sprite instances do not get cleaned up. Running a program at 60FPS for a long time can make 60.000, 70.000 Sprite instances. How can I prevent that?


It will clean up when the GC runs as long as you have no dangling references. You can manually invoke the GC (see the static class members for the "GC" class), but doing so isn't usually needed and shouldn't be done unless you know what you are doing and have spent some time studying the GC. If you have no dangling references, the GC may just not have needed to run yet. They won't affect performance sitting there dead (until the GC runs), so that isn't much of an issue. The fact that you have so many instances is probably a bit of an issue, though, which is why I suggested just using a single global instance of Sprite. That, or design an object pool (a simple Stack<> often suffices).

Quote from: "SuperV1234"

It runs fine on my GTX275 with less than 5000 bullets. The source code I posted before works perfectly. It's just if I add more than 4800-4900 bullets.


Ah, I see. Sorry for the confusion.

Quote from: "SuperV1234"

I can't use a single Sprite instance. Maybe you meant a single Image instance?


Quote from: "Ashenwraith"
You might not be able to use a single sprite


Why not? You should definitely be using a single Image instance since its all the same image, but you can also use the same Sprite instance. Just set the values on the sprite before drawing it.

Quote from: "Ashenwraith"
Well looking at the code above should you really be creating a new vector every time you change the position and draw the sprite?


Structs are not objects in C#, they are value types and are generally considered incredibly cheap. As far as implementation goes, "new" on a struct is completely different than on an object, and structs never result in garbage collection (unless the struct constructor itself generates objects, which itself is a bad idea).

Quote from: "Ashenwraith"
DDS goes directly into video memory without any decompression/work and is much smaller so any time you are moving around lots of texture data it's a lot faster. You may just notice the initial load being faster if you aren't doing anything complex.


DDS can help with loading times like you mentioned, but once its loaded, its all the same no matter what the source was. It does nothing to help the issue of drawing tons of bullets.

Storing in memory in a DDS format can help when bandwidth is an issue, but I highly doubt that would be the case here. I wouldn't be surprised at all if API calls were the main bottleneck.
Title: Bullet Hell performance and optimization problems
Post by: Ashenwraith on June 16, 2010, 09:57:07 am
Quote from: "Laurent"
I see.

Unfortunately, I don't plan to add compressed texture formats to SFML.


I'm curious why that is.

DDS has made so many strides at the forefront of graphics tech with new improvements in quality.

Now with YCoCg you can have near lossless, but even good old DXT 1 and 3 have are optimized to where you no longer have to fear artifacts.

SFML doesn't support 8bit, but it's also not going to support DDS?

32bit pngs are not very useful for making any kind of an optimized 2D game.
Title: Bullet Hell performance and optimization problems
Post by: Laurent on June 16, 2010, 10:04:02 am
Quote
I'm curious why that is.

Because nobody needs that except you :)
This is not a feature, this is an optimization. And my point is view is that an optimization should not be written unless it is really needed, so I'll wait for a little more feedback like yours before deciding to support compressed textures.
Title: Bullet Hell performance and optimization problems
Post by: Ashenwraith on June 16, 2010, 10:05:19 am
Quote from: "Spodi"

Quote from: "Ashenwraith"
You might not be able to use a single sprite


Why not? You should definitely be using a single Image instance since its all the same image, but you can also use the same Sprite instance. Just set the values on the sprite before drawing it.



Because most people use their sprites to store their position/transformation and other data. If you are constantly changing it then it needs to be stored somewhere else.
Title: Bullet Hell performance and optimization problems
Post by: Ashenwraith on June 16, 2010, 10:18:14 am
Quote from: "Laurent"
Quote
I'm curious why that is.

Because nobody needs that except you :)
This is not a feature, this is an optimization. And my point is view is that an optimization should not be written unless it is really needed, so I'll wait for a little more feedback like yours before deciding to support compressed textures.


Well honestly I don't think most people know about it because they haven't made a game with a lot of 2D assets/art. It's sort of necessary because you will hit a wall with 32-b png when you grow out of pac-man/mario clones.

The Holy Spirit project is one for example that could benefit a lot from dds compression (whether they know or not I'm not sure), but they don't even have an artist last I checked.
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 16, 2010, 10:26:52 am
Quote from: "Mindiell"
Quote from: "SuperV1234"
By commenting the Draw instruction, the game handles 20000 bullets without slowdowns.

Is it a SFML limitation, or is there any chance I'm doing something wrong drawing the sprite?

I'm not really sure about what I'll say, because I can't open your code file (Ubuntu, so C# is hard to read).

But, what I understand is that you are not drawing all your sprites in one block. I think that SFML2 was optimized for such things. If you are drawing some sprites and doing others things, you are not using SFML optimization.
Can you show us your main loop and the place where you are doing the drawings ?
I usually do updates of all my objects, then drawing of all them.


I'm using SFML 1.6 because I had trouble rendering text with the SVN version.

My rendering code is a for loop, which does this:
Code: [Select]
public void Tick()
        {
            for (int i = Entities.Count - 1; i >= 0; i--)
                Entities[i].Tick();  
        }


Entities.Tick(); basically means Entities.Update(); Entities.Draw();

So it's taking a single entity, updating it, drawing it, then passing to the next entity.
Title: Bullet Hell performance and optimization problems
Post by: Laurent on June 16, 2010, 10:27:07 am
Quote
Well honestly I don't think most people know about it because they haven't made a game with a lot of 2D assets/art. It's sort of necessary because you will hit a wall with 32-b png when you grow out of pac-man/mario clones.

The Holy Spirit project is one for example that could benefit a lot from dds compression (whether they know or not I'm not sure), but they don't even have an artist last I checked.

I agree, but I'm just waiting until people actually need it. There are so many things that I can do before it happens... ;)
Title: Bullet Hell performance and optimization problems
Post by: Mindiell on June 16, 2010, 11:01:47 am
Quote from: "SuperV1234"
Entities.Tick(); basically means Entities.Update(); Entities.Draw();

So it's taking a single entity, updating it, drawing it, then passing to the next entity.
Right, what about Updating every entities, then drawing each entities ?
Something more like :
Code: [Select]
for (int i = Entities.Count - 1; i >= 0; i--)
                Entities[i].Update();
for (int i = Entities.Count - 1; i >= 0; i--)
                Entities[i].Draw();
I'm not sure (Laurent ?), but I think it would be better to draw everything in only one pass, while doing nothing else...
Title: Bullet Hell performance and optimization problems
Post by: Laurent on June 16, 2010, 11:07:48 am
Quote
I'm not sure (Laurent ?), but I think it would be better to draw everything in only one pass, while doing nothing else...

I don't think that would make a difference, actually.
Title: Bullet Hell performance and optimization problems
Post by: Ashenwraith on June 16, 2010, 11:14:02 am
Quote from: "Laurent"
Quote
I'm not sure (Laurent ?), but I think it would be better to draw everything in only one pass, while doing nothing else...

I don't think that would make a difference, actually.


What about drawing the bullets as sf::shapes or even points?

Are there hardware optimizations for that?
Title: Bullet Hell performance and optimization problems
Post by: Laurent on June 16, 2010, 11:16:59 am
Quote
What about drawing the bullets as sf::shapes or even points?

Are there hardware optimizations for that?

It wouldn't help, unless its computer is limited by texture operations, which is probably not the case.
Title: Bullet Hell performance and optimization problems
Post by: SuperV1234 on June 17, 2010, 09:58:44 am
I updated to SFML 2 and now it handles around 13000 bullets at 60FPS. Do you think I should spend more time optimizing or should I start working on the game itself?
Title: Bullet Hell performance and optimization problems
Post by: Laurent on June 17, 2010, 11:02:26 am
You should definitely work on the game. Optimizing something that is far from being complete is a waste of time.
Title: Bullet Hell performance and optimization problems
Post by: Ashenwraith on June 18, 2010, 09:02:19 pm
Quote from: "SuperV1234"
I updated to SFML 2 and now it handles around 13000 bullets at 60FPS. Do you think I should spend more time optimizing or should I start working on the game itself?


You have to ask yourself if it it's worth it and motivates you to get it done.

If it's bugging you a lot because your bullet hell feels like bullet boring than work on it, but...

A lot of people like to at least have a skeleton of a game to play with and improve.