How to fill only certain circular parts of the window in pygame?

前端 未结 1 403
误落风尘
误落风尘 2020-12-21 20:11

For this, if you\'re familiar with it, think the dark mode in the boo levels in Super Mario Maker 2. I\'m trying to create a circular spotlight around the character that wil

相关标签:
1条回答
  • 2020-12-21 20:41

    I suggest a solution, which combines a clipping region pygame.Surface.set_clip and drawing a black rectangle with a circular transparent area in the center.

    Define a radius and create a square pygame.Surface with twice the radius.

    radius = 50
    cover_surf = pygame.Surface((radius*2, radius*2))
    

    Set a white color key which identifies the transparent color (set_colorkey) a nd draw a white (transparent) circle on the surface:

    cover_surf.set_colorkey((255, 255, 255))
    pygame.draw.circle(cover_surf, (255, 255, 255), (radius, radius), radius)
    

    Define the center of the circular region which you want to see (in the following clip_center).
    In the main application loop, clear the display and set the clipping region, the draw the scene. Before you update the display draw cover_surf in the clipping region:

    while run:
        # [...]
    
        # clear screen and set clipping region
        screen.fill(0)    
        clip_rect = pygame.Rect(clip_center[0]-radius, clip_center[1]-radius, radius*2, radius*2)
        screen.set_clip(clip_rect)
    
        # draw the scene
        # [...]
    
        # draw transparent circle and update display
        screen.blit(cover_surf, clip_rect)
        pygame.display.flip()
    

    Minimal example: repl.it/@Rabbid76/PyGame-ClipCircularRegion-2

    import pygame
    pygame.init()
    screen = pygame.display.set_mode((500, 500))
    clock = pygame.time.Clock()
    
    radius = 50
    cover_surf = pygame.Surface((radius*2, radius*2))
    cover_surf.fill(0)
    cover_surf.set_colorkey((255, 255, 255))
    pygame.draw.circle(cover_surf, (255, 255, 255), (radius, radius), radius)
    
    run = True
    while run:
        clock.tick(60)
    
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
    
        clip_center = pygame.mouse.get_pos()
    
        # clear screen and set clipping region
        screen.fill(0)    
        clip_rect = pygame.Rect(clip_center[0]-radius, clip_center[1]-radius, radius*2, radius*2)
        screen.set_clip(clip_rect)
    
        # draw the scene
        for x in range(10):
            for y in range(10):
                color = (255, 255, 255) if (x+y) % 2 == 0 else (255, 0, 0)
                pygame.draw.rect(screen, color, (x*50, y*50, 50, 50))
    
        # draw transparent circle and update display
        screen.blit(cover_surf, clip_rect)
        pygame.display.flip()
    

    If you want multiple circular drawing areas, then create a pygame.Surface.set_clip with the same size as the display and set whit color key:

    cover_surf = pygame.Surface((400, 400))
    cover_surf.set_colorkey((255, 255, 255))
    

    Fill the entire surface black and draw white circles on the surface:

    cover_surf.fill(0)
    pygame.draw.circle(cover_surf, (255, 255, 255), (100, 100), 50)
    pygame.draw.circle(cover_surf, (255, 255, 255), (300, 300), 70)
    

    Blit the cover_surf on the window, before updating the display:

    while run:
        # [...]
    
        # draw transparent circle and update display
        screen.blit(cover_surf, (0, 0))
        pygame.display.flip()
    

    Minimal example: repl.it/@Rabbid76/PyGame-ClipCircularRegion-3

    import pygame
    pygame.init()
    screen = pygame.display.set_mode((400, 400))
    clock = pygame.time.Clock()
    
    cover_surf = pygame.Surface((400, 400))
    cover_surf.set_colorkey((255, 255, 255))
    
    px = [100, 200, 300]
    dx = [1, 2, 3] 
    
    run = True
    while run:
        clock.tick(60)
    
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
    
        # create cover surface
        cover_surf.fill(0)
        for i in range(3):
            radius = 40 + i*20
            pygame.draw.circle(cover_surf, (255, 255, 255), (px[i], 100+(i*100)), radius)
            px[i] += dx[i]
            if px[i] < radius or px[i] > 400 - radius:
                dx[i] = -dx[i]
            
        # draw the scene
        for x in range(10):
            for y in range(10):
                color = (255, 255, 255) if (x+y) % 2 == 0 else (255, 0, 0)
                pygame.draw.rect(screen, color, (x*50, y*50, 50, 50))
    
        # draw transparent circle and update display
        screen.blit(cover_surf, (0, 0))
        pygame.display.flip()
    
    0 讨论(0)
提交回复
热议问题