Python 椭圆与圆的碰撞检测
我想在椭圆和圆之间进行碰撞检测。我这样做的方式是:Python 椭圆与圆的碰撞检测,python,math,pygame,collision-detection,ellipse,Python,Math,Pygame,Collision Detection,Ellipse,我想在椭圆和圆之间进行碰撞检测。我这样做的方式是: 计算从椭圆中心到圆的角度 计算该点在该角度的椭圆中的位置 检查是否与该点发生碰撞 然而,我有一个小问题。当我计算角度时,它好像偏离了90度。我做了一个肮脏的修正,简单地增加了1.5弧度来解释90度,这有点工作,但存在不一致性,在某些角度下不能正常工作,特别是在0.7和-2.6弧度左右。这是代码(所有的冲突内容都在collision类中的eliple方法中) 导入pygame 从数学输入sin,cos,atan2,弧度 pygame.init()
collision
类中的eliple
方法中)
导入pygame
从数学输入sin,cos,atan2,弧度
pygame.init()
SW=1200
SH=600
WIN=pygame.display
D=赢。设置_模式((SW,SH))
班级圈子:
定义初始(自身,半径):
self.x=0
self.y=0
自半径=半径
def更新(自我,pos):
self.x=pos[0]
self.y=pos[1]
def绘图(自显示):
pygame.draw.circle(显示,(255,0,0),(int(self.x),int(self.y)),self.radius,2)
圆圈=圆圈(30)
类椭圆:
定义初始值(自身、中心、接收、ry):
自我中心
self.collide=False
self.rx=rx
self.ry=ry
def绘图(自显示):
角度=0
当角度<6.28时:
角度+=0.001
x=自中心[0]+sin(角度)*自接收
y=自中心[1]+cos(角度)*自中心
如果自碰撞:
显示。将_设置为((int(x),int(y)),(255,0,0))
其他:
显示。将_设置为((int(x),int(y)),(0,0,255))
pygame.draw.circle(D,(0,255,0),(int(自中心[0]),int(自中心[1])),5)
def碰撞(自身、圆):
#与圆成角度
dx=圆x-自中心[0]
dy=圆y-自中心[1]
角度=atan2(-dy,dx)
打印(角度)
#点位于椭圆中该角度处的位置
x=sin(角度+1.5)*self.rx+self.center[0]
y=cos(角度+1.5)*self.ry+self.center[1]
#打印(x,y)
#绘制点只是为了确保其工作正常
#(调试)
pygame.draw.circle(D,(0,255,0),(int(x),int(y)),5)
#我们刚才看到的点之间的距离
#计算出圆的中心
距离=((x-circle.x)**2+(y-circle.y)**2)**0.5
#打印(距离)
#碰撞条件
如果距离<圆半径:
self.collide=True
其他:
self.collide=False
椭圆=椭圆([600300],300200)
尽管如此:
events=pygame.event.get()
mousePos=pygame.mouse.get_pos()
对于事件中的事件:
如果event.type==pygame.QUIT:
pygame.quit()
D.填充((255、255、255))
循环更新(鼠标点)
画圆(D)
椭圆图(D)
椭圆.碰撞(圆)
pygame.display.flip()
第一个错误是,1.5不等于pi/2:
从数学导入pi
x=sin(角度+1.5)*self.rx+self.center[0]
y=cos(角度+1.5)*self.ry+self.center[1]
x=sin(角度+pi/2)*self.rx+self.center[0]
y=cos(角度+pi/2)*自转角+自中心[1]
第二,通过角度计算椭圆上的点稍微复杂一些。请参见问题的答案和:
从数学导入pi、sin、cos、atan2、弧度、copysign、sqrt
类椭圆:
# [...]
def pointFromAngle(自身,a):
c=cos(a)
s=sin(a)
ta=s/c##tan(a)
tt=ta*self.rx/self.ry#tan(t)
d=1sqrt(1.+tt*tt)
x=自中心[0]+复制符号(自接收*d,c)
y=自中心[1]-复制符号(自中心*tt*d,s)
返回x,y
def碰撞(自身、圆):
# [...]
#点位于椭圆中该角度处的位置
x、 y=自身点fromAngle(角度)
# [...]
最简单的例子:
导入数学
导入pygame
班级圈子:
定义初始(自、中心x、中心y、半径):
self.center=中心x,中心y
自半径=半径
def更新(自我、中心x、中心y):
self.center=中心x,中心y
def绘图(自、表面):
pygame.draw.circle(曲面,(255,0,0),(圆(自中心[0])、圆(自中心[1])、自半径,3)
类椭圆:
定义初始(自、中心、顶点):
self.center=中心
self.collide=False
self.vertex=顶点
def绘图(自、表面):
bounding_rect=pygame.rect(0,0,self.vertex[0]*2,self.vertex[1]*2)
边界中心=圆形(自中心[0]),圆形(自中心[1])
pygame.draw.ellipse(曲面,(0,255,0),边界矩形,3)
def pointFromAngle(自身,a):
c=数学cos(a)
s=数学。sin(a)
ta=s/c##tan(a)
tt=ta*self.vertex[0]/self.vertex[1]##tan(t)
d=1数学sqrt(1.+tt*tt)
x=self.center[0]+数学复制符号(self.vertex[0]*d,c)
y=self.center[1]-数学复制符号(self.vertex[1]*tt*d,s)
返回x,y
定义相交圆椭圆(圆,椭圆):
dx=圆.中心[0]-椭圆.中心[0]
dy=圆.中心[1]-椭圆.中心[1]
角度=数学常数2(-dy,dx)
x、 y=椭圆。点从角度(角度)
距离=数学形(x-圆.中心[0],y-圆.中心[1])
返回距离谢谢你的回答。我明白为什么你发布的解决方案会起作用,但我不明白为什么我的解决方案不起作用,因为画的点清楚地一直在椭圆上。我很困惑。@hippozipos你用不同的方法缩放了sin(角度)
和cos(角度)
import pygame
from math import sin, cos, atan2, radians
pygame.init()
SW = 1200
SH = 600
WIN = pygame.display
D = WIN.set_mode((SW, SH))
class Circle:
def __init__(self, radius):
self.x = 0
self.y = 0
self.radius = radius
def update(self, pos):
self.x = pos[0]
self.y = pos[1]
def draw(self, display):
pygame.draw.circle(display, (255, 0, 0), (int(self.x), int(self.y)), self.radius, 2)
circle = Circle(30)
class Ellipse:
def __init__(self, centre, rx, ry):
self.centre = centre
self.collided = False
self.rx = rx
self.ry = ry
def draw(self, display):
angle = 0
while angle < 6.28:
angle += 0.001
x = self.centre[0] + sin(angle)* self.rx
y = self.centre[1] + cos(angle)* self.ry
if self.collided:
display.set_at((int(x), int(y)), (255, 0, 0))
else:
display.set_at((int(x), int(y)), (0, 0, 255))
pygame.draw.circle(D, (0, 255, 0), (int(self.centre[0]), int(self.centre[1])), 5)
def collision(self, circle):
#angle to the circle
dx = circle.x - self.centre[0]
dy = circle.y - self.centre[1]
angle = atan2(-dy, dx)
print(angle)
#where the point lies in the ellipse at that angle
x = sin(angle + 1.5)* self.rx + self.centre[0]
y = cos(angle + 1.5)* self.ry + self.centre[1]
#print(x, y)
#drawing the point just to make sure its working
# (debugging)
pygame.draw.circle(D, (0, 255, 0), (int(x), int(y)), 5)
# distance between the point we just
# calculated and the circle's centre
distance = ((x-circle.x)**2 + (y-circle.y)**2)**0.5
#print(distance)
#collision condition
if distance < circle.radius:
self.collided = True
else:
self.collided = False
ellipse = Ellipse([600, 300], 300, 200)
while True:
events = pygame.event.get()
mousePos = pygame.mouse.get_pos()
for event in events:
if event.type == pygame.QUIT:
pygame.quit()
D.fill((255, 255, 255))
circle.update(mousePos)
circle.draw(D)
ellipse.draw(D)
ellipse.collision(circle)
pygame.display.flip()