[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[pygame] Alpha Channel Speed Question



I have a question - Do you know of a way to get method 3 as outlined below to be faster? The necessity of doing all those extra blits to preserve the alpha channel is really slowing things down.




import pygame

WIDTH = 800
HEIGHT = 600
bg = None

def Init():
    global bg, font
    pygame.init()
    bg = pygame.display.set_mode((WIDTH, HEIGHT), 0, 32)
    font = pygame.font.Font(None, 18)

def Run():
    bgcolor1 = (255, 255, 255)
    bgcolor2 = (192, 192, 192)
    bgcolor3 = (128, 128, 128)
    nightcolor = [0, 0, 0, 64]

# Create a bitmap - assume this is an expensive operation
# taking a few seconds.
bitmap = pygame.Surface((100, 100), pygame.SRCALPHA, 32).convert_alpha()
pygame.draw.circle(bitmap, (0, 255, 255), [50, 50], 50, 0)
bitmappos = [0, 0]


# Create the nighttime overlay
night = pygame.Surface((WIDTH, HEIGHT/3), pygame.SRCALPHA, 32).convert_alpha()
night.fill(nightcolor)


    # Loop forever
    quitgame = 0
    while not quitgame:
        pygame.event.pump()

# Fill background
bg.fill(bgcolor1, (0, 0, WIDTH, HEIGHT/3))
Print(bg, 'I want to darken the circle only. (Move the mouse left and right to test.)', (0, 10))
Print(bg, 'Moving the mouse up here uses overlay method 1, which overlays the background and circle.', (0, 25))
Print(bg, 'This method is fast, but undesirable because it colors the background.', (0, 40))
bg.fill(bgcolor2, (0, HEIGHT*1/3, WIDTH, HEIGHT/3))
Print(bg, "Moving the mouse up here uses overlay method 2, which overlays the circle only, but also destroys the circle's alpha channel.", (0, HEIGHT/3+10))
bg.fill(bgcolor3, (0, HEIGHT*2/3, WIDTH, HEIGHT/3))
Print(bg, 'Moving the mouse down here uses overlay method 3, which overlays the circle only, but is very slow.', (0, HEIGHT*2/3+10))
Print(bg, "Do you know of a faster way to darken the bitmap, without modifying the original picture?", (0, HEIGHT*2/3+25))


# Render night (the part in question)
if bitmappos[1] < HEIGHT/3:
# Method that colors it all include the background
bg.blit(bitmap, (bitmappos[0]-50, bitmappos[1]-50))
bg.blit(night, (0, 0))
elif bitmappos[1] < HEIGHT*2/3:
# Method that colors only the circle but destroys its alpha channel
w, h = bitmap.get_size()
temp = pygame.Surface((w, h), pygame.SRCALPHA, 32).convert_alpha()
temp.blit(bitmap, (0, 0))
temp.blit(night, (0, 0))
bg.blit(temp, (bitmappos[0]-50, bitmappos[1]-50))
else:
# Method that colors only the circle, but is too slow
w, h = bitmap.get_size()
temp = pygame.Surface((w, h), pygame.SRCALPHA, 32).convert_alpha()
temp.blit(bitmap, (0, 0))
temp.blit(night, (0, 0))
pygame.surfarray.pixels_alpha(temp)[:, :] = pygame.surfarray.pixels_alpha(bitmap)
bg.blit(temp, (bitmappos[0]-50, bitmappos[1]-50))


        pygame.display.update()

        # Look for quit
        for e in pygame.event.get():
            if e.type in [pygame.QUIT, pygame.MOUSEBUTTONDOWN]:
                quitgame = 1
                break
            elif e.type == pygame.KEYDOWN:
                if e.key == 27:
                    quitgame = 1
                    break
            elif e.type == pygame.MOUSEMOTION:
                bitmappos = e.pos
                nightcolor[3] = e.pos[0]/float(WIDTH) * 255
                night.fill(nightcolor)

def Print(bg, text, loc):
    fontcolor = (0, 0, 0)
    pic = font.render(text, 1, fontcolor)
    bg.blit(pic, loc)

def Terminate():
    pygame.quit()

def main():
    Init()
    Run()
    Terminate()

main()