如何测试一个点是否在椭圆中?
How can I test if a point is in an ellipse?
我正在做一个 Pygame 项目,地图上有水。如果玩家进入水中,我想放慢玩家的速度。 有水的区域呈椭圆形。如果形状为矩形,我可以减慢播放器的速度,但我不希望非水区域减慢播放器的速度。那么我怎样才能得到玩家应该减速的区域呢? 如何控制人物坐标是否在椭圆内?
编辑:我检查了评论中的 link,它对我有用。
椭圆与点的碰撞可以简化为圆与点的碰撞,方法是将椭圆缩放为圆,缩放点到椭圆中心的距离向量同样的方式。由于椭圆在 PyGame 中是轴对齐的,这可以很容易地通过按 ellipse 轴长度的比例缩放其中一个坐标来实现。
定义椭圆(ellipse_rect
)的外接矩形(pygame.Rect
)并得到半轴(a
,b
):
a = ellipse_rect.width // 2
b = ellipse_rect.height // 2
计算半轴的比例
scale_y = a / b
定义一个点(test_x
,test_y
)并计算该点到椭圆中心的向量(cpt_x
,cpt_y
)。用半x轴和半y轴的比例缩放向量的y坐标:
cpt_x, cpt_y = ellipse_rect.center
dx = test_x - cpt_x
dy = (test_y - cpt_y) * scale_y
如果Euclidean distance(dx*dx + dy*dy
)的平方小于半x轴(a*a
)的平方,则点在椭圆内:
collide = dx*dx + dy*dy <= a*a
另见 Collision and Intersection - Point and Ellipse
最小示例:
import pygame
pygame.init()
width, height = 400, 400
window = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
ellipse_rect = pygame.Rect(0, 0, 200, 100)
ellipse_rect.center = window.get_rect().center
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
a = ellipse_rect.width // 2
b = ellipse_rect.height // 2
scale_y = a / b
cpt_x, cpt_y = ellipse_rect.center
test_x, test_y = pygame.mouse.get_pos()
dx = test_x - cpt_x
dy = (test_y - cpt_y) * scale_y
collide = dx*dx + dy*dy <= a*a
window.fill(0)
color = (127, 0, 0) if collide else (0, 127, 0)
pygame.draw.ellipse(window, color, ellipse_rect)
if collide:
pygame.draw.ellipse(window, (255, 255, 255), ellipse_rect, 3)
pygame.display.flip()
pygame.quit()
exit()
我正在做一个 Pygame 项目,地图上有水。如果玩家进入水中,我想放慢玩家的速度。 有水的区域呈椭圆形。如果形状为矩形,我可以减慢播放器的速度,但我不希望非水区域减慢播放器的速度。那么我怎样才能得到玩家应该减速的区域呢? 如何控制人物坐标是否在椭圆内?
编辑:我检查了评论中的 link,它对我有用。
椭圆与点的碰撞可以简化为圆与点的碰撞,方法是将椭圆缩放为圆,缩放点到椭圆中心的距离向量同样的方式。由于椭圆在 PyGame 中是轴对齐的,这可以很容易地通过按 ellipse 轴长度的比例缩放其中一个坐标来实现。
定义椭圆(ellipse_rect
)的外接矩形(pygame.Rect
)并得到半轴(a
,b
):
a = ellipse_rect.width // 2
b = ellipse_rect.height // 2
计算半轴的比例
scale_y = a / b
定义一个点(test_x
,test_y
)并计算该点到椭圆中心的向量(cpt_x
,cpt_y
)。用半x轴和半y轴的比例缩放向量的y坐标:
cpt_x, cpt_y = ellipse_rect.center
dx = test_x - cpt_x
dy = (test_y - cpt_y) * scale_y
如果Euclidean distance(dx*dx + dy*dy
)的平方小于半x轴(a*a
)的平方,则点在椭圆内:
collide = dx*dx + dy*dy <= a*a
另见 Collision and Intersection - Point and Ellipse
最小示例:
import pygame
pygame.init()
width, height = 400, 400
window = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()
ellipse_rect = pygame.Rect(0, 0, 200, 100)
ellipse_rect.center = window.get_rect().center
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
a = ellipse_rect.width // 2
b = ellipse_rect.height // 2
scale_y = a / b
cpt_x, cpt_y = ellipse_rect.center
test_x, test_y = pygame.mouse.get_pos()
dx = test_x - cpt_x
dy = (test_y - cpt_y) * scale_y
collide = dx*dx + dy*dy <= a*a
window.fill(0)
color = (127, 0, 0) if collide else (0, 127, 0)
pygame.draw.ellipse(window, color, ellipse_rect)
if collide:
pygame.draw.ellipse(window, (255, 255, 255), ellipse_rect, 3)
pygame.display.flip()
pygame.quit()
exit()