Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fade the screen out and back in using PyGame?

So I am trying to fade my screen out and back in after completing a level using PyGame. My problem is that only the fadeout() works and not the fadein(). When calling the fadein() the screen turns black for a few seconds then suddenly shows the next level. I can't find the problem, any ideas?

def fadeout():
    fadeout = pg.Surface((screen_width, screen_height))
    fadeout = fadeout.convert()
    fadeout.fill(black)
    for i in range(255):
        fadeout.set_alpha(i)
        screen.blit(fadeout, (0, 0))
        pg.display.update()


def fadein():
    fadein = pg.Surface((screen_width, screen_height))
    fadein = fadein.convert()
    fadein.fill(black)
    for i in range(255):
        fadein.set_alpha(255-i)
        screen.blit(fadein, (0, 0))
        pg.display.update()
like image 238
Tripti Avatar asked Oct 24 '19 11:10

Tripti


People also ask

What is pygame flip?

flip() for software displays. It allows only a portion of the screen to updated, instead of the entire area. If no argument is passed it updates the entire Surface area like pygame. display.

What does convert () do in pygame?

convert() is used to convert the pygame. Surface to the same pixel format as the one you use for final display, the same one created from pygame.

What does surface do in pygame?

When using Pygame, surfaces are generally used to represent the appearance of the object and its position on the screen. All the objects, text, images that we create in Pygame are created using surfaces.


1 Answers

Your problem is that you fade in to a black screen, so you don't see any effect. A black screen with a black half-translucent Surface drawn on top is still a black Surface.

You should render the first frame of your level, and blit that Surface to the screen before blitting the fadein surface onto the screen.


Here's a simple example that I hacked together. Press a key to switch from one scene to the next.

import pygame
import random
from itertools import cycle

class Cloud(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((50, 20))
        self.image.set_colorkey((11, 12, 13))
        self.image.fill((11, 12, 13))
        pygame.draw.ellipse(self.image, pygame.Color('white'), self.image.get_rect())
        self.rect = self.image.get_rect(topleft=(x,y))

    def update(self, dt, events):
        self.rect.move_ip(dt/10, 0)
        if self.rect.left >= pygame.display.get_surface().get_rect().width:
            self.rect.right = 0

class DayScene:
    def __init__(self):
        self.clouds = pygame.sprite.Group(Cloud(0, 30), Cloud(100, 40), Cloud(400, 50))

    def draw(self, screen):
        screen.fill(pygame.Color('lightblue'))
        self.clouds.draw(screen)

    def update(self, dt, events):
        self.clouds.update(dt, events)

class NightScene:
    def __init__(self):
        sr = pygame.display.get_surface().get_rect()
        self.sky = pygame.Surface(sr.size)
        self.sky.fill((50,0,50))
        for x in random.sample(range(sr.width), 50):
            pygame.draw.circle(self.sky, (200, 200, 0), (x, random.randint(0, sr.height)), 1)
        self.clouds = pygame.sprite.Group(Cloud(70, 70), Cloud(60, 40), Cloud(0, 50), Cloud(140, 10), Cloud(100, 20))

    def draw(self, screen):
        screen.blit(self.sky, (0, 0))
        self.clouds.draw(screen)

    def update(self, dt, events):
        self.clouds.update(dt, events)

class Fader:

    def __init__(self, scenes):
        self.scenes = cycle(scenes)
        self.scene = next(self.scenes)
        self.fading = None
        self.alpha = 0
        sr = pygame.display.get_surface().get_rect()
        self.veil = pygame.Surface(sr.size)
        self.veil.fill((0, 0, 0))

    def next(self):
        if not self.fading:
            self.fading = 'OUT'
            self.alpha = 0

    def draw(self, screen):
        self.scene.draw(screen)
        if self.fading:
            self.veil.set_alpha(self.alpha)
            screen.blit(self.veil, (0, 0))

    def update(self, dt, events):
        self.scene.update(dt, events)

        if self.fading == 'OUT':
            self.alpha += 8
            if self.alpha >= 255:
                self.fading = 'IN'
                self.scene = next(self.scenes)
        else:
            self.alpha -= 8
            if self.alpha <= 0:
                self.fading = None

def main():
    screen_width, screen_height = 300, 300
    screen = pygame.display.set_mode((screen_width, screen_height))
    clock = pygame.time.Clock()
    dt = 0
    fader = Fader([DayScene(), NightScene()])

    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return
            if e.type == pygame.KEYDOWN:
                fader.next()

        fader.draw(screen)
        fader.update(dt, events)

        pygame.display.flip()
        dt = clock.tick(30)

main()

enter image description here

By abstracting each scene into it's own class and delegating the scene change to the Fader class, we're able to let the scenes continue (or add a simple if statement to prevent that) and to handle events while fading.

like image 144
sloth Avatar answered Sep 18 '22 17:09

sloth