Fade in screen in pyGame?

So I wanted to make my menu fade in when the game starts and fade out when it quits. To do so, I created a second surface and planned to fill it with black and then gradually increase alpha. So in the constructor I added:

    self.fadeInSurface = pygame.display.set_mode(screen_size, flag)


In the main game method before the game loop starts:

self.fadeIn()


And the aforementioned fadeIn() looks like this:

def fadeIn(self):
for i in range(100):
self.fadeInSurface.fill((0,0,0))
self.fadeInSurface.set_alpha(i)
self.clock.tick(30)
pygame.display.flip()


But instead of a fade-in, all I get is solid black screen for a short time and then the menu appears without any eye candy whatsoever. What am I doing wrong?

EDIT: Thanks to @Heckel, I made something like this:

def fadeIn(self):
for i in range(255):
self.surface.blit(self.background, (0,0), None, BLEND_RGB_MAX)
self.surface.blit(self.curStart, (100,200), None)
self.surface.blit(self.curQuit, (400,350), None)
self.fadeInSurface.fill((0,0,0))
self.fadeInSurface.set_alpha(255-i)
self.surface.blit(self.fadeInSurface, (0,0))
self.clock.tick(30)
pygame.display.flip()


so that I have the main surface (called surface) on which I project my buttons and background and a secondary surface (called fadeInSurface) which is solid black but its alpha changes. Running this code, however, still results in solid black screen for a few seconds and then a sudden change to full clarity of the whole menu :( Why is that so?

2 Answers

Very good idea, I must say. I've solved the problem. First of all, you absolutely don't need to use a for-loop (That's the reason why things happen pretty fast).

I ask you:

The game does not have a main loop already? In your code, in the very first frame of the game, you run a loop that increment all the colour-value up to its maximum. So, that's the problem.

I'm not using your variables, but hopefully my example will be understandable. Try something like that:

from pygame import *
DONE = False
screen = display.set_mode((1024,768))
alphaSurface = Surface((1024,768)) # The custom-surface of the size of the screen.
alphaSurface.fill((255,255,255)) # Fill it with whole white before the main-loop.
alphaSurface.set_alpha(0) # Set alpha to 0 before the main-loop.
alph = 0 # The increment-variable.
while not DONE:
screen.fill((0,0,0)) # At each main-loop fill the whole screen with black.
alph += 0.1 # Increment alpha by a really small value (To make it slower, try 0.01)
alphaSurface.set_alpha(alph) # Set the incremented alpha-value to the custom surface.
screen.blit(alphaSurface,(0,0)) # Blit it to the screen-surface (Make them separate)

# Trivial pygame stuff.
if key.get_pressed()[K_ESCAPE]:
DONE = True
for ev in event.get():
if ev.type == QUIT:
DONE = True
display.flip() # Flip the whole screen at each frame.
quit()


You should be able to run this code properly. I hope it helped.

The opposite:

alphaSurface.set_alpha(255) # Set alpha to 255 before the main-loop.
alph = 255 # The Decrement-variable.
alph -= 0.1 # Decrement alpha by a really small value (To make it slower, try 0.01)


You need a blit before the flip to display your black surface. The solid black comes from the fact that you don't display anything on the screen. Also, if you want your menu to fade in the black surface needs to fade out so you have to decrease its alpha.

Although, this will still not work because you only draw the black surface during the loop, not your menu.

I don't know how is the rest of your code but you should draw the black surface after you drew the menu, all in one loop. You should have a variable that keeps the alpha of your black surface, and you stop displaying it when the alpha is 0.

Maybe this will help you.

• Thank you for your reply. I edited the initial post to show my further work using it - could you look at it and tell me your opinion on how to solve this? – Straightfw May 24 '14 at 22:46