I'm currently working on a space exploration game in 2D top view. I have quite a few planets and since the map span is much greater than the display I end up with a lot of planet sprites lying outside the display area. At the moment I assume Pygame will not actually blit the sprite if they are not located in the display (as I understand it blitting and drawing to a surface slows things quite a lot) is that true ? Or would I need to add a condition to check if the sprite is located within the display prior to the blit call ? The reason I'm asking is that the way my game works is that each time a planet is discovered 2 new ones are created ... which means that the game can get quite big, and potentially very slow.
Thank you
No, it won't blit the images. Pygame will simply ignore it if you're trying to blit something that's outside of the screen. It shouldn't slow down your program unless there's a huge amounts of objects, since it'll take a fraction of time for pygame to determine that the image is outside of the screen. This isn't a huge deal though.
Realized my answer lacked proof (which is bad, mkay...), so I ran some test to prove my point. I tested 3 conditions: blitting to the screen, blitting outside the screen, and doing nothing. The number of seconds they took are insignificant because they're based on my computer's performance (a 5 year old laptop), so look for the factors between them instead; they should be similar for everyone.
5,000 blits
- Inside: 0.033265519510593734 seconds
- Outside: 0.002402466401003767 seconds
- Nothing: 0.00023237229449441657 seconds
500,000 blits
- Inside: 3.639024520190433 seconds
- Outside: 0.23328839021967726 seconds
- Nothing: 0.023549600850092247 seconds
50,000,000 blits
- Inside: 360.48034191795153 seconds
- Outside: 23.317473949049596 seconds
- Nothing: 2.3507101910654455 seconds
As you can see, blitting outside the screen takes more time than not blitting, but it doesn't take nearly as much time as actually blitting to the screen. Blitting outside the screen is barely a cost.
For further reference, here's the test I created:
setup = """
import pygame
pygame.init()
screen = pygame.display.set_mode((100, 100))
image = pygame.Surface((100, 100))
"""
statement1 = """
for i in range(5000):
screen.blit(image, (0, 0))
"""
statement2 = """
for i in range(5000):
screen.blit(image, (200, 200))
"""
statement3 = """
for i in range(5000):
pass
"""
from timeit import timeit
num_of_times = 10000
inside = timeit(stmt=statement1, setup=setup, number=num_of_times)
outside = timeit(stmt=statement2, setup=setup, number=num_of_times)
nothing = timeit(stmt=statement3, setup=setup, number=num_of_times)
print("Inside: {} seconds".format(inside/num_of_times))
print("Outside: {} seconds".format(outside/num_of_times))
print("Nothing: {} seconds".format(nothing/num_of_times))