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

Re: [pygame] Surface blitting not effective



Hi Julian,

A self blit works like other blits. What happened in your program was that the self blit did not clear the background. So the menu image was repeatedly blitted onto itself. Blitting a semi-transparent color onto itself just strengths the color on the target surface until it becomes totally opaque.

Lenard Lindstrom

On 10/10/10 05:19 PM, Julian Marchant wrote:
Well, wouldn't you know it? By changing:

bgsurface = pygame.display.get_surface()

to:

bgsurface = pygame.display.get_surface().copy()

i.e. blitting a copy of the window instead of the window to the window, alpha transparency works perfectly. I probably should have known, but I didn't realize that the window was blitting itself to itself.

But now I have a question: What exactly happens when you blit a surface to itself? It seems pretty clear that it caused alpha transparency for something else being blitted to it to not work in this case, but I still don't quite understand why. Sorry, but I just like to understand why things happen. :)

------------------------------------------------------------------------
*From:* Lenard Lindstrom <len-l@xxxxxxxxx>
*To:* pygame-users@xxxxxxxx
*Sent:* Sun, October 10, 2010 1:46:36 PM
*Subject:* Re: [pygame] Surface blitting not effective

There are a couple of things happening in this program which make it hard to know what is happening with the alpha blit. First, the display surface is blitted to itself:

class Game(object):
    ....
    def __init__(self):
        ....
        self.window = pygame.display.set_mode(self.rect.size)

    ....
def menu(self, options, cursor, anim_wait, color=pygame.Color(0,0,0,155), border=16, sep=8):
        ....
        #Create background surface
        bgsurface = pygame.display.get_surface()
        ....
        #Begin menu loop
        while 1:
        ....
            #Draw
            self.window.blit(bgsurface, self.rect)
....

Second, the menu surface is of an unknown format:

        #Create menu surface
        dlgsurface = pygame.Surface((xsize,ysize)).convert()
        dlgsurface.fill(color)
        dlgsurface.set_alpha(color.a)

Surface.convert() makes dlgsurface have the same properties as the display. If the display has per-pixel-alpha (Is that possible?) then so will dlgsurface. Blanket alpha, as set by Surface.set_alpha(), is ignored in this case. Better to create the menu surface with a known format:

dlgsurface = pygame.Surface((xsize, ysize), 0, 24) # no per-pixel alpha


Lenard Lindstrom


On 09/10/10 08:31 PM, B W wrote:
> Your blits were copying the source to positions outside the target surface. I always suspect this if I can't see my graphics. You can insert statements like "dlgsurface.get_rect().collidepoint(choicerect.topleft)" or "print dlgsurface.get_rect().colliderect(choicerect)" to tell whether the source rect intersects the target rect.
>
> I has a sneaking suspicion about the alpha problem and it paid off. Someone who understands the internals of color alphas and surface alphas would have to explain the why. :)
>
>        #Create menu surface
>        dlgsurface = pygame.Surface((xsize,ysize)).convert()
>        ##change
> #        dlgsurface.fill(color)
>        dlgsurface.fill(*color[3:])
>        dlgsurface.set_alpha(color.a)
>        dlgrect = dlgsurface.get_rect(center=self.rect.center)
>        ##new
>        drawrect = dlgsurface.get_rect()
>
>        cursor_rect = []
>        ypos = border
>
>        for option in options:
>            ##change
> #            choicerect = option.get_rect(centerx=dlgrect.centerx, \
> #                    top=dlgrect.top + ypos)
>            choicerect = option.get_rect(centerx=drawrect.centerx, \
>                    top=drawrect.top + ypos)
>            dlgsurface.blit(option, choicerect)
>            ##change
> # cursor_rect.append(cursor[0].get_rect(centery=choicerect.centery, \ > # left = dlgrect.left+border))
>            cursor_rect.append(cursor[0].get_rect(
>                centery=dlgrect.top+choicerect.centery,
>                left=dlgrect.left+border))
>            ypos += option.get_height() + sep
>