6

I am using pygame and python for a project I am building, and I am building a splashscreen for when the game first opens. I have a .png that I want to show for the splashscreen, and decided to fade it in and out from black. the best way I found to do this was by blitting the image with a set alpha. I made this code, but it runs really slowly (the program hangs for 30 seconds) and doesn't give an alpha. Only displays the picture onscreen. What am i doing wrong?

screen = pygame.display.set_mode([1066,600])

#Drawable surface
background = pygame.Surface(screen.get_size())

#Used for converting color maps
background = background.convert()

#Splashscreen

#image fades in
for i in range (225):
    background.fill((0,0,0))
    image = pygame.image.load("logo.png")
    image.set_alpha(i)
    logoimage = screen.blit(image,(0,0))
    pygame.display.flip()

pygame.time.delay(2000)

#image fades out

#goes on to display main menu
Ben Schwabe
  • 1,283
  • 1
  • 21
  • 36

3 Answers3

11

Another problem that you might be having (besides what monkey said) is that you might need to use surface.convert() which converts the image into a form where the alpha can be changed. You can do either of the following.

image = pygame.image.load("logo.png")
image = image.convert()

or

image = pygame.image.load("logo.png").convert()

I have found that, although surface.convert_alpha() should do pretty much the same thing, it doesn't usually work. Try this test code to check.

import pygame, sys
pygame.init()
window=pygame.display.set_mode((1500, 800))
background=pygame.Surface((window.get_rect().width, window.get_rect().height))
background.fill((0, 0, 0))
image=pygame.image.load('InsertImageHere.png')
image=image.convert()
image2=pygame.image.load('InsertImage2Here.png')
image2=image2.convert_alpha()
rect=image.get_rect()
rect2=image2.get_rect()
rect2.left=rect.width+1
i=1
while True:
    for event in pygame.event.get():
        if event.type==12:
            pygame.quit()
            sys.exit()
    image.set_alpha(i)
    image2.set_alpha(i)
    window.fill((255, 255, 255))
    window.blit(background, background.get_rect())
    window.blit(image, rect)
    window.blit(image2, rect2)
    pygame.time.delay(20)
    i+=1
    if i==255:
        i=1
    pygame.display.update()

In my testings, image 1 faded in properly, but image 2 stayed dark the whole time. You should try it for yourself; your computer might work differently.

If surface.convert_alpha() does work for you, you should use it, otherwise, do what I said before. This should solve your problem.

You should also note that I used pygame.time.delay(20) rather than 2000 like you had before. 2000 would be a bit too long if you are increasing the alpha in incraments of one.

ThisIsAQuestion
  • 1,887
  • 14
  • 20
  • yup, the `.convert()` fixed the issue, thanks for all the help! I don't quite undestand what the `.convert()` did, so I'll go study up on that now! – Ben Schwabe Sep 04 '12 at 23:43
  • convert_alpha() changes the image to per pixel alpha. That is why set_alpha won't work. In order to use set_alpha you must have an image without per pixel alpha. Use colorkey instead. – ndvo Apr 18 '13 at 01:48
5

[1] You don't want to load the image every iteration. Because creating a new surface is a slow operation. [2] Your loop draws 225 times, then afterward the final iteration, waits 2000ms.

You want:

image = pygame.image.load("logo.png")

for i in range (225):
    background.fill((0,0,0))    
    image.set_alpha(i)
    screen.blit(image,(0,0))
    pygame.display.flip()
    pygame.time.delay(20)

To fade in and out, you need to keep looping until the player clicks/hits a button. Like this:

import pygame
from pygame.locals import *

# ...

def title_loop():
    # title screen main loop    
    image = pygame.image.load("logo.png")
    done = False
    alpha = 0
    alpha_vel = 1

    # fade alpha in-out while waiting    
    while not done:        
        # get key input
        for event in pygame.event.get():
            if event.type == QUIT:
                done = true
            if event.type == KEYDOWN:
                if event.key = K_ESCAPE:
                    done = true

        # draw
        if alpha >= 255 or alpha <= 0:
            alpha_vel *= -1
        alpha += alpha_vel

        background.fill((0,0,0))
        image.set_alpha(i)
        screen.blit(image,(0,0))
        pygame.display.flip()

        pygame.time.delay(20)
ninMonkey
  • 7,211
  • 8
  • 37
  • 66
  • I tried what you suggested, and it works fine, but for some reason the image just stays completely opaque. If I use `get_alpha()` on it, then it tells me the correct alpha that it should be, but the image is not displaying with that alpha. Is this possibly a bug? – Ben Schwabe Sep 04 '12 at 14:18
  • Oh, when the image has per-pixel-alpha, then `set_alpha` value is ignored. Right after `image = pygame.image.load("logo.png")` add `image.set_alpha(None)` , which I think will disable per-pixel alpha, making it read your value. edit: Or try `pygameNerd`s post to remove the per-pixel-alpha. – ninMonkey Sep 04 '12 at 21:03
2

PygameNerd your example is close, but it doesn't really work.

The image.convert() will fade properly, but it doesn't support alpha channel. Try it on a non black background & it shows. The image.convert_alpha() will not fade, but the alpha channel does work properly.

I'm surprised that pygame doesn't support this out of the box, but anyway. Here is an answer: http://www.nerdparadise.com/tech/python/pygame/blitopacity/

Its a bit complex, but works fine. Transparent background & fading all in one package.

Mark Gossage
  • 196
  • 4