How do I focus light or how do I only draw certain circular parts of the window in pygame?
Solution 1:
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()