Как сделать прозрачное изображение в Pygame, чтобы сделать «вырез» из альфы - PullRequest
0 голосов
/ 09 мая 2019

Учитывая поверхность пигмея, заполненную несколькими пикселями, я хочу программно создать «окно» альфа-канала в этом изображении (так, чтобы фон просвечивал).

enter image description here

Очевидно, я понимаю, что это можно сделать тривиально с помощью редактора растровых изображений, и вопрос в том, чтобы сделать это на лету как часть другой, более сложной операции.

Итак, я создал спрайт, который переключается между изображениями «полный красный» и «красный с отверстием», и попытался динамически создать окно растрового изображения, перетаскивая полностью прозрачное изображение на базовое растровое изображение.

Я думаю, что происходит то, что PyGame не рисует полностью прозрачные пиксели, потому что, ну, они прозрачные! Есть ли способ сделать их так, чтобы окно было сделано?

Я пытался добавить pygame.BLEND_RGBA_MIN и другие (согласно предложению в Необходимость прозрачности на поверхности в Pygame ), но не смог достичь желаемого результата.

Все, что я когда-либо получаю, - это черный квадрат с красным центром, а не окно на заднем плане.

import pygame

# Window size
WINDOW_WIDTH  = 400
WINDOW_HEIGHT = 400
FPS           = 60

# background colours
INKY_BLACK    = (128, 128, 128)

class HoleSprite( pygame.sprite.Sprite ):
    def __init__( self ):
        pygame.sprite.Sprite.__init__( self )
        # Make a full-image (no hole)
        self.base_image = pygame.Surface( ( 32, 32 ), pygame.SRCALPHA )
        self.base_image.fill( ( 255,0,0 ) )
        # Make an image with a see-through window
        self.hole_image = pygame.Surface( ( 32, 32 ), pygame.SRCALPHA )
        self.hole_image.fill( ( 255,0,0 ) )
        self.hole       = pygame.Surface( ( 10, 10 ), pygame.SRCALPHA )
        self.hole.fill( ( 0, 0, 0, 255 ) ) # transparent
        self.hole_image.blit( self.hole, [ 10,10, 10,10 ] ) # punch the middle out?
        # sprite housekeeping
        self.image  = self.base_image
        self.rect   = self.image.get_rect()
        self.rect.x = WINDOW_WIDTH  // 2   # centred
        self.rect.y = WINDOW_HEIGHT // 2
        self.last   = 0

    def update( self ):
        time_ms = pygame.time.get_ticks()
        # FLip the images each second
        if ( time_ms - self.last > 1000 ):
            if ( self.image == self.hole_image ):
                self.image = self.base_image
            else:
                self.image = self.hole_image
            self.last = time_ms


### MAIN
pygame.init()
pygame.font.init()
SURFACE = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE
WINDOW  = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), SURFACE )
pygame.display.set_caption("Hole Srite Test")

anims = pygame.sprite.GroupSingle()
holey = HoleSprite( )
anims.add( holey )

clock = pygame.time.Clock()
done  = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True

    # Repaint the screen
    anims.update()
    WINDOW.fill( INKY_BLACK )
    anims.draw( WINDOW )

    pygame.display.flip()
    # Update the window, but not more than 60fps
    clock.tick_busy_loop( FPS )

pygame.quit()

1 Ответ

2 голосов
/ 09 мая 2019

Первое: вам нужно (0,0,0,0) вместо (0,0,0,255)

Второе: вам нужно использовать fill(color, rect), чтобы создать прозрачное отверстие непосредственно в красном прямоугольнике.

self.hole_image.fill( (0, 0, 0, 0), (10, 10, 10, 10) )

Или выможет рисовать прозрачный прямоугольник непосредственно на красной поверхности

pygame.draw.rect(self.hole_image, (0, 0, 0, 0), (10, 10, 10, 10) )

Когда вы перетаскиваете прозрачное изображение на полноцветное изображение, оно не заменяет пиксели, а смешивает оба цвета (прозрачный и полный), и вы получаете полный цвет.

blit() имеет флаги BLEND_ADD, BLEND_SUB, BLEND_MULT и т. Д., И, возможно, используя один из этих флагов, вы можете заменить пиксели, но я никогда не пробовал.

Другая информация: прозрачность Pygame

Полный код:

import pygame

# Window size
WINDOW_WIDTH  = 400
WINDOW_HEIGHT = 400
FPS           = 60

# background colours
INKY_BLACK    = (128, 128, 128)

class HoleSprite( pygame.sprite.Sprite ):
    def __init__( self ):
        pygame.sprite.Sprite.__init__( self )
        # Make a full-image (no hole)
        self.base_image = pygame.Surface( ( 32, 32 ), pygame.SRCALPHA )
        self.base_image.fill( ( 255,0,0 ) )
        # Make an image with a see-through window

        self.hole_image = pygame.Surface( ( 32, 32 ), pygame.SRCALPHA )
        self.hole_image.fill( ( 255,0,0 ) )
        self.hole_image.fill( (0, 0, 0, 0), (10, 10, 10, 10) )
        # OR
        #pygame.draw.rect(self.hole_image, (0, 0, 0, 0), (10, 10, 10, 10) )

        # sprite housekeeping
        self.image  = self.base_image
        self.rect   = self.image.get_rect()
        self.rect.x = WINDOW_WIDTH  // 2   # centred
        self.rect.y = WINDOW_HEIGHT // 2
        self.last   = 0

    def update( self ):
        time_ms = pygame.time.get_ticks()
        # FLip the images each second
        if ( time_ms - self.last > 1000 ):
            if ( self.image == self.hole_image ):
                self.image = self.base_image
            else:
                self.image = self.hole_image
            self.last = time_ms


### MAIN
pygame.init()
pygame.font.init()
SURFACE = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE
WINDOW  = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), SURFACE )
pygame.display.set_caption("Hole Srite Test")

anims = pygame.sprite.GroupSingle()
holey = HoleSprite( )
anims.add( holey )

clock = pygame.time.Clock()
done  = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True

    # Repaint the screen
    anims.update()
    WINDOW.fill( INKY_BLACK )
    anims.draw( WINDOW )

    pygame.display.flip()
    # Update the window, but not more than 60fps
    clock.tick_busy_loop( FPS )

pygame.quit()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...