Pygame: How to draw in non rectangle clipping area

2019-04-30 04:02发布

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

2条回答
倾城 Initia
2楼-- · 2019-04-30 04:50

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.

查看更多
Evening l夕情丶
3楼-- · 2019-04-30 05:01

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()
查看更多
登录 后发表回答