arcade icon indicating copy to clipboard operation
arcade copied to clipboard

Optimize Rotating Sprites to Points

Open eschan145 opened this issue 3 years ago • 5 comments

Optimization Request

I am creating a battlefield simulator, where two armies attack each other with swords, bows and arrows, etc. When an arrow is fired, it needs to aim towards its target. I used the destination_point property in the turn_and_move example.

The problem with this is it consumed a huge amount of CPU. My framerate started as 60 FPS without the arrows pointing to the target, but when they did, my FPS dropped below 20. This problem has occurred in many other projects. Is there a way this can be optimized?

eschan145 avatar Jul 05 '22 18:07 eschan145

I'd probably try profiling the code to see where the time is being spent. What environment do you use to develop?

Alternatively, if you post the code somewhere I can run through a profiler.

pvcraven avatar Jul 05 '22 18:07 pvcraven

We do have a discord server that might be a better palce to discuss things like this. It might not be an arcade issue, but a general python issue having to deal with speed constraints. There are probably many ways to speed this up if you set some limitations or work with acceptable approximations.

einarf avatar Jul 05 '22 18:07 einarf

I'm using Windows 10, with Python 3.10 and in Visual Studio Code.

eschan145 avatar Jul 05 '22 18:07 eschan145

einarf is correct, you'll probably get the quickest responses from Discord.

VSCode can do profiling of Python code I believe. You can also do it off the command line. I've only used Pycharm Professional for profiling, but profiling makes finding root causes for things like this dead simple.

pvcraven avatar Jul 05 '22 18:07 pvcraven

If your goal is to have arrows follow a pre-determined trajectory after they're fired from the bow, the example you're referring to is overkill.

I'll suggest a potential fix in the next paragraph, but the best way to optimize will depend on what you're trying to build. How many sprites are on screen at the same time right now? Also, do each of them have complicated update logic? When are collision checks being made? We don't have enough information to work with right now, so it would be extremely useful if you could provide code or at least answer some of these questions.

My hunch is that you should make the projectile class a lot simpler. Try having the constructor calculate a flight time to the target using the target's position at time of firing, x & y velocity, and maybe a vertical velocity passed to the constructor. Then make the on_update function do the following:

  1. Decrement remaining flight time based on delta_time
  2. Set the x, y, and angle based on the total time elapsed out of the flight time
  3. Only check for collisions with enemies after the sprite is sufficiently "close" to the ground, This can be handled by moving arrows from a flying sprite list to a near_ground sprite list used for collision checks.
  4. "Destroy" the sprite if it's flight time has elapsed (more on this below)

There are also other things you can try like storing arrow instances in a pool that you pull from instead of creating or destroying instances. When an archer "fires" an arrow, you would take the first arrow from the unused arrow pool, set its flight attributes, and then put it back in the unused pool after the game is done with it.

pushfoo avatar Jul 05 '22 19:07 pushfoo

Closing, as this seems to have more to do with poor performance in drawing shapes.

pvcraven avatar Aug 17 '22 15:08 pvcraven