Reputation: 33
Ive been making a particle system in XNA and i am trying to create two particle effects. a firework explosion and a fountain firework.
the problem i am having is that when i add new particles to the explosion (im doing this fast because i want them to all spawn at the same time) the frame rate drops greatly.
i was wondering if anyone a solution to make this better. i saw that the official example uses a queue method. would this help the problem i am facing? or would it make the program slower to load as it would have to load all these particles into the queue at the start?
add new particle :
if (isActive)
{
timeSinceLastEmission += gameTime.ElapsedGameTime.Milliseconds;
if (emitterFrequency == 0 || timeSinceLastEmission >= emitterFrequency)
{
emitterFrequency = emissionInterval;
for (int i = 0; i < Math.Round(timeSinceLastEmission / emitterFrequency); i++)
{
if (particleList.Count < MaxParticles)
addParticle();
}
timeSinceLastEmission = 0;
}
}
draw function :
public void draw(SpriteBatch spriteBatch)
{
spriteBatch.Begin();
for (int i = 0; i < particleList.Count; i++)
{
spriteBatch.Draw(particleList[i].texture,
particleList[i].position,
null,
particleList[i].color,
particleList[i].rotation,
particleList[i].origin,
particleList[i].textureScale,
SpriteEffects.None,
0);
}
spriteBatch.End();
}
any help would be greatly appreciated.
Upvotes: 0
Views: 651
Reputation: 27225
You need to do two things:
First, you need to make your particle type a struct
instead of a class
. (I am guessing it is.)
A class
allocates heap memory, and your list will be full of references to those objects sitting on the heap. Each of those heap objects needs to be managed by the garbage collector. When you have lots of objects this is very slow. (For too many reasons to go into detail here.)
A struct
, however, will sit directly in the memory allocated for the list. The runtime can do things like allocate and clear that memory in bulk - considerably faster. Your struct
is quite a bit bigger than a reference, so try to make it as small as you can. Do you really need a per-particle texture and origin? You could make those per-particle-system.
(Another good reason is because SpriteBatch
is much faster if you avoid texture changes, as they necessitate a new batch - slow.)
Second, you should set List.Capacity
to the maximum size of your particle system.
Or, better still, you could use the constructor for the list that lets you set the starting capacity. This will allocate the memory memory your list needs all at once. Whenever a list reaches capacity, it has to allocate a new, bigger list, and copy its contents across. So, if you start it off big enough, it doesn't have to repeatedly do this slow operation.
(Note: you'll find you can't set individual members on structs in a list, like you can with classes - the compiler will give you an error. You have to copy out the whole struct, modify it, and copy it back in. This isn't too bad. But, if you want, you can avoid it by using an array - but then you must manage size and capacity yourself.)
(Note #2: "Slow" in this answer is in relation to optimising a particle system, because you're working with large numbers of frequently-updated objects. These operations aren't slow in a general sense.)
Upvotes: 1