我正在制作一款益智游戏,要求用户在背景上“画圆”以将球送到出口。他们通过按住鼠标按钮创建圆圈,圆圈增大;当它足够大的时候,它们就会松开,然后它被“打孔”进入物理空间,然后球会对它作出反应。
然而,我有一个问题,当两个圆相交时(因此球应该通过),如果交点不大于球的直径,则球与内部碰撞这个圈子像往常一样。
这可能有点难以理解,所以这里有一个显示问题的截屏视频链接(你无法在Stack Overflow上嵌入视频):http://www.youtube.com/watch?v=3dKyPzqTDhs
希望这使我的问题清楚。以下是Ball
和Circle
类的Python / PyGame代码:
class Ball():
def __init__(self, (x,y), size, colourID):
"""Setting up the new instance"""
self.x = x
self.y = y
self.size = size
self.exited = False
self.colour = setColour(colourID)
self.thickness = 0
self.speed = 0.01
self.angle = math.pi/2
def display(self, surface):
"""Draw the ball"""
# pygame.gfxdraw.aacircle(screen,cx,cy,new_dist,settings['MINIMAP_RINGS'])
if self.exited != True:
pygame.draw.circle(surface, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)
def move(self):
"""Move the ball according to angle and speed"""
self.x += math.sin(self.angle) * self.speed
self.y -= math.cos(self.angle) * self.speed
(self.angle, self.speed) = module_physicsEngine.addVectors((self.angle, self.speed), gravity)
self.speed *= drag
Circle
类:
class Circle():
def __init__(self, (x,y), size, colourID):
"""Set up the new instance of the Circle class"""
self.x = x
self.y = y
self.size = size
self.colour = setColour(colourID)
self.thickness = 2
self.angle = 0 # Needed for collision...
self.speed = 0 # detection against balls
def display(self, surface):
"""Draw the circle"""
pygame.draw.circle(surface, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)
在游戏的主循环(while running == True:
等)中,此代码用于对每个球执行操作:
for b in balls:
b.move()
for i, ball in enumerate(balls):
for ball2 in balls[i+1:]:
collideBalls(ball, ball2)
collideCircle(b) # <---------------- This is the important line
collideExit(b)
b.display(screen)
最后,collideCircle(b)
函数,每个球调用一次以检查与圆内部的碰撞,并检查圆是否相交。
def collideCircle(ball):
"""Check for collision between a ball and a circle"""
hit = False
closestDist = 0
for c in circles:
# Code cannot be replaced with physicsEngine.collideTest because it
# is slightly differnt, testing if ball [ball] inside a circle [c]
dx = c.x - ball.x
dy = c.y - ball.y
distance = math.hypot(dx, dy)
if distance <= c.size - ball.size:
# If BALL inside any CIRCLE
hit = False
break
else:
# If we're outside of a circle.
if closestDist < c.size - (distance - ball.size):
hit = c
closestDist = (c.size - (distance - ball.size))
if hit:
module_physicsEngine.circleBounce(hit, ball)
好的,所以我知道这是一个冗长而有说服力的问题,但我认为你拥有所需的所有信息。解决方案是让球正确地与线if distance <= c.size - ball.size:
进行交互吗?
无论如何,提前谢谢!
纳丹出去了。TL; DR - 观看youtube视频,并告诉我它为什么无效。
答案 0 :(得分:1)
问题在于无意识的点击而不是错过的点击。你真正想要检查的是球的所有部分是否被某个圆覆盖,而你正在做的检查是否有任何圆圈只是部分重叠 - 但如果任何圆圈完全覆盖球,则覆盖。
我认为任何潜在的生命点,即最近的圆形内壁,通过检查它与所有其他圆圈的距离,让该点沿着墙“行走”。如果它然后离开球,这是一个错误的打击。
首先,您会找到触及球的圆圈列表。和以前一样,如果有任何一个覆盖它,你可以跳过其余的检查。同时找到圆圈最接近球的壁点。对于每个最近的壁点,如果它与另一个圆重叠,则将其移动到最接近球但距离当前点更远的交叉点。如果它在球外,请丢弃它。对所有圆圈重复此过程,因为两个以上可能重叠。另请注意,移动该点可能会导致其进入新的圈子。
您可以预先计算交叉点并丢弃任何其他圆圈内的任何球半径。
这肯定可以改进,但我认为这是一个开始。当一对圆的两个交叉点与球重叠时,我怀疑涉及这种情况的错误,但是一条步行链将其中一个引导到球外。也许初始碰撞点应该仅由两个交叉点替换,而不是最接近的交叉点。
答案 1 :(得分:0)
我观看了视频,我喜欢游戏原理。 :)
问题是,当你遇到一个包围球的圆圈时,你break
就会离开循环。我指的是片段
if distance <= c.size - ball.size:
# If BALL inside any CIRCLE
hit = False
break
在这种情况下,为什么不检查所有其他圈子?可能还有另一个未选中的圈子导致hit
。
if condition == True:
,那是不可思议的。只需说if condition:
。