Pygame: How to draw in non rectangle clipping area

2019-04-30 04:09发布

问题:

Hi I would like to set in pygame non rectangle clipping area (in this case as character "P"), where it would be strict limited, where to draw another objects.

Is there any option?

thanks a lot

回答1:

Let's see if I correctly understand your question: you want to "blit" an image onto a surface, but do it through a mask which would only allow certain pixels of the source to actually end up on the surface?

I had this precise problem and at first I thought it would only be doable through PIL. However after some reading and experimentation, it turns out that it can actually be done with the help of pygame's rather obscure "special flags". Below is a function which hopefully does what you want.

def blit_mask(source, dest, destpos, mask, maskrect):
    """
    Blit an source image to the dest surface, at destpos, with a mask, using
    only the maskrect part of the mask.
    """
    tmp = source.copy()
    tmp.blit(mask, maskrect.topleft, maskrect, special_flags=pygame.BLEND_RGBA_MULT)
    dest.blit(tmp, destpos, dest.get_rect().clip(maskrect))

The mask should be white where you want it to be transparent and black otherwise.



回答2:

And here is full code, that blits 2 rects on "Hello World! :D" text. Enjoy.

import pygame, sys, time
from pygame.constants import QUIT
pygame.init()

windowSurface = pygame.display.set_mode((800, 600), 0, 32)
pygame.display.set_caption('Hello World!')

WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)

basicFont = pygame.font.SysFont("Times New Roman", 100)

text = basicFont.render('Hello world! :D', True, WHITE)

def blit_mask(source, dest, destpos, mask, maskrect):

        """
        Blit an source image to the dest surface, at destpos, with a mask, using
        only the maskrect part of the mask.
        """
        windowSurface.fill(WHITE)
        tmp = source.copy()

        tmp.blit(mask, destpos, maskrect, special_flags=pygame.BLEND_RGBA_MULT)  # mask 1 green


        tmp.blit(red, (destpos[0]+100,0), maskrect, special_flags=pygame.BLEND_RGBA_MULT)  # mask 2 red

        dest.blit(tmp, (0,0), dest.get_rect().clip(maskrect))

        pygame.display.update()

red = pygame.Surface((200,100))
red.fill(RED)

green = pygame.Surface((100,100),0)
green.fill(GREEN)

for a in range(700):
    blit_mask(text, windowSurface , (a,0), green, (0,0,800,600))

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()