2

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.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
LStep
  • 87
  • 5
  • Have a look at [this answer](https://stackoverflow.com/a/54594196/2280890), you might find it helpful. Otherwise you should [edit] your question to include a [mre]. To fix your specific fade out issue, you need to call `fade.fill("black")` in your second `for` loop. (I prefer [named colors](https://www.pygame.org/docs/ref/color_list.html) if I can help it). It doesn't strictly matter in the first loop as you're overwriting with a more opaque image, for the reduced alpha, you need to clear/reset the screen for it to be visible. – import random Jan 04 '23 at 05:33

1 Answers1

1

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:

Rabbid76
  • 202,892
  • 27
  • 131
  • 174