Reputation: 373
I'm creating a GUI library with pygame
. I'd like to support transparent surfaces as well as transparent rect
s. The transparent rects work when I use self.original_image.set_alpha(100)
. I'm converting the pygame surface so it can accept an alpha with surface.convert()
, however the image ends up with a black background and some distortion when I do this. surface.convert_alpha()
doesn't seem to have any effect.
class UIComponent(pg.sprite.Sprite):
def __init__(self, width=10, height=10, visible=True):
pg.sprite.Sprite.__init__(self)
self.width_percent, self.height_percent = 0, 0
self.x_offset, self.y_offset = 0, 0
self.alignments = []
self.original_image = pg.Surface((width, height))
self.image = self.original_image
self.original_image.set_alpha(100)
self.rect = self.image.get_rect()
def set_image(self, surface):
self.original_image = surface.convert()
self.image = self.original_image
What the surface looks like after surface.convert()
What the actual image looks like.
EDIT:
Request for the code that interacts with UIComponent
to create the sword.
self.slot_icon = UILib.UIComponent()
self.slot_icon.set_image(win.icon)
self.slot_icon.add_alignment(self.slot_icon.relative_width)
self.slot_icon.add_alignment(self.slot_icon.height_ratio_constraint)
self.slot_icon.width_percent = 0.03
self.slot_icon.add_alignment(self.slot_icon.center_x)
self.slot_icon.add_alignment(self.slot_icon.center_y)
In win
:
def __init__(self):
self.s_width = 0
self.s_height = 0
self.screen = pg.display.set_mode()
self.icon = pg.image.load("icon.png")
Upvotes: 0
Views: 2173
Reputation: 101162
There are three different kinds of transparency supported in pygame: colorkeys, surface alphas, and pixel alphas; and you can't easily mix surface alphas and pixel alphas
If you want to use set_alpha
to set the transparency of the entire Surface
, you use surface alpha (that means setting, well, the alpha value of the entire surface).
But the image you want to use is a PNG which uses pixel alpha (that means each pixel has its own alpha value); so you should call convert_alpha
on the Surface
after loading so the image.
If you want to change the surface alpha of such an image, there are basically two ways:
Option 1: use a colorkey
import pygame
import itertools
class UIComponent(pygame.sprite.Sprite):
def __init__(self, width=10, height=10, visible=True):
pygame.sprite.Sprite.__init__(self)
self.width_percent, self.height_percent = 0, 0
self.x_offset, self.y_offset = 0, 0
self.alignments = []
self.original_image = pygame.Surface((width, height))
self.image = self.original_image
self.rect = self.image.get_rect()
def set_image(self, surface):
self.original_image = surface
self.image = pygame.Surface(surface.get_size())
self.image.fill((1,2,3))
self.image.set_colorkey((1,2,3))
self.image.blit(self.original_image.copy(), (0, 0))
self.rect = self.image.get_rect(center=self.rect.center)
def main():
pygame.init()
screen = pygame.display.set_mode((200, 200))
comp = UIComponent()
comp.set_image(pygame.transform.scale2x(pygame.image.load('sword.png').convert_alpha()))
comp.rect.center = screen.get_rect().center
sprites = pygame.sprite.Group(comp)
E = pygame.USEREVENT + 1
alphas = itertools.cycle((10, 100, 200, 255))
pygame.time.set_timer(E, 1000)
while True:
for e in pygame.event.get():
if e.type == pygame.QUIT:
return
if e.type == E:
comp.image.set_alpha(next(alphas))
screen.fill((30, 30, 30))
sprites.update()
sprites.draw(screen)
pygame.display.flip()
main()
Option 2: use a temporary surface and BLEND_RGBA_MULT
to "apply" the transparency:
import pygame
import itertools
class UIComponent(pygame.sprite.Sprite):
def __init__(self, width=10, height=10, visible=True):
pygame.sprite.Sprite.__init__(self)
self.width_percent, self.height_percent = 0, 0
self.x_offset, self.y_offset = 0, 0
self.alignments = []
self.original_image = pygame.Surface((width, height))
self.image = self.original_image
self.rect = self.image.get_rect()
def set_image(self, surface):
self.original_image = surface
self.image = self.original_image.copy()
self.rect = self.image.get_rect(center=self.rect.center)
def set_alpha(self, alpha_value):
tmp = pygame.Surface(self.rect.size, pygame.SRCALPHA)
tmp.fill((255, 255, 255, alpha_value))
self.image = self.original_image.copy()
self.image.blit(tmp, (0, 0), special_flags=pygame.BLEND_RGBA_MULT)
def main():
pygame.init()
screen = pygame.display.set_mode((200, 200))
comp = UIComponent()
comp.set_image(pygame.transform.scale2x(pygame.image.load('sword.png').convert_alpha()))
comp.rect.center = screen.get_rect().center
sprites = pygame.sprite.Group(comp)
E = pygame.USEREVENT + 1
alphas = itertools.cycle((10, 100, 200, 255))
pygame.time.set_timer(E, 1000)
while True:
for e in pygame.event.get():
if e.type == pygame.QUIT:
return
if e.type == E:
comp.set_alpha(next(alphas))
screen.fill((30, 30, 30))
sprites.update()
sprites.draw(screen)
pygame.display.flip()
main()
The result is the same:
Upvotes: 1