[英]Fill the area of intersection of two Circles in Pygame
I am working on a pygame project and I encountered a problem.我正在做一个 pygame 项目,我遇到了一个问题。 I have two circles A and B as shown below.
我有两个圆圈 A 和 B,如下所示。 Which are overlapped Now I want to fill only some part of the circle which is common to both circles.
哪些是重叠的现在我只想填充两个圆圈共有的圆圈的一部分。 Is there any way to achieve that?
有什么办法可以实现吗?
I know I can fill circle B with red colour and circle A with white, but there is a certain area and circle A goes outside that area.我知道我可以用红色填充圆 B,用白色填充圆 A,但是有一个特定的区域,而圆 A 超出了该区域。 So I cannot implement that.
所以我无法实施。
The image of circles and filled position is mentioned in this image:此图像中提到了圆圈和填充 position 的图像:
Create 2 pygame.Surface
objects with per pixel alpha ( pygame.SRCALPHA
):创建 2 个具有每个像素 alpha 的
pygame.Surface
对象( pygame.SRCALPHA
):
surf1 = pygame.Surface((500, 500), pygame.SRCALPHA)
surf2 = pygame.Surface((500, 500), pygame.SRCALPHA)
Define the center point and radius of the 2 circles:定义 2 个圆的中心点和半径:
pos1, rad1 = (250, 200), 100
pos2, rad2 = (250, 250), 80
Draw the circles on the 2 surfaces, with the same color:用相同的颜色在 2 个表面上绘制圆圈:
pygame.draw.circle(surf1, (255, 0, 0, 255), pos1, rad1)
pygame.draw.circle(surf2, (255, 0, 0, 255), pos2, rad2)
Blend one surface on the other, using the blend mode pygame.BLEND_RGBA_MIN
:使用混合模式
pygame.BLEND_RGBA_MIN
混合一个表面到另一个表面:
surf1.blit(surf2, (0, 0), special_flags = pygame.BLEND_RGBA_MIN)
At this point surf1
contains the intersection area of the 2 circles.此时
surf1
包含 2 个圆的相交区域。
To get the outer section, another step is required.要获得外部部分,还需要另一个步骤。 Blend
surf1
on surf2
, using the blend mode pygame.BLEND_RGBA_MIN
:在
surf1
上混合surf2
,使用混合模式pygame.BLEND_RGBA_MIN
:
surf2.blit(surf1, (0, 0), special_flags = pygame.BLEND_RGBA_SUB)
Now surf2
contains the the part of circle B which is left if circle A is subtracted:现在
surf2
包含圆 B中减去圆 A后剩下的部分:
Minimal example:最小的例子:
repl.it/@Rabbid76/PyGame-CircleIntersection
repl.it/@Rabbid76/PyGame-CircleIntersection
import pygame
pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()
pos1, rad1 = (250, 200), 100
pos2, rad2 = (250, 250), 80
surf1 = pygame.Surface((500, 500), pygame.SRCALPHA)
surf2 = pygame.Surface((500, 500), pygame.SRCALPHA)
pygame.draw.circle(surf1, (255, 0, 0, 255), pos1, rad1)
pygame.draw.circle(surf2, (255, 0, 0, 255), pos2, rad2)
surf1.blit(surf2, (0, 0), special_flags = pygame.BLEND_RGBA_MIN)
surf2.blit(surf1, (0, 0), special_flags = pygame.BLEND_RGBA_SUB)
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
print(pygame.key.name(event.key))
window.fill((255, 255, 255))
window.blit(surf2, (0, 0))
pygame.draw.circle(window, (128, 128, 128), pos1, rad1+1, 3)
pygame.draw.circle(window, (128, 128, 128), pos2, rad2+1, 3)
pygame.display.flip()
I couldn't find a way to do it with pygame
functions, so I made a quick demo on how to do it yourself here:我找不到使用
pygame
函数的方法,所以我在这里做了一个关于如何自己做的快速演示:
import pygame
import math
import time
# Screen dimensions
WIDTH = 600
HEIGHT = 400
# Circle and screen colours
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# Circle data
BIGGER_POS = (300, 150)
SMALLER_POS = (300, 220)
BIGGER_RADIUS = 130
SMALLER_RADIUS = 100
BIGGER_COLOUR = GREEN
SMALLER_COLOUR = BLUE
INTERSECTION_COLOUR = RED
def prepare_screen():
"""
Create the initial screen.
"""
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
screen.fill(WHITE)
return screen
def draw_circles(screen):
"""
Draw the circles and wait to visually inspect what they look like.
"""
bigger = pygame.draw.circle(screen, BIGGER_COLOUR, BIGGER_POS, BIGGER_RADIUS)
smaller = pygame.draw.circle(screen, SMALLER_COLOUR, SMALLER_POS, SMALLER_RADIUS)
pygame.display.update()
time.sleep(3)
return bigger, smaller
def calculate_distance(p1: tuple, p2: tuple):
"""
Calculate distance between two points p1 and p2.
"""
return math.sqrt(((p1[0] - p2[0])**2) + ((p1[1] - p2[1])**2))
def draw_intersection(screen, bigger, smaller):
"""
Animation to mark intersecting points with red.
Ideally this should only go through colliding points, but I'm lazy and made it iterate through all pixels
instead.
"""
for x in range(WIDTH):
for y in range(HEIGHT):
print("Checking point", x, y)
# A point is in the intersection if it's within the radius-es of both circles
if calculate_distance(bigger.center, (x, y)) <= BIGGER_RADIUS and \
calculate_distance(smaller.center, (x, y)) <= SMALLER_RADIUS:
screen.set_at((x, y), INTERSECTION_COLOUR)
pygame.display.update()
# Get screen to draw on
screen = prepare_screen()
# Draw some initial circles
bigger, smaller = draw_circles(screen)
# Draw the intersection
draw_intersection(screen, bigger, smaller)
# Finally sleep some to allow visual inspection, and quit
time.sleep(3)
pygame.quit()
Feel free to adjust as needed - note that various places can be optimised, made more readable etc.根据需要随意调整 - 请注意,可以优化各个地方,使其更具可读性等。
Result:结果:
Let me know if anything's unclear.让我知道是否有任何不清楚的地方。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.