Optimize Rotating Sprites to Points
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?
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.
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.
I'm using Windows 10, with Python 3.10 and in Visual Studio Code.
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.
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:
- Decrement remaining flight time based on
delta_time - Set the x, y, and angle based on the total time elapsed out of the flight time
- Only check for collisions with enemies after the sprite is sufficiently "close" to the ground, This can be handled by moving arrows from a
flyingsprite list to anear_groundsprite list used for collision checks. - "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.
Closing, as this seems to have more to do with poor performance in drawing shapes.