Search code examples
pythonpygamefadepygame-surface

Im trying to make a fade in and out


I am trying to create a function that will fade in and out for a game that I'm making. the problem is that the first part works fine but the second pard doesn't work.

WIDTH = screen width, HEIGHT = screen height, WINDOW = the name of the window, and I imported pygame as pg

def fade():
    fade = pg.Surface((WIDTH, HEIGHT))
    fade.fill((0,0,0))
    opacity = 0
    for r in range(0, 100):
        opacity += 1
        fade.set_alpha(opacity)
        WINDOW.blit(fade, (0,0))
        pg.display.update()
        pg.time.delay(10)
    for r in range(0, 100):
        opacity -= 1
        fade.set_alpha(opacity)
        WINDOW.blit(fade, (0,0))
        pg.display.update()
        pg.time.delay(10)

From looking at the code everything should work fine but it doesn't. I didn't paste the entire code because its 300 lines.


Solution

  • What they actually do is draw a transparent image over the background over and over again until the background is completely covered. You can't make the background visible again by blending the image with less transparency over it. You have to completely redraw the whole scene in every frame, blending an ever more agile transparent image over it.
    I suggest to write a blitFadeIn and blitFadeOut function and call it in the application loop.

    Minimal example:

    import pygame
    
    pygame.init()
    window = pygame.display.set_mode((400, 400))
    clock = pygame.time.Clock()
    
    background = pygame.Surface(window.get_size())
    ts, w, h, c1, c2 = 50, *background.get_size(), (128, 128, 128), (64, 64, 64)
    tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
    [pygame.draw.rect(background, color, rect) for rect, color in tiles]
    
    font = pygame.font.SysFont(None, 100)
    text = font.render("image", True, (255, 255, 0))
    image = pygame.Surface(window.get_size(), pygame.SRCALPHA)
    pygame.draw.ellipse(image, "red", window.get_rect().inflate(-20, -20))
    image.blit(text, text.get_rect(center = window.get_rect().center))
    
    image.set_alpha(0)
    
    def blitFadeIn(target, image, pos, step=2):
        alpha = image.get_alpha()
        alpha = min(255, alpha + step)
        image.set_alpha(alpha)
        target.blit(image, pos)
        return alpha == 255
    
    def blitFadeOut(target, image, pos, step=2):
        alpha = image.get_alpha()
        alpha = max(0, alpha - step)
        image.set_alpha(alpha)
        target.blit(image, pos)
        return alpha == 0
    
    fade_in = False
    fade_out = False
    run = True
    while run:
        clock.tick(100)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False 
            if event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN:
                if not fade_in and not fade_out:
                    fade_in = True
    
        window.blit(background, (0, 0))
        if fade_in:
            done = blitFadeIn(window, image, (0, 0))
            if done:
                fade_in, fade_out = False, True
        if fade_out:
            done = blitFadeOut(window, image, (0, 0))
            if done:
                fade_out = False
        pygame.display.flip()
    
    pygame.quit()
    exit()
    

    Also see: