Anish Shanbhag
Anish Shanbhag

Reputation: 424

Transparent Image in Pygame

I have a sprite in Pygame that is a blue circle. I want this image to be drawn to the screen "faded", e.g. translucent. However, I don't want a translucent rectangle to be drawn over it; instead, I want the actual image to be modified and made translucent. Any help is greatly appreciated!

Right now I have:

Class Circle(pygame.sprite.Sprite):

    self.image = self.image = pygame.image.load("circle.png")

circle = Circle()

and eventually...

window.blit(pygame.transform.scale(circle.image, (zoom, zoom)), (100, 100))

How the circle.png looks:

enter image description here

How I want the image to look after making it transparent:

enter image description here

I am blitting the image onto the window, which is a white background.

Upvotes: 4

Views: 5335

Answers (3)

skrx
skrx

Reputation: 20488

First, your image/surface needs to use per-pixel alpha, therefore call the convert_alpha() method when you load it. If you want to create a new surface (as in the example), you can also pass pygame.SRCALPHA to pygame.Surface.

The second step is to create another surface (called alpha_surface here) which you fill with white and the desired alpha value (the fourth element of the color tuple).

Finally, you have to blit the alpha_surface onto your image and pass pygame.BLEND_RGBA_MULT as the special_flags argument. That will make the opaque parts of the image translucent.

import pygame as pg


pg.init()
screen = pg.display.set_mode((800, 600))
clock = pg.time.Clock()
BLUE = pg.Color('dodgerblue2')
BLACK = pg.Color('black')

# Load your image and use the convert_alpha method to use
# per-pixel alpha.
# IMAGE = pygame.image.load('circle.png').convert_alpha()
# A surface with per-pixel alpha for demonstration purposes.
IMAGE = pg.Surface((300, 300), pg.SRCALPHA)
pg.draw.circle(IMAGE, BLACK, (150, 150), 150)
pg.draw.circle(IMAGE, BLUE, (150, 150), 130)

alpha_surface = pg.Surface(IMAGE.get_size(), pg.SRCALPHA)
# Fill the surface with white and use the desired alpha value
# here (the fourth element).
alpha_surface.fill((255, 255, 255, 90))
# Now blit the transparent surface onto your image and pass
# BLEND_RGBA_MULT as the special_flags argument. 
IMAGE.blit(alpha_surface, (0, 0), special_flags=pg.BLEND_RGBA_MULT)

done = False
while not done:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            done = True

    screen.fill((50, 50, 50))
    pg.draw.rect(screen, (250, 120, 0), (100, 300, 200, 100))
    screen.blit(IMAGE, (150, 150))

    pg.display.flip()
    clock.tick(60)

pg.quit()

Upvotes: 4

Gomes J. A.
Gomes J. A.

Reputation: 1485

As the Surface.set_alpha() documentation says, you can have surfaces with "homogeneous alpha" or per pixel alpha, but not both, wich I believe is what you want. It might work with colorkey transparency, but I'm not sure (I didn't tested that yet). Any non RGBA (without active alpha channel) pixel format might work if you use set_colorkey() and set_alpha() before blitting.

So, the code might look like:

class Circle(pygame.sprite.Sprite):
    def __init__(self)
        self.image = pygame.image.load("circle.png")
        # get the surface's top-left pixel color and use it as colorkey
        colorkey = self.image.get_at((0, 0))
        self.image.set_colorkey(colorkey)

At some point in your code (immediately before rendering) you might want to set the transparency by calling:

circle.image.set_alpha(some_int_val)

And then you can scale and blit it as intended.

Upvotes: 1

Andy
Andy

Reputation: 263

Create a new Surface with per-pixel alpha.

surf = pygame.Surface((circle_width, circle_height), pygame.SRCALPHA)

Make the surface transparent

surf.set_alpha(128)  # alpha value

Draw the circle to that surface at (x=0, y=0)

surf.blit(pygame.transform.scale(circle.image, (zoom, zoom)), (0, 0))

Draw the surface to the window

window.blit(surf, (circle_x, circle_y))

Upvotes: 0

Related Questions