Drawing random stars in background, pygame
Question:
I am working on a platformer game in which I want to add random stars in the background. I have written some code in the function drawBackDrop()
which will make some stars at random positions on the screen.
It works fine, but for drawing the stars I have to update it every frame, so the function is called everytime and it makes random stars differently every time.
I want it to appear only once and then not update, so the stars remain at constant positions.
My drawBackDrop()
function:
def drawBackdrop():
if globals.theme == "dark":
a = random.randint(3, 12)
x = random.randint(5, globals.screen_width - 12)
y = random.randint(5, globals.screen_height - 12)
numberOfStars = random.randint(35, 55)
starRect = pygame.Rect(x, y, a, a)
for i in range(numberOfStars):
pygame.draw.rect(globals.screen, "White", starRect)
if globals.theme == "light":
pass #Sun and Clouds
This is the code of scene in which I call the function:
def draw(self, sceneManager, screen):
if globals.theme == "light":
screen.fill(globals.light_blue)
elif globals.theme == "dark":
screen.fill(globals.black)
draw.drawBackdrop()
self.cameraSystem.update(screen)
What I get:
As you can see, the stars are being formed every frame. I want it to form only once and then draw the same stars in screen until I win/lose/leave.
How do I only call the function once? Or is there any other way to draw random stars?
Answers:
There’s two ways you can go here.
- Paint the stars to a background layer, and blit that every frame
- Generate the list of random stars once, and store them. Repainting the same Rects every frame. (As @matszwecja suggested in a comment)
But first note that there’s a minor bug in your code. It’s not generating the stars correctly – IFF I understand your intentions correctly. It looks like you wanted to generate a random set of stars, but it was painting the same star over and over.
def drawBackdrop():
if globals.theme == "dark":
numberOfStars = random.randint(35, 55) # <<-- MOVED outside loop
for i in range(numberOfStars): # <<-- MOVED Loop
a = random.randint(3, 12)
x = random.randint(5, globals.screen_width - 12)
y = random.randint(5, globals.screen_height - 12)
starRect = pygame.Rect(x, y, a, a)
pygame.draw.rect(globals.screen, "White", starRect)
Background Surface
def makeBackgroundStars():
""" Generate a transparent background overlay with stars """
background = pygame.Surface( ( globals.screen_width, globals.screen_height ), pygame.SRCALPHA )
numberOfStars = random.randint(35, 55)
for i in range(numberOfStars):
a = random.randint(3, 12)
x = random.randint(5, globals.screen_width - 12)
y = random.randint(5, globals.screen_height - 12)
starRect = pygame.Rect(x, y, a, a)
pygame.draw.rect( background, "White", starRect )
return background
The you just need to make the initial image, and then blit it every frame. Probably you’d include all background graphics into this image too.
star_field = makeBackgroundStars()
# in main loop
# ...
globals.screen.blit( star_field, ( 0, 0 ) )
List of Star Rectangles
star_positions = [] # global to hold rects
def genererateStars():
""" generate a random amount of stars for the background """
global star_positions
numberOfStars = random.randint(35, 55) # <<-- MOVED outside loop
for i in range(numberOfStars): # <<-- MOVED Loop
a = random.randint(3, 12)
x = random.randint(5, globals.screen_width - 12)
y = random.randint(5, globals.screen_height - 12)
star_positions.append( pygame.Rect(x, y, a, a) ) # save it for later
def paintStars( screen ):
""" Draw the stars to the background """
global star_positions
for starRect in star_positions:
pygame.draw.rect( screen, "White", starRect )
I am working on a platformer game in which I want to add random stars in the background. I have written some code in the function drawBackDrop()
which will make some stars at random positions on the screen.
It works fine, but for drawing the stars I have to update it every frame, so the function is called everytime and it makes random stars differently every time.
I want it to appear only once and then not update, so the stars remain at constant positions.
My drawBackDrop()
function:
def drawBackdrop():
if globals.theme == "dark":
a = random.randint(3, 12)
x = random.randint(5, globals.screen_width - 12)
y = random.randint(5, globals.screen_height - 12)
numberOfStars = random.randint(35, 55)
starRect = pygame.Rect(x, y, a, a)
for i in range(numberOfStars):
pygame.draw.rect(globals.screen, "White", starRect)
if globals.theme == "light":
pass #Sun and Clouds
This is the code of scene in which I call the function:
def draw(self, sceneManager, screen):
if globals.theme == "light":
screen.fill(globals.light_blue)
elif globals.theme == "dark":
screen.fill(globals.black)
draw.drawBackdrop()
self.cameraSystem.update(screen)
What I get:
As you can see, the stars are being formed every frame. I want it to form only once and then draw the same stars in screen until I win/lose/leave.
How do I only call the function once? Or is there any other way to draw random stars?
There’s two ways you can go here.
- Paint the stars to a background layer, and blit that every frame
- Generate the list of random stars once, and store them. Repainting the same Rects every frame. (As @matszwecja suggested in a comment)
But first note that there’s a minor bug in your code. It’s not generating the stars correctly – IFF I understand your intentions correctly. It looks like you wanted to generate a random set of stars, but it was painting the same star over and over.
def drawBackdrop():
if globals.theme == "dark":
numberOfStars = random.randint(35, 55) # <<-- MOVED outside loop
for i in range(numberOfStars): # <<-- MOVED Loop
a = random.randint(3, 12)
x = random.randint(5, globals.screen_width - 12)
y = random.randint(5, globals.screen_height - 12)
starRect = pygame.Rect(x, y, a, a)
pygame.draw.rect(globals.screen, "White", starRect)
Background Surface
def makeBackgroundStars():
""" Generate a transparent background overlay with stars """
background = pygame.Surface( ( globals.screen_width, globals.screen_height ), pygame.SRCALPHA )
numberOfStars = random.randint(35, 55)
for i in range(numberOfStars):
a = random.randint(3, 12)
x = random.randint(5, globals.screen_width - 12)
y = random.randint(5, globals.screen_height - 12)
starRect = pygame.Rect(x, y, a, a)
pygame.draw.rect( background, "White", starRect )
return background
The you just need to make the initial image, and then blit it every frame. Probably you’d include all background graphics into this image too.
star_field = makeBackgroundStars()
# in main loop
# ...
globals.screen.blit( star_field, ( 0, 0 ) )
List of Star Rectangles
star_positions = [] # global to hold rects
def genererateStars():
""" generate a random amount of stars for the background """
global star_positions
numberOfStars = random.randint(35, 55) # <<-- MOVED outside loop
for i in range(numberOfStars): # <<-- MOVED Loop
a = random.randint(3, 12)
x = random.randint(5, globals.screen_width - 12)
y = random.randint(5, globals.screen_height - 12)
star_positions.append( pygame.Rect(x, y, a, a) ) # save it for later
def paintStars( screen ):
""" Draw the stars to the background """
global star_positions
for starRect in star_positions:
pygame.draw.rect( screen, "White", starRect )