Как заполнить только определенные части окна в pygame? - PullRequest
1 голос
/ 07 мая 2020

Для этого, если вы знакомы с этим, подумайте о темном режиме на уровнях Boo в Super Mario Maker 2. Я пытаюсь создать круговой прожектор вокруг персонажа, который также сделает видимым все, что находится в диапазоне кругов. (например, часть пола, на которой стоит человек, враг или что-либо еще с места происшествия). Мой план - сначала нарисовать круг / прожектор, затем сцену, а затем персонажа. Затем я хочу, чтобы все, что не было выделено прожектором, было затемнено.

Итак, мой вопрос:

Кто-нибудь знает, как заполнить весь экран, за исключением того, что находится внутри круга?

1 Ответ

3 голосов
/ 07 мая 2020

Я предлагаю решение, которое объединяет область отсечения pygame.Surface.set_clip и рисование черного прямоугольника с круглой прозрачной областью в центре.

Определите радиус и создайте квадрат pygame.Surface с удвоенным радиусом.

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

Установите ключ белого цвета, который определяет прозрачный цвет (set_colorkey) и нарисуйте белый (прозрачный ) круг на поверхности:

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

Определите центр круговой области, которую вы хотите видеть (в следующем clip_center).
В основном приложении l oop очистите отобразить и установить область отсечения, нарисовать сцену. Перед обновлением дисплея нарисуйте cover_surf в области отсечения:

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()

См. Пример:

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()

Если вам нужно несколько круговых областей рисования, создайте pygame.Surface.set_clip с тем же размером, что и дисплей, и установите белый цветовой ключ:

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

Заполните всю поверхность черным и нарисуйте белые круги на поверхности:

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 cover_surf в окне перед обновлением дисплея:

while run:
    # [...]

    # draw transparent circle and update display
    screen.blit(cover_surf, (0, 0))
    pygame.display.flip()

См. пример:

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()
...