Performance tips on spawning multiple animated sprites simultaneously

In my game, you can cast a spell that causes all of the enemies on screen to catch fire. There can be as many as 40 or 50 enemies on the screen at once. Currently, there’s a perceptible lag (about one second) when you tap the spell button, and I’d like to get rid of it. Here’s how it’s implemented:

  • I loop through all the enemies on the screen
  • For each, I create a new three frame animated sprite via display.newSprite(imageSheet, sequenceData)
  • I set the flame sprite’s frame to a random index, so that all the flames don’t burn in sync
  • I tell the animation to play
  • I create two timers for each enemy: one that runs once for X seconds, after which the flame disappears, and a second that runs repeatedly every 100ms for the same total duration X, dealing damage to the enemy over time.
  • I add an event listener to the flame, so that when the enemy dies, it calls removeSelf()
  • In a separate table, I keep track of the relationship between the flame sprite and the enemy sprite
  • In my enterFrame loop, I update the x and y of the flame sprite to match the coordinates of the enemy sprite (which has separate movement logic in the frame loop)

The lag only lasts for a brief moment, after which the enemies move smoothly around the screen happily (unhappily?) engulfed in flames. Does anything in the above stand out as a potential problem spot? I would have posted code, but it’s spread out across a couple of classes, so I thought this would be easier.

For what it’s worth, the enemies are physics objects, but the flames are not. 

Thanks!

Could you post code?

Maybe in your config make your game 60fps and not 30?

I would not normally suggest this, but this is one of those cases where caching may help.

Consider this case:

  1. First time through.  
  • You need 5 sprites.

  • Make them

  • Show them

  • Hide them at end, DO NOT DELETE THEM.

  • Pause them.

  • Move the way offscreen <10000, 10000>

  • Keep track of them in a table.

  1. Second time through.
  • You need 7 sprites

  • Move the 5 ‘saved’ sprites into position.

  • Unpause them

  • Make 2 new sprites

  • Show them

  • Hide them at end, DO NOT DELETE THEM.

  • Pause them.

  • Move the way offscreen <10000, 10000>

  • Keep track of them in a table.

At end of level/game/whatever, purge all sprites in your stored sprites. i.e. delete them.

Interesting question.  If I have time, I’ll late add a solution to my answer pack for August. 

Do all enemies start and stop to burn at exactly the same moment? I’m asking because your TWO timers per enemy seem overkill, and it sounds like just ONE “if…then” statement in some global gameLoop enterFrame could easily have the same functionality.

Also, don’t create 50 sprites at the same time in the middle of gameplay. Create these at the start of your level, or even during the menu screen or whatever.

Does the enemy have an enterFrame loop? If so, you don’t need the eventListener on the flame. Just remove the flame (or better: keep it but move it offscreen) when the enemy dies by using code that runs the enemy.

Hi @aaronkarp,

Are all of the enemies the same (visually)? If so, an even further optimization would be to build a series of “enemy burning” animation frames into the same sprite/image sheet as they use for their core animation (I assume they’re animated objects, not static images). Then, when they “burn”, just change to that sequence and start playing it… that would be the most optimal, because the sheet and frames would already be loaded in advance, and you wouldn’t need to create 40-50 new sprites and track their position with the enemies, etc. etc.

As for your current scheme, why do you even need separate timers for each enemy? Start one main timer when they all begin to burn, for the duration of the burning spell. At the same time, start another timer which repeats each 100ms and deals damage to all burning enemies. As it loops through and deals damage, if an enemy dies, remove that enemy (and the fire sprite). I see no reason why these timers need to be individually created/associated with each enemy.

Best regards,

Brent

Could you post code?

Maybe in your config make your game 60fps and not 30?

I would not normally suggest this, but this is one of those cases where caching may help.

Consider this case:

  1. First time through.  
  • You need 5 sprites.

  • Make them

  • Show them

  • Hide them at end, DO NOT DELETE THEM.

  • Pause them.

  • Move the way offscreen <10000, 10000>

  • Keep track of them in a table.

  1. Second time through.
  • You need 7 sprites

  • Move the 5 ‘saved’ sprites into position.

  • Unpause them

  • Make 2 new sprites

  • Show them

  • Hide them at end, DO NOT DELETE THEM.

  • Pause them.

  • Move the way offscreen <10000, 10000>

  • Keep track of them in a table.

At end of level/game/whatever, purge all sprites in your stored sprites. i.e. delete them.

Interesting question.  If I have time, I’ll late add a solution to my answer pack for August. 

Do all enemies start and stop to burn at exactly the same moment? I’m asking because your TWO timers per enemy seem overkill, and it sounds like just ONE “if…then” statement in some global gameLoop enterFrame could easily have the same functionality.

Also, don’t create 50 sprites at the same time in the middle of gameplay. Create these at the start of your level, or even during the menu screen or whatever.

Does the enemy have an enterFrame loop? If so, you don’t need the eventListener on the flame. Just remove the flame (or better: keep it but move it offscreen) when the enemy dies by using code that runs the enemy.

Hi @aaronkarp,

Are all of the enemies the same (visually)? If so, an even further optimization would be to build a series of “enemy burning” animation frames into the same sprite/image sheet as they use for their core animation (I assume they’re animated objects, not static images). Then, when they “burn”, just change to that sequence and start playing it… that would be the most optimal, because the sheet and frames would already be loaded in advance, and you wouldn’t need to create 40-50 new sprites and track their position with the enemies, etc. etc.

As for your current scheme, why do you even need separate timers for each enemy? Start one main timer when they all begin to burn, for the duration of the burning spell. At the same time, start another timer which repeats each 100ms and deals damage to all burning enemies. As it loops through and deals damage, if an enemy dies, remove that enemy (and the fire sprite). I see no reason why these timers need to be individually created/associated with each enemy.

Best regards,

Brent