Trianglular picture in pygame

44 Views Asked by At

Is it possible to put a picture in a triangle (or any polygon) in pygame?

It is easy to do on a rectangle so is it possible to maybe have a rectangle over a triangle and only show the union of the two shapes?

eg. I only want the part inside the white triangle to show on screen

I tried fitting the picture as rectangle but giving traingle coordinates, It did not work.

1

There are 1 best solutions below

0
Rabbid76 On

If you just want to clip an image, you can use the pygame.maks module.

Convert a pygame.mask.Mask to a pygame.Surface with pygame.mask.Mask.to_surface. Use setsurface to specify the source image and the unsetcolor argument to specify the transparent background:

def clip_surface(surf, mask):
    return mask.to_surface(setsurface = surf.convert_alpha(), unsetcolor = (0, 0, 0, 0))

The mask can be created for example from a triangular polygon:

mask_image = pygame.Surface(image.get_size(), pygame.SRCALPHA)
pygame.draw.polygon(mask_image, (255, 255, 255), [(100, 200), (0, 0), (200, 0)])
mask = pygame.mask.from_surface(mask_image)

Minimal example:

import pygame

def clip_surface(surf, mask):
    return mask.to_surface(setsurface = surf.convert_alpha(), unsetcolor = (0, 0, 0, 0))

def checker_image(ts, w, h, c1, c2):
    surf = pygame.Surface((w, h))
    [pygame.draw.rect(surf, c1 if (x+y) % 2 == 0 else c2, (x*ts, y*ts, ts, ts)) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
    return surf

pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()

try:
    image = pygame.image.load('Apple.png')
except:
    image = checker_image(20, 200, 200, (255, 128, 128), (255, 64, 64))
image = pygame.transform.scale(image, (200, 200))

background = checker_image(40, *window.get_size(), (129, 128, 128), (96, 96, 96))
mask_image = pygame.Surface(image.get_size(), pygame.SRCALPHA)
pygame.draw.polygon(mask_image, (255, 255, 255), [(100, 200), (0, 0), (200, 0)])
mask = pygame.mask.from_surface(mask_image)

clipped_image = clip_surface(image, mask)
image.set_alpha(127)

run = True
while run:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False          

    window.blit(background, (0, 0))
    image_rect = clipped_image.get_rect(center = window.get_rect().center)
    window.blit(image, image_rect)
    window.blit(clipped_image, image_rect)
    pygame.draw.rect(window, (0, 0, 0), image_rect, 3)
    pygame.draw.polygon(window, (255, 0, 0), [(150, 250), (50, 50), (250, 50)], 1)
    pygame.display.flip()

pygame.quit()
exit()