2

I am currently working on making a pygame code that draws a polygon on top of existing JPG.

What I do is draw 2 surfaces, one for the Background JPG at the bottom and another for the polygon on top. For the polygon surface, I need to give "SRCALPHA" property to the surface so that no background Fill will block the view at the Background JPG. However, when I do this, I cannot use polygon surface.set_alpha to control polygon's transparency.

What is the method to do this or should I entirely change my approach?

Edit: After this problem is solved, i get another problem in similar thing, please see Python pygame alpha in text and help me if you know the solution. Thank you very much.

HA HA chan
  • 123
  • 1
  • 9
  • maybe conver to `RGBA` and use use colors `(r, g, b, 0)` to get transparent pixels (instead of using `SRCALPHA`) - or first `blit` image with `SRCALPHA` to new surface to get pixels `RGBA` but without `SRCALPHA` – furas Aug 16 '20 at 07:27
  • I am sorry that i don't know how to convert to RGBA. Would you mind giving me a demonstration code on how to do this? For the polygon, i am drawing it by pygame.draw.polygon(), the 4th input in color seems not influencing result. Also, i want the image to be at bottom, so its transparency should have no effect. Thank you very much. – HA HA chan Aug 16 '20 at 09:38
  • 1
    to convert existing surface/image [image.conver_alpha()](https://www.pygame.org/docs/ref/surface.html#pygame.Surface.convert_alpha) – furas Aug 17 '20 at 12:33
  • see example [complex tarnsparency](https://github.com/furas/python-examples/tree/master/pygame/transparency/complex-example) – furas Aug 17 '20 at 12:40
  • Thank you. I tried to use surface().convert_alpha() with surf.fill((0,0,0,0)), and gives 4th input in color while drawing polygon. It works and give me the result that polygon are with 50% transparency. – HA HA chan Aug 25 '20 at 16:36

1 Answers1

3

You are mixing two things together that you do not need to (and cannot mix). However you do not need to use set_alpha() to achieve what you want.

SRCALPHA tells it that you are going to use per pixel alpha on this surface. If you read the docs here you will find it says 'SRCALPHA the pixel format will include a per-pixel alpha'. Here you see that the docs for set_alpha() indicate it is incompatible with per-pixel alpha 'For a surface with per pixel alpha, blanket alpha is ignored' (unless you are using pygame 2 which I doubt).

From your description of the problem, I doubt that you need set_alpha though. If you have created your upper surface to use per pixel alpha with "SRCALPHA" then the pixels you do not draw will already be transparent. when you blit it over the other surface only the polygon you drew should be transferred.

Here is an example:

GREEN = pygame.Color('green')
RED = pygame.Color('red')

size = (800, 400)
    
pygame.init()
screen = pygame.display.set_mode(size)

lowersurf = pygame.Surface(size)
lowersurf.fill(GREEN)

polysurf = pygame.Surface(size, flags=pygame.SRCALPHA)
pygame.draw.polygon(polysurf, RED, ((100, 100), (600, 100), (600, 200), (350, 300), (100, 200)), 4)

lowersurf.blit(polysurf, (0, 0))

screen.blit(lowersurf, (0, 0))
pygame.display.flip()

It draws a polygon outline on the transparent polysurf and then blits that onto the normal lowersurf.

Then it blits the resulting lowersurf onto the screen.

Edit:

In a comment the OP asked how to draw the polygon onto the lowersurf with transparency so that it would have 50% transparency. One way that can be done by drawing the images onto the polysurf with as partially transparent. Like this:

GREEN = pygame.Color('green')
RED = pygame.Color('red')

transparent_red = RED
transparent_red[3] = 125

size = (800, 400)
    
pygame.init()
screen = pygame.display.set_mode(size)

lowersurf = pygame.Surface(size)
lowersurf.fill(GREEN)

polysurf = pygame.Surface(size, flags=pygame.SRCALPHA)
pygame.draw.polygon(polysurf, transparent_red, ((100, 100), (600, 100), (600, 200), (350, 300), (100, 200)), 4)

lowersurf.blit(polysurf, (0, 0))

screen.blit(lowersurf, (0, 0))
pygame.display.flip()

This creates a color transparent_red that is 50% transparent. The fourth parameter in the color is the alpha value and it ranges from 0 (fully transparent) to 255 (fully opaque), and so 125 is halfway.

A further approach, which is likely what you really want, is to do this with the entire polysurf and not just specific things drawn onto it. Draw the entire polysurf as originally done and then adjust the alpha of the entire surface before drawing it. Like this:

GREEN = pygame.Color('green')
RED = pygame.Color('red')

size = (800, 400)

blend_alpha = 125
    
pygame.init()
screen = pygame.display.set_mode(size)

lowersurf = pygame.Surface(size)
lowersurf.fill(GREEN)

polysurf = pygame.Surface(size, flags=pygame.SRCALPHA)
pygame.draw.polygon(polysurf, RED, ((100, 100), (600, 100), (600, 200), (350, 300), (100, 200)), 4)

transparent_polysurf = polysurf.copy()
transparent_polysurf.fill((255, 255, 255, blend_alpha), special_flags=pygame.BLEND_RGBA_MULT)

lowersurf.blit(transparent_polysurf, (0, 0))

screen.blit(lowersurf, (0, 0))
pygame.display.flip()

In this example I copied the polysurf and then used the fill() using special_flags=pygame.BLEND_RGBA_MULT (see docs here) on the copy to make it partially transparent before blit'ing the copy. I did that so the original is unaffected, but if you don't care, then you can do the blending fill() directly on polysurf without making a copy.

As I said, you likely want to go with the last approach since it blends everything from polysurf with the same level of transparency. The other approach is useful if you want to blend different things drawn to polysurf with different transparency levels.

Glenn Mackintosh
  • 2,765
  • 1
  • 10
  • 18
  • In your example, the lowersurf can be view as green at location outside polygon, but how can i do so that the polygon have 50% transparency? (such that we can see mixture color of green and red) Thank you. – HA HA chan Aug 25 '20 at 16:14
  • @HAHAchan See the edit in the above answer. It shows two ways to do what you ask. – Glenn Mackintosh Aug 25 '20 at 23:18